summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.bzrignore159
-rw-r--r--BUILD/Makefile.am44
-rwxr-xr-xBUILD/compile-alpha-cxx10
-rwxr-xr-xBUILD/compile-alpha-debug7
-rwxr-xr-xBUILD/compile-ia64-debug-max13
-rwxr-xr-xBUILD/compile-pentium-debug-max2
-rwxr-xr-xBUILD/compile-pentium-debug-no-bdb2
-rwxr-xr-xBUILD/compile-pentium-debug-openssl13
-rwxr-xr-xBUILD/compile-pentium-max2
-rwxr-xr-xBUILD/compile-pentium-mysqlfs-debug13
-rwxr-xr-xBUILD/compile-pentium-pgcc23
-rwxr-xr-xBUILD/compile-pentium-symbols15
-rwxr-xr-xBUILD/compile-solaris-sparc-debug16
-rw-r--r--BitKeeper/etc/logging_ok35
-rwxr-xr-xBitKeeper/triggers/post-commit49
-rwxr-xr-xBuild-tools/Do-all-build-steps8
-rwxr-xr-xBuild-tools/Do-compile2
-rwxr-xr-xBuild-tools/Do-rpm25
-rw-r--r--Docs/Flags/belgium.eps254
-rw-r--r--Docs/Flags/belgium.gifbin0 -> 181 bytes
-rw-r--r--Docs/Flags/belgium.txt0
-rw-r--r--Docs/Flags/mexico.eps258
-rw-r--r--Docs/Flags/mexico.gifbin0 -> 269 bytes
-rw-r--r--Docs/Flags/mexico.txt0
-rwxr-xr-xDocs/Flags/norway.eps256
-rwxr-xr-xDocs/Flags/norway.gifbin0 -> 416 bytes
-rw-r--r--Docs/Flags/norway.txt0
-rw-r--r--Docs/Flags/philippines.eps240
-rw-r--r--Docs/Flags/philippines.gifbin0 -> 306 bytes
-rw-r--r--Docs/Flags/philippines.txt0
-rwxr-xr-xDocs/Flags/slovenia.eps357
-rw-r--r--Docs/Flags/slovenia.gifbin0 -> 705 bytes
-rwxr-xr-xDocs/Flags/slovenia.txt0
-rw-r--r--Docs/Flags/turkey.eps237
-rw-r--r--Docs/Flags/turkey.gifbin0 -> 169 bytes
-rw-r--r--Docs/Flags/turkey.txt0
-rw-r--r--Docs/Makefile.am8
-rwxr-xr-xDocs/Support/docbook-fixup.pl110
-rwxr-xr-xDocs/Support/make-docbook19
-rwxr-xr-xDocs/Support/update-reserved-words.pl89
-rw-r--r--Docs/bk.txt3
-rw-r--r--Docs/internals.texi59
-rw-r--r--Docs/manual.ja.texi2
-rw-r--r--Docs/manual.texi17493
-rw-r--r--Docs/mirrors.texi392
-rw-r--r--Docs/my_sys.txt140
-rw-r--r--Docs/mysqld_error.txt458
-rw-r--r--Docs/section.Infolinks.texi880
-rw-r--r--Docs/section.Testimonials.texi31
-rw-r--r--Docs/section.Users.texi414
-rw-r--r--Docs/template.texi522
-rw-r--r--Docs/world.sql5386
-rw-r--r--Makefile.am27
-rw-r--r--SSL/NOTES376
-rw-r--r--SSL/cacert.pem21
-rw-r--r--SSL/client-cert.pem67
-rw-r--r--SSL/client-key.pem15
-rw-r--r--SSL/client-req.pem30
-rwxr-xr-xSSL/run-client10
-rwxr-xr-xSSL/run-server9
-rw-r--r--SSL/server-cert.pem67
-rw-r--r--SSL/server-key.pem15
-rw-r--r--SSL/server-req.pem30
-rw-r--r--VC++Files/InstallShield/Script Files/Setup.dbgbin0 -> 28458 bytes
-rw-r--r--VC++Files/InstallShield/Script Files/Setup.inobin0 -> 58611 bytes
-rw-r--r--VC++Files/InstallShield/Script Files/Setup.insbin0 -> 57122 bytes
-rw-r--r--VC++Files/InstallShield/Script Files/Setup.obsbin0 -> 65611 bytes
-rw-r--r--VC++Files/InstallShield/Script Files/Setup.rul640
-rw-r--r--VC++Files/client/mysql.dsp102
-rw-r--r--VC++Files/client/mysqladmin.dsp92
-rw-r--r--VC++Files/client/mysqlclient.dsp494
-rw-r--r--VC++Files/client/mysqlclient.dsw29
-rw-r--r--VC++Files/client/mysqldump.dsp102
-rw-r--r--VC++Files/client/mysqlimport.dsp93
-rw-r--r--VC++Files/client/mysqlshow.dsp92
-rw-r--r--VC++Files/dbug/dbug.dsp98
-rw-r--r--VC++Files/dbug/dbug.dsw29
-rw-r--r--VC++Files/heap/heap.dsp195
-rw-r--r--VC++Files/innobase/innobase.dsp441
-rw-r--r--VC++Files/isam/isam.dsp206
-rw-r--r--VC++Files/isam/isam.dsw29
-rw-r--r--VC++Files/isamchk/isamchk.dsp98
-rw-r--r--VC++Files/libmysql/libmySQL.dsp465
-rw-r--r--VC++Files/libmysql/libmysql.dsw29
-rw-r--r--VC++Files/libmysqltest/myTest.dsp92
-rw-r--r--VC++Files/libmysqltest/mytest.dsw29
-rw-r--r--VC++Files/merge/merge.dsp142
-rw-r--r--VC++Files/merge/merge.dsw29
-rw-r--r--VC++Files/myisam/myisam.dsp292
-rw-r--r--VC++Files/myisamchk/myisamchk.dsp104
-rw-r--r--VC++Files/myisamlog/myisamlog.dsp105
-rw-r--r--VC++Files/myisammrg/myisammrg.dsp173
-rw-r--r--VC++Files/myisampack/myisampack.dsp107
-rw-r--r--VC++Files/mysql.dsp80
-rw-r--r--VC++Files/mysql.dsw656
-rw-r--r--VC++Files/mysqlbinlog/mysqlbinlog.dsp103
-rw-r--r--VC++Files/mysqlcheck/mysqlcheck.dsp102
-rw-r--r--VC++Files/mysqlmanager/MySqlManager.dsp253
-rw-r--r--VC++Files/mysqlmanager/mysqlmanager.dsw29
-rw-r--r--VC++Files/mysqlshutdown/myshutdown.dsp101
-rw-r--r--VC++Files/mysqlshutdown/mysqlshutdown.dsp119
-rw-r--r--VC++Files/mysqlwatch/mysqlwatch.dsp70
-rw-r--r--VC++Files/mysys/mysys.dsp507
-rw-r--r--VC++Files/mysys/mysys.dsw29
-rw-r--r--VC++Files/pack_isam/pack_isam.dsp103
-rw-r--r--VC++Files/perror/perror.dsp109
-rw-r--r--VC++Files/regex/regex.dsp114
-rw-r--r--VC++Files/regex/regex.dsw29
-rw-r--r--VC++Files/replace/replace.dsp93
-rw-r--r--VC++Files/sql/mysqld.dsp1281
-rw-r--r--VC++Files/sql/mysqldmax.dsp1003
-rw-r--r--VC++Files/sql/old/mysqld.dsw29
-rw-r--r--VC++Files/strings/backup/strings.dsp244
-rw-r--r--VC++Files/strings/backup/strings.dsw29
-rw-r--r--VC++Files/strings/noMASM/strings.dsp246
-rw-r--r--VC++Files/strings/strings.dsp248
-rw-r--r--VC++Files/test1/test1.dsp102
-rw-r--r--VC++Files/thr_insert_test/thr_insert_test.dsp109
-rw-r--r--VC++Files/thr_test/thr_test.dsp104
-rw-r--r--VC++Files/vio/vio.dsp108
-rw-r--r--VC++Files/zlib/contrib/asm386/zlibvc.dsp651
-rw-r--r--VC++Files/zlib/contrib/asm386/zlibvc.dsw41
-rw-r--r--VC++Files/zlib/zlib.dsp186
-rw-r--r--acconfig.h15
-rw-r--r--acinclude.m4249
-rw-r--r--bdb/include/btree_ext.h122
-rw-r--r--bdb/include/clib_ext.h38
-rw-r--r--bdb/include/common_ext.h44
-rw-r--r--bdb/include/env_ext.h35
-rw-r--r--bdb/include/hash_ext.h106
-rw-r--r--bdb/include/lock_ext.h39
-rw-r--r--bdb/include/log_ext.h33
-rw-r--r--bdb/include/mp_ext.h33
-rw-r--r--bdb/include/os_ext.h62
-rw-r--r--bdb/include/qam_ext.h56
-rw-r--r--bdb/include/tcl_ext.h89
-rw-r--r--bdb/include/txn_ext.h24
-rw-r--r--bdb/include/xa_ext.h17
-rwxr-xr-xbuild-tags11
-rw-r--r--client/Makefile.am6
-rw-r--r--client/client_priv.h9
-rw-r--r--client/completion_hash.cc75
-rw-r--r--client/completion_hash.h33
-rw-r--r--client/connect_test.c29
-rw-r--r--client/errmsg.c53
-rw-r--r--client/get_password.c57
-rw-r--r--client/insert_test.c37
-rw-r--r--client/list_test.c42
-rw-r--r--client/my_readline.h29
-rw-r--r--client/mysql.cc250
-rw-r--r--client/mysqladmin.c26
-rw-r--r--client/mysqlbinlog.cc116
-rw-r--r--client/mysqlcheck.c12
-rw-r--r--client/mysqldump.c19
-rw-r--r--client/mysqlimport.c16
-rw-r--r--client/mysqlmanager-pwgen.c157
-rw-r--r--client/mysqlmanagerc.c178
-rw-r--r--client/mysqlshow.c14
-rw-r--r--client/mysqltest.c958
-rw-r--r--client/password.c31
-rw-r--r--client/readline.cc50
-rw-r--r--client/select_test.c28
-rw-r--r--client/showdb_test.c22
-rw-r--r--client/sql_string.cc31
-rw-r--r--client/sql_string.h29
-rw-r--r--client/ssl_test.c22
-rw-r--r--client/thimble.cc20
-rw-r--r--client/thread_test.c33
-rw-r--r--client/violite.c394
-rw-r--r--configure.in177
-rw-r--r--dbug/dbug.c4
-rw-r--r--dbug/dbug_analyze.c2
-rw-r--r--dbug/example1.c2
-rw-r--r--dbug/example2.c2
-rw-r--r--dbug/example3.c2
-rw-r--r--dbug/factorial.c2
-rw-r--r--dbug/main.c2
-rw-r--r--dbug/sanity.c2
-rw-r--r--div/deadlock_test.c16
-rw-r--r--extra/Makefile.am2
-rw-r--r--extra/comp_err.c31
-rw-r--r--extra/my_print_defaults.c33
-rw-r--r--extra/mysql_install.c196
-rw-r--r--extra/perror.c34
-rw-r--r--extra/replace.c31
-rw-r--r--extra/resolve_stack_dump.c50
-rw-r--r--fs/CorbaFS.idl38
-rw-r--r--fs/Makefile.am93
-rw-r--r--fs/README58
-rwxr-xr-xfs/RunServer.sh2
-rw-r--r--fs/database.c628
-rw-r--r--fs/dump.sql28
-rw-r--r--fs/korbit-kernel-2.4.1-patch35661
-rw-r--r--fs/libmysqlfs.c151
-rw-r--r--fs/libmysqlfs.h81
-rw-r--r--fs/my.cnf5
-rw-r--r--fs/mysqlcorbafs.c991
-rw-r--r--fs/mysqlcorbafs.h157
-rw-r--r--fs/mysqlcorbafs_test.c92
-rwxr-xr-xfs/mysqlfsck11
-rw-r--r--heap/_check.c12
-rw-r--r--heap/_rectest.c6
-rw-r--r--heap/heapdef.h7
-rw-r--r--heap/hp_block.c6
-rw-r--r--heap/hp_clear.c8
-rw-r--r--heap/hp_close.c12
-rw-r--r--heap/hp_create.c44
-rw-r--r--heap/hp_delete.c12
-rw-r--r--heap/hp_extra.c6
-rw-r--r--heap/hp_hash.c94
-rw-r--r--heap/hp_info.c6
-rw-r--r--heap/hp_open.c11
-rw-r--r--heap/hp_panic.c6
-rw-r--r--heap/hp_rename.c6
-rw-r--r--heap/hp_rfirst.c6
-rw-r--r--heap/hp_rkey.c8
-rw-r--r--heap/hp_rlast.c6
-rw-r--r--heap/hp_rnext.c6
-rw-r--r--heap/hp_rprev.c6
-rw-r--r--heap/hp_rrnd.c6
-rw-r--r--heap/hp_rsame.c6
-rw-r--r--heap/hp_scan.c6
-rw-r--r--heap/hp_static.c6
-rw-r--r--heap/hp_test1.c8
-rw-r--r--heap/hp_test2.c47
-rw-r--r--heap/hp_update.c6
-rw-r--r--heap/hp_write.c13
-rw-r--r--include/Makefile.am17
-rw-r--r--include/config-win.h34
-rw-r--r--include/dbug.h29
-rw-r--r--include/errmsg.h34
-rw-r--r--include/ft_global.h39
-rw-r--r--include/getopt.h16
-rw-r--r--include/hash.h30
-rw-r--r--include/heap.h36
-rw-r--r--include/m_ctype.h59
-rw-r--r--include/m_string.h32
-rw-r--r--include/md5.h (renamed from sql/md5.h)29
-rw-r--r--include/merge.h29
-rw-r--r--include/my_alarm.h29
-rw-r--r--include/my_base.h67
-rw-r--r--include/my_bitmap.h29
-rw-r--r--include/my_dir.h29
-rw-r--r--include/my_getopt.h53
-rw-r--r--include/my_global.h (renamed from include/global.h)117
-rw-r--r--include/my_list.h29
-rw-r--r--include/my_net.h84
-rw-r--r--include/my_no_pthread.h29
-rw-r--r--include/my_nosys.h29
-rw-r--r--include/my_pthread.h48
-rw-r--r--include/my_semaphore.h51
-rw-r--r--include/my_sys.h222
-rw-r--r--include/my_tree.h50
-rw-r--r--include/myisam.h48
-rw-r--r--include/myisammrg.h39
-rw-r--r--include/myisampack.h29
-rw-r--r--include/mysql.h291
-rw-r--r--include/mysql_com.h91
-rw-r--r--include/mysql_embed.h30
-rw-r--r--include/mysqld_error.h27
-rw-r--r--include/mysys_err.h29
-rw-r--r--include/nisam.h29
-rw-r--r--include/queues.h30
-rw-r--r--include/raid.h34
-rw-r--r--include/sslopt-case.h38
-rw-r--r--include/sslopt-longopts.h31
-rw-r--r--include/sslopt-usage.h32
-rw-r--r--include/sslopt-vars.h30
-rw-r--r--include/t_ctype.h20
-rw-r--r--include/thr_alarm.h49
-rw-r--r--include/thr_lock.h31
-rw-r--r--include/violite.h211
-rw-r--r--innobase/btr/btr0btr.c8
-rw-r--r--innobase/btr/btr0cur.c17
-rw-r--r--innobase/btr/btr0sea.c2
-rw-r--r--innobase/buf/buf0buf.c2
-rw-r--r--innobase/buf/buf0lru.c9
-rw-r--r--innobase/data/data0data.c2
-rw-r--r--innobase/dict/dict0boot.c109
-rw-r--r--innobase/dict/dict0crea.c20
-rw-r--r--innobase/dict/dict0dict.c35
-rw-r--r--innobase/dict/dict0load.c38
-rw-r--r--innobase/eval/eval0eval.c8
-rw-r--r--innobase/fil/fil0fil.c11
-rw-r--r--innobase/fsp/fsp0fsp.c8
-rw-r--r--innobase/ibuf/ibuf0ibuf.c20
-rw-r--r--innobase/include/Makefile.am2
-rw-r--r--innobase/include/Makefile.i2
-rw-r--r--innobase/include/btr0btr.ic6
-rw-r--r--innobase/include/buf0buf.ic7
-rw-r--r--innobase/include/dict0dict.ic2
-rw-r--r--innobase/include/dyn0dyn.h7
-rw-r--r--innobase/include/ha0ha.ic2
-rw-r--r--innobase/include/row0mysql.ic3
-rw-r--r--innobase/include/row0vers.ic2
-rw-r--r--innobase/include/srv0srv.h1
-rw-r--r--innobase/include/sync0rw.ic3
-rw-r--r--innobase/include/univ.i3
-rw-r--r--innobase/lock/lock0lock.c7
-rw-r--r--innobase/log/log0log.c17
-rw-r--r--innobase/mem/mem0dbg.c6
-rw-r--r--innobase/mtr/mtr0mtr.c8
-rw-r--r--innobase/odbc/odbc0odbc.c2
-rw-r--r--innobase/os/os0file.c33
-rw-r--r--innobase/os/os0thread.c6
-rw-r--r--innobase/page/page0cur.c9
-rw-r--r--innobase/page/page0page.c6
-rw-r--r--innobase/pars/pars0opt.c3
-rw-r--r--innobase/pars/pars0pars.c2
-rw-r--r--innobase/que/que0que.c46
-rw-r--r--innobase/rem/rem0cmp.c2
-rw-r--r--innobase/rem/rem0rec.c4
-rw-r--r--innobase/row/row0ins.c4
-rw-r--r--innobase/row/row0mysql.c95
-rw-r--r--innobase/row/row0purge.c2
-rw-r--r--innobase/row/row0sel.c21
-rw-r--r--innobase/row/row0uins.c2
-rw-r--r--innobase/row/row0umod.c2
-rw-r--r--innobase/row/row0upd.c2
-rw-r--r--innobase/srv/srv0srv.c68
-rw-r--r--innobase/srv/srv0start.c36
-rw-r--r--innobase/sync/sync0arr.c2
-rw-r--r--innobase/sync/sync0rw.c6
-rw-r--r--innobase/sync/sync0sync.c2
-rw-r--r--innobase/trx/trx0purge.c6
-rw-r--r--innobase/trx/trx0rec.c5
-rw-r--r--innobase/trx/trx0roll.c10
-rw-r--r--innobase/trx/trx0trx.c10
-rw-r--r--innobase/trx/trx0undo.c8
-rw-r--r--isam/_cache.c20
-rw-r--r--isam/_dbug.c6
-rw-r--r--isam/_dynrec.c26
-rw-r--r--isam/_key.c6
-rw-r--r--isam/_locking.c6
-rw-r--r--isam/_packrec.c12
-rw-r--r--isam/_page.c6
-rw-r--r--isam/_search.c6
-rw-r--r--isam/_statrec.c8
-rw-r--r--isam/changed.c6
-rw-r--r--isam/close.c6
-rw-r--r--isam/create.c14
-rw-r--r--isam/delete.c8
-rw-r--r--isam/extra.c7
-rw-r--r--isam/info.c6
-rw-r--r--isam/isamchk.c14
-rw-r--r--isam/isamdef.h6
-rw-r--r--isam/isamlog.c10
-rw-r--r--isam/log.c6
-rw-r--r--isam/open.c6
-rw-r--r--isam/pack_isam.c32
-rw-r--r--isam/panic.c6
-rw-r--r--isam/range.c6
-rw-r--r--isam/rfirst.c6
-rw-r--r--isam/rkey.c6
-rw-r--r--isam/rlast.c6
-rw-r--r--isam/rnext.c6
-rw-r--r--isam/rprev.c6
-rw-r--r--isam/rrnd.c6
-rw-r--r--isam/rsame.c6
-rw-r--r--isam/rsamepos.c6
-rw-r--r--isam/sort.c6
-rw-r--r--isam/static.c8
-rw-r--r--isam/test1.c8
-rw-r--r--isam/test2.c16
-rw-r--r--isam/test3.c10
-rw-r--r--isam/update.c6
-rw-r--r--isam/write.c8
-rw-r--r--libmysql/Makefile.am19
-rw-r--r--libmysql/Makefile.shared18
-rw-r--r--libmysql/conf_to_src.c29
-rw-r--r--libmysql/dll.c31
-rw-r--r--libmysql/errmsg.c54
-rw-r--r--libmysql/get_password.c31
-rw-r--r--libmysql/libmysql.c698
-rw-r--r--libmysql/libmysql.def122
-rw-r--r--libmysql/manager.c273
-rw-r--r--libmysql/net.c427
-rw-r--r--libmysql/password.c31
-rw-r--r--libmysql/violite.c443
-rw-r--r--libmysql_r/Makefile.am2
-rw-r--r--libmysqld/Makefile.am135
-rw-r--r--libmysqld/copyright14
-rw-r--r--libmysqld/embedded_priv.h32
-rw-r--r--libmysqld/examples/Makefile.am26
-rwxr-xr-xlibmysqld/examples/test-run138
-rw-r--r--libmysqld/lib_load.cc44
-rw-r--r--libmysqld/lib_sql.cc602
-rw-r--r--libmysqld/lib_vio.c215
-rw-r--r--libmysqld/libmysqld.c2091
-rw-r--r--libmysqld/libmysqld.def72
-rwxr-xr-xltconfig4
-rw-r--r--man/Makefile.am2
-rw-r--r--[-rwxr-xr-x]man/isamchk.12
-rw-r--r--man/isamlog.12
-rw-r--r--man/mysql.14
-rw-r--r--man/mysql_zap.12
-rw-r--r--[-rwxr-xr-x]man/mysqlaccess.12
-rw-r--r--[-rwxr-xr-x]man/mysqladmin.12
-rw-r--r--[-rwxr-xr-x]man/mysqld.14
-rw-r--r--man/mysqld_multi.14
-rw-r--r--[-rwxr-xr-x]man/mysqld_safe.1 (renamed from man/safe_mysqld.1)20
-rw-r--r--[-rwxr-xr-x]man/mysqldump.12
-rw-r--r--[-rwxr-xr-x]man/mysqlshow.12
-rw-r--r--[-rwxr-xr-x]man/perror.12
-rw-r--r--man/replace.12
-rw-r--r--man/which.22
-rw-r--r--merge/Makefile.am8
-rw-r--r--merge/mrg_close.c (renamed from merge/close.c)8
-rw-r--r--merge/mrg_create.c (renamed from merge/create.c)8
-rw-r--r--merge/mrg_def.h (renamed from merge/mrgdef.h)6
-rw-r--r--merge/mrg_delete.c (renamed from merge/delete.c)8
-rw-r--r--merge/mrg_extra.c (renamed from merge/extra.c)8
-rw-r--r--merge/mrg_info.c (renamed from merge/info.c)8
-rw-r--r--merge/mrg_locking.c (renamed from merge/_locking.c)8
-rw-r--r--merge/mrg_open.c (renamed from merge/open.c)16
-rw-r--r--merge/mrg_panic.c (renamed from merge/panic.c)8
-rw-r--r--merge/mrg_rrnd.c (renamed from merge/rrnd.c)8
-rw-r--r--merge/mrg_rsame.c (renamed from merge/rsame.c)8
-rw-r--r--merge/mrg_static.c (renamed from merge/static.c)8
-rw-r--r--merge/mrg_update.c (renamed from merge/update.c)8
-rw-r--r--myisam/Makefile.am19
-rw-r--r--myisam/ft_boolean_search.c462
-rw-r--r--myisam/ft_dump.c233
-rw-r--r--myisam/ft_eval.c10
-rw-r--r--myisam/ft_eval.h7
-rw-r--r--myisam/ft_nlq_search.c (renamed from myisam/ft_search.c)127
-rw-r--r--myisam/ft_parser.c152
-rw-r--r--myisam/ft_static.c32
-rw-r--r--myisam/ft_stem.c7
-rw-r--r--myisam/ft_stopwords.c15
-rw-r--r--myisam/ft_test1.c10
-rw-r--r--myisam/ft_test1.h7
-rw-r--r--myisam/ft_update.c211
-rw-r--r--myisam/ftdefs.h73
-rw-r--r--myisam/fulltext.h1
-rw-r--r--myisam/mi_cache.c26
-rw-r--r--myisam/mi_changed.c8
-rw-r--r--myisam/mi_check.c214
-rw-r--r--myisam/mi_checksum.c6
-rw-r--r--myisam/mi_close.c6
-rw-r--r--myisam/mi_create.c111
-rw-r--r--myisam/mi_dbug.c8
-rw-r--r--myisam/mi_delete.c15
-rw-r--r--myisam/mi_delete_all.c13
-rw-r--r--myisam/mi_delete_table.c10
-rw-r--r--myisam/mi_dynrec.c92
-rw-r--r--myisam/mi_extra.c46
-rw-r--r--myisam/mi_info.c10
-rw-r--r--myisam/mi_key.c36
-rw-r--r--myisam/mi_locking.c34
-rw-r--r--myisam/mi_log.c6
-rw-r--r--myisam/mi_open.c102
-rw-r--r--myisam/mi_packrec.c12
-rw-r--r--myisam/mi_page.c10
-rw-r--r--myisam/mi_panic.c6
-rw-r--r--myisam/mi_range.c22
-rw-r--r--myisam/mi_rename.c10
-rw-r--r--myisam/mi_rfirst.c6
-rw-r--r--myisam/mi_rkey.c12
-rw-r--r--myisam/mi_rlast.c6
-rw-r--r--myisam/mi_rnext.c4
-rw-r--r--myisam/mi_rnext_same.c8
-rw-r--r--myisam/mi_rprev.c4
-rw-r--r--myisam/mi_rrnd.c6
-rw-r--r--myisam/mi_rsame.c11
-rw-r--r--myisam/mi_rsamepos.c6
-rw-r--r--myisam/mi_scan.c6
-rw-r--r--myisam/mi_search.c1253
-rw-r--r--myisam/mi_static.c12
-rw-r--r--myisam/mi_statrec.c63
-rw-r--r--myisam/mi_test1.c8
-rw-r--r--myisam/mi_test2.c158
-rw-r--r--myisam/mi_test3.c6
-rw-r--r--myisam/mi_test_all.res90
-rwxr-xr-xmyisam/mi_test_all.sh20
-rw-r--r--myisam/mi_unique.c6
-rw-r--r--myisam/mi_update.c16
-rw-r--r--myisam/mi_write.c255
-rw-r--r--myisam/myisamchk.c570
-rw-r--r--myisam/myisamdef.h126
-rw-r--r--myisam/myisamlog.c15
-rw-r--r--myisam/myisampack.c44
-rw-r--r--myisam/sort.c166
-rw-r--r--myisammrg/Makefile.am4
-rw-r--r--myisammrg/myrg_close.c8
-rw-r--r--myisammrg/myrg_create.c18
-rw-r--r--myisammrg/myrg_def.h (renamed from myisammrg/mymrgdef.h)6
-rw-r--r--myisammrg/myrg_delete.c8
-rw-r--r--myisammrg/myrg_extra.c13
-rw-r--r--myisammrg/myrg_info.c2
-rw-r--r--myisammrg/myrg_locking.c8
-rw-r--r--myisammrg/myrg_open.c60
-rw-r--r--myisammrg/myrg_panic.c8
-rw-r--r--myisammrg/myrg_queue.c2
-rw-r--r--myisammrg/myrg_rfirst.c2
-rw-r--r--myisammrg/myrg_rkey.c2
-rw-r--r--myisammrg/myrg_rlast.c2
-rw-r--r--myisammrg/myrg_rnext.c2
-rw-r--r--myisammrg/myrg_rprev.c2
-rw-r--r--myisammrg/myrg_rrnd.c2
-rw-r--r--myisammrg/myrg_rsame.c8
-rw-r--r--myisammrg/myrg_static.c12
-rw-r--r--myisammrg/myrg_update.c8
-rw-r--r--myisammrg/myrg_write.c30
-rw-r--r--mysql-test/Makefile.am2
-rwxr-xr-xmysql-test/create-test-result4
-rwxr-xr-xmysql-test/fix-result22
-rw-r--r--mysql-test/include/have_bdb.inc2
-rw-r--r--mysql-test/include/have_gemini.inc2
-rw-r--r--mysql-test/include/have_innodb.inc2
-rw-r--r--mysql-test/include/have_isam.inc2
-rw-r--r--mysql-test/include/have_openssl.inc4
-rw-r--r--mysql-test/include/have_openssl_1.inc4
-rw-r--r--mysql-test/include/have_openssl_2.inc4
-rw-r--r--mysql-test/include/master-slave.inc9
-rw-r--r--mysql-test/include/not_embedded.inc5
-rw-r--r--mysql-test/install_test_db.sh28
-rw-r--r--mysql-test/mysql-test-run.sh823
-rw-r--r--mysql-test/r/alias.result59
-rw-r--r--mysql-test/r/alter_table.result82
-rw-r--r--mysql-test/r/analyse.result7
-rw-r--r--mysql-test/r/auto_increment.result59
-rw-r--r--mysql-test/r/backup.result30
-rw-r--r--mysql-test/r/bdb-crash.result29
-rw-r--r--mysql-test/r/bdb-deadlock.result21
-rw-r--r--mysql-test/r/bdb.result621
-rw-r--r--mysql-test/r/bench_count_distinct.result4
-rw-r--r--mysql-test/r/big_test.require2
-rw-r--r--mysql-test/r/bigint.result63
-rw-r--r--mysql-test/r/binary.result22
-rw-r--r--mysql-test/r/bulk_replace.result11
-rw-r--r--mysql-test/r/case.result23
-rw-r--r--mysql-test/r/check.result5
-rw-r--r--mysql-test/r/comments.result12
-rw-r--r--mysql-test/r/compare.result8
-rw-r--r--mysql-test/r/count_distinct.result35
-rw-r--r--mysql-test/r/count_distinct2.result129
-rw-r--r--mysql-test/r/create.result82
-rw-r--r--mysql-test/r/ctype_latin1_de.result207
-rw-r--r--mysql-test/r/delayed.result20
-rw-r--r--mysql-test/r/delete.result26
-rw-r--r--mysql-test/r/dirty-close.result4
-rw-r--r--mysql-test/r/dirty_close.result9
-rw-r--r--mysql-test/r/distinct.result163
-rw-r--r--mysql-test/r/drop.result39
-rw-r--r--mysql-test/r/empty_table.result6
-rw-r--r--mysql-test/r/err000001.result25
-rw-r--r--mysql-test/r/explain.result17
-rw-r--r--mysql-test/r/flush.result29
-rw-r--r--mysql-test/r/foreign_key.result15
-rw-r--r--mysql-test/r/fulltext.result127
-rw-r--r--mysql-test/r/fulltext_cache.result54
-rw-r--r--mysql-test/r/fulltext_distinct.result43
-rw-r--r--mysql-test/r/fulltext_left_join.result29
-rw-r--r--mysql-test/r/fulltext_multi.result26
-rw-r--r--mysql-test/r/fulltext_order_by.result65
-rw-r--r--mysql-test/r/fulltext_update.result20
-rw-r--r--mysql-test/r/fulltext_var.result6
-rw-r--r--mysql-test/r/func_crypt.result4
-rw-r--r--mysql-test/r/func_date_add.result35
-rw-r--r--mysql-test/r/func_encrypt.result136
-rw-r--r--mysql-test/r/func_equal.result14
-rw-r--r--mysql-test/r/func_group.result74
-rw-r--r--mysql-test/r/func_in.result13
-rw-r--r--mysql-test/r/func_like.result11
-rw-r--r--mysql-test/r/func_math.result13
-rw-r--r--mysql-test/r/func_misc.result4
-rw-r--r--mysql-test/r/func_op.result5
-rw-r--r--mysql-test/r/func_regexp.result29
-rw-r--r--mysql-test/r/func_set.result9
-rw-r--r--mysql-test/r/func_str.result84
-rw-r--r--mysql-test/r/func_system.result6
-rw-r--r--mysql-test/r/func_test.result23
-rw-r--r--mysql-test/r/func_time.result160
-rw-r--r--mysql-test/r/func_timestamp.result8
-rw-r--r--mysql-test/r/gcc296.result15
-rw-r--r--mysql-test/r/gemini.result370
-rw-r--r--mysql-test/r/grant_cache.result153
-rw-r--r--mysql-test/r/group_by.result313
-rw-r--r--mysql-test/r/handler.result139
-rw-r--r--mysql-test/r/have_openssl.require2
-rw-r--r--mysql-test/r/have_openssl_1.require2
-rw-r--r--mysql-test/r/have_openssl_2.require (renamed from mysql-test/r/have_gemini.require)2
-rw-r--r--mysql-test/r/have_symlink.require2
-rw-r--r--mysql-test/r/having.result40
-rw-r--r--mysql-test/r/heap.result110
-rw-r--r--mysql-test/r/identity.result2
-rw-r--r--mysql-test/r/innodb.result520
-rw-r--r--mysql-test/r/innodb_cache.result15
-rw-r--r--mysql-test/r/ins000001.result9
-rw-r--r--mysql-test/r/insert.result15
-rw-r--r--mysql-test/r/insert_select.result55
-rw-r--r--mysql-test/r/isam.result73
-rw-r--r--mysql-test/r/isolation.result61
-rw-r--r--mysql-test/r/join.result174
-rw-r--r--mysql-test/r/join_crash.result109
-rw-r--r--mysql-test/r/join_outer.result321
-rw-r--r--mysql-test/r/key.result130
-rw-r--r--mysql-test/r/key_diff.result13
-rw-r--r--mysql-test/r/key_primary.result10
-rw-r--r--mysql-test/r/keywords.result12
-rw-r--r--mysql-test/r/kill.result7
-rw-r--r--mysql-test/r/limit.result27
-rw-r--r--mysql-test/r/lock.result43
-rw-r--r--mysql-test/r/lock_multi.result18
-rw-r--r--mysql-test/r/merge.result332
-rw-r--r--mysql-test/r/multi_update.result41
-rw-r--r--mysql-test/r/myisam.result51
-rw-r--r--mysql-test/r/not_embedded.require2
-rw-r--r--mysql-test/r/null.result26
-rw-r--r--mysql-test/r/null_key.result71
-rw-r--r--mysql-test/r/odbc.result8
-rw-r--r--mysql-test/r/openssl_1.result2
-rw-r--r--mysql-test/r/openssl_2.result2
-rw-r--r--mysql-test/r/order_by.result329
-rw-r--r--mysql-test/r/order_fill_sortbuf.result10
-rw-r--r--mysql-test/r/overflow.result2
-rw-r--r--mysql-test/r/query_cache.result492
-rw-r--r--mysql-test/r/raid.result188
-rw-r--r--mysql-test/r/range.result85
-rw-r--r--mysql-test/r/rename.result25
-rw-r--r--mysql-test/r/replace.result23
-rw-r--r--mysql-test/r/rollback.result9
-rw-r--r--mysql-test/r/rpl000001.result82
-rw-r--r--mysql-test/r/rpl000002.result25
-rw-r--r--mysql-test/r/rpl000003.result12
-rw-r--r--mysql-test/r/rpl000004.result28
-rw-r--r--mysql-test/r/rpl000005.result14
-rw-r--r--mysql-test/r/rpl000006.result24
-rw-r--r--mysql-test/r/rpl000007.result19
-rw-r--r--mysql-test/r/rpl000008.result22
-rw-r--r--mysql-test/r/rpl000009.result80
-rw-r--r--mysql-test/r/rpl000010.result12
-rw-r--r--mysql-test/r/rpl000011.result14
-rw-r--r--mysql-test/r/rpl000012.result25
-rw-r--r--mysql-test/r/rpl000013.result17
-rw-r--r--mysql-test/r/rpl000014.result43
-rw-r--r--mysql-test/r/rpl000015.result34
-rw-r--r--mysql-test/r/rpl000016.result58
-rw-r--r--mysql-test/r/rpl000017.result9
-rw-r--r--mysql-test/r/rpl000018.result8
-rw-r--r--mysql-test/r/rpl_compat.result77
-rw-r--r--mysql-test/r/rpl_failsafe.result33
-rw-r--r--mysql-test/r/rpl_get_lock.result12
-rw-r--r--mysql-test/r/rpl_log.result98
-rw-r--r--mysql-test/r/rpl_magic.result36
-rw-r--r--mysql-test/r/rpl_mystery22.result19
-rw-r--r--mysql-test/r/rpl_skip_error.result11
-rw-r--r--mysql-test/r/rpl_sporadic_master.result19
-rw-r--r--mysql-test/r/sel000001.result5
-rw-r--r--mysql-test/r/sel000002.result5
-rw-r--r--mysql-test/r/sel000003.result5
-rw-r--r--mysql-test/r/sel000031.result8
-rw-r--r--mysql-test/r/sel000032.result8
-rw-r--r--mysql-test/r/sel000033.result6
-rw-r--r--mysql-test/r/sel000100.result26
-rw-r--r--mysql-test/r/select.result1453
-rw-r--r--mysql-test/r/select_found.result64
-rw-r--r--mysql-test/r/select_safe.result29
-rw-r--r--mysql-test/r/show_check.result133
-rw-r--r--mysql-test/r/slave-running.result1
-rw-r--r--mysql-test/r/slave-stopped.result1
-rw-r--r--mysql-test/r/status.result13
-rw-r--r--mysql-test/r/symlink.result65
-rw-r--r--mysql-test/r/tablelock.result36
-rw-r--r--mysql-test/r/temp_table.result44
-rw-r--r--mysql-test/r/truncate.result12
-rw-r--r--mysql-test/r/type_blob.result187
-rw-r--r--mysql-test/r/type_date.result41
-rw-r--r--mysql-test/r/type_datetime.result24
-rw-r--r--mysql-test/r/type_decimal.result147
-rw-r--r--mysql-test/r/type_enum.result8
-rw-r--r--mysql-test/r/type_float.result33
-rw-r--r--mysql-test/r/type_ranges.result154
-rw-r--r--mysql-test/r/type_time.result12
-rw-r--r--mysql-test/r/type_timestamp.result34
-rw-r--r--mysql-test/r/type_uint.result6
-rw-r--r--mysql-test/r/type_year.result6
-rw-r--r--mysql-test/r/union.result144
-rw-r--r--mysql-test/r/update.result73
-rw-r--r--mysql-test/r/user_var.result16
-rw-r--r--mysql-test/r/varbinary.result21
-rw-r--r--mysql-test/r/variables.result21
-rw-r--r--mysql-test/r/warnings.result9
-rwxr-xr-xmysql-test/resolve-stack8
-rw-r--r--mysql-test/std_data/des_key_file4
-rw-r--r--mysql-test/std_data/gemini.dat5
-rw-r--r--mysql-test/std_data/master-bin.001bin113 -> 98 bytes
-rw-r--r--mysql-test/t/alter_table.test29
-rw-r--r--mysql-test/t/analyse.test1
-rw-r--r--mysql-test/t/auto_increment.test15
-rw-r--r--mysql-test/t/backup.test6
-rw-r--r--mysql-test/t/bdb-crash.test1
-rw-r--r--mysql-test/t/bdb.test16
-rw-r--r--mysql-test/t/bench_count_distinct.test3
-rw-r--r--mysql-test/t/bigint.test23
-rw-r--r--mysql-test/t/bulk_replace.test14
-rw-r--r--mysql-test/t/check.test3
-rw-r--r--mysql-test/t/count_distinct2-master.opt1
-rw-r--r--mysql-test/t/count_distinct2.test79
-rw-r--r--mysql-test/t/create.test20
-rw-r--r--mysql-test/t/ctype_latin1_de-master.opt1
-rw-r--r--mysql-test/t/ctype_latin1_de.test46
-rw-r--r--mysql-test/t/dirty_close.test (renamed from mysql-test/t/dirty-close.test)0
-rw-r--r--mysql-test/t/drop.test44
-rw-r--r--mysql-test/t/flush.test32
-rw-r--r--mysql-test/t/fulltext.test53
-rw-r--r--mysql-test/t/fulltext_cache.test14
-rw-r--r--mysql-test/t/fulltext_distinct.test41
-rw-r--r--mysql-test/t/fulltext_left_join.test2
-rw-r--r--mysql-test/t/fulltext_order_by.test7
-rw-r--r--mysql-test/t/fulltext_var.test5
-rw-r--r--mysql-test/t/func_crypt.test3
-rw-r--r--mysql-test/t/func_encrypt-master.opt1
-rw-r--r--mysql-test/t/func_encrypt.test67
-rw-r--r--mysql-test/t/func_like.test2
-rw-r--r--mysql-test/t/func_str.test6
-rw-r--r--mysql-test/t/func_system.test2
-rw-r--r--mysql-test/t/func_time.test12
-rw-r--r--mysql-test/t/gemini.test355
-rw-r--r--mysql-test/t/grant_cache-master.opt1
-rw-r--r--mysql-test/t/grant_cache.test102
-rw-r--r--mysql-test/t/group_by.test40
-rw-r--r--mysql-test/t/handler.test67
-rw-r--r--mysql-test/t/heap.test22
-rw-r--r--mysql-test/t/innodb.test105
-rw-r--r--mysql-test/t/innodb_cache-master.opt1
-rw-r--r--mysql-test/t/innodb_cache.test14
-rw-r--r--mysql-test/t/insert.test12
-rw-r--r--mysql-test/t/insert_select.test58
-rw-r--r--mysql-test/t/isam.test59
-rw-r--r--mysql-test/t/isolation.test208
-rw-r--r--mysql-test/t/join.test2
-rw-r--r--mysql-test/t/key.test8
-rw-r--r--mysql-test/t/keywords.test4
-rw-r--r--mysql-test/t/kill.test8
-rw-r--r--mysql-test/t/limit.test2
-rw-r--r--mysql-test/t/lock.test42
-rw-r--r--mysql-test/t/lock_multi.test49
-rw-r--r--mysql-test/t/merge.test58
-rw-r--r--mysql-test/t/multi_update.test53
-rw-r--r--mysql-test/t/myisam.test2
-rw-r--r--mysql-test/t/null.test1
-rw-r--r--mysql-test/t/openssl_1.test6
-rw-r--r--mysql-test/t/openssl_2.test5
-rw-r--r--mysql-test/t/order_by.test49
-rw-r--r--mysql-test/t/order_fill_sortbuf-master.opt1
-rw-r--r--mysql-test/t/order_fill_sortbuf.test21
-rw-r--r--mysql-test/t/query_cache-master.opt1
-rw-r--r--mysql-test/t/query_cache.test336
-rw-r--r--mysql-test/t/rename.test16
-rw-r--r--mysql-test/t/rpl000001.test31
-rw-r--r--mysql-test/t/rpl000002.test2
-rw-r--r--mysql-test/t/rpl000009.test53
-rw-r--r--mysql-test/t/rpl000014.test10
-rw-r--r--mysql-test/t/rpl000015.test14
-rw-r--r--mysql-test/t/rpl000016-slave.opt1
-rwxr-xr-xmysql-test/t/rpl000016-slave.sh1
-rw-r--r--mysql-test/t/rpl000016.test17
-rwxr-xr-xmysql-test/t/rpl000017-slave.sh3
-rw-r--r--mysql-test/t/rpl000017.test4
-rwxr-xr-xmysql-test/t/rpl000018-master.sh3
-rw-r--r--mysql-test/t/rpl000018.test7
-rw-r--r--mysql-test/t/rpl_compat.test86
-rw-r--r--mysql-test/t/rpl_failsafe.test24
-rw-r--r--mysql-test/t/rpl_get_lock.test3
-rw-r--r--mysql-test/t/rpl_log.test57
-rw-r--r--mysql-test/t/rpl_magic.test31
-rw-r--r--mysql-test/t/rpl_mystery22.test1
-rw-r--r--mysql-test/t/rpl_sporadic_master.test8
-rw-r--r--mysql-test/t/select.test6
-rw-r--r--mysql-test/t/select_found.test32
-rw-r--r--mysql-test/t/show_check.test30
-rw-r--r--mysql-test/t/status.test10
-rw-r--r--mysql-test/t/symlink.test89
-rw-r--r--mysql-test/t/tablelock.test7
-rw-r--r--mysql-test/t/truncate.test6
-rw-r--r--mysql-test/t/type_datetime.test9
-rw-r--r--mysql-test/t/type_enum.test1
-rw-r--r--mysql-test/t/union.test73
-rw-r--r--mysql-test/t/update.test11
-rw-r--r--mysql-test/t/varbinary.test16
-rw-r--r--mysql-test/xml/README74
-rw-r--r--mysql-test/xml/tests/sel000001.xml21
-rw-r--r--mysql-test/xml/tests/sel000002.xml20
-rw-r--r--mysql-test/xml/tests/sel000003.xml21
-rw-r--r--mysql-test/xml/tests/sel000004.xml17
-rw-r--r--mysql-test/xml/tests/sel000005.xml17
-rw-r--r--mysql-test/xml/tests/sel000006.xml17
-rw-r--r--mysql-test/xml/tests/sel000007.xml17
-rw-r--r--mysql-test/xml/tests/sel000008.xml17
-rw-r--r--mysql-test/xml/tests/sel000009.xml17
-rw-r--r--mysql-test/xml/tests/sel000010.xml17
-rw-r--r--mysql-test/xml/tests/sel000011.xml17
-rw-r--r--mysql-test/xml/tests/sel000012.xml16
-rw-r--r--mysql-test/xml/tests/sel000013.xml16
-rw-r--r--mysql-test/xml/tests/sel000014.xml17
-rw-r--r--mysql-test/xml/tests/sel000015.xml17
-rw-r--r--mysql-test/xml/tests/sel000016.xml17
-rw-r--r--mysql-test/xml/tests/sel000017.xml17
-rw-r--r--mysql-test/xml/tests/sel000018.xml17
-rw-r--r--mysql-test/xml/tests/sel000019.xml17
-rw-r--r--mysql-test/xml/tests/sel000020.xml17
-rw-r--r--mysql-test/xml/tests/sel000021.xml17
-rw-r--r--mysql-test/xml/tests/sel000022.xml17
-rw-r--r--mysql-test/xml/tests/sel000023.xml17
-rw-r--r--mysql-test/xml/tests/sel000024.xml17
-rw-r--r--mysql-test/xml/tests/sel000025.xml17
-rw-r--r--mysql-test/xml/tests/sel000026.xml17
-rw-r--r--mysql-test/xml/tests/sel000027.xml17
-rw-r--r--mysql-test/xml/tests/sel000028.xml17
-rw-r--r--mysql-test/xml/tests/sel000029.xml17
-rw-r--r--mysql-test/xml/tests/sel000030.xml17
-rw-r--r--mysql-test/xml/xsl/README4
-rw-r--r--mysql-test/xml/xsl/mysqltest.xsl59
-rw-r--r--mysys/Makefile.am12
-rw-r--r--mysys/array.c29
-rw-r--r--mysys/charset.c85
-rw-r--r--mysys/checksum.c31
-rw-r--r--mysys/default.c50
-rw-r--r--mysys/errors.c29
-rw-r--r--mysys/getopt.c4
-rw-r--r--mysys/getopt1.c2
-rw-r--r--mysys/getvar.c31
-rw-r--r--mysys/hash.c49
-rw-r--r--mysys/list.c29
-rw-r--r--mysys/make-conf.c31
-rw-r--r--mysys/md5.c (renamed from sql/md5.c)34
-rw-r--r--mysys/mf_brkhant.c29
-rw-r--r--mysys/mf_cache.c23
-rw-r--r--mysys/mf_casecnv.c37
-rw-r--r--mysys/mf_dirname.c114
-rw-r--r--mysys/mf_fn_ext.c29
-rw-r--r--mysys/mf_format.c128
-rw-r--r--mysys/mf_getdate.c29
-rw-r--r--mysys/mf_iocache.c768
-rw-r--r--mysys/mf_iocache2.c134
-rw-r--r--mysys/mf_keycache.c109
-rw-r--r--mysys/mf_loadpath.c29
-rw-r--r--mysys/mf_pack.c36
-rw-r--r--mysys/mf_pack2.c53
-rw-r--r--mysys/mf_path.c29
-rw-r--r--mysys/mf_qsort.c360
-rw-r--r--mysys/mf_qsort2.c29
-rw-r--r--mysys/mf_radix.c29
-rw-r--r--mysys/mf_same.c29
-rw-r--r--mysys/mf_sleep.c29
-rw-r--r--mysys/mf_sort.c31
-rw-r--r--mysys/mf_soundex.c29
-rw-r--r--mysys/mf_stripp.c29
-rw-r--r--mysys/mf_tempfile.c41
-rw-r--r--mysys/mf_unixpath.c29
-rw-r--r--mysys/mf_util.c29
-rw-r--r--mysys/mf_wcomp.c29
-rw-r--r--mysys/mf_wfile.c29
-rw-r--r--mysys/mulalloc.c29
-rw-r--r--mysys/my_alarm.c29
-rw-r--r--mysys/my_alloc.c113
-rw-r--r--mysys/my_append.c29
-rw-r--r--mysys/my_bit.c31
-rw-r--r--mysys/my_bitmap.c33
-rw-r--r--mysys/my_chsize.c29
-rw-r--r--mysys/my_clock.c31
-rw-r--r--mysys/my_compress.c35
-rw-r--r--mysys/my_copy.c29
-rw-r--r--mysys/my_create.c29
-rw-r--r--mysys/my_delete.c30
-rw-r--r--mysys/my_div.c29
-rw-r--r--mysys/my_dup.c39
-rw-r--r--mysys/my_error.c29
-rw-r--r--mysys/my_fopen.c29
-rw-r--r--mysys/my_fstream.c34
-rw-r--r--mysys/my_getopt.c578
-rw-r--r--mysys/my_getwd.c29
-rw-r--r--mysys/my_init.c33
-rw-r--r--mysys/my_lib.c40
-rw-r--r--mysys/my_lock.c29
-rw-r--r--mysys/my_lockmem.c29
-rw-r--r--mysys/my_lread.c29
-rw-r--r--mysys/my_lwrite.c29
-rw-r--r--mysys/my_malloc.c29
-rw-r--r--mysys/my_messnc.c29
-rw-r--r--mysys/my_mkdir.c29
-rw-r--r--mysys/my_net.c29
-rw-r--r--mysys/my_once.c29
-rw-r--r--mysys/my_open.c29
-rw-r--r--mysys/my_pread.c29
-rw-r--r--mysys/my_pthread.c71
-rw-r--r--mysys/my_quick.c29
-rw-r--r--mysys/my_read.c43
-rw-r--r--mysys/my_realloc.c29
-rw-r--r--mysys/my_redel.c29
-rw-r--r--mysys/my_rename.c29
-rw-r--r--mysys/my_seek.c38
-rw-r--r--mysys/my_static.c36
-rw-r--r--mysys/my_static.h29
-rw-r--r--mysys/my_symlink.c29
-rw-r--r--mysys/my_symlink2.c50
-rw-r--r--mysys/my_tempnam.c23
-rw-r--r--mysys/my_thr_init.c29
-rw-r--r--mysys/my_vsnprintf.c32
-rw-r--r--mysys/my_wincond.c29
-rw-r--r--mysys/my_winsem.c406
-rw-r--r--mysys/my_winthread.c29
-rw-r--r--mysys/my_write.c29
-rw-r--r--mysys/mysys_priv.h31
-rw-r--r--mysys/ptr_cmp.c32
-rw-r--r--mysys/queues.c49
-rw-r--r--mysys/raid.cc155
-rw-r--r--mysys/safemalloc.c29
-rw-r--r--mysys/string.c31
-rw-r--r--mysys/test_charset.c33
-rw-r--r--mysys/test_dir.c29
-rw-r--r--mysys/test_fn.c29
-rw-r--r--mysys/testhash.c31
-rw-r--r--mysys/thr_alarm.c33
-rw-r--r--mysys/thr_lock.c29
-rw-r--r--mysys/thr_mutex.c44
-rw-r--r--mysys/thr_rwlock.c29
-rw-r--r--mysys/tree.c108
-rw-r--r--mysys/typelib.c32
-rw-r--r--pstack/Makefile.am36
-rw-r--r--pstack/aout/Makefile.am1
-rw-r--r--pstack/aout/aout64.h475
-rw-r--r--pstack/aout/stab.def264
-rw-r--r--pstack/aout/stab_gnu.h37
-rw-r--r--pstack/bucomm.c238
-rw-r--r--pstack/bucomm.h85
-rw-r--r--pstack/budbg.h58
-rw-r--r--pstack/debug.c3509
-rw-r--r--pstack/debug.h798
-rw-r--r--pstack/demangle.h90
-rw-r--r--pstack/filemode.c266
-rw-r--r--pstack/ieee.c7602
-rw-r--r--pstack/ieee.h138
-rw-r--r--pstack/libiberty.h180
-rw-r--r--pstack/linuxthreads.c90
-rw-r--r--pstack/linuxthreads.h28
-rw-r--r--pstack/pstack.c2745
-rw-r--r--pstack/pstack.h22
-rw-r--r--pstack/pstacktrace.h24
-rw-r--r--pstack/rddbg.c462
-rw-r--r--pstack/stabs.c5082
-rw-r--r--readline/bind.c65
-rw-r--r--readline/callback.c1
-rw-r--r--readline/complete.c33
-rw-r--r--readline/display.c20
-rw-r--r--readline/funmap.c12
-rw-r--r--readline/histexpand.c15
-rw-r--r--readline/histfile.c8
-rw-r--r--readline/history.c2
-rw-r--r--readline/history.h6
-rw-r--r--readline/histsearch.c2
-rw-r--r--readline/input.c2
-rw-r--r--readline/isearch.c6
-rw-r--r--readline/kill.c34
-rw-r--r--readline/macro.c19
-rw-r--r--readline/readline.c63
-rw-r--r--readline/readline.h38
-rw-r--r--readline/rlstdc.h4
-rw-r--r--readline/rltty.c11
-rw-r--r--readline/search.c20
-rw-r--r--readline/shell.c1
-rw-r--r--readline/terminal.c21
-rw-r--r--readline/tilde.c12
-rw-r--r--readline/tilde.h4
-rw-r--r--readline/undo.c9
-rw-r--r--readline/util.c14
-rw-r--r--readline/vi_mode.c68
-rw-r--r--regex/cclass.h6
-rw-r--r--regex/cname.h4
-rw-r--r--regex/debug.c2
-rw-r--r--regex/main.c18
-rw-r--r--regex/regcomp.c74
-rw-r--r--regex/regcomp.ih2
-rw-r--r--regex/regerror.c10
-rw-r--r--regex/regexec.c2
-rw-r--r--regex/regexp.c2
-rw-r--r--regex/regfree.c2
-rw-r--r--regex/reginit.c4
-rw-r--r--regex/split.c2
-rw-r--r--scripts/Makefile.am9
-rw-r--r--scripts/explain_log.sh383
-rw-r--r--scripts/make_binary_distribution.sh9
-rw-r--r--scripts/mysql_config.sh13
-rw-r--r--scripts/mysql_explain_log.sh383
-rw-r--r--scripts/mysql_fix_extensions.sh16
-rw-r--r--scripts/mysql_fix_privilege_tables.sh19
-rw-r--r--scripts/mysql_install_db.sh27
-rw-r--r--scripts/mysql_new_fix_privilege_tables.sh25
-rw-r--r--scripts/mysqld_multi.sh16
-rw-r--r--scripts/mysqld_safe-watch.sh (renamed from scripts/safe_mysqld-watch.sh)2
-rw-r--r--scripts/mysqld_safe.sh (renamed from scripts/safe_mysqld.sh)100
-rw-r--r--scripts/mysqlhotcopy.sh2
-rw-r--r--sql-bench/Comments/interbase18
-rw-r--r--sql-bench/Makefile.am8
-rw-r--r--sql-bench/as3ap.sh636
-rw-r--r--sql-bench/bench-count-distinct.sh258
-rw-r--r--sql-bench/bench-init.pl.sh28
-rw-r--r--sql-bench/crash-me.sh41
-rw-r--r--sql-bench/limits/db2.cfg270
-rw-r--r--sql-bench/limits/interbase-dialect1.cfg514
-rw-r--r--sql-bench/limits/interbase-dialect3.cfg514
-rw-r--r--sql-bench/limits/interbase-superserver.cfg514
-rw-r--r--sql-bench/run-all-tests.sh20
-rw-r--r--sql-bench/server-cfg.sh221
-rw-r--r--sql-bench/test-ATIS.sh17
-rw-r--r--sql-bench/test-alter-table.sh14
-rw-r--r--sql-bench/test-big-tables.sh16
-rw-r--r--sql-bench/test-connect.sh88
-rw-r--r--sql-bench/test-insert.sh114
-rw-r--r--sql-bench/test-select.sh18
-rw-r--r--sql-bench/test-transactions.sh297
-rw-r--r--sql-bench/test-wisconsin.sh68
-rw-r--r--sql/ChangeLog5
-rw-r--r--sql/Makefile.am38
-rw-r--r--sql/cache_manager.cc12
-rw-r--r--sql/cache_manager.h10
-rw-r--r--sql/convert.cc26
-rw-r--r--sql/custom_conf.h6
-rw-r--r--sql/derror.cc47
-rw-r--r--sql/des_key_file.cc107
-rw-r--r--sql/field.cc313
-rw-r--r--sql/field.h186
-rw-r--r--sql/field_conv.cc6
-rw-r--r--sql/filesort.cc319
-rw-r--r--sql/frm_crypt.cc6
-rw-r--r--sql/gen_lex_hash.cc20
-rw-r--r--sql/ha_berkeley.cc53
-rw-r--r--sql/ha_berkeley.h8
-rw-r--r--sql/ha_gemini.cc3630
-rw-r--r--sql/ha_gemini.h208
-rw-r--r--sql/ha_heap.cc48
-rw-r--r--sql/ha_heap.h9
-rw-r--r--sql/ha_innodb.cc (renamed from sql/ha_innobase.cc)345
-rw-r--r--sql/ha_innodb.h (renamed from sql/ha_innobase.h)36
-rw-r--r--sql/ha_isam.cc29
-rw-r--r--sql/ha_isam.h18
-rw-r--r--sql/ha_isammrg.cc16
-rw-r--r--sql/ha_isammrg.h11
-rw-r--r--sql/ha_myisam.cc208
-rw-r--r--sql/ha_myisam.h26
-rw-r--r--sql/ha_myisammrg.cc51
-rw-r--r--sql/ha_myisammrg.h6
-rw-r--r--sql/handler.cc200
-rw-r--r--sql/handler.h73
-rw-r--r--sql/hash_filo.cc6
-rw-r--r--sql/hash_filo.h8
-rw-r--r--sql/hostname.cc6
-rw-r--r--sql/init.cc6
-rw-r--r--sql/item.cc55
-rw-r--r--sql/item.h44
-rw-r--r--sql/item_buff.cc6
-rw-r--r--sql/item_cmpfunc.cc24
-rw-r--r--sql/item_cmpfunc.h12
-rw-r--r--sql/item_create.cc44
-rw-r--r--sql/item_create.h8
-rw-r--r--sql/item_func.cc266
-rw-r--r--sql/item_func.h137
-rw-r--r--sql/item_strfunc.cc249
-rw-r--r--sql/item_strfunc.h50
-rw-r--r--sql/item_sum.cc327
-rw-r--r--sql/item_sum.h39
-rw-r--r--sql/item_timefunc.cc18
-rw-r--r--sql/item_timefunc.h126
-rw-r--r--sql/item_uniq.cc6
-rw-r--r--sql/item_uniq.h6
-rw-r--r--sql/key.cc12
-rw-r--r--sql/lex.h42
-rw-r--r--sql/lex_symbol.h6
-rw-r--r--sql/lock.cc169
-rw-r--r--sql/log.cc451
-rw-r--r--sql/log_event.cc1893
-rw-r--r--sql/log_event.h660
-rw-r--r--sql/matherr.c8
-rw-r--r--sql/mf_iocache.cc646
-rw-r--r--sql/mini_client.cc624
-rw-r--r--sql/mini_client.h42
-rw-r--r--sql/my_lock.c8
-rw-r--r--sql/mysql_priv.h171
-rw-r--r--sql/mysqld.cc905
-rw-r--r--sql/net_pkg.cc17
-rw-r--r--sql/net_serv.cc457
-rw-r--r--sql/opt_ft.h2
-rw-r--r--sql/opt_range.cc273
-rw-r--r--sql/opt_range.h26
-rw-r--r--sql/opt_sum.cc21
-rw-r--r--sql/password.c8
-rw-r--r--sql/procedure.cc6
-rw-r--r--sql/procedure.h6
-rw-r--r--sql/records.cc19
-rw-r--r--sql/repl_failsafe.cc853
-rw-r--r--sql/repl_failsafe.h38
-rw-r--r--sql/share/Makefile.am6
-rw-r--r--sql/share/charsets/Index4
-rw-r--r--sql/share/czech/errmsg.txt383
-rw-r--r--sql/share/danish/errmsg.txt9
-rw-r--r--sql/share/dutch/errmsg.txt38
-rw-r--r--sql/share/english/errmsg.txt9
-rw-r--r--sql/share/estonian/errmsg.txt358
-rw-r--r--sql/share/french/errmsg.txt9
-rw-r--r--sql/share/german/errmsg.txt9
-rw-r--r--sql/share/greek/errmsg.txt9
-rw-r--r--sql/share/hungarian/errmsg.txt9
-rw-r--r--sql/share/italian/errmsg.txt9
-rw-r--r--sql/share/japanese/errmsg.txt9
-rw-r--r--sql/share/korean/errmsg.txt9
-rw-r--r--sql/share/norwegian-ny/errmsg.txt9
-rw-r--r--sql/share/norwegian/errmsg.txt9
-rw-r--r--sql/share/polish/errmsg.txt9
-rw-r--r--sql/share/portuguese/errmsg.txt9
-rw-r--r--sql/share/romanian/errmsg.txt9
-rw-r--r--sql/share/russian/errmsg.txt9
-rw-r--r--sql/share/slovak/errmsg.txt9
-rw-r--r--sql/share/spanish/errmsg.txt9
-rw-r--r--sql/share/swedish/errmsg.OLD20
-rw-r--r--sql/share/swedish/errmsg.txt9
-rw-r--r--sql/share/ukrainian/errmsg.txt9
-rw-r--r--sql/slave.cc2283
-rw-r--r--sql/slave.h395
-rw-r--r--sql/sql_acl.cc381
-rw-r--r--sql/sql_acl.h11
-rw-r--r--sql/sql_analyse.cc45
-rw-r--r--sql/sql_analyse.h37
-rw-r--r--sql/sql_base.cc377
-rw-r--r--sql/sql_cache.cc3460
-rw-r--r--sql/sql_cache.h418
-rw-r--r--sql/sql_class.cc65
-rw-r--r--sql/sql_class.h338
-rw-r--r--sql/sql_crypt.cc6
-rw-r--r--sql/sql_crypt.h6
-rw-r--r--sql/sql_db.cc256
-rw-r--r--sql/sql_delete.cc573
-rw-r--r--sql/sql_do.cc2
-rw-r--r--sql/sql_handler.cc278
-rw-r--r--sql/sql_insert.cc101
-rw-r--r--sql/sql_lex.cc78
-rw-r--r--sql/sql_lex.h85
-rw-r--r--sql/sql_list.cc8
-rw-r--r--sql/sql_list.h96
-rw-r--r--sql/sql_load.cc132
-rw-r--r--sql/sql_manager.cc8
-rw-r--r--sql/sql_map.cc6
-rw-r--r--sql/sql_map.h6
-rw-r--r--sql/sql_parse.cc1680
-rw-r--r--sql/sql_rename.cc29
-rw-r--r--sql/sql_repl.cc877
-rw-r--r--sql/sql_repl.h48
-rw-r--r--sql/sql_select.cc1227
-rw-r--r--sql/sql_select.h40
-rw-r--r--sql/sql_show.cc337
-rw-r--r--sql/sql_sort.h55
-rw-r--r--sql/sql_string.cc119
-rw-r--r--sql/sql_string.h30
-rw-r--r--sql/sql_table.cc440
-rw-r--r--sql/sql_test.cc9
-rw-r--r--sql/sql_udf.cc17
-rw-r--r--sql/sql_udf.h6
-rw-r--r--sql/sql_union.cc254
-rw-r--r--sql/sql_update.cc526
-rw-r--r--sql/sql_yacc.yy1291
-rw-r--r--sql/stacktrace.c12
-rw-r--r--sql/structs.h37
-rw-r--r--sql/table.cc25
-rw-r--r--sql/table.h19
-rw-r--r--sql/thr_malloc.cc10
-rw-r--r--sql/time.cc27
-rw-r--r--sql/udf_example.cc8
-rw-r--r--sql/uniques.cc166
-rw-r--r--sql/unireg.cc12
-rw-r--r--sql/unireg.h8
-rw-r--r--strings/Makefile.am4
-rw-r--r--strings/atof.c31
-rw-r--r--strings/bchange.c34
-rw-r--r--strings/bcmp.c48
-rw-r--r--strings/bcopy-duff.c29
-rw-r--r--strings/bfill.c18
-rw-r--r--strings/bmove.c18
-rw-r--r--strings/bmove512.c31
-rw-r--r--strings/bmove_upp.c31
-rw-r--r--strings/bzero.c16
-rw-r--r--strings/conf_to_src.c29
-rw-r--r--strings/ctype-big5.c31
-rw-r--r--strings/ctype-czech.c33
-rw-r--r--strings/ctype-euc_kr.c31
-rw-r--r--strings/ctype-gb2312.c31
-rw-r--r--strings/ctype-gbk.c35
-rw-r--r--strings/ctype-latin1_de.c361
-rw-r--r--strings/ctype-sjis.c31
-rw-r--r--strings/ctype-tis620.c18
-rw-r--r--strings/ctype-ujis.c18
-rw-r--r--strings/ctype.c33
-rw-r--r--strings/do_ctype.c31
-rw-r--r--strings/int2str.c31
-rw-r--r--strings/is_prefix.c31
-rw-r--r--strings/llstr.c31
-rw-r--r--strings/longlong2str.c31
-rw-r--r--strings/memcmp.c29
-rw-r--r--strings/memcpy.c29
-rw-r--r--strings/memset.c18
-rw-r--r--strings/r_strinstr.c31
-rw-r--r--strings/str2int.c34
-rw-r--r--strings/str_test.c31
-rw-r--r--strings/strappend.c33
-rw-r--r--strings/strcat.c16
-rw-r--r--strings/strcend.c31
-rw-r--r--strings/strchr.c16
-rw-r--r--strings/strcmp.c16
-rw-r--r--strings/strcont.c31
-rw-r--r--strings/strend.c18
-rw-r--r--strings/strfill.c31
-rw-r--r--strings/strings-not-used.h18
-rw-r--r--strings/strinstr.c31
-rw-r--r--strings/strlen.c16
-rw-r--r--strings/strmake.c31
-rw-r--r--strings/strmov.c31
-rw-r--r--strings/strnlen.c31
-rw-r--r--strings/strnmov.c31
-rw-r--r--strings/strrchr.c16
-rw-r--r--strings/strstr.c18
-rw-r--r--strings/strto.c31
-rw-r--r--strings/strtol.c31
-rw-r--r--strings/strtoll.c31
-rw-r--r--strings/strtoul.c31
-rw-r--r--strings/strtoull.c31
-rw-r--r--strings/strxmov.c18
-rw-r--r--strings/strxnmov.c18
-rw-r--r--strings/t_ctype.h20
-rw-r--r--strings/udiv.c31
-rw-r--r--support-files/binary-configure.sh2
-rwxr-xr-xsupport-files/build-tags9
-rw-r--r--support-files/mysql-max.spec.sh4
-rw-r--r--support-files/mysql-multi.server.sh8
-rw-r--r--support-files/mysql.server.sh8
-rw-r--r--support-files/mysql.spec.sh39
-rwxr-xr-xtests/fork2_test.pl2
-rwxr-xr-xtests/fork_big.pl2
-rwxr-xr-xtests/insert_and_repair.pl2
-rwxr-xr-xtests/mail_to_db.pl110
-rw-r--r--tests/myisam-big-rows.tst72
-rwxr-xr-xtests/rename_test.pl2
-rwxr-xr-xtests/test_delayed_insert.pl2
-rw-r--r--tools/Makefile.am20
-rw-r--r--tools/managertest1.nc16
-rw-r--r--tools/mysqlmanager-sample.pwd1
-rw-r--r--tools/mysqlmanager.c1857
-rw-r--r--vio/Makefile.am27
-rw-r--r--vio/Vio.cc23
-rw-r--r--vio/Vio.h64
-rw-r--r--vio/VioAcceptorFd.cc18
-rw-r--r--vio/VioAcceptorFd.h23
-rw-r--r--vio/VioConnectorFd.cc22
-rw-r--r--vio/VioConnectorFd.h19
-rw-r--r--vio/VioFd.cc156
-rw-r--r--vio/VioFd.h38
-rw-r--r--vio/VioPipe.cc25
-rw-r--r--vio/VioPipe.h38
-rw-r--r--vio/VioSSL.cc292
-rw-r--r--vio/VioSSL.h54
-rw-r--r--vio/VioSSLAcceptorFd.cc4
-rw-r--r--vio/VioSSLFactoriesFd.cc360
-rw-r--r--vio/VioSSLFactoriesFd.h64
-rw-r--r--vio/VioSocket.cc326
-rw-r--r--vio/VioSocket.h55
-rw-r--r--vio/test-ssl.c147
-rw-r--r--vio/test-sslclient.c105
-rw-r--r--vio/test-sslserver.c157
-rw-r--r--vio/version.cc7
-rw-r--r--vio/vio-global.h33
-rw-r--r--vio/vio.c132
-rw-r--r--vio/vioelitexx.cc26
-rw-r--r--vio/violite.h101
-rw-r--r--vio/viosocket.c (renamed from sql/violite.c)178
-rw-r--r--vio/viossl.c360
-rw-r--r--vio/viosslfactories.c344
-rw-r--r--vio/viotest-ssl.c156
-rw-r--r--vio/viotest-ssl.cc104
-rw-r--r--vio/viotypes.h32
1278 files changed, 152725 insertions, 33502 deletions
diff --git a/.bzrignore b/.bzrignore
index 1699cf52943..6781375218d 100644
--- a/.bzrignore
+++ b/.bzrignore
@@ -7,6 +7,7 @@
*.la
*.lo
*.o
+*.reject
*.spec
*/*_pure_*warnings
*/.pure
@@ -20,6 +21,8 @@
.out
.snprj/*
.vimrc
+50
+=6
BitKeeper/etc/config
BitKeeper/etc/csets
BitKeeper/etc/csets-in
@@ -32,6 +35,7 @@ BitKeeper/tmp/bkr3sAHD
BitKeeper/tmp/gone
COPYING
COPYING.LIB
+Docs/#manual.texi#
Docs/INSTALL-BINARY
Docs/include.texi
Docs/manual.aux
@@ -54,6 +58,8 @@ Docs/manual_letter.ps
Docs/manual_toc.html
Docs/my_sys.doc
Docs/mysql.info
+Docs/tex.fmt
+Docs/texi2dvi.out
INSTALL-SOURCE
Logs/*
MIRRORS
@@ -115,17 +121,32 @@ bdb/dist/template/rec_txn
bdb/examples_java
bdb/hash/hash_auto.c
bdb/include/btree_auto.h
+bdb/include/btree_ext.h
+bdb/include/clib_ext.h
+bdb/include/common_ext.h
bdb/include/crdel_auto.h
bdb/include/db_auto.h
+bdb/include/db_ext.h
bdb/include/db_server.h
+bdb/include/env_ext.h
bdb/include/gen_client_ext.h
bdb/include/gen_server_ext.h
bdb/include/hash_auto.h
+bdb/include/hash_ext.h
+bdb/include/lock_ext.h
bdb/include/log_auto.h
+bdb/include/log_ext.h
+bdb/include/mp_ext.h
+bdb/include/mutex_ext.h
+bdb/include/os_ext.h
bdb/include/qam_auto.h
+bdb/include/qam_ext.h
bdb/include/rpc_client_ext.h
bdb/include/rpc_server_ext.h
+bdb/include/tcl_ext.h
bdb/include/txn_auto.h
+bdb/include/txn_ext.h
+bdb/include/xa_ext.h
bdb/java/src/com/sleepycat/db/DbConstants.java
bdb/log/log_auto.c
bdb/qam/qam_auto.c
@@ -151,6 +172,8 @@ client/mysqlbinlog
client/mysqlcheck
client/mysqldump
client/mysqlimport
+client/mysqlmanager-pwgen
+client/mysqlmanagerc
client/mysqlshow
client/mysqltest
client/mysys_priv.h
@@ -168,6 +191,7 @@ db-*.*.*
dbug/user.t
extra/comp_err
extra/my_print_defaults
+extra/mysql_install
extra/perror
extra/replace
extra/resolve_stack_dump
@@ -179,6 +203,8 @@ include/my_config.h
include/my_global.h
include/mysql_version.h
include/widec.h
+innobase/conftest.s1
+innobase/conftest.subs
innobase/ib_config.h
innobase/ib_config.h.in
isam/isamchk
@@ -196,12 +222,113 @@ libmysql_r/acconfig.h
libmysql_r/conf_to_src
libmysql_r/my_static.h
libmysql_r/mysys_priv.h
+libmysqld/backup_dir
+libmysqld/convert.cc
+libmysqld/derror.cc
+libmysqld/errmsg.c
+libmysqld/examples/completion_hash.cc
+libmysqld/examples/completion_hash.h
+libmysqld/examples/link_sources
+libmysqld/examples/my_readline.h
+libmysqld/examples/mysql
+libmysqld/examples/mysql.cc
+libmysqld/examples/mysqltest
+libmysqld/examples/mysqltest.c
+libmysqld/examples/readline.cc
+libmysqld/examples/sql_string.cc
+libmysqld/examples/sql_string.h
+libmysqld/examples/test-gdbinit
+libmysqld/field.cc
+libmysqld/field_conv.cc
+libmysqld/filesort.cc
+libmysqld/get_password.c
+libmysqld/ha_berkeley.cc
+libmysqld/ha_heap.cc
+libmysqld/ha_innobase.cc
+libmysqld/ha_innodb.cc
+libmysqld/ha_isam.cc
+libmysqld/ha_isammrg.cc
+libmysqld/ha_myisam.cc
+libmysqld/ha_myisammrg.cc
+libmysqld/handler.cc
+libmysqld/hash_filo.cc
+libmysqld/hostname.cc
+libmysqld/init.cc
+libmysqld/item.cc
+libmysqld/item_buff.cc
+libmysqld/item_cmpfunc.cc
+libmysqld/item_create.cc
+libmysqld/item_func.cc
+libmysqld/item_strfunc.cc
+libmysqld/item_sum.cc
+libmysqld/item_timefunc.cc
+libmysqld/item_uniq.cc
+libmysqld/key.cc
+libmysqld/lock.cc
+libmysqld/log.cc
+libmysqld/log_event.cc
+libmysqld/md5.c
+libmysqld/mf_iocache.cc
+libmysqld/mini_client.cc
+libmysqld/net_pkg.cc
+libmysqld/net_serv.cc
+libmysqld/opt_ft.cc
+libmysqld/opt_range.cc
+libmysqld/opt_sum.cc
+libmysqld/password.c
+libmysqld/procedure.cc
+libmysqld/records.cc
+libmysqld/repl_failsafe.cc
+libmysqld/simple-test
+libmysqld/slave.cc
+libmysqld/sql_acl.cc
+libmysqld/sql_analyse.cc
+libmysqld/sql_base.cc
+libmysqld/sql_cache.cc
+libmysqld/sql_class.cc
+libmysqld/sql_command
+libmysqld/sql_crypt.cc
+libmysqld/sql_db.cc
+libmysqld/sql_delete.cc
+libmysqld/sql_do.cc
+libmysqld/sql_handler.cc
+libmysqld/sql_insert.cc
+libmysqld/sql_lex.cc
+libmysqld/sql_list.cc
+libmysqld/sql_load.cc
+libmysqld/sql_manager.cc
+libmysqld/sql_map.cc
+libmysqld/sql_parse.cc
+libmysqld/sql_rename.cc
+libmysqld/sql_repl.cc
+libmysqld/sql_select.cc
+libmysqld/sql_show.cc
+libmysqld/sql_string.cc
+libmysqld/sql_table.cc
+libmysqld/sql_test.cc
+libmysqld/sql_udf.cc
+libmysqld/sql_union.cc
+libmysqld/sql_unions.cc
+libmysqld/sql_update.cc
+libmysqld/sql_yacc.cc
+libmysqld/stacktrace.c
+libmysqld/table.cc
+libmysqld/thr_malloc.cc
+libmysqld/time.cc
+libmysqld/uniques.cc
+libmysqld/unireg.cc
libtool
linked_client_sources
linked_include_sources
linked_libmysql_r_sources
linked_libmysql_sources
+linked_libmysqld_sources
+linked_libmysqldex_sources
linked_server_sources
+linked_tools_sources
+locked
+myisam/FT1.MYD
+myisam/FT1.MYI
myisam/ft_dump
myisam/ft_eval
myisam/ft_test1
@@ -218,14 +345,23 @@ mysql-test/gmon.out
mysql-test/install_test_db
mysql-test/mysql-test-run
mysql-test/r/*.reject
+mysql-test/r/rpl000002.eval
+mysql-test/r/rpl000014.eval
+mysql-test/r/rpl000015.eval
+mysql-test/r/rpl000016.eval
+mysql-test/r/rpl_log.eval
+mysql-test/r/slave-running.eval
+mysql-test/r/slave-stopped.eval
mysql-test/share/mysql
mysql-test/var/*
mysql.kdevprj
mysql.proj
mysqld.S
mysqld.sym
+mysys/#mf_iocache.c#
mysys/test_charset
mysys/test_dir
+mysys/test_io_cache
mysys/test_thr_alarm
mysys/test_thr_lock
mysys/testhash
@@ -239,7 +375,9 @@ scripts/make_binary_distribution
scripts/msql2mysql
scripts/mysql_config
scripts/mysql_convert_table_format
+scripts/mysql_explain_log
scripts/mysql_find_rows
+scripts/mysql_fix_extensions
scripts/mysql_fix_privilege_tables
scripts/mysql_install_db
scripts/mysql_setpermission
@@ -247,10 +385,12 @@ scripts/mysql_zap
scripts/mysqlaccess
scripts/mysqlbug
scripts/mysqld_multi
+scripts/mysqld_safe
scripts/mysqldumpslow
scripts/mysqlhotcopy
scripts/safe_mysqld
sql-bench/Results-linux/ATIS-mysql_bdb-Linux_2.2.14_my_SMP_i686
+sql-bench/bench-count-distinct
sql-bench/bench-init.pl
sql-bench/compare-results
sql-bench/compare-results-all
@@ -269,6 +409,7 @@ sql-bench/test-connect
sql-bench/test-create
sql-bench/test-insert
sql-bench/test-select
+sql-bench/test-transactions
sql-bench/test-wisconsin
sql/.gdbinit
sql/gen_lex_hash
@@ -277,11 +418,17 @@ sql/lex_hash.h
sql/mini_client_errors.c
sql/mysqlbinlog
sql/mysqld
+sql/mysqld-purecov
+sql/mysqld-purify
+sql/mysqld-quantify
+sql/new.cc
sql/share/*.sys
sql/share/charsets/gmon.out
sql/share/gmon.out
+sql/share/mysql
sql/share/norwegian-ny/errmsg.sys
sql/share/norwegian/errmsg.sys
+sql/sql_select.cc.orig
sql/sql_yacc.cc
sql/sql_yacc.h
stamp-h
@@ -303,5 +450,13 @@ support-files/mysql.server
support-files/mysql.spec
tags
tmp/*
-bdb/include/db_ext.h
-bdb/include/mutex_ext.h
+tools/my_vsnprintf.c
+tools/mysqlmanager
+tools/mysqlmngd
+tools/mysys_priv.h
+vio/test-ssl
+vio/test-sslclient
+vio/test-sslserver
+vio/viotest-ssl
+Docs/mysql.xml
+mysql-test/r/rpl000001.eval
diff --git a/BUILD/Makefile.am b/BUILD/Makefile.am
new file mode 100644
index 00000000000..438b3a528cd
--- /dev/null
+++ b/BUILD/Makefile.am
@@ -0,0 +1,44 @@
+# Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the Free
+# Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+# MA 02111-1307, USA
+
+## Process this file with automake to create Makefile.in
+
+EXTRA_DIST = FINISH.sh \
+ SETUP.sh \
+ compile-alpha \
+ compile-alpha-ccc \
+ compile-alpha-cxx \
+ compile-alpha-debug \
+ compile-ia64-debug-max \
+ compile-pentium \
+ compile-pentium-debug \
+ compile-pentium-debug-max \
+ compile-pentium-debug-no-bdb \
+ compile-pentium-debug-openssl \
+ compile-pentium-gcov \
+ compile-pentium-gprof \
+ compile-pentium-max \
+ compile-pentium-myodbc \
+ compile-pentium-mysqlfs-debug \
+ compile-pentium-pgcc \
+ compile-solaris-sparc \
+ compile-solaris-sparc-debug \
+ compile-solaris-sparc-fortre \
+ compile-solaris-sparc-purify
+
+# Don't update the files from bitkeeper
+%::SCCS/s.%
diff --git a/BUILD/compile-alpha-cxx b/BUILD/compile-alpha-cxx
index 2992604644b..3e6eee9a0d6 100755
--- a/BUILD/compile-alpha-cxx
+++ b/BUILD/compile-alpha-cxx
@@ -1,17 +1,17 @@
/bin/rm -f */.deps/*.P */*.o
make -k clean
/bin/rm -f */.deps/*.P */*.o
-/bin/rm -f config.cache mysql-*.tar.gz
+/bin/rm -f */.deps/*.P config.cache innobase/config.cache bdb/build_unix/config.cache mysql-*.tar.gz
aclocal; autoheader; aclocal; automake; autoconf
-CC=ccc CFLAGS="-fast" CXX=cxx CXXFLAGS="-fast -noexceptions -nortti" ./configure --prefix=/usr/local/mysql --disable-shared --with-extra-charsets=complex --enable-thread-safe-client --with-mysqld-ldflags=-non_shared --with-client-ldflags=-non_shared
+CC=ccc CFLAGS="-fast" CXX=cxx CXXFLAGS="-fast -noexceptions -nortti" ./configure --prefix=/usr/local/mysql --disable-shared --with-extra-charsets=complex --enable-thread-safe-client --with-mysqld-ldflags=-non_shared --with-client-ldflags=-non_shared --without-extra-tools
-make
-rm */.deps/*
+make -j2
+find . -name ".deps" | xargs rm -r
make
if [ $? = 0 ]
then
- rm */.deps/*
+ find . -name ".deps" | xargs rm -r
bin/mysqladmin shutdown
sur make install
if [ $? = 0 ]
diff --git a/BUILD/compile-alpha-debug b/BUILD/compile-alpha-debug
index 6672027445e..60d1b9af659 100755
--- a/BUILD/compile-alpha-debug
+++ b/BUILD/compile-alpha-debug
@@ -1,7 +1,8 @@
+/bin/rm -f */.deps/*.P */*.o
make -k clean
-/bin/rm -f */.deps/*.P
-/bin/rm -f config.cache
+/bin/rm -f */.deps/*.P */*.o
+/bin/rm -f */.deps/*.P config.cache innobase/config.cache bdb/build_unix/config.cache mysql-*.tar.gz
aclocal; autoheader; aclocal; automake; autoconf
-CFLAGS=-O6 CXX=gcc CXXFLAGS="-O6 -felide-constructors -fno-exceptions -fno-rtti" ./configure --prefix=/usr/local/mysql --with-debug
+CFLAGS=-O1 CC=gcc CXX=gcc CXXFLAGS="-O1 -felide-constructors -fno-exceptions -fno-rtti" ./configure --prefix=/usr/local/mysql --with-debug --with-extra-charsets=complex --without-extra-tools
make
diff --git a/BUILD/compile-ia64-debug-max b/BUILD/compile-ia64-debug-max
new file mode 100755
index 00000000000..9cd54de428d
--- /dev/null
+++ b/BUILD/compile-ia64-debug-max
@@ -0,0 +1,13 @@
+gmake -k clean || true
+/bin/rm -f */.deps/*.P config.cache innobase/config.cache bdb/build_unix/config.cache
+
+aclocal && autoheader && aclocal && automake && autoconf
+(cd bdb/dist && sh s_all)
+(cd innobase && aclocal && autoheader && aclocal && automake && autoconf)
+if [ -d gemini ]
+then
+ (cd gemini && aclocal && autoheader && aclocal && automake && autoconf)
+fi
+
+CC=ecc CFLAGS="-w1 -DEXTRA_DEBUG -DSAFEMALLOC -DSAFE_MUTEX -O2" CXX=ecc CXXFLAGS="-w1 -DEXTRA_DEBUG -DSAFEMALLOC -DSAFE_MUTEX -O2" ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex --enable-thread-safe-client --with-mysqld-ldflags=-all-static --with-client-ldflags=-all-static --with-debug --with-innodb --with-embedded-server
+gmake
diff --git a/BUILD/compile-pentium-debug-max b/BUILD/compile-pentium-debug-max
index 993c48565b8..d320f968c4e 100755
--- a/BUILD/compile-pentium-debug-max
+++ b/BUILD/compile-pentium-debug-max
@@ -8,6 +8,6 @@ c_warnings="$c_warnings $debug_extra_warnings"
cxx_warnings="$cxx_warnings $debug_extra_warnings"
extra_configs="$pentium_configs $debug_configs"
-extra_configs="$extra_configs --with-berkeley-db --with-innodb --enable-local-infile"
+extra_configs="$extra_configs --with-berkeley-db --with-innodb --with-embedded-server --with-openssl --enable-local-infile"
. "$path/FINISH.sh"
diff --git a/BUILD/compile-pentium-debug-no-bdb b/BUILD/compile-pentium-debug-no-bdb
index fad58bec437..d7e70f868cc 100755
--- a/BUILD/compile-pentium-debug-no-bdb
+++ b/BUILD/compile-pentium-debug-no-bdb
@@ -4,6 +4,6 @@ path=`dirname $0`
. "$path/SETUP.sh"
extra_flags="$pentium_cflags $debug_cflags"
-extra_configs="$pentium_configs $debug_configs --without-berkeley-db"
+extra_configs="$pentium_configs $debug_configs --without-berkeley-db $static_link"
. "$path/FINISH.sh"
diff --git a/BUILD/compile-pentium-debug-openssl b/BUILD/compile-pentium-debug-openssl
new file mode 100755
index 00000000000..5de1c18a5d7
--- /dev/null
+++ b/BUILD/compile-pentium-debug-openssl
@@ -0,0 +1,13 @@
+#! /bin/sh
+
+path=`dirname $0`
+. "$path/SETUP.sh"
+
+extra_flags="$pentium_cflags $debug_cflags"
+c_warnings="$c_warnings $debug_extra_warnings"
+cxx_warnings="$cxx_warnings $debug_extra_warnings"
+extra_configs="$pentium_configs $debug_configs"
+
+extra_configs="$extra_configs --with-debug=full --with-vio --with-openssl --without-innodb"
+
+. "$path/FINISH.sh"
diff --git a/BUILD/compile-pentium-max b/BUILD/compile-pentium-max
index 55f88ef4748..9838e6a287b 100755
--- a/BUILD/compile-pentium-max
+++ b/BUILD/compile-pentium-max
@@ -8,6 +8,6 @@ extra_configs="$pentium_configs"
strip=yes
extra_configs="$extra_configs --with-innodb --with-berkeley-db \
- --enable-thread-safe-client"
+ --enable-thread-safe-client --with-openssl --with-vio"
. "$path/FINISH.sh"
diff --git a/BUILD/compile-pentium-mysqlfs-debug b/BUILD/compile-pentium-mysqlfs-debug
new file mode 100755
index 00000000000..6643553d943
--- /dev/null
+++ b/BUILD/compile-pentium-mysqlfs-debug
@@ -0,0 +1,13 @@
+#! /bin/sh
+
+path=`dirname $0`
+. "$path/SETUP.sh"
+
+extra_flags="$pentium_cflags $debug_cflags"
+c_warnings="$c_warnings $debug_extra_warnings"
+cxx_warnings="$cxx_warnings $debug_extra_warnings"
+extra_configs="$pentium_configs $debug_configs $static_link"
+
+extra_configs="$extra_configs --with-debug=full --with-mysqlfs --without-server --without-pstack"
+
+. "$path/FINISH.sh"
diff --git a/BUILD/compile-pentium-pgcc b/BUILD/compile-pentium-pgcc
index ee70fd2bde0..2d806009b21 100755
--- a/BUILD/compile-pentium-pgcc
+++ b/BUILD/compile-pentium-pgcc
@@ -1,10 +1,21 @@
AM_MAKEFLAGS="-j 2"
-make -k clean
+gmake -k clean || true
/bin/rm -f */.deps/*.P config.cache
-
-aclocal; autoheader; aclocal; automake; autoconf
-
+
+aclocal && autoheader && aclocal && automake && autoconf
+(cd bdb/dist && sh s_all)
+(cd innobase && aclocal && autoheader && aclocal && automake && autoconf)
+if [ -d gemini ]
+then
+ (cd gemini && aclocal && autoheader && aclocal && automake && autoconf)
+fi
+
export PATH=/usr/local/pgcc/bin:$PATH
-CFLAGS="-O6 -mpentiumpro -fomit-frame-pointer -mstack-align-double" CXX=gcc CXXFLAGS="-O6 -mpentiumpro -fomit-frame-pointer -felide-constructors -fno-exceptions -fno-rtti -mstack-align-double" ./configure --prefix=/usr/local/mysql --enable-assembler --with-mysqld-ldflags=-all-static --disable-shared --with-extra-charsets=complex --enable-thread-safe-client
-make -j 2
+CFLAGS="-Wimplicit -Wreturn-type -Wid-clash-51 -Wswitch -Wtrigraphs -Wcomment -W -Wchar-subscripts -Wformat -Wimplicit-function-dec -Wimplicit-int -Wparentheses -Wsign-compare -Wwrite-strings -Wunused -O6 -mpentiumpro -fomit-frame-pointer -mstack-align-double" CXX=gcc CXXFLAGS="-Wimplicit -Wreturn-type -Wid-clash-51 -Wswitch -Wtrigraphs -Wcomment -W -Wchar-subscripts -Wformat -Wimplicit-function-dec -Wimplicit-int -Wparentheses -Wsign-compare -Wwrite-strings -Woverloaded-virtual -Wextern-inline -Wsign-promo -Wreorder -Wctor-dtor-privacy -Wnon-virtual-dtor -felide-constructors -fno-exceptions -fno-rtti -O6 -fomit-frame-pointer -mpentiumpro -mstack-align-double" ./configure --prefix=/usr/local/mysql --enable-assembler --with-extra-charsets=complex --enable-thread-safe-client --with-mysqld-ldflags=-all-static --with-client-ldflags=-all-static
+
+gmake -j 4
+
+mkdir -p tmp
+nm --numeric-sort sql/mysqld > tmp/mysqld.sym
+objdump -d sql/mysqld > tmp/mysqld.S
strip sql/mysqld
diff --git a/BUILD/compile-pentium-symbols b/BUILD/compile-pentium-symbols
deleted file mode 100755
index 4f63763606f..00000000000
--- a/BUILD/compile-pentium-symbols
+++ /dev/null
@@ -1,15 +0,0 @@
-#! /bin/sh
-
-path=`dirname $0`
-. "$path/SETUP.sh"
-
-extra_flags="$pentium_cflags $fast_cflags -g"
-extra_configs="$pentium_configs"
-
-# Use the optimized version if it exists
-if test -d /usr/local/BerkeleyDB-opt/
-then
- extra_configs="$extra_configs --with-berkeley-db=/usr/local/BerkeleyDB-opt/"
-fi
-
-. "$path/FINISH.sh"
diff --git a/BUILD/compile-solaris-sparc-debug b/BUILD/compile-solaris-sparc-debug
new file mode 100755
index 00000000000..0b6a7219593
--- /dev/null
+++ b/BUILD/compile-solaris-sparc-debug
@@ -0,0 +1,16 @@
+#! /bin/sh
+
+gmake -k clean || true
+/bin/rm -f */.deps/*.P config.cache
+
+aclocal && autoheader && aclocal && automake && autoconf
+(cd bdb/dist && sh s_all)
+(cd innobase && aclocal && autoheader && aclocal && automake && autoconf)
+if [ -d gemini ]
+then
+ (cd gemini && aclocal && autoheader && aclocal && automake && autoconf)
+fi
+
+CFLAGS="-g -Wimplicit -Wreturn-type -Wid-clash-51 -Wswitch -Wtrigraphs -Wcomment -W -Wchar-subscripts -Wformat -Wimplicit-function-dec -Wimplicit-int -Wparentheses -Wsign-compare -Wwrite-strings -Wunused -O3 -fno-omit-frame-pointer -mcpu=v8 -Wa,-xarch=v8plusa" CXX=gcc CXXFLAGS="-Wimplicit -Wreturn-type -Wid-clash-51 -Wswitch -Wtrigraphs -Wcomment -W -Wchar-subscripts -Wformat -Wimplicit-function-dec -Wimplicit-int -Wparentheses -Wsign-compare -Wwrite-strings -Woverloaded-virtual -Wextern-inline -Wsign-promo -Wreorder -Wctor-dtor-privacy -Wnon-virtual-dtor -felide-constructors -fno-exceptions -fno-rtti -O3 -fno-omit-frame-pointer -mcpu=v8 -Wa,-xarch=v8plusa -g" ./configure --prefix=/usr/local/mysql --enable-assembler --with-extra-charsets=complex --enable-thread-safe-client --with-debug
+
+gmake -j 4
diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok
index 03e5543a92f..fc2cbd97a56 100644
--- a/BitKeeper/etc/logging_ok
+++ b/BitKeeper/etc/logging_ok
@@ -1,14 +1,47 @@
+Administrator@co3064164-a.
+Administrator@co3064164-a.rochd1.qld.optushome.com.au
+Administrator@fred.
Miguel@light.local
+Sinisa@sinisa.nasamreza.org
+ahlentz@co3064164-a.rochd1.qld.optusnet.com.au
+arjen@co3064164-a.bitbike.com
+bell@sanja.is.com.ua
+davida@isil.mysql.com
heikki@donna.mysql.fi
+heikki@hundin.mysql.fi
+jani@hynda.mysql.fi
+jani@janikt.pp.saunalahti.fi
+jani@rhols221.adsl.netsonic.fi
+jcole@abel.spaceapes.com
+jcole@main.burghcom.com
+jcole@sarvik.tfr.cafe.ee
+jcole@tetra.spaceapes.com
jorge@linux.jorge.mysql.com
+kaj@work.mysql.com
miguel@light.local
monty@bitch.mysql.fi
monty@donna.mysql.fi
monty@hundin.mysql.fi
monty@tik.mysql.fi
+monty@tramp.mysql.fi
monty@work.mysql.com
mwagner@cash.mwagner.org
+mwagner@evoq.mwagner.org
paul@central.snake.net
+paul@teton.kitebird.com
+root@x3.internalnet
sasha@mysql.sashanet.com
serg@serg.mysql.com
-heikki@hundin.mysql.fi
+tfr@sarvik.tfr.cafe.ee
+tim@bitch.mysql.fi
+tim@black.box
+tim@hundin.mysql.fi
+tim@threads.polyesthetic.msg
+tim@white.box
+tim@work.mysql.com
+tom@basil-firewall.home.com
+tonu@hundin.mysql.fi
+tonu@volk.internalnet
+tonu@x153.internalnet
+tonu@x3.internalnet
+venu@work.mysql.com
diff --git a/BitKeeper/triggers/post-commit b/BitKeeper/triggers/post-commit
index dc5f2f2b824..275c278f29d 100755
--- a/BitKeeper/triggers/post-commit
+++ b/BitKeeper/triggers/post-commit
@@ -4,6 +4,7 @@
TO=dev-public@mysql.com
FROM=$USER@mysql.com
INTERNALS=internals@lists.mysql.com
+DOCS=docs-commit@mysql.com
LIMIT=10000
if [ "$REAL_EMAIL" = "" ]
@@ -17,37 +18,65 @@ BK_STATUS=$BK_STATUS$BK_COMMIT
if [ "$BK_STATUS" = OK ]
then
+
+#++
+# dev-public@
+#--
echo "Commit successful, notifying developers at $TO"
(
cat <<EOF
-List-ID: <bk.mysql>
+List-ID: <bk.mysql-4.0>
From: $FROM
To: $TO
-Subject: bk commit into 3.23 tree
+Subject: bk commit - 4.0 tree
EOF
bk changes -v -r+
bk cset -r+ -d
) | head -n $LIMIT | /usr/sbin/sendmail -t
+
+#++
+# internals@ mail
+#--
echo "Notifying internals list at $INTERNALS"
(
cat <<EOF
-List-ID: <bk.mysql>
+List-ID: <bk.mysql-4.0>
From: $FROM
To: $INTERNALS
-Subject: bk commit into 3.23 tree
+Subject: bk commit into 4.0 tree
+
+Below is the list of changes that have just been committed into a
+4.0 repository of $USER. When $USER does a push, they will be propogated to
+the main repository and within 24 hours after the push to the public repository.
+For information on how to access the public repository
+see http://www.mysql.com/doc/I/n/Installing_source_tree.html
+
+EOF
+ bk changes -v -r+
+ bk cset -r+ -d
+ ) | head -n $LIMIT | /usr/sbin/sendmail -t
-Below is the list of changes that have just been commited into a local
-3.23. repository of $USER. When $USER does a push, they will be
-propogaged to the main repository and within 24 hours after the push into
-the public repository. For information on how to access
-the public repository see
-http://www.mysql.com/doc/I/n/Installing_source_tree.html
+#++
+# docs-commit@ mail
+#--
+ bk changes -v -r+ | grep -q Docs/manual.texi
+ if [ $? -eq 0 ]
+ then
+ echo "Notifying docs list at $DOCS"
+ (
+ cat <<EOF
+List-ID: <bk.mysql-4.0>
+From: $FROM
+To: $DOCS
+Subject: bk commit - 4.0 tree (Manual)
EOF
bk changes -v -r+
bk cset -r+ -d
) | head -n $LIMIT | /usr/sbin/sendmail -t
+ fi
+
else
echo "commit failed because '$BK_STATUS', sorry life is hard..."
fi
diff --git a/Build-tools/Do-all-build-steps b/Build-tools/Do-all-build-steps
index c236fe20f99..a9989aae768 100755
--- a/Build-tools/Do-all-build-steps
+++ b/Build-tools/Do-all-build-steps
@@ -63,9 +63,13 @@ aclocal; autoheader; aclocal; automake; autoconf
--with-low-memory \
--with-mit-threads=yes $EXTRA_CONFIG \
--enable-thread-safe-client \
- --with-berkeley-db \
--enable-local-infile \
- --with-innodb
+ --with-berkeley-db \
+ --with-innodb \
+ --with-vio \
+ --without-pstack \
+ --with-extra-tools \
+ --with-embedded-server
gmake -j 2
diff --git a/Build-tools/Do-compile b/Build-tools/Do-compile
index e0e7fb51933..39af865a68e 100755
--- a/Build-tools/Do-compile
+++ b/Build-tools/Do-compile
@@ -221,7 +221,7 @@ if ($opt_stage <= 5 && !$opt_no_test && !$opt_no_mysqltest)
{
system("mkdir $bench_tmpdir") if (! -d $bench_tmpdir);
safe_cd("${test_dir}/mysql-test");
- check_system("./mysql-test-run --tmpdir=$bench_tmpdir --master_port=$mysql_tcp_port --slave_port=$slave_port --sleep=10", "tests were successful");
+ check_system("./mysql-test-run --tmpdir=$bench_tmpdir --master_port=$mysql_tcp_port --slave_port=$slave_port --manager-port=$manager_port --no-manager --sleep=10", "tests were successful");
}
# Start the server if we are going to run any of the benchmarks
diff --git a/Build-tools/Do-rpm b/Build-tools/Do-rpm
index 046ba93a1dd..6ce8c9c3e45 100755
--- a/Build-tools/Do-rpm
+++ b/Build-tools/Do-rpm
@@ -5,6 +5,7 @@
function copy_to_bmachine
{
if [ x$local_build = x1 ]; then
+ rm -f $2
cp $1 $2
else
scp $1 $owner@$bmachine:$2
@@ -14,6 +15,7 @@ function copy_to_bmachine
function copy_from_bmachine
{
if [ x$local_build = x1 ]; then
+ rm -f $2
cp $1 $2
else
scp $owner@$bmachine:$1 $2
@@ -90,10 +92,7 @@ while test $# -gt 0; do
done
echo "Removing old MySQL packages"
-rm -rf $rpmdir/BUILD/mysql-*
-rm -f $rpmdir/SOURCES/mysql-*
-rm -f $rpmdir/SRPMS/MySQL-*
-rm -f $rpmdir/SPEC/mysql-*
+rm -f $bpath/NEW-RPMS/MySQL-*rpm
if [ ! -d "$logdir" ]; then
echo "$logdir does not exist, creating"
@@ -105,12 +104,20 @@ if [ ! -f "$tarball" ]; then
exit 1
fi
-echo "Building RPM for MySQL version $VER on $bmachine"
-
log=$logdir/Log-RPM-`date +%y%m%d-%H%M`
+echo "Building RPM for MySQL version $VER on $bmachine"
+echo "Details in $log"
+
(
set -x
+# remove old stuff
+rm -rf $rpmdir/BUILD/mysql-*
+rm -f $rpmdir/SOURCES/mysql-*
+rm -f $rpmdir/SRPMS/MySQL-*
+rm -f $rpmdir/SPECS/mysql-*
+rm -rf /var/tmp/mysql
+
# Copy MySQL source and spec files
#Sasha: I left the scp stuff commented out instead of deleted to make it
@@ -156,7 +163,7 @@ if [ ! x$skip_perl=x1 ]; then
set -x
# First clean up so we do not get old versions when wildcard matching
- rm -f $rpmdir/SOURCES/DBI-*.spec
+ rm -f $rpmdir/SOURCES/DBI-*.spec $rpmdir/SOURCES/mysql*
rm -f $rpmdir/RPMS/i386/Perl-*.rpm
rm -f $rpmdir/SRPMS/Perl-*.rpm
rm -f $rpmdir/RPMS/i386/MySQL*-$VER_NO_DASH*.rpm
@@ -226,5 +233,9 @@ if [ x$local_build != x1 ]; then
# And the perl ones
#scp $owner@$bmachine:$rpmdir/RPMS/i386/Perl*-*.rpm $bpath/NEW-RPMS
#scp $owner@$bmachine:$rpmdir/SRPMS/Perl*-*.rpm $bpath/NEW-RPMS
+
+ #Remove some of the files that can interfere with future builds
+
+ rm -rf /var/tmp/mysql
fi
) > $log 2>&1
diff --git a/Docs/Flags/belgium.eps b/Docs/Flags/belgium.eps
new file mode 100644
index 00000000000..295021fae58
--- /dev/null
+++ b/Docs/Flags/belgium.eps
@@ -0,0 +1,254 @@
+%!PS-Adobe-3.0 EPSF-3.0
+%%Creator: Adobe Photoshop Version 5.5
+%%Title: belgium.eps
+%%CreationDate: Fri Sep 14 2001 08:55:12
+%%BoundingBox: 0 0 32 22
+%%HiResBoundingBox: 0 0 32 22
+%%SuppressDotGainCompensation
+%%EndComments
+%%BeginProlog
+%%EndProlog
+%%BeginSetup
+%%EndSetup
+%ImageData: 32 22 8 3 1 32 2 "beginimage"
+%BeginPhotoshop: 1246
+% 3842494D03ED000000000010004800000001000200480000000100023842494D
+% 040D000000000004000000783842494D03F30000000000080000000000000000
+% 3842494D040A00000000000100003842494D271000000000000A000100000000
+% 000000023842494D03F5000000000048002F66660001006C6666000600000000
+% 0001002F6666000100A1999A0006000000000001003200000001005A00000006
+% 000000000001003500000001002D000000060000000000013842494D03F80000
+% 000000700000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF03E80000
+% 0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF03E800000000FFFF
+% FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF03E800000000FFFFFFFFFFFF
+% FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF03E800003842494D0408000000000010
+% 000000010000024000000240000000003842494D041400000000000400000001
+% 3842494D040C00000000035F0000000100000020000000160000006000000840
+% 0000034300180001FFD8FFE000104A46494600010201004800480000FFEE000E
+% 41646F626500648000000001FFDB0084000C08080809080C09090C110B0A0B11
+% 150F0C0C0F1518131315131318110C0C0C0C0C0C110C0C0C0C0C0C0C0C0C0C0C
+% 0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C010D0B0B0D0E0D100E0E10140E0E0E
+% 14140E0E0E0E14110C0C0C0C0C11110C0C0C0C0C0C110C0C0C0C0C0C0C0C0C0C
+% 0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0CFFC0001108001600200301220002
+% 1101031101FFDD00040002FFC4013F0000010501010101010100000000000000
+% 030001020405060708090A0B0100010501010101010100000000000000010002
+% 030405060708090A0B1000010401030204020507060805030C33010002110304
+% 211231054151611322718132061491A1B14223241552C16233347282D1430725
+% 9253F0E1F163733516A2B283264493546445C2A3743617D255E265F2B384C3D3
+% 75E3F3462794A485B495C4D4E4F4A5B5C5D5E5F55666768696A6B6C6D6E6F637
+% 475767778797A7B7C7D7E7F71100020201020404030405060707060535010002
+% 1103213112044151617122130532819114A1B14223C152D1F0332462E1728292
+% 435315637334F1250616A2B283072635C2D2449354A317644555367465E2F2B3
+% 84C3D375E3F34694A485B495C4D4E4F4A5B5C5D5E5F55666768696A6B6C6D6E6
+% F62737475767778797A7B7C7FFDA000C03010002110311003F00F2A5E93FE2D7
+% A4F4ACDE857DB9987464D8DCA7B43EEA98F7068AE876DDD635DEDF72F365EA9F
+% E2ABFF0013D91FF871FF00F9EB1D657C76528F244C4989E38EB134CFCA80726B
+% D8B2FAE9D17A3E374BAACC6C0C6A5E6F6B4BABA58D31B2D3B7731A3C170F938D
+% 8EDC7B48A9808638821A26617A2FD7CFF9229FFC30DFFA8B979F657F45BBFA8E
+% FC8553F84E49CB97899489F59DCBD272B8B19E4E64C23753D68767FFD0F2A5E9
+% 3FE2D733268E857B2AC0BF2DA729E4D94BA80D07D3A3D9FACE4E3D9BBFB0BCD9
+% 2599F1BAFB99E2E1AE28FCFC7C3FF8D7A99B96FE734BD8EDFF00A13EADF5D33F
+% 2ADE97536CE9D938E05ED3BEC763904ECB7DBFA0CAB9FF00F4570F936BCE3DA0
+% D2F00B1DA92C81A7958B052553E15C3EC46B83E73F2FB95FF8E3D172DC7F749D
+% 7B9553DBD9E1FC7D4FFFD9003842494D03FD000000000006010000000000
+%EndPhotoshop
+gsave % EPS gsave
+/hascolor
+/deviceinfo where
+{pop deviceinfo /Colors known
+{deviceinfo /Colors get exec 1 gt}
+{false} ifelse}
+{/statusdict where
+{pop statusdict /processcolors known
+{statusdict /processcolors get exec 1 gt}
+{false} ifelse}
+{false} ifelse}
+ifelse
+def
+40 dict begin
+/_image systemdict /image get def
+/_setgray systemdict /setgray get def
+/_currentgray systemdict /currentgray get def
+/_settransfer systemdict /settransfer get def
+/_currenttransfer systemdict /currenttransfer get def
+/blank 0 _currenttransfer exec
+1 _currenttransfer exec eq def
+/negative blank
+{0 _currenttransfer exec 0.5 lt}
+{0 _currenttransfer exec 1 _currenttransfer exec gt}
+ifelse def
+/inverted? negative def
+/level2 systemdict /languagelevel known
+{languagelevel 2 ge} {false} ifelse def
+/level3 systemdict /languagelevel known
+{languagelevel 3 ge} {false} ifelse def
+/foureq {4 index eq 8 1 roll
+4 index eq 8 1 roll
+4 index eq 8 1 roll
+4 index eq 8 1 roll
+pop pop pop pop and and and} def
+hascolor {/band 0 def} {/band 5 def} ifelse
+/setcmykcolor where {pop
+1 0 0 0 setcmykcolor _currentgray 1 exch sub
+0 1 0 0 setcmykcolor _currentgray 1 exch sub
+0 0 1 0 setcmykcolor _currentgray 1 exch sub
+0 0 0 1 setcmykcolor _currentgray 1 exch sub
+4 {4 copy} repeat
+1 0 0 0 foureq {/band 1 store} if
+0 1 0 0 foureq {/band 2 store} if
+0 0 1 0 foureq {/band 3 store} if
+0 0 0 1 foureq {/band 4 store} if
+0 0 0 0 foureq {/band 6 store} if} if
+blank {/band 6 store} if
+gsave % Image Header gsave
+/rows 22 def
+/cols 32 def
+32 22 scale
+level2 {
+band 0 eq {
+/DeviceRGB
+} {/DeviceGray} ifelse
+setcolorspace currentdict /PhotoshopDuotoneColorSpace undef currentdict /PhotoshopDuotoneAltColorSpace undef } if
+/picstr1 32 string def
+/picstr2 32 string def
+/picstr3 32 string def
+/picstr4 32 string def
+/readdata {currentfile exch readhexstring pop} def
+/image2 level2 {/image load def} {{begin
+Width Height BitsPerComponent ImageMatrix
+Decode length 2 eq
+{/DataSource load image} if
+Decode length 6 eq
+{DataSource 0 get DataSource 1 get DataSource 2 get
+true 3 colorimage} if
+Decode length 8 eq
+{DataSource 0 get DataSource 1 get
+DataSource 2 get DataSource 3 get
+true 4 colorimage} if
+end} def} ifelse
+/_image2 level2 {/_image load def} {{begin
+Width Height BitsPerComponent ImageMatrix
+/DataSource load _image end} def} ifelse
+/beginimage {
+band 0 eq band 4 eq or band 5 eq or
+{image2}
+{negative {{pop 0}} {{pop 1}} ifelse
+_settransfer _image2} ifelse
+} def
+12 dict begin
+/ImageType 1 def
+/Width cols def
+/Height rows def
+/ImageMatrix [cols 0 0 rows neg 0 rows] def
+/BitsPerComponent 8 def
+band 0 eq
+{/Decode [0 1 0 1 0 1] def
+/MultipleDataSources true def
+/DataSource [
+{picstr1 readdata}
+{picstr2 readdata}
+{picstr3 readdata picstr4 readdata pop}
+] def}
+{/Decode [0 1] def
+/DataSource {
+picstr1 readdata pop
+picstr2 readdata pop
+picstr3 readdata pop
+picstr4 readdata
+} def}
+ifelse
+currentdict end
+%%BeginBinary: 5821
+beginimage
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000FFFFFFFFFFFFFFFFFFFFC6C6C6C6C6C6C6C6C6C600
+0000000000000000000000D6D6D6D6D6D6D6D6D6D60000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000CBCBCBCBCBCBCBCBCBCB3B3B3B3B3B3B3B3B3B3B00
+0000000000000000000000FFFFFFFFFFFFFFFFFFFFC6C6C6C6C6C6C6C6C6C600
+0000000000000000000000D6D6D6D6D6D6D6D6D6D60000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000CBCBCBCBCBCBCBCBCBCB3B3B3B3B3B3B3B3B3B3B00
+0000000000000000000000FFFFFFFFFFFFFFFFFFFFC6C6C6C6C6C6C6C6C6C600
+0000000000000000000000D6D6D6D6D6D6D6D6D6D60000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000CBCBCBCBCBCBCBCBCBCB3B3B3B3B3B3B3B3B3B3B00
+0000000000000000000000FFFFFFFFFFFFFFFFFFFFC6C6C6C6C6C6C6C6C6C600
+0000000000000000000000D6D6D6D6D6D6D6D6D6D60000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000CBCBCBCBCBCBCBCBCBCB3B3B3B3B3B3B3B3B3B3B00
+0000000000000000000000FFFFFFFFFFFFFFFFFFFFC6C6C6C6C6C6C6C6C6C600
+0000000000000000000000D6D6D6D6D6D6D6D6D6D60000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000CBCBCBCBCBCBCBCBCBCB3B3B3B3B3B3B3B3B3B3B00
+0000000000000000000000FFFFFFFFFFFFFFFFFFFFC6C6C6C6C6C6C6C6C6C600
+0000000000000000000000D6D6D6D6D6D6D6D6D6D60000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000CBCBCBCBCBCBCBCBCBCB3B3B3B3B3B3B3B3B3B3B00
+0000000000000000000000FFFFFFFFFFFFFFFFFFFFC6C6C6C6C6C6C6C6C6C600
+0000000000000000000000D6D6D6D6D6D6D6D6D6D60000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000CBCBCBCBCBCBCBCBCBCB3B3B3B3B3B3B3B3B3B3B00
+0000000000000000000000FFFFFFFFFFFFFFFFFFFFC6C6C6C6C6C6C6C6C6C600
+0000000000000000000000D6D6D6D6D6D6D6D6D6D60000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000CBCBCBCBCBCBCBCBCBCB3B3B3B3B3B3B3B3B3B3B00
+0000000000000000000000FFFFFFFFFFFFFFFFFFFFC6C6C6C6C6C6C6C6C6C600
+0000000000000000000000D6D6D6D6D6D6D6D6D6D60000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000CBCBCBCBCBCBCBCBCBCB3B3B3B3B3B3B3B3B3B3B00
+0000000000000000000000FFFFFFFFFFFFFFFFFFFFC6C6C6C6C6C6C6C6C6C600
+0000000000000000000000D6D6D6D6D6D6D6D6D6D60000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000CBCBCBCBCBCBCBCBCBCB3B3B3B3B3B3B3B3B3B3B00
+0000000000000000000000FFFFFFFFFFFFFFFFFFFFC6C6C6C6C6C6C6C6C6C600
+0000000000000000000000D6D6D6D6D6D6D6D6D6D60000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000CBCBCBCBCBCBCBCBCBCB3B3B3B3B3B3B3B3B3B3B00
+0000000000000000000000FFFFFFFFFFFFFFFFFFFFC6C6C6C6C6C6C6C6C6C600
+0000000000000000000000D6D6D6D6D6D6D6D6D6D60000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000CBCBCBCBCBCBCBCBCBCB3B3B3B3B3B3B3B3B3B3B00
+0000000000000000000000FFFFFFFFFFFFFFFFFFFFC6C6C6C6C6C6C6C6C6C600
+0000000000000000000000D6D6D6D6D6D6D6D6D6D60000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000CBCBCBCBCBCBCBCBCBCB3B3B3B3B3B3B3B3B3B3B00
+0000000000000000000000FFFFFFFFFFFFFFFFFFFFC6C6C6C6C6C6C6C6C6C600
+0000000000000000000000D6D6D6D6D6D6D6D6D6D60000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000CBCBCBCBCBCBCBCBCBCB3B3B3B3B3B3B3B3B3B3B00
+0000000000000000000000FFFFFFFFFFFFFFFFFFFFC6C6C6C6C6C6C6C6C6C600
+0000000000000000000000D6D6D6D6D6D6D6D6D6D60000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000CBCBCBCBCBCBCBCBCBCB3B3B3B3B3B3B3B3B3B3B00
+0000000000000000000000FFFFFFFFFFFFFFFFFFFFC6C6C6C6C6C6C6C6C6C600
+0000000000000000000000D6D6D6D6D6D6D6D6D6D60000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000CBCBCBCBCBCBCBCBCBCB3B3B3B3B3B3B3B3B3B3B00
+0000000000000000000000FFFFFFFFFFFFFFFFFFFFC6C6C6C6C6C6C6C6C6C600
+0000000000000000000000D6D6D6D6D6D6D6D6D6D60000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000CBCBCBCBCBCBCBCBCBCB3B3B3B3B3B3B3B3B3B3B00
+0000000000000000000000FFFFFFFFFFFFFFFFFFFFC6C6C6C6C6C6C6C6C6C600
+0000000000000000000000D6D6D6D6D6D6D6D6D6D60000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000CBCBCBCBCBCBCBCBCBCB3B3B3B3B3B3B3B3B3B3B00
+0000000000000000000000FFFFFFFFFFFFFFFFFFFFC6C6C6C6C6C6C6C6C6C600
+0000000000000000000000D6D6D6D6D6D6D6D6D6D60000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000CBCBCBCBCBCBCBCBCBCB3B3B3B3B3B3B3B3B3B3B00
+0000000000000000000000FFFFFFFFFFFFFFFFFFFFC6C6C6C6C6C6C6C6C6C600
+0000000000000000000000D6D6D6D6D6D6D6D6D6D60000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000CBCBCBCBCBCBCBCBCBCB3B3B3B3B3B3B3B3B3B3B00
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+
+%%EndBinary
+grestore end % Image Trailer grestore
+grestore % EPS grestore
diff --git a/Docs/Flags/belgium.gif b/Docs/Flags/belgium.gif
new file mode 100644
index 00000000000..2bceaef6afc
--- /dev/null
+++ b/Docs/Flags/belgium.gif
Binary files differ
diff --git a/Docs/Flags/belgium.txt b/Docs/Flags/belgium.txt
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/Docs/Flags/belgium.txt
diff --git a/Docs/Flags/mexico.eps b/Docs/Flags/mexico.eps
new file mode 100644
index 00000000000..907642cfec2
--- /dev/null
+++ b/Docs/Flags/mexico.eps
@@ -0,0 +1,258 @@
+%!PS-Adobe-3.0 EPSF-3.0
+%%Creator: Adobe Photoshop Version 5.5
+%%Title: mexico.eps
+%%CreationDate: Fri Sep 21 2001 22:25:39
+%%BoundingBox: 0 0 32 22
+%%HiResBoundingBox: 0 0 32 22
+%%SuppressDotGainCompensation
+%%EndComments
+%%BeginProlog
+%%EndProlog
+%%BeginSetup
+%%EndSetup
+%ImageData: 32 22 8 3 1 32 2 "beginimage"
+%BeginPhotoshop: 1362
+% 3842494D03ED000000000010004800000001000200480000000100023842494D
+% 040D000000000004000000783842494D03F30000000000080000000000000000
+% 3842494D040A00000000000100003842494D271000000000000A000100000000
+% 000000023842494D03F5000000000048002F66660001006C6666000600000000
+% 0001002F6666000100A1999A0006000000000001003200000001005A00000006
+% 000000000001003500000001002D000000060000000000013842494D03F80000
+% 000000700000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF03E80000
+% 0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF03E800000000FFFF
+% FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF03E800000000FFFFFFFFFFFF
+% FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF03E800003842494D0408000000000010
+% 000000010000024000000240000000003842494D041400000000000400000001
+% 3842494D040C0000000003D30000000100000020000000160000006000000840
+% 000003B700180001FFD8FFE000104A46494600010201004800480000FFEE000E
+% 41646F626500648000000001FFDB0084000C08080809080C09090C110B0A0B11
+% 150F0C0C0F1518131315131318110C0C0C0C0C0C110C0C0C0C0C0C0C0C0C0C0C
+% 0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C010D0B0B0D0E0D100E0E10140E0E0E
+% 14140E0E0E0E14110C0C0C0C0C11110C0C0C0C0C0C110C0C0C0C0C0C0C0C0C0C
+% 0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0CFFC0001108001600200301220002
+% 1101031101FFDD00040002FFC4013F0000010501010101010100000000000000
+% 030001020405060708090A0B0100010501010101010100000000000000010002
+% 030405060708090A0B1000010401030204020507060805030C33010002110304
+% 211231054151611322718132061491A1B14223241552C16233347282D1430725
+% 9253F0E1F163733516A2B283264493546445C2A3743617D255E265F2B384C3D3
+% 75E3F3462794A485B495C4D4E4F4A5B5C5D5E5F55666768696A6B6C6D6E6F637
+% 475767778797A7B7C7D7E7F71100020201020404030405060707060535010002
+% 1103213112044151617122130532819114A1B14223C152D1F0332462E1728292
+% 435315637334F1250616A2B283072635C2D2449354A317644555367465E2F2B3
+% 84C3D375E3F34694A485B495C4D4E4F4A5B5C5D5E5F55666768696A6B6C6D6E6
+% F62737475767778797A7B7C7FFDA000C03010002110311003F00C0E9FD3F01F8
+% 18CF7E354E73AA61738B1A4925AD924ED5DF7D48FAB9F57B2BA55B664F4BC3BD
+% E321CD0EB28ADE40D951DBB9EC3E2B88E9BFF2762FFC4D7FF52D5D5626366E5F
+% D4DCBC6C663ACAECC87FACDAC6E798AE934D6DAFD3BFD8EBB66F7B2B7FFA2FD1
+% 5175F9B8791CAE490E625649AE3D2DC3E42723CE484A4787D7B9B5FF00C62743
+% FABD8FF57F1B27A7F4FC3A4DB92C8BA8A6A6EE63ABB9FA59533DD5BBDAE5E6B9
+% 38D8EDC7B48A9808638821A2661779D7FA6E574BFA974E1DDEA1ADB9ED7566D9
+% 6B8175377AF5328F7FA74D776ED967ABFACD9EB5FF00CCBEABAFE1F2BFA2DDFD
+% 477E42AD649C8E489D4588E8FA0FC371E33C84CF0C654725488ECFFFD0C0E9F9
+% 37370319A312D7015300703541F6B7DC375CD72EFBEA4754CDABA55ADAFA4666
+% 40390E3BEB7E2000ECABDBFA7CEA5FFF0045785A4B2F94E1FBC9AE1FD2DB8EFF
+% 00E738BC8F0FDEE55C37EBF97DCE2FF9DE97DABFC64752CCBFA1D0CB7A565E2B
+% 465308B2D7629693E9DFECFD5B3721FBBFB0BCCF26D79C7B41A5E0163B525903
+% 4F2B160A4ACE6AF746DD3F79EEFE1BC7F709571D7EB3E5F6B87FE7FADFFFD900
+% 3842494D03FD000000000006010000000000
+%EndPhotoshop
+gsave % EPS gsave
+/hascolor
+/deviceinfo where
+{pop deviceinfo /Colors known
+{deviceinfo /Colors get exec 1 gt}
+{false} ifelse}
+{/statusdict where
+{pop statusdict /processcolors known
+{statusdict /processcolors get exec 1 gt}
+{false} ifelse}
+{false} ifelse}
+ifelse
+def
+40 dict begin
+/_image systemdict /image get def
+/_setgray systemdict /setgray get def
+/_currentgray systemdict /currentgray get def
+/_settransfer systemdict /settransfer get def
+/_currenttransfer systemdict /currenttransfer get def
+/blank 0 _currenttransfer exec
+1 _currenttransfer exec eq def
+/negative blank
+{0 _currenttransfer exec 0.5 lt}
+{0 _currenttransfer exec 1 _currenttransfer exec gt}
+ifelse def
+/inverted? negative def
+/level2 systemdict /languagelevel known
+{languagelevel 2 ge} {false} ifelse def
+/level3 systemdict /languagelevel known
+{languagelevel 3 ge} {false} ifelse def
+/foureq {4 index eq 8 1 roll
+4 index eq 8 1 roll
+4 index eq 8 1 roll
+4 index eq 8 1 roll
+pop pop pop pop and and and} def
+hascolor {/band 0 def} {/band 5 def} ifelse
+/setcmykcolor where {pop
+1 0 0 0 setcmykcolor _currentgray 1 exch sub
+0 1 0 0 setcmykcolor _currentgray 1 exch sub
+0 0 1 0 setcmykcolor _currentgray 1 exch sub
+0 0 0 1 setcmykcolor _currentgray 1 exch sub
+4 {4 copy} repeat
+1 0 0 0 foureq {/band 1 store} if
+0 1 0 0 foureq {/band 2 store} if
+0 0 1 0 foureq {/band 3 store} if
+0 0 0 1 foureq {/band 4 store} if
+0 0 0 0 foureq {/band 6 store} if} if
+blank {/band 6 store} if
+gsave % Image Header gsave
+/rows 22 def
+/cols 32 def
+32 22 scale
+level2 {
+band 0 eq {
+/DeviceRGB
+} {/DeviceGray} ifelse
+setcolorspace currentdict /PhotoshopDuotoneColorSpace undef currentdict /PhotoshopDuotoneAltColorSpace undef } if
+/picstr1 32 string def
+/picstr2 32 string def
+/picstr3 32 string def
+/picstr4 32 string def
+/readdata {currentfile exch readhexstring pop} def
+/image2 level2 {/image load def} {{begin
+Width Height BitsPerComponent ImageMatrix
+Decode length 2 eq
+{/DataSource load image} if
+Decode length 6 eq
+{DataSource 0 get DataSource 1 get DataSource 2 get
+true 3 colorimage} if
+Decode length 8 eq
+{DataSource 0 get DataSource 1 get
+DataSource 2 get DataSource 3 get
+true 4 colorimage} if
+end} def} ifelse
+/_image2 level2 {/_image load def} {{begin
+Width Height BitsPerComponent ImageMatrix
+/DataSource load _image end} def} ifelse
+/beginimage {
+band 0 eq band 4 eq or band 5 eq or
+{image2}
+{negative {{pop 0}} {{pop 1}} ifelse
+_settransfer _image2} ifelse
+} def
+12 dict begin
+/ImageType 1 def
+/Width cols def
+/Height rows def
+/ImageMatrix [cols 0 0 rows neg 0 rows] def
+/BitsPerComponent 8 def
+band 0 eq
+{/Decode [0 1 0 1 0 1] def
+/MultipleDataSources true def
+/DataSource [
+{picstr1 readdata}
+{picstr2 readdata}
+{picstr3 readdata picstr4 readdata pop}
+] def}
+{/Decode [0 1] def
+/DataSource {
+picstr1 readdata pop
+picstr2 readdata pop
+picstr3 readdata pop
+picstr4 readdata
+} def}
+ifelse
+currentdict end
+%%BeginBinary: 5821
+beginimage
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000FFFFFFFFFFFFFFFFFFFFC6C6C6C6C6C6C6C6C6C600
+00B5B5B5B5B5B5B5B5B5B5FFFFFFFFFFFFFFFFFFFF0000000000000000000000
+0000000000000000000000FFFFFFFFFFFFFFFFFFFF0000000000000000000000
+006B6B6B6B6B6B6B6B6B6BFFFFFFFFFFFFFFFFFFFF3B3B3B3B3B3B3B3B3B3B00
+0000000000000000000000FFFFFFFFFFFFFFFFFFFFC6C6C6C6C6C6C6C6C6C600
+00B5B5B5B5B5B5B5B5B5B5FFFFFFFFFFFFFFFFFFFF0000000000000000000000
+0000000000000000000000FFFFFFFFFFFFFFFFFFFF0000000000000000000000
+006B6B6B6B6B6B6B6B6B6BFFFFFFFFFFFFFFFFFFFF3B3B3B3B3B3B3B3B3B3B00
+0000000000000000000000FFFFFFFFFFFFFFFFFFFFC6C6C6C6C6C6C6C6C6C600
+00B5B5B5B5B5B5B5B5B5B5FFFFFFFFFFFFFFFFFFFF0000000000000000000000
+0000000000000000000000FFFFFFFFFFFFFFFFFFFF0000000000000000000000
+006B6B6B6B6B6B6B6B6B6BFFFFFFFFFFFFFFFFFFFF3B3B3B3B3B3B3B3B3B3B00
+0000000000000000000000FFFFFFFFFFFFFFFFFFFFC6C6C6C6C6C6C6C6C6C600
+00B5B5B5B5B5B5B5B5B5B5FFFFFFFFFFFFFFFFFFFF0000000000000000000000
+0000000000000000000000FFFFFFFFFFFFFFFFFFFF0000000000000000000000
+006B6B6B6B6B6B6B6B6B6BFFFFFFFFFFFFFFFFFFFF3B3B3B3B3B3B3B3B3B3B00
+0000000000000000000000FFFFFFFFFFFFFFFFFFFFC6C6C6C6C6C6C6C6C6C600
+00B5B5B5B5B5B5B5B5B5B5FFFFFFFFFFFFFFFFFFFF0000000000000000000000
+0000000000000000000000FFFFFFFFFFFFFFFFFFFF0000000000000000000000
+006B6B6B6B6B6B6B6B6B6BFFFFFFFFFFFFFFFFFFFF3B3B3B3B3B3B3B3B3B3B00
+0000000000000000000000FFFFFFFFFFFFFFFFFFFFC6C6C6C6C6C6C6C6C6C600
+00B5B5B5B5B5B5B5B5B5B5FFFFFFFFFFFFFFFFFFFF0000000000000000000000
+0000000000000000000000FFFFFFFFFFFFFFFFFFFF0000000000000000000000
+006B6B6B6B6B6B6B6B6B6BFFFFFFFFFFFFFFFFFFFF3B3B3B3B3B3B3B3B3B3B00
+0000000000000000000000FFFFFFFFFF94FFFFFFFFC6C6C6C6C6C6C6C6C6C600
+00B5B5B5B5B5B5B5B5B5B5FFFFFFFFFF42FFFFFFFF0000000000000000000000
+0000000000000000000000FFFFFFFFFF00FFFFFFFF0000000000000000000000
+006B6B6B6B6B6B6B6B6B6BFFFFFFFFFF53FFFFFFFF3B3B3B3B3B3B3B3B3B3B00
+0000000000000000000000FFFFFF6B427B5AFFFFFFC6C6C6C6C6C6C6C6C6C600
+00B5B5B5B5B5B5B5B5B5B5FFFFFF6B183929FFFFFF0000000000000000000000
+0000000000000000000000FFFFFF73000000FFFFFF0000000000000000000000
+006B6B6B6B6B6B6B6B6B6BFFFFFF6C224733FFFFFF3B3B3B3B3B3B3B3B3B3B00
+0000000000000000000000FFFFFF319C397B6BFFFFC6C6C6C6C6C6C6C6C6C600
+00B5B5B5B5B5B5B5B5B5B5FFFFFF9C42213931FFFF0000000000000000000000
+0000000000000000000000FFFFFF0000000000FFFF0000000000000000000000
+006B6B6B6B6B6B6B6B6B6BFFFFFF6B5625473DFFFF3B3B3B3B3B3B3B3B3B3B00
+0000000000000000000000FFFF8C6B39945A63FFFFC6C6C6C6C6C6C6C6C6C600
+00B5B5B5B5B5B5B5B5B5B5FFFF8431184A2931FFFF0000000000000000000000
+0000000000000000000000FFFF840000001010FFFF0000000000000000000000
+006B6B6B6B6B6B6B6B6B6BFFFF863D1F58353CFFFF3B3B3B3B3B3B3B3B3B3B00
+0000000000000000000000FFFF00FF94637B94FFFFC6C6C6C6C6C6C6C6C6C600
+00B5B5B5B5B5B5B5B5B5B5FFFF5AFF4A294A94FFFF0000000000000000000000
+0000000000000000000000FFFF10FF00000094FFFF0000000000000000000000
+006B6B6B6B6B6B6B6B6B6BFFFF37FF58365194FFFF3B3B3B3B3B3B3B3B3B3B00
+0000000000000000000000FF21FF1810EFEFB518FFC6C6C6C6C6C6C6C6C6C600
+00B5B5B5B5B5B5B5B5B5B5FF73FF6B7B9CEFAD84FF0000000000000000000000
+0000000000000000000000FF00FF000800EFA500FF0000000000000000000000
+006B6B6B6B6B6B6B6B6B6BFF4EFF464EA4EFAF55FF3B3B3B3B3B3B3B3B3B3B00
+0000000000000000000000FFFF21FF9494FF21FFFFC6C6C6C6C6C6C6C6C6C600
+00B5B5B5B5B5B5B5B5B5B5FFFF73FF4242FF63FFFF0000000000000000000000
+0000000000000000000000FFFF00FF0000FF00FFFF0000000000000000000000
+006B6B6B6B6B6B6B6B6B6BFFFF4EFF5353FF44FFFF3B3B3B3B3B3B3B3B3B3B00
+0000000000000000000000FFFFFF2121D621FFFFFFC6C6C6C6C6C6C6C6C6C600
+00B5B5B5B5B5B5B5B5B5B5FFFFFF6373DE63FFFFFF0000000000000000000000
+0000000000000000000000FFFFFF0000CE00FFFFFF0000000000000000000000
+006B6B6B6B6B6B6B6B6B6BFFFFFF444EDA44FFFFFF3B3B3B3B3B3B3B3B3B3B00
+0000000000000000000000FFFFFFFFFFFFFFFFFFFFC6C6C6C6C6C6C6C6C6C600
+00B5B5B5B5B5B5B5B5B5B5FFFFFFFFFFFFFFFFFFFF0000000000000000000000
+0000000000000000000000FFFFFFFFFFFFFFFFFFFF0000000000000000000000
+006B6B6B6B6B6B6B6B6B6BFFFFFFFFFFFFFFFFFFFF3B3B3B3B3B3B3B3B3B3B00
+0000000000000000000000FFFFFFFFFFFFFFFFFFFFC6C6C6C6C6C6C6C6C6C600
+00B5B5B5B5B5B5B5B5B5B5FFFFFFFFFFFFFFFFFFFF0000000000000000000000
+0000000000000000000000FFFFFFFFFFFFFFFFFFFF0000000000000000000000
+006B6B6B6B6B6B6B6B6B6BFFFFFFFFFFFFFFFFFFFF3B3B3B3B3B3B3B3B3B3B00
+0000000000000000000000FFFFFFFFFFFFFFFFFFFFC6C6C6C6C6C6C6C6C6C600
+00B5B5B5B5B5B5B5B5B5B5FFFFFFFFFFFFFFFFFFFF0000000000000000000000
+0000000000000000000000FFFFFFFFFFFFFFFFFFFF0000000000000000000000
+006B6B6B6B6B6B6B6B6B6BFFFFFFFFFFFFFFFFFFFF3B3B3B3B3B3B3B3B3B3B00
+0000000000000000000000FFFFFFFFFFFFFFFFFFFFC6C6C6C6C6C6C6C6C6C600
+00B5B5B5B5B5B5B5B5B5B5FFFFFFFFFFFFFFFFFFFF0000000000000000000000
+0000000000000000000000FFFFFFFFFFFFFFFFFFFF0000000000000000000000
+006B6B6B6B6B6B6B6B6B6BFFFFFFFFFFFFFFFFFFFF3B3B3B3B3B3B3B3B3B3B00
+0000000000000000000000FFFFFFFFFFFFFFFFFFFFC6C6C6C6C6C6C6C6C6C600
+00B5B5B5B5B5B5B5B5B5B5FFFFFFFFFFFFFFFFFFFF0000000000000000000000
+0000000000000000000000FFFFFFFFFFFFFFFFFFFF0000000000000000000000
+006B6B6B6B6B6B6B6B6B6BFFFFFFFFFFFFFFFFFFFF3B3B3B3B3B3B3B3B3B3B00
+0000000000000000000000FFFFFFFFFFFFFFFFFFFFC6C6C6C6C6C6C6C6C6C600
+00B5B5B5B5B5B5B5B5B5B5FFFFFFFFFFFFFFFFFFFF0000000000000000000000
+0000000000000000000000FFFFFFFFFFFFFFFFFFFF0000000000000000000000
+006B6B6B6B6B6B6B6B6B6BFFFFFFFFFFFFFFFFFFFF3B3B3B3B3B3B3B3B3B3B00
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+
+%%EndBinary
+grestore end % Image Trailer grestore
+grestore % EPS grestore
diff --git a/Docs/Flags/mexico.gif b/Docs/Flags/mexico.gif
new file mode 100644
index 00000000000..96a0f2a5bc7
--- /dev/null
+++ b/Docs/Flags/mexico.gif
Binary files differ
diff --git a/Docs/Flags/mexico.txt b/Docs/Flags/mexico.txt
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/Docs/Flags/mexico.txt
diff --git a/Docs/Flags/norway.eps b/Docs/Flags/norway.eps
new file mode 100755
index 00000000000..a880f267b70
--- /dev/null
+++ b/Docs/Flags/norway.eps
@@ -0,0 +1,256 @@
+%!PS-Adobe-3.0 EPSF-3.0
+%%Creator: Adobe Photoshop Version 5.5
+%%Title: norway.eps
+%%CreationDate: Tue Oct 09 2001 21:06:06
+%%BoundingBox: 0 0 32 22
+%%HiResBoundingBox: 0 0 32 22
+%%SuppressDotGainCompensation
+%%EndComments
+%%BeginProlog
+%%EndProlog
+%%BeginSetup
+%%EndSetup
+%ImageData: 32 22 8 3 1 32 2 "beginimage"
+%BeginPhotoshop: 1312
+% 3842494D03ED000000000010004800000001000200480000000100023842494D
+% 040D000000000004000000783842494D03F30000000000080000000000000000
+% 3842494D040A00000000000100003842494D271000000000000A000100000000
+% 000000023842494D03F5000000000048002F66660001006C6666000600000000
+% 0001002F6666000100A1999A0006000000000001003200000001005A00000006
+% 000000000001003500000001002D000000060000000000013842494D03F80000
+% 000000700000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF03E80000
+% 0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF03E800000000FFFF
+% FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF03E800000000FFFFFFFFFFFF
+% FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF03E800003842494D0408000000000010
+% 000000010000024000000240000000003842494D041400000000000400000001
+% 3842494D040C0000000003A10000000100000020000000160000006000000840
+% 0000038500180001FFD8FFE000104A46494600010201004800480000FFEE000E
+% 41646F626500648000000001FFDB0084000C08080809080C09090C110B0A0B11
+% 150F0C0C0F1518131315131318110C0C0C0C0C0C110C0C0C0C0C0C0C0C0C0C0C
+% 0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C010D0B0B0D0E0D100E0E10140E0E0E
+% 14140E0E0E0E14110C0C0C0C0C11110C0C0C0C0C0C110C0C0C0C0C0C0C0C0C0C
+% 0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0CFFC0001108001600200301220002
+% 1101031101FFDD00040002FFC4013F0000010501010101010100000000000000
+% 030001020405060708090A0B0100010501010101010100000000000000010002
+% 030405060708090A0B1000010401030204020507060805030C33010002110304
+% 211231054151611322718132061491A1B14223241552C16233347282D1430725
+% 9253F0E1F163733516A2B283264493546445C2A3743617D255E265F2B384C3D3
+% 75E3F3462794A485B495C4D4E4F4A5B5C5D5E5F55666768696A6B6C6D6E6F637
+% 475767778797A7B7C7D7E7F71100020201020404030405060707060535010002
+% 1103213112044151617122130532819114A1B14223C152D1F0332462E1728292
+% 435315637334F1250616A2B283072635C2D2449354A317644555367465E2F2B3
+% 84C3D375E3F34694A485B495C4D4E4F4A5B5C5D5E5F55666768696A6B6C6D6E6
+% F62737475767778797A7B7C7FFDA000C03010002110311003F00E231B1B1DD8F
+% 51353092C6924B44CC2D5CBC0C16B7376E354367D836431BA6FC77BEDDBA7F84
+% 7FBECFDF4B03298DC1C66FDB76454C1B7EC18EF8F68F6FAAF7EFB3FE31FF004D
+% 1C0CAAB2FA85B7750F67EA9B9DF64AACDFEA54EB31BF56B1C29A3D0A7F47FA35
+% 272FCBE3F6F9AFE958CDE31D32FEA7F5B8FD52FD5FF81E876F366919729FD125
+% 1E197F53F5FE8D838FF65C5FF42CFF00347F721E4E363B71ED22A60218E20868
+% 9985B9F6C67FDCFF00FE17637FE9440CFCA63B0725BF6DDF353C6DFB063B27DA
+% 7DBEAB1FBEBFF8C67D055872D8C6BF7DC47C2B3EBFF8D36F273123090FB84E3E
+% 93EAAC7E9F17FFD0E231AD78C7A80A5E406375059074F3B16AE5E4DC5B9B38B6
+% B777D8264D5A6DC77B5BBA2EFF000BF4EBDBFF005DF4D718928B96FE6F9CAFF3
+% 42EBFDB63F9B8BFEE1E933F1F1721F3FCE2AFDAFF37FA1FF00AF1E8BD6B3FD03
+% FEF67FE9443C9B5E71ED06978058ED49640D3CAC58292A71AB1F2EFF00D66F66
+% F73DB9FF003BF2CBFCC767FFD9003842494D03FD000000000006000000000000
+%EndPhotoshop
+gsave % EPS gsave
+/hascolor
+/deviceinfo where
+{pop deviceinfo /Colors known
+{deviceinfo /Colors get exec 1 gt}
+{false} ifelse}
+{/statusdict where
+{pop statusdict /processcolors known
+{statusdict /processcolors get exec 1 gt}
+{false} ifelse}
+{false} ifelse}
+ifelse
+def
+40 dict begin
+/_image systemdict /image get def
+/_setgray systemdict /setgray get def
+/_currentgray systemdict /currentgray get def
+/_settransfer systemdict /settransfer get def
+/_currenttransfer systemdict /currenttransfer get def
+/blank 0 _currenttransfer exec
+1 _currenttransfer exec eq def
+/negative blank
+{0 _currenttransfer exec 0.5 lt}
+{0 _currenttransfer exec 1 _currenttransfer exec gt}
+ifelse def
+/inverted? negative def
+/level2 systemdict /languagelevel known
+{languagelevel 2 ge} {false} ifelse def
+/level3 systemdict /languagelevel known
+{languagelevel 3 ge} {false} ifelse def
+/foureq {4 index eq 8 1 roll
+4 index eq 8 1 roll
+4 index eq 8 1 roll
+4 index eq 8 1 roll
+pop pop pop pop and and and} def
+hascolor {/band 0 def} {/band 5 def} ifelse
+/setcmykcolor where {pop
+1 0 0 0 setcmykcolor _currentgray 1 exch sub
+0 1 0 0 setcmykcolor _currentgray 1 exch sub
+0 0 1 0 setcmykcolor _currentgray 1 exch sub
+0 0 0 1 setcmykcolor _currentgray 1 exch sub
+4 {4 copy} repeat
+1 0 0 0 foureq {/band 1 store} if
+0 1 0 0 foureq {/band 2 store} if
+0 0 1 0 foureq {/band 3 store} if
+0 0 0 1 foureq {/band 4 store} if
+0 0 0 0 foureq {/band 6 store} if} if
+blank {/band 6 store} if
+gsave % Image Header gsave
+/rows 22 def
+/cols 32 def
+32 22 scale
+level2 {
+band 0 eq {
+/DeviceRGB
+} {/DeviceGray} ifelse
+setcolorspace currentdict /PhotoshopDuotoneColorSpace undef currentdict /PhotoshopDuotoneAltColorSpace undef } if
+/picstr1 32 string def
+/picstr2 32 string def
+/picstr3 32 string def
+/picstr4 32 string def
+/readdata {currentfile exch readhexstring pop} def
+/image2 level2 {/image load def} {{begin
+Width Height BitsPerComponent ImageMatrix
+Decode length 2 eq
+{/DataSource load image} if
+Decode length 6 eq
+{DataSource 0 get DataSource 1 get DataSource 2 get
+true 3 colorimage} if
+Decode length 8 eq
+{DataSource 0 get DataSource 1 get
+DataSource 2 get DataSource 3 get
+true 4 colorimage} if
+end} def} ifelse
+/_image2 level2 {/_image load def} {{begin
+Width Height BitsPerComponent ImageMatrix
+/DataSource load _image end} def} ifelse
+/beginimage {
+band 0 eq band 4 eq or band 5 eq or
+{image2}
+{negative {{pop 0}} {{pop 1}} ifelse
+_settransfer _image2} ifelse
+} def
+12 dict begin
+/ImageType 1 def
+/Width cols def
+/Height rows def
+/ImageMatrix [cols 0 0 rows neg 0 rows] def
+/BitsPerComponent 8 def
+band 0 eq
+{/Decode [0 1 0 1 0 1] def
+/MultipleDataSources true def
+/DataSource [
+{picstr1 readdata}
+{picstr2 readdata}
+{picstr3 readdata picstr4 readdata pop}
+] def}
+{/Decode [0 1] def
+/DataSource {
+picstr1 readdata pop
+picstr2 readdata pop
+picstr3 readdata pop
+picstr4 readdata
+} def}
+ifelse
+currentdict end
+%%BeginBinary: 5821
+beginimage
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+00C6C6C6C6C6C6C5D1C40B08BDD2C5C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C600
+000000000000000018B50604AC17000000000000000000000000000000000000
+000000000000000011DBBABAD611000000000000000000000000000000000000
+003B3B3B3B3B3B3B4FBE1B19B64E3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B00
+00C6C6C6C6C6C6C5D1C40B08BDD2C5C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C600
+000000000000000018B50604AC17000000000000000000000000000000000000
+000000000000000011DBBABAD611000000000000000000000000000000000000
+003B3B3B3B3B3B3B4FBE1B19B64E3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B00
+00C6C6C6C6C6C6C5D1C40B08BDD2C5C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C600
+000000000000000018B50604AC17000000000000000000000000000000000000
+000000000000000011DBBABAD611000000000000000000000000000000000000
+003B3B3B3B3B3B3B4FBE1B19B64E3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B00
+00C6C6C6C6C6C6C5D1C40B08BDD2C5C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C600
+000000000000000018B50604AC17000000000000000000000000000000000000
+000000000000000011DBBABAD611000000000000000000000000000000000000
+003B3B3B3B3B3B3B4FBE1B19B64E3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B00
+00C6C6C6C6C6C6C5D1C40B08BDD2C5C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C600
+000000000000000018B50604AC17000000000000000000000000000000000000
+000000000000000011DBBABAD611000000000000000000000000000000000000
+003B3B3B3B3B3B3B4FBE1B19B64E3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B00
+00C6C6C6C6C6C6C5D1C40B08BDD2C5C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C600
+000000000000000018B50604AC17000000000000000000000000000000000000
+000000000000000011DBBABAD611000000000000000000000000000000000000
+003B3B3B3B3B3B3B4FBE1B19B64E3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B00
+00C5C5C5C5C5C5C4D0C40B08BDD1C4C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C500
+000000000000000014B50604AC13000000000000000000000000000000000000
+00000000000000000DDBBABAD60D000000000000000000000000000000000000
+003B3B3B3B3B3B3B4CBE1B19B64B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B00
+00D1D1D1D1D1D1D0DCCB0B08C4DDD0D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D100
+00171717171717172EBD0604B42D171717171717171717171717171717171700
+001010101010101021DEBABAD921101010101010101010101010101010101000
+004E4E4E4E4E4E4E61C51B19BD604E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E00
+00C3C3C3C3C3C3C3CAA00A089ACAC3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C300
+00B2B2B2B2B2B2B2BA9B020096BAB2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B200
+00D8D8D8D8D8D8D8DBDEB6B5DCDBD8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D800
+00BBBBBBBBBBBBBBC2A418169FC2BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB00
+000B0B0B0B0B0B0B0B090808090B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B00
+0006060606060606060200000206060606060606060606060606060606060600
+00BABABABABABABABAB6B5B5B6BABABABABABABABABABABABABABABABABABA00
+001B1B1B1B1B1B1B1B181616181B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B00
+0009090909090909090808080809090909090909090909090909090909090900
+0005050505050505040100000104050505050505050505050505050505050500
+00B9B9B9B9B9B9B9B9B5B5B5B5B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B900
+001A1A1A1A1A1A1A1917161617191A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A00
+00C0C0C0C0C0C0C0C69D0A0898C6C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C000
+00B2B2B2B2B2B2B2B998020093B9B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B200
+00DADADADADADADADCDEB6B5DCDCDADADADADADADADADADADADADADADADADA00
+00BBBBBBBBBBBBBBC1A118169DC1BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB00
+00D2D2D2D2D2D2D1DDCB0B08C4DED1D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D200
+00181818181818182FBD0604B42E181818181818181818181818181818181800
+001111111111111122DEBABAD922111111111111111111111111111111111100
+004F4F4F4F4F4F4F62C51B19BD614F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F00
+00C5C5C5C5C5C5C4D0C40B08BDD1C4C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C500
+000000000000000014B50604AC13000000000000000000000000000000000000
+00000000000000000DDBBABAD60D000000000000000000000000000000000000
+003B3B3B3B3B3B3B4CBE1B19B64B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B00
+00C6C6C6C6C6C6C5D1C40B08BDD2C5C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C600
+000000000000000018B50604AC17000000000000000000000000000000000000
+000000000000000011DBBABAD611000000000000000000000000000000000000
+003B3B3B3B3B3B3B4FBE1B19B64E3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B00
+00C6C6C6C6C6C6C5D1C40B08BDD2C5C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C600
+000000000000000018B50604AC17000000000000000000000000000000000000
+000000000000000011DBBABAD611000000000000000000000000000000000000
+003B3B3B3B3B3B3B4FBE1B19B64E3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B00
+00C6C6C6C6C6C6C5D1C40B08BDD2C5C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C600
+000000000000000018B50604AC17000000000000000000000000000000000000
+000000000000000011DBBABAD611000000000000000000000000000000000000
+003B3B3B3B3B3B3B4FBE1B19B64E3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B00
+00C6C6C6C6C6C6C5D1C40B08BDD2C5C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C600
+000000000000000018B50604AC17000000000000000000000000000000000000
+000000000000000011DBBABAD611000000000000000000000000000000000000
+003B3B3B3B3B3B3B4FBE1B19B64E3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B00
+00C6C6C6C6C6C6C5D1C40B08BDD2C5C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C600
+000000000000000018B50604AC17000000000000000000000000000000000000
+000000000000000011DBBABAD611000000000000000000000000000000000000
+003B3B3B3B3B3B3B4FBE1B19B64E3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B00
+00C6C6C6C6C6C6C5D1C40B08BDD2C5C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C600
+000000000000000018B50604AC17000000000000000000000000000000000000
+000000000000000011DBBABAD611000000000000000000000000000000000000
+003B3B3B3B3B3B3B4FBE1B19B64E3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B00
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+
+%%EndBinary
+grestore end % Image Trailer grestore
+grestore % EPS grestore
diff --git a/Docs/Flags/norway.gif b/Docs/Flags/norway.gif
new file mode 100755
index 00000000000..e9ca1632c9f
--- /dev/null
+++ b/Docs/Flags/norway.gif
Binary files differ
diff --git a/Docs/Flags/norway.txt b/Docs/Flags/norway.txt
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/Docs/Flags/norway.txt
diff --git a/Docs/Flags/philippines.eps b/Docs/Flags/philippines.eps
new file mode 100644
index 00000000000..8d0ca0f91ec
--- /dev/null
+++ b/Docs/Flags/philippines.eps
@@ -0,0 +1,240 @@
+%!PS-Adobe-3.0 EPSF-3.0
+%%Creator: Adobe Photoshop Version 5.5
+%%Title: philippines.eps
+%%CreationDate: Sat Sep 15 2001 09:49:39
+%%BoundingBox: 0 0 30 20
+%%HiResBoundingBox: 0 0 30 20
+%%SuppressDotGainCompensation
+%%EndComments
+%%BeginProlog
+%%EndProlog
+%%BeginSetup
+%%EndSetup
+%ImageData: 30 20 8 3 1 30 2 "beginimage"
+%BeginPhotoshop: 1196
+% 3842494D03ED000000000010004800000001000200480000000100023842494D
+% 040D000000000004000000783842494D03F30000000000080000000000000000
+% 3842494D040A00000000000100003842494D271000000000000A000100000000
+% 000000023842494D03F5000000000048002F66660001006C6666000600000000
+% 0001002F6666000100A1999A0006000000000001003200000001005A00000006
+% 000000000001003500000001002D000000060000000000013842494D03F80000
+% 000000700000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF03E80000
+% 0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF03E800000000FFFF
+% FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF03E800000000FFFFFFFFFFFF
+% FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF03E800003842494D0408000000000010
+% 000000010000024000000240000000003842494D041400000000000400000001
+% 3842494D040C00000000032E000000010000001E000000140000005C00000730
+% 0000031200180001FFD8FFE000104A46494600010201004800480000FFEE000E
+% 41646F626500648000000001FFDB0084000C08080809080C09090C110B0A0B11
+% 150F0C0C0F1518131315131318110C0C0C0C0C0C110C0C0C0C0C0C0C0C0C0C0C
+% 0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C010D0B0B0D0E0D100E0E10140E0E0E
+% 14140E0E0E0E14110C0C0C0C0C11110C0C0C0C0C0C110C0C0C0C0C0C0C0C0C0C
+% 0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0CFFC00011080014001E0301220002
+% 1101031101FFDD00040002FFC4013F0000010501010101010100000000000000
+% 030001020405060708090A0B0100010501010101010100000000000000010002
+% 030405060708090A0B1000010401030204020507060805030C33010002110304
+% 211231054151611322718132061491A1B14223241552C16233347282D1430725
+% 9253F0E1F163733516A2B283264493546445C2A3743617D255E265F2B384C3D3
+% 75E3F3462794A485B495C4D4E4F4A5B5C5D5E5F55666768696A6B6C6D6E6F637
+% 475767778797A7B7C7D7E7F71100020201020404030405060707060535010002
+% 1103213112044151617122130532819114A1B14223C152D1F0332462E1728292
+% 435315637334F1250616A2B283072635C2D2449354A317644555367465E2F2B3
+% 84C3D375E3F34694A485B495C4D4E4F4A5B5C5D5E5F55666768696A6B6C6D6E6
+% F62737475767778797A7B7C7FFDA000C03010002110311003F00DCFAD5FE2E7A
+% 6757DF9580E6E1751324C08AAC3F4BF4B5B7F9B77FC2D6BCABAAF47EA5D1F28E
+% 2751A1D45A356CEAD70FDFA9E3DB633FAABE80C90CAC3AFB5E2BA9825CF79800
+% 0EEE71FA2BCF7EBAFD6FE9BD528774CC4A1B9550D0E55A383FBD8A3E935DFF00
+% 0CA6F87FC7799E5E7931733889E5F1C847148CB8F2CE1FBD1E2FDDFEBB630F21
+% 93999018459FD291D31C3FBC5F3449697D8F1FF73F1297D8F1FF0073F12B57FE
+% 52F27FB99BFC5C7FFAB1B7FF0027B9BFDFC5FE34FF00F55BFFD07FAF7FF39BED
+% 07EDDFF266E3E87A13E8CFFC2CFBBD6FF8DFFAD2E4173092CC3D3CBA7CBFE07F
+% 51ECBE1FFEE687C9B7F92F97FC2FF59FBEF4E92E61241B6FFFD93842494D03FD
+% 000000000006010000000000
+%EndPhotoshop
+gsave % EPS gsave
+/hascolor
+/deviceinfo where
+{pop deviceinfo /Colors known
+{deviceinfo /Colors get exec 1 gt}
+{false} ifelse}
+{/statusdict where
+{pop statusdict /processcolors known
+{statusdict /processcolors get exec 1 gt}
+{false} ifelse}
+{false} ifelse}
+ifelse
+def
+40 dict begin
+/_image systemdict /image get def
+/_setgray systemdict /setgray get def
+/_currentgray systemdict /currentgray get def
+/_settransfer systemdict /settransfer get def
+/_currenttransfer systemdict /currenttransfer get def
+/blank 0 _currenttransfer exec
+1 _currenttransfer exec eq def
+/negative blank
+{0 _currenttransfer exec 0.5 lt}
+{0 _currenttransfer exec 1 _currenttransfer exec gt}
+ifelse def
+/inverted? negative def
+/level2 systemdict /languagelevel known
+{languagelevel 2 ge} {false} ifelse def
+/level3 systemdict /languagelevel known
+{languagelevel 3 ge} {false} ifelse def
+/foureq {4 index eq 8 1 roll
+4 index eq 8 1 roll
+4 index eq 8 1 roll
+4 index eq 8 1 roll
+pop pop pop pop and and and} def
+hascolor {/band 0 def} {/band 5 def} ifelse
+/setcmykcolor where {pop
+1 0 0 0 setcmykcolor _currentgray 1 exch sub
+0 1 0 0 setcmykcolor _currentgray 1 exch sub
+0 0 1 0 setcmykcolor _currentgray 1 exch sub
+0 0 0 1 setcmykcolor _currentgray 1 exch sub
+4 {4 copy} repeat
+1 0 0 0 foureq {/band 1 store} if
+0 1 0 0 foureq {/band 2 store} if
+0 0 1 0 foureq {/band 3 store} if
+0 0 0 1 foureq {/band 4 store} if
+0 0 0 0 foureq {/band 6 store} if} if
+blank {/band 6 store} if
+gsave % Image Header gsave
+/rows 20 def
+/cols 30 def
+30 20 scale
+level2 {
+band 0 eq {
+/DeviceRGB
+} {/DeviceGray} ifelse
+setcolorspace currentdict /PhotoshopDuotoneColorSpace undef currentdict /PhotoshopDuotoneAltColorSpace undef } if
+/picstr1 30 string def
+/picstr2 30 string def
+/picstr3 30 string def
+/picstr4 30 string def
+/readdata {currentfile exch readhexstring pop} def
+/image2 level2 {/image load def} {{begin
+Width Height BitsPerComponent ImageMatrix
+Decode length 2 eq
+{/DataSource load image} if
+Decode length 6 eq
+{DataSource 0 get DataSource 1 get DataSource 2 get
+true 3 colorimage} if
+Decode length 8 eq
+{DataSource 0 get DataSource 1 get
+DataSource 2 get DataSource 3 get
+true 4 colorimage} if
+end} def} ifelse
+/_image2 level2 {/_image load def} {{begin
+Width Height BitsPerComponent ImageMatrix
+/DataSource load _image end} def} ifelse
+/beginimage {
+band 0 eq band 4 eq or band 5 eq or
+{image2}
+{negative {{pop 0}} {{pop 1}} ifelse
+_settransfer _image2} ifelse
+} def
+12 dict begin
+/ImageType 1 def
+/Width cols def
+/Height rows def
+/ImageMatrix [cols 0 0 rows neg 0 rows] def
+/BitsPerComponent 8 def
+band 0 eq
+{/Decode [0 1 0 1 0 1] def
+/MultipleDataSources true def
+/DataSource [
+{picstr1 readdata}
+{picstr2 readdata}
+{picstr3 readdata picstr4 readdata pop}
+] def}
+{/Decode [0 1] def
+/DataSource {
+picstr1 readdata pop
+picstr2 readdata pop
+picstr3 readdata pop
+picstr4 readdata
+} def}
+ifelse
+currentdict end
+%%BeginBinary: 4963
+beginimage
+A62301080808080808080808080808080808080808080808080808080808A31F
+00000000000000000000000000000000000000000000000000000000E3BCB3B5
+B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5AB3114161616
+161616161616161616161616161616161616161616161616FCE05F0101080808
+08080808080808080808080808080808080808080808FFDF5C00000000000000
+0000000000000000000000000000000000000000FDF0CEB3B3B5B5B5B5B5B5B5
+B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5FEE1691414161616161616161616
+16161616161616161616161616161616F9FEFBA6230108080808080808080808
+0808080808080808080808080808F5F8F6A31F00000000000000000000000000
+000000000000000000000000CD32ADE3BCB3B5B5B5B5B5B5B5B5B5B5B5B5B5B5
+B5B5B5B5B5B5B5B5B5B5F2E4EFAB311416161616161616161616161616161616
+1616161616161616F9FDFBFCE05F010108080808080808080808080808080808
+080808080808F5F7F6FFDF5C0000000000000000000000000000000000000000
+00000000CD55ADFDF0CEB3B3B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5
+B5B5F2E7EFFEE169141416161616161616161616161616161616161616161616
+F7F7F7F7FCFCA62301080808080808080808080808080808080808080808F7F6
+F8F7FFFFA31F00000000000000000000000000000000000000000000F9F0FFF9
+FDFDE3BCB3B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5F7F6F8F7FEFE
+AB3114161616161616161616161616161616161616161616F7F7F7F7FAF9FCE0
+5F010108080808080808080808080808080808080808F7F7F7F7F9F5FFDF5C00
+0000000000000000000000000000000000000000F9F9FEF9E8CDFDF0CEB3B3B5
+B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5F7F7F8F7F7F2FEE1691414161616
+16161616161616161616161616161616F7F7F9F7F9FBF7FAFAA6230108080808
+0808080808080808080808080808F7F7F5F7F5F2F7F9F9A31F00000000000000
+000000000000000000000000F9F9CDFECD8DFEE8E8E3BCB3B5B5B5B5B5B5B5B5
+B5B5B5B5B5B5B5B5B5B5F7F7F2F8F2EAF8F7F7AB311416161616161616161616
+1616161616161616F7FAFBFBFBFDF9FDFBFCE05F010108080808080808080808
+080808080808F7F9F2F6F2F7F5F7F6FFDF5C0000000000000000000000000000
+00000000F9E88DAD8D55CD55ADFDF0CEB3B3B5B5B5B5B5B5B5B5B5B5B5B5B5B5
+B5B5F7F7EAEFEAE7F2E7EFFEE169141416161616161616161616161616161616
+F7F7FAFEFFFFFFFBF7F7FCFCA62301050505050505050505050505050505F7F7
+F9F8FEFEFEF2F7F7FFFFA31F00000000000000000000000000000000F9FEE832
+0303038DFEFEFDFDE3BCB3B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8F7F8F7E4E3E3
+E3EAF8F8FEFEAB3114161616161616161616161616161616F7FBFBFFFFFFFFFD
+FBF9F7FBFDE05F131313131313131313131313131313F6F6F2FEFEFEFEF7F2F5
+F7F2F7DF5C000000000000000000000000000000F0AD8D03030303558DCDF98D
+55F0CEABABABABABABABABABABABABABABABF6EFEAE3E3E3E3E7EAF2F7EAE7E1
+69191919191919191919191919191919F7FBFBFFFFFFFFFDFBF9F7FBFDF4D9B9
+B9B9B9B9B9B9B9B9B9B9B9B9B9B9F6F2F2FEFEFEFEF7F2F5F7F2F7E05D000000
+000000000000000000000000F08D8D03030303558DCDF98D55DA5E0D0D0D0D0D
+0D0D0D0D0D0D0D0D0D0DF6EAEAE3E3E3E3E7EAF2F7EAE7E58239393939393939
+3939393939393939F7F7F7FEFFFFFFFBF7F7FCF7E7CBC6CACACACACACACACACA
+CACACACACACAF7F7F6F8FEFEFEF2F8F7FFF6A522000000000000000000000000
+00000000F9FEF0320303038DFFFEFDF0A4280000000000000000000000000000
+0000F7F8F6E4E3E3E3EAF8F8FEF6B9553B3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D
+F7F7FBFBFBFDF9FDF9FCF4D9C4C4C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6F7F6
+F2F2F2F7F5F7F5FFE05D000000000000000000000000000000000000F9F08D8D
+8D55CD55CDFDDA5E000000000000000000000000000000000000F7F6EAEAEAE7
+F2E7F2FEE5823B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3BF7F7F9F7F9FBF7FA
+FAE7CCC3C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6F7F6F5F7F5F2F7F9F9A5
+1F00000000000000000000000000000000000000F9F0CDFECD8DFEE8E8A42300
+000000000000000000000000000000000000F7F6F2F8F2EAF8F7F7B9533A3B3B
+3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3BF7F7F7F7FAF9F7F4D9C3C3C6C6C6C6C6
+C6C6C6C6C6C6C6C6C6C6C6C6C6C6F7F7F7F7F9F5F8E05D000000000000000000
+000000000000000000000000F9F9FEF9E8CDFFDA5E0000000000000000000000
+00000000000000000000F7F7F8F7F7F2F8E5823A3A3B3B3B3B3B3B3B3B3B3B3B
+3B3B3B3B3B3B3B3BF7F7F7F7F7FCE7CCC3C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6
+C6C6C6C6C6C6F7F6F7F7F8FFA51F000000000000000000000000000000000000
+00000000F9F0F9F9FFFDA4230000000000000000000000000000000000000000
+0000F7F6F7F7F8FEB9533A3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B
+F9FDFBFCF4D9C4C4C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6F5F7
+F6FFE05D000000000000000000000000000000000000000000000000CD55ADFD
+DA5E000000000000000000000000000000000000000000000000F2E7EFFEE582
+3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3BF9FDFBE7CCC3C6C6
+C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6F5F7F6A51F0000000000
+0000000000000000000000000000000000000000CD55ADA42300000000000000
+000000000000000000000000000000000000F2E7EFB9533A3B3B3B3B3B3B3B3B
+3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3BFCF4D9C3C4C6C6C6C6C6C6C6C6C6C6C6
+C6C6C6C6C6C6C6C6C6C6C6C6C6C6FFE05D000000000000000000000000000000
+000000000000000000000000FDDA5E0000000000000000000000000000000000
+00000000000000000000FEE5823A3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B
+3B3B3B3B3B3B3B3BE7CCC3C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6
+C6C6C6C6C6C6A51F000000000000000000000000000000000000000000000000
+00000000A41F0000000000000000000000000000000000000000000000000000
+0000B9533A3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B
+
+%%EndBinary
+grestore end % Image Trailer grestore
+grestore % EPS grestore
diff --git a/Docs/Flags/philippines.gif b/Docs/Flags/philippines.gif
new file mode 100644
index 00000000000..2f2a17a852d
--- /dev/null
+++ b/Docs/Flags/philippines.gif
Binary files differ
diff --git a/Docs/Flags/philippines.txt b/Docs/Flags/philippines.txt
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/Docs/Flags/philippines.txt
diff --git a/Docs/Flags/slovenia.eps b/Docs/Flags/slovenia.eps
new file mode 100755
index 00000000000..1588713978f
--- /dev/null
+++ b/Docs/Flags/slovenia.eps
@@ -0,0 +1,357 @@
+%!PS-Adobe-3.0 EPSF-3.0
+%%Creator: Adobe Photoshop Version 5.5
+%%Title: slovenia.eps
+%%CreationDate: Mon Jan 07 2002 15:19:42
+%%BoundingBox: 0 0 32 22
+%%HiResBoundingBox: 0 0 32 22
+%%SuppressDotGainCompensation
+%%EndComments
+%%BeginProlog
+%%EndProlog
+%%BeginSetup
+%%EndSetup
+%ImageData: 32 22 8 3 1 32 2 "beginimage"
+%BeginPhotoshop: 1300
+% 3842494D03ED000000000010004800000001000200480000000100023842494D
+% 040D000000000004000000783842494D03F30000000000080000000000000000
+% 3842494D040A00000000000100003842494D271000000000000A000100000000
+% 000000023842494D03F5000000000048002F66660001006C6666000600000000
+% 0001002F6666000100A1999A0006000000000001003200000001005A00000006
+% 000000000001003500000001002D000000060000000000013842494D03F80000
+% 000000700000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF03E80000
+% 0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF03E800000000FFFF
+% FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF03E800000000FFFFFFFFFFFF
+% FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF03E800003842494D0408000000000010
+% 000000010000024000000240000000003842494D041400000000000400000001
+% 3842494D040C0000000003960000000100000020000000160000006000000840
+% 0000037A00180001FFD8FFE000104A46494600010201004800480000FFEE000E
+% 41646F626500648000000001FFDB0084000C08080809080C09090C110B0A0B11
+% 150F0C0C0F1518131315131318110C0C0C0C0C0C110C0C0C0C0C0C0C0C0C0C0C
+% 0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C010D0B0B0D0E0D100E0E10140E0E0E
+% 14140E0E0E0E14110C0C0C0C0C11110C0C0C0C0C0C110C0C0C0C0C0C0C0C0C0C
+% 0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0CFFC0001108001600200301220002
+% 1101031101FFDD00040002FFC4013F0000010501010101010100000000000000
+% 030001020405060708090A0B0100010501010101010100000000000000010002
+% 030405060708090A0B1000010401030204020507060805030C33010002110304
+% 211231054151611322718132061491A1B14223241552C16233347282D1430725
+% 9253F0E1F163733516A2B283264493546445C2A3743617D255E265F2B384C3D3
+% 75E3F3462794A485B495C4D4E4F4A5B5C5D5E5F55666768696A6B6C6D6E6F637
+% 475767778797A7B7C7D7E7F71100020201020404030405060707060535010002
+% 1103213112044151617122130532819114A1B14223C152D1F0332462E1728292
+% 435315637334F1250616A2B283072635C2D2449354A317644555367465E2F2B3
+% 84C3D375E3F34694A485B495C4D4E4F4A5B5C5D5E5F55666768696A6B6C6D6E6
+% F62737475767778797A7B7C7FFDA000C03010002110311003F0096759D1BA4FD
+% 55E837E1F47E9B9D99978D48BFD4C6AED7EEF46B76FB366DB373AC77E91EF577
+% EA93BA3F54CCCEC4EB1D0BA5E1D9850D8FB2D75CBB7D95BFF9EDFBB6FA6B84FA
+% A3D5F2FA0751A73D949BA97B3D3BAB100BAB76D77B09FCF6ED6BD5AFAE5D7B27
+% EB1F516DD5D0EAB171DA59435F1BCEE3BACB2CDBEDDCF77E6AD38F2FCA911C47
+% 262F5478CF31EE438A12FDCF6B8BFC0641CBF32458C1908FF672FF00BD7D5FF6
+% 0FD4AFFCAFE97FF6CE3FFE45677D64E89F546AFABBD52CC7C1E9CCBD98790EA9
+% F5D5407878A9E58EADCC6EFDED77D0DABC6BECB91FE8CA85B8D7B6A7B8B0801A
+% 493F2465C87282248E77192013578F5FFC711F77E646A706403FB93FFBD7FFD0
+% E231AD78C7A80A5E406375059074F3B113D6B3FD03FEF67FE945CEA4B3A5567E
+% 5DFF00ACF6587DCF6E1FCEFCB1FF0031D9E8BD6B3FD03FEF67FE9443C9B5E71E
+% D06978058ED49640D3CAC5829251AB1F2EFF00D6566F73DB9FF3BF2CBFCC767F
+% FFD93842494D03FD000000000006000000000000
+%EndPhotoshop
+%%BeginICCProfile: (Photoshop Profile) -1 Hex
+% 00000C484C696E6F021000006D6E74725247422058595A2007CE000200090006
+% 00310000616373704D5346540000000049454320735247420000000000000000
+% 000000000000F6D6000100000000D32D48502020000000000000000000000000
+% 0000000000000000000000000000000000000000000000000000000000000000
+% 0000001163707274000001500000003364657363000001840000006C77747074
+% 000001F000000014626B707400000204000000147258595A0000021800000014
+% 6758595A0000022C000000146258595A0000024000000014646D6E6400000254
+% 00000070646D6464000002C400000088767565640000034C0000008676696577
+% 000003D4000000246C756D69000003F8000000146D6561730000040C00000024
+% 74656368000004300000000C725452430000043C0000080C675452430000043C
+% 0000080C625452430000043C0000080C7465787400000000436F707972696768
+% 74202863292031393938204865776C6574742D5061636B61726420436F6D7061
+% 6E790000646573630000000000000012735247422049454336313936362D322E
+% 31000000000000000000000012735247422049454336313936362D322E310000
+% 0000000000000000000000000000000000000000000000000000000000000000
+% 0000000000000000000000000000000058595A20000000000000F35100010000
+% 000116CC58595A200000000000000000000000000000000058595A2000000000
+% 00006FA2000038F50000039058595A2000000000000062990000B785000018DA
+% 58595A2000000000000024A000000F840000B6CF646573630000000000000016
+% 49454320687474703A2F2F7777772E6965632E63680000000000000000000000
+% 1649454320687474703A2F2F7777772E6965632E636800000000000000000000
+% 0000000000000000000000000000000000000000000000000000000000000000
+% 0000000064657363000000000000002E4945432036313936362D322E31204465
+% 6661756C742052474220636F6C6F7572207370616365202D2073524742000000
+% 00000000000000002E4945432036313936362D322E312044656661756C742052
+% 474220636F6C6F7572207370616365202D207352474200000000000000000000
+% 00000000000000000000000064657363000000000000002C5265666572656E63
+% 652056696577696E6720436F6E646974696F6E20696E2049454336313936362D
+% 322E3100000000000000000000002C5265666572656E63652056696577696E67
+% 20436F6E646974696F6E20696E2049454336313936362D322E31000000000000
+% 000000000000000000000000000000000000000076696577000000000013A4FE
+% 00145F2E0010CF140003EDCC0004130B00035C9E0000000158595A2000000000
+% 004C09560050000000571FE76D65617300000000000000010000000000000000
+% 00000000000000000000028F0000000273696720000000004352542063757276
+% 000000000000040000000005000A000F00140019001E00230028002D00320037
+% 003B00400045004A004F00540059005E00630068006D00720077007C00810086
+% 008B00900095009A009F00A400A900AE00B200B700BC00C100C600CB00D000D5
+% 00DB00E000E500EB00F000F600FB01010107010D01130119011F0125012B0132
+% 0138013E0145014C0152015901600167016E0175017C0183018B0192019A01A1
+% 01A901B101B901C101C901D101D901E101E901F201FA0203020C0214021D0226
+% 022F02380241024B0254025D02670271027A0284028E029802A202AC02B602C1
+% 02CB02D502E002EB02F50300030B03160321032D03380343034F035A03660372
+% 037E038A039603A203AE03BA03C703D303E003EC03F9040604130420042D043B
+% 0448045504630471047E048C049A04A804B604C404D304E104F004FE050D051C
+% 052B053A05490558056705770586059605A605B505C505D505E505F606060616
+% 0627063706480659066A067B068C069D06AF06C006D106E306F507070719072B
+% 073D074F076107740786079907AC07BF07D207E507F8080B081F08320846085A
+% 086E0882089608AA08BE08D208E708FB09100925093A094F09640979098F09A4
+% 09BA09CF09E509FB0A110A270A3D0A540A6A0A810A980AAE0AC50ADC0AF30B0B
+% 0B220B390B510B690B800B980BB00BC80BE10BF90C120C2A0C430C5C0C750C8E
+% 0CA70CC00CD90CF30D0D0D260D400D5A0D740D8E0DA90DC30DDE0DF80E130E2E
+% 0E490E640E7F0E9B0EB60ED20EEE0F090F250F410F5E0F7A0F960FB30FCF0FEC
+% 1009102610431061107E109B10B910D710F511131131114F116D118C11AA11C9
+% 11E81207122612451264128412A312C312E31303132313431363138313A413C5
+% 13E5140614271449146A148B14AD14CE14F01512153415561578159B15BD15E0
+% 160316261649166C168F16B216D616FA171D17411765178917AE17D217F7181B
+% 18401865188A18AF18D518FA19201945196B199119B719DD1A041A2A1A511A77
+% 1A9E1AC51AEC1B141B3B1B631B8A1BB21BDA1C021C2A1C521C7B1CA31CCC1CF5
+% 1D1E1D471D701D991DC31DEC1E161E401E6A1E941EBE1EE91F131F3E1F691F94
+% 1FBF1FEA20152041206C209820C420F0211C2148217521A121CE21FB22272255
+% 228222AF22DD230A23382366239423C223F0241F244D247C24AB24DA25092538
+% 2568259725C725F726272657268726B726E827182749277A27AB27DC280D283F
+% 287128A228D429062938296B299D29D02A022A352A682A9B2ACF2B022B362B69
+% 2B9D2BD12C052C392C6E2CA22CD72D0C2D412D762DAB2DE12E162E4C2E822EB7
+% 2EEE2F242F5A2F912FC72FFE3035306C30A430DB3112314A318231BA31F2322A
+% 3263329B32D4330D3346337F33B833F1342B3465349E34D83513354D358735C2
+% 35FD3637367236AE36E937243760379C37D738143850388C38C839053942397F
+% 39BC39F93A363A743AB23AEF3B2D3B6B3BAA3BE83C273C653CA43CE33D223D61
+% 3DA13DE03E203E603EA03EE03F213F613FA23FE24023406440A640E74129416A
+% 41AC41EE4230427242B542F7433A437D43C044034447448A44CE45124555459A
+% 45DE4622466746AB46F04735477B47C04805484B489148D7491D496349A949F0
+% 4A374A7D4AC44B0C4B534B9A4BE24C2A4C724CBA4D024D4A4D934DDC4E254E6E
+% 4EB74F004F494F934FDD5027507150BB51065150519B51E65231527C52C75313
+% 535F53AA53F65442548F54DB5528557555C2560F565C56A956F75744579257E0
+% 582F587D58CB591A596959B85A075A565AA65AF55B455B955BE55C355C865CD6
+% 5D275D785DC95E1A5E6C5EBD5F0F5F615FB36005605760AA60FC614F61A261F5
+% 6249629C62F06343639763EB6440649464E9653D659265E7663D669266E8673D
+% 679367E9683F689668EC6943699A69F16A486A9F6AF76B4F6BA76BFF6C576CAF
+% 6D086D606DB96E126E6B6EC46F1E6F786FD1702B708670E0713A719571F0724B
+% 72A67301735D73B87414747074CC7528758575E1763E769B76F8775677B37811
+% 786E78CC792A798979E77A467AA57B047B637BC27C217C817CE17D417DA17E01
+% 7E627EC27F237F847FE5804780A8810A816B81CD8230829282F4835783BA841D
+% 848084E3854785AB860E867286D7873B879F8804886988CE8933899989FE8A64
+% 8ACA8B308B968BFC8C638CCA8D318D988DFF8E668ECE8F368F9E9006906E90D6
+% 913F91A89211927A92E3934D93B69420948A94F4955F95C99634969F970A9775
+% 97E0984C98B89924999099FC9A689AD59B429BAF9C1C9C899CF79D649DD29E40
+% 9EAE9F1D9F8B9FFAA069A0D8A147A1B6A226A296A306A376A3E6A456A4C7A538
+% A5A9A61AA68BA6FDA76EA7E0A852A8C4A937A9A9AA1CAA8FAB02AB75ABE9AC5C
+% ACD0AD44ADB8AE2DAEA1AF16AF8BB000B075B0EAB160B1D6B24BB2C2B338B3AE
+% B425B49CB513B58AB601B679B6F0B768B7E0B859B8D1B94AB9C2BA3BBAB5BB2E
+% BBA7BC21BC9BBD15BD8FBE0ABE84BEFFBF7ABFF5C070C0ECC167C1E3C25FC2DB
+% C358C3D4C451C4CEC54BC5C8C646C6C3C741C7BFC83DC8BCC93AC9B9CA38CAB7
+% CB36CBB6CC35CCB5CD35CDB5CE36CEB6CF37CFB8D039D0BAD13CD1BED23FD2C1
+% D344D3C6D449D4CBD54ED5D1D655D6D8D75CD7E0D864D8E8D96CD9F1DA76DAFB
+% DB80DC05DC8ADD10DD96DE1CDEA2DF29DFAFE036E0BDE144E1CCE253E2DBE363
+% E3EBE473E4FCE584E60DE696E71FE7A9E832E8BCE946E9D0EA5BEAE5EB70EBFB
+% EC86ED11ED9CEE28EEB4EF40EFCCF058F0E5F172F1FFF28CF319F3A7F434F4C2
+% F550F5DEF66DF6FBF78AF819F8A8F938F9C7FA57FAE7FB77FC07FC98FD29FDBA
+% FE4BFEDCFF6DFFFF
+%%EndICCProfile
+gsave % EPS gsave
+/hascolor
+/deviceinfo where
+{pop deviceinfo /Colors known
+{deviceinfo /Colors get exec 1 gt}
+{false} ifelse}
+{/statusdict where
+{pop statusdict /processcolors known
+{statusdict /processcolors get exec 1 gt}
+{false} ifelse}
+{false} ifelse}
+ifelse
+def
+40 dict begin
+/_image systemdict /image get def
+/_setgray systemdict /setgray get def
+/_currentgray systemdict /currentgray get def
+/_settransfer systemdict /settransfer get def
+/_currenttransfer systemdict /currenttransfer get def
+/blank 0 _currenttransfer exec
+1 _currenttransfer exec eq def
+/negative blank
+{0 _currenttransfer exec 0.5 lt}
+{0 _currenttransfer exec 1 _currenttransfer exec gt}
+ifelse def
+/inverted? negative def
+/level2 systemdict /languagelevel known
+{languagelevel 2 ge} {false} ifelse def
+/level3 systemdict /languagelevel known
+{languagelevel 3 ge} {false} ifelse def
+/foureq {4 index eq 8 1 roll
+4 index eq 8 1 roll
+4 index eq 8 1 roll
+4 index eq 8 1 roll
+pop pop pop pop and and and} def
+hascolor {/band 0 def} {/band 5 def} ifelse
+/setcmykcolor where {pop
+1 0 0 0 setcmykcolor _currentgray 1 exch sub
+0 1 0 0 setcmykcolor _currentgray 1 exch sub
+0 0 1 0 setcmykcolor _currentgray 1 exch sub
+0 0 0 1 setcmykcolor _currentgray 1 exch sub
+4 {4 copy} repeat
+1 0 0 0 foureq {/band 1 store} if
+0 1 0 0 foureq {/band 2 store} if
+0 0 1 0 foureq {/band 3 store} if
+0 0 0 1 foureq {/band 4 store} if
+0 0 0 0 foureq {/band 6 store} if} if
+blank {/band 6 store} if
+gsave % Image Header gsave
+/rows 22 def
+/cols 32 def
+32 22 scale
+level2 {
+band 0 eq {
+/DeviceRGB
+} {/DeviceGray} ifelse
+setcolorspace currentdict /PhotoshopDuotoneColorSpace undef currentdict /PhotoshopDuotoneAltColorSpace undef } if
+/picstr1 32 string def
+/picstr2 32 string def
+/picstr3 32 string def
+/picstr4 32 string def
+/readdata {currentfile exch readhexstring pop} def
+/image2 level2 {/image load def} {{begin
+Width Height BitsPerComponent ImageMatrix
+Decode length 2 eq
+{/DataSource load image} if
+Decode length 6 eq
+{DataSource 0 get DataSource 1 get DataSource 2 get
+true 3 colorimage} if
+Decode length 8 eq
+{DataSource 0 get DataSource 1 get
+DataSource 2 get DataSource 3 get
+true 4 colorimage} if
+end} def} ifelse
+/_image2 level2 {/_image load def} {{begin
+Width Height BitsPerComponent ImageMatrix
+/DataSource load _image end} def} ifelse
+/beginimage {
+band 0 eq band 4 eq or band 5 eq or
+{image2}
+{negative {{pop 0}} {{pop 1}} ifelse
+_settransfer _image2} ifelse
+} def
+12 dict begin
+/ImageType 1 def
+/Width cols def
+/Height rows def
+/ImageMatrix [cols 0 0 rows neg 0 rows] def
+/BitsPerComponent 8 def
+band 0 eq
+{/Decode [0 1 0 1 0 1] def
+/MultipleDataSources true def
+/DataSource [
+{picstr1 readdata}
+{picstr2 readdata}
+{picstr3 readdata picstr4 readdata pop}
+] def}
+{/Decode [0 1] def
+/DataSource {
+picstr1 readdata pop
+picstr2 readdata pop
+picstr3 readdata pop
+picstr4 readdata
+} def}
+ifelse
+currentdict end
+%%BeginBinary: 5821
+beginimage
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+00F7F7F7F8FAF9F9F9F9F9F9F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F700
+00F7F7F7F9FBFBFBFBFBFBFBF8F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F700
+00F7F7F7F8F9F9F9F9F9F9F9F8F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F700
+00F7F7F7F9FAFAFAFAFAFAFAF8F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F700
+00F7F7F7F7F2F2F6F6F6F1F4F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F700
+00F7F7F7F2E9E8ECECECE7EAF4F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F700
+00F7F7F7F1EEEEEBEBEBEFEDF3F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F700
+00F7F7F7F3ECECEFEFEFEBEDF5F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F700
+00F7F7FDAB5B5D3F3C426657D5FCF7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F700
+00F7F7FE8134381A151C422BB5FEF7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F700
+00F7F7FDB8808CA3A4A0848ECCFDF7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F700
+00F7F7FE94484C3430365443C1FDF7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F700
+00F7F7FF8D33320833004623C8FEF7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F700
+00F7F7FF6B2C310831004617A9FFF7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F700
+00F7F7FDBE7F92B18FB98099CBFDF7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F700
+00F7F7FF7E373C1B3C144C29B6FEF7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F700
+00F7F7FF990000194E06000CCEFEF7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F700
+00F7F7FF7700001148000000AFFFF7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F700
+00F7F7FDB9ADBBA883B5BBAEC9FDF7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F700
+00F7F7FF8813152450161517BBFEF7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F700
+00FFFFFF9E0000248205000BD7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00
+00FFFFFF7C00001D7E000000B8FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00
+00FAFAFFBBA8B2BFDEB5B3ABCCFFFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFA00
+00FEFEFF8D1214318A151416C3FFFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFE00
+00A4A4A968443E72FC37562B8EA8A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A400
+00A1A1A7493B3A6DFC30521B71A7A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A100
+00E0E0E5ABBCC5D2F9C2CCB5B7E5E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E000
+00A9A9AE5D4C4A7AFC42613181AEA9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A900
+0002020034D6E1E1FFD2EEA71900020202020202020202020202020202020200
+0000000010D6E4DDFECEF59E0000000000000000000000000000000000000000
+00B3B3B69AE8F3F0FAECF9D39BB6B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B300
+001414142AD8E5E0FED2F3A71914141414141414141414141414141414141400
+000707012BBFC8E8EEDEC4A70D04070707070707070707070707070707070700
+000000000FCEF4F6F4F5F69A0000000000000000000000000000000000000000
+00B5B5B6A3DCFCF8F6F8FEBEA9B6B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B500
+0016161428CBE8F2F2EEE8A21615161616161616161616161616161616161600
+000808070479D4B6B7B3CE460008080808080808080808080808080808080800
+00000000005DF5E7E4EADE270000000000000000000000000000000000000000
+00B5B5B5B0ACF5F7F4FAE4A2B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B500
+00161616156EEBDAD8DBDA3E1416161616161616161616161616161616161600
+000808080315B9EDD4F187030708080808080808080808080808080808080800
+0000000000028DFDF6F257000000000000000000000000000000000000000000
+00B5B5B5B7A6B6F8FEEEA6AFB6B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B500
+00161616151A9FF8EDF16E141616161616161616161616161616161616161600
+00070707070015AFF37F02040707070707070707070707070707070707070700
+0000000000000184D55100000000000000000000000000000000000000000000
+00B6B6B6B6B8A5B5D7A5ADB8B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B600
+0016161616141996DE6814151616161616161616161616161616161616161600
+0003030303030007270000030303030303030303030303030303030303030300
+0000000000000000080000000000000000000000000000000000000000000000
+00BABABABABABCB0A1B6BCBABABABABABABABABABABABABABABABABABABABA00
+0015151515151515221415151515151515151515151515151515151515151500
+00828282828282807B8182828282828282828282828282828282828282828200
+0000000000000000000000000000000000000000000000000000000000000000
+0041414141414142434140414141414141414141414141414141414141414100
+002E2E2E2E2E2E2E2C2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E00
+00D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+003E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E00
+00C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C600
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+003B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B00
+00C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C600
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+003B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B00
+00C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C600
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+003B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B00
+00C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C600
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+003B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B00
+00C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C600
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+003B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B00
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+
+%%EndBinary
+grestore end % Image Trailer grestore
+grestore % EPS grestore
diff --git a/Docs/Flags/slovenia.gif b/Docs/Flags/slovenia.gif
new file mode 100644
index 00000000000..d16dadf3923
--- /dev/null
+++ b/Docs/Flags/slovenia.gif
Binary files differ
diff --git a/Docs/Flags/slovenia.txt b/Docs/Flags/slovenia.txt
new file mode 100755
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/Docs/Flags/slovenia.txt
diff --git a/Docs/Flags/turkey.eps b/Docs/Flags/turkey.eps
new file mode 100644
index 00000000000..17cfb962d0c
--- /dev/null
+++ b/Docs/Flags/turkey.eps
@@ -0,0 +1,237 @@
+%!PS-Adobe-3.0 EPSF-3.0
+%%Creator: Adobe Photoshop Version 5.5
+%%Title: turkey.eps
+%%CreationDate: Sun Sep 16 2001 10:01:58
+%%BoundingBox: 0 0 30 20
+%%HiResBoundingBox: 0 0 30 20
+%%SuppressDotGainCompensation
+%%EndComments
+%%BeginProlog
+%%EndProlog
+%%BeginSetup
+%%EndSetup
+%ImageData: 30 20 8 3 1 30 2 "beginimage"
+%BeginPhotoshop: 1098
+% 3842494D03ED000000000010004800000001000200480000000100023842494D
+% 040D000000000004000000783842494D03F30000000000080000000000000000
+% 3842494D040A00000000000100003842494D271000000000000A000100000000
+% 000000023842494D03F5000000000048002F66660001006C6666000600000000
+% 0001002F6666000100A1999A0006000000000001003200000001005A00000006
+% 000000000001003500000001002D000000060000000000013842494D03F80000
+% 000000700000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF03E80000
+% 0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF03E800000000FFFF
+% FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF03E800000000FFFFFFFFFFFF
+% FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF03E800003842494D0408000000000010
+% 000000010000024000000240000000003842494D041400000000000400000001
+% 3842494D040C0000000002CC000000010000001E000000140000005C00000730
+% 000002B000180001FFD8FFE000104A46494600010201004800480000FFEE000E
+% 41646F626500648000000001FFDB0084000C08080809080C09090C110B0A0B11
+% 150F0C0C0F1518131315131318110C0C0C0C0C0C110C0C0C0C0C0C0C0C0C0C0C
+% 0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C010D0B0B0D0E0D100E0E10140E0E0E
+% 14140E0E0E0E14110C0C0C0C0C11110C0C0C0C0C0C110C0C0C0C0C0C0C0C0C0C
+% 0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0CFFC00011080014001E0301220002
+% 1101031101FFDD00040002FFC4013F0000010501010101010100000000000000
+% 030001020405060708090A0B0100010501010101010100000000000000010002
+% 030405060708090A0B1000010401030204020507060805030C33010002110304
+% 211231054151611322718132061491A1B14223241552C16233347282D1430725
+% 9253F0E1F163733516A2B283264493546445C2A3743617D255E265F2B384C3D3
+% 75E3F3462794A485B495C4D4E4F4A5B5C5D5E5F55666768696A6B6C6D6E6F637
+% 475767778797A7B7C7D7E7F71100020201020404030405060707060535010002
+% 1103213112044151617122130532819114A1B14223C152D1F0332462E1728292
+% 435315637334F1250616A2B283072635C2D2449354A317644555367465E2F2B3
+% 84C3D375E3F34694A485B495C4D4E4F4A5B5C5D5E5F55666768696A6B6C6D6E6
+% F62737475767778797A7B7C7FFDA000C03010002110311003F00E5F0B0F233B2
+% ABC4C666FBAE3B58DE3E64FE6B5BF9CA599463E3D9E95378C92DD1EF634864FF
+% 00C1B9DEEB1BFCBD8AE7D5BCDC7C2EA8D7E53B653757650FB62767AAC755EAC7
+% F2377B90EB191D17A832EB69AB20324B03A2CA6C046DDED737D963166D0E107C
+% 75FEABDB99CFDD947B404A11DBDD97AB8BD5FD5F4B9E9293DDBDEE7C01B89303
+% 812A29ACDD1FFFD0E4525CC24B2DEF5E9D25CC24929FFFD93842494D03FD0000
+% 00000006010000000000
+%EndPhotoshop
+gsave % EPS gsave
+/hascolor
+/deviceinfo where
+{pop deviceinfo /Colors known
+{deviceinfo /Colors get exec 1 gt}
+{false} ifelse}
+{/statusdict where
+{pop statusdict /processcolors known
+{statusdict /processcolors get exec 1 gt}
+{false} ifelse}
+{false} ifelse}
+ifelse
+def
+40 dict begin
+/_image systemdict /image get def
+/_setgray systemdict /setgray get def
+/_currentgray systemdict /currentgray get def
+/_settransfer systemdict /settransfer get def
+/_currenttransfer systemdict /currenttransfer get def
+/blank 0 _currenttransfer exec
+1 _currenttransfer exec eq def
+/negative blank
+{0 _currenttransfer exec 0.5 lt}
+{0 _currenttransfer exec 1 _currenttransfer exec gt}
+ifelse def
+/inverted? negative def
+/level2 systemdict /languagelevel known
+{languagelevel 2 ge} {false} ifelse def
+/level3 systemdict /languagelevel known
+{languagelevel 3 ge} {false} ifelse def
+/foureq {4 index eq 8 1 roll
+4 index eq 8 1 roll
+4 index eq 8 1 roll
+4 index eq 8 1 roll
+pop pop pop pop and and and} def
+hascolor {/band 0 def} {/band 5 def} ifelse
+/setcmykcolor where {pop
+1 0 0 0 setcmykcolor _currentgray 1 exch sub
+0 1 0 0 setcmykcolor _currentgray 1 exch sub
+0 0 1 0 setcmykcolor _currentgray 1 exch sub
+0 0 0 1 setcmykcolor _currentgray 1 exch sub
+4 {4 copy} repeat
+1 0 0 0 foureq {/band 1 store} if
+0 1 0 0 foureq {/band 2 store} if
+0 0 1 0 foureq {/band 3 store} if
+0 0 0 1 foureq {/band 4 store} if
+0 0 0 0 foureq {/band 6 store} if} if
+blank {/band 6 store} if
+gsave % Image Header gsave
+/rows 20 def
+/cols 30 def
+30 20 scale
+level2 {
+band 0 eq {
+/DeviceRGB
+} {/DeviceGray} ifelse
+setcolorspace currentdict /PhotoshopDuotoneColorSpace undef currentdict /PhotoshopDuotoneAltColorSpace undef } if
+/picstr1 30 string def
+/picstr2 30 string def
+/picstr3 30 string def
+/picstr4 30 string def
+/readdata {currentfile exch readhexstring pop} def
+/image2 level2 {/image load def} {{begin
+Width Height BitsPerComponent ImageMatrix
+Decode length 2 eq
+{/DataSource load image} if
+Decode length 6 eq
+{DataSource 0 get DataSource 1 get DataSource 2 get
+true 3 colorimage} if
+Decode length 8 eq
+{DataSource 0 get DataSource 1 get
+DataSource 2 get DataSource 3 get
+true 4 colorimage} if
+end} def} ifelse
+/_image2 level2 {/_image load def} {{begin
+Width Height BitsPerComponent ImageMatrix
+/DataSource load _image end} def} ifelse
+/beginimage {
+band 0 eq band 4 eq or band 5 eq or
+{image2}
+{negative {{pop 0}} {{pop 1}} ifelse
+_settransfer _image2} ifelse
+} def
+12 dict begin
+/ImageType 1 def
+/Width cols def
+/Height rows def
+/ImageMatrix [cols 0 0 rows neg 0 rows] def
+/BitsPerComponent 8 def
+band 0 eq
+{/Decode [0 1 0 1 0 1] def
+/MultipleDataSources true def
+/DataSource [
+{picstr1 readdata}
+{picstr2 readdata}
+{picstr3 readdata picstr4 readdata pop}
+] def}
+{/Decode [0 1] def
+/DataSource {
+picstr1 readdata pop
+picstr2 readdata pop
+picstr3 readdata pop
+picstr4 readdata
+} def}
+ifelse
+currentdict end
+%%BeginBinary: 4963
+beginimage
+C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C60000
+0000000000000000000000000000000000000000000000000000000000000000
+00000000000000000000000000000000000000000000000000003B3B3B3B3B3B
+3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3BC6C6C6C6C6C6C6C6
+C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C600000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000003B3B3B3B3B3B3B3B3B3B3B3B3B3B
+3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3BC6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6
+C6C6C6C6C6C6C6C6C6C6C6C6C6C6000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+000000000000000000003B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B
+3B3B3B3B3B3B3B3BC6C6C6C6C6C6C6C6C6C4C6C7C6C6C6C6C6C6C6C6C6C6C6C6
+C6C6C6C6C6C60000000000000000000000070200000000000000000000000000
+0000000000000000000000000000000702000000000000000000000000000000
+00003B3B3B3B3B3B3B3B3B3B3B413D3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B
+C6C6C6C6C6C6C6C4C9DCE2D7C9C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C60000
+000000000000106D895310000000000000000000000000000000000000000000
+00000000106E89541000000000000000000000000000000000003B3B3B3B3B3B
+3B3B478EA47B473B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3BC6C6C6C6C6C6C4D3
+F0E9D1C7C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C60000000000000043D3AA
+38070000000000000000000000000000000000000000000000000043D4AA3807
+0000000000000000000000000000000000003B3B3B3B3B3B3B6EDCBD66413B3B
+3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3BC6C6C6C6C6C4D1F9E2C4C4C6C6C6C6C6
+C6C6C6C6C6C6C6C6C6C6C6C6C6C600000000000038FA89000000000000000000
+00000000000000000000000000000000000038FA890000000000000000000000
+000000000000000000003B3B3B3B3B3B66FAA43B3B3B3B3B3B3B3B3B3B3B3B3B
+3B3B3B3B3B3B3B3BC6C6C6C6C6C7F0F0C6C4C6C6C6C6C6C6C6C6C6C6C6C6C6C6
+C6C6C6C6C6C6000000000007D3D3000000000000000000000000000000000000
+00000000000000000007D4D40000000000000000000000000000000000000000
+00003B3B3B3B3B41DCDC3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B
+C6C6C6C6C4D1F9DCC4C6C6C6C6C4D3CDCCC6C6C6C6C6C6C6C6C6C6C6C6C60000
+00000038FA6D00000000000043271C0200000000000000000000000000000000
+0038FA6E00000000000043271C020000000000000000000000003B3B3B3B3B66
+FA8E3B3B3B3B3B3B6E59513D3B3B3B3B3B3B3B3B3B3B3B3BC6C6C6C6C4DCF9D7
+C4C6C6C6C6CDE9F9D3C4C6C6C6C6C6C6C6C6C6C6C6C600000000006DFA530000
+00000027AAFA430000000000000000000000000000000000006EFA5400000000
+0027AAFA43000000000000000000000000003B3B3B3B3B8EFA7B3B3B3B3B3B59
+BDFA6E3B3B3B3B3B3B3B3B3B3B3B3B3BC6C6C6C6C4DCF9D7C4C6C6C6C6CDE9F0
+D7C6C6C6C6C6C6C6C6C6C6C6C6C600000000006DFA53000000000027AAD35300
+00000000000000000000000000000000006EFA54000000000027AAD454000000
+000000000000000000003B3B3B3B3B8EFA7B3B3B3B3B3B59BDDC7B3B3B3B3B3B
+3B3B3B3B3B3B3B3BC6C6C6C6C4D3F9DCC4C6C6C6C6C4D3CDC9C6C6C6C6C6C6C6
+C6C6C6C6C6C6000000000043FA6D000000000000432710020000000000000000
+00000000000000000043FA6E0000000000004327100200000000000000000000
+00003B3B3B3B3B6EFA8E3B3B3B3B3B3B6E59473D3B3B3B3B3B3B3B3B3B3B3B3B
+C6C6C6C6C6C7F0F0C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C60000
+00000007D3D30200000000000000000000000000000000000000000000000000
+0007D4D4020000000000000000000000000000000000000000003B3B3B3B3B41
+DCDC3D3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3BC6C6C6C6C6C4D1F9
+E2C4C4C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C600000000000038FA8900
+000000000000000000000000000000000000000000000000000038FA89000000
+0000000000000000000000000000000000003B3B3B3B3B3B66FAA43B3B3B3B3B
+3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3BC6C6C6C6C6C6C4D3F0E9D1C7C6C6C6C6
+C6C6C6C6C6C6C6C6C6C6C6C6C6C60000000000000043D3AA3809000000000000
+0000000000000000000000000000000000000043D4AA38090000000000000000
+000000000000000000003B3B3B3B3B3B3B6EDCBD66423B3B3B3B3B3B3B3B3B3B
+3B3B3B3B3B3B3B3BC6C6C6C6C6C6C6C4C9DCE2D7C9C6C6C6C6C6C6C6C6C6C6C6
+C6C6C6C6C6C60000000000000000106D89531000000000000000000000000000
+000000000000000000000000106E895410000000000000000000000000000000
+00003B3B3B3B3B3B3B3B478EA47B473B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B
+C6C6C6C6C6C6C6C6C6C4C6C7C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C60000
+0000000000000000000702000000000000000000000000000000000000000000
+00000000000000070200000000000000000000000000000000003B3B3B3B3B3B
+3B3B3B3B3B413D3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3BC6C6C6C6C6C6C6C6
+C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C600000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000003B3B3B3B3B3B3B3B3B3B3B3B3B3B
+3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3BC6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6
+C6C6C6C6C6C6C6C6C6C6C6C6C6C6000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+000000000000000000003B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B
+3B3B3B3B3B3B3B3BC6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6
+C6C6C6C6C6C60000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+00003B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B
+
+%%EndBinary
+grestore end % Image Trailer grestore
+grestore % EPS grestore
diff --git a/Docs/Flags/turkey.gif b/Docs/Flags/turkey.gif
new file mode 100644
index 00000000000..99715c01b04
--- /dev/null
+++ b/Docs/Flags/turkey.gif
Binary files differ
diff --git a/Docs/Flags/turkey.txt b/Docs/Flags/turkey.txt
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/Docs/Flags/turkey.txt
diff --git a/Docs/Makefile.am b/Docs/Makefile.am
index 17def904875..d1312a56311 100644
--- a/Docs/Makefile.am
+++ b/Docs/Makefile.am
@@ -21,7 +21,8 @@ info_TEXINFOS = manual.texi
targets = manual.txt mysql.info manual.html
BUILT_SOURCES = $(targets) manual_toc.html include.texi
-EXTRA_DIST = $(noinst_SCRIPTS) $(BUILT_SOURCES) mysqld_error.txt INSTALL-BINARY
+EXTRA_DIST = $(noinst_SCRIPTS) $(BUILT_SOURCES) mysqld_error.txt \
+ INSTALL-BINARY mirrors.texi
all: $(targets) txt_files
@@ -96,6 +97,9 @@ nusphere.pdf: manual.texi
# Target to produce DocBook XML
mysql.xml: manual.texi include.texi
$(MAKEINFO) --force --no-ifinfo --docbook manual.texi
+ mv mysql.xml mysql-tmp.xml
+ Support/docbook-fixup.pl <mysql-tmp.xml >mysql.xml
+ rm -f mysql-tmp.xml
# The texi2dvi gives a lot of harmless errors. Just ignore them unless
# you want to help with the typesetting part.
@@ -131,7 +135,7 @@ dist-hook:
GT = $(srcdir)/Support/generate-text-files.pl
../INSTALL-SOURCE: mysql.info $(GT)
- perl -w $(GT) mysql.info "Installing" "Compatibility" > $@
+ perl -w $(GT) mysql.info "Installing" "Tutorial" > $@
# We put the description for the binary installation here so that
# people who download source wont have to see it. It is moved up to
diff --git a/Docs/Support/docbook-fixup.pl b/Docs/Support/docbook-fixup.pl
new file mode 100755
index 00000000000..ae4bfc26b42
--- /dev/null
+++ b/Docs/Support/docbook-fixup.pl
@@ -0,0 +1,110 @@
+#!/usr/bin/perl
+
+sub fix_underscore {
+ $str = shift;
+ $str =~ tr/_/-/;
+ return $str;
+};
+
+sub strip_emph {
+ $str = shift;
+ $str =~ s{<emphasis>(.+?)</emphasis>}
+ {$1}gs;
+ return $str;
+};
+
+
+$data = join "", <STDIN>;
+
+print STDERR "Changing @@ to @...\n";
+$data =~ s/@@/@/gs;
+
+print STDERR "Changing '_' to '-' in references...\n";
+$data =~ s{id=\"(.+?)\"}
+ {"id=\"".&fix_underscore($1)."\""}gsex;
+$data =~ s{linkend=\"(.+?)\"}
+ {"linkend=\"".&fix_underscore($1)."\""}gsex;
+
+print STDERR "Changing ULINK to SYSTEMITEM...\n";
+$data =~ s{<ulink url=\"(.+?)\"></ulink>}
+ {<systemitem role=\"url\">$1</systemitem>}gs;
+
+print STDERR "Removing INFORMALFIGURE...\n";
+$data =~ s{<informalfigure>(.+?)</informalfigure>}
+ {}gs;
+
+print STDERR "Adding PARA inside ENTRY...\n";
+$data =~ s{<entry>(.*?)</entry>}
+ {<entry><para>$1</para></entry>}gs;
+
+print STDERR "Removing mailto: from email addresses...\n";
+$data =~ s{mailto:}
+ {}gs;
+
+print STDERR "Fixing spacing problem with titles...\n";
+$data =~ s{</(\w+)>(\w{2,})}
+ {</$1> $2}gs;
+
+# 2002-01-30 arjen@mysql.com
+print STDERR "Removing COLSPEC...\n";
+$data =~ s{\n *<colspec colwidth=\"[0-9]+\*\">}
+ {}gs;
+
+# 2002-01-31 arjen@mysql.com
+print STDERR "Making first row in table THEAD...\n";
+$data =~ s{([ ]*)<tbody>\n([ ]*<row>(.+?)</row>)}
+ {$1<thead>\n$2\n$1</thead>\n$1<tbody>}gs;
+
+# 2002-01-31 arjen@mysql.com
+print STDERR "Removing EMPHASIS inside THEAD...\n";
+$data =~ s{<thead>(.+?)</thead>}
+ {"<thead>".&strip_emph($1)."</thead>"}gsex;
+
+# 2002-01-31 arjen@mysql.com
+print STDERR "Removing lf before /PARA in ENTRY...\n";
+$data =~ s{(<entry><para>(.+?))\n(</para></entry>)}
+ {$1$3}gs;
+
+# 2002-01-31 arjen@mysql.com
+print STDERR "Removing whitespace before /PARA...\n";
+$data =~ s{[ ]+</para>}
+ {</para>}gs;
+
+# 2002-01-31 arjen@mysql.com
+print STDERR "Removing empty PARA in ENTRY...\n";
+$data =~ s{<entry><para></para></entry>}
+ {<entry></entry>}gs;
+
+# 2002-01-31 arjen@mysql.com
+print STDERR "Removing PARA around INDEXENTRY if no text in PARA...\n";
+$data =~ s{<para>((<indexterm role=\"(cp|fn)\">(<(primary|secondary)>[^<]+?</(primary|secondary)>)+?</indexterm>)+?)[\n]*</para>[\n]*}
+ {$1\n}gs;
+
+# -----
+
+@apx = ("Users", "MySQL Testimonials", "News",
+ "GPL-license", "LGPL-license");
+
+foreach $apx (@apx) {
+ print STDERR "Removing appendix $apx...\n";
+ $data =~ s{<appendix id=\"$apx\">(.+?)</appendix>}
+ {}gs;
+
+ print STDERR " ... Building list of removed nodes ...\n";
+ foreach(split "\n", $&) {
+ push @nodes, $2 if(/<(\w+) id=\"(.+?)\">/)
+ };
+};
+
+print STDERR "Fixing references to removed nodes...\n";
+foreach $node (@nodes) {
+ $web = $node;
+ $web =~ s/[ ]/_/;
+ $web = "http://www.mysql.com/doc/" .
+ (join "/", (split //, $web)[0..1])."/$web.html";
+ print STDERR "$node -> $web\n";
+ $data =~ s{<(\w+) linkend=\"$node\">}
+ {$web}gs;
+};
+
+print STDOUT $data;
diff --git a/Docs/Support/make-docbook b/Docs/Support/make-docbook
new file mode 100755
index 00000000000..2904eef4926
--- /dev/null
+++ b/Docs/Support/make-docbook
@@ -0,0 +1,19 @@
+#!/bin/sh
+# 2002-01-30 arjen@mysql.com
+# Use this to create mysql.xml (the DocBook XML format output of manual.texi)
+# Requires makeinfo 4.0c
+
+#create include.texi with version/port #
+ echo "@c This file is autogenerated by the Makefile" > include.texi
+ echo -n "@set mysql_version " >> include.texi
+ grep "AM_INIT_AUTOMAKE(mysql, " ../configure.in | \
+ sed -e 's;AM_INIT_AUTOMAKE(mysql, ;;' -e 's;);;' >> include.texi
+ echo -n "@set default_port " >> include.texi
+ grep "MYSQL_TCP_PORT_DEFAULT=" ../configure.in | \
+ sed -e 's;MYSQL_TCP_PORT_DEFAULT=;;' >> include.texi
+
+# produce DocBook XML
+ makeinfo --force --no-ifinfo --docbook manual.texi
+ mv mysql.xml mysql-tmp.xml
+ Support/docbook-fixup.pl <mysql-tmp.xml >mysql.xml
+ rm -f mysql-tmp.xml
diff --git a/Docs/Support/update-reserved-words.pl b/Docs/Support/update-reserved-words.pl
new file mode 100755
index 00000000000..e7f8329009e
--- /dev/null
+++ b/Docs/Support/update-reserved-words.pl
@@ -0,0 +1,89 @@
+#!/usr/bin/perl
+
+# Based on a Emacs macro by david@mysql.com
+# Implemented in Perl by jeremy@mysql.com
+# 2001-11-20 Fixups by arjen@mysql.com, 2 keywords and 15 synonyms were missing
+# 2001-12-07 Fixup by arjen@mysql.com, add column headings for multitable.
+
+print STDERR "Scanning lex.h for symbols..\n";
+open LEX, "<../sql/lex.h";
+while($line = <LEX>) {
+ if($line =~ /\{\s*\"([A-Z_]+)\"/) {
+ $words{$1} = $1;
+ } elsif($line =~ /sql_functions/) {
+ last;
+ };
+};
+close LEX;
+
+print STDERR "Scanning sql_yacc.yy for non-reserved words...\n";
+open YACC, "<../sql/sql_yacc.yy";
+while(<YACC> !~ /^keyword:/) {};
+while(($line = <YACC>) =~ /[\s|]+([A-Z_]+)/) {
+ $keyword = $1;
+ $keyword =~ s/_SYM//;
+ delete $words{$keyword};
+};
+close YACC;
+
+
+$list = sprintf("\@c Reserved word list updated %s by %s.\n".
+ "\@c To regenerate, use Support/update-reserved-words.pl.\n\n",
+ &pretty_date, $ENV{USER});
+
+
+print STDERR "Copying reserved words to an array...\n";
+foreach(keys %words) { push @words, $words{$_}; };
+
+print STDERR "Sorting array...\n";
+@words = sort @words;
+
+printf STDERR "There are %i reserved words.\n", scalar @words;
+
+@pre = ("\@item", "\@tab", " \@tab", "\@tab");
+@post = ("", "\n", "", "\n");
+
+for($i=0; $word = shift(@words); $i++) {
+ $list .= sprintf "%s %-30s %s", $pre[$i%4], "\@code\{$word\}", $post[$i%4];
+}; $list .= "\n";
+
+open OLD, "<manual.texi";
+open NEW, ">manual-tmp.texi";
+
+print STDERR "Copying beginning of manual.texi...\n";
+while(($line = <OLD>) !~ /START_OF_RESERVED_WORDS/) { print NEW $line; };
+print NEW "\@c START_OF_RESERVED_WORDS\n\n";
+print STDERR "Inserting list of reserved words...\n";
+print NEW "\@multitable \@columnfractions .25 .25 .25 .25\n";
+print NEW "\@item \@strong{Word} \@tab \@strong{Word} \@tab \@strong{Word} \@tab \@strong{Word}\n";
+print NEW $list;
+print NEW "\@end multitable\n";
+print STDERR "Skipping over old list...\n";
+while(($line = <OLD>) !~ /END_OF_RESERVED_WORDS/) {};
+print NEW "\n\@c END_OF_RESERVED_WORDS\n";
+print STDERR "Copying end of manual.texi...\n";
+while($line = <OLD>) { print NEW $line; };
+
+close OLD;
+close NEW;
+
+print STDERR "Moving manual-tmp.texi to manual.texi...\n";
+unlink "manual.texi";
+rename "manual-tmp.texi", "manual.texi";
+
+print STDERR "Reserved word list updated successfully!\n";
+
+sub pretty_date {
+ @time = ($time = shift)?((localtime($time))[0..6]):((localtime)[0..6]);
+
+ ($sec, $min, $hour, $mday, $mon, $year, $wday) = @time;
+ $wday = (Sun,Mon,Tue,Wed,Thu,Fri,Sat)[$wday];
+ $mon = (Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec)[$mon];
+ $year += 1900;
+
+ $pretty = sprintf("%s %s %2i %02i:%02i:%02i %i",
+ $wday, $mon, $mday, $hour, $min, $sec, $year);
+
+ return $pretty;
+};
+
diff --git a/Docs/bk.txt b/Docs/bk.txt
index cb2521b2b05..4c83c48aea6 100644
--- a/Docs/bk.txt
+++ b/Docs/bk.txt
@@ -55,5 +55,4 @@ Their developers, and especially the president of the company Larry McVoy really
like MySQL and are very anxious to help us. Make sure it is obvious that you
work for MySQL, of course. And, of course, do not bug them with little things
that you can figure out on your own or with my help - they were nice to offer us
-support, but we should not abuse it.
-
+support, but we should not abuse it. \ No newline at end of file
diff --git a/Docs/internals.texi b/Docs/internals.texi
index 2195b42d9a0..72724a22ec0 100644
--- a/Docs/internals.texi
+++ b/Docs/internals.texi
@@ -183,24 +183,28 @@ and then we read the rows in the sorted order into a row buffer
We are using @uref{http://www.bitkeeper.com/, BitKeeper} for source management.
@item
-You should use the @strong{MySQL} 3.23 or 4.0 source for all developments.
+You should use the @strong{MySQL} 4.0 source for all developments.
@item
If you have any questions about the @strong{MySQL} source, you can post these
-to @email{developers@@mysql.com} and we will answer them.
-Note that we will shortly change the name of this list to
-@email{internals@@mysql.com}, to more accurately reflect what should be
-posted to this list.
+to @email{dev-public@@mysql.com} and we will answer them. Please
+remember to not use this internal email list in public!
@item
-Try to write code in a lot of black boxes that can be reused or at
-least have a clean interface.
+Try to write code in a lot of black boxes that can be reused or use at
+least a clean, easy to change interface.
@item
Reuse code; There is already a lot of algorithms in MySQL for list handling,
queues, dynamic and hashed arrays, sorting, etc. that can be reused.
@item
+Use the @code{my_*} functions like @code{my_read()}/@code{my_write()}/
+@code{my_malloc()} that you can find in the @code{mysys} library instead
+of the direct system calls; This will make your code easier to debug and
+more portable.
+
+@item
Try to always write optimized code, so that you don't have to
go back and rewrite it a couple of months later. It's better to
spend 3 times as much time designing and writing an optimal function than
@@ -222,7 +226,11 @@ Do not check the same pointer for @code{NULL} more than once.
@item
Use long function and variable names in English; This makes your code
-easier to read. Use the 'varible_name' style instead of 'VariableName'.
+easier to read.
+
+@item
+Use my_var as opposed to myVar or MyVar (@samp{_} rather than dancing SHIFT
+to seperate words in identifiers).
@item
Think assembly - make it easier for the compiler to optimize your code.
@@ -232,14 +240,8 @@ Comment your code when you do something that someone else may think
is not ''trivial''.
@item
-Use the @code{my_*} functions like @code{my_read()}/@code{my_write()}/
-@code{my_malloc()} that you can find in the @code{mysys} library instead
-of the direct system calls; This will make your code easier to debug and
-more portable.
-
-@item
-Use @code{libstring} functions instead of standard libc string functions
-whenever possible.
+Use @code{libstring} functions (in the strings directory)
+instead of standard libc string functions whenever possible.
@item
Avoid using @code{malloc()} (its REAL slow); For memory allocations
@@ -254,10 +256,6 @@ easily discuss it thoroughly if some other developer thinks there is better
way to do the same thing!
@item
-Use my_var as opposed to myVar or MyVar (@samp{_} rather than dancing SHIFT
-to seperate words in identifiers).
-
-@item
Class names start with a capital letter.
@item
@@ -481,6 +479,27 @@ Functions i mysys: (For flags se my_sys.h)
void end_key_cache _A((void));
- End key-cacheing.
+@node DBUG,,,
+@chapter The DBUG tags to use:
+
+Here is some of the tags we now use:
+(We should probably add a couple of new ones)
+
+"enter" Arguments to the function.
+"exit" Results from the function.
+"info" is something that may be interesting.
+"warning" is when something doesn't go the usual route or may be wrong.
+"error" when something went wrong.
+"loop" write in a loop, that is probably only useful when debugging
+ the loop. These should normally be deleted when on is
+ satisfied with the code and it has been in real use for a while.
+
+Some specific to mysqld, because we want to watch these carefully:
+
+"trans" Starting/stopping transactions.
+"quit" 'info' when mysqld is preparing to die.
+"query" Print query
+
@node protocol,,,
@chapter MySQL client/server protocol
diff --git a/Docs/manual.ja.texi b/Docs/manual.ja.texi
index d3ee43acd29..dea7046b538 100644
--- a/Docs/manual.ja.texi
+++ b/Docs/manual.ja.texi
@@ -3187,7 +3187,7 @@ encounter per year, but we are as always very flexible towards our customers!
@c @image{Flags/estonia} Estonia [Tradenet] @
@c @uref{http://mysql.tradenet.ee, WWW}
@item
-@c EMAIL: tonu@spamm.ee (Tonu Samuel)
+@c EMAIL: tonu@spam.ee (Tonu Samuel)
@image{Flags/estonia} Estonia [OKinteractive] @
@uref{http://mysql.mirror.ok.ee, WWW}
@item
diff --git a/Docs/manual.texi b/Docs/manual.texi
index a93d5b2194b..105453c87b5 100644
--- a/Docs/manual.texi
+++ b/Docs/manual.texi
@@ -1,15 +1,27 @@
\input texinfo @c -*-texinfo-*-
-@c Copyright 1997-2001 TcX AB, Detron HB and MySQL Finland AB
+@c Copyright 1997-2002 TcX AB, Detron HB and MySQL Finland AB
+@c
+@c This manual is NOT distributed under a GPL style license.
+@c Use of the manual is subject to the following terms:
+@c - Conversion to other formats is allowed, but the actual
+@c content may not be altered or edited in any way.
+@c - You may create a printed copy for your own personal use.
+@c - For all other uses, such as selling printed copies or
+@c using (parts of) the manual in another publication,
+@c prior written agreement from MySQL AB is required.
+@c
+@c Please e-mail docs@mysql.com for more information or if
+@c you are interested in doing a translation.
@c
@c *********************************************************
-@c Note that @node names are used on our Website.
+@c Note that @node names are used on our web site.
@c So do not change node names without checking
@c Makefile.am and SitePages first.
@c *********************************************************
@c
@c %**start of header
-@c there's a better way to do this.. i just don't know it yet
+@c there's a better way to do this... i just don't know it yet
@c sed will remove the "@c ifnusphere " to make this valid
@c ifnusphere @set nusphere 1
@@ -66,7 +78,7 @@ END-INFO-DIR-ENTRY
@sp 10
@center @titlefont{MySQL Reference Manual}
@sp 10
-@center Copyright @copyright{} 1997-2001 MySQL AB
+@center Copyright @copyright{} 1997-2002 MySQL AB
@c blank page after title page makes page 1 be a page front.
@c also makes the back of the title page blank.
@page
@@ -95,16 +107,12 @@ END-INFO-DIR-ENTRY
@node Top, Introduction, (dir), (dir)
-@c @ifhtml
-@c <IMG SRC="Images/mysql-logo.gif">
-@c <!--Image doesn't exist. Can't find suitable replacement. (Matt) -->
-@c @end ifhtml
-
@ifinfo
-This is a manual for MySQL. This version is about the
-@value{mysql_version} version of MySQL. You can find a manual
-about any older version of MySQL in the binary or source
-distribution for that version.
+This is a manual for the @code{MySQL Database System}.
+This version is about the @value{mysql_version} version of
+@code{MySQL Server}. You can find a specific manual for any older
+version of @code{MySQL Server} in the binary or source distribution
+for that version.
@end ifinfo
@menu
@@ -112,85 +120,82 @@ distribution for that version.
* Installing:: Installing MySQL
* Tutorial:: MySQL Tutorial
* MySQL Database Administration:: MySQL Database Administration
-* MySQL Optimization:: MySQL Optimization
+* MySQL Optimisation:: MySQL Optimisation
* Reference:: MySQL language reference
* Table types:: MySQL table types
* Clients:: MySQL client tools and APIs
* Extending MySQL:: Extending MySQL
* Problems:: Problems
-* Users:: Some MySQL users
-* MySQL customer usage:: MySQL customer usage
* Contrib:: Contributed programs
* Credits:: Contributors to MySQL
* News:: MySQL change history
* Porting:: Comments on porting to other systems
* Environment variables:: MySQL environment variables
* Regexp:: Description of MySQL regular expression syntax
-* Unireg:: What is Unireg?
* GPL license:: GNU General Public License
-* LGPL license:: GNU Library General Public License
-* Placeholder:: Pieces of the manual in transit
+* LGPL license:: GNU Lesser General Public License
* Function Index:: SQL command, type and function index
* Concept Index:: Concept Index
@end menu
-
-
@node Introduction, Installing, Top, Top
@chapter General Information About MySQL
@cindex overview
@cindex general information
-@cindex online location of manual
-@cindex manual, online location
-This is the MySQL reference manual; it documents MySQL
-Version @value{mysql_version}. As MySQL is work in progress,
-the manual gets updated frequently. There is a very good chance that
-this version is out of date, unless you are looking at it online. The
-most recent version of this manual is available at
-@uref{http://www.mysql.com/documentation/} in many different formats. If you
-have a hard time finding information in the manual, you can try the
-searchable PHP version at @uref{http://www.mysql.com/documentation/manual.php}.
-
-MySQL is a very fast, multi-threaded, multi-user, and robust SQL
-(Structured Query Language) database server.
-
-MySQL is free software. It is licensed with the @strong{GNU
-GENERAL PUBLIC LICENSE} @uref{http://www.gnu.org/}.
+The @code{MySQL (TM)} software delivers a very fast, multi-threaded,
+multi-user, and robust @code{SQL} (@code{Structured Query Language})
+database server.
+@code{MySQL Server} is intended for mission-critical, heavy load
+production systems as well as for embedding into mass-deployed software.
+@code{MySQL} is a trademark of @code{MySQL AB}.
+
+The @code{MySQL} software has @code{Dual licensing}, you can use
+@code{MySQL Server} free of charge under the
+@code{GNU GENERAL PUBLIC LICENSE} (@uref{http://www.gnu.org/licenses/}).
+You can also purchase commercial @code{MySQL Server} licenses from
+@code{MySQL AB} if you do not wish to be bound by the terms of the
+@code{GPL}.
@xref{Licensing and Support}.
-@uref{http://www.mysql.com/, The MySQL home page}
-provides the latest information about MySQL.
+The @code{MySQL} web site (@uref{http://www.mysql.com/}) provides the
+latest information about the @code{MySQL} software.
The following list describes some useful sections of the manual:
@itemize @bullet
@item
-For information about the company behind MySQL, see
-@ref{What is MySQL AB}.
+For information about the company behind the @code{MySQL Database Server},
+see @ref{What is MySQL AB}.
@item
-For a discussion of MySQL's capabilities, see @ref{Features}.
+For a discussion about the capabilities of the @code{MySQL Database Server},
+see @ref{Features}.
@item
For installation instructions, see @ref{Installing}.
@item
-For tips on porting MySQL to new architectures or operating
-systems, see @ref{Porting}.
+For tips on porting the @code{MySQL Database Software} to new architectures
+or operating systems, see @ref{Porting}.
+
+@item
+For information about upgrading from a Version 3.23 release, see
+@ref{Upgrading-from-3.23}.
@item
For information about upgrading from a Version 3.22 release, see
@ref{Upgrading-from-3.22}.
@item
-For a tutorial introduction to MySQL, see @ref{Tutorial}.
+For a tutorial introduction to the @code{MySQL Database Server},
+see @ref{Tutorial}.
@item
-For examples of SQL and benchmarking information, see the benchmarking
-directory (@file{sql-bench} in the distribution).
+For examples of @code{SQL} and benchmarking information, see the
+benchmarking directory (@file{sql-bench} in the distribution).
@item
For a history of new features and bug fixes, see @ref{News}.
@@ -215,7 +220,7 @@ The @code{mysqlbug} script should be used to generate bug reports.
For source distributions, the @code{mysqlbug} script can be found in the
@file{scripts} directory. For binary distributions, @code{mysqlbug} can
be found in the @file{bin} directory. If you have found a sensitive
-security bug in MySQL, you should send an email to
+security bug in @code{MySQL Server}, you should send an e-mail to
@email{security@@mysql.com}.
@cindex errors, reporting
@@ -223,265 +228,66 @@ security bug in MySQL, you should send an email to
@cindex mailing list address
@cindex @code{mysqlbug} script, location
-If you have any suggestions concerning additions or corrections to this
-manual, please send them to the manual team at @email{docs@@mysql.com}.
-
-This is a reference manual; it does not provide general instruction on SQL
-or relational database concepts. If you want general information about SQL,
-see @ref{General-SQL}. For books that focus more specifically on
-MySQL, see @ref{MySQL-Books}.
-
@menu
-* MySQL and MySQL AB:: MySQL, MySQL AB, and Open Source
+* Manual-info:: About This Manual
+* What-is:: What Is MySQL
+* What is MySQL AB:: What Is MySQL AB
+* Licensing and Support:: MySQL Support and Licensing
+* MySQL 4.0 In A Nutshell:: MySQL 4.0 In A Nutshell
* MySQL Information Sources:: MySQL Information Sources
-* Licensing and Support:: MySQL Licensing and Support
* Compatibility:: How Standards-compatible Is MySQL?
-* Comparisons:: How MySQL Compares to Other Databases
* TODO:: MySQL and the future (The TODO)
+* Comparisons:: How MySQL Compares to Other Open Source Databases
@end menu
-@node MySQL and MySQL AB, MySQL Information Sources, Introduction, Introduction
-@section MySQL, MySQL AB, and Open Source
-
-@menu
-* What-is:: What is MySQL?
-* What is MySQL AB:: What is MySQL AB?
-* Manual-info:: About this manual
-* Manual conventions:: Conventions used in this manual
-* History:: History of MySQL
-* Features:: The main features of MySQL
-* Stability:: How stable is MySQL?
-* Table size:: How Big Can MySQL Tables Be?
-* Year 2000 compliance:: Year 2000 compliance
-@end menu
-
-
-@node What-is, What is MySQL AB, MySQL and MySQL AB, MySQL and MySQL AB
-@subsection What Is MySQL
-
-@cindex MySQL, defined
-@cindex MySQL, introduction
-
-MySQL, the most popular Open Source SQL database, is provided
-by MySQL AB. MySQL AB is a commercial company that
-builds its business providing services around the MySQL database.
-@xref{What is MySQL AB}.
-
-@table @asis
-
-@item MySQL is a database management system.
-
-A database is a structured collection of data. It may be anything from a
-simple shopping list to a picture gallery or the vast amounts of
-information in a corporate network. To add, access, and process data
-stored in a computer database, you need a database management system
-such as MySQL. Since computers are very good at handling large
-amounts of data, database management plays a central role in computing,
-as stand-alone utilities, or as parts of other applications.
-
-@cindex databases, defined
-
-@item MySQL is a relational database management system.
-
-A relational database stores data in separate tables rather than putting
-all the data in one big storeroom. This adds speed and flexibility. The
-tables are linked by defined relations making it possible to combine
-data from several tables on request. The SQL part of MySQL
-stands for "Structured Query Language" - the most common standardized
-language used to access databases.
-
-@cindex relational databases, defined
-@cindex SQL, defined
-@item MySQL is Open Source Software.
-
-Open Source means that it is possible for anyone to use and modify.
-Anybody can download MySQL from the Internet and use it
-without paying anything. Anybody so inclined can study the source code
-and change it to fit their needs. MySQL uses the GPL (GNU
-General Public License) @uref{http://www.gnu.org}, to define what you
-may and may not do with the software in different situations. If you
-feel uncomfortable with the GPL or need to embed MySQL into a
-commercial application you can buy a commercially licensed version from
-us.
-
-@cindex open source, defined
-@cindex General Public License
-
-@item Why use MySQL?
+@node Manual-info, What-is, Introduction, Introduction
+@section About This Manual
-MySQL is very fast, reliable, and easy to use. If that is what
-you are looking for, you should give it a try. MySQL also has a
-very practical set of features developed in very close cooperation with
-our users. You can find a performance comparison of MySQL
-to some other database managers on our benchmark page.
-@xref{MySQL Benchmarks}.
-
-MySQL was originally developed to handle very large databases
-much faster than existing solutions and has been successfully used in
-highly demanding production environments for several years. Though
-under constant development, MySQL today offers a rich and very
-useful set of functions. The connectivity, speed, and security make
-MySQL highly suited for accessing databases on the Internet.
-
-@item The technical features of MySQL
-
-For advanced technical information, see @ref{Reference}. MySQL is
-a client/server system that consists of a multi-threaded SQL server
-that supports different backends, several different client programs and
-libraries, administrative tools, and several programming interfaces.
-
-We also provide MySQL as a multi-threaded library which you can
-link into your application to get a smaller, faster, easier to manage
-product.
-
-@item MySQL has a lot of contributed software available.
-
-It is very likely that you will find that your favorite application or
-language already supports MySQL.
-
-@end table
-
-@cindex pronunciation, MySQL
-@cindex MySQL, pronunciation
-@cindex goals of MySQL
-The official way to pronounce MySQL is ``My Ess Que Ell'' (not
-MY-SEQUEL). But we try to avoid correcting people who say MY-SEQUEL.
-
-
-@node What is MySQL AB, Manual-info, What-is, MySQL and MySQL AB
-@subsection What Is MySQL AB
-
-@cindex MySQL AB, defined
-
-MySQL AB is the Swedish company owned and run by the MySQL
-founders and main developers. We are dedicated to developing MySQL
-and spreading our database to new users. MySQL AB owns the copyright
-to the MySQL server source code and the MySQL trademark.
-A significant amount of revenues from our services goes to developing
-MySQL. @xref{What-is}.
-
-MySQL AB has been profitable providing MySQL from the start.
-We don't get any outside funding, but have earned all our money ourselves.
-
-We are searching after partners that would like to support our development
-of MySQL so that we could accelerate the development pace. If you
-are interested in doing this, you can email @email{partner@@mysql.com} about
-this!
-
-MySQL AB has currently 20+ people
-(@uref{http://www.mysql.com/development/team.html}) on its payroll and is growing rapidly.
-
-
-Our main sources of income are:
-
-@itemize @bullet
-@item
-Commercial high quality support for MySQL provided by the
-MySQL developers themselves. If you are interested in purchasing
-a support contract, please visit @uref{https://order.mysql.com/} to view our
-support options or to order support.
-
-@item
-Consulting services. We have developers and consultants in 12 countries
-and partners in many other countries that can help you with almost any
-MySQL related issues. If you need consulting services, please
-email a good description of your needs to @email{info@@mysql.com}! If we
-can't handle this ourselves we can usually find a partner or a developer
-that can help you with your problems.
-
-@item
-We sell licenses for using MySQL as an embedded database.
-@xref{Cost}. If you have a commercial product for which you need a fast,
-high quality database, but you can't afford to make your product Open Source,
-you can buy the right to use the MySQL server under a normal
-commercial copyright. If you are interested in this you can buy
-MySQL licenses at @uref{https://order.mysql.com/} or contact us
-at @email{licensing@@mysql.com}.
-
-@item
-Advertising. @uref{http://www.mysql.com/} is a very popular web site with
-more than 10,000,000 page views per months (January 2001). By putting a
-banner on this you are guaranteed to reach a lot of potential customers
-in the Open source, Linux and database community. If you are interested
-in this email @email{advertising@@mysql.com}.
-
-@item
-We are building a partner program to be able to provide MySQL
-services in every country. If you are interested in becoming a partner
-of MySQL AB please visit
-@uref{http://www.mysql.com/information/partners.html} or email
-@email{partner@@mysql.com}.
-
-@item
-We provide MySQL training through our partner programs. For more
-information, please email @email{info@@mysql.com}.
-
-@item
-The MySQL brand has, since 1995, been associated with speed and
-reliability, and is known to be something you can depend upon. If you are
-interested in using the MySQL trademark in your marketing, you
-can email @email{info@@mysql.com} about this.
-@end itemize
-
-The MySQL core values show our dedication to MySQL and
-Open Source.
-
-We want MySQL to be:
-
-@itemize @bullet
-@item
-The best and the most used database in the world.
-@item
-Available and affordable for all.
-@item
-Easy to use.
-@item
-Continuously improved while remaining fast and safe.
-@item
-Fun to use and improve.
-@item
-Free from bugs.
-@end itemize
+@cindex online location of manual
+@cindex manual, online location
-MySQL AB and the people of MySQL AB:
+This is the @code{MySQL} reference manual; it documents @code{MySQL}
+Version @value{mysql_version}. Being a reference manual, it does not
+provide general instruction on @code{SQL} or relational database
+concepts.
-@itemize @bullet
-@item
-Promote Open Source Philosophy and support the Open Source Community.
-@item
-Aim to be good citizens.
-@item
-Prefer partners that share our values and mind-set.
-@item
-Answer mail and give support.
-@item
-Are a virtual company, networking with others.
-@item
-Work against software patents.
-@end itemize
+As the @code{MySQL Database Software} is work in progress, the manual
+is also updated frequently.
+The most recent version of this manual is available at
+@uref{http://www.mysql.com/documentation/} in many different formats,
+currently there are Texinfo, plain text, Info, HTML, PostScript, PDF
+and Windows HLP versions.
+The primary document is the Texinfo file.
+The HTML version is produced automatically using a modified version of
+@code{texi2html}.
+The plain text and Info versions are produced with @code{makeinfo}.
+The Postscript version is produced using @code{texi2dvi} and @code{dvips}.
+The PDF version is produced with @code{pdftex}.
-@node Manual-info, Manual conventions, What is MySQL AB, MySQL and MySQL AB
-@subsection About This Manual
+If you have a hard time finding information in the manual, you can try
+our searchable PHP version at @uref{http://www.mysql.com/doc/}.
-This manual is currently available in Texinfo, plain text, Info, HTML,
-PostScript, and PDF versions. The primary document is the Texinfo file.
-The HTML version is produced automatically using a modified version of
-@code{texi2html}. The plain text and Info versions are produced with
-@code{makeinfo}. The Postscript version is produced using @code{texi2dvi}
-and @code{dvips}. The PDF version is produced with @code{pdftex}.
+If you have any suggestions concerning additions or corrections to this
+manual, please send them to the manual team at @email{docs@@mysql.com}.
@cindex manual, available formats
@cindex Texinfo
This manual is written and maintained by David Axmark, Michael (Monty)
-Widenius, Jeremy Cole, and Paul DuBois. For other contributors,
-see @ref{Credits}.
+Widenius, Jeremy Cole, Arjen Lentz, and Paul DuBois. For other
+contributors, see @ref{Credits}.
+The copyright (2002) to this manual is owned by the Swedish company
+@code{MySQL AB}. @xref{Copyright}.
-@node Manual conventions, History, Manual-info, MySQL and MySQL AB
+@menu
+* Manual conventions:: Conventions Used in This Manual
+@end menu
+
+@node Manual conventions, , Manual-info, Manual-info
@subsection Conventions Used in This Manual
This manual uses certain typographical conventions:
@@ -546,7 +352,7 @@ shell> setenv VARNAME value
shell> some_command
@end example
-Often, database, table, and column names must be substituted into commands. To
+Often database, table, and column names must be substituted into commands. To
indicate that such substitution is necessary, this manual uses
@code{db_name}, @code{tbl_name} and @code{col_name}. For example, you might
see a statement like this:
@@ -606,7 +412,116 @@ alternatives are listed within braces (@samp{@{} and @samp{@}}):
@end example
-@node History, Features, Manual conventions, MySQL and MySQL AB
+@node What-is, What is MySQL AB, Manual-info, Introduction
+@section What Is MySQL
+
+@cindex MySQL, defined
+@cindex MySQL, introduction
+
+@code{MySQL}, the most popular @code{Open Source} SQL database, is
+developed and provided by @code{MySQL AB}. @code{MySQL AB} is a
+commercial company that builds its business providing services around
+the @code{MySQL} database.
+@xref{What is MySQL AB}.
+
+The @code{MySQL} web site (@uref{http://www.mysql.com/})
+provides the latest information about @code{MySQL} software and
+@code{MySQL AB}.
+
+@table @asis
+
+@item @code{MySQL} is a database management system.
+
+A database is a structured collection of data. It may be anything from a
+simple shopping list to a picture gallery or the vast amounts of
+information in a corporate network. To add, access, and process data
+stored in a computer database, you need a database management system
+such as @code{MySQL} Server. Since computers are very good at handling large
+amounts of data, database management plays a central role in computing,
+as stand-alone utilities, or as parts of other applications.
+
+@cindex databases, defined
+
+@item MySQL is a relational database management system.
+
+A relational database stores data in separate tables rather than putting
+all the data in one big storeroom. This adds speed and flexibility.
+The tables are linked by defined relations making it possible to combine
+data from several tables on request. The @code{SQL} part of
+``@code{MySQL}'' stands for ``@code{Structured Query Language}''
+- the most common standardised language used to access databases.
+
+@cindex relational databases, defined
+@cindex SQL, defined
+@item MySQL Software is Open Source.
+
+@code{Open Source} means that it is possible for anyone to use and modify.
+Anybody can download the @code{MySQL} software from the Internet and use it
+without paying anything. Anybody so inclined can study the source code
+and change it to fit their needs. The @code{MySQL} software uses the
+@code{GPL} (@code{GNU General Public License})
+@uref{http://www.gnu.org/licenses/}, to define what you
+may and may not do with the software in different situations.
+If you feel uncomfortable with the @code{GPL} or need to embed
+@code{MySQL} code into a commercial application you can buy a
+commercially licensed version from us.
+@xref{MySQL server licenses}.
+
+@cindex Open Source, defined
+@cindex General Public License
+
+@item Why use the MySQL Database Server?
+
+The @code{MySQL Database Server} is very fast, reliable, and easy to use.
+If that is what you are looking for, you should give it a try.
+@code{MySQL Server} also has a practical set of features developed in
+close cooperation with our users. You can find a performance comparison
+of @code{MySQL Server} to some other database managers on our benchmark page.
+@xref{MySQL Benchmarks}.
+
+@code{MySQL Server} was originally developed to handle large databases
+much faster than existing solutions and has been successfully used in
+highly demanding production environments for several years. Though
+under constant development, @code{MySQL Server} today offers a rich and
+useful set of functions. The connectivity, speed, and security make
+@code{MySQL Server} highly suited for accessing databases on the Internet.
+
+@item The technical features of MySQL Server
+
+For advanced technical information, see @ref{Reference}.
+The @code{MySQL Database Software} is a client/server system that consists
+of a multi-threaded @code{SQL} server that supports different backends,
+several different client programs and libraries, administrative tools,
+and a wide range of programming interfaces (@code{API}s).
+
+We also provide @code{MySQL Server} as a multi-threaded library which you
+can link into your application to get a smaller, faster, easier to manage
+product.
+
+@item There is a lot of contributed MySQL software available.
+
+It is very likely that you will find that your favorite application or
+language already supports the @code{MySQL Database Server}.
+
+@end table
+
+@cindex pronunciation, MySQL
+@cindex MySQL, pronunciation
+@cindex goals of MySQL
+The official way to pronounce @code{MySQL} is ``My Ess Que Ell'' (not
+``my sequel''), but we don't mind if you pronounce it as ``my sequel''
+or in some other localised way.
+
+
+@menu
+* History:: History of MySQL
+* Features:: The Main Features of MySQL
+* Stability:: How Stable Is MySQL?
+* Table size:: How Big Can MySQL Tables Be?
+* Year 2000 compliance:: Year 2000 Compliance
+@end menu
+
+@node History, Features, What-is, What-is
@subsection History of MySQL
@cindex MySQL history
@@ -621,340 +536,273 @@ flexible enough for our needs. This resulted in a new SQL interface to our
database but with almost the same API interface as @code{mSQL}. This API was
chosen to ease porting of third-party code.
-The derivation of the name MySQL is not perfectly clear. Our base
+The derivation of the name @code{MySQL} is not perfectly clear. Our base
directory and a large number of our libraries and tools have had the prefix
``my'' for well over 10 years. However, Monty's daughter (some years younger)
-is also named My. Which of the two gave its name to MySQL is
+is also named My. Which of the two gave its name to @code{MySQL} is
still a mystery, even for us.
-@node Features, Stability, History, MySQL and MySQL AB
+@node Features, Stability, History, What-is
@subsection The Main Features of MySQL
@cindex main features of MySQL
@cindex features of MySQL
The following list describes some of the important characteristics
-of MySQL:
+of the @code{MySQL Database Software}. @xref{MySQL 4.0 In A Nutshell}.
@c This list is too technical and should be divided into one feature
@c list comparable to commercial competition and a very technical on
@c with max limits (from crash-me) and so on.
+@table @asis
+@item Internals and Portability
@itemize @bullet
@item
+Written in C and C++. Tested with a broad range of different compilers.
+@item
+No memory leaks. The @code{MySQL} code has been tested with Purify,
+a commercial memory leakage detector.
+@item
+Works on many different platforms. @xref{Which OS}.
+@item
+Uses GNU Automake, Autoconf (Ver 2.52 or newer), and Libtool for portability.
+@item
+APIs for C, C++, Eiffel, Java, Perl, PHP, Python and Tcl. @xref{Clients}.
+@item
Fully multi-threaded using kernel threads. This means it can easily
use multiple CPUs if available.
-
@item
-C, C++, Eiffel, Java, Perl, PHP, Python and Tcl APIs. @xref{Clients}.
-
+Very fast B-tree disk tables with index compression.
@item
-Works on many different platforms. @xref{Which OS}.
+A very fast thread-based memory allocation system.
+@item
+Very fast joins using an optimised one-sweep multi-join.
+@item
+In-memory hash tables which are used as temporary tables.
+@item
+SQL functions are implemented through a highly optimised class library and
+should be as fast as possible! Usually there isn't any memory allocation
+at all after query initialisation.
+@end itemize
+@item Column Types
+@itemize @bullet
@item
Many column types: signed/unsigned integers 1, 2, 3, 4, and 8 bytes
long, @code{FLOAT}, @code{DOUBLE}, @code{CHAR}, @code{VARCHAR},
@code{TEXT}, @code{BLOB}, @code{DATE}, @code{TIME}, @code{DATETIME},
@code{TIMESTAMP}, @code{YEAR}, @code{SET}, and @code{ENUM} types.
@xref{Column types}.
-
@item
-Very fast joins using an optimized one-sweep multi-join.
+Fixed-length and variable-length records.
+@item
+@cindex default values
+All columns have default values.
+You can use @code{INSERT} to insert a subset of a table's columns; those
+columns that are not explicitly given values are set to their default
+values.
+@end itemize
+@item Commands and Functions
+@itemize @bullet
@item
Full operator and function support in the @code{SELECT} and @code{WHERE}
parts of queries. For example:
@example
-mysql> SELECT CONCAT(first_name, " ", last_name) FROM tbl_name
- WHERE income/dependents > 10000 AND age > 30;
+mysql> SELECT CONCAT(first_name, " ", last_name)
+ FROM tbl_name
+ WHERE income/dependents > 10000 AND age > 30;
@end example
@item
-SQL functions are implemented through a highly optimized class library and
-should be as fast as possible! Usually there isn't any memory allocation
-at all after query initialization.
-
-@item
Full support for SQL @code{GROUP BY} and @code{ORDER BY} clauses. Support
for group functions (@code{COUNT()}, @code{COUNT(DISTINCT ...)},
@code{AVG()}, @code{STD()}, @code{SUM()}, @code{MAX()} and @code{MIN()}).
-
@item
Support for @code{LEFT OUTER JOIN} and @code{RIGHT OUTER JOIN} with ANSI
SQL and ODBC syntax.
-
+@item
+Aliases on tables and columns are allowed as in the SQL92 standard.
+@item
+@code{DELETE}, @code{INSERT}, @code{REPLACE}, and @code{UPDATE} return
+the number of rows that were changed (affected). It is possible to return
+the number of rows matched instead by setting a flag when connecting to the
+server.
+@item
+The @code{MySQL}-specific @code{SHOW} command can be used to retrieve
+information about databases, tables, and indexes. The @code{EXPLAIN} command
+can be used to determine how the optimiser resolves a query.
+@item
+Function names do not clash with table or column names. For example,
+@code{ABS} is a valid column name. The only restriction is that for a
+function call, no spaces are allowed between the function name and the
+@samp{(} that follows it. @xref{Reserved words}.
@item
You can mix tables from different databases in the same query (as of
Version 3.22).
+@end itemize
+@item Security
+@itemize @bullet
@item
A privilege and password system that is very flexible and secure, and
allows host-based verification. Passwords are secure because all
password traffic is encrypted when you connect to a server.
+@end itemize
+@item Scalability and Limits
+@itemize @bullet
@item
-ODBC (Open-DataBase-Connectivity) support for Win32 (with source). All
-ODBC 2.5 functions and many others. For example, you can use MS Access to
-connect to your MySQL server. @xref{ODBC}.
-
-@item
-Very fast B-tree disk tables with index compression.
-
-@item
-Up to 32 indexes per table are allowed. Each index may consist of 1 to 16
-columns or parts of columns. The maximum index length is 500 bytes (this
-may be changed when compiling MySQL). An index may use a prefix
-of a @code{CHAR} or @code{VARCHAR} field.
-
-@item
-Fixed-length and variable-length records.
-
-@item
-In-memory hash tables which are used as temporary tables.
-
-@item
-Handles large databases. We are using MySQL with some
+Handles large databases. We are using @code{MySQL Server} with some
databases that contain 50,000,000 records and we know of users that
-uses MySQL with 60,000 tables and about 5,000,000,000 rows
-
-@item
-All columns have default values. You can use @code{INSERT} to insert a
-subset of a table's columns; those columns that are not explicitly given
-values are set to their default values.
-
+uses @code{MySQL Server} with 60,000 tables and about 5,000,000,000 rows.
@item
-Uses GNU Automake, Autoconf, and Libtool for portability.
-
-@item
-Written in C and C++. Tested with a broad range of different compilers.
+Up to 32 indexes per table are allowed. Each index may consist of 1 to 16
+columns or parts of columns. The maximum index width is 500 bytes
+(this may be changed when compiling @code{MySQL Server}).
+An index may use a prefix of a @code{CHAR} or @code{VARCHAR} field.
+@end itemize
+@item Connectivity
+@itemize @bullet
@item
-A very fast thread-based memory allocation system.
-
+Clients may connect to the @code{MySQL} server using TCP/IP Sockets,
+Unix Sockets (Unix), or Named Pipes (NT).
@item
-No memory leaks. MySQL has been tested with Purify, a commercial
-memory leakage detector.
+@code{ODBC} (Open-DataBase-Connectivity) support for Win32 (with source).
+All ODBC 2.5 functions and many others. For example, you can use
+MS Access to connect to your @code{MySQL} server. @xref{ODBC}.
+@end itemize
+@item Localisation
+@itemize @bullet
@item
-Includes @code{myisamchk}, a very fast utility for table checking,
-optimization, and repair. All of the functionality of @code{myisamchk}
-is also available through the SQL interface as well.
-@xref{MySQL Database Administration}.
-
+The server can provide error messages to clients in many languages.
+@xref{Languages}.
@item
Full support for several different character sets, including
-ISO-8859-1 (Latin1), big5, ujis, and more. For example, the
-Scandinavian characters `@ringaccent{a}', `@"a' and `@"o' are allowed
-in table and column names.
-
+ISO-8859-1 (Latin1), german, big5, ujis, and more. For example,
+the Scandinavian characters 'å', 'ä' and 'ö' are allowed in table
+and column names.
@item
-All data are saved in the chosen character set. All comparisons for normal
+All data is saved in the chosen character set. All comparisons for normal
string columns are case insensitive.
-
@item
Sorting is done according to the chosen character set (the Swedish
-way by default). It is possible to change this when the MySQL server
-is started up. To see an example of very advanced sorting, look at the
-Czech sorting code. MySQL supports many different character sets
-that can be specified at compile and run time.
-
-@item
-Aliases on tables and columns are allowed as in the SQL92 standard.
-
-@item
-@code{DELETE}, @code{INSERT}, @code{REPLACE}, and @code{UPDATE} return
-the number of rows that were changed (affected). It is possible to return
-the number of rows matched instead by setting a flag when connecting to the
-server.
+way by default). It is possible to change this when the @code{MySQL}
+server is started. To see an example of very advanced sorting, look
+at the Czech sorting code. @code{MySQL Server} supports many different
+character sets that can be specified at compile and run time.
+@end itemize
+@item Clients and Tools
+@itemize @bullet
@item
-Function names do not clash with table or column names. For example,
-@code{ABS} is a valid column name. The only restriction is that for a
-function call, no spaces are allowed between the function name and the
-@samp{(} that follows it. @xref{Reserved words}.
-
+Includes @code{myisamchk}, a very fast utility for table checking,
+optimisation, and repair. All of the functionality of @code{myisamchk}
+is also available through the SQL interface as well.
+@xref{MySQL Database Administration}.
@item
-All MySQL programs can be invoked with the @code{--help} or @code{-?}
+All @code{MySQL} programs can be invoked with the @code{--help} or @code{-?}
options to obtain online assistance.
-
-@item
-The server can provide error messages to clients in many languages.
-@xref{Languages}.
-
-@item
-Clients may connect to the MySQL server using TCP/IP Sockets,
-Unix Sockets (Unix), or Named Pipes (NT).
-
-@item
-The MySQL-specific @code{SHOW} command can be used to retrieve
-information about databases, tables, and indexes. The @code{EXPLAIN} command
-can be used to determine how the optimizer resolves a query.
@end itemize
+@end table
+
-@node Stability, Table size, Features, MySQL and MySQL AB
+@node Stability, Table size, Features, What-is
@subsection How Stable Is MySQL?
@cindex stability
-This section addresses the questions ``How stable is MySQL?'' and
-``Can I depend on MySQL in this project?'' We will try to clarify
-some issues and to answer some of the more important questions that seem to
-concern many people. This section has been put together from information
-gathered from the mailing list (which is very active in reporting bugs).
-
-At TcX, MySQL has worked without any problems in our projects since
-mid-1996. When MySQL was released to a wider public, we noticed that
-there were some pieces of ``untested code'' that were quickly found by the
-new users who made queries in a manner different than our own. Each new
-release has had fewer portability problems than the previous one (even though
-each has had many new features).
-
-Each release of MySQL has been usable, and there have been problems
-only when users start to use code from the ``gray zones.'' Naturally, outside
-users don't know what the gray zones are; this section attempts to indicate
-those that are currently known. The descriptions deal with Version 3.23
-of MySQL. All known and reported bugs are fixed in the latest
-version, with the exception of the bugs listed in the bugs section, which
-are things that are design-related. @xref{Bugs}.
-
-MySQL is written in multiple layers and different independent
-modules. These modules are listed below with an indication of how
+This section addresses the questions ``@emph{How stable is MySQL Server?}''
+and ``@emph{Can I depend on MySQL Server in this project?}''
+We will try to clarify these issues and answer some important
+questions that concern many potential users. The information in this
+section is based on data gathered from the mailing list, which is
+very active in identifying problems as well as reporting types of use.
+
+Original code stems back from the early 80s, providing a stable code
+base, and the ISAM table format remains backwards compatible.
+At TcX, the predecessor of @code{MySQL AB}, @code{MySQL} code has worked
+in projects since mid-1996, without any problems.
+When the @code{MySQL Database Software} was released to a wider public,
+we noticed that there were
+some pieces of ``untested code'' that were quickly found by the new
+users who made different types of queries from us. Each new release
+has had fewer portability problems (even though each new release has
+had many new features).
+
+Each release of the @code{MySQL Server} has been usable. There have only
+been problems
+when users try code from the ``gray zones.'' Naturally, new users
+don't know what the gray zones are; this section attempts to indicate
+those that are currently known.
+The descriptions mostly deal with Version 3.23 of @code{MySQL Server}.
+All known and reported bugs are fixed in the latest version, with the
+exception of those listed in the bugs section, which are things that
+are design-related. @xref{Bugs}.
+
+The @code{MySQL Server} design is multi-layered with independent modules.
+Some of the newer modules are listed below with an indication of how
well-tested each of them is:
@cindex modules, list of
@table @strong
-@item The ISAM table handler --- Stable
-This manages storage and retrieval of all data in MySQL Version 3.22
-and earlier. In all MySQL releases there hasn't been a single
-(reported) bug in this code. The only known way to get a corrupted table
-is to kill the server in the middle of an update. Even that is unlikely
-to destroy any data beyond rescue, because all data are flushed to disk
-between each query. There hasn't been a single bug report about lost data
-because of bugs in MySQL.
-
-@cindex ISAM table handler
-@cindex storing, data
-@cindex retrieving, data
-@cindex data, ISAM table handler
-
-@item The MyISAM table handler --- Stable
-This is new in MySQL Version 3.23. It's largely based on the ISAM
-table code but has a lot of new and very useful features.
-
-@item The parser and lexical analyser --- Stable
-There hasn't been a single reported bug in this system for a long time.
-
-@item The C client code --- Stable
-No known problems. In early Version 3.20 releases, there were some limitations
-in the send/receive buffer size. As of Version 3.21, the buffer size is now
-dynamic up to a default of 16M.
-
-@item Standard client programs --- Stable
-These include @code{mysql}, @code{mysqladmin}, @code{mysqlshow},
-@code{mysqldump}, and @code{mysqlimport}.
-
-@item Basic SQL --- Stable
-The basic SQL function system and string classes and dynamic memory
-handling. Not a single reported bug in this system.
-
-@item Query optimizer --- Stable
-
-@item Range optimizer --- Stable
-
-@item Join optimizer --- Stable
-
-@item Locking --- Gamma
+@item Replication -- Gamma
+Large server clusters using replication are in production use, with
+good results. Work on enhanced replication features is continuing
+in @code{MySQL} 4.0.
+
+@item @code{InnoDB} tables -- Stable (in 3.23 from 3.23.47)
+The @code{InnoDB} transactional table handler has now been declared
+stable in the @code{MySQL} 3.23 development tree, starting from
+version 3.23.47.
+@code{InnoDB} is being used in large, heavy load production systems.
+
+@item @code{BDB} tables -- Gamma
+The @code{Berkeley DB} code is very stable, but we are still improving
+the @code{BDB} transactional table handler interface in
+@code{MySQL Server}, so it will take some time before this is as well
+tested as the other table types.
+
+@item @code{FULLTEXT} -- Beta
+Full text search works but is not yet widely used.
+Important enhancements are being implemented for @code{MySQL} 4.0.
+
+@item @code{MyODBC 2.50} (uses ODBC SDK 2.5) -- Gamma
+Increasingly in wide use. Some issues brought up appear to be
+application related and independent of the ODBC driver or underlying
+database server.
+
+@item Automatic recovery of @code{MyISAM} tables -- Gamma
+This status only regards the new code in the @code{MyISAM} table
+handler that checks if the table was closed properly on open and
+executes an automatic check/repair of the table if it wasn't.
+
+@item Bulk-insert -- Alpha
+New feature in @code{MyISAM} tables in @code{MySQL} 4.0 for faster
+insert of many rows.
+
+@item Locking -- Gamma
This is very system-dependent. On some systems there are big problems
-using standard OS locking (@code{fcntl()}). In these cases, you should run the
-MySQL daemon with the @code{--skip-locking} flag. Problems are known
-to occur on some Linux systems, and on SunOS when using NFS-mounted file
-systems.
-
-@item Linux threads --- Stable
-The major problem found has been with the @code{fcntl()} call, which is
-fixed by using the @w{@code{--skip-locking}} option to
-@code{mysqld}. Some people have reported lockup problems with Version 0.5.
-LinuxThreads will need to be recompiled if you plan to use
-1000+ concurrent connections. Although it is possible to run that many
-connections with the default LinuxThreads (however, you will never go
-above 1021), the default stack spacing of 2 MB makes the application
-unstable, and we have been able to reproduce a coredump after creating
-1021 idle connections. @xref{Linux}.
-
-@item Solaris 2.5+ pthreads --- Stable
-We use this for all our production work.
-
-@item MIT-pthreads (Other systems) --- Stable
-There have been no reported bugs since Version 3.20.15 and no known bugs since
-Version 3.20.16. On some systems, there is a ``misfeature'' where some
-operations are quite slow (a 1/20 second sleep is done between each query).
-Of course, MIT-pthreads may slow down everything a bit, but index-based
-@code{SELECT} statements are usually done in one time frame so there shouldn't
-be a mutex locking/thread juggling.
-
-@item Other thread implementions --- Beta - Gamma
-The ports to other systems are still very new and may have bugs, possibly
-in MySQL, but most often in the thread implementation itself.
-
-@item @code{LOAD DATA ...}, @code{INSERT ... SELECT} --- Stable
-Some people thought they had found bugs here, but these usually have
-turned out to be misunderstandings. Please check the manual before reporting
-problems!
-
-@item @code{ALTER TABLE} --- Stable
-Small changes in Version 3.22.12.
-
-@item DBD --- Stable
-Now maintained by Jochen Wiedmann
-(@email{wiedmann@@neckar-alb.de}). Thanks!
-
-@item @code{mysqlaccess} --- Stable
-Written and maintained by Yves Carlier
-(@email{Yves.Carlier@@rug.ac.be}). Thanks!
-
-@item @code{GRANT} --- Stable
-Big changes made in MySQL Version 3.22.12.
-
-@item @strong{MyODBC} (uses ODBC SDK 2.5) --- Gamma
-It seems to work well with some programs.
-
-@item Replication -- Beta / Gamma
-We are still working on replication, so don't expect this to be rock
-solid yet. On the other hand, some MySQL users are already
-using this with good results.
-
-@item BDB Tables -- Beta
-The Berkeley DB code is very stable, but we are still improving the interface
-between MySQL and BDB tables, so it will take some time before this
-is as tested as the other table types.
-
-@item InnoDB Tables -- Beta
-This is a recent addition to @code{MySQL}. They appear to work good and
-can be used after some initial testing.
-
-@item Automatic recovery of MyISAM tables - Beta
-This only affects the new code that checks if the table was closed properly
-on open and executes an automatic check/repair of the table if it wasn't.
-
-@item MERGE tables -- Beta / Gamma
-The usage of keys on @code{MERGE} tables is still not that tested. The
-other part of the @code{MERGE} code is quite well tested.
-
-@item FULLTEXT -- Beta
-Text search seems to work, but is still not widely used.
+using standard OS locking (@code{fcntl()}). In these cases, you should
+run @code{mysqld} with the @code{--skip-locking} flag.
+Problems are known to occur on some Linux systems, and on SunOS when
+using NFS-mounted file systems.
@end table
-MySQL AB provides e-mail support for paying customers, but the
-MySQL mailing list usually provides answers to common questions.
-Bugs are usually fixed right away with a patch; for serious bugs, there is
-almost always a new release.
+@code{MySQL AB} provides high-quality support for paying customers,
+but the @code{MySQL} mailing list usually provides answers to common
+questions. Bugs are usually fixed right away with a patch; for serious
+bugs, there is almost always a new release.
-@node Table size, Year 2000 compliance, Stability, MySQL and MySQL AB
+@node Table size, Year 2000 compliance, Stability, What-is
@subsection How Big Can MySQL Tables Be?
@cindex tables, maximum size
@@ -963,31 +811,31 @@ almost always a new release.
@cindex limits, file size
@cindex files, size limits
-MySQL Version 3.22 has a 4G limit on table size. With the new
-@code{MyISAM} in MySQL Version 3.23 the maximum table size is
-pushed up to 8 million terabytes (2 ^ 63 bytes).
+@code{MySQL} Version 3.22 has a 4G limit on table size. With the new
+@code{MyISAM} table type in @code{MySQL} Version 3.23, the maximum table
+size is pushed up to 8 million terabytes (2 ^ 63 bytes).
Note, however, that operating systems have their own file size
limits. Here are some examples:
-@multitable @columnfractions .5 .5
+@multitable @columnfractions .6 .4
@item @strong{Operating System} @tab @strong{File Size Limit}
@item Linux-Intel 32 bit @tab 2G, 4G or more, depends on Linux version
@item Linux-Alpha @tab 8T (?)
@item Solaris 2.5.1 @tab 2G (possible 4G with patch)
@item Solaris 2.6 @tab 4G
@item Solaris 2.7 Intel @tab 4G
-@item Solaris 2.7 ULTRA-SPARC @tab 8T (?)
+@item Solaris 2.7 ULTRA-SPARC @tab 512G
@end multitable
On Linux 2.2 you can get bigger tables than 2G by using the LFS patch for
the ext2 file system. On Linux 2.4 there exists also patches for ReiserFS
to get support for big files.
-This means that the table size for MySQL is normally limited by
-the operating system.
+This means that the table size for @code{MySQL} databases is normally
+limited by the operating system.
-By default, MySQL tables have a maximum size of about 4G. You can
+By default, @code{MySQL} tables have a maximum size of about 4G. You can
check the maximum table size for a table with the @code{SHOW TABLE STATUS}
command or with the @code{myisamchk -dv table_name}.
@xref{SHOW}.
@@ -1006,39 +854,40 @@ have, in effect, much bigger tables. @xref{myisampack, ,
You can go around the operating system file limit for @code{MyISAM} data
files by using the @code{RAID} option. @xref{CREATE TABLE}.
-Another solution can be the included MERGE library, which allows you to
-handle a collection of identical tables as one. @xref{MERGE, MERGE
-tables}.
+Another solution can be the included @code{MERGE} library, which allows
+you to handle a collection of identical tables as one.
+@xref{MERGE, MERGE tables}.
-@node Year 2000 compliance, , Table size, MySQL and MySQL AB
+@node Year 2000 compliance, , Table size, What-is
@subsection Year 2000 Compliance
@cindex Year 2000 compliance
@cindex compliance, Y2K
@cindex date functions, Y2K compliance
-MySQL itself has no problems with Year 2000 (Y2K) compliance:
+The @code{MySQL Server} itself has no problems with Year 2000 (Y2K)
+compliance:
@itemize @bullet
@item
-MySQL uses Unix time functions and has no problems with dates
+@code{MySQL Server} uses Unix time functions and has no problems with dates
until @code{2069}; all 2-digit years are regarded to be in the range
@code{1970} to @code{2069}, which means that if you store @code{01} in a
-@code{year} column, MySQL treats it as @code{2001}.
+@code{year} column, @code{MySQL Server} treats it as @code{2001}.
@item
-All MySQL date functions are stored in one file @file{sql/time.cc}
+All @code{MySQL} date functions are stored in one file @file{sql/time.cc}
and coded very carefully to be year 2000-safe.
@item
-In MySQL Version 3.22 and later, the new @code{YEAR} column type
-can store years @code{0} and @code{1901} to @code{2155} in 1 byte and display
-them using 2 or 4 digits.
+In @code{MySQL} Version 3.22 and later, the new @code{YEAR} column type
+can store years @code{0} and @code{1901} to @code{2155} in 1 byte and
+display them using 2 or 4 digits.
@end itemize
-You may run into problems with applications that use MySQL in a
-way that is not Y2K-safe. For example, many old applications store
+You may run into problems with applications that use @code{MySQL Server}
+in a way that is not Y2K-safe. For example, many old applications store
or manipulate years using 2-digit values (which are ambiguous) rather than
4-digit values. This problem may be compounded by applications that use
values such as @code{00} or @code{99} as ``missing'' value indicators.
@@ -1047,14 +896,16 @@ Unfortunately, these problems may be difficult to fix, because different
applications may be written by different programmers, each of whom may
use a different set of conventions and date-handling functions.
-Here is a simple demonstration illustrating that MySQL doesn't have
-any problems with dates until the year 2030:
+Here is a simple demonstration illustrating that @code{MySQL Server}
+doesn't have any problems with dates until the year 2030:
@example
mysql> DROP TABLE IF EXISTS y2k;
Query OK, 0 rows affected (0.01 sec)
-mysql> CREATE TABLE y2k (date date, date_time datetime, time_stamp timestamp);
+mysql> CREATE TABLE y2k (date date,
+ date_time datetime,
+ time_stamp timestamp);
Query OK, 0 rows affected (0.00 sec)
mysql> INSERT INTO y2k VALUES
@@ -1105,1027 +956,1061 @@ range up to only @code{2030-01-01}. @code{TIMESTAMP} has a range of
@code{1970} to @code{2030} on 32-bit machines (signed value). On 64-bit
machines it handles times up to @code{2106} (unsigned value).
-Even though MySQL is Y2K-compliant, it is your responsibility to
-provide unambiguous input. See @ref{Y2K issues} for MySQL's rules
-for dealing with ambiguous date input data (data containing 2-digit year
-values).
-
-
-@node MySQL Information Sources, Licensing and Support, MySQL and MySQL AB, Introduction
-@section MySQL Information Sources
-
-@cindex manuals, about MySQL
-@cindex books, about MySQL
-
-@menu
-* MySQL-Books:: Books About MySQL
-* General-SQL:: General SQL Information and Tutorials
-* Useful Links:: Useful MySQL-related Links
-* Questions:: MySQL Mailing Lists
-@end menu
+Even though @code{MySQL Server} is Y2K-compliant, it is your responsibility
+to provide unambiguous input. See @ref{Y2K issues} for @code{MySQL Server}'s
+rules for dealing with ambiguous date input data (data containing 2-digit
+year values).
-@node MySQL-Books, General-SQL, MySQL Information Sources, MySQL Information Sources
-@subsection Books About MySQL
-For the latest book information, with user comments, please visit
-@uref{http://www.mysql.com/portal/books/html/index.html}.
+@node What is MySQL AB, Licensing and Support, What-is, Introduction
+@section What Is MySQL AB
-While this manual is still the right place for up to date technical
-information, its primary goal is to contain everything there is to know
-about MySQL. It is sometimes nice to have a bound book to read
-in bed or while you travel. Here is a list of books about MySQL and
-related subjects (in English).
+@cindex MySQL AB, defined
-By purchasing a book through these hyperlinks provided herein, you are
-contributing to the development of MySQL.
+@code{MySQL AB} is the company of the @code{MySQL} founders and main
+developers. @code{MySQL AB} was originally established in Sweden by
+David Axmark, Allan Larsson and Michael @code{Monty} Widenius.
-@emph{MySQL}
-@multitable @columnfractions .3 .7
-@item Available @tab @uref{http://service.bfast.com/bfast/click?bfmid=2181&sourceid=34233559&bfpid=0735709211&bfmtype=book, Barnes and Noble}
-@item Publisher @tab New Riders
-@item Author @tab Paul DuBois
-@item Pub Date @tab 1st Edition December 1999
-@item ISBN @tab 0735709211
-@item Pages @tab 800
-@item Price @tab $49.99 US
-@item Downloadable examples @tab
- @uref{http://www.kitebird.com/mysql-book/, @code{samp_db} distribution}
-@item Errata @tab
-@uref{http://www.kitebird.com/mysql-book/errata.html, are available here}
-@end multitable
+All the developers of the @code{MySQL} server are employed by the company.
+We are a virtual organisation with people in a dozen countries around
+the world. We communicate extensively over the net every day with each
+other and with our users, supporters and partners.
-Foreword by Michael ``Monty'' Widenius, MySQL Moderator.
-@*
+We are dedicated to developing the @code{MySQL} software and spreading
+our database to new users. @code{MySQL AB} owns the copyright to the
+@code{MySQL} source code, the @code{MySQL} logo and trademark and this
+manual. @xref{What-is}.
-In @emph{MySQL}, Paul DuBois provides you with a comprehensive guide to
-one of the most popular relational database systems. Paul has
-contributed to the online documentation for MySQL and is an
-active member of the MySQL community. The principal MySQL
-developer, Monty Widenius, and a network of his fellow developers
-reviewed the manuscript, and provided Paul with the kind of insight
-no one else could supply.
-@*
+@menu
+* MySQL AB business model and services:: The Business Model and Services of MySQL AB
+* Contact information:: Contact Information
+@end menu
-Instead of merely giving you a general overview of MySQL, Paul
-teaches you how to make the most of its capabilities. Through two
-sample database applications that run throughout the book, he
-gives you solutions to problems you're sure to face. He helps you
-integrate MySQL efficiently with third-party tools, such as PHP
-and Perl, enabling you to generate dynamic Web pages through
-database queries. He teaches you to write programs that access
-MySQL databases, and also provides a comprehensive set of
-references to column types, operators, functions, SQL syntax,
-MySQL programming, C API, Perl @code{DBI}, and PHP API.
-@emph{MySQL} simply gives you the kind of information you won't find
-anywhere else.
-@*
+The @code{MySQL} core values show our dedication to @code{MySQL} and
+@code{Open Source}.
-If you use MySQL, this book provides you with:
+We want the @code{MySQL Database Software} to be:
@itemize @bullet
@item
-An introduction to MySQL and SQL.
-@item
-Coverage of MySQL's data types and how to use them.
+The best and the most widely used database in the world.
@item
-Thorough treatment of how to write client programs in C.
-@item
-A guide to using the Perl @code{DBI} and PHP APIs for developing
-command-line and Web-based applications.
+Available and affordable for all.
@item
-Tips on administrative issues such as user accounts, backup,
-crash recovery, and security.
+Easy to use.
@item
-Help in choosing an ISP for MySQL access.
+Continuously improving while remaining fast and safe.
@item
-A comprehensive reference for MySQL's data types, operators,
-functions, and SQL statements and utilities.
+Fun to use and improve.
@item
-Complete reference guides for MySQL's C API, the Perl @code{DBI} API,
-and PHP's MySQL-related functions.
+Free from bugs.
@end itemize
-@*
-
-@emph{MySQL & mSQL}
-@multitable @columnfractions .3 .7
-@item Available @tab @uref{http://service.bfast.com/bfast/click?bfmid=2181&sourceid=34233559&bfpid=1565924347&bfmtype=book, Barnes and Noble}
-@item Publisher @tab O'Reilly
-@item Authors @tab Randy Jay Yarger, George Reese & Tim King
-@item Pub Date @tab 1st Edition July 1999
-@item ISBN @tab 1-56592-434-7, Order Number: 4347
-@item Pages @tab 506
-@item Price @tab $34.95
-@end multitable
-
-This book teaches you how to use MySQL and @code{mSQL}, two popular
-and robust database products that support key subsets of SQL on both Linux
-and Unix systems. Anyone who knows basic C, Java, Perl, or Python can
-write a program to interact with a database, either as a stand-alone
-application or through a Web page. This book takes you through the
-whole process, from installation and configuration to programming
-interfaces and basic administration. Includes plenty of tutorial
-material.
-@*
-
-@emph{Sams' Teach Yourself MySQL in 21 Days}
-@multitable @columnfractions .3 .7
-@item Available @tab @uref{http://service.bfast.com/bfast/click?bfmid=2181&sourceid=34233559&bfpid=0672319144&bfmtype=book, Barnes and Noble}
-@item Publisher @tab Sams
-@item Authors @tab Mark Maslakowski and Tony Butcher
-@item Pub Date @tab June 2000
-@item ISBN @tab 0672319144
-@item Pages @tab 650
-@item Price @tab $39.99
-@end multitable
-
-Sams' @emph{Teach Yourself MySQL in 21 Days} is for intermediate Linux users
-who want to move into databases. A large share of the audience is Web
-developers who need a database to store large amounts of information that
-can be retrieved via the Web.
-
-Sams' @emph{Teach Yourself MySQL in 21 Days} is a practical, step-by-step
-tutorial. The reader will learn to design and employ this open source
-database technology into his or her Web site using practical, hands-on
-examples to follow.
-@*
-
-@emph{E-Commerce Solutions with MySQL}
-@multitable @columnfractions .3 .7
-@item Available @tab @uref{http://service.bfast.com/bfast/click?bfmid=2181&sourceid=34233559&bfpid=0761524452&bfmtype=book, Barnes and Noble}
-@item Publisher @tab Prima Communications, Inc.
-@item Authors @tab N/A
-@item Pub Date @tab January 2000
-@item ISBN @tab 0761524452
-@item Pages @tab 500
-@item Price @tab $39.99
-@end multitable
-
-No description available.
-@*
-
-@emph{MySQL and PHP from Scratch}
-@multitable @columnfractions .3 .7
-@item Available @tab @uref{http://service.bfast.com/bfast/click?bfmid=2181&sourceid=34233559&bfpid=0789724405&bfmtype=book, Barnes and Noble}
-@item Publisher @tab Que
-@item Authors @tab N/A
-@item Pub Date @tab September 2000
-@item ISBN @tab 0789724405
-@item Pages @tab 550
-@item Price @tab $34.99
-@end multitable
-
-This book puts together information on installing, setting up, and
-troubleshooting Apache, MySQL, PHP3, and IMP into one complete
-volume. You also learn how each piece is part of a whole by learning,
-step-by-step, how to create a web-based e-mail system. Learn to run
-the equivalent of Active Server Pages (ASP) using PHP3, set up an
-e-commerce site using a database and the Apache web server, and create
-a data entry system (such as sales, product quality tracking, customer
-preferences, etc) that no installation in the PC.
-@*
-
-@emph{Professional MySQL Programming}
-@multitable @columnfractions .3 .7
-@item Available @tab @uref{http://shop.barnesandnoble.com/bookSearch/isbnInquiry.asp?isbn=1861005164, Barnes and Noble}
-@item Publisher @tab Wrox Press, Inc.
-@item Authors @tab N/A
-@item Pub Date @tab Late 2001
-@item ISBN @tab 1861005164
-@item Pages @tab 1000
-@item Price @tab $49.99
-@end multitable
-
-No description available.
-@*
-
-@emph{Professional Linux Programming}
-@multitable @columnfractions .3 .7
-@item Available @tab @uref{http://service.bfast.com/bfast/click?bfmid=2181&sourceid=34233559&bfpid=1861003013&bfmtype=book, Barnes and Noble}
-@item Publisher @tab Wrox Press, Inc.
-@item Authors @tab N/A
-@item Pub Date @tab September 2000
-@item ISBN @tab 1861003013
-@item Pages @tab 1155
-@item Price @tab $47.99
-@end multitable
-
-In this follow-up to the best-selling @emph{Beginning Linux Programming},
-you will learn from the authors' real-world knowledge and experience of
-developing software for Linux; you'll be taken through the development
-of a sample 'DVD Store' application, with 'theme' chapters addressing
-different aspects of its implementation. Meanwhile, individual
-``take-a-break'' chapters cover important topics that go beyond the
-bounds of the central theme. All focus on the practical aspects of
-programming, showing how crucial it is to choose the right tools for
-the job, use them as they should be used, and get things right first
-time.
-@*
-
-@emph{PHP and MySQL Web Development}
-@multitable @columnfractions .3 .7
-@item Available @tab @uref{http://service.bfast.com/bfast/click?bfmid=2181&sourceid=34233559&bfpid=0672317842&bfmtype=book, Barnes and Noble}
-@item Publisher @tab Sams
-@item Authors @tab Luke Welling, Laura Thomson
-@item Pub Date @tab March 2001
-@item ISBN @tab 0672317842
-@item Pages @tab 700
-@item Price @tab $49.99
-@end multitable
-
-@emph{PHP and MySQL Web Development} introduces you to the advantages
-of implementing both MySQL and PHP. These advantages are detailed
-through the provision of both statistics and several case studies. A
-practical web application is developed throughout the book, providing
-you with the tools necessary to implement a functional online
-database. Each function is developed separately, allowing you the
-choice to incorporate only those parts that you would like to
-implement. Programming concepts of the PHP language are highlighted,
-including functions which tie MySQL support into a PHP script and
-advanced topics regarding table manipulation.
-@*
-
-@strong{Books recommended by the MySQL Developers}
-
-@emph{SQL-99 Complete, Really}
-@multitable @columnfractions .3 .7
-@item Available @tab @uref{http://service.bfast.com/bfast/click?bfmid=2181&sourceid=34233559&bfpid=0879305681&bfmtype=book, Barnes and Noble}
-@item Publisher @tab CMP Books
-@item Authors @tab Peter Gulutzan, Trudy Pelzer
-@item Pub Date @tab April 1999
-@item ISBN @tab 0879305681
-@item Pages @tab 1104
-@item Price @tab $55.96
-@end multitable
-
-This book contains complete descriptions of the new standards for
-syntax, data structures, and retrieval processes of SQL databases. As
-an example-based reference manual, it includes all of the CLI
-functions, information, schema tables, and status codes, as well as a
-working SQL database provided on the companion disk.
-@*
-
-@emph{C, A reference manual}
-@multitable @columnfractions .3 .7
-@item Available @tab @uref{http://service.bfast.com/bfast/click?bfmid=2181&sourceid=34233559&bfpid=0133262243&bfmtype=book, Barnes and Noble}
-@item Publisher @tab Prentice Hall
-@item Authors @tab Samuel P. Harbison, Guy L. Steele
-@item Pub Date @tab September 1994
-@item ISBN @tab 0133262243
-@item Pages @tab 480
-@item Price @tab $35.99
-@end multitable
-
-A new and improved revision of the bestselling C language
-reference. This manual introduces the notion of "Clean C", writing C
-code that can be compiled as a C++ program, C programming style that
-emphasizes correctness, portability, maintainability, and
-incorporates the ISO C Amendment 1 (1994) which specifies new
-facilities for writing portable, international programs in C.
-@*
-
-@emph{C++ for Real Programmers}
-@multitable @columnfractions .3 .7
-@item Available @tab @uref{http://service.bfast.com/bfast/click?bfmid=2181&sourceid=34233559&bfpid=0120499428&bfmtype=book, Barnes and Noble}
-@item Publisher @tab Academic Press, Incorporated
-@item Authors @tab Jeff Alger, Jim Keogh
-@item Pub Date @tab February 1998
-@item ISBN @tab 0120499428
-@item Pages @tab 388
-@item Price @tab $39.95
-@end multitable
-
-@emph{C++ For Real Programmers} bridges the gap between C++ as described
-in beginner and intermediate-level books and C++ as it is practiced by
-experts. Numerous valuable techniques are described, organized into
-three simple themes: indirection, class hierarchies, and memory
-management. It also provides in-depth coverage of template creation,
-exception handling, pointers and optimization techniques. The focus of
-the book is on ANSI C++ and, as such, is compiler independent.
-
-@emph{C++ For Real Programmers} is a revision of
-@emph{Secrets of the C++ Masters} and includes a new appendix comparing C++
-with Java. The book comes with a 3.5" disk for Windows with source code.
-@*
-
-@emph{Algorithms in C}
-@multitable @columnfractions .3 .7
-@item Available @tab @uref{http://service.bfast.com/bfast/click?bfmid=2181&sourceid=34233559&bfpid=0201514257&bfmtype=book, Barnes and Noble}
-@item Publisher @tab Addison Wesley Longman, Inc.
-@item Authors @tab Robert Sedgewick
-@item Pub Date @tab April 1990
-@item ISBN @tab 0201514257
-@item Pages @tab 648
-@item Price @tab $45.75
-@end multitable
-
-@emph{Algorithms in C} describes a variety of algorithms in a number of
-areas of interest, including: sorting, searching, string-processing, and
-geometric, graph and mathematical algorithms. The book emphasizes
-fundamental techniques, providing readers with the tools to confidently
-implement, run, and debug useful algorithms.
-@*
-
-@emph{Multithreaded Programming with Pthreads}
-@multitable @columnfractions .3 .7
-@item Available @tab @uref{http://service.bfast.com/bfast/click?bfmid=2181&sourceid=34233559&bfpid=0136807291&bfmtype=book, Barnes and Noble}
-@item Publisher @tab Prentice Hall
-@item Authors @tab Bil Lewis, Daniel J. Berg
-@item Pub Date @tab October 1997
-@item ISBN @tab 0136807291
-@item Pages @tab 432
-@item Price @tab $34.95
-@end multitable
-
-Based on the best-selling @emph{Threads Primer},
-@emph{Multithreaded Programming with Pthreads} gives you a solid
-understanding of Posix threads: what they are, how they work, when to use
-them, and how to optimize them. It retains the clarity and humor of
-@emph{Threads Primer}, but includes expanded comparisons to Win32 and OS/2
-implementations. Code examples tested on all of the major UNIX platforms
-are featured along with detailed explanations of how and why they use threads.
-@*
-
-@emph{Programming the PERL DBI: Database Programming with PERL}
-@multitable @columnfractions .3 .7
-@item Available @tab @uref{http://service.bfast.com/bfast/click?bfmid=2181&sourceid=34233559&bfpid=1565926994&bfmtype=book, Barnes and Noble}
-@item Publisher @tab O'Reilly & Associates, Incorporated
-@item Authors @tab Alligator Descartes, Tim Bunce
-@item Pub Date @tab February 2000
-@item ISBN @tab 1565926994
-@item Pages @tab 400
-@item Price @tab $27.96
-@end multitable
-@emph{Programming the Perl DBI} is coauthored by Alligator Descartes, one
-of the most active members of the DBI community, and by Tim Bunce, the
-inventor of DBI. For the uninitiated, the book explains the architecture
-of DBI and shows you how to write DBI-based programs. For the experienced
-DBI dabbler, this book explains DBI's nuances and the peculiarities of each
-individual DBD.
-
-The book includes:
+@code{MySQL AB} and the people at @code{MySQL AB}:
@itemize @bullet
@item
-An introduction to DBI and its design.
+Promote @code{Open Source} Philosophy and support the
+@code{Open Source} Community.
@item
-How to construct queries and bind parameters.
+Aim to be good citizens.
@item
-Working with database, driver, and statement handles.
+Prefer partners that share our values and mind-set.
@item
-Debugging techniques.
+Answer e-mail and provide support.
@item
-Coverage of each existing DBD.
+Are a virtual company, networking with others.
@item
-A complete reference to DBI.
+Work against software patents.
@end itemize
-@*
+The @code{MySQL} web site (@uref{http://www.mysql.com/})
+provides the latest information about @code{MySQL} and @code{MySQL AB}.
-@node General-SQL, Useful Links, MySQL-Books, MySQL Information Sources
-@subsection General SQL Information and Tutorials
-The following book has been recommended by several people on the MySQL
-mailing list:
+@node MySQL AB business model and services, Contact information, What is MySQL AB, What is MySQL AB
+@subsection The Business Model and Services of MySQL AB
-@example
-Judith S. Bowman, Sandra L. Emerson and Marcy Darnovsky
-@emph{The Practical SQL Handbook: Using Structured Query Language}
-Second Edition
-Addison-Wesley
-ISBN 0-201-62623-3
-http://www.awl.com
-@end example
+One of the most common questions we encounter is:
+``@emph{How can you make a living from something you give away for free?}''
+This is how.
-The following book has also received some recommendations by MySQL
-users:
+@code{MySQL AB} makes money on support, services, commercial licenses
+and royalties, and we use these revenues to fund product development
+and to expand the @code{MySQL} business.
-@example
-Martin Gruber
-@emph{Understanding SQL}
-ISBN 0-89588-644-8
-Publisher Sybex 510 523 8233
-Alameda, CA USA
-@end example
+@menu
+* Business Services Support:: Support
+* Business Services Training:: Training and Certification
+* Business Services Consulting:: Consulting
+* Business Services Commercial licenses:: Commercial Licenses
+* Business Services Partnering:: Partnering
+* Business Services Advertising:: Advertising
+@end menu
-A SQL tutorial is available on the net at
-http://w3.one.net/~jhoffman/sqltut.htm
+The company has been profitable since its inception. In October 2001,
+we accepted venture financing from leading Scandinavian investors and
+a handful of business angels. This investment is used to solidify our
+business model and build a basis for sustainable growth.
-@node Useful Links, Questions, General-SQL, MySQL Information Sources
-@subsection Useful MySQL-related Links
+@node Business Services Support, Business Services Training, MySQL AB business model and services, MySQL AB business model and services
+@subsubsection Support
+@code{MySQL AB} is run and owned by the founders and main developers of
+the @code{MySQL} database. The developers are committed to giving support
+to customers and other users in order to stay in touch with their needs
+and problems. All our support is given by qualified developers. Really
+tricky questions are answered by Michael @code{Monty} Widenius, principal
+author of the @code{MySQL Server}.
+@xref{Support}.
-Apart from the following links, you can find and download a lot of
-MySQL programs, tools and APIs from the
-@uref{http://www.mysql.com/Downloads/Contrib/, Contrib directory}.
-@cindex @code{Contrib} directory
+To order support at various levels, please visit the order section at
+@uref{https://order.mysql.com/} or contact our sales staff at
+@email{sales@@mysql.com}.
-@cindex URLs to MySQL information
-@cindex related information URLs
-MySQL
-@subheading Tutorials and Manuals
-@table @asis
-@item @uref{http://michael.bacarella.com/research/mysqlmyths.html, MySQL Myths Debunked}
-MySQL used in the real world.
+@node Business Services Training, Business Services Consulting, Business Services Support, MySQL AB business model and services
+@subsubsection Training and Certification
+@cindex training
+@cindex MySQL training
+@cindex certification
+@cindex MySQL certification
+@code{MySQL AB} delivers @code{MySQL} and related training worldwide.
+We offer both open courses and In-House courses tailored to the
+specific needs of your company. @code{MySQL Training} is also available
+through our partners, the @code{Authorised MySQL Training Centers}.
+
+Our training material uses the same example databases as our
+documentation and our sample applications, and it is always updated
+to reflect the latest @code{MySQL} version. Our trainers are backed by
+the development team to guarantee the quality of the training and the
+continuous development of the course material. This also ensures
+that no questions raised during the courses remain unanswered.
+
+Attending our training courses will enable you to achieve your goals
+related to your @code{MySQL} applications. You will also:
+@itemize @bullet
+@item
+Save time.
+@item
+Improve the performance of your application(s).
+@item
+Reduce or eliminate the need for additional hardware, decreasing cost.
+@item
+Enhance security.
+@item
+Increase customers and co-workers satisfaction.
+@item
+Prepare yourself for @code{MySQL Certification}.
+@end itemize
+
+If you are interested in our training as a potential participant or
+as a training partner, please visit the training section at
+@uref{http://www.mysql.com/training/} or contact us at:
+@email{training@@mysql.com}.
+
+We plan to release the @code{MySQL Certification Program} in 2002, for
+details see @uref{http://www.mysql.com/training/certification.html}.
+If you would like to be kept informed about the
+@code{MySQL Certification Program},
+please e-mail @email{certification@@mysql.com}.
+
+
+@node Business Services Consulting, Business Services Commercial licenses, Business Services Training, MySQL AB business model and services
+@subsubsection Consulting
+@cindex consulting
+@cindex MySQL consulting
+@code{MySQL AB} and its @code{Authorised Partners} offer consulting
+services to users of @code{MySQL Server} and to those who embed
+@code{MySQL Server} in their own software, all over the world.
+
+Our consultants can help you design and tune your databases, construct
+efficient queries, tune your platform for optimal performance, resolve
+migration issues, set up replication, build robust transactional
+applications, and more.
+We also help customers embed @code{MySQL Server} in their products and
+applications for large-scale deployment.
+
+Our consultants work in close collaboration with our development team
+which ensures the technical quality of our professional services.
+Consulting assignments range from 2-day power start sessions to
+projects that span weeks and months. Our expertise does not only cover
+@code{MySQL Server}, but extends into programming and scripting
+languages such as PHP, Perl and more.
+
+If you are interested in our consulting services or want to become a
+consulting partner, please visit the consulting section of our web site
+at @uref{http://www.mysql.com/consulting/} or contact our consulting
+staff at @email{consulting@@mysql.com}.
+
+
+@node Business Services Commercial licenses, Business Services Partnering, Business Services Consulting, MySQL AB business model and services
+@subsubsection Commercial Licenses
+The @code{MySQL} database is released under the
+@code{GNU General Public License} (@code{GPL}).
+This means that the @code{MySQL} software can be used free of charge
+under the @code{GPL}. If you do not want to be bound by the @code{GPL}
+terms (like the requirement that your own application becomes @code{GPL}
+as well), you may purchase a commercial license for the same product
+from @code{MySQL AB} at @uref{https://order.mysql.com/}.
+Since @code{MySQL AB} owns the copyright to the @code{MySQL} source code,
+we are able to employ @code{Dual Licensing} which means that the same
+product is available both under @code{GPL} and under a commercial
+license. This does not in any way affect the @code{Open Source}
+commitment of @code{MySQL AB}. For details about when a commercial
+license is required, please see @ref{MySQL server licenses}.
+
+We also sell commercial licenses of third-party @code{Open Source GPL}
+software that adds value to @code{MySQL Server}. A good example is the
+@code{InnoDB} transactional table handler that offers @code{ACID}
+support, row-level locking, crash recovery, multiversioning, foreign
+key support, and more. @xref{InnoDB}.
+
+
+@node Business Services Partnering, Business Services Advertising, Business Services Commercial licenses, MySQL AB business model and services
+@subsubsection Partnering
+@cindex partnering with MySQL AB
+@code{MySQL AB} has a worldwide partner programme that covers training
+courses, Consulting & Support, publications plus reselling and
+distributing @code{MySQL} and related products. @code{MySQL AB Partners}
+get visibility on the @uref{http://www.mysql.com/} web site and the right
+to use special versions of the @code{MySQL} trademarks to identify their
+products and promote their business.
+
+If you are interested in becoming a @code{MySQL AB Partner}, please e-mail
+to @email{partner@@mysql.com}.
+
+The word @code{MySQL} and the @code{MySQL} dolphin logo are trademarks of
+@code{MySQL AB}. @xref{MySQL AB Logos and Trademarks}.
+These trademarks represent a significant value that the @code{MySQL}
+founders have built over the years.
+
+
+@node Business Services Advertising, , Business Services Partnering, MySQL AB business model and services
+@subsubsection Advertising
+The @code{MySQL} web site (@uref{http://www.mysql.com/}) is popular among
+developers and users. In October 2001, we served 10 million page views.
+Our visitors represent a group that makes purchase decisions and
+recommendations for both software and hardware. Twelve per cent of our
+visitors authorise purchase decisions, and only nine per cent are not
+involved in purchase decisions at all. More than 65% have made one or
+more online business purchase within the last half-year, and 70% plan
+to make one in the next months.
+
+If you are interested in placing banner ads on our web site
+@uref{http://www.mysql.com/}, please send an email to
+@email{advertising@@mysql.com}.
+
+
+@node Contact information, , MySQL AB business model and services, What is MySQL AB
+@subsection Contact Information
-@item @uref{http://www.4t2.com/mysql}
-Information about the German MySQL mailing list.
+@cindex contact information
+@cindex employment, contact information
+@cindex licensing, contact information
+@cindex advertising, contact information
+@cindex employment with MySQL
+@cindex jobs at MySQL
-@item @uref{http://www2.rent-a-database.de/mysql/}
-MySQL handbook in German.
+The @code{MySQL} web site (@uref{http://www.mysql.com/})
+provides the latest information about @code{MySQL} and @code{MySQL AB}.
-@item @uref{http://www.bitmover.com:8888//home/bk/mysql}
-Web access to the MySQL BitKeeper repository.
+For press service and inquiries not covered in our News releases
+(@uref{http://www.mysql.com/news/}), please e-mail to
+@email{press@@mysql.com}.
-@item @uref{http://www.analysisandsolutions.com/code/mybasic.htm}
-Beginners MySQL Tutorial on how to install and set up
-MySQL on a Windows machine.
+If you have a valid support contract with @code{MySQL AB}; you will
+get timely, precise answers to your technical questions about the
+@code{MySQL} software. For more information, see @ref{Support}.
+You can order your support contract at
+@uref{https://order.mysql.com/}, or send an email to
+@email{sales@@mysql.com}.
-@item @uref{http://www.devshed.com/Server_Side/MySQL/}
-A lot of MySQL tutorials.
+For information about @code{MySQL} training, please visit the training
+section at @uref{http://www.mysql.com/training/}. If you have
+restricted access to the Internet, please contact the @code{MySQL AB}
+training staff at @email{training@@mysql.com}.
+@xref{Business Services Training}.
+
+For information on the @code{MySQL Certification Program}, please see
+@uref{http://www.mysql.com/training/certification.html}.
+If you would like to be kept informed about the
+@code{MySQL Certification Program}, please e-mail
+@email{certification@@mysql.com}.
+@xref{Business Services Training}.
+
+If you're interested in consulting, please visit the consulting
+section at @uref{http://www.mysql.com/consulting/}. If you have
+restricted access to the Internet, please contact the @code{MySQL AB}
+consulting staff at @email{consulting@@mysql.com}.
+@xref{Business Services Consulting}.
+
+Commercial licenses may be purchased online at
+@uref{https://order.mysql.com/}. There you will also find information
+on how to fax your purchase order to @code{MySQL AB}. If you have
+questions regarding licensing or you want a quote for a high-volume
+license deal, please fill in the contact form on our web site
+(@uref{http://www.mysql.com/}) or send an email
+to @email{licensing@@mysql.com} (for licensing questions) or to
+@email{sales@@mysql.com} (for sales inquiries).
+@xref{MySQL server licenses}.
-@item @uref{http://mysql.hitstar.com/}
-MySQL manual in Chinese.
+If you represent a business that is interested in partnering with
+@code{MySQL AB}, please send e-mail to @email{partner@@mysql.com}.
+@xref{Business Services Partnering}.
+
+If you are interested in placing a banner advertisement on the
+@code{MySQL} web site (@uref{http://www.mysql.com/}), please send
+e-mail to @email{advertising@@mysql.com}.
+@xref{Business Services Advertising}.
+
+For more information on the @code{MySQL} trademark policy, refer to
+@uref{http://www.mysql.com/company/trademark.html} or email
+@email{trademark@@mysql.com}.
+@xref{MySQL AB Logos and Trademarks}.
+
+If you are interested in any of the @code{MySQL AB} jobs listed in our
+jobs section (@uref{http://www.mysql.com/development/jobs/}),
+please send an e-mail to @email{jobs@@mysql.com}.
+Please do not send your cv as an attachment, but rather as plain text
+at the end of your email.
+
+For general discussion amongst our many users, please direct your
+attention to the appropriate mailing list.
+@xref{Questions}.
+
+Reports of errors (often called bugs), as well as questions and
+comments, should be sent to the mailing list at
+@email{mysql@@lists.mysql.com}. If you have found a sensitive
+security bug in the @code{MySQL Server}, you should send an e-mail
+to @email{security@@mysql.com}.
+@xref{Bug reports}.
-@item @uref{http://www.linuxplanet.com/linuxplanet/tutorials/1046/1/}
-Setting Up a MySQL-based Web site.
+If you have benchmark results that we can publish, please
+contact us at @email{benchmarks@@mysql.com}.
-@item @uref{http://www.hotwired.com/webmonkey/backend/tutorials/tutorial1.html}
-MySQL-Perl tutorial.
+If you have any suggestions concerning additions or corrections to this
+manual, please send them to the manual team at @email{docs@@mysql.com}.
-@item @uref{http://www.iserver.com/support/contrib/perl5/modules.html}
-Installing new Perl modules that require locally installed modules.
+For questions or comments about the workings or content of the
+@code{MySQL} web site (@uref{http://www.mysql.com/}),
+please send e-mail to @email{webmaster@@mysql.com}.
-@item @uref{http://www.hotwired.com/webmonkey/databases/tutorials/tutorial4.html}
-PHP/MySQL Tutorial.
+Questions about the @code{MySQL Portals}
+(@uref{http://www.mysql.com/portal/})
+may be sent to @email{portals@@mysql.com}.
-@item @uref{http://www.useractive.com/}
-Hands on tutorial for MySQL.
-@end table
+@code{MySQL AB} has a privacy policy, which can be read at
+@uref{http://www.mysql.com/company/privacy.html}.
+For any queries regarding this policy, please e-mail
+@email{privacy@@mysql.com}.
-@subheading Porting MySQL/Using MySQL on Different Systems
+For all other inquires, please send e-mail to @email{info@@mysql.com}.
-@table @asis
-@item @uref{http://www.entropy.ch/software/macosx/mysql/}
-Binary of MySQL for Mac OS X Client. Includes information of how to
-build and use MySQL on Mac OS X.
-@item @uref{http://xclave.macnn.com/MySQL/}
-The Mac OS Xclave. Running MySQL on Mac OS X.
+@node Licensing and Support, MySQL 4.0 In A Nutshell, What is MySQL AB, Introduction
+@section MySQL Support and Licensing
-@item @uref{http://www.prnet.de/RegEx/mysql.html}
-MySQL for Mac OS X Server.
+@cindex licensing terms
+@cindex support terms
-@item @uref{http://www.latencyzero.com/macosx/mysql.html}
-Building MySQL for Mac OS X.
+This section describes @code{MySQL} support and licensing arrangements:
-@item @uref{http://www.essencesw.com/Software/mysqllib.html}
-New Client libraries for the Mac OS Classic (Macintosh).
+@menu
+* Support:: Support Offered by MySQL AB
+* Copyright:: Copyrights and Licenses Used by MySQL
+* MySQL server licenses:: MySQL Server Licenses
+* MySQL AB Logos and Trademarks:: MySQL AB Logos and Trademarks
+@end menu
-@item @uref{http://www.lilback.com/macsql/}
-Client libraries for Mac OS Classic (Macintosh).
-@item @uref{http://sixk.maniasys.com/index_en.html}
-MySQL for Amiga
-@end table
+@node Support, Copyright, Licensing and Support, Licensing and Support
+@subsection Support Offered by MySQL AB
-@subheading Perl-related Links
+@cindex support, types
+@cindex types of support
+@cindex commercial support, types
+@cindex costs, support
+@cindex licensing costs
+@cindex support costs
+@cindex prices, support
+
+Technical support from @code{MySQL AB} means individualised answers
+to your unique problems direct from the software engineers who code
+the @code{MySQL} database engine.
+
+We try to take a broad and inclusive view of technical support. Almost
+any problem involving @code{MySQL} software is important to us if it's
+important to you.
+Typically customers seek help on how to get different commands and
+utilities to work, remove performance bottlenecks, restore crashed
+systems, understand operating system or networking impacts on @code{MySQL},
+set-up best practices for backup and recovery, utilise @code{API}s, etc.
+Our support covers only the @code{MySQL} server and our own utilities,
+not third-party products that access the @code{MySQL} server, though we
+try to help with these where we can.
+
+Detailed information about our various support options is given at
+@uref{https://order.mysql.com/} where support contracts can also be
+ordered online. If you have restricted access to the Internet, contact
+our sales staff at @email{sales@@mysql.com}.
+
+Technical support is like life insurance. You can live happily
+without it for years, but when your hour arrives it becomes
+critically important, yet it's too late to buy it!
+If you use @code{MySQL} Server for important applications and encounter
+sudden troubles, it might take too long to figure out all the answers
+yourself. You may need immediate access to the most experienced
+@code{MySQL} troubleshooters available, those employed by @code{MySQL AB}.
+
+
+@node Copyright, MySQL server licenses, Support, Licensing and Support
+@subsection Copyrights and Licenses Used by MySQL
-@table @asis
-@item @uref{http://dbimysql.photoflux.com/}
-Perl DBI with MySQL FAQ.
-@end table
+@cindex copyrights
+@cindex licenses
-@subheading MySQL Discussion Forums
+@code{MySQL AB} owns the copyright to the @code{MySQL} source code,
+the @code{MySQL} logos and trademarks and this manual.
+@xref{What is MySQL AB}.
+There are several different licenses relevant to the @code{MySQL}
+distribution:
-@table @asis
-@item @uref{http://www.weberdev.com/}
-Examples using MySQL; (check Top 20)
+@enumerate
+@item
+The @code{MySQL}-specific source needed to build the @code{mysqlclient}
+library is licensed under the @code{LGPL} and the programs in the
+@file{client} directory are under the @code{GPL}. Each file states
+at the beginning which license it is under.
-@item @uref{http://futurerealm.com/forum/futureforum.htm}
-FutureForum Web Discussion Software.
-@end table
+@item
+The client library, and the @code{GNU} @code{getopt} library, are covered
+by the ``GNU LESSER GENERAL PUBLIC LICENSE.'' @xref{LGPL license}.
+The aim of this is to make it possible to add MySQL support (client
+side, i.e. the ability to connect to a @code{MySQL} server) into
+commercial products without a license.
-@c FIX We should get longer descriptions for things in this category!
-@subheading Commercial Applications that Support MySQL
+@item
+All the source in the server, and the @code{GNU} @code{readline} library,
+are covered by the ``GNU GENERAL PUBLIC LICENSE.'' @xref{GPL license}.
+The text of this license can also be found as the file @file{COPYING}
+in the distributions.
-@table @asis
-@item @uref{http://www.supportwizard.com/}
-SupportWizard; Interactive helpdesk on the Web (This product includes a
-licensed copy of MySQL.)
-
-@item @uref{http://www.sonork.com/}
-Sonork, Instant Messenger that is not only Internet oriented. It's
-focused on private networks and on small to medium companies. Client
-is free, server is free for up to 5 seats.
-
-@item @uref{http://www.stweb.org/}
-StWeb - Stratos Web and Application server - An easy-to-use, cross
-platform, Internet/Intranet development and deployment system for
-development of web-enabled applications. The standard version of StWeb
-has a native interface to MySQL database.
-
-@item @uref{http://www.rightnowtech.com/}
-Right Now Web; Web automation for customer service.
-
-@item @uref{http://www.icaap.org/Bazaar/}
-Bazaar; Interactive Discussion Forums with Web interface.
-
-@cindex PhoneSweep
-@item @uref{http://www.phonesweep.com/}
-PhoneSweepT is the world's first commercial Telephone Scanner. Many break-ins
-in recent years have come not through the Internet, but through unauthorized
-dial-up modems. PhoneSweep lets you find these modems by repeatedly placing
-phone calls to every phone number that your organization
-controls. PhoneSweep has a built-in expert system that can recognize
-more than 250 different kinds of remote-access programs, including
-Carbon Copy(TM), pcANYWHERE(TM), and Windows NT RAS. All information is stored
-in the SQL database. It then generates a comprehensive report detailing
-which services were discovered on which dial-up numbers in your organization.
-@end table
+@item
+Some parts of the source (the @code{regexp} library) are covered
+by a Berkeley-style copyright.
-@subheading SQL Clients and Report Writers
+@item
+Older versions of @code{MySQL} (3.22 and earlier) are subject to a
+more strict license
+(@uref{http://www.mysql.com/support/arrangements/mypl.html}).
+See the documentation of the specific version for information.
-@table @asis
-@item @uref{http://www.urbanresearch.com/software/utils/urbsql/index.html, urSQL}
-SQL Editor and Query Utility. Custom syntax highlighting, editable
-results grid, exportable result-sets, basic MySQL admin functions,
-Etc.. For Windows.
+@item
+The manual is @emph{not} distributed under a @code{GPL} style license.
+Use of the manual is subject to the following terms:
+@itemize @bullet
+@item
+Conversion to other formats is allowed, but the actual content
+may not be altered or edited in any way.
+@item
+You may create a printed copy for your own personal use.
+@item
+For all other uses, such as selling printed copies or using
+(parts of) the manual in another publication, prior written
+agreement from @code{MySQL AB} is required.
+@end itemize
+Please e-mail @email{docs@@mysql.com} for more information or
+if you are interested in doing a translation.
+@end enumerate
-@item @uref{http://www.edatanew.com/, MySQL Data Manager}
-MySQL Data Manager * is platform independent web client
-(written in perl) for MySQL server over TCP/IP.
+For information about how the @code{MySQL} licenses work in practice,
+please refer to @ref{MySQL server licenses}.
+Also see @ref{MySQL AB Logos and Trademarks}.
-@item @uref{http://ksql.sourceforge.net/}
-KDE MySQL client.
-@item @uref{http://www.ecker-software.de}
-A Windows GUI client by David Ecker.
+@node MySQL server licenses, MySQL AB Logos and Trademarks, Copyright, Licensing and Support
+@subsection MySQL Server Licenses
-@item @uref{http://www.icaap.org/software/kiosk/}
-Kiosk; a MySQL client for database management. Written in Perl.
-Will be a part of Bazaar.
+@cindex licensing policy
+@cindex technical support, licensing
+@cindex support, licensing
+@cindex General Public License, MySQL
+@cindex GPL, MySQL
+@cindex licensing, examples
+@cindex selling products
+@cindex products, selling
-@item @uref{http://www.casestudio.com/}
-Db design tool that supports MySQL 3.23.
+The @code{MySQL} server is released under the
+@code{GNU General Public License} (@code{GPL}),
+which probably is the best known @code{Open Source} license.
+The formal terms of the @code{GPL} license can be found at
+@uref{http://www.gnu.org/licenses/}.
+See also @uref{http://www.gnu.org/licenses/gpl-faq.html}.
-@item @uref{http://home.skif.net/~voland/zeos/eng/index.html}
-Zeos - A client that supports MySQL, Interbase and PostgreSQL.
+Since the @code{MySQL} server is released under the @code{GPL},
+it may often be used for free, but for certain uses you may want
+or need to buy commercial licenses from @code{MySQL AB} at
+@uref{https://order.mysql.com/}.
-@item @uref{http://www.geocities.com/SiliconValley/Ridge/4280/GenericReportWriter/grwhome.html}
-A free report writer in Java
+Older versions of @code{MySQL} (3.22 and earlier) are subject to a
+more strict license
+(@uref{http://www.mysql.com/support/arrangements/mypl.html}).
+See the documentation of the specific version for information.
-@item @uref{http://www.javaframework.de}
-MySQLExport - Export of MySQL create statements and data in a lot of
-different formats (SQL, HTML, CVS, text, ZIP, GZIP...)
+Please note that the use of the @code{MySQL} server under commercial
+license, @code{GPL} or the old @code{MySQL} license does not
+automatically give you the right to use @code{MySQL AB} trademarks.
+@xref{MySQL AB Logos and Trademarks}.
-@item @uref{http://dlabs.4t2.com}
-M2D, a MySQL Administration client for Windows. M2D supports
-administration of MySQL databases, creation of new databases and
-tables, editing, and more.
-@item @uref{http://dlabs.4t2.com}
-Dexter, a small server written in Perl which can be used as a proxy server for
-MySQL or as a database extender.
+@menu
+* Using the MySQL server under a commercial license:: Using the MySQL Server Under a Commercial License
+* Using the MySQL server for free under GPL:: Using the MySQL Server for Free Under GPL
+@end menu
-@item @uref{http://www.scibit.com/Products/Software/Utils/Mascon.asp}
-Mascon is a powerful Win32 GUI for administering MySQL databases.
+@node Using the MySQL server under a commercial license, Using the MySQL server for free under GPL, MySQL server licenses, MySQL server licenses
+@subsubsection Using the MySQL Server Under a Commercial License
-@item @uref{http://www.rtlabs.com/}
-MacSQL Monitor. GUI for MySQL, ODBC, and JDBC databases for the Mac OS.
-@end table
+The @code{GPL} license is contagious in the sense that when a program
+is linked to a @code{GPL} program the resulting product must also be
+released under @code{GPL} lest you break the license terms and forfeit
+your right to use the @code{GPL} program altogether.
+
+You need a commercial license:
-@subheading Distributions that Include MySQL
+@itemize @bullet
+@item
+When you link a program with code from the @code{MySQL} server or from
+@code{GPL} released clients and don't want the resulting product to be
+@code{GPL}, maybe because you want to build a commercial product or keep
+the added non-@code{GPL} code closed source for other reasons. When
+purchasing commercial licenses, you are not using the @code{MySQL} server
+under @code{GPL} even though it's the same code.
-@c FIX add the rest (at least a couple more Linuxes)
+@item
+When you distribute a non-@code{GPL} application that ONLY works with the
+@code{MySQL} server and ship it with the @code{MySQL} server. This type
+of solution is actually considered to be linking even if it's done over
+a network.
-@table @asis
-@item @uref{http://www.suse.com/}
-SuSE Linux (6.1 and above)
+@item
+When you distribute copies of the @code{MySQL} server without providing
+the source code as required under the @code{GPL} license.
-@item @uref{http://www.redhat.com/}
-RedHat Linux (7.0 and above)
+@item
+When you want to support the further development of the @code{MySQL}
+database even if you don't formally need a commercial license.
+Purchasing support directly from @code{MySQL AB} is another good way
+of contributing to the development of the @code{MySQL} software, with
+immediate advantages for you.
+@xref{Support}.
+@end itemize
-@item @uref{http://distro.conectiva.com.br}
-Conectiva Linux (4.0 and above)
-@end table
+If you require a license, you will need one for each installation of the
+@code{MySQL} server. This covers any number of CPUs on a machine, and there
+is no artificial limit on the number of clients that connect to the server
+in any way.
-@subheading Web Development Tools that Support MySQL
+To purchase commercial licenses and support, please visit the order section
+of our web site at @uref{https://order.mysql.com/}. If you have restricted
+access to the Internet, please contact our sales staff at
+@email{sales@@mysql.com}.
-@table @asis
-@item @uref{http://www.php.net/}
-PHP: A server-side HTML-embedded scripting language.
-@item @uref{http://www.midgard-project.org}
-The Midgard Application Server; a powerful Web development environment
-based on MySQL and PHP.
+@node Using the MySQL server for free under GPL, , Using the MySQL server under a commercial license, MySQL server licenses
+@subsubsection Using the MySQL Server for Free Under GPL
+
+@cindex licensing, free
+@cindex free licensing
+
+You can use the @code{MySQL} server for free under the @code{GPL}:
+
+@itemize @bullet
+@item
+When you link a program with code from the @code{MYSQL} server and
+release the resulting product under @code{GPL}.
+
+@item
+When you distribute the @code{MySQL} server source code bundled with
+other programs that are not linked to or dependant on @code{MySQL Server}
+for their functionality even if you sell the distribution commercially.
-@item @uref{http://www.smartworker.org}
-SmartWorker is a platform for Web application development.
+@item
+When using the @code{MySQL} server internally in your company.
-@item @uref{http://xsp.lentus.se/}
-XSP: e(X)tendible (S)erver (P)ages and is a HTML embedded tag language
-written in Java (previously known as XTAGS.)
+@item
+When include the @code{MySQL} client code in a commercial program.
+The client part of the @code{MySQL} software is licensed under the
+@code{LGPL} (@code{GNU Lesser General Public License}).
+The formal terms of the @code{LGPL} license can be found at
+@uref{http://www.gnu.org/licenses/}.
-@cindex dbServ
-@item @uref{http://www.dbServ.de/}
-dbServ is an extension to a web server to integrate database output into
-your HTML code. You may use any HTML function in your output. Only the
-client will stop you. It works as standalone server or as Java servlet.
+However, the @code{mysql} command-line client does include code
+from the @code{GNU} @code{readline} library that is under the @code{GPL}.
-@item @uref{http://www.chilisoft.com/}
-Platform independent ASP from Chili!Soft
+@item
+@cindex ISP services
+@cindex services, ISP
+@cindex services, web
+@cindex Internet Service Providers
+When you are an Internet Service Provider (ISPs) offering web
+hosting with @code{MySQL} servers for your customers.
+On the other hand, we do encourage people to use ISPs that have
+@code{MySQL} support, as this will give them the confidence that if
+they have some problem with the @code{MySQL} installation, their ISP
+will in fact have the resources to solve the problem for them.
-@item @uref{http://www.voicenet.com/~zellert/tjFM}
-A JDBC driver for MySQL.
+All ISPs that want to keep themselves up-to-date should subscribe
+to our @code{announce} mailing list so that they can be aware of
+critical issues that may be relevant for their @code{MySQL} installations.
-@item @uref{http://www.wernhart.priv.at/php/}
-MySQL + PHP demos.
+Note that even if an ISP does not have a commercial license for
+@code{MySQL} Server, they should at least give their customers read
+access to the source of the @code{MySQL} installation so that the
+customers can verify that it is patched correctly.
-@item @uref{http://www.dbwww.com/}
-ForwardSQL: HTML interface to manipulate MySQL databases.
+@item
+@cindex web server, running
+@cindex running a web server
+When you use the @code{MySQL} Database Software in conjunction with
+a Web server, you do not need a commercial license. This is true even
+if you run a commercial Web server that uses @code{MySQL} Server, because
+you are not selling an embedded @code{MySQL} version yourself. However,
+in this case we would like you to purchase @code{MySQL} support, because
+the @code{MySQL} software is helping your enterprise.
+@end itemize
+
+If your use of @code{MySQL} database software does not require a commercial
+license, we encourage you to purchase support from @code{MySQL AB} anyway.
+This way you contribute towards @code{MySQL} development and also gain
+immediate advantages for yourself. @xref{Support}.
+
+If you use the @code{MySQL} database software in a commercial context
+such that you profit by its use, we ask that you further the development
+of the @code{MySQL} software by purchasing some level of support. We feel
+that if the @code{MySQL} database helps your business, it is reasonable to
+ask that you help @code{MySQL AB}.
+(Otherwise, if you ask us support questions, you are not only using
+for free something into which we've put a lot a work, you're asking
+us to provide free support, too.)
+
+
+@node MySQL AB Logos and Trademarks, , MySQL server licenses, Licensing and Support
+@subsection MySQL AB Logos and Trademarks
+
+@cindex logos
+@cindex trademarks
+
+Many users of the @code{MySQL} database want to display the
+@code{MySQL AB} dolphin logo on their web sites, on their books or
+boxed products. We welcome and encourage this although it should be
+noted that the word @code{MySQL} and the @code{MySQL} dolphin logo
+are trademarks of @code{MySQL AB} and may only be used as stated in
+our trademark policy at
+@uref{http://www.mysql.com/company/trademark.html}.
-@item @uref{http://www.daa.com.au/~james/www-sql/}
-WWW-SQL: Display database information.
+@menu
+* The Original MySQL logo:: The Original MySQL Logo
+* MySQL Logos that may be Used Without Written Permission:: MySQL Logos that may be Used Without Written Permission
+* When need MySQL logo permission:: When do you need a Written Permission to use MySQL Logos?
+* MySQL AB Partnership Logos:: MySQL AB Partnership Logos
+* Using MySQL word in presentations:: Using the word @code{MySQL} in Printed Text or Presentations
+* Using MySQL word in company and product names:: Using the word @code{MySQL} in Company and Product Names
+@end menu
-@item @uref{http://www.minivend.com/minivend/}
-Minivend: A Web shopping cart.
-@item @uref{http://www.heitml.com/}
-HeiTML: A server-side extension of HTML and a 4GL language at the same time.
+@node The Original MySQL logo, MySQL Logos that may be Used Without Written Permission, MySQL AB Logos and Trademarks, MySQL AB Logos and Trademarks
+@subsubsection The Original MySQL Logo
-@item @uref{http://www.metahtml.com/}
-Metahtml: A Dynamic Programming Language for WWW Applications.
+@c FIX: picture: MySQL logo
-@item @uref{http://www.binevolve.com/}
-VelocityGen for Perl and Tcl.
+The @code{MySQL} dolphin logo was designed by the Finnish advertising
+agency Priority in 2001. The dolphin was chosen as a suitable symbol
+for the @code{MySQL} database since it is a smart, fast and lean animal,
+effortlessly navigating oceans of data. We also happen to like dolphins.
-@item @uref{http://hawkeye.net/}
-Hawkeye Internet Server Suite.
+The original @code{MySQL} logo may only be used by representatives of
+@code{MySQL AB} and by those having a written agreement allowing them
+to do so.
-@item @uref{http://www.fastflow.com/}
-Network Database Connection For Linux
-@item @uref{http://www.wdbi.net/}
-WDBI: Web browser as a universal front end to databases which supports
-MySQL well.
+@node MySQL Logos that may be Used Without Written Permission, When need MySQL logo permission, The Original MySQL logo, MySQL AB Logos and Trademarks
+@subsubsection MySQL Logos that may be Used Without Written Permission
-@item @uref{http://www.webgroove.com/}
-WebGroove Script: HTML compiler and server-side scripting language.
+@c FIX: pictures: powered by, works with, included - logos
-@item @uref{http://www.ihtml.com/}
-A server-side Web site scripting language.
+We have designed a set of special @emph{Conditional Use} logos that may be
+downloaded from our web site at
+@uref{http://www.mysql.com/downloads/logos.html}
+and used on third party web sites without written permission from
+@code{MySQL AB}.
+The use of these logos is not entirely unrestricted, but as the name
+implies subject to our trademark policy that is also available on our
+web site. You should read through the trademark policy if you plan to
+use them. The requirements are basically:
-@item @uref{ftp://ftp.igc.apc.org/pub/myodbc/README}
-How to use MySQL with ColdFusion on Solaris.
+@itemize @bullet
+@item
+Use the logo you need as displayed on the @uref{http://www.mysql.com/}
+site. You may scale it to fit your needs, but not change colours or design,
+or alter the graphics in any way.
-@item @uref{http://calistra.com/MySQL/}
-Calistra's ODBC MySQL Administrator.
+@item
+Make it evident that you, and not @code{MySQL AB}, are the creator and
+owner of the site that displays the @code{MySQL} trademark.
-@cindex Webmerger
-@item @uref{http://www.webmerger.com}
-Webmerger - This CGI tool interprets files and generates dynamic output
-based on a set of simple tags. Ready-to-run drivers for MySQL and
-PostgreSQL through ODBC.
+@item
+Don't use the trademark in a way that is detrimental to @code{MySQL AB}
+or to the value of @code{MySQL AB} trademarks. We reserve the right to
+revoke the right to use the @code{MySQL AB} trademark.
-@item @uref{http://phpclub.net/}
-PHPclub - Tips and tricks for PHP.
+@item
+If you use the trademark on a web site, make it clickable, leading directly
+to @uref{http://www.mysql.com/}.
-@item @uref{http://www.penguinservices.com/scripts}
-MySQL and Perl Scripts.
+@item
+If you are using the @code{MySQL} database under @code{GPL} in an
+application, your application must (i) be @code{Open Source},
+(ii) be able to connect to a @code{MySQL} server.
+@end itemize
-@item @uref{http://www.widgetchuck.com}
-The Widgetchuck; Web Site Tools and Gadgets
+Contact us at @email{trademark@@mysql.com} to inquire about special
+arrangements to fit your needs.
-@item @uref{http://www.adcycle.com/}
-AdCycle - advertising management software.
+@node When need MySQL logo permission, MySQL AB Partnership Logos, MySQL Logos that may be Used Without Written Permission, MySQL AB Logos and Trademarks
+@subsubsection When do you need a Written Permission to use MySQL Logos?
-@cindex pwPage
-@item @uref{http://sourceforge.net/projects/pwpage/}
-pwPage - provides an extremely fast and simple approach to the creation
-of database forms. That is, if a database table exists and an HTML page
-has been constructed using a few simple guidelines, pwPage can be
-immediately used for table data selections, insertions, updates, deletions
-and selectable table content reviewing.
+In the following cases you need a written permission from @code{MySQL AB}
+before using @code{MySQL} logos:
-@item @uref{http://www.omnis-software.com/products/studio/studio.html}
-OMNIS Studio is a rapid application development (RAD) tool.
+@itemize @bullet
+@item
+When displaying any @code{MySQL AB} logo anywhere except on your web site.
-@cindex Web+
-@item @uref{http://www.webplus.com}
-talentsoft Web+ 4.6 - a powerful and comprehensive development language for
-use in creating web-based client/server applications without writing
-complicated, low-level, and time-consuming CGI programs.
-@end table
+@item
+When displaying any @code{MySQL AB} logo except the @emph{Conditional Use}
+logos above on web sites or elsewhere.
+@end itemize
-@subheading Database Design Tools with MySQL Support
+Out of legal and commercial reasons we have to monitor the use of MySQL
+trademarks on products, books etc. We will usually require a fee for
+displaying @code{MySQL AB} logos on commercial products, since we think
+it is reasonable that some of the revenue is returned to fund further
+development of the @code{MySQL} database.
-@table @asis
-@item @uref{http://www.mysql.com/documentation/dezign/}
-"DeZign for databases" is a database development tool that uses an
-entity relationship diagram (ERD).
-@end table
-@subheading Web Servers with MySQL Tools
+@node MySQL AB Partnership Logos, Using MySQL word in presentations, When need MySQL logo permission, MySQL AB Logos and Trademarks
+@subsubsection MySQL AB Partnership Logos
-@table @asis
-@item @uref{ftp://ftp.kcilink.com/pub/}
-mod_auth_mysql, An Apache authentication module.
+@c FIX: pictures: partnership logos - Bertrand?
-@item @uref{http://www.roxen.com/}
-The Roxen Challenger Web server.
-@end table
+@code{MySQL} partnership logos may only be used by companies and persons
+having a written partnership agreement with @code{MySQL AB}. Partnerships
+include certification as a @code{MySQL} trainer or consultant.
+Please see @xref{Business Services Partnering,,Partnering}.
-@subheading Extensions for Other Programs
-@table @asis
-@item @uref{http://www.seawood.org/msql_bind/}
-MySQL support for BIND (The Internet Domain Name Server).
+@node Using MySQL word in presentations, Using MySQL word in company and product names, MySQL AB Partnership Logos, MySQL AB Logos and Trademarks
+@subsubsection Using the word @code{MySQL} in Printed Text or Presentations
-@item @uref{http://www.inet-interactive.com/sendmail/}
-MySQL support for Sendmail and Procmail.
-@end table
+@code{MySQL AB} welcomes references to the @code{MySQL} database, but
+note that the word @code{MySQL} is a trademark of @code{MySQL AB}.
+Because of this, you should append the trademark symbol @code{TM} to
+the first or most prominent use of the word @code{MySQL} in a text and
+where appropriate use a statement that @code{MySQL} is a trademark of
+@code{MySQL AB}. Please refer to our trademark policy at
+@uref{http://www.mysql.com/company/trademark.html} for details.
-@subheading Using MySQL with Other Programs
-@table @asis
-@item @uref{http://www.iserver.com/support/addonhelp/database/mysql/msaccess.html}
-Using MySQL with Access.
+@node Using MySQL word in company and product names, , Using MySQL word in presentations, MySQL AB Logos and Trademarks
+@subsubsection Using the word @code{MySQL} in Company and Product Names
-@item @uref{http://www.iserver.com/support/contrib/perl5/modules.html}
-Installing new Perl modules that require locally installed modules.
-@end table
+Use of the word @code{MySQL} in product or company names or in Internet
+domain names is not allowed without written permission from @code{MySQL AB}.
-@subheading ODBC-related Links
-@table @asis
-@item @uref{http://www.iodbc.org/}
-Popular iODBC Driver Manager (libiodbc) now available as Open Source.
+@node MySQL 4.0 In A Nutshell, MySQL Information Sources, Licensing and Support, Introduction
+@section MySQL 4.0 In A Nutshell
-@item @uref{http://users.ids.net/~bjepson/freeODBC/}
-The FreeODBC Pages.
+Dateline: 16 October 2001, Uppsala, Sweden
-@item @uref{http://genix.net/unixODBC/}
-The unixODBC Project goals are to develop and promote unixODBC to be the
-definitive standard for ODBC on the Linux platform. This is to include GUI
-support for KDE.
+Long promised by @code{MySQL AB} and long awaited by our users,
+MySQL Server 4.0 is now available in alpha version for download from
+@uref{http://www.mysql.com/} and our mirrors.
-@item @uref{http://www.sw-soft.com/products/BtrieveODBC/}
-A MySQL-based ODBC driver for Btrieve.
-@end table
+Main new features of MySQL Server 4.0 are geared towards our existing
+business and community users, enhancing the MySQL database software
+as the solution for mission-critical, heavy load database systems.
+Other new features target the users of embedded databases.
-@subheading @strong{API}-related Links
+@menu
+* Nutshell Stepwise Rollout:: Stepwise Rollout
+* Nutshell Ready for Immediate Development Use:: Ready for Immediate Development Use
+* Nutshell Embedded MySQL:: Embedded MySQL
+* Nutshell Other features:: Other Features Available From MySQL 4.0.0
+* Nutshell Future features:: Future MySQL 4.0 Features
+* Nutshell 4.1 development release:: MySQL 4.1, The Following Development Release
+@end menu
-@table @asis
-@item @uref{http://www.jppp.com/}
-Partially implemented TDataset-compatible components for MySQL.
-@item @uref{http://www.riverstyx.net/qpopmysql/}
-qpopmysql - A patch to allow POP3 authentication from a MySQL
-database. There's also a link to Paul Khavkine's patch for Procmail to
-allow any MTA to deliver to users in a MySQL database.
+@node Nutshell Stepwise Rollout, Nutshell Ready for Immediate Development Use, MySQL 4.0 In A Nutshell, MySQL 4.0 In A Nutshell
+@subsection Stepwise Rollout
-@item @uref{http://www.pbc.ottawa.on.ca}
-Visual Basic class generator for Active X.
+The rollout of MySQL Server 4.0 will come in several steps, with
+the first version labelled 4.0.0 already containing most of the
+new features. Additional features will be incorporated into
+MySQL 4.0.1, 4.0.2 onwards; very probably within a couple of months,
+MySQL 4.0 will be labelled beta. Further new features will then
+be added in MySQL 4.1, which is targeted for alpha release
+in early 2002.
-@item @uref{http://www.essencesw.com/Software/mysqllib.html}
-New Client libraries for the Mac OS Classic (Macintosh).
-@item @uref{http://www.lilback.com/macsql/}
-Client libraries for the Macintosh.
+@node Nutshell Ready for Immediate Development Use, Nutshell Embedded MySQL, Nutshell Stepwise Rollout, MySQL 4.0 In A Nutshell
+@subsection Ready for Immediate Development Use
-@item @uref{http://www.essencesw.com/Plugins/mysqlplug.html}
-Plugin for REALbasic (for Macintosh)
+Users are not recommended to switch their production systems
+to MySQL Server 4.0 until it is released in beta version.
+However, even the initial release has passed our extensive
+test suite without any errors on any of the platforms we test on.
+Due to the large number of new features, we thus recommend
+MySQL Server 4.0 even in alpha form for development use, with
+the release schedule of MySQL Server 4.0 being such that it will
+reach stable state before the deployment of user applications
+now under development.
-@item @uref{http://www.iis.ee.ethz.ch/~neeri/macintosh/gusi-qa.html}
-A library that emulates BSD sockets and pthreads on Macintosh. This can
-be used if you want to compile the MySQL client library on Mac.
-It could probably even be sued to port MySQL to Macintosh, but we
-don't know of anyone that has tried that.
-@cindex SCMDB
-@item @uref{http://www.dedecker.net/jessie/scmdb/}
-SCMDB - an add-on for SCM that ports the MySQL C library to scheme
-(SCM). With this library scheme developers can make connections to a
-MySQL database and use embedded SQL in their programs.
-@end table
+@node Nutshell Embedded MySQL, Nutshell Other features, Nutshell Ready for Immediate Development Use, MySQL 4.0 In A Nutshell
+@subsection Embedded MySQL
-@subheading Other MySQL-related Links
+@code{libmysqld} makes MySQL Server suitable for a vastly expanded realm of
+applications. Using the embedded MySQL server library, one can
+embed MySQL Server into various applications and electronics devices, where
+the end user has no knowledge of there actually being an underlying
+database. Embedded MySQL Server is ideal for use behind
+the scenes in internet appliances, public kiosks, turn-key
+hardware/ software combination units, high performance internet
+servers, self-contained databases distributed on CD-ROM etc.
-@table @asis
-@item @uref{http://www.satisoft.com/, SAT}
-The Small Application Toolkit (SAT) is a collection of utilities
-intended to simplify the development of small, multi-user, GUI based
-applications in a (Microsoft -or- X) Windows Client / Unix Server
-environment.
+Many embedded MySQL users will benefit from the @emph{dual licensing}
+scheme of the MySQL software, where besides the GPL license also commercial
+licensing is available for those not wishing to be bound by the GPL.
+The embedded MySQL library uses the same interface as the normal
+client library, so it is convenient and easy to use. @xref{libmysqld}.
-@item @uref{http://www.wix.com/mysql-hosting/}
-Registry of Web providers who support MySQL.
-@item @uref{http://www.softagency.co.jp/mysql/index.en.html}
-Links about using MySQL in Japan/Asia.
+@node Nutshell Other features, Nutshell Future features, Nutshell Embedded MySQL, MySQL 4.0 In A Nutshell
+@subsection Other Features Available From MySQL 4.0.0
-@item @uref{http://abattoir.cc.ndsu.nodak.edu/~nem/mysql/udf/}
-MySQL UDF Registry.
+@itemize @bullet
+@item
+Version 4.0 further increases @emph{the speed of MySQL Server}
+in a number of areas,
+such as bulk @code{INSERT}s, searching on packed indices, creation of
+@code{FULLTEXT} indices as well as @code{COUNT(DISTINCT)}.
-@item @uref{http://www.open.com.au/products.html}
-Commercial Web defect tracking system.
+@item
+The table handler @code{InnoDB} is now offered as a feature of the
+standard MySQL server, including full support for @code{transactions}
+and @code{row-level locking}.
-@item @uref{http://www.stonekeep.com/pts/}
-PTS: Project Tracking System.
+@item
+MySQL Server 4.0 will support secure traffic between the client and the server,
+greatly increasing security against malicious intrusion and unauthorised
+access. Web applications being a cornerstone of MySQL use, web developers
+have been able to use SSL to secure the traffic between the
+the end user browser and the Web application, be it written in
+PHP, Perl, ASP or using any other web development tool. However,
+the traffic between the development tool and the mysqld server
+process has been protected only by virtue of them being processes
+residing on computers within the same firewall. In MySQL Server 4.0,
+the @emph{mysqld} server daemon process can itself use
+@code{Secure Sockets Layer} (@code{SSL}),
+thus enabling secure traffic to MySQL databases from, say, a Windows
+application residing outside the firewall.
-@item @uref{http://tomato.nvgc.vt.edu/~hroberts/mot}
-Job and software tracking system.
+@item
+Our German, Austrian and Swiss users will note that we have a new character
+set latin_de which corrects the @emph{German sorting order}, placing German
+Umlauts in the same order as German telephone books.
-@item @uref{http://www.cynergi.net/exportsql/}
-ExportSQL: A script to export data from Access95+.
+@item
+Features to simplify @code{migration} from other database systems to MySQL
+Server include @code{TRUNCATE TABLE} (like in Oracle) and @code{IDENTITY} as a
+synonym for automatically incremented keys (like in Sybase). Many users will
+also be happy to learn that MySQL Server now supports the @code{UNION} statement,
+a long awaited standard SQL feature.
-@item @uref{http://SAL.KachinaTech.COM/H/1/MYSQL.html}
-SAL (Scientific Applications on Linux) MySQL entry.
+@item
+In the process of building features for new users, we have not forgotten
+requests by the community of loyal users.
+We have multi-table @code{DELETE} statements.
+By adding support for @code{symbolic linking} to @code{MyISAM} on the table
+level (and not just database level as before), as well as by enabling symlink
+handling by default on Windows, we hope to show that we take enhancement
+requests seriously.
+Functions like @code{SQL_CALC_FOUND_ROWS} and @code{FOUND_ROWS()} makes it
+possible to know how many rows a query would have returned without a
+@code{LIMIT} clause.
+@end itemize
-@item @uref{http://www.infotech-nj.com/itech/index.shtml}
-A consulting company which mentions MySQL in the right company.
-@item @uref{http://www.pmpcs.com/}
-PMP Computer Solutions. Database developers using MySQL and
-@code{mSQL}.
+@node Nutshell Future features, Nutshell 4.1 development release, Nutshell Other features, MySQL 4.0 In A Nutshell
+@subsection Future MySQL 4.0 Features
-@item @uref{http://www.aewa.org/}
-Airborne Early Warning Association.
+For the upcoming MySQL Server 4.0 releases (4.0.1, 4.0.2 and onwards),
+expect the following features now still under development:
-@item @uref{http://www.dedserius.com/y2kmatrix/}
-Y2K tester.
-@end table
+@itemize @bullet
+@item
+Mission-critical, heavy-load users of MySQL Server will appreciate
+the additions to our replication system and our online hot backup.
+Later versions of 4.0 will include @code{fail-safe replication};
+already in existing 4.0.0, the @code{LOAD DATA FROM MASTER} command
+will soon automate slave setup. The @code{online backup} will make
+it easy to add a new replication slave without taking down
+the master, and have a very low performance penalty on
+update-heavy systems.
-@subheading SQL and Database Interfaces
+@item
+A convenience feature for Database Administrators is that
+mysqld parameters (startup options) can soon be set without
+taking down the servers.
-@table @asis
-@item @uref{http://java.sun.com/products/jdbc/}
-The JDBC database access API.
+@item
+The new @code{FULLTEXT} search properties of MySQL Server 4.0 enables the
+use of @code{FULLTEXT} indexing of large text masses with both binary and
+natural language searching logic. Users can customise minimal word
+length and define their own stop word lists in any human language,
+enabling a new set of applications to be built on MySQL Server.
-@item @uref{http://www.gagme.com/mysql}
-Patch for @code{mSQL} Tcl.
+@item
+Many read-heavy applications will benefit from
+further increased speed through the rewritten @code{key cache}.
-@item @uref{http://www.amsoft.ru/easysql/}
-EasySQL: An ODBC-like driver manager.
+@item
+Many developers will also be happy to see the @code{MySQL command help}
+in the client.
+@end itemize
-@item @uref{http://www.lightlink.com/hessling/rexxsql.html}
-A REXX interface to SQL databases.
-@item @uref{http://www.mytcl.cx/}
-Tcl interface based on tcl-sql with many bugfixes.
+@node Nutshell 4.1 development release, , Nutshell Future features, MySQL 4.0 In A Nutshell
+@subsection MySQL 4.1, The Following Development Release
-@item @uref{http://www.binevolve.com/~tdarugar/tcl-sql/}
-Tcl interface.
+Internally, through a new .frm file format for table definitions,
+MySQL Server 4.0 lays the foundation for the new features of MySQL Server 4.1,
+such as @code{nested subqueries}, @code{stored procedures}, and
+@code{foreign key integrity rules}, which form the top of the
+wish list for many of our customers. Along with those, we will
+also include simpler additions, such as
+multi-table @code{UPDATE} statements.
-@item @uref{http://www.contrib.andrew.cmu.edu/~shadow/sql.html}
-SQL Reference Page with a lot of interesting links.
+After those additions, critics of the MySQL Database Server have
+to be more imaginative
+than ever in pointing out deficiencies in the MySQL Database
+Management System. For long already known for its stability,
+speed, and ease of use, MySQL Server will then match the requirement
+checklist of very demanding buyers.
-@end table
-@subheading Examples of MySQL Use
+@node MySQL Information Sources, Compatibility, MySQL 4.0 In A Nutshell, Introduction
+@section MySQL Information Sources
-@table @asis
-@c Added 990601
-@c EMAIL: thuss@little6.com (Todd Huss)
-@item @uref{http://www.little6.com/about/linux/}
-Little6 Inc., An online contract and job finding site that is powered by
-MySQL, PHP3, and Linux.
-
-@c Added 990521
-@c EMAIL: nh@delec.com (Hillbrecht Nicole)
-@item @uref{http://www.delec.com/is/products/prep/examples/BookShelf/index.html}
-DELECis - A tool that makes it very easy to create an automatically generated
-table documentation. They have used MySQL as an example.
-
-@c Added 990521
-@c EMAIL: info@worldrecords.com (Jim Rota)
-@item @uref{http://www.worldrecords.com}
-World Records - A search engine for information about music that uses
-MySQL and PHP.
-
-@item @uref{http://www.webtechniques.com/archives/1998/01/note/}
-A Contact Database using MySQL and PHP.
-
-@item @uref{http://modems.rosenet.net/mysql/}
-Web based interface and Community Calendar with PHP.
+@menu
+* Portals:: MySQL Portals
+* Questions:: MySQL Mailing Lists
+@end menu
-@item @uref{http://www.odbsoft.com/cook/sources.htm}
-Perl package to generate html from a SQL table structure and for generating
-SQL statements from an html form.
-
-@item @uref{http://www.gusnet.cx/proj/telsql/}
-Basic telephone database using @code{DBI}/@code{DBD}.
-
-@item @uref{http://tecfa.unige.ch/guides/java/staf2x/ex/jdbc/coffee-break}
-JDBC examples by Daniel K. Schneider.
-
-@item @uref{http://www.spade.com/linux/howto/PostgreSQL-HOWTO-41.html}
-SQL BNF
-
-@item @uref{http://www.ooc.com/}
-Object Oriented Concepts Inc; CORBA applications with examples in source.
-
-@item @uref{http://www.pbc.ottawa.on.ca/}
-DBWiz; Includes an example of how to manage cursors in VB.
-
-@cindex Pluribus
-@item @uref{http://keilor.cs.umass.edu/pluribus/}
-Pluribus is a free search engine that learns to improve
-the quality of its results over time. Pluribus works by recording
-which pages a user prefers among those returned for a query. A user
-votes for a page by selecting it; Pluribus then uses that knowledge
-to improve the quality of the results when someone else submits the
-same (or similar) query. Uses PHP and MySQL.
-
-@c EMAIL: paul@sword.damocles.com (Paul Bannister)
-@item @uref{http://www.stopbit.com/}
-Stopbit - A technology news site using MySQL and PHP.
-
-@item @uref{http://www.linuxsupportline.com/~kalendar/}
-KDE based calendar manager - The calendar manager has both single user
-(file based) and multi-user (MySQL database) support.
-
-@item @uref{http://tim.desert.net/~tim/imger/}
-Example of storing/retrieving images with MySQL and CGI.
-
-@item @uref{http://www.penguinservices.com/scripts}
-Online shopping cart system.
-
-@c Added 990928 from editor@city-gallery.com
-@cindex Old Photo Album
-@item @uref{http://www.city-gallery.com/album/}
-Old Photo Album - The album is a collaborative popular history of photography
-project that generates all pages from data stored in a MySQL
-database. Pages are dynamically generated through a php3 interface to the
-database content. Users contribute images and descriptions. Contributed
-images are stored on the web server to avoid storing them in the database
-as BLOBs. All other information is stored on the shared MySQL server.
-@end table
-@subheading General Database Links
+@node Portals, Questions, MySQL Information Sources, MySQL Information Sources
+@subsection MySQL Portals
-@table @asis
-@item @uref{http://www.pcslink.com/~ej/dbweb.html}
-Database Jump Site
+@cindex MySQL Portals
+@cindex manuals, about MySQL
+@cindex books, about MySQL
+@cindex MySQL Testimonials
+@cindex users, of MySQL
+@cindex news sites
+@cindex search engines, web
+@cindex web search engines
+@cindex online magazines
+@cindex magazines, online
+@cindex web sites
+@cindex services
+@cindex PHP, web sites
+@cindex consultants, list of
+@cindex web pages, miscellaneous
+@cindex @code{Contrib} directory
+@cindex URLs to MySQL information
+@cindex MySQL related information URLs
-@item @uref{http://black.hole-in-the.net/guy/webdb/}
-Homepage of the webdb-l (Web Databases) mailing list.
+The @code{MySQL Portals} (@uref{http://www.mysql.com/portal/})
+represent the ultimate resource to find @code{MySQL AB Partners},
+as well as books, or other @code{MySQL} related solutions that you
+may be looking for. Items are categorized and rated in order to
+make it easy for you to locate information.
-@item @uref{http://www.symbolstone.org/technology/perl/DBI/index.html}
-Perl @code{DBI}/@code{DBD} modules homepage.
+By registering as a user, you will have the ability to comment and
+rate items presented in portals. You will also receive relevant
+newsletters according to your user profile that you may update at
+any time.
-@item @uref{http://www.student.uni-koeln.de/cygwin/}
-Cygwin tools. Unix on top of Windows.
+Some of the current @code{MySQL Portal} categories:
-@item @uref{http://dbasecentral.com/}
-dbasecentral.com; Development and distribution of powerful and easy-to-use
-database applications and systems.
+@itemize @bullet
+@item Partners
+Find @code{MySQL AB} partners worldwide.
-@cindex Tek-Tips forums
-@cindex forums, Tek-Tips
-@item @uref{http://www.tek-tips.com/}
-Tek-Tips Forums are 800+ independent peer-to-peer non-commercial support
-forums for Computer Professionals. Features include automatic e-mail
-notification of responses, a links library, and member confidentiality
-guaranteed.
+@item Books
+Comment, vote, and buy books related to @code{MySQL}.
-@item @uref{http://www.public.asu.edu/~peterjn/btree/}
-B-Trees: Balanced Tree Data Structures.
+@item Development
+Various links to different sites that are using @code{MySQL Server}
+for different purposes, with a description of each site.
+This information can give you an idea of who uses the @code{MySQL}
+database software and how @code{MySQL Server} can fulfill
+requirements.
-@item @uref{http://www.fit.qut.edu.au/~maire/baobab/lecture/sld001.htm}
-A lecture about B-Trees.
-@end table
+Do let us know about @emph{your} site or success story too!
+@uref{http://www.mysql.com/feedback/testimonial.php}.
+
+@item Software
+Find, buy, download several applications and wrappers that make
+use of the @code{MySQL} server.
-There are also many Web pages that use MySQL. @xref{Users}.
-Send any additions to this list to @email{webmaster@@mysql.com}. We now
-require that you show a MySQL logo somewhere if you wish your
-site to be added. It is okay to have it on a ``used tools'' page or
-something similar.
+@item Distributions
+From here you can find the various Linux distributions and other
+software packages that contain the @code{MySQL} software.
+
+@item Service Providers
+Companies providing @code{MySQL}-related services.
+@end itemize
-@node Questions, , Useful Links, MySQL Information Sources
+@node Questions, , Portals, MySQL Information Sources
@subsection MySQL Mailing Lists
@cindex reporting, errors
+@cindex errors, reporting
@cindex MySQL mailing lists
@menu
-* Mailing-list:: The MySQL mailing lists
-* Asking questions:: Asking questions or reporting bugs
-* Bug reports:: How to report bugs or problems
-* Answering questions:: Guidelines for answering questions on the mailing list
+* Mailing-list:: The MySQL Mailing Lists
+* Asking questions:: Asking Questions or Reporting Bugs
+* Bug reports:: How to Report Bugs or Problems
+* Answering questions:: Guidelines for Answering Questions on the Mailing List
@end menu
This section introduces you to the MySQL mailing lists, and gives
-some guidelines as to how to use them.
+some guidelines as to how to use them. By subscribing to a mailing
+list, you will receive as emails all other postings on the list,
+and you will be able to send in your own questions and answers.
@node Mailing-list, Asking questions, Questions, Questions
@subsubsection The MySQL Mailing Lists
@cindex mailing lists
-@cindex email lists
+@cindex e-mail lists
To subscribe to the main MySQL mailing list, send a message to the
electronic mail address @email{mysql-subscribe@@lists.mysql.com}.
@@ -2136,7 +2021,7 @@ the electronic mail address @email{mysql-unsubscribe@@lists.mysql.com}.
Only the address to which you send your messages is significant. The
subject line and the body of the message are ignored.
-@c the last two addresses in this paragraph are NOT @email because they
+@c the last two addresses in this paragraph are not @email because they
@c shouldn't be live links.
If your reply address is not valid, you can specify your address
explicitly. Adding a hyphen to the subscribe or unsubscribe command
@@ -2148,7 +2033,7 @@ address replaced by a @samp{=}. For example, to subscribe
Mail to @email{mysql-subscribe@@lists.mysql.com} or
@email{mysql-unsubscribe@@lists.mysql.com} is handled automatically by the
ezmlm mailing list processor. Information about ezmlm is available at
-@uref{http://www.ezmlm.org, The ezmlm Website}.
+the ezmlm web site (@uref{http://www.ezmlm.org/}).
To post a message to the list itself, send your message to
@code{mysql@@lists.mysql.com}. However, please @emph{do not} send mail about
@@ -2177,7 +2062,7 @@ subscribe to.
@item @email{mysql-subscribe@@lists.mysql.com} mysql
The main list for general MySQL discussion. Please note that some
-topics are better discussed on the more-specialized lists. If you post to the
+topics are better discussed on the more-specialised lists. If you post to the
wrong list, you may not get an answer!
@item @email{mysql-digest-subscribe@@lists.mysql.com} mysql-digest
@@ -2189,7 +2074,7 @@ On this list you should only post a full, repeatable bug report using
the @code{mysqlbug} script (if you are running on Windows, you should
include a description of the operating system and the MySQL version).
Preferably, you should test the problem using the latest stable or development
-version of MySQL before posting! Anyone should be able to repeat the
+version of MySQL Server before posting! Anyone should be able to repeat the
bug by just using @code{mysql test < script} on the included test case. All
bugs posted on this list will be corrected or documented in the next
MySQL release! If there are only small code changes involved, we
@@ -2206,24 +2091,30 @@ can also discuss MySQL development and post patches.
A digest version of the @code{internals} list.
@item @email{java-subscribe@@lists.mysql.com} java
-Discussion about MySQL and Java. Mostly about the JDBC drivers.
+Discussion about the MySQL server and Java. Mostly about the JDBC drivers.
@item @email{java-digest-subscribe@@lists.mysql.com} java-digest
A digest version of the @code{java} list.
@item @email{win32-subscribe@@lists.mysql.com} win32
-All things concerning MySQL on Microsoft operating systems such as
-Win95, Win98, NT, and Win2000.
+All things concerning the MySQL software on Microsoft operating systems
+such as Win95, Win98, NT, and Win2000.
@item @email{win32-digest-subscribe@@lists.mysql.com} win32-digest
A digest version of the @code{win32} list.
@item @email{myodbc-subscribe@@lists.mysql.com} myodbc
-All things about connecting to MySQL with ODBC.
+All things about connecting to the MySQL server with ODBC.
@item @email{myodbc-digest-subscribe@@lists.mysql.com} myodbc-digest
A digest version of the @code{myodbc} list.
+@item @email{mycc-subscribe@@lists.mysql.com} mycc
+All things about the MySQL MyCC graphical client.
+
+@item @email{mycc-digest-subscribe@@lists.mysql.com} mycc-digest
+A digest version of the @code{mycc} list.
+
@item @email{plusplus-subscribe@@lists.mysql.com} plusplus
All things concerning programming with the C++ API to MySQL.
@@ -2231,7 +2122,7 @@ All things concerning programming with the C++ API to MySQL.
A digest version of the @code{plusplus} list.
@item @email{msql-mysql-modules-subscribe@@lists.mysql.com} msql-mysql-modules
-A list about the Perl support in MySQL. msql-mysql-modules
+A list about the Perl support for MySQL with msql-mysql-modules.
@item @email{msql-mysql-modules-digest-subscribe@@lists.mysql.com} msql-mysql-modules-digest
A digest version of the @code{msql-mysql-modules} list.
@@ -2255,15 +2146,15 @@ guarantee the quality on these.
@table @code
@item @email{mysql-france-subscribe@@yahoogroups.com} A French mailing list
@item @email{list@@tinc.net} A Korean mailing list
-Email @code{subscribe mysql your@@email.address} to this list.
+Email @code{subscribe mysql your@@e-mail.address} to this list.
@item @email{mysql-de-request@@lists.4t2.com} A German mailing list
-Email @code{subscribe mysql-de your@@email.address} to this list.
+Email @code{subscribe mysql-de your@@e-mail.address} to this list.
You can find information about this mailing list at
-@uref{http://www.4t2.com/mysql}.
+@uref{http://www.4t2.com/mysql/}.
@item @email{mysql-br-request@@listas.linkway.com.br} A Portugese mailing list
-Email @code{subscribe mysql-br your@@email.address} to this list.
+Email @code{subscribe mysql-br your@@e-mail.address} to this list.
@item @email{mysql-alta@@elistas.net} A Spanish mailing list
-Email @code{subscribe mysql your@@email.address} to this list.
+Email @code{subscribe mysql your@@e-mail.address} to this list.
@end table
@@ -2272,7 +2163,7 @@ Email @code{subscribe mysql your@@email.address} to this list.
@cindex net etiquette
@cindex mailing lists, archive location
-@cindex searching, MySQL webpages
+@cindex searching, MySQL web pages
Before posting a bug report or question, please do the following:
@@ -2280,7 +2171,7 @@ Before posting a bug report or question, please do the following:
@item
Start by searching the MySQL online manual at:
@*
-@uref{http://www.mysql.com/documentation/manual.php}
+@uref{http://www.mysql.com/doc/}
@*
We try to keep the manual up to date by updating it frequently with
solutions to newly found problems!
@@ -2288,7 +2179,7 @@ solutions to newly found problems!
@item
Search the MySQL mailing list archives:
@*
-@uref{http://www.mysql.com/documentation/}
+@uref{http://lists.mysql.com/}
@*
@item
You can also use @uref{http://www.mysql.com/search.html} to search all the
@@ -2333,7 +2224,7 @@ missing, please include it with your message! Please read this section
carefully and make sure that all the information described here is included
in your report.
-@cindex bug reports, email address
+@cindex bug reports, e-mail address
The normal place to report bugs and problems is
@email{mysql@@lists.mysql.com}. If you can make a test case that clearly
demonstrates the bug, you should post it to the @email{bugs@@lists.mysql.com}
@@ -2341,7 +2232,7 @@ list. Note that on this list you should only post a full, repeatable bug
report using the @code{mysqlbug} script. If you are running on Windows,
you should include a description of the operating system and the
MySQL version. Preferably, you should test the problem using
-the latest stable or development version of MySQL before
+the latest stable or development version of MySQL Server before
posting! Anyone should be able to repeat the bug by just using
``@code{mysql test < script}'' on the included test case or run the
shell or perl script that is included in the bug report. All bugs
@@ -2350,6 +2241,9 @@ MySQL release! If there are only small code changes involved
to correct this problem, we will also post a patch that fixes the
problem.
+If you have found a sensitive security bug in MySQL, you should send an
+e-mail to @email{security@@mysql.com}.
+
Remember that it is possible to respond to a message containing too much
information, but not to one containing too little. Often people omit facts
because they think they know the cause of a problem and assume that some
@@ -2361,7 +2255,7 @@ first time.
The most common errors are that people don't indicate the version number of
the MySQL distribution they are using, or don't indicate what
-platform they have MySQL installed on (including the platform
+platform they have the MySQL server installed on (including the platform
version number). This is highly relevant information, and in 99 cases out of
100 the bug report is useless without it! Very often we get questions like,
``Why doesn't this work for me?'' then we find that the feature
@@ -2426,7 +2320,7 @@ Sometimes the amount of memory (real and virtual) is relevant. If in doubt,
include these values.
@item
-If you are using a source distribution of MySQL, the name and
+If you are using a source distribution of the MySQL software, the name and
version number of the compiler used is needed. If you have a binary
distribution, the distribution name is needed.
@@ -2476,7 +2370,7 @@ mysql> SHOW STATUS;
If a bug or problem occurs while running @strong{mysqld}, try to provide an
input script that will reproduce the anomaly. This script should include any
necessary source files. The more closely the script can reproduce your
-situation, the better. If you can make a repeatable test case, you should
+situation, the better. If you can make a reproduceable test case, you should
post this to @email{bugs@@lists.mysql.com} for a high priority treatment!
If you can't provide a script, you should at least include the output
@@ -2495,7 +2389,7 @@ archive to @uref{ftp://support.mysql.com/pub/mysql/secret/}. Then send a
short description of the problem to @email{bugs@@lists.mysql.com}.
@item
-If you think that MySQL produces a strange result from a query,
+If you think that the MySQL server produces a strange result from a query,
include not only the result, but also your opinion of what the result
should be, and an account describing the basis for your opinion.
@@ -2554,17 +2448,17 @@ problem yourself.
@item
If you get a @code{parse error}, please check your syntax closely! If
you can't find something wrong with it, it's extremely likely that your
-current version of MySQL doesn't support the query you are
+current version of MySQL Server doesn't support the query you are
using. If you are using the current version and the manual at
-@uref{http://www.mysql.com/documentation/manual.php} doesn't cover the
-syntax you are using, MySQL doesn't support your query. In this
+@uref{http://www.mysql.com/doc/} doesn't cover the
+syntax you are using, MySQL Server doesn't support your query. In this
case, your only options are to implement the syntax yourself or e-mail
@email{mysql-licensing@@mysql.com} and ask for an offer to implement it!
If the manual covers the syntax you are using, but you have an older version
-of MySQL, you should check the MySQL change history to see
+of MySQL Server, you should check the MySQL change history to see
when the syntax was implemented. In this case, you have the option of
-upgrading to a newer version of MySQL. @xref{News}.
+upgrading to a newer version of MySQL Server. @xref{News}.
@item
If you have a problem such that your data appears corrupt or you get
@@ -2574,20 +2468,20 @@ try repairing your tables with @code{myisamchk} or @code{CHECK TABLE} and
@item
If you often get corrupted tables you should try to find out when and why this
-happens! In this case, the @file{mysql-data-directory/'hostname'.err} file
+happens. In this case, the @file{mysql-data-directory/'hostname'.err} file
may contain some information about what happened. @xref{Error log}. Please
-include any relevant information from this file in your bug report! Normally
-@code{mysqld} should @strong{NEVER} crash a table if nothing killed it in the
+include any relevant information from this file in your bug report. Normally
+@code{mysqld} should @strong{never} crash a table if nothing killed it in the
middle of an update! If you can find the cause of @code{mysqld} dying,
-it's much easier for us to provide you with a fix for the problem!
+it's much easier for us to provide you with a fix for the problem.
@xref{What is crashing}.
@item
-If possible, download and install the most recent version of MySQL
+If possible, download and install the most recent version of MySQL Server
and check whether or not it solves your problem. All versions of
-MySQL are thoroughly tested and should work without problems! We
-believe in making everything as backward compatible as possible, and you
-should be able to switch MySQL versions in minutes!
+the MySQL software are thoroughly tested and should work without problems.
+We believe in making everything as backward compatible as possible,
+and you should be able to switch MySQL versions without any hassle.
@xref{Which version}.
@end itemize
@@ -2605,13 +2499,13 @@ For information on reporting bugs in @strong{MyODBC}, see @ref{ODBC Problems}.
For solutions to some common problems, see @xref{Problems}.
When answers are sent to you individually and not to the mailing list,
-it is considered good etiquette to summarize the answers and send the
+it is considered good etiquette to summarise the answers and send the
summary to the mailing list so that others may have the benefit of
responses you received that helped you solve your problem!
@node Answering questions, , Bug reports, Questions
-@subsubsection Guidelines for Answering Question on the Mailing List
+@subsubsection Guidelines for Answering Questions on the Mailing List
@cindex net etiquette
@cindex questions, answering
@@ -2624,784 +2518,125 @@ asked. Try to make your answer general enough that people other than the
original poster may benefit from it. When you post to the list, please make
sure that your answer is not a duplication of a previous answer.
-Try to summarize the essential part of the question in your reply; don't feel
+Try to summarise the essential part of the question in your reply; don't feel
obliged to quote the entire original message.
Please don't post mail messages from your browser with HTML mode turned on!
Many users don't read mail with a browser!
-@node Licensing and Support, Compatibility, MySQL Information Sources, Introduction
-@section MySQL Licensing and Support
-
-@cindex licensing terms
-@cindex support terms
-
-@menu
-* Licensing policy:: MySQL licensing policy
-* Copyright:: Copyrights used by MySQL
-* Licensing examples:: Example licensing situations
-* Cost:: MySQL licensing and support costs
-* Support:: Types of commercial support
-@end menu
-
-This section describes MySQL support and licensing
-arrangements:
-
-@itemize @bullet
-
-@item The copyrights under which MySQL is distributed
-(@pxref{Copyright})
-
-@item Sample situations illustrating when a license is required
-(@pxref{Licensing examples})
-
-@item Support costs (@pxref{Cost}) and support benefits
-(@pxref{Support})
-
-@item Commercial licensing costs
-@end itemize
-
-
-@node Licensing policy, Copyright, Licensing and Support, Licensing and Support
-@subsection MySQL Licensing Policy
-
-@cindex licensing policy
-@cindex technical support, licensing
-@cindex support, licensing
-@cindex General Public License, MySQL
-
-The formal terms of the GPL license can be found at @ref{GPL license}.
-Basically, our licensing policy and interpretation of the GPL is as follows:
-
-Note that older versions of MySQL are still using a more
-@uref{http://www.mysql.com/support/arrangements/mypl.html, strict license}.
-See the documentation for that version for more information. If you need a
-commercial MySQL license, because the GPL license doesn't suit your
-application, you can buy one at @uref{https://order.mysql.com/}.
-
-For normal internal use, MySQL costs nothing. You do not have
-to pay us if you do not want to.
-
-A license is required if:
-
-@itemize @minus
-@item
-You link a program, that is not free software, with code from the
-MySQL server or clients that has the GPL copyright. This
-happens for example when you use MySQL as an embedded server
-in your applications or when you add not free extensions to the
-MySQL server. In this case your application/code would also
-become GPL through the GPL license that acts as a virus. By licensing
-MySQL server from MySQL AB under a commercial
-license you will avoid this problem.
-See @uref{http://www.gnu.org/copyleft/gpl-faq.html}.
-@item
-You have a commercial application that ONLY works with MySQL
-and ships the application with the MySQL server. This is
-because we view this as linking even if it is done over the network.
-
-@item
-You have a distribution of MySQL and you don't provide the
-source code for your copy of the MySQL server, as defined in
-the GPL license.
-@end itemize
-
-A license is @strong{NOT} required if:
-
-@itemize @minus
-
-@item
-You do not need a license to include the client code in commercial
-programs. The client part of MySQL licensed with the
-LGPL @code{GNU Library General Public License}. The @code{mysql} command-line
-client includes code from the @code{readline} library that is under
-the @code{GPL}.
-
-@item
-If your use of MySQL does not require a license, but you
-like MySQL and want to encourage further development, you are
-certainly welcome to purchase a license or MySQL support anyway.
-
-@item
-If you use MySQL in a commercial context such that you profit by
-its use, we ask that you further the development of MySQL by
-purchasing some level of support. We feel that if MySQL helps
-your business, it is reasonable to ask that you help MySQL.
-(Otherwise, if you ask us support questions, you are not only using for
-free something into which we've put a lot a work, you're asking us to
-provide free support, too.)
-@end itemize
-
-For circumstances under which a MySQL license is required, you
-need a license per machine that runs the @code{mysqld} server. However,
-a multiple-CPU machine counts as a single machine, and there is no
-restriction on the number of MySQL servers that run on one
-machine, or on the number of clients concurrently connected to a server
-running on that machine!
-
-If you have any questions as to whether or not a license is required for
-your particular use of MySQL, please read this again and then
-contact us. @xref{Contact information}.
-
-If you require a MySQL license, the easiest way to pay for it
-is to use the license form on MySQL's secure server at
-@uref{https://order.mysql.com/}. Other forms of payment are
-discussed in @ref{Payment information}.
-
-
-@node Copyright, Licensing examples, Licensing policy, Licensing and Support
-@subsection Copyrights Used by MySQL
-
-@cindex copyrights
-
-@menu
-* Copyright changes:: Possible future copyright changes
-@end menu
-
-There are several different copyrights on the MySQL distribution:
-
-@enumerate
-@item
-The MySQL-specific source needed to build the
-@code{mysqlclient} library is licensed under the @code{LGPL} and
-programs in the @file{client} directory is GPL. Each file has a header
-that shows which copyright is used for that file.
-
-@item The client library and the (GNU @code{getopt}) library are covered
-by the ``GNU LIBRARY GENERAL PUBLIC LICENSE.'' @xref{LGPL license}.
-
-@item Some parts of the source (the @code{regexp} library) are covered
-by a Berkeley-style copyright.
-
-@item
-All the source in the server and the (GNU @code{readline}) library
-is covered by the ``GNU GENERAL PUBLIC LICENSE.'' @xref{GPL license}.
-This is also available as the file @file{COPYING} in the distributions.
-
-@end enumerate
-
-One goal is that the SQL client library should be free enough that it is
-possible to add MySQL support into commercial products
-without a license. For this reason, we chose the LGPL license for the
-client code.
-@cindex licensing, free
-@cindex free licensing
-
-This means that you can use MySQL for free with any program that uses
-any of the free software licenses. MySQL is also free for any end
-user for his own or company usage.
-
-However, if you use MySQL for something important to you, you may
-want to help secure its development by purchasing licenses or a support
-contract. @xref{Support}.
-
-
-@node Copyright changes, , Copyright, Copyright
-@subsubsection Copyright Changes
-
-Version 3.22 of MySQL is still using a more strict license.
-See the documentation for that version for more information.
-
-
-@node Licensing examples, Cost, Copyright, Licensing and Support
-@subsection Example Licensing Situations
-
-@menu
-* Products that use MySQL:: Selling products that use MySQL
-* ISP:: ISP MySQL services
-* Web server:: Running a web server using MySQL.
-@end menu
-
-@cindex licensing, examples
-@cindex selling products
-@cindex products, selling
-
-This section describes some situations illustrating whether or not you
-must license the MySQL server. Generally these examples
-involve providing MySQL as an integral part of a product.
-
-Note that a single MySQL license covers any number of CPUs and
-@code{mysqld} servers on a machine! There is no artificial limit on the
-number of clients that connect to the server in any way.
-
-
-@node Products that use MySQL, ISP, Licensing examples, Licensing examples
-@subsubsection Selling Products that use MySQL
-
-To determine whether or not you need a MySQL license when
-selling your application, you should ask whether the proper functioning
-of your application is dependent on the use of MySQL and
-whether you include the MySQL server with your product. There
-are several cases to consider:
-
-@itemize @bullet
-@item
-Does your application require MySQL to function properly?
-
-@item
-If your product requires MySQL, you need a license for any
-machine that runs the @code{mysqld} server. For example, if you've
-designed your application around MySQL, then you've really made
-a commercial product that requires the engine, so you need a license.
-
-@item
-If your application does not require MySQL, you do not need to obtain
-a license. For example, if using MySQL just adds some new optional
-features to your product (such as adding logging to a database if
-MySQL is used rather than logging to a text file), it should
-fall within normal use, and a license would not be required.
-
-@item
-In other words, you need a license if you sell a product designed
-specifically for use with MySQL or that requires the
-MySQL server to function at all. This is true whether or not
-you provide MySQL for your client as part of your product
-distribution.
-
-@item
-It also depends on what you're doing for the client. Do you plan to
-provide your client with detailed instructions on installing
-MySQL with your software? Then your product may be contingent
-on the use of MySQL; if so, you need to buy a license. If you
-are simply tying into a database that you expect already to have been
-installed by the time your software is purchased, then you probably
-don't need a license.
-
-@end itemize
-
-
-@node ISP, Web server, Products that use MySQL, Licensing examples
-@subsubsection ISP MySQL Services
-
-@cindex ISP services
-@cindex services, ISP
-@cindex services, web
-@cindex Internet Service Providers
-
-Internet Service Providers (ISPs) often host MySQL servers for
-their customers. With the GPL license this does not require a license.
-
-On the other hand, we do encourage people to use ISPs that have
-MySQL support, as this will give them the confidence that if
-they have some problem with their MySQL installation, their ISP
-will be able to solve the problem for them (in some cases with the help
-from the MySQL development team).
-
-All ISPs that want to keep themselves up-to-date should subscribe
-to our @code{announce} mailing list so that they can be aware of fatal issues
-that may be relevant for their MySQL installations.
-
-Note that if the ISP doesn't have a license for MySQL,
-it should give its customers at least read access to the source of
-the MySQL installation so that its customer can verify that
-it is patched correctly.
-
-
-@node Web server, , ISP, Licensing examples
-@subsubsection Running a Web Server Using MySQL
-
-@cindex web server, running
-@cindex running, a web server
-
-If you use MySQL in conjunction with a Web server on Unix, you
-don't have to pay for a license.
-
-This is true even if you run a commercial Web server that uses
-MySQL, because you are not selling an embedded MySQL
-version yourself. However, in this case we would like you to purchase
-MySQL support, because MySQL is helping your enterprise.
-
-
-@node Cost, Support, Licensing examples, Licensing and Support
-@subsection MySQL Licensing and Support Costs
-
-@cindex costs, licensing and support
-@cindex licensing costs
-@cindex support costs
-@cindex prices, licensing and support
-
-@menu
-* Payment information:: Payment information
-* Contact information:: Contact information
-@end menu
-
-Our current license prices are shown below. To make a purchase, please visit
-@uref{https://order.mysql.com/}.
-
-If you pay by credit card, the currency is EURO (European Union Euro) so the
-prices will differ slightly.
-
-@multitable @columnfractions .3 .3 .3
-@item @strong{Number of licenses} @tab @strong{Per copy}
-@item 1-9 @tab 230 EURO
-@item 10-24 @tab 138 EURO
-@item 25-49 @tab 117 EURO
-@item 50-99 @tab 102 EURO
-@item 100-249 @tab 91 EURO
-@item 250-499 @tab 76 EURO
-@item 500-999 @tab 66 EURO
-@end multitable
-
-For high volume (OEM) purchases, please contact
-@email{sales@@mysql.com}.
-
-For OEM purchases, you must act as the middle-man for eventual problems
-or extension requests from your users. We also require that OEM
-customers have at least an extended e-mail support contract. Note that
-OEM licenses only apply for products where the user doesn't have direct
-access to the MySQL server (embedded system). In other words,
-the MySQL server should only be used with the application
-that was supplied you.
-
-If you have a low-margin, high-volume product, you can always talk to us
-about other terms (for example, a percent of the sale price). If you do,
-please be informative about your product, pricing, market, and any other
-information that may be relevant.
-
-A full-price license is not a support agreement and includes very minimal
-support. This means that we try to answer any relevant questions. If the
-answer is in the documentation, we will direct you to the appropriate
-section. If you have not purchased a license or support, we probably will
-not answer at all.
-
-If you discover what we consider a real bug, we are likely to fix it in
-any case. But if you pay for support we will notify you about the fix
-status instead of just fixing it in a later release.
-
-More comprehensive support is sold separately. Descriptions of what each
-level of support includes are given in @ref{Support}. Costs for the various
-types of commercial support are shown below. Support level prices are in
-EURO (European Union Euro). One EURO is about 1.06 USD.
-
-@multitable @columnfractions .5 .5
-@item @strong{Type of support} @tab @strong{Cost per year}
-@item Basic e-mail support. @xref{Basic email support}. @tab EURO 200
-@item Extended e-mail support @xref{Extended email support}. @tab EURO 1000
-@item Login support @xref{Login support}. @tab EURO 2000
-@item Extended login support @xref{Extended login support}. @tab EURO 5000
-@item Telephone support @xref{Telephone support}. @tab EURO 12000
-@end multitable
-
-You may upgrade from any lower level of support to a higher level of
-support for the difference in price between the two support levels.
-
-We do also provide telephone support (mostly emergency support but also
-24/7 support). This support option doesn't however have a fixed price
-but is negotiated for case to case. If you are interested in this option
-you can email @email{sales@@mysql.com} and tell us about your needs.
-
-Note that as our sales staff is very busy, it may take some time until
-your request is handled. Our support staff does however always answer
-promptly to support questions!
-
-
-@node Payment information, Contact information, Cost, Cost
-@subsubsection Payment information
-
-@cindex payment information
-
-Currently we can take SWIFT payments, checks, or credit cards.
-
-Payment should be made to:
-
-@example
-Postgirot Bank AB
-105 06 STOCKHOLM, SWEDEN
-
-MySQL AB
-BOX 6434
-11382 STOCKHOLM, SWEDEN
-
-SWIFT address: PGSI SESS
-Account number: 96 77 06 - 3
-@end example
-
-Specify: license and/or support and your name and e-mail address.
-
-In Europe and Japan you can use EuroGiro (that should be less expensive) to the
-same account.
-
-If you want to pay by check, make it payable to ``MySQL Finland AB'' and
-mail it to the address below:
-
-@example
-MySQL AB
-BOX 6434, Torsgatan 21
-11382 STOCKHOLM, SWEDEN
-@end example
-
-If you want to pay by credit card over the Internet, you can use
-@uref{https://order.mysql.com/, MySQL AB's secure license form}.
-
-You can also print a copy of the license form, fill it in, and send it by fax
-to:
-
-+46-8-729 69 05
-
-If you want us to bill you, you can use the license form and write ``bill
-us'' in the comment field. You can also mail a message to
-@email{sales@@mysql.com} (@strong{not} @code{mysql@@lists.mysql.com}!)
-with your company information and ask us to bill you.
-
-
-@node Contact information, , Payment information, Cost
-@subsubsection Contact Information
-
-@cindex contact information
-@cindex licensing, contact information
-@cindex advertising, contact information
-@cindex employment, contact information
-@cindex partnering with MySQL
-@cindex employment with MySQL
-@cindex jobs at MySQL
-
-For commercial licensing, please contact the MySQL licensing
-team. The much preferred method is by e-mail to
-@email{licensing@@mysql.com}. Fax is also possible but handling of
-these may take much longer (Fax +46-8-729 69 05).
-
-If you represent a business that is interested in partnering with
-MySQL, please send e-mail to @email{partner@@mysql.com}.
-
-For timely, precise answers to technical questions about MySQL
-you should @uref{https://order.mysql.com/, order} one of our
-@uref{http://www.mysql.com/support/arrangements/types.html, support contracts}.
-MySQL support is provided by the MySQL developers so the
-standard is extremely high.
-
-If you are interested in placing a banner advertisement on our Web site,
-please send e-mail to @email{advertising@@mysql.com}.
-
-If you are interested in any of the jobs listed in our
-@uref{http://www.mysql.com/development/jobs/, jobs} section, please send e-mail
-to @email{jobs@@mysql.com}.
-
-For general discussion amongst our many users, please direct your attention to
-the appropriate @uref{http://www.mysql.com/documentation/lists.html, mailing
-list}.
-
-For general information inquires, please send e-mail to
-@email{info@@mysql.com}.
-
-For questions or comments about the workings or content of the Web site,
-please send e-mail to @email{webmaster@@mysql.com}.
-
+@node Compatibility, TODO, MySQL Information Sources, Introduction
+@section How Standards-compatible Is MySQL?
-@node Support, , Cost, Licensing and Support
-@subsection Types of Commercial Support
+@cindex compatibility, with ANSI SQL
+@cindex standards compatibility
+@cindex extensions, to ANSI SQL
+@cindex ANSI SQL92, extensions to
-@cindex support, types
-@cindex types, of support
-@cindex commercial support, types
+This section describes how MySQL relates to the ANSI SQL standards.
+MySQL Server has many extensions to the ANSI SQL standards, and here you
+will find out what they are, and how to use them. You will also find
+information about functionality missing from MySQL Server, and how to work
+around some differences.
+
+Our goal is to not, without a very good reason, restrict MySQL Server usability
+for any usage. Even if we don't have the resources to do development
+for every possible use, we are always willing to help and offer
+suggestions to people that is trying to use MySQL Server in new territories.
+
+One of our main goals with the product is to continue to work towards
+ANSI 99 compliancy, but without sacrificing speed or reliability.
+We are not afraid to add extensions to SQL or support for non-SQL
+features if this greatly increase the usability of MySQL Server for a big
+part of our users. (The new @code{HANDLER} interface in MySQL Server 4.0
+is an example of this strategy. @xref{HANDLER}.)
+
+We will continue to support transactional and not transactional
+databases to satisfy both heavy web/logging usage and mission critical
+24/7 usage.
+
+MySQL Server was designed from the start to work with medium large databases
+(10-100 million rows / about 100 MB per table) on small computer
+systems. We will continue to extend MySQL Server to both work even better
+with terabyte size databases, but we are also doing work to make it possible
+to compile a reduced MySQL version that is more suitable for hand held
+devices and embedded usage. The compact design of the MySQL server makes both
+of these directions possible without any conflicts in the source tree.
+
+We are currently not targeting real time support or clustered databases
+(even if you can already do a lot of things with our replication
+services).
+
+We don't believe that one should have native XML support in the
+database, but will instead add the XML support our users request from
+us on the client side. We think it's better to keep the main server
+code as ``lean and clean'' as possible and instead develop libraries to
+deal with the complexity on the client side. This is part of the strategy
+mentioned above of not sacrificing speed or reliability in the
+server.
@menu
-* Basic email support:: Basic email support
-* Extended email support:: Extended email support
-* Login support:: Login support
-* Extended login support:: Extended login support
-* Telephone support:: Telephone support
-* Table handler support:: Support for other table handlers
+* Standards:: What Standards Does MySQL Follow?
+* ANSI mode:: Running MySQL in ANSI Mode
+* Extensions to ANSI:: MySQL Extensions to ANSI SQL92
+* Differences from ANSI:: MySQL Differences Compared to ANSI SQL92
+* Bugs:: Known Errors and Design Deficiencies in MySQL
@end menu
-The following is true of all support options:
-
-@itemize @bullet
-@item
-The support is per year.
-@item
-We will fix, or provide a reasonable workaround for any repeatable bug.
-@item
-We will give a reasonable effort to find and fix any other MySQL related bug.
-@item
-The higher level of support contract the more effort we will put into finding
-a solution to your problems.
-@item
-The following is true for all support contracts except Basic email support:
-
-For non-bug related things, like helping you optimize your queries or
-your system, extending MySQL with new functionality, etc., we charge 200
-EURO/hour, which is deducted from your support contract. In other words,
-if you have login support (2000 EURO), you can expect us to work up to
-10 hours to help you with things like this.
-@end itemize
-
-
-@node Basic email support, Extended email support, Support, Support
-@subsubsection Basic E-mail Support
-
-@cindex email, technical support
-@cindex technical support, by email
-
-Basic e-mail support is a very inexpensive support option and should be
-thought of more as a way to support our development of MySQL
-than as a real support option. We at MySQL do give a lot of free
-support in all the different MySQL lists, and the money we get from
-basic e-mail support is largely used to make this possible.
-
-At this support level, the MySQL mailing lists are the preferred
-means of communication. Questions normally should be mailed to the primary
-mailing list (@email{mysql@@lists.mysql.com}) or one of the other regular
-lists (for example, @email{win32@@lists.mysql.com} for Windows-related
-MySQL questions), as someone else already may have experienced and
-solved the problem you have. @xref{Asking questions}.
-However, by purchasing basic e-mail support, you also have access to the
-support address @email{mysql-support@@mysql.com}, which is not available
-as part of the minimal support that you get by purchasing a MySQL
-license. This means that for especially critical questions, you can
-cross-post your message to @email{mysql-support@@mysql.com}. (If the
-message contains sensitive data, you should post only to
-@email{mysql-support@@mysql.com}.)
-
-@strong{REMEMBER!} to ALWAYS include your registration number and expiration
-date when you send a message to @email{mysql-support@@mysql.com}.
-
-Note that if you have encountered a critical, repeatable bug, and follow
-the rules outlined in the manual section of how to report bugs and send
-it to @email{bugs@@lists.mysql.com}, we promise to try to fix this as
-soon as possible, regardless of your support level! @xref{Bug reports}.
-
-Basic e-mail support includes the following types of service:
-
-@itemize @bullet
-@item
-If your question is already answered in the manual, we will inform you of the
-correct section in which you can find the answer. If the answer is not in
-the manual, we will point you in the right direction to solve your problem.
-
-@item
-We guarantee a timely answer for your e-mail messages. We can't guarantee
-that we can solve any problem, but at least you will receive an answer if we
-can contact you by e-mail.
-
-@item
-We will help with unexpected problems when you install MySQL from a
-binary distribution on supported platforms. This level of support does not
-cover installing MySQL from a source distribution. Supported
-platforms are those for which MySQL is known to work.
-@xref{Which OS}.
-
-@item
-We will help you with bugs and missing features. Any bugs that are found are
-fixed for the next MySQL release. If the bug is critical for
-you, we will mail you a patch for it as soon the bug is fixed. Critical
-bugs always have the highest priority for us, and we ensure that they are
-fixed as soon as possible.
-
-@item
-Your suggestions for the further development of MySQL will be
-taken into consideration. By taking email support you have already
-helped the further development of MySQL. If you want to have
-more input, upgrade to a higher level of support.
-
-@item
-If you want us to help optimize your system, you must upgrade to a
-higher level of support.
-@end itemize
-
-
-@node Extended email support, Login support, Basic email support, Support
-@subsubsection Extended E-mail Support
-
-@cindex extended email support
-
-Extended e-mail support includes everything in basic e-mail support with
-these additions:
-
-@itemize @bullet
-@item
-Your e-mail will be dealt with before mail from basic e-mail support users and
-non-registered users.
-
-@item
-Your suggestions for the further development of MySQL will
-receive strong consideration. Simple extensions that suit the basic
-goals of MySQL are implemented in a matter of days. By taking
-extended e-mail support you have already helped the further development
-of MySQL.
-
-@item
-Typical situations that are covered by extended e-mail support are:
-
-@itemize @minus
-@item
-We will answer and (within reason) solve questions that relate to possible
-bugs in MySQL. As soon as the bug is found and corrected, we
-will mail a patch for it.
-
-@item
-We will help with unexpected problems when you install MySQL from a
-source or binary distribution on supported platforms.
-
-@item
-We will answer questions about missing features and offer hints how to work
-around them.
-
-@item
-We will provide hints on optimizing @code{mysqld} for your situation.
-@end itemize
-
-@item
-You are allowed to influence the priority of items on the MySQL
-TODO List. @xref{TODO}. This will ensure that the features you really need
-will be implemented sooner than they might be otherwise.
-@end itemize
-
-
-@node Login support, Extended login support, Extended email support, Support
-@subsubsection Login Support
-
-@cindex login support
-
-Login support includes everything in extended e-mail support with
-these additions:
-
-@itemize @bullet
-@item
-Your e-mail will be dealt with even before e-mail from extended e-mail
-support users.
-
-@item
-Your suggestions for the further development of MySQL will
-be taken into very high consideration. Realistic extensions that can be
-implemented in a couple of hours and that suit the basic goals of
-MySQL will be implemented as soon as possible.
+@node Standards, ANSI mode, Compatibility, Compatibility
+@subsection What Standards Does MySQL Follow?
-@item
-If you have a very specific problem, we can try to log in on your system
-to solve the problem ``in place.''
+Entry level SQL92. ODBC levels 0-3.51.
-@item
-Like any database vendor, we can't guarantee that we can rescue any data from
-crashed tables, but if the worst happens, we will help you rescue as much as
-possible. MySQL has proven itself very reliable, but anything is
-possible due to circumstances beyond our control (for example, if your system
-crashes or someone kills the server by executing a @code{kill -9} command).
+We are aiming towards supporting the full ANSI SQL99 standard,
+but without concessions to speed and quality of the code.
-@item
-We will provide hints on optimizing your system and your queries.
-
-@item
-You are allowed to call a MySQL developer (in moderation) and
-discuss your MySQL-related problems. This option is however
-only to be used as a last result during an emergency after we have
-failed to grasp the total problem with email. To make efficient
-use of our time we need to first get all facts about the problem,
-before talking on phone, to be able to work as efficiently as possible on
-solving the problem.
-@end itemize
+@node ANSI mode, Extensions to ANSI, Standards, Compatibility
+@subsection Running MySQL in ANSI Mode
-@node Extended login support, Telephone support, Login support, Support
-@subsubsection Extended Login Support
+@cindex running, ANSI mode
+@cindex ANSI mode, running
-Extended login support includes everything in login support with these
-additions:
+If you start @code{mysqld} with the @code{--ansi} option, the following
+behavior of MySQL Server changes:
@itemize @bullet
@item
-Your e-mail has the highest possible priority.
-
-@item
-We will actively examine your system and help you optimize it and your
-queries. We may also optimize and/or extend MySQL to better
-suit your needs.
+@code{||} is string concatenation instead of @code{OR}.
@item
-You may also request special extensions just for you. For example:
-@example
-mysql> select MY_FUNC(col1,col2) from table;
-@end example
+You can have any number of spaces between a function name and the @samp{(}.
+This forces all function names to be treated as reserved words.
@item
-We will provide a binary distribution of all important MySQL
-releases for your system, as long as we can get an account on a
-similar system. In the worst case, we may require access to your system
-to be able to create a binary distribution.
+@samp{"} will be an identifier quote character (like the MySQL Server
+@samp{`} quote character) and not a string quote character.
@item
-If you can provide accommodations and pay for traveler fares, you can
-even get a MySQL developer to visit you and offer you help with
-your troubles. Extended login support entitles you to one personal
-encounter per year, but we are always very flexible towards our
-customers! If the visit takes 16 hours or more, the first 8 hours is
-without charge. For the hours above 8 hours, you will be charged with a
-rate that is at least 20 % less than our standard rates.
-@end itemize
-
-
-@node Telephone support, Table handler support, Extended login support, Support
-@subsubsection Telephone Support
-
-Telephone support includes everything in extended login support with
-these additions:
+@code{REAL} will be a synonym for @code{FLOAT} instead of a synonym of
+@code{DOUBLE}.
-@itemize @bullet
-@item
-We will provide you with a dynamic web page showing the current list of
-@code{MySQL} developers that you can phone when you have a critical
-problem.
@item
-For non critical problem, you can request a MySQL developer to
-phone back within 48 hours to discuss @code{MySQL} related issues.
+The default transaction isolation level is @code{SERIALIZABLE}.
+@xref{SET TRANSACTION}.
@end itemize
-
-@node Table handler support, , Telephone support, Support
-@subsubsection Support for other table handlers
-
-@cindex support, BDB Tables
-@cindex support, InnoDB Tables
-
-To get support for @code{BDB} tables, @code{InnoDB} tables you have
-to pay an additional 30% on the standard support price for each of
-the table handlers you would like to have support for.
-
-We at @code{MySQL AB} will help you create a proper bug report for the
-table handler and submit it to the developers for the specific table
-handler. We will also do our best to ensure that you will get a timely
-answer or solution from the developers of the table handler.
-
-Even if we are quite confident that we can solve most problems within a
-timely manner, we can't guarantee a quick solution for any problems you
-can get with the different table handlers. We will however do our best
-to help you get the problem solved.
-
-
-@node Compatibility, Comparisons, Licensing and Support, Introduction
-@section How Standards-compatible Is MySQL?
-
-@cindex compatibility, with ANSI SQL
-@cindex standards compatibility
-@cindex extensions, to ANSI SQL
-@cindex ANSI SQL92, extensions to
-
-@menu
-* Extensions to ANSI:: MySQL extensions to ANSI SQL92
-* Differences from ANSI:: MySQL differences compared to ANSI SQL92
-* ANSI mode:: Running MySQL in ANSI mode
-* Missing functions:: Functionality missing from MySQL
-* Standards:: What standards does MySQL follow?
-* Commit-rollback:: How to cope without @code{COMMIT}-@code{ROLLBACK}
-* Bugs:: Known errors and design deficiencies in MySQL
-@end menu
-
-This section describes how MySQL relates to the ANSI SQL standards.
-MySQL has many extensions to the ANSI SQL standards, and here you
-will find out what they are, and how to use them. You will also find
-information about functionality missing from MySQL, and how to work
-around some differences.
+This is the same as using
+@code{--sql-mode=REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,
+IGNORE_SPACE,SERIALIZE,ONLY_FULL_GROUP_BY}.
-@node Extensions to ANSI, Differences from ANSI, Compatibility, Compatibility
+@node Extensions to ANSI, Differences from ANSI, ANSI mode, Compatibility
@subsection MySQL Extensions to ANSI SQL92
-MySQL includes some extensions that you probably will not find in
+@cindex hints
+MySQL Server includes some extensions that you probably will not find in
other SQL databases. Be warned that if you use them, your code will not be
portable to other SQL servers. In some cases, you can write code that
includes MySQL extensions, but is still portable, by using comments
-of the form @code{/*! ... */}. In this case, MySQL will parse and
+of the form @code{/*! ... */}. In this case, MySQL Server will parse and
execute the code within the comment as it would any other MySQL
statement, but other SQL servers will ignore the extensions. For example:
@@ -3418,7 +2653,7 @@ CREATE /*!32302 TEMPORARY */ TABLE (a int);
@end example
The above means that if you have Version 3.23.02 or newer, then MySQL
-will use the @code{TEMPORARY} keyword.
+Server will use the @code{TEMPORARY} keyword.
MySQL extensions are listed below:
@@ -3440,7 +2675,7 @@ comparisons to be done according to the ASCII order used on the
MySQL server host.
@item
-MySQL maps each database to a directory under the MySQL
+MySQL Server maps each database to a directory under the MySQL
data directory, and tables within a database to filenames in the database
directory.
@@ -3454,7 +2689,7 @@ This has a few implications:
@itemize @minus
@item
-Database names and table names are case sensitive in MySQL on
+Database names and table names are case sensitive in MySQL Server on
operating systems that have case-sensitive filenames (like most Unix
systems). @xref{Name case sensitivity}.
@@ -3472,7 +2707,7 @@ and @file{.frm} files to which the table corresponds.
In SQL statements, you can access tables from different databases
with the @code{db_name.tbl_name} syntax. Some SQL servers provide
the same functionality but call this @code{User space}.
-MySQL doesn't support tablespaces as in:
+MySQL Server doesn't support tablespaces as in:
@code{create table ralph.my_table...IN my_tablespace}.
@item
@@ -3562,18 +2797,18 @@ One can specify @code{ASC} and @code{DESC} with @code{GROUP BY}.
@item
To make it easier for users who come from other SQL environments,
-MySQL supports aliases for many functions. For example, all
+MySQL Server supports aliases for many functions. For example, all
string functions support both ANSI SQL syntax and ODBC syntax.
@item
-MySQL understands the @code{||} and @code{&&} operators to mean
-logical OR and AND, as in the C programming language. In MySQL,
+MySQL Server understands the @code{||} and @code{&&} operators to mean
+logical OR and AND, as in the C programming language. In MySQL Server,
@code{||} and @code{OR} are synonyms, as are @code{&&} and @code{AND}.
-Because of this nice syntax, MySQL doesn't support
+Because of this nice syntax, MySQL Server doesn't support
the ANSI SQL @code{||} operator for string concatenation; use
@code{CONCAT()} instead. Because @code{CONCAT()} takes any number
of arguments, it's easy to convert use of the @code{||} operator to
-MySQL.
+MySQL Server.
@item
@code{CREATE DATABASE} or @code{DROP DATABASE}.
@@ -3606,12 +2841,12 @@ operators.
@item
@code{CONCAT()} or @code{CHAR()} with one argument or more than two
-arguments. (In MySQL, these functions can take any number of
+arguments. (In MySQL Server, these functions can take any number of
arguments.)
@item The @code{BIT_COUNT()}, @code{CASE}, @code{ELT()},
@code{FROM_DAYS()}, @code{FORMAT()}, @code{IF()}, @code{PASSWORD()},
-@code{ENCRYPT()}, @code{md5()}, @code{ENCODE()}, @code{DECODE()},
+@code{ENCRYPT()}, @code{MD5()}, @code{ENCODE()}, @code{DECODE()},
@code{PERIOD_ADD()}, @code{PERIOD_DIFF()}, @code{TO_DAYS()}, or
@code{WEEKDAY()} functions.
@@ -3631,7 +2866,7 @@ Use of @code{REPLACE} instead of @code{DELETE} + @code{INSERT}.
The @code{FLUSH}, @code{RESET} and @code{DO} statements.
@item
-The possibility to set variables in a statement with @code{:=}:
+The ability to set variables in a statement with @code{:=}:
@example
SELECT @@a:=SUM(total),@@b=COUNT(*),@@a/@@b AS avg FROM test_table;
SELECT @@t1:=(@@t2:=1)+@@t3:=4,@@t1,@@t2,@@t3;
@@ -3640,19 +2875,15 @@ SELECT @@t1:=(@@t2:=1)+@@t3:=4,@@t1,@@t2,@@t3;
@end itemize
-@node Differences from ANSI, ANSI mode, Extensions to ANSI, Compatibility
+@node Differences from ANSI, Bugs, Extensions to ANSI, Compatibility
@subsection MySQL Differences Compared to ANSI SQL92
-We try to make MySQL follow the ANSI SQL standard and the
-ODBC SQL standard, but in some cases MySQL does some things
+We try to make MySQL Server follow the ANSI SQL standard and the
+ODBC SQL standard, but in some cases MySQL Server does things
differently:
@itemize @bullet
@item
-@code{--} is only a comment if followed by a white space. @xref{Missing
-comments}.
-
-@item
For @code{VARCHAR} columns, trailing spaces are removed when the value is
stored. @xref{Bugs}.
@@ -3671,74 +2902,33 @@ This is because we don't think it's good to have to evaluate a lot of
extra conditions in this case.
@end itemize
-
-@node ANSI mode, Missing functions, Differences from ANSI, Compatibility
-@subsection Running MySQL in ANSI Mode
-
-@cindex running, ANSI mode
-@cindex ANSI mode, running
-
-If you start @code{mysqld} with the @code{--ansi} option, the following
-behavior of MySQL changes:
-
-@itemize @bullet
-@item
-@code{||} is string concatenation instead of @code{OR}.
-
-@item
-You can have any number of spaces between a function name and the @samp{(}.
-This forces all function names to be treated as reserved words.
-
-@item
-@samp{"} will be an identifier quote character (like the MySQL
-@samp{`} quote character) and not a string quote character.
-
-@item
-@code{REAL} will be a synonym for @code{FLOAT} instead of a synonym of
-@code{DOUBLE}.
-
-@item
-The default transaction isolation level is @code{SERIALIZABLE}.
-@xref{SET TRANSACTION}.
-@end itemize
-
-This is the same as using @code{--sql-mode=REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,SERIALIZE,ONLY_FULL_GROUP_BY}.
-
-@node Missing functions, Standards, ANSI mode, Compatibility
-@subsection Functionality Missing from MySQL
-
-@cindex missing functionality
-@cindex functionality, missing
-
-The following functionality is missing in the current version of
-MySQL. For a prioritized list indicating when new extensions
-may be added to MySQL, you should consult
-@uref{http://www.mysql.com/documentation/manual.php?section=TODO, the
-online MySQL TODO list}. That is the latest version of the TODO
-list in this manual. @xref{TODO}.
-
@menu
-* Missing Sub-selects:: Sub-selects
-* Missing SELECT INTO TABLE:: @code{SELECT INTO TABLE}
-* Missing Transactions:: Transactions
-* Missing Triggers:: Triggers
-* Missing Foreign Keys:: Foreign Keys
-* Broken Foreign KEY:: Reasons NOT to Use Foreign Keys constraints
-* Missing Views:: Views
-* Missing comments:: @samp{--} as the start of a comment
+* ANSI diff Sub-selects:: Sub-@code{SELECT}s
+* ANSI diff SELECT INTO TABLE:: @code{SELECT INTO TABLE}
+* ANSI diff Transactions:: Transactions and Atomic Operations
+* ANSI diff Triggers:: Stored Procedures and Triggers
+* ANSI diff Foreign Keys:: Foreign Keys
+* ANSI diff Views:: Views
+* ANSI diff comments:: @samp{--} as the Start of a Comment
@end menu
+For a prioritised list indicating when new extensions will be added to
+MySQL Server, you should consult the online MySQL TODO list at
+@uref{http://www.mysql.com/documentation/manual.php?section=TODO}.
+That is the latest version of the TODO list in this manual. @xref{TODO}.
+
-@node Missing Sub-selects, Missing SELECT INTO TABLE, Missing functions, Missing functions
-@subsubsection Sub-selects
+@node ANSI diff Sub-selects, ANSI diff SELECT INTO TABLE, Differences from ANSI, Differences from ANSI
+@subsubsection Sub-@code{SELECT}s
@cindex sub-selects
-MySQL currently only supports sub selects of the form @code{INSERT
-... SELECT ...} and @code{REPLACE ... SELECT ...}. You can however use
-the function @code{IN()} in other contexts.
+MySQL Server currently only supports nested queries of the form
+@code{INSERT ... SELECT ...} and @code{REPLACE ... SELECT ...}.
+You can however use the function @code{IN()} in other contexts.
+Sub-selects are scheduled for implementation in Version 4.x.
-In many cases you can rewrite the query without a sub-select:
+Meanwhile, you can often rewrite the query without a sub-select:
@example
SELECT * FROM table1 WHERE id IN (SELECT id FROM table2);
@@ -3753,13 +2943,15 @@ SELECT table1.* FROM table1,table2 WHERE table1.id=table2.id;
The queries:
@example
SELECT * FROM table1 WHERE id NOT IN (SELECT id FROM table2);
-SELECT * FROM table1 WHERE NOT EXISTS (SELECT id FROM table2 where table1.id=table2.id);
+SELECT * FROM table1 WHERE NOT EXISTS (SELECT id FROM table2
+ WHERE table1.id=table2.id);
@end example
Can be rewritten as:
@example
-SELECT table1.* FROM table1 LEFT JOIN table2 ON table1.id=table2.id where table2.id IS NULL
+SELECT table1.* FROM table1 LEFT JOIN table2 ON table1.id=table2.id
+ WHERE table2.id IS NULL;
@end example
For more complicated subqueries you can often create temporary tables
@@ -3767,7 +2959,7 @@ to hold the subquery. In some cases, however this option will not
work. The most frequently encountered of these cases arises with
@code{DELETE} statements, for which standard SQL does not support joins
(except in sub-selects). For this situation there are two options
-available until subqueries are supported by MySQL.
+available until subqueries are supported by MySQL Server.
The first option is to use a procedural programming language (such as
Perl or PHP) to submit a @code{SELECT} query to obtain the primary keys
@@ -3775,7 +2967,7 @@ for the records to be deleted, and then use these values to construct
the @code{DELETE} statement (@code{DELETE FROM ... WHERE ... IN (key1,
key2, ...)}).
-The second option is to use interactive SQL to contruct a set of
+The second option is to use interactive SQL to construct a set of
@code{DELETE} statements automatically, using the MySQL
extension @code{CONCAT()} (in lieu of the standard @code{||} operator).
For example:
@@ -3791,149 +2983,230 @@ the @code{mysql} command-line interpreter, piping its output back to a
second instance of the interpreter:
@example
-prompt> mysql --skip-column-names mydb < myscript.sql | mysql mydb
+shell> mysql --skip-column-names mydb < myscript.sql | mysql mydb
@end example
-MySQL 4.0 supports multi-table deletes that can be used to efficiently
-delete rows based on information from one table or even from many tables
-at the same time.
+MySQL Server 4.0 supports multi-table deletes that can be used to
+efficiently delete rows based on information from one table or even
+from many tables at the same time.
-@node Missing SELECT INTO TABLE, Missing Transactions, Missing Sub-selects, Missing functions
+
+@node ANSI diff SELECT INTO TABLE, ANSI diff Transactions, ANSI diff Sub-selects, Differences from ANSI
@subsubsection @code{SELECT INTO TABLE}
@findex SELECT INTO TABLE
-MySQL doesn't yet support the Oracle SQL extension:
-@code{SELECT ... INTO TABLE ...}. MySQL supports instead the
+MySQL Server doesn't yet support the Oracle SQL extension:
+@code{SELECT ... INTO TABLE ...}. MySQL Server supports instead the
ANSI SQL syntax @code{INSERT INTO ... SELECT ...}, which is basically
the same thing. @xref{INSERT SELECT}.
@example
-INSERT INTO tblTemp2 (fldID) SELECT tblTemp1.fldOrder_ID FROM tblTemp1 WHERE
-tblTemp1.fldOrder_ID > 100;
+INSERT INTO tblTemp2 (fldID) SELECT tblTemp1.fldOrder_ID
+ FROM tblTemp1 WHERE tblTemp1.fldOrder_ID > 100;
@end example
Alternatively, you can use @code{SELECT INTO OUTFILE...} or @code{CREATE
-TABLE ... SELECT} to solve your problem.
+TABLE ... SELECT}.
-@node Missing Transactions, Missing Triggers, Missing SELECT INTO TABLE, Missing functions
-@subsubsection Transactions
+@node ANSI diff Transactions, ANSI diff Triggers, ANSI diff SELECT INTO TABLE, Differences from ANSI
+@subsubsection Transactions and Atomic Operations
+@findex COMMIT
+@findex ROLLBACK
@cindex transactions, support
-
-As MySQL does nowadays support transactions, the following
-discussion is only valid if you are only using the non-transaction-safe
-table types. @xref{COMMIT}.
-
-The question is often asked, by the curious and the critical, ``Why is
-MySQL not a transactional database?'' or ``Why does MySQL
-not support transactions?''
-
-MySQL has made a conscious decision to support another paradigm
-for data integrity, ``atomic operations.'' It is our thinking and
-experience that atomic operations offer equal or even better integrity
-with much better performance. We, nonetheless, appreciate and understand
-the transactional database paradigm and plan, within the next few releases,
-to introduce transaction-safe tables on a per table basis. We will be
-giving our users the possibility to decide if they need the speed of
-atomic operations or if they need to use transactional features in their
-applications.
-
-How does one use the features of MySQL to maintain rigorous integrity
+@cindex transaction-safe tables
+@cindex tables, updating
+@cindex updating, tables
+@cindex @code{InnoDB} tables
+@cindex @code{BDB} tables
+@cindex @code{ACID}
+
+MySQL Server supports transactions with the @code{InnoDB} and @code{BDB}
+@code{Transactional table handlers}. @xref{Table types}.
+@code{InnoDB} provides @code{ACID} compliancy.
+
+However, the non-transactional table types in MySQL Server such as
+@code{MyISAM} follow another paradigm for data integrity called
+``@code{Atomic Operations}.'' Atomic operations often offer equal or
+even better integrity with much better performance.
+With MySQL Server supporting both paradigms, the user is able to decide if
+they need the speed of atomic operations or if they need to use
+transactional features in their applications. This choice can be made
+on a per-table basis.
+
+How does one use the features of MySQL Server to maintain rigorous integrity
and how do these features compare with the transactional paradigm?
-First, in the transactional paradigm, if your applications are written
-in a way that is dependent on the calling of ``rollback'' instead of
-``commit'' in critical situations, then transactions are more
-convenient. Moreover, transactions ensure that unfinished updates or
+@enumerate
+@item
+In the transactional paradigm, if your applications are written in a
+way that is dependent on the calling of @code{ROLLBACK} instead of
+@code{COMMIT} in critical situations, then transactions are more
+convenient. Transactions also ensure that unfinished updates or
corrupting activities are not committed to the database; the server is
given the opportunity to do an automatic rollback and your database is
saved.
-MySQL, in almost all cases, allows you to solve for potential
-problems by including simple checks before updates and by running simple
-scripts that check the databases for inconsistencies and automatically
-repair or warn if such occurs. Note that just by using the
-MySQL log or even adding one extra log, one can normally fix
-tables perfectly with no data integrity loss.
-
-Moreover, fatal transactional updates can be rewritten to be
-atomic. In fact,we will go so far as to say that all integrity problems
-that transactions solve can be done with @code{LOCK TABLES} or atomic updates,
-ensuring that you never will get an automatic abort from the database,
-which is a common problem with transactional databases.
-
-Not even transactions can prevent all loss if the server goes down. In
-such cases even a transactional system can lose data. The difference
-between different systems lies in just how small the time-lap is where
-they could lose data. No system is 100% secure, only ``secure
-enough.'' Even Oracle, reputed to be the safest of transactional
-databases, is reported to sometimes lose data in such situations.
-
-To be safe with MySQL, you only need to have backups and have
-the update logging turned on. With this you can recover from any
-situation that you could with any transactional database. It is, of
-course, always good to have backups, independent of which database you
-use.
+MySQL Server, in almost all cases, allows you to resolve potential problems
+by including simple checks before updates and by running simple scripts
+that check the databases for inconsistencies and automatically repair
+or warn if such an inconsistency occurs. Note that just by using the
+MySQL log or even adding one extra log, one can normally fix tables
+perfectly with no data integrity loss.
+
+@item
+More often than not, fatal transactional updates can be rewritten to be
+atomic. Generally speaking, all integrity problems that transactions
+solve can be done with @code{LOCK TABLES} or atomic updates, ensuring
+that you never will get an automatic abort from the database, which is
+a common problem with transactional databases.
+
+@item
+Even a transactional system can lose data if the server goes down.
+The difference between different systems lies in just how small the
+time-lap is where they could lose data. No system is 100% secure, only
+``secure enough.'' Even Oracle, reputed to be the safest of
+transactional databases, is reported to sometimes lose data in such
+situations.
+
+To be safe with MySQL Server, whether using transactional tables or not, you
+only need to have backups and have the update logging turned on. With
+this you can recover from any situation that you could with any
+other transactional database. It is, of course, always good to have
+backups, independent of which database you use.
+@end enumerate
The transactional paradigm has its benefits and its drawbacks. Many
-users and application developers depend on the ease with which they can
-code around problems where an abort appears to be, or is necessary, and they
-may have to do a little more work with MySQL to either think
-differently or write more. If you are new to the atomic operations
-paradigm, or more familiar or more comfortable with transactions, do not
-jump to the conclusion that MySQL has not addressed these
-issues. Reliability and integrity are foremost in our minds. Recent
-estimates indicate that there are more than 1,000,000 @code{mysqld} servers
-currently running, many of which are in production environments. We
-hear very, very seldom from our users that they have lost any data, and
-in almost all of those cases user error is involved. This is, in our
-opinion, the best proof of MySQL's stability and reliability.
-
-Lastly, in situations where integrity is of highest importance,
-MySQL's current features allow for transaction-level or better
-reliability and integrity. If you lock tables with @code{LOCK TABLES}, all
-updates will stall until any integrity checks are made. If you only obtain
-a read lock (as opposed to a write lock), then reads and inserts are
-still allowed to happen. The new inserted records will not be seen by
-any of the clients that have a @code{READ} lock until they release their read
-locks. With @code{INSERT DELAYED} you can queue inserts into a local queue,
-until the locks are released, without having the client wait for the insert
-to complete. @xref{INSERT DELAYED}.
-
-``Atomic,'' in the sense that we mean it, is nothing magical. It only means
-that you can be sure that while each specific update is running, no other
-user can interfere with it, and there will never be an automatic
-rollback (which can happen on transaction based systems if you are not
-very careful). MySQL also guarantees that there will not be
-any dirty reads. You can find some example of how to write atomic updates
-in the commit-rollback section. @xref{Commit-rollback}.
-
-We have thought quite a bit about integrity and performance, and we
-believe that our atomic operations paradigm allows for both high
-reliability and extremely high performance, on the order of three to
-five times the speed of the fastest and most optimally tuned of
-transactional databases. We didn't leave out transactions because they
-are hard to do. The main reason we went with atomic operations as
-opposed to transactions is that by doing this we could apply many speed
-optimizations that would not otherwise have been possible.
-
-Many of our users who have speed foremost in their minds are not at all
-concerned about transactions. For them transactions are not an
-issue. For those of our users who are concerned with or have wondered
-about transactions vis-a-vis MySQL, there is a ``MySQL
-way'' as we have outlined above. For those where safety is more
-important than speed, we recommend them to use the @code{BDB},
-or @code{InnoDB} tables for all their critical data. @xref{Table types}.
-
-One final note: We are currently working on a safe replication schema
-that we believe to be better than any commercial replication system we
-know of. This system will work most reliably under the atomic
-operations, non-transactional, paradigm. Stay tuned.
-
-
-@node Missing Triggers, Missing Foreign Keys, Missing Transactions, Missing functions
+users and application developers depend on the ease with which they
+can code around problems where an abort appears to be, or is necessary.
+However, even if you are new to the atomic operations paradigm, or more
+familiar with transactions, do consider the speed benefit that
+non-transactional tables can offer, on the order of three to five times
+the speed of the fastest and most optimally tuned transactional tables.
+
+In situations where integrity is of highest importance, MySQL Server offers
+transaction-level or better reliability and integrity even for
+non-transactional tables.
+If you lock tables with @code{LOCK TABLES}, all updates will stall
+until any integrity checks are made. If you only obtain a read lock
+(as opposed to a write lock), then reads and inserts are still allowed
+to happen. The new inserted records will not be seen by any of the
+clients that have a @code{READ} lock until they release their read
+locks. With @code{INSERT DELAYED} you can queue inserts into a local
+queue, until the locks are released, without having the client wait
+for the insert to complete. @xref{INSERT DELAYED}.
+
+``Atomic,'' in the sense that we mean it, is nothing magical. It only
+means that you can be sure that while each specific update is running,
+no other user can interfere with it, and there will never be an
+automatic rollback (which can happen with transactional tables if you
+are not very careful). MySQL Server also guarantees that there will not be
+any dirty reads.
+
+Following are some techniques for working with non-transactional tables:
+
+@itemize @bullet
+@item
+Loops that need transactions normally can be coded with the help of
+@code{LOCK TABLES}, and you don't need cursors when you can update
+records on the fly.
+
+@item
+To avoid using @code{ROLLBACK}, you can use the following strategy:
+
+@enumerate
+@item
+Use @code{LOCK TABLES ...} to lock all the tables you want to access.
+@item
+Test conditions.
+@item
+Update if everything is okay.
+@item
+Use @code{UNLOCK TABLES} to release your locks.
+@end enumerate
+
+This is usually a much faster method than using transactions with
+possible @code{ROLLBACK}s, although not always. The only situation
+this solution doesn't handle is when someone kills the threads in the
+middle of an update. In this case, all locks will be released but some
+of the updates may not have been executed.
+
+@item
+You can also use functions to update records in a single operation.
+You can get a very efficient application by using the following
+techniques:
+
+@itemize @bullet
+@item Modify fields relative to their current value.
+@item Update only those fields that actually have changed.
+@end itemize
+
+For example, when we are doing updates to some customer information, we
+update only the customer data that has changed and test only that none of
+the changed data, or data that depend on the changed data, has changed
+compared to the original row. The test for changed data is done with the
+@code{WHERE} clause in the @code{UPDATE} statement. If the record wasn't
+updated, we give the client a message: "Some of the data you have changed
+have been changed by another user". Then we show the old row versus the new
+row in a window, so the user can decide which version of the customer record
+he should use.
+
+This gives us something that is similar to column locking but is actually
+even better, because we only update some of the columns, using values that
+are relative to their current values. This means that typical @code{UPDATE}
+statements look something like these:
+
+@example
+UPDATE tablename SET pay_back=pay_back+'relative change';
+
+UPDATE customer
+ SET
+ customer_date='current_date',
+ address='new address',
+ phone='new phone',
+ money_he_owes_us=money_he_owes_us+'new_money'
+ WHERE
+ customer_id=id AND address='old address' AND phone='old phone';
+@end example
+
+As you can see, this is very efficient and works even if another client
+has changed the values in the @code{pay_back} or @code{money_he_owes_us}
+columns.
+
+@item
+@findex mysql_insert_id()
+@findex LAST_INSERT_ID()
+In many cases, users have wanted @code{ROLLBACK} and/or @code{LOCK
+TABLES} for the purpose of managing unique identifiers for some tables.
+This can be handled much more efficiently by using an
+@code{AUTO_INCREMENT} column and either the SQL function
+@code{LAST_INSERT_ID()} or the C API function @code{mysql_insert_id()}.
+@xref{mysql_insert_id, , @code{mysql_insert_id()}}.
+
+@cindex rows, locking
+@cindex locking, row-level
+Generally, you can code around row-level locking. Some cases really
+need it, but they are very few. For instance, you can use a flag
+column in the table and do something like this:
+
+@example
+UPDATE tbl_name SET row_flag=1 WHERE id=ID;
+@end example
+
+MySQL returns 1 for the number of affected rows if the row was
+found and @code{row_flag} wasn't already 1 in the original row.
+
+You can think of it as MySQL Server changed the above query to:
+
+@example
+UPDATE tbl_name SET row_flag=1 WHERE id=ID and row_flag <> 1;
+@end example
+@end itemize
+
+
+@node ANSI diff Triggers, ANSI diff Foreign Keys, ANSI diff Transactions, Differences from ANSI
@subsubsection Stored Procedures and Triggers
@cindex stored procedures and triggers, defined
@@ -3953,14 +3226,12 @@ each time a record is deleted from a transaction table and that automatically
deletes the corresponding customer from a customer table when all his
transactions are deleted.
-The planned update language will be able to
-handle stored procedures, but without triggers. Triggers usually slow
-down everything, even queries for which they are not needed.
-
-To see when MySQL might get stored procedures, see @ref{TODO}.
+The planned update language will be able to handle stored procedures.
+Our aim is to have stored procedures implemented in MySQL Server 4.1.
+We are also looking at triggers.
-@node Missing Foreign Keys, Broken Foreign KEY, Missing Triggers, Missing functions
+@node ANSI diff Foreign Keys, ANSI diff Views, ANSI diff Triggers, Differences from ANSI
@subsubsection Foreign Keys
@cindex foreign keys
@@ -3977,151 +3248,135 @@ SELECT * from table1,table2 where table1.id = table2.id;
@xref{JOIN, , @code{JOIN}}. @xref{example-Foreign keys}.
-The @code{FOREIGN KEY} syntax in MySQL exists only for compatibility
-with other SQL vendors' @code{CREATE TABLE} commands; it doesn't do
-anything. The @code{FOREIGN KEY} syntax without @code{ON DELETE ...} is
-mostly used for documentation purposes. Some ODBC applications may use this
-to produce automatic @code{WHERE} clauses, but this is usually easy to
-override. @code{FOREIGN KEY} is sometimes used as a constraint check, but
-this check is unnecessary in practice if rows are inserted into the tables in
-the right order. MySQL only supports these clauses because some
-applications require them to exist (regardless of whether or not they
-work).
-
-In MySQL, you can work around the problem of @code{ON DELETE
-...} not being implemented by adding the appropriate @code{DELETE} statement to
-an application when you delete records from a table that has a foreign key.
-In practice this is as quick (in some cases quicker) and much more portable
-than using foreign keys.
-
-In the near future we will extend the @code{FOREIGN KEY} implementation so
-that at least the information will be saved in the table specification file
-and may be retrieved by @code{mysqldump} and ODBC. At a later stage we will
-implement the foreign key constraints for application that can't easily be
-coded to avoid them.
+In MySQL Server 3.23.44 and up, @code{InnoDB} tables supports checking of
+foreign key constraints. @xref{InnoDB}. For other table types, MySQL Server
+does parse the @code{FOREIGN KEY} syntax in @code{CREATE TABLE}
+commands, but without further action being taken.
-@menu
-* Broken Foreign KEY:: Reasons NOT to use foreign keys constraints
-@end menu
-
-
-@node Broken Foreign KEY, Missing Views, Missing Foreign Keys, Missing functions
-@subsubsection Reasons NOT to Use Foreign Keys constraints
-
-@cindex foreign keys, reasons not to use
+The @code{FOREIGN KEY} syntax without @code{ON DELETE ...} is mostly
+used for documentation purposes. Some ODBC applications may use this
+to produce automatic @code{WHERE} clauses, but this is usually easy to
+override. @code{FOREIGN KEY} is sometimes used as a constraint check,
+but this check is unnecessary in practice if rows are inserted into the
+tables in the right order.
+
+In MySQL Server, you can work around the problem of @code{ON DELETE ...} not
+being implemented by adding the appropriate @code{DELETE} statement to
+an application when you delete records from a table that has a foreign
+key. In practice this is as quick (in some cases quicker) and much more
+portable than using foreign keys.
+
+In MySQL Server 4.0 you can use multi-table delete to delete rows from many
+tables with one command. @xref{DELETE}.
+
+In the near future we will extend the @code{FOREIGN KEY} implementation
+so that the information will be saved in the table specification file
+and may be retrieved by @code{mysqldump} and ODBC. At a later stage we
+will implement the foreign key constraints for applications that can't
+easily be coded to avoid them.
+
+Do keep in mind that foreign keys are often misused, which can cause
+severe problems. Even when used properly, it is not a magic solution for
+the referential integrity problem, although it does make things easier
+in some cases.
-There are so many problems with foreign key constraints that we don't
-know where to start:
+Some advantages of foreign key enforcement:
@itemize @bullet
@item
-Foreign key constraints make life very complicated, because the foreign
-key definitions must be stored in a database and implementing them would
-destroy the whole ``nice approach'' of using files that can be moved,
-copied, and removed.
+Assuming proper design of the relations, foreign key constraints will
+make it more difficult for a programmer to introduce an inconsistency
+into the database.
@item
-The speed impact is terrible for @code{INSERT} and @code{UPDATE}
-statements, and in this case almost all @code{FOREIGN KEY} constraint
-checks are useless because you usually insert records in the right
-tables in the right order, anyway.
+Using cascading updates and deletes can simplify the client code.
@item
-There is also a need to hold locks on many more tables when updating one
-table, because the side effects can cascade through the entire database. It's
-MUCH faster to delete records from one table first and subsequently delete
-them from the other tables.
+Properly designed foreign key rules aid in documenting relations
+between tables.
+@end itemize
-@item
-You can no longer restore a table by doing a full delete from the table
-and then restoring all records (from a new source or from a backup).
+Disadvantages:
+@itemize @bullet
@item
-If you use foreign key constraints you can't dump and restore tables
-unless you do so in a very specific order.
+Mistakes, that are easy to make in designing key relations, can cause
+severe problems, for example, circular rules, or the wrong combination
+of cascading deletes.
@item
-It's very easy to do ``allowed'' circular definitions that make the
-tables impossible to re-create each table with a single create statement,
-even if the definition works and is usable.
+A properly written application will make sure internally that it is
+not violating referential integrity constraints before proceding with
+a query. Thus, additionaly checks on the database level will only slow
+down performance for such application.
@item
-It's very easy to overlook @code{FOREIGN KEY ... ON DELETE} rules when
-one codes an application. It's not unusual that one loses a lot of
-important information just because a wrong or misused @code{ON DELETE} rule.
+It is not uncommon for a DBA to make such a complex topology of
+relations that it becomes very difficult, and in some cases impossible
+to backup or restore individual tables.
@end itemize
-The only nice aspect of @code{FOREIGN KEY} is that it gives ODBC and some
-other client programs the ability to see how a table is connected and to use
-this to show connection diagrams and to help in building applications.
-
-MySQL will soon store @code{FOREIGN KEY} definitions so that a
-client can ask for and receive an answer about how the original
-connection was made. The current @file{.frm} file format does not have
-any place for it. At a later stage we will implement the foreign key
-constraints for application that can't easily be coded to avoid them.
-
-@node Missing Views, Missing comments, Broken Foreign KEY, Missing functions
+@node ANSI diff Views, ANSI diff comments, ANSI diff Foreign Keys, Differences from ANSI
@subsubsection Views
@cindex views
-MySQL doesn't yet support views, but we plan to implement these
-to about 4.1.
+It is planned to implement views in MySQL Server around Version 4.1.
Views are mostly useful for letting users access a set of relations as one
table (in read-only mode). Many SQL databases don't allow one to update
any rows in a view, but you have to do the updates in the separate tables.
-As MySQL is mostly used in applications and on web system where
+As MySQL Server is mostly used in applications and on web system where
the application writer has full control on the database usage, most of
-our users haven't regarded views to be very important. (At least no one
-has been interested enough in this to be prepared to finance the
-implementation of views).
+our users haven't regarded views to be very important.
+(At least no one has been interested enough in this to be prepared to
+finance the implementation of views).
-One doesn't need views in MySQL to restrict access to columns
-as MySQL has a very sophisticated privilege
-system. @xref{Privilege system}.
+One doesn't need views in MySQL Server to restrict access to columns
+as MySQL Server has a very sophisticated privilege system.
+@xref{Privilege system}.
-@node Missing comments, , Missing Views, Missing functions
+@node ANSI diff comments, , ANSI diff Views, Differences from ANSI
@subsubsection @samp{--} as the Start of a Comment
@cindex comments, starting
@cindex starting, comments
-Some other SQL databases use @samp{--} to start comments. MySQL
-has @samp{#} as the start comment character, even if the @code{mysql}
-command-line tool removes all lines that start with @samp{--}.
-You can also use the C comment style @code{/* this is a comment */} with
-MySQL.
+Some other SQL databases use @samp{--} to start comments.
+MySQL Server has @samp{#} as the start comment character. You can also use
+the C comment style @code{/* this is a comment */} with MySQL Server.
@xref{Comments}.
-MySQL Version 3.23.3 and above supports the @samp{--} comment style
-only if the comment is followed by a space. This is because this
-degenerate comment style has caused many problems with automatically
-generated SQL queries that have used something like the following code,
-where we automatically insert the value of the payment for
+MySQL Server Version 3.23.3 and above supports the @samp{--} comment style,
+provided the comment is followed by a space. This is because this
+comment style has caused many problems with automatically generated
+SQL queries that have used something like the following code, where
+we automatically insert the value of the payment for
@code{!payment!}:
@example
UPDATE tbl_name SET credit=credit-!payment!
@end example
-What do you think will happen when the value of @code{payment} is negative?
+Think about what happens if the value of @code{payment} is negative?
+Because @code{1--1} is legal in SQL, the consequences of allowing
+comments to start with @samp{--} are terrible.
-Because @code{1--1} is legal in SQL, we think it is terrible that
-@samp{--} means start comment.
+Using our implementation of this method of commenting in MySQL Server
+Version 3.23.3 and up, @code{1-- This is a comment} is actually safe.
-In MySQL Version 3.23 you can, however, use:
-@code{1-- This is a comment}
+Another safe feature is that the @code{mysql} command-line client
+removes all lines that start with @samp{--}.
-The following discussion only concerns you if you are running a MySQL
-version earlier than Version 3.23:
-If you have a SQL program in a text file that contains @samp{--} comments
-you should use:
+The following information is only relevant if you are running a
+MySQL version earlier than Version 3.23.3:
+
+If you have a SQL program in a text file that contains @samp{--}
+comments you should use:
@example
shell> replace " --" " #" < text-file-with-funny-comments.sql \
@@ -4148,149 +3403,8 @@ shell> replace " #" " --" -- text-file-with-funny-comments.sql
@end example
-@node Standards, Commit-rollback, Missing functions, Compatibility
-@subsection What Standards Does MySQL Follow?
-
-Entry level SQL92. ODBC levels 0-2.
-
-
-@node Commit-rollback, Bugs, Standards, Compatibility
-@subsection How to Cope Without @code{COMMIT}/@code{ROLLBACK}
-
-@findex COMMIT
-@findex ROLLBACK
-@cindex transaction-safe tables
-@cindex tables, updating
-@cindex updating, tables
-@cindex @code{BDB} tables
-@cindex @code{InnoDB} tables
-
-The following mostly applies only for @code{ISAM}, @code{MyISAM}, and
-@code{HEAP} tables. If you only use transaction-safe tables (@code{BDB},
-or @code{InnoDB} tables) in an an update, you can do
-@code{COMMIT} and @code{ROLLBACK} also with MySQL.
-@xref{COMMIT}.
-
-The problem with handling @code{COMMIT}-@code{ROLLBACK} efficiently with
-the above table types would require a completely different table layout
-than MySQL uses today. The table type would also need extra
-threads that do automatic cleanups on the tables, and the disk usage
-would be much higher. This would make these table types about 2-4 times
-slower than they are today.
-
-For the moment, we prefer implementing the SQL server language (something
-like stored procedures). With this you would very seldom really need
-@code{COMMIT}-@code{ROLLBACK.} This would also give much better performance.
-
-Loops that need transactions normally can be coded with the help of
-@code{LOCK TABLES}, and you don't need cursors when you can update records
-on the fly.
-
-We at TcX had a greater need for a real fast database than a 100%
-general database. Whenever we find a way to implement these features without
-any speed loss, we will probably do it. For the moment, there are many more
-important things to do. Check the TODO for how we prioritize things at
-the moment. (Customers with higher levels of support can alter this, so
-things may be reprioritized.)
-
-The current problem is actually @code{ROLLBACK}. Without
-@code{ROLLBACK}, you can do any kind of @code{COMMIT} action with
-@code{LOCK TABLES}. To support @code{ROLLBACK} with the above table
-types, MySQL would have to be changed to store all old records
-that were updated and revert everything back to the starting point if
-@code{ROLLBACK} was issued. For simple cases, this isn't that hard to do
-(the current @code{isamlog} could be used for this purpose), but it
-would be much more difficult to implement @code{ROLLBACK} for
-@code{ALTER/DROP/CREATE TABLE}.
-
-To avoid using @code{ROLLBACK}, you can use the following strategy:
-
-@enumerate
-@item
-Use @code{LOCK TABLES ...} to lock all the tables you want to access.
-@item
-Test conditions.
-@item
-Update if everything is okay.
-@item
-Use @code{UNLOCK TABLES} to release your locks.
-@end enumerate
-
-This is usually a much faster method than using transactions with possible
-@code{ROLLBACK}s, although not always. The only situation this solution
-doesn't handle is when someone kills the threads in the middle of an
-update. In this case, all locks will be released but some of the updates may
-not have been executed.
-
-You can also use functions to update records in a single operation.
-You can get a very efficient application by using the following techniques:
-
-@itemize @bullet
-@item Modify fields relative to their current value.
-@item Update only those fields that actually have changed.
-@end itemize
-
-For example, when we are doing updates to some customer information, we
-update only the customer data that has changed and test only that none of
-the changed data, or data that depend on the changed data, has changed
-compared to the original row. The test for changed data is done with the
-@code{WHERE} clause in the @code{UPDATE} statement. If the record wasn't
-updated, we give the client a message: "Some of the data you have changed
-have been changed by another user". Then we show the old row versus the new
-row in a window, so the user can decide which version of the customer record
-he should use.
-
-This gives us something that is similar to column locking but is actually
-even better, because we only update some of the columns, using values that
-are relative to their current values. This means that typical @code{UPDATE}
-statements look something like these:
-
-@example
-UPDATE tablename SET pay_back=pay_back+'relative change';
-
-UPDATE customer
- SET
- customer_date='current_date',
- address='new address',
- phone='new phone',
- money_he_owes_us=money_he_owes_us+'new_money'
- WHERE
- customer_id=id AND address='old address' AND phone='old phone';
-@end example
-
-As you can see, this is very efficient and works even if another client has
-changed the values in the @code{pay_back} or @code{money_he_owes_us} columns.
-
-@findex mysql_insert_id()
-@findex LAST_INSERT_ID()
-In many cases, users have wanted @code{ROLLBACK} and/or @code{LOCK
-TABLES} for the purpose of managing unique identifiers for some tables. This
-can be handled much more efficiently by using an @code{AUTO_INCREMENT} column
-and either the SQL function @code{LAST_INSERT_ID()} or the C API function
-@code{mysql_insert_id()}. @xref{mysql_insert_id, , @code{mysql_insert_id()}}.
-
-@cindex rows, locking
-At MySQL AB, we have never had any need for row-level locking
-because we have always been able to code around it. Some cases really need
-row locking, but they are very few. If you want row-level locking, you
-can use a flag column in the table and do something like this:
-
-@example
-UPDATE tbl_name SET row_flag=1 WHERE id=ID;
-@end example
-
-MySQL returns 1 for the number of affected rows if the row was
-found and @code{row_flag} wasn't already 1 in the original row.
-
-You can think of it as MySQL changed the above query to:
-
-@example
-UPDATE tbl_name SET row_flag=1 WHERE id=ID and row_flag <> 1;
-@end example
-
-
-@node Bugs, , Commit-rollback, Compatibility
-@subsection Known errors and design deficiencies in MySQL
+@node Bugs, , Differences from ANSI, Compatibility
+@subsection Known Errors and Design Deficiencies in MySQL
@cindex bugs, known
@cindex errors, known
@@ -4320,7 +3434,7 @@ will probably be ignored).
cause problems on tables for which you are using @code{INSERT DELAYED}.
@item
-Doing a @code{LOCK TABLE ..} and @code{FLUSH TABLES ..} doesn't
+Doing a @code{LOCK TABLE ...} and @code{FLUSH TABLES ...} doesn't
guarantee that there isn't a half-finished transaction in progress on the
table.
@@ -4339,8 +3453,6 @@ and line terminator characters of more than 1 character.
The following problems are known and will be fixed in due time:
@itemize @bullet
-@item
-For the moment @code{MATCH} only works with @code{SELECT} statements.
@item
When using @code{SET CHARACTER SET}, one can't use translated
@@ -4349,12 +3461,12 @@ characters in database, table and column names.
@item
@code{DELETE FROM merge_table} used without a @code{WHERE}
will only clear the mapping for the table, not delete everything in the
-mapped tables
+mapped tables.
@item
-You cannot build in another directory when using
+You cannot build the server in another directory when using
MIT-pthreads. Because this requires changes to MIT-pthreads, we are not
-likely to fix this.
+likely to fix this. @xref{MIT-pthreads}.
@item
@code{BLOB} values can't ``reliably'' be used in @code{GROUP BY} or
@@ -4372,12 +3484,13 @@ precision, @code{IF}, and @code{ELT()} with @code{BIGINT} or @code{DOUBLE}
precision and the rest with @code{DOUBLE} precision. One should try to
avoid using bigger unsigned long long values than 63 bits
(9223372036854775807) for anything else than bit fields!
+MySQL Server 4.0 has better @code{BIGINT} handling than 3.23.
@item
All string columns, except @code{BLOB} and @code{TEXT} columns, automatically
have all trailing spaces removed when retrieved. For @code{CHAR} types this
is okay, and may be regarded as a feature according to ANSI SQL92. The bug is
-that in MySQL, @code{VARCHAR} columns are treated the same way.
+that in MySQL Server, @code{VARCHAR} columns are treated the same way.
@item
You can only have up to 255 @code{ENUM} and @code{SET} columns in one table.
@@ -4412,10 +3525,11 @@ select * from temporary_table, temporary_table as t2;
@end example
@item
-@code{RENAME} doesn't work with @code{TEMPORARY} tables.
+@code{RENAME} doesn't work with @code{TEMPORARY} tables or tables used in a
+@code{MERGE} table.
@item
-The optimizer may handle @code{DISTINCT} differently if you are using
+The optimiser may handle @code{DISTINCT} differently if you are using
'hidden' columns in a join or not. In a join, hidden columns are
counted as part of the result (even if they are not shown) while in
normal queries hidden columns doesn't participate in the @code{DISTINCT}
@@ -4425,19 +3539,21 @@ the hidden columns when executing @code{DISTINCT}
An example of this is:
@example
-SELECT DISTINCT mp3id FROM band_downloads WHERE userid = 9 ORDER BY id
-DESC;
+SELECT DISTINCT mp3id FROM band_downloads
+ WHERE userid = 9 ORDER BY id DESC;
@end example
and
@example
-SELECT DISTINCT band_downloads.mp3id, FROM band_downloads,band_mp3
-WHERE band_downloads.userid = 9 AND band_mp3.id = band_downloads.mp3id
-ORDER BY band_downloads.id DESC;
+SELECT DISTINCT band_downloads.mp3id
+ FROM band_downloads,band_mp3
+ WHERE band_downloads.userid = 9
+ AND band_mp3.id = band_downloads.mp3id
+ ORDER BY band_downloads.id DESC;
@end example
-In the second case you may in MySQL 3.23.x get two identical rows
+In the second case you may in MySQL Server 3.23.x get two identical rows
in the result set (because the hidden 'id' column may differ).
Note that the this only happens for queries where you don't have the
@@ -4445,48 +3561,48 @@ ORDER BY columns in the result, something that is you are not allowed
to do in ANSI SQL.
@item
-Because MySQL allows you to work with table types that doesn't
-support transactions (and thus can't @code{rollback} data) some things
-behaves a little different in MySQL than in other SQL servers:
-(This is just to ensure that MySQL never need to do a rollback
-for a SQL command). This may be a little awkward at times as column
-Because MySQL allows you to work with table types that don't
+Because MySQL Server allows you to work with table types that don't
support transactions, and thus can't @code{rollback} data, some things
-behave a little differently in MySQL than in other SQL servers.
-This is just to ensure that MySQL never need to do a rollback
+behave a little differently in MySQL Server than in other SQL servers.
+This is just to ensure that MySQL Server never need to do a rollback
for a SQL command. This may be a little awkward at times as column
values must be checked in the application, but this will actually give
-you a nice speed increase as it allows MySQL to do some
-optimizations that otherwise would be very hard to do.
+you a nice speed increase as it allows MySQL Server to do some
+optimisations that otherwise would be very hard to do.
-If you set a column to an incorrect value, MySQL will, instead of
+If you set a column to an incorrect value, MySQL Server will, instead of
doing a rollback, store the @code{best possible value} in the column:
@itemize @minus
@item
If you try to store a value outside the range in a numerical column,
-MySQL will instead store the smallest or biggest possible value in
+MySQL Server will instead store the smallest or biggest possible value in
the column.
@item
If you try to store a string that doesn't start with a number into a
-numerical column, MySQL will store 0 into it.
+numerical column, MySQL Server will store 0 into it.
@item
If you try to store @code{NULL} into a column that doesn't take
-@code{NULL} values, MySQL will store 0 or @code{''} (empty
+@code{NULL} values, MySQL Server will store 0 or @code{''} (empty
string) in it instead. (This behavior can, however, be changed with the
-DDONT_USE_DEFAULT_FIELDS compile option).
@item
MySQL allows you to store some wrong date values into
@code{DATE} and @code{DATETIME} columns. (Like 2000-02-31 or 2000-02-00).
-If the date is totally wrong, MySQL will store the special
+If the date is totally wrong, MySQL Server will store the special
0000-00-00 date value in the column.
@item
-If you set an @code{enum} to an unsupported value, it will be set to
+If you set an @code{ENUM} column to an unsupported value, it will be set to
the error value 'empty string', with numeric value 0.
+
+@item
+If you set an @code{SET} column to an unsupported value, the value will
+be ignored.
+
@end itemize
@item
@@ -4498,7 +3614,7 @@ Creation of a table of type @code{MERGE} doesn't check if the underlying
tables are of compatible types.
@item
-MySQL can't yet handle @code{NaN}, @code{-Inf} and @code{Inf}
+MySQL Server can't yet handle @code{NaN}, @code{-Inf} and @code{Inf}
values in double. Using these will cause problems when trying to export
and import data. We should as an intermediate solution change @code{NaN} to
@code{NULL} (if possible) and @code{-Inf} and @code{Inf} to the
@@ -4506,6 +3622,7 @@ Minimum respective maximum possible @code{double} value.
@item
@code{LIMIT} on negative numbers are treated as big positive numbers.
+
@item
If you use @code{ALTER TABLE} to first add an @code{UNIQUE} index to a
table used in a @code{MERGE} table and then use @code{ALTER TABLE} to
@@ -4537,7 +3654,7 @@ Delayed insert handler has pending inserts to a table.
@end itemize
@item
-Before MySQL Version 3.23.2 an @code{UPDATE} that updated a key with
+Before MySQL Server Version 3.23.2 an @code{UPDATE} that updated a key with
a @code{WHERE} on the same key may have failed because the key was used to
search for records and the same row may have been found multiple times:
@@ -4551,58 +3668,552 @@ A workaround is to use:
mysql> UPDATE tbl_name SET KEY=KEY+1 WHERE KEY+0 > 100;
@end example
-This will work because MySQL will not use index on expressions in
+This will work because MySQL Server will not use index on expressions in
the @code{WHERE} clause.
@item
-Before MySQL Version 3.23, all numeric types where treated as fixed-point
-fields. That means you had to specify how many decimals a floating-point
-field shall have. All results were returned with the correct number of
-decimals.
+Before MySQL Server Version 3.23, all numeric types where treated as
+fixed-point fields. That means you had to specify how many decimals
+a floating-point field shall have. All results were returned with the
+correct number of decimals.
@end itemize
For platform-specific bugs, see the sections about compiling and porting.
-@node Comparisons, TODO, Compatibility, Introduction
-@section How MySQL Compares to Other Databases
+@node TODO, Comparisons, Compatibility, Introduction
+@section MySQL and The Future (The TODO)
-@cindex databases, MySQL vs. others
-@cindex comparisons, MySQL vs. others
+@cindex ToDo list for MySQL
@menu
-* Compare mSQL:: How MySQL compares to @code{mSQL}
-* Compare PostgreSQL:: How MySQL compares with PostgreSQL
+* TODO MySQL 4.0:: Things That Should be in 4.0
+* TODO MySQL 4.1:: Things That Should be in 4.1
+* TODO future:: Things That Must be Done in the Near Future
+* TODO sometime:: Things That Have to be Done Sometime
+* TODO unplanned:: Things we don't Have any Plans to do
@end menu
-This section compares MySQL to other popular databases.
+This appendix lists the features that we plan to implement in MySQL Server.
+
+Everything in this list is approximately in the order it will be done. If you
+want to affect the priority order, please register a license or support us and
+tell us what you want to have done more quickly. @xref{Licensing and Support}.
+
+The plan is that we in the future will support the full ANSI SQL99
+standard, but with a lot of useful extensions. The challenge is to do
+this without sacrifying the speed or compromise the code.
+
+
+@node TODO MySQL 4.0, TODO MySQL 4.1, TODO, TODO
+@subsection Things That Should be in 4.0
+
+We are now in the final stages one the development of the MySQL Server
+4.0. server. The target is to quickly implement the rest of the
+following features and then shift development to MySQL Server
+4.1. @xref{MySQL 4.0 In A Nutshell}.
+
+The news section for 4.0 includes a list of the features we have already
+implemented in the 4.0 tree. @xref{News-4.0.x}.
+
+This section lists features not yet implemented in the current version
+of MySQL Server 4.0, which will however be implemented in later versions
+of MySQL 4.0. This being very volatile information, please consider this
+list valid only if you are reading it from the MySQL web site
+(@uref{http://www.mysql.com/}).
+
+@itemize @bullet
+@item
+Allow users to change startup options without taking down the server.
+@item
+Better command line argument handling.
+@item
+New key cache, which will give better performance when using many threads.
+@item
+New table definition file format (@code{.frm} files) This will enable us
+to not run out of bits when adding more table options. One will still
+be able to use the old @code{.frm} file format with 4.0. All newly created
+tables will, however, use the new format.
+
+The new file format will enable us to add new column types, more options
+for keys and possible to store and retrieve @code{FOREIGN KEY} definitions.
+@item
+@code{SHOW COLUMNS FROM table_name} (used by @code{mysql} client to allow
+expansions of column names) should not open the table, but only the
+definition file. This will require less memory and be much faster.
+@item
+@code{SET SQL_DEFAULT_TABLE_TYPE=[MyISAM | INNODB | BDB | HEAP]}.
+@end itemize
+
+
+@node TODO MySQL 4.1, TODO future, TODO MySQL 4.0, TODO
+@subsection Things That Should be in 4.1
+
+We will start working on MySQL 4.1 as soon as MySQL 4.0 goes into beta.
+
+The following features is the ones we plan that should be in MySQL 4.1.
+Note that because we have many developers that are working on different
+projects, there will also be many additional features. There is also a
+small chance that some of these features will be added to MySQL 4.0.
+
+@itemize @bullet
+@item
+Subqueries.
+@code{SELECT id FROM t WHERE grp IN (SELECT grp FROM g WHERE u > 100)}
+@item
+Foreign keys, including cascading delete.
+@item
+Fail safe replication.
+@item
+Replication should work with @code{RAND()} and user variables @code{@@var}.
+@item
+Online backup with very low performance penalty. The online backup will
+make it easy to add a new replication slave without taking down the
+master.
+@item
+Derived tables.
+@example
+SELECT a.col1, b.col2
+ FROM (SELECT MAX(col1) AS col1 FROM root_table) a,
+ other_table b
+ WHERE a.col1=b.col1;
+@end example
+
+This could be done by automatically creating temporary tables for the
+derived tables for the duration of the query.
+@item
+Allow @code{DELETE} on @code{MyISAM} tables to use the record cache.
+To do this, we need to update the threads record cache when we update
+the @code{.MYD} file.
+@item
+When using @code{SET CHARACTER SET} we should translate the whole query
+at once and not only strings. This will enable users to use the translated
+characters in database, table and column names.
+@item
+Add @code{record_in_range()} method to @code{MERGE} tables to be
+able to choose the right index when there is many to choose from. We should
+also extend the info interface to get the key distribution for each index,
+if @code{analyze} is run on all sub tables.
+@item
+@code{RENAME TABLE} on a table used in an active @code{MERGE} table may
+corrupt the table.
+@item
+A faster, smaller embedded MySQL library. (Compatible with the old one)
+@item
+Stable openssl support. (MySQL 4.0 supports rudimentary, not 100 % tested
+support for openssl).
+@item
+Add support for sorting on @code{UNICODE}.
+@item
+Character set casts and syntax for handling multiple character sets.
+@item
+When using @code{SET CHARACTER SET} we should translate the whole query
+at once and not only strings. This will enable users to use the translated
+characters in database, table and column names.
+@item
+Help for all commands from the client.
+@item
+New faster client/server protocol which will support prepared statements,
+bound parameters and bound result columns, binary transfer of data,
+warnings...
+@item
+Add database and real table name (in case of alias) to the MYSQL_FIELD
+structure.
+@item
+Add options to the client/server protocol to get progress notes
+for long running commands.
+@item
+Implement @code{RENAME DATABASE}. To make this safe for all table handlers,
+it should work as follows:
+@itemize @bullet
+@item
+Create the new database.
+@item
+For every table do a rename of the table to another database, as
+we do with the @code{RENAME} command.
+@item
+Drop the old database.
+@end itemize
+@item
+Add true @code{VARCHAR} support (There is already support for this in
+@code{MyISAM}).
+@item
+Optimise @code{BIT} type to take 1 bit (now @code{BIT} takes 1 char).
+@item
+New internal file interface change. This will make all file handling much
+more general and make it easier to add extensions like RAID nicely.
+(The current implementation is a hack).
+@item
+Better in-memory (@code{HEAP}) tables:
+@itemize @bullet
+@item
+Support for B-tree indexes
+@item
+Dynamic size rows
+@item
+Faster row handling (less copying)
+@end itemize
+@end itemize
+
+
+@node TODO future, TODO sometime, TODO MySQL 4.1, TODO
+@subsection Things That Must be Done in the Real Near Future
+
+@itemize @bullet
+@item
+Atomic multi-table updates, eg @code{update items,month set
+items.price=month.price where items.id=month.id;};
+@item
+Don't allow more than a defined number of threads to run MyISAM recover
+at the same time.
+@item
+Change @code{INSERT ... SELECT} to optionally use concurrent inserts.
+@item
+Return the original field types() when doing @code{SELECT MIN(column)
+... GROUP BY}.
+@item
+Multiple result sets.
+@item
+Make it possible to specify @code{long_query_time} with a granularity
+in microseconds.
+@item
+Add a configurable prompt to the @code{mysql} command line client, with
+options like database in use, time and date...
+@item
+Link the @code{myisampack} code into the server.
+@item
+Port of the MySQL code to QNX.
+@item
+Port of the MySQL code to BeOS.
+@item
+Port of the MySQL clients to LynxOS.
+@item
+Add a temporary key buffer cache during @code{INSERT/DELETE/UPDATE} so that we
+can gracefully recover if the index file gets full.
+@item
+If you perform an @code{ALTER TABLE} on a table that is symlinked to another
+disk, create temporary tables on this disk.
+@item
+Implement a @code{DATE/DATETIME} type that handles time zone information
+properly, so that dealing with dates in different time zones is easier.
+@item
+FreeBSD and MIT-pthreads; Do sleeping threads take CPU?
+@item
+Check if locked threads take any CPU.
+@item
+Fix configure so that one can compile all libraries (like @code{MyISAM})
+without threads.
+@item
+Add an option to periodically flush key pages for tables with delayed keys
+if they haven't been used in a while.
+@item
+Allow join on key parts (optimisation issue).
+@item
+@code{INSERT SQL_CONCURRENT} and @code{mysqld --concurrent-insert} to do
+a concurrent insert at the end of the file if the file is read-locked.
+@item
+Server side cursors.
+@item
+Check if @code{lockd} works with modern Linux kernels; If not, we have
+to fix @code{lockd}! To test this, start @code{mysqld} with
+@code{--enable-locking} and run the different fork* test suits. They shouldn't
+give any errors if @code{lockd} works.
+@item
+Allow SQL variables in @code{LIMIT}, like in @code{LIMIT @@a,@@b}.
+@item
+Allow update of variables in @code{UPDATE} statements. For example:
+@code{UPDATE TABLE foo SET @@a=a+b,a=@@a, b=@@a+c}
+@item
+Change when user variables are updated so that one can use them with
+@code{GROUP BY}, as in the following example:
+@code{SELECT id, @@a:=count(*), sum(sum_col)/@@a FROM table_name GROUP BY id}.
+@item
+Don't add automatic @code{DEFAULT} values to columns. Give an error when using
+an @code{INSERT} that doesn't contain a column that doesn't have a
+@code{DEFAULT}.
+@item
+Fix @file{libmysql.c} to allow two @code{mysql_query()} commands in a row
+without reading results or give a nice error message when one does this.
+@item
+Check why MIT-pthreads @code{ctime()} doesn't work on some FreeBSD systems.
+@item
+Add an @code{IMAGE} option to @code{LOAD DATA INFILE} to not update
+@code{TIMESTAMP} and @code{AUTO_INCREMENT} fields.
+@item
+Added @code{LOAD DATE INFILE ... UPDATE} syntax.
+@itemize @bullet
+@item
+For tables with primary keys, if the data contains the primary key,
+entries matching that primary key are updated from the remainder of the
+columns. However, columns @strong{missing} from the incoming data feed are not
+touched.
+@item
+For tables tables with primary keys that are missing some part of the key
+in the incoming data stream, or that have no primary key, the feed is
+treated as a @code{LOAD DATA INFILE ... REPLACE INTO} is now.
+@end itemize
+@item
+Make @code{LOAD DATA INFILE} understand syntax like:
+@example
+LOAD DATA INFILE 'file_name.txt' INTO TABLE tbl_name
+ TEXT_FIELDS (text_field1, text_field2, text_field3)
+ SET table_field1=concatenate(text_field1, text_field2),
+ table_field3=23
+ IGNORE text_field3
+@end example
+This can be used to skip over extra columns in the text file,
+or update columns based on expressions of the read data...
+@item
+@code{LOAD DATA INFILE 'file_name' INTO TABLE 'table_name' ERRORS TO err_table_name}
+This would cause any errors and warnings to be logged into the
+@code{err_table_name} table. That table would have a structure like:
+
+@example
+line_number - line number in data file
+error_message - the error/warning message
+and maybe
+data_line - the line from the data file
+@end example
+@item
+Automatic output from @code{mysql} to Netscape.
+@item
+@code{LOCK DATABASES}. (with various options)
+@item
+@code{DECIMAL} and @code{NUMERIC} types can't read exponential numbers;
+@code{Field_decimal::store(const char *from,uint len)} must be recoded
+to fix this.
+@item
+Functions:
+ADD_TO_SET(value,set) and REMOVE_FROM_SET(value,set)
+@item
+Add use of @code{t1 JOIN t2 ON ...} and @code{t1 JOIN t2 USING ...}
+Currently, you can only use this syntax with @code{LEFT JOIN}.
+@item
+Many more variables for @code{show status}. Records reads and
+updated. Selects on 1 table and selects with joins. Mean number of
+tables in select. Number of @code{ORDER BY} and @code{GROUP BY} queries.
+@item
+If you abort @code{mysql} in the middle of a query, you should open
+another connection and kill the old running query.
+Alternatively, an attempt should be made to detect this in the server.
+@item
+Add a handler interface for table information so you can use it as a system
+table. This would be a bit slow if you requested information about all tables,
+but very flexible. @code{SHOW INFO FROM tbl_name} for basic table information
+should be implemented.
+@item
+@code{NATURAL JOIN}.
+@item
+Allow @code{select a from crash_me left join crash_me2 using (a)}; In this
+case @code{a} is assumed to come from the @code{crash_me} table.
+@item
+Fix that @code{ON} and @code{USING} works with the @code{JOIN}
+join type.
+@item
+Oracle like @code{CONNECT BY PRIOR ...} to search hierarchy structures.
+@item
+@code{mysqladmin copy database new-database}; Requires @code{COPY}
+command to be added to @code{mysqld}
+@item
+Processlist should show number of queries/thread.
+@item
+@code{SHOW HOSTS} for printing information about the hostname cache.
+@item
+@code{DELETE} and @code{REPLACE} options to the @code{UPDATE} statement
+(this will delete rows when one gets a duplicate key error while updating).
+@item
+Change the format of @code{DATETIME} to store fractions of seconds.
+@item
+Add all missing ANSI92 and ODBC 3.0 types.
+@item
+Change table names from empty strings to @code{NULL} for calculated columns.
+@item
+Don't use 'Item_copy_string' on numerical values to avoid
+number->string->number conversion in case of:
+@code{SELECT COUNT(*)*(id+0) FROM table_name GROUP BY id}
+@item
+Make it possible to use the new GNU regexp library instead of the current
+one (The GNU library should be much faster than the old one).
+@item
+Change that @code{ALTER TABLE} doesn't abort clients that executes
+@code{INSERT DELAYED}.
+@item
+Fix that when columns referenced in an @code{UPDATE} clause contains the old
+values before the update started.
+@item
+Add simulation of @code{pread()}/@code{pwrite()} on Windows to enable
+concurrent inserts.
+@item
+A logfile analyser that could parsed out information about which tables
+are hit most often, how often multi-table joins are executed, etc. It
+should help users identify areas or table design that could be optimised
+to execute much more efficient queries.
+@item
+Add @code{SUM(DISTINCT)}
+@item
+Add @code{ANY()},@code{EVERY()} and @code{SOME()} group functions. In
+ANSI SQL these only works on boolean columns, but we can extend these to
+work on any columns/expressions by applying: value == 0 -> FALSE and
+value <> 0 -> TRUE.
+@item
+Fix that the type for @code{MAX(column)} is the same as the column type.
+@example
+create table t1 (a DATE);
+insert into t1 values (now());
+create table t2 select MAX(a) from t1;
+show columns from t2;
+@end example
+@item
+Come up with a nice syntax for a statement that will @code{UPDATE} the row
+if it exists and @code{INSERT} a new row if the row didn't exist.
+(Like @code{REPLACE} works with @code{INSERT} / @code{DELETE})
+@end itemize
+
+
+@node TODO sometime, TODO unplanned, TODO future, TODO
+@subsection Things That Have to be Done Sometime
+
+@itemize @bullet
+@item
+Implement function: @code{get_changed_tables(timeout,table1,table2,...)}
+@item
+Change reading through tables to use memmap when possible. Now only
+compressed tables use memmap.
+@item
+Add a new privilege @strong{'Show_priv'} for @code{SHOW} commands.
+@item
+Make the automatic timestamp code nicer. Add timestamps to the update
+log with @code{SET TIMESTAMP=#;}
+@item
+Use read/write mutex in some places to get more speed.
+@item
+Full foreign key support. One probably wants to implement a procedural
+language first.
+@item
+Simple views (first on one table, later on any expression).
+@item
+Automatically close some tables if a table, temporary table or temporary files
+gets error 23 (not enough open files).
+@item
+When one finds a field=#, change all occurrences of field to #. Now this
+is only done for some simple cases.
+@item
+Change all const expressions with calculated expressions if possible.
+@item
+Optimise key = expression. At the moment only key = field or key =
+constant are optimised.
+@item
+Join some of the copy functions for nicer code.
+@item
+Change @file{sql_yacc.yy} to an inline parser to reduce its size and get
+better error messages (5 days).
+@item
+Change the parser to use only one rule per different number of arguments
+in function.
+@item
+Use of full calculation names in the order part. (For ACCESS97)
+@item
+@code{MINUS}, @code{INTERSECT} and @code{FULL OUTER JOIN}.
+(Currently @code{UNION} (in 4.0) and @code{LEFT OUTER JOIN} are supported)
+@item
+@code{SQL_OPTION MAX_SELECT_TIME=#} to put a time limit on a query.
+@item
+Make the update log to a database.
+@item
+Negative @code{LIMIT} to retrieve data from the end.
+@item
+Alarm around client connect/read/write functions.
+@item
+Please note the changes to @code{safe_mysqld}: according to FSSTND (which
+Debian tries to follow) PID files should go into @file{/var/run/<progname>.pid}
+and log files into @file{/var/log}. It would be nice if you could put the
+"DATADIR" in the first declaration of "pidfile" and "log", so the
+placement of these files can be changed with a single statement.
+@item
+Allow a client to request logging.
+@item
+Add use of @code{zlib()} for @code{gzip}-ed files to @code{LOAD DATA INFILE}.
+@item
+Fix sorting and grouping of @code{BLOB} columns (partly solved now).
+@item
+Stored procedures. Triggers are also being looked at.
+@item
+A simple (atomic) update language that
+can be used to write loops and such in the MySQL server.
+@item
+Change to use semaphores when counting threads. One should first implement
+a semaphore library to MIT-pthreads.
+@item
+Don't assign a new @code{AUTO_INCREMENT} value when one sets a column to 0.
+Use @code{NULL} instead.
+@item
+Add full support for @code{JOIN} with parentheses.
+@item
+As an alternative for one thread / connection manage a pool of threads
+to handle the queries.
+@item
+Allow one to get more than one lock with @code{GET_LOCK}. When doing this,
+one must also handle the possible deadlocks this change will introduce.
+@end itemize
+
+Time is given according to amount of work, not real time.
+
+
+@node TODO unplanned, , TODO sometime, TODO
+@subsection Things we don't Have any Plans to do
+
+@itemize @bullet
+@item
+Nothing; We aim towards full ANSI 92 / ANSI 99 compliancy.
+@end itemize
+
-This section has been written by the MySQL developers, so it
-should be read with that in mind. There are no factual errors contained
-in this section that we know of. If you find something which you believe
-to be an error, please contact us about it at @email{docs@@mysql.com}.
+@node Comparisons, , TODO, Introduction
+@section How MySQL Compares to Other Databases
-For a list of all supported limits, functions, and types, see the
-@code{crash-me} Web page at
+@cindex databases, MySQL vs. others
+@cindex comparisons, MySQL vs. others
+
+Our users have successfully run their own benchmarks against a number
+of @code{Open Source} and traditional database servers.
+We are aware of tests against @code{Oracle} server, @code{DB/2} server,
+@code{Microsoft SQL Server} and other commercial products.
+Due to legal reasons we are restricted from publishing some of those
+benchmarks in our reference manual.
+
+This section includes a comparison with @code{mSQL} for historical
+reasons and with @code{PostgreSQL} as it is also an Open Source
+database. If you have benchmark results that we can publish, please
+contact us at @email{benchmarks@@mysql.com}.
+
+For comparative lists of all supported functions and types as well
+as measured operational limits of many different database systems,
+see the @code{crash-me} web page at
@uref{http://www.mysql.com/information/crash-me.php}.
+@menu
+* Compare mSQL:: How MySQL compares to @code{mSQL}
+* Compare PostgreSQL:: How MySQL Compares to @code{PostgreSQL}
+@end menu
+
@node Compare mSQL, Compare PostgreSQL, Comparisons, Comparisons
@subsection How MySQL Compares to @code{mSQL}
+@cindex mSQL, MySQL vs mSQL, overview
@table @strong
@item Performance
For a true comparison of speed, consult the growing MySQL benchmark
suite. @xref{MySQL Benchmarks}.
-Because there is no thread creation overhead, a small parser, few features, and
-simple security, @code{mSQL} should be quicker at:
+Because there is no thread creation overhead, a small parser, few
+features, and simple security, @code{mSQL} should be quicker at:
@itemize @bullet
@item
-Tests that perform repeated connects and disconnects, running a very simple
-query during each connection.
+Tests that perform repeated connects and disconnects, running a very
+simple query during each connection.
@item
@code{INSERT} operations into very simple tables with few columns and keys.
@@ -4615,11 +4226,11 @@ query during each connection.
easy.)
@end itemize
-Because these operations are so simple, it is hard to be better at them when
-you have a higher startup overhead. After the connection is established,
-MySQL should perform much better.
+Because these operations are so simple, it is hard to be better at
+them when you have a higher startup overhead. After the connection
+is established, MySQL Server should perform much better.
-On the other hand, MySQL is much faster than @code{mSQL} (and
+On the other hand, MySQL Server is much faster than @code{mSQL} (and
most other SQL implementations) on the following:
@itemize @bullet
@@ -4627,11 +4238,11 @@ most other SQL implementations) on the following:
Complex @code{SELECT} operations.
@item
-Retrieving large results (MySQL has a better, faster, and safer
+Retrieving large results (MySQL Server has a better, faster, and safer
protocol).
@item
-Tables with variable-length strings, because MySQL has more efficient
+Tables with variable-length strings, because MySQL Server has more efficient
handling and can have indexes on @code{VARCHAR} columns.
@item
@@ -4647,23 +4258,24 @@ Handling tables with large record lengths.
@code{SELECT} on large tables.
@item
-Handling many connections at the same time. MySQL is fully
+Handling many connections at the same time. MySQL Server is fully
multi-threaded. Each connection has its own thread, which means that
no thread has to wait for another (unless a thread is modifying
-a table another thread wants to access). In @code{mSQL}, once one connection
-is established, all others must wait until the first has finished, regardless
-of whether the connection is running a query that is short or long. When the
-first connection terminates, the next can be served, while all the others wait
-again, etc.
+a table another thread wants to access). In @code{mSQL}, once one
+connection is established, all others must wait until the first has
+finished, regardless of whether the connection is running a query
+that is short or long. When the first connection terminates, the
+next can be served, while all the others wait again, etc.
@item
Joins.
-@code{mSQL} can become pathologically slow if you change the order of tables
-in a @code{SELECT}. In the benchmark suite, a time more than 15000 times
-slower than MySQL was seen. This is due to @code{mSQL}'s lack of a
-join optimizer to order tables in the optimal order. However, if you put the
-tables in exactly the right order in @code{mSQL}2 and the @code{WHERE} is
-simple and uses index columns, the join will be relatively fast!
+@code{mSQL} can become pathologically slow if you change the order of
+tables in a @code{SELECT}. In the benchmark suite, a time more than
+15000 times slower than MySQL Server was seen. This is due to @code{mSQL}'s
+lack of a join optimiser to order tables in the optimal order.
+However, if you put the tables in exactly the right order in
+@code{mSQL}2 and the @code{WHERE} is simple and uses index columns,
+the join will be relatively fast!
@xref{MySQL Benchmarks}.
@item
@@ -4681,15 +4293,16 @@ Using @code{TEXT} or @code{BLOB} columns.
@itemize @bullet
@item @code{GROUP BY} and @code{HAVING}.
@code{mSQL} does not support @code{GROUP BY} at all.
-MySQL supports a full @code{GROUP BY} with both @code{HAVING} and
+MySQL Server supports a full @code{GROUP BY} with both @code{HAVING} and
the following functions: @code{COUNT()}, @code{AVG()}, @code{MIN()},
-@code{MAX()}, @code{SUM()}, and @code{STD()}. @code{COUNT(*)} is optimized to
-return very quickly if the @code{SELECT} retrieves from one table, no other
-columns are retrieved, and there is no @code{WHERE} clause. @code{MIN()} and
-@code{MAX()} may take string arguments.
+@code{MAX()}, @code{SUM()}, and @code{STD()}. @code{COUNT(*)} is
+optimised to return very quickly if the @code{SELECT} retrieves from
+one table, no other columns are retrieved, and there is no
+@code{WHERE} clause. @code{MIN()} and @code{MAX()} may take string
+arguments.
@item @code{INSERT} and @code{UPDATE} with calculations.
-MySQL can do calculations in an @code{INSERT} or @code{UPDATE}.
+MySQL Server can do calculations in an @code{INSERT} or @code{UPDATE}.
For example:
@example
@@ -4697,49 +4310,47 @@ mysql> UPDATE SET x=x*10+y WHERE x<20;
@end example
@item Aliasing.
-MySQL has column aliasing.
+MySQL Server has column aliasing.
@item Qualifying column names.
-In MySQL, if a column name is unique among the tables used in a
+In MySQ ServerL, if a column name is unique among the tables used in a
query, you do not have to use the full qualifier.
@item @code{SELECT} with functions.
-MySQL has many functions (too many to list here; see @ref{Functions}).
+MySQL Server has many functions (too many to list here; see @ref{Functions}).
@end itemize
@item Disk Space Efficiency
That is, how small can you make your tables?
-MySQL has very precise types, so you can create tables that take
+MySQ ServerL has very precise types, so you can create tables that take
very little space. An example of a useful MySQL datatype is the
-@code{MEDIUMINT} that is 3 bytes long. If you have 100,000,000 records,
-saving even one byte per record is very important.
+@code{MEDIUMINT} that is 3 bytes long. If you have 100,000,000
+records, saving even one byte per record is very important.
@code{mSQL2} has a more limited set of column types, so it is
more difficult to get small tables.
@item Stability
-This is harder to judge objectively. For a discussion of MySQL
+This is harder to judge objectively. For a discussion of MySQL Server
stability, see @ref{Stability}.
We have no experience with @code{mSQL} stability, so we cannot say
anything about that.
@item Price
-Another important issue is the license. MySQL has a
-more flexible license than @code{mSQL}, and is also less expensive than
-@code{mSQL}. Whichever product you choose to use, remember to at least
-consider paying for a license or e-mail support. (You are required to get
-a license if you include MySQL with a product that you sell,
-of course.)
+Another important issue is the license. MySQL Server has a
+more flexible license than @code{mSQL}, and is also less expensive
+than @code{mSQL}. Whichever product you choose to use, remember to
+at least consider paying for a license or e-mail support.
@item Perl Interfaces
-MySQL has basically the same interfaces to Perl as @code{mSQL} with
+MySQL Server has basically the same interfaces to Perl as @code{mSQL} with
some added features.
@item JDBC (Java)
-MySQL currently has a lot of different JDBC drivers:
+MySQL Server currently has a lot of different JDBC drivers:
@itemize @bullet
@item
@@ -4764,14 +4375,14 @@ and educational use (not supported anymore).
@end itemize
The recommended driver is the mm driver. The Resin driver may also be
-good (at least the benchmarks looks good), but we haven't received that much
-information about this yet.
+good (at least the benchmarks looks good), but we haven't received that
+much information about this yet.
-We know that @code{mSQL} has a JDBC driver, but we have too little experience
-with it to compare.
+We know that @code{mSQL} has a JDBC driver, but we have too little
+experience with it to compare.
@item Rate of Development
-MySQL has a very small team of developers, but we are quite
+MySQL Server has a small core team of developers, but we are quite
used to coding C and C++ very rapidly. Because threads, functions,
@code{GROUP BY}, and so on are still not implemented in @code{mSQL}, it
has a lot of catching up to do. To get some perspective on this, you
@@ -4781,17 +4392,17 @@ compare it with the News section of the MySQL Reference Manual
most rapidly.
@item Utility Programs
-Both @code{mSQL} and MySQL have many interesting third-party
+Both @code{mSQL} and MySQL Server have many interesting third-party
tools. Because it is very easy to port upward (from @code{mSQL} to
-MySQL), almost all the interesting applications that are available for
-@code{mSQL} are also available for MySQL.
+MySQL Server), almost all the interesting applications that are available for
+@code{mSQL} are also available for MySQ ServerL.
-MySQL comes with a simple @code{msql2mysql} program that fixes
-differences in spelling between @code{mSQL} and MySQL for the
+MySQL Server comes with a simple @code{msql2mysql} program that fixes
+differences in spelling between @code{mSQL} and MySQL Server for the
most-used C API functions.
For example, it changes instances of @code{msqlConnect()} to
@code{mysql_connect()}. Converting a client program from @code{mSQL} to
-MySQL usually takes a couple of minutes.
+MySQL Server usually requires only minor effort.
@end table
@menu
@@ -4808,7 +4419,7 @@ MySQL usually takes a couple of minutes.
@cindex converting, tools
@cindex tools, converting
-According to our experience, it would just take a few hours to convert tools
+According to our experience, it doesn't take long to convert tools
such as @code{msql-tcl} and @code{msqljava} that use the
@code{mSQL} C API so that they work with the MySQL C API.
@@ -4816,8 +4427,8 @@ The conversion procedure is:
@enumerate
@item
-Run the shell script @code{msql2mysql} on the source. This requires the
-@code{replace} program, which is distributed with MySQL.
+Run the shell script @code{msql2mysql} on the source. This requires
+the @code{replace} program, which is distributed with MySQL Server.
@item
Compile.
@@ -4830,25 +4441,27 @@ Differences between the @code{mSQL} C API and the MySQL C API are:
@itemize @bullet
@item
-MySQL uses a @code{MYSQL} structure as a connection type (@code{mSQL}
+MySQL Server uses a @code{MYSQL} structure as a connection type (@code{mSQL}
uses an @code{int}).
@item
@code{mysql_connect()} takes a pointer to a @code{MYSQL} structure as a
-parameter. It is easy to define one globally or to use @code{malloc()} to get
-one. @code{mysql_connect()} also takes two parameters for specifying the
-user and password. You may set these to @code{NULL, NULL} for default use.
+parameter. It is easy to define one globally or to use @code{malloc()}
+to get one. @code{mysql_connect()} also takes two parameters for
+specifying the user and password. You may set these to
+@code{NULL, NULL} for default use.
@item
-@code{mysql_error()} takes the @code{MYSQL} structure as a parameter. Just add
-the parameter to your old @code{msql_error()} code if you are porting old code.
+@code{mysql_error()} takes the @code{MYSQL} structure as a parameter.
+Just add the parameter to your old @code{msql_error()} code if you are
+porting old code.
@item
-MySQL returns an error number and a text error message for all
+MySQL Server returns an error number and a text error message for all
errors. @code{mSQL} returns only a text error message.
@item
-Some incompatibilities exist as a result of MySQL supporting
+Some incompatibilities exist as a result of MySQL Server supporting
multiple connections to the server from the same process.
@end itemize
@@ -4857,10 +4470,10 @@ multiple connections to the server from the same process.
@subsubsection How @code{mSQL} and MySQL Client/Server Communications Protocols Differ
@cindex communications protocols
-@cindex mSQL vs. MySQL
+@cindex mSQL vs. MySQL, protocol
-There are enough differences that it is impossible (or at least not easy)
-to support both.
+There are enough differences that it is impossible
+(or at least not easy) to support both.
The most significant ways in which the MySQL protocol differs
from the @code{mSQL} protocol are listed below:
@@ -4871,15 +4484,15 @@ A message buffer may contain many result rows.
@item
The message buffers are dynamically enlarged if the query or the
-result is bigger than the current buffer, up to a configurable server and
-client limit.
+result is bigger than the current buffer, up to a configurable server
+and client limit.
@item
All packets are numbered to catch duplicated or missing packets.
@item
-All column values are sent in ASCII. The lengths of columns and rows are sent
-in packed binary coding (1, 2, or 3 bytes).
+All column values are sent in ASCII. The lengths of columns and rows
+are sent in packed binary coding (1, 2, or 3 bytes).
@item
MySQL can read in the result unbuffered (without having to store the
@@ -4893,10 +4506,6 @@ the connection.
If a connection is idle for 8 hours, the server closes the connection.
@end itemize
-@menu
-* Syntax differences:: How @code{mSQL} 2.0 SQL Syntax Differs from MySQL
-@end menu
-
@node Syntax differences, , Protocol differences, Compare mSQL
@subsubsection How @code{mSQL} 2.0 SQL Syntax Differs from MySQL
@@ -4905,19 +4514,21 @@ If a connection is idle for 8 hours, the server closes the connection.
@strong{Column types}
@table @code
-@item MySQL
+@item MySQL Server
Has the following additional types (among others;
@pxref{CREATE TABLE, , @code{CREATE TABLE}}):
@itemize @bullet
@item
+@c FIX bad lingo, needs rephrasing
@code{ENUM} type for one of a set of strings.
@item
+@c FIX bad lingo, needs rephrasing
@code{SET} type for many of a set of strings.
@item
@code{BIGINT} type for 64-bit integers.
@end itemize
@item
-MySQL also supports
+MySQL Server also supports
the following additional type attributes:
@itemize @bullet
@item
@@ -4951,7 +4562,7 @@ And @code{LIKE} works.
@strong{Index Creation}
@table @code
-@item MySQL
+@item MySQL Server
Indexes may be specified at table creation time with the @code{CREATE TABLE}
statement.
@item mSQL
@@ -4963,7 +4574,7 @@ Indexes must be created after the table has been created, with separate
@strong{To Insert a Unique Identifier into a Table}
@table @code
-@item MySQL
+@item MySQL Server
Use @code{AUTO_INCREMENT} as a column type
specifier.
@xref{mysql_insert_id, , @code{mysql_insert_id()}}.
@@ -4975,7 +4586,7 @@ Create a @code{SEQUENCE} on a table and select the @code{_seq} column.
@strong{To Obtain a Unique Identifier for a Row}
@table @code
-@item MySQL
+@item MySQL Server
Add a @code{PRIMARY KEY} or @code{UNIQUE} key to the table and use this.
New in Version 3.23.11: If the @code{PRIMARY} or @code{UNIQUE} key consists of only one
column and this is of type integer, one can also refer to it as
@@ -4989,7 +4600,7 @@ depending on many factors.
@strong{To Get the Time a Column Was Last Modified}
@table @code
-@item MySQL
+@item MySQL Server
Add a @code{TIMESTAMP} column to the table. This column is automatically set
to the current date and time for @code{INSERT} or @code{UPDATE} statements if
you don't give the column a value or if you give it a @code{NULL} value.
@@ -5002,20 +4613,20 @@ Use the @code{_timestamp} column.
@strong{@code{NULL} Value Comparisons}
@table @code
-@item MySQL
-MySQL follows
+@item MySQL Server
+MySQL Server follows
ANSI SQL, and a comparison with @code{NULL} is always @code{NULL}.
@item mSQL
In @code{mSQL}, @code{NULL = NULL} is TRUE. You
must change @code{=NULL} to @code{IS NULL} and @code{<>NULL} to
-@code{IS NOT NULL} when porting old code from @code{mSQL} to MySQL.
+@code{IS NOT NULL} when porting old code from @code{mSQL} to MySQL Server.
@end table
@noindent
@strong{String Comparisons}
@table @code
-@item MySQL
+@item MySQL Server
Normally, string comparisons are performed in case-independent fashion with
the sort order determined by the current character set (ISO-8859-1 Latin1 by
default). If you don't like this, declare your columns with the
@@ -5030,7 +4641,7 @@ sorting in ASCII order.
@strong{Case-insensitive Searching}
@table @code
-@item MySQL
+@item MySQL Server
@code{LIKE} is a case-insensitive or case-sensitive operator, depending on
the columns involved. If possible, MySQL uses indexes if the
@code{LIKE} argument doesn't start with a wild-card character.
@@ -5042,7 +4653,7 @@ Use @code{CLIKE}.
@strong{Handling of Trailing Spaces}
@table @code
-@item MySQL
+@item MySQL Server
Strips all spaces at the end of @code{CHAR} and @code{VARCHAR}
columns. Use a @code{TEXT} column if this behavior is not desired.
@item mSQL
@@ -5053,20 +4664,20 @@ Retains trailing space.
@strong{@code{WHERE} Clauses}
@table @code
-@item MySQL
-MySQL correctly prioritizes everything (@code{AND} is evaluated
-before @code{OR}). To get @code{mSQL} behavior in MySQL, use
+@item MySQL Server
+MySQL correctly prioritises everything (@code{AND} is evaluated
+before @code{OR}). To get @code{mSQL} behavior in MySQL Server, use
parentheses (as shown in an example below).
@item mSQL
Evaluates everything from left to right. This means that some logical
calculations with more than three arguments cannot be expressed in any
way. It also means you must change some queries when you upgrade to
-MySQL. You do this easily by adding parentheses. Suppose you
+MySQL Server. You do this easily by adding parentheses. Suppose you
have the following @code{mSQL} query:
@example
mysql> SELECT * FROM table WHERE a=1 AND b=2 OR a=3 AND b=4;
@end example
-To make MySQL evaluate this the way that @code{mSQL} would,
+To make MySQL Server evaluate this the way that @code{mSQL} would,
you must add parentheses:
@example
mysql> SELECT * FROM table WHERE (a=1 AND (b=2 OR (a=3 AND (b=4))));
@@ -5077,42 +4688,40 @@ mysql> SELECT * FROM table WHERE (a=1 AND (b=2 OR (a=3 AND (b=4))));
@strong{Access Control}
@table @code
-@item MySQL
+@item MySQL Server
Has tables to store grant (permission) options per user, host, and
database. @xref{Privileges}.
@item mSQL
Has a file @file{mSQL.acl} in which you can grant read/write privileges for
users.
-@item
@end table
@node Compare PostgreSQL, , Compare mSQL, Comparisons
-@subsection How MySQL Compares to PostgreSQL
+@subsection How MySQL Compares to @code{PostgreSQL}
@cindex PostgreSQL vs. MySQL, overview
When reading the following, please note that both products are continually
evolving. We at MySQL AB and the PostgreSQL developers are both working
on making our respective database as good as possible, so we are both a
-serious choice to any commercial database.
+serious alternative to any commercial database.
The following comparison is made by us at MySQL AB. We have tried to be
-as accurate and fair as possible, but because we don't have a full
-knowledge of all PostgreSQL features while we know MySQL througly, we
-may have got some things wrong. We will however correct these when they
-come to our attention.
-
-We would first like to note that PostgreSQL and MySQL are both widely used
-products, but with different design goals, even if we are both striving to
-be ANSI SQL compatible. This means that for some applications MySQL is
-more suited, while for others PostgreSQL is more suited. When choosing
+as accurate and fair as possible, but because while we know MySQL Server thorougly
+we don't have a full knowledge of all PostgreSQL features, so we may have
+got some things wrong. We will however correct these when they come to our
+attention.
+
+We would first like to note that PostgreSQL and MySQL Server are both widely used
+products, but with different design goals, even if we are both striving
+towards ANSI SQL compliancy. This means that for some applications MySQL Server
+is more suited, while for others PostgreSQL is more suited. When choosing
which database to use, you should first check if the database's feature set
-satisfies your application. If you need raw speed, MySQL is probably your
+satisfies your application. If you need raw speed, MySQL Server is probably your
best choice. If you need some of the extra features that only PostgreSQL
can offer, you should use @code{PostgreSQL}.
-@cindex PostgreSQL/MySQL, strategies
@menu
* MySQL-PostgreSQL goals:: MySQL and PostgreSQL development strategies
* MySQL-PostgreSQL features:: Featurewise Comparison of MySQL and PostgreSQL
@@ -5123,7 +4732,8 @@ can offer, you should use @code{PostgreSQL}.
@node MySQL-PostgreSQL goals, MySQL-PostgreSQL features, Compare PostgreSQL, Compare PostgreSQL
@subsubsection MySQL and PostgreSQL development strategies
-When adding things to MySQL we take pride to do an optimal, definite
+@cindex PostgreSQL vs. MySQL, strategies
+When adding things to MySQL Server we take pride to do an optimal, definite
solution. The code should be so good that we shouldn't have any need to
change it in the foreseeable future. We also do not like to sacrifice
speed for features but instead will do our utmost to find a solution
@@ -5139,11 +4749,11 @@ about every three weeks, and a major branch every year. All releases are
throughly tested with our testing tools on a lot of different platforms.
PostgreSQL is based on a kernel with lots of contributors. In this setup
-it makes sense to prioritize adding a lot of new features, instead of
-implementing them optimally, because one can always optimize things
+it makes sense to prioritise adding a lot of new features, instead of
+implementing them optimally, because one can always optimise things
later if there arises a need for this.
-Another big difference between MySQL and PostgreSQL is that
+Another big difference between MySQL Server and PostgreSQL is that
nearly all of the code in the MySQL server are coded by developers that
are employed by MySQL AB and are still working on the server code. The
exceptions are the transaction engines, and the regexp library.
@@ -5154,7 +4764,7 @@ It was only recently that the PostgreSQL developers announced that their
current developer group had finally had time to take a look at all
the code in the current PostgreSQL release.
-Both of the above development methods has it's own merits and drawbacks.
+Both of the above development methods have their own merits and drawbacks.
We here at MySQL AB think of course that our model is better because our
model gives better code consistency, more optimal and reusable code, and
in our opinion, fewer bugs. Because we are the authors of the MySQL server
@@ -5164,49 +4774,50 @@ code, we are better able to coordinate new features and releases.
@node MySQL-PostgreSQL features, MySQL-PostgreSQL benchmarks, MySQL-PostgreSQL goals, Compare PostgreSQL
@subsubsection Featurewise Comparison of MySQL and PostgreSQL
-@cindex PostgreSQL/MySQL, features
+@cindex PostgreSQL vs. MySQL, features
-On the @uref{http://www.mysql.com/information/crash-me.php, crash-me}
-page you can find a list of those database constructs and limits that
+On the crash-me page
+(@uref{http://www.mysql.com/information/crash-me.php})
+you can find a list of those database constructs and limits that
one can detect automatically with a program. Note however that a lot of
the numerical limits may be changed with startup options for respective
database. The above web page is however extremely useful when you want to
ensure that your applications works with many different databases or
-when you want to convert your application from one datbase to another.
+when you want to convert your application from one database to another.
-MySQL offers the following advantages over PostgreSQL:
+MySQL Server offers the following advantages over PostgreSQL:
@itemize @bullet
@item
-@code{MySQL} is generally much faster than PostgreSQL.
-@xref{MySQL-PostgreSQL benchmarks}.
+@code{MySQL} Server is generally much faster than PostgreSQL. MySQL
+4.0.1 has also a query cache that can boost up the query speed for
+mostly-read-only sites many times.
@item
-MySQL has a much larger user base than PostgreSQL, therefor the
-code is more tested and has historically been more stable than
-PostgreSQL. MySQL is the much more used in production
-environments than PostgreSQL, mostly thanks to that MySQL AB,
-formerly TCX DataKonsult AB, has provided top quality commercial support
-for MySQL from the day it was released, whereas until recently
-PostgreSQL was unsupported.
+MySQL has a much larger user base than PostgreSQL, therefore the code is
+more tested and has historically proven more stable than PostgreSQL.
+MySQL Server is more used in production environments than PostgreSQL,
+mostly thanks to that MySQL AB, formerly TCX DataKonsult AB, has
+provided top quality commercial support for MySQL Server from the day it
+was released, whereas until recently PostgreSQL was unsupported.
@item
-MySQL works better on Windows than PostgreSQL does. MySQL runs as a
-native Windows application (a service on NT/Win2000/WinXP), while
-PostgreSQL is run under the cygwin emulation. We have heard that
-PostgreSQL is not yet that stable on Windows but we haven't been able to
-verify this ourselves.
+MySQL Server works better on Windows than PostgreSQL does. MySQL Server
+runs as a native Windows application (a service on NT/Win2000/WinXP),
+while PostgreSQL is run under the @code{Cygwin} emulation. We have
+heard that PostgreSQL is not yet that stable on Windows but we haven't
+been able to verify this ourselves.
@item
MySQL has more APIs to other languages and is supported by more
existing programs than PostgreSQL. @xref{Contrib}.
@item
-MySQL works on 24/7 heavy duty systems. In most circumstances
-you never have to run any cleanups on MySQL. PostgreSQL doesn't
+MySQL Server works on 24/7 heavy duty systems. In most circumstances
+you never have to run any cleanups on MySQL Server. PostgreSQL doesn't
yet support 24/7 systems because you have to run @code{VACUUM()}
once in a while to reclaim space from @code{UPDATE} and @code{DELETE}
-commands and to perform statistics analyzes that are critical to get
+commands and to perform statistics analyses that are critical to get
good performance with PostgreSQL. @code{VACUUM()} is also needed after
adding a lot of new rows to a table. On a busy system with lots of changes,
@code{VACUUM()} must be run very frequently, in the worst cases even
@@ -5216,48 +4827,48 @@ practically dead. The PostgreSQL team has fixing this on their TODO,
but we assume that this is not an easy thing to fix permanently.
@item
-A working, tested replication feature used by sites like:
+MySQL replication has been thoroughly tested, and is used by sites like:
@itemize @minus
-@item Yahoo Finance (@uref{http://finance.yahoo.com})
+@item Yahoo Finance (@uref{http://finance.yahoo.com/})
@item Mobile.de (@uref{http://www.mobile.de/})
-@item Slashdot (@uref{http://www.slashdot.org})
+@item Slashdot (@uref{http://www.slashdot.org/})
@end itemize
@item
Included in the MySQL distribution are two different testing suites,
-@file{mysql-test-run} and
-@uref{http://www.mysql.com/information/crash-me.php,crash-me}, as well
+@file{mysql-test-run} and crash-me
+(@uref{http://www.mysql.com/information/crash-me.php}), as well
as a benchmark suite. The test system is actively updated with code to
-test each new feature and almost all repeatable bugs that have come to
-our attention. We test MySQL with these on a lot of platforms before
+test each new feature and almost all reproduceable bugs that have come to
+our attention. We test MySQL Server with these on a lot of platforms before
every release. These tests are more sophisticated than anything we have
-seen from PostgreSQL, and they ensures that the MySQL is kept to a high
+seen from PostgreSQL, and they ensures that the MySQL Server is kept to a high
standard.
@item
-There are far more books in print about MySQL than about PostgreSQL.
-O'Reilly, Sams, Que, and New Riders are all major publishers with books
+There are far more books in print about MySQL Server than about PostgreSQL.
+O'Reilly, SAMS, Que, and New Riders are all major publishers with books
about MySQL. All MySQL features are also documented in the MySQL on-line
manual, because when a new feature is implemented, the MySQL developers
are required to document it before it's included in the source.
@item
-MySQL supports more of the standard ODBC functions than @code{PostgreSQL}.
+MySQL Server supports more of the standard ODBC functions than @code{PostgreSQL}.
@item
-MySQL has a much more sophisticated @code{ALTER TABLE}.
+MySQL Server has a much more sophisticated @code{ALTER TABLE}.
@item
-MySQL has support for tables without transactions for applications that
+MySQL Server has support for tables without transactions for applications that
need all speed they can get. The tables may be memory based, @code{HEAP}
tables or disk based @code{MyISAM}. @xref{Table types}.
@item
-MySQL has support for two different table handlers that support
-transactions, @code{BerkeleyDB} and @code{InnoDB}. Because every
+MySQL Server has support for two different table handlers that support
+transactions, @code{InnoDB} and @code{BerkeleyDB}. Because every
transaction engine performs differently under different conditions, this
gives the application writer more options to find an optimal solution for
-his or her setup. @xref{Table types}.
+his or her setup, if need be per individual table. @xref{Table types}.
@item
@code{MERGE} tables gives you a unique way to instantly make a view over
@@ -5267,41 +4878,43 @@ systems where you have log files that you order for example by month.
@item
The option to compress read-only tables, but still have direct access to
-the rows in the table, gives you better performance by minimizing disk
+the rows in the table, gives you better performance by minimising disk
reads. This is very useful when you are archiving things.
@xref{myisampack}.
@item
-MySQL has internal support for fulltext search. @xref{Fulltext Search}.
+MySQL Server has internal support for fulltext search. @xref{Fulltext Search}.
@item
You can access many databases from the same connection (depending of course
on your privileges).
@item
-MySQL is coded from the start to be multi-threaded while PostgreSQL uses
-processes. Context switching and access to common storage areas is much
-faster between threads than between separate processes, this gives MySQL
-a big speed advantage in multi-user applications and also makes it easier
-for MySQL to take full advantage of symmetric multiprocessor (SMP) systems.
+MySQL Server is coded from the start to be multi-threaded while
+PostgreSQL uses processes. Context switching and access to common
+storage areas is much faster between threads than between separate
+processes, this gives MySQL Server a big speed advantage in multi-user
+applications and also makes it easier for MySQL Server to take full
+advantage of symmetric multiprocessor (SMP) systems.
@item
-MySQL has a much more sophisticated privilege system than PostgreSQL.
-While PostgreSQL only supports @code{INSERT}, @code{SELECT}, and
-@code{UPDATE/DELETE} grants per user on a database or a table, MySQL allows
-you to define a full set of different privileges on database, table and
-column level. MySQL also allows you to specify the privilege on host and
-user combinations. @xref{GRANT}.
+MySQL Server has a much more sophisticated privilege system than
+PostgreSQL. While PostgreSQL only supports @code{INSERT},
+@code{SELECT}, and @code{UPDATE/DELETE} grants per user on a database or
+a table, MySQL Server allows you to define a full set of different
+privileges on database, table and column level. MySQL Server also
+allows you to specify the privilege on host and user combinations.
+@xref{GRANT}.
@item
-MySQL supports a compressed client/server protocol which improves
+MySQL Server supports a compressed client/server protocol which improves
performance over slow links.
@item
-MySQL employs a ``table handler'' concept, and is the only relational
+MySQL Server employs a ``table handler'' concept, and is the only relational
database we know of built around this concept. This allows different
-low-level table types to be swapped into the SQL engine, and each table
-type can be optimized for different performance characteristics.
+low-level table types to be called from the SQL engine, and each table
+type can be optimised for different performance characteristics.
@item
All MySQL table types (except @strong{InnoDB}) are implemented as files
@@ -5309,26 +4922,27 @@ All MySQL table types (except @strong{InnoDB}) are implemented as files
and even symlink databases and tables, even when the server is down.
@item
-Tools to repair and optimize @strong{MyISAM} tables (the most common
+Tools to repair and optimise @strong{MyISAM} tables (the most common
MySQL table type). A repair tool is only needed when a physical corruption
of a data file happens, usually from a hardware failure. It allows a
majority of the data to be recovered.
@item
-Upgrading MySQL is painless. When you are upgrading MySQL, you don't need
-to dump/restore your data, as you have to do with most PostgreSQL upgrades.
+Upgrading MySQL Server is painless. When you are upgrading MySQL
+Server, you don't need to dump/restore your data, as you have to do with
+most PostgreSQL upgrades.
@end itemize
-Drawbacks with MySQL compared to PostgreSQL:
+Drawbacks with MySQL Server compared to PostgreSQL:
@itemize @bullet
@item
-The transaction support in MySQL is not yet as well tested as PostgreSQL's
-system.
+The transaction support in MySQL Server is not yet as well tested as
+PostgreSQL's system.
@item
-Because MySQL uses threads, which are not yet flawless on many OSes, one
-must either use binaries from @uref{http://www.mysql.com/downloads}, or
+Because MySQL Server uses threads, which are not yet flawless on many OSes, one
+must either use binaries from @uref{http://www.mysql.com/downloads/}, or
carefully follow our instructions on
@uref{http://www.mysql.com/doc/I/n/Installing_source.html} to get an
optimal binary that works in all cases.
@@ -5338,26 +4952,27 @@ Table locking, as used by the non-transactional @code{MyISAM} tables, is
in many cases faster than page locks, row locks or versioning. The
drawback however is that if one doesn't take into account how table
locks work, a single long-running query can block a table for updates
-for a long time. This can usable be avoided when designing the
+for a long time. This can usually be avoided when designing the
application. If not, one can always switch the trouble table to use one
of the transactional table types. @xref{Table locking}.
@item
-With UDF (user defined functions) one can extend MySQL with both normal
+With UDF (user defined functions) one can extend MySQL Server with both normal
SQL functions and aggregates, but this is not yet as easy or as flexible
as in PostgreSQL. @xref{Adding functions}.
@item
-Updates and deletes that run over multiple tables is harder to do in
-MySQL. This will, hoever, be fixed in MySQL 4.0 with multi-table
-@code{DELETE} and multi-table @code{UPDATE} and in MySQL 4.1
-with subselects.
+Updates that run over multiple tables is harder to do in MySQL Server.
+This will, however, be fixed in MySQL Server 4.0.2 with multi-table
+@code{UPDATE} and in MySQL Server 4.1 with subselects. In MySQL Server
+4.0 one can use multi-table deletes to delete from many tables at the
+same time. @xref{DELETE}.
@end itemize
-PostgreSQL currently offers the following advantages over MySQL:
+PostgreSQL currently offers the following advantages over MySQL Server:
Note that because we know the MySQL road map, we have included in the
-following table the version when MySQL should support this feature.
+following table the version when MySQL Server should support this feature.
Unfortunately we couldn't do this for previous comparison, because we
don't know the PostgreSQL roadmap.
@@ -5371,13 +4986,13 @@ don't know the PostgreSQL roadmap.
@item Unions @tab 4.0
@item Full join @tab 4.0 or 4.1
@item Triggers @tab 4.1
-@item Constrainst @tab 4.1
+@item Constraints @tab 4.1
@item Cursors @tab 4.1 or 4.2
@item Extensible index types like R-trees @tab R-trees are planned for 4.2
@item Inherited tables @tab Not planned
@end multitable
-Other reasons to use PostgreSQL:
+Other reasons someone may consider for using PostgreSQL:
@itemize @bullet
@item
@@ -5387,10 +5002,22 @@ Standard usage in PostgreSQL is closer to ANSI SQL in some cases.
One can speed up PostgreSQL by coding things as stored procedures.
@item
+For geographical data, R-TREES makes PostgreSQL better than MySQL Server.
+
+@item
+The PostgreSQL optimiser can do some optimisation that the current MySQL
+optimiser can't do. Most notable is doing joins when you don't have the
+proper keys in place and doing a join where you are using different keys
+combined with OR. The MySQL benchmark suite at
+@uref{http://www.mysql.com/information/benchmarks.html} shows you what
+kind of constructs you should watch out for when using different
+databases.
+
+@item
PostgreSQL has a bigger team of developers that contribute to the server.
@end itemize
-Drawbacks with PostgreSQL compared to MySQL:
+Drawbacks with PostgreSQL compared to MySQL Server:
@itemize @bullet
@item
@@ -5406,10 +5033,6 @@ Much slower @code{INSERT}, @code{DELETE}, and @code{UPDATE}.
For a complete list of drawbacks, you should also examine the first table
in this section.
-@menu
-* MySQL-PostgreSQL benchmarks:: Benchmarking MySQL and PostgreSQL
-@end menu
-
@node MySQL-PostgreSQL benchmarks, , MySQL-PostgreSQL features, Compare PostgreSQL
@subsubsection Benchmarking MySQL and PostgreSQL
@@ -5417,7 +5040,7 @@ in this section.
@cindex PostgreSQL vs. MySQL, benchmarks
The only open source benchmark that we know of that can be used to
-benchmark MySQL and PostgreSQL (and other databases) is our own. It can
+benchmark MySQL Server and PostgreSQL (and other databases) is our own. It can
be found at @uref{http://www.mysql.com/information/benchmarks.html}.
We have many times asked the PostgreSQL developers and some PostgreSQL
@@ -5455,23 +5078,23 @@ benchmark page.
Before going to the other benchmarks we know of, we would like to give
some background on benchmarks:
-It's very easy to write a test that shows ANY database to be best
+It's very easy to write a test that shows @strong{any} database to be the best
database in the world, by just restricting the test to something the
-database is very good at and not test anything that the database is not
-good at. If one after this publishes the result with a single figure,
-things are even easier.
+database is very good at and not testing anything that the database is
+not good at. If one, after doing this, summarises the result with as
+a single figure, things are even easier.
-This would be like us measuring the speed of MySQL compared to PostgreSQL
+This would be like us measuring the speed of MySQL Server compared to PostgreSQL
by looking at the summary time of the MySQL benchmarks on our web page.
-Based on this MySQL would be more than 40 times faster than PostgreSQL,
+Based on this MySQL Server would be more than 40 times faster than PostgreSQL,
something that is of course not true. We could make things even worse
by just taking the test where PostgreSQL performs worst and claim that
-MySQL is more than 2000 times faster than PostgreSQL.
+MySQL Server is more than 2000 times faster than PostgreSQL.
-The case is that MySQL does a lot of optimizations that PostgreSQL
+The case is that MySQL does a lot of optimisations that PostgreSQL
doesn't do. This is of course also true the other way around. An SQL
-optimizer is a very complex thing, and a company could spend years on
-just making the optimizer faster and faster.
+optimiser is a very complex thing, and a company could spend years on
+just making the optimiser faster and faster.
When looking at the benchmark results you should look for things that
you do in your application and just use these results to decide which
@@ -5481,24 +5104,24 @@ give you a notion about things to avoid and what you may have to do in
other ways.
We know of two benchmark tests that claims that PostgreSQL performs better
-than MySQL. These both where multi-user tests, a test that we here at
+than MySQL Server. These both where multi-user tests, a test that we here at
MySQL AB haven't had time to write and include in the benchmark suite,
mainly because it's a big task to do this in a manner that is fair against
all databases.
-One is the benchmark paid for by Great Bridge, which you can read about at:
-@uref{http://www.greatbridge.com/about/press.php?content_id=4}.
+One is the benchmark paid for by Great Bridge, the company that for 16 months
+attempted to build a business based on PostgreSQL but now has ceased
+operations. This is the probably worst benchmark we have ever seen anyone
+conduct. This was not only tuned to only test what PostgreSQL is absolutely
+best at, it was also totally unfair against every other database involved in
+the test.
-This is the probably worst benchmark we have ever seen anyone conduct. This
-was not only tuned to only test what PostgreSQL is absolutely best at, it
-was also totally unfair against every other database involved in the test.
-
-@strong{NOTE}: We know that not even some of the main PostgreSQL
-developers did like the way Great Bridge conducted the benchmark, so we
-don't blame them for the way the benchmark was made.
+@strong{Note}: We know that even some of the main PostgreSQL
+developers did not like the way Great Bridge conducted the benchmark, so we
+don't blame the PostgreSQL team for the way the benchmark was done.
This benchmark has been condemned in a lot of postings and newsgroups so
-we will here just shortly repeat some things that where wrong with it.
+we will here just shortly repeat some things that were wrong with it.
@itemize @bullet
@item
@@ -5509,11 +5132,11 @@ a true benchmark tool, but an application/setup testing tool. To refer
this as a ``standard'' benchmark tool is to stretch the truth a long way.
@item
-Great Bridge admitted that they had optimized the PostgreSQL database
+Great Bridge admitted that they had optimised the PostgreSQL database
(with @code{VACUUM()} before the test) and tuned the startup for the tests,
something they hadn't done for any of the other databases involved. To
-say ``This process optimizes indexes and frees up disk space a bit. The
-optimized indexes boost performance by some margin.'' Our benchmarks
+say ``This process optimises indexes and frees up disk space a bit. The
+optimised indexes boost performance by some margin.'' Our benchmarks
clearly indicate that the difference in running a lot of selects on a
database with and without @code{VACUUM()} can easily differ by a factor
of ten.
@@ -5539,7 +5162,7 @@ database itself.
@item
When running the database against Oracle and MS-SQL (Great Bridge has
-indirectly indicated that the databases they used in the test), they
+indirectly indicated the databases they used in the test), they
didn't use the native protocol but instead ODBC. Anyone that has ever
used Oracle knows that all real application uses the native interface
instead of ODBC. Doing a test through ODBC and claiming that the results
@@ -5552,7 +5175,7 @@ databases of course).
They refer to the TPC-C tests, but they don't mention anywhere that the
test they did was not a true TPC-C test and they were not even allowed to
call it a TPC-C test. A TPC-C test can only be conducted by the rules
-approved by the TPC Council (@uref{http://www.tpc.org}). Great Bridge
+approved by the TPC Council (@uref{http://www.tpc.org/}). Great Bridge
didn't do that. By doing this they have both violated the TPC trademark
and miscredited their own benchmarks. The rules set by the TPC Council
are very strict to ensure that no one can produce false results or make
@@ -5561,25 +5184,25 @@ doing this.
@item
After the first test, we contacted Great Bridge and mentioned to them
-some of the obvious mistakes they had done with MySQL:
+some of the obvious mistakes they had done with MySQL Server:
@itemize @minus
@item
Running with a debug version of our ODBC driver
@item
-Running on a Linux system that wasn't optimized for threads
+Running on a Linux system that wasn't optimised for threads
@item
Using an old MySQL version when there was a recommended newer one available
@item
-Not starting MySQL with the right options for heavy multi-user use (the
-default installation of MySQL is tuned for minimal resource use).
+Not starting MySQL Server with the right options for heavy multi-user use (the
+default installation of MySQL Server is tuned for minimal resource use).
@end itemize
-Great Bridge did run a new test, with our optimized ODBC driver and with
-better startup options for MySQL, but refused to either use our updated
+Great Bridge did run a new test, with our optimised ODBC driver and with
+better startup options for MySQL Server, but refused to either use our updated
glibc library or our standard binary (used by 80% of our users), which was
statically linked with a fixed glibc library.
@@ -5594,14 +5217,14 @@ only partial, chosen results (instead of publishing it all).
@end itemize
Tim Perdue, a long time PostgreSQL fan and a reluctant MySQL user
-published a comparison on
-@uref{http://www.phpbuilder.com/columns/tim20001112.php3,phpbuider}.
+published a comparison on PHPbuilder
+(@uref{http://www.phpbuilder.com/columns/tim20001112.php3}).
When we became aware of the comparison, we phoned Tim Perdue about this
because there were a lot of strange things in his results. For example,
-he claimed that MySQL had a problem with five users in his tests, when we
+he claimed that MySQL Server had a problem with five users in his tests, when we
know that there are users with similar machines as his that are using
-MySQL with 2000 simultaneous connections doing 400 queries per second.
+MySQL Server with 2000 simultaneous connections doing 400 queries per second.
(In this case the limit was the web bandwidth, not the database.)
It sounded like he was using a Linux kernel that either had some
@@ -5623,10 +5246,10 @@ He has not done that yet.
Because of this we can't put any trust in this benchmark either :(
Over time things also changes and the above benchmarks are not that
-relevant anymore. MySQL now have a couple of different table handlers
+relevant anymore. MySQL Server now has a couple of different table handlers
with different speed/concurrency tradeoffs. @xref{Table types}. It
would be interesting to see how the above tests would run with the
-different transactional table types in MySQL. PostgreSQL has of course
+different transactional table types in MySQL Server. PostgreSQL has of course
also got new features since the test was made. As the above test are
not publicly available there is no way for us to know how the
database would preform in the same tests today.
@@ -5635,7 +5258,8 @@ database would preform in the same tests today.
Conclusion:
The only benchmarks that exist today that anyone can download and run
-against MySQL and PostgreSQL is the MySQL benchmarks. We here at MySQL
+against MySQL Server and PostgreSQL is the MySQL benchmarks.
+We here at MySQL AB
believe that open source databases should be tested with open source tools!
This is the only way to ensure that no one does tests that nobody can
reproduce and use this to claim that a database is better than another.
@@ -5646,7 +5270,7 @@ The thing we find strange is that every test we have seen about
PostgreSQL, that is impossible to reproduce, claims that PostgreSQL is
better in most cases while our tests, which anyone can reproduce,
clearly shows otherwise. With this we don't want to say that PostgreSQL
-isn't good at many things (it is!) or that it isn't faster than MySQL
+isn't good at many things (it is!) or that it isn't faster than MySQL Server
under certain conditions. We would just like to see a fair test where
they are very good so that we could get some friendly competition going!
@@ -5657,499 +5281,6 @@ tests, and a better documentation of what the individual tests really
do and how to add more tests to the suite.
-@node TODO, , Comparisons, Introduction
-@section MySQL and the future (The TODO)
-
-@cindex ToDo list for MySQL
-
-@menu
-* TODO MySQL 4.0:: Things that should be in Version 4.0
-* TODO future:: Things that must be done in the near future
-* TODO sometime:: Things that have to be done sometime
-* TODO unplanned:: Some things we don't have any plans to do
-@end menu
-
-This appendix lists the features that we plan to implement in MySQL.
-
-Everything in this list is approximately in the order it will be done. If you
-want to affect the priority order, please register a license or support us and
-tell us what you want to have done more quickly. @xref{Licensing and Support}.
-
-The plan is that we in the future will support the full ANSI SQL99
-standard, but with a lot of useful extensions. The challenge is to do
-this without sacrifying the speed or compromise the code.
-
-
-@node TODO MySQL 4.0, TODO future, TODO, TODO
-@subsection Things that should be in 4.0
-
-We plan to make MySQL Version 4.0 a ``quick'' release where we only
-add some new stuff to enable others to help us with developing new features
-into Version 4.1. The MySQL 4.0 version should only take us about
-a month to make after which we want to stabilize it and start working on
-Version 4.1. Version 4.0 should have the following new features:
-
-The news section for 4.0 includes a list of the features we have already
-implemented in the 4.0 tree. @xref{News-4.0.x}.
-
-@itemize @bullet
-@item
-New table definition file format (@code{.frm} files) This will enable us
-to not run out of bits when adding more table options. One will still
-be able to use the old @code{.frm} file format with 4.0. All newly created
-tables will, however, use the new format.
-
-The new file format will enable us to add new column types, more options
-for keys and @code{FOREIGN KEY} support.
-@item
-@code{mysqld} as a library. This will have the same interface as the
-standard MySQL client (with an extra function to just set up
-startup parameters) but will be faster (no TCP/IP or socket overhead),
-smaller and much easier to use for embedded products.
-
-One will be able to define at link time if one wants to use the
-client/server model or a stand-alone application just by defining which
-library to link with.
-
-The @code{mysqld} will support all standard MySQL features and
-one can use it in a threaded client to run different queries in each
-thread.
-@item
-Replication should work with @code{RAND()} and user variables @code{@@var}.
-@item
-Online backup with very low performance penalty. The online backup will
-make it easy to add a new replication slave without taking down the
-master.
-@item
-@code{DELETE FROM table_name} will return the number of deleted rows. For
-fast execution one should use @code{TRUNCATE table_name}.
-@item
-Allow @code{DELETE} on @code{MyISAM} tables to use the record cache.
-To do this, we need to update the threads record cache when we update
-the @code{.MYD} file.
-@item
-Better replication.
-@item
-More functions for full-text search.
-@xref{Fulltext Features to Appear in MySQL 4.0}.
-@item
-Character set casts and syntax for handling multiple character sets.
-@item
-Allow users to change startup options without taking down the server.
-@item
-Help for all commands from the client.
-@item
-Secure connections (with SSL).
-@item
-Extend the optimizer to be able to optimize some @code{ORDER BY key_name DESC}
-queries.
-@item
-@code{SHOW COLUMNS FROM table_name} (used by @code{mysql} client to allow
-expansions of column names) should not open the table, but only the
-definition file. This will require less memory and be much faster.
-@item
-New key cache
-@item
-When using @code{SET CHARACTER SET} we should translate the whole query
-at once and not only strings. This will enable users to use the translated
-characters in database, table and column names.
-@item
-Add a portable interface over @code{gethostbyaddr_r()} so that we can change
-@code{ip_to_hostname()} to not block other threads while doing DNS lookups.
-@item
-Add @code{record_in_range()} method to @code{MERGE} tables to be
-able to choose the right index when there is many to choose from. We should
-also extend the info interface to get the key distribution for each index,
-of @code{analyze} is run on all sub tables.
-@item
-@code{SET SQL_DEFAULT_TABLE_TYPE=[MyISAM | INNODB | BDB | HEAP]}.
-@end itemize
-
-
-@node TODO future, TODO sometime, TODO MySQL 4.0, TODO
-@subsection Things that must be done in the real near future
-
-@itemize @bullet
-@item
-Fail safe replication.
-@item
-Subqueries.
-@code{select id from t where grp in (select grp from g where u > 100)}
-@item
-Derived tables.
-@example
-select a.col1, b.col2 from (select max(col1) as col1 from root_table ) a,
-other_table b where a.col1=b.col1
-@end example
-
-This could be done by automatically creating temporary tables for the
-derived tables for the duration of the query.
-@item
-Add @code{PREPARE} of statements and sending of parameters to @code{mysqld}.
-@item
-Extend the server/client protocol to support warnings.
-@item
-Add options to the server/protocol protocol to get progress notes
-for long running commands.
-@item
-Add database and real table name (in case of alias) to the MYSQL_FIELD
-structure.
-@item
-Don't allow more than a defined number of threads to run MyISAM recover
-at the same time.
-@item
-Change @code{INSERT ... SELECT} to optionally use concurrent inserts.
-@item
-Implement @code{RENAME DATABASE}. To make this safe for all table handlers,
-it should work as follows:
-@itemize @bullet
-@item
-Create the new database.
-@item
-For every table do a rename of the table to another database, as
-we do with the @code{RENAME} command.
-@item
-Drop the old database.
-@end itemize
-@item
-Return the original field types() when doing @code{SELECT MIN(column)
-... GROUP BY}.
-@item
-Multiple result sets.
-@item
-Change the protocol to allow binary transfer of values. To do this
-efficiently, we need to add an API to allow binding of variables.
-@item
-Make it possible to specify @code{long_query_time} with a granularity
-in microseconds.
-@item
-Add a configurable prompt to the @code{mysql} command line client, with
-options like database in use, time and date...
-@item
-Add range checking to @code{MERGE} tables.
-@item
-Link the @code{myisampack} code into the server.
-@item
-Port of MySQL to BeOS.
-@item
-Port of the MySQL clients to LynxOS.
-@item
-Add a temporary key buffer cache during @code{INSERT/DELETE/UPDATE} so that we
-can gracefully recover if the index file gets full.
-@item
-If you perform an @code{ALTER TABLE} on a table that is symlinked to another
-disk, create temporary tables on this disk.
-@item
-Implement a @code{DATE/DATETIME} type that handles time zone information
-properly, so that dealing with dates in different time zones is easier.
-@item
-FreeBSD and MIT-pthreads; Do sleeping threads take CPU?
-@item
-Check if locked threads take any CPU.
-@item
-Fix configure so that one can compile all libraries (like @code{MyISAM})
-without threads.
-@item
-Add an option to periodically flush key pages for tables with delayed keys
-if they haven't been used in a while.
-@item
-Allow join on key parts (optimization issue).
-@item
-@code{INSERT SQL_CONCURRENT} and @code{mysqld --concurrent-insert} to do
-a concurrent insert at the end of the file if the file is read-locked.
-@item
-Remember @code{FOREIGN} key definitions in the @file{.frm} file.
-@item
-Cascading @code{DELETE}
-@item
-Server side cursors.
-@item
-Check if @code{lockd} works with modern Linux kernels; If not, we have
-to fix @code{lockd}! To test this, start @code{mysqld} with
-@code{--enable-locking} and run the different fork* test suits. They shouldn't
-give any errors if @code{lockd} works.
-@item
-Allow SQL variables in @code{LIMIT}, like in @code{LIMIT @@a,@@b}.
-@item
-Allow update of variables in @code{UPDATE} statements. For example:
-@code{UPDATE TABLE foo SET @@a=a+b,a=@@a, b=@@a+c}
-@item
-Change when user variables are updated so that one can use them with
-@code{GROUP BY}, as in the following example:
-@code{SELECT id, @@a:=count(*), sum(sum_col)/@@a FROM table_name GROUP BY id}.
-@item
-Don't add automatic @code{DEFAULT} values to columns. Give an error when using
-an @code{INSERT} that doesn't contain a column that doesn't have a
-@code{DEFAULT}.
-@item
-Caching of queries and results. This should be done as a separated
-module that examines each query and if this is query is in the cache
-the cached result should be returned. When one updates a table one
-should remove as few queries as possible from the cache.
-This should give a big speed bost on machines with much RAM where
-queries are often repeated (like WWW applications).
-One idea would be to only cache queries of type:
-@code{SELECT CACHED ...}
-@item
-Fix @file{libmysql.c} to allow two @code{mysql_query()} commands in a row
-without reading results or give a nice error message when one does this.
-@item
-Optimize @code{BIT} type to take 1 bit (now @code{BIT} takes 1 char).
-@item
-Check why MIT-pthreads @code{ctime()} doesn't work on some FreeBSD systems.
-@item
-Add an @code{IMAGE} option to @code{LOAD DATA INFILE} to not update
-@code{TIMESTAMP} and @code{AUTO_INCREMENT} fields.
-@item
-Added @code{LOAD DATE INFILE.. UPDATE} syntax.
-@itemize @bullet
-@item
-For tables with primary keys, if the data contains the primary key,
-entries matching that primary key are updated from the remainder of the
-columns. However, columns MISSING from the incoming data feed are not
-touched.
-@item
-For tables tables with primary keys that are missing some part of the key
-in the incoming data stream, or that have no primary key, the feed is
-treated as a @code{LOAD DATA INFILE ... REPLACE INTO} is now.
-@end itemize
-@item
-Make @code{LOAD DATA INFILE} understand syntax like:
-@example
-LOAD DATA INFILE 'file_name.txt' INTO TABLE tbl_name
-TEXT_FIELDS (text_field1, text_field2, text_field3)
-SET table_field1=concatenate(text_field1, text_field2), table_field3=23
-IGNORE text_field3
-
-This can be used to skip over extra columns in the text file, or update columns
-based on expressions of the read data...
-@end example
-@item
-@code{LOAD DATA INFILE 'file_name' INTO TABLE 'table_name' ERRORS TO err_table_name}
-This would cause any errors and warnings to be logged into the err_table_name
-table. That table would have a structure like:
-
-@example
-line_number - line number in data file
-error_message - the error/warning message
-and maybe
-data_line - the line from the data file
-@end example
-@item
-Add true @code{VARCHAR} support (There is already support for this in MyISAM).
-@item
-Automatic output from @code{mysql} to netscape.
-@item
-@code{LOCK DATABASES}. (with various options)
-@item
-Change sort to allocate memory in ``hunks'' to get better memory utilization.
-@item
-@code{DECIMAL} and @code{NUMERIC} types can't read exponential numbers;
-@code{Field_decimal::store(const char *from,uint len)} must be recoded
-to fix this.
-@item
-Functions:
-ADD_TO_SET(value,set) and REMOVE_FROM_SET(value,set)
-@item
-Add use of @code{t1 JOIN t2 ON ...} and @code{t1 JOIN t2 USING ...}
-Currently, you can only use this syntax with @code{LEFT JOIN}.
-@item
-Add full support for @code{unsigned long long} type.
-@item
-Many more variables for @code{show status}. Counts for:
-@code{INSERT}/@code{DELETE}/@code{UPDATE} statements. Records reads and
-updated. Selects on 1 table and selects with joins. Mean number of
-tables in select. Number of @code{ORDER BY} and @code{GROUP BY} queries.
-@item
-If you abort @code{mysql} in the middle of a query, you should open
-another connection and kill the old running query.
-Alternatively, an attempt should be made to detect this in the server.
-@item
-Add a handler interface for table information so you can use it as a system
-table. This would be a bit slow if you requested information about all tables,
-but very flexible. @code{SHOW INFO FROM tbl_name} for basic table information
-should be implemented.
-@item
-Add support for UNICODE.
-@item
-@code{NATURAL JOIN} and @code{UNION JOIN}
-@item
-Allow @code{select a from crash_me left join crash_me2 using (a)}; In this
-case a is assumed to come from the crash_me table.
-@item
-Fix that @code{ON} and @code{USING} works with the @code{JOIN}
-join type.
-@item
-Oracle like @code{CONNECT BY PRIOR ...} to search hierarchy structures.
-@item
-@code{mysqladmin copy database new-database}. -- Requires COPY command to be
-added to @code{mysqld}
-@item
-Processlist should show number of queries/thread.
-@item
-@code{SHOW HOSTS} for printing information about the hostname cache.
-@item
-@code{DELETE} and @code{REPLACE} options to the @code{UPDATE} statement
-(this will delete rows when one gets a duplicate key error while updating).
-@item
-Change the format of @code{DATETIME} to store fractions of seconds.
-@item
-Add all missing ANSI92 and ODBC 3.0 types.
-@item
-Change table names from empty strings to @code{NULL} for calculated columns.
-@item
-Don't use 'Item_copy_string' on numerical values to avoid
-number->string->number conversion in case of:
-@code{SELECT COUNT(*)*(id+0) FROM table_name GROUP BY id}
-@item
-Make it possible to use the new GNU regexp library instead of the current
-one (The GNU library should be much faster than the old one).
-@item
-Change that @code{ALTER TABLE} doesn't abort clients that executes
-@code{INSERT DELAYED}.
-@item
-Fix that when columns referenced in an @code{UPDATE} clause contains the old
-values before the update started.
-@item
-@code{myisamchk}, @code{REPAIR} and @code{OPTIMIZE TABLE} should be able
-to handle cases where the data and/or index files are symbolic links.
-@item
-Add simulation of @code{pread()}/@code{pwrite()} on Windows to enable
-concurrent inserts.
-@item
-A logfile analyzer that could parsed out information about which tables
-are hit most often, how often multi-table joins are executed, etc. It
-should help users identify areas or table design that could be optimized
-to execute much more efficient queries.
-@item
-Add @code{SUM(DISTINCT)}
-@item
-Add @code{ANY()},@code{EVERY()} and @code{SOME()} group functions. In
-ANSI SQL these only works on boolean columns, but we can extend these to
-work on any columns/expressions by applying: value == 0 -> FALSE and
-value <> 0 -> TRUE.
-@item
-Fix that the type for @code{MAX(column)} is the same as the column type.
-@example
-create table t1 (a DATE);
-insert into t1 values (now());
-create table t2 select max(a) from t1;
-show columns from t2;
-@end example
-@item
-Come up with a nice syntax for a statement that will @code{UPDATE} the row
-if it exists and @code{INSERT} a new row if the row didn't exist.
-(Like @code{REPLACE} works with @code{INSERT} / @code{DELETE})
-@end itemize
-
-
-@node TODO sometime, TODO unplanned, TODO future, TODO
-@subsection Things that have to be done sometime
-
-@itemize @bullet
-@item
-Implement function: @code{get_changed_tables(timeout,table1,table2,...)}
-@item
-Atomic multi-table updates, eg @code{update items,month set
-items.price=month.price where items.id=month.id;};
-@item
-Change reading through tables to use memmap when possible. Now only
-compressed tables use memmap.
-@item
-Add a new privilege @strong{'Show_priv'} for @code{SHOW} commands.
-@item
-Make the automatic timestamp code nicer. Add timestamps to the update
-log with @code{SET TIMESTAMP=#;}
-@item
-Use read/write mutex in some places to get more speed.
-@item
-Full foreign key support. One probably wants to implement a procedural
-language first.
-@item
-Simple views (first on one table, later on any expression).
-@item
-Automatically close some tables if a table, temporary table or temporary files
-gets error 23 (not enough open files).
-@item
-When one finds a field=#, change all occurrences of field to #. Now this
-is only done for some simple cases.
-@item
-Change all const expressions with calculated expressions if possible.
-@item
-Optimize key = expression. At the moment only key = field or key =
-constant are optimized.
-@item
-Join some of the copy functions for nicer code.
-@item
-Change @file{sql_yacc.yy} to an inline parser to reduce its size and get
-better error messages (5 days).
-@item
-Change the parser to use only one rule per different number of arguments
-in function.
-@item
-Use of full calculation names in the order part. (For ACCESS97)
-@item
-@code{UNION}, @code{MINUS}, @code{INTERSECT} and @code{FULL OUTER JOIN}.
-(Currently only @code{LEFT OUTER JOIN} is supported)
-@item
-Allow @code{UNIQUE} on fields that can be @code{NULL}.
-@item
-@code{SQL_OPTION MAX_SELECT_TIME=#} to put a time limit on a query.
-@item
-Make the update log to a database.
-@item
-Negative @code{LIMIT} to retrieve data from the end.
-@item
-Alarm around client connect/read/write functions.
-@item
-Please note the changes to @code{safe_mysqld}: according to FSSTND (which
-Debian tries to follow) PID files should go into @file{/var/run/<progname>.pid}
-and log files into @file{/var/log}. It would be nice if you could put the
-"DATADIR" in the first declaration of "pidfile" and "log", so the
-placement of these files can be changed with a single statement.
-@item
-Allow a client to request logging.
-@item
-Add use of @code{zlib()} for @code{gzip}-ed files to @code{LOAD DATA INFILE}.
-@item
-Fix sorting and grouping of @code{BLOB} columns (partly solved now).
-@item
-Stored procedures. This is currently not regarded to be very
-important as stored procedures are not very standardized yet.
-Another problem is that true stored procedures make it much harder for
-the optimizer and in many cases the result is slower than before
-We will, on the other hand, add a simple (atomic) update language that
-can be used to write loops and such in the MySQL server.
-@item
-Change to use semaphores when counting threads. One should first implement
-a semaphore library to MIT-pthreads.
-@item
-Don't assign a new @code{AUTO_INCREMENT} value when one sets a column to 0.
-Use @code{NULL} instead.
-@item
-Add full support for @code{JOIN} with parentheses.
-@item
-As an alternative for one thread / connection manage a pool of threads
-to handle the queries.
-@item
-Allow one to get more than one lock with @code{GET_LOCK}. When doing this,
-one must also handle the possible deadlocks this change will introduce.
-@end itemize
-
-Time is given according to amount of work, not real time.
-
-
-@node TODO unplanned, , TODO sometime, TODO
-@subsection Some things we don't have any plans to do
-
-@itemize @bullet
-@item
-Nothing; In the long run we plan to be fully ANSI 92 / ANSI 99 compliant.
-@end itemize
-
-
-
-
@node Installing, Tutorial, Introduction, Top
@chapter MySQL Installation
@@ -6162,6 +5293,7 @@ Nothing; In the long run we plan to be fully ANSI 92 / ANSI 99 compliant.
* Post-installation:: Post-installation setup and testing
* Upgrade:: Upgrading/Downgrading MySQL
* Operating System Specific Notes:: Operating System Specific Notes
+* Perl support:: Perl Installation Comments
@end menu
This chapter describes how to obtain and install MySQL:
@@ -6174,7 +5306,7 @@ For a list of sites from which you can obtain MySQL, see
@item
To see which platforms are supported, see @ref{Which OS}. Please note that
not all supported system are equally good for running MySQL on them.
-On some it is much more robust and efficient than others - see @ref{Which OS}
+On some it is much more robust and efficient than others - see @ref{Which OS}
for details.
@item
@@ -6287,906 +5419,275 @@ installation chapter. @xref{Installing binary}.
@node Windows installation, , Linux-RPM, Quick Standard Installation
@subsection Installing MySQL on Windows
-The following instructions apply to precompiled binary distributions.
-If you download a source distribution, you will have to compile and install
-it yourself.
-
-If you don't have a copy of the MySQL distribution, you should
-first download one from @uref{http://www.mysql.com/downloads/mysql-3.23.html}.
-
-If you plan to connect to MySQL from some other program, you will
-probably also need the @strong{MyODBC} driver. You can find this at the
-@strong{MyODBC} download page
-(@uref{http://www.mysql.com/downloads/api-myodbc.html}).
-
-To install either distribution, unzip it in some empty directory and run the
-@code{Setup.exe} program.
-
-By default, MySQL-Windows is configured to be installed in
-@file{C:\mysql}. If you want to install MySQL elsewhere,
-install it in @file{C:\mysql} first, then move the installation to
-where you want it. If you do move MySQL, you must indicate
-where everything is located by supplying a @code{--basedir} option when
-you start the server. For example, if you have moved the MySQL
-distribution to @file{D:\programs\mysql}, you must start @code{mysqld}
-like this:
-
-@example
-C:\> D:\programs\mysql\bin\mysqld --basedir D:\programs\mysql
-@end example
-
-Use @code{mysqld --help} to display all the options that @code{mysqld}
-understands!
-
-With all newer MySQL versions, you can also create a
-@file{C:\my.cnf} file that holds any default options for the
-MySQL server. Copy the file @file{\mysql\my-xxxxx.cnf} to
-@file{C:\my.cnf} and edit it to suit your setup. Note that you should
-specify all paths with @samp{/} instead of @samp{\}. If you use
-@samp{\}, you need to specify it twice, because @samp{\} is the escape
-character in MySQL. @xref{Option files}.
-
-Starting with MySQL 3.23.38, the Windows distribution includes
-both the normal and the @strong{MySQL-Max} binaries. The main benefit
-of using the normal @code{mysqld.exe} binary is that it's a little
-faster and uses less resources.
-
-Here is a list of the different MySQL servers you can use:
-
-@multitable @columnfractions .25 .75
-@item @code{mysqld} @tab
-Compiled with full debugging and automatic memory allocation checking,
-symbolic links, BDB and InnoDB tables.
-@item @code{mysqld-opt} @tab
-Optimized binary with no support for transactional tables.
-@item @code{mysqld-nt} @tab
-Optimized binary for NT with support for named pipes. You can run this
-version on Win98, but in this case no named pipes are created and you must
-have TCP/IP installed.
-@item @code{mysqld-max} @tab
-Optimized binary with support for symbolic links, BDB and InnoDB tables.
-@item @code{mysqld-max-nt} @tab
-Like @code{mysqld-max}, but compiled with support for named pipes.
-@end multitable
-
-All of the above binaries are optimized for the Pentium Pro processor but
-should work on any Intel processor >= i386.
-
-NOTE: If you want to use InnoDB tables, there are certain startup
-options that must be specified in your @file{my.ini} file! @xref{InnoDB start}.
-
-
-@node General Installation Issues, Installing source, Quick Standard Installation, Installing
-@section General Installation Issues
-
-@c @node Methods of Installation, , ,
-@c @subsection Methods of Installation
-
-@c FIX: this needs to be written?
-
-@menu
-* Getting MySQL:: How to Get MySQL
-* Which OS:: Operating Systems Supported by MySQL
-* Which version:: Which MySQL Version to Use
-* Installation layouts:: Installation Layouts
-* Many versions:: How and When Updates Are Released
-* MySQL binaries:: MySQL Binaries Compiled by MySQL AB
-@end menu
-
-
-@node Getting MySQL, Which OS, General Installation Issues, General Installation Issues
-@subsection How to Get MySQL
-
-@cindex downloading
-@cindex MySQL version
-@cindex version, latest
-@cindex getting MySQL
-@cindex mirror sites
-@cindex URLS for downloading MySQL
-
-Check the @uref{http://www.mysql.com/, MySQL home page} for
-information about the current version and for downloading instructions.
-
-Our main download mirror is located at:
-
-@uref{http://download.sourceforge.net/mirrors/mysql/}
-
-If you are interested in becoming a MySQL mirror site, you may
-anonymously rsync with: @code{rsync://download.sourceforge.net/mysql/}. Please
-send e-mail to @email{webmaster@@mysql.com} notifying us of your mirror to be
-added to the list below.
-
-If you have problems downloading from our main site, try using one of the
-mirrors listed below.
-
-Please report bad or out-of-date mirrors to @email{webmaster@@mysql.com}.
-
-@c START_OF_MIRROR_LISTING
-
-@strong{Europe:}
-
-@itemize @bullet
-
-@item
-@c EMAIL: sl@iuinfo.tuwien.ac.at (Tony Sprinzl)
-@image{Flags/austria} Austria [Univ. of Technology/Vienna] @
-@uref{http://gd.tuwien.ac.at/db/mysql/, WWW}
-@uref{ftp://gd.tuwien.ac.at/db/mysql/, FTP}
-
-@c @item
-@c Not ok 20000919; Old site (Matt)
-@c EMAIL: delian@naturella.com (Delian Delchev)
-@c @image{Flags/bulgaria} Bulgaria [Naturella] @
-@c @uref{http://archive.nat.bg/pub/mirror/mysql/, WWW}
-@c @uref{ftp://ftp.ntrl.net/pub/mirror/mysql/, FTP}
-
-@item
-@c EMAIL: salle@online.bg (Admin)
-@image{Flags/bulgaria} Bulgaria [online.bg/Sofia] @
-@uref{http://mysql.online.bg/, WWW}
-@uref{ftp://mysql.online.bg/, FTP}
-
-@c @item
-@c Added: 990614
-@c Not ok 20000919; Out of date (Matt)
-@c EMAIL: vuksan@veus.hr (Vladimir Vuksan)
-@c @image{Flags/croatia} Croatia [HULK] @
-@c @uref{http://ftp.linux.hr/pub/mysql/, WWW}
-@c @uref{ftp://ftp.linux.hr/pub/mysql/, FTP}
-
-@item
-@c Added: 990614
-@c EMAIL: kas@informatics.muni.cz (Jan Kasprzak)
-@image{Flags/czech-republic} Czech Republic [Masaryk University in Brno] @
-@uref{http://mysql.linux.cz/index.html, WWW}
-@uref{ftp://ftp.fi.muni.cz/pub/mysql/, FTP}
-
-@item
-@c Added: 990920
-@c EMAIL: radek@sopik.cz (Radek Libovicky)
-@image{Flags/czech-republic} Czech Republic [www.sopik.cz] @
-@uref{http://www.mysql.cz/, WWW}
-
-@item
-@c Added: 000418
-@c EMAIL: feela@ipex.cz (Ondrej Feela Filip)
-@image{Flags/czech-republic} Czech Republic [www.gin.cz] @
-@uref{http://mysql.gin.cz/, WWW}
-@uref{ftp://ftp.gin.cz/pub/MIRRORS/www.mysql.com/, FTP}
-
-@item
-@c removed 991020 (no DNS entry). New name 991026. Added 991121
-@c Statistics at http://mirror.borsen.dk/
-@c EMAIL: guru@borsen.dk (Jesper Angelo)
-@image{Flags/denmark} Denmark [Borsen] @
-@uref{ http://mysql.borsen.dk/, WWW}
-
-@item
-@c EMAIL: mkp@socsci.auc.dk (Martin Kasper Petersen)
-@image{Flags/denmark} Denmark [SunSITE] @
-@uref{http://mirrors.sunsite.dk/mysql/, WWW}
-@uref{ftp://sunsite.dk/mirrors/mysql/, FTP}
-
-@c @item
-@c Tõnu does not work there anymore :-) 990720
-@c EMAIL: tonu@tradenet.ee (Tõnu Samuel)
-@c @image{Flags/estonia} Estonia [Tradenet] @
-@c @uref{http://mysql.tradenet.ee, WWW}
-
-@item
-@c EMAIL: tonu@spam.ee (Tõnu Samuel)
-@image{Flags/estonia} Estonia [OKinteractive] @
-@uref{http://mysql.mirror.ok.ee, WWW}
-
-@c @item
-@c Changed 990531
-@c Not ok 20000919; Old site (Matt)
-@c EMAIL: Steeve.Devergne@minet.net (Steeve Devergne)
-@c @image{Flags/france} France [minet] @
-@c @uref{http://www.minet.net/devel/mysql/, WWW}
-
-@item
-@c EMAIL: alex@mtesa.net (Alexandre Dupouy)
-@image{Flags/france} France [mtesa.net] @
-@uref{http://mysql.mtesa.net/, WWW}
-
-@item
-@c EMAIL: mrjack@fastorama.com (MrJacK)
-@image{Flags/france} France [fastorama.com, Chatenois] @
-@uref{http://mysql.fastorama.com/, WWW}
-@uref{ftp://ftp.fastorama.com/unix/mysql/, FTP}
-
-@c @item
-@c Not ok 20000919; Old site (Matt)
-@c EMAIL: Jaakko.Hyvatti@eunet.fi
-@c @image{Flags/finland} Finland [EUnet] @
-@c @uref{http://mysql.eunet.fi/, WWW}
-
-@c @item
-@c Added 990829
-@c Not ok 20000919; Non-existent (Matt)
-@c EMAIL: tomi.hakala@clinet.fi (Tomi Hakala)
-@c @image{Flags/finland} Finland [clinet] @
-@c @uref{ftp://ftp.clinet.fi/mirrors/ftp.mysql.org/pub/mysql/, FTP}
-
-@item
-@c Added 20001019
-@c EMAIL: d@d.tj (Dominique L . Bouix)
-@image{Flags/finland} Finland [tonnikala.net] @
-@uref{http://mysql.tonnikala.org/, WWW}
-
-@item
-@c Added 981208
-@c EMAIL: noel@uni-bonn.de (Noel Koethe)
-@image{Flags/germany} Germany [Kernelnotes.de, Bonn] @
-@uref{http://www.kernelnotes.de/mysql/, WWW}
-@uref{ftp://ftp.kernelnotes.de/pub/mirror/mysql.org/, FTP}
-
-@item
-@c EMAIL: th@rz.fh-wolfenbuettel.de (Thorsten Ludewig)
-@image{Flags/germany} Germany [Wolfenbuettel] @
-@uref{http://www.fh-wolfenbuettel.de/ftp/pub/database/mysql/, WWW}
-@uref{ftp://ftp.fh-wolfenbuettel.de/pub/database/mysql/, FTP}
-
-@c @item
-@c Ok 980114. Removed 981208 (down > 3 days) ok 981214
-@c Not ok 20000919; Non-existent (Matt)
-@c EMAIL: straub@gks.de (Hans-Peter Straub)
-@c @image{Flags/germany} Germany [Staufen] @
-@c @uref{http://mysql.staufen.de/, WWW}
-
-@c @item
-@c Added 990614
-@c Not ok 20000919; Non-existent (Matt)
-@c EMAIL: thomas.rohde@ecrc.de (Thomas Rohde)
-@c @image{Flags/germany} Germany [Cable & Wireless] @
-@c @uref{ftp://ftp.ecrc.net/pub/database/mysql/, FTP}
-
-@item
-@c Added 981208
-@c EMAIL: christias@noc.ntua.gr (Panagiotis Christias)
-@image{Flags/greece} Greece [NTUA, Athens] @
-@uref{http://www.ntua.gr/mysql/, WWW}
-@uref{ftp://ftp.ntua.gr/pub/databases/mysql/, FTP}
-
-@item
-@c EMAIL: torlasz@xenia.sote.hu (Laszlo L. Tornoc)
-@image{Flags/hungary} Hungary [Xenia] @
-@uref{http://mysql.sote.hu/, WWW}
-@uref{ftp://xenia.sote.hu/pub/mirrors/www.mysql.com/, FTP}
-
-@item
-@c EMAIL: hendlein@tiszanet.hu (Hendlein Peter)
-@image{Flags/hungary} Hungary [TiszaneT] @
-@uref{http://mysql.tiszanet.hu/, WWW}
-@uref{ftp://mysql.tiszanet.hu/pub/mirrors/mysql/, FTP}
-
-@item
-@c EMAIL: i.habencius@telnet.hu (Habencius Istvan)
-@image{Flags/hungary} Hungary [stop.hu] @
-@uref{http://mysql.mirror.stop.hu/, WWW}
-
-@item
-@c EMAIL: mirrors@gm.is (Tomas Edwardsson)
-@image{Flags/iceland} Iceland [GM] @
-@uref{http://mysql.gm.is/, WWW}
-@uref{ftp://ftp.gm.is/pub/mysql/, FTP}
-
-@c @item
-@c Out of date 990906
-@c EMAIL: bourbon@netvision.net.il (Zeev Suraski)
-@c @image{Flags/israel} Israel [Netvision] @
-@c @uref{http://mysql.netvision.net.il/, WWW}
-
-@c @item
-@c Not working 99.03.06
-@c EMAIL: maruzz@matrice.it (Giovanni Maruzzelli)
-@c @image{Flags/italy} Italy [Matrice] @
-@c @uref{http://www.matrice.it/risorse/mysql/, WWW}
-
-@item
-@c EMAIL: gabriele@feelinglinux.com (Giansante Gabriele)
-@image{Flags/italy} Italy [feelinglinux.com] @
-@uref{http://mysql.feelinglinux.com/, WWW}
-
+The MySQL server for Windows is available in two distribution types:
+@enumerate
@item
-@c EMAIL: irena@yacc.it
-@image{Flags/italy} Italy [Teta Srl] @
-@uref{http://www.teta.it/mysql/, WWW}
-
+The binary distribution contains a setup program which installs
+everything you need so you can start the server immediately.
@item
-@c EMAIL: rudy@comm2000.it (Rudy)
-@image{Flags/italy} Italy [tzone.it] @
-@uref{http://mysql.tzone.it/, WWW}
+The source distribution contains all the code and support files
+for building the executables using the VC++ 6.0 compiler.
+@xref{Windows source build}.
+@end enumerate
-@c @item
-@c Added 991121
-@c Not ok 20000919; Old site (Matt)
-@c EMAIL: nick@iol.ie (Nick Hilliard)
-@c @image{Flags/ireland} Ireland [Ireland On-Line/Dublin] @
-@c @uref{http://mysql.iol.ie, WWW}
-@c @uref{ftp://ftp.iol.ie/pub/mysql, FTP}
+Generally speaking, you should use the binary distribution.
+You will need the following:
+@itemize @bullet
@item
-@c Added 20001031
-@c EMAIL: dave@esat.net (Dave Rynne)
-@image{Flags/ireland} Ireland [Esat Net] @
-@uref{http://ftp.esat.net/mirrors/download.sourceforge.net/pub/mirrors/mysql/, WWW}
-@uref{ftp://ftp.esat.net/mirrors/download.sourceforge.net/pub/mirrors/mysql/, FTP}
+A Windows 32 bits Operational System of the family Win9x, ME,
+NT and Win 2000. The NT family permits running the MySQL server
+as a service. @xref{NT start}.
+If you want to use tables bigger than 4G, you should install MySQL
+on NTFS or newer file system. Don't forget to use @code{MAX_ROWS} and
+@code{AVG_ROW_LENGTH} when you create the table. @xref{CREATE TABLE}.
@item
-@c Added 20010524
-@c EMAIL: arvids@parks.lv (Arvids)
-@image{Flags/latvia} Latvia [linux.lv] @
-@uref{ftp://ftp.linux.lv/pub/software/mysql/, FTP}
-
+TCP/IP protocol support.
@item
-@c Added 20001125
-@c EMAIL: mleicher@silverpoint.nl (Marcel Leicher)
-@image{Flags/netherlands} Netherlands [Silverpoint] @
-@uref{http://mysql.silverpoint.nl/, WWW}
+A copy of the MySQL binary or distribution for Windows, which
+can be downloaded from @uref{http://www.mysql.com/downloads/}.
+Note: The distribution files are supplied with a zipped format
+and we recommended the use of an adequate FTP client with resume
+feature to avoid corruption of files during the download process.
@item
-@c EMAIL: mysql@widexs.nl (Wouter de Jong)
-@image{Flags/netherlands} Netherlands [Widexs BV] @
-@uref{http://mysql.widexs.nl/, WWW}
-@uref{ftp://mysql.widexs.nl/pub/mysql/, FTP}
-
+A @code{ZIP} program to unpacked the distribution file.
@item
-@c EMAIL: peter@proserve.nl (ProServe - Peter Batenburg)
-@image{Flags/netherlands} Netherlands [ProServe] @
-@uref{http://mysql.proserve.nl/, WWW}
-
+Enough space on the hard drive to unpack, install and to create the
+databases in accorandance with your requirements.
@item
-@c EMAIL: W.Sylwestrzak@icm.edu.pl (Wojtek Sylwestrzak)
-@c mirroring nightly at 05:25
-@image{Flags/poland} Poland [Sunsite] @
-@uref{http://sunsite.icm.edu.pl/mysql/, WWW}
-@uref{ftp://sunsite.icm.edu.pl/pub/unix/mysql/, FTP}
+If you plan to connect to the MySQL server via @code{ODBC}, you
+will also need the @code{MyODBC} driver. @xref{ODBC}.
+@end itemize
-@item
-@c EMAIL: admin@net.ncservice.com.pl (Marian Witkowski)
-@image{Flags/poland} Poland [ncservice.com/Gdansk] @
-@uref{http://mysql.service.net.pl/, WWW}
-@c @item
-@c EMAIL: melo@co.telenet.pt (Pedro Melo)
-@c Temp out of service (email from Pedro)
-@c @image{Flags/portugal} Portugal [IP] @
-@c @uref{http://mysql.ip.pt, WWW}
+@menu
+* Windows binary installation:: Installing the Binaries
+* Windows prepare environment:: Preparing the Windows MySQL Environment
+* Windows server first start:: Starting the Server for the First Time
+@end menu
-@c @item
-@c Not ok 20000919; Non-existent (Matt)
-@c EMAIL: support@leirianet.pt (Equipa de suporte do Leirianet)
-@c @image{Flags/portugal} Portugal [lerianet] @
-@c @uref{http://mysql.leirianet.pt, WWW}
-@c @uref{ftp://ftp.leirianet.pt/pub/mysql/,FTP}
-
-@item
-@c Added 20001031
-@c bofh@netc.pt (Bruno Rodrigues)
-@image{Flags/portugal} Portugal [Netc] @
-@uref{http://ftp.netc.pt/pub/mysql/, WWW}
-@uref{ftp://ftp.netc.pt/pub/mysql/, FTP}
-
-@item
-@c EMAIL: keeper@roedu.net (Mihai RUSU)
-@image{Flags/romania} Romania [roedu.net/Bucharest] @
-@uref{ftp://ftp.roedu.net/pub/mirrors/ftp.mysql.com/, FTP}
+@node Windows binary installation, Windows prepare environment, Windows installation, Windows installation
+@subsubsection Installing the Binaries
+@enumerate
@item
-@c EMAIL: kuzmin@dn.ru (Roma Kuzmin)
-@image{Flags/russia} Russia [DirectNet] @
-@uref{http://mysql.directnet.ru/, WWW}
-@uref{ftp://ftp.dn.ru/pub/MySQL/, FTP}
-
-@c @item
-@c down 990113
-@c EMAIL: nikkic@cityline.ru (Nikki Chumakov)
-@c @image{Flags/russia} Russia [Cityline] @
-@c @uref{ftp://mysql.cityline.ru/pub/mysql, FTP}
-@c @uref{http://mysql.cityline.ru, WWW}
-@c EMAIL: bar@izhcom.ru (Alexander I Barkov)
-
-@c @item
-@c Not ok 20000919; Non-existent (Matt)
-@c @image{Flags/russia} Russia [IZHCOM] @
-@c @uref{http://mysql.udm.net/, WWW}
-@c @uref{ftp://ftp.izhcom.ru/pub/mysql/,FTP}
-
+If you are working on an NT or Win2000 server, logon as a user with
+with administrator privileges.
@item
-@c Added 990507
-@c EMAIL: demon@gpad.ac.ru (Dima Sivachenko)
-@image{Flags/russia} Russia [Scientific Center/Chernogolovka] @
-@uref{ftp://ftp.chg.ru/pub/databases/mysql/, FTP}
-
-@c @item
-@c Not ok 20000919; Old site (Matt)
-@c EMAIL: sebi@dnttm.ro (Sebastian DEAC)
-@c @image{Flags/romania} Romania [Timisoara] @
-@c @uref{http://download.dnttm.ro/mysql, WWW}
-@c @uref{ftp://ftp.dnttm.ro/pub/mysql, FTP}
+If you are doing an upgrade of an earlier MySQL installation,
+it is necessary to stop the server. If you are running the server
+as a service, use:
-@c @item
-@c Not ok 20001123; Non-existent (Matt)
-@c EMAIL: tim@lbi.ro (Bogdan Surdu)
-@c @image{Flags/romania}
-@c Romania [Bucharest] @
-@c @uref{http://www.lbi.ro/MySQL/, WWW}
-@c @uref{ftp://ftp.lbi.ro/mirrors/ftp.tcx.se, FTP}
+@example
+C:\> NET STOP MySQL
+@end example
-@c @item
-@c Removed 20000521 because there is no mirror here.
-@c EMAIL: jips@masterd.es (Juan Ignacio Pérez Sacristán)
-@c @image{Flags/spain} Spain [MasterD]
-@c @uref{http://mysql.masterd.es, WWW}
+Otherwise, use:
-@item
-@c EMAIL: Patrik.Karen@sdi.slu.se (Patrik Karen)
-@c ftp -> remove old files
-@image{Flags/sweden} Sweden [Sunet] @
-@uref{http://ftp.sunet.se/pub/unix/databases/relational/mysql/, WWW}
-@uref{ftp://ftp.sunet.se/pub/unix/databases/relational/mysql/, FTP}
+@example
+C:\mysql\bin> mysqladmin -u root shutdown
+@end example
@item
-@c EMAIL: archive@sunsite.cnlab-switch.ch (Thomas Lenggenhager)
-@image{Flags/switzerland} Switzerland [Sunsite] @
-@uref{http://sunsite.cnlab-switch.ch/ftp/mirror/mysql/, WWW}
-@uref{ftp://sunsite.cnlab-switch.ch/mirror/mysql/, FTP}
+On NT/Win2000 machines, if you want to change the server executable
+(e.g. -max or -nt), it is also necessary to remove the service:
-@c @item
-@c Not ok 20000919; Non-existent (Matt)
-@c simon@oyster.co.uk (Simon Gornall)
-@c @image{Flags/great-britain} UK [Oyster/UK] @
-@c @uref{ftp://ftp.oyster.co.uk/pub/mysql, FTP}
-
-@item
-@c EMAIL: keet@mordor.plig.net (Christiaan Keet)
-@image{Flags/great-britain} UK [PLiG/UK] @
-@uref{http://ftp.plig.org/pub/mysql/, WWW}
-@uref{ftp://ftp.plig.org/pub/mysql/, FTP}
-
-@c @item
-@c Not ok 20010808; Non-existent (Matt)
-@c EMAIL: sean@telekon.co.uk (Sean Gibson)
-@c @image{Flags/great-britain} UK [Telekon Internet/UK] @
-@c @uref{ftp://ftp.telekon.co.uk/pub/mysql/, FTP}
-
-@c @item
-@c lance@uklinux.net (Lance)
-@c @image{Flags/great-britain} UK [uklinux.net] @
-@c @uref{http://mirror.uklinux.net/mysql/, WWW}
-@c @uref{ftp://mirror.uklinux.net/pub/mysql/, FTP}
-
-@c @item
-@c unknown
-@c @image{Flags/great-britain} UK [MicroMuse] @
-@c @uref{ftp://ftp.micromuse.co.uk/pub/packages/unix/databases/mysql/, FTP}
-
-@c @item
-@c Not ok 20000919; Old site (Matt)
-@c lmjm@icparc.ic.ac.uk (Lee McLoughlin)
-@c @image{Flags/great-britain} UK [SunSITE] @
-@c @uref{http://sunsite.org.uk/packages/mysql/, WWW}
-@c @uref{ftp://sunsite.org.uk/packages/mysql/, FTP}
-
-@item
-@c EMAIL: sander@paco.net (Alexander Ivanov)
-@image{Flags/ukraine} Ukraine [PACO] @
-@uref{http://mysql.paco.net.ua, WWW}
-@uref{ftp://mysql.paco.net.ua/, FTP}
-
-@item
-@c EMAIL: mizi@alkar.net (Alexander Ryumshin)
-@image{Flags/ukraine} Ukraine [ISP Alkar Teleport/Dnepropetrovsk] @
-@uref{http://mysql.dp.ua/, WWW}
-
-@item
-@c EMAIL: bole@bolex.bolex.co.yu (Bosko Radivojevic)
-@image{Flags/yugoslavia} Yugoslavia [bolex.co.yu] @
-@uref{http://mysql.boa.org.yu/, WWW}
-@uref{ftp://ftp.linux.org.yu/pub/MySQL/, FTP}
-
-@end itemize
-
-@strong{North America:}
-
-@itemize @bullet
-@c @item
-@c Not ok 990101 (only to 981007)
-@c EMAIL: sysop@polarcom.com (Seamus Venasse)
-@c @image{Flags/canada} Canada [Polaris Computing] @
-@c @uref{http://mysql.polaris.ca/, WWW}
-
-@item
-@c Ok 980109
-@c EMAIL: wojtek@tryc.on.ca (Wojtjeck Tryc)
-@image{Flags/canada} Canada [Tryc] @
-@uref{http://web.tryc.on.ca/mysql/, WWW}
-
-@c @item
-@c not updated 990218. Added again 990918
-@c Not ok 20000919; Non-existent (Matt)
-@c EMAIL: rhooper@cyberus.ca (Roy Hooper)
-@c @image{Flags/canada} Canada [Cyberus] @
-@c @uref{http://mysql.cyberus.ca/, WWW}
-@c @uref{ftp://mysql.cyberus.ca/, FTP}
-
-@item
-@c EMAIL: mleber@he.net (Mike Leber)
-@c Added 980312
-@image{Flags/usa} USA [Hurricane Electric/San Jose] @
-@uref{http://mysql.he.net/, WWW}
+@example
+C:\mysql\bin> mysqld-max-nt --remove
+@end example
@item
-@c EMAIL: ask@valueclick.com (Ask Bjoern Hansen)
-@c Added 20000925
-@image{Flags/usa} USA [ValueClick, Los Angeles CA] @
-@uref{http://mysql.valueclick.com/, WWW}
-@uref{ftp://mysql.valueclick.com/pub/mysql/Downloads/, FTP}
-
-@c @item
-@c Not ok 20000919; Non-existent (Matt)
-@c EMAIL: meltzer@icsnet.com (Jeffrey Meltzer)
-@c Added 000108
-@c @image{Flags/usa} USA [Meltzer/New York State] @
-@c @uref{ftp://ftp.meltzer.org/pub/mysql/, FTP}
-
-@c @item
-@c No such directory 990830
-@c EMAIL: tps@users.buoy.com (Tim Sailer)
-@c @image{Flags/usa} USA [Buoy/New York] @
-@c @uref{http://www.buoy.com/mysql/, WWW}
-
-@c @item
-@c EMAIL: db@hpnc.com (Douglas Bowyer)
-@c Added 980107, removed 981124 because of 'file not found'
-@c @image{Flags/usa} USA [Hypernet Communications/Dallas] @
-@c @uref{http://epsilon.hpnc.com/mysql, WWW}
-
-@c @item @c **********************************
-@c Not updated 980106
-@c EX: twh@iquest.net (Thomas Holt) who no longer works there
-@c @image{Flags/usa} USA [IQuest/Indiana] @
-@c @uref{http://mirrors.iquest.net/mysql/, WWW}
-
-@c @item @c **********************************
-@c Only a partial mirror so we exclude it from the list
-@c EX: lindberg@id.wustl.edu (Fred Lindberg)
-@c @image{Flags/usa} USA [Washington University/St. Louis] @
-@c @uref{ftp://ftp.id.wustl.edu/pub/database/mysql/, FTP}
-
-@c removed 991111 -> no answer
-@c @item
-@c EMAIL: andrew@netcasting.net (Andrew Sawyers)
-@c @image{Flags/usa} USA [Netcasting/West Coast] @
-@c @uref{ftp://ftp.netcasting.net/pub/mysql/, FTP}
-
-@c @item
-@c No mirror! 980809 David
-@c EMAIL: savages@savages.com (Shaun Savage)
-@c @image{Flags/usa} USA [Savages/Oregon] @
-@c @uref{http://mysql.savages.com, WWW}
-
-@c @item
-@c Not ok 20000919; Non-existent (Matt)
-@c EMAIL: paul@gina.net (Paul Vining)
-@c mirrors ftp.sunet.se
-@c @image{Flags/usa} USA [Gina net/Florida] @
-@c @uref{http://www.gina.net/mysql/, WWW}
-
-@c Out of date 2000-01-08 (Not updated since 1999-10)
-@c @item
-@c EMAIL: wswanson@pingzero.net (Wylie Swanson)
-@c mirrors mysql.org
-@c @image{Flags/usa} USA [pingzero/Los Angeles] @
-@c @uref{http://mysql.pingzero.net/, WWW}
-
+Unzip the distribution file to a temporary directory.
@item
-@c EMAIL: ftpkeeper@mirror.sit.wisc.edu
-@image{Flags/usa} USA [Wisconsin University/Wisconsin] @
-@uref{http://mirror.sit.wisc.edu/mysql/, WWW}
-@uref{ftp://mirror.sit.wisc.edu/mirrors/mysql/, FTP}
-
-@c @item
-@c Not ok 20000919; Out of date (Matt)
-@c EMAIL: ftp-admin@digex.net
-@c @image{Flags/usa} USA [DIGEX] @
-@c @uref{ftp://ftp.digex.net/pub/packages/database/mysql/, FTP}
-
+Run the @file{setup.exe} file to begin the installation process.
+If you want to install into another directory than the default
+@file{c:\mysql}, use the @code{Browse} button to specify your
+preferred directory.
@item
-@c EMAIL: andrew.sawyers@thelinuxstore.com
-@image{Flags/usa} USA [LinuxWired/Scottsdale, AZ] @
-@uref{http://mysql.linuxwired.net/, WWW}
-@uref{ftp://ftp.linuxwired.net/pub/mirrors/mysql/, FTP}
-
-@c @item
-@c EMAIL: dan@surfsouth.com (Dan Muntz)
-@c @image{Flags/usa} USA [Venoma.Org/Valdosta, GA] @
-@c @uref{http://mysql.venoma.org/, WWW}
+Finish the install process.
+@end enumerate
-@item
-@c EMAIL: hkind@adgrafix.com (Hans Kind)
-@image{Flags/usa} USA [adgrafix.com/Boston, MA] @
-@uref{http://mysql.adgrafix.com/, WWW}
-@item
-@c EMAIL: Pjacob@netnumina.com (Philip Jacob)
-@image{Flags/usa} USA [netNumina/Cambridge, MA] @
-@uref{http://mysql.mirrors.netnumina.com/, WWW}
+@node Windows prepare environment, Windows server first start, Windows binary installation, Windows installation
+@subsubsection Preparing the Windows MySQL Environment
-@item
-@c EMAIL: hagler@ahaza.com (Mark Hagler)
-@image{Flags/usa} USA [Ahaza Systems/Seattle, WA] @
-@uref{http://mysql.mirrortree.com/, WWW}
-@uref{ftp://mysql.mirrortree.com/pub/mysql/, FTP}
+Starting with MySQL 3.23.38, the Windows distribution includes
+both the normal and the @strong{MySQL-Max} server binaries.
+Here is a list of the different MySQL servers you can use:
-@end itemize
+@multitable @columnfractions .25 .75
+@item @strong{Binary} @tab @strong{Description}
+@item @code{mysqld} @tab
+Compiled with full debugging and automatic memory allocation
+checking, symbolic links, InnoDB and BDB tables.
+@item @code{mysqld-opt} @tab
+Optimised binary with no support for transactional tables.
+@item @code{mysqld-nt} @tab
+Optimised binary for NT with support for named pipes. You can
+run this version on Win98, but in this case no named pipes are
+created and you must have TCP/IP installed.
+@item @code{mysqld-max} @tab
+Optimised binary with support for symbolic links,
+InnoDB and BDB tables.
+@item @code{mysqld-max-nt} @tab
+Like @code{mysqld-max}, but compiled with support for named
+pipes.
+@end multitable
-@strong{South America:}
+All of the above binaries are optimised for the Pentium Pro
+processor but should work on any Intel processor >= i386.
+In the following circumstances you will need to use the MySQL
+configuration file:
@itemize @bullet
-
@item
-@c Added 20001102
-@c EMAIL: nico@bannerlandia.com (Nicolas Moldavsky)
-@image{Flags/argentina} Argentina [bannerlandia.com] @
-@uref{http://mysql.bannerlandia.com.ar/, WWW}
-@uref{ftp://mysql.bannerlandia.com.ar/mirrors/mysql/, FTP}
-
-@c @item
-@c Not ok 20000919; Non-existent (Matt)
-@c EMAIL: gaiser@matrix.com.br (Roberto Gaiser)
-@c @image{Flags/brazil} Brazil [Matrix] @
-@c @uref{http://mysql.matrix.com.br, WWW}
-
+The install/data directories are different than the default
+@file{c:\mysql} and @file{c:\mysql\data}.
@item
-@c jpabuyer@vision.cl
-@image{Flags/chile} Chile [Vision] @
-@uref{http://mysql.vision.cl/, WWW}
-
-@item
-@c EMAIL: bartschm@psi.com (Marcelo Bartsch)
-@image{Flags/chile} Chile [PSINet] @
-@uref{http://mysql.psinet.cl/, WWW}
-@uref{ftp://ftp.psinet.cl/pub/database/mysql/, FTP}
-
+If you want to use one of the these servers:
+@itemize @bullet
+@item mysqld.exe
+@item mysqld-max.exe
+@item mysqld-max-nt.exe
+@end itemize
@item
-@c EMAIL: jpabuyer@tecnoera.com (Juan Pablo Abuyeres)
-@image{Flags/chile} Chile [Tecnoera] @
-@uref{http://mysql.tecnoera.com/, WWW}
-
-@c @item
-@c Removed 990730
-@c @c EMAIL: dan@amerikanclaris.com (Danilo Lotina F.)
-@c @image{Flags/chile} Chile [Amerikanclaris] @
-@c @uref{http://www.labs.amerikanclaris.cl/mysql, WWW}
-@c @uref{ftp://ftp.amerikanclaris.cl/pub/mysql, FTP}
+If you need to tune the server settings.
@end itemize
-@strong{Asia:}
+Normally you can use the @code{WinMySQLAdmin} tool to edit the
+configuration file @code{my.ini}. In this case you don't have to worry
+about the following section.
-@itemize @bullet
-@c @item
-@c Host cannot be resolved for last week at least 20010809 Tonu
-@c EMAIL: mirnshi@263.net (Meng Lingbo)
-@c @image{Flags/china} China [Freecode] @
-@c @uref{http://www.freecode.net.cn/mirror/mysql/, WWW}
+There are two configuration files with the same function: @file{my.cnf}
+and @file{my.ini} file, however please note that only of one these
+should be used to avoid confusion. Both files are plain text. The
+@file{my.cnf} file , if used, should be created in the root directory of
+drive C and the @file{my.ini} file on the WinDir directory e.g:
+@file{C:\WINDOWS} or @file{C:\WINNT}. MySQL will first read the
+@code{my.ini} file, followed by the @code{my.cnf} file.
-@item
-@c EMAIL: yusun@atwell.co.jp (yu sun)
-@image{Flags/china} China [linuxforum.net] @
-@uref{http://www2.linuxforum.net/mirror/mysql/, WWW}
-
-@item
-@c EMAIL: vfong@hklpg.org (Vincent Fong)
-@image{Flags/china} China [HKLPG/Hong Kong] @
-@uref{http://mysql.hklpg.org, WWW}
+If your PC uses a boot loader where the C drive isn't the boot drive,
+then your only option is to use the @file{my.ini} file. Also note that
+if you use the @code{WinMySQLAdmin} tool, only the @file{my.ini} file is
+used by this tool. The @file{\mysql\bin} directory contains a help file
+with instructions for using this tool.
-@item
-@c EMAIL: jason-wong@gremlins.com.hk (Gremlins Jason Wong)
-@image{Flags/china} China [Gremlins/Hong Kong] @
-@uref{http://mysql.gremlins.com.hk/, WWW}
-@uref{ftp://ftp.mirrors.gremlins.com.hk/mysql/, FTP}
+Using @code{notepad.exe}, create the configuration file and
+edit the base section and keys:
-@item
-@c EMAIL: shell@linux.org.hk (Shell Hung)
-@image{Flags/china} China [shellhung.org/Hong Kong] @
-@uref{http://mysql.shellhung.org/, WWW}
-@uref{ftp://ftp.shellhung.org/pub/Mirror/mysql/, FTP}
+@example
+[mysqld]
+basedir=the_install_path #e.g. c:/mysql
+datadir=the_data_path #e.g. c:/mysql/data or d:/mydata/data
+@end example
-@c @item
-@c Not ok 20010308; Other content! (Tonu)
-@c EMAIL: xcyber@yahoo.com (xcyber)
-@c @image{Flags/china} China [xcyber.org/Hong Kong] @
-@c @uref{http://mysql.xcyber.org/, WWW}
+If the data directory is other than the default
+@file{c:\mysql\data}, you must cut the whole @file{\data\mysql}
+directory and paste it on the your option new directory,
+e.g.: @file{d:\mydata\mysql}.
-@c @item
-@c Not ok 20010330; Non-existent! (Matt)
-@c EMAIL: marquischan@hotmail.com (Marquis Chan)
-@c @image{Flags/china} China [TraLand.com/Hong Kong] @
-@c @uref{http://www.traland.com/mysql/, WWW}
+If you want to use the @code{InnoDB} transactional tables, you
+need to manually create two new directories to hold the InnoDB
+data and log files, e.g. @file{c:\ibdata} and @file{c:\iblogs}.
+You will also need to add some extra lines to the configuration
+file. @xref{InnoDB start}.
-@c @item
-@c Not ok 20000919; Non-existent (Matt)
-@c EMAIL: george@netfirm.net (Hongsheng Zhu)
-@c @image{Flags/china} China [Netfirm] @
-@c @uref{http://mysql.netfirm.net, WWW}
+If you don't want to use @code{InnoDB} tables, add the
+@code{skip-innodb} option to the configuration file.
-@item
-@c EMAIL: dnata@incaf.net (Denie Nataprawira)
-@image{Flags/indonesia} Indonesia [incaf.net] @
-@uref{http://mysql.incaf.net/, WWW}
+Now you are ready to test starting the server.
-@item
-@c EMAIL: andika@piksi.itb.ac.id (Andika Triwidada)
-@image{Flags/indonesia} Indonesia [web.id] @
-@uref{http://mysql.itb.web.id/, WWW}
-@uref{ftp://mysql.itb.web.id/pub/MySQL/, FTP}
-@item
-@c Ok 980805
-@c EMAIL: takeshi@SoftAgency.co.jp
-@image{Flags/japan} Japan [Soft Agency] @
-@uref{http://www.softagency.co.jp/MySQL, WWW}
+@node Windows server first start, , Windows prepare environment, Windows installation
+@subsubsection Starting the Server for the First Time
-@item
-@c EMAIL: takafumi@u-aizu.ac.jp (Takafumi Hayashi)
-@image{Flags/japan} Japan [u-aizu.ac.jp/Aizu] @
-@uref{ftp://ftp.u-aizu.ac.jp/ftp/pub/dbms/mysql/mysql.com, FTP}
+Testing from a DOS command prompt is the best thing to do because
+the server prints messages, so if something is wrong with your
+configuration you will see a more accurate error message which
+will make it easier for you to identify and fix any problems.
-@c @item
-@c Ok 980109 Removed 990730
-@c EMAIL: satoshi@HappySize.co.jp (Satoshi TATSUOKA)
-@c @image{Flags/japan} Japan [HappySize] @
-@c @uref{http://www.happysize.co.jp/mysql/, WWW}
-@c @uref{ftp://ftp.happysize.co.jp/pub/mysql/, FTP}
+Make sure you are in the right directory, then enter:
-@c @item
-@c Ok 981204
-@c Not ok 20000919; Old site (Matt)
-@c EMAIL: hiroyuki@nucba.ac.jp (hiroyuki kurimoto)
-@c @image{Flags/japan} Japan [Nagoya Syouka University] @
-@c @uref{http://mirror.nucba.ac.jp/mirror/mysql, WWW}
-@c @uref{ftp://mirror.nucba.ac.jp/mirror/mysql, FTP}
-
-@c @item
-@c Not ok 20000919; Old site (Matt)
-@c EMAIL: ahmlhs@nmsvr.chosun.com (Ho-sun Lee)
-@c @image{Flags/south-korea} South Korea [KREONet] @
-@c @uref{http://linux.kreonet.re.kr/mysql/, WWW}
-
-@item
-@c EMAIL: jasper@webiiz.com (Kang, Tae-jin)
-@image{Flags/south-korea} South Korea [Webiiz] @
-@uref{http://mysql.webiiz.com/, WWW}
+@example
+C:\mysql\bin> mysqld-max --standalone
+@end example
-@item
-@c EMAIL: hollywar@holywar.net (Oh Junseon)
-@image{Flags/south-korea} South Korea [PanworldNet] @
-@uref{http://mysql.holywar.net/, WWW}
-
-@c @item
-@c ftp -> remove old files
-@c EX: ahmlhs@nmsvr.chosun.com (Ho-sun Lee)
-@c @image{Flags/south-korea} South Korea [KREONet] @
-@c @uref{ftp://linux.kreonet.re.kr/pub/tools/db/mysql/, FTP}
-
-@c @item
-@c Removed 990308
-@c EMAIL: terence@com5.net (Terence Chan)
-@c @image{Flags/singapore} Singapore [Com5 Productions] @
-@c @uref{http://mysql.com5.net, WWW}
-@c @uref{ftp://ftp.com5.net/pub/mysql, FTP}
-
-@item
-@c EMAIL: csy@hjc.edu.sg
-@image{Flags/singapore} Singapore [HJC] @
-@uref{http://mysql.hjc.edu.sg, WWW}
-@uref{ftp://ftp.hjc.edu.sg/mysql, FTP}
-
-@c @item
-@c Not ok 20000919; Old site (Matt)
-@c 991118: Removed because a user complained about that the page contains
-@c nothing about MySQL. 991119: Added again because it is a mirror again
-@c EMAIL: dean@ht.net.tw (Dean Lin)
-@c @image{Flags/taiwan} Taiwan [HT] @
-@c @uref{http://mysql.ht.net.tw, WWW}
+You should see the below print messages:
-@item
-@c EMAIL: linda@ttn.com.tw (Linda Hu)
-@image{Flags/taiwan} Taiwan [TTN] @
-@uref{http://mysql.ttn.net, WWW}
+@example
+InnoDB: The first specified data file c:\ibdata\ibdata1 did not exist:
+InnoDB: a new database to be created!
+InnoDB: Setting file c:\ibdata\ibdata1 size to 209715200
+InnoDB: Database physically writes the file full: wait...
+InnoDB: Log file c:\iblogs\ib_logfile0 did not exist: new to be created
+InnoDB: Setting log file c:\iblogs\ib_logfile0 size to 31457280
+InnoDB: Log file c:\iblogs\ib_logfile1 did not exist: new to be created
+InnoDB: Setting log file c:\iblogs\ib_logfile1 size to 31457280
+InnoDB: Log file c:\iblogs\ib_logfile2 did not exist: new to be created
+InnoDB: Setting log file c:\iblogs\ib_logfile2 size to 31457280
+InnoDB: Doublewrite buffer not found: creating new
+InnoDB: Doublewrite buffer created
+InnoDB: creating foreign key constraint system tables
+InnoDB: foreign key constraint system tables created
+011024 10:58:25 InnoDB: Started
+@end example
+
+For further information about running MySQL on Windows,
+see @ref{Windows}.
-@c @item
-@c Ok 980321 No connect -> removed 990730
-@c EMAIL: tby@ccca.nctu.edu.tw (Bao-Yi Tuang)
-@c @image{Flags/taiwan} Taiwan [NCTU] @
-@c @uref{http://mysql.taconet.com.tw, WWW}
-@c @item
-@c Out of date 990905 (~2 months)
-@c @item @c **********************************
-@c Error 980106
-@c EX: WolfySu@acer.net (Wolfy Su)
-@c @image{Flags/taiwan} Taiwan [Acer] @
-@c @uref{http://mysql.acer.net/, WWW}
+@node General Installation Issues, Installing source, Quick Standard Installation, Installing
+@section General Installation Issues
-@c @item @c **********************************
-@c files to delete
-@c EX: service@wownet.net
-@c @image{Flags/taiwan} Taiwan [Wownet] @
-@c @uref{ftp://ftp.wownet.net/mysql/, FTP}
+@c @node Methods of Installation, , ,
+@c @subsection Methods of Installation
-@c @item @c **********************************
-@c No contact 980106
-@c EX: serge@oneway.net
-@c @image{Flags/taiwan} Taiwan [Oneway] @
-@c @uref{ftp://ftp.oneway.com.tw/pub/mysql/, FTP}
+@c FIX: this needs to be written?
-@item
-@c Added 20001031
-@c EMAIL: ijliao@php.nctu.edu.tw (Ying-Chieh Liao)
-@image{Flags/taiwan} Taiwan [nctu.edu/HsinChu] @
-@uref{http://mysql.nctu.edu.tw/, WWW}
+@menu
+* Getting MySQL:: How to Get MySQL
+* Which OS:: Operating Systems Supported by MySQL
+* Which version:: Which MySQL Version to Use
+* Installation layouts:: Installation Layouts
+* Many versions:: How and When Updates Are Released
+* MySQL binaries:: MySQL Binaries Compiled by MySQL AB
+* Installing binary:: Installing a MySQL Binary Distribution
+@end menu
-@end itemize
-
-@c @strong{Australia:}
-@c @itemize @bullet
-@c @item
-@c Added 980610
-@c EMAIL: jason@dstc.edu.au (Jason Andrade)
-@c @image{Flags/australia} Australia [AARNet/Queensland] @
-@c @uref{http://mysql.mirror.aarnet.edu.au/, WWW}
-@c @uref{ftp://mysql.mirror.aarnet.edu.au/, FTP}
+@node Getting MySQL, Which OS, General Installation Issues, General Installation Issues
+@subsection How to Get MySQL
-@c @item
-@c Added 980805. Removed 000102 'no such directory'
-@c EMAIL: sdd@ntccc.tas.gov.au (Scott Donovan)
-@c @image{Flags/australia} Australia [Tas] @
-@c @uref{http://ftp.tas.gov.au/mysql, WWW}
-@c @uref{ftp://ftp.tas.gov.au/pub/mysql, FTP}
+@cindex downloading
+@cindex MySQL version
+@cindex version, latest
+@cindex getting MySQL
+@cindex mirror sites
+@cindex URLS for downloading MySQL
-@c @item
-@c Ok 980623
-@c Not ok 20000919; Old site (Matt)
-@c EMAIL: samh@bluep.com (Sam Hadzajlic)
-@c @image{Flags/australia} Australia [Blue Planet/Melbourne] @
-@c @uref{http://mysql.bluep.com/, WWW}
-@c removed because ftp was not working 990729 & 30
-@c @uref{ftp://mysql.bluep.com/pub/mirror1/mysql/, FTP}
+Check the MySQL homepage (@uref{http://www.mysql.com/}) for
+information about the current version and for downloading instructions.
-@c @item
-@c Added 990531
-@c EMAIL: gavin@itworks.com.au (Gavin Cameron)
-@c @image{Flags/australia} Australia [ITworks Consulting/Victoria] @
-@c @uref{http://mysql.itworks.com.au, WWW}
+Our main download mirror is located at:
-@c @item
-@c 980610 Only the toplevel dir!
-@c EMAIL: lucifer@maths.uq.edu.au (David Conran)
-@c @image{Flags/australia} Australia FTP @
-@c @uref{ftp://ftp.sage-au.org.au/pub/database/mysql, [Sage]}
-@c @end itemize
+@uref{http://mirrors.sunsite.dk/mysql/}
-@strong{Africa:}
+If you are interested in becoming a MySQL mirror site, you may
+anonymously rsync with: @code{rsync://sunsite.dk/ftp/mirrors/mysql/}. Please
+send e-mail to @email{webmaster@@mysql.com} notifying us of your mirror to be
+added to the list below.
-@itemize @bullet
+If you have problems downloading from our main site, try using one of the
+mirrors listed below.
-@item
-@c EMAIL: ftp-admin@mweb.com (Warren Baker)
-@image{Flags/south-africa1} South-Africa [Mweb] @
-@uref{http://www.mysql.mweb.co.za/, WWW}
+Please report bad or out-of-date mirrors to @email{webmaster@@mysql.com}.
-@item
-@c Ok 981010
-@c EMAIL: oskar@is.co.za (Oskar Pearson)
-@image{Flags/south-africa1} South Africa [The Internet Solution/Johannesburg] @
-@uref{ftp://ftp.is.co.za/linux/mysql/, FTP}
+@c START_OF_MIRROR_LISTING
-@end itemize
+@c Mirrors list is created by PHP script (that really needs to be documented!) from database (tfr@mysql.com)
+@include mirrors.texi
@c END_OF_MIRROR_LISTING
@@ -7291,7 +5792,7 @@ efficiently, if your tables are big.
@item
Our level of expertise here at MySQL AB with the platform. If we know
-a platform well, we introduce platform-specific optimizations/fixes enabled at
+a platform well, we introduce platform-specific optimisations/fixes enabled at
compile time. We can also provide advice on configuring your system optimally
for MySQL.
@@ -7310,7 +5811,7 @@ ReiserFS (or any similar Linux distribution) and Sparc with Solaris 2.7
or 2.8. FreeBSD comes third, but we really hope it will join the top
club once the thread library is improved. We also hope that at some
point we will be able to include all other platforms on which
-MySQL compiles, runs ok, but not quite with the same level of
+MySQL compiles, runs okay, but not quite with the same level of
stability and performance, into the top category. This will require some
effort on our part in cooperation with the developers of the OS/library
components MySQL depends upon. If you are interested in making
@@ -7325,7 +5826,7 @@ for a dedicated purpose - running MySQL, and compare platforms in that
regard only. With this in mind, the result of this comparison
would be different if we included more issues into it. And in some cases,
the reason one OS is better than the other could simply be that we have put
-forth more effort into testing on and optimizing for that particular platform.
+forth more effort into testing on and optimising for that particular platform.
We are just stating our observations to help you make a
decision on which platform to use MySQL on in your setup.
@@ -7344,12 +5845,12 @@ release or the last stable release:
@itemize @bullet
@item
-Normally, if you are beginning to use MySQL for the first time
-or trying to port it to some system for which there is no binary
-distribution, we recommend going with the stable release (currently
-Version @value{mysql_version}. Note that all MySQL releases are
-checked with the MySQL benchmarks and an extensive test suite
-before each release.
+Normally, if you are beginning to use MySQL for the first time or trying
+to port it to some system for which there is no binary distribution, we
+recommend going with the stable release (currently Version 3.23. Note
+that all MySQL releases are checked with the MySQL benchmarks and an
+extensive test suite before each release (even the development
+releases).
@item
Otherwise, if you are running an old system and want to upgrade, but
@@ -7390,12 +5891,12 @@ install the standard @code{MySQL} RPM.
@item
If you want to configure @code{mysqld} with some extra features that are
-NOT in the standard binary distributions. Here is a list of the most
+not in the standard binary distributions. Here is a list of the most
common extra options that you may want to use:
@itemize @bullet
-@item @code{--with-berkeley-db}
@item @code{--with-innodb}
+@item @code{--with-berkeley-db}
@item @code{--with-raid}
@item @code{--with-libwrap}
@item @code{--with-named-z-lib (This is done for some of the binaries)}
@@ -7409,7 +5910,7 @@ the same processor family.
If you want a faster MySQL server you may want to recompile it
with support for only the character sets you need, use a better compiler
-(like @code{pgcc}) or use compiler options that are better optimized for your
+(like @code{pgcc}) or use compiler options that are better optimised for your
processor.
@item
@@ -7499,7 +6000,7 @@ hundreds of megabytes of data.
@item The MySQL benchmark suite
This runs a range of common queries. It is also a test to see whether the
-latest batch of optimizations actually made the code faster.
+latest batch of optimisations actually made the code faster.
@xref{MySQL Benchmarks}.
@item The @code{crash-me} test
@@ -7610,7 +6111,8 @@ Stable tested releases are meant to appear about 1-2 times a year, but
if small bugs are found, a release with only bug fixes will be released.
@item
-Working releases are meant to appear about every 1-8 weeks.
+Working releases/bug fixes to old releases are meant to appear about
+every 1-8 weeks.
@item
Binary distributions for some platforms will be made by us for major releases.
@@ -7619,12 +6121,12 @@ less frequently.
@item
We usually make patches available as soon as we have located and fixed
-small bugs.
+small bugs. They are posted to @email{bugs@@lists.mysql.com} and will
+be added to the next release.
@item
-For non-critical but annoying bugs, we will make patches available if they
-are sent to us. Otherwise we will combine many of them into a larger
-patch.
+For non-critical but annoying bugs, we will add them the MySQL source
+repository and they will be fixed in the next release.
@item
If there is, by any chance, a fatal bug in a release we will make a new
@@ -7639,8 +6141,12 @@ and things that ``must be done.'' ``Somewhat frozen'' means that we may
add small things that ``almost surely will not affect anything that's
already working.''
+MySQL uses a little different naming scheme that most other products.
+In general it's relatively safe to use any version that has been out for
+a couple of weeks without being replaced with a new version.
+@xref{Which version}.
-@node MySQL binaries, , Many versions, General Installation Issues
+@node MySQL binaries, Installing binary, Many versions, General Installation Issues
@subsection MySQL Binaries Compiled by MySQL AB
@cindex binary distributions
@@ -7699,6 +6205,223 @@ If you want to compile a debug version of MySQL, you should add
@code{--with-debug} or @code{--with-debug=full} to the above configure lines
and remove any @code{-fomit-frame-pointer} options.
+For the Windows distribution, please see @ref{Windows installation}.
+
+
+@node Installing binary, , MySQL binaries, General Installation Issues
+@subsection Installing a MySQL Binary Distribution
+
+@cindex installing, binary distribution
+@cindex binary distributions, installing
+
+See also @ref{Windows binary installation},
+@ref{Linux-RPM}, and @ref{Building clients}.
+
+You need the following tools to install a MySQL binary distribution:
+
+@itemize @bullet
+@item
+GNU @code{gunzip} to uncompress the distribution.
+
+@item
+A reasonable @code{tar} to unpack the distribution. GNU @code{tar} is
+known to work. Sun @code{tar} is known to have problems.
+@end itemize
+
+@cindex RPM, defined
+@cindex RedHat Package Manager
+An alternative installation method under Linux is to use RPM (RedHat Package
+Manager) distributions. @xref{Linux-RPM}.
+
+@c texi2html fails to split chapters if I use strong for all of this.
+If you run into problems, @strong{please always use @code{mysqlbug}} when
+posting questions to @email{mysql@@lists.mysql.com}. Even if the problem
+isn't a bug, @code{mysqlbug} gathers system information that will help others
+solve your problem. By not using @code{mysqlbug}, you lessen the likelihood
+of getting a solution to your problem! You will find @code{mysqlbug} in the
+@file{bin} directory after you unpack the distribution. @xref{Bug reports}.
+
+@cindex commands, for binary distribution
+The basic commands you must execute to install and use a MySQL
+binary distribution are:
+
+@example
+shell> groupadd mysql
+shell> useradd -g mysql mysql
+shell> cd /usr/local
+shell> gunzip < /path/to/mysql-VERSION-OS.tar.gz | tar xvf -
+shell> ln -s mysql-VERSION-OS mysql
+shell> cd mysql
+shell> scripts/mysql_install_db
+shell> chown -R root /usr/local/mysql
+shell> chown -R mysql /usr/local/mysql/data
+shell> chgrp -R mysql /usr/local/mysql
+shell> chown -R root /usr/local/mysql/bin
+shell> bin/safe_mysqld --user=mysql &
+@end example
+
+@cindex adding, new users
+@cindex new users, adding
+@cindex users, adding
+
+You can add new users using the @code{bin/mysql_setpermission} script if
+you install the @code{DBI} and @code{Msql-Mysql-modules} Perl modules.
+
+A more detailed description follows.
+
+To install a binary distribution, follow the steps below, then proceed
+to @ref{Post-installation}, for post-installation setup and testing:
+
+@enumerate
+@item
+Pick the directory under which you want to unpack the distribution, and move
+into it. In the example below, we unpack the distribution under
+@file{/usr/local} and create a directory @file{/usr/local/mysql} into which
+MySQL is installed. (The following instructions therefore assume
+you have permission to create files in @file{/usr/local}. If that directory
+is protected, you will need to perform the installation as @code{root}.)
+
+@item
+Obtain a distribution file from one of the sites listed in
+@ref{Getting MySQL, , Getting MySQL}.
+
+MySQL binary distributions are provided as compressed @code{tar}
+archives and have names like @file{mysql-VERSION-OS.tar.gz}, where
+@code{VERSION} is a number (for example, @code{3.21.15}), and @code{OS}
+indicates the type of operating system for which the distribution is intended
+(for example, @code{pc-linux-gnu-i586}).
+
+@item
+If you see a binary distribution marked with the @code{-max} prefix, this
+means that the binary has support for transaction-safe tables and other
+features. @xref{mysqld-max, , @code{mysqld-max}}. Note that all binaries
+are built from the same MySQL source distribution.
+
+@item
+Add a user and group for @code{mysqld} to run as:
+
+@example
+shell> groupadd mysql
+shell> useradd -g mysql mysql
+@end example
+
+These commands add the @code{mysql} group and the @code{mysql} user. The
+syntax for @code{useradd} and @code{groupadd} may differ slightly on different
+versions of Unix. They may also be called @code{adduser} and @code{addgroup}.
+You may wish to call the user and group something else instead of @code{mysql}.
+
+@item
+Change into the intended installation directory:
+
+@example
+shell> cd /usr/local
+@end example
+
+@item
+Unpack the distribution and create the installation directory:
+
+@example
+shell> gunzip < /path/to/mysql-VERSION-OS.tar.gz | tar xvf -
+shell> ln -s mysql-VERSION-OS mysql
+@end example
+
+The first command creates a directory named @file{mysql-VERSION-OS}. The
+second command makes a symbolic link to that directory. This lets you refer
+more easily to the installation directory as @file{/usr/local/mysql}.
+
+@item
+Change into the installation directory:
+
+@example
+shell> cd mysql
+@end example
+
+You will find several files and subdirectories in the @code{mysql} directory.
+The most important for installation purposes are the @file{bin} and
+@file{scripts} subdirectories.
+
+@table @file
+@item bin
+@tindex PATH environment variable
+@tindex environment variable, PATH
+This directory contains client programs and the server
+You should add the full pathname of this directory to your
+@code{PATH} environment variable so that your shell finds the MySQL
+programs properly. @xref{Environment variables}.
+
+@item scripts
+This directory contains the @code{mysql_install_db} script used to initialise
+the @code{mysql} database containing the grant tables that store the server
+access permissions.
+@end table
+
+@item
+If you would like to use @code{mysqlaccess} and have the MySQL
+distribution in some non-standard place, you must change the location where
+@code{mysqlaccess} expects to find the @code{mysql} client. Edit the
+@file{bin/mysqlaccess} script at approximately line 18. Search for a line
+that looks like this:
+
+@example
+$MYSQL = '/usr/local/bin/mysql'; # path to mysql executable
+@end example
+
+Change the path to reflect the location where @code{mysql} actually is
+stored on your system. If you do not do this, you will get a @code{Broken
+pipe} error when you run @code{mysqlaccess}.
+
+@item
+Create the MySQL grant tables (necessary only if you haven't
+installed MySQL before):
+@example
+shell> scripts/mysql_install_db
+@end example
+
+Note that MySQL versions older than Version 3.22.10 started the
+MySQL server when you run @code{mysql_install_db}. This is no
+longer true!
+
+@item
+Change ownership of binaries to @code{root} and ownership of the data
+directory to the user that you will run @code{mysqld} as:
+
+@example
+shell> chown -R root /usr/local/mysql
+shell> chown -R mysql /usr/local/mysql/data
+shell> chgrp -R mysql /usr/local/mysql
+@end example
+
+The first command changes the @code{owner} attribute of the files to the
+@code{root} user, the second one changes the @code{owner} attribute of the
+data directory to the @code{mysql} user, and the third one changes the
+@code{group} attribute to the @code{mysql} group.
+
+@item
+If you want to install support for the Perl @code{DBI}/@code{DBD} interface,
+see @ref{Perl support}.
+
+@item
+If you would like MySQL to start automatically when you boot your
+machine, you can copy @code{support-files/mysql.server} to the location where
+your system has its startup files. More information can be found in the
+@code{support-files/mysql.server} script itself and in
+@ref{Automatic start}.
+
+@end enumerate
+
+After everything has been unpacked and installed, you should initialise
+and test your distribution.
+
+You can start the MySQL server with the following command:
+
+@example
+shell> bin/safe_mysqld --user=mysql &
+@end example
+
+@xref{safe_mysqld, , @code{safe_mysqld}}.
+
+@xref{Post-installation}.
+
@node Installing source, Post-installation, General Installation Issues, Installing
@section Installing a MySQL Source Distribution
@@ -7743,9 +6466,9 @@ sometimes required. If you have problems, we recommend trying GNU
@end itemize
If you are using a recent version of @strong{gcc}, recent enough to understand
-@code{-fno-exceptions} option, it is @strong{VERY IMPORTANT} that you use
+@code{-fno-exceptions} option, it is @strong{very important} that you use
it. Otherwise, you may compile a binary that crashes randomly. We also
-recommend that you use @code{-felide-contructors} and @code{-fno-rtti} along
+recommend that you use @code{-felide-constructors} and @code{-fno-rtti} along
with @code{-fno-exceptions}. When in doubt, do the following:
@example
@@ -7757,7 +6480,7 @@ CFLAGS="-O3" CXX=gcc CXXFLAGS="-O3 -felide-constructors -fno-exceptions -fno-rtt
On most systems this will give you a fast and stable binary.
@c texi2html fails to split chapters if I use strong for all of this.
-If you run into problems, @strong{PLEASE ALWAYS USE @code{mysqlbug}} when
+If you run into problems, @strong{please always use @code{mysqlbug}} when
posting questions to @email{mysql@@lists.mysql.com}. Even if the problem
isn't a bug, @code{mysqlbug} gathers system information that will help others
solve your problem. By not using @code{mysqlbug}, you lessen the likelihood
@@ -7772,6 +6495,7 @@ of getting a solution to your problem! You will find @code{mysqlbug} in the
* Installing source tree:: Installing from the Development Source Tree
* Compilation problems:: Problems Compiling?
* MIT-pthreads:: MIT-pthreads Notes
+* Windows source build:: Windows Source Distribution
@end menu
@@ -7816,7 +6540,7 @@ you install the @code{DBI} and @code{Msql-Mysql-modules} Perl modules.
A more detailed description follows.
To install a source distribution, follow the steps below, then proceed
-to @ref{Post-installation}, for post-installation initialization and testing:
+to @ref{Post-installation}, for post-installation initialisation and testing:
@enumerate
@item
@@ -7940,7 +6664,7 @@ your system has its startup files. More information can be found in the
@ref{Automatic start}.
@end enumerate
-After everything has been installed, you should initialize and test your
+After everything has been installed, you should initialise and test your
distribution:
@example
@@ -7962,8 +6686,8 @@ running. @xref{Multiple servers}.
@cindex applying, patches
Sometimes patches appear on the mailing list or are placed in the
-@uref{http://www.mysql.com/Downloads/Patches, patches area} of the
-MySQL Web site.
+patches area of the MySQL web site
+(@uref{http://www.mysql.com/Downloads/Patches/}).
To apply a patch from the mailing list, save the message in which the patch
appears in a file, change into the top-level directory of your MySQL
@@ -8040,6 +6764,10 @@ warnings about @file{mysql.cc}. (If @code{make} stops, try @code{make -k}
to tell it to continue with the rest of the build even if errors occur.)
@item
+If you want to get a embedded MySQL library (@code{libmysqld.a}) you should
+use the @code{--with-embedded-server} option.
+
+@item
If you don't want your log files and database directories located under
@file{/usr/local/var}, use a @code{configure} command, something like one
of these:
@@ -8055,7 +6783,8 @@ installed under @file{/usr/local/mysql} rather than the default of
@file{/usr/local}. The second command preserves the default installation
prefix, but overrides the default location for database directories
(normally @file{/usr/local/var}) and changes it to
-@code{/usr/local/mysql/data}.
+@code{/usr/local/mysql/data}. After you have compiled MySQL, you can
+change these options with option files. @xref{Option files}.
@cindex changing socket location
@cindex socket location, changing
@@ -8112,6 +6841,7 @@ the compiler you are using:
@tindex CXXFLAGS environment variable
@tindex environment variable, CXXFLAGS
@multitable @columnfractions .20 .80
+@item @strong{Compiler} @tab @strong{Recommended options}
@item gcc 2.7.2.1 @tab
CC=gcc CXX=gcc CXXFLAGS="-O3 -felide-constructors"
@item egcs 1.0.3a @tab
@@ -8137,8 +6867,8 @@ following for all recent gcc versions:
CFLAGS="-O3 -mpentiumpro" CXX=gcc CXXFLAGS="-O3 -mpentiumpro -felide-constructors -fno-exceptions -fno-rtti" ./configure --prefix=/usr/local/mysql --enable-assembler --with-mysqld-ldflags=-all-static
@end example
-The binaries we provide on the MySQL Web site at
-@uref{http://www.mysql.com} are all compiled with full optimization and
+The binaries we provide on the MySQL web site at
+@uref{http://www.mysql.com/} are all compiled with full optimisation and
should be perfect for most users. @xref{MySQL binaries}. There are some
things you can tweak to make an even faster binary, but this is only for
advanced users. @xref{Compile and link options}.
@@ -8231,7 +6961,7 @@ system-specific section of this manual.
@cindex BitKeeper tree
@cindex cvs tree
-@strong{CAUTION:} You should read this section only if you are interested
+@strong{Caution:} You should read this section only if you are interested
in helping us test our new code. If you just want to get MySQL up
and running on your system, you should use a standard release distribution
(either a source or binary distribution will do).
@@ -8248,7 +6978,8 @@ Download @strong{BitKeeper} from
Follow the instructions to install it.
@item
-After @strong{BitKeeper} is installed, use this command if you want to clone
+After @strong{BitKeeper} is installed, first go to the directory you
+want to work from, and then use this command if you want to clone
the MySQL 3.23 branch:
@example
@@ -8261,12 +6992,19 @@ To clone the 4.0 branch, use this command instead:
shell> bk clone bk://work.mysql.com:7001 mysql-4.0
@end example
+In the above examples the source tree will be set up in the @file{mysql/}
+or @file{mysql-4.0/} subdirectory of your current directory.
+
The initial download of the source tree may take a while, depending on the
speed of your connection; be patient.
@item
-You will need GNU @code{autoconf}, @code{automake}, @code{libtool}, and
-@code{m4} to run the next set of commands.
+You will need GNU @code{autoconf 2.13}, @code{automake 1.4},
+@code{libtool}, and @code{m4} to run the next set of commands.
+
+If you are using the 3.23 tree the new versions of @code{autoconf}
+(2.52) and @code{automake} (1.5) will not work.
+
If you get some strange error during this stage, check that you really
have @code{libtool} installed!
@@ -8314,7 +7052,7 @@ You can examine the change history for the tree with all the diffs by using
@code{bk sccstool}. If you see some funny diffs or code that you have a
question about, do not hesitate to send e-mail to
@email{internals@@lists.mysql.com}. Also, if you think you have a better idea
-on how to do something, send an email to the same address with a patch.
+on how to do something, send an e-mail to the same address with a patch.
@code{bk diffs} will produce a patch for you after you have made changes
to the source. If you do not have the time to code your idea, just send
a description.
@@ -8548,7 +7286,7 @@ link your clients with the new client library. @xref{Debugging client}.
@end itemize
-@node MIT-pthreads, , Compilation problems, Installing source
+@node MIT-pthreads, Windows source build, Compilation problems, Installing source
@subsection MIT-pthreads Notes
@cindex MIT-pthreads
@@ -8574,7 +7312,7 @@ shell> ./configure --with-mit-threads
@end example
Building in a non-source directory is not supported when using
-MIT-pthreads, because we want to minimize our changes to this code.
+MIT-pthreads, because we want to minimise our changes to this code.
@item
The checks that determine whether or not to use MIT-pthreads occur only
@@ -8640,6 +7378,75 @@ needed, but may be interesting for someone.)
@end itemize
+@node Windows source build, , MIT-pthreads, Installing source
+@subsection Windows Source Distribution
+
+You will need the following:
+
+@itemize @bullet
+@item
+VC++ 6.0 compiler (updated with 4 or 5 SP and Pre-processor package)
+The Pre-processor package is necessary for the macro assembler.
+More details at:
+@uref{http://msdn.microsoft.com/vstudio/sp/vs6sp5/faq.asp}.
+@item
+The MySQL source distribution for Windows, which can be downloaded
+from @uref{http://www.mysql.com/downloads/}.
+@end itemize
+
+Building MySQL
+
+@enumerate
+@item
+Create a work directory (e.g.: workdir).
+@item
+Unpack the source distribution in the above directory.
+@item
+Start the VC++ 6.0 compiler.
+@item
+In the @code{File} menu, select @code{Open Workspace}.
+@item
+Open the @file{mysql.dsw} workspace you find on the work directory.
+@item
+From the @code{Build} menu,
+select the @code{Set Active Configuration} menu.
+@item
+Click over the screen selecting @code{mysqld - Win32 Debug}
+and click OK.
+@item
+Press @code{F7} to begin the build of the debug server, libs and
+some client applications.
+@item
+When the compilation finishes, copy the libs and the executables
+to a separate directory.
+@item
+Compile the release versions that you want, in the same way.
+@item
+Create the directory for the MySQL stuff: e.g. @file{c:\mysql}
+@item
+From the workdir directory copy for the c:\mysql directory the
+following directories:
+
+@itemize @bullet
+@item Data
+@item Docs
+@item Share
+@end itemize
+
+@item
+Create the directory @file{c:\mysql\bin} and copy all the servers
+and clients that you compiled previously.
+@item
+If you want, also create the @file{lib} directory and copy the
+libs that you compiled previously.
+@item
+Do a clean using Visual Studio.
+@end enumerate
+
+Set up and start the server in the same way as for the binary
+Windows distribution. @xref{Windows prepare environment}.
+
+
@node Post-installation, Upgrade, Installing source, Installing
@section Post-installation Setup and Testing
@@ -8654,7 +7461,7 @@ needed, but may be interesting for someone.)
@end menu
Once you've installed MySQL (from either a binary or source
-distribution), you need to initialize the grant tables, start the server,
+distribution), you need to initialise the grant tables, start the server,
and make sure that the server works okay. You may also wish to arrange
for the server to be started and stopped automatically when your system
starts up and shuts down.
@@ -9012,7 +7819,7 @@ If you are running RedHat Version 5.0 with a version of @code{glibc} older than
2.0.7-5, you should make sure you have installed all @code{glibc} patches!
There is a lot of information about this in the MySQL mail
archives. Links to the mail archives are available online at
-@uref{http://www.mysql.com/documentation/}.
+@uref{http://lists.mysql.com/}.
Also, see @ref{Linux}.
You can also start @code{mysqld} manually using the @code{--skip-grant-tables}
@@ -9035,11 +7842,11 @@ reload the grant tables.
@cindex server, starting problems
@cindex problems, starting the server
-If you are going to use tables that support transactions (BDB, InnoDB),
+If you are going to use tables that support transactions (InnoDB, BDB),
you should first create a my.cnf file and set startup options
for the table types you plan to use. @xref{Table types}.
-Generally, you start the @code{mysqld} server in one of three ways:
+Generally, you start the @code{mysqld} server in one of these ways:
@itemize @bullet
@item
@@ -9053,23 +7860,7 @@ for @code{mysqld} and then runs it with those options. @xref{safe_mysqld, ,
@code{safe_mysqld}}.
@item
-On NT you should install @code{mysqld} as a service as follows:
-@example
-bin\mysqld-nt --install # Install MySQL as a service
-@end example
-
-You can now start/stop @code{mysqld} as follows:
-@example
-NET START mysql
-NET STOP mysql
-@end example
-
-Note that in this case you can't use any other options for @code{mysqld}!
-
-You can remove the service as follows:
-@example
-bin\mysqld-nt --remove # remove MySQL as a service
-@end example
+For Windows NT/2000, please see @ref{NT start}.
@item
By invoking @code{mysqld} directly.
@@ -9106,7 +7897,7 @@ correctly, check the log file to see if you can find out why. Log files
are located in the data directory (typically
@file{/usr/local/mysql/data} for a binary distribution,
@file{/usr/local/var} for a source distribution,
-@file{\mysql\data\mysql.err} on Windows.) Look in the data directory for
+@file{\mysql\data\mysql.err} on Windows). Look in the data directory for
files with names of the form @file{host_name.err} and
@file{host_name.log} where @code{host_name} is the name of your server
host. Then check the last few lines of these files:
@@ -9150,7 +7941,7 @@ Can't start server : Bind on unix socket...
Use @code{ps} to make sure that you don't have another @code{mysqld} server
running. If you can't find another server running, you can try to execute
the command @code{telnet your-host-name tcp-ip-port-number} and press
-@code{RETURN} a couple of times. If you don't get an error message like
+Enter a couple of times. If you don't get an error message like
@code{telnet: Unable to connect to remote host: Connection refused},
something is using the TCP/IP port @code{mysqld} is trying to use.
See @ref{mysql_install_db} and @ref{Multiple servers}.
@@ -9168,6 +7959,13 @@ or
shell> mysqladmin -h 'your-host-name' variables
@end example
+If you get @code{Errcode 13}, which means @code{Permission denied}, when
+starting @code{mysqld} this means that you didn't have the right to
+read/create files in the MySQL database or log directory. In this case
+you should either start @code{mysqld} as the root user or change the
+permissions for the involved files and directories so that you have the
+right to use them.
+
If @code{safe_mysqld} starts the server but you can't connect to it,
you should make sure you have an entry in @file{/etc/hosts} that looks like
this:
@@ -9185,7 +7983,7 @@ to find the problem. @xref{Making trace files}.
If you are using InnoDB tables, refer to the InnoDB-specific startup
options. @xref{InnoDB start}.
-If you are using BDB (Berkeley DB) tables, you should familiarize
+If you are using BDB (Berkeley DB) tables, you should familiarise
yourself with the different BDB specific startup options. @xref{BDB start}.
@@ -9307,14 +8105,102 @@ particularly if you notice symptoms such as all your @code{DBI} scripts
dumping core after you upgrade MySQL.
@menu
+* Upgrading-from-3.23:: Upgrading from a 3.23 version to 4.0
* Upgrading-from-3.22:: Upgrading from a 3.22 version to 3.23
* Upgrading-from-3.21:: Upgrading from a 3.21 version to 3.22
* Upgrading-from-3.20:: Upgrading from a 3.20 version to 3.21
* Upgrading-to-arch:: Upgrading to another architecture
@end menu
+@cindex compatibility, between MySQL versions
+@cindex upgrading, 3.23 to 4.0
+@node Upgrading-from-3.23, Upgrading-from-3.22, Upgrade, Upgrade
+@subsection Upgrading From Version 3.23 to Version 4.0
+
+You can use your old data files without any modification with Version 4.0.
+If you want to move your data from a MySQL 4.0 server to an older server,
+you have to use @code{mysqldump}.
+
+Old clients should work with a Version 4.0 server without any problems.
+
+The following lists tell what you have to watch out for when upgrading to
+version 4.0;
+
+@itemize @bullet
+@item
+@code{SHOW INDEX} has 2 columns more (@code{Null} and @code{Index_type})
+than it had in 3.23.
+@item
+@code{SIGNED} is a reserved word.
+@item
+The result of all bitwise operators @code{|}, @code{&}, @code{<<},
+@code{>>} and @code{~} is now unsigned. This may cause problems if you
+are using them in a context where you want a signed result.
+@xref{Cast Functions}.
+@item
+@strong{NOTE:} When you use subtraction between integer values where
+one is of type @code{UNSIGNED}, the result will be unsigned! In other
+words, before upgrading to MySQL 4.0, you should check your application
+for cases where you are subtracting a value from an unsigned entity and
+want a negative answer or subtracting an unsigned value from an
+integer column. You can disable this behaviour by using the
+@code{--sql-mode=NO_UNSIGNED_SUBTRACTION} option when starting
+@code{mysqld}. @xref{Cast Functions}.
+@item
+To use @code{MATCH ... AGAINST (... IN BOOLEAN MODE)} with your tables,
+you need to rebuild them with @code{ALTER TABLE table_name TYPE=MyISAM},
+@strong{even} if they are of @code{MyISAM} type.
+@item
+@code{LOCATE()} and @code{INSTR()} are case sensitive if one of the
+arguments is a binary string.
+@item
+@code{HEX(string)} now returns the characters in string converted to
+hexadecimal. If you want to convert a number to hexadecimal, you should
+ensure that you call @code{HEX()} with a numeric argument.
+@item
+In 3.23, @code{INSERT INTO ... SELECT} always had @code{IGNORE} enabled.
+In 4.0.1, MySQL will stop (and possibly roll back) in case of an error if you
+don't specify @code{IGNORE}.
+@item
+@file{safe_mysqld} is renamed to @file{mysqld_safe}.
+@item
+The old C API functions @code{mysql_drop_db}, @code{mysql_create_db} and
+@code{mysql_connect} are not supported anymore, unless you compile
+MySQL with @code{CFLAGS=-DUSE_OLD_FUNCTIONS}. Instead of doing this,
+it is preferable to change the client to use the new 4.0 API.
+@item
+In the @code{MYSQL_FIELD} structure, @code{length} and @code{max_length} has
+changed from @code{unsigned int} to @code{unsigned long}. This should not
+cause any other problems than some warnings if you use these to
+@code{printf()} type function.
+@item
+You should use @code{TRUNCATE TABLE} when you want to delete all rows
+from a table and you don't care of how many rows where deleted.
+(Because @code{TRUNCATE TABLE} is faster than @code{DELETE FROM table_name}).
+@item
+You will get an error if you have an active @code{LOCK TABLES} or
+transaction when trying to execute @code{TRUNCATE TABLE} or @code{DROP
+DATABASE}.
+@item
+You should use integers to store values in BIGINT columns (instead of using
+strings as you did in MySQL 3.23). Using strings will still work, but using
+integers is more efficient.
+@item
+Format of @code{SHOW OPEN TABLE} has changed.
+@item
+Multithreaded clients should use @code{mysql_thread_init()} and
+@code{mysql_thread_end()}. @xref{Threaded clients}.
+@item
+If you want to recompile the Perl DBD::mysql module, you must get
+Msql-Mysql-modules version 1.2218 or newer, because the older DBD modules
+used the deprecated @code{drop_db()} call.
+@item
+@code{RAND(seed)} returns a different random number series in 4.0 than in
+3.23; This was done to get @code{RAND(seed)} and @code{RAND(seed+1)} more
+different.
+@end itemize
-@node Upgrading-from-3.22, Upgrading-from-3.21, Upgrade, Upgrade
+@node Upgrading-from-3.22, Upgrading-from-3.21, Upgrading-from-3.23, Upgrade
@subsection Upgrading From Version 3.22 to Version 3.23
@cindex compatibility, between MySQL versions
@@ -9346,7 +8232,7 @@ because configure didn't detect the @code{readlink} system call).
@item
@code{OPTIMIZE TABLE} now only works for @strong{MyISAM} tables.
-For other table types, you can use @code{ALTER TABLE} to optimize the table.
+For other table types, you can use @code{ALTER TABLE} to optimise the table.
During @code{OPTIMIZE TABLE} the table is now locked from other threads.
@item
@@ -9357,6 +8243,10 @@ some cases, for example in SQL scripts that use named commands without a
semicolon! Long format commands still work from the first line.
@item
+Date functions that work on part of dates (like @code{MONTH()}) will now
+return 0 for @code{0000-00-00} dates. (MySQL 3.22 returned @code{NULL}).
+
+@item
If you are using the @code{german} character sort order, you must repair
all your tables with @code{isamchk -r}, as we have made some changes in
the sort order!
@@ -9487,7 +8377,7 @@ return any server error, only @code{CR_UNKNOWN_ERROR} (but it
works for client errors), and the server uses the old @code{password()}
checking rather than the new one.
-If you are @strong{NOT} using the @code{--old-protocol} option to
+If you are @strong{not} using the @code{--old-protocol} option to
@code{mysqld}, you will need to make the following changes:
@itemize @bullet
@@ -9639,7 +8529,7 @@ After you import the @code{mysql} database on the new machine, execute
information.
-@node Operating System Specific Notes, , Upgrade, Installing
+@node Operating System Specific Notes, Perl support, Upgrade, Installing
@section Operating System Specific Notes
@menu
@@ -9685,12 +8575,12 @@ binary in most cases is the best choice.
MySQL uses LinuxThreads on Linux. If you are using an old
Linux version that doesn't have @code{glibc2}, you must install
LinuxThreads before trying to compile MySQL. You can get
-LinuxThreads at @uref{http://www.mysql.com/Downloads/Linux}.
+LinuxThreads at @uref{http://www.mysql.com/Downloads/Linux/}.
-@strong{NOTE:} We have seen some strange problems with Linux 2.2.14 and
+@strong{Note:} We have seen some strange problems with Linux 2.2.14 and
MySQL on SMP systems; If you have a SMP system, we recommend
-you to upgrade to Linux 2.4 ASAP! Your system will be faster and more
-stable by doing this!
+you to upgrade to Linux 2.4 as soon as possible! Your system will be
+faster and more stable by doing this!
Note that @code{glibc} versions before and including Version 2.1.1 have
a fatal bug in @code{pthread_mutex_timedwait} handling, which is used
@@ -9767,7 +8657,7 @@ the more threads you can safely create. We recommend the values between
128K and 256K.
If you use a lot of concurrent connections, you may suffer from a "feature"
-in the 2.2 kernel that penalizes a process for forking or cloning a child
+in the 2.2 kernel that penalises a process for forking or cloning a child
in an attempt to prevent a fork bomb attack. This will cause MySQL
not to scale well as you increase the number of concurrent clients. On
single CPU systems, we have seen this manifested in a very slow thread
@@ -9817,9 +8707,9 @@ threads that only
hold the mutex for a short time. On an SMP system, ironic as it is, if
you link MySQL against unmodified @strong{LinuxThreads},
removing processors from the machine improves MySQL performance
-in many cases. We have made a patch available for @strong{glibc 2.1.3},
-@uref{http://www.mysql.com/Downloads/Linux/linuxthreads-2.1-patch,linuxthreads-2.1-patch}
-to correct this behavior.
+in many cases. We have made a patch available for @strong{glibc 2.1.3}
+to correct this behavior
+(@uref{http://www.mysql.com/Downloads/Linux/linuxthreads-2.1-patch}).
With @strong{glibc-2.2.2}
MySQL version 3.23.36 will use the adaptive mutex, which is much
@@ -9828,7 +8718,9 @@ that under some conditions, the current mutex code in @strong{glibc-2.2.2}
overspins, which hurts MySQL performance. The chance of this
condition can be reduced by renicing @code{mysqld} process to the highest
priority. We have also been able to correct the overspin behavior with
-a patch, available @uref{http://www.mysql.com/Downloads/Linux/linuxthreads-2.2.2.patch,here}. It combines the correction of overspin, maximum number of
+a patch, available at
+@uref{http://www.mysql.com/Downloads/Linux/linuxthreads-2.2.2.patch}.
+It combines the correction of overspin, maximum number of
threads, and stack spacing all in one. You will need to apply it in the
@code{linuxthreads} directory with
@code{patch -p0 </tmp/linuxthreads-2.2.2.patch}.
@@ -9874,11 +8766,12 @@ If you see a dead @code{mysqld} daemon process with @code{ps}, this usually
means that you have found a bug in MySQL or you have a corrupted
table. @xref{Crashing}.
-To get a core dump on Linux if @code{mysqld} dies with a SIGSEGV
-signal, you can start @code{mysqld} with the @code{--core-file} option. Note
+To get a core dump on Linux if @code{mysqld} dies with a SIGSEGV signal,
+you can start @code{mysqld} with the @code{--core-file} option. Note
that you also probably need to raise the @code{core file size} by adding
-@code{ulimit -c 1000000} to @code{safe_mysqld} or starting @code{safe_mysqld}
-with @code{--core-file-sizes=1000000}. @xref{safe_mysqld, , @code{safe_mysqld}}.
+@code{ulimit -c 1000000} to @code{safe_mysqld} or starting
+@code{safe_mysqld} with @code{--core-file-sizes=1000000}.
+@xref{safe_mysqld, , @code{safe_mysqld}}.
If you are linking your own MySQL client and get the error:
@@ -9923,6 +8816,13 @@ CC=fcc CFLAGS="-O -K fast -K lib -K omitfp -Kpreex -D_GNU_SOURCE -DCONST=const -
MySQL needs at least Linux Version 2.0.
+@strong{WARNING}:
+We have have reports from some MySQL users that they have got serious
+stability problems with MySQL with Linux kernel 2.2.14. If you are
+using this kernel you should upgrade to 2.2.19 (or newer) or to a 2.4
+kernel. If you have a multi-cpu box, then you should seriously consider
+using 2.4 as this will give you a significant speed boost.
+
The binary release is linked with @code{-static}, which means you do not
normally need to worry about which version of the system libraries you
have. You need not install LinuxThreads, either. A program linked with
@@ -10004,6 +8904,11 @@ also work. There have been some problems with the @code{glibc} RPMs from
RedHat, so if you have problems, check whether or not there are any updates!
The @code{glibc} 2.0.7-19 and 2.0.7-29 RPMs are known to work.
+If you are using gcc 3.0 and above to compile MySQL, you must install
+the @code{libstdc++v3} library before compiling MySQL; If you don't do
+this you will get an error about a missing @code{__cxa_pure_virtual}
+symbol during linking!
+
On some older Linux distributions, @code{configure} may produce an error
like this:
@@ -10056,6 +8961,8 @@ You can avoid using @file{libg++.a} by running @code{configure} like this:
shell> CXX=gcc ./configure
@end example
+If you are running gcc 3.0 and above, you can't use the above trick with
+setting to CXX=gcc.
@node Linux-SPARC, Linux-Alpha, Linux-x86, Linux
@subsubsection Linux SPARC Notes
@@ -10090,10 +8997,10 @@ kernel 2.2.13-SMP, Compaq C compiler (V6.2-504) and Compaq C++ compiler
(V6.3-005) on a Comaq DS20 machine with an Alpha EV6 processor.
You can find the above compilers at
-@uref{http://www.support.compaq.com/alpha-tools}). By using these compilers,
+@uref{http://www.support.compaq.com/alpha-tools/}). By using these compilers,
instead of gcc, we get about 9-14 % better performance with MySQL.
-Note that the configure line optimized the binary for the current CPU; This
+Note that the configure line optimised the binary for the current CPU; This
means you can only use our binary if you have an Alpha EV6 processor. We also
compile statically to avoid library problems.
@@ -10112,11 +9019,11 @@ Some known problems when running MySQL on Linux-Alpha:
@itemize @bullet
@item
Debugging threaded applications like MySQL will not work with
-@code{gdb 4.18}. You should download and use gdb 5.0 instead!
+@code{gdb 4.18}. You should download and use gdb 5.1 instead!
@item
If you try linking @code{mysqld} statically when using @code{gcc}, the
-resulting image will core dump at start. In other words, @strong{DON'T}
+resulting image will core dump at start. In other words, @strong{don't}
use @code{--with-mysqld-ldflags=-all-static} with @code{gcc}.
@end itemize
@@ -10158,9 +9065,9 @@ to the @code{LD_LIBRARY_PATH} environment variable.
@node Windows, Solaris, Linux, Operating System Specific Notes
@subsection Windows Notes
-This section describes installation and use of MySQL on Windows.
-This information is also provided in the @file{README} file that comes
-with the MySQL Windows distribution.
+This section describes using MySQL on Windows. This information
+is also provided in the @file{README} file that comes with the
+MySQL Windows distribution. @xref{Windows installation}.
@menu
* Win95 start:: Starting MySQL on Win95 / Win98
@@ -10168,7 +9075,7 @@ with the MySQL Windows distribution.
* Windows running:: Running MySQL on Windows
* Windows and SSH:: Connecting to a remote MySQL from Windows with SSH
* Windows symbolic links:: Splitting data across different disks under Win32
-* Windows compiling:: Compiling MySQL clients on Windows.
+* Windows client compiling:: Compiling MySQL clients on Windows.
* Windows vs Unix:: MySQL-Windows compared to Unix MySQL
@end menu
@@ -10178,16 +9085,18 @@ with the MySQL Windows distribution.
MySQL uses TCP/IP to connect a client to a server. (This will
allow any machine on your network to connect to your MySQL
-server.) Because of this, you must install TCP/IP on your machine before
-starting MySQL. You can find TCP/IP on your Windows CD-ROM.
+server.) Because of this, you must install TCP/IP on your
+machine before starting MySQL. You can find TCP/IP on your
+Windows CD-ROM.
-Note that if you are using an old Win95 release (for example OSR2), it's
-likely that you have an old Winsock package! MySQL requires
-Winsock 2! You can get the newest Winsock from
-@uref{http://www.microsoft.com/}. Win98 has the new Winsock 2 library, so
-the above doesn't apply for Win98.
+Note that if you are using an old Win95 release (for example
+OSR2), it's likely that you have an old Winsock package;
+MySQL requires Winsock 2! You can get the newest Winsock from
+@uref{http://www.microsoft.com/}. Win98 has the new Winsock 2
+library, so the above doesn't apply for Win98.
-To start the @code{mysqld} server, you should start an MS-DOS window and type:
+To start the @code{mysqld} server, you should start an MS-DOS
+window and type:
@example
C:\> C:\mysql\bin\mysqld
@@ -10201,104 +9110,110 @@ You can kill the MySQL server by executing:
C:\> C:\mysql\bin\mysqladmin -u root shutdown
@end example
+This calls the MySQL administation utility as user `root', which
+is the default Administrator in the MySQL grant system. Please
+note that the MySQL grant system is wholly independent from any
+login users under Windows.
+
Note that Win95 and Win98 don't support creation of named pipes.
On Win95 and Win98, you can only use named pipes to connect to a
-remote MySQL server running on a Windows NT server host.
-(The MySQL server must also support named pipes, of
-course. For example, using @code{mysqld-opt} under NT will not allow
-named pipe connections. You should use either @code{mysqld-nt} or
-@code{mysqld-max-nt}.)
+remote MySQL server running on a Windows NT/2000 server host.
+(The MySQL server must also support named pipes, of course.
+For example, using @code{mysqld-opt} under NT/2000 will not
+allow named pipe connections. You should use either
+@code{mysqld-nt} or @code{mysqld-max-nt}.)
If @code{mysqld} doesn't start, please check the
-@file{\mysql\data\mysql.err} file to see if the server wrote any message
-there to indicate the cause of the problem. You can also try to start
-the server with @code{mysqld --standalone}; In this case, you may get
-some useful information on the screen that may help solve the problem.
+@file{\mysql\data\mysql.err} file to see if the server wrote any
+message there to indicate the cause of the problem. You can also
+try to start the server with @code{mysqld --standalone}; In this
+case, you may get some useful information on the screen that may
+help solve the problem.
-The last option is to start @code{mysqld} with @code{--standalone
---debug}. In this case @code{mysqld} will write a log file
-@file{C:\mysqld.trace} that should contain the reason why @code{mysqld}
-doesn't start. @xref{Making trace files}.
+The last option is to start @code{mysqld} with
+@code{--standalone --debug}.
+In this case @code{mysqld} will write a log file
+@file{C:\mysqld.trace} that should contain the reason why
+@code{mysqld} doesn't start. @xref{Making trace files}.
+
+Use @code{mysqld --help} to display all the options that
+@code{mysqld} understands!
@node NT start, Windows running, Win95 start, Windows
@subsubsection Starting MySQL on Windows NT or Windows 2000
-The Win95/Win98 section also applies to MySQL on NT/Win2000, with
-the following differences:
-
-To get MySQL to work with TCP/IP on NT, you must install
+To get MySQL to work with TCP/IP on Windows NT 4, you must install
service pack 3 (or newer)!
-Note that everything in the following that applies for NT also applies
-for Win2000!
-
-For NT/Win2000, the server name is @code{mysqld-nt}. Normally you
-should install MySQL as a service on NT/Win2000:
+Normally you should install MySQL as a service on NT/Win2000.
+In case the server was already running, first stop it using
+the following command:
@example
-C:\> C:\mysql\bin\mysqld-nt --install
+C:\mysql\bin> mysqladmin -u root shutdown
@end example
-or
+This calls the MySQL administation utility as user `@code{root}',
+which is the default @code{Administrator} in the MySQL grant system.
+Please note that the MySQL grant system is wholly independent from
+any login users under Windows.
+
+Now install the server service:
@example
-C:\> C:\mysql\bin\mysqld-max-nt --install
+C:\mysql\bin> mysqld-max-nt --install
@end example
-(Under Windows NT, you can actually install any of the server binaries
-as a service, but only those having names that end with @code{-nt.exe}
-provide support for named pipes.)
+If any options are required, they must be specified as
+``@code{Start parameters}'' in the Windows @code{Services}
+utility before you start the MySQL service.
-You can start and stop the MySQL service with these commands:
+The @code{Services} utility
+(@code{Windows Service Control Manager}) can be found in the
+@code{Windows Control Panel} (under @code{Administrative Tools}
+on Windows 2000). It is advisable to close the Services utility
+while performing the @code{--install} or @code{--remove}
+operations, this prevents some odd errors.
-@example
-C:\> NET START mysql
-C:\> NET STOP mysql
-@end example
+For information about which server binary to run, see
+@ref{Windows prepare environment}.
-Note that in this case you can't use any other options for @code{mysqld-nt}!
+Please note that from MySQL version 3.23.44, you have the choice
+of set up the service as @code{Manual} instead (if you don't wish
+the service to be started automatically during the boot process):
-You can also run @code{mysqld-nt} as a stand-alone program on NT if you need
-to start @code{mysqld-nt} with any options! If you start @code{mysqld-nt}
-without options on NT, @code{mysqld-nt} tries to start itself as a service
-with the default service options. If you have stopped @code{mysqld-nt}, you
-have to start it with @code{NET START mysql}.
+@example
+C:\mysql\bin> mysqld-max-nt --install-manual
+@end example
-The service is installed with the name @code{MySQL}. Once installed, it must
-be started using the Services Control Manager (SCM) Utility found in the
-Control Panel, or by using the @code{NET START MySQL} command. If any options
-are desired, they must be specified as ``Startup parameters'' in the SCM utility
-before you start the MySQL service. Once running, @code{mysqld-nt}
-can be stopped using @code{mysqladmin}, or from the SCM utility or by using
-the command @code{NET STOP MySQL}. If you use SCM to stop @code{mysqld-nt},
-there is a strange message from SCM about @code{mysqld shutdown normally}.
-When run as a service, @code{mysqld-nt} has no access to a console and so no
-messages can be seen.
+The service is installed with the name @code{MySQL}. Once
+installed, it can be immediately started from the @code{Services}
+utility, or by using the command @code{NET START MySQL}.
-On NT you can get the following service error messages:
+Once running, @code{mysqld-max-nt} can be stopped using
+@code{mysqladmin}, from the Services utility or by using the
+command @code{NET STOP MySQL}.
-@multitable @columnfractions .3 .7
-@item Permission Denied @tab Means that it cannot find @code{mysqld-nt.exe}.
-@item Cannot Register @tab Means that the path is incorrect.
-@item Failed to install service. @tab Means that the service is already installed or that the Service Control Manager is in bad state.
-@end multitable
+Please note that when run as a service, @code{mysqld-max-nt}
+has no access to a console and so no messages can be seen.
+Errors can be checked in @file{c:\mysql\data\mysql.err}.
-If you have problems installing @code{mysqld-nt} as a service, try starting
-it with the full path:
+If you have problems installing @code{mysqld-max-nt} as a
+service, try starting it with the full path:
@example
-C:\> C:\mysql\bin\mysqld-nt --install
+C:\> C:\mysql\bin\mysqld-max-nt --install
@end example
-If this doesn't work, you can get @code{mysqld-nt} to start properly by fixing
-the path in the registry!
+If this doesn't work, you can get @code{mysqld-max-nt} to
+start properly by fixing the path in the registry!
-If you don't want to start @code{mysqld-nt} as a service, you can start it as
-follows:
+If you don't want to start @code{mysqld-max-nt} as a service,
+you can start it as follows:
@example
-C:\> C:\mysql\bin\mysqld-nt --standalone
+C:\> C:\mysql\bin\mysqld-max-nt --standalone
@end example
or
@@ -10307,8 +9222,8 @@ or
C:\> C:\mysql\bin\mysqld --standalone --debug
@end example
-The last version gives you a debug trace in @file{C:\mysqld.trace}.
-@xref{Making trace files}.
+The last method gives you a debug trace in
+@file{C:\mysqld.trace}. @xref{Making trace files}.
@node Windows running, Windows and SSH, NT start, Windows
@@ -10317,17 +9232,21 @@ The last version gives you a debug trace in @file{C:\mysqld.trace}.
@cindex TCP/IP
@cindex named pipes
-MySQL supports TCP/IP on all Windows platforms and named pipes on NT.
-The default is to use named pipes for local connections on NT and TCP/IP for
-all other cases if the client has TCP/IP installed. The host name specifies
-which protocol is used:
+MySQL supports TCP/IP on all Windows platforms and named pipes on
+NT/2000. The default is to use named pipes for local connections
+on NT/2000 and TCP/IP for all other cases if the client has TCP/IP
+installed. The host name specifies which protocol is used:
@multitable @columnfractions .3 .7
-@strong{Host name} @tab @strong{Protocol}
-@item NULL (none) @tab On NT, try named pipes first; if that doesn't work, use TCP/IP. On Win95/Win98, TCP/IP is used.
+@item @strong{Host name} @tab @strong{Protocol}
+@item NULL (none) @tab
+On NT/2000, try named pipes first; if that doesn't work, use TCP/IP.
+On Win95/Win98, TCP/IP is used.
@item . @tab Named pipes
-@item localhost @tab TCP/IP to current host
-@item hostname @tab TCP/IP
+@item localhost @tab
+TCP/IP to current host
+@item hostname @tab
+TCP/IP
@end multitable
You can force a MySQL client to use named pipes by specifying the
@@ -10354,6 +9273,7 @@ MySQL clients.
There are two versions of the MySQL command-line tool:
@multitable @columnfractions .25 .75
+@item @strong{Binary} @tab @strong{Description}
@item @code{mysql} @tab Compiled on native Windows, which offers very limited text editing capabilities.
@item @code{mysqlc} @tab Compiled with the Cygnus GNU compiler and libraries, which offers @code{readline} editing.
@end multitable
@@ -10437,14 +9357,14 @@ On your Windows machine, start some ODBC application (such as Access).
@item
Create a new file in Windows and link to MySQL using the ODBC
-driver the same way you normally do, EXCEPT type in @code{localhost}
+driver the same way you normally do, except type in @code{localhost}
for the MySQL host server --- not @code{yourmysqlservername}.
@end itemize
You should now have an ODBC connection to MySQL, encrypted using SSH.
-@node Windows symbolic links, Windows compiling, Windows and SSH, Windows
+@node Windows symbolic links, Windows client compiling, Windows and SSH, Windows
@subsubsection Splitting Data Across Different Disks on Windows
@cindex symbolic links
@@ -10484,7 +9404,7 @@ should instead use the @code{skip-symlink} option if you want to
disable this.
-@node Windows compiling, Windows vs Unix, Windows symbolic links, Windows
+@node Windows client compiling, Windows vs Unix, Windows symbolic links, Windows
@subsubsection Compiling MySQL Clients on Windows
@cindex compiling, on Windows
@@ -10508,7 +9428,7 @@ Note that as the mysqlclient libraries are compiled as threaded libraries,
you should also compile your code to be multi-threaded!
-@node Windows vs Unix, , Windows compiling, Windows
+@node Windows vs Unix, , Windows client compiling, Windows
@subsubsection MySQL-Windows Compared to Unix MySQL
@cindex Windows, versus Unix
@@ -10559,10 +9479,6 @@ connections.
We plan to fix this problem when our Windows developers have figured out a
nice workaround.
-@item UDF functions
-For the moment, MySQL-Windows does not support user-definable
-functions.
-
@item @code{DROP DATABASE}
You can't drop a database that is in use by some thread.
@@ -10632,12 +9548,18 @@ from usage by other threads. This has to do with the fact that on Windows,
you can't delete a file that is in use by another threads. (In the future,
we may find some way to work around this problem.)
-@item @code{DROP TABLE} on a table that is in use by a @code{MERGE} table will not work
-The @code{MERGE} handler does its table mapping hidden from MySQL.
-Because Windows doesn't allow you to drop files that are open, you first
-must flush all @code{MERGE} tables (with @code{FLUSH TABLES}) or drop the
-@code{MERGE} table before dropping the table. We will fix this at the same
-time we introduce @code{VIEW}s.
+@item
+@code{DROP TABLE} on a table that is in use by a @code{MERGE} table will
+not work on Windows because @code{MERGE} handler does the table mapping
+hidden from the upper layer of MySQL. Because Windows doesn't allow you
+to drop files that are open, you first must flush all @code{MERGE}
+tables (with @code{FLUSH TABLES}) or drop the @code{MERGE} table before
+dropping the table. We will fix this at the same time we introduce
+@code{VIEW}s.
+@item
+@code{DATA DIRECTORY} and @code{INDEX DIRECTORY} directives in
+@code{CREATE TABLE} is ignored on Windows, because Windows doesn't support
+symbolic links.
@end table
Here are some open issues for anyone who might want to help us with the Windows
@@ -10803,6 +9725,14 @@ libc internal error: _rmutex_unlock: rmutex not held
Add @code{-mt} to @code{CFLAGS} and @code{CXXFLAGS} and try again.
+If you are using the SFW version of gcc (which comes with Solaris 8),
+you must add @file{/opt/sfw/lib} to the environment variable
+@code{LD_LIBRARY_PATH} before running configure.
+
+If you are using the gcc available from @code{sunfreeware.com}, you may
+have many problems. You should recompile gcc and GNU binutils on the
+machine you will be running them from to avoid any problems.
+
If you get the following error when compiling MySQL with @code{gcc},
it means that your @code{gcc} is not configured for your version of Solaris:
@@ -10868,13 +9798,6 @@ Add the pathname of the directory where @file{libmysqlclient.so} is located
to the @code{LD_RUN_PATH} environment variable before running your client.
@end itemize
-When using the @code{--with-libwrap} configure option, you must also
-include the libraries that @file{libwrap.a} needs:
-
-@example
---with-libwrap="/opt/NUtcpwrapper-7.6/lib/libwrap.a -lnsl -lsocket
-@end example
-
If you have problems with configure trying to link with @code{-lz} and
you don't have @code{zlib} installed, you have two options:
@@ -11009,14 +9932,15 @@ it with a trace file or under @code{gdb}. @xref{Using gdb on mysqld}.
@node BSD Notes, Mac OS X, Solaris, Operating System Specific Notes
@subsection BSD Notes
+This section provides information for the various BSD flavours,
+as well as specific versions within those.
+
@menu
* FreeBSD:: FreeBSD Notes
* NetBSD:: NetBSD notes
-* OpenBSD:: OpenBSD Notes
-* OpenBSD 2.5:: OpenBSD 2.5 Notes
+* OpenBSD:: OpenBSD 2.5 Notes
* OpenBSD 2.8:: OpenBSD 2.8 Notes
-* BSDI:: BSD/OS Notes
-* BSDI2:: BSD/OS Version 2.x Notes
+* BSDI:: BSD/OS Version 2.x Notes
* BSDI3:: BSD/OS Version 3.x Notes
* BSDI4:: BSD/OS Version 4.x Notes
@end menu
@@ -11029,12 +9953,13 @@ FreeBSD 3.x is recommended for running MySQL since the thread package
is much more integrated.
The easiest and therefor the preferred way to install is to use the
-mysql-server and mysql-client ports available on @uref{http://www.freebsd.org}.
+mysql-server and mysql-client ports available on
+@uref{http://www.freebsd.org/}.
Using these gives you:
@itemize @bullet
@item
-A working MySQL with all optimizations known to work on your version
+A working MySQL with all optimisations known to work on your version
of FreeBSD enabled.
@item
@@ -11067,6 +9992,20 @@ correct (otherwise you will have problems connecting to the database). The
127.0.0.1 localhost localhost.your.domain
@end example
+The recommended way to compile and install MySQL on FreeBSD with
+gcc (2.95.2 and up) is:
+
+@example
+CC=gcc CFLAGS="-O2 -fno-strength-reduce" \
+CXX=gcc CXXFLAGS="-O2 -fno-rtti -fno-exceptions -felide-constructors -fno-strength-reduce" \
+./configure --prefix=/usr/local/mysql --enable-assembler
+gmake
+gmake install
+./scripts/mysql_install_db
+cd /usr/local/mysql
+./bin/mysqld_safe &
+@end example
+
If you notice that @code{configure} will use MIT-pthreads, you should read
the MIT-pthreads notes. @xref{MIT-pthreads}.
@@ -11087,11 +10026,16 @@ appropriate class for this user in the password file if you are not
using the default (use: chpass mysqld-user-name). @xref{safe_mysqld, ,
@code{safe_mysqld}}.
+If you have a lot of memory you should consider rebuilding
+the kernel to allow MySQL to take more than 512M of RAM.
+Take a look at @code{option MAXDSIZ} in the LINT config
+file for more info.
+
If you get problems with the current date in MySQL, setting the
@code{TZ} variable will probably help. @xref{Environment variables}.
To get a secure and stable system you should only use FreeBSD kernels
-that are marked @code{-STABLE}.
+that are marked @code{-RELEASE}.
@node NetBSD, OpenBSD, FreeBSD, BSD Notes
@@ -11101,16 +10045,7 @@ To compile on NetBSD you need GNU @code{make}. Otherwise the compile will
crash when @code{make} tries to run @code{lint} on C++ files.
-@node OpenBSD, OpenBSD 2.5, NetBSD, BSD Notes
-@subsubsection OpenBSD Notes
-
-@menu
-* OpenBSD 2.5:: OpenBSD 2.5 Notes
-* OpenBSD 2.8:: OpenBSD 2.8 Notes
-@end menu
-
-
-@node OpenBSD 2.5, OpenBSD 2.8, OpenBSD, BSD Notes
+@node OpenBSD, OpenBSD 2.8, NetBSD, BSD Notes
@subsubsection OpenBSD 2.5 Notes
On OpenBSD Version 2.5, you can compile MySQL with native threads
@@ -11121,7 +10056,7 @@ CFLAGS=-pthread CXXFLAGS=-pthread ./configure --with-mit-threads=no
@end example
-@node OpenBSD 2.8, BSDI, OpenBSD 2.5, BSD Notes
+@node OpenBSD 2.8, BSDI, OpenBSD, BSD Notes
@subsubsection OpenBSD 2.8 Notes
Our users have reported that OpenBSD 2.8 has a threading bug which causes
@@ -11131,17 +10066,7 @@ The symptoms of this threading bug are: slow response, high load, high CPU
usage, and crashes.
-@node BSDI, BSDI2, OpenBSD 2.8, BSD Notes
-@subsubsection BSD/OS Notes
-
-@menu
-* BSDI2:: BSD/OS 2.x notes
-* BSDI3:: BSD/OS 3.x notes
-* BSDI4:: BSD/OS 4.x notes
-@end menu
-
-
-@node BSDI2, BSDI3, BSDI, BSD Notes
+@node BSDI, BSDI3, OpenBSD 2.8, BSD Notes
@subsubsection BSD/OS Version 2.x Notes
If you get the following error when compiling MySQL, your
@@ -11166,7 +10091,7 @@ If you get problems with the current date in MySQL, setting the
@code{TZ} variable will probably help. @xref{Environment variables}.
-@node BSDI3, BSDI4, BSDI2, BSD Notes
+@node BSDI3, BSDI4, BSDI, BSD Notes
@subsubsection BSD/OS Version 3.x Notes
Upgrade to BSD/OS Version 3.1. If that is not possible, install
@@ -11230,7 +10155,7 @@ before running make.
Note that the above means that you can't symbolic link a database directories
to another database directory or symbolic link a table to another database
-on BSDI! (Making a symbolic link to another disk is ok).
+on BSDI! (Making a symbolic link to another disk is okay).
@node Mac OS X, Other Unix Notes, BSD Notes, Operating System Specific Notes
@@ -11372,7 +10297,7 @@ There are a couple of small problems when compiling MySQL on
HP-UX. We recommend that you use @code{gcc} instead of the HP-UX native
compiler, because @code{gcc} produces better code!
-We recommend using gcc 2.95 on HP-UX. Don't use high optimization
+We recommend using gcc 2.95 on HP-UX. Don't use high optimisation
flags (like -O6) as this may not be safe on HP-UX.
Note that MIT-pthreads can't be compiled with the HP-UX compiler
@@ -11381,7 +10306,7 @@ because it can't compile @code{.S} (assembler) files.
The following configure line should work:
@example
-CFLAGS="-DHPUX -I/opt/dce/include" CXXFLAGS="-DHPUX -I/opt/dce/include -felide-constructors -fno-exceptions -fno-rtti" CXX=gcc ./configure --with-pthread --with-named-thread-libs='-ldce' --prefix=/usr/local/mysql --disable-shared
+CFLAGS="-DHPUX -I/opt/dce/include -fpic" CXXFLAGS="-DHPUX -I/opt/dce/include -felide-constructors -fno-exceptions -fno-rtti" CXX=gcc ./configure --with-pthread --with-named-thread-libs='-ldce' --prefix=/usr/local/mysql --disable-shared
@end example
If you are compiling @code{gcc} 2.95 yourself, you should NOT link it with
@@ -11484,12 +10409,12 @@ MySQL with HP-UX:x compiler:
@itemize @bullet
@item
I had to use the compile-time flag @code{-D_REENTRANT} to get the compiler
-to recognize the prototype for @code{localtime_r}. Alternatively I could have
+to recognise the prototype for @code{localtime_r}. Alternatively I could have
supplied the prototype for @code{localtime_r}. But I wanted to catch other
bugs without needing to run into them. I wasn't sure where I needed it, so I
added it to all flags.
@item
-The optimization flags used by MySQL (-O3) are not recognized by HP's
+The optimisation flags used by MySQL (-O3) are not recognised by HP's
compilers. I did not change the flags.
@end itemize
@@ -11538,9 +10463,9 @@ you must also remove the @code{-qstrict} option (this is a limitation in
the IBM C compiler).
If you are using @code{gcc} or @code{egcs} to compile MySQL, you
-@strong{MUST} use the @code{-fno-exceptions} flag, as the exception
+@strong{must} use the @code{-fno-exceptions} flag, as the exception
handling in @code{gcc}/@code{egcs} is not thread safe! (This is tested with
-@code{egcs} 1.1.). There are also some known problems with IBM's assembler,
+@code{egcs} 1.1.) There are also some known problems with IBM's assembler,
which may cause it to generate bad code when used with gcc.
We recommend the following @code{configure} line with @code{egcs} and
@@ -11689,7 +10614,7 @@ work:
CC="cc -pthread"
CFLAGS="-O4 -ansi_alias -ansi_args -fast -inline speed all -arch host"
CXX="cxx -pthread"
-CXXFLAGS="-O4 -ansi_alias -ansi_args -fast -inline speed all -arch host"
+CXXFLAGS="-O4 -ansi_alias -ansi_args -fast -inline speed all -arch host -noexceptions -nortti"
export CC CFLAGS CXX CXXFLAGS
./configure \
--prefix=/usr/local/mysql \
@@ -11778,7 +10703,7 @@ The @code{alloca()} function also may have an incorrect prototype in
When using @code{gcc}, you can also try running @code{configure} like this:
@example
-shell> CFLAGS=-D_PTHREAD_USE_D4 CXX=gcc CXXFLAGS=-O3 ./configure ....
+shell> CFLAGS=-D_PTHREAD_USE_D4 CXX=gcc CXXFLAGS=-O3 ./configure ...
@end example
If you have problems with signals (MySQL dies unexpectedly
@@ -11807,7 +10732,7 @@ Please submit a full bug report.
To fix this you should change to the @code{sql} directory and do a ``cut
and paste'' of the last @code{gcc} line, but change @code{-O3} to
@code{-O0} (or add @code{-O0} immediately after @code{gcc} if you don't
-have any @code{-O} option on your compile line.) After this is done you
+have any @code{-O} option on your compile line). After this is done you
can just change back to the top-level directly and run @code{make}
again.
@@ -11835,7 +10760,7 @@ that defines @code{HAVE_READDIR_R}. You may have to remove the
@code{HAVE_TERM_H} line as well.
SGI recommends that you install all of the patches on this page as a set:
-http://support.sgi.com/surfzone/patches/patchset/6.2_indigo.rps.html
+@uref{http://support.sgi.com/surfzone/patches/patchset/6.2_indigo.rps.html}
At the very minimum, you should install the latest kernel rollup, the
latest @code{rld} rollup, and the latest @code{libc} rollup.
@@ -11880,7 +10805,7 @@ following is reported to work
CC=cc CXX=CC CFLAGS='-O3 -n32 -TARG:platform=IP22 -I/usr/local/include \
-L/usr/local/lib' CXXFLAGS='-O3 -n32 -TARG:platform=IP22 \
-I/usr/local/include -L/usr/local/lib' ./configure --prefix=/usr/local/mysql \
---with-berkeley-db --with-innodb \
+--with-innodb --with-berkeley-db \
--with-libwrap=/usr/local --with-named-curses-libs=/usr/local/lib/libncurses.a
@end example
@@ -12058,12 +10983,6 @@ CC=cc CXX=CC ./configure --prefix=/usr/local/mysql
If you want to use @code{gcc}, you must use @code{gcc} 2.95.2 or newer.
-
-@menu
-* OS/2:: OS/2 Notes
-@end menu
-
-
@node OS/2, BeOS, Other Unix Notes, Operating System Specific Notes
@subsection OS/2 Notes
@@ -12149,6 +11068,301 @@ with any technical questions they may have while doing the port.
+@node Perl support, , Operating System Specific Notes, Installing
+@section Perl Installation Comments
+
+@cindex Perl, installing
+@cindex installing, Perl
+
+@menu
+* Perl installation:: Installing Perl on Unix
+* ActiveState Perl:: Installing ActiveState Perl on Windows
+* Windows Perl:: Installing the MySQL Perl distribution on Windows
+* Perl support problems:: Problems using the Perl @code{DBI}/@code{DBD} interface
+@end menu
+
+
+@node Perl installation, ActiveState Perl, Perl support, Perl support
+@subsection Installing Perl on Unix
+
+Perl support for MySQL is provided by means of the
+@code{DBI}/@code{DBD} client interface. @xref{Perl}. The Perl
+@code{DBD}/@code{DBI} client code requires Perl Version 5.004 or later. The
+interface @strong{will not work} if you have an older version of Perl.
+
+MySQL Perl support also requires that you've installed
+MySQL client programming support. If you installed MySQL
+from RPM files, client programs are in the client RPM, but client programming
+support is in the developer RPM. Make sure you've installed the latter RPM.
+
+As of Version 3.22.8, Perl support is distributed separately from the main
+MySQL distribution. If you want to install Perl support, the files
+you will need can be obtained from
+@uref{http://www.mysql.com/Downloads/Contrib/}.
+
+The Perl distributions are provided as compressed @code{tar} archives and
+have names like @file{MODULE-VERSION.tar.gz}, where @code{MODULE} is the
+module name and @code{VERSION} is the version number. You should get the
+@code{Data-Dumper}, @code{DBI}, and @code{Msql-Mysql-modules} distributions
+and install them in that order. The installation procedure is shown below.
+The example shown is for the @code{Data-Dumper} module, but the procedure is
+the same for all three distributions:
+
+@enumerate
+@item
+Unpack the distribution into the current directory:
+@example
+shell> gunzip < Data-Dumper-VERSION.tar.gz | tar xvf -
+@end example
+This command creates a directory named @file{Data-Dumper-VERSION}.
+
+@item
+Change into the top-level directory of the unpacked distribution:
+@example
+shell> cd Data-Dumper-VERSION
+@end example
+
+@item
+Build the distribution and compile everything:
+@example
+shell> perl Makefile.PL
+shell> make
+shell> make test
+shell> make install
+@end example
+@end enumerate
+
+The @code{make test} command is important because it verifies that the
+module is working. Note that when you run that command during the
+@code{Msql-Mysql-modules} installation to exercise the interface code, the
+MySQL server must be running or the test will fail.
+
+It is a good idea to rebuild and reinstall the @code{Msql-Mysql-modules}
+distribution whenever you install a new release of MySQL,
+particularly if you notice symptoms such as all your @code{DBI} scripts
+dumping core after you upgrade MySQL.
+
+If you don't have the right to install Perl modules in the system directory
+or if you to install local Perl modules, the following reference may help
+you:
+
+@example
+@uref{http://www.iserver.com/support/contrib/perl5/modules.html}
+@end example
+
+Look under the heading
+@code{Installing New Modules that Require Locally Installed Modules}.
+
+
+@node ActiveState Perl, Windows Perl, Perl installation, Perl support
+@subsection Installing ActiveState Perl on Windows
+
+@cindex installing, Perl on Windows
+@cindex Perl, installing on Windows
+@cindex ActiveState Perl
+
+To install the MySQL @code{DBD} module with ActiveState Perl on
+Windows, you should do the following:
+
+@itemize @bullet
+@item
+Get ActiveState Perl from
+@uref{http://www.activestate.com/Products/ActivePerl/}
+and install it.
+
+@item
+Open a DOS shell.
+
+@item
+If required, set the HTTP_proxy variable. For example, you might try:
+
+@example
+set HTTP_proxy=my.proxy.com:3128
+@end example
+
+@item
+Start the PPM program:
+
+@example
+C:\> c:\perl\bin\ppm.pl
+@end example
+
+@item
+If you have not already done so, install @code{DBI}:
+
+@example
+ppm> install DBI
+@end example
+
+@item
+If this succeeds, run the following command:
+
+@example
+install ftp://ftp.de.uu.net/pub/CPAN/authors/id/JWIED/DBD-mysql-1.2212.x86.ppd
+@end example
+@end itemize
+
+The above should work at least with ActiveState Perl Version 5.6.
+
+If you can't get the above to work, you should instead install the
+@strong{MyODBC} driver and connect to MySQL server through
+ODBC:
+
+@example
+use DBI;
+$dbh= DBI->connect("DBI:ODBC:$dsn","$user","$password") ||
+ die "Got error $DBI::errstr when connecting to $dsn\n";
+@end example
+
+
+@node Windows Perl, Perl support problems, ActiveState Perl, Perl support
+@subsection Installing the MySQL Perl Distribution on Windows
+
+The MySQL Perl distribution contains @code{DBI},
+@code{DBD:MySQL} and @code{DBD:ODBC}.
+
+@itemize @bullet
+@item
+Get the Perl distribution for Windows from
+@uref{http://www.mysql.com/download.html}.
+
+@item
+Unzip the distribution in @code{C:} so that you get a @file{C:\PERL} directory.
+
+@item
+Add the directory @file{C:\PERL\BIN} to your path.
+
+@item
+Add the directory @file{C:\PERL\BIN\MSWIN32-x86-thread} or
+@file{C:\PERL\BIN\MSWIN32-x86} to your path.
+
+@item
+Test that @code{perl} works by executing @code{perl -v} in a DOS shell.
+@end itemize
+
+
+@node Perl support problems, , Windows Perl, Perl support
+@subsection Problems Using the Perl @code{DBI}/@code{DBD} Interface
+
+@cindex problems, installing Perl
+@cindex Perl DBI/DBD, installation problems
+
+If Perl reports that it can't find the @file{../mysql/mysql.so} module,
+then the problem is probably that Perl can't locate the shared library
+@file{libmysqlclient.so}.
+
+You can fix this by any of the following methods:
+
+@itemize @bullet
+@item
+Compile the @code{Msql-Mysql-modules} distribution with @code{perl
+Makefile.PL -static -config} rather than @code{perl Makefile.PL}.
+
+@item
+Copy @code{libmysqlclient.so} to the directory where your other shared
+libraries are located (probably @file{/usr/lib} or @file{/lib}).
+
+@item
+On Linux you can add the pathname of the directory where
+@file{libmysqlclient.so} is located to the @file{/etc/ld.so.conf} file.
+
+@tindex LD_RUN_PATH environment variable
+@tindex Environment variable, LD_RUN_PATH
+@item
+Add the pathname of the directory where @file{libmysqlclient.so} is located
+to the @code{LD_RUN_PATH} environment variable.
+@end itemize
+
+If you get the following errors from @code{DBD-mysql},
+you are probably using @code{gcc} (or using an old binary compiled with
+@code{gcc}):
+
+@example
+/usr/bin/perl: can't resolve symbol '__moddi3'
+/usr/bin/perl: can't resolve symbol '__divdi3'
+@end example
+
+Add @code{-L/usr/lib/gcc-lib/... -lgcc} to the link command when the
+@file{mysql.so} library gets built (check the output from @code{make} for
+@file{mysql.so} when you compile the Perl client). The @code{-L} option
+should specify the pathname of the directory where @file{libgcc.a} is located
+on your system.
+
+Another cause of this problem may be that Perl and MySQL aren't both
+compiled with @code{gcc}. In this case, you can solve the mismatch by
+compiling both with @code{gcc}.
+
+If you get the following error from @code{Msql-Mysql-modules}
+when you run the tests:
+
+@example
+t/00base............install_driver(mysql) failed: Can't load '../blib/arch/auto/DBD/mysql/mysql.so' for module DBD::mysql: ../blib/arch/auto/DBD/mysql/mysql.so: undefined symbol: uncompress at /usr/lib/perl5/5.00503/i586-linux/DynaLoader.pm line 169.
+@end example
+
+it means that you need to include the compression library, -lz, to the
+link line. This can be doing the following change in the file
+@file{lib/DBD/mysql/Install.pm}:
+
+@example
+$sysliblist .= " -lm";
+
+to
+
+$sysliblist .= " -lm -lz";
+@end example
+
+After this, you @strong{must} run 'make realclean' and then proceed with the
+installation from the beginning.
+
+If you want to use the Perl module on a system that doesn't support dynamic
+linking (like SCO) you can generate a static version of Perl that includes
+@code{DBI} and @code{DBD-mysql}. The way this works is that you generate a
+version of Perl with the @code{DBI} code linked in and install it on top of
+your current Perl. Then you use that to build a version of Perl that
+additionally has the @code{DBD} code linked in, and install that.
+
+On SCO, you must have the following environment variables set:
+
+@example
+shell> LD_LIBRARY_PATH=/lib:/usr/lib:/usr/local/lib:/usr/progressive/lib
+or
+shell> LD_LIBRARY_PATH=/usr/lib:/lib:/usr/local/lib:/usr/ccs/lib:/usr/progressive/lib:/usr/skunk/lib
+shell> LIBPATH=/usr/lib:/lib:/usr/local/lib:/usr/ccs/lib:/usr/progressive/lib:/usr/skunk/lib
+shell> MANPATH=scohelp:/usr/man:/usr/local1/man:/usr/local/man:/usr/skunk/man:
+@end example
+
+First, create a Perl that includes a statically linked @code{DBI} by running
+these commands in the directory where your @code{DBI} distribution is
+located:
+
+@example
+shell> perl Makefile.PL -static -config
+shell> make
+shell> make install
+shell> make perl
+@end example
+
+Then you must install the new Perl. The output of @code{make perl} will
+indicate the exact @code{make} command you will need to execute to perform
+the installation. On SCO, this is @code{make -f Makefile.aperl inst_perl
+MAP_TARGET=perl}.
+
+Next, use the just-created Perl to create another Perl that also includes a
+statically-linked @code{DBD::mysql} by running these commands in the
+directory where your @code{Msql-Mysql-modules} distribution is located:
+
+@example
+shell> perl Makefile.PL -static -config
+shell> make
+shell> make install
+shell> make perl
+@end example
+
+Finally, you should install this new Perl. Again, the output of @code{make
+perl} indicates the command to use.
+
+
+
@node Tutorial, MySQL Database Administration, Installing, Top
@chapter Introduction to MySQL: A MySQL Tutorial
@@ -12277,11 +11491,11 @@ that's okay. At this point, it's more important to find out a little about
how to issue queries than to jump right in creating tables, loading data
into them, and retrieving data from them. This section describes the basic
principles of entering commands, using several queries you can try out to
-familiarize yourself with how @code{mysql} works.
+familiarise yourself with how @code{mysql} works.
Here's a simple command that asks the server to tell you its version number
and the current date. Type it in as shown below following the @code{mysql>}
-prompt and hit the RETURN key:
+prompt and press Enter:
@example
mysql> SELECT VERSION(), CURRENT_DATE;
@@ -12406,7 +11620,7 @@ Here, too, notice the prompt. It switches back to @code{mysql>} after you
type @code{\c}, providing feedback to indicate that @code{mysql} is ready
for a new command.
-The following table shows each of the prompts you may see and summarizes what
+The following table shows each of the prompts you may see and summarises what
they mean about the state that @code{mysql} is in:
@cindex prompts, meanings
@@ -12432,7 +11646,7 @@ mysql> SELECT USER()
If this happens to you (you think you've entered a statement but the only
response is a @code{->} prompt), most likely @code{mysql} is waiting for the
semicolon. If you don't notice what the prompt is telling you, you might sit
-there for a while before realizing what you need to do. Enter a semicolon to
+there for a while before realising what you need to do. Enter a semicolon to
complete the statement, and @code{mysql} will execute it:
@example
@@ -12461,7 +11675,7 @@ mysql> SELECT * FROM my_table WHERE name = "Smith AND age < 30;
">
@end example
-If you enter this @code{SELECT} statement, then hit RETURN and wait for the
+If you enter this @code{SELECT} statement, then press Enter and wait for the
result, nothing will happen. Instead of wondering why this
query takes so long, notice the clue provided by the @code{">} prompt. It
tells you that @code{mysql} expects to see the rest of an unterminated
@@ -12531,11 +11745,11 @@ to think of real-world situations in which a similar type of database might
be used. For example, a database like this could be used by a farmer to keep
track of livestock, or by a veterinarian to keep track of patient records.
A menagerie distribution containing some of the queries and sample data used
-in the following sections can be obtained from the MySQL Web site.
-It's available in either
-@uref{http://www.mysql.com/Downloads/Contrib/Examples/menagerie.tar.gz,compressed @code{tar} format}
-or
-@uref{http://www.mysql.com/Downloads/Contrib/Examples/menagerie.zip,Zip format}.
+in the following sections can be obtained from the MySQL web site.
+It's available in either compressed @code{tar} format
+(@uref{http://www.mysql.com/Downloads/Contrib/Examples/menagerie.tar.gz})
+or Zip format
+(@uref{http://www.mysql.com/Downloads/Contrib/Examples/menagerie.zip}).
Use the @code{SHOW} statement to find out what databases currently exist
on the server:
@@ -12778,6 +11992,7 @@ use @code{NULL} values. To represent these in your text file, use
this (where the whitespace between values is a single tab character):
@multitable @columnfractions .15 .15 .15 .15 .25 .15
+@item @strong{name} @tab @strong{owner} @tab @strong{species} @tab @strong{sex} @tab @strong{birth} @tab @strong{death}
@item @code{Whistler} @tab @code{Gwen} @tab @code{bird} @tab @code{\N} @tab @code{1997-12-09} @tab @code{\N}
@end multitable
@@ -13037,7 +12252,7 @@ mysql> SELECT owner FROM pet;
@findex DISTINCT
However, notice that the query simply retrieves the @code{owner} field from
-each record, and some of them appear more than once. To minimize the output,
+each record, and some of them appear more than once. To minimise the output,
retrieve each unique output record just once by adding the keyword
@code{DISTINCT}:
@@ -13265,7 +12480,7 @@ mysql> SELECT name, birth, death,
+--------+------------+------------+------+
@end example
-The query uses @code{death IS NOT NULL} rather than @code{death != NULL}
+The query uses @code{death IS NOT NULL} rather than @code{death <> NULL}
because @code{NULL} is a special value. This is explained later.
@xref{Working with NULL, , Working with @code{NULL}}.
@@ -13350,12 +12565,12 @@ The @code{NULL} value can be surprising until you get used to it.
Conceptually, @code{NULL} means missing value or unknown value and it
is treated somewhat differently than other values. To test for @code{NULL},
you cannot use the arithmetic comparison operators such as @code{=}, @code{<},
-or @code{!=}. To demonstrate this for yourself, try the following query:
+or @code{<>}. To demonstrate this for yourself, try the following query:
@example
-mysql> SELECT 1 = NULL, 1 != NULL, 1 < NULL, 1 > NULL;
+mysql> SELECT 1 = NULL, 1 <> NULL, 1 < NULL, 1 > NULL;
+----------+-----------+----------+----------+
-| 1 = NULL | 1 != NULL | 1 < NULL | 1 > NULL |
+| 1 = NULL | 1 <> NULL | 1 < NULL | 1 > NULL |
+----------+-----------+----------+----------+
| NULL | NULL | NULL | NULL |
+----------+-----------+----------+----------+
@@ -13378,7 +12593,7 @@ The default truth value from a boolean operation is 1.
This special treatment of @code{NULL} is why, in the previous section, it
was necessary to determine which animals are no longer alive using
-@code{death IS NOT NULL} instead of @code{death != NULL}.
+@code{death IS NOT NULL} instead of @code{death <> NULL}.
@node Pattern matching, Counting rows, Working with NULL, Retrieving data
@@ -13396,7 +12611,7 @@ SQL pattern matching allows you to use @samp{_} to match any single
character and @samp{%} to match an arbitrary number of characters (including
zero characters). In MySQL, SQL patterns are case insensitive by
default. Some examples are shown below. Note that you do not use @code{=}
-or @code{!=} when you use SQL patterns; use the @code{LIKE} or @code{NOT
+or @code{<>} when you use SQL patterns; use the @code{LIKE} or @code{NOT
LIKE} comparison operators instead.
To find names beginning with @samp{b}:
@@ -13630,7 +12845,7 @@ ERROR 1140 at line 1: Mixing of GROUP columns (MIN(),MAX(),COUNT()...)
with no GROUP columns is illegal if there is no GROUP BY clause
@end example
-@code{COUNT()} and @code{GROUP BY} are useful for characterizing your
+@code{COUNT()} and @code{GROUP BY} are useful for characterising your
data in various ways. The following examples show different ways to
perform animal census operations.
@@ -13742,7 +12957,7 @@ A date so you know when the event occurred.
A field to describe the event.
@item
-An event type field, if you want to be able to categorize events.
+An event type field, if you want to be able to categorise events.
@end itemize
Given these considerations, the @code{CREATE TABLE} statement for the
@@ -13757,13 +12972,14 @@ As with the @code{pet} table, it's easiest to load the initial records
by creating a tab-delimited text file containing the information:
@multitable @columnfractions .15 .15 .15 .55
+@item @strong{name} @tab @strong{date} @tab @strong{type} @tab @strong{remark}
@item Fluffy @tab 1995-05-15 @tab litter @tab 4 kittens, 3 female, 1 male
@item Buffy @tab 1993-06-23 @tab litter @tab 5 puppies, 2 female, 3 male
@item Buffy @tab 1994-06-19 @tab litter @tab 3 puppies, 3 female
@item Chirpy @tab 1999-03-21 @tab vet @tab needed beak straightened
@item Slim @tab 1997-08-03 @tab vet @tab broken rib
-@item Bowser @tab 1991-10-12 @tab kennel
-@item Fang @tab 1991-10-12 @tab kennel
+@item Bowser @tab 1991-10-12 @tab kennel @tab
+@item Fang @tab 1991-10-12 @tab kennel @tab
@item Fang @tab 1998-08-28 @tab birthday @tab Gave him a new chew toy
@item Claws @tab 1998-03-17 @tab birthday @tab Gave him a new flea collar
@item Whistler @tab 1998-12-09 @tab birthday @tab First birthday
@@ -13971,6 +13187,7 @@ mysql> SELECT * FROM shop;
* example-Foreign keys:: Using foreign keys
* Searching on two keys:: Searching on Two Keys
* Calculating days:: Calculating visits per day
+* example-AUTO_INCREMENT:: Using AUTO_INCREMENT
@end menu
@@ -14154,22 +13371,26 @@ select * from shop where price=@@min_price or price=@@max_price;
@cindex foreign keys
@cindex keys, foreign
-You don't need foreign keys to join 2 tables.
+In MySQL 3.23.44 and up, @code{InnoDB} tables supports checking of
+foreign key constraints. @xref{InnoDB}.
+See also @ref{ANSI diff Foreign Keys}.
-The only thing MySQL doesn't do is @code{CHECK} to make sure that
-the keys you use really exist in the table(s) you're referencing and it
-doesn't automatically delete rows from table with a foreign key
+You don't actually need foreign keys to join 2 tables.
+The only thing MySQL currently doesn't do (in type types other than
+@code{InnoDB}), is @code{CHECK} to make sure that the keys you use
+really exist in the table(s) you're referencing and it
+doesn't automatically delete rows from a table with a foreign key
definition. If you use your keys like normal, it'll work just fine:
@example
-CREATE TABLE persons (
+CREATE TABLE person (
id SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT,
name CHAR(60) NOT NULL,
PRIMARY KEY (id)
);
-CREATE TABLE shirts (
+CREATE TABLE shirt (
id SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT,
style ENUM('t-shirt', 'polo', 'dress') NOT NULL,
color ENUM('red', 'blue', 'orange', 'white', 'black') NOT NULL,
@@ -14178,24 +13399,24 @@ CREATE TABLE shirts (
);
-INSERT INTO persons VALUES (NULL, 'Antonio Paz');
+INSERT INTO person VALUES (NULL, 'Antonio Paz');
-INSERT INTO shirts VALUES
+INSERT INTO shirt VALUES
(NULL, 'polo', 'blue', LAST_INSERT_ID()),
(NULL, 'dress', 'white', LAST_INSERT_ID()),
(NULL, 't-shirt', 'blue', LAST_INSERT_ID());
-INSERT INTO persons VALUES (NULL, 'Lilliana Angelovska');
+INSERT INTO person VALUES (NULL, 'Lilliana Angelovska');
-INSERT INTO shirts VALUES
+INSERT INTO shirt VALUES
(NULL, 'dress', 'orange', LAST_INSERT_ID()),
(NULL, 'polo', 'red', LAST_INSERT_ID()),
(NULL, 'dress', 'blue', LAST_INSERT_ID()),
(NULL, 't-shirt', 'white', LAST_INSERT_ID());
-SELECT * FROM persons;
+SELECT * FROM person;
+----+---------------------+
| id | name |
+----+---------------------+
@@ -14203,7 +13424,7 @@ SELECT * FROM persons;
| 2 | Lilliana Angelovska |
+----+---------------------+
-SELECT * FROM shirts;
+SELECT * FROM shirt;
+----+---------+--------+-------+
| id | style | color | owner |
+----+---------+--------+-------+
@@ -14217,7 +13438,7 @@ SELECT * FROM shirts;
+----+---------+--------+-------+
-SELECT s.* FROM persons p, shirts s
+SELECT s.* FROM person p, shirt s
WHERE p.name LIKE 'Lilliana%'
AND s.owner = p.id
AND s.color <> 'white';
@@ -14239,9 +13460,9 @@ SELECT s.* FROM persons p, shirts s
@cindex searching, two keys
@cindex keys, searching on two
-MySQL doesn't yet optimize when you search on two different
-keys combined with @code{OR} (Searching on one key with different @code{OR}
-parts is optimized quite good):
+MySQL doesn't yet optimise when you search on two different
+keys combined with @code{OR} (searching on one key with different @code{OR}
+parts is optimised quite well):
@example
SELECT field1_index, field2_index FROM test_table WHERE field1_index = '1'
@@ -14250,12 +13471,12 @@ OR field2_index = '1'
The reason is that we haven't yet had time to come up with an efficient
way to handle this in the general case. (The @code{AND} handling is,
-in comparison, now completely general and works very well).
+in comparison, now completely general and works very well.)
For the moment you can solve this very efficiently by using a
-@code{TEMPORARY} table. This type of optimization is also very good if
+@code{TEMPORARY} table. This type of optimisation is also very good if
you are using very complicated queries where the SQL server does the
-optimizations in the wrong order.
+optimisations in the wrong order.
@example
CREATE TEMPORARY TABLE tmp
@@ -14266,10 +13487,10 @@ SELECT * from tmp;
DROP TABLE tmp;
@end example
-The above way to solve this query is in effect an @code{UNION} of two queries.
+The above way to solve this query is in effect a @code{UNION} of two queries.
+@xref{UNION}.
-
-@node Calculating days, , Searching on two keys, Examples
+@node Calculating days, example-AUTO_INCREMENT, Searching on two keys, Examples
@subsection Calculating visits per day
@findex BIT_OR
@@ -14300,6 +13521,67 @@ The above calculates how many different days was used for a given
year/month combination, with automatic removal of duplicate entries.
+@node example-AUTO_INCREMENT, , Calculating days, Examples
+@subsection Using AUTO_INCREMENT
+
+@cindex AUTO_INCREMENT
+The @code{AUTO_INCREMENT} attribute can be used to generate an unique
+identity for new rows:
+
+@example
+CREATE TABLE animals (id mediumint not null auto_increment,
+name char(30) not null,
+primary key (id));
+INSERT INTO animals (name) values ("dog"),("cat"),("penguin"),("lax"),("whale");
+SELECT * FROM animals;
+
+Which returns:
+
++----+---------+
+| id | name |
++----+---------+
+| 1 | dog |
+| 2 | cat |
+| 3 | penguin |
+| 4 | lax |
+| 5 | whale |
++----+---------+
+@end example
+
+For MyISAM and BDB tables you can specify @code{AUTO_INCREMENT} on
+secondary column in a multi-column key. In this case the generated
+value for the autoincrement column is calculated as
+@code{MAX(auto_increment_column)+1) WHERE prefix=given-prefix}. This is
+useful when you want to put data into ordered groups.
+
+@example
+CREATE TABLE animals (grp enum ('fish','mammal','bird') not null,
+id mediumint not null auto_increment,
+name char(30) not null,
+primary key (grp,id));
+INSERT INTO animals (grp,name) values ("mammal","dog"),("mammal","cat"),("bird","penguin"),("fish","lax"),("mammal","whale");
+SELECT * FROM animals order by grp,id;
+
+Which returns:
+
++--------+----+---------+
+| grp | id | name |
++--------+----+---------+
+| fish | 1 | lax |
+| mammal | 1 | dog |
+| mammal | 2 | cat |
+| mammal | 3 | whale |
+| bird | 1 | penguin |
++--------+----+---------+
+@end example
+
+Note that in this case, the auto_increment value will be reused if you
+delete the row with the biggest auto_increment value in any group.
+
+You can get the used @code{AUTO_INCREMENT} key with the
+@code{LAST_INSERT_ID()} SQL function or the @code{mysql_insert_id()} API
+function.
+
@node Batch mode, Twin, Examples, Tutorial
@section Using @code{mysql} in Batch Mode
@@ -14424,11 +13706,8 @@ laboratory testing, neuroimaging, psychological status assessment, and family
history collection. In addition, data are collected on medical and
environmental risk factors.
-More information about Twin studies can be found at:
-
-@example
-@url{http://www.imm.ki.se/TWIN/TWINUKW.HTM}
-@end example
+More information about Twin studies can be found at:
+@uref{http://www.imm.ki.se/TWIN/TWINUKW.HTM}
The latter part of the project is administered with a Web interface
written using Perl and MySQL.
@@ -14538,7 +13817,7 @@ This identifies a twin in a pair. It has a value of @code{1} or @code{2}.
@item column @code{ptvab}
This is an inverse of @code{tvab}. When @code{tvab} is @code{1} this is
@code{2}, and vice versa. It exists to save typing and to make it easier for
-MySQL to optimize the query.
+MySQL to optimise the query.
@end table
This query demonstrates, among other things, how to do lookups on a
@@ -14603,9 +13882,9 @@ group by
@cindex Apache
-The Contrib section includes programs that let you authenticate your
-users from a MySQL database and also let you log your log files
-into a MySQL table. @xref{Contrib}.
+There are programs that let you authenticate your users from a MySQL
+database and also let you log your log files into a MySQL table.
+@xref{Portals}.
You can change the Apache logging format to be easily readable by
MySQL by putting the following into the Apache configuration file:
@@ -14626,7 +13905,7 @@ FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' ESCAPED BY '\\'
-@node MySQL Database Administration, MySQL Optimization, Tutorial, Top
+@node MySQL Database Administration, MySQL Optimisation, Tutorial, Top
@chapter MySQL Database Administration
@menu
@@ -14635,7 +13914,7 @@ FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' ESCAPED BY '\\'
* User Account Management:: MySQL User Account Management
* Disaster Prevention:: Disaster Prevention and Recovery
* Database Administration:: Database Administration Language Reference
-* Localization:: MySQL Localization and International Usage
+* Localisation:: MySQL Localisation and International Usage
* Server-Side Scripts:: MySQL Server-Side Scripts and Utilities
* Client-Side Scripts:: MySQL Client-Side Scripts and Utilities
* Log Files:: The MySQL Log Files
@@ -14662,6 +13941,17 @@ FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' ESCAPED BY '\\'
@cindex options, command-line
@cindex mysqld options
+In most cases you should manage mysqld options through option files.
+@xref{Option files}.
+
+@code{mysqld} and @code{mysqld.server} reads options from the
+@code{mysqld} and @code{server} groups. @code{mysqld_safe} read options
+from the @code{mysqld}, @code{server}, @code{mysqld_safe} and
+@code{safe_mysqld} groups. An embedded MySQL server usually reads
+options from the @code{server}, @code{embedded} and
+@code{xxxxx_SERVER}, where @code{xxxxx} is the name of the application.
+
+
@code{mysqld} accepts the following command-line options:
@table @code
@@ -14698,21 +13988,25 @@ specify @code{--core-file-size} to @code{safe_mysqld}. @xref{safe_mysqld, ,
@item -h, --datadir=path
Path to the database root.
+@item --debug[...]=
+If MySQL is configured with @code{--with-debug}, you can use this
+option to get a trace file of what @code{mysqld} is doing.
+@xref{Making trace files}.
+
@item --default-character-set=charset
Set the default character set. @xref{Character sets}.
@item --default-table-type=type
Set the default table type for tables. @xref{Table types}.
-@item --debug[...]=
-If MySQL is configured with @code{--with-debug}, you can use this
-option to get a trace file of what @code{mysqld} is doing.
-@xref{Making trace files}.
-
@item --delay-key-write-for-all-tables
Don't flush key buffers between writes for any @code{MyISAM} table.
@xref{Server parameters}.
+@item --des-key-file=filename
+Read the default keys used by @code{des_encrypt()} and @code{des_decrypt()}
+from this file.
+
@item --enable-locking
Enable system locking. Note that if you use this option on a system
which a not fully working lockd() (as on Linux) you will easily get
@@ -14778,13 +14072,14 @@ also set this explicitely to @code{""} if you want to disable this
option. If this option is used, @code{mysqld} will on open check if the
table is marked as crashed or if if the table wasn't closed properly.
(The last option only works if you are running with
-@code{--skip-locking}). If this is the case @code{mysqld} will run
+@code{--skip-locking}.) If this is the case @code{mysqld} will run
check on the table. If the table was corrupted, @code{mysqld} will
attempt to repair it.
The following options affects how the repair works.
@multitable @columnfractions .3 .7
+@item @strong{Option} @tab @strong{Description}
@item DEFAULT @tab The same as not giving any option to
@code{--myisam-recover}.
@item BACKUP @tab If the data table was changed during recover, save a
@@ -14820,10 +14115,10 @@ Only use one thread (for debugging under Linux). @xref{Debugging server}.
Give a variable a value. @code{--help} lists variables. You can find a full
description for all variables in the @code{SHOW VARIABLES} section in this
manual. @xref{SHOW VARIABLES}. The tuning server parameters section includes
-information of how to optimize these. @xref{Server parameters}.
+information of how to optimise these. @xref{Server parameters}.
@item --safe-mode
-Skip some optimize stages. Implies @code{--skip-delay-key-write}.
+Skip some optimise stages. Implies @code{--skip-delay-key-write}.
@item --safe-show-database
Don't show databases for which the user doesn't have any privileges.
@@ -14836,7 +14131,7 @@ command, if the user doesn't have @code{INSERT} privilege to the
@item --skip-concurrent-insert
Turn off the ability to select and insert at the same time on @code{MyISAM}
tables. (This is only to be used if you think you have found a bug in this
-feature).
+feature.)
@item --skip-delay-key-write
Ignore the @code{delay_key_write} option for all tables.
@@ -14912,9 +14207,9 @@ Sets the default transaction isolation level. @xref{SET TRANSACTION}.
Path for temporary files. It may be useful if your default @code{/tmp}
directory resides on a partition too small to hold temporary tables.
-@item -u, --user=user_name
-Run @code{mysqld} daemon as user @code{user_name}. This option is
-@emph{mandatory} when starting @code{mysqld} as root.
+@item -u, --user= [user_name | userid]
+Run @code{mysqld} daemon as user @code{user_name} or @code{userid} (numeric).
+This option is @emph{mandatory} when starting @code{mysqld} as root.
@item -V, --version
Output version information and exit.
@@ -14961,7 +14256,6 @@ MySQL reads default options from the following files on Windows:
@item @strong{Filename} @tab @strong{Purpose}
@item @code{windows-system-directory\my.ini} @tab Global options
@item @code{C:\my.cnf} @tab Global options
-@item @code{C:\mysql\data\my.cnf} @tab Server-specific options
@end multitable
Note that on Windows, you should specify all paths with @code{/} instead of
@@ -14978,11 +14272,13 @@ Options specified on the command line or in option files take precedence over
environment variable values. @xref{Environment variables}.
The following programs support option files: @code{mysql},
-@code{mysqladmin}, @code{mysqld}, @code{mysqldump}, @code{mysqlimport},
-@code{mysql.server}, @code{myisamchk}, and @code{myisampack}.
+@code{mysqladmin}, @code{mysqld}, @code{mysqld_safe}, @code{mysql.server},
+@code{mysqldump}, @code{mysqlimport}, @code{mysqlshow}, @code{mysqlcheck},
+@code{myisamchk}, and @code{myisampack}.
-You can use option files to specify any long option that a program supports!
-Run the program with @code{--help} to get a list of available options.
+Any long option that may be given on the command line when running a MySQL
+program can be given in an option file as well (without the leading double
+dash). Run the program with @code{--help} to get a list of available options.
An option file can contain lines of the following forms:
@@ -15064,6 +14360,7 @@ All MySQL clients that support option files support the
following options:
@multitable @columnfractions .40 .60
+@item @strong{Option} @tab @strong{Description}
@item --no-defaults @tab Don't read any option files.
@item --print-defaults @tab Print the program name and all options that it will get.
@item --defaults-file=full-path-to-default-file @tab Only use the given configuration file.
@@ -15141,28 +14438,28 @@ servers:
At least the following options should be different per server:
-@table @code
+@itemize
@item port=#
@item socket=path
@item pid-file=path
-@end table
+@end itemize
The following options should be different, if they are used:
-@table @code
+@itemize
@item log=path
@item log-bin=path
@item log-update=path
@item log-isam=path
@item bdb-logdir=path
-@end table
+@end itemize
If you want more performance, you can also specify the following differently:
-@table @code
+@itemize
@item tmpdir=path
@item bdb-tmpdir=path
-@end table
+@end itemize
@xref{Command-line options}.
@@ -15171,11 +14468,7 @@ start them with @code{./bin/safe_mysqld} then in most cases the only
option you need to add/change is the @code{socket} and @code{port}
argument to @code{safe_mysqld}.
-
-@menu
-* Multiple servers:: Running Multiple MySQL Servers on the Same Machine
-@end menu
-
+@xref{Multiple servers, ,Running Multiple MySQL Servers on the Same Machine}.
@node Multiple servers, , Installing many servers, Configuring MySQL
@subsection Running Multiple MySQL Servers on the Same Machine
@@ -15242,16 +14535,16 @@ files to @code{safe_mysqld} with @code{--log}, @code{--log-update}, or
@code{--log-slow-queries}. Otherwise, both servers may be trying to
write to the same log file.
-@strong{WARNING}: Normally you should never have two servers that update
+@strong{Warning}: Normally you should never have two servers that update
data in the same database! If your OS doesn't support fault-free system
locking, this may lead to unpleasant surprises!
If you want to use another database directory for the second server, you
can use the @code{--datadir=path} option to @code{safe_mysqld}.
-@strong{NOTE} also that starting several MySQL servers
+@strong{Note} also that starting several MySQL servers
(@code{mysqlds}) in different machines and letting them access one data
-directory over @code{NFS} is generally a @strong{BAD IDEA}! The problem
+directory over @code{NFS} is generally a @strong{bad idea}! The problem
is that the @code{NFS} will become the bottleneck with the speed. It is
not meant for such use. And last but not least, you would still have to
come up with a solution how to make sure that two or more @code{mysqlds}
@@ -15354,11 +14647,12 @@ When running MySQL, follow these guidelines whenever possible:
@itemize @bullet
@item
-DON'T EVER GIVE ANYONE (EXCEPT THE MySQL ROOT USER) ACCESS TO THE
-@code{user} TABLE IN THE @code{mysql} DATABASE! The encrypted password
-is the real password in MySQL. If you know the password listed in
-the @code{user} table for a given user, you can easily log in as that
-user if you have access to the host listed for that account.
+@strong{Do not ever give anyone (except the mysql root user) access to the
+@code{user} table in the @code{mysql} database!} This is critical.
+@strong{The encrypted password is the real password in MySQL.}
+Anyone who knows the password which is listed in the @code{user} table
+and has access to the host listed for the account @strong{can easily log
+in as that user}.
@item
Learn the MySQL access privilege system. The @code{GRANT} and
@@ -15397,7 +14691,7 @@ for someone who does not know it.
@item
Invest in a firewall. This protects you from at least 50% of all types of
exploits in any software. Put MySQL behind the firewall or in
-a demilitarized zone (DMZ).
+a demilitarised zone (DMZ).
Checklist:
@itemize @minus
@@ -15498,7 +14792,7 @@ Users of Java JDBC:
Do not transmit plain (unencrypted) data over the Internet. These data are
accessible to everyone who has the time and ability to intercept it and use
it for their own purposes. Instead, use an encrypted protocol such as SSL or
-SSH. MySQL supports internal SSL connections as of Version 3.23.9.
+SSH. MySQL supports internal SSL connections as of Version 4.0.0.
SSH port-forwarding can be used to create an encrypted (and compressed)
tunnel for the communication.
@item
@@ -15511,7 +14805,7 @@ shell> tcpdump -l -i eth0 -w - src or dst port 3306 | strings
@end example
(This works under Linux and should work with small modifications under
-other systems). Warning: If you do not see data this doesn't always
+other systems.) Warning: If you do not see data this doesn't always
actually mean that it is encrypted. If you need high security, you should
consult with a security expert.
@end itemize
@@ -15536,11 +14830,14 @@ All other information is transferred as text that can be read by anyone
who is able to watch the connection. If you are concerned about this,
you can use the compressed protocol (in MySQL Version 3.22 and above)
to make things much harder. To make things even more secure you should use
-@code{ssh}. You can find an open source @code{ssh} client at
-@uref{http://www.openssh.org}, and a commercial @code{ssh} client at
-@uref{http://www.ssh.com}. With this, you can get an encrypted TCP/IP
+@code{ssh}. You can find an Open Source @code{ssh} client at
+@uref{http://www.openssh.org/}, and a commercial @code{ssh} client at
+@uref{http://www.ssh.com/}. With this, you can get an encrypted TCP/IP
connection between a MySQL server and a MySQL client.
+If you are using MySQL 4.0, you can also use internal openssl support.
+@xref{Secure connections}.
+
To make a MySQL system secure, you should strongly consider the
following suggestions:
@@ -15556,8 +14853,7 @@ this:
@example
shell> mysql -u root mysql
-mysql> UPDATE user SET Password=PASSWORD('new_password')
- WHERE user='root';
+mysql> UPDATE user SET Password=PASSWORD('new_password') WHERE user='root';
mysql> FLUSH PRIVILEGES;
@end example
@@ -15585,12 +14881,11 @@ user=mysql
This will cause the server to start as the designated user whether you
start it manually or by using @code{safe_mysqld} or @code{mysql.server}.
-For more details, see @ref{Changing MySQL user, , Changing MySQL
-user}.
+For more details, see @ref{Changing MySQL user}.
@item
-Don't support symlinks to tables (This can be disabled with the
-@code{--skip-symlink} option. This is especially important if you run
+Don't support symlinks to tables (this can be disabled with the
+@code{--skip-symlink} option). This is especially important if you run
@code{mysqld} as root as anyone that has write access to the mysqld data
directories could then delete any file in the system!
@xref{Symbolic links to tables}.
@@ -15656,7 +14951,7 @@ new users with those privileges that the user has right to grant, you should
give the user the following privilege:
@example
-GRANT INSERT(user) on mysql.user to 'user'@'hostname';
+GRANT INSERT(user) on mysql.user to 'user'@@'hostname';
@end example
This will ensure that the user can't change any privilege columns directly,
@@ -15716,12 +15011,12 @@ privileges according to your identity and @strong{what you want to do}.
MySQL considers both your hostname and user name in identifying you
because there is little reason to assume that a given user name belongs to
the same person everywhere on the Internet. For example, the user
-@code{bill} who connects from @code{whitehouse.gov} need not be the same
-person as the user @code{bill} who connects from @code{microsoft.com}.
+@code{joe} who connects from @code{office.com} need not be the same
+person as the user @code{joe} who connects from @code{elsewhere.com}.
MySQL handles this by allowing you to distinguish users on different
-hosts that happen to have the same name: you can grant @code{bill} one set
-of privileges for connections from @code{whitehouse.gov}, and a different set
-of privileges for connections from @code{microsoft.com}.
+hosts that happen to have the same name: you can grant @code{joe} one set
+of privileges for connections from @code{office.com}, and a different set
+of privileges for connections from @code{elsewhere.com}.
MySQL access control involves two stages:
@@ -15742,26 +15037,26 @@ The server uses the @code{user}, @code{db}, and @code{host} tables in the
grant tables are shown below:
@multitable @columnfractions .2 .25 .25 .25
-@item @strong{Table name} @tab @code{user} @tab @code{db} @tab @code{host}
+@item @strong{Table name} @tab @code{user} @tab @code{db} @tab @code{host}
-@item @strong{Scope fields} @tab @code{Host} @tab @code{Host} @tab @code{Host}
-@item @tab @code{User} @tab @code{Db} @tab @code{Db}
-@item @tab @code{Password} @tab @code{User} @tab
+@item @strong{Scope fields} @tab @code{Host} @tab @code{Host} @tab @code{Host}
+@item @tab @code{User} @tab @code{Db} @tab @code{Db}
+@item @tab @code{Password} @tab @code{User} @tab
@item @strong{Privilege fields} @tab @code{Select_priv} @tab @code{Select_priv} @tab @code{Select_priv}
-@item @tab @code{Insert_priv} @tab @code{Insert_priv} @tab @code{Insert_priv}
-@item @tab @code{Update_priv} @tab @code{Update_priv} @tab @code{Update_priv}
-@item @tab @code{Delete_priv} @tab @code{Delete_priv} @tab @code{Delete_priv}
-@item @tab @code{Index_priv} @tab @code{Index_priv} @tab @code{Index_priv}
-@item @tab @code{Alter_priv} @tab @code{Alter_priv} @tab @code{Alter_priv}
-@item @tab @code{Create_priv} @tab @code{Create_priv} @tab @code{Create_priv}
-@item @tab @code{Drop_priv} @tab @code{Drop_priv} @tab @code{Drop_priv}
-@item @tab @code{Grant_priv} @tab @code{Grant_priv} @tab @code{Grant_priv}
-@item @tab @code{References_priv} @tab @tab
-@item @tab @code{Reload_priv} @tab @tab
-@item @tab @code{Shutdown_priv} @tab @tab
-@item @tab @code{Process_priv} @tab @tab
-@item @tab @code{File_priv} @tab @tab
+@item @tab @code{Insert_priv} @tab @code{Insert_priv} @tab @code{Insert_priv}
+@item @tab @code{Update_priv} @tab @code{Update_priv} @tab @code{Update_priv}
+@item @tab @code{Delete_priv} @tab @code{Delete_priv} @tab @code{Delete_priv}
+@item @tab @code{Index_priv} @tab @code{Index_priv} @tab @code{Index_priv}
+@item @tab @code{Alter_priv} @tab @code{Alter_priv} @tab @code{Alter_priv}
+@item @tab @code{Create_priv} @tab @code{Create_priv} @tab @code{Create_priv}
+@item @tab @code{Drop_priv} @tab @code{Drop_priv} @tab @code{Drop_priv}
+@item @tab @code{Grant_priv} @tab @code{Grant_priv} @tab @code{Grant_priv}
+@item @tab @code{References_priv} @tab @tab
+@item @tab @code{Reload_priv} @tab @tab
+@item @tab @code{Shutdown_priv} @tab @tab
+@item @tab @code{Process_priv} @tab @tab
+@item @tab @code{File_priv} @tab @tab
@end multitable
For the second stage of access control (request verification), the server
@@ -15815,14 +15110,14 @@ Scope fields are strings, declared as shown below; the default value for
each is the empty string:
@multitable @columnfractions .15 .15 .7
-@item @strong{Field name} @tab @strong{Type}
-@item @code{Host} @tab @code{CHAR(60)}
-@item @code{User} @tab @code{CHAR(16)}
-@item @code{Password} @tab @code{CHAR(16)}
-@item @code{Db} @tab @code{CHAR(64)} @tab (@code{CHAR(60)} for the
+@item @strong{Field name} @tab @strong{Type} @tab @strong{Notes}
+@item @code{Host} @tab @code{CHAR(60)} @tab
+@item @code{User} @tab @code{CHAR(16)} @tab
+@item @code{Password} @tab @code{CHAR(16)} @tab
+@item @code{Db} @tab @code{CHAR(64)} @tab (@code{CHAR(60)} for the
@code{tables_priv} and @code{columns_priv} tables)
-@item @code{Table_name} @tab @code{CHAR(60)}
-@item @code{Column_name} @tab @code{CHAR(60)}
+@item @code{Table_name} @tab @code{CHAR(60)} @tab
+@item @code{Column_name} @tab @code{CHAR(60)} @tab
@end multitable
In the @code{user}, @code{db} and @code{host} tables,
@@ -15833,13 +15128,18 @@ In the @code{tables_priv} and @code{columns_priv} tables, the privilege
fields are declared as @code{SET} fields:
@multitable @columnfractions .2 .2 .6
-@item @strong{Table name} @tab @strong{Field name} @tab @strong{Possible set elements}
-@item @code{tables_priv} @tab @code{Table_priv} @tab @code{'Select', 'Insert',
-'Update', 'Delete', 'Create', 'Drop', 'Grant', 'References', 'Index', 'Alter'}
-@item @code{tables_priv} @tab @code{Column_priv} @tab @code{'Select', 'Insert',
-'Update', 'References'}
-@item @code{columns_priv} @tab @code{Column_priv} @tab @code{'Select', 'Insert',
-'Update', 'References'}
+@item @strong{Table name}
+ @tab @strong{Field name}
+ @tab @strong{Possible set elements}
+@item @code{tables_priv}
+ @tab @code{Table_priv}
+ @tab @code{'Select', 'Insert', 'Update', 'Delete', 'Create', 'Drop', 'Grant', 'References', 'Index', 'Alter'}
+@item @code{tables_priv}
+ @tab @code{Column_priv}
+ @tab @code{'Select', 'Insert', 'Update', 'References'}
+@item @code{columns_priv}
+ @tab @code{Column_priv}
+ @tab @code{'Select', 'Insert', 'Update', 'References'}
@end multitable
Briefly, the server uses the grant tables like this:
@@ -16036,7 +15336,7 @@ currently executing queries, including queries that set or change passwords.
Privileges on the @code{mysql} database can be used to change passwords
and other access privilege information. (Passwords are stored
encrypted, so a malicious user cannot simply read them to know the plain
-text password). If they can access the @code{mysql.user} password
+text password.) If they can access the @code{mysql.user} password
column, they can use it to log into the MySQL server
for the given user. (With sufficient privileges, the same user can
replace a password with a different one.)
@@ -16079,7 +15379,7 @@ Alternate forms of the @code{-h}, @code{-u}, and @code{-p} options are
@code{--password=your_pass}. Note that there is @emph{no space} between
@code{-p} or @code{--password=} and the password following it.
-@strong{NOTE:} Specifying a password on the command line is not secure!
+@strong{Note:} Specifying a password on the command line is not secure!
Any user on your system may then find out your password by typing a command
like: @code{ps auxww}. @xref{Option files}.
@@ -16232,7 +15532,7 @@ MySQL does not store passwords in plaintext form for anyone to
see. Rather, the password supplied by a user who is attempting to
connect is encrypted (using the @code{PASSWORD()} function). The
encrypted password is then used when the client/server is checking if
-the password is correct (This is done without the encrypted password
+the password is correct. (This is done without the encrypted password
ever traveling over the connection.) Note that from MySQL's
point of view the encrypted password is the REAL password, so you should
not give anyone access to it! In particular, don't give normal users
@@ -16496,7 +15796,7 @@ tables and adds those to the user's privileges. Access is allowed or denied
based on the result.
Expressed in boolean terms, the preceding description of how a user's
-privileges are calculated may be summarized like this:
+privileges are calculated may be summarised like this:
@example
global privileges
@@ -16715,7 +16015,7 @@ hostname is an IP, even if you try to connect with a hostname:
@example
shell> mysqladmin -u root -pxxxx -h some-hostname ver
-Access denied for user: 'root@' (Using password: YES)
+Access denied for user: 'root@@' (Using password: YES)
@end example
This means that MySQL got some error when trying to resolve the
@@ -16880,6 +16180,7 @@ to restart @code{mysqld} with @code{--skip-grant-tables} to run
* Adding users:: Adding New Users to MySQL
* Passwords:: Setting Up Passwords
* Password security:: Keeping Your Password Secure
+* Secure connections:: Using Secure Connections
@end menu
@@ -16898,9 +16199,14 @@ to restart @code{mysqld} with @code{--skip-grant-tables} to run
@example
GRANT priv_type [(column_list)] [, priv_type [(column_list)] ...]
ON @{tbl_name | * | *.* | db_name.*@}
- TO user_name [IDENTIFIED BY 'password']
+ TO user_name [IDENTIFIED BY [PASSWORD] 'password']
[, user_name [IDENTIFIED BY 'password'] ...]
- [WITH GRANT OPTION]
+ [REQUIRE
+ [@{SSL| X509@}]
+ [CIPHER cipher [AND]]
+ [ISSUER issuer [AND]]
+ [SUBJECT subject]]
+ [WITH [GRANT OPTION | MAX_QUERIES_PER_HOUR=#]]
REVOKE priv_type [(column_list)] [, priv_type [(column_list)] ...]
ON @{tbl_name | * | *.* | db_name.*@}
@@ -16968,7 +16274,7 @@ you use a @code{column_list} clause) are @code{SELECT}, @code{INSERT}, and
You can set global privileges by using @code{ON *.*} syntax. You can set
database privileges by using @code{ON db_name.*} syntax. If you specify
@code{ON *} and you have a current database, you will set the privileges for
-that database. (@strong{WARNING:} If you specify @code{ON *} and you
+that database. (@strong{Warning:} If you specify @code{ON *} and you
@emph{don't} have a current database, you will affect the global privileges!)
In order to accommodate granting rights to users from arbitrary hosts,
@@ -16984,14 +16290,19 @@ You can specify wild cards in the hostname. For example,
for any host in the @code{144.155.166} class C subnet.
The simple form @code{user} is a synonym for @code{user@@"%"}.
-@strong{NOTE:} If you allow anonymous users to connect to the MySQL
-server (which is the default), you should also add all local users as
-@code{user@@localhost} because otherwise the anonymous user entry for the
-local host in the @code{mysql.user} table will be used when the user tries to
-log into the MySQL server from the local machine! Anonymous users
-are defined by inserting entries with @code{User=''} into the
-@code{mysql.user} table. You can verify if this applies to you by executing
-this query:
+
+MySQL doesn't support wildcards in user names. Anonymous users are
+defined by inserting entries with @code{User=''} into the
+@code{mysql.user} table or creating an user with an empty name with the
+@code{GRANT} command.
+
+@strong{Note:} If you allow anonymous users to connect to the MySQL
+server, you should also grant privileges to all local users as
+@code{user@@localhost} because otherwise the anonymous user entry for
+the local host in the @code{mysql.user} table will be used when the user
+tries to log into the MySQL server from the local machine!
+
+You can verify if this applies to you by executing this query:
@example
mysql> SELECT Host,User FROM mysql.user WHERE User='';
@@ -17034,7 +16345,10 @@ password will be set to the password specified by the @code{IDENTIFIED BY}
clause, if one is given. If the user already had a password, it is replaced
by the new one.
-@strong{WARNING:} If you create a new user but do not specify an
+Optional @code{PASSWORD} changes behaviour of @code{IDENTIFIED BY} from
+accepting plain password to accept encrypted password as argument.
+
+@strong{Warning:} If you create a new user but do not specify an
@code{IDENTIFIED BY} clause, the user has no password. This is insecure.
Passwords can also be set with the @code{SET PASSWORD} command.
@@ -17053,6 +16367,12 @@ to other users any privileges the user has at the specified privilege level.
You should be careful to whom you give the @strong{grant} privilege, as two
users with different privileges may be able to join privileges!
+@code{MAX_QUERIES_PER_HOUR=#} limits the number of queries the user can
+do during one hour. If @code{#} is 0, then this means that there is no
+limit of the number of queries. This works by MySQL resetting a user
+specific query counter to 0, after it has gone more than one hour
+since the counter started incrementing.
+
You cannot grant another user a privilege you don't have yourself;
the @strong{grant} privilege allows you to give away only those privileges
you possess.
@@ -17122,6 +16442,7 @@ dropped only with explicit @code{REVOKE} commands or by manipulating the
MySQL grant tables.
@end itemize
+For a description of using @code{REQUIRE}, see @xref{Secure connections}.
@node User names, Privilege changes, GRANT, User Account Management
@subsection MySQL User Names and Passwords
@@ -17186,7 +16507,7 @@ or the short form:
mysql -u monty -p database_name
@end example
-Note that in the last example the password is @strong{NOT} 'database_name'.
+Note that in the last example the password is @strong{not} 'database_name'.
If you want to use the @code{-p} option to supply a password you should do so
like this:
@@ -17249,7 +16570,7 @@ After installing MySQL, you set up the initial access privileges by
running @code{scripts/mysql_install_db}.
@xref{Quick install}.
The @code{mysql_install_db} script starts up the @code{mysqld}
-server, then initializes the grant tables to contain the following set
+server, then initialises the grant tables to contain the following set
of privileges:
@itemize @bullet
@@ -17257,7 +16578,7 @@ of privileges:
The MySQL @code{root} user is created as a superuser who can do
anything. Connections must be made from the local host.
-@strong{NOTE:}
+@strong{Note:}
The initial @code{root} password is empty, so anyone can connect as @code{root}
@emph{without a password} and be granted all privileges.
@@ -17273,7 +16594,7 @@ Other privileges are denied. For example, normal users can't use
@code{mysqladmin shutdown} or @code{mysqladmin processlist}.
@end itemize
-@strong{NOTE:} The default privileges are different for Windows.
+@strong{Note:} The default privileges are different for Windows.
@xref{Windows running}.
Because your installation is initially wide open, one of the first things you
@@ -17283,17 +16604,17 @@ password using the @code{PASSWORD()} function):
@example
shell> mysql -u root mysql
-mysql> UPDATE user SET Password=PASSWORD('new_password')
- WHERE user='root';
-mysql> FLUSH PRIVILEGES;
+mysql> SET PASSWORD FOR root@@localhost=PASSWORD('new_password');
@end example
-You can, in MySQL Version 3.22 and above, use the @code{SET PASSWORD}
-statement:
+If you know what you are doing, you can also directly manipulate the
+privilege tables:
@example
shell> mysql -u root mysql
-mysql> SET PASSWORD FOR root=PASSWORD('new_password');
+mysql> UPDATE user SET Password=PASSWORD('new_password')
+ WHERE user='root';
+mysql> FLUSH PRIVILEGES;
@end example
Another way to set the password is by using the @code{mysqladmin} command:
@@ -17334,8 +16655,8 @@ the database directory, which is listed when you run @code{mysqld
--help}.) Then run the @code{mysql_install_db} script, possibly after
editing it first to have the privileges you want.
-@strong{NOTE:} For MySQL versions older than Version 3.22.10,
-you should NOT delete the @file{.frm} files. If you accidentally do this,
+@strong{Note:} For MySQL versions older than Version 3.22.10,
+you should not delete the @file{.frm} files. If you accidentally do this,
you should copy them back from your MySQL distribution before
running @code{mysql_install_db}.
@@ -17355,8 +16676,8 @@ or by manipulating the MySQL grant tables directly. The
preferred method is to use @code{GRANT} statements, because they are
more concise and less error-prone. @xref{GRANT}.
-There is also a lot of contributed programs like @code{phpmyadmin} that
-can be used to create and administrate users. @xref{Contrib}.
+There are also a lot of contributed programs like @code{phpmyadmin}
+that can be used to create and administrate users. @xref{Portals}.
The examples below show how to use the @code{mysql} client to set up new
users. These examples assume that privileges are set up according to the
@@ -17530,9 +16851,8 @@ mysql> FLUSH PRIVILEGES;
You can also use @code{xmysqladmin}, @code{mysql_webadmin}, and even
@code{xmysql} to insert, change, and update values in the grant tables.
-You can find these utilities in the
-@uref{http://www.mysql.com/Downloads/Contrib/,Contrib directory of the MySQL
-Website}.
+You can find these utilities in the Contrib directory of the
+MySQL web site (@uref{http://www.mysql.com/Downloads/Contrib/}).
@node Passwords, Password security, Adding users, User Account Management
@@ -17616,7 +16936,7 @@ your Unix password and your MySQL password are the same, that
Unix password file. @xref{User names}.
-@node Password security, , Passwords, User Account Management
+@node Password security, Secure connections, Passwords, User Account Management
@subsection Keeping Your Password Secure
It is inadvisable to specify your password in a way that exposes it to
@@ -17637,7 +16957,7 @@ Use a @code{-pyour_pass} or @code{--password=your_pass} option on the command
line. This is convenient but insecure, because your password becomes visible
to system status programs (such as @code{ps}) that may be invoked by other
users to display command lines. (MySQL clients typically overwrite
-the command-line argument with zeroes during their initialization sequence,
+the command-line argument with zeroes during their initialisation sequence,
but there is still a brief interval during which the value is visible.)
@item
@@ -17692,6 +17012,181 @@ All in all, the safest methods are to have the client program prompt for the
password or to specify the password in a properly protected @file{.my.cnf}
file.
+@node Secure connections, , Password security, User Account Management
+@subsection Using Secure Connections
+
+@cindex openssl
+@cindex SSL and X509 Basics
+
+@menu
+* Secure basics:: Basics
+* Secure requirements:: Requirements
+* Secure GRANT:: GRANT OPTIONS
+@end menu
+
+@node Secure basics, Secure requirements, Secure connections, Secure connections
+@subsubsection Basics
+
+MySQL has support for SSL encrypted connections. To understand how MySQL
+uses SSL, we need to explain some basics about SSL and X509. People who
+are already aware of it can skip this part.
+
+By default, MySQL uses unencrypted connections between client and
+server. This means that someone could watch all your traffic and look at
+the data being sent/received. Actually, they could even change the data
+while it is in transit between client and server. Sometimes you need to
+move really secret data over public networks and in such a case using an
+unencrypted connection is unacceptable.
+
+SSL is a protocol which uses different encryption algorithms to ensure
+that data which comes from public network can be trusted. It has
+mechanisms to detect any change, loss or replay of data. SSL also
+incorpores algorithms to recognise and provide identity verification
+using the X509 standard.
+
+@cindex What is encryption
+Encryption is the way to make any kind of data unreadable. In fact,
+today's practice requires many additional security elements from
+encryption algorithms. They should resist many kind of known attacks
+like just messing with order of encrypted messages or replaying data
+twice.
+
+@cindex What is X509/Certificate?
+X509 is a standard that makes it possible to identify someone in the
+Internet. It is most commonly used in e-commerce applications. In basic
+terms, there should be some company called "Certificate Authority" which
+assigns electronic certificates to anyone who needs them. Certificates
+rely on asymmetric encryption algorithms which have two encryption keys
+- public and secret. A certificate owner can prove his identity by
+showing his certificate to other party. A certificate consists of his
+owner's public key. Any data encrypted with this public key can only be
+decrypted using the corresponding secret key, which is held by the owner
+of the certificate.
+
+MySQL doesn't use encrypted on connections by default, because this
+would make the client/server protocol much slower. Any kind of
+additional functionality requires computer to do additional work and
+encrypting data is CPU-intensive operation require time and can delay
+MySQL main tasks. By default MySQL is tuned to be fast as possible.
+
+If you need more information about SSL/X509/encryption, you should use
+your favourite internet search engine and search for keywords you are
+interested in.
+
+@node Secure requirements, Secure GRANT, Secure basics, Secure connections
+@subsubsection Requirements
+
+To get secure connections to work with MySQL you must do the following:
+
+@enumerate
+@item
+Install the openssl library. We have tested MySQL with openssl 0.9.6.
+@uref{http://www.openssl.org/}.
+@item
+Configure MySQL with @code{--with-vio --with-openssl}.
+@item
+If you are using an old MySQL installation, you have to update your
+@code{mysql.user} table with some new columns. You can do this by
+running the @code{mysql_fix_privilege_tables.sh} script.
+@item
+You can check if a running mysqld server supports @code{openssl} by
+examining if @code{SHOW VARIABLES LIKE 'have_openssl'} returns @code{YES}.
+@end enumerate
+
+
+@node Secure GRANT, , Secure requirements, Secure connections
+@subsubsection GRANT options
+
+@cindex SSL related options
+@findex REQUIRE GRANT option
+@findex GRANT statemenet
+
+MySQL can check X509 certificate attributes in addition to the
+normal username/password scheme. All the usual options are still
+required (username, password, IP address mask, database/table name).
+
+There are different possibilities to limit connections:
+
+@itemize @bullet
+@item
+Without any SSL/X509 options, all kind of encrypted/unencrypted
+connections are allowed if username and password are valid.
+
+@item
+@code{REQUIRE SSL} option limits the server to allow only SSL
+encrypted connections. Note that this option can be omitted
+if there are any ACL records which allow non-SSL connections.
+
+@example
+GRANT ALL PRIVILEGES ON test.* TO root@@localhost
+IDENTIFIED BY "goodsecret" REQUIRE SSL
+@end example
+
+@item
+@code{REQUIRE X509} means that client should have valid certificate
+but we do not care about the exact certificate, issuer or subject.
+The only restriction is that it should be possible to verify its
+signature with one of the CA certificates.
+
+@example
+GRANT ALL PRIVILEGES ON test.* TO root@@localhost
+IDENTIFIED BY "goodsecret" REQUIRE X509
+@end example
+
+@item
+@code{REQUIRE ISSUER issuer} makes connection more restrictive: now
+client must present a valid X509 certificate issued by CA "issuer".
+Using X509 certificates always implies encryption, so the option "SSL"
+is not neccessary anymore.
+
+@example
+GRANT ALL PRIVILEGES ON test.* TO root@@localhost
+IDENTIFIED BY "goodsecret"
+REQUIRE ISSUER "C=FI, ST=Some-State, L=Helsinki,
+O=MySQL Finland AB, CN=Tonu Samuel/Email=tonu@@mysql.com"
+@end example
+
+@item
+@code{REQUIRE SUBJECT subject} requires clients to have valid X509
+certificate with subject "subject" on it. If client have valid
+certificate but having different "subject" then the connection is
+still not allowed.
+
+@example
+GRANT ALL PRIVILEGES ON test.* TO root@@localhost
+IDENTIFIED BY "goodsecret"
+REQUIRE SUBJECT "C=EE, ST=Some-State, L=Tallinn,
+O=MySQL demo client certificate, CN=Tonu Samuel/Email=tonu@@mysql.com"
+@end example
+
+@item
+@code{REQUIRE CIPHER cipher} is needed to assure enough strong ciphers
+and keylengths will be used. SSL itself can be weak if old algorithms
+with short encryption keys are used. Using this option, we can ask for
+some exact cipher method to allow a connection.
+
+@example
+GRANT ALL PRIVILEGES ON test.* TO root@@localhost
+IDENTIFIED BY "goodsecret"
+REQUIRE CIPHER "EDH-RSA-DES-CBC3-SHA"
+@end example
+
+Also it is allowed to combine these options with each other like this:
+
+@example
+GRANT ALL PRIVILEGES ON test.* TO root@@localhost
+IDENTIFIED BY "goodsecret"
+REQUIRE SUBJECT "C=EE, ST=Some-State, L=Tallinn,
+O=MySQL demo client certificate, CN=Tonu Samuel/Email=tonu@@mysql.com"
+AND ISSUER "C=FI, ST=Some-State, L=Helsinki,
+O=MySQL Finland AB, CN=Tonu Samuel/Email=tonu@@mysql.com"
+AND CIPHER "EDH-RSA-DES-CBC3-SHA"
+@end example
+
+But it is not allowed to use any of options twice. Only different
+options can be mixed.
+@end itemize
+
@node Disaster Prevention, Database Administration, User Account Management, MySQL Database Administration
@section Disaster Prevention and Recovery
@@ -17760,8 +17255,8 @@ you executed @code{mysqldump}.
If you have to restore something, try to recover your tables using
@code{REPAIR TABLE} or @code{myisamchk -r} first. That should work in
99.9% of all cases. If @code{myisamchk} fails, try the following
-procedure: (This will only work if you have started MySQL with
-@code{--log-update}. @xref{Update log}.):
+procedure (this will only work if you have started MySQL with
+@code{--log-update}, @pxref{Update log}):
@enumerate
@item
@@ -17889,7 +17384,7 @@ CHECK TABLE tbl_name[,tbl_name...] [option [option...]]
option = QUICK | FAST | MEDIUM | EXTENDED | CHANGED
@end example
-@code{CHECK TABLE} only works on @code{MyISAM} tables. On
+@code{CHECK TABLE} only works on @code{MyISAM} and @code{InnoDB} tables. On
@code{MyISAM} tables it's the same thing as running @code{myisamchk -m
table_name} on the table.
@@ -17920,7 +17415,7 @@ The different check types stand for the following:
@item @code{QUICK} @tab Don't scan the rows to check for wrong links.
@item @code{FAST} @tab Only check tables which haven't been closed properly.
@item @code{CHANGED} @tab Only check tables which have been changed since last check or haven't been closed properly.
-@item @code{MEDIUM} @tab Scan rows to verify that deleted links are ok. This also calculates a key checksum for the rows and verifies this with a calcualted checksum for the keys.
+@item @code{MEDIUM} @tab Scan rows to verify that deleted links are okay. This also calculates a key checksum for the rows and verifies this with a calcualted checksum for the keys.
@item @code{EXTENDED} @tab Do a full key lookup for all keys for each row. This ensures that the table is 100 % consistent, but will take a long time!
@end multitable
@@ -17936,32 +17431,32 @@ CHECK TABLE test_table FAST QUICK;
Which only would do a quick check on the table if it wasn't closed properly.
-@strong{NOTE:} that in some case @code{CHECK TABLE} will change the
+@strong{Note:} that in some case @code{CHECK TABLE} will change the
table! This happens if the table is marked as 'corrupted' or 'not
closed properly' but @code{CHECK TABLE} didn't find any problems in the
-table. In this case @code{CHECK TABLE} will mark the table as ok.
+table. In this case @code{CHECK TABLE} will mark the table as okay.
If a table is corrupted, then it's most likely that the problem is in
the indexes and not in the data part. All of the above check types
checks the indexes throughly and should thus find most errors.
-If you just want to check a table that you assume is ok, you should use
-no check options or the @code{QUICK} option. The later should be used
+If you just want to check a table that you assume is okay, you should use
+no check options or the @code{QUICK} option. The latter should be used
when you are in a hurry and can take the very small risk that
-@code{QUICK} didn't find an error in the data file (In most cases
+@code{QUICK} didn't find an error in the data file. (In most cases
MySQL should find, under normal usage, any error in the data
file. If this happens then the table will be marked as 'corrupted',
-in which case the table can't be used until it's repaired).
+in which case the table can't be used until it's repaired.)
@code{FAST} and @code{CHANGED} are mostly intended to be used from a
script (for example to be executed from cron) if you want to check your
table from time to time. In most cases you @code{FAST} is to be prefered
over @code{CHANGED}. (The only case when it isn't is when you suspect a
-bug you have found a bug in the @code{MyISAM} code.).
+bug you have found a bug in the @code{MyISAM} code.)
@code{EXTENDED} is only to be used after you have run a normal check but
still get strange errors from a table when MySQL tries to
-update a row or find a row by key (this is VERY unlikely to happen if a
+update a row or find a row by key (this is very unlikely if a
normal check has succeeded!).
Some things reported by check table, can't be corrected automatically:
@@ -18046,13 +17541,13 @@ In the following text we will talk about @code{myisamchk}, but everything
also applies to the old @code{isamchk}.
You can use the @code{myisamchk} utility to get information about your
-database tables, check and repair them, or optimize them. The following
+database tables, check and repair them, or optimise them. The following
sections describe how to invoke @code{myisamchk} (including a
description of its options), how to set up a table maintenance schedule,
and how to use @code{myisamchk} to perform its various functions.
You can, in most cases, also use the command @code{OPTIMIZE TABLES} to
-optimize and repair tables, but this is not as fast or reliable (in case
+optimise and repair tables, but this is not as fast or reliable (in case
of real fatal errors) as @code{myisamchk}. On the other hand,
@code{OPTIMIZE TABLE} is easier to use and you don't have to worry about
flushing tables.
@@ -18072,7 +17567,7 @@ make a lot of changes to a table)
* Crash recovery:: Using @code{myisamchk} for Crash Recovery
* Check:: How to Check Tables for Errors
* Repair:: How to Repair Tables
-* Optimization:: Table Optimization
+* Optimisation:: Table Optimisation
@end menu
@@ -18157,14 +17652,6 @@ tables while you are running @code{myisamchk}. In MySQL Version 3.23
the easiest way to avoid this problem is to use @code{CHECK TABLE}
instead of @code{myisamchk} to check tables.
-@menu
-* myisamchk general options:: General Options for @code{myisamchk}
-* myisamchk check options:: Check Options for @code{myisamchk}
-* myisamchk repair options:: Repair Options for myisamchk
-* myisamchk other options:: Other Options for @code{myisamchk}
-@end menu
-
-
@node myisamchk general options, myisamchk check options, myisamchk syntax, Table maintenance
@subsubsection General Options for @code{myisamchk}
@@ -18183,6 +17670,7 @@ Display a help message and exit.
Set the value of a variable. The possible variables and their default values
for myisamchk can be examined with @code{myisamchk --help}:
@multitable @columnfractions .3 .7
+@item @strong{Variable} @tab @strong{Value}
@item key_buffer_size @tab 523264
@item read_buffer_size @tab 262136
@item write_buffer_size @tab 262136
@@ -18203,8 +17691,6 @@ through the key buffer is used in the following cases:
@item
If you use @code{--safe-recover}.
@item
-If you are using a @code{FULLTEXT} index.
-@item
If the temporary files needed to sort the keys would be more than twice
as big as when creating the key file directly. This is often the case
when you have big @code{CHAR}, @code{VARCHAR} or @code{TEXT} keys as the
@@ -18249,7 +17735,7 @@ Check table for errors. This is the default operation if you are not
giving @code{myisamchk} any options that override this.
@item -e or --extend-check
-Check the table VERY thoroughly (which is quite slow if you have many
+Check the table very thoroughly (which is quite slow if you have many
indexes). This option should only be used in extreme cases. Normally,
@code{myisamchk} or @code{myisamchk --medium-check} should, in most
cases, be able to find out if there are any errors in the table.
@@ -18356,8 +17842,8 @@ Other actions that @code{myisamchk} can do, besides repair and check tables:
@table @code
@item -a or --analyze
-Analyze the distribution of keys. This improves join performance by
-enabling the join optimizer to better choose in which order it should
+Analyse the distribution of keys. This improves join performance by
+enabling the join optimiser to better choose in which order it should
join the tables and which keys it should use:
@code{myisamchk --describe --verbose table_name'} or using @code{SHOW KEYS} in
MySQL.
@@ -18369,11 +17855,11 @@ given, then sets the next auto_increment value to the highest used value
for the auto key + 1.
@item -S or --sort-index
Sort the index tree blocks in high-low order.
-This will optimize seeks and will make table scanning by key faster.
+This will optimise seeks and will make table scanning by key faster.
@item -R or --sort-records=#
-Sorts records according to an index. This makes your data much more localized
+Sorts records according to an index. This makes your data much more localised
and may speed up ranged @code{SELECT} and @code{ORDER BY} operations on
-this index. (It may be VERY slow to do a sort the first time!)
+this index. (It may be very slow to do a sort the first time!)
To find out a table's index numbers, use @code{SHOW INDEX}, which shows a
table's indexes in the same order that @code{myisamchk} sees them. Indexes are
numbered beginning with 1.
@@ -18419,7 +17905,7 @@ index file is truncated at start, so one usually ignore this space.
This space is needed on the same disk as the original index file!
@item
When using @code{--recover} or @code{--sort-recover}
-(but not when using @code{--safe-recover}, you will need space for a
+(but not when using @code{--safe-recover}), you will need space for a
sort buffer for:
@code{(largest_key + row_pointer_length)*number_of_rows * 2}.
You can check the length of the keys and the row_pointer_length with
@@ -18454,14 +17940,16 @@ to check tables at any time. While you do this, all clients that try
to update the table will wait until @code{myisamchk} is ready before
continuing.
-If you use @code{myisamchk} to repair or optimize tables, you
-@strong{MUST} always ensure that the @code{mysqld} server is not using
+If you use @code{myisamchk} to repair or optimise tables, you
+@strong{must} always ensure that the @code{mysqld} server is not using
the table (this also applies if you are using @code{--skip-locking}).
If you don't take down @code{mysqld} you should at least do a
@code{mysqladmin flush-tables} before you run @code{myisamchk}.
+Your tables @strong{may be corrupted} if the server and @code{myisamchk}
+access the tables simultaneously.
This chapter describes how to check for and deal with data corruption
-in MySQL databases. If your tables get corrupted a lot you should
+in MySQL databases. If your tables get corrupted frequently you should
try to find the reason for this! @xref{Crashing}.
The @code{MyISAM} table section contains reason for why a table could be
@@ -18509,7 +17997,7 @@ To check a MyISAM table, use the following commands:
@table @code
@item myisamchk tbl_name
This finds 99.99% of all errors. What it can't find is corruption that
-involves @strong{ONLY} the data file (which is very unusual). If you want
+involves @strong{only} the data file (which is very unusual). If you want
to check a table, you should normally run @code{myisamchk} without options or
with either the @code{-s} or @code{--silent} option.
@@ -18522,7 +18010,7 @@ in the index tree.
@item myisamchk -e tbl_name
This does a complete and thorough check of all data (@code{-e} means
``extended check''). It does a check-read of every key for each row to verify
-that they indeed point to the correct row. This may take a LONG time on a
+that they indeed point to the correct row. This may take a long time on a
big table with many keys. @code{myisamchk} will normally stop after the first
error it finds. If you want to obtain more information, you can add the
@code{--verbose} (@code{-v}) option. This causes @code{myisamchk} to keep
@@ -18535,7 +18023,7 @@ print some informational statistics, too.
@end table
-@node Repair, Optimization, Check, Table maintenance
+@node Repair, Optimisation, Check, Table maintenance
@subsubsection How to Repair Tables
@cindex tables, repairing
@@ -18634,7 +18122,7 @@ memory} errors), or if @code{myisamchk} crashes, go to Stage 3.
@noindent
@strong{Stage 2: Easy safe repair}
-NOTE: If you want repairing to go much faster, you should add: @code{-O
+Note: If you want repairing to go much faster, you should add: @code{-O
sort_buffer=# -O key_buffer=#} (where # is about 1/4 of the available
memory) to all @code{isamchk/myisamchk} commands.
@@ -18720,11 +18208,11 @@ the index file.
@end enumerate
-@node Optimization, , Repair, Table maintenance
-@subsubsection Table Optimization
+@node Optimisation, , Repair, Table maintenance
+@subsubsection Table Optimisation
-@cindex tables, optimizing
-@cindex optimizing, tables
+@cindex tables, optimising
+@cindex optimising, tables
To coalesce fragmented records and eliminate wasted space resulting from
deleting or updating records, run @code{myisamchk} in recovery mode:
@@ -18733,9 +18221,9 @@ deleting or updating records, run @code{myisamchk} in recovery mode:
shell> myisamchk -r tbl_name
@end example
-You can optimize a table in the same way using the SQL @code{OPTIMIZE TABLE}
+You can optimise a table in the same way using the SQL @code{OPTIMIZE TABLE}
statement. @code{OPTIMIZE TABLE} does a repair of the table, a key
-analyzes and also sorts the index tree to give faster key lookups.
+analyses and also sorts the index tree to give faster key lookups.
There is also no possibility of unwanted interaction between a utility
and the server, because the server does all the work when you use
@code{OPTIMIZE TABLE}. @xref{OPTIMIZE TABLE}.
@@ -18743,11 +18231,11 @@ and the server, because the server does all the work when you use
@code{myisamchk} also has a number of other options you can use to improve
the performance of a table:
-@table @code
+@itemize
@item -S, --sort-index
@item -R index_num, --sort-records=index_num
@item -a, --analyze
-@end table
+@end itemize
For a full description of the option. @xref{myisamchk syntax}.
@@ -18828,7 +18316,7 @@ myisamchk -r --silent --sort-index -O sort_buffer_size=16M */*.MYI
To get a description of a table or statistics about it, use the commands shown
below. We explain some of the information in more detail later:
-@table @code
+@itemize @bullet
@item myisamchk -d tbl_name
Runs @code{myisamchk} in ``describe mode'' to produce a description of
your table. If you start the MySQL server using the
@@ -18847,7 +18335,7 @@ must read the whole table.
@item myisamchk -eiv tbl_name
This is like @code{-eis}, but tells you what is being done.
-@end table
+@end itemize
@cindex examples, @code{myisamchk} output
@cindex @code{myisamchk}, example output
@@ -18993,7 +18481,7 @@ Explanations for the types of information @code{myisamchk} produces are
given below. The ``keyfile'' is the index file. ``Record'' and ``row''
are synonymous:
-@table @code
+@itemize @bullet
@item ISAM file
Name of the ISAM (index) file.
@@ -19011,18 +18499,18 @@ How many records are in the table.
@item Deleted blocks
How many deleted blocks still have reserved space.
-You can optimize your table to minimize this space.
-@xref{Optimization}.
+You can optimise your table to minimise this space.
+@xref{Optimisation}.
@item Datafile: Parts
For dynamic record format, this indicates how many data blocks there are. For
-an optimized table without fragmented records, this is the same as @code{Data
+an optimised table without fragmented records, this is the same as @code{Data
records}.
@item Deleted data
How many bytes of non-reclaimed deleted data there are.
-You can optimize your table to minimize this space.
-@xref{Optimization}.
+You can optimise your table to minimise this space.
+@xref{Optimisation}.
@item Datafile pointer
The size of the data file pointer, in bytes. It is usually 2, 3, 4, or 5
@@ -19053,7 +18541,7 @@ Other possible values are @code{Compressed} and @code{Packed}.
A list of all keys in the table. For each key, some low-level information
is presented:
-@table @code
+@itemize @minus
@item Key
This key's number.
@@ -19082,19 +18570,19 @@ The size of each index block. By default this is 1024, but the value may be
changed at compile time.
@item Rec/key
-This is a statistical value used by the optimizer. It tells how many
+This is a statistical value used by the optimiser. It tells how many
records there are per value for this key. A unique key always has a
value of 1. This may be updated after a table is loaded (or greatly
changed) with @code{myisamchk -a}. If this is not updated at all, a default
value of 30 is given.
-@end table
+@end itemize
@item
In the first example above, the 9th key is a multi-part key with two parts.
@item Keyblocks used
What percentage of the keyblocks are used. Because the table used in the
-examples had just been reorganized with @code{myisamchk}, the values are very
+examples had just been reorganised with @code{myisamchk}, the values are very
high (very near the theoretical maximum).
@item Packed
@@ -19129,8 +18617,8 @@ What percentage of the data file is unused.
Average number of blocks per record (that is, how many links a fragmented
record is composed of). This is always 1 for fixed-format tables. This value
should stay as close to 1.0 as possible. If it gets too big, you can
-reorganize the table with @code{myisamchk}.
-@xref{Optimization}.
+reorganise the table with @code{myisamchk}.
+@xref{Optimisation}.
@item Recordblocks
How many blocks (links) are used. For fixed format, this is the same as the number
@@ -19153,7 +18641,7 @@ the sum of all such losses, in bytes.
When the dynamic table format is used, record fragments are linked with
pointers (4 to 7 bytes each). @code{Linkdata} is the sum of the amount of
storage used by all such pointers.
-@end table
+@end itemize
If a table has been compressed with @code{myisampack}, @code{myisamchk
-d} prints additional information about each table column. See
@@ -19161,7 +18649,7 @@ If a table has been compressed with @code{myisampack}, @code{myisamchk
information and a description of what it means.
-@node Database Administration, Localization, Disaster Prevention, MySQL Database Administration
+@node Database Administration, Localisation, Disaster Prevention, MySQL Database Administration
@section Database Administration Language Reference
@@ -19169,6 +18657,7 @@ information and a description of what it means.
* OPTIMIZE TABLE:: @code{OPTIMIZE TABLE} Syntax
* ANALYZE TABLE:: @code{ANALYZE TABLE} Syntax
* FLUSH:: @code{FLUSH} Syntax
+* RESET:: @code{RESET} Syntax
* KILL:: @code{KILL} Syntax
* SHOW:: @code{SHOW} Syntax
@end menu
@@ -19197,7 +18686,7 @@ For the moment @code{OPTIMIZE TABLE} only works on @strong{MyISAM} and
@code{BDB} tables. For @code{BDB} tables, @code{OPTIMIZE TABLE} is
currently mapped to @code{ANALYZE TABLE}. @xref{ANALYZE TABLE}.
-You can get optimize table to work on other table types by starting
+You can get optimise table to work on other table types by starting
@code{mysqld} with @code{--skip-new} or @code{--safe-mode}, but in this
case @code{OPTIMIZE TABLE} is just mapped to @code{ALTER TABLE}.
@@ -19229,8 +18718,8 @@ running!
ANALYZE TABLE tbl_name[,tbl_name...]
@end example
-Analyze and store the key distribution for the table. During the
-analyze the table is locked with a read lock. This works on
+Analyse and store the key distribution for the table. During the
+analyse the table is locked with a read lock. This works on
@code{MyISAM} and @code{BDB} tables.
This is equivalent to running @code{myisamchk -a} on the table.
@@ -19253,10 +18742,10 @@ You can check the stored key distribution with the @code{SHOW INDEX} command.
@xref{SHOW DATABASE INFO}.
If the table hasn't changed since the last @code{ANALYZE TABLE} command,
-the table will not be analyzed again.
+the table will not be analysed again.
-@node FLUSH, KILL, ANALYZE TABLE, Database Administration
+@node FLUSH, RESET, ANALYZE TABLE, Database Administration
@subsection @code{FLUSH} Syntax
@findex FLUSH
@@ -19276,6 +18765,8 @@ the @strong{RELOAD} privilege.
@code{flush_option} can be any of the following:
@multitable @columnfractions .15 .85
+@item @strong{Option} @tab @strong{Description}
+
@item @code{HOSTS} @tab Empties the host cache tables. You should flush the
host tables if some of your hosts change IP number or if you get the
error message @code{Host ... is blocked}. When more than
@@ -19283,9 +18774,11 @@ error message @code{Host ... is blocked}. When more than
connection to the MySQL server, MySQL assumes
something is wrong and blocks the host from further connection requests.
Flushing the host tables allows the host to attempt to connect
-again. @xref{Blocked host}.) You can start @code{mysqld} with
+again. @xref{Blocked host}. You can start @code{mysqld} with
@code{-O max_connection_errors=999999999} to avoid this error message.
+@item @code{DES_KEY_FILE} @tab Reloads the des keys from the file specified with @code{--des-key-file}.
+
@item @code{LOGS} @tab Closes and reopens all log files.
If you have specified the update log file or a binary log file without
an extension, the extension number of the log file will be incremented
@@ -19297,7 +18790,9 @@ signal to the @code{mysqld} server.
@item @code{PRIVILEGES} @tab Reloads the privileges from the grant tables in
the @code{mysql} database.
-@item @code{TABLES} @tab Closes all open tables and force all tables in use to be closed.
+@item @code{QUERY CACHE} @tab Defragment the query cache to better utilise its memory. This command will not remove any queries from the cache.
+
+@item @code{TABLES} @tab Closes all open tables and force all tables in use to be closed. This also flushes the query cache.
@item @code{[TABLE | TABLES] table_name [,table_name...]} @tab Flushes only the given tables.
@@ -19310,12 +18805,36 @@ You can also access each of the commands shown above with the @code{mysqladmin}
utility, using the @code{flush-hosts}, @code{flush-logs}, @code{reload},
or @code{flush-tables} commands.
-Take also a look at the @code{RESET} command used with
-replication. @xref{Replication SQL}.
+Take also a look at the @code{RESET} command used with replication.
+@xref{RESET}.
+
+@node RESET, KILL, FLUSH, Database Administration
+@subsection @code{RESET} Syntax
+@example
+FLUSH flush_option [,flush_option]
+@end example
+The @code{RESET} command is used to clear things. It also acts as an stronger
+version of the @code{FLUSH} command. @xref{FLUSH}.
-@node KILL, SHOW, FLUSH, Database Administration
+@multitable @columnfractions .15 .85
+@item @strong{Option} @tab @strong{Description}
+
+@item @code{MASTER}
+@tab Deletes all binary logs listed in the index file, resetting the binlog
+index file to be empty. In pre-3.23.26 versions, @code{FLUSH MASTER} (Master)
+
+@item @code{SLAVE}
+@tab Makes the slave forget its replication position in the master
+logs. In pre 3.23.26 versions the command was called
+@code{FLUSH SLAVE}(Slave)
+
+@item @code{QUERY CACHE}
+@tab Removes all query results from the query cache.
+@end multitable
+
+@node KILL, SHOW, RESET, Database Administration
@subsection @code{KILL} Syntax
@findex KILL
@@ -19369,12 +18888,6 @@ If the thread is waiting for free disk space in a @code{write} call, the
write is aborted with an disk full error message.
@end itemize
-
-@menu
-* SHOW:: @code{SHOW} Syntax
-@end menu
-
-
@node SHOW, , KILL, Database Administration
@subsection @code{SHOW} Syntax
@@ -19450,7 +18963,7 @@ host. You can also get this list using the @code{mysqlshow} command.
@code{SHOW TABLES} lists the tables in a given database. You can also
get this list using the @code{mysqlshow db_name} command.
-@strong{NOTE:} If a user doesn't have any privileges for a table, the table
+@strong{Note:} If a user doesn't have any privileges for a table, the table
will not show up in the output from @code{SHOW TABLES} or @code{mysqlshow
db_name}.
@@ -19495,13 +19008,16 @@ are returned:
@item @code{Sub_part} @tab Number of indexed characters if the
column is only partly indexed.
@code{NULL} if the entire key is indexed.
+@item @code{Null} $tab Contains 'YES' if the column may contain @code{NULL}.
+@item @code{Index_type} @tab Index method used.
@item @code{Comment} @tab Various remarks. For now, it tells
- whether index is FULLTEXT or not.
+in MySQL < 4.0.2 whether index is @code{FULLTEXT} or not.
@end multitable
Note that as the @code{Cardinality} is counted based on statistics
stored as integers, it's not necessarily accurate for small tables.
+The @code{Null} and @code{Index_type} columns were added in MySQL 4.0.2.
@node SHOW TABLE STATUS, SHOW STATUS, SHOW DATABASE INFO, SHOW
@subsubsection @code{SHOW TABLE STATUS}
@@ -19676,7 +19192,7 @@ open by the slave thread
acquired immediately. Available after 3.23.33.
@item @code{Table_locks_waited} @tab Number of times a table lock could not
be acquired immediately and a wait was needed. If this is high, and you
-have performance problems, you should first optimize your queries, and then
+have performance problems, you should first optimise your queries, and then
either split your table(s) or use replication. Available after 3.23.33.
@item @code{Threads_cached} @tab Number of threads in the thread cache.
@item @code{Threads_connected} @tab Number of currently open connections.
@@ -19701,7 +19217,12 @@ queries that require MySQL to scan whole tables or you have
joins that don't use keys properly.
@item
If @code{Threads_created} is big, you may want to increase the
-@code{thread_cache_size} variable.
+@code{thread_cache_size} variable. The cache hit rate can be calculated
+with @code{Threads_created}/@code{Connections}.
+@item
+If @code{Created_tmp_disk_tables} is big, you may want to increase the
+@code{tmp_table_size} variable to get the temporary tables memory based
+instead of disk based.
@end itemize
@@ -19722,85 +19243,93 @@ The output resembles that shown below, though the format and numbers may
differ somewhat:
@example
-+-------------------------+---------------------------+
-| Variable_name | Value |
-+-------------------------+---------------------------+
-| ansi_mode | OFF |
-| back_log | 50 |
-| basedir | /my/monty/ |
-| bdb_cache_size | 16777216 |
-| bdb_log_buffer_size | 32768 |
-| bdb_home | /my/monty/data/ |
-| bdb_max_lock | 10000 |
-| bdb_logdir | |
-| bdb_shared_data | OFF |
-| bdb_tmpdir | /tmp/ |
-| binlog_cache_size | 32768 |
-| concurrent_insert | ON |
-| connect_timeout | 5 |
-| datadir | /my/monty/data/ |
-| delay_key_write | ON |
-| delayed_insert_limit | 100 |
-| delayed_insert_timeout | 300 |
-| delayed_queue_size | 1000 |
-| flush | OFF |
-| flush_time | 0 |
-| have_bdb | YES |
-| have_innodb | YES |
-| have_raid | YES |
-| have_ssl | NO |
-| init_file | |
-| interactive_timeout | 28800 |
-| join_buffer_size | 131072 |
-| key_buffer_size | 16776192 |
-| language | /my/monty/share/english/ |
-| large_files_support | ON |
-| log | OFF |
-| log_update | OFF |
-| log_bin | OFF |
-| log_slave_updates | OFF |
-| long_query_time | 10 |
-| low_priority_updates | OFF |
-| lower_case_table_names | 0 |
-| max_allowed_packet | 1048576 |
-| max_binlog_cache_size | 4294967295 |
-| max_connections | 100 |
-| max_connect_errors | 10 |
-| max_delayed_threads | 20 |
-| max_heap_table_size | 16777216 |
-| max_join_size | 4294967295 |
-| max_sort_length | 1024 |
-| max_tmp_tables | 32 |
-| max_write_lock_count | 4294967295 |
-| myisam_recover_options | DEFAULT |
-| myisam_sort_buffer_size | 8388608 |
-| net_buffer_length | 16384 |
-| net_read_timeout | 30 |
-| net_retry_count | 10 |
-| net_write_timeout | 60 |
-| open_files_limit | 0 |
-| pid_file | /my/monty/data/donna.pid |
-| port | 3306 |
-| protocol_version | 10 |
-| record_buffer | 131072 |
-| query_buffer_size | 0 |
-| safe_show_database | OFF |
-| server_id | 0 |
-| skip_locking | ON |
-| skip_networking | OFF |
-| skip_show_database | OFF |
-| slow_launch_time | 2 |
-| socket | /tmp/mysql.sock |
-| sort_buffer | 2097116 |
-| table_cache | 64 |
-| table_type | MYISAM |
-| thread_cache_size | 4 |
-| thread_stack | 65536 |
-| tmp_table_size | 1048576 |
-| tmpdir | /tmp/ |
-| version | 3.23.29a-gamma-debug |
-| wait_timeout | 28800 |
-+-------------------------+---------------------------+
++------------------------------+---------------------------+
+| Variable_name | Value |
++------------------------------+---------------------------+
+| ansi_mode | OFF |
+| back_log | 50 |
+| basedir | /my/monty/ |
+| bdb_cache_size | 16777216 |
+| bdb_log_buffer_size | 32768 |
+| bdb_home | /my/monty/data/ |
+| bdb_max_lock | 10000 |
+| bdb_logdir | |
+| bdb_shared_data | OFF |
+| bdb_tmpdir | /tmp/ |
+| binlog_cache_size | 32768 |
+| concurrent_insert | ON |
+| connect_timeout | 5 |
+| datadir | /my/monty/data/ |
+| delay_key_write | ON |
+| delayed_insert_limit | 100 |
+| delayed_insert_timeout | 300 |
+| delayed_queue_size | 1000 |
+| flush | OFF |
+| flush_time | 0 |
+| ft_min_word_len | 4 |
+| ft_max_word_len | 254 |
+| ft_max_word_len_for_sort | 20 |
+| ft_boolean_syntax | + -><()~* |
+| have_bdb | YES |
+| have_innodb | YES |
+| have_raid | YES |
+| have_openssl | NO |
+| init_file | |
+| interactive_timeout | 28800 |
+| join_buffer_size | 131072 |
+| key_buffer_size | 16776192 |
+| language | /my/monty/share/english/ |
+| large_files_support | ON |
+| log | OFF |
+| log_update | OFF |
+| log_bin | OFF |
+| log_slave_updates | OFF |
+| long_query_time | 10 |
+| low_priority_updates | OFF |
+| lower_case_table_names | 0 |
+| max_allowed_packet | 1048576 |
+| max_binlog_cache_size | 4294967295 |
+| max_connections | 100 |
+| max_connect_errors | 10 |
+| max_delayed_threads | 20 |
+| max_heap_table_size | 16777216 |
+| max_join_size | 4294967295 |
+| max_sort_length | 1024 |
+| max_tmp_tables | 32 |
+| max_write_lock_count | 4294967295 |
+| myisam_bulk_insert_tree_size | 8388608 |
+| myisam_recover_options | DEFAULT |
+| myisam_sort_buffer_size | 8388608 |
+| net_buffer_length | 16384 |
+| net_read_timeout | 30 |
+| net_retry_count | 10 |
+| net_write_timeout | 60 |
+| open_files_limit | 0 |
+| pid_file | /my/monty/data/donna.pid |
+| port | 3306 |
+| protocol_version | 10 |
+| record_buffer | 131072 |
+| query_buffer_size | 0 |
+| query_cache_limit | 1048576 |
+| query_cache_size | 16768060 |
+| query_cache_startup_type | 1 |
+| safe_show_database | OFF |
+| server_id | 0 |
+| skip_locking | ON |
+| skip_networking | OFF |
+| skip_show_database | OFF |
+| slow_launch_time | 2 |
+| socket | /tmp/mysql.sock |
+| sort_buffer | 2097116 |
+| table_cache | 64 |
+| table_type | MYISAM |
+| thread_cache_size | 4 |
+| thread_stack | 65536 |
+| tmp_table_size | 1048576 |
+| tmpdir | /tmp/ |
+| version | 3.23.29a-gamma-debug |
+| wait_timeout | 28800 |
++------------------------------+---------------------------+
@end example
Each option is described below. Values for buffer sizes, lengths, and stack
@@ -19810,14 +19339,14 @@ indicates 16 megabytes. The case of suffix letters does not matter;
@code{16M} and @code{16m} are equivalent:
@cindex variables, values
-@table @code
+@itemize
@item @code{ansi_mode}.
Is @code{ON} if @code{mysqld} was started with @code{--ansi}.
@xref{ANSI mode}.
@item @code{back_log}
The number of outstanding connection requests MySQL can have. This
-comes into play when the main MySQL thread gets @strong{VERY}
+comes into play when the main MySQL thread gets @strong{very}
many connection requests in a very short time. It then takes some time
(although very little) for the main thread to check the connection and start
a new thread. The @code{back_log} value indicates how many requests can be
@@ -19878,10 +19407,10 @@ The default character set.
The supported character sets.
@item @code{concurrent_inserts}
-If @code{ON} (the default), MySQL will allow you to use @code{INSERT}
-on @code{MyISAM} tables at the same time as you run @code{SELECT} queries
-on them. You can turn this option off by starting @code{mysqld} with @code{--safe}
-or @code{--skip-new}.
+If @code{ON} (the default), MySQL will allow you to use @code{INSERT} on
+@code{MyISAM} tables at the same time as you run @code{SELECT} queries
+on them. You can turn this option off by starting @code{mysqld} with
+@code{--safe} or @code{--skip-new}.
@cindex timeout
@item @code{connect_timeout}
@@ -19927,15 +19456,42 @@ tables will be closed (to free up resources and sync things to disk). We
only recommend this option on Win95, Win98, or on systems where you have
very little resources.
-@item @code{have_bdb}
-@code{YES} if @code{mysqld} supports Berkeley DB tables. @code{DISABLED}
-if @code{--skip-bdb} is used.
+@item @code{ft_min_word_len}
+The minimum length of the word to be included in a @code{FULLTEXT} index.
+@strong{Note: @code{FULLTEXT} index have to be rebuilt after changing
+this variable.}
+
+@item @code{ft_max_word_len}
+The maximum length of the word to be included in a @code{FULLTEXT} index.
+@strong{Note: @code{FULLTEXT} index have to be rebuilt after changing
+this variable.}
+
+@item @code{ft_max_word_len_sort}
+The maximum length of the word in a @code{FULLTEXT} index
+to be used in fast index recreation method in @code{REPAIR},
+@code{CREATE INDEX}, or @code{ALTER TABLE}. Longer words are inserted the
+slow way. The rule of the thumb is as follows: with
+@code{ft_max_word_len_sort} increasing, @strong{MySQL} will create bigger
+temporary files (thus slowing the process down, due to disk I/O), and will put
+fewer keys in one sort block (againg, decreasing the efficiency). When
+@code{ft_max_word_len_sort} is too small, instead, @strong{MySQL} will insert a
+lot of words into index the slow way - but short words will be inserted very
+fast. It applies only to index recreation during @code{REPAIR},
+@code{CREATE INDEX}, or @code{ALTER TABLE}.
+
+@item @code{ft_boolean_syntax}
+List of operators supported by @code{MATCH ... AGAINST(... IN BOOLEAN MODE)}.
+@xref{Fulltext Search}.
+
@item @code{have_innodb}
@code{YES} if @code{mysqld} supports InnoDB tables. @code{DISABLED}
if @code{--skip-innodb} is used.
+@item @code{have_bdb}
+@code{YES} if @code{mysqld} supports Berkeley DB tables. @code{DISABLED}
+if @code{--skip-bdb} is used.
@item @code{have_raid}
@code{YES} if @code{mysqld} supports the @code{RAID} option.
-@item @code{have_ssl}
+@item @code{have_openssl}
@code{YES} if @code{mysqld} supports SSL (encryption) on the client/server
protocol.
@@ -19968,7 +19524,7 @@ Increase this to get better index handling (for all reads and multiple
writes) to as much as you can afford; 64M on a 256M machine that mainly
runs MySQL is quite common. If you, however, make this too big
(more than 50% of your total memory?) your system may start to page and
-become REALLY slow. Remember that because MySQL does not cache
+become extremely slow. Remember that because MySQL does not cache
data read, that you will have to leave some room for the OS filesystem
cache.
@@ -20016,13 +19572,14 @@ names will be case-insensitive.
@xref{Name case sensitivity}.
@item @code{max_allowed_packet}
-The maximum size of one packet. The message buffer is initialized to
+The maximum size of one packet. The message buffer is initialised to
@code{net_buffer_length} bytes, but can grow up to @code{max_allowed_packet}
bytes when needed. This value by default is small, to catch big (possibly
wrong) packets. You must increase this value if you are using big
@code{BLOB} columns. It should be as big as the biggest @code{BLOB} you want
-to use. The current protocol limits @code{max_allowed_packet} to 16M.
-
+to use. The protocol limits for @code{max_allowed_packet} is 16M in MySQL
+3.23 and 2G in MySQL 4.0.
+
@item @code{max_binlog_cache_size}
If a multi-statement transaction requires more than this amount of memory,
one will get the error "Multi-statement transaction required more than
@@ -20073,6 +19630,15 @@ Maximum number of temporary tables a client can keep open at the same time.
@item @code{max_write_lock_count}
After this many write locks, allow some read locks to run in between.
+@item @code{myisam_bulk_insert_tree_size}
+MySQL uses special tree-like cache to make bulk inserts (that is,
+@code{INSERT ... SELECT}, @code{INSERT ... VALUES (...), (...), ...}, and
+@code{LOAD DATA INFILE}) faster. This variable limits
+the size of the cache tree in bytes per thread. Setting it to 0
+will disable this optimization.
+@strong{Note:} This cache is only used when adding data to non-empty table.
+Default value is 8 MB.
+
@item @code{myisam_recover_options}
The value of the @code{--myisam-recover} option.
@@ -20147,6 +19713,22 @@ buffer to avoid a disk seeks. If not set, then it's set to the value of
The initial allocation of the query buffer. If most of your queries are
long (like when inserting blobs), you should increase this!
+@item @code{query_cache_limit}
+Don't cache results that are bigger than this. (Default 1M).
+
+@item @code{query_cache_size}
+The memory allocated to store results from old queries.
+If this is 0, the query cache is disabled (default).
+
+@item @code{query_cache_startup_type}
+This may be set (only numeric) to
+@multitable @columnfractions .1 .2 .7
+@item @strong{Value} @tab @strong{Alias} @tab @strong{Comment}
+@item 0 @tab OFF @tab Don't cache or retrieve results.
+@item 1 @tab ON @tab Cache all results except @code{SELECT SQL_NO_CACHE ...} queries.
+@item 2 @tab DEMAND @tab Cache only @code{SELECT SQL_CACHE ...} queries.
+@end multitable
+
@item @code{safe_show_databases}
Don't show databases for which the user doesn't have any database or
table privileges. This can improve security if you're concerned about
@@ -20188,19 +19770,13 @@ operations.
@item @code{table_cache}
The number of open tables for all threads. Increasing this value
increases the number of file descriptors that @code{mysqld} requires.
-MySQL needs two file descriptors for each unique open table.
-See below for comments on file descriptor limits. You can check if you
-need to increase the table cache by checking the @code{Opened_tables}
-variable. @xref{SHOW}. If this variable is big and you don't do
-@code{FLUSH TABLES} a lot (which just forces all tables to be closed and
-reopenend), then you should increase the value of this variable.
-
-Make sure that your operating system can handle the number of open file
-descriptors implied by the @code{table_cache} setting. If @code{table_cache}
-is set too high, MySQL may run out of file descriptors and refuse
-connections, fail to perform queries, and be very unreliable.
+You can check if you need to increase the table cache by checking the
+@code{Opened_tables} variable. @xref{SHOW}. If this variable is big and
+you don't do @code{FLUSH TABLES} a lot (which just forces all tables to
+be closed and reopenend), then you should increase the value of this
+variable.
-For information about how the table cache works, see @ref{Table cache}.
+For more information about the table cache, see @ref{Table cache}.
@item @code{table_type}
The default table type
@@ -20246,7 +19822,7 @@ The version number for the server.
@item @code{wait_timeout}
The number of seconds the server waits for activity on a connection before
closing it. See also @code{interactive_timeout}.
-@end table
+@end itemize
The manual section that describes tuning MySQL contains some
information of how to tune the above variables. @xref{Server parameters}.
@@ -20278,7 +19854,7 @@ subsystem)
@cindex threads, display
@cindex processes, display
-@code{SHOW PROCESSLIST} shows you which threads are running. You can
+@code{SHOW [FULL] PROCESSLIST} shows you which threads are running. You can
also get this information using the @code{mysqladmin processlist}
command. If you have the @strong{process} privilege, you can see all
threads. Otherwise, you can see only your own threads. @xref{KILL, ,
@@ -20291,6 +19867,105 @@ one extra connection for a client with the @code{Process_priv} privilege
to ensure that you should always be able to login and check the system
(assuming you are not giving this privilege to all your users).
+Some frequently states in @code{mysqladmin processlist}
+
+@itemize @bullet
+@item @code{Checking table}
+The thread doing an [automatic ?] checking of the table.
+@item @code{Closing tables}
+Means that the thread is flushing the changed table data to disk and
+closing the used tables. This should be a fast operation. If not, then
+you should check that you don't have a full disk or that the disk is not
+in very heavy use.
+@item @code{Connect Out}
+Slave connecting to master.
+@item @code{Copying to tmp table on disk}
+The temporary result set was larger than @code{tmp_table_size} and the
+thread is now changing the in memory based temporary table to a disk
+based one to save memory.
+@item @code{Creating tmp table}
+The thread is creating a temporary table to hold a part of the result for
+the query.
+@item @code{deleting from main table}
+When executing the first part of a multi-table delete and we are only
+deleting from the first table.
+@item @code{deleting from reference tables}
+When executing the second part of a multi-table delete and we are deleting
+the matched rows from the other tables.
+@item @code{Flushing tables}
+The thread is executing @code{FLUSH TABLES} and is waiting for all
+threads to close their tables.
+@item @code{Killed}
+Someone has sent a kill to the thread and it should abort next time it
+checks the kill flag. The flag is checked in each major loop in MySQL,
+but in some cases it may still take a short time for the thread to die.
+If the thread is locked by some other thread, the kill will take affect
+as soon as the other thread releases it's lock.
+@item @code{Sending data}
+The thread is processing rows for a @code{SELECT} statement and is
+also sending data to the client.
+@item @code{Sorting for group}
+The thread is doing a sort to satsify a @code{GROUP BY}.
+@item @code{Sorting for order}
+The thread is doing a sort to satsify a @code{ORDER BY}.
+@item @code{Opening tables}
+This simply means that the thread is trying to open a table. This is
+should be very fast procedure, unless something prevents opening. For
+example an @code{ALTER TABLE} or a @code{LOCK TABLE} can prevent opening
+a table until the command is finished.
+@item @code{Removing duplicates}
+The query was using @code{SELECT DISTINCT} in such a way that MySQL
+couldn't optimize that distinct away at an early stage. Because of this
+MySQL has to do an extra stage to remove all duplicated rows before
+sending the result to the client.
+@item @code{Reopen table}
+The thread got a lock for the table, but noticed after getting the lock
+that the underlying table structure changed. It has freed the lock,
+closed the table and is now trying to reopen it.
+@item @code{Repair by sorting}
+The repair code is using sorting to create indexes.
+@item @code{Repair with keycache}
+The repair code is using creating keys one by one through the key cache.
+This is much slower than @code{Repair by sorting}.
+@item @code{Searching rows for update}
+The thread is doing a first phase to find all matching rows before
+updating them. This has to be done if the @code{UPDATE} is changing
+the index that is used to find the involved rows.
+@item @code{Sleeping}
+The thread is wating for the client to send a new command to it.
+@item @code{System lock}
+The thread is waiting for getting to get a external system lock for the
+table. If you are not using multiple mysqld servers that are accessing
+the same tables, you can disable system locks with the
+@code{--skip-locking} option.
+@item @code{Upgrading lock}
+The @code{INSERT DELAYED} handler is trying to get a lock for the table
+to insert rows.
+@item @code{Updating}
+The thread is searching for rows to update and updating them.
+@item @code{User Lock}
+The thread is waiting on a @code{GET_LOCK()}.
+@item @code{Waiting for tables}
+The thread got a notification that the underlying structure for a table
+has changed and it needs to reopen the table to get the new structure.
+To be able to reopen the table it must however wait until all other
+threads have closed the table in question.
+
+This notification happens if another thread has used @code{FLUSH TABLES}
+or one of the following commands on the table in question: @code{FLUSH
+TABLES table_name}, @code{ALTER TABLE}, @code{RENAME TABLE},
+@code{REPAIR TABLE}, @code{ANALYZE TABLE} or @code{OPTIMIZE TABLE}.
+@item @code{waiting for handler insert}
+The @code{INSERT DELAYED} handler has processed all inserts and are
+waiting to get new ones.
+@end itemize
+
+Most states are very quick operations. If threads last in any of these
+states for many seconds, there may be a problem around that needs to be
+investigated.
+
+There are some other states that are not mentioned above, but most of
+these are only useful to find bugs in @code{mysqld}.
@node SHOW GRANTS, SHOW CREATE TABLE, SHOW PROCESSLIST, SHOW
@subsubsection @code{SHOW GRANTS}
@@ -20332,8 +20007,8 @@ Create Table: CREATE TABLE t (
@ref{SET OPTION, , @code{SET OPTION SQL_QUOTE_SHOW_CREATE}}.
-@node Localization, Server-Side Scripts, Database Administration, MySQL Database Administration
-@section MySQL Localization and International Usage
+@node Localisation, Server-Side Scripts, Database Administration, MySQL Database Administration
+@section MySQL Localisation and International Usage
@menu
* Character sets:: The Character Set Used for Data and Sorting
@@ -20342,10 +20017,11 @@ Create Table: CREATE TABLE t (
* Character arrays:: The character definition arrays
* String collating:: String Collating Support
* Multi-byte characters:: Multi-byte Character Support
+* Problems with character sets:: Problems With Character Sets
@end menu
-@node Character sets, Languages, Localization, Localization
+@node Character sets, Languages, Localisation, Localisation
@subsection The Character Set Used for Data and Sorting
@cindex character sets
@@ -20383,7 +20059,7 @@ use this character set for this connection.
One should use @code{mysql_real_escape_string()} when escaping strings
for a SQL query. @code{mysql_real_escape_string()} is identical to the
-old @code{mysql_escape_string()} function, except that it takes the MYSQL
+old @code{mysql_escape_string()} function, except that it takes the @code{MYSQL}
connection handle as the first parameter.
If the client is compiled with different paths than where the server is
@@ -20411,8 +20087,37 @@ default-character-set=character-set-name
but normally this is never needed.
+@menu
+* German character set:: German character set
+@end menu
+
+@node German character set, , Character sets, Character sets
+@subsubsection German character set
+
+To get German sorting order, you should start @code{mysqld} with
+@code{--default-character-set=latin_de}. This will give you the following
+characteristics.
-@node Languages, Adding character set, Character sets, Localization
+When sorting and comparing string's the following mapping is done on the
+strings before doing the comparison:
+
+@example
+ä -> ae
+ö -> oe
+ü -> ue
+ß -> ss
+@end example
+
+All accented characters, are converted to their un-accented uppercase
+counterpart. All letters are converted to uppercase.
+
+When comparing strings with @code{LIKE} the one -> two character mapping
+is not done. All letters are converted to uppercase. Accent are removed
+from all letters except: @code{Ü}, @code{ü}, @code{Ö}, @code{ö},
+@code{Ä} and @code{ä}.
+
+
+@node Languages, Adding character set, Character sets, Localisation
@subsection Non-English Error Messages
@cindex error messages, languages
@@ -20454,7 +20159,7 @@ If you upgrade to a newer version of MySQL, remember to repeat
your changes with the new @file{errmsg.txt} file.
-@node Adding character set, Character arrays, Languages, Localization
+@node Adding character set, Character arrays, Languages, Localisation
@subsection Adding a New Character Set
@cindex character sets, adding
@@ -20482,7 +20187,7 @@ Assign an unique number to it.
@item
Create the file @file{sql/share/charsets/MYSET.conf}.
-(You can use @file{sql/share/charsets/latin1.conf} as a base for this).
+(You can use @file{sql/share/charsets/latin1.conf} as a base for this.)
The syntax for the file very simple:
@@ -20578,7 +20283,7 @@ If you want to have the character set included in the MySQL
distribution, mail a patch to @email{internals@@lists.mysql.com}.
-@node Character arrays, String collating, Adding character set, Localization
+@node Character arrays, String collating, Adding character set, Localisation
@subsection The character definition arrays
@code{to_lower[]} and @code{to_upper[]} are simple arrays that hold the
@@ -20600,7 +20305,7 @@ the discussion of string collating below. @xref{String collating}.
@code{ctype[]} is an array of bit values, with one element for one character.
(Note that @code{to_lower[]}, @code{to_upper[]}, and @code{sort_order[]}
are indexed by character value, but @code{ctype[]} is indexed by character
-value + 1. This is an old legacy to be able to handle EOF.)
+value + 1. This is an old legacy to be able to handle @code{EOF}.)
You can find the following bitmask definitions in @file{m_ctype.h}:
@@ -20626,7 +20331,7 @@ _U + _X = 01 + 0200 = 0201
@end example
-@node String collating, Multi-byte characters, Character arrays, Localization
+@node String collating, Multi-byte characters, Character arrays, Localisation
@subsection String Collating Support
@cindex collating, strings
@@ -20646,7 +20351,7 @@ the maximum ratio the strings may grow during @code{my_strxfrm_MYSET} (it
must be a positive integer).
-@node Multi-byte characters, , String collating, Localization
+@node Multi-byte characters, Problems with character sets, String collating, Localisation
@subsection Multi-byte Character Support
@cindex characters, multi-byte
@@ -20665,8 +20370,43 @@ You must specify the @code{mbmaxlen_MYSET=N} value in the special
comment at the top of the source file. @code{N} should be set to the
size in bytes of the largest character in the set.
+@node Problems with character sets, , Multi-byte characters, Localisation
+@subsection Problems With Character Sets
+
+If you try to use a character set that is not compiled into your binary,
+you can run into a couple of different problems:
+
+@itemize @bullet
+@item
+Your program has a wrong path to where the character sets are stored.
+(Default @file{/usr/local/mysql/share/mysql/charsets}).
+This can be fixed by using the @code{--character-sets-dir}
+option to the program in question.
+@item
+The character set is a multi-byte-character set that can't be loaded
+dynamically. In this case you have to recompile the program with the
+support for the character set.
+@item
+The character set is a dynamic character set, but you don't have a
+configure file for it. In this case you should install the configure
+file for the character set from a new MySQL distribution.
+@item
+Your @file{Index} file doesn't contain the name for the character set.
+
+@example
+ERROR 1105: File '/usr/local/share/mysql/charsets/?.conf' not found
+(Errcode: 2)
+@end example
+
+In this case you should either get a new @code{Index} file or add
+by hand the name of any missing character sets.
+@end itemize
+
+For MyISAM tables, you can check the character set name and number for a
+table with @code{myisamchk -dvv table_name}.
+
-@node Server-Side Scripts, Client-Side Scripts, Localization, MySQL Database Administration
+@node Server-Side Scripts, Client-Side Scripts, Localisation, MySQL Database Administration
@section MySQL Server-Side Scripts and Utilities
@menu
@@ -20733,7 +20473,7 @@ The list below briefly describes the MySQL programs:
@cindex @code{myisamchk}
@item myisamchk
-Utility to describe, check, optimize, and repair MySQL tables.
+Utility to describe, check, optimise, and repair MySQL tables.
Because @code{myisamchk} has many functions, it is described in its own
chapter. @xref{MySQL Database Administration}.
@@ -20840,7 +20580,7 @@ Most of the options to @code{safe_mysqld} are the same as the options to
@code{safe_mysqld} supports the following options:
-@table @code
+@itemize
@item --basedir=path
@item --core-file-size=#
Size of the core file @code{mysqld} should be able to create. Passed to @code{ulimit -c}.
@@ -20867,7 +20607,7 @@ Number of files @code{mysqld} should be able to open. Passed to @code{ulimit -n}
@item --timezone=#
Set the timezone (the @code{TZ}) variable to the value of this parameter.
@item --user=#
-@end table
+@end itemize
The @code{safe_mysqld} script is written so that it normally is able to start
a server that was installed from either a source or a binary version of
@@ -20920,7 +20660,7 @@ edited version that you can reinstall.
@cindex @code{mysqld_multi}
@code{mysqld_multi} is meant for managing several @code{mysqld}
-processes running in different UNIX sockets and TCP/IP ports.
+processes running in different Unix sockets and TCP/IP ports.
The program will search for group(s) named [mysqld#] from my.cnf (or the
given --config-file=...), where # can be any positive number starting
@@ -20947,10 +20687,10 @@ list. Anything after a white space is ignored.
@code{mysqld_multi} supports the following options:
-@table @code
+@itemize
@cindex config-file option
@item --config-file=...
-Alternative config file. NOTE: This will not affect this program's own
+Alternative config file. Note: This will not affect this program's own
options (group @code{[mysqld_multi]}), but only groups
[mysqld#]. Without this option everything will be searched from the
ordinary my.cnf file.
@@ -20962,7 +20702,7 @@ Give an example of a config file.
Print this help and exit.
@cindex log option
@item --log=...
-Log file. Full path to and the name for the log file. NOTE: If the file
+Log file. Full path to and the name for the log file. Note: If the file
exists, everything will be appended.
@cindex mysqladmin option
@item --mysqladmin=...
@@ -20983,16 +20723,16 @@ Password for user for @code{mysqladmin}.
@cindex tcp-ip option
@item --tcp-ip
Connect to the MySQL server(s) via the TCP/IP port instead of
-the UNIX socket. This affects stopping and reporting. If a socket file
+the Unix socket. This affects stopping and reporting. If a socket file
is missing, the server may still be running, but can be accessed only
-via the TCP/IP port. By default connecting is done via the UNIX socket.
+via the TCP/IP port. By default connecting is done via the Unix socket.
@cindex user option
@item --user=...
MySQL user for @code{mysqladmin}.
@cindex version option
@item --version
Print the version number and exit.
-@end table
+@end itemize
Some notes about @code{mysqld_multi}:
@@ -21012,7 +20752,7 @@ shell> mysql -u root -S /tmp/mysql.sock -proot_password -e
@xref{Privileges}.
@end example
You will have to do the above for each @code{mysqld} running in each
-data directory, that you have (just change the socket, -S=...)
+data directory, that you have (just change the socket, -S=...).
@item
@code{pid-file} is very important, if you are using @code{safe_mysqld}
to start @code{mysqld} (e.g. --mysqld=safe_mysqld) Every @code{mysqld}
@@ -21022,7 +20762,7 @@ should have its own @code{pid-file}. The advantage using
it, if a @code{mysqld} process fails due to signal kill -9, or
similar. (Like segmentation fault, which MySQL should never do,
of course ;) Please note that @code{safe_mysqld} script may require that
-you start it from a certain place. This means that you may have to CD to
+you start it from a certain place. This means that you may have to @code{cd} to
a certain directory, before you start the @code{mysqld_multi}. If
you have problems starting, please see the @code{safe_mysqld}
script. Check especially the lines:
@@ -21037,7 +20777,7 @@ release) if test -d /data/mysql -a -f ./share/mysql/english/errmsg.sys
The above test should be successful, or you may encounter problems.
@item
Beware of the dangers starting multiple @code{mysqlds} in the same data
-directory. Use separate data directories, unless you @strong{KNOW} what
+directory. Use separate data directories, unless you @strong{know} what
you are doing!
@item
The socket file and the TCP/IP port must be different for every @code{mysqld}.
@@ -21048,23 +20788,23 @@ more flexibility. The order in which the @code{mysqlds} are started or
stopped depends on the order in which they appear in the config file.
@item
When you want to refer to a certain group using GNR with this program,
-just use the number in the end of the group name ( [mysqld# <== ).
+just use the number in the end of the group name ([mysqld# <== ).
@item
You may want to use option '--user' for @code{mysqld}, but in order to
do this you need to be root when you start the @code{mysqld_multi}
script. Having the option in the config file doesn't matter; you will
just get a warning, if you are not the superuser and the @code{mysqlds}
-are started under @strong{YOUR} UNIX account. @strong{IMPORTANT}: Make
+are started under @strong{your} Unix account. @strong{Important}: Make
sure that the @code{pid-file} and the data directory are
-read+write(+execute for the latter one) accessible for @strong{THAT}
-UNIX user, who the specific @code{mysqld} process is started
-as. @strong{DON'T} use the UNIX root account for this, unless you
-@strong{KNOW} what you are doing!
-@item
-@strong{MOST IMPORTANT}: Make sure that you understand the meanings of
-the options that are passed to the @code{mysqlds} and why @strong{WOULD
-YOU WANT} to have separate @code{mysqld} processes. Starting multiple
-@code{mysqlds} in one data directory @strong{WILL NOT} give you extra
+read+write(+execute for the latter one) accessible for @strong{that}
+Unix user, who the specific @code{mysqld} process is started
+as. @strong{Do not} use the Unix root account for this, unless you
+@strong{know} what you are doing!
+@item
+@strong{Most important}: Make sure that you understand the meanings of
+the options that are passed to the @code{mysqld}s and @strong{why one
+would want} to have separate @code{mysqld} processes. Starting multiple
+@code{mysqld}s in one data directory @strong{will not} give you extra
performance in a threaded system!
@end itemize
@@ -21165,7 +20905,7 @@ file. It is permissible to omit the @file{.MYI} extension.
@code{myisampack} supports the following options:
-@table @code
+@itemize @bullet
@item -b, --backup
Make a backup of the table as @code{tbl_name.OLD}.
@@ -21187,7 +20927,7 @@ Display a help message and exit.
@item -j big_tbl_name, --join=big_tbl_name
Join all tables named on the command line into a single table
@code{big_tbl_name}. All tables that are to be combined
-MUST be identical (same column names and types, same indexes, etc.).
+@strong{must} be identical (same column names and types, same indexes, etc.).
@item -p #, --packlength=#
Specify the record length storage size, in bytes. The value should be 1, 2,
@@ -21219,7 +20959,7 @@ Wait and retry if table is in use. If the @code{mysqld} server was
invoked with the @code{--skip-locking} option, it is not a good idea to
invoke @code{myisampack} if the table might be updated during the
packing process.
-@end table
+@end itemize
@cindex examples, compressed tables
The sequence of commands shown below illustrates a typical table compression
@@ -21487,7 +21227,7 @@ The number of bits used in the Huffman tree.
After you have run @code{pack_isam}/@code{myisampack} you must run
@code{isamchk}/@code{myisamchk} to re-create the index. At this time you
can also sort the index blocks and create statistics needed for
-the MySQL optimizer to work more efficiently:
+the MySQL optimiser to work more efficiently:
@example
myisamchk -rq --analyze --sort-index table_name.MYI
@@ -21513,20 +21253,20 @@ the following configure options:
@multitable @columnfractions .3 .7
@item @strong{Option} @tab @strong{Comment}
@item --with-server-suffix=-max @tab Add a suffix to the @code{mysqld} version string.
-@item --with-bdb @tab Support for Berkeley DB (BDB) tables
@item --with-innodb @tab Support for InnoDB tables.
+@item --with-bdb @tab Support for Berkeley DB (BDB) tables
@item CFLAGS=-DUSE_SYMDIR @tab Symbolic links support for Windows.
@end multitable
You can find the MySQL-max binaries at
@uref{http://www.mysql.com/downloads/mysql-max-3.23.html}.
-The Windows MySQL 3.23 binary distribution includes both the
+The Windows MySQL binary distributions includes both the
standard @code{mysqld.exe} binary and the @code{mysqld-max.exe} binary.
@uref{http://www.mysql.com/downloads/mysql-3.23.html}.
@xref{Windows installation}.
-Note that as Berkeley DB and InnoDB are not available for all platforms,
+Note that as InnoDB and Berkeley DB are not available for all platforms,
some of the @code{Max} binaries may not have support for both of these.
You can check which table types are supported by doing the following
query:
@@ -21540,7 +21280,7 @@ mysql> show variables like "have_%";
| have_innodb | NO |
| have_isam | YES |
| have_raid | NO |
-| have_ssl | NO |
+| have_openssl | NO |
+---------------+-------+
@end example
@@ -21548,12 +21288,12 @@ The meaning of the values are:
@multitable @columnfractions .3 .7
@item @strong{Value} @tab @strong{Meaning}.
-@item YES @tab The option is activated and usable.
-@item NO @tab MySQL is not compiled with support for this option.
-@item DISABLED @tab The xxxx option is disabled because one started @code{mysqld} with @code{--skip-xxxx} or because one didn't start @code{mysqld} with all needed options to enable the option. In this case the @code{hostname.err} file should contain a reason for why the option is disabled.
+@item @code{YES} @tab The option is activated and usable.
+@item @code{NO} @tab MySQL is not compiled with support for this option.
+@item @code{DISABLED} @tab The xxxx option is disabled because one started @code{mysqld} with @code{--skip-xxxx} or because one didn't start @code{mysqld} with all needed options to enable the option. In this case the @code{hostname.err} file should contain a reason for why the option is disabled.
@end multitable
-@strong{NOTE}: To be able to create InnoDB tables you @strong{MUST} edit
+@strong{Note}: To be able to create InnoDB tables you @strong{must} edit
your startup options to include at least the @code{innodb_data_file_path}
option. @xref{InnoDB start}.
@@ -21662,7 +21402,7 @@ The list below briefly describes the MySQL programs:
@cindex @code{myisamchk}
@item myisamchk
-Utility to describe, check, optimize, and repair MySQL tables.
+Utility to describe, check, optimise, and repair MySQL tables.
Because @code{myisamchk} has many functions, it is described in its own
chapter. @xref{MySQL Database Administration}.
@@ -21760,7 +21500,7 @@ retrieve the result set.
Using @code{mysql} is very easy. Just start it as follows:
@code{mysql database} or @code{mysql --user=user_name --password=your_password database}. Type a SQL statement, end it with @samp{;}, @samp{\g}, or @samp{\G}
-and press RETURN/ENTER.
+and press Enter.
@cindex @code{mysql} command line options
@cindex command line options, @code{mysql}
@@ -21819,8 +21559,8 @@ Continue even if we get a SQL error.
@cindex @code{no-named-commands}, @code{mysql} option
@item -g, --no-named-commands
Named commands are disabled. Use \* form only, or use named commands
-only in the beginning of a line ending with a semicolon (;). Since
-Version 10.9, the client now starts with this option ENABLED by default!
+only in the beginning of a line ending with a semicolon (@samp{;}). Since
+Version 10.9, the client now starts with this option @strong{enabled} by default!
With the -g option, long format commands will still work from the first
line, however.
@@ -21875,7 +21615,7 @@ other database in the update log.
@item @code{--pager[=...]}
Output type. Default is your @code{ENV} variable @code{PAGER}. Valid
pagers are less, more, cat [> filename], etc. See interactive help (\h)
-also. This option does not work in batch mode. Pager works only in UNIX.
+also. This option does not work in batch mode. Pager works only in Unix.
@cindex @code{password}, @code{mysql} option
@item -p[password], --password[=...]
@@ -21951,7 +21691,7 @@ You can also set the following variables with @code{-O} or
@cindex @code{select_limit}
@cindex @code{max_join_size}
@multitable @columnfractions .3 .2 .5
-@item Variable Name @tab Default @tab Description
+@item @strong{Variable Name} @tab @strong{Default} @tab @strong{Description}
@item connect_timeout @tab 0 @tab Number of seconds before timeout connection.
@item max_allowed_packet @tab 16777216 @tab Max packetlength to send/receive from to server
@item net_buffer_length @tab 16384 @tab Buffer for TCP/IP and socket communication
@@ -21987,7 +21727,7 @@ tee (\T) Set outfile [to_outfile]. Append everything into given outfile.
use (\u) Use another database. Takes database name as argument.
@end example
-From the above, pager only works in UNIX.
+From the above, pager only works in Unix.
@cindex status command
The @code{status} command gives you some information about the
@@ -22074,7 +21814,7 @@ each command, just before the command line appears again waiting for the
next command.
@item
-Browsing, or searching the results in the interactive mode in UNIX less,
+Browsing, or searching the results in the interactive mode in Unix less,
more, or any other similar program, is now possible with option
@code{--pager[=...]}. Without argument, @code{mysql} client will look
for environment variable PAGER and set @code{pager} to that.
@@ -22083,7 +21823,7 @@ command @code{pager} and disabled with command @code{nopager}. The
command takes an argument optionally and the @code{pager} will be set to
that. Command @code{pager} can be called without an argument, but this
requires that the option @code{--pager} was used, or the @code{pager}
-will default to stdout. @code{pager} works only in UNIX, since it uses
+will default to stdout. @code{pager} works only in Unix, since it uses
the popen() function, which doesn't exist in Windows. In Windows, the
@code{tee} option can be used instead, although it may not be as handy
as @code{pager} can be in some situations.
@@ -22122,11 +21862,11 @@ mysql> pager cat | tee /dr1/tmp/res.txt | tee /dr2/tmp/res2.txt | less -n -i -S
You can also combine the two functions above; have the @code{tee}
enabled, @code{pager} set to 'less' and you will be able to browse the
results in unix 'less' and still have everything appended into a file
-the same time. The difference between @code{UNIX tee} used with the
+the same time. The difference between Unix @code{tee} used with the
@code{pager} and the @code{mysql} client in-built @code{tee}, is that
-the in-built @code{tee} works even if you don't have the @code{UNIX tee}
+the in-built @code{tee} works even if you don't have the Unix @code{tee}
available. The in-built @code{tee} also logs everything that is printed
-on the screen, where the @code{UNIX tee} used with @code{pager} doesn't
+on the screen, where the Unix @code{tee} used with @code{pager} doesn't
log quite that much. Last, but not least, the interactive @code{tee} is
more handy to switch on and off, when you want to log something into a
file, but want to be able to turn the feature off sometimes.
@@ -22227,6 +21967,7 @@ The @code{mysqladmin status} command result has the following columns:
@cindex uptime
@multitable @columnfractions .3 .7
+@item @strong{Column} @tab @strong{Description}
@item Uptime @tab Number of seconds the MySQL server has been up.
@cindex threads
@item Threads @tab Number of active threads (clients).
@@ -22308,7 +22049,7 @@ Instead of making one query for each table, execute all queries in 1
query separately for each database. Table names will be in a comma
separated list.
@item -a, --analyze
-Analyze given tables.
+Analyse given tables.
@item --auto-repair
If a checked table is corrupted, automatically fix it. Repairing will be
done after all tables have been checked, if corrupted ones were found.
@@ -22347,7 +22088,7 @@ Connect to host.
Faster than extended-check, but only finds 99.99 percent of all
errors. Should be good enough for most cases.
@item -o, --optimize
-Optimize table
+Optimise table
@item -p, --password[=...]
Password to use when connecting to server. If password is not given
it's solicited on the tty.
@@ -22468,12 +22209,16 @@ is @code{localhost}.
Lock all tables before starting the dump. The tables are locked with
@code{READ LOCAL} to allow concurrent inserts in the case of @code{MyISAM}
tables.
+@item -K, --disable-keys
+@code{/*!40000 ALTER TABLE tb_name DISABLE KEYS */;} and
+@code{/*!40000 ALTER TABLE tb_name ENABLE KEYS */;}
+will be put in the output.
@item -n, --no-create-db
-'CREATE DATABASE /*!32312 IF NOT EXISTS*/ db_name;' will not be put in the
+@code{CREATE DATABASE /*!32312 IF NOT EXISTS*/ db_name;} will not be put in the
output. The above line will be added otherwise, if --databases or
--all-databases option was given.
@item -t, --no-create-info
-Don't write table creation information (The @code{CREATE TABLE} statement.)
+Don't write table creation information (the @code{CREATE TABLE} statement).
@item -d, --no-data
Don't write any row information for the table. This is very useful if you
just want to get a dump of the structure for a table!
@@ -22517,7 +22262,11 @@ Verbose mode. Print out more information on what the program does.
@item -V, --version
Print version information and exit.
@item -w, --where='where-condition'
-Dump only selected records. Note that QUOTES are mandatory:
+Dump only selected records. Note that quotes are mandatory:
+@item -X, --xml
+Dumps a database as well formed XML
+@item -x, --first-slave
+Locks all tables across all databases.
@example
"--where=user='jimf'" "-wuserid>1" "-wuserid<1"
@@ -22661,7 +22410,7 @@ directly to the same options to @code{LOAD DATA INFILE}.
@code{mysqlimport} is invoked like this:
@example
-shell> mysqlimport [options] database textfile1 [textfile2....]
+shell> mysqlimport [options] database textfile1 [textfile2 ...]
@end example
For each text file named on the command line,
@@ -22712,8 +22461,8 @@ is @code{localhost}.
See the description for the @code{--replace} option.
@item -l, --lock-tables
-Lock @strong{ALL} tables for writing before processing any text files. This
-ensures that all tables are synchronized on the server.
+Lock @strong{all} tables for writing before processing any text files. This
+ensures that all tables are synchronised on the server.
@item -L, --local
Read input files from the client. By default, text files are assumed to be on
@@ -22837,22 +22586,32 @@ argument).
@cindex error messages, displaying
@cindex perror
-@code{perror} can be used to print error message(s). @code{perror} can
-be invoked like this:
+@cindex errno
+@cindex Errcode
+
+For most system errors MySQL will, in addition to a internal text message,
+also print the system error code in one of the following styles:
+@code{message ... (errno: #)} or @code{message ... (Errcode: #)}.
+
+You can find out what the error code means by either examining the
+documentation for your system or use the @code{perror} utility.
+
+@code{perror} prints a description for a system error code, or an MyISAM/ISAM
+table handler error code.
+
+@code{perror} is invoked like this:
@example
shell> perror [OPTIONS] [ERRORCODE [ERRORCODE...]]
-For example:
+Example:
-shell> perror 64 79
+shell> perror 13 64
+Error code 13: Permission decided
Error code 64: Machine is not on the network
-Error code 79: Can not access a needed shared library
@end example
-@code{perror} can be used to display a description for a system error
-code, or an MyISAM/ISAM table handler error code. The error messages
-are mostly system dependent.
+Note that the error messages are mostly system dependent!
@node Batch Commands, , perror, Client-Side Scripts
@@ -22895,6 +22654,7 @@ MySQL has several different log files that can help you find
out what's going on inside @code{mysqld}:
@multitable @columnfractions .3 .7
+@item @strong{Log file} @tab @strong{Description}
@item The error log @tab Problems encountering starting, running or stopping @code{mysqld}.
@item The isam log @tab Logs all changes to the ISAM tables. Used only for debugging the isam code.
@item The query log @tab Established connections and executed queries.
@@ -22923,7 +22683,7 @@ switch to a new log) by executing @code{FLUSH LOGS}. @xref{FLUSH}.
@code{mysqld} writes all errors to the stderr, which the
@code{safe_mysqld} script redirects to a file called
@code{'hostname'.err}. (On Windows, @code{mysqld} writes this directly
-to @file{\mysql\data\mysql.err}).
+to @file{\mysql\data\mysql.err}.)
This contains information indicating when @code{mysqld} was started and
stopped and also any critical errors found when running. If @code{mysqld}
@@ -22967,7 +22727,7 @@ after the query is executed, but before any locks are released.
@cindex update log
@cindex files, update log
-@strong{NOTE}: The update log is replaced by the binary
+@strong{Note}: The update log is replaced by the binary
log. @xref{Binary log}. With this you can do anything that you can do
with the update log.
@@ -22981,7 +22741,7 @@ extension, @code{mysqld} will create log file names like so:
time you execute @code{mysqladmin refresh}, execute @code{mysqladmin
flush-logs}, execute the @code{FLUSH LOGS} statement, or restart the server.
-@strong{NOTE:} For the above scheme to work, you should NOT create
+@strong{Note:} For the above scheme to work, you must not create
your own files with the same filename as the update log + some extensions
that may be regarded as a number, in the directory used by the update log!
@@ -23046,15 +22806,20 @@ file is written in the data directory.
If you supply an extension to @code{--log-bin=filename.extension}, the
extension will be silenty removed.
-To the binary log filename @code{mysqld} will append an extension that is a
-number that is incremented each time you execute @code{mysqladmin
-refresh}, execute @code{mysqladmin flush-logs}, execute the @code{FLUSH LOGS}
-statement or restart the server.
+To the binary log filename @code{mysqld} will append an extension that
+is a number that is incremented each time you execute @code{mysqladmin
+refresh}, execute @code{mysqladmin flush-logs}, execute the @code{FLUSH
+LOGS} statement or restart the server. A new binary log will also
+automaticly be created when it reaches @code{max_bin_log_size}. You can
+delete all not active binary log files with the @code{RESET MASTER}
+command. @xref{RESET}.
You can use the following options to @code{mysqld} to affect what is logged
to the binary log:
@multitable @columnfractions .4 .6
+@item @strong{Option} @tab @strong{Description}
+
@item @code{binlog-do-db=database_name} @tab
Tells the master it should log updates for the specified database, and
exclude all others not explicitly mentioned.
@@ -23135,7 +22900,7 @@ suffixed with @code{-slow.log}. If a filename is given, but doesn't
contain a path, the file is written in the data directory.
The slow query log can be used to find queries that take a long time to
-execute and are thus candidates for optimization. With a large log, that
+execute and are thus candidates for optimisation. With a large log, that
can become a difficult task. You can pipe the slow query log through the
@code{mysqldumpslow} command to get a summary of the queries which
appear in the log.
@@ -23178,7 +22943,7 @@ The above command does the following:
@itemize @bullet
@item
If standard logging (@code{--log}) or slow query logging
-(@code{--log-slow-queries}) is used, closes and reopens the log file.
+(@code{--log-slow-queries}) is used, closes and reopens the log file
(@file{mysql.log} and @file{`hostname`-slow.log} as default).
@item
If update logging (@code{--log-update}) is used, closes the update log and
@@ -23223,6 +22988,10 @@ You will be introduced to replication and learn how to implement it.
Towards the end, there are some frequently asked questions and descriptions
of problems and how to solve them.
+We suggest that you visit our website at @uref{http://www.mysql.com/}
+often and read updates to this section. Replication is constantly being
+improved, and we update the manual frequently with the most current
+information.
@node Replication Intro, Replication Implementation, Replication, Replication
@subsection Introduction
@@ -23238,7 +23007,7 @@ Starting in Version 3.23.15, MySQL supports one-way replication
internally. One server acts as the master, while the other acts as the
slave. Note that one server could play the roles of master in one pair
and slave in the other. The master server keeps a binary log of updates
-(@xref{Binary log}.) and an index file to binary logs to keep track of
+(@pxref{Binary log}) and an index file to binary logs to keep track of
log rotation. The slave, upon connecting, informs the master where it
left off since the last successfully propagated update, catches up on
the updates, and then blocks and waits for the master to notify it of
@@ -23259,11 +23028,11 @@ master. @xref{Backup}.
MySQL replication is based on the server keeping track of all
changes to your database (updates, deletes, etc) in the binary
-log. (@xref{Binary log}.) and the slave server(s) reading the saved
+log (@pxref{Binary log}) and the slave server(s) reading the saved
queries from the master server's binary log so that the slave can
execute the same queries on its copy of the data.
-It is @strong{very important} to realize that the binary log is simply a
+It is @strong{very important} to realise that the binary log is simply a
record starting from a fixed point in time (the moment you enable binary
logging). Any slaves which you set up will need copies of all the data
from your master as it existed the moment that you enabled binary
@@ -23271,11 +23040,29 @@ logging on the master. If you start your slaves with data that doesn't
agree with what was on the master @strong{when the binary log was
started}, your slaves may fail.
-A future version (4.0) of MySQL will remove the need to keep a
-(possibly large) snapshot of data for new slaves that you might wish to
-set up through the live backup functionality with no locking required.
-However, at this time, it is necessary to block all writes either with a
-global read lock or by shutting down the master while taking a snapshot.
+Starting in 4.0.0, one can use @code{LOAD DATA FROM MASTER} to set up
+a slave. Note that 4.0.0 slaves cannot communicate with 3.23 masters, but 4.0.1
+and later version slaves can. 3.23 slave cannot talk to 4.0 master.
+
+You must also be aware that @code{LOAD DATA FROM MASTER} currently works only
+if all the tables on the master are @code{MyISAM} type, and will acuire a
+global read lock, so no writes are possible while the tables are being
+transferred from the master. This limitation is of a temporary nature, and is
+due to the fact that we have not yet implemented hot lock-free table backup.
+It will be removed in the future 4.0 branch versions once we implemented hot
+backup enabling @code{LOAD DATA FROM MASTER} to work without blocking master
+updates.
+
+Due to the above limitation, we recommend that at this point you use
+@code{LOAD DATA FROM MASTER} only if the dataset on the master is relatively
+small, or if a prolonged read lock on the master is acceptable. While the
+actual speed of @code{LOAD DATA FROM MASTER} may vary from system to system,
+a good rule for a rough estimate of how long it is going to take is 1 second
+per 1 MB of the data file. You will get close to the estimate if both master
+and slave are equivalent to 700 MHz Pentium, are connected through
+100 MBit/s network, and your index file is about half the size of your data
+file. Of course, your mileage will vary from system to system, the above rule
+just gives you a rough order of magnitude estimate.
Once a slave is properly configured and running, it will simply connect
to the master and wait for updates to process. If the master goes away
@@ -23299,6 +23086,19 @@ your databases and have not configured replication before. You will need
to shutdown your master server briefly to complete the steps outlined
below.
+While the above method is the most straightforward way to set up a slave,
+it is not the only one. For example, if you already have a snapshot
+of the master, and
+the master already has server id set and binary logging enabled, one can
+set up a slave without shutting the master down or even blocking the updates.
+Please refer to @xref{Replication FAQ}. for more details.
+
+If you want to become a real MySQL replication guru, we suggest that you
+begin with studing, pondering, and trying all commands
+mentioned in @xref{Replication SQL}. You should also familiarize yourself
+with replication startup options in @code{my.cnf} in
+@xref{Replication Options}.
+
@enumerate
@item
Make sure you have a recent version of MySQL installed on the master
@@ -23416,16 +23216,6 @@ of the master's binary log is has processed. @strong{Do not} remove or
edit the file, unless you really know what you are doing. Even in that case,
it is preferred that you use @code{CHANGE MASTER TO} command.
-
-@menu
-* Replication Features:: Replication Features and Known Problems
-* Replication Options:: Replication Options in my.cnf
-* Replication SQL:: SQL Commands Related to Replication
-* Replication FAQ:: Replication FAQ
-* Replication Problems:: Troubleshooting Replication
-@end menu
-
-
@node Replication Features, Replication Options, Replication HOWTO, Replication
@subsection Replication Features and Known Problems
@@ -23450,9 +23240,11 @@ on the master and the slave. If not, you may get duplicate key errors on
the slave, because a key that is regarded as unique on the master may
not be that in the other character set.
@item
-@code{LOAD DATA INFILE} will be handled properly as long as the file
+In 3.23, @code{LOAD DATA INFILE} will be handled properly as long as the file
still resides on the master server at the time of update
-propagation. @code{LOAD LOCAL DATA INFILE} will be skipped.
+propagation. @code{LOAD LOCAL DATA INFILE} will be skipped. In 4.0, this
+limitation is not present - all forms of @code{LOAD DATA INFILE} are properly
+replicated.
@item
Update queries that use user variables are not replication-safe (yet).
@item
@@ -23572,7 +23364,17 @@ to get rid of old logs while the slave is running.
If you are using replication, we recommend you to use MySQL Version
3.23.30 or later. Older versions work, but they do have some bugs and are
-missing some features.
+missing some features. Some of the options below may not be available in
+your version if it is not the most recent one. For all options specific to
+the 4.0 branch, there is a note indicating so. Otherwise, if you discover
+that the option you are interested in is not available in your 3.23 version,
+and you really need it, please upgrade to the most recent 3.23 branch.
+
+Please be aware that 4.0 branch is still in alpha, so some things may not be
+working as smoothly as you would like. If you really would like to try
+the new features of 4.0, we recommend you do it in such a way that in
+case there is a problem your mission critical applications will not be
+disrupted.
On both master and slave you need to use the @code{server-id} option.
This sets an unique replication id. You should pick a unique value in the
@@ -23582,8 +23384,8 @@ Example: @code{server-id=3}
The following table has the options you can use for the @strong{MASTER}:
@multitable @columnfractions .3 .7
-
@item @strong{Option} @tab @strong{Description}
+
@item @code{log-bin=filename} @tab
Write to a binary update log to the specified location. Note that if you
give it a parameter with an extension (for example,
@@ -23614,7 +23416,7 @@ current database is 'database_name'. All others database are ignored.
Note that if you use this you should ensure that you only do updates in
the current database.
-Example: @code{binlog-do-db=some_database}.
+Example: @code{binlog-do-db=sales}.
@item @code{binlog-ignore-db=database_name} @tab
Tells the master that updates where the current database is
@@ -23622,47 +23424,72 @@ Tells the master that updates where the current database is
you use this you should ensure that you only do updates in the current
database.
-Example: @code{binlog-ignore-db=some_database}
+Example: @code{binlog-ignore-db=accounting}
@end multitable
The following table has the options you can use for the @strong{SLAVE}:
@multitable @columnfractions .3 .7
-
@item @strong{Option} @tab @strong{Description}
+
@item @code{master-host=host} @tab
Master hostname or IP address for replication. If not set, the slave
-thread will not be started.
+thread will not be started. Note that the setting of @code{master-host}
+will be ignored if there exists a valid @code{master.info} file. Probably a
+better name for this options would have been something like
+@code{bootstrap-master-host}, but it is too late to change now.
Example: @code{master-host=db-master.mycompany.com}.
@item @code{master-user=username} @tab
-The user the slave thread will us for authentication when connecting to
+The username the slave thread will use for authentication when connecting to
the master. The user must have @code{FILE} privilege. If the master user
-is not set, user @code{test} is assumed.
+is not set, user @code{test} is assumed. The value in @code{master.info} will
+take precedence if it can be read.
Example: @code{master-user=scott}.
@item @code{master-password=password} @tab
The password the slave thread will authenticate with when connecting to
-the master. If not set, an empty password is assumed.
+the master. If not set, an empty password is assumed.The value in
+@code{master.info} will take precedence if it can be read.
Example: @code{master-password=tiger}.
@item @code{master-port=portnumber} @tab
The port the master is listening on. If not set, the compiled setting of
@code{MYSQL_PORT} is assumed. If you have not tinkered with
-@code{configure} options, this should be 3306.
+@code{configure} options, this should be 3306. The value in
+@code{master.info} will take precedence if it can be read.
Example: @code{master-port=3306}.
@item @code{master-connect-retry=seconds} @tab
The number of seconds the slave thread will sleep before retrying to
connect to the master in case the master goes down or the connection is
-lost. Default is 60.
+lost. Default is 60.
Example: @code{master-connect-retry=60}.
+@item @code{master-ssl} @tab
+Available after 4.0.0. Turn SSL on for replication. Be warned that is
+this is a relatively new feature.
+
+Example: @code{master-ssl}.
+
+@item @code{master-ssl-key} @tab
+Available after 4.0.0. Master SSL keyfile name. Only applies if you have
+enabled @code{master-ssl}.
+
+Example: @code{master-ssl-key=SSL/master-key.pem}.
+
+@item @code{master-ssl-cert} @tab
+Available after 4.0.0. Master SSL certificate file name. Only applies if
+you have enabled @code{master-ssl}.
+
+
+Example: @code{master-ssl-key=SSL/master-cert.pem}.
+
@item @code{master-info-file=filename} @tab
The location of the file that remembers where we left off on the master
during the replication process. The default is master.info in the data
@@ -23671,6 +23498,23 @@ is the desire to be rebelious.
Example: @code{master-info-file=master.info}.
+@item @code{report-host} @tab
+Available after 4.0.0. Hostname or IP of the slave to be reported to to
+the master during slave registration. Will appear in the output of
+@code{SHOW SLAVE HOSTS}. Leave unset if you do not want the slave to
+register itself with the master. Note that it is not sufficient for the
+master to simply read the IP of the slave off the socket once the slave
+connects. Due to @code{NAT} and other routing issues, that IP may not be
+valid for connecting to the slave from the master or other hosts.
+
+Example: @code{report-host=slave1.mycompany.com}
+
+@item @code{report-port} @tab
+Available after 4.0.0. Port for connecting to slave reported to the
+master during slave registration. Set it only if the slave is listening
+on a non-default port or if you have a special tunnel from the master or
+other clients to the slave. If not sure, leave this option unset.
+
@item @code{replicate-do-table=db_name.table_name} @tab
Tells the slave thread to restrict replication to the specified table.
To specify more than one table, use the directive multiple times, once
@@ -23739,7 +23583,7 @@ Updates to a database with a different name than the original
Example: @code{replicate-rewrite-db=master_db_name->slave_db_name}.
-@item @code{slave-skip-errors=err_code1,err_code2,..} @tab
+@item @code{slave-skip-errors=err_code1,err_code2,...} @tab
Available only in 3.23.47 and later. Tells the slave thread to continue
replication when a query returns an error from the provided
list. Normally, replication will discontinue when an error is
@@ -23818,7 +23662,21 @@ logs. In pre 3.23.26 versions the command was called
@code{FLUSH SLAVE}(Slave)
@item @code{LOAD TABLE tblname FROM MASTER}
- @tab Downloads a copy of the table from master to the slave. (Slave)
+ @tab Downloads a copy of the table from master to the slave. Implemented
+ mainly for debugging of @code{LOAD DATA FROM MASTER}, but some "gourmet"
+ users might find it useful for other things. Do not use it if you consider
+ yourself the average "non-hacker" type user. (Slave)
+
+@item @code{LOAD DATA FROM MASTER} @tab
+Available starting in 4.0.0. Takes a snapshot of the master and copies
+it to the slave. Updates the values of @code{MASTER_LOG_FILE} and
+@code{MASTER_LOG_POS} so that the slave will start replicating from the
+correct position. Will honor table and database exclusion rules
+specified with @code{replicate-*} options. So far works only with
+@code{MyISAM} tables and acquires a global read lock on the master while
+taking the snapshot. In the future it is planned to make it work with
+@code{InnoDB} tables and to remove the need for global read lock using
+the non-blocking online backup feature.
@item @code{CHANGE MASTER TO master_def_list}
@tab Changes the master parameters to the values specified in
@@ -23826,10 +23684,9 @@ logs. In pre 3.23.26 versions the command was called
is a comma-separated list of @code{master_def} where @code{master_def} is
one of the following: @code{MASTER_HOST}, @code{MASTER_USER},
@code{MASTER_PASSWORD}, @code{MASTER_PORT}, @code{MASTER_CONNECT_RETRY},
-@code{MASTER_LOG_FILE}, @code{MASTER_LOG_POS}. Example:
+@code{MASTER_LOG_FILE}, @code{MASTER_LOG_POS}. For example:
@example
-
CHANGE MASTER TO
MASTER_HOST='master2.mycompany.com',
MASTER_USER='replication',
@@ -23837,7 +23694,6 @@ CHANGE MASTER TO
MASTER_PORT=3306,
MASTER_LOG_FILE='master2-bin.001',
MASTER_LOG_POS=4;
-
@end example
You only need to specify the values that need to be changed. The values that
@@ -23849,12 +23705,46 @@ automatically be reset to an empty string and 0, respectively (the start
values). Note that if you restart the slave, it will remember its last master.
If this is not desirable, you should delete the @file{master.info} file before
restarting, and the slave will read its master from @code{my.cnf} or the
-command line. (Slave)
+command line.
+
+This command is useful for setting up a slave when you have the snapshot of
+the master and have record the log and the offset on the master that the
+snapshot corresponds to. You can run
+ @code{CHANGE MASTER TO MASTER_LOG_FILE='log_name_on_master',
+ MASTER_LOG_POS=log_offset_on_master} on the slave after restoring the
+snapshot.
+
+(Slave)
@item @code{SHOW MASTER STATUS} @tab Provides status information on the binlog of the master. (Master)
+@item @code{SHOW SLAVE HOSTS} @tab Available after 4.0.0. Gives a
+listing of slaves currently registered with the master (Master)
+
@item @code{SHOW SLAVE STATUS} @tab Provides status information on essential parameters of the slave thread. (Slave)
-@item @code{SHOW MASTER LOGS} @tab Only available starting in Version 3.23.28. Lists the binary logs on the master. You should use this command prior to @code{PURGE MASTER LOGS TO} to find out how far you should go.
+
+@item @code{SHOW MASTER LOGS} @tab Only available starting in Version
+3.23.28. Lists the binary logs on the master. You should use this
+command prior to @code{PURGE MASTER LOGS TO} to find out how far you
+should go. (Master)
+
+@item @code{SHOW BINLOG EVENTS [ IN 'logname' ] [ FROM pos ]
+ [ LIMIT [offset,] rows ] } @tab
+Shows the events in the binary update log. Primarily used for
+testing/debugging, but can also be used by regular clients that for some
+reason need to read the binary log contents. (Master)
+
+@item @code{SHOW NEW MASTER FOR SLAVE WITH MASTER_LOG_FILE='logfile' AND
+ MASTER_LOG_POS=pos AND
+MASTER_LOG_SEQ=log_seq AND MASTER_SERVER_ID=server_id} @tab
+This command is used when a slave of a possibly dead/unavailable master
+needs to be switched to replicate off another slave that has been
+replicating the same master. The command will return recalculated
+replication coordinates, and the output can be used in a subsequent
+@code{CHANGE MASTER TO} command. Normal users should never need to run
+this command. It is primarily reserved for internal use by the fail-safe
+replication code. We may later change the syntax if we find a more
+intuitive way to describe this operation.
@item @code{PURGE MASTER LOGS TO 'logname'}
@tab Available starting in Version 3.23.28. Deletes all the
@@ -23886,6 +23776,87 @@ last log on the list), backup all the logs you are about to delete
@node Replication FAQ, Replication Problems, Replication SQL, Replication
@subsection Replication FAQ
+@strong{Q}: How do I configure a slave if the master is already running
+and I do not want to stop it?
+
+@strong{A}: There are several options. If you have taken a backup of the
+master at some point and recorded the binlog name and offset ( from the
+output of @code{SHOW MASTER STATUS} ) corresponding to the snapshot, do
+the following:
+
+@itemize @bullet
+@item
+Make sure unique server id is assigned to the slave.
+@item
+Execute @code{CHANGE MASTER TO MASTER_HOST='master-host-name',
+ MASTER_USER='master-user-name', MASTER_PASSWORD='master-pass',
+ MASTER_LOG_FILE='recorded-log-name', MASTER_LOG_POS=recorded_log_pos}
+@item
+Execute @code{SLAVE START}
+@end itemize
+
+If you do not have a backup of the master already, here is a quick way to
+do it consistently:
+
+@itemize @bullet
+@item
+@code{FLUSH TABLES WITH READ LOCK}
+@item
+@code{gtar zcf /tmp/backup.tar.gz /var/lib/mysql} ( or a variation of this)
+@item
+@code{SHOW MASTER STATUS} - make sure to record the output - you will need it
+later
+@item
+@code{UNLOCK TABLES}
+@end itemize
+
+Afterwards, follow the instructions for the case when you have a snapshot and
+have records the log name and offset. You can use the same snapshot to set up
+several slaves. As long as the binary logs of the master are left intact, you
+can wait as long as several days or in some cases maybe a month to set up a
+slave once you have the snapshot of the master. In theory the waiting gap can
+be infinite. The two practical limitations is the diskspace of the master
+getting filled with old logs, and the amount of time it will take the slave to
+catch up.
+
+In version 4.0.0 and newer, you can also use @code{LOAD DATA FROM
+MASTER}. This is a convenient command that will take a snapshot,
+restore it to the slave, and adjust the log name and offset on the slave
+all at once. In the future, @code{LOAD DATA FROM MASTER} will be the
+recommended way to set up a slave. Be warned, howerver, that the read
+lock may be held for a long time if you use this command. It is not yet
+implemented as efficiently as we would like to have it. If you have
+large tables, the preferred method at this time is still with a local
+@code{tar} snapshot after executing @code{FLUSH TABLES WITH READ LOCK}.
+
+@strong{Q}: Does the slave need to be connected to the master all the time?
+
+@strong{A}: No, it does not. You can have the slave go down or stay
+disconnected for hours or even days, then reconnect, catch up on the
+updates, and then disconnect or go down for a while again. So you can,
+for example, use master-slave setup over a dial-up link that is up only
+for short periods of time. The implications of that are that at any
+given time the slave is not guaranteed to be in sync with the master
+unless you take some special measures. In the future, we will have the
+option to block the master until at least one slave is in sync.
+
+@strong{Q}: How do I force the master to block updates until the slave catches
+up?
+
+@strong{A}: Execute the following commands:
+
+@itemize @bullet
+@item
+Master: @code{FLUSH TABLES WITH READ LOCK}
+@item
+Master: @code{SHOW MASTER STATUS} - record the log name and the offset
+@item
+Slave: @code{SELECT MASTER_POS_WAIT('recorded_log_name', recorded_log_offset)}
+When the select returns, the slave is currently in sync with the master
+@item
+Master: @code{UNLOCK TABLES} - now the master will continue updates.
+@end itemize
+
@cindex @code{Binlog_Dump}
@strong{Q}: Why do I sometimes see more than one @code{Binlog_Dump} thread on
the master after I have restarted the slave?
@@ -23964,12 +23935,12 @@ can safely happen in any order, or unless you take care of mis-ordered
updates somehow in the client code.
-You must also realize that two-way replication actually does not improve
+You must also realise that two-way replication actually does not improve
performance very much, if at all, as far as updates are concerned. Both
servers need to do the same amount of updates each, as you would have
one server do. The only difference is that there will be a little less
lock contention, because the updates originating on another server will
-be serialized in one slave thread. This benefit, though, might be
+be serialised in one slave thread. This benefit, though, might be
offset by network delays.
@cindex performance, improving
@@ -23990,7 +23961,7 @@ performance-enhancing replication?
@strong{A}:
If the part of your code that is responsible for database access has
-been properly abstracted/modularized, converting it to run with the
+been properly abstracted/modularised, converting it to run with the
replicated setup should be very smooth and easy - just change the
implementation of your database access to read from some slave or the
master, and to always write to the master. If your code does not have
@@ -24025,7 +23996,7 @@ query, among your many thousands, gave you an error. If you have written a lot o
you may want to automate the conversion task by using Monty's
@code{replace} utility, which comes with the standard distribution of
MySQL, or just write your own Perl script. Hopefully, your
-code follows some recognizable pattern. If not, then you are probably
+code follows some recognisable pattern. If not, then you are probably
better off re-writing it anyway, or at least going through and manually
beating it into a pattern.
@@ -24159,7 +24130,7 @@ If the slave is running, did it establish connection with the master? Do
@code{State} column. If it says @code{connecting to master}, verify the
privileges for the replication user on the master, master host name, your
DNS setup, whether the master is actually running, whether it is reachable
-from the slave, and if all that seems ok, read the error logs.
+from the slave, and if all that seems okay, read the error logs.
@item
If the slave was running, but then stopped, look at SHOW SLAVE STATUS
output and check the error logs. It usually
@@ -24266,33 +24237,33 @@ isolate it into a separate test case first. Then report the problem to
-@node MySQL Optimization, Reference, MySQL Database Administration, Top
-@chapter MySQL Optimization
+@node MySQL Optimisation, Reference, MySQL Database Administration, Top
+@chapter MySQL Optimisation
@menu
-* Optimize Overview:: Optimization Overview
-* Query Speed:: Optimizing @code{SELECT}s and Other Queries
+* Optimise Overview:: Optimisation Overview
+* Query Speed:: Optimising @code{SELECT}s and Other Queries
* Locking Issues:: Locking Issues
-* Optimizing Database Structure:: Optimizing Database Structure
-* Optimizing the Server:: Optimizing the MySQL Server
+* Optimising Database Structure:: Optimising Database Structure
+* Optimising the Server:: Optimising the MySQL Server
* Disk issues:: Disk Issues
@end menu
-Optimization is a complicated task because it ultimately requires
+Optimisation is a complicated task because it ultimately requires
understanding of the whole system. While it may be possible to do some
-local optimizations with small knowledge of your system or application,
+local optimisations with small knowledge of your system or application,
the more optimal you want your system to become the more you will have
to know about it.
This chapter will try to explain and give some examples of different
-ways to optimize MySQL. Remember, however, that there are
+ways to optimise MySQL. Remember, however, that there are
always some (increasingly harder) additional ways to make the system
even faster.
-@node Optimize Overview, Query Speed, MySQL Optimization, MySQL Optimization
-@section Optimization Overview
+@node Optimise Overview, Query Speed, MySQL Optimisation, MySQL Optimisation
+@section Optimisation Overview
The most important part for getting a system fast is of course the basic
design. You also need to know what kinds of things your system will be
@@ -24303,14 +24274,14 @@ The most common bottlenecks are:
@item Disk seeks.
It takes time for the disk to find a piece of data. With modern disks in
1999, the mean time for this is usually lower than 10ms, so we can in
-theory do about 1000 seeks a second. This time improves slowly with new
-disks and is very hard to optimize for a single table. The way to
-optimize this is to spread the data on more than one disk.
+theory do about 100 seeks a second. This time improves slowly with new
+disks and is very hard to optimise for a single table. The way to
+optimise this is to spread the data on more than one disk.
@item Disk reading/writing.
When the disk is at the correct position we need to read the data. With
-modern disks in 1999, one disk delivers something like 10-20Mb/s. This
-is easier to optimize than seeks because you can read in parallel from
+modern disks in 1999, one disk delivers something like 10-20MB/s. This
+is easier to optimise than seeks because you can read in parallel from
multiple disks.
@item CPU cycles.
@@ -24335,26 +24306,51 @@ for most systems, but one should be aware of it.
@end menu
-@node Design Limitations, Portability, Optimize Overview, Optimize Overview
+@node Design Limitations, Portability, Optimise Overview, Optimise Overview
@subsection MySQL Design Limitations/Tradeoffs
@cindex design, limitations
@cindex limitations, design
-Because MySQL uses extremely fast table locking (multiple readers /
-single writers) the biggest remaining problem is a mix of a steady stream of
-inserts and slow selects on the same table.
+When using the MyISAM table handler, MySQL uses extremely fast table
+locking (multiple readers / single writers). The biggest problem with
+this table type is a if you have a mix of a steady stream of updates and
+slow selects on the same table. If this is a problem with some tables,
+you can use another table type for these. @xref{Table types}.
-We believe that for a huge number of systems the extremely fast
-performance in other cases make this choice a win. This case is usually
-also possible to solve by having multiple copies of the table, but it
-takes more effort and hardware.
+MySQL can work with both transactional and not transactional tables. To
+be able to work smoothly with not transactional tables (which can't
+rollback if something goes wrong), MySQL has the following rules:
-We are also working on some extensions to solve this problem for some
-common application niches.
+@cindex default values
+@itemize @bullet
+@item
+All columns has default values.
+@item
+If you insert a 'wrong' value in a column like a @code{NULL} in a
+@code{NOT NULL} column or a too big numerical value in a numerical
+column, MySQL will instead of giving an error instead set the column to
+the 'best possible value'. For numerical values this is 0, the smallest
+possible values or the largest possible value. For strings this is
+either the empty string or the longest possible string that can be in
+the column.
+@item
+All calculated expressions returns a value that can be used instead of
+signaling an error condition. For example 1/0 returns @code{NULL}
+@end itemize
+
+The reason for the above rules is that we can't check these conditions
+before the query starts to execute. If we encounter a problem after
+updating a few rows, we can't just rollback as the table type may not
+support this. We can't stop because in that case the update would be
+'half done' which is probably the worst possible scenario. In this case
+it's better to 'do the best you can' and then continue as if nothing
+happened.
+The above means that one should not use MySQL to check fields content,
+but one should do this in the application.
-@node Portability, Internal use, Design Limitations, Optimize Overview
+@node Portability, Internal use, Design Limitations, Optimise Overview
@subsection Portability
@cindex portability
@@ -24394,7 +24390,7 @@ is, they have different design compromises that lead to different
behavior.
If you strive for database independence, you need to get a good feeling
-for each SQL server's bottlenecks. MySQL is VERY fast in
+for each SQL server's bottlenecks. MySQL is very fast in
retrieving and updating things, but will have a problem in mixing slow
readers/writers on the same table. Oracle, on the other hand, has a big
problem when you try to access rows that you have recently updated
@@ -24415,11 +24411,11 @@ MySQL-specific keywords to a query. The code inside
@code{/**/} will be treated as a comment (ignored) by most other SQL
servers.
-If REAL high performance is more important than exactness, as in some
-Web applications, a possibility is to create an application layer that
+If high performance is more important than exactness, as in some
+Web applications, it is possibile to create an application layer that
caches all results to give you even higher performance. By letting
old results 'expire' after a while, you can keep the cache reasonably
-fresh. This is quite nice in case of extremely high load, in which case
+fresh. This provides a method to handle high load spikes, in which case
you can dynamically increase the cache and set the expire timeout higher
until things get back to normal.
@@ -24428,7 +24424,7 @@ of the initial size of the cache and how often the table should normally
be refreshed.
-@node Internal use, MySQL Benchmarks, Portability, Optimize Overview
+@node Internal use, MySQL Benchmarks, Portability, Optimise Overview
@subsection What Have We Used MySQL For?
@cindex uses, of MySQL
@@ -24493,7 +24489,7 @@ makes the machine feel very slow and unresponsive while big batches are
going. Hopefully this will be better handled in future Linux Kernels.
-@node MySQL Benchmarks, Custom Benchmarks, Internal use, Optimize Overview
+@node MySQL Benchmarks, Custom Benchmarks, Internal use, Optimise Overview
@subsection The MySQL Benchmark Suite
@cindex benchmark suite
@@ -24515,27 +24511,27 @@ multi-threaded tests to the benchmark suite.
For example, (run on the same NT 4.0 machine):
@multitable @columnfractions .6 .2 .2
-@strong{Reading 2000000 rows by index} @tab @strong{Seconds} @tab @strong{Seconds}
-@item mysql @tab 367 @tab 249
-@item mysql_odbc @tab 464
-@item db2_odbc @tab 1206
-@item informix_odbc @tab 121126
-@item ms-sql_odbc @tab 1634
-@item oracle_odbc @tab 20800
-@item solid_odbc @tab 877
-@item sybase_odbc @tab 17614
+@item @strong{Reading 2000000 rows by index} @tab @strong{Seconds} @tab @strong{Seconds}
+@item mysql @tab 367 @tab 249
+@item mysql_odbc @tab 464 @tab
+@item db2_odbc @tab 1206 @tab
+@item informix_odbc @tab 121126 @tab
+@item ms-sql_odbc @tab 1634 @tab
+@item oracle_odbc @tab 20800 @tab
+@item solid_odbc @tab 877 @tab
+@item sybase_odbc @tab 17614 @tab
@end multitable
@multitable @columnfractions .6 .2 .2
-@strong{Inserting (350768) rows} @tab @strong{Seconds} @tab @strong{Seconds}
-@item mysql @tab 381 @tab 206
-@item mysql_odbc @tab 619
-@item db2_odbc @tab 3460
-@item informix_odbc @tab 2692
-@item ms-sql_odbc @tab 4012
-@item oracle_odbc @tab 11291
-@item solid_odbc @tab 1801
-@item sybase_odbc @tab 4802
+@item @strong{Inserting (350768) rows} @tab @strong{Seconds} @tab @strong{Seconds}
+@item mysql @tab 381 @tab 206
+@item mysql_odbc @tab 619 @tab
+@item db2_odbc @tab 3460 @tab
+@item informix_odbc @tab 2692 @tab
+@item ms-sql_odbc @tab 4012 @tab
+@item oracle_odbc @tab 11291 @tab
+@item solid_odbc @tab 1801 @tab
+@item sybase_odbc @tab 4802 @tab
@end multitable
In the above test MySQL was run with a 8M index cache.
@@ -24545,7 +24541,7 @@ We have gather some more benchmark results at
Note that Oracle is not included because they asked to be removed. All
Oracle benchmarks have to be passed by Oracle! We believe that makes
-Oracle benchmarks @strong{VERY} biased because the above benchmarks are
+Oracle benchmarks @strong{very} biased because the above benchmarks are
supposed to show what a standard installation can do for a single
client.
@@ -24583,7 +24579,7 @@ We can find the result from crash-me on a lot of different databases at
@uref{http://www.mysql.com/information/crash-me.php}.
-@node Custom Benchmarks, , MySQL Benchmarks, Optimize Overview
+@node Custom Benchmarks, , MySQL Benchmarks, Optimise Overview
@subsection Using Your Own Benchmarks
@cindex benchmarks
@@ -24607,8 +24603,8 @@ It is very common that some problems only occur when the system is very
heavily loaded. We have had many customers who contact us when they
have a (tested) system in production and have encountered load problems. In
every one of these cases so far, it has been problems with basic design
-(table scans are NOT good at high load) or OS/Library issues. Most of
-this would be a @strong{LOT} easier to fix if the systems were not
+(table scans are @strong{not good} at high load) or OS/Library issues. Most of
+this would be a @strong{lot} easier to fix if the systems were not
already in production.
To avoid problems like this, you should put some effort into benchmarking
@@ -24619,8 +24615,8 @@ As the name suggests, it can bring your system down to its knees if you ask it,
so make sure to use it only on your development systems.
-@node Query Speed, Locking Issues, Optimize Overview, MySQL Optimization
-@section Optimizing @code{SELECT}s and Other Queries
+@node Query Speed, Locking Issues, Optimise Overview, MySQL Optimisation
+@section Optimising @code{SELECT}s and Other Queries
@cindex queries, speed of
@cindex permission checks, effect on speed
@@ -24630,7 +24626,7 @@ First, one thing that affects all queries: The more complex permission
system setup you have, the more overhead you get.
If you do not have any @code{GRANT} statements done, MySQL will
-optimize the permission checking somewhat. So if you have a very high
+optimise the permission checking somewhat. So if you have a very high
volume it may be worth the time to avoid grants. Otherwise more
permission check results in a larger overhead.
@@ -24650,7 +24646,7 @@ mysql> select benchmark(1000000,1+1);
The above shows that MySQL can execute 1,000,000 @code{+}
expressions in 0.32 seconds on a @code{PentiumII 400MHz}.
-All MySQL functions should be very optimized, but there may be
+All MySQL functions should be very optimised, but there may be
some exceptions, and the @code{benchmark(loop_count,expression)} is a
great tool to find out if this is a problem with your query.
@@ -24658,14 +24654,15 @@ great tool to find out if this is a problem with your query.
* EXPLAIN:: @code{EXPLAIN} Syntax (Get Information About a @code{SELECT})
* Estimating performance:: Estimating query performance
* SELECT speed:: Speed of @code{SELECT} queries
-* Where optimizations:: How MySQL optimizes @code{WHERE} clauses
-* DISTINCT optimization:: How MySQL Optimizes @code{DISTINCT}
-* LEFT JOIN optimization:: How MySQL optimizes @code{LEFT JOIN}
-* LIMIT optimization:: How MySQL optimizes @code{LIMIT}
+* Where optimisations:: How MySQL optimises @code{WHERE} clauses
+* DISTINCT optimisation:: How MySQL Optimises @code{DISTINCT}
+* LEFT JOIN optimisation:: How MySQL optimises @code{LEFT JOIN}
+* ORDER BY optimisation:: How MySQL Optimises @code{ORDER BY}
+* LIMIT optimisation:: How MySQL optimises @code{LIMIT}
* Insert speed:: Speed of @code{INSERT} queries
* Update speed:: Speed of @code{UPDATE} queries
* Delete speed:: Speed of @code{DELETE} queries
-* Tips:: Other Optimization Tips
+* Tips:: Other Optimisation Tips
@end menu
@@ -24673,7 +24670,7 @@ great tool to find out if this is a problem with your query.
@subsection @code{EXPLAIN} Syntax (Get Information About a @code{SELECT})
@findex EXPLAIN
-@findex SELECT, optimizing
+@findex SELECT, optimising
@example
EXPLAIN tbl_name
@@ -24689,8 +24686,8 @@ information about how tables are joined and in which order.
With the help of @code{EXPLAIN}, you can see when you must add indexes
to tables to get a faster @code{SELECT} that uses indexes to find the
-records. You can also see if the optimizer joins the tables in an optimal
-order. To force the optimizer to use a specific join order for a
+records. You can also see if the optimiser joins the tables in an optimal
+order. To force the optimiser to use a specific join order for a
@code{SELECT} statement, add a @code{STRAIGHT_JOIN} clause.
For non-simple joins, @code{EXPLAIN} returns a row of information for each
@@ -24760,7 +24757,7 @@ MySQL will not continue searching for more rows for the current row
combination after it has found the first matching row.
@item Not exists
-MySQL was able to do a @code{LEFT JOIN} optimization on the
+MySQL was able to do a @code{LEFT JOIN} optimisation on the
query and will not examine more rows in this table for the previous row
combination after it finds one row that matches the @code{LEFT JOIN} criteria.
@@ -24832,7 +24829,7 @@ the @code{const} join type.
The table has at most one matching row, which will be read at the start
of the query. Because there is only one row, values from the column in
this row can be regarded as constants by the rest of the
-optimizer. @code{const} tables are very fast as they are read only once!
+optimiser. @code{const} tables are very fast as they are read only once!
@item eq_ref
One row will be read from this table for each combination of rows from
@@ -24875,7 +24872,7 @@ number is also used when you restrict queries with the @code{max_join_size}
variable.
@xref{Server parameters}.
-The following example shows how a @code{JOIN} can be optimized progressively
+The following example shows how a @code{JOIN} can be optimised progressively
using the information provided by @code{EXPLAIN}.
Suppose you have the @code{SELECT} statement shown below, that you examine
@@ -24927,7 +24924,7 @@ The tables have the indexes shown below:
The @code{tt.ActualPC} values aren't evenly distributed.
@end itemize
-Initially, before any optimizations have been performed, the @code{EXPLAIN}
+Initially, before any optimisations have been performed, the @code{EXPLAIN}
statement produces the following information:
@example
@@ -25019,7 +25016,7 @@ do eq_ref PRIMARY PRIMARY 15 tt.ClientID 1
@end example
Note that the @code{rows} column in the output from @code{EXPLAIN} is an
-educated guess from the MySQL join optimizer. To optimize a
+educated guess from the MySQL join optimiser. To optimise a
query, you should check if the numbers are even close to the truth. If not,
you may get better performance by using @code{STRAIGHT_JOIN} in your
@code{SELECT} statement and trying to list the tables in a different order in
@@ -25063,7 +25060,7 @@ go much slower until your applications is only bound by disk-seeks
the data grows. @xref{Server parameters}.
-@node SELECT speed, Where optimizations, Estimating performance, Query Speed
+@node SELECT speed, Where optimisations, Estimating performance, Query Speed
@subsection Speed of @code{SELECT} Queries
@findex SELECT speed
@@ -25081,11 +25078,11 @@ Some general tips:
@itemize @bullet
@item
-To help MySQL optimize queries better, run @code{myisamchk
+To help MySQL optimise queries better, run @code{myisamchk
--analyze} on a table after it has been loaded with relevant data. This
updates a value for each index part that indicates the average number of
rows that have the same value. (For unique indexes, this is always 1,
-of course.). MySQL will use this to decide which index to
+of course.) MySQL will use this to decide which index to
choose when you connect two tables with 'a non-constant expression'.
You can check the result from the @code{analyze} run by doing @code{SHOW
INDEX FROM table_name} and examining the @code{Cardinality} column.
@@ -25100,21 +25097,21 @@ time for a large table!
@end itemize
-@node Where optimizations, DISTINCT optimization, SELECT speed, Query Speed
-@subsection How MySQL Optimizes @code{WHERE} Clauses
+@node Where optimisations, DISTINCT optimisation, SELECT speed, Query Speed
+@subsection How MySQL Optimises @code{WHERE} Clauses
@findex WHERE
-@cindex optimizations
+@cindex optimisations
-The @code{WHERE} optimizations are put in the @code{SELECT} part here because
-they are mostly used with @code{SELECT}, but the same optimizations apply for
+The @code{WHERE} optimisations are put in the @code{SELECT} part here because
+they are mostly used with @code{SELECT}, but the same optimisations apply for
@code{WHERE} in @code{DELETE} and @code{UPDATE} statements.
Also note that this section is incomplete. MySQL does many
-optimizations, and we have not had time to document them all.
+optimisations, and we have not had time to document them all.
-Some of the optimizations performed by MySQL are listed below:
+Some of the optimisations performed by MySQL are listed below:
@itemize @bullet
@item
@@ -25139,8 +25136,8 @@ Constant condition removal (needed because of constant folding):
Constant expressions used by indexes are evaluated only once.
@item
@code{COUNT(*)} on a single table without a @code{WHERE} is retrieved
-directly from the table information. This is also done for any @code{NOT NULL}
-expression when used with only one table.
+directly from the table information for MyISAM and HEAP tables. This is
+also done for any @code{NOT NULL} expression when used with only one table.
@item
Early detection of invalid constant expressions. MySQL quickly
detects that some @code{SELECT} statements are impossible and returns no rows.
@@ -25228,12 +25225,12 @@ mysql> SELECT ... FROM tbl_name ORDER BY key_part1 DESC,key_part2 DESC,... ;
@end example
-@node DISTINCT optimization, LEFT JOIN optimization, Where optimizations, Query Speed
-@subsection How MySQL Optimizes @code{DISTINCT}
+@node DISTINCT optimisation, LEFT JOIN optimisation, Where optimisations, Query Speed
+@subsection How MySQL Optimises @code{DISTINCT}
@findex DISTINCT
-@cindex optimizing, DISTINCT
+@cindex optimising, DISTINCT
@code{DISTINCT} is converted to a @code{GROUP BY} on all columns,
@code{DISTINCT} combined with @code{ORDER BY} will in many cases also
@@ -25254,12 +25251,12 @@ MySQL will stop reading from t2 (for that particular row in t1)
when the first row in t2 is found.
-@node LEFT JOIN optimization, LIMIT optimization, DISTINCT optimization, Query Speed
-@subsection How MySQL Optimizes @code{LEFT JOIN} and @code{RIGHT JOIN}
+@node LEFT JOIN optimisation, ORDER BY optimisation, DISTINCT optimisation, Query Speed
+@subsection How MySQL Optimises @code{LEFT JOIN} and @code{RIGHT JOIN}
@findex LEFT JOIN
-@cindex optimizing, LEFT JOIN
+@cindex optimising, LEFT JOIN
@code{A LEFT JOIN B} in MySQL is implemented as follows:
@@ -25276,12 +25273,12 @@ that are used in the @code{LEFT JOIN} condition.
All @code{LEFT JOIN} conditions are moved to the @code{WHERE} clause.
@item
-All standard join optimizations are done, with the exception that a table is
+All standard join optimisations are done, with the exception that a table is
always read after all tables it is dependent on. If there is a circular
dependence then MySQL will issue an error.
@item
-All standard @code{WHERE} optimizations are done.
+All standard @code{WHERE} optimisations are done.
@item
If there is a row in @code{A} that matches the @code{WHERE} clause, but there
@@ -25300,7 +25297,7 @@ matches the @code{LEFT JOIN} condition.
@code{RIGHT JOIN} is implemented analogously as @code{LEFT JOIN}.
The table read order forced by @code{LEFT JOIN} and @code{STRAIGHT JOIN}
-will help the join optimizer (which calculates in which order tables
+will help the join optimiser (which calculates in which order tables
should be joined) to do its work much more quickly, as there are fewer
table permutations to check.
@@ -25320,12 +25317,124 @@ SELECT * FROM b,a LEFT JOIN c ON (c.key=a.key) LEFT JOIN d (d.key=a.key) WHERE b
@end example
-@node LIMIT optimization, Insert speed, LEFT JOIN optimization, Query Speed
-@subsection How MySQL Optimizes @code{LIMIT}
+@node ORDER BY optimisation, LIMIT optimisation, LEFT JOIN optimisation, Query Speed
+@subsection How MySQL Optimises @code{ORDER BY}
+
+In some cases MySQL can uses index to satisfy an @code{ORDER BY} or
+@code{GROUP BY} request without doing any extra sorting.
+
+The index can also be used even if the @code{ORDER BY} doesn't match the
+index exactly, as long as all the unused index parts and all the extra
+are @code{ORDER BY} columns are constants in the @code{WHERE}
+clause. The following queries will use the index to resolve the
+@code{ORDER BY} / @code{GROUP BY} part:
+
+@example
+SELECT * FROM t1 ORDER BY key_part1,key_part2,...
+SELECT * FROM t1 WHERE key_part1=constant ORDER BY key_part2
+SELECT * FROM t1 WHERE key_part1=constant GROUP BY key_part2
+SELECT * FROM t1 ORDER BY key_part1 DESC,key_part2 DESC
+SELECT * FROM t1 WHERE key_part1=1 ORDER BY key_part1 DESC,key_part2 DESC
+@end example
+
+Some cases where MySQL can NOT use indexes to resolve the @code{ORDER
+BY}: (Note that MySQL will still use indexes to find the rows that
+matches the where clause):
+
+@itemize @bullet
+@item
+You are doing an @code{ORDER BY} on different keys:
+
+@code{SELECT * FROM t1 ORDER BY key1,key2}
+@item
+You are doing an @code{ORDER BY} on not following key parts.
+
+@code{SELECT * FROM t1 WHERE key2=constant ORDER BY key_part2}
+
+@item
+You are mixing @code{ASC} and @code{DESC}.
+
+@code{SELECT * FROM t1 ORDER BY key_part1 DESC,key_part2 ASC}
+
+@item
+The key used to fetch the rows are not the same one that is used to
+do the @code{ORDER BY}:
+
+@code{SELECT * FROM t1 WHERE key2=constant ORDER BY key1}
+
+@item
+You are joining many tables and the columns you are doing an @code{ORDER
+BY} on are not all from the first not-const table that is used to
+retrieve rows (This is the first table in the @code{EXPLAIN} output which
+doesn't use a @code{const} row fetch method).
+
+@item
+You have different @code{ORDER BY} and @code{GROUP BY} expressions.
+
+@item
+The used table index is an index type that doesn't store rows in order.
+(Like index in @code{HEAP} tables).
+@end itemize
+
+
+In the cases where MySQL have to sort the result, it uses the following
+algorithm:
+
+@itemize @bullet
+@item
+Read all rows according to key or by table scanning.
+Rows that doesn't match the WHERE clause are skipped.
+@item
+Store the sort-key in a buffer (of size @code{sort_buffer}).
+@item
+When the buffer gets full, run a qsort on it and store the result
+in a temporary file. Save a pointer to the sorted block.
+(In the case where all rows fits into the sort buffer, no temporary
+file is created)
+@item
+Repeat the above until all rows have been read.
+@item
+Do a multi-merge of up to @code{MERGEBUFF} (7) regions to one block in
+another temporary file. Repeat until all blocks from the first file
+are in the second file.
+@item
+Repeat the following until there is less than @code{MERGEBUFF2} (15)
+blocks left.
+@item
+On the last multi-merge, only the pointer to the row (last part of
+the sort-key) is written to a result file.
+@item
+Now the code in @file{sql/records.cc} will be used to read through them
+in sorted order by using the row pointers in the result file. To
+optimize this, we read in a big block of row pointers, sort these and
+then we read the rows in the sorted order into a row buffer
+(@code{record_rnd_buffer}) .
+@end itemize
+
+You can with @code{EXPLAIN SELECT ... ORDER BY} check if MySQL can use
+indexes to resolve the query. If you get @code{Using filesort} in the
+@code{extra} column, then MySQL can't use indexes to resolve the
+@code{ORDER BY}. @xref{EXPLAIN}.
+
+If you want to have a higher @code{ORDER BY} speed, you should first
+see if you can get MySQL to use indexes instead of having to do an extra
+sorting phase. If this is not possible, then you can do:
+
+@itemize @bullet
+@item
+Increase the size of the @code{sort_buffer} variable.
+@item
+Increase the size of the @code{record_rnd_buffer} variable.
+@item
+Change @code{tmpdir} to point to a dedicated disk with lots of empty space.
+@end itemize
+
+@node LIMIT optimisation, Insert speed, ORDER BY optimisation, Query Speed
+@subsection How MySQL Optimises @code{LIMIT}
@findex LIMIT
-@cindex optimizing, LIMIT
+@cindex optimising, LIMIT
In some cases MySQL will handle the query differently when you are
using @code{LIMIT #} and not using @code{HAVING}:
@@ -25349,7 +25458,7 @@ key value changes. In this case @code{LIMIT #} will not calculate any
unnecessary @code{GROUP BY}'s.
@item
As soon as MySQL has sent the first @code{#} rows to the client, it
-will abort the query.
+will abort the query (If you are not using @code{SQL_CALC_FOUND_ROWS}).
@item
@code{LIMIT 0} will always quickly return an empty set. This is useful
to check the query and to get the column types of the result columns.
@@ -25359,7 +25468,7 @@ space is needed to resolve the query.
@end itemize
-@node Insert speed, Update speed, LIMIT optimization, Query Speed
+@node Insert speed, Update speed, LIMIT optimisation, Query Speed
@subsection Speed of @code{INSERT} Queries
@findex INSERT
@@ -25396,14 +25505,16 @@ Some ways to speed up inserts:
@itemize @bullet
@item
If you are inserting many rows from the same client at the same time, use
-multiple value lists @code{INSERT} statements. This is much faster (many
-times in some cases) than using separate @code{INSERT} statements.
+multiple value lists @code{INSERT} statements. This is much faster (many times
+in some cases) than using separate @code{INSERT} statements. If you are adding
+data to non-empty table, you may tune up @code{myisam_bulk_insert_tree_size}
+variable to make it even faster. @xref{SHOW VARIABLES}.
@item
If you are inserting a lot of rows from different clients, you can get
higher speed by using the @code{INSERT DELAYED} statement. @xref{INSERT,
, @code{INSERT}}.
@item
-Note that with @code{MyISAM} you can insert rows at the same time
+Note that with @code{MyISAM} tables you can insert rows at the same time
@code{SELECT}s are running if there are no deleted rows in the tables.
@item
When loading a table from a text file, use @code{LOAD DATA INFILE}. This
@@ -25445,10 +25556,21 @@ Execute a @code{FLUSH TABLES} statement or the shell command @code{mysqladmin
flush-tables}.
@end enumerate
-This procedure will be built into @code{LOAD DATA INFILE} in some future
-version of MySQL.
+Note that @code{LOAD DATA INFILE} also does the above optimization if
+you insert into an empty table; The main difference with the above
+procedure is that you can let myisamchk allocate much more temporary
+memory for the index creation that you may want MySQL to allocate for
+every index recreation.
+
+Since @strong{MySQL 4.0} you can also use
+@code{ALTER TABLE tbl_name DISABLE KEYS} instead of
+@code{myisamchk --keys-used=0 -rq /path/to/db/tbl_name} and
+@code{ALTER TABLE tbl_name ENABLE KEYS} instead of
+@code{myisamchk -r -q /path/to/db/tbl_name}. This way you can also skip
+@code{FLUSH TABLES} steps.
@item
-You can speed up insertions by locking your tables:
+You can speed up insertions that is done over multiple statements by
+locking your tables:
@example
mysql> LOCK TABLES a WRITE;
@@ -25463,6 +25585,9 @@ be as many index buffer flushes as there are different @code{INSERT}
statements. Locking is not needed if you can insert all rows with a single
statement.
+For transactional tables, you should use @code{BEGIN/COMMIT} instead of
+@code{LOCK TABLES} to get a speedup.
+
Locking will also lower the total time of multi-connection tests, but the
maximum wait time for some threads will go up (because they wait for
locks). For example:
@@ -25495,7 +25620,7 @@ To get some more speed for both @code{LOAD DATA INFILE} and
@node Update speed, Delete speed, Insert speed, Query Speed
@subsection Speed of @code{UPDATE} Queries
-Update queries are optimized as a @code{SELECT} query with the additional
+Update queries are optimised as a @code{SELECT} query with the additional
overhead of a write. The speed of the write is dependent on the size of
the data that is being updated and the number of indexes that are
updated. Indexes that are not changed will not be updated.
@@ -25522,10 +25647,10 @@ the index cache. @xref{Server parameters}.
@node Tips, , Delete speed, Query Speed
-@subsection Other Optimization Tips
+@subsection Other Optimisation Tips
-@cindex optimization, tips
-@cindex tips, optimization
+@cindex optimisation, tips
+@cindex tips, optimisation
Unsorted tips for faster systems:
@@ -25540,7 +25665,7 @@ Always check that all your queries really use the indexes you have created
in the tables. In MySQL you can do this with the @code{EXPLAIN}
command. @xref{EXPLAIN, Explain, Explain, manual}.
@item
-Try to avoid complex @code{SELECT} queries on tables that are updated a
+Try to avoid complex @code{SELECT} queries on MyISAM tables that are updated a
lot. This is to avoid problems with table locking.
@item
The new @code{MyISAM} tables can insert rows in a table without deleted
@@ -25549,7 +25674,7 @@ for you, you should consider methods where you don't have to delete rows
or run @code{OPTIMIZE TABLE} after you have deleted a lot of rows.
@item
Use @code{ALTER TABLE ... ORDER BY expr1,expr2...} if you mostly
-retrieve rows in expr1,expr2.. order. By using this option after big
+retrieve rows in expr1,expr2... order. By using this option after big
changes to the table, you may be able to get higher performance.
@item
In some cases it may make sense to introduce a column that is 'hashed'
@@ -25667,7 +25792,7 @@ Try to keep the names simple (use @code{name} instead of
@code{customer_name} in the customer table). To make your names portable
to other SQL servers you should keep them shorter than 18 characters.
@item
-If you need REALLY high speed, you should take a look at the low-level
+If you need really high speed, you should take a look at the low-level
interfaces for data storage that the different SQL servers support! For
example, by accessing the MySQL @code{MyISAM} directly, you could
get a speed increase of 2-5 times compared to using the SQL interface.
@@ -25677,7 +25802,7 @@ the application, and usually it should only be accessed by one process
above problems by introducing low-level @code{MyISAM} commands in the
MySQL server (this could be one easy way to get more
performance if needed). By carefully designing the database interface,
-it should be quite easy to support this types of optimization.
+it should be quite easy to support this types of optimisation.
@item
In many cases it's faster to access data from a database (using a live
connection) than accessing a text file, just because the database is
@@ -25697,7 +25822,7 @@ from the data, you should not lose anything by using @code{DELAY_KEY_WRITE}.
@end itemize
-@node Locking Issues, Optimizing Database Structure, Query Speed, MySQL Optimization
+@node Locking Issues, Optimising Database Structure, Query Speed, MySQL Optimisation
@section Locking Issues
@@ -25717,10 +25842,17 @@ from the data, you should not lose anything by using @code{DELAY_KEY_WRITE}.
You can find a discussion about different locking methods in the appendix.
@xref{Locking methods}.
-All locking in MySQL is deadlock-free. This is managed by always
+All locking in MySQL is deadlock-free, except for @code{InnoDB} and
+@code{BDB} type tables.
+This is managed by always
requesting all needed locks at once at the beginning of a query and always
locking the tables in the same order.
+@code{InnoDB} type tables automatically acquire their row locks and
+@code{BDB} type tables
+their page locks during the processing of SQL statements, not at the start
+of the transaction.
+
The locking method MySQL uses for @code{WRITE} locks works as follows:
@itemize @bullet
@@ -25760,7 +25892,7 @@ mysql> UNLOCK TABLES;
You can use the @code{LOW_PRIORITY} options with @code{INSERT},
@code{UPDATE} or @code{DELETE} or @code{HIGH_PRIORITY} with
-@code{SELECT} if you want to prioritize retrieval in some specific
+@code{SELECT} if you want to prioritise retrieval in some specific
cases. You can also start @code{mysqld} with @code{--low-priority-updates}
to get the same behaveour.
@@ -25780,16 +25912,18 @@ priority, which might help some applications.
The table locking code in MySQL is deadlock free.
MySQL uses table locking (instead of row locking or column
-locking) on all table types, except @code{BDB} tables, to achieve a very
-high lock speed. For large tables, table locking is MUCH better than
+locking) on all table types, except @code{InnoDB} and @code{BDB} tables,
+to achieve a very
+high lock speed. For large tables, table locking is much better than
row locking for most applications, but there are, of course, some
pitfalls.
-For @code{BDB} and @code{InnoDB} tables, MySQL only uses table
-locking if you explicitely lock the table with @code{LOCK TABLES} or
-execute a command that will modify every row in the table, like
-@code{ALTER TABLE}. For these table types we recommend you to not use
-@code{LOCK TABLES} at all.
+For @code{InnoDB} and @code{BDB} tables, MySQL only uses table
+locking if you explicitly lock the table with @code{LOCK TABLES}.
+For these table types we recommend you to not use
+@code{LOCK TABLES} at all, because @code{InnoDB} uses automatic
+row level locking and @code{BDB} uses page level locking to
+ensure transaction isolation.
In MySQL Version 3.23.7 and above, you can insert rows into
@code{MyISAM} tables at the same time other threads are reading from the
@@ -25881,8 +26015,8 @@ option to @code{DELETE} may help. @xref{DELETE, , @code{DELETE}}.
@end itemize
-@node Optimizing Database Structure, Optimizing the Server, Locking Issues, MySQL Optimization
-@section Optimizing Database Structure
+@node Optimising Database Structure, Optimising the Server, Locking Issues, MySQL Optimisation
+@section Optimising Database Structure
@menu
@@ -25891,13 +26025,13 @@ option to @code{DELETE} may help. @xref{DELETE, , @code{DELETE}}.
* MySQL indexes:: How MySQL Uses Indexes
* Indexes:: Column Indexes
* Multiple-column indexes:: Multiple-Column Indexes
+* Open tables:: Why So Many Open tables?
* Table cache:: How MySQL Opens and Closes Tables
* Creating many tables:: Drawbacks to Creating Large Numbers of Tables in the Same Database
-* Open tables:: Why So Many Open tables?
@end menu
-@node Design, Data size, Optimizing Database Structure, Optimizing Database Structure
+@node Design, Data size, Optimising Database Structure, Optimising Database Structure
@subsection Design Choices
@cindex design, choices
@@ -25933,20 +26067,20 @@ You lose a lot of space, as you must duplicate indexes from the nodes
Deletes will degenerate the table over time (as indexes in nodes are
usually not updated on delete).
@item
-It's harder to cache ONLY the index data.
+It's harder to cache only the index data.
@end itemize
-@node Data size, MySQL indexes, Design, Optimizing Database Structure
+@node Data size, MySQL indexes, Design, Optimising Database Structure
@subsection Get Your Data as Small as Possible
@cindex data, size
@cindex reducing, data size
-@cindex storage space, minimizing
+@cindex storage space, minimising
@cindex tables, improving performance
@cindex performance, improving
-One of the most basic optimization is to get your data (and indexes) to
+One of the most basic optimisation is to get your data (and indexes) to
take as little space on the disk (and in memory) as possible. This can
give huge improvements because disk reads are faster and normally less
main memory will be used. Indexing also takes less resources if
@@ -25956,13 +26090,13 @@ MySQL supports a lot of different table types and row formats.
Choosing the right table format may give you a big performance gain.
@xref{Table types}.
-You can get better performance on a table and minimize storage space
+You can get better performance on a table and minimise storage space
using the techniques listed below:
@itemize @bullet
@item
Use the most efficient (smallest) types possible. MySQL has
-many specialized types that save disk space and memory.
+many specialised types that save disk space and memory.
@item
Use the smaller integer types if possible to get smaller tables. For
@@ -25993,7 +26127,7 @@ Only create the indexes that you really need. Indexes are good for
retrieval but bad when you need to store things fast. If you mostly
access a table by searching on a combination of columns, make an index
on them. The first index part should be the most used column. If you are
-ALWAYS using many columns, you should use the column with more duplicates
+@strong{always} using many columns, you should use the column with more duplicates
first to get better compression of the index.
@item
@@ -26012,7 +26146,7 @@ can be used to find the relevant rows when scanning the table.
@end itemize
-@node MySQL indexes, Indexes, Data size, Optimizing Database Structure
+@node MySQL indexes, Indexes, Data size, Optimising Database Structure
@subsection How MySQL Uses Indexes
@cindex indexes, use of
@@ -26041,7 +26175,7 @@ Retrieve rows from other tables when performing joins.
@item
Find the @code{MAX()} or @code{MIN()} value for a specific indexed
-column. This is optimized by a preprocessor that checks if you are
+column. This is optimised by a preprocessor that checks if you are
using @code{WHERE} key_part_# = constant on all key parts < N. In this case
MySQL will do a single key lookup and replace the @code{MIN()}
expression with a constant. If all expressions are replaced with
@@ -26053,22 +26187,12 @@ SELECT MIN(key_part2),MAX(key_part2) FROM table_name where key_part1=10
@item
Sort or group a table if the sorting or grouping is done on a leftmost
-prefix of a usable key (for example, @code{ORDER BY key_part_1,key_part_2 }). The
-key is read in reverse order if all key parts are followed by @code{DESC}.
-
-The index can also be used even if the @code{ORDER BY} doesn't match the index
-exactly, as long as all the unused index parts and all the extra
-are @code{ORDER BY} columns are constants in the @code{WHERE} clause. The
-following queries will use the index to resolve the @code{ORDER BY} part:
-
-@example
-SELECT * FROM foo ORDER BY key_part1,key_part2,key_part3;
-SELECT * FROM foo WHERE column=constant ORDER BY column, key_part1;
-SELECT * FROM foo WHERE key_part1=const GROUP BY key_part2;
-@end example
+prefix of a usable key (for example, @code{ORDER BY
+key_part_1,key_part_2 }). The key is read in reverse order if all key
+parts are followed by @code{DESC}. @xref{ORDER BY optimisation}.
@item
-In some cases a query can be optimized to retrieve values without
+In some cases a query can be optimised to retrieve values without
consulting the data file. If all used columns for some table are numeric
and form a leftmost prefix for some key, the values may be retrieved
from the index tree for greater speed:
@@ -26087,14 +26211,14 @@ mysql> SELECT * FROM tbl_name WHERE col1=val1 AND col2=val2;
If a multiple-column index exists on @code{col1} and @code{col2}, the
appropriate rows can be fetched directly. If separate single-column
-indexes exist on @code{col1} and @code{col2}, the optimizer tries to
+indexes exist on @code{col1} and @code{col2}, the optimiser tries to
find the most restrictive index by deciding which index will find fewer
rows and using that index to fetch the rows.
@cindex indexes, leftmost prefix of
@cindex leftmost prefix of indexes
If the table has a multiple-column index, any leftmost prefix of the
-index can be used by the optimizer to find rows. For example, if you
+index can be used by the optimiser to find rows. For example, if you
have a three-column index on @code{(col1,col2,col3)}, you have indexed
search capabilities on @code{(col1)}, @code{(col1,col2)}, and
@code{(col1,col2,col3)}.
@@ -26152,7 +26276,7 @@ index is used for columns that you compare with the following operators:
@code{LIKE} with a non-wild-card prefix like @code{'something%'}.
Any index that doesn't span all @code{AND} levels in the @code{WHERE} clause
-is not used to optimize the query. In other words: To be able to use an
+is not used to optimise the query. In other words: To be able to use an
index, a prefix of the index must be used in every @code{AND} group.
The following @code{WHERE} clauses use indexes:
@@ -26160,7 +26284,7 @@ The following @code{WHERE} clauses use indexes:
... WHERE index_part1=1 AND index_part2=2 AND other_column=3
... WHERE index=1 OR A=10 AND index=2 /* index = 1 OR index = 2 */
... WHERE index_part1='hello' AND index_part_3=5
- /* optimized like "index_part1='hello'" */
+ /* optimised like "index_part1='hello'" */
... WHERE index1=1 and index2=2 or index1=3 and index3=3;
/* Can use index on index1 but not on index2 or index 3 */
@end example
@@ -26179,23 +26303,13 @@ would be available. Some of the cases where this happens are:
@item
If the use of the index would require MySQL to access more
than 30 % of the rows in the table. (In this case a table scan is
-probably much faster, as this will require us to do much fewer seeks).
+probably much faster, as this will require us to do much fewer seeks.)
Note that if such a query uses @code{LIMIT} to only retrieve
part of the rows, MySQL will use an index anyway, as it can
much more quickly find the few rows to return in the result.
@end itemize
-
-@menu
-* Indexes:: Column Indexes
-* Multiple-column indexes:: Multiple-Column Indexes
-* Table cache:: How MySQL Opens and Closes Tables
-* Creating many tables:: Drawbacks to Creating Large Numbers of Tables in the Same Database
-* Open tables:: Why So Many Open tables?
-@end menu
-
-
-@node Indexes, Multiple-column indexes, MySQL indexes, Optimizing Database Structure
+@node Indexes, Multiple-column indexes, MySQL indexes, Optimising Database Structure
@subsection Column Indexes
@cindex indexes, columns
@@ -26238,7 +26352,7 @@ created only from @code{VARCHAR} and @code{TEXT} columns.
Indexing always happens over the entire column and partial indexing is not
supported. See @ref{Fulltext Search} for details.
-@node Multiple-column indexes, Table cache, Indexes, Optimizing Database Structure
+@node Multiple-column indexes, Open tables, Indexes, Optimising Database Structure
@subsection Multiple-Column Indexes
@cindex multi-column indexes
@@ -26247,7 +26361,7 @@ supported. See @ref{Fulltext Search} for details.
MySQL can create indexes on multiple columns. An index may
consist of up to 15 columns. (On @code{CHAR} and @code{VARCHAR} columns you
-can also use a prefix of the column as a part of an index).
+can also use a prefix of the column as a part of an index.)
A multiple-column index can be considered a sorted array containing values
that are created by concatenating the values of the indexed columns.
@@ -26299,8 +26413,31 @@ For more information on the manner in which MySQL uses indexes to
improve query performance, see @ref{MySQL indexes, , MySQL
indexes}.
+@node Open tables, Table cache, Multiple-column indexes, Optimising Database Structure
+@subsection Why So Many Open tables?
+
+@cindex tables, open
+@cindex open tables
-@node Table cache, Creating many tables, Multiple-column indexes, Optimizing Database Structure
+When you run @code{mysqladmin status}, you'll see something like this:
+
+@example
+Uptime: 426 Running threads: 1 Questions: 11082 Reloads: 1 Open tables: 12
+@end example
+
+This can be somewhat perplexing if you only have 6 tables.
+
+MySQL is multithreaded, so it may have many queries on the same table
+simultaneously. To minimise the problem with two threads having
+different states on the same file, the table is opened independently by
+each concurrent thread. This takes some memory but will normaly increase
+performance. Wth ISAM and MyISAM tables this also requires one extra file
+descriptor for the data file. With these table types the index file
+descriptor is shared between all threads.
+
+You can read more about this topic in the next section. @xref{Table cache}.
+
+@node Table cache, Creating many tables, Open tables, Optimising Database Structure
@subsection How MySQL Opens and Closes Tables
@findex table_cache
@@ -26325,11 +26462,37 @@ at least @code{200 * n}, where @code{n} is the maximum number of tables
in a join. You also need to reserve some extra file descriptors for
temporary tables and files.
-The cache of open tables can grow to a maximum of @code{table_cache}
-(default 64; this can be changed with the @code{-O table_cache=#}
-option to @code{mysqld}). A table is never closed, except when the
-cache is full and another thread tries to open a table or if you use
-@code{mysqladmin refresh} or @code{mysqladmin flush-tables}.
+Make sure that your operating system can handle the number of open file
+descriptors implied by the @code{table_cache} setting. If
+@code{table_cache} is set too high, MySQL may run out of file
+descriptors and refuse connections, fail to perform queries, and be very
+unreliable. You also have to take into account that the MyISAM table
+handler needs two file descriptors for each unique open table. You can
+in increase the number of file descriptors available for MySQL with
+the @code{--open-files-limit=#} startup option. @xref{Not enough file
+handles}.
+
+The cache of open tables will be keept at a level of @code{table_cache}
+entries (default 64; this can be changed with the @code{-O
+table_cache=#} option to @code{mysqld}). Note that in MySQL may
+temporarly open even more tables to be able to execute queries.
+
+A not used table is closed and removed from the table cache under the
+following circumstances:
+
+@itemize @bullet
+@item
+When the cache is full and a thread tries to open a table that is not in
+the cache.
+@item
+When the cache contains more than @code{table_cache} entires and
+a thread is not anymore using a table.
+@item
+When someone executes @code{mysqladmin refresh} or
+@code{mysqladmin flush-tables}.
+@item
+When someone executes 'FLUSH TABLES'
+@end itemize
When the table cache fills up, the server uses the following procedure
to locate a cache entry to use:
@@ -26356,13 +26519,20 @@ use of the table takes only one file descriptor. The extra descriptor
for the first open is used for the index file; this descriptor is shared
among all threads.
+If you are opening a table with the @code{HANDLER table_name OPEN}
+statement, a dedicated table object is allocated for the thread.
+This table object is not shared by other threads an will not be closed
+until the thread calls @code{HANDLER table_name CLOSE} or the thread dies.
+@xref{HANDLER}. When this happens, the table is put back in the table_cache
+(if it isn't full).
+
You can check if your table cache is too small by checking the mysqld
-variable @code{opened_tables}. If this is quite big, even if you
+variable @code{Opened_tables}. If this is quite big, even if you
haven't done a lot of @code{FLUSH TABLES}, you should increase your table
cache. @xref{SHOW STATUS}.
-@node Creating many tables, Open tables, Table cache, Optimizing Database Structure
+@node Creating many tables, , Table cache, Optimising Database Structure
@subsection Drawbacks to Creating Large Numbers of Tables in the Same Database
@cindex tables, too many
@@ -26374,30 +26544,8 @@ every table that has to be opened, another must be closed. You can reduce
this overhead by making the table cache larger.
-@node Open tables, , Creating many tables, Optimizing Database Structure
-@subsection Why So Many Open tables?
-
-@cindex tables, open
-@cindex open tables
-
-When you run @code{mysqladmin status}, you'll see something like this:
-
-@example
-Uptime: 426 Running threads: 1 Questions: 11082 Reloads: 1 Open tables: 12
-@end example
-
-This can be somewhat perplexing if you only have 6 tables.
-
-MySQL is multithreaded, so it may have many queries on the same
-table simultaneously. To minimize the problem with two threads having
-different states on the same file, the table is opened independently by
-each concurrent thread. This takes some memory and one extra file
-descriptor for the data file. The index file descriptor is shared
-between all threads.
-
-
-@node Optimizing the Server, Disk issues, Optimizing Database Structure, MySQL Optimization
-@section Optimizing the MySQL Server
+@node Optimising the Server, Disk issues, Optimising Database Structure, MySQL Optimisation
+@section Optimising the MySQL Server
@menu
@@ -26410,11 +26558,11 @@ between all threads.
@end menu
-@node System, Server parameters, Optimizing the Server, Optimizing the Server
+@node System, Server parameters, Optimising the Server, Optimising the Server
@subsection System/Compile Time and Startup Parameter Tuning
-@cindex compiling, optimizing
-@cindex system optimization
+@cindex compiling, optimising
+@cindex system optimisation
@cindex startup parameters, tuning
We start with the system level things since some of these decisions have
@@ -26465,7 +26613,7 @@ are using @code{--skip-locking}
@end itemize
-@node Server parameters, Compile and link options, System, Optimizing the Server
+@node Server parameters, Compile and link options, System, Optimising the Server
@subsection Tuning Server Parameters
@cindex parameters, server
@@ -26587,7 +26735,7 @@ is done.
When you have installed MySQL, the @file{support-files} directory will
contain some different @code{my.cnf} example files, @file{my-huge.cnf},
@file{my-large.cnf}, @file{my-medium.cnf}, and @file{my-small.cnf}, you can
-use as a base to optimize your system.
+use as a base to optimise your system.
If there are very many connections, ``swapping problems'' may occur unless
@code{mysqld} has been configured to use very little memory for each
@@ -26608,7 +26756,7 @@ options listed after it on the command line will not be reflected in the
output.
-@node Compile and link options, Memory use, Server parameters, Optimizing the Server
+@node Compile and link options, Memory use, Server parameters, Optimising the Server
@subsection How Compiling and Linking Affects the Speed of MySQL
@cindex linking, speed
@@ -26638,10 +26786,10 @@ important if you compile the SQL server yourself!
We have tested both the Cygnus CodeFusion and Fujitsu compilers, but
when we tested them, neither was sufficiently bug free to allow
-MySQL to be compiled with optimizations on.
+MySQL to be compiled with optimisations on.
When you compile MySQL you should only include support for the
-character sets that you are going to use. (Option @code{--with-charset=xxx}).
+character sets that you are going to use. (Option @code{--with-charset=xxx}.)
The standard MySQL binary distributions are compiled with support
for all character sets.
@@ -26664,7 +26812,7 @@ the resulting binary can be up to 4 % faster.
@item
If you connect using TCP/IP rather than Unix sockets, the result is 7.5%
slower on the same computer. (If you are connection to @code{localhost},
-MySQL will, by default, use sockets).
+MySQL will, by default, use sockets.)
@item
If you connect using TCP/IP from another computer over a 100M Ethernet,
@@ -26709,7 +26857,7 @@ binary by compiling with @code{pgcc}. The standard MySQL
Linux binary is linked statically to get it faster and more portable.
-@node Memory use, DNS, Compile and link options, Optimizing the Server
+@node Memory use, DNS, Compile and link options, Optimising the Server
@subsection How MySQL Uses Memory
@cindex memory use
@@ -26818,7 +26966,7 @@ checking available swap with @code{swap -s}. We have tested
be no memory leaks.
-@node DNS, SET OPTION, Memory use, Optimizing the Server
+@node DNS, SET OPTION, Memory use, Optimising the Server
@subsection How MySQL uses DNS
@cindex DNS
@@ -26853,7 +27001,7 @@ If you don't want to allow connections over @code{TCP/IP}, you can do this
by starting @code{mysqld} with @code{--skip-networking}.
-@node SET OPTION, , DNS, Optimizing the Server
+@node SET OPTION, , DNS, Optimising the Server
@subsection @code{SET} Syntax
@findex SET OPTION
@@ -26952,6 +27100,16 @@ flag again, the @code{SQL_MAX_JOIN_SIZE} variable will be ignored.
You can set a default value for this variable by starting @code{mysqld} with
@code{-O max_join_size=#}.
+@item SQL_QUERY_CACHE_TYPE = OFF | ON | DEMAND
+@item SQL_QUERY_CACHE_TYPE = 0 | 1 | 2
+Set query cache setting for this thread.
+@multitable @columnfractions .3 .7
+@item @strong{Option} @tab @strong{Description}
+@item 0 or OFF @tab Don't cache or retrieve results.
+@item 1 or ON @tab Cache all results except @code{SELECT SQL_NO_CACHE ...} queries.
+@item 2 or DEMAND @tab Cache only @code{SELECT SQL_CACHE ...} queries.
+@end multitable
+
@item SQL_SAFE_UPDATES = 0 | 1
If set to @code{1}, MySQL will abort if an @code{UPDATE} or
@code{DELETE} is attempted that doesn't use a key or @code{LIMIT} in the
@@ -26984,7 +27142,7 @@ for replication of tables with fancy column names to work.
@item TIMESTAMP = timestamp_value | DEFAULT
Set the time for this client. This is used to get the original timestamp if
you use the update log to restore rows. @code{timestamp_value} should be a
-UNIX Epoch timestamp, not a MySQL timestamp.
+Unix epoch timestamp, not a MySQL timestamp.
@item LAST_INSERT_ID = #
Set the value to be returned from @code{LAST_INSERT_ID()}. This is stored in
@@ -26997,15 +27155,9 @@ command when inserting an @code{AUTO_INCREMENT} value. This is mainly used
with the update log.
@end table
+@xref{SET TRANSACTION}.
-@menu
-* SET TRANSACTION:: @code{SET TRANSACTION} Syntax
-@end menu
-
-
-
-
-@node Disk issues, , Optimizing the Server, MySQL Optimization
+@node Disk issues, , Optimising the Server, MySQL Optimisation
@section Disk Issues
@cindex disk issues
@@ -27018,7 +27170,7 @@ problems gets more and more apparent when the data starts to grow so
large that effective caching becomes impossible. For large databases,
where you access data more or less randomly, you can be sure that you
will need at least one disk seek to read and a couple of disk seeks to
-write things. To minimize this problem, use disks with low seek times.
+write things. To minimise this problem, use disks with low seek times.
@item
Increase the number of available disk spindles (and thereby reduce
@@ -27045,7 +27197,7 @@ stripe-sizes. @xref{Custom Benchmarks}.
Note that the speed difference for striping is @strong{very} dependent
on the parameters. Depending on how you set the striping parameters and
number of disks you may get a difference in orders of magnitude. Note that
-you have to choose to optimize for random or sequential access.
+you have to choose to optimise for random or sequential access.
@end table
@item
@@ -27173,7 +27325,7 @@ databases on different disks. @xref{Windows symbolic links}.
@cindex databases, symbolic links
Before MySQL 4.0 you should not symlink tables, if you are not
-very carefully with them. The problem is that if you run @code{ALTER
+very careful with them. The problem is that if you run @code{ALTER
TABLE}, @code{REPAIR TABLE} or @code{OPTIMIZE TABLE} on a symlinked
table, the symlinks will be removed and replaced by the original
files. This happens because the above command works by creating a
@@ -27213,7 +27365,7 @@ will be created in the same directory where the data/index file is.
@item
When you drop a table that is using symlinks, both the symlink and the
file the symlink points to is dropped. This is a good reason to why you
-should NOT run @code{mysqld} as root and not allow persons to have write
+should @strong{not} run @code{mysqld} as root and not allow persons to have write
access to the MySQL database directories.
@item
@@ -27247,11 +27399,16 @@ Things that are not yet supported:
@end itemize
-
-
-@node Reference, Table types, MySQL Optimization, Top
+@node Reference, Table types, MySQL Optimisation, Top
@chapter MySQL Language Reference
+MySQL has a very complex, but intuitive and easy to learn SQL
+interface. This chapter describes the various commands, types, and functions
+you will need to know in order to use MySQL efficiently and
+effectively. This chapter also serves as a reference to all functionality
+included in MySQL. In order to use this chapter effectively, you
+may find it useful to refer to the various indexes.
+
@menu
* Language Structure:: Language Structure
* Column types:: Column types
@@ -27261,15 +27418,9 @@ Things that are not yet supported:
* Basic User Commands:: Basic MySQL User Utility Commands
* Transactional Commands:: MySQL Transactional and Locking Commands
* Fulltext Search:: MySQL Full-text Search
+* Query Cache:: MySQL Query Cache
@end menu
-MySQL has a very complex, but intuitive and easy to learn SQL
-interface. This chapter describes the various commands, types, and functions
-you will need to know in order to use MySQL efficiently and
-effectively. This chapter also serves as a reference to all functionality
-included in MySQL. In order to use this chapter effectively, you
-may find it useful to refer to the various indexes.
-
@node Language Structure, Column types, Reference, Reference
@section Language Structure
@@ -27320,7 +27471,7 @@ if you run in ANSI mode). Examples:
Within a string, certain sequences have special meaning. Each of these
sequences begins with a backslash (@samp{\}), known as the @emph{escape
-character}. MySQL recognizes the following escape sequences:
+character}. MySQL recognises the following escape sequences:
@c these aren't really functions, but that's probably the most reasonable index
@table @code
@@ -27366,7 +27517,7 @@ A tab character.
ASCII(26) (Control-Z). This character can be encoded to allow you to
go around the problem that ASCII(26) stands for END-OF-FILE on Windows.
(ASCII(26) will cause problems if you try to use
-@code{mysql database < filename}).
+@code{mysql database < filename}.)
@findex \\ (escape)
@findex escape (\\)
@@ -27508,14 +27659,19 @@ like an integer (64-bit precision). In string context these act like a binary
string where each pair of hex digits is converted to a character:
@example
+mysql> SELECT x'FF'
+ -> 255
mysql> SELECT 0xa+0;
-> 10
mysql> select 0x5061756c;
-> Paul
@end example
+The x'hexstring' syntax (new in 4.0) is based on ANSI SQL and the 0x
+syntax is based on ODBC.
Hexadecimal strings are often used by ODBC to give values for BLOB columns.
-
+You can convert a string or a number to hexadecimal with the @code{HEX()}
+function.
@node NULL values, , Hexadecimal values, Literals
@subsubsection @code{NULL} Values
@@ -27542,11 +27698,6 @@ or export formats (@code{LOAD DATA INFILE}, @code{SELECT ... INTO OUTFILE}).
@cindex columns, names
@cindex aliases, names
-@menu
-* Name case sensitivity:: Case sensitivity in names
-@end menu
-
-
Database, table, index, column, and alias names all follow the same rules in
MySQL.
@@ -27700,7 +27851,7 @@ ISO-8859-1 Latin1; this may be changed with the
@code{--default-character-set} option to @code{mysqld}. @xref{Character
sets}.
-Variables don't have to be initialized. They contain @code{NULL} by default
+Variables don't have to be initialised. They contain @code{NULL} by default
and can store an integer, real, or string value. All variables for
a thread are automatically freed when the thread exits.
@@ -27744,12 +27895,6 @@ SELECT (@@aa:=id) AS a, (@@aa+3) AS b FROM table_name HAVING b=5;
The reason is that @code{@@aa} will not contain the value of the current
row, but the value of @code{id} for the previous accepted row.
-
-@menu
-* Comments:: Comment Syntax
-* Reserved words:: Is MySQL Picky About Reserved Words?
-@end menu
-
@node Comments, Reserved words, Variables, Language Structure
@subsection Comment Syntax
@@ -27784,7 +27929,7 @@ parses @code{/* ... */} comments:
@item
Single-quote and double-quote characters are taken to indicate the beginning
of a quoted string, even within a comment. If the quote is not matched by a
-second quote within the comment, the parser doesn't realize the comment has
+second quote within the comment, the parser doesn't realise the comment has
ended. If you are running @code{mysql} interactively, you can tell that it
has gotten confused like this because the prompt changes from @code{mysql>}
to @code{'>} or @code{">}.
@@ -27798,8 +27943,8 @@ These limitations apply both when you run @code{mysql} interactively
and when you put commands in a file and tell @code{mysql} to read its
input from that file with @code{mysql < some-file}.
-MySQL doesn't support the @samp{--} ANSI SQL comment style.
-@xref{Missing comments}.
+MySQL only supports the @samp{--} ANSI SQL comment style if it is
+followed by a space. @xref{ANSI diff comments}.
@node Reserved words, , Comments, Language Structure
@@ -27821,84 +27966,110 @@ them are forbidden by ANSI SQL92 as column and/or table names
A few are reserved because MySQL needs them and is
(currently) using a @code{yacc} parser:
-@c This is fixed by including the symbols table from lex.h here and then running
-@c fix-mysql-reserved-words in emacs (or let David do it):
-@c (defun fix-mysql-reserved-words ()
-@c (interactive)
-@c (let ((cnt 0))
-@c (insert "\n@item ")
-@c (while (looking-at "[ \t]*{ +\"\\([^\"]+\\)\"[ \t]*,.*\n")
-@c (replace-match "@code{\\1}")
-@c (incf cnt)
-@c (if (> cnt 3)
-@c (progn
-@c (setf cnt 0)
-@c (insert "\n@item "))
-@c (insert " @tab ")))))
-@c But remove the non alphanumeric entries by hand first.
-@c Updated after 3.23.4 990928 by David
+@c START_OF_RESERVED_WORDS
@multitable @columnfractions .25 .25 .25 .25
-@item @code{action} @tab @code{add} @tab @code{aggregate} @tab @code{all}
-@item @code{alter} @tab @code{after} @tab @code{and} @tab @code{as}
-@item @code{asc} @tab @code{avg} @tab @code{avg_row_length} @tab @code{auto_increment}
-@item @code{between} @tab @code{bigint} @tab @code{bit} @tab @code{binary}
-@item @code{blob} @tab @code{bool} @tab @code{both} @tab @code{by}
-@item @code{cascade} @tab @code{case} @tab @code{char} @tab @code{character}
-@item @code{change} @tab @code{check} @tab @code{checksum} @tab @code{column}
-@item @code{columns} @tab @code{comment} @tab @code{constraint} @tab @code{create}
-@item @code{cross} @tab @code{current_date} @tab @code{current_time} @tab @code{current_timestamp}
-@item @code{data} @tab @code{database} @tab @code{databases} @tab @code{date}
-@item @code{datetime} @tab @code{day} @tab @code{day_hour} @tab @code{day_minute}
-@item @code{day_second} @tab @code{dayofmonth} @tab @code{dayofweek} @tab @code{dayofyear}
-@item @code{dec} @tab @code{decimal} @tab @code{default} @tab @code{delayed}
-@item @code{delay_key_write} @tab @code{delete} @tab @code{desc} @tab @code{describe}
-@item @code{distinct} @tab @code{distinctrow} @tab @code{double} @tab @code{drop}
-@item @code{end} @tab @code{else} @tab @code{escape} @tab @code{escaped}
-@item @code{enclosed} @tab @code{enum} @tab @code{explain} @tab @code{exists}
-@item @code{fields} @tab @code{file} @tab @code{first} @tab @code{float}
-@item @code{float4} @tab @code{float8} @tab @code{flush} @tab @code{foreign}
-@item @code{from} @tab @code{for} @tab @code{full} @tab @code{function}
-@item @code{global} @tab @code{grant} @tab @code{grants} @tab @code{group}
-@item @code{having} @tab @code{heap} @tab @code{high_priority} @tab @code{hour}
-@item @code{hour_minute} @tab @code{hour_second} @tab @code{hosts} @tab @code{identified}
-@item @code{ignore} @tab @code{in} @tab @code{index} @tab @code{infile}
-@item @code{inner} @tab @code{insert} @tab @code{insert_id} @tab @code{int}
-@item @code{integer} @tab @code{interval} @tab @code{int1} @tab @code{int2}
-@item @code{int3} @tab @code{int4} @tab @code{int8} @tab @code{into}
-@item @code{if} @tab @code{is} @tab @code{isam} @tab @code{join}
-@item @code{key} @tab @code{keys} @tab @code{kill} @tab @code{last_insert_id}
-@item @code{leading} @tab @code{left} @tab @code{length} @tab @code{like}
-@item @code{lines} @tab @code{limit} @tab @code{load} @tab @code{local}
-@item @code{lock} @tab @code{logs} @tab @code{long} @tab @code{longblob}
-@item @code{longtext} @tab @code{low_priority} @tab @code{max} @tab @code{max_rows}
-@item @code{match} @tab @code{mediumblob} @tab @code{mediumtext} @tab @code{mediumint}
-@item @code{middleint} @tab @code{min_rows} @tab @code{minute} @tab @code{minute_second}
-@item @code{modify} @tab @code{month} @tab @code{monthname} @tab @code{myisam}
-@item @code{natural} @tab @code{numeric} @tab @code{no} @tab @code{not}
-@item @code{null} @tab @code{on} @tab @code{optimize} @tab @code{option}
-@item @code{optionally} @tab @code{or} @tab @code{order} @tab @code{outer}
-@item @code{outfile} @tab @code{pack_keys} @tab @code{partial} @tab @code{password}
-@item @code{precision} @tab @code{primary} @tab @code{procedure} @tab @code{process}
-@item @code{processlist} @tab @code{privileges} @tab @code{read} @tab @code{real}
-@item @code{references} @tab @code{reload} @tab @code{regexp} @tab @code{rename}
-@item @code{replace} @tab @code{restrict} @tab @code{returns} @tab @code{revoke}
-@item @code{rlike} @tab @code{row} @tab @code{rows} @tab @code{second}
-@item @code{select} @tab @code{set} @tab @code{show} @tab @code{shutdown}
-@item @code{smallint} @tab @code{soname} @tab @code{sql_big_tables} @tab @code{sql_big_selects}
-@item @code{sql_low_priority_updates} @tab @code{sql_log_off} @tab @code{sql_log_update} @tab @code{sql_select_limit}
-@item @code{sql_small_result} @tab @code{sql_big_result} @tab @code{sql_warnings} @tab @code{straight_join}
-@item @code{starting} @tab @code{status} @tab @code{string} @tab @code{table}
-@item @code{tables} @tab @code{temporary} @tab @code{terminated} @tab @code{text}
-@item @code{then} @tab @code{time} @tab @code{timestamp} @tab @code{tinyblob}
-@item @code{tinytext} @tab @code{tinyint} @tab @code{trailing} @tab @code{to}
-@item @code{type} @tab @code{use} @tab @code{using} @tab @code{unique}
-@item @code{unlock} @tab @code{unsigned} @tab @code{update} @tab @code{usage}
-@item @code{values} @tab @code{varchar} @tab @code{variables} @tab @code{varying}
-@item @code{varbinary} @tab @code{with} @tab @code{write} @tab @code{when}
-@item @code{where} @tab @code{year} @tab @code{year_month} @tab @code{zerofill}
+@item @strong{Word} @tab @strong{Word} @tab @strong{Word} @tab @strong{Word}
+@c Reserved word list updated Fri Dec 7 10:49:17 2001 by arjen.
+@c To regenerate, use Support/update-reserved-words.pl.
+
+@item @code{ADD} @tab @code{ALL}
+ @tab @code{ALTER} @tab @code{ANALYZE}
+@item @code{AND} @tab @code{AS}
+ @tab @code{ASC} @tab @code{AUTO_INCREMENT}
+@item @code{BDB} @tab @code{BERKELEYDB}
+ @tab @code{BETWEEN} @tab @code{BIGINT}
+@item @code{BINARY} @tab @code{BLOB}
+ @tab @code{BOTH} @tab @code{BY}
+@item @code{CASCADE} @tab @code{CASE}
+ @tab @code{CHANGE} @tab @code{CHAR}
+@item @code{CHARACTER} @tab @code{COLUMN}
+ @tab @code{COLUMNS} @tab @code{CONSTRAINT}
+@item @code{CREATE} @tab @code{CROSS}
+ @tab @code{CURRENT_DATE} @tab @code{CURRENT_TIME}
+@item @code{CURRENT_TIMESTAMP} @tab @code{DATABASE}
+ @tab @code{DATABASES} @tab @code{DAY_HOUR}
+@item @code{DAY_MINUTE} @tab @code{DAY_SECOND}
+ @tab @code{DEC} @tab @code{DECIMAL}
+@item @code{DEFAULT} @tab @code{DELAYED}
+ @tab @code{DELETE} @tab @code{DESC}
+@item @code{DESCRIBE} @tab @code{DISTINCT}
+ @tab @code{DISTINCTROW} @tab @code{DOUBLE}
+@item @code{DROP} @tab @code{ELSE}
+ @tab @code{ENCLOSED} @tab @code{ESCAPED}
+@item @code{EXISTS} @tab @code{EXPLAIN}
+ @tab @code{FIELDS} @tab @code{FLOAT}
+@item @code{FOR} @tab @code{FOREIGN}
+ @tab @code{FROM} @tab @code{FULLTEXT}
+@item @code{FUNCTION} @tab @code{GRANT}
+ @tab @code{GROUP} @tab @code{HAVING}
+@item @code{HIGH_PRIORITY} @tab @code{HOUR_MINUTE}
+ @tab @code{HOUR_SECOND} @tab @code{IF}
+@item @code{IGNORE} @tab @code{IN}
+ @tab @code{INDEX} @tab @code{INFILE}
+@item @code{INNER} @tab @code{INNODB}
+ @tab @code{INSERT} @tab @code{INSERT_ID}
+@item @code{INT} @tab @code{INTEGER}
+ @tab @code{INTERVAL} @tab @code{INTO}
+@item @code{IS} @tab @code{JOIN}
+ @tab @code{KEY} @tab @code{KEYS}
+@item @code{KILL} @tab @code{LAST_INSERT_ID}
+ @tab @code{LEADING} @tab @code{LEFT}
+@item @code{LIKE} @tab @code{LIMIT}
+ @tab @code{LINES} @tab @code{LOAD}
+@item @code{LOCK} @tab @code{LONG}
+ @tab @code{LONGBLOB} @tab @code{LONGTEXT}
+@item @code{LOW_PRIORITY} @tab @code{MASTER_LOG_SEQ}
+ @tab @code{MASTER_SERVER_ID} @tab @code{MATCH}
+@item @code{MEDIUMBLOB} @tab @code{MEDIUMINT}
+ @tab @code{MEDIUMTEXT} @tab @code{MIDDLEINT}
+@item @code{MINUTE_SECOND} @tab @code{MRG_MYISAM}
+ @tab @code{NATURAL} @tab @code{NOT}
+@item @code{NULL} @tab @code{NUMERIC}
+ @tab @code{ON} @tab @code{OPTIMIZE}
+@item @code{OPTION} @tab @code{OPTIONALLY}
+ @tab @code{OR} @tab @code{ORDER}
+@item @code{OUTER} @tab @code{OUTFILE}
+ @tab @code{PARTIAL} @tab @code{PRECISION}
+@item @code{PRIMARY} @tab @code{PRIVILEGES}
+ @tab @code{PROCEDURE} @tab @code{PURGE}
+@item @code{READ} @tab @code{REAL}
+ @tab @code{REFERENCES} @tab @code{REGEXP}
+@item @code{RENAME} @tab @code{REPLACE}
+ @tab @code{REQUIRE} @tab @code{RESTRICT}
+@item @code{RETURNS} @tab @code{REVOKE}
+ @tab @code{RIGHT} @tab @code{RLIKE}
+@item @code{SELECT} @tab @code{SET}
+ @tab @code{SHOW} @tab @code{SMALLINT}
+@item @code{SONAME} @tab @code{SQL_AUTO_IS_NULL}
+ @tab @code{SQL_BIG_RESULT} @tab @code{SQL_BIG_SELECTS}
+@item @code{SQL_BIG_TABLES} @tab @code{SQL_BUFFER_RESULT}
+ @tab @code{SQL_CALC_FOUND_ROWS} @tab @code{SQL_LOG_BIN}
+@item @code{SQL_LOG_OFF} @tab @code{SQL_LOG_UPDATE}
+ @tab @code{SQL_LOW_PRIORITY_UPDATES} @tab @code{SQL_MAX_JOIN_SIZE}
+@item @code{SQL_QUOTE_SHOW_CREATE} @tab @code{SQL_SAFE_UPDATES}
+ @tab @code{SQL_SELECT_LIMIT} @tab @code{SQL_SLAVE_SKIP_COUNTER}
+@item @code{SQL_SMALL_RESULT} @tab @code{SQL_WARNINGS}
+ @tab @code{SSL} @tab @code{STARTING}
+@item @code{STRAIGHT_JOIN} @tab @code{STRIPED}
+ @tab @code{TABLE} @tab @code{TABLES}
+@item @code{TERMINATED} @tab @code{THEN}
+ @tab @code{TINYBLOB} @tab @code{TINYINT}
+@item @code{TINYTEXT} @tab @code{TO}
+ @tab @code{TRAILING} @tab @code{UNION}
+@item @code{UNIQUE} @tab @code{UNLOCK}
+ @tab @code{UNSIGNED} @tab @code{UPDATE}
+@item @code{USAGE} @tab @code{USE}
+ @tab @code{USING} @tab @code{VALUES}
+@item @code{VARBINARY} @tab @code{VARCHAR}
+ @tab @code{VARYING} @tab @code{WHEN}
+@item @code{WHERE} @tab @code{WITH}
+ @tab @code{WRITE} @tab @code{YEAR_MONTH}
+@item @code{ZEROFILL}
@end multitable
+@c END_OF_RESERVED_WORDS
+
The following symbols (from the table above) are disallowed by ANSI SQL
but allowed by MySQL as column/table names. This is because some
of these names are very natural names and a lot of people have already
@@ -27925,7 +28096,7 @@ used them.
MySQL supports a number of column types, which may be grouped into
three categories: numeric types, date and time types, and string (character)
types. This section first gives an overview of the types available and
-summarizes the storage requirements for each column type, then provides a
+summarises the storage requirements for each column type, then provides a
more detailed description of the properties of the types in each category.
The overview is intentionally brief. The more detailed descriptions should
be consulted for additional information about particular column types, such
@@ -27961,6 +28132,10 @@ that are optional.
Note that if you specify @code{ZEROFILL} for a column, MySQL will
automatically add the @code{UNSIGNED} attribute to the column.
+@strong{Warning:} You should be aware that when you use subtraction
+between integers values where one is of type @code{UNSIGNED}, the result
+will be unsigned! @xref{Cast Functions}.
+
@table @code
@tindex TINYINT
@item TINYINT[(M)] [UNSIGNED] [ZEROFILL]
@@ -28008,6 +28183,18 @@ values, so you shouldn't use unsigned big integers larger than
@code{9223372036854775807} (63 bits) except with bit functions! If you
do that, some of the last digits in the result may be wrong because of
rounding errors when converting the @code{BIGINT} to a @code{DOUBLE}.
+
+MySQL 4.0 can handle @code{BIGINT} in the following cases:
+@itemize @bullet
+@item
+Use integers to store big unsigned values in a @code{BIGINT} column.
+@item
+In @code{MIN(big_int_column)} and @code{MAX(big_int_column)}.
+@item
+When using operators (@code{+}, @code{-}, @code{*} etc) where
+both operands are integers.
+@end itemize
+
@item
You can always store an exact integer value in a @code{BIGINT} column by
storing it as a string, as there is in this case there will be no
@@ -28153,7 +28340,7 @@ are @code{1901} to @code{2155}, @code{0000} in the 4-digit year format,
and 1970-2069 if you use the 2-digit format (70-69). MySQL displays
@code{YEAR} values in @code{YYYY} format, but allows you to assign values to
@code{YEAR} columns using either strings or numbers. (The @code{YEAR} type is
-new in MySQL Version 3.22.). @xref{YEAR}.
+new in MySQL Version 3.22.) @xref{YEAR}.
@tindex NATIONAL CHAR
@tindex NCHAR
@@ -28193,7 +28380,7 @@ These three are synonyms for @code{CHAR(1)}.
@tindex VARCHAR
@item [NATIONAL] VARCHAR(M) [BINARY]
-A variable-length string. @strong{NOTE:} Trailing spaces are removed when
+A variable-length string. @strong{Note:} Trailing spaces are removed when
the value is stored (this differs from the ANSI SQL specification). The range
of @code{M} is 1 to 255 characters. @code{VARCHAR} values are sorted and
compared in case-insensitive fashion unless the @code{BINARY} keyword is
@@ -28365,7 +28552,7 @@ digits when the value is stored.
The @code{REAL} and @code{DOUBLE PRECISION} types do not accept
precision specifications. As an extension to the ANSI/ISO SQL92
-standard, MySQL recognizes @code{DOUBLE} as a synonym for the
+standard, MySQL recognises @code{DOUBLE} as a synonym for the
@code{DOUBLE PRECISION} type. In contrast with the standard's
requirement that the precision for @code{REAL} be smaller than that used
for @code{DOUBLE PRECISION}, MySQL implements both as 8-byte
@@ -28574,7 +28761,7 @@ later:
@itemize @bullet
@item
Let MySQL set the column when the row is created.
-This will initialize it to the current date and time.
+This will initialise it to the current date and time.
@item
When you perform subsequent updates to other columns in the row, set
@@ -28582,7 +28769,7 @@ the @code{TIMESTAMP} column explicitly to its current value.
@end itemize
On the other hand, you may find it just as easy to use a @code{DATETIME}
-column that you initialize to @code{NOW()} when the row is created and
+column that you initialise to @code{NOW()} when the row is created and
leave alone for subsequent updates.
@code{TIMESTAMP} values may range from the beginning of 1970 to sometime in
@@ -28797,7 +28984,7 @@ You can specify @code{TIME} values in a variety of formats:
@itemize @bullet
@item
As a string in @code{'D HH:MM:SS.fraction'} format. (Note that
-MySQL doesn't yet store the fraction for the time column). One
+MySQL doesn't yet store the fraction for the time column.) One
can also use one of the following ``relaxed'' syntax:
@code{HH:MM:SS.fraction}, @code{HH:MM:SS}, @code{HH:MM}, @code{D HH:MM:SS},
@@ -28827,14 +29014,14 @@ seconds values that are less than @code{10}. @code{'8:3:2'} is the same as
@code{'08:03:02'}.
Be careful about assigning ``short'' @code{TIME} values to a @code{TIME}
-column. Without semicolon, MySQL interprets values using the
+column. Without colons, MySQL interprets values using the
assumption that the rightmost digits represent seconds. (MySQL
interprets @code{TIME} values as elapsed time rather than as time of
day.) For example, you might think of @code{'1112'} and @code{1112} as
meaning @code{'11:12:00'} (12 minutes after 11 o'clock), but
MySQL interprets them as @code{'00:11:12'} (11 minutes, 12 seconds).
Similarly, @code{'12'} and @code{12} are interpreted as @code{'00:00:12'}.
-@code{TIME} values with semicolon, instead, are always treated as
+@code{TIME} values with colons, by contrast, are always treated as
time of the day. That is @code{'11:12'} will mean @code{'11:12:00'},
not @code{'00:11:12'}.
@@ -29080,7 +29267,9 @@ certain circumstances:
@item
If you insert an invalid value into an @code{ENUM} (that is, a string not
present in the list of allowed values), the empty string is inserted
-instead as a special error value.
+instead as a special error value. This string can be distinguished from a
+'normal' empty string by the fact that this string has the numerical value
+0. More about this later.
@item
If an @code{ENUM} is declared @code{NULL}, @code{NULL} is also a legal value
@@ -29214,6 +29403,9 @@ specified at table creation time. For example, if a column is specified as
@code{SET("a","b","c","d")}, then @code{"a,d"}, @code{"d,a"}, and
@code{"d,a,a,d,d"} will all appear as @code{"a,d"} when retrieved.
+If you set a @code{SET} column to an unsupported value, the value will
+be ignored.
+
@code{SET} values are sorted numerically. @code{NULL} values sort before
non-@code{NULL} @code{SET} values.
@@ -29410,7 +29602,7 @@ An expression that contains @code{NULL} always produces a @code{NULL} value
unless otherwise indicated in the documentation for the operators and
functions involved in the expression.
-@strong{NOTE:} There must be no whitespace between a function name and the
+@strong{Note:} There must be no whitespace between a function name and the
parenthesis following it. This helps the MySQL parser distinguish
between function calls and references to tables or columns that happen to
have the same name as a function. Spaces around arguments are permitted,
@@ -29448,7 +29640,9 @@ mysql> select MOD(29,9);
* String functions:: String functions
* Numeric Functions:: Numeric Functions
* Date and time functions:: Date and time functions
+* Cast Functions:: Cast Functions
* Other Functions:: Other Functions
+* Group by functions:: Functions for Use with @code{GROUP BY} Clauses
@end menu
@@ -29642,6 +29836,32 @@ mysql> select 1 IS NOT NULL, 0 IS NOT NULL, NULL IS NOT NULL;
-> 1 1 0
@end example
+@cindex ODBC compatibility
+@cindex compatibility, with ODBC
+To be able to work good with other programs, MySQL supports the following
+extra features when using @code{IS NULL}:
+
+@itemize @bullet
+@item
+You can find the last inserted row with:
+
+@example
+SELECT * FROM tbl_name WHERE auto_col IS NULL
+@end example
+
+This can be disabled by setting @code{SQL_AUTO_IS_NULL=0}. @xref{SET OPTION}.
+@item
+For @code{NOT NULL} @code{DATE} and @code{DATETIME} columns you can find
+the special date @code{0000-00-00} by using:
+
+@example
+SELECT * FROM tbl_name WHERE date_column IS NULL
+@end example
+
+This is needed to get some ODBC applications to work (as ODBC doesn't
+support a @code{0000-00-00} date)
+@end itemize
+
@findex BETWEEN ... AND
@item expr BETWEEN min AND max
If @code{expr} is greater than or equal to @code{min} and @code{expr} is
@@ -30011,14 +30231,23 @@ mysql> select OCT(12);
@end example
@findex HEX()
-@item HEX(N)
-Returns a string representation of the hexadecimal value of @code{N}, where
-@code{N} is a longlong (@code{BIGINT}) number. This is equivalent to
-@code{CONV(N,10,16)}. Returns @code{NULL} if @code{N} is @code{NULL}:
+@item HEX(N_or_S)
+
+If N_OR_S is a number, returns a string representation of the hexadecimal
+value of @code{N}, where @code{N} is a longlong (@code{BIGINT}) number.
+This is equivalent to @code{CONV(N,10,16)}.
+
+If N_OR_S is a string, returns a hexadecimal string of N_OR_S where each
+character in N_OR_S is converted to 2 hexadecimal digits. This is the
+invers of the @code{0xff} strings.
@example
mysql> select HEX(255);
-> 'FF'
+mysql> select HEX("abc");
+ -> 616263
+mysql> select 0x616263;
+ -> "abc"
@end example
@findex CHAR()
@@ -30087,6 +30316,15 @@ mysql> select OCTET_LENGTH('text');
Note that for @code{CHAR_LENGTH()}, multi-byte characters are only counted
once.
+@findex BIT_LENGTH()
+@item BIT_LENGTH(str)
+Returns the length of the string @code{str} in bits:
+
+@example
+mysql> select BIT_LENGTH('text');
+ -> 32
+@end example
+
@findex LOCATE()
@findex POSITION()
@item LOCATE(substr,str)
@@ -30101,7 +30339,9 @@ mysql> select LOCATE('xbar', 'foobar');
-> 0
@end example
-This function is multi-byte safe.
+This function is multi-byte safe. In MySQL 3.23 this function is case
+insensitive, while in 4.0 it's only case insensitive if either argument is
+a binary string.
@findex LOCATE()
@item LOCATE(substr,str,pos)
@@ -30114,7 +30354,9 @@ mysql> select LOCATE('bar', 'foobarbar',5);
-> 7
@end example
-This function is multi-byte safe.
+This function is multi-byte safe. In MySQL 3.23 this function is case
+insensitive, while in 4.0 it's only case insensitive if either argument is
+a binary string.
@findex INSTR()
@item INSTR(str,substr)
@@ -30129,7 +30371,9 @@ mysql> select INSTR('xbar', 'foobar');
-> 0
@end example
-This function is multi-byte safe.
+This function is multi-byte safe. In MySQL 3.23 this function is case
+insensitive, while in 4.0 it's only case insensitive if either argument is
+a binary string.
@findex LPAD()
@item LPAD(str,len,padstr)
@@ -30371,7 +30615,7 @@ Returns a value @code{1} to @code{N} if the string @code{str} is in the list
@code{strlist} consisting of @code{N} substrings. A string list is a string
composed of substrings separated by @samp{,} characters. If the first
argument is a constant string and the second is a column of type @code{SET},
-the @code{FIND_IN_SET()} function is optimized to use bit arithmetic!
+the @code{FIND_IN_SET()} function is optimised to use bit arithmetic!
Returns @code{0} if @code{str} is not in @code{strlist} or if @code{strlist}
is the empty string. Returns @code{NULL} if either argument is @code{NULL}.
This function will not work properly if the first argument contains a
@@ -30509,6 +30753,7 @@ SQL simple regular expression comparison. Returns @code{1} (TRUE) or @code{0}
in the pattern:
@multitable @columnfractions .1 .9
+@item @strong{Char} @tab @strong{Description}
@item @code{%} @tab Matches any number of characters, even zero characters
@item @code{_} @tab Matches exactly one character
@end multitable
@@ -30525,6 +30770,7 @@ with the escape character. If you don't specify the @code{ESCAPE} character,
@samp{\} is assumed:
@multitable @columnfractions .1 .9
+@item @strong{String} @tab @strong{Description}
@item @code{\%} @tab Matches one @code{%} character
@item @code{\_} @tab Matches one @code{_} character
@end multitable
@@ -30627,18 +30873,16 @@ mysql> select STRCMP('text', 'text');
@findex MATCH ... AGAINST()
@item MATCH (col1,col2,...) AGAINST (expr)
+@itemx MATCH (col1,col2,...) AGAINST (expr IN BOOLEAN MODE)
@code{MATCH ... AGAINST()} is used for full-text search and returns
relevance - similarity measure between the text in columns
@code{(col1,col2,...)} and the query @code{expr}. Relevance is a
positive floating-point number. Zero relevance means no similarity.
-For @code{MATCH ... AGAINST()} to work, a @strong{FULLTEXT} index
-must be created first. @xref{CREATE TABLE, , @code{CREATE TABLE}}.
-@code{MATCH ... AGAINST()} is available in MySQL Version
-3.23.23 or later. For details and usage examples
-@pxref{Fulltext Search}.
+@code{MATCH ... AGAINST()} is available in MySQL version
+3.23.23 or later. @code{IN BOOLEAN MODE} extension was added in version
+4.0.1. For details and usage examples @pxref{Fulltext Search}.
@end table
-
@node Case Sensitivity Operators, , String comparison functions, String functions
@subsubsection Case Sensitivity
@@ -30660,6 +30904,8 @@ mysql> select BINARY "a" = "A";
-> 0
@end example
+@code{BINARY string} is a shorthand for @code{CAST(string AS BINARY)}.
+@xref{Cast Functions}.
@code{BINARY} was introduced in MySQL Version 3.23.0.
Note that in some context MySQL will not be able to use the
@@ -30689,9 +30935,13 @@ make string comparison even more flexible.
@node Arithmetic functions, Mathematical functions, Numeric Functions, Numeric Functions
@subsubsection Arithmetic Operations
+@cindex operators, cast
The usual arithmetic operators are available. Note that in the case of
@samp{-}, @samp{+}, and @samp{*}, the result is calculated with
@code{BIGINT} (64-bit) precision if both arguments are integers!
+If one of the argument is an unsigned integer, and the other argument
+is also an integer, the result will be an unsigned integer.
+@xref{Cast Functions}.
@cindex operations, arithmetic
@cindex arithmetic expressions
@@ -30727,8 +30977,9 @@ mysql> select 18014398509481984*18014398509481984;
-> 0
@end example
-The result of the last expression is incorrect because the result of the integer
-multiplication exceeds the 64-bit range of @code{BIGINT} calculations.
+The result of the last expression is incorrect because the result of the
+integer multiplication exceeds the 64-bit range of @code{BIGINT}
+calculations.
@findex / (division)
@findex division (/)
@@ -31031,16 +31282,17 @@ Returns a random floating-point value in the range @code{0} to @code{1.0}.
If an integer argument @code{N} is specified, it is used as the seed value:
@example
mysql> select RAND();
- -> 0.5925
+ -> 0.9233482386203
mysql> select RAND(20);
- -> 0.1811
+ -> 0.15888261251047
mysql> select RAND(20);
- -> 0.1811
+ -> 0.15888261251047
mysql> select RAND();
- -> 0.2079
+ -> 0.63553050033332
mysql> select RAND();
- -> 0.7888
+ -> 0.70100469486881
@end example
+
You can't use a column with @code{RAND()} values in an @code{ORDER BY}
clause, because @code{ORDER BY} would evaluate the column multiple times.
In MySQL Version 3.23, you can, however, do:
@@ -31052,6 +31304,10 @@ table1,table2 WHERE a=b AND c<d ORDER BY RAND() LIMIT 1000}.
Note that a @code{RAND()} in a @code{WHERE} clause will be re-evaluated
every time the @code{WHERE} is executed.
+@code{RAND()} is not meant to be a perfect random generator, but instead a
+fast way to generate add-hook random numbers that will be portable between
+platforms for the same MySQL version.
+
@findex LEAST()
@item LEAST(X,Y,...)
With two or more arguments, returns the smallest (minimum-valued) argument.
@@ -31143,8 +31399,7 @@ The above happens because 10.28 is actually stored as something like
10.2799999999999999.
@end table
-
-@node Date and time functions, Other Functions, Numeric Functions, Functions
+@node Date and time functions, Cast Functions, Numeric Functions, Functions
@subsection Date and Time Functions
@findex date and time functions
@@ -31266,6 +31521,9 @@ mysql> select WEEK('1998-12-31',1);
-> 53
@end example
+Note: in Version 4.0, @code{WEEK(#,0)} was changed to match the
+calendar in the USA.
+
@findex YEAR()
@item YEAR(date)
Returns the year for @code{date}, in the range @code{1000} to @code{9999}:
@@ -31505,6 +31763,7 @@ the days that were lost when the calendar was changed.
Formats the @code{date} value according to the @code{format} string. The
following specifiers may be used in the @code{format} string:
@multitable @columnfractions .1 .6
+@item @strong{Specifier} @tab @strong{Description}
@item @code{%M} @tab Month name (@code{January}..@code{December})
@item @code{%W} @tab Weekday name (@code{Sunday}..@code{Saturday})
@item @code{%D} @tab Day of the month with English suffix (@code{1st}, @code{2nd}, @code{3rd}, etc.)
@@ -31617,10 +31876,11 @@ mysql> select NOW() + 0;
@item UNIX_TIMESTAMP()
@itemx UNIX_TIMESTAMP(date)
If called with no argument, returns a Unix timestamp (seconds since
-@code{'1970-01-01 00:00:00'} GMT). If @code{UNIX_TIMESTAMP()} is called with
-a @code{date} argument, it returns the value of the argument as seconds since
-@code{'1970-01-01 00:00:00'} GMT. @code{date} may be a @code{DATE} string,
-a @code{DATETIME} string, a @code{TIMESTAMP}, or a number in the format
+@code{'1970-01-01 00:00:00'} GMT) as an unsigned integer. If
+@code{UNIX_TIMESTAMP()} is called with a @code{date} argument, it
+returns the value of the argument as seconds since @code{'1970-01-01
+00:00:00'} GMT. @code{date} may be a @code{DATE} string, a
+@code{DATETIME} string, a @code{TIMESTAMP}, or a number in the format
@code{YYMMDD} or @code{YYYYMMDD} in local time:
@example
@@ -31631,11 +31891,14 @@ mysql> select UNIX_TIMESTAMP('1997-10-04 22:23:00');
@end example
When @code{UNIX_TIMESTAMP} is used on a @code{TIMESTAMP} column, the function
-will receive the value directly, with no implicit
+will return the internal timestamp value directly, with no implicit
``string-to-unix-timestamp'' conversion.
If you give @code{UNIX_TIMESTAMP()} a wrong or out-of-range date, it will
return 0.
+If you want to subtract @code{UNIX_TIMESTAMP()} columns, you may want to
+cast the result to signed integers. @xref{Cast Functions}.
+
@findex FROM_UNIXTIME()
@item FROM_UNIXTIME(unix_timestamp)
Returns a representation of the @code{unix_timestamp} argument as a value in
@@ -31686,8 +31949,105 @@ mysql> select TIME_TO_SEC('00:39:38');
@end example
@end table
+@node Cast Functions, Other Functions, Date and time functions, Functions
+@subsection Cast Functions
+
+The syntax of the @code{CAST} function is:
+
+@findex CAST
+@findex CONVERT
+
+@example
+CAST(expression AS type)
+
+or
+
+CONVERT(expression,type)
+@end example
+
+Where type is one of:
+@itemize @bullet
+@item
+@code{BINARY}
+@item
+@code{DATE}
+@item
+@code{DATETIME}
+@item
+@code{SIGNED @{INTEGER@}}
+@item
+@code{TIME}
+@item
+@code{UNSIGNED @{INTEGER@}}
+@end itemize
+
+@code{CAST()} is ANSI SQL99 syntax and @code{CONVERT()} is ODBC syntax.
+
+The cast function is mainly useful when you want to create a column with
+a specific type in a @code{CREATE ... SELECT}:
+
+@example
+CREATE TABLE new_table SELECT CAST('2000-01-01' AS DATE);
+@end example
+
+@code{CAST(string AS BINARY} is the same thing as @code{BINARY string}.
+
+To cast a string to a numeric value, you don't normally have to do
+anything; Just use the string value as it would be a number:
+
+@example
+mysql> select 1+'1';
+ -> 2
+@end example
+
+MySQL supports arithmetic with both signed and unsigned 64 bit values.
+If you are using an numerical operations (like @code{+}) and one of the
+operands are @code{unsigned integer}, then the result will be unsigned.
+You can override this by using the @code{SIGNED} and @code{UNSIGNED}
+cast operators, which will cast the operation to signed respective
+unsigned 64 bit integer.
+
+@example
+mysql> select CAST(1-2 AS UNSIGNED)
+ -> 18446744073709551615
+mysql select CAST(CAST(1-2 AS UNSIGNED) AS SIGNED);
+ -> -1
+@end example
+
+Note that if either operation is a floating point value (In this context
+@code{DECIMAL()} is regarded as a floating point value) the result will
+be a floating point value and is not affected by the above rule.
+
+@example
+mysql> select CAST(1 AS UNSIGNED) -2.0
+ -> -1.0
+@end example
+
+If you are using a string in an arithmetic operation, this is converted
+to a floating point number.
+
+The @code{CAST()} and @code{CONVERT()} functions were added in MySQL 4.0.2.
+
+The handing of unsigned values was changed in MySQL 4.0 to be able to
+support @code{BIGINT} values properly. If you have some code that you
+want to run in both MySQL 4.0 and 3.23 (in which case you probably can't
+use the CAST function), you can use the following trick to get a signed
+result when subtracting two unsigned integer columns:
+
+@example
+SELECT (unsigned_column_1+0.0)-(unsigned_column_2+0.0);
+@end example
+
+The idea is that the columns are converted to floating point before doing
+the subtraction.
-@node Other Functions, , Date and time functions, Functions
+If you get a problem with @code{UNSIGNED} columns in your old MySQL
+application when porting to MySQL 4.0, you can use the
+@code{--sql-mode=NO_UNSIGNED_SUBTRACTION} option when starting
+@code{mysqld}. Note however that as long as you use this, you will not
+be able to make efficient use of the @code{UNSIGNED BIGINT} column type.
+
+@node Other Functions, Group by functions, Cast Functions, Functions
@subsection Other Functions
@menu
@@ -31711,12 +32071,14 @@ these operators have a maximum range of 64 bits.
@findex | (bitwise OR)
@findex OR, bitwise
@item |
-Bitwise OR:
+Bitwise OR
@example
mysql> select 29 | 15;
-> 31
@end example
+The result is an unsigned 64 bit integer.
+
@findex & (bitwise AND)
@findex AND, bitwise
@item &
@@ -31726,6 +32088,8 @@ mysql> select 29 & 15;
-> 13
@end example
+The result is an unsigned 64 bit integer.
+
@findex << (left shift)
@item <<
Shifts a longlong (@code{BIGINT}) number to the left:
@@ -31734,6 +32098,8 @@ mysql> select 1 << 2;
-> 4
@end example
+The result is an unsigned 64 bit integer.
+
@findex >> (right shift)
@item >>
Shifts a longlong (@code{BIGINT}) number to the right:
@@ -31742,6 +32108,8 @@ mysql> select 4 >> 2;
-> 1
@end example
+The result is an unsigned 64 bit integer.
+
@findex ~
@item ~
Invert all bits:
@@ -31750,6 +32118,8 @@ mysql> select 5 & ~1;
-> 4
@end example
+The result is an unsigned 64 bit integer.
+
@findex BIT_COUNT()
@item BIT_COUNT(N)
Returns the number of bits that are set in the argument @code{N}:
@@ -31864,6 +32234,83 @@ mysql> select MD5("testing");
This is an "RSA Data Security, Inc. MD5 Message-Digest Algorithm".
+@findex des_encrypt()
+@item des_encrypt(string_to_encrypt, flag, [, (key_number | key_string) ] )
+
+Encrypts the string with the given key using the DES algorithm, which
+provides strong encryption.
+
+Note that this function only works if you have configured MySQL with
+SLL support. @xref{Secure connections}.
+
+The encryption key to use is chosen the following way:
+
+@multitable @columnfractions .2 .8
+@item @strong{Argument} @tab @strong{Description}
+@item Only one argument @tab
+The first key from @code{des-key-file} is used.
+@item key number @tab
+The given key (0-9) from the @code{des-key-file} is used.
+@item string @tab
+The given @code{key_string} will be used to crypt @code{string_to_encrypt}.
+@end multitable
+
+The return string will be a binary string where the first character
+will be @code{CHAR(128 | key-number)}.
+
+The 128 is added to make it easier to recognize a crypted key.
+If one uses a string key, @code{key-number} will be 127.
+
+On error, this function returns NULL.
+
+The string length for the result will be
+@code{new_length= org_length + (8-(org_length % 8))+1}.
+
+The @code{des-key-file} has the following format:
+
+@example
+key-number key-string
+key-number key-string
+@end example
+
+The @code{key-number} must be a number between 0-9. The numbers may be
+in any order. @code{des-key-string} is string that will be used to
+crypt the message. Between the number and the key there should be at
+least one space. The first key is the default key that will be used
+if one doesn't specify a key to @code{des_encrypt()}
+
+You can tell MySQL to read new key values from the key file with the
+@code{FLUSH DES_KEY_FILE} command.
+
+One benefit with having a set of default keys on can use is that it
+gives applications a way to check for existence of crypted column,
+without giving the end user the right to uncrypt the data.
+
+@example
+SELECT customer_address FROM customer_table WHERE
+crypted_credit_card = DES_ENCRYPT("credit_card_number");
+@end example
+
+@findex des_decrypt()
+@item des_decrypt(string_to_decrypt [, key_string])
+
+Decrypts a string crypted with @code{des_encrypt()}.
+
+Note that this function only works if you have configured MySQL with
+SLL support. @xref{Secure connections}.
+
+If one only gives this a string argument, then it will use the right key
+from the @code{des-key-file} to decrypt the message. For this to work
+the user must have the @code{PROCESS_PRIV} privilege.
+
+If one calls this function with 2 arguments, the second argument is
+used to decrypt the message.
+
+If the @code{string_to_decrypt} doesn't look like a crypted string MySQL will
+return the given @code{string_to_decrypt}.
+
+On error, this function returns NULL.
+
@findex LAST_INSERT_ID([expr])
@item LAST_INSERT_ID([expr])
Returns the last automatically generated value that was inserted into an
@@ -32043,16 +32490,193 @@ above number is calculated as @code{209*255^3 + 207*255^2 + 224*255 +40}.
@findex MASTER_POS_WAIT()
@item MASTER_POS_WAIT(log_name, log_pos)
Blocks until the slave reaches the specified position in the master log during
-replication. If master information is not initialized, returns NULL. If the
+replication. If master information is not initialised, returns NULL. If the
slave is not running, will block and wait until it is started and goes to or
past
the specified position. If the slave is already past the specified position,
returns immediately. The return value is the number of log events it had to
wait to get to the specified position, or NULL in case of error. Useful for
-control of master-slave synchronization, but was originally written to
+control of master-slave synchronisation, but was originally written to
facilitate replication testing.
+
+@findex FOUND_ROWS()
+@findex LIMIT
+@item FOUND_ROWS()
+Returns the number of rows that the last @code{SELECT SQL_CALC_FOUND_ROWS ...}
+command would have returned, if wasn't restricted with @code{LIMIT}.
+
+@example
+SELECT SQL_CALC_FOUND_ROWS * FROM table_name WHERE id > 100 LIMIT 10;
+SELECT FOUND_ROWS();
+@end example
+
+The second select will return how many rows the SELECT should have
+returned if we would remove the @code{LIMIT} clause.
+
+Note that if you are using @code{SELECT SQL_CALC_FOUND_ROWS ...} MySQL has
+to calculate all rows in the result set. This is however faster than
+if you would not use @code{LIMIT} as the result set doesn't have to be sent
+to the client.
+@end table
+
+
+@node Group by functions, , Other Functions, Functions
+@subsection Functions for Use with @code{GROUP BY} Clauses
+
+@findex GROUP BY functions
+@findex functions, GROUP BY
+
+If you use a group function in a statement containing no @code{GROUP BY}
+clause, it is equivalent to grouping on all rows.
+
+@table @code
+@findex COUNT()
+@item COUNT(expr)
+Returns a count of the number of non-@code{NULL} values in the rows
+retrieved by a @code{SELECT} statement:
+
+@example
+mysql> select student.student_name,COUNT(*)
+ from student,course
+ where student.student_id=course.student_id
+ GROUP BY student_name;
+
+@end example
+
+@code{COUNT(*)} is somewhat different in that it returns a count of
+the number of rows retrieved, whether or not they contain @code{NULL}
+values.
+
+@code{COUNT(*)} is optimised to
+return very quickly if the @code{SELECT} retrieves from one table, no
+other columns are retrieved, and there is no @code{WHERE} clause.
+For example:
+
+@example
+mysql> select COUNT(*) from student;
+@end example
+
+@findex COUNT(DISTINCT)
+@findex DISTINCT
+@item COUNT(DISTINCT expr,[expr...])
+Returns a count of the number of different non-@code{NULL} values:
+
+@example
+mysql> select COUNT(DISTINCT results) from student;
+@end example
+
+In MySQL you can get the number of distinct expression
+combinations that don't contain NULL by giving a list of expressions.
+In ANSI SQL you would have to do a concatenation of all expressions
+inside @code{CODE(DISTINCT ...)}.
+
+@findex AVG()
+@item AVG(expr)
+Returns the average value of @code{expr}:
+
+@example
+mysql> select student_name, AVG(test_score)
+ from student
+ GROUP BY student_name;
+@end example
+
+@findex MIN()
+@findex MAX()
+@item MIN(expr)
+@itemx MAX(expr)
+Returns the minimum or maximum value of @code{expr}. @code{MIN()} and
+@code{MAX()} may take a string argument; in such cases they return the
+minimum or maximum string value. @xref{MySQL indexes}.
+
+@example
+mysql> select student_name, MIN(test_score), MAX(test_score)
+ from student
+ GROUP BY student_name;
+@end example
+
+@findex SUM()
+@item SUM(expr)
+Returns the sum of @code{expr}. Note that if the return set has no rows,
+it returns NULL!
+
+@findex STD()
+@findex STDDEV()
+@cindex Oracle compatibility
+@cindex compatibility, with Oracle
+@item STD(expr)
+@itemx STDDEV(expr)
+Returns the standard deviation of @code{expr}. This is an extension to
+ANSI SQL. The @code{STDDEV()} form of this function is provided for Oracle
+compatibility.
+
+@findex BIT_OR()
+@item BIT_OR(expr)
+Returns the bitwise @code{OR} of all bits in @code{expr}. The calculation is
+performed with 64-bit (@code{BIGINT}) precision.
+
+@findex BIT_AND()
+@item BIT_AND(expr)
+Returns the bitwise @code{AND} of all bits in @code{expr}. The calculation is
+performed with 64-bit (@code{BIGINT}) precision.
@end table
+@cindex @code{GROUP BY}, extensions to ANSI SQL
+MySQL has extended the use of @code{GROUP BY}. You can use columns or
+calculations in the @code{SELECT} expressions that don't appear in
+the @code{GROUP BY} part. This stands for @emph{any possible value for this
+group}. You can use this to get better performance by avoiding sorting and
+grouping on unnecessary items. For example, you don't need to group on
+@code{customer.name} in the following query:
+
+@example
+mysql> select order.custid,customer.name,max(payments)
+ from order,customer
+ where order.custid = customer.custid
+ GROUP BY order.custid;
+@end example
+
+In ANSI SQL, you would have to add @code{customer.name} to the @code{GROUP
+BY} clause. In MySQL, the name is redundant if you don't run in
+ANSI mode.
+
+@strong{Don't use this feature} if the columns you omit from the
+@code{GROUP BY} part aren't unique in the group! You will get
+unpredictable results.
+
+In some cases, you can use @code{MIN()} and @code{MAX()} to obtain a specific
+column value even if it isn't unique. The following gives the value of
+@code{column} from the row containing the smallest value in the @code{sort}
+column:
+
+@example
+substr(MIN(concat(rpad(sort,6,' '),column)),7)
+@end example
+
+@xref{example-Maximum-column-group-row}.
+
+@cindex @code{ORDER BY}, aliases in
+@cindex aliases, in @code{ORDER BY} clauses
+@cindex @code{GROUP BY}, aliases in
+@cindex aliases, in @code{GROUP BY} clauses
+@cindex expression aliases
+@cindex aliases, for expressions
+Note that if you are using MySQL Version 3.22 (or earlier) or if
+you are trying to follow ANSI SQL, you can't use expressions in @code{GROUP
+BY} or @code{ORDER BY} clauses. You can work around this limitation by
+using an alias for the expression:
+
+@example
+mysql> SELECT id,FLOOR(value/100) AS val FROM tbl_name
+ GROUP BY id,val ORDER BY val;
+@end example
+
+In MySQL Version 3.23 you can do:
+
+@example
+mysql> SELECT id,FLOOR(value/100) FROM tbl_name ORDER BY RAND();
+@end example
+
+
@node Data Manipulation, Data Definition, Functions, Reference
@section Data Manipulation: @code{SELECT}, @code{INSERT}, @code{UPDATE}, @code{DELETE}
@@ -32060,8 +32684,9 @@ facilitate replication testing.
@menu
* SELECT:: @code{SELECT} Syntax
+* HANDLER:: @code{HANDLER} Syntax
* INSERT:: @code{INSERT} Syntax
-* INSERT DELAYED:: @code{INSERT DELAYED} syntax
+* INSERT DELAYED:: @code{INSERT DELAYED} Syntax
* UPDATE:: @code{UPDATE} Syntax
* DELETE:: @code{DELETE} Syntax
* TRUNCATE:: @code{TRUNCATE} Syntax
@@ -32070,7 +32695,7 @@ facilitate replication testing.
* DO:: @code{DO} Syntax
@end menu
-@node SELECT, INSERT, Data Manipulation, Data Manipulation
+@node SELECT, HANDLER, Data Manipulation, Data Manipulation
@subsection @code{SELECT} Syntax
@findex SELECT
@@ -32078,7 +32703,7 @@ facilitate replication testing.
@c help SELECT
@example
SELECT [STRAIGHT_JOIN] [SQL_SMALL_RESULT] [SQL_BIG_RESULT] [SQL_BUFFER_RESULT]
- [HIGH_PRIORITY]
+ [SQL_CACHE | SQL_NO_CACHE] [SQL_CALC_FOUND_ROWS] [HIGH_PRIORITY]
[DISTINCT | DISTINCTROW | ALL]
select_expression,...
[INTO @{OUTFILE | DUMPFILE@} 'file_name' export_options]
@@ -32122,6 +32747,12 @@ mysql> select concat(last_name,', ',first_name) AS full_name
@end example
@item
+It is not allowed to use a column alias in a @code{WHERE} clause,
+because the column value may not yet be determined when the
+@code{WHERE} clause is executed.
+@xref{Problems with alias}.
+
+@item
The @code{FROM table_references} clause indicates the tables from which to
retrieve rows. If you name more than one table, you are performing a
join. For information on join syntax, see @ref{JOIN, , @code{JOIN}}.
@@ -32172,7 +32803,7 @@ MySQL support. @xref{Functions}.
@item
The @code{HAVING} clause can refer to any column or alias named in the
@code{select_expression}. It is applied last, just before items are sent to
-the client, with no optimization. Don't use @code{HAVING} for items that
+the client, with no optimisation. Don't use @code{HAVING} for items that
should be in the @code{WHERE} clause. For example, do not write this:
@example
@@ -32200,9 +32831,8 @@ mysql> select user,max(salary) AS sum from users
@end example
@item
-@code{SQL_SMALL_RESULT}, @code{SQL_BIG_RESULT}, @code{SQL_BUFFER_RESULT},
-@code{STRAIGHT_JOIN}, and @code{HIGH_PRIORITY} are MySQL extensions
-to ANSI SQL92.
+All options beginning with @code{SQL_}, @code{STRAIGHT_JOIN}, and
+@code{HIGH_PRIORITY} are MySQL extensions to ANSI SQL.
@item
@code{HIGH_PRIORITY} will give the @code{SELECT} higher priority than
@@ -32213,7 +32843,7 @@ statement that is waiting for the table to be free.
@item
@code{SQL_BIG_RESULT} can be used with @code{GROUP BY} or @code{DISTINCT}
-to tell the optimizer that the result set will have many rows. In this case,
+to tell the optimiser that the result set will have many rows. In this case,
MySQL will directly use disk-based temporary tables if needed.
MySQL will also, in this case, prefer sorting to doing a
temporary table with a key on the @code{GROUP BY} elements.
@@ -32225,12 +32855,27 @@ in cases where it takes a long time to send the result set to the client.
@item
@code{SQL_SMALL_RESULT}, a MySQL-specific option, can be used
-with @code{GROUP BY} or @code{DISTINCT} to tell the optimizer that the
+with @code{GROUP BY} or @code{DISTINCT} to tell the optimiser that the
result set will be small. In this case, MySQL will use fast
temporary tables to store the resulting table instead of using sorting. In
MySQL Version 3.23 this shouldn't normally be needed.
@item
+@code{SQL_CALC_FOUND_ROWS} tells MySQL to calculate how many rows there
+would be in the result, disregarding any @code{LIMIT} clause. The number
+of rows can be obtained with @code{SELECT
+FOUND_ROWS()}. @xref{Miscellaneous functions}.
+
+@item
+@code{SQL_CACHE} tells MySQL to store the query result in the query cache
+if you are using @code{SQL_QUERY_CACHE_TYPE=2} (@code{DEMAND}).
+@xref{Query Cache}.
+
+@item
+@code{SQL_NO_CACHE} tells MySQL to not allow the query result to be stored
+in the query cache. @xref{Query Cache}.
+
+@item
@cindex @code{GROUP BY}, extensions to ANSI SQL
If you use @code{GROUP BY}, the output rows will be sorted according to the
@code{GROUP BY} as if you would have had an @code{ORDER BY} over all the fields
@@ -32249,9 +32894,24 @@ read the @code{GROUP BY} description.
@xref{Group by functions}.
@item
-@code{STRAIGHT_JOIN} forces the optimizer to join the tables in the order in
+@cindex hints
+@code{SQL_BUFFER_RESULT} will force the result to be put into a temporary
+table. This will help MySQL free the table locks early and will help
+in cases where it takes a long time to send the result set to the client.
+
+@item
+@cindex hints
+@code{SQL_SMALL_RESULT}, a MySQL-specific option, can be used
+with @code{GROUP BY} or @code{DISTINCT} to tell the optimiser that the
+result set will be small. In this case, MySQL will use fast
+temporary tables to store the resulting table instead of using sorting. In
+MySQL Version 3.23 this shouldn't normally be needed.
+
+@item
+@cindex hints
+@code{STRAIGHT_JOIN} forces the optimiser to join the tables in the order in
which they are listed in the @code{FROM} clause. You can use this to speed up
-a query if the optimizer joins the tables in non-optimal order.
+a query if the optimiser joins the tables in non-optimal order.
@xref{EXPLAIN, , @code{EXPLAIN}}.
@item
@@ -32308,7 +32968,7 @@ the @code{ESCAPED BY} character:
Additionally, @code{ASCII 0} is converted to @code{ESCAPED BY} followed by 0
(@code{ASCII 48}).
-The reason for the above is that you MUST escape any @code{FIELDS
+The reason for the above is that you @strong{must} escape any @code{FIELDS
TERMINATED BY}, @code{ESCAPED BY}, or @code{LINES TERMINATED BY}
characters to reliably be able to read the file back. @code{ASCII 0} is
escaped to make it easier to view with some pagers.
@@ -32348,9 +33008,10 @@ the examined rows will be write locked.
@menu
* JOIN:: @code{JOIN} Syntax
+* UNION:: @code{UNION} Syntax
@end menu
-@node JOIN, , SELECT, SELECT
+@node JOIN, UNION, SELECT, SELECT
@subsubsection @code{JOIN} Syntax
@findex JOIN
@@ -32437,7 +33098,7 @@ mysql> select table1.* from table1
This example finds all rows in @code{table1} with an @code{id} value that is
not present in @code{table2} (that is, all rows in @code{table1} with no
corresponding row in @code{table2}). This assumes that @code{table2.id} is
-declared @code{NOT NULL}, of course. @xref{LEFT JOIN optimization}.
+declared @code{NOT NULL}, of course. @xref{LEFT JOIN optimisation}.
@item
The @code{USING} @code{(column_list)} clause names a list of columns that must
@@ -32461,16 +33122,24 @@ with a @code{USING} clause that names all columns that exist in both
tables.
@item
+@cindex hints
+@code{INNER JOIN} and @code{,} (comma) are semantically equivalent.
+Both do a full join between the tables used. Normally, you specify
+how the tables should be linked in the WHERE condition.
+
+@item
@code{RIGHT JOIN} works analogously as @code{LEFT JOIN}. To keep code
portable across databases, it's recommended to use @code{LEFT JOIN}
instead of @code{RIGHT JOIN}.
@item
+@cindex hints
@code{STRAIGHT_JOIN} is identical to @code{JOIN}, except that the left table
is always read before the right table. This can be used for those (few)
-cases where the join optimizer puts the tables in the wrong order.
+cases where the join optimiser puts the tables in the wrong order.
@item
+@cindex hints
As of MySQL Version 3.23.12, you can give hints about which
index MySQL should use when retrieving information from a
table. This is useful if @code{EXPLAIN} shows that MySQL is
@@ -32495,10 +33164,88 @@ mysql> select * from table1 IGNORE INDEX (key3) WHERE key1=1 and key2=2 AND
key3=3;
@end example
-@xref{LEFT JOIN optimization, , @code{LEFT JOIN} optimization}.
+@xref{LEFT JOIN optimisation, , @code{LEFT JOIN} optimisation}.
+
+
+@node UNION, , JOIN, SELECT
+@subsubsection @code{UNION} Syntax
+
+@findex UNION
+
+@example
+SELECT ...
+UNION [ALL]
+SELECT ...
+ [UNION
+ SELECT ...]
+@end example
+
+@code{UNION} is implemented in MySQL 4.0.0.
+
+@code{UNION} is used to combine the result from many @code{SELECT}
+statements into one result set.
+
+The @code{SELECT} commands are normal select commands, but with the following
+restrictions:
+
+@itemize @bullet
+@item
+Only the last @code{SELECT} command can have @code{INTO OUTFILE}.
+@item
+Only the last @code{SELECT} command can have @code{ORDER BY}.
+@end itemize
+
+If you don't use the keyword @code{ALL} for the @code{UNION}, all
+returned rows will be unique, like if you had done a @code{DISTINCT} for
+the total result set. If you specify @code{ALL}, then you will get all
+matching rows from all the used @code{SELECT} statements.
+
+
+@findex HANDLER
+@node HANDLER, INSERT, SELECT, Data Manipulation
+@subsection @code{HANDLER} Syntax
+
+@example
+HANDLER table OPEN [ AS alias ]
+HANDLER table READ index @{ = | >= | <= | < @} (value1, value2, ... ) [ WHERE ... ] [LIMIT ... ]
+HANDLER table READ index @{ FIRST | NEXT | PREV | LAST @} [ WHERE ... ] [LIMIT ... ]
+HANDLER table READ @{ FIRST | NEXT @} [ WHERE ... ] [LIMIT ... ]
+HANDLER table CLOSE
+@end example
+
+The @code{HANDLER} statement provides direct access to MySQL table
+interface, bypassing SQL optimiser. Thus, it is faster then SELECT.
+
+The first form of @code{HANDLER} statement opens a table, making
+in accessible via the following @code{HANDLER ... READ} routines.
+This table object is not shared by other threads an will not be closed
+until the thread calls @code{HANDLER table_name CLOSE} or the thread dies.
+
+The second form fetches one (or, specified by @code{LIMIT} clause) row
+where the index specified complies to the condition and @code{WHERE}
+condition is met. If the index consists of several parts (spans over
+several columns) the values are specified in comma-separated list,
+providing values only for few first columns is possible.
+
+The third form fetches one (or, specified by @code{LIMIT} clause) row
+from the table in index order, matching @code{WHERE} condition.
+The fourth form (without index specification) fetches one (or, specified
+by @code{LIMIT} clause) row from the table in natural row order (as stored
+in data file) matching @code{WHERE} condition. It is faster than
+@code{HANDLER table READ index} when full table scan is desired.
-@node INSERT, INSERT DELAYED, SELECT, Data Manipulation
+The last form closes the table, opened with @code{HANDLER ... OPEN}.
+
+@code{HANDLER} is somewhat low-level statement, for example it does not
+provide consistency. That is @code{HANDLER ... OPEN} does @strong{NOT}
+takes a snapshot of the table, and does @strong{NOT} locks the table. The
+above means, that after @code{HANDLER ... OPEN} table data can be
+modified (by this or other thread) and these modifications may appear only
+partially in @code{HANDLER ... NEXT} or @code{HANDLER ... PREV} scans.
+
+
+@node INSERT, INSERT DELAYED, HANDLER, Data Manipulation
@subsection @code{INSERT} Syntax
@findex INSERT
@@ -32536,11 +33283,18 @@ If you specify no column list for @code{INSERT ... VALUES} or @code{INSERT
the columns in the table, use @code{DESCRIBE tbl_name} to find out.
@item
+@cindex default values
Any column not explicitly given a value is set to its default value. For
example, if you specify a column list that doesn't name all the columns in
the table, unnamed columns are set to their default values. Default value
assignment is described in @ref{CREATE TABLE, , @code{CREATE TABLE}}.
+MySQL always has a default value for all fields. This is something
+that is imposed on MySQL to be able to work with both transactional
+and not transactional tables.
+
+Our view is that checking of fields content should be done in the
+application and not in the database server.
@item
An @code{expression} may refer to any column that was set earlier in a value
list. For example, you can say this:
@@ -32669,7 +33423,7 @@ the query. @xref{INSERT}.
@item
To ensure that the update log/binary log can be used to re-create the
original tables, MySQL will not allow concurrent inserts during
-@code{INSERT .... SELECT}.
+@code{INSERT ... SELECT}.
@end itemize
You can of course also use @code{REPLACE} instead of @code{INSERT} to
@@ -32677,7 +33431,7 @@ overwrite old rows.
@node INSERT DELAYED, UPDATE, INSERT, Data Manipulation
-@subsection @code{INSERT DELAYED} syntax
+@subsection @code{INSERT DELAYED} Syntax
@findex INSERT DELAYED
@findex DELAYED
@@ -32870,40 +33624,92 @@ only a given number of rows are changed.
@findex DELETE
@example
-DELETE [LOW_PRIORITY] FROM tbl_name
+DELETE [LOW_PRIORITY | QUICK] FROM table_name
[WHERE where_definition]
+ [ORDER BY ...]
[LIMIT rows]
+
+or
+
+DELETE [LOW_PRIORITY | QUICK] table_name[.*] [,table_name[.*] ...] FROM
+table-references [WHERE where_definition]
+
+or
+
+DELETE [LOW_PRIORITY | QUICK] FROM table_name[.*], [table_name[.*] ...] USING
+table-references [WHERE where_definition]
@end example
-@code{DELETE} deletes rows from @code{tbl_name} that satisfy the condition
+@code{DELETE} deletes rows from @code{table_name} that satisfy the condition
given by @code{where_definition}, and returns the number of records deleted.
If you issue a @code{DELETE} with no @code{WHERE} clause, all rows are
deleted. If you do this in @code{AUTOCOMMIT} mode, this works as
-@code{TRUNCATE}. @xref{TRUNCATE}. One problem with this is that
-@code{DELETE} will return zero as the number of affected records, but
-this will be fixed in 4.0.
+@code{TRUNCATE}. @xref{TRUNCATE}. In MySQL 3.23 @code{DELETE} without a
+@code{WHERE} clause will return zero as the number of affected records.
If you really want to know how many records are deleted when you are deleting
all rows, and are willing to suffer a speed penalty, you can use a
@code{DELETE} statement of this form:
@example
-mysql> DELETE FROM tbl_name WHERE 1>0;
+mysql> DELETE FROM table_name WHERE 1>0;
@end example
-Note that this is MUCH slower than @code{DELETE FROM tbl_name} with no
+Note that this is much slower than @code{DELETE FROM table_name} with no
@code{WHERE} clause, because it deletes rows one at a time.
If you specify the keyword @code{LOW_PRIORITY}, execution of the
@code{DELETE} is delayed until no other clients are reading from the table.
-Deleted records are maintained in a linked list and subsequent @code{INSERT}
-operations reuse old record positions. To reclaim unused space and reduce
-file sizes, use the @code{OPTIMIZE TABLE} statement or the @code{myisamchk}
-utility to reorganize tables. @code{OPTIMIZE TABLE} is easier, but
-@code{myisamchk} is faster.
-See @ref{OPTIMIZE TABLE, , @code{OPTIMIZE TABLE}} and @ref{Optimization}.
+If you specify the word @code{QUICK} then the table handler will not
+merge index leafs during delete, which may speed up certain kind of
+deletes.
+
+In MyISAM tables deleted records are maintained in a linked list and
+subsequent @code{INSERT} operations reuse old record positions. To
+reclaim unused space and reduce file sizes, use the @code{OPTIMIZE
+TABLE} statement or the @code{myisamchk} utility to reorganise tables.
+@code{OPTIMIZE TABLE} is easier, but @code{myisamchk} is faster. See
+@ref{OPTIMIZE TABLE, , @code{OPTIMIZE TABLE}} and @ref{Optimisation}.
+
+The first multi table delete format is supported starting from MySQL 4.0.0.
+The second multi table delete format is supported starting from MySQL 4.0.2.
+
+The idea is that only matching rows from the tables listed
+@strong{before} the @code{FROM} or before the @code{USING} clause is
+deleted. The effect is that you can delete rows from many tables at the
+same time and also have additional tables that are used for searching.
+
+The @code{.*} after the table names is there just to be compatible with
+@code{Access}:
+
+@example
+DELETE t1,t2 FROM t1,t2,t3 WHERE t1.id=t2.id AND t2.id=t3.id
+
+or
+
+DELETE FROM t1,t2 USING t1,t2,t3 WHERE t1.id=t2.id AND t2.id=t3.id
+@end example
+
+In the above case we delete matching rows just from tables @code{t1} and
+@code{t2}.
+
+@code{ORDER BY} and using multiple tables in the DELETE is supported in
+MySQL 4.0.
+
+If an @code{ORDER BY} clause is used, the rows will be deleted in that order.
+This is really only useful in conjunction with @code{LIMIT}. For example:
+
+@example
+DELETE FROM somelog
+WHERE user = 'jcole'
+ORDER BY timestamp
+LIMIT 1
+@end example
+
+This will delete the oldest entry (by @code{timestamp}) where the row matches
+the @code{WHERE} clause.
The MySQL-specific @code{LIMIT rows} option to @code{DELETE} tells
the server the maximum number of rows to be deleted before control is
@@ -32922,16 +33728,19 @@ the @code{LIMIT} value.
TRUNCATE TABLE table_name
@end example
-Is in 3.23 and the same thing as @code{DELETE FROM table_name}. @xref{DELETE}.
-The differences are:
+In 3.23 @code{TRUNCATE TABLE} is mapped to
+@code{COMMIT ; DELETE FROM table_name}. @xref{DELETE}.
+
+The differences between @code{TRUNCATE TABLE} and @code{DELETE FROM ...}
+are:
@itemize @bullet
@item
-Implemented as a drop and re-create of the table, which makes this
-much faster when deleting many rows.
+Truncates does a drop and re-create of the table, which is much faster
+than deleting rows one by one.
@item
-Not transaction-safe; @code{TRUNCATE TABLE} will automatically end the current
-transaction as if @code{COMMIT} would have been called.
+Not transaction-safe; You will get an error if you have an active
+transaction or an active table lock.
@item
Doesn't return the number of deleted rows.
@item
@@ -32942,7 +33751,6 @@ files have become corrupted.
@code{TRUNCATE} is an Oracle SQL extension.
-
@node REPLACE, LOAD DATA, TRUNCATE, Data Manipulation
@subsection @code{REPLACE} Syntax
@@ -33551,9 +34359,10 @@ The @code{DROP DATABASE} command removes from the given database
directory all files with the following extensions:
@multitable @columnfractions .25 .25 .25 .25
-@item .BAK @tab .DAT @tab .HSH @tab .ISD
-@item .ISM @tab .ISM @tab .MRG @tab .MYD
-@item .MYI @tab .db @tab .frm
+@item @strong{Ext} @tab @strong{Ext} @tab @strong{Ext} @tab @strong{Ext}
+@item .BAK @tab .DAT @tab .HSH @tab .ISD
+@item .ISM @tab .ISM @tab .MRG @tab .MYD
+@item .MYI @tab .db @tab .frm @tab
@end multitable
All subdirectories that consists of 2 digits (@code{RAID} directories)
@@ -33566,16 +34375,6 @@ exist.
@cindex @code{mysqladmin}
You can also drop databases with @code{mysqladmin}. @xref{Client-Side Scripts}.
-
-@menu
-* CREATE TABLE:: @code{CREATE TABLE} Syntax
-* ALTER TABLE:: @code{ALTER TABLE} Syntax
-* RENAME TABLE:: @code{RENAME TABLE} Syntax
-* DROP TABLE:: @code{DROP TABLE} Syntax
-* CREATE INDEX:: @code{CREATE INDEX} Syntax
-* DROP INDEX:: @code{DROP INDEX} Syntax
-@end menu
-
@node CREATE TABLE, ALTER TABLE, DROP DATABASE, Data Definition
@subsection @code{CREATE TABLE} Syntax
@@ -33597,7 +34396,7 @@ create_definition:
or INDEX [index_name] (index_col_name,...)
or UNIQUE [INDEX] [index_name] (index_col_name,...)
or FULLTEXT [INDEX] [index_name] (index_col_name,...)
- or [CONSTRAINT symbol] FOREIGN KEY index_name (index_col_name,...)
+ or [CONSTRAINT symbol] FOREIGN KEY [index_name] (index_col_name,...)
[reference_definition]
or CHECK (expr)
@@ -33643,21 +34442,22 @@ reference_option:
RESTRICT | CASCADE | SET NULL | NO ACTION | SET DEFAULT
table_options:
- TYPE = @{BDB | HEAP | ISAM | InnoDB | MERGE | MYISAM @}
+ TYPE = @{BDB | HEAP | ISAM | InnoDB | MERGE | MRG_MYISAM | MYISAM @}
or AUTO_INCREMENT = #
or AVG_ROW_LENGTH = #
or CHECKSUM = @{0 | 1@}
or COMMENT = "string"
or MAX_ROWS = #
or MIN_ROWS = #
-or PACK_KEYS = @{0 | 1@}
+or PACK_KEYS = @{0 | 1 | DEFAULT@}
or PASSWORD = "string"
or DELAY_KEY_WRITE = @{0 | 1@}
or ROW_FORMAT= @{ default | dynamic | fixed | compressed @}
or RAID_TYPE= @{1 | STRIPED | RAID0 @} RAID_CHUNKS=# RAID_CHUNKSIZE=#
or UNION = (table_name,[table_name...])
-or DATA DIRECTORY="directory"
-or INDEX DIRECTORY="directory"
+or INSERT_METHOD= @{NO | FIRST | LAST @}
+or DATA DIRECTORY="absolute path to directory"
+or INDEX DIRECTORY="absolute path to directory"
select_statement:
[IGNORE | REPLACE] SELECT ... (Some legal select statement)
@@ -33677,7 +34477,7 @@ you create a table. A temporary table will automatically be deleted if a
connection dies and the name is per connection. This means that two different
connections can both use the same temporary table name without conflicting
with each other or with an existing table of the same name. (The existing table
-is hidden until the temporary table is deleted).
+is hidden until the temporary table is deleted.)
In MySQL Version 3.23 or later, you can use the keywords
@code{IF NOT EXISTS} so that an error does not occur if the table already
@@ -33725,6 +34525,9 @@ positive number. This is done to avoid precision problems when
numbers 'wrap' over from positive to negative and also to ensure that one
doesn't accidentally get an auto_increment column that contains 0.
+In MyISAM and BDB tables you can specify @code{AUTO_INCREMENT} secondary
+column in a multi-column key. @xref{example-AUTO_INCREMENT}.
+
@cindex ODBC compatibility
@cindex compatibility, with ODBC
To make MySQL compatible with some ODBC applications, you can find
@@ -33753,6 +34556,7 @@ as setting it to @code{NULL}, because @code{0} is a valid @code{TIMESTAMP}
value.
@item
+@cindex default values
If no @code{DEFAULT} value is specified for a column, MySQL
automatically assigns one.
@@ -33775,8 +34579,10 @@ column in a table, the default value is the current date and time.
@xref{Date and time types}.
@item
-For string types other than @code{ENUM}, the default value is the empty string.
-For @code{ENUM}, the default is the first enumeration value.
+For string types other than @code{ENUM}, the default value is the empty
+string. For @code{ENUM}, the default is the first enumeration value (if
+you haven't explicitely specified another default value with the
+@code{DEFAULT} directive).
@end itemize
Default values must be constants. This means, for example, that you cannot
@@ -33862,7 +34668,7 @@ The @code{FOREIGN KEY}, @code{CHECK}, and @code{REFERENCES} clauses don't
actually do anything. The syntax for them is provided only for compatibility,
to make it easier to port code from other SQL servers and to run applications
that create tables with references.
-@xref{Missing functions}.
+@xref{Differences from ANSI}.
@item
Each @code{NULL} column takes one bit extra, rounded up to the nearest byte.
@@ -33884,11 +34690,13 @@ implemented in MySQL Version 3.23 and above.
The different table types are:
@multitable @columnfractions .20 .80
+@item @strong{Table type} @tab @strong{Description}
@item BDB or Berkeley_db @tab Transaction-safe tables with page locking. @xref{BDB}.
@item HEAP @tab The data for this table is only stored in memory. @xref{HEAP}.
@item ISAM @tab The original table handler. @xref{ISAM}.
@item InnoDB @tab Transaction-safe tables with row locking. @xref{InnoDB}.
@item MERGE @tab A collection of MyISAM tables used as one table. @xref{MERGE}.
+@item MRG_MyISAM @tab An alias for MERGE tables
@item MyISAM @tab The new binary portable table handler that is replacing ISAM. @xref{MyISAM}.
@end multitable
@xref{Table types}.
@@ -33899,21 +34707,22 @@ specified. For example, if @code{TYPE=BDB} is specified, and that distribution
of MySQL does not support @code{BDB} tables, the table will be created
as @code{MyISAM} instead.
-The other table options are used to optimize the behavior of the
+The other table options are used to optimise the behavior of the
table. In most cases, you don't have to specify any of them.
The options work for all table types, if not otherwise indicated:
@multitable @columnfractions .20 .80
+@item @strong{Option} @tab @strong{Description}
@item @code{AUTO_INCREMENT} @tab The next auto_increment value you want to set for your table (MyISAM).
@item @code{AVG_ROW_LENGTH} @tab An approximation of the average row length for your table. You only need to set this for large tables with variable size records.
@item @code{CHECKSUM} @tab Set this to 1 if you want MySQL to maintain a checksum for all rows (makes the table a little slower to update but makes it easier to find corrupted tables) (MyISAM).
@item @code{COMMENT} @tab A 60-character comment for your table.
@item @code{MAX_ROWS} @tab Max number of rows you plan to store in the table.
@item @code{MIN_ROWS} @tab Minimum number of rows you plan to store in the table.
-@item @code{PACK_KEYS} @tab Set this to 1 if you want to have a smaller index. This usually makes updates slower and reads faster (MyISAM, ISAM).
+@item @code{PACK_KEYS} @tab Set this to 1 if you want to have a smaller index. This usually makes updates slower and reads faster (MyISAM, ISAM). Setting this to 0 will disable all packing of keys. Setting this to @code{DEFAULT} (MySQL 4.0) will tell the table handler to only pack long @code{CHAR}/@code{VARCHAR} columns.
@item @code{PASSWORD} @tab Encrypt the @code{.frm} file with a password. This option doesn't do anything in the standard MySQL version.
@item @code{DELAY_KEY_WRITE} @tab Set this to 1 if want to delay key table updates until the table is closed (MyISAM).
-@item @code{ROW_FORMAT} @tab Defines how the rows should be stored. Currently you can only use the DYNAMIC and STATIC options for MyISAM tables.
+@item @code{ROW_FORMAT} @tab Defines how the rows should be stored. Currently this option only works with MyISAM tables, which supports the @code{DYNAMIC} and @code{FIXED} row formats. @xref{MyISAM table formats}.
@end multitable
When you use a @code{MyISAM} table, MySQL uses the product of
@@ -33932,13 +34741,13 @@ many numbers that are the same. Prefix compression means that every
key needs one extra byte to indicate how many bytes of the previous key are
the same for the next key (note that the pointer to the row is stored
in high-byte-first-order directly after the key, to improve
-compression.) This means that if you have many equal keys on two rows
+compression). This means that if you have many equal keys on two rows
in a row, all following 'same' keys will usually only take 2 bytes
(including the pointer to the row). Compare this to the ordinary case
where the following keys will take storage_size_for_key +
pointer_size (usually 4). On the other hand, if all keys are
totally different, you will lose 1 byte per key, if the key isn't a
-key that can have @code{NULL} values (In this case the packed key length will
+key that can have @code{NULL} values. (In this case the packed key length will
be stored in the same byte that is used to mark if a key is @code{NULL}.)
@item
@@ -33995,16 +34804,18 @@ automatically be deleted.
To ensure that the update log/binary log can be used to re-create the
original tables, MySQL will not allow concurrent inserts during
-@code{CREATE TABLE .... SELECT}.
+@code{CREATE TABLE ... SELECT}.
@item
The @code{RAID_TYPE} option will help you to break the 2G/4G limit for
-the MyISAM data file (not the index file) on
-operating systems that don't support big files. You can get also more speed
-from the I/O bottleneck by putting @code{RAID} directories on different
-physical disks. @code{RAID_TYPE} will work on any OS, as long as you have
-configured MySQL with @code{--with-raid}. For now the only allowed
-@code{RAID_TYPE} is @code{STRIPED} (@code{1} and @code{RAID0} are aliases
-for this).
+the MyISAM data file (not the index file) on operating systems that
+don't support big files. Note that this option is not recommended for
+file system that supports big files!
+
+You can get more speed from the I/O bottleneck by putting @code{RAID}
+directories on different physical disks. @code{RAID_TYPE} will work on
+any OS, as long as you have configured MySQL with @code{--with-raid}.
+For now the only allowed @code{RAID_TYPE} is @code{STRIPED} (@code{1}
+and @code{RAID0} are aliases for this).
If you specify @code{RAID_TYPE=STRIPED} for a @code{MyISAM} table,
@code{MyISAM} will create @code{RAID_CHUNKS} subdirectories named 00,
@@ -34020,19 +34831,27 @@ tables as one. This only works with MERGE tables. @xref{MERGE}.
For the moment you need to have @code{SELECT}, @code{UPDATE}, and
@code{DELETE} privileges on the tables you map to a @code{MERGE} table.
All mapped tables must be in the same database as the @code{MERGE} table.
+
+@item
+If you want to insert data in a @code{MERGE} table, you have to specify with
+@code{INSERT_METHOD} into with table the row should be inserted.
+@xref{MERGE}. This option was introduced in MySQL 4.0.0.
+
@item
In the created table the @code{PRIMARY} key will be placed first, followed
by all @code{UNIQUE} keys and then the normal keys. This helps the
-MySQL optimizer to prioritize which key to use and also more quickly
+MySQL optimiser to prioritise which key to use and also more quickly
detect duplicated @code{UNIQUE} keys.
@item
By using @code{DATA DIRECTORY="directory"} or @code{INDEX
DIRECTORY="directory"} you can specify where the table handler should
-put it's table and index files. This only works for @code{MyISAM} tables
-in @code{MySQL} 4.0, when you are not using the @code{--skip-symlink}
-option. @xref{Symbolic links to tables}.
+put it's table and index files. Note that the directory should be a full
+path to the directory (not relative path).
+This only works for @code{MyISAM} tables in @code{MySQL} 4.0, when you
+are not using the @code{--skip-symlink} option. @xref{Symbolic links to
+tables}.
@end itemize
@@ -34106,11 +34925,13 @@ alter_specification:
or ADD [CONSTRAINT symbol] FOREIGN KEY index_name (index_col_name,...)
[reference_definition]
or ALTER [COLUMN] col_name @{SET DEFAULT literal | DROP DEFAULT@}
- or CHANGE [COLUMN] old_col_name create_definition
- or MODIFY [COLUMN] create_definition
+ or CHANGE [COLUMN] old_col_name create_definition [FIRST | AFTER column_name]
+ or MODIFY [COLUMN] create_definition [FIRST | AFTER column_name]
or DROP [COLUMN] col_name
or DROP PRIMARY KEY
or DROP INDEX index_name
+ or DISABLE KEYS
+ or ENABLE KEYS
or RENAME [TO] new_tbl_name
or ORDER BY col
or table_options
@@ -34278,6 +35099,15 @@ indexes are created in a separate batch (like in @code{REPAIR}).
This should make @code{ALTER TABLE} much faster when you have many indexes.
@item
+Since @strong{MySQL 4.0} the above feature can be activated explicitly.
+@code{ALTER TABLE ... DISABLE KEYS} makes MySQL to stop updating
+non-unique indexes for @code{MyISAM} table.
+@code{ALTER TABLE ... ENABLE KEYS} then should be used to recreate missing
+indexes. As MySQL does it with special algorithm which is much
+faster then inserting keys one by one, disabling keys could give a
+considerable speedup on bulk inserts.
+
+@item
@findex mysql_info()
With the C API function @code{mysql_info()}, you can find out how many
records were copied, and (when @code{IGNORE} is used) how many records were
@@ -34290,7 +35120,7 @@ The @code{FOREIGN KEY}, @code{CHECK}, and @code{REFERENCES} clauses don't
actually do anything. The syntax for them is provided only for compatibility,
to make it easier to port code from other SQL servers and to run applications
that create tables with references.
-@xref{Missing functions}.
+@xref{Differences from ANSI}.
@end itemize
Here is an example that shows some of the uses of @code{ALTER TABLE}. We
@@ -34401,6 +35231,7 @@ If MySQL encounters any errors in a multiple table rename, it
will do a reverse rename for all renamed tables to get everything back
to the original state.
+@code{RENAME TABLE} was added in MySQL 3.23.23.
@node DROP TABLE, CREATE INDEX, RENAME TABLE, Data Definition
@subsection @code{DROP TABLE} Syntax
@@ -34421,8 +35252,8 @@ exist.
@code{RESTRICT} and @code{CASCADE} are allowed to make porting easier.
For the moment they don't do anything.
-@strong{NOTE}: @code{DROP TABLE} is not transaction-safe and will
-automatically commit any active transactions.
+@strong{Note}: @code{DROP TABLE} will
+automatically commit current active transaction.
@node CREATE INDEX, DROP INDEX, DROP TABLE, Data Definition
@@ -34454,7 +35285,7 @@ columns.
For @code{CHAR} and @code{VARCHAR} columns, indexes can be created that
use only part of a column, using @code{col_name(length)} syntax. (On
-@code{BLOB} and @code{TEXT} columns the length is required). The
+@code{BLOB} and @code{TEXT} columns the length is required.) The
statement shown below creates an index using the first 10 characters of
the @code{name} column:
@@ -34594,8 +35425,8 @@ By default, MySQL runs in @code{autocommit} mode. This means that
as soon as you execute an update, MySQL will store the update on
disk.
-If you are using transactions safe tables (like @code{BDB},
-@code{InnoDB}, you can put MySQL into
+If you are using transactions safe tables (like @code{InnoDB},
+@code{BDB}, you can put MySQL into
non-@code{autocommit} mode with the following command:
@example
@@ -34634,9 +35465,10 @@ The following commands automatically end a transaction (as if you had done
a @code{COMMIT} before executing the command):
@multitable @columnfractions .33 .33 .33
-@item @code{ALTER TABLE} @tab @code{BEGIN} @tab @code{CREATE INDEX}
-@item @code{DROP DATABASE} @tab @code{DROP TABLE} @tab @code{RENAME TABLE}
-@item @code{TRUNCATE}
+@item @strong{Command} @tab @strong{Command} @tab @strong{Command}
+@item @code{ALTER TABLE} @tab @code{BEGIN} @tab @code{CREATE INDEX}
+@item @code{DROP DATABASE} @tab @code{DROP TABLE} @tab @code{RENAME TABLE}
+@item @code{TRUNCATE} @tab @tab
@end multitable
You can change the isolation level for transactions with
@@ -34719,7 +35551,7 @@ tables to transactions safe tables.
You can safely kill a thread that is waiting for a table lock with
@code{KILL}. @xref{KILL}.
-Note that you should @strong{NOT} lock any tables that you are using with
+Note that you should @strong{not} lock any tables that you are using with
@code{INSERT DELAYED}. This is because that in this case the @code{INSERT}
is done by a separate thread.
@@ -34806,8 +35638,7 @@ future transactions.
You can set the default isolation level for @code{mysqld} with
@code{--transaction-isolation=...}. @xref{Command-line options}.
-
-@node Fulltext Search, , Transactional Commands, Reference
+@node Fulltext Search, Query Cache, Transactional Commands, Reference
@section MySQL Full-text Search
@cindex searching, full-text
@@ -34819,9 +35650,9 @@ and searching. Full-text indexes in MySQL are an index of type
@code{FULLTEXT}. @code{FULLTEXT} indexes can be created from @code{VARCHAR}
and @code{TEXT} columns at @code{CREATE TABLE} time or added later with
@code{ALTER TABLE} or @code{CREATE INDEX}. For large datasets, adding
-@code{FULLTEXT} index with @code{ALTER TABLE} (or @code{CREATE INDEX}) would
-be much faster than inserting rows into the empty table with a @code{FULLTEXT}
-index.
+@code{FULLTEXT} index with @code{ALTER TABLE} (or @code{CREATE INDEX})
+would be much faster than inserting rows into the empty table that has
+a @code{FULLTEXT} index.
Full-text search is performed with the @code{MATCH} function.
@@ -34837,8 +35668,8 @@ Query OK, 0 rows affected (0.00 sec)
mysql> INSERT INTO articles VALUES
-> (0,'MySQL Tutorial', 'DBMS stands for DataBase Management ...'),
-> (0,'How To Use MySQL Efficiently', 'After you went through a ...'),
- -> (0,'Optimizing MySQL','In this tutorial we will show how to ...'),
- -> (0,'1001 MySQL Trick','1. Never run mysqld as root. 2. Normalize ...'),
+ -> (0,'Optimising MySQL','In this tutorial we will show how to ...'),
+ -> (0,'1001 MySQL Trick','1. Never run mysqld as root. 2. Normalise ...'),
-> (0,'MySQL vs. YourSQL', 'In the following database comparison we ...'),
-> (0,'MySQL Security', 'When configured properly, MySQL could be ...');
Query OK, 5 rows affected (0.00 sec)
@@ -34854,7 +35685,8 @@ mysql> SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('database');
2 rows in set (0.00 sec)
@end example
-The function @code{MATCH} matches a natural language query @code{AGAINST}
+The function @code{MATCH} matches a natural language (or boolean,
+see below) query in case-insensitive fashion @code{AGAINST}
a text collection (which is simply the set of columns covered by a
@code{FULLTEXT} index). For every row in a table it returns relevance -
a similarity measure between the text in that row (in the columns that are
@@ -34870,7 +35702,7 @@ The above is a basic example of using @code{MATCH} function. Rows are
returned with relevance decreasing.
@example
-mysql> SELECT id,MATCH (title,body) AGAINST ('Tutorial') FROM articles;
+mysql> SELECT id,MATCH title,body AGAINST ('Tutorial') FROM articles;
+----+-----------------------------------------+
| id | MATCH (title,body) AGAINST ('Tutorial') |
+----+-----------------------------------------+
@@ -34888,14 +35720,14 @@ This example shows how to retrieve the relevances. As neither @code{WHERE}
nor @code{ORDER BY} clauses are present, returned rows are not ordered.
@example
-mysql> SELECT id, body, MATCH (title,body) AGAINST (
+mysql> SELECT id, body, MATCH title,body AGAINST (
-> 'Security implications of running MySQL as root') AS score
-> FROM articles WHERE MATCH (title,body) AGAINST
-> ('Security implications of running MySQL as root');
+----+-----------------------------------------------+-----------------+
| id | body | score |
+----+-----------------------------------------------+-----------------+
-| 4 | 1. Never run mysqld as root. 2. Normalize ... | 1.5055546709332 |
+| 4 | 1. Never run mysqld as root. 2. Normalise ... | 1.5055546709332 |
| 6 | When configured properly, MySQL could be ... | 1.31140957288 |
+----+-----------------------------------------------+-----------------+
2 rows in set (0.00 sec)
@@ -34904,7 +35736,7 @@ mysql> SELECT id, body, MATCH (title,body) AGAINST (
This is more complex example - the query returns the relevance and still
sorts the rows with relevance decreasing. To achieve it one should specify
@code{MATCH} twice. Note, that this will cause no additional overhead, as
-MySQL optimizer will notice that these two @code{MATCH} calls are
+MySQL optimiser will notice that these two @code{MATCH} calls are
identical and will call full-text search code only once.
MySQL uses a very simple parser to split text into words. A
@@ -34923,7 +35755,7 @@ relevance of the row.
Such a technique works best with large collections (in fact, it was
carefully tuned this way). For very small tables, word distribution
does not reflect adequately their semantical value, and this model
-may sometimes produce bizarre results.
+may sometimes produce bisarre results.
@example
mysql> SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('MySQL');
@@ -34942,33 +35774,106 @@ We all know this happens far too often when we are trying to find something on
the Internet with a search engine. It is with this reasoning that such rows
have been assigned a low semantical value in @strong{this particular dataset}.
+Since version 4.0.1 MySQL can also perform boolean fulltext searches using
+@code{IN BOOLEAN MODE} modifier.
+
+@example
+mysql> SELECT * FROM articles WHERE MATCH (title,body) AGAINST (
+ -> '+MySQL -YourSQL' IN BOOLEAN MODE);
++----+------------------------------+-----------------------------------------------+
+| id | title | body |
++----+------------------------------+-----------------------------------------------+
+| 1 | MySQL Tutorial | DBMS stands for DataBase Management ... |
+| 2 | How To Use MySQL Efficiently | After you went through a ... |
+| 3 | Optimising MySQL | In this tutorial we will show how to ... |
+| 4 | 1001 MySQL Trick | 1. Never run mysqld as root. 2. Normalise ... |
+| 6 | MySQL Security | When configured properly, MySQL could be ... |
++----+------------------------------+-----------------------------------------------+
+@end example
+
+This query retrieved all the rows that contain the word @code{MySQL}
+(note: 50% threshold is gone), but does @strong{not} contain the word
+@code{YourSQL}. Note, that it does not auto-magically sort rows in
+decreasing relevance order (the last row has the highest relevance,
+as it contains @code{MySQL} twice). Boolean fulltext search can also
+work even without @code{FULLTEXT} index, but it would be @strong{slow}.
+
+Boolean fulltext search supports the following operators:
+
+@table @code
+@item +
+A plus sign prepended to a word indicates that this word @strong{must be}
+present in every row returned.
+@item -
+A minus sign prepended to a word indicates that this word @strong{must not}
+be present in the rows returned.
+@item
+By default - without plus or minus - the word is optional, but the rows that
+contain it will be rated higher. This mimicks the behaviour of
+@code{MATCH ... AGAINST()} without @code{IN BOOLEAN MODE} modifier.
+@item < >
+These two operators are used to increase and decrease word's contribution
+to the relevance value, assigned to a row. See an example below.
+@item ( )
+Parentheses are used - as usual - to group words into subexpressions.
+@item ~
+This is negation operator. It makes word's contribution to the row
+relevance negative. It's useful for marking noise words. A row that has
+such a word will be rated lower than others, but will not be excluded
+altogether, as with @code{-} operator.
+@item *
+This is truncation operator. Unlike others it should be @strong{appended}
+to the word, not prepended.
+@end table
+
+And here are some examples:
+
+@table @code
+@item apple banana
+find rows that contain at least one of these words.
+@item +apple +juice
+... both words
+@item +apple macintosh
+... word ``apple'', but rank it higher if it also contain ``macintosh''
+@item +apple -macintosh
+... word ``apple'' but not ``macintosh''
+@item +apple +(>pie <strudel)
+... ``apple'' and ``pie'', or ``apple'' and ``strudel'' (in any
+order), but rank ``apple pie'' higher than ``apple strudel''.
+@item apple*
+... ``apple'', ``apples'', ``applesauce'', and ``applet''
+@end table
+
@menu
-* Fulltext restrictions:: Fulltext restrictions
+* Fulltext Restrictions:: Fulltext Restrictions
* Fulltext Fine-tuning:: Fine-tuning MySQL Full-text Search
-* Fulltext Features to Appear in MySQL 4.0:: New Features of Full-text Search to Appear in MySQL 4.0
* Fulltext TODO:: Full-text Search TODO
@end menu
-
-@node Fulltext restrictions, Fulltext Fine-tuning, Fulltext Search, Fulltext Search
-@subsection Fulltext restrictions
+@node Fulltext Restrictions, Fulltext Fine-tuning, Fulltext Search, Fulltext Search
+@subsection Fulltext Restrictions
@itemize @bullet
@item
All parameters to the @code{MATCH} function must be columns from the
-same table that is part of the same fulltext index.
+same table that is part of the same fulltext index, unless this
+@code{MATCH} is @code{IN BOOLEAN MODE}.
+@item
+Column list between @code{MATCH} and @code{AGAINST} must match exactly
+a column list in the @code{FULLTEXT} index definition, unless this
+@code{MATCH} is @code{IN BOOLEAN MODE}.
@item
The argument to @code{AGAINST} must be a constant string.
@end itemize
-@node Fulltext Fine-tuning, Fulltext Features to Appear in MySQL 4.0, Fulltext restrictions, Fulltext Search
+@node Fulltext Fine-tuning, Fulltext TODO, Fulltext Restrictions, Fulltext Search
@subsection Fine-tuning MySQL Full-text Search
-Unfortunately, full-text search has no user-tunable parameters yet,
-although adding some is very high on the TODO. However, if you have a
-MySQL source distribution (@xref{Installing source}.), you can
-somewhat alter the full-text search behavior.
+Unfortunately, full-text search has few user-tunable parameters yet,
+although adding some is very high on the TODO. If you have a
+MySQL source distribution (@pxref{Installing source}), you can
+more control on the full-text search behavior.
Note that full-text search was carefully tuned for the best searching
effectiveness. Modifying the default behavior will, in most cases,
@@ -34978,22 +35883,19 @@ unless you know what you are doing!
@itemize @bullet
@item
-Minimal length of word to be indexed is defined in
-@code{myisam/ftdefs.h} file by the line
-@example
-#define MIN_WORD_LEN 4
-@end example
-Change it to the value you prefer, recompile MySQL, and rebuild
+Minimal length of word to be indexed is defined by MySQL
+variable @code{ft_min_word_length}. @xref{SHOW VARIABLES}.
+Change it to the value you prefer, and rebuild
your @code{FULLTEXT} indexes.
@item
-The stopword list is defined in @code{myisam/ft_static.c}
+The stopword list is defined in @file{myisam/ft_static.c}
Modify it to your taste, recompile MySQL and rebuild
your @code{FULLTEXT} indexes.
@item
The 50% threshold is caused by the particular weighting scheme chosen. To
-disable it, change the following line in @code{myisam/ftdefs.h}:
+disable it, change the following line in @file{myisam/ftdefs.h}:
@example
#define GWS_IN_USE GWS_PROB
@end example
@@ -35003,55 +35905,26 @@ to
@end example
and recompile MySQL.
There is no need to rebuild the indexes in this case.
+@strong{Note:} by doing this you @strong{severely} decrease MySQL ability
+to provide adequate relevance values by @code{MATCH} function.
+It means, that if you really need to search for such a common words,
+then you should rather search @code{IN BOOLEAN MODE}, which does not
+has 50% threshold.
-@end itemize
-
-
-@node Fulltext Features to Appear in MySQL 4.0, Fulltext TODO, Fulltext Fine-tuning, Fulltext Search
-@subsection New Features of Full-text Search to Appear in MySQL 4.0
-
-This section includes a list of the fulltext features that are already
-implemented in the 4.0 tree. It explains
-@strong{More functions for full-text search} entry of @ref{TODO MySQL 4.0}.
-
-@itemize @bullet
-@item @code{REPAIR TABLE} with @code{FULLTEXT} indexes,
-@code{ALTER TABLE} with @code{FULLTEXT} indexes, and
-@code{OPTIMIZE TABLE} with @code{FULLTEXT} indexes are now
-up to 100 times faster.
-
-@item @code{MATCH ... AGAINST} is going to supports the following
-@strong{boolean operators}:
-
-@itemize @bullet
-@item @code{+}word means the that word @strong{must} be present in every
-row returned.
-@item @code{-}word means the that word @strong{must not} be present in every
-row returned.
-@item @code{<} and @code{>} can be used to decrease and increase word
-weight in the query.
-@item @code{~} can be used to assign a @strong{negative} weight to a noise
-word.
-@item @code{*} is a truncation operator.
-@end itemize
-
-Boolean search utilizes a more simplistic way of calculating the relevance,
-that does not have a 50% threshold.
-
-@item Searches are now up to 2 times faster due to optimized search algorithm.
-
-@item Utility program @code{ft_dump} added for low-level @code{FULLTEXT}
-index operations (querying/dumping/statistics).
+@item
+Sometimes search engine maintaner would like to change operators used
+for boolean fulltext search. They are defined by a
+@code{ft_boolean_syntax} variable. @xref{SHOW VARIABLES}.
+Still, this variable is read-only, its value is set in
+@file{myisam/ft_static.c}.
@end itemize
-
-@node Fulltext TODO, , Fulltext Features to Appear in MySQL 4.0, Fulltext Search
+@node Fulltext TODO, , Fulltext Fine-tuning, Fulltext Search
@subsection Full-text Search TODO
@itemize @bullet
@item Make all operations with @code{FULLTEXT} index @strong{faster}.
-@item Support for braces @code{()} in boolean full-text search.
@item Phrase search, proximity operators
@item Boolean search can work without @code{FULLTEXT} index
(yes, @strong{very} slow).
@@ -35067,6 +35940,229 @@ parameters to @code{FULLTEXT} in @code{CREATE/ALTER TABLE}).
@end itemize
+@node Query Cache, , Fulltext Search, Reference
+@section MySQL Query Cache
+
+@cindex Query Cache
+@cindex @code{SELECT}, Query Cache
+
+From version 4.0.1, @code{MySQL server} features a @code{Query Cache}.
+When in use, the query cache stores the text of a @code{SELECT} query
+together with the corresponding result that is sent to a client.
+If another identical query is received, the server can then retrieve
+the results from the query cache rather than parsing and executing the
+same query again.
+
+The query cache is extremely useful in an environment where (some)
+tables don't change very often and you have a lot of identical queries.
+This is a typical situation for many web servers that use a lot of
+dynamic content.
+
+Following are some performance data for the query cache
+(We got these by running the MySQL benchmark suite on a Linux Alpha
+2x500 MHz with 2GB RAM and a 64MB query cache):
+
+@itemize @bullet
+@item
+If you want to disable the query cache code set @code{query_cache_size=0}.
+By disabling the query cache code there is no noticeable overhead.
+@item
+If all of the queries you're preforming are simple (such as selecting a
+row from a table with one row); but still differ so that the queries can
+not be cached, the overhead for having the query cache active is 13%.
+This could be regarded as the worst case scenario. However, in real life,
+queries are much more complicated than our simple example so the overhead
+is normally significantly lower.
+@item
+Searches after one row in a one row table is 238% faster.
+This can be regarded as close to the minimum speedup to be expected for
+a query that is cached.
+@end itemize
+
+@menu
+* Query Cache How:: How The Query Cache Operates
+* Query Cache Configuration:: Query Cache Configuration
+* Query Cache in SELECT:: Query Cache Options in @code{SELECT}
+* Query Cache Status and Maintenance:: Query Cache Status and Maintenance
+@end menu
+
+
+@node Query Cache How, Query Cache Configuration, Query Cache, Query Cache
+@subsection How The Query Cache Operates
+
+Queries are compared before parsing, thus
+
+@example
+SELECT * FROM TABLE
+@end example
+
+and
+
+@example
+Select * from table
+@end example
+
+are regarded as different queries for query cache, so queries need
+to be exactly the same (byte for byte) to be seen as identical.
+In addition, a query may be seen as different if for instance one
+client is using a new communication protocol format or another
+character set than another client.
+
+Queries that uses different databases, uses different protocol versions
+or the uses different default character sets are considered different
+queries and cached separately.
+
+The cache does work for @code{SELECT CALC_ROWS ...} and
+@code{SELECT FOUND_ROWS() ...} type queries because the number of
+found rows is also stored in the cache.
+
+If a table changes (@code{INSERT}, @code{UPDATE}, @code{DELETE},
+@code{TRUNCATE}, @code{ALTER} or @code{DROP TABLE|DATABASE}),
+then all cached queries that used this table (possibly through a
+@code{MRG_MyISAM} table!) become invalid and are removed from the cache.
+
+Currently all @code{InnoDB} tables are invalidated on @code{COMMIT},
+in the future this will be changed so only tables changed in the
+transaction cause the corresponding cache entries to be invalidated.
+
+A query cannot be cached if it contains one of the functions:
+@multitable @columnfractions .25 .25 .25 .25
+@item @strong{Function} @tab @strong{Function}
+ @tab @strong{Function} @tab @strong{Function}
+@item @code{User Defined Functions} @tab @code{CONNECTION_ID}
+ @tab @code{FOUND_ROWS} @tab @code{GET_LOCK}
+@item @code{RELEASE_LOCK} @tab @code{LOAD_FILE}
+ @tab @code{MASTER_POS_WAIT} @tab @code{NOW}
+@item @code{SYSDATE} @tab @code{CURRENT_TIMESTAMP}
+ @tab @code{CURDATE} @tab @code{CURRENT_DATE}
+@item @code{CURTIME} @tab @code{CURRENT_TIME}
+ @tab @code{DATABASE} @tab @code{ENCRYPT} (with one parameter)
+@item @code{LAST_INSERT_ID} @tab @code{RAND}
+ @tab @code{UNIX_TIMESTAMP} (without parameters) @tab @code{USER}
+@item @code{BENCHMARK}
+@end multitable
+
+Nor can a query be cached if it contains user variables,
+if it is of the form @code{SELECT ... IN SHARE MODE} or
+of the form @code{SELECT * FROM AUTOINCREMENT_FIELD IS NULL}
+(to retrieve last insert id - ODBC work around).
+
+However, @code{FOUND ROWS()} will return the correct value,
+even if the preceding query was fetched from the cache.
+
+Queries that don't use any tables or if the user has a column privilege for
+any of the involved tables are not cached.
+
+Before a query is fetched from the query cache, MySQL will check that
+the user has SELECT privilege to all the involved databases and
+tables. If this is not the case, the cached result will not be used.
+
+@node Query Cache Configuration, Query Cache in SELECT, Query Cache How, Query Cache
+@subsection Query Cache Configuration
+
+The query cache adds a few @code{MySQL} system variables for
+@code{mysqld} which may be set in a configuration file, on the
+command line when starting @code{mysqld}.
+
+@itemize
+@item @code{query_cache_limit}
+Don't cache results that are bigger than this. (Default 1M).
+
+@item @code{query_cache_size}
+The memory allocated to store results from old queries.
+If this is 0, the query cache is disabled (default).
+
+@item @code{query_cache_startup_type}
+This may be set (only numeric) to
+@multitable @columnfractions .3 .7
+@item @strong{Option} @tab @strong{Description}
+@item 0 @tab (OFF, don't cache or retrieve results)
+@item 1 @tab (ON, cache all results except @code{SELECT SQL_NO_CACHE ...} queries)
+@item 2 @tab (DEMAND, cache only @code{SELECT SQL_CACHE ...} queries)
+@end multitable
+@end itemize
+
+
+Inside a thread (connection), the behaviour of the query cache can be
+changed from the default. The syntax is as follows:
+
+@code{SQL_QUERY_CACHE_TYPE = OFF | ON | DEMAND}
+@code{SQL_QUERY_CACHE_TYPE = 0 | 1 | 2}
+
+@multitable @columnfractions .3 .7
+@item @strong{Option} @tab @strong{Description}
+@item 0 or OFF @tab Don't cache or retrieve results.
+@item 1 or ON @tab Cache all results except @code{SELECT SQL_NO_CACHE ...} queries.
+@item 2 or DEMAND @tab Cache only @code{SELECT SQL_CACHE ...} queries.
+@end multitable
+
+By default @code{SQL_QUERY_CACHE_TYPE} depends on the value of
+@code{query_cache_startup_type} when the thread was created.
+
+
+@node Query Cache in SELECT, Query Cache Status and Maintenance, Query Cache Configuration, Query Cache
+@subsection Query Cache Options in @code{SELECT}
+
+There are two possible query cache related parameters that may be
+specified in a @code{SELECT} query:
+
+@findex SQL_CACHE
+@findex SQL_NO_CACHE
+
+@multitable @columnfractions .3 .7
+@item @strong{Option} @tab @strong{Description}
+@item @code{SQL_CACHE}
+ @tab If @code{SQL_QUERY_CACHE_TYPE} is @code{DEMAND}, allow the query to be cached.
+ If @code{SQL_QUERY_CACHE_TYPE} is @code{ON}, this is the default.
+ If @code{SQL_QUERY_CACHE_TYPE} is @code{OFF}, do nothing.
+@item @code{SQL_NO_CACHE}
+ @tab Make this query non-cachable, don't allow this query to be stored in the cache.
+@end multitable
+
+
+@node Query Cache Status and Maintenance, , Query Cache in SELECT, Query Cache
+@subsection Query Cache Status and Maintenance
+
+With the @code{FLUSH QUERY CACHE} command you can defragment the query
+cache to better utilise its memory. This command will not remove any
+queries from the cache.
+@code{FLUSH TABLES} also flushes the query cache.
+
+The @code{RESET QUERY CACHE} command removes all query results from the
+query cache.
+
+You can monitor query cache performance in @code{SHOW STATUS}:
+
+@multitable @columnfractions .3 .7
+@item @strong{Variable} @tab @strong{Description}
+@item @code{Qcache_queries_in_cache}
+ @tab Number of queries registered in the cache.
+@item @code{Qcache_inserts}
+ @tab Number of queries added to the cache.
+@item @code{Qcache_hits}
+ @tab Number of cache hits.
+@item @code{Qcache_not_cached}
+ @tab Number of non-cached queries
+ (not cachable, or due to @code{SQL_QUERY_CACHE_TYPE}).
+@item @code{Qcache_free_memory}
+ @tab Amount of free memory for query cache.
+@item @code{Qcache_total_blocks}
+ @tab Total number of blocks in query cache.
+@item @code{Qcache_free_blocks}
+ @tab Number of free memory blocks in query cache.
+@end multitable
+
+Total number of queries =
+@code{Qcache_inserts} + @code{Qcache_hits} + @code{Qcache_not_cached}.
+
+The query cache uses variable length blocks, so @code{Qcache_total_blocks}
+and @code{Qcache_free_blocks} may indicate query cache memory fragmentation.
+After @code{FLUSH QUERY CACHE} only a single (big) free block remains.
+
+Note: Every query needs a minimum of two blocks (one for the query text
+and one or more for the query results). Also, every table that is used
+by a query needs one block, but if two or more queries use same table
+only one block needs to be allocated.
@node Table types, Clients, Reference, Top
@@ -35085,8 +36181,8 @@ parameters to @code{FULLTEXT} in @code{CREATE/ALTER TABLE}).
As of MySQL Version 3.23.6, you can choose between three basic
table formats (@code{ISAM}, @code{HEAP} and @code{MyISAM}. Newer
-MySQL may support additional table type (@code{BDB},
-or @code{InnoDB}), depending on how you compile it.
+MySQL may support additional table type (@code{InnoDB},
+or @code{BDB}), depending on how you compile it.
When you create a new table, you can tell MySQL which table
type it should use for the table. MySQL will always create a
@@ -35101,7 +36197,7 @@ trying to use a table type that is not compiled-in or activated,
MySQL will instead create a table of type @code{MyISAM}. This
is a very useful feature when you want to copy tables between different
SQL servers that supports different table types (like copying tables to
-a slave that is optimized for speed by not having transactional tables).
+a slave that is optimised for speed by not having transactional tables).
This automatic table changing can however also be very confusing for new
MySQL users. We plan to fix this by introducing warnings in
MySQL 4.0 and giving a warning when a table type is automatically
@@ -35111,7 +36207,7 @@ You can convert tables between different types with the @code{ALTER
TABLE} statement. @xref{ALTER TABLE, , @code{ALTER TABLE}}.
Note that MySQL supports two different kinds of
-tables. Transaction-safe tables (@code{BDB}, @code{InnoDB}
+tables: transaction-safe tables (@code{InnoDB} and @code{BDB})
and not transaction-safe tables (@code{HEAP}, @code{ISAM},
@code{MERGE}, and @code{MyISAM}).
@@ -35152,8 +36248,8 @@ of both worlds.
* MERGE:: MERGE tables
* ISAM:: ISAM tables
* HEAP:: HEAP tables
-* BDB:: BDB or Berkeley_db tables
* InnoDB:: InnoDB tables
+* BDB:: BDB or Berkeley_db tables
@end menu
@@ -35215,7 +36311,7 @@ behavior is still present.
@item
When inserted in sorted order (as when you are using an @code{AUTO_INCREMENT}
column) the key tree will be split so that the high node only contains one
-key. This will improve the space utilization in the key tree.
+key. This will improve the space utilisation in the key tree.
@item
@code{BLOB} and @code{TEXT} columns can be indexed.
@item
@@ -35275,13 +36371,13 @@ The following options to @code{mysqld} can be used to change the behavior of
@code{MyISAM} tables. @xref{SHOW VARIABLES}.
@multitable @columnfractions .40 .60
-@item @strong{Option} @tab @strong{Meaning}
+@item @strong{Option} @tab @strong{Description}
@item @code{--myisam-recover=#} @tab Automatic recover of crashed tables.
@item @code{-O myisam_sort_buffer_size=#} @tab Buffer used when recovering tables.
@item @code{--delay-key-write-for-all-tables} @tab Don't flush key buffers between writes for any MyISAM table
-@item @code{-O myisam_max_extra_sort_file_size=#} @tab Used to help MySQL to decide when to use the slow but safe key cache index create method. @strong{NOTE} that this parameter is given in megabytes!
-@item @code{-O myisam_max_sort_file_size=#} @tab Don't use the fast sort index method to created index if the temporary file would get bigger than this.
-@strong{NOTE} that this paramter is given in megabytes!
+@item @code{-O myisam_max_extra_sort_file_size=#} @tab Used to help MySQL to decide when to use the slow but safe key cache index create method. @strong{Note} that this parameter is given in megabytes!
+@item @code{-O myisam_max_sort_file_size=#} @tab Don't use the fast sort index method to created index if the temporary file would get bigger than this. @strong{Note} that this paramter is given in megabytes!
+@item @code{-O myisam_bulk_insert_tree_size=#} @tab Size of tree cache used in bulk insert optimisation. @strong{Note} that this is a limit @strong{per thread}!
@end multitable
The automatic recovery is activated if you start @code{mysqld} with
@@ -35367,6 +36463,13 @@ high-byte first.
automatically depending on the type of columns you are using. The third,
compressed tables, can only be created with the @code{myisampack} tool.
+When you @code{CREATE} or @code{ALTER} a table you can for tables that
+doesn't have @code{BLOB}'s force the table format to @code{DYNAMIC} or
+@code{FIXED} with the @code{ROW_FORMAT=#} table option. In the future
+you will be able to compress/decompress tables by specifying
+@code{ROW_FORMAT=compressed | default} to @code{ALTER TABLE}.
+@xref{CREATE TABLE}.
+
@menu
* Static format:: Static (Fixed-length) table characteristics
* Dynamic format:: Dynamic table characteristics
@@ -35406,7 +36509,7 @@ Easy to cache.
Easy to reconstruct after a crash, because records are located in fixed
positions.
@item
-Doesn't have to be reorganized (with @code{myisamchk}) unless a huge number of
+Doesn't have to be reorganised (with @code{myisamchk}) unless a huge number of
records are deleted and you want to return free disk space to the operating
system.
@item
@@ -35493,7 +36596,7 @@ This is a read-only type that is generated with the optional
All MySQL distributions, even those that existed before MySQL
went GPL, can read tables that were compressed with @code{myisampack}.
@item
-Compressed tables take very little disk space. This minimizes disk usage, which
+Compressed tables take very little disk space. This minimises disk usage, which
is very nice when using slow disks (like CD-ROMs).
@item
Each record is compressed separately (very little access overhead). The
@@ -35521,8 +36624,7 @@ converted to @code{ENUM}.
A column may use a combination of the above compressions.
@end itemize
@item
-Can handle fixed- or dynamic-length records, but not @code{BLOB} or @code{TEXT}
-columns.
+Can handle fixed- or dynamic-length records.
@item
Can be uncompressed with @code{myisamchk}.
@end itemize
@@ -35603,7 +36705,7 @@ If you get the following warning from @code{CHECK TABLE} or @code{myisamchk}:
this means that this counter has come out of sync. This doesn't mean
that the table is corrupted, but means that you should at least do a
-check on the table to verify that it's ok.
+check on the table to verify that it's okay.
The counter works as follows:
@@ -35618,7 +36720,7 @@ When the last instance of a table is closed (because of a @code{FLUSH} or
because there isn't room in the table cache) the counter is
decremented if the table has been updated at any point.
@item
-When you repair the table or check the table and it was ok,
+When you repair the table or check the table and it was okay,
the counter is reset to 0.
@item
To avoid problems with interaction with other processes that may do a
@@ -35632,9 +36734,9 @@ In other words, the only ways this can go out of sync are:
The @code{MyISAM} tables are copied without a @code{LOCK} and
@code{FLUSH TABLES}.
@item
-MySQL has crashed between an update and the final close
-(Note that the table may still be ok, as MySQL always issues writes
-for everything between each statement).
+MySQL has crashed between an update and the final close.
+(Note that the table may still be okay, as MySQL always issues writes
+for everything between each statement.)
@item
Someone has done a @code{myisamchk --repair} or @code{myisamchk
--update-state}on a table that was in use by @code{mysqld}.
@@ -35657,15 +36759,15 @@ is not signaled to the other servers.
@code{MERGE} tables are new in MySQL Version 3.23.25. The code
is still in gamma, but should be resonable stable.
-A @code{MERGE} table is a collection of identical @code{MyISAM} tables
-that can be used as one. You can only @code{SELECT}, @code{DELETE}, and
-@code{UPDATE} from the collection of tables. If you @code{DROP} the
-@code{MERGE} table, you are only dropping the @code{MERGE}
-specification.
+A @code{MERGE} table (also known as a @code{MRG_MyISAM} table) is a
+collection of identical @code{MyISAM} tables that can be used as one.
+You can only @code{SELECT}, @code{DELETE}, and @code{UPDATE} from the
+collection of tables. If you @code{DROP} the @code{MERGE} table, you
+are only dropping the @code{MERGE} specification.
Note that @code{DELETE FROM merge_table} used without a @code{WHERE}
will only clear the mapping for the table, not delete everything in the
-mapped tables. (We plan to fix this in 4.0).
+mapped tables. (We plan to fix this in 4.1).
With identical tables we mean that all tables are created with identical
column and key information. You can't put a MERGE over tables where the
@@ -35725,11 +36827,12 @@ The disadvantages with @code{MERGE} tables are:
@itemize @bullet
@item
-You can't use @code{INSERT} on @code{MERGE} tables, as MySQL
-can't know in which of the tables we should insert the row.
-@item
You can only use identical @code{MyISAM} tables for a @code{MERGE} table.
@item
+@code{AUTO_INCREMENT} columns are not automatically updated on @code{INSERT}.
+@item
+@code{REPLACE} doesn't work.
+@item
@code{MERGE} tables uses more file descriptors. If you are using a
@strong{MERGE} that maps over 10 tables and 10 users are using this, you
are using 10*10 + 10 file descriptors. (10 data files for 10 users
@@ -35751,6 +36854,14 @@ mapped by a @code{MERGE} table that is 'open'. If you do this, the
get unexpected results.
@end itemize
+When you create a @code{MERGE} table you have to specify with
+@code{UNION(list-of-tables)} which tables you want to use as
+one. Optionally you can specify with @code{INSERT_METHOD} if you want
+insert for the @code{MERGE} table to happen in the first or last table
+in the @code{UNION} list. If you don't specify @code{INSERT_METHOD} or
+specify @code{NO}, then all @code{INSERT} commands on the @code{MERGE}
+table will return an error.
+
The following example shows you how to use @code{MERGE} tables:
@example
@@ -35758,7 +36869,7 @@ CREATE TABLE t1 (a INT AUTO_INCREMENT PRIMARY KEY, message CHAR(20));
CREATE TABLE t2 (a INT AUTO_INCREMENT PRIMARY KEY, message CHAR(20));
INSERT INTO t1 (message) VALUES ("Testing"),("table"),("t1");
INSERT INTO t2 (message) VALUES ("Testing"),("table"),("t2");
-CREATE TABLE total (a INT NOT NULL, message CHAR(20), KEY(a)) TYPE=MERGE UNION=(t1,t2);
+CREATE TABLE total (a INT NOT NULL, message CHAR(20), KEY(a)) TYPE=MERGE UNION=(t1,t2) INSERT_METHOD=LAST;
@end example
Note that we didn't create a @code{UNIQUE} or @code{PRIMARY KEY} in the
@@ -35803,17 +36914,64 @@ Change the @code{.MRG} file and issue a @code{FLUSH TABLE} on the
read the new definition file.
@end itemize
+@menu
+* MERGE table problems:: MERGE table problems.
+@end menu
+
+@node MERGE table problems, , MERGE, MERGE
+@subsection MERGE table problems.
+
+The following are the known problems with @code{MERGE} tables:
+
+@itemize @bullet
+@item
+@code{MERGE} table cannot maintain UNIQUE constraints over the whole
+table. When you do INSERT, the data goes into the first or last table
+(according to @code{INSERT_METHOD=xxx}) and this MyISAM table ensures
+that the data are unique, but it knows nothing about the first MyISAM table.
+@item
+@code{DELETE FROM merge_table} used without a @code{WHERE}
+will only clear the mapping for the table, not delete everything in the
+mapped tables.
+@item
+@code{RENAME TABLE} on a table used in an active @code{MERGE} table may
+corrupt the table. This will be fixed in MySQL 4.0.x.
+@item
+Creation of a table of type @code{MERGE} doesn't check if the underlying
+tables are of compatible types. If you use @code{MERGE} tables in this
+fashion, you are very likely to run into strange problems.
+@item
+If you use @code{ALTER TABLE} to first add an @code{UNIQUE} index to a
+table used in a @code{MERGE} table and then use @code{ALTER TABLE} to
+add a normal index on the @code{MERGE} table, the key order will be
+different for the tables if there was an old non-unique key in the
+table. This is because @code{ALTER TABLE} puts @code{UNIQUE} keys before
+normal keys to be able to detect duplicate keys as early as possible.
+@item
+The range optimizer can't yet use @code{MERGE} table efficiently and may
+sometimes produce non-optimal joins. This will be fixed in MySQL 4.0.x.
+@item
+@code{DROP TABLE} on a table that is in use by a @code{MERGE} table will
+not work on Windows because the @code{MERGE} handler does the table mapping
+hidden from the upper layer of MySQL. Because Windows doesn't allow you
+to drop files that are open, you first must flush all @code{MERGE}
+tables (with @code{FLUSH TABLES}) or drop the @code{MERGE} table before
+dropping the table. We will fix this at the same time we introduce
+@code{VIEW}s.
+@end itemize
+
@node ISAM, HEAP, MERGE, Table types
@section ISAM Tables
@cindex tables, ISAM
-You can also use the deprecated ISAM table type. This will disappear
-rather soon because @code{MyISAM} is a better implementation of the same
-thing. ISAM uses a @code{B-tree} index. The index is stored in a file
-with the @code{.ISM} extension, and the data is stored in a file with the
-@code{.ISD} extension. You can check/repair ISAM tables with the
-@code{isamchk} utility. @xref{Crash recovery}.
+You can also use the deprecated @code{ISAM} table type. This will disappear
+rather soon (probably in MySQL 4.1) because @code{MyISAM} is a better
+implementation of the same thing. @code{ISAM} uses a @code{B-tree} index. The
+index is stored in a file with the @code{.ISM} extension, and the data
+is stored in a file with the @code{.ISD} extension. You can
+check/repair @code{ISAM} tables with the @code{isamchk} utility. @xref{Crash
+recovery}.
@code{ISAM} has the following features/properties:
@@ -35830,7 +36988,7 @@ tables. @xref{MyISAM}. The major differences compared to @code{MyISAM}
tables are:
@itemize @bullet
-@item ISAM tables are not binary portable across OS/Platforms.
+@item @code{ISAM} tables are not binary portable across OS/Platforms.
@item Can't handle tables > 4G.
@item Only support prefix compression on strings.
@item Smaller key limits.
@@ -35846,8 +37004,9 @@ TABLE} statement:
mysql> ALTER TABLE tbl_name TYPE = MYISAM;
@end example
+The embedded MySQL versions doesn't support @code{ISAM} tables.
-@node HEAP, BDB, ISAM, Table types
+@node HEAP, InnoDB, ISAM, Table types
@section HEAP Tables
@cindex tables, @code{HEAP}
@@ -35856,7 +37015,7 @@ mysql> ALTER TABLE tbl_name TYPE = MYISAM;
makes them very fast, but if MySQL crashes you will lose all
data stored in them. @code{HEAP} is very useful for temporary tables!
-The MySQL internal HEAP tables use 100% dynamic hashing
+The MySQL internal @code{HEAP} tables use 100% dynamic hashing
without overflow areas. There is no extra space needed for free lists.
@code{HEAP} tables also don't have problems with delete + inserts, which
normally is common with hashed tables:
@@ -35909,7 +37068,7 @@ To free memory, you should execute @code{DELETE FROM heap_table},
@code{TRUNCATE heap_table} or @code{DROP TABLE heap_table}.
@item
MySQL cannot find out approximately how many rows there
-are between two values (this is used by the range optimizer to decide which
+are between two values (this is used by the range optimiser to decide which
index to use). This may affect some queries if you change a @code{MyISAM}
table to a @code{HEAP} table.
@item
@@ -35927,336 +37086,93 @@ SUM_OVER_ALL_KEYS(max_length_of_key + sizeof(char*) * 2)
@code{sizeof(char*)} is 4 on 32-bit machines and 8 on 64-bit machines.
-@node BDB, InnoDB, HEAP, Table types
-@section BDB or Berkeley_DB Tables
-
-@cindex tables, @code{BDB}
-@cindex tables, @code{Berkeley DB}
+@node InnoDB, BDB, HEAP, Table types
+@section InnoDB Tables
@menu
-* BDB overview:: Overview of BDB Tables
-* BDB install:: Installing BDB
-* BDB start:: BDB startup options
-* BDB characteristic:: Some characteristic of @code{BDB} tables:
-* BDB TODO:: Some things we need to fix for BDB in the near future:
-* BDB portability:: Operating systems supported by @strong{BDB}
-* BDB errors:: Errors You May Get When Using BDB Tables
+* InnoDB overview:: InnoDB Tables Overview
+* InnoDB start:: InnoDB Startup Options
+* InnoDB init:: Creating InnoDB Tablespace
+* Using InnoDB tables:: Creating InnoDB Tables
+* Adding and removing:: Adding and Removing InnoDB Data and Log Files
+* Backing up:: Backing up and Recovering an InnoDB Database
+* Moving:: Moving an InnoDB Database to Another Machine
+* InnoDB transaction model:: InnoDB Transaction Model.
+* Implementation:: Implementation of Multiversioning
+* Table and index:: Table and Index Structures
+* File space management:: File Space Management and Disk i/o
+* Error handling:: Error Handling
+* InnoDB restrictions:: Restrictions on InnoDB Tables
+* InnoDB contact information:: InnoDB Contact Information.
@end menu
-@node BDB overview, BDB install, BDB, BDB
-@subsection Overview of BDB Tables
-
-Support for BDB tables is included in the MySQL source distribution
-starting from Version 3.23.34 and is activated in the MySQL-Max
-binary.
-
-BerkeleyDB, available at @uref{http://www.sleepycat.com/} has provided
-MySQL with a transactional table handler. By using BerkeleyDB
-tables, your tables may have a greater chance of surviving crashes, and also
-provides @code{COMMIT} and @code{ROLLBACK} on transactions. The
-MySQL source distribution comes with a BDB distribution that has a
-couple of small patches to make it work more smoothly with MySQL.
-You can't use a non-patched @code{BDB} version with MySQL.
-
-We at MySQL AB are working in close cooperation with Sleepycat to
-keep the quality of the MySQL/BDB interface high.
-
-When it comes to supporting BDB tables, we are committed to help our
-users to locate the problem and help creating a reproducable test case
-for any problems involving BDB tables. Any such test case will be
-forwarded to Sleepycat who in turn will help us find and fix the
-problem. As this is a two stage operation, any problems with BDB tables
-may take a little longer for us to fix than for other table handlers.
-However, as the BerkeleyDB code itself has been used by many other
-applications than MySQL, we don't envision any big problems with
-this. @xref{Table handler support}.
-
-
-@node BDB install, BDB start, BDB overview, BDB
-@subsection Installing BDB
-
-If you have downloaded a binary version of MySQL that includes
-support for BerkeleyDB, simply follow the instructions for installing a
-binary version of MySQL.
-@xref{Installing binary}. @xref{mysqld-max, , @code{mysqld-max}}.
-
-To compile MySQL with Berkeley DB support, download MySQL
-Version 3.23.34 or newer and configure @code{MySQL} with the
-@code{--with-berkeley-db} option. @xref{Installing source}.
-
-@example
-cd /path/to/source/of/mysql-3.23.34
-./configure --with-berkeley-db
-@end example
-
-Please refer to the manual provided with the @code{BDB} distribution for
-more updated information.
-
-Even though Berkeley DB is in itself very tested and reliable,
-the MySQL interface is still considered beta quality.
-We are actively improving and optimizing it to get it stable very
-soon.
-
-
-@node BDB start, BDB characteristic, BDB install, BDB
-@subsection BDB startup options
-
-If you are running with @code{AUTOCOMMIT=0} then your changes in @code{BDB}
-tables will not be updated until you execute @code{COMMIT}. Instead of commit
-you can execute @code{ROLLBACK} to forget your changes. @xref{COMMIT}.
-
-If you are running with @code{AUTOCOMMIT=1} (the default), your changes
-will be committed immediately. You can start an extended transaction with
-the @code{BEGIN WORK} SQL command, after which your changes will not be
-committed until you execute @code{COMMIT} (or decide to @code{ROLLBACK}
-the changes).
-
-The following options to @code{mysqld} can be used to change the behavior of
-BDB tables:
-
-@multitable @columnfractions .30 .70
-@item @strong{Option} @tab @strong{Meaning}
-@item @code{--bdb-home=directory} @tab Base directory for BDB tables. This should be the same directory you use for --datadir.
-@item @code{--bdb-lock-detect=#} @tab Berkeley lock detect. One of (DEFAULT, OLDEST, RANDOM, or YOUNGEST).
-@item @code{--bdb-logdir=directory} @tab Berkeley DB log file directory.
-@item @code{--bdb-no-sync} @tab Don't synchronously flush logs.
-@item @code{--bdb-no-recover} @tab Don't start Berkeley DB in recover mode.
-@item @code{--bdb-shared-data} @tab Start Berkeley DB in multi-process mode (Don't use @code{DB_PRIVATE} when initializing Berkeley DB)
-@item @code{--bdb-tmpdir=directory} @tab Berkeley DB tempfile name.
-@item @code{--skip-bdb} @tab Don't use berkeley db.
-@item @code{-O bdb_max_lock=1000} @tab Set the maximum number of locks possible. @xref{SHOW VARIABLES}.
-@end multitable
-
-If you use @code{--skip-bdb}, MySQL will not initialize the
-Berkeley DB library and this will save a lot of memory. Of course,
-you cannot use @code{BDB} tables if you are using this option.
-
-Normally you should start @code{mysqld} without @code{--bdb-no-recover} if you
-intend to use BDB tables. This may, however, give you problems when you
-try to start @code{mysqld} if the BDB log files are corrupted. @xref{Starting
-server}.
-
-With @code{bdb_max_lock} you can specify the maximum number of locks
-(10000 by default) you can have active on a BDB table. You should
-increase this if you get errors of type @code{bdb: Lock table is out of
-available locks} or @code{Got error 12 from ...} when you have do long
-transactions or when @code{mysqld} has to examine a lot of rows to
-calculate the query.
-
-You may also want to change @code{binlog_cache_size} and
-@code{max_binlog_cache_size} if you are using big multi-line transactions.
-@xref{COMMIT}.
-
-
-@node BDB characteristic, BDB TODO, BDB start, BDB
-@subsection Some characteristic of @code{BDB} tables:
-
-@itemize @bullet
-@item
-To be able to rollback transactions BDB maintain log files. For maximum
-performance you should place these on another disk than your databases
-by using the @code{--bdb_log_dir} options.
-@item
-MySQL performs a checkpoint each time a new BDB log
-file is started, and removes any log files that are not needed for
-current transactions. One can also run @code{FLUSH LOGS} at any time
-to checkpoint the Berkeley DB tables.
-
-For disaster recovery, one should use table backups plus
-MySQL's binary log. @xref{Backup}.
-
-@strong{Warning}: If you delete old log files that are in use, BDB will
-not be able to do recovery at all and you may lose data if something
-goes wrong.
-@item
-MySQL requires a @code{PRIMARY KEY} in each BDB table to be
-able to refer to previously read rows. If you don't create one,
-MySQL will create an maintain a hidden @code{PRIMARY KEY} for
-you. The hidden key has a length of 5 bytes and is incremented for each
-insert attempt.
-@item
-If all columns you access in a @code{BDB} table are part of the same index or
-part of the primary key, then MySQL can execute the query
-without having to access the actual row. In a @code{MyISAM} table the
-above holds only if the columns are part of the same index.
-@item
-The @code{PRIMARY KEY} will be faster than any other key, as the
-@code{PRIMARY KEY} is stored together with the row data. As the other keys are
-stored as the key data + the @code{PRIMARY KEY}, it's important to keep the
-@code{PRIMARY KEY} as short as possible to save disk and get better speed.
-@item
-@code{LOCK TABLES} works on @code{BDB} tables as with other tables. If
-you don't use @code{LOCK TABLE}, MYSQL will issue an internal
-multiple-write lock on the table to ensure that the table will be
-properly locked if another thread issues a table lock.
-@item
-Internal locking in @code{BDB} tables is done on page level.
-@item
-@code{SELECT COUNT(*) FROM table_name} is slow as @code{BDB} tables doesn't
-maintain a count of the number of rows in the table.
-@item
-Scanning is slower than with @code{MyISAM} tables as one has data in BDB
-tables stored in B-trees and not in a separate data file.
-@item
-The application must always be prepared to handle cases where
-any change of a @code{BDB} table may make an automatic rollback and any
-read may fail with a deadlock error.
-@item
-Keys are not compressed to previous keys as with ISAM or MyISAM
-tables. In other words, the key information will take a little more
-space in @code{BDB} tables compared to MyISAM tables which don't use
-@code{PACK_KEYS=0}.
-@item
-There is often holes in the BDB table to allow you to insert new rows in
-the middle of the key tree. This makes BDB tables somewhat larger than
-MyISAM tables.
-@item
-The optimizer needs to know an approximation of the number of rows in
-the table. MySQL solves this by counting inserts and
-maintaining this in a separate segment in each BDB table. If you don't
-do a lot of @code{DELETE} or @code{ROLLBACK}:s this number should be
-accurate enough for the MySQL optimizer, but as MySQL
-only store the number on close, it may be wrong if MySQL dies
-unexpectedly. It should not be fatal even if this number is not 100 %
-correct. One can update the number of rows by executing @code{ANALYZE
-TABLE} or @code{OPTIMIZE TABLE}. @xref{ANALYZE TABLE} . @xref{OPTIMIZE
-TABLE}.
-@item
-If you get full disk with a @code{BDB} table, you will get an error
-(probably error 28) and the transaction should roll back. This is in
-contrast with @code{MyISAM} and @code{ISAM} tables where @code{mysqld} will
-wait for enough free disk before continuing.
-@end itemize
-
-
-@node BDB TODO, BDB portability, BDB characteristic, BDB
-@subsection Some things we need to fix for BDB in the near future:
-
-@itemize @bullet
-@item
-It's very slow to open many BDB tables at the same time. If you are
-going to use BDB tables, you should not have a very big table cache (>
-256 ?) and you should use @code{--no-auto-rehash} with the @code{mysql}
-client. We plan to partly fix this in 4.0.
-@item
-@code{SHOW TABLE STATUS} doesn't yet provide that much information for BDB
-tables.
-@item
-Optimize performance.
-@item
-Change to not use page locks at all when we are scanning tables.
-@end itemize
-
-
-@node BDB portability, BDB errors, BDB TODO, BDB
-@subsection Operating systems supported by @strong{BDB}
-
-If you after having built MySQL with support for BDB tables get
-the following error in the log file when you start @code{mysqld}:
-
-@example
-bdb: architecture lacks fast mutexes: applications cannot be threaded
-Can't init dtabases
-@end example
-
-This means that @code{BDB} tables are not supported for your architecture.
-In this case you have to rebuild MySQL without BDB table support.
-
-NOTE: The following list is not complete; We will update this as we get
-more information about this.
-
-Currently we know that BDB tables works with the following operating
-system.
-
-@itemize @bullet
-@item
-Linux 2.x intel
-@item
-Solaris sparc
-@item
-SCO OpenServer
-@item
-SCO UnixWare 7.0.1
-@end itemize
-
-It doesn't work with the following operating systems:
-
-@itemize @bullet
-@item
-Linux 2.x Alpha
-@item
-Max OS X
-@end itemize
-
-
-@node BDB errors, , BDB portability, BDB
-@subsection Errors You May Get When Using BDB Tables
-
-@itemize @bullet
-@item
-If you get the following error in the @code{hostname.err log} when
-starting @code{mysqld}:
-
-@example
-bdb: Ignoring log file: .../log.XXXXXXXXXX: unsupported log version #
-@end example
-it means that the new @code{BDB} version doesn't support the old log
-file format. In this case you have to delete all @code{BDB} log BDB
-from your database directory (the files that has the format
-@code{log.XXXXXXXXXX} ) and restart @code{mysqld}. We would also
-recommend you to do a @code{mysqldump --opt} of your old @code{BDB}
-tables, delete the old table and restore the dump.
-@item
-If you are running in not @code{auto_commit} mode and delete a table you
-are using by another thread you may get the following error messages in
-the MySQL error file:
-
-@example
-001119 23:43:56 bdb: Missing log fileid entry
-001119 23:43:56 bdb: txn_abort: Log undo failed for LSN: 1 3644744: Invalid
-@end example
-This is not fatal but we don't recommend that you delete tables if you are
-not in @code{auto_commit} mode, until this problem is fixed (the fix is
-not trivial).
-@end itemize
+@node InnoDB overview, InnoDB start, InnoDB, InnoDB
+@subsection InnoDB Tables Overview
+@cindex transactions, support
+@cindex transaction-safe tables
+@cindex ACID
+
+InnoDB provides MySQL with a transaction-safe (@code{ACID} compliant)
+table handler with commit, rollback, and crash recovery capabilities.
+InnoDB does locking on row level and also provides an Oracle-style
+consistent
+non-locking read in @code{SELECT}s. These features increase
+multiuser concurrency and performance. There is no need for
+lock escalation in InnoDB,
+because row level locks in InnoDB fit in very small space.
+InnoDB tables support @code{FOREIGN KEY} constraints
+as the first table type in MySQL.
-@node InnoDB, , BDB, Table types
-@section InnoDB Tables
+InnoDB has been designed for maximum performance
+when processing
+large data volumes. Its CPU efficiency is probably not
+matched by any other disk-based relational database engine.
-@menu
-* InnoDB overview:: InnoDB tables overview
-* InnoDB start:: InnoDB startup options
-* InnoDB init:: Creating InnoDB table space.
-* Using InnoDB tables:: Creating InnoDB tables
-* Adding and removing:: Adding and removing InnoDB data and log files
-* Backing up:: Backing up and recovering an InnoDB database
-* Moving:: Moving an InnoDB database to another machine
-* InnoDB transaction model:: InnoDB transaction model.
-* Implementation:: Implementation of multiversioning
-* Table and index:: Table and index structures
-* File space management:: File space management and disk i/o
-* Error handling:: Error handling
-* InnoDB restrictions:: Some restrictions on InnoDB tables
-* InnoDB contact information:: InnoDB contact information.
-@end menu
+Technically, InnoDB is a complete database backend placed under MySQL.
+InnoDB has its own buffer pool for caching data and indexes in main
+memory. InnoDB stores its tables and indexes in a tablespace, which
+may consist of several files. This is different from, for example,
+MyISAM tables where each table is stored as a separate file.
+InnoDB tables can be of any size also on those operating
+systems where file size is limited to 2 GB.
+You can find the latest information about InnoDB at
+@uref{http://www.innodb.com/}. The most up-to-date version of the
+InnoDB manual is always placed there, and you can also order
+commercial licenses and support for InnoDB.
-@node InnoDB overview, InnoDB start, InnoDB, InnoDB
-@subsection InnoDB tables overview
+InnoDB is currently (October 2001) used in production at
+several large database sites requiring high performance.
+The famous Internet news site Slashdot.org runs on
+InnoDB. Mytrix, Inc. stores over 1 TB of data in
+InnoDB, and another site handles an average
+load of 800 inserts/updates per second in InnoDB.
InnoDB tables are included in the MySQL source distribution
-starting from 3.23.34a and are activated in the @strong{MySQL -max}
-binary.
+starting from 3.23.34a and are activated in the MySQL -Max
+binary. For Windows the -Max binaries are contained in the
+standard distribution.
If you have downloaded a binary version of MySQL that includes
-support for InnoDB (mysqld-max), simply follow the instructions for
-installing a binary version of MySQL. @xref{Installing binary}.
+support for InnoDB, simply follow the instructions of the
+MySQL manual
+for installing a binary version of MySQL. If you already have
+MySQL-3.23 installed, then the simplest way to install
+MySQL -Max is to replace the server executable @file{mysqld}
+with the corresponding executable in the -Max distribution.
+MySQL and MySQL -Max differ only in the server executable.
+@xref{Installing binary}.
@xref{mysqld-max, , @code{mysqld-max}}.
-To compile MySQL with InnoDB support, download MySQL-3.23.37 or newer
-and configure MySQL with the @code{--with-innodb} option.
+To compile MySQL with InnoDB support,
+download MySQL-3.23.34a or newer version from
+@uref{http://www.mysql.com/}
+and configure MySQL with the
+@code{--with-innodb} option. See the
+MySQL manual
+about installing a MySQL source distribution.
@xref{Installing source}.
@example
@@ -36264,103 +37180,175 @@ cd /path/to/source/of/mysql-3.23.37
./configure --with-innodb
@end example
-To get InnoDB to work you have to specify where the data for InnoDB
-tables should be stored by specifying the @code{innodb_data_file_path}
-option on the command line or in an MySQL option file. @xref{InnoDB
-start}. If you have configured MySQL for InnoDB but you have not
-specified the above option, @code{mysqld} will print at start:
+To use InnoDB you have to specify InnoDB startup options in
+your @file{my.cnf} or @file{my.ini} file. The minimal way
+to modify it is to add to the @code{[mysqld]} section the line
@example
-Can't initialize InnoDB as 'innodb_data_file_path' is not set
+innodb_data_file_path=ibdata:30M
@end example
-InnoDB provides MySQL with a transaction-safe table handler with
-commit, rollback, and crash recovery capabilities. InnoDB does
-locking on row level, and also provides an Oracle-style consistent
-non-locking read in @code{SELECTS}, which increases transaction
-concurrency. There is not need for lock escalation in InnoDB,
-because row level locks in InnoDB fit in very small space.
-
-InnoDB has been designed for maximum performance when processing
-large data volumes. Its CPU efficiency is probably not
-matched by any other disk-based relational database engine.
-
-You can find the latest information about InnoDB at
-@uref{http://www.innodb.com}. The most up-to-date version of the
-InnoDB manual is always placed there, and you can also order commercial
-support for InnoDB.
-
-Technically, InnoDB is a database backend placed under MySQL. InnoDB
-has its own buffer pool for caching data and indexes in main
-memory. InnoDB stores its tables and indexes in a tablespace, which
-may consist of several files. This is different from, for example,
-@code{MyISAM} tables where each table is stored as a separate file.
+but to get good performance it is best that you specify options
+like recommended below in the section 'InnoDB startup options'.
InnoDB is distributed under the GNU GPL License Version 2 (of June 1991).
In the source distribution of MySQL, InnoDB appears as a subdirectory.
@node InnoDB start, InnoDB init, InnoDB overview, InnoDB
-@subsection InnoDB startup options
+@subsection InnoDB Startup Options
-Beginning from MySQL-3.23.37 the prefix of the options is changed
-from @code{innobase_...} to @code{innodb_...}.
-
-To use InnoDB tables you @strong{MUST} specify configuration parameters
+To use InnoDB tables in MySQL-Max-3.23
+you @strong{MUST} specify configuration parameters
in the MySQL configuration file in the @code{[mysqld]} section of
the configuration file @file{my.cnf}. @xref{Option files}.
-The only required parameter to use InnoDB is @code{innodb_data_file_path},
-but you should set others if you want to get a better performance.
+The only required parameter to use InnoDB in MySQL-Max-3.23
+is @code{innodb_data_file_path}.
+In MySQL-4.0 you do not need to specify even
+@code{innodb_data_file_path}. The default is to create a 64 MB
+data file @file{ibdata1} to the @code{datadir} of MySQL.
+
+But to get good performance you MUST explicitly set the InnoDB parameters
+listed below in examples.
Suppose you have a Windows NT machine with 128 MB RAM and a single 10 GB
-hard disk. Below is an example of possible configuration parameters in
+hard disk. Below is an example of possible configuration parameters in
@file{my.cnf} for InnoDB:
@example
-innodb_data_file_path = ibdata1:2000M;ibdata2:2000M
+[mysqld]
+# You can write your other MySQL server options here
+# ...
+#
innodb_data_home_dir = c:\ibdata
-set-variable = innodb_mirrored_log_groups=1
+# Data files must be able to
+# hold your data and indexes
+innodb_data_file_path = ibdata1:2000M;ibdata2:2000M
+# Set buffer pool size to 50 - 80 %
+# of your computer's memory
+set-variable = innodb_buffer_pool_size=70M
+set-variable = innodb_additional_mem_pool_size=10M
innodb_log_group_home_dir = c:\iblogs
+# .._log_arch_dir must be the same
+# as .._log_group_home_dir
+innodb_log_arch_dir = c:\iblogs
+innodb_log_archive=0
set-variable = innodb_log_files_in_group=3
-set-variable = innodb_log_file_size=30M
+# Set the log file size to about
+# 15 % of the buffer pool size
+set-variable = innodb_log_file_size=10M
set-variable = innodb_log_buffer_size=8M
+# Set ..flush_log_at_trx_commit to
+# 0 if you can afford losing
+# a few last transactions
innodb_flush_log_at_trx_commit=1
-innodb_log_arch_dir = c:\iblogs
-innodb_log_archive=0
-set-variable = innodb_buffer_pool_size=80M
-set-variable = innodb_additional_mem_pool_size=10M
set-variable = innodb_file_io_threads=4
set-variable = innodb_lock_wait_timeout=50
@end example
-Note that data files must be < 4G, and < 2G on
+Note that @strong{InnoDB does not create directories:
+you have to create them yourself.}
+Check also that the MySQL server
+has the @strong{rights to create files in the directories} you specify.
+
+Note that data files must be < 2G in
some file systems! The total size of data files has
-to be >= 10 MB.
-InnoDB does not create directories:
-you have to create them yourself.
+to be >= 10 MB. The combined size of log files MUST be < 4G
+in 32-bit computers.
+
+The default value for @code{innodb_data_home_dir} is the @code{datadir}
+of MySQL. If you do not specify @code{innodb_data_home_dir}, then
+you cannot use absolute paths in @code{innodb_data_file_path}.
+
+When you the first time create an InnoDB database, it
+is best that you start the MySQL server from the command
+prompt. Then InnoDB will print the information about the
+database creation to the screen, and you see what is
+happening. See below in section 3 what the printout
+should look like.
+For example, in Windows you can start @file{mysqld-max.exe} with:
+@example
+your-path-to-mysqld>mysqld-max --standalone --console
+@end example
-Suppose you have a Linux machine with 512 MB RAM and
+@strong{Where to put my.cnf or my.ini in Windows?}
+The rules for Windows are the following:
+
+@itemize @bullet
+@item Only one of @file{my.cnf} or @file{my.ini} should be created.
+@item The @file{my.cnf} file should be placed in the root
+directory of the drive @file{C:}.
+@item The @file{my.ini} file should be placed in the WINDIR directory, e.g,
+@file{C:\WINDOWS} or @file{C:\WINNT}. You can use the @code{SET}
+command of MS-DOS to print the value of WINDIR.
+@item If your PC uses a boot loader where the @file{C:} drive
+is not the boot drive, then your only option is to use the @file{my.ini} file.
+@end itemize
+
+@strong{Where to specify options in Unix?}
+On Unix @file{mysqld} reads options from the following files, if they exist,
+in the following order:
+
+@itemize @bullet
+@item @file{/etc/my.cnf} Global options.
+@item @file{COMPILATION_DATADIR/my.cnf} Server-specific options.
+@item @file{defaults-extra-file} The file specified with
+@code{--defaults-extra-file=...}.
+@item @file{~/.my.cnf} User-specific options.
+@end itemize
+
+@code{COMPILATION_DATADIR} is the MySQL data directory which was
+specified as a @code{./configure} option when @file{mysqld}
+was compiled
+(typically @file{/usr/local/mysql/data} for a
+binary installation or @file{/usr/local/var}
+for a source installation).
+
+If you are not sure from where @file{mysqld} reads its @file{my.cnf}
+or @file{my.ini}, you can give the path as a command-line option:
+@code{--defaults-file=your_path_to_my_cnf}.
+
+Suppose you have a Linux computer with 512 MB RAM and
three 20 GB hard disks (at directory paths @file{/},
@file{/dr2} and @file{/dr3}).
Below is an example of possible configuration parameters in @file{my.cnf} for
InnoDB:
@example
-innodb_data_file_path = ibdata/ibdata1:2000M;dr2/ibdata/ibdata2:2000M
+[mysqld]
+# You can write your other MySQL server options here
+# ...
+#
innodb_data_home_dir = /
-set-variable = innodb_mirrored_log_groups=1
-innodb_log_group_home_dir = /dr3
+# Data files must be able to
+# hold your data and indexes
+innodb_data_file_path = ibdata/ibdata1:2000M;dr2/ibdata/ibdata2:2000M
+# Set buffer pool size to 50 - 80 %
+# of your computer's memory, but
+# make sure on Linux x86 the total
+# memory usage is < 2 GB
+set-variable = innodb_buffer_pool_size=350M
+set-variable = innodb_additional_mem_pool_size=20M
+innodb_log_group_home_dir = /dr3/iblogs
+# .._log_arch_dir must be the same
+# as .._log_group_home_dir
+innodb_log_arch_dir = /dr3/iblogs
+innodb_log_archive=0
set-variable = innodb_log_files_in_group=3
+# Set the log file size to about
+# 15 % of the buffer pool size
set-variable = innodb_log_file_size=50M
set-variable = innodb_log_buffer_size=8M
+# Set ..flush_log_at_trx_commit to
+# 0 if you can afford losing
+# a few last transactions
innodb_flush_log_at_trx_commit=1
-innodb_log_arch_dir = /dr3/iblogs
-innodb_log_archive=0
-set-variable = innodb_buffer_pool_size=400M
-set-variable = innodb_additional_mem_pool_size=20M
set-variable = innodb_file_io_threads=4
set-variable = innodb_lock_wait_timeout=50
+#innodb_flush_method=fdatasync
+#innodb_fast_shutdown=1
+#set-variable = innodb_thread_concurrency=5
@end example
Note that we have placed the two data files on different disks.
@@ -36374,18 +37362,36 @@ improve the performance of the database if all data is not placed
on the same physical disk. Putting log files on a different disk from
data is very often beneficial for performance.
+@strong{Warning:} on Linux x86 you must be careful you
+@strong{do not set memory usage
+too high}. glibc will allow the process heap to grow over thread stacks,
+which will crash your server. Make sure
+@example
+innodb_buffer_pool_size + key_buffer +
+max_connections * (sort_buffer + record_buffer) + max_connections * 1 MB
+@end example
+is significantly smaller than 2 GB. Each thread will use a stack
+(often 1 MB) and in the worst case also
+@code{sort_buffer + record_buff}
+additional memory.
+
The meanings of the configuration parameters are the following:
@multitable @columnfractions .30 .70
+@item @strong{Option} @tab @strong{Description}
@item @code{innodb_data_home_dir} @tab
The common part of the directory path for all InnoDB data files.
+The default for this parameter is the @code{datadir} of MySQL.
@item @code{innodb_data_file_path} @tab
Paths to individual data files and their sizes. The full directory path
to each data file is acquired by concatenating innodb_data_home_dir to
the paths specified here. The file sizes are specified in megabytes,
-hence the 'M' after the size specification above. Do not set a file size
-bigger than 4000M, and on most operating systems not bigger than 2000M.
+hence the 'M' after the size specification above.
InnoDB also understands the abbreviation 'G', 1G meaning 1024M.
+Starting from
+3.23.44 you can set the file size bigger than 4 GB on those
+operating systems which support big files.
+On some operating systems files must be < 2 GB.
The sum of the sizes of the files must be at least 10 MB.
@item @code{innodb_mirrored_log_groups} @tab
Number of identical copies of log groups we
@@ -36397,10 +37403,13 @@ Number of log files in the log group. InnoDB writes to the files in a
circular fashion. Value 3 is recommended here.
@item @code{innodb_log_file_size} @tab
Size of each log file in a log group in megabytes. Sensible values range
-from 1M to the size of the buffer pool specified below. The bigger the
-value, the less checkpoint flush activity is needed in the buffer pool,
+from 1M to 1/nth of the size of the buffer pool specified below,
+where n is the number of log files in the group. The
+bigger the value,
+the less checkpoint flush activity is needed in the buffer pool,
saving disk i/o. But bigger log files also mean that recovery will be
-slower in case of a crash. File size restriction as for a data file.
+slower in case of a crash. The combined size of log files must
+be < 4 GB on 32-bit computers.
@item @code{innodb_log_buffer_size} @tab
The size of the buffer which InnoDB uses to write log to the log files
on disk. Sensible values range from 1M to half the combined size of log
@@ -36425,7 +37434,7 @@ archive InnoDB log files.
The size of the memory buffer InnoDB uses to cache data and indexes of
its tables. The bigger you set this the less disk i/o is needed to
access data in tables. On a dedicated database server you may set this
-parameter up to 90 % of the machine physical memory size. Do not set it
+parameter up to 80 % of the machine physical memory size. Do not set it
too large, though, because competition of the physical memory may cause
paging in the operating system.
@item @code{innodb_additional_mem_pool_size} @tab
@@ -36437,7 +37446,7 @@ will start to allocate memory from the operating system, and write
warning messages to the MySQL error log.
@item @code{innodb_file_io_threads} @tab
Number of file i/o threads in InnoDB. Normally, this should be 4, but
-on Windows NT disk i/o may benefit from a larger number.
+on Windows disk i/o may benefit from a larger number.
@item @code{innodb_lock_wait_timeout} @tab
Timeout in seconds an InnoDB transaction may wait for a lock before
being rolled back. InnoDB automatically detects transaction deadlocks
@@ -36454,7 +37463,7 @@ Another option is @code{O_DSYNC}.
@node InnoDB init, Using InnoDB tables, InnoDB start, InnoDB
-@subsection Creating InnoDB table space
+@subsection Creating InnoDB Tablespace
Suppose you have installed MySQL and have edited @file{my.cnf} so that
it contains the necessary InnoDB configuration parameters.
@@ -36520,7 +37529,23 @@ mysqld: ready for connections
@node Error creating InnoDB, , InnoDB init, InnoDB init
-@subsubsection If something goes wrong in database creation
+@subsubsection If Something Goes Wrong in Database Creation
+
+If InnoDB prints an operating system error in a file operation,
+usually the problem is one of the following:
+
+@itemize @bullet
+@item You did not create InnoDB data or log directories.
+@item @file{mysqld} does not have the rights to create files in those
+directories.
+@item @file{mysqld} does not read the right @file{my.cnf} or @file{my.ini}
+file, and consequently does not see the options you specified.
+@item The disk is full or a disk quota is exceeded.
+@item You have created a subdirectory whose name is equal to a data file
+you specified.
+@item There is a syntax error in @code{innodb_data_home_dir}
+or @code{innodb_data_file_path}.
+@end itemize
If something goes wrong in an InnoDB database creation, you should
delete all files created by InnoDB. This means all data files, all log
@@ -36531,7 +37556,7 @@ directories. Then you can try the InnoDB database creation again.
@node Using InnoDB tables, Adding and removing, InnoDB init, InnoDB
-@subsection Creating InnoDB tables
+@subsection Creating InnoDB Tables
Suppose you have started the MySQL client with the command
@code{mysql test}.
@@ -36562,20 +37587,12 @@ SHOW TABLE STATUS FROM test LIKE 'CUSTOMER'
@end example
Note that the statistics @code{SHOW} gives about InnoDB tables
-are only approximate: they are used in SQL optimization. Table and
+are only approximate: they are used in SQL optimisation. Table and
index reserved sizes in bytes are accurate, though.
-NOTE: @code{DROP DATABASE} does not currently work for InnoDB tables!
-You must drop the tables individually. Also take care not to delete or
-add @file{.frm} files to your InnoDB database manually: use
-@code{CREATE TABLE} and @code{DROP TABLE} commands.
-InnoDB has its own internal data dictionary, and you will get problems
-if the MySQL @file{.frm} files are out of 'sync' with the InnoDB
-internal data dictionary.
+@subsubsection Converting MyISAM Tables to InnoDB
-@subsubsection Converting MyISAM tables to InnoDB
-
-InnoDB does not have a special optimization for separate index creation.
+InnoDB does not have a special optimisation for separate index creation.
Therefore it does not pay to export and import the table and create indexes
afterwards.
The fastest way to alter a table to InnoDB is to do the inserts
@@ -36613,9 +37630,63 @@ it is better that you kill the database process and delete all InnoDB data
and log files and all InnoDB table @file{.frm} files, and start
your job again, rather than wait for millions of disk i/os to complete.
+@subsubsection Foreign Key Constraints
+
+InnoDB version 3.23.44 features foreign key constraints. InnoDB is the
+first MySQL table type which allows you to define foreign key
+constraints to guard the integrity of your data.
+
+The syntax of a foreign key constraint definition in InnoDB:
+@example
+FOREIGN KEY (index_col_name, ...) REFERENCES table_name (index_col_name, ...)
+@end example
+
+An example:
+
+@example
+CREATE TABLE parent(id INT NOT NULL, PRIMARY KEY (id)) TYPE=INNODB;
+CREATE TABLE child(id INT, parent_id INT, INDEX par_ind (parent_id),
+ FOREIGN KEY (parent_id) REFERENCES parent(id)) TYPE=INNODB;
+@end example
+
+Both tables have to be InnoDB type and there must be an index
+where the foreign key and the referenced key are listed as the first
+columns. Any @code{ALTER TABLE} currently removes all foreign key
+constrainst defined for the table, but not the constraints
+that reference the table. Corresponding columns in the foreign key
+and the referenced key have to have similar internal data types
+inside InnoDB so that they can be compared without a type
+conversion. The length of string types need not be the same.
+The size and the signedness of integer types has to be same.
+
+When doing foreign key checks InnoDB sets shared row
+level locks on child or parent records it has to look at.
+InnoDB checks foreign key constraints immediately: the check
+is not deferred to transaction commit.
+
+InnoDB allows you to drop any table even though that
+would break the foreign key constraints which reference
+the table. When you drop a table the constraints which
+were defined in its create statement are also dropped.
+
+If you recreate a table which was dropped, it has to have
+a definition which conforms to the foreign key constraints
+referencing it. It must have the right column names and types,
+and it must have indexes on the referenced keys, as stated above.
+
+You can list the foreign key constraints for a table
+@code{T} with
+@example
+SHOW TABLE STATUS FROM yourdatabasename LIKE 'T';
+@end example
+The foreign key constraints are listed in the table comment of
+the output.
+
+InnoDB does not yet support @code{CASCADE ON DELETE}
+or other special options on the constraints.
@node Adding and removing, Backing up, Using InnoDB tables, InnoDB
-@subsection Adding and removing InnoDB data and log files
+@subsection Adding and Removing InnoDB Data and Log Files
You cannot increase the size of an InnoDB data file. To add more into
your tablespace you have to add a new data file. To do this you have to
@@ -36624,7 +37695,7 @@ new file to @code{innodb_data_file_path}, and then start MySQL
again.
Currently you cannot remove a data file from InnoDB. To decrease the
-size of your database you have to use @code{mysqldump} to dump
+size of your database you have to use @file{mysqldump} to dump
all your tables, create a new database, and import your tables to the
new database.
@@ -36638,7 +37709,7 @@ you at the startup that it is creating new log files.
@node Backing up, Moving, Adding and removing, InnoDB
-@subsection Backing up and recovering an InnoDB database
+@subsection Backing up and Recovering an InnoDB Database
The key to safe database management is taking regular backups.
To take a 'binary' backup of your database you have to do the following:
@@ -36757,7 +37828,7 @@ because there will be more log to apply to the database.
@node Moving, InnoDB transaction model, Backing up, InnoDB
-@subsection Moving an InnoDB database to another machine
+@subsection Moving an InnoDB Database to Another Machine
InnoDB data and log files are binary-compatible on all platforms
if the floating point number format on the machines is the same.
@@ -36778,10 +37849,10 @@ a table.
@node InnoDB transaction model, Implementation, Moving, InnoDB
-@subsection InnoDB transaction model
+@subsection InnoDB Transaction Model
In the InnoDB transaction model the goal has been to combine the best
-sides of a multiversioning database to traditional two-phase locking.
+properties of a multiversioning database to traditional two-phase locking.
InnoDB does locking on row level and runs queries by default
as non-locking consistent reads, in the style of Oracle.
The lock table in InnoDB is stored so space-efficiently that lock
@@ -36790,7 +37861,7 @@ to lock every row in the database, or any random subset of the rows,
without InnoDB running out of memory.
In InnoDB all user activity happens inside transactions. If the
-auto commit mode is used in MySQL, then each SQL statement
+auto-commit mode is used in MySQL, then each SQL statement
will form a single transaction. If the auto commit mode is
switched off, then we can think that a user always has a transaction
open. If he issues
@@ -36804,17 +37875,17 @@ on the other hand cancels all modifications made by the current
transaction.
@menu
-* InnoDB consistent read:: Consistent read
-* InnoDB locking reads:: Locking reads
-* InnoDB Next-key locking:: Next-key locking: avoiding the phantom problem
-* InnoDB Locks set:: Locks set by different SQL statements in InnoDB
-* InnoDB Deadlock detection:: Deadlock detection and rollback
-* InnoDB Consistent read example:: An example of how the consistent read works in InnoDB
+* InnoDB consistent read:: Consistent Read
+* InnoDB locking reads:: Locking Reads
+* InnoDB Next-key locking:: Next-key Locking: Avoiding the Phantom Problem
+* InnoDB Locks set:: Locks Set by Different SQL Statements in InnoDB
+* InnoDB Deadlock detection:: Deadlock Detection and Rollback
+* InnoDB Consistent read example:: An Example of How the Consistent Read Works in InnoDB
@end menu
@node InnoDB consistent read, InnoDB locking reads, InnoDB transaction model, InnoDB transaction model
-@subsubsection Consistent read
+@subsubsection Consistent Read
A consistent read means that InnoDB uses its multiversioning to
present to a query a snapshot of the database at a point in time.
@@ -36840,7 +37911,7 @@ on the table.
@node InnoDB locking reads, InnoDB Next-key locking, InnoDB consistent read, InnoDB transaction model
-@subsubsection Locking reads
+@subsubsection Locking Reads
A consistent read is not convenient in some circumstances.
Suppose you want to add a new row into your table @code{CHILD},
@@ -36898,7 +37969,7 @@ on the rows.
@node InnoDB Next-key locking, InnoDB Locks set, InnoDB locking reads, InnoDB transaction model
-@subsubsection Next-key locking: avoiding the phantom problem
+@subsubsection Next-key Locking: Avoiding the Phantom Problem
In row level locking InnoDB uses an algorithm called next-key locking.
InnoDB does the row level locking so that when it searches or
@@ -36942,7 +38013,7 @@ after the last record in the index. Just that happens in the previous
example: the locks set by InnoDB will prevent any insert to
the table where @code{ID} would be bigger than 100.
-You can use the next-key locking to implement a uniqueness
+You can use next-key locking to implement a uniqueness
check in your application: if you read your data in share mode
and do not see a duplicate for a row you are going to insert,
then you can safely insert your row and know that the next-key
@@ -36951,9 +38022,8 @@ anyone meanwhile inserting a duplicate for your row. Thus the next-key
locking allows you to 'lock' the non-existence of something in your
table.
-
@node InnoDB Locks set, InnoDB Deadlock detection, InnoDB Next-key locking, InnoDB transaction model
-@subsubsection Locks set by different SQL statements in InnoDB
+@subsubsection Locks Set by Different SQL Statements in InnoDB
@itemize @bullet
@item
@@ -36994,6 +38064,12 @@ lock on every record the search encounters.
@code{DELETE FROM ... WHERE ...} : sets an exclusive next-key
lock on every record the search encounters.
@item
+If a @code{FOREIGN KEY} constraint is defined on a table,
+any insert, update, or delete which requires checking of the constraint
+condition sets shared record level locks on the records it
+looks at to check the constraint. Also in the case where the
+constraint fails, InnoDB sets these locks.
+@item
@code{LOCK TABLES ... } : sets table locks. In the implementation
the MySQL layer of code sets these locks. The automatic deadlock detection
of InnoDB cannot detect deadlocks where such table locks are involved:
@@ -37006,7 +38082,7 @@ locks. But that does not put transaction integerity into danger.
@node InnoDB Deadlock detection, InnoDB Consistent read example, InnoDB Locks set, InnoDB transaction model
-@subsubsection Deadlock detection and rollback
+@subsubsection Deadlock Detection and Rollback
InnoDB automatically detects a deadlock of transactions and rolls
back the transaction whose lock request was the last one to build
@@ -37025,7 +38101,7 @@ stores row locks in a format where it cannot afterwards know which was
set by which SQL statement.
@node InnoDB Consistent read example, , InnoDB Deadlock detection, InnoDB transaction model
-@subsubsection An example of how the consistent read works in InnoDB
+@subsubsection An Example of How the Consistent Read Works in InnoDB
When you issue a consistent read, that is, an ordinary @code{SELECT}
statement, InnoDB will give your transaction a timepoint according
@@ -37057,9 +38133,9 @@ v SELECT * FROM t;
COMMIT;
SELECT * FROM t;
- ----------------------
- | 1 | 2 |
- ----------------------
+ ---------------------
+ | 1 | 2 |
+ ---------------------
@end example
Thus user A sees the row inserted by B only when B has committed the
@@ -37074,7 +38150,7 @@ SELECT * FROM t LOCK IN SHARE MODE;
@end example
-@subsection Performance tuning tips
+@subsection Performance Tuning Tips
@strong{1.}
If the Unix @file{top} or the Windows @file{Task Manager} shows that
@@ -37147,9 +38223,8 @@ InnoDB database.
@strong{9.}
Beware also of other big disk-bound operations.
-Use @code{DROP TABLE}
-or @code{TRUNCATE} (from MySQL-4.0 up) to empty a table, not
-@code{DELETE FROM yourtable}.
+Use @code{DROP TABLE} or @code{TRUNCATE} (from MySQL-4.0 up) to empty a
+table, not @code{DELETE FROM yourtable}.
@strong{10.}
Use the multi-line @code{INSERT} to reduce
@@ -37167,15 +38242,24 @@ This tip is of course valid for inserts into any table type, not just InnoDB.
Starting from version 3.23.41 InnoDB includes the InnoDB
Monitor which prints information on the InnoDB internal state.
When swithed on, InnoDB Monitor
-will make the MySQL server to print data to the standard
-output about once every 10 seconds. This data is useful in
+will make the MySQL server @file{mysqld} to print data
+(note: the MySQL client will not print anything)
+to the standard
+output about once every 15 seconds. This data is useful in
performance tuning.
+On Windows you must start @code{mysqld-max}
+from a MS-DOS prompt
+with the @code{--standalone --console}
+options to direct the output to the MS-DOS prompt
+window.
+
+There is a separate @code{innodb_lock_monitor} which
+prints the same information as @code{innodb_monitor}
+plus information on locks set by each transaction.
The printed information includes data on:
@itemize @bullet
@item
-table and record locks held by each active transaction,
-@item
lock waits of a transactions,
@item
semaphore waits of threads,
@@ -37288,8 +38372,8 @@ may have lock contention. The output can also help to
trace reasons for transaction deadlocks.
@item
Section SYNC INFO will report reserved semaphores
-if you compile InnoDB with <code>UNIV_SYNC_DEBUG</code>
-defined in <tt>univ.i</tt>.
+if you compile InnoDB with @code{UNIV_SYNC_DEBUG}
+defined in @file{univ.i}.
@item
Section SYNC ARRAY INFO reports threads waiting
for a semaphore and statistics on how many times
@@ -37311,7 +38395,7 @@ currently doing.
@end itemize
@node Implementation, Table and index, InnoDB transaction model, InnoDB
-@subsection Implementation of multiversioning
+@subsection Implementation of Multiversioning
Since InnoDB is a multiversioned database, it must keep information
of old versions of rows in the tablespace. This information is stored
@@ -37342,7 +38426,9 @@ a snapshot that in a consistent read could need the information
in the update undo log to build an earlier version of a database
row.
-You must remember to commit your transactions regularly. Otherwise
+You must remember to commit your transactions regularly,
+also those transactions which only issue consistent reads.
+Otherwise
InnoDB cannot discard data from the update undo logs, and the
rollback segment may grow too big, filling up your tablespace.
@@ -37361,7 +38447,19 @@ time as the SQL statement which did the deletion.
@node Table and index, File space management, Implementation, InnoDB
-@subsection Table and index structures
+@subsection Table and Index Structures
+
+MySQL stores its data dictionary information of tables
+in @file{.frm}
+files in database directories. But every InnoDB type table
+also has its own entry in InnoDB internal data dictionaries
+inside the tablespace. When MySQL drops a table or a database,
+it has to delete both a @file{.frm} file or files, and
+the corresponding entries inside the InnoDB data dictionary.
+This is the reason why you cannot move InnoDB tables between
+databases simply by moving the @file{.frm} files, and why
+@code{DROP DATABASE} did not work for InnoDB type tables
+in MySQL versions <= 3.23.43.
Every InnoDB table has a special index called the clustered index
where the data of the rows is stored. If you define a
@@ -37389,15 +38487,15 @@ index. Note that if the primary key is long, the secondary indexes
will use more space.
@menu
-* InnoDB physical structure:: Physical structure of an index
-* InnoDB Insert buffering:: Insert buffering
-* InnoDB Adaptive hash:: Adaptive hash indexes
-* InnoDB Physical record:: Physical record structure
+* InnoDB physical structure:: Physical Structure of an Index
+* InnoDB Insert buffering:: Insert Buffering
+* InnoDB Adaptive hash:: Adaptive Hash Indexes
+* InnoDB Physical record:: Physical Record Structure
@end menu
@node InnoDB physical structure, InnoDB Insert buffering, Table and index, Table and index
-@subsubsection Physical structure of an index
+@subsubsection Physical Structure of an Index
All indexes in InnoDB are B-trees where the index records are
stored in the leaf pages of the tree. The default size of an index
@@ -37413,7 +38511,7 @@ InnoDB will try to contract the index tree to free the page.
@node InnoDB Insert buffering, InnoDB Adaptive hash, InnoDB physical structure, Table and index
-@subsubsection Insert buffering
+@subsubsection Insert Buffering
It is a common situation in a database application that the
primary key is a unique identifier and new rows are inserted in the
@@ -37441,7 +38539,7 @@ to a table up to 15 times.
@node InnoDB Adaptive hash, InnoDB Physical record, InnoDB Insert buffering, Table and index
-@subsubsection Adaptive hash indexes
+@subsubsection Adaptive Hash Indexes
If a database fits almost entirely in main memory, then the fastest way
to perform queries on it is to use hash indexes. InnoDB has an
@@ -37465,7 +38563,7 @@ databases.
@node InnoDB Physical record, , InnoDB Adaptive hash, Table and index
-@subsubsection Physical record structure
+@subsubsection Physical Record Structure
@itemize @bullet
@item
@@ -37488,7 +38586,7 @@ If the total length of the fields in a record is < 128 bytes, then
the pointer is 1 byte, else 2 bytes.
@end itemize
-@subsubsection How an auto-increment column works in InnoDB
+@subsubsection How an Auto-increment Column Works in InnoDB
After a database startup, when a user first does an insert to a
table @code{T}
@@ -37523,12 +38621,12 @@ integer that can be stored in the specified integer type.
@node File space management, Error handling, Table and index, InnoDB
-@subsection File space management and disk i/o
+@subsection File Space Management and Disk i/o
@menu
* InnoDB Disk i/o:: Disk i/o
-* InnoDB File space:: File space management
-* InnoDB File Defragmenting:: Defragmenting a table
+* InnoDB File space:: File Space Management
+* InnoDB File Defragmenting:: Defragmenting a Table
@end menu
@@ -37571,18 +38669,18 @@ file size in @code{innodb_data_file_path}. The partition must be
1000 000 bytes.
@example
-innodb_data_file_path=hdd1:3Gnewraw;hdd2:2Gnewraw
+innodb_data_file_path=hdd1:5Gnewraw;hdd2:2Gnewraw
@end example
-When you start the database again you MUST change the keyword
+When you start the database again you @strong{must} change the keyword
to @code{raw}. Otherwise InnoDB will write over your
partition!
@example
-innodb_data_file_path=hdd1:3Graw;hdd2:2Graw
+innodb_data_file_path=hdd1:5Graw;hdd2:2Graw
@end example
-Using a raw disk you can on some Unixes perform non-buffered i/o.
+By using a raw disk you can on some Unixes perform unbuffered i/o.
There are two read-ahead heuristics in InnoDB: sequential read-ahead
and random read-ahead. In sequential read-ahead InnoDB notices that
@@ -37595,7 +38693,7 @@ reads to the i/o system.
@node InnoDB File space, InnoDB File Defragmenting, InnoDB Disk i/o, File space management
-@subsubsection File space management
+@subsubsection File Space Management
The data files you define in the configuration file form the tablespace
of InnoDB. The files are simply catenated to form the tablespace,
@@ -37643,7 +38741,7 @@ consistent read.
@node InnoDB File Defragmenting, , InnoDB File space, File space management
-@subsubsection Defragmenting a table
+@subsubsection Defragmenting a Table
If there are random insertions or deletions
in the indexes of a table, the indexes
@@ -37667,13 +38765,13 @@ not occur.
@node Error handling, InnoDB restrictions, File space management, InnoDB
-@subsection Error handling
+@subsection Error Handling
The error handling in InnoDB is not always the same as
specified in the ANSI SQL standards. According to the ANSI
standard, any error during an SQL statement should cause the
rollback of that statement. InnoDB sometimes rolls back only
-part of the statement.
+part of the statement, or the whole transaction.
The following list specifies the error handling of InnoDB.
@itemize @bullet
@@ -37682,9 +38780,9 @@ If you run out of file space in the tablespace,
you will get the MySQL @code{'Table is full'} error
and InnoDB rolls back the SQL statement.
@item
-A transaction deadlock or a timeout in a lock wait will give
-@code{'Table handler error 1000000'} and InnoDB rolls back
-the SQL statement.
+A transaction deadlock or a timeout in a lock wait make InnoDB
+to roll back
+the whole transaction.
@item
A duplicate key error only rolls back the insert of that particular row,
even in a statement like @code{INSERT INTO ... SELECT ...}.
@@ -37700,13 +38798,20 @@ they roll back the corresponding SQL statement.
@node InnoDB restrictions, InnoDB contact information, Error handling, InnoDB
-@subsection Some restrictions on InnoDB tables
+@subsection Restrictions on InnoDB Tables
@itemize @bullet
-@item @code{SHOW TABLE STATUS} does not give accurate statistics
+@item
+@strong{WARNING:} Do @strong{NOT} convert MySQL system tables from
+MyISAM TO InnoDB tables! This is not supported; If you do this MySQL
+will not restart until you restore the old system tables from a backup
+or re-generate them with the mysql_install_db script.
+
+@item
+@code{SHOW TABLE STATUS} does not give accurate statistics
on InnoDB tables, except for the physical size reserved by the table.
-The row count is only a rough estimate used in SQL optimization.
+The row count is only a rough estimate used in SQL optimisation.
@item
If you try to create an unique index on a prefix of a column you will get an
@@ -37716,7 +38821,7 @@ error:
CREATE TABLE T (A CHAR(20), B INT, UNIQUE (A(5))) TYPE = InnoDB;
@end example
-If you create a non unique index on a prefix of a column, InnoDB will
+If you create a non-unique index on a prefix of a column, InnoDB will
create an index over the whole column.
@item
@code{INSERT DELAYED} is not supported for InnoDB tables.
@@ -37740,23 +38845,19 @@ A table cannot contain more than 1000 columns.
deletes all rows, one by one, which is not that fast. In future versions
of MySQL you can use @code{TRUNCATE} which is fast.
@item
-Before dropping a database with InnoDB tables one has to drop
-the individual InnoDB tables first.
-@item
The default database page size in InnoDB is 16 kB. By recompiling the
code one can set it from 8 kB to 64 kB.
The maximun row length is slightly less than half of a database page
in versions <= 3.23.40 of InnoDB. Starting from source
release 3.23.41 BLOB and
TEXT columns are allowed to be < 4 GB, the total row length must also be
-< 4 GB. InnoDB does not store fields whose size is <= 30 bytes on separate
+< 4 GB. InnoDB does not store fields whose size is <= 128 bytes on separate
pages. After InnoDB has modified the row by storing long fields on
-separate pages, the remaining length of the row must be slightly less
-than half a database page.
+separate pages, the remaining length of the row must be less
+than half a database page. The maximun key length is 7000 bytes.
@item
-The maximum data or log file size is 2 GB or 4 GB depending on how large
-files your operating system supports. Support for > 4 GB files will
-be added to InnoDB in a future version.
+On some operating systems data files must be < 2 GB. The combined
+size of log files must be < 4 GB on 32-bit computers.
@item
The maximum tablespace size is 4 billion database pages. This is also
the maximum size for a table. The minimum tablespace size is 10 MB.
@@ -37764,15 +38865,15 @@ the maximum size for a table. The minimum tablespace size is 10 MB.
@node InnoDB contact information, , InnoDB restrictions, InnoDB
-@subsection InnoDB contact information
+@subsection InnoDB Contact Information
Contact information of Innobase Oy, producer of the InnoDB engine.
-Website: @uref{http://www.innodb.com}. Email:
-@email{Heikki.Tuuri@@innodb.com}
+Web site: @uref{http://www.innodb.com/}.
+Email: @email{Heikki.Tuuri@@innodb.com}
@example
phone: 358-9-6969 3250 (office) 358-40-5617367 (mobile)
-InnoDB Oy Inc.
+Innobase Oy Inc.
World Trade Center Helsinki
Aleksanterinkatu 17
P.O.Box 800
@@ -37781,6 +38882,322 @@ Finland
@end example
+@node BDB, , InnoDB, Table types
+@section BDB or Berkeley_DB Tables
+
+@cindex tables, @code{BDB}
+@cindex tables, @code{Berkeley DB}
+
+@menu
+* BDB overview:: Overview of BDB Tables
+* BDB install:: Installing BDB
+* BDB start:: BDB startup options
+* BDB characteristics:: Characteristics of @code{BDB} tables:
+* BDB TODO:: Things we need to fix for BDB in the near future:
+* BDB portability:: Operating systems supported by @strong{BDB}
+* BDB restrictions:: Restrictions on BDB Tables
+* BDB errors:: Errors That May Occur When Using BDB Tables
+@end menu
+
+@node BDB overview, BDB install, BDB, BDB
+@subsection Overview of BDB Tables
+
+Support for BDB tables is included in the MySQL source distribution
+starting from Version 3.23.34 and is activated in the MySQL-Max
+binary.
+
+BerkeleyDB, available at @uref{http://www.sleepycat.com/} has provided
+MySQL with a transactional table handler. By using BerkeleyDB
+tables, your tables may have a greater chance of surviving crashes, and also
+provides @code{COMMIT} and @code{ROLLBACK} on transactions. The
+MySQL source distribution comes with a BDB distribution that has a
+couple of small patches to make it work more smoothly with MySQL.
+You can't use a non-patched @code{BDB} version with MySQL.
+
+We at MySQL AB are working in close cooperation with Sleepycat to
+keep the quality of the MySQL/BDB interface high.
+
+When it comes to supporting BDB tables, we are committed to help our
+users to locate the problem and help creating a reproducable test case
+for any problems involving BDB tables. Any such test case will be
+forwarded to Sleepycat who in turn will help us find and fix the
+problem. As this is a two stage operation, any problems with BDB tables
+may take a little longer for us to fix than for other table handlers.
+However, as the BerkeleyDB code itself has been used by many other
+applications than MySQL, we don't envision any big problems with
+this. @xref{Support}.
+
+
+@node BDB install, BDB start, BDB overview, BDB
+@subsection Installing BDB
+
+If you have downloaded a binary version of MySQL that includes
+support for BerkeleyDB, simply follow the instructions for installing a
+binary version of MySQL.
+@xref{Installing binary}. @xref{mysqld-max, , @code{mysqld-max}}.
+
+To compile MySQL with Berkeley DB support, download MySQL
+Version 3.23.34 or newer and configure @code{MySQL} with the
+@code{--with-berkeley-db} option. @xref{Installing source}.
+
+@example
+cd /path/to/source/of/mysql-3.23.34
+./configure --with-berkeley-db
+@end example
+
+Please refer to the manual provided with the @code{BDB} distribution for
+more updated information.
+
+Even though Berkeley DB is in itself very tested and reliable,
+the MySQL interface is still considered beta quality.
+We are actively improving and optimising it to get it stable very
+soon.
+
+
+@node BDB start, BDB characteristics, BDB install, BDB
+@subsection BDB startup options
+
+If you are running with @code{AUTOCOMMIT=0} then your changes in @code{BDB}
+tables will not be updated until you execute @code{COMMIT}. Instead of commit
+you can execute @code{ROLLBACK} to forget your changes. @xref{COMMIT}.
+
+If you are running with @code{AUTOCOMMIT=1} (the default), your changes
+will be committed immediately. You can start an extended transaction with
+the @code{BEGIN WORK} SQL command, after which your changes will not be
+committed until you execute @code{COMMIT} (or decide to @code{ROLLBACK}
+the changes).
+
+The following options to @code{mysqld} can be used to change the behavior of
+BDB tables:
+
+@multitable @columnfractions .30 .70
+@item @strong{Option} @tab @strong{Description}
+@item @code{--bdb-home=directory} @tab Base directory for BDB tables. This should be the same directory you use for --datadir.
+@item @code{--bdb-lock-detect=#} @tab Berkeley lock detect. One of (DEFAULT, OLDEST, RANDOM, or YOUNGEST).
+@item @code{--bdb-logdir=directory} @tab Berkeley DB log file directory.
+@item @code{--bdb-no-sync} @tab Don't synchronously flush logs.
+@item @code{--bdb-no-recover} @tab Don't start Berkeley DB in recover mode.
+@item @code{--bdb-shared-data} @tab Start Berkeley DB in multi-process mode (Don't use @code{DB_PRIVATE} when initialising Berkeley DB)
+@item @code{--bdb-tmpdir=directory} @tab Berkeley DB tempfile name.
+@item @code{--skip-bdb} @tab Don't use berkeley db.
+@item @code{-O bdb_max_lock=1000} @tab Set the maximum number of locks possible. @xref{SHOW VARIABLES}.
+@end multitable
+
+If you use @code{--skip-bdb}, MySQL will not initialise the
+Berkeley DB library and this will save a lot of memory. Of course,
+you cannot use @code{BDB} tables if you are using this option.
+
+Normally you should start @code{mysqld} without @code{--bdb-no-recover} if you
+intend to use BDB tables. This may, however, give you problems when you
+try to start @code{mysqld} if the BDB log files are corrupted. @xref{Starting
+server}.
+
+With @code{bdb_max_lock} you can specify the maximum number of locks
+(10000 by default) you can have active on a BDB table. You should
+increase this if you get errors of type @code{bdb: Lock table is out of
+available locks} or @code{Got error 12 from ...} when you have do long
+transactions or when @code{mysqld} has to examine a lot of rows to
+calculate the query.
+
+You may also want to change @code{binlog_cache_size} and
+@code{max_binlog_cache_size} if you are using big multi-line transactions.
+@xref{COMMIT}.
+
+
+@node BDB characteristics, BDB TODO, BDB start, BDB
+@subsection Characteristics of @code{BDB} tables:
+
+@itemize @bullet
+@item
+To be able to rollback transactions BDB maintain log files. For maximum
+performance you should place these on another disk than your databases
+by using the @code{--bdb_log_dir} options.
+@item
+MySQL performs a checkpoint each time a new BDB log
+file is started, and removes any log files that are not needed for
+current transactions. One can also run @code{FLUSH LOGS} at any time
+to checkpoint the Berkeley DB tables.
+
+For disaster recovery, one should use table backups plus
+MySQL's binary log. @xref{Backup}.
+
+@strong{Warning}: If you delete old log files that are in use, BDB will
+not be able to do recovery at all and you may lose data if something
+goes wrong.
+@item
+MySQL requires a @code{PRIMARY KEY} in each BDB table to be
+able to refer to previously read rows. If you don't create one,
+MySQL will create an maintain a hidden @code{PRIMARY KEY} for
+you. The hidden key has a length of 5 bytes and is incremented for each
+insert attempt.
+@item
+If all columns you access in a @code{BDB} table are part of the same index or
+part of the primary key, then MySQL can execute the query
+without having to access the actual row. In a @code{MyISAM} table the
+above holds only if the columns are part of the same index.
+@item
+The @code{PRIMARY KEY} will be faster than any other key, as the
+@code{PRIMARY KEY} is stored together with the row data. As the other keys are
+stored as the key data + the @code{PRIMARY KEY}, it's important to keep the
+@code{PRIMARY KEY} as short as possible to save disk and get better speed.
+@item
+@code{LOCK TABLES} works on @code{BDB} tables as with other tables. If
+you don't use @code{LOCK TABLE}, MySQL will issue an internal
+multiple-write lock on the table to ensure that the table will be
+properly locked if another thread issues a table lock.
+@item
+Internal locking in @code{BDB} tables is done on page level.
+@item
+@code{SELECT COUNT(*) FROM table_name} is slow as @code{BDB} tables doesn't
+maintain a count of the number of rows in the table.
+@item
+Scanning is slower than with @code{MyISAM} tables as one has data in BDB
+tables stored in B-trees and not in a separate data file.
+@item
+The application must always be prepared to handle cases where
+any change of a @code{BDB} table may make an automatic rollback and any
+read may fail with a deadlock error.
+@item
+Keys are not compressed to previous keys as with ISAM or MyISAM
+tables. In other words, the key information will take a little more
+space in @code{BDB} tables compared to MyISAM tables which don't use
+@code{PACK_KEYS=0}.
+@item
+There is often holes in the BDB table to allow you to insert new rows in
+the middle of the key tree. This makes BDB tables somewhat larger than
+MyISAM tables.
+@item
+The optimiser needs to know an approximation of the number of rows in
+the table. MySQL solves this by counting inserts and
+maintaining this in a separate segment in each BDB table. If you don't
+do a lot of @code{DELETE} or @code{ROLLBACK}:s this number should be
+accurate enough for the MySQL optimiser, but as MySQL
+only store the number on close, it may be wrong if MySQL dies
+unexpectedly. It should not be fatal even if this number is not 100 %
+correct. One can update the number of rows by executing @code{ANALYZE
+TABLE} or @code{OPTIMIZE TABLE}. @xref{ANALYZE TABLE} . @xref{OPTIMIZE
+TABLE}.
+@item
+If you get full disk with a @code{BDB} table, you will get an error
+(probably error 28) and the transaction should roll back. This is in
+contrast with @code{MyISAM} and @code{ISAM} tables where @code{mysqld} will
+wait for enough free disk before continuing.
+@end itemize
+
+
+@node BDB TODO, BDB portability, BDB characteristics, BDB
+@subsection Things we need to fix for BDB in the near future:
+
+@itemize @bullet
+@item
+It's very slow to open many BDB tables at the same time. If you are
+going to use BDB tables, you should not have a very big table cache (>
+256 ?) and you should use @code{--no-auto-rehash} with the @code{mysql}
+client. We plan to partly fix this in 4.0.
+@item
+@code{SHOW TABLE STATUS} doesn't yet provide that much information for BDB
+tables.
+@item
+Optimise performance.
+@item
+Change to not use page locks at all when we are scanning tables.
+@end itemize
+
+
+@node BDB portability, BDB restrictions, BDB TODO, BDB
+@subsection Operating systems supported by @strong{BDB}
+
+If you after having built MySQL with support for BDB tables get
+the following error in the log file when you start @code{mysqld}:
+
+@example
+bdb: architecture lacks fast mutexes: applications cannot be threaded
+Can't init dtabases
+@end example
+
+This means that @code{BDB} tables are not supported for your architecture.
+In this case you have to rebuild MySQL without BDB table support.
+
+NOTE: The following list is not complete; We will update this as we get
+more information about this.
+
+Currently we know that BDB tables works with the following operating
+system.
+
+@itemize @bullet
+@item
+Linux 2.x intel
+@item
+Solaris sparc
+@item
+SCO OpenServer
+@item
+SCO UnixWare 7.0.1
+@end itemize
+
+It doesn't work with the following operating systems:
+
+@itemize @bullet
+@item
+Linux 2.x Alpha
+@item
+Max OS X
+@end itemize
+
+@node BDB restrictions, BDB errors, BDB portability, BDB
+@subsection Restrictions on BDB Tables
+
+Here follows the restrictions you have when using BDB tables:
+
+@itemize @bullet
+@item
+BDB tables store in the .db file the path to the file as it was created
+(My guess is that this is to be able to detect locks in a multi-user
+environment that supports symlinks).
+
+The effect of this is that BDB tables are not movable between directories!
+@item
+When taking backups of BDB tables, you have to either use
+@code{mysqldump} or take a backup of all @code{table_name.db} files and
+the BDB log files. The BDB log files are the files in the base data
+directory named @code{log.XXXXXX} (6 digits);
+The BDB table handler stores unfinished transactions in the log files
+and requires these to be present when @code{mysqld} starts.
+@end itemize
+
+@node BDB errors, , BDB restrictions, BDB
+@subsection Errors That May Occur When Using BDB Tables
+
+@itemize @bullet
+@item
+If you get the following error in the @code{hostname.err log} when
+starting @code{mysqld}:
+
+@example
+bdb: Ignoring log file: .../log.XXXXXXXXXX: unsupported log version #
+@end example
+it means that the new @code{BDB} version doesn't support the old log
+file format. In this case you have to delete all @code{BDB} log BDB
+from your database directory (the files that has the format
+@code{log.XXXXXXXXXX} ) and restart @code{mysqld}. We would also
+recommend you to do a @code{mysqldump --opt} of your old @code{BDB}
+tables, delete the old table and restore the dump.
+@item
+If you are running in not @code{auto_commit} mode and delete a table you
+are using by another thread you may get the following error messages in
+the MySQL error file:
+
+@example
+001119 23:43:56 bdb: Missing log fileid entry
+001119 23:43:56 bdb: txn_abort: Log undo failed for LSN: 1 3644744: Invalid
+@end example
+
+This is not fatal but we don't recommend that you delete tables if you are
+not in @code{auto_commit} mode, until this problem is fixed (the fix is
+not trivial).
+@end itemize
+
+
@node Clients, Extending MySQL, Table types, Top
@@ -37820,8 +39237,8 @@ create dynamic Web pages. It contains support for accessing several
databases, including MySQL. PHP may be run as a separate program
or compiled as a module for use with the Apache Web server.
-The distribution and documentation are available at the
-@uref{http://www.php.net/, PHP web site}.
+The distribution and documentation are available at the PHP web site
+(@uref{http://www.php.net/}).
@menu
* PHP problems:: Common problems with MySQL and PHP
@@ -37880,7 +39297,7 @@ database type. For MySQL, this driver is called
For more information on the Perl5 DBI, please visit the @code{DBI} Web
page and read the documentation:
@example
-@uref{http://www.symbolstone.org/technology/perl/DBI/index.html}
+@uref{http://www.symbolstone.org/technology/perl/DBI/}
@end example
For more information on Object Oriented Programming
(OOP) as defined in Perl5, see the Perl OOP page:
@@ -37904,6 +39321,7 @@ Installation instructions for MySQL Perl support are given in
@strong{Portable DBI Methods}
@multitable @columnfractions .3 .7
+@item @strong{Method} @tab @strong{Description}
@item @code{connect} @tab Establishes a connection to a database server.
@item @code{disconnect} @tab Disconnects from the database server.
@item @code{prepare} @tab Prepares a SQL statement for execution.
@@ -37927,6 +39345,7 @@ Installation instructions for MySQL Perl support are given in
@strong{MySQL-specific Methods}
@multitable @columnfractions .3 .7
+@item @strong{Method} @tab @strong{Description}
@item @code{insertid} @tab The latest @code{AUTO_INCREMENT} value.
@item @code{is_blob} @tab Which columns are @code{BLOB} values.
@item @code{is_key} @tab Which columns are keys.
@@ -38083,7 +39502,7 @@ $rv = $dbh->do($statement)
or die "Can't execute $statement: $dbh- >errstr\n";
@end example
-Generally the 'do' statement is MUCH faster (and is preferable)
+Generally the 'do' statement is much faster (and is preferable)
than prepare/execute for statements that don't contain parameters.
@findex DBI->quote()
@@ -38392,7 +39811,7 @@ translate to other formats.
You can find the latest @code{DBI} information at
the @code{DBI} Web page:
@example
-@uref{http://www.symbolstone.org/technology/perl/DBI/index.html}
+@uref{http://www.symbolstone.org/technology/perl/DBI/}
@end example
@@ -38423,17 +39842,16 @@ are known to work with @strong{MyODBC}.
@node Installing MyODBC, ODBC administrator, ODBC, ODBC
@subsection How To Install MyODBC
-@strong{MyODBC} is a 32-bit ODBC (2.50) level 0 (with level 1 and level
-2 features) driver for connecting an ODBC-aware application to
-MySQL. @strong{MyODBC} works on Windows95, Windows98, NT, and
-on most Unix platforms.
+@strong{MyODBC} is a 32-bit ODBC (2.50) level 0 (with level 1 and
+level 2 features) driver for connecting an ODBC-aware application
+to MySQL. @strong{MyODBC} works on Windows95, Windows98, NT, 2000
+and on most Unix platforms.
-@strong{MyODBC} is in public domain, and you can find the newest version
-at @uref{http://www.mysql.com/downloads/api-myodbc.html}.
+@strong{MyODBC} is in public domain, and you can find the newest
+version at @uref{http://www.mysql.com/downloads/api-myodbc.html}.
If you have problem with @strong{MyODBC} and your program also works
-with OLEDB, you should try the OLEDB driver that you can find in the
-Contrib section. @xref{Contrib}.
+with OLEDB, you should try the OLEDB driver.
Normally you only need to install @strong{MyODBC} on Windows machines.
You only need @strong{MyODBC} for Unix if you have a program like
@@ -38442,9 +39860,7 @@ to the databases.
If you want to install @strong{MyODBC} on a Unix box, you will also need
an @strong{ODBC} manager. @strong{MyODBC} is known to work with
-most of the Unix ODBC managers. You can find a list at these in the
-@strong{ODBC}-related links section on the MySQL useful links page.
-@xref{Useful Links}.
+most of the Unix ODBC managers. @xref{Portals}.
To install @strong{MyODBC} on Windows, you should download the
appropriate @strong{MyODBC} .zip file (for Windows or NT/Win2000),
@@ -38593,7 +40009,7 @@ set this in the opton argument. The following options are listed in the
same order as they appear in the @strong{MyODBC} connect screen:
@multitable @columnfractions .1 .9
-@item @strong{Bit} @tab @strong{Meaning}
+@item @strong{Bit} @tab @strong{Description}
@item 1 @tab The client can't handle that @strong{MyODBC} returns the real width of a column.
@item 2 @tab The client can't handle that MySQL returns the true value of affected rows. If this flag is set then MySQL returns 'found rows' instead. One must have MySQL 3.21.14 or newer to get this to work.
@item 4 @tab Make a debug log in c:\myodbc.log. This is the same as putting @code{MYSQL_DEBUG=d:t:O,c::\myodbc.log} in @file{AUTOEXEC.BAT}
@@ -38602,13 +40018,13 @@ same order as they appear in the @strong{MyODBC} connect screen:
@item 32 @tab Simulate a ODBC 1.0 driver in some context.
@item 64 @tab Ignore use of database name in 'database.table.column'.
@item 128 @tab Force use of ODBC manager cursors (experimental).
-@item 256 @tab Disable the use of extended fetch (experimental)
+@item 256 @tab Disable the use of extended fetch (experimental).
@item 512 @tab Pad CHAR fields to full column length.
@item 1024 @tab SQLDescribeCol() will return fully qualifed column names
@item 2048 @tab Use the compressed server/client protocol
@item 4096 @tab Tell server to ignore space after function name and before @code{'('} (needed by PowerBuilder). This will make all function names keywords!
@item 8192 @tab Connect with named pipes to a @code{mysqld} server running on NT.
-@item 16384 @tab Change LONGLONG columns to INT columns (Some applications can't handle LONGLONG).
+@item 16384 @tab Change LONGLONG columns to INT columns (some applications can't handle LONGLONG).
@item 32768 @tab Return 'user' as Table_qualifier and Table_owner from SQLTables (experimental)
@item 65536 @tab Read parameters from the @code{client} and @code{odbc} groups from @file{my.cnf}
@item 131072 @tab Add some extra safety checks (should not bee needed but...)
@@ -38673,7 +40089,7 @@ To make Access work:
@item
If you are using Access 2000, you should get and install the newest
(version 2.6 or above) Microsoft MDAC (@code{Microsoft Data Access
-Components}) from @uref{http://www.microsoft.com/data}. This will fix
+Components}) from @uref{http://www.microsoft.com/data/}. This will fix
the following bug in Access: when you export data to MySQL, the
table and column names aren't specified. Another way to around this bug
is to upgrade to MyODBC Version 2.50.33 and MySQL Version
@@ -38689,19 +40105,37 @@ Note that if you are using MySQL Version 3.22, you must to apply the
MDAC patch and use MyODBC 2.50.32 or 2.50.34 and above to go around
this problem.
@item
-Set the ``Return matching rows'' MyODBC option field when connecting to
-MySQL.
-@item
-You should have a primary key in the table. If not, new or updated rows
-may show up as @code{#Deleted#}.
+For all Access versions, you should enable the MyODBC option flag
+@code{Return matching rows}. For Access 2.0, you should additionally enable
+@code{Simulate ODBC 1.0}.
@item
You should have a timestamp in all tables you want to be able to update.
For maximum portability @code{TIMESTAMP(14)} or simple @code{TIMESTAMP}
is recommended instead of other @code{TIMESTAMP(X)} variations.
@item
-Only use double float fields. Access fails when comparing with single floats.
-The symptom usually is that new or updated rows may show up as @code{#Deleted#}
-or that you can't find or update rows.
+You should have a primary key in the table. If not, new or updated rows
+may show up as @code{#DELETED#}.
+@item
+Only use @code{DOUBLE} float fields. Access fails when comparing with
+single floats. The symptom usually is that new or updated rows may show
+up as @code{#DELETED#} or that you can't find or update rows.
+@item
+If you are linking a table through MyODBC, which has @code{BIGINT} as
+one of the column, then the results will be displayed as @code{#DELETED}. The
+work around solution is:
+@itemize @bullet
+@item
+Have one more dummy column with @code{TIMESTAMP} as the data type, preferably
+@code{TIMESTAMP(14)}.
+@item
+Check the @code{'Change BIGINT columns to INT'} in connection options dialog in
+ODBC DSN Administrator
+@item
+Delete the table link from access and re-create it.
+@end itemize
+
+It still displays the previous records as @code{#DELETED#}, but newly
+added/updated records will be displayed properly.
@item
If you still get the error @code{Another user has changed your data} after
adding a @code{TIMESTAMP} column, the following trick may help you:
@@ -38712,6 +40146,10 @@ set the @code{DefaultValue} property for the @code{TIMESTAMP} column to
@code{NOW()}. It may be a good idea to hide the @code{TIMESTAMP} column
from view so your users are not confused.
@item
+In some cases, Access may generate illegal SQL queries that
+MySQL can't understand. You can fix this by selecting
+@code{"Query|SQLSpecific|Pass-Through"} from the Access menu.
+@item
Access on NT will report @code{BLOB} columns as @code{OLE OBJECTS}. If
you want to have @code{MEMO} columns instead, you should change the
column to @code{TEXT} with @code{ALTER TABLE}.
@@ -38719,19 +40157,9 @@ column to @code{TEXT} with @code{ALTER TABLE}.
Access can't always handle @code{DATE} columns properly. If you have a problem
with these, change the columns to @code{DATETIME}.
@item
-In some cases, Access may generate illegal SQL queries that
-MySQL can't understand. You can fix this by selecting
-@code{"Query|SQLSpecific|Pass-Through"} from the Access menu.
-@item
-If you have in Access a column defined as BYTE, Access will try to export this
-as @code{TINYINT} instead of @code{TINYINT UNSIGNED}. This will give you
-problems if you have values > 127 in the column!
-@item
-If you are using Access 7.0, You should use the option flag @code{Return
-matching rows}.
-@item
-If you are using Access 2.0, You should use the option flags @code{Return
-matching rows} and @code{Simulate ODBC 1.0}.
+If you have in Access a column defined as @code{BYTE}, Access will try
+to export this as @code{TINYINT} instead of @code{TINYINT UNSIGNED}.
+This will give you problems if you have values > 127 in the column!
@end itemize
@cindex ADO program
@@ -38805,7 +40233,7 @@ You have to change it to output @code{VARCHAR} rather than @code{ENUM}, as
it exports the latter in a manner that causes MySQL grief.
@cindex Excel
@item Excel
-Works. Some tips:
+Works. A few tips:
@itemize @bullet
@item
If you have problems with dates, try to select them as strings using the
@@ -38814,7 +40242,7 @@ If you have problems with dates, try to select them as strings using the
select CONCAT(rise_time), CONCAT(set_time)
from sunrise_sunset;
@end example
-Values retrieved as strings this way should be correctly recognized
+Values retrieved as strings this way should be correctly recognised
as time values by Excel97.
The purpose of @code{CONCAT()} in this example is to fool ODBC into thinking
@@ -38874,7 +40302,7 @@ Click OK and you see the rows in your Word document.
Test program for ODBC.
@cindex Delphi program
@item Delphi
-You must use BDE Version 3.2 or newer. Set the `Don't optimize column width'
+You must use BDE Version 3.2 or newer. Set the @code{Don't optimize column width}
option field when connecting to MySQL.
Also, here is some potentially useful Delphi code that sets up both an
@@ -38923,7 +40351,7 @@ fReg:= TRegistry.Create;
@item C++ Builder
Tested with BDE Version 3.0. The only known problem is that when the table
schema changes, query fields are not updated. BDE, however, does not seem
-to recognize primary keys, only the index PRIMARY, though this has not
+to recognise primary keys, only the index PRIMARY, though this has not
been a problem.
@item Vision
@@ -39027,7 +40455,7 @@ send the whole MyODBC or ODBC log file!
If you are unable to find out what's wrong, the last option is to
make an archive (tar or zip) that contains a MyODBC trace file, the ODBC
log file, and a README file that explains the problem. You can send this
-to @uref{ftp://support.mysql.com/pub/mysql/secret}. Only we at
+to @uref{ftp://support.mysql.com/pub/mysql/secret/}. Only we at
MySQL AB will have access to the files you upload, and we will
be very discrete with the data!
@@ -39051,10 +40479,12 @@ likely it is that we can fix the problem!
* C API datatypes:: C API Datatypes
* C API function overview:: C API Function Overview
* C API functions:: C API Function Descriptions
-* C Thread functions::
+* C Thread functions:: C Thread Functions
+* C Embedded Server func:: C Embedded Server Function Descriptions
* C API problems:: Common questions and problems when using the C API
* Building clients:: Building Client Programs
* Threaded clients:: How to Make a Threaded Client
+* libmysqld:: libmysqld, the Embedded MySQL Server Library
@end menu
The C API code is distributed with MySQL. It is included in the
@@ -39094,8 +40524,10 @@ The MySQL server shrinks each communication buffer to
the buffer associated with a connection is not decreased until the connection
is closed, at which time client memory is reclaimed.
-For programming with threads, consult the 'how to make a thread-safe
-client' chapter. @xref{Threaded clients}.
+For programming with threads, see @ref{Threaded clients}.
+For creating a stand-alone application which includes the
+"server" and "client" in the same program (and does not
+communicate with an external MySQL server), see @ref{libmysqld}.
@node C API datatypes, C API function overview, C, C
@@ -39172,7 +40604,7 @@ The type of the field.
The @code{type} value may be one of the following:
@multitable @columnfractions .3 .55
-@item @strong{Type value} @tab @strong{Type meaning}
+@item @strong{Type value} @tab @strong{Type description}
@item @code{FIELD_TYPE_TINY} @tab @code{TINYINT} field
@item @code{FIELD_TYPE_SHORT} @tab @code{SMALLINT} field
@item @code{FIELD_TYPE_LONG} @tab @code{INTEGER} field
@@ -39218,7 +40650,7 @@ Different bit-flags for the field. The @code{flags} value may have zero
or more of the following bits set:
@multitable @columnfractions .3 .55
-@item @strong{Flag value} @tab @strong{Flag meaning}
+@item @strong{Flag value} @tab @strong{Flag description}
@item @code{NOT_NULL_FLAG} @tab Field can't be @code{NULL}
@item @code{PRI_KEY_FLAG} @tab Field is part of a primary key
@item @code{UNIQUE_KEY_FLAG} @tab Field is part of a unique key
@@ -39251,6 +40683,7 @@ You may use the following convenience macros to determine the boolean
status of the @code{flags} value:
@multitable @columnfractions .3 .5
+@item @strong{Flag status} @tab @strong{Description}
@item @code{IS_NOT_NULL(flags)} @tab True if this field is defined as @code{NOT NULL}
@item @code{IS_PRI_KEY(flags)} @tab True if this field is a primary key
@item @code{IS_BLOB(flags)} @tab True if this field is a @code{BLOB} or @code{TEXT} (deprecated; test @code{field->type} instead)
@@ -39272,6 +40705,8 @@ greater detail in the next section.
@xref{C API functions}.
@multitable @columnfractions .3 .7
+@item @strong{Function} @tab @strong{Description}
+
@item @strong{mysql_affected_rows()} @tab
Returns the number of rows changed/deleted/inserted by the last @code{UPDATE},
@code{DELETE}, or @code{INSERT} query.
@@ -39368,7 +40803,7 @@ Returns the server version number.
Returns information about the most recently executed query.
@item @strong{mysql_init()} @tab
-Gets or initializes a @code{MYSQL} structure.
+Gets or initialises a @code{MYSQL} structure.
@item @strong{mysql_insert_id()} @tab
Returns the ID generated for an @code{AUTO_INCREMENT} column by the previous
@@ -39436,14 +40871,14 @@ Retrieves a complete result set to the client.
@item @strong{mysql_thread_id()} @tab
Returns the current thread ID.
-@item @strong{mysql_thread_save()} @tab
-Returns 1 if the clients are compiled as thread-safe.
+@item @strong{mysql_thread_safe()} @tab
+Returns 1 if the clients are compiled as thread safe.
@item @strong{mysql_use_result()} @tab
Initiates a row-by-row result set retrieval.
@end multitable
-To connect to the server, call @code{mysql_init()} to initialize a
+To connect to the server, call @code{mysql_init()} to initialise a
connection handler, then call @code{mysql_real_connect()} with that
handler (along with other information such as the hostname, user name,
and password). Upon connection, @code{mysql_real_connect()} sets the
@@ -39474,7 +40909,7 @@ retrieve the entire result set all at once by calling
@code{mysql_store_result()}. This function acquires from the server all the
rows returned by the query and stores them in the client. The second way is
for the client to initiate a row-by-row result set retrieval by calling
-@code{mysql_use_result()}. This function initializes the retrieval, but does
+@code{mysql_use_result()}. This function initialises the retrieval, but does
not actually get any rows from the server.
In both cases, you access rows by calling @code{mysql_fetch_row()}. With
@@ -39758,7 +41193,7 @@ this case the user and database are not changed
The @code{db} parameter may be set to @code{NULL} if you don't want to have a
default database.
-@subsubheading Return values
+@subsubheading Return Values
Zero for success. Non-zero if an error occurred.
@@ -39968,7 +41403,7 @@ if(mysql_drop_db(&mysql, "my_database"))
Instructs the server to write some debug information to the log. The
connected user must have the @strong{process} privilege for this to work.
-@subsubheading Return values
+@subsubheading Return Values
Zero if the command was successful. Non-zero if an error occurred.
@@ -40277,7 +41712,7 @@ for(i = 0; i < num_fields; i++)
Returns the lengths of the columns of the current row within a result set.
If you plan to copy field values, this length information is also useful for
-optimization, because you can avoid calling @code{strlen()}. In addition, if
+optimisation, because you can avoid calling @code{strlen()}. In addition, if
the result set contains binary data, you @emph{must} use this function to
determine the size of the data, because @code{strlen()} returns incorrect
results for any field containing null characters.
@@ -40461,7 +41896,6 @@ of @code{mysql_field_count()} whether or not the statement was a
@code{MYSQL_FIELD_OFFSET mysql_field_seek(MYSQL_RES *result, MYSQL_FIELD_OFFSET offset)}
-* Threaded clients:: How to Make a Threaded Client
@subsubheading Description
Sets the field cursor to the given offset. The next call to
@@ -40650,16 +42084,16 @@ None.
@subsubheading Description
-Allocates or initializes a @code{MYSQL} object suitable for
+Allocates or initialises a @code{MYSQL} object suitable for
@code{mysql_real_connect()}. If @code{mysql} is a @code{NULL} pointer, the
-function allocates, initializes, and returns a new object. Otherwise the
-object is initialized and the address of the object is returned. If
+function allocates, initialises, and returns a new object. Otherwise the
+object is initialised and the address of the object is returned. If
@code{mysql_init()} allocates a new object, it will be freed when
@code{mysql_close()} is called to close the connection.
@subsubheading Return Values
-An initialized @code{MYSQL*} handle. @code{NULL} if there was
+An initialised @code{MYSQL*} handle. @code{NULL} if there was
insufficient memory to allocate a new object.
@subsubheading Errors
@@ -40953,7 +42387,7 @@ else // query succeeded, process any data returned by it
@}
@end example
-An alternative (if you KNOW that your query should have returned a result set)
+An alternative (if you know that your query should have returned a result set)
is to replace the @code{mysql_errno(&mysql)} call with a check if
@code{mysql_field_count(&mysql)} is = 0. This will only happen if something
went wrong.
@@ -41022,6 +42456,7 @@ Note that the group @code{client} is always read if you use
The specified group in the option file may contain the following options:
@multitable @columnfractions .3 .7
+@item @strong{Option} @tab @strong{Description}
@item @code{connect_timeout} @tab Connect timeout in seconds. On Linux this timeout is also used for waiting for the first answer from the server.
@item @code{compress} @tab Use the compressed client/server protocol.
@item @code{database} @tab Connect to this database if no database was specified in the connect command.
@@ -41034,7 +42469,6 @@ The specified group in the option file may contain the following options:
@item @code{port} @tab Default port number.
@item @code{return-found-rows} @tab Tell @code{mysql_info()} to return found rows instead of updated rows when using @code{UPDATE}.
@item @code{socket} @tab Default socket number.
-@item
@item @code{user} @tab Default user.
@end multitable
@@ -41162,7 +42596,7 @@ The parameters are specified as follows:
@item
The first parameter should be the address of an existing @code{MYSQL}
structure. Before calling @code{mysql_real_connect()} you must call
-@code{mysql_init()} to initialize the @code{MYSQL} structure. You can
+@code{mysql_init()} to initialise the @code{MYSQL} structure. You can
change a lot of connect options with the @code{mysql_options()}
call. @xref{mysql_options}.
@@ -41211,14 +42645,13 @@ The value of @code{client_flag} is usually 0, but can be set to a combination
of the following flags in very special circumstances:
@multitable @columnfractions .25 .7
-@item @strong{Flag name} @tab @strong{Flag meaning}
-@code{mysqld} to be more ODBC-friendly.
+@item @strong{Flag name} @tab @strong{Flag description}
@item @code{CLIENT_COMPRESS} @tab Use compression protocol.
@item @code{CLIENT_FOUND_ROWS} @tab Return the number of found (matched) rows, not the number of affected rows.
@item @code{CLIENT_IGNORE_SPACE} @tab Allow spaces after function names. Makes all functions names reserved words.
@item @code{CLIENT_INTERACTIVE} @tab Allow @code{interactive_timeout} seconds (instead of @code{wait_timeout} seconds) of inactivity before closing the connection.
@item @code{CLIENT_NO_SCHEMA} @tab Don't allow the @code{db_name.tbl_name.col_name} syntax. This is for ODBC. It causes the parser to generate an error if you use that syntax, which is useful for trapping bugs in some ODBC programs.
-@item @code{CLIENT_ODBC} @tab The client is an ODBC client. This changes
+@item @code{CLIENT_ODBC} @tab The client is an ODBC client. This changes @code{mysqld} to be more ODBC-friendly.
@item @code{CLIENT_SSL} @tab Use SSL (encrypted protocol).
@end multitable
@end itemize
@@ -41608,10 +43041,10 @@ use @code{mysql_field_count()} to check for this.
allocates a @code{MYSQL_RES} structure, and places the result into this
structure.
-@code{mysql_store_results()} returns a null pointer if the query didn't return
+@code{mysql_store_result()} returns a null pointer if the query didn't return
a result set (if the query was, for example, an @code{INSERT} statement).
-@code{mysql_store_results()} also returns a null pointer if reading of the
+@code{mysql_store_result()} also returns a null pointer if reading of the
result set failed. You can check if you got an error by checking if
@code{mysql_error()} doesn't return a null pointer, if
@code{mysql_errno()} returns <> 0, or if @code{mysql_field_count()}
@@ -41742,19 +43175,19 @@ The connection to the server was lost during the query.
An unknown error occurred.
@end table
-@node C Thread functions, C API problems, C API functions, C
+@node C Thread functions, C Embedded Server func, C API functions, C
@subsection C Threaded Function Descriptions
You need to use the following functions when you want to create a
threaded client. @xref{Threaded clients}.
@menu
-* my_init::
-* my_thread_init()::
-* my_thread_end()::
+* my_init:: @code{my_init()}
+* mysql_thread_init:: @code{mysql_thread_init()}
+* mysql_thread_end:: @code{mysql_thread_end()}
@end menu
-@node my_init, my_thread_init(), C Thread functions, C Thread functions
+@node my_init, mysql_thread_init, C Thread functions, C Thread functions
@subsubsection @code{my_init()}
@findex @code{my_init()}
@@ -41762,25 +43195,25 @@ threaded client. @xref{Threaded clients}.
@subsubheading Description
This function needs to be called once in the program before calling any
-MySQL function. This initializes some global variables that MySQL
-needs. If you are using a thread safe client library, this will also
-call @code{my_thread_init()} for this thread.
+MySQL function. This initialises some global variables that MySQL
+needs. If you are using a thread-safe client library, this will also
+call @code{mysql_thread_init()} for this thread.
-This is automatically called by @code{mysql_init()}
-and @code{mysql_connect()}.
+This is automatically called by @code{mysql_init()},
+@code{mysql_server_init()} and @code{mysql_connect()}.
@subsubheading Return Values
none.
-@node my_thread_init(), my_thread_end(), my_init, C Thread functions
-@subsubsection @code{my_thread_init()}
+@node mysql_thread_init, mysql_thread_end, my_init, C Thread functions
+@subsubsection @code{mysql_thread_init()}
-@findex @code{my_thread_init()}
+@findex @code{mysql_thread_init()}
@subsubheading Description
-This function needs to be called for each created thread to initialize
+This function needs to be called for each created thread to initialise
thread specific variables.
This is automatically called by @code{my_init()} and @code{mysql_connect()}.
@@ -41789,31 +43222,124 @@ This is automatically called by @code{my_init()} and @code{mysql_connect()}.
none.
-@node my_thread_end(), , my_thread_init(), C Thread functions
-@subsubsection @code{my_thread_end()}
+@node mysql_thread_end, , mysql_thread_init, C Thread functions
+@subsubsection @code{mysql_thread_end()}
-@findex @code{my_thread_end()}
+@findex @code{mysql_thread_end()}
@subsubheading Description
This function needs to be called before calling @code{pthread_exit()} to
-freed memory allocated by @code{my_thread_init()}.
+free memory allocated by @code{mysql_thread_init()}.
-Note that this function is NOT invoked automatically by the client
-library!
+Note that this function @strong{is not invoked automatically} by the client
+library. It must be called explicitly to avoid a memory leak.
@subsubheading Return Values
none.
-@node C API problems, Building clients, C Thread functions, C
+@node C Embedded Server func, C API problems, C Thread functions, C
+@subsection C Embedded Server Function Descriptions
+
+You must use the following functions if you want to allow your
+application to be linked against the embedded MySQL server library.
+@xref{libmysqld}.
+
+If the program is linked with @code{-lmysqlclient} instead of
+@code{-lmysqld}, these functions do nothing. This makes it
+possible to choose between using the embedded MySQL server and
+a stand-alone server without modifying any code.
+
+@menu
+* mysql_server_init:: @code{mysql_server_init()}
+* mysql_server_end:: @code{mysql_server_end()}
+@end menu
+
+@node mysql_server_init, mysql_server_end, C Embedded Server func, C Embedded Server func
+@subsubsection @code{mysql_server_init()}
+
+@findex @code{mysql_server_init()}
+
+@code{int mysql_server_init(int argc, char **argv, char **groups)}
+
+@subsubheading Description
+
+This function @strong{must} be called once in the program before
+calling any other MySQL function. It starts up the server and
+initialises any subsystems (@code{mysys}, InnoDB, etc.) that the
+server uses. If this function is not called, the program will
+crash. If you are using the DBUG package that comes with MySQL,
+you should call this after you have called @code{MY_INIT()}.
+
+The @code{argc} and @code{argv} arguments are analogous to the
+arguments to @code{main()}. The first element of @code{argv}
+is ignored (it typically contains the program name). For
+convenience, @code{argc} may be @code{0} (zero) if there are no
+command-line arguments for the server.
+
+The @code{NULL}-terminated list of strings in @code{groups}
+selects which groups in the option files will be active.
+@xref{Option files}. For convenience, @code{groups} may be
+@code{NULL}, in which case the @code{[server]} and @code{[emedded]} groups
+will be active.
+
+@subsubheading Example
+
+@example
+#include <mysql.h>
+#include <stdlib.h>
+
+static char *server_args[] = @{
+ "this_program", /* this string is not used */
+ "--datadir=.",
+ "--set-variable=key_buffer_size=32M"
+@};
+static char *server_groups[] = @{
+ "embedded",
+ "server",
+ "this_program_SERVER",
+ (char *)NULL
+@};
+
+int main(void) @{
+ mysql_server_init(sizeof(server_args) / sizeof(char *),
+ server_args, server_groups);
+
+ /* Use any MySQL API functions here */
+
+ mysql_server_end();
+
+ return EXIT_SUCCESS;
+@}
+@end example
+
+@subsubheading Return Values
+
+0 if okay, 1 if an error occurred.
+
+@node mysql_server_end, , mysql_server_init, C Embedded Server func
+@subsubsection @code{mysql_server_end()}
+
+@findex @code{mysql_server_end()}
+
+@subsubheading Description
+
+This function @strong{must} be called once in the program after
+all other MySQL functions. It shuts down the embedded server.
+
+@subsubheading Return Values
+
+none.
+
+@node C API problems, Building clients, C Embedded Server func, C
@subsection Common questions and problems when using the C API
@tindex @code{mysql_query()}
@tindex @code{mysql_store_result()}
@menu
-* NULL mysql_store_result:: Why Is It that After @code{mysql_query()} Returns Success, @code{mysql_store_result()} Sometimes Returns @code{NULL?}
+* NULL mysql_store_result:: Why Is It that After @code{mysql_query()} Returns Success, @code{mysql_store_result()} Sometimes Returns @code{NULL}?
* Query results:: What Results Can I Get From a Query?
* Getting unique ID:: How Can I Get the Unique ID for the Last Inserted Row?
* C API linking problems:: Problems Linking with the C API
@@ -41821,7 +43347,7 @@ none.
@node NULL mysql_store_result, Query results, C API problems, C API problems
-@subsubsection Why Is It that After @code{mysql_query()} Returns Success, @code{mysql_store_result()} Sometimes Returns @code{NULL?}
+@subsubsection Why Is It that After @code{mysql_query()} Returns Success, @code{mysql_store_result()} Sometimes Returns @code{NULL}?
It is possible for @code{mysql_store_result()} to return @code{NULL}
following a successful call to @code{mysql_query()}. When this happens, it
@@ -41852,14 +43378,6 @@ example.
You can test for an error by calling @code{mysql_error()} or
@code{mysql_errno()}.
-@cindex queries, C API results
-@menu
-* Query results:: What Results Can I Get From a Query?
-* Getting unique ID:: How Can I Get the Unique ID for the Last Inserted Row?
-* C API linking problems:: Problems Linking with the C API
-@end menu
-
-
@node Query results, Getting unique ID, NULL mysql_store_result, C API problems
@subsubsection What Results Can I Get From a Query?
@@ -41982,7 +43500,7 @@ For clients that use MySQL header files, you may need to specify a
files.
-@node Threaded clients, , Building clients, C
+@node Threaded clients, libmysqld, Building clients, C
@subsection How to Make a Threaded Client
@cindex clients, threaded
@@ -41995,11 +43513,11 @@ have your own alarm that can break a long read to a server. If you
install interrupt handlers for the @code{SIGPIPE} interrupt,
the socket handling should be thread safe.
-In the older binaries we distribute on our Web site, the client
-libraries are not normally compiled with the thread-safe option (the
-Windows binaries are by default compiled to be thread safe).
-Newer binary distributions should have both a normal and a
-thread-safe client library.
+In the older binaries we distribute on our web site
+(@uref{http://www.mysql.com/}), the client libraries are not normally
+compiled with the thread-safe option (the Windows binaries are by
+default compiled to be thread safe). Newer binary distributions should
+have both a normal and a thread-safe client library.
To get a threaded client where you can interrupt the client from other
threads and set timeouts when talking with the MySQL server, you should
@@ -42018,7 +43536,7 @@ interrupts, you can make great use of the routines in the
@code{my_init()} first! @xref{C Thread functions}.
All functions except @code{mysql_real_connect()} are by default
-thread safe. The following notes describe how to compile a thread safe
+thread safe. The following notes describe how to compile a thread-safe
client library and use it in a thread-safe manner. (The notes below for
@code{mysql_real_connect()} actually apply to @code{mysql_connect()} as
well, but because @code{mysql_connect()} is deprecated, you should be
@@ -42033,12 +43551,12 @@ shell> ./configure --enable-thread-safe-client
This will create a thread-safe client library @code{libmysqlclient_r}.
@code{--enable-thread-safe-client}. This library is thread safe per
-connection. You can let two threads share the same connection as long
-as you do the following:
+connection. You can let two threads share the same connection with
+the following caveats:
@itemize @bullet
@item
-Two threads can't send a query to the MySQL at the same time on
+Two threads can't send a query to the MySQL server at the same time on
the same connection. In particular, you have to ensure that between a
@code{mysql_query()} and @code{mysql_store_result()} no other thread is using
the same connection.
@@ -42047,9 +43565,9 @@ Many threads can access different result sets that are retrieved with
@code{mysql_store_result()}.
@item
If you use @code{mysql_use_result}, you have to ensure that no other thread
-is asking anything on the same connection until the result set is closed.
+is using the same connection until the result set is closed.
However, it really is best for threaded clients that share the same
-connection to use @code{mysql_use_result()}.
+connection to use @code{mysql_store_result()}.
@item
If you want to use multiple threads on the same connection, you must
have a mutex lock around your @code{mysql_query()} and
@@ -42063,14 +43581,14 @@ establish and release a mutex lock.
@end itemize
You need to know the following if you have a thread that is calling
-MySQL functions, but that thread has not created the connection to the
+MySQL functions which did not create the connection to the
MySQL database:
When you call @code{mysql_init()} or @code{mysql_connect()}, MySQL will
create a thread specific variable for the thread that is used by the
debug library (among other things).
-If you have in a thread call a MySQL function, before a thread has
+If you call a MySQL function, before the thread has
called @code{mysql_init()} or @code{mysql_connect()}, the thread will
not have the necessary thread specific variables in place and you are
likely to end up with a core dump sooner or later.
@@ -42082,18 +43600,350 @@ The get things to work smoothly you have to do the following:
Call @code{my_init()} at the start of your program if it calls
any other MySQL function before calling @code{mysql_real_connect()}.
@item
-Call @code{my_thread_init()} in the thread handler before calling
+Call @code{mysql_thread_init()} in the thread handler before calling
any MySQL function.
@item
-In the thread, call @code{my_thread_end()} before calling
+In the thread, call @code{mysql_thread_end()} before calling
@code{pthread_exit()}. This will free the memory used by MySQL thread
specific variables.
@end enumerate
You may get some errors because of undefined symbols when linking your
-client with @code{mysqlclient_r}. In most cases this is because you haven't
+client with @code{libmysqlclient_r}. In most cases this is because you haven't
included the thread libraries on the link/compile line.
+@node libmysqld, , Threaded clients, C
+@subsection libmysqld, the Embedded MySQL Server Library
+
+@cindex libmysqld
+@cindex embedded MySQL server library
+
+@menu
+* libmysqld overview:: Overview of the Embedded MySQL Server Library
+* libmysqld compiling:: Compiling Programs with @code{libmysqld}
+* libmysqld restrictions:: Restrictions when Using the Embedded MySQL Server
+* libmysqld options:: Using Option Files with the Embedded Server
+* libmysqld TODO:: Things left to do in Embedded Server (TODO)
+* libmysqld example:: A Simple Embedded Server Example
+* libmysqld licensing:: Licensing the Embedded Server
+@end menu
+
+@node libmysqld overview, libmysqld compiling, libmysqld, libmysqld
+@subsubsection Overview of the Embedded MySQL Server Library
+
+The embedded MySQL server library makes it possible to run a
+full-featured MySQL server inside the client application. The
+main benefits are increased speed and more simple management for
+embedded applications.
+
+The API is identical for the embedded MySQL version and the
+client/server version. To change an old threaded application to use the
+embedded library, you normally only have to add calls to the following
+functions:
+
+@multitable @columnfractions .25 .7
+@item @strong{Function} @tab @strong{When to call}
+@item @code{mysql_server_init()} @tab Should be called before any other other MySQL function is called, preferably early in the @code{main()} function.
+@item @code{mysql_server_end()} @tab Should be called before your program exits.
+@item @code{mysql_thread_init()} @tab Should be called in each thread you create that will access MySQL.
+@item @code{mysql_thread_end()} @tab Should be called before calling @code{pthread_exit()}
+@end multitable
+
+Then you must link your code with @code{libmysqld.a} instead of @code{libmysqlclient.a}.
+
+The above @code{mysql_server_xxx} functions are also included in
+@code{libmysqlclient.a} to allow you to change between the embedded and the
+client/server version by just linking your application with the right
+library. @xref{mysql_server_init}.
+
+
+@node libmysqld compiling, libmysqld restrictions, libmysqld overview, libmysqld
+@subsubsection Compiling Programs with @code{libmysqld}
+
+To get a @code{libmysqld} library you should configure MySQL with the
+@code{--with-embedded-server} option.
+
+When you link your program with @code{libmysqld}, you must also include
+the system-specific @code{pthread} libraries and some libraries that
+the MySQL server uses. You can get the full list of libraries by executing
+@code{mysql_config --libmysqld-libs}.
+
+The correct flags for compiling and linking a threaded program
+must be used, even if you do not directly call any thread
+functions in your code.
+
+@node libmysqld restrictions, libmysqld options, libmysqld compiling, libmysqld
+@subsubsection Restrictions when using the Embedded MySQL Server
+
+The embedded server has the following limitations:
+
+@itemize @bullet
+@item
+No support for ISAM tables. (This is mainly done to make the library smaller)
+@item
+No UDF functions.
+@item
+No stack trace on core dump.
+@item
+No internal RAID support. (This is not normally needed as most OS has
+nowadays support for big files).
+@item
+You can set this up as a server or a master (no replication).
+@item
+You can't connect to the embedded server from an outside process with
+sockets or TCP/IP.
+@end itemize
+
+Some of these limitations can be changed by editing the @file{mysql_embed.h}
+include file and recompiling MySQL.
+
+@node libmysqld options, libmysqld TODO, libmysqld restrictions, libmysqld
+@subsubsection Using Option Files with the Embedded Server
+
+@cindex defaults, embedded
+
+The following is the recommended way to use option files to make it easy
+to switch between a client/server application and one where MySQL is
+embedded. @xref{Option files}.
+
+@itemize @bullet
+@item
+Put common options in the @code{[server]} section. These will be read by
+both MySQL versions.
+@item
+Put client/server specific options in the @code{[mysqld]} section.
+@item
+Put embedded MySQL specific options in the @code{[embedded]} section.
+@item
+Put application specific options in a @code{[ApplicationName_SERVER]}
+section.
+@end itemize
+
+@node libmysqld TODO, libmysqld example, libmysqld options, libmysqld
+@subsubsection Things left to do in Embedded Server (TODO)
+
+@cindex TODO, embedded server
+
+@itemize @bullet
+@item
+Currently we only provide a static version of the @code{mysqld} library,
+in the future we will also provide a shared library for this.
+@item
+We are going to provide options to leave out some parts of MySQL to make
+the library smaller.
+@item
+There is still a lot of speed optimisation to do.
+@item
+Errors are written to stderr. We will add an option to specify a
+filename for these.
+@item
+We have to change InnoDB to not be so verbose when using in the embedded
+version.
+@end itemize
+
+
+@node libmysqld example, libmysqld licensing, libmysqld TODO, libmysqld
+@subsubsection A Simple Embedded Server Example
+
+This example program and makefile should work without any
+changes on a Linux or FreeBSD system. For other operating
+systems, minor changes will be needed. This example is
+designed to give enough details to understand the problem,
+without the clutter that is a necessary part of a real
+application.
+
+To try out the example, create an @file{test_libmysqld} directory
+at the same level as the mysql-4.0 source directory. Save
+the @file{test_libmysqld.c} source and the @file{GNUmakefile} in the
+directory, and run GNU @file{make} from inside the @file{test_libmysqld}
+directory.
+
+@file{test_libmysqld.c}
+@example
+/*
+ * A simple example client, using the embedded MySQL server library
+ */
+
+#include <mysql.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+MYSQL *db_connect(const char *dbname);
+void db_disconnect(MYSQL *db);
+void db_do_query(MYSQL *db, const char *query);
+
+const char *server_groups[] = @{
+ "test_libmysqld_SERVER", "embedded", "server", NULL
+@};
+
+int
+main(int argc, char **argv)
+@{
+ MYSQL *one, *two;
+
+ /* mysql_server_init() must be called before any other mysql
+ * functions.
+ *
+ * You can use mysql_server_init(0, NULL, NULL), and it will
+ * initialise the server using groups = @{
+ * "server", "embedded", NULL
+ * @}.
+ *
+ * In your $HOME/.my.cnf file, you probably want to put:
+
+[test_libmysqld_SERVER]
+language = /path/to/source/of/mysql/sql/share/english
+
+ * You could, of course, modify argc and argv before passing
+ * them to this function. Or you could create new ones in any
+ * way you like. But all of the arguments in argv (except for
+ * argv[0], which is the program name) should be valid options
+ * for the MySQL server.
+ *
+ * If you link this client against the normal mysqlclient
+ * library, this function is just a stub that does nothing.
+ */
+ mysql_server_init(argc, argv, (char **)server_groups);
+
+ one = db_connect("test");
+ two = db_connect(NULL);
+
+ db_do_query(one, "show table status");
+ db_do_query(two, "show databases");
+
+ mysql_close(two);
+ mysql_close(one);
+
+ /* This must be called after all other mysql functions */
+ mysql_server_end();
+
+ exit(EXIT_SUCCESS);
+@}
+
+static void
+die(MYSQL *db, char *fmt, ...)
+@{
+ va_list ap;
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ (void)putc('\n', stderr);
+ if (db)
+ db_disconnect(db);
+ exit(EXIT_FAILURE);
+@}
+
+MYSQL *
+db_connect(const char *dbname)
+@{
+ MYSQL *db = mysql_init(NULL);
+ if (!db)
+ die(db, "mysql_init failed: no memory");
+ /*
+ * Notice that the client and server use separate group names.
+ * This is critical, because the server will not accept the
+ * client's options, and vice versa.
+ */
+ mysql_options(db, MYSQL_READ_DEFAULT_GROUP, "test_libmysqld_CLIENT");
+ if (!mysql_real_connect(db, NULL, NULL, NULL, dbname, 0, NULL, 0))
+ die(db, "mysql_real_connect failed: %s", mysql_error(db));
+
+ return db;
+@}
+
+void
+db_disconnect(MYSQL *db)
+@{
+ mysql_close(db);
+@}
+
+void
+db_do_query(MYSQL *db, const char *query)
+@{
+ if (mysql_query(db, query) != 0)
+ goto err;
+
+ if (mysql_field_count(db) > 0)
+ @{
+ MYSQL_RES *res;
+ MYSQL_ROW row, end_row;
+ int num_fields;
+
+ if (!(res = mysql_store_result(db)))
+ goto err;
+ num_fields = mysql_num_fields(res);
+ while ((row = mysql_fetch_row(res)))
+ @{
+ (void)fputs(">> ", stdout);
+ for (end_row = row + num_fields; row < end_row; ++row)
+ (void)printf("%s\t", row ? (char*)*row : "NULL");
+ (void)fputc('\n', stdout);
+ @}
+ (void)fputc('\n', stdout);
+ @}
+ else
+ (void)printf("Affected rows: %lld\n", mysql_affected_rows(db));
+
+ return;
+
+err:
+ die(db, "db_do_query failed: %s [%s]", mysql_error(db), query);
+@}
+@end example
+
+@file{GNUmakefile}
+@example
+# This assumes the MySQL software is installed in /usr/local/mysql
+inc := /usr/local/mysql/include/mysql
+lib := /usr/local/mysql/lib
+
+# If you have not installed the MySQL software yet, try this instead
+#inc := $(HOME)/mysql-4.0/include
+#lib := $(HOME)/mysql-4.0/libmysqld
+
+CC := gcc
+CPPFLAGS := -I$(inc) -D_THREAD_SAFE -D_REENTRANT
+CFLAGS := -g -W -Wall
+LDFLAGS := -static
+# You can change -lmysqld to -lmysqlclient to use the
+# client/server library
+LDLIBS = -L$(lib) -lmysqld -lz -lm -lcrypt
+
+ifneq (,$(shell grep FreeBSD /COPYRIGHT 2>/dev/null))
+# FreeBSD
+LDFLAGS += -pthread
+else
+# Assume Linux
+LDLIBS += -lpthread
+endif
+
+# This works for simple one-file test programs
+sources := $(wildcard *.c)
+objects := $(patsubst %c,%o,$(sources))
+targets := $(basename $(sources))
+
+all: $(targets)
+
+clean:
+ rm -f $(targets) $(objects) *.core
+@end example
+
+@node libmysqld licensing, , libmysqld example, libmysqld
+@subsubsection Licensing the Embedded Server
+
+The MySQL source code is covered by the GNU GPL license
+(@pxref{GPL license}). One result of this is that any program
+which includes, by linking with @code{libmysqld}, the MySQL
+source code must be released as free software (under a license
+compatible with the GPL).
+
+We encourage everyone to promote free software by releasing
+code under the GPL or a compatible license. For those who
+are not able to do this, another option is to purchase the
+MySQL code from MySQL AB under a looser license. For details
+concerning this issue, please see @ref{MySQL server licenses}.
+
@node Cplusplus, Java, C, Clients
@section MySQL C++ APIs
@@ -42104,8 +43954,8 @@ included the thread libraries on the link/compile line.
@cindex C++ APIs
-Two APIs are available in the MySQL
-@uref{http://www.mysql.com/Downloads/Contrib/,Contrib directory}.
+Two APIs are available in the MySQL Contrib directory
+(@uref{http://www.mysql.com/Downloads/Contrib/}).
@node Borland C++, , Cplusplus, Cplusplus
@@ -42115,7 +43965,7 @@ Two APIs are available in the MySQL
You can compile the MySQL Windows source with Borland C++ 5.02.
(The Windows source includes only projects for Microsoft VC++, for
-Borland C++ you have to do the project files yourself).
+Borland C++ you have to do the project files yourself.)
One known problem with Borland C++ is that it uses a different structure
alignment than VC++. This means that you will run into problems if you
@@ -42153,12 +44003,13 @@ documentation for MySQL-specific features.
@cindex Python APIs
-The MySQL @uref{http://www.mysql.com/Downloads/Contrib/,Contrib directory}
+The MySQL Contrib directory
+(@uref{http://www.mysql.com/Downloads/Contrib/})
contains a Python interface written by Joseph Skinner.
You can also use the Python interface to iODBC to access a
MySQL server.
-@uref{http://starship.skyport.net/~lemburg/,mxODBC}
+@uref{http://starship.skyport.net/~lemburg/} (mxODBC)
@node Tcl, Eiffel, Python, Clients
@@ -42166,9 +44017,9 @@ MySQL server.
@cindex Tcl APIs
-@uref{http://www.binevolve.com/~tdarugar/tcl-sql/, Tcl at binevolve}.
-The
-@uref{http://www.mysql.com/Downloads/Contrib,Contrib directory} contains a Tcl
+@uref{http://www.binevolve.com/~tdarugar/tcl-sql/} (Tcl at binevolve).
+The Contrib directory
+(@uref{http://www.mysql.com/Downloads/Contrib/}) contains a Tcl
interface that is based on msqltcl 1.50.
@@ -42178,26 +44029,310 @@ interface that is based on msqltcl 1.50.
@cindex Eiffel Wrapper
@cindex wrappers, Eiffel
-The MySQL @uref{http://www.mysql.com/Downloads/Contrib/,Contrib directory}
+The MySQL Contrib directory
+(@uref{http://www.mysql.com/Downloads/Contrib/})
contains an Eiffel wrapper written by Michael Ravits.
-You can also find this at:
-@url{http://www.netpedia.net/hosting/newplayer/}
-
-
-
@node Extending MySQL, Problems, Clients, Top
@chapter Extending MySQL
@menu
+* MySQL internals:: MySQL Internals
* Adding functions:: Adding New Functions to MySQL
* Adding procedures:: Adding New Procedures to MySQL
-* MySQL internals:: MySQL Internals
@end menu
-@node Adding functions, Adding procedures, Extending MySQL, Extending MySQL
+@node MySQL internals, Adding functions, Extending MySQL, Extending MySQL
+@section MySQL Internals
+
+@cindex internals
+@cindex threads
+
+This chapter describes a lot of things that you need to know when
+working on the MySQL code. If you plan to contribute to MySQL
+development, want to have access to the bleeding-edge in-between
+versions code, or just want to keep track of development, follow the
+instructions in @xref{Installing source tree}.
+If you are interested in MySQL internals, you should also subscribe
+to our @code{internals} mailing list. This list is relatively low
+traffic. For details on how to subscribe, please see
+@ref{Mailing-list}.
+All developers at MySQL AB are on the @code{internals} list and we
+help other people who are working on the MySQL code. Feel free to
+use this list both to ask questions about the code and to send
+patches that you would like to contribute to the MySQL project!
+
+@menu
+* MySQL threads:: MySQL threads
+* MySQL test suite:: MySQL test suite
+@end menu
+
+
+@node MySQL threads, MySQL test suite, MySQL internals, MySQL internals
+@subsection MySQL Threads
+
+The MySQL server creates the following threads:
+
+@itemize @bullet
+
+@item
+The TCP/IP connection thread handles all connection requests and
+creates a new dedicated thread to handle the authentication and
+and SQL query processing for each connection.
+
+@item
+On Windows NT there is a named pipe handler thread that does the same work as
+the TCP/IP connection thread on named pipe connect requests.
+
+@item
+The signal thread handles all signals. This thread also normally handles
+alarms and calls @code{process_alarm()} to force timeouts on connections
+that have been idle too long.
+
+@item
+If @code{mysqld} is compiled with @code{-DUSE_ALARM_THREAD}, a dedicated
+thread that handles alarms is created. This is only used on some systems where
+there are problems with @code{sigwait()} or if one wants to use the
+@code{thr_alarm()} code in ones application without a dedicated signal
+handling thread.
+
+@item
+If one uses the @code{--flush_time=#} option, a dedicated thread is created
+to flush all tables at the given interval.
+
+@item
+Every connection has its own thread.
+
+@item
+Every different table on which one uses @code{INSERT DELAYED} gets its
+own thread.
+
+@item
+If you use @code{--master-host}, a slave replication thread will be
+started to read and apply updates from the master.
+@end itemize
+
+@code{mysqladmin processlist} only shows the connection, @code{INSERT DELAYED},
+and replication threads.
+
+
+@node MySQL test suite, , MySQL threads, MySQL internals
+@subsection MySQL Test Suite
+
+@cindex mysqltest, MySQL Test Suite
+@cindex testing mysqld, mysqltest
+
+Until recently, our main full-coverage test suite was based on proprietary
+customer data and for that reason has not been publicly available. The only
+publicly available part of our testing process consisted of the @code{crash-me}
+test, a Perl DBI/DBD benchmark found in the @code{sql-bench} directory, and
+miscellaneous tests located in @code{tests} directory. The lack of a
+standardised publicly available test suite has made it difficult for our users,
+as well developers, to do regression tests on the MySQL code. To
+address this problem, we have created a new test system that is included in
+the source and binary distributions starting in Version 3.23.29.
+
+The current set of test cases doesn't test everything in MySQL, but it
+should catch most obvious bugs in the SQL processing code, OS/library
+issues, and is quite thorough in testing replication. Our eventual goal
+is to have the tests cover 100% of the code. We welcome contributions
+to our test suite. You may especially want to contribute tests that
+examine the functionality critical to your system, as this will ensure
+that all future MySQL releases will work well with your
+applications.
+
+@menu
+* running mysqltest:: Running the MySQL Test Suite
+* extending mysqltest:: Extending the MySQL Test Suite
+* Reporting mysqltest bugs:: Reporting Bugs in the MySQL Test Suite
+@end menu
+
+
+@node running mysqltest, extending mysqltest, MySQL test suite, MySQL test suite
+@subsubsection Running the MySQL Test Suite
+
+The test system consist of a test language interpreter
+(@code{mysqltest}), a shell script to run all
+tests(@code{mysql-test-run}), the actual test cases written in a special
+test language, and their expected results. To run the test suite on
+your system after a build, type @code{make test} or
+@code{mysql-test/mysql-test-run} from the source root. If you have
+installed a binary distribution, @code{cd} to the install root
+(eg. @code{/usr/local/mysql}), and do @code{scripts/mysql-test-run}.
+All tests should succeed. If not, you should try to find out why and
+report the problem if this is a bug in MySQL.
+@xref{Reporting mysqltest bugs}.
+
+If you have a copy of @code{mysqld} running on the machine where you want to
+run the test suite you do not have to stop it, as long as it is not using
+ports @code{9306} and @code{9307}. If one of those ports is taken, you should
+edit @code{mysql-test-run} and change the values of the master and/or slave
+port to one that is available.
+
+You can run one individual test case with
+@code{mysql-test/mysql-test-run test_name}.
+
+If one test fails, you should test running @code{mysql-test-run} with
+the @code{--force} option to check if any other tests fails.
+
+
+@node extending mysqltest, Reporting mysqltest bugs, running mysqltest, MySQL test suite
+@subsubsection Extending the MySQL Test Suite
+
+You can use the @code{mysqltest} language to write your own test cases.
+Unfortunately, we have not yet written full documentation for it - we plan to
+do this shortly. You can, however, look at our current test cases and use
+them as an example. The following points should help you get started:
+
+@itemize @bullet
+@item
+The tests are located in @code{mysql-test/t/*.test}
+
+@item
+A test case consists of @code{;} terminated statements and is similar to the
+input of @code{mysql} command line client. A statement by default is a query
+to be sent to MySQL server, unless it is recognised as internal
+command (eg. @code{sleep}).
+
+@item
+All queries that produce results, e.g. @code{SELECT}, @code{SHOW},
+@code{EXPLAIN}, etc., must be preceded with @code{@@/path/to/result/file}. The
+file must contain the expected results. An easy way to generate the result
+file is to run @code{mysqltest -r < t/test-case-name.test} from
+@code{mysql-test} directory, and then edit the generated result files, if
+needed, to adjust them to the expected output. In that case, be very careful
+about not adding or deleting any invisible characters - make sure to only
+change the text and/or delete lines. If you have to insert a line, make sure
+the fields are separated with a hard tab, and there is a hard tab at the end.
+You may want to use @code{od -c} to make sure your text editor has not messed
+anything up during edit. We, of course, hope that you will never have to edit
+the output of @code{mysqltest -r} as you only have to do it when you find a
+bug.
+
+@item
+To be consistent with our setup, you should put your result files in
+@code{mysql-test/r} directory and name them @code{test_name.result}. If the
+test produces more than one result, you should use @code{test_name.a.result},
+@code{test_name.b.result}, etc.
+
+@item
+If a statement returns an error, you should on the line before the statement
+specify with the @code{--error error-number}. The error number can be
+a list of possible error numbers separated with @code{','}.
+
+@item
+If you are writing a replication test case, you should on the first line of
+the test file, put @code{source include/master-slave.inc;}. To switch between
+master and slave, use @code{connection master;} and @code{connection slave;}.
+If you need to do something on an alternate connection, you can do
+@code{connection master1;} for the master, and @code{connection slave1;} for
+the slave.
+
+@item
+If you need to do something in a loop, you can use something like this:
+@example
+let $1=1000;
+while ($1)
+@{
+ # do your queries here
+ dec $1;
+@}
+@end example
+
+@item
+To sleep between queries, use the @code{sleep} command. It supports fractions
+of a second, so you can do @code{sleep 1.3;}, for example, to sleep 1.3
+seconds.
+
+@item
+To run the slave with additional options for your test case, put them
+in the command-line format in @code{mysql-test/t/test_name-slave.opt}. For
+the master, put them in @code{mysql-test/t/test_name-master.opt}.
+
+@item
+If you have a question about the test suite, or have a test case to contribute,
+e-mail to @email{internals@@lists.mysql.com}. As the list does not accept
+attachments, you should ftp all the relevant files to:
+@uref{ftp://support.mysql.com/pub/mysql/Incoming/}
+
+@end itemize
+
+
+@node Reporting mysqltest bugs, , extending mysqltest, MySQL test suite
+@subsubsection Reporting Bugs in the MySQL Test Suite
+
+If your MySQL version doesn't pass the test suite you should
+do the following:
+
+@itemize @bullet
+@item
+Don't send a bug report before you have found out as much as possible of
+what when wrong! When you do it, please use the @code{mysqlbug} script
+so that we can get information about your system and @code{MySQL}
+version. @xref{Bug reports}.
+@item
+Make sure to include the output of @code{mysql-test-run}, as well as
+contents of all @code{.reject} files in @code{mysql-test/r} directory.
+@item
+If a test in the test suite fails, check if the test fails also when run
+by its own:
+
+@example
+cd mysql-test
+mysql-test-run --local test-name
+@end example
+
+If this fails, then you should configure MySQL with
+@code{--with-debug} and run @code{mysql-test-run} with the
+@code{--debug} option. If this also fails send the trace file
+@file{var/tmp/master.trace} to ftp://support.mysql.com/pub/mysql/secret
+so that we can examine it. Please remember to also include a full
+description of your system, the version of the mysqld binary and how you
+compiled it.
+
+@item
+Try also to run @code{mysql-test-run} with the @code{--force} option to
+see if there is any other test that fails.
+
+@item
+If you have compiled MySQL yourself, check our manual for how
+to compile MySQL on your platform or, preferable, use one of
+the binaries we have compiled for you at
+@uref{http://www.mysql.com/downloads/}. All our standard binaries should
+pass the test suite !
+
+@item
+If you get an error, like @code{Result length mismatch} or @code{Result
+content mismatch} it means that the output of the test didn't match
+exactly the expected output. This could be a bug in MySQL or
+that your mysqld version produces slight different results under some
+circumstances.
+
+Failed test results are put in a file with the same base name as the
+result file with the @code{.reject} extension. If your test case is
+failing, you should do a diff on the two files. If you cannot see how
+they are different, examine both with @code{od -c} and also check their
+lengths.
+
+@item
+If a test fails totally, you should check the logs file in the
+@code{mysql-test/var/log} directory for hints of what went wrong.
+
+@item
+If you have compiled MySQL with debugging you can try to debug this
+by running @code{mysql-test-run} with the @code{--gdb} and/or @code{--debug}
+options.
+@xref{Making trace files}.
+
+If you have not compiled MySQL for debugging you should probably
+do that. Just specify the @code{--with-debug} options to @code{configure}!
+@xref{Installing source}.
+@end itemize
+
+
+@node Adding functions, Adding procedures, MySQL internals, Extending MySQL
@section Adding New Functions to MySQL
@cindex functions, new
@@ -42276,7 +44411,7 @@ to create and drop functions.
All active functions are reloaded each time the server starts, unless
you start @code{mysqld} with the @code{--skip-grant-tables} option. In
-this case, UDF initialization is skipped and UDFs are unavailable.
+this case, UDF initialisation is skipped and UDFs are unavailable.
(An active function is one that has been loaded with @code{CREATE FUNCTION}
and not removed with @code{DROP FUNCTION}.)
@@ -42285,6 +44420,10 @@ functions}. For the UDF mechanism to work, functions must be written in C or
C++, your operating system must support dynamic loading and you must have
compiled @code{mysqld} dynamically (not statically).
+Note that to make @code{AGGREGATE} work, you must have a
+@code{mysql.func} table that contains the column @code{type}. If this
+is not the case, you should run the script
+@code{mysql_fix_privilege_tables} to get this fixed.
@node Adding UDF, Adding native function, CREATE FUNCTION, Adding functions
@@ -42295,10 +44434,11 @@ compiled @code{mysqld} dynamically (not statically).
@cindex functions, user-definable, adding
@menu
-* UDF calling sequences:: UDF calling sequences
-* UDF arguments:: Argument processing
-* UDF return values:: Return values and error handling
-* UDF compiling:: Compiling and installing user-definable functions
+* UDF calling:: UDF Calling Sequences
+* UDF aggr. calling :: UDF Calling Sequences for aggregate functions
+* UDF arguments:: Argument Processing
+* UDF return values:: Return Values and Error Handling
+* UDF compiling:: Compiling and Installing User-definable Functions
@end menu
@@ -42315,7 +44455,7 @@ you are using @code{--with-mysqld-ldflags=-all-static} If you want to
use an UDF that needs to access symbols from @code{mysqld} (like the
@code{methaphone} example in @file{sql/udf_example.cc} that uses
@code{default_charset_info}), you must link the program with
-@code{-rdynamic}. (see @code{man dlopen}).
+@code{-rdynamic} (see @code{man dlopen}).
For each function that you want to use in SQL statements, you should define
corresponding C (or C++) functions. In the discussion below, the name
@@ -42340,7 +44480,7 @@ function is shown below:
@end multitable
@item @code{xxx_init()} (optional)
-The initialization function for @code{xxx()}. It can be used to:
+The initialisation function for @code{xxx()}. It can be used to:
@itemize @bullet
@item
@@ -42360,30 +44500,62 @@ Specify whether or not the result can be @code{NULL}.
@end itemize
@item @code{xxx_deinit()} (optional)
-The deinitialization function for @code{xxx()}. It should deallocate any
-memory allocated by the initialization function.
+The deinitialisation function for @code{xxx()}. It should deallocate any
+memory allocated by the initialisation function.
@end table
When a SQL statement invokes @code{XXX()}, MySQL calls the
-initialization function @code{xxx_init()} to let it perform any required
+initialisation function @code{xxx_init()} to let it perform any required
setup, such as argument checking or memory allocation. If @code{xxx_init()}
returns an error, the SQL statement is aborted with an error message and the
-main and deinitialization functions are not called. Otherwise, the main
+main and deinitialisation functions are not called. Otherwise, the main
function @code{xxx()} is called once for each row. After all rows have been
-processed, the deinitialization function @code{xxx_deinit()} is called so it
+processed, the deinitialisation function @code{xxx_deinit()} is called so it
can perform any required cleanup.
+For aggregate functions (like @code{SUM()}), you must also provide the
+following functions:
+
+@table @asis
+@item @code{xxx_reset()} (required)
+Reset sum and insert the argument as the initial value for a new group.
+@item @code{xxx_add()} (required)
+Add the argument to the old sum.
+@end table
+
+When using aggregate UDF functions MySQL works the following way:
+
+@enumerate
+@item
+Call @code{xxx_init()} to let the aggregate function allocate the memory it
+will need to store results.
+@item
+Sort the table according to the @code{GROUP BY} expression.
+@item
+For the first row in a new group, call the @code{xxx_reset()} function.
+@item
+For each new row that belongs in the same group, call the
+@code{xxx_add()} function.
+@item
+When the group changes or after the last row has been processed,
+call @code{xxx()} to get the result for the aggregate.
+@item
+Repeat 3-5 until all rows has been processed
+@item
+Call @code{xxx_deinit()} to let the UDF free any memory it has allocated.
+@end enumerate
+
All functions must be thread safe (not just the main function,
-but the initialization and deinitialization functions as well). This means
+but the initialisation and deinitialisation functions as well). This means
that you are not allowed to allocate any global or static variables that
change! If you need memory, you should allocate it in @code{xxx_init()}
and free it in @code{xxx_deinit()}.
-@node UDF calling sequences, UDF arguments, Adding UDF, Adding UDF
-@subsubsection UDF Calling Sequences
+@node UDF calling, UDF aggr. calling , Adding UDF, Adding UDF
+@subsubsection UDF Calling Sequences for simple functions
-@cindex calling sequences, UDF
+@cindex calling sequences for simple functions, UDF
The main function should be declared as shown below. Note that the return
type and parameters differ, depending on whether you will declare the SQL
@@ -42395,8 +44567,8 @@ For @code{STRING} functions:
@example
char *xxx(UDF_INIT *initid, UDF_ARGS *args,
- char *result, unsigned long *length,
- char *is_null, char *error);
+ char *result, unsigned long *length,
+ char *is_null, char *error);
@end example
@noindent
@@ -42415,7 +44587,7 @@ double xxx(UDF_INIT *initid, UDF_ARGS *args,
char *is_null, char *error);
@end example
-The initialization and deinitialization functions are declared like this:
+The initialisation and deinitialisation functions are declared like this:
@example
my_bool xxx_init(UDF_INIT *initid, UDF_ARGS *args, char *message);
@@ -42426,7 +44598,7 @@ void xxx_deinit(UDF_INIT *initid);
The @code{initid} parameter is passed to all three functions. It points to a
@code{UDF_INIT} structure that is used to communicate information between
functions. The @code{UDF_INIT} structure members are listed below. The
-initialization function should fill in any members that it wishes to change.
+initialisation function should fill in any members that it wishes to change.
(To use the default for a member, leave it unchanged.):
@table @code
@@ -42449,6 +44621,10 @@ digits. For real functions, the default is 13 plus the number of decimals
indicated by @code{initid->decimals}. (For numeric functions, the length
includes any sign or decimal point characters.)
+If you want to return a blob, you can set this to 65K or 16M; This
+memory is not allocated but used to decide which column type to use if
+there is a need to temporary store the data.
+
@item char *ptr
A pointer that the function can use for its own purposes. For example,
functions can use @code{initid->ptr} to communicate allocated memory
@@ -42464,18 +44640,73 @@ or deallocate the memory.
@end table
-@node UDF arguments, UDF return values, UDF calling sequences, Adding UDF
+@node UDF aggr. calling , UDF arguments, UDF calling, Adding UDF
+@subsubsection UDF Calling Sequences for aggregate functions
+
+@cindex calling sequences for aggregate functions, UDF
+
+Here follows a description of the different functions you need to define
+when you want to create an aggregate UDF function.
+
+@example
+char *xxx_reset(UDF_INIT *initid, UDF_ARGS *args,
+ char *is_null, char *error);
+@end example
+
+This function is called when MySQL finds the first row in a new group.
+In the function you should reset any internal summary variables and then set
+the given argument as the first argument in the group.
+
+In many cases this is implemented internally by reseting all variables
+and then calling @code{xxx_add()}.
+
+@example
+char *xxx_add(UDF_INIT *initid, UDF_ARGS *args,
+ char *is_null, char *error);
+@end example
+
+This function is called for all rows that belongs to the same group,
+except for the first row. In this you should add the value in UDF_ARGS
+to your internal summary variable.
+
+The @code{xxx()} function should be declared identical as when you
+define a simple UDF function. @xref{UDF calling}.
+
+This function is called when all rows in the group has been processed.
+You should normally never access the @code{args} variable here but
+return your value based on your internal summary variables.
+
+All argument processing in @code{xxx_reset()} and @code{xxx_add()}
+should be done identically as for normal UDF functions. @xref{UDF
+arguments}.
+
+The return value handling in @code{xxx()} should be done identically as
+for a normal UDF. @xref{UDF return values}.
+
+The pointer argument to @code{is_null} and @code{error} is the same for
+all calls to @code{xxx_reset()}, @code{xxx_add()} and @code{xxx()}.
+You can use this to remember that you got an error or if the @code{xxx()}
+function should return @code{NULL}. Note that you should not store a string
+into @code{*error}! This is just a 1 byte flag!
+
+@code{is_null} is reset for each group (before calling @code{xxx_reset()}.
+@code{error} is never reset.
+
+If @code{isnull} or @code{error} are set after @code{xxx()} then MySQL
+will return @code{NULL} as the result for the group function.
+
+@node UDF arguments, UDF return values, UDF aggr. calling , Adding UDF
@subsubsection Argument Processing
@cindex argument processing
@cindex processing, arguments
-The @code{args} parameter points to a @code{UDF_ARGS} structure that thas the
+The @code{args} parameter points to a @code{UDF_ARGS} structure that has the
members listed below:
@table @code
@item unsigned int arg_count
-The number of arguments. Check this value in the initialization function
+The number of arguments. Check this value in the initialisation function
if you want your function to be called with a particular number of arguments.
For example:
@@ -42493,7 +44724,7 @@ The types for each argument. The possible type values are
@code{STRING_RESULT}, @code{INT_RESULT}, and @code{REAL_RESULT}.
To make sure that arguments are of a given type and return an
-error if they are not, check the @code{arg_type} array in the initialization
+error if they are not, check the @code{arg_type} array in the initialisation
function. For example:
@example
@@ -42506,7 +44737,7 @@ if (args->arg_type[0] != STRING_RESULT ||
@end example
As an alternative to requiring your function's arguments to be of particular
-types, you can use the initialization function to set the @code{arg_type}
+types, you can use the initialisation function to set the @code{arg_type}
elements to the types you want. This causes MySQL to coerce
arguments to those types for each call to @code{xxx()}. For example, to
specify coercion of the first two arguments to string and integer, do this in
@@ -42518,7 +44749,7 @@ args->arg_type[1] = INT_RESULT;
@end example
@item char **args
-@code{args->args} communicates information to the initialization function
+@code{args->args} communicates information to the initialisation function
about the general nature of the arguments your function was called with. For a
constant argument @code{i}, @code{args->args[i]} points to the argument
value. (See below for instructions on how to access the value properly.)
@@ -42561,12 +44792,13 @@ real_val = *((double*) args->args[i]);
@end itemize
@item unsigned long *lengths
-For the initialization function, the @code{lengths} array indicates the
-maximum string length for each argument. For each invocation of the main
-function, @code{lengths} contains the actual lengths of any string arguments
-that are passed for the row currently being processed. For arguments of
-types @code{INT_RESULT} or @code{REAL_RESULT}, @code{lengths} still contains
-the maximum length of the argument (as for the initialization function).
+For the initialisation function, the @code{lengths} array indicates the
+maximum string length for each argument. You should not change these.
+For each invocation of the main function, @code{lengths} contains the
+actual lengths of any string arguments that are passed for the row
+currently being processed. For arguments of types @code{INT_RESULT} or
+@code{REAL_RESULT}, @code{lengths} still contains the maximum length of
+the argument (as for the initialisation function).
@end table
@@ -42578,7 +44810,7 @@ the maximum length of the argument (as for the initialization function).
@cindex errors, handling for UDFs
@cindex handling, errors
-The initialization function should return @code{0} if no error occurred and
+The initialisation function should return @code{0} if no error occurred and
@code{1} otherwise. If an error occurs, @code{xxx_init()} should store a
null-terminated error message in the @code{message} parameter. The message
will be returned to the client. The message buffer is
@@ -42589,7 +44821,8 @@ terminal screen.
The return value of the main function @code{xxx()} is the function value, for
@code{long long} and @code{double} functions. A string functions should
return a pointer to the result and store the length of the string in the
-@code{length} arguments. @code{result} is a buffer at least 255 bytes long.
+@code{length} arguments.
+
Set these to the contents and length of the return value. For example:
@example
@@ -42597,12 +44830,16 @@ memcpy(result, "result string", 13);
*length = 13;
@end example
-If your string functions that needs to return a string longer than 255
-bytes, you must allocate the space for it with @code{malloc()} in your
+The @code{result} buffer that is passed to the calc function is 255 byte
+big. If your result fits in this, you don't have to worry about memory
+allocation for results.
+
+If your string function needs to return a string longer than 255 bytes,
+you must allocate the space for it with @code{malloc()} in your
@code{xxx_init()} function or your @code{xxx()} function and free it in
your @code{xxx_deinit()} function. You can store the allocated memory
in the @code{ptr} slot in the @code{UDF_INIT} structure for reuse by
-future @code{xxx()} calls. @xref{UDF calling sequences}.
+future @code{xxx()} calls. @xref{UDF calling}.
To indicate a return value of @code{NULL} in the main function, set
@code{is_null} to @code{1}:
@@ -42621,7 +44858,7 @@ parameter to @code{1}:
If @code{xxx()} sets @code{*error} to @code{1} for any row, the function
value is @code{NULL} for the current row and for any subsequent rows
processed by the statement in which @code{XXX()} was invoked. (@code{xxx()}
-will not even be called for subsequent rows.) @strong{NOTE:} In
+will not even be called for subsequent rows.) @strong{Note:} In
MySQL versions prior to 3.22.10, you should set both @code{*error}
and @code{*is_null}:
@@ -42703,6 +44940,7 @@ mysql> CREATE FUNCTION myfunc_double RETURNS REAL SONAME "udf_example.so";
mysql> CREATE FUNCTION myfunc_int RETURNS INTEGER SONAME "udf_example.so";
mysql> CREATE FUNCTION lookup RETURNS STRING SONAME "udf_example.so";
mysql> CREATE FUNCTION reverse_lookup RETURNS STRING SONAME "udf_example.so";
+mysql> CREATE AGGREGATE FUNCTION avgcost RETURNS REAL SONAME "udf_example.so";
@end example
Functions can be deleted using @code{DROP FUNCTION}:
@@ -42713,6 +44951,7 @@ mysql> DROP FUNCTION myfunc_double;
mysql> DROP FUNCTION myfunc_int;
mysql> DROP FUNCTION lookup;
mysql> DROP FUNCTION reverse_lookup;
+mysql> DROP FUNCTION avgcost;
@end example
The @code{CREATE FUNCTION} and @code{DROP FUNCTION} statements update the
@@ -42730,7 +44969,7 @@ will continue to use the old version.
Active functions are reloaded each time the server starts, unless you start
@code{mysqld} with the @code{--skip-grant-tables} option. In this case, UDF
-initialization is skipped and UDFs are unavailable. (An active function is
+initialisation is skipped and UDFs are unavailable. (An active function is
one that has been loaded with @code{CREATE FUNCTION} and not removed with
@code{DROP FUNCTION}.)
@@ -42805,7 +45044,7 @@ can take a look at @code{Item_func_mod::fix_length_and_dec} for a
typical example of how to do this.
@end enumerate
-All functions must be thread safe (In other words, don't use any global or
+All functions must be thread safe (in other words, don't use any global or
static variables in the functions without protecting them with mutexes).
If you want to return @code{NULL}, from @code{::val()}, @code{::val_int()}
@@ -42828,7 +45067,7 @@ absolutely necessary!
@end itemize
-@node Adding procedures, MySQL internals, Adding functions, Extending MySQL
+@node Adding procedures, , Adding functions, Extending MySQL
@section Adding New Procedures to MySQL
@cindex procedures, adding
@@ -42842,8 +45081,9 @@ can be done on row-by-row or @code{GROUP BY} level.
We have created an example procedure in MySQL Version 3.23 to
show you what can be done.
-Additionally we recommend you to take a look at 'mylua', which you can find in the Contrib directory. @xref{Contrib}. Which this you can use the LUA
-language to load a procedure at runtime into @code{mysqld}.
+Additionally we recommend you to take a look at @code{mylua}.
+With this you can use the LUA language to load a procedure at
+runtime into @code{mysqld}.
@menu
* procedure analyse:: Procedure analyse
@@ -42890,292 +45130,7 @@ You can find all information about procedures by examining the following files:
@end itemize
-@node MySQL internals, , Adding procedures, Extending MySQL
-@section MySQL Internals
-
-@cindex internals
-@cindex threads
-
-This chapter describes a lot of things that you need to know when
-working on the MySQL code. If you plan to contribute to MySQL
-development, want to have access to the bleeding-edge in-between
-versions code, or just want to keep track of development, follow the
-instructions in @xref{Installing source tree}. If you are interested in MySQL
-internals, you should also subscribe to @email{internals@@lists.mysql.com}.
-This is a relatively low traffic list, in comparison with
-@email{mysql@@lists.mysql.com}.
-
-@menu
-* MySQL threads:: MySQL threads
-* MySQL test suite:: MySQL test suite
-@end menu
-
-
-@node MySQL threads, MySQL test suite, MySQL internals, MySQL internals
-@subsection MySQL Threads
-
-The MySQL server creates the following threads:
-
-@itemize @bullet
-
-@item
-The TCP/IP connection thread handles all connection requests and
-creates a new dedicated thread to handle the authentication and
-and SQL query processing for each connection.
-
-@item
-On Windows NT there is a named pipe handler thread that does the same work as
-the TCP/IP connection thread on named pipe connect requests.
-
-@item
-The signal thread handles all signals. This thread also normally handles
-alarms and calls @code{process_alarm()} to force timeouts on connections
-that have been idle too long.
-
-@item
-If @code{mysqld} is compiled with @code{-DUSE_ALARM_THREAD}, a dedicated
-thread that handles alarms is created. This is only used on some systems where
-there are problems with @code{sigwait()} or if one wants to use the
-@code{thr_alarm()} code in ones application without a dedicated signal
-handling thread.
-
-@item
-If one uses the @code{--flush_time=#} option, a dedicated thread is created
-to flush all tables at the given interval.
-
-@item
-Every connection has its own thread.
-
-@item
-Every different table on which one uses @code{INSERT DELAYED} gets its
-own thread.
-
-@item
-If you use @code{--master-host}, a slave replication thread will be
-started to read and apply updates from the master.
-@end itemize
-
-@code{mysqladmin processlist} only shows the connection, @code{INSERT DELAYED},
-and replication threads.
-
-
-@node MySQL test suite, , MySQL threads, MySQL internals
-@subsection MySQL Test Suite
-
-@cindex mysqltest, MySQL Test Suite
-@cindex testing mysqld, mysqltest
-
-Until recently, our main full-coverage test suite was based on proprietary
-customer data and for that reason has not been publicly available. The only
-publicly available part of our testing process consisted of the @code{crash-me}
-test, a Perl DBI/DBD benchmark found in the @code{sql-bench} directory, and
-miscellaneous tests located in @code{tests} directory. The lack of a
-standardized publicly available test suite has made it difficult for our users,
-as well developers, to do regression tests on the MySQL code. To
-address this problem, we have created a new test system that is included in
-the source and binary distributions starting in Version 3.23.29.
-
-The current set of test cases doesn't test everything in MySQL, but it
-should catch most obvious bugs in the SQL processing code, OS/library
-issues, and is quite thorough in testing replication. Our eventual goal
-is to have the tests cover 100% of the code. We welcome contributions
-to our test suite. You may especially want to contribute tests that
-examine the functionality critical to your system, as this will ensure
-that all future MySQL releases will work well with your
-applications.
-
-@menu
-* running mysqltest:: Running the MySQL Test Suite
-* extending mysqltest:: Extending the MySQL Test Suite
-* Reporting mysqltest bugs:: Reporting Bugs in the MySQL Test Suite
-@end menu
-
-
-@node running mysqltest, extending mysqltest, MySQL test suite, MySQL test suite
-@subsubsection Running the MySQL Test Suite
-
-The test system consist of a test language interpreter
-(@code{mysqltest}), a shell script to run all
-tests(@code{mysql-test-run}), the actual test cases written in a special
-test language, and their expected results. To run the test suite on
-your system after a build, type @code{make test} or
-@code{mysql-test/mysql-test-run} from the source root. If you have
-installed a binary distribution, @code{cd} to the install root
-(eg. @code{/usr/local/mysql}), and do @code{scripts/mysql-test-run}.
-All tests should succeed. If not, you should try to find out why and
-report the problem if this is a bug in MySQL.
-@xref{Reporting mysqltest bugs}.
-
-If you have a copy of @code{mysqld} running on the machine where you want to
-run the test suite you do not have to stop it, as long as it is not using
-ports @code{9306} and @code{9307}. If one of those ports is taken, you should
-edit @code{mysql-test-run} and change the values of the master and/or slave
-port to one that is available.
-
-You can run one individual test case with
-@code{mysql-test/mysql-test-run test_name}.
-
-If one test fails, you should test running @code{mysql-test-run} with
-the @code{--force} option to check if any other tests fails.
-
-
-@node extending mysqltest, Reporting mysqltest bugs, running mysqltest, MySQL test suite
-@subsubsection Extending the MySQL Test Suite
-
-You can use the @code{mysqltest} language to write your own test cases.
-Unfortunately, we have not yet written full documentation for it - we plan to
-do this shortly. You can, however, look at our current test cases and use
-them as an example. The following points should help you get started:
-
-@itemize @bullet
-@item
-The tests are located in @code{mysql-test/t/*.test}
-
-@item
-A test case consists of @code{;} terminated statements and is similar to the
-input of @code{mysql} command line client. A statement by default is a query
-to be sent to MySQL server, unless it is recognized as internal
-command ( eg. @code{sleep} ).
-
-@item
-All queries that produce results, e.g. @code{SELECT}, @code{SHOW},
-@code{EXPLAIN}, etc., must be preceded with @code{@@/path/to/result/file}. The
-file must contain the expected results. An easy way to generate the result
-file is to run @code{mysqltest -r < t/test-case-name.test} from
-@code{mysql-test} directory, and then edit the generated result files, if
-needed, to adjust them to the expected output. In that case, be very careful
-about not adding or deleting any invisible characters - make sure to only
-change the text and/or delete lines. If you have to insert a line, make sure
-the fields are separated with a hard tab, and there is a hard tab at the end.
-You may want to use @code{od -c} to make sure your text editor has not messed
-anything up during edit. We, of course, hope that you will never have to edit
-the output of @code{mysqltest -r} as you only have to do it when you find a
-bug.
-
-@item
-To be consistent with our setup, you should put your result files in
-@code{mysql-test/r} directory and name them @code{test_name.result}. If the
-test produces more than one result, you should use @code{test_name.a.result},
-@code{test_name.b.result}, etc.
-
-@item
-If a statement returns an error, you should on the line before the statement
-specify with the @code{--error error-number}. The error number can be
-a list of possible error numbers separated with @code{','}.
-
-@item
-If you are writing a replication test case, you should on the first line of
-the test file, put @code{source include/master-slave.inc;}. To switch between
-master and slave, use @code{connection master;} and @code{connection slave;}.
-If you need to do something on an alternate connection, you can do
-@code{connection master1;} for the master, and @code{connection slave1;} for
-the slave.
-
-@item
-If you need to do something in a loop, you can use something like this:
-@example
-let $1=1000;
-while ($1)
-@{
- # do your queries here
- dec $1;
-@}
-@end example
-
-@item
-To sleep between queries, use the @code{sleep} command. It supports fractions
-of a second, so you can do @code{sleep 1.3;}, for example, to sleep 1.3
-seconds.
-
-@item
-To run the slave with additional options for your test case, put them
-in the command-line format in @code{mysql-test/t/test_name-slave.opt}. For
-the master, put them in @code{mysql-test/t/test_name-master.opt}.
-
-@item
-If you have a question about the test suite, or have a test case to contribute,
-e-mail to @email{internals@@lists.mysql.com}. As the list does not accept
-attachments, you should ftp all the relevant files to:
-@url{ftp://support.mysql.com/pub/mysql/Incoming}
-
-@end itemize
-
-
-@node Reporting mysqltest bugs, , extending mysqltest, MySQL test suite
-@subsubsection Reporting Bugs in the MySQL Test Suite
-
-If your MySQL version doesn't pass the test suite you should
-do the following:
-
-@itemize @bullet
-@item
-Don't send a bug report before you have found out as much as possible of
-what when wrong! When you do it, please use the @code{mysqlbug} script
-so that we can get information about your system and @code{MySQL}
-version. @xref{Bug reports}.
-@item
-Make sure to include the output of @code{mysql-test-run}, as well as
-contents of all @code{.reject} files in @code{mysql-test/r} directory.
-@item
-If a test in the test suite fails, check if the test fails also when run
-by its own:
-
-@example
-cd mysql-test
-mysql-test-run --local test-name
-@end example
-
-If this fails, then you should configure MySQL with
-@code{--with-debug} and run @code{mysql-test-run} with the
-@code{--debug} option. If this also fails send the trace file
-@file{var/tmp/master.trace} to ftp://support.mysql.com/pub/mysql/secret
-so that we can examine it. Please remember to also include a full
-description of your system, the version of the mysqld binary and how you
-compiled it.
-
-@item
-Try also to run @code{mysql-test-run} with the @code{--force} option to
-see if there is any other test that fails.
-
-@item
-If you have compiled MySQL yourself, check our manual for how
-to compile MySQL on your platform or, preferable, use one of
-the binaries we have compiled for you at
-@uref{http://www.mysql.com/downloads/}. All our standard binaries should
-pass the test suite !
-
-@item
-If you get an error, like @code{Result length mismatch} or @code{Result
-content mismatch} it means that the output of the test didn't match
-exactly the expected output. This could be a bug in MySQL or
-that your mysqld version produces slight different results under some
-circumstances.
-
-Failed test results are put in a file with the same base name as the
-result file with the @code{.reject} extension. If your test case is
-failing, you should do a diff on the two files. If you cannot see how
-they are different, examine both with @code{od -c} and also check their
-lengths.
-
-@item
-If a test fails totally, you should check the logs file in the
-@code{mysql-test/var/log} directory for hints of what went wrong.
-
-@item
-If you have compiled MySQL with debugging you can try to debug this
-by running @code{mysql-test-run} with the @code{--gdb} and/or @code{--debug}
-options.
-@xref{Making trace files}.
-
-If you have not compiled MySQL for debugging you should probably
-do that. Just specify the @code{--with-debug} options to @code{configure}!
-@xref{Installing source}.
-@end itemize
-
-
-
-
-@node Problems, Users, Extending MySQL, Top
+@node Problems, Contrib, Extending MySQL, Top
@appendix Problems and Common Errors
@cindex problems, common errors
@@ -43183,7 +45138,7 @@ do that. Just specify the @code{--with-debug} options to @code{configure}!
@menu
* What is crashing:: How to determine what is causing problems
-* Common errors:: Some common errors when using MySQL
+* Common errors:: Common Errors When Using MySQL
* Installation Issues:: Installation Related Issues
* Administration Issues:: Administration Related Issues
* Query Issues:: Query Related Issues
@@ -43220,7 +45175,7 @@ The machine doesn't answer to a remote machine's pings.
Different, unrelated programs don't behave correctly.
@item
If your system rebooted unexpectedly (a faulty user level program should
-NEVER be able to take down your system).
+@strong{never} be able to take down your system).
@end itemize
In this case you should start by checking all your cables and run some
@@ -43295,7 +45250,7 @@ described in this manual. @xref{Asking questions}.
@node Common errors, Installation Issues, What is crashing, Problems
-@appendixsec Some Common Errors When Using MySQL
+@appendixsec Common Errors When Using MySQL
@cindex errors, list of
@@ -43314,7 +45269,7 @@ described in this manual. @xref{Asking questions}.
* Commands out of sync:: @code{Commands out of sync} error in client
* Ignoring user:: @code{Ignoring user} error
* Cannot find table:: @code{Table 'xxx' doesn't exist} error
-* Cannot initialize character set:: @code{Can@'t initialize character set xxx} error.
+* Cannot initialize character set:: @code{Can't initialize character set xxx} error
* Not enough file handles:: File Not Found
@end menu
@@ -43359,6 +45314,7 @@ You normally can get the following error codes in this case
(which one you get is OS-dependent):
@multitable @columnfractions .3 .7
+@item @strong{Error code} @tab @strong{Description}
@item @code{CR_SERVER_GONE_ERROR} @tab The client couldn't send a question to the
server.
@item @code{CR_SERVER_LOST} @tab The client didn't get an error when writing
@@ -43473,7 +45429,7 @@ problem is :
@itemize @bullet
@item
Check if the server is up by doing @code{telnet your-host-name
-tcp-ip-port-number} and press @code{RETURN} a couple of times. If there
+tcp-ip-port-number} and press Enter a couple of times. If there
is a MySQL server running on this port you should get a
responses that includes the version number of the running MySQL
server. If you get an error like @code{telnet: Unable to connect to
@@ -43598,16 +45554,36 @@ When a MySQL client or the @code{mysqld} server gets a packet bigger
than @code{max_allowed_packet} bytes, it issues a @code{Packet too large}
error and closes the connection.
-If you are using the @code{mysql} client, you may specify a bigger buffer by
-starting the client with @code{mysql --set-variable=max_allowed_packet=8M}.
+In MySQL 3.23 the biggest possible packet is 16M (due to limits in the
+client/server protocol). In MySQL 4.0.1 and up, this is only limited by
+the amount on memory you have on your server (up to a theoretical
+maximum of 2G).
-If you are using other clients that do not allow you to specify the maximum
-packet size (such as @code{DBI}), you need to set the packet size when you
-start the server. You cau use a command-line option to @code{mysqld} to set
-@code{max_allowed_packet} to a larger size. For example, if you are
-expecting to store the full length of a @code{BLOB} into a table, you'll need
-to start the server with the @code{--set-variable=max_allowed_packet=16M}
-option.
+A communication packet is a single SQL statement sent to the MySQL server
+or a single row that is sent to the client.
+
+When a MySQL client or the @code{mysqld} server gets a packet bigger
+than @code{max_allowed_packet} bytes, it issues a @code{Packet too
+large} error and closes the connection. With some clients, you may also
+get @code{Lost connection to MySQL server during query} error if the
+communication packet is too big.
+
+Note that both the client and the server has it's own
+@code{max_allowed_packet} variable. If you want to handle big packets,
+you have to increase this variable both in the client and in the server.
+
+It's safe to increase this variable as memory is only allocated when
+needed; This variable is more a precaution to catch wrong packets
+between the client/server and also to ensure that you don't accidently
+use big packets so that you run out of memory.
+
+If you are using the @code{mysql} client, you may specify a bigger
+buffer by starting the client with @code{mysql --set-variable=max_allowed_packet=8M}. Other clients have different methods to set this variable.
+
+You can use the option file to set @code{max_allowed_packet} to a larger
+size in @code{mysqld}. For example, if you are expecting to store the
+full length of a @code{MEDIUMBLOB} into a table, you'll need to start
+the server with the @code{set-variable=max_allowed_packet=16M} option.
You can also get strange problems with large packets if you are using
big blobs, but you haven't given @code{mysqld} access to enough memory
@@ -43817,7 +45793,7 @@ You can check which tables you have in the current database with
@node Cannot initialize character set, Not enough file handles, Cannot find table, Common errors
-@appendixsubsec @code{Can@'t initialize character set xxx} error.
+@appendixsubsec @code{Can't initialize character set xxx} error
@cindex multibyte character sets
@@ -43909,8 +45885,8 @@ number 256 to affect the number of file descriptors available to
@code{ulimit} (and @code{open-files-limit}) can increase the number of
file descriptors, but only up to the limit imposed by the operating
system. There is also a 'hard' limit that can only be overrided if you
-start @code{safe_mysqld} or @code{mysqld} as root (Just remember that
-you need to also use the @code{--user=..} option in this case). If you
+start @code{safe_mysqld} or @code{mysqld} as root (just remember that
+you need to also use the @code{--user=...} option in this case). If you
need to increase the OS limit on the number of file descriptors
available to each process, consult the documentation for your operating
system.
@@ -43950,10 +45926,10 @@ symbols that start with @code{mysql_}, like the following:
@end example
you should be able to solve this by adding @code{-Lpath-to-the-mysql-library
--lmysqlclient} @strong{LAST} on your link line.
+-lmysqlclient} @strong{last} on your link line.
If you get @code{undefined reference} errors for the @code{uncompress}
-or @code{compress} function, add @code{-lz} @strong{LAST} on your link
+or @code{compress} function, add @code{-lz} @strong{last} on your link
line and try again!
If you get @code{undefined reference} errors for functions that should
@@ -44523,6 +46499,7 @@ the server runs, for example, in @code{safe_mysqld} or @code{mysql.server}.
* Problems with alias:: Problems with @code{alias}
* Deleting from related tables:: Deleting Rows from Related Tables
* No matching rows:: Solving Problems with No Matching Rows
+* Problems with float:: Problems with floating point comparison
@end menu
@node Case sensitivity, Using DATE, Query Issues, Query Issues
@@ -44765,7 +46742,7 @@ id's per query if the @code{related_column} is an index. If the
number of arguments in the @code{IN} clause.
-@node No matching rows, , Deleting from related tables, Query Issues
+@node No matching rows, Problems with float, Deleting from related tables, Query Issues
@appendixsubsec Solving Problems with No Matching Rows
@cindex no matching rows
@@ -44793,16 +46770,10 @@ the table that was last removed from the query.
@item
If you are comparing @code{FLOAT} or @code{DOUBLE} columns with numbers that
-have decimals, you can't use @code{=}! This problem is common in most
-computer languages because floating-point values are not exact values:
-
-@example
-mysql> SELECT * FROM table_name WHERE float_column=3.5;
- ->
-mysql> SELECT * FROM table_name WHERE float_column between 3.45 and 3.55;
-@end example
-
-In most cases, changing the @code{FLOAT} to a @code{DOUBLE} will fix this!
+have decimals, you can't use @code{'='}. This problem is common in most
+computer languages because floating-point values are not exact values.
+In most cases, changing the @code{FLOAT} to a @code{DOUBLE} will fix this.
+@xref{Problems with float}.
@item
If you still can't figure out what's wrong, create a minimal test that can
@@ -44820,6 +46791,128 @@ shell> mysql test2 < query.sql
Post the test file using @code{mysqlbug} to @email{mysql@@lists.mysql.com}.
@end enumerate
+@node Problems with float, , No matching rows, Query Issues
+@appendixsubsec Problems with floating point comparison
+
+Floating point numbers cause confusion sometimes, because these numbers
+are not stored as exact values inside computer architecture. What one
+can see on the screen usually is not the exact value of the number.
+
+Field types @code{FLOAT}, @code{DOUBLE} and @code{DECIMAL} are such.
+
+@example
+CREATE TABLE t1 (i int, d1 decimal(9,2), d2 decimal(9,2));
+INSERT INTO t1 values (1, 101.40, 21.40), (1, -80.00, 0.00), (2, 0.00, 0.00),
+(2, -13.20, 0.00), (2, 59.60, 46.40), (2, 30.40, 30.40), (3, 37.00, 7.40),
+(3, -29.60, 0.00), (4, 60.00, 15.40), (4, -10.60, 0.00), (4, -34.00, 0.00),
+(5, 33.00, 0.00), (5, -25.80, 0.00), (5, 0.00, 7.20), (6, 0.00, 0.00),
+(6, -51.40, 0.00);
+
+mysql> SELECT i, SUM(d1) AS a, SUM(d2) AS b FROM t1 GROUP BY i HAVING a <> b;
++------+--------+-------+
+| i | a | b |
++------+--------+-------+
+| 1 | 21.40 | 21.40 |
+| 2 | 76.80 | 76.80 |
+| 3 | 7.40 | 7.40 |
+| 4 | 15.40 | 15.40 |
+| 5 | 7.20 | 7.20 |
+| 6 | -51.40 | 0.00 |
++------+--------+-------+
+@end example
+
+The result is correct. Although the first five records look like they
+shouldn't pass the comparison test, they may do so because the
+difference between the numbers show up around tenth decimal, or so
+depending on computer architecture.
+
+The problem cannot be solved by using ROUND() (or similar function),
+because the result is still a floating point number. Example:
+
+@example
+mysql> SELECT i, ROUND(SUM(d1), 2) AS a, ROUND(SUM(d2), 2) AS b FROM t1 GROUP BY i HAVING a <> b;
++------+--------+-------+
+| i | a | b |
++------+--------+-------+
+| 1 | 21.40 | 21.40 |
+| 2 | 76.80 | 76.80 |
+| 3 | 7.40 | 7.40 |
+| 4 | 15.40 | 15.40 |
+| 5 | 7.20 | 7.20 |
+| 6 | -51.40 | 0.00 |
++------+--------+-------+
+@end example
+
+This is what the numbers in row 'a' look like:
+@example
+mysql> SELECT i, ROUND(SUM(d1), 2)*1.0000000000000000 AS a, ROUND(SUM(d2), 2) AS b FROM t1 GROUP BY i HAVING a <> b;
++------+----------------------+-------+
+| i | a | b |
++------+----------------------+-------+
+| 1 | 21.3999999999999986 | 21.40 |
+| 2 | 76.7999999999999972 | 76.80 |
+| 3 | 7.4000000000000004 | 7.40 |
+| 4 | 15.4000000000000004 | 15.40 |
+| 5 | 7.2000000000000002 | 7.20 |
+| 6 | -51.3999999999999986 | 0.00 |
++------+----------------------+-------+
+@end example
+
+Depending on the computer architecture you may or may not see similar results.
+Each CPU may evaluate floating point numbers differently. For example in
+some machines you may get 'right' results by multiplaying both arguments
+with 1, an example follows.
+
+@strong{WARNING: NEVER TRUST THIS METHOD IN YOUR APPLICATION, THIS IS
+AN EXAMPLE OF A WRONG METHOD!!!}
+
+@example
+mysql> SELECT i, ROUND(SUM(d1), 2)*1 AS a, ROUND(SUM(d2), 2)*1 AS b FROM t1 GROUP
+BY i HAVING a <> b;
++------+--------+------+
+| i | a | b |
++------+--------+------+
+| 6 | -51.40 | 0.00 |
++------+--------+------+
+@end example
+
+The reason why the above example seems to be working is that on the
+particular machine where the test was done, the CPU floating point
+arithmetics happens to round the numbers to same, but there is no
+rule that any CPU should do so, so it cannot be trusted.
+
+The correct way to do floating point number comparison is to first
+decide on what is the wanted tolerance between the numbers and then do
+the comparsion against the tolerance number. For example, if we agree on
+that floating point numbers should be regarded the same, if they are
+same with precision of one of ten thousand (0.0001), the comparsion
+should be done like this:
+
+@example
+mysql> SELECT i, SUM(d1) AS a, SUM(d2) AS b FROM t1 GROUP BY i HAVING ABS(a - b) > 0.0001;
++------+--------+------+
+| i | a | b |
++------+--------+------+
+| 6 | -51.40 | 0.00 |
++------+--------+------+
+1 row in set (0.00 sec)
+@end example
+
+And vice versa, if we wanted to get rows where the numbers are the same,
+the test would be:
+
+@example
+mysql> SELECT i, SUM(d1) AS a, SUM(d2) AS b FROM t1 GROUP BY i HAVING ABS(a - b) < 0.0001;
++------+-------+-------+
+| i | a | b |
++------+-------+-------+
+| 1 | 21.40 | 21.40 |
+| 2 | 76.80 | 76.80 |
+| 3 | 7.40 | 7.40 |
+| 4 | 15.40 | 15.40 |
+| 5 | 7.20 | 7.20 |
++------+-------+-------+
+@end example
@node Table Definition Issues, , Query Issues, Problems
@appendixsec Table Definition Related Issues
@@ -44894,9 +46987,9 @@ SELECT col_name1, col_name3, col_name2 FROM tbl_name;
will return columns in the order @code{col_name1}, @code{col_name3}, @code{col_name2}.
-You should @strong{NEVER}, in an application, use @code{SELECT *} and
+You should @strong{never}, in an application, use @code{SELECT *} and
retrieve the columns based on their position, because the order in which
-columns are returned @strong{CANNOT} be guaranteed over time. A simple
+columns are returned @strong{cannot} be guaranteed over time. A simple
change to your database may cause your application to fail rather
dramatically.
@@ -44945,469 +47038,7 @@ We plan to fix the above in 4.0.
-@node Users, MySQL customer usage, Problems, Top
-@appendix Some MySQL Users
-
-@cindex users, of MySQL
-@cindex news sites
-
-This appendix lists some users of MySQL that have given us permission
-to list them in our documentation. It is by far not a complete list, but
-should give you a general idea of who uses MySQL and what it can
-be used for.
-
-@appendixsec General News Sites
-
-@itemize @bullet
-
-@item @uref{http://www.yahoo.com/, Yahoo!}
-
-@item @uref{http://slashdot.org/, Slashdot: A pro-Linux/tech news and comment/discussion site}
-
-@item @uref{http://www.linux.com/, All about Linux}
-
-@item @uref{http://www.linuxtoday.com/, Linuxtoday}
-
-@item @uref{http://www.32bitsonline.com/, 32Bits Online: because there's
-more than one way to compute}
-
-@item @uref{http://www.freshmeat.net/, Freshmeat: News about new versions of computer-related stuff}
-
-@end itemize
-
-@cindex search engines, web
-@cindex web search engines
-@appendixsec Some Web Search Engines
-
-@itemize @bullet
-
-@item @uref{http://www.aaa.com.au, AAA Matilda Web Search}
-
-@item @uref{http://www.whatsnu.com/, What's New}
-
-@item @uref{http://www.aladin.de/, Aladin}
-
-@item @uref{http://www.columbus-finder.de/, Columbus Finder}
-
-@item @uref{http://www.spider.de/, Spider}
-
-@item @uref{http://www.blitzsuche.de/, Blitzsuche}
-
-@item @uref{http://www.indoseek.co.id, Indoseek Indonesia}
-
-@item @uref{http://www.yaboo.dk/, Yaboo - Yet Another BOOkmarker}
-
-
-@item @uref{http://www.ozsearch.com.au, OzSearch Internet Guide}
-
-@item @uref{http://www.splatsearch.com/, Splat! Search}
-
-@item @uref{http://osdls.library.arizona.edu/, The Open Source Digital Library System Project}
-@end itemize
-
-@appendixsec Some Information Search Engines Concentrated on Some Area
-
-@itemize @bullet
-
-@item @uref{http://www.spylog.ru/, SpyLOG ; A very popular Web counter site}
-
-@item @uref{http://www.tucows.com/, TuCows Network; Free Software archive}
-
-@item @uref{http://www.jobvertise.com,Jobvertise: Post and search for jobs}
-
-@item @uref{http://www.musicdatabase.com, The Music Database}
-
-@item @uref{http://www.soccersearch.com, Football (Soccer) search page}
-
-@item @uref{http://www.headrush.net/takedown, TAKEDOWN - wrestling}
-
-@item @uref{http://www.lyrics.net, The International Lyrics Network}
-
-@item @uref{http://TheMatrix.com/~matrix/band_search.phtml, Musicians looking for other musicians (Free Service)}
-
-@item @uref{http://www.addall.com/AddBooks/Stores.html,AddALL books searching and price comparison}
-
-@item @uref{http://www.herbaria.harvard.edu/Data/Gray/gray.html,Harvard's Gray Herbarium Index of Plant Names}
-
-@item @uref{http://www.game-developer.com/,The Game Development Search Engine}
-
-@item @uref{www.theinnkeeper.com, The Innkeeper Vacation Guides}
-
-@item @uref{http://www.macgamedatabase.com/, The Mac Game Database uses PHP and MySQL}
-@c From: Marc Antony Vose <suzerain@suzerain.com>
-
-@item @uref{http://www.csse.monash.edu.au/publications/, Research
-Publications at Monash University in Australia}
-
-@item @uref{http://www.ipielle.emr.it/bts/index.html,
-Occupational Health & Safety Web site database (a project for the ECC)}
-@c c.presutti@ipielle.emr.it
-
-@item @uref{http://data.mch.mcgill.ca/, Bioinformatics databases at the
-Montreal Children's Hospital using MySQL}
-@c saeed@www.debelle.mcgill.ca
-@end itemize
-
-@cindex online magazines
-@cindex magazines, online
-@appendixsec Online Magazines
-
-@itemize @bullet
-@item @uref{http://www.spoiler.com, Spoiler Webzine}.
-An online magazine featuring music, literature, arts, and design content.
-@item @uref{http://www.linux-magazin.de/newsflash/, Daily news about Linux in German language}
-@item @uref{http://www.betazine.com,Betazine - The Ultimate Online Beta Tester's Magazine}
-@item @uref{http://www.currents.net/ccinfo/aboutcc.html,Computer Currents Magazine}
-@end itemize
-
-@cindex web sites
-@appendixsec Web Sites that Use MySQL as a Backend
-
-@itemize @bullet
-
-@item @uref{http://liftoff.msfc.nasa.gov, NASA}
-@item @uref{http://kids.msfc.nasa.gov, NASA KIDS}
-@item @uref{http://science.nasa.gov, Sience@@NASA}
-
-@item @uref{http://www.handy.de/, handy.de}
-
-@item @uref{http://lindev.jmc.tju.edu/qwor, Qt Widget and Object Repository}
-
-@item @uref{http://www.samba-choro.com.br, Brazilian samba site (in Portuguese)}
-
-@item @uref{http://pgss.iss.uw.edu.pl/en_index.ISS, Polish General Social Survey}
-
-@item @uref{http://www.expo2000.com, Expo2000} World-wide distribution of
-tickets for this event is implemented using MySQL and tcl/tk. More than
-5000 travel agencies all over the world have access to it.
-
-@item @uref{http://www.freevote.com/, FreeVote.com is a free voting
-service with millions of users.}
-
-@item @uref{http://f1.tauzero.se, Forza Motorsport}
-
-@item @uref{http://www.dreamhost.com/, DreamHost Web Hosting}
-
-@end itemize
-
-@cindex services
-@appendixsec Some Domain/Internet/Web and Related Services
-
-@itemize @bullet
-
-@item @uref{http://www.wix.com/mysql-hosting, Registry of Web providers that
-support MySQL}
-
-@item @uref{http://www.yi.org/, Dynamic DNS Services}
-
-@item @uref{http://www.dynodns.net/, Dynamic domain name service}
-
-@item @uref{http://www.ods.org/, Open DNS Project; free dynamic DNS service}
-
-@c @item @uref{http://dynodns.net, Free dynamic DNS implementation}
-@c EMAIL: A Moore <amoore@mooresystems.com>
-
-@item @uref{http://www.hn.org/, Hammernode; Public DNS Servers}
-
-@item @uref{http://www.fdns.net/, Free 3rd level domains}
-
-@item @uref{http://worldcommunity.com/, Online Database}
-
-@item @uref{http://www.bigbiz.com, BigBiz Internet Services}
-
-@item @uref{http://virt.circle.net, The Virt Gazette}
-
-@item @uref{http://www.california.com, Global InfoNet Inc}
-
-@item @uref{http://www.webhosters.com, WebHosters - A Guide to WWW Providers}
-
-@item @uref{http://online.dn.ru, Internet information server}
-
-@item @uref{http://www.stopbit.com, A technology news site}
-
-@item @uref{http://www.worldnetla.net, WorldNet Communications - An Internet Services Provider}
-
-@item @uref{http://www.netizen.com.au/, Netizen: Australian-based Web consultancy}
-
-@item @uref{http://www.trainingpages.co.uk, Search site for training courses in the UK}
-
-@item @uref{http://chat.nitco.com, Gannon Chat (GPL). Written in Perl and Javascript}
-
-@item @uref{http://www.addurls.com/,A general links directory}
-
-@item @uref{http://www.bookmarktracker.com, A Web-based bookmark management service}
-
-@item @uref{http://www.cdrom.com,Walnut Creek CDROM}
-
-@item @uref{http://www.wwwthreads.org/, WWWThreads; Interactive discussion Forums}
-
-@item @uref{http://pvmon.portici.enea.it/Meteo, In Italian; Storage data from meteo station}
-
-@item @uref{http://www.buysell.net/, Online "Person To Person" Auction}
-
-@item @uref{http://tips.pair.com,Tips on Web development}
-
-@item @uref{http://www.mailfriends.com, Mailfriends.com is a FREE service for
-everybody who wants to find friends over the internet.}
-
-@item @uref{http://www.uninova.com/cgi-bin/wctelnets?list, Web Page Telnet BBS List}
-
-@item @uref{http://www.uninova.com/cnc.html,UniNova Digital Postcards}
-
-@c @item @uref{http://cabinboy.powersurfr.com, An Internet RFC search engine}
-
-@item @uref{http://www.dslreports.com, DSL-provider search with reviews}.
-Made with MySQL and Modperl, all pages are generated dynamically out of
-the MySQL database
-@end itemize
-
-@cindex PHP, web sites
-@appendixsec Web Sites that Use @code{PHP} and MySQL
-
-@itemize @bullet
-@c @item @uref{http://www.wh200th.com, White House 200th Anniversary site}
-
-@item @uref{http://support.jgaa.com/, Jgaa's Internet - Official Support Site}
-
-@item @uref{http://io.incluso.com, Ionline - online publication:} MySQL,
-PHP, Java, Web programming, DB development
-
-@item @uref{http://www.baboo.com, BaBoo(Browse and bookmark). Free Web-based bookmark manager and Calendar}
-
-@item @uref{http://www.courses.pjc.cc.fl.us/Schedule/index.php, Course
-Schedule System at Pensacola Junior College}
-
-@item @uref{http://www.fccj.org, Florida Community College at Jacksonville}
-
-@item @uref{http://www.32bit.com/, 32bit.com; An extensive shareware / freeware archive}
-
-@item @uref{http://www.jokes2000.com/, Jokes 2000}
-@c Added 990604; EMAIL: ah@dybdahl.dk
-
-
-@item @uref{http://www.burken.nu/ , Burken.NU} Burken is a webhotel that
-provides scripts, among other things, for remote users, like counters,
-guestbooks etc.
-@c Added 990608; EMAIL: spacedmp@SpaceDump.Burken.NU (Anders Olausson)
-
-@item @uref{http://tips.pair.com, tips.pair.com} Contains tips on html,
-javascript, 2d/3d graphics, and PHP3/MySQL. All pages are generated from
-a database.
-@c Added 990614; EMAIL: downey@image.dk (Rune Madsen)
-
-@item @uref{http://www.softwarezrus.com/, Softwarezrus.com}
-Ecommerce site that is selling computers.
-@end itemize
-
-@cindex consultants, list of
-@appendixsec Some MySQL Consultants
-
-@itemize @bullet
-
-@item @uref{http://www.ayni.com, Ayni AG}
-
-@item @uref{http://worldcommunity.com/, Online Database}
-
-@item @uref{http://www2.dataguard.no/,DataGuard (Uses MySQL and PHP)}
-
-@item @uref{http://wwits.net/programs/mysql.phtml, WWITS (Uses MySQL and PHP)}
-
-@item @uref{http://www.worldcommunity.com/, WCN - The World Community Network}
-
-@item @uref{http://www.chipcastle.com, Chip Castle Dot Com Inc}
-@c Added 990603 EMAIL: chip@chipcastle.com (Chip Castle)
-
-@item @uref{http://www.cyber.com.au/, Cybersource Pty. Ltd}
-
-@item @uref{http://www.spring.de, Spring infotainment gmbh & co. kg}
-@c added 990905 "Oliver Pischke" <opischke@spring.de>
-
-@item @uref{http://www.wamdesign.com/, Develops Web sites using MySQL}
-@c Added 990905; max@wamdesign.com
-
-@item @uref{http://www.berkeleyconsultants.com, Berkeley Consultants Group}
-
-@item @uref{http://www.jammconsulting.com/, JAMM Consulting Inc.}
-
-@end itemize
-
-@appendixsec Programming
-
-@cindex web pages, miscellaneous
-@appendixsec Uncategorized Pages
-
-@itemize @bullet
-
-@item @uref{http://www.feature-showcase.com/htmls/demo_mysql.sql,
-AZC.COM's Feature Showcase}
-
-@item @uref{http://www.teach.org.uk/subjects/trainingcourse/g.html, Course Search}
-
-@item @uref{http://www.northerbys.com, Northerbys Online Auctions}
-
-@item @uref{http://www.schiphol.nl/flights/home.htm, Amsterdam Airport Schiphol}
-
-@item @uref{http://TheMatrix.com/seventhsin/query.phtml, CD database}
-
-@item @uref{http://TheMatrix.com/~flmm/GEAR.html, Used Audio Gear Database}
-
-@item @uref{http://www.kiss.de/musik-mueller, Musical note-sheets}
-
-@item @uref{http://www.bagism.com, Bagism - A John Lennon fan page}
-
-@item @uref{http://www.selftaught.com/, US Folk art broker}
-
-@item @uref{http://organizer.net/, Mail reading on the Web}
-
-@item @uref{http://www.mypage.org/, Free home pages on www.somecoolname.mypage.org}
-
-@item @uref{http://www.schulweb.de/, Der Server f@"ur Schulen im Web (In German)}
-
-@item @uref{http://www.ald.net/, Auldhaefen Online Services}
-
-@item @uref{http://www.cary.net/, CaryNET Information Center}
-
-@item @uref{http://www.dataden.com/, Dataden Computer Systems}
-
-@item @uref{http://andree.grm.se/, Andr@'emuseet (In Swedish)}
-
-@item @uref{http://www.him.net/, HOMESITE Internet Marketing}
-
-@item @uref{http://www.jade-v.com/techinfo.html, Jade-V Network Services }
-
-@item @uref{http://ww2010.atmos.uiuc.edu/(Gl)/abt/aknw/tech.rxml,
-Weather World 2010 Technical Credits} @*
-
-@item @uref{http://gimp.foebud.org/registry/doc/, About The Gimp plugin registry}
-
-@item @uref{http://www.fast-inc.com/Products/Archiver/database.html, Java tool
-Archiver technical detail (Slightly optimistic about MySQL
-ANSI-92 compliance)}
-
-@item @uref{http://www.gamesdomain.com/cheats/usrcheat.phtml, Games Domain Cheats Database}
-
-@item @uref{http://www.kcilink.com/poweredby/, The "Powered By" Page (Kcilink)}
-
-@item @uref{http://www.netcasting.net/index.whtml, Netcasting}
-
-@item @uref{http://homepages.tig.com.au/~mjj/nbltips, NBL (Australian National Basketball League) tipping}
-
-@item @uref{http://www.cgishop.com/, CGI shop}
-
-@item @uref{http://www.whirlycott.com/, Whirlycott: Website Design}
-
-@item @uref{http://www.mtp.dk, Museum Tusculanum Press}
-
-@item @uref{http://csdgi.historie.ku.dk/biblio, Centro Siciliano di Documentazione}
-
-@item @uref{http://caribou.dyn.ml.org:8000, Quake statistics database}
-
-@item @uref{http://www.astroforum.ch, Astroforum: Astrologie and related things (in German)}
-
-@item @uref{http://www.opendebate.com, OpenDebate - Interactive Polls & Open Discussion}
-
-@item @uref{http://vermeer.organik.uni-erlangen.de/dissertationen/, Online chemical dissertation server}
-
-@item @uref{http://www.freschinfo.com, FreSch! The Free Scholarship Search Service}
-
-@item @uref{http://www.nada.kth.se/~staffanu/pinball, Stockholm Pinball Locator}
-
-@item @uref{http://www.hek.com, HEK A construction company}
-
-@item @uref{http://www.nbi.nl, Elsevier Bussines Information}
-
-@item @uref{http://vaccination.medicallink.se/, Medical Links (Using ColdFusion and MySQL)}
-
-@item @uref{http://www.joblink-usa.com, Search for jobs & people at JobLink-USA}
-
-@item @uref{http://www.skydive.net/competfs, Competition Formation Skydiving}
-
-@item @uref{http://www.galaxy-net.net/Galaxy-NET Telecommunications, E-commerce and internal accounting}
-
-@item @uref{http://www.borsen.dk/, Denmark's leading business daily newspaper B@o{}rsen}
-
-@item @uref{http://tmmm.simplenet.com/indb/, The Internet NES Database}
-
-@item @uref{http://www.russia.cz, Travel agency in Prague in 3 languages}
-
-@item @uref{http://www.linkstation.de, Linkstation}
-
-@item @uref{http://www.peoplestaff.com, Searchable online database at Peoplestaff}
-
-@item @uref{http://www.dreamhorse.com, A searchable database system for horse classified ads}
-
-@item @uref{http://pootpoot.com/,The Poot site}
-
-@item @uref{http://grateful.net/hw_html/,"Playin' in the LAN"; a network monitoring suite}
-
-@c Update from Christopher Milton <cmilton@bwn.net> 1999-12-21
-@item @uref{http://www.usapa.army.mil,U.S. Army Publishing Agency}
-
-@item @uref{http://www.nekretnine.co.yu/,Realestate handling in Yugoslavia}
-
-@item @uref{http://demo.cpsoft.com/pims/devFAQ.html, PIMS; a Patient Information Management System}
-
-@item @uref{http://cpsoft.com,Pilkington Software Inc}
-
-@item @uref{http://www.no-quarter.org/,A Vietnam Veteran's Memorial (The Wall) database}
-
-@item @uref{http://www.gamers-union.com/,Gamer's Union specializes in auctions of used & out-of-print gaming material}
-
-@item @uref{http://www.montereyhigh.com/office/dbul.php3, A daily bulletin at Monterey High school}
-
-@item @uref{http://www.myEastside.com,Community-owned site serving Lake
-Washington's Eastside residents and businesses}
-
-@item @uref{http://bowling-france.net/,French bowling site}
-@end itemize
-
-Send any additions to this list to @email{webmaster@@mysql.com}.
-
-@page
-
-
-
-
-@node MySQL customer usage, Contrib, Users, Top
-@appendix MySQL customer usage
-
-@cindex MySQL usage
-
-The section 'Some MySQL Users' contains a lot of different links to
-MySQL users but doesn't provide that much information about how
-they are using MySQL. @xref{Users}. This manual section is to
-give you an idea of how other MySQL users are using
-MySQL to solve their problems.
-
-This manual section is very new and we plan to add more stories here
-shortly. If you are interested in contributing of how you use
-MySQL in a unique environment or have success store about how you
-use MySQL, you can write to @code{docs@@mysql.com} with
-subject @code{Success:}. Note that as we are very busy it may take some
-time before you get some feedback for your story.
-
-@itemize @bullet
-@item
-@strong{Peter Zaitsev of Spylog.ru} writes:
-I think you might be interested in my database size. The whole database
-is currently on 15 servers and I think it's about 60.000 of tables
-containing about 5.000.000.000 of rows. My mostly loaded server
-currently holds about 10.000 of tables with 1.000.000.000 of rows in it.
-Hugest tables have about 50.000.000 of rows, and this value will raise
-as soon as I'll move to 2.4 kernel with large files. Currently I have to
-delete much of logs for large sites to hold table sizes in 2Gb.
-
-@item
-@strong{Texas Instruments} is using MySQL for handling tables
-that contain up to 2,000 million rows in a validation regression database.
-@end itemize
-
-@page
-
-
-
-
-@node Contrib, Credits, MySQL customer usage, Top
+@node Contrib, Credits, Problems, Top
@appendix Contributed Programs
@cindex contributed programs
@@ -45416,14 +47047,24 @@ that contain up to 2,000 million rows in a validation regression database.
Many users of MySQL have contributed @emph{very} useful support
tools and add-ons.
-@ifclear web
-A list of what is available at @uref{http://www.mysql.com/Downloads/Contrib/}
+A list of what is available at
+@uref{http://www.mysql.com/Downloads/Contrib/}
(or any mirror) is shown below.
+
+Please visit our Software Portal at
+@uref{http://www.mysql.com/portal/software/}.
+The community facilities there also allow for your input!
+
If you want to build MySQL support for the Perl @code{DBI}/@code{DBD}
interface, you should fetch the @code{Data-Dumper}, @code{DBI}, and
@code{Msql-Mysql-modules} files and install them.
@xref{Perl support}.
-@end ifclear
+
+Note: The programs listed here can be freely downloaded and used.
+They are copyrighted by their respective owners.
+Please see each product documentation for more details on licensing and terms.
+MySQL AB assumes no liability for the correctness of the information in this
+chapter or for the proper operation of the programs listed herein.
@appendixsec APIs
@@ -45431,26 +47072,26 @@ interface, you should fetch the @code{Data-Dumper}, @code{DBI}, and
@itemize @bullet
@item Perl Modules
@itemize @minus
-@item @uref{http://www.mysql.com/Downloads/Contrib/Data-Dumper-2.101.tar.gz, Data-Dumper-2.101.tar.gz}
+@item @uref{http://www.mysql.com/Downloads/Contrib/Data-Dumper-2.101.tar.gz}
Perl @code{Data-Dumper} module. Useful with @code{DBI}/@code{DBD} support for
older Perl installations.
-@item @uref{http://www.mysql.com/Downloads/Contrib/DBI-1.15.tar.gz, DBI-1.15.tar.gz}
+@item @uref{http://www.mysql.com/Downloads/Contrib/DBI-1.18.tar.gz}
Perl @code{DBI} module.
-@item @uref{http://www.mysql.com/Downloads/Contrib/KAMXbase1.2.tar.gz,KAMXbase1.2.tar.gz}
+@item @uref{http://www.mysql.com/Downloads/Contrib/KAMXbase1.2.tar.gz}
Convert between @file{.dbf} files and MySQL tables. Perl
module written by Pratap Pereira @email{pereira@@ee.eng.ohio-state.edu},
extended by Kevin A. McGrail @email{kmcgrail@@digital1.peregrinehw.com}.
This converter can handle MEMO fields.
-@item @uref{http://www.mysql.com/Downloads/Contrib/Msql-Mysql-modules-1.2216.tar.gz, Msql-Mysql-modules-1.2216.tar.gz}
+@item @uref{http://www.mysql.com/Downloads/Contrib/Msql-Mysql-modules-1.2218.tar.gz}
Perl @code{DBD} module to access mSQL and MySQL databases.
-@item @uref{http://www.mysql.com/Downloads/Contrib/Data-ShowTable-3.3.tar.gz, Data-ShowTable-3.3.tar.gz}
+@item @uref{http://www.mysql.com/Downloads/Contrib/Data-ShowTable-3.3.tar.gz}
Perl @code{Data-ShowTable} module. Useful with @code{DBI}/@code{DBD} support.
-@item @uref{http://www.mysql.com/Downloads/Contrib/HandySQL-1.1.tar.gz, HandySQL-1.1.tar.gz}
+@item @uref{http://www.mysql.com/Downloads/Contrib/HandySQL-1.1.tar.gz}
HandySQL is a MySQL access module. It offers a C interface embedded in Perl and is
approximately 20% faster than regular DBI.
@@ -45459,12 +47100,12 @@ approximately 20% faster than regular DBI.
@cindex JDBC
@item JDBC
@itemize @bullet
-@item @uref{http://www.mysql.com/Downloads/Contrib/mm.mysql.jdbc-1.2c.tar.gz, mm.mysql.jdbc-1.2c.tar.gz}
+@item @uref{http://www.mysql.com/Downloads/Contrib/mm.mysql.jdbc-1.2c.tar.gz}
The mm JDBC driver for MySQL. This is a production release
and is actively developed. By Mark Matthews
(@email{mmatthew@@ecn.purdue.edu}).
-@item @uref{http://www.mysql.com/Downloads/Contrib/mm.mysql.jdbc-2.0pre5.tar.gz, mm.mysql.jdbc-2.0pre5.tar.gz}
+@item @uref{http://www.mysql.com/Downloads/Contrib/mm.mysql.jdbc-2.0pre5.tar.gz}
The mm JDBC driver for MySQL. This is a pre-release beta version
and is actively developed. By Mark Matthews
(@email{mmatthew@@ecn.purdue.edu}).
@@ -45473,17 +47114,17 @@ license. Please check @uref{http://www.worldserver.com/mm.mysql/} for
the latest drivers (and other JDBC information) because these drivers may be out of date.
@item @uref{http://www.caucho.com/projects/jdbc-mysql/index.xtp}
-The Resin commercial JDBC driver, which is released under open source.
+The Resin commercial JDBC driver, which is released under Open Source.
It claims to be faster than the mm driver, but we haven't received that much
information about this yet.
-@item @uref{http://www.mysql.com/Downloads/Contrib/twz1jdbcForMysql-1.0.4-GA.tar.gz, twz1jdbcForMysql-1.0.4-GA.tar.gz}
+@item @uref{http://www.mysql.com/Downloads/Contrib/twz1jdbcForMysql-1.0.4-GA.tar.gz}
The twz driver: A type 4 JDBC driver by Terrence W. Zellers
@email{zellert@@voicenet.com}. This is commercial but is free for
private and educational use. (Not supported anymore.)
@c no answer from server 990830
@c You can always find the latest driver at @uref{http://www.voicenet.com/~zellert/tjFM/}.
-@item @uref{http://www.mysql.com/Downloads/Contrib/pmdamysql.tgz,pmdamysql.tgz}
+@item @uref{http://www.mysql.com/Downloads/Contrib/pmdamysql.tgz}
A MySQL PMDA. Provides MySQL server status and configuration
variables.
@end itemize
@@ -45491,15 +47132,15 @@ variables.
@cindex OLEDB
@item OLEDB
@itemize @bullet
-@item @uref{http://www.mysql.com/Downloads/Win32/MyOLEDB.exe, MyOLEDB.exe}
-OLEDB handler for MySQL. By SWsoft.
-@item @uref{http://www.mysql.com/Downloads/Win32/MySamples.zip, MySamples.zip}
-Examples and documentation for MyOLEDB. By SWsoft.
-@item @uref{http://www.mysql.com/Downloads/Win32/Myoledb.zip, Myoledb.zip}
-Source for MyOLEDB. By SWsoft.
-@item @uref{http://www.mysql.com/Downloads/Win32/MyOLEDB.chm, MyOLEDB.chm}
+@item @uref{http://www.mysql.com/Downloads/Win32/MyOLEDB3.exe}
+MyOLEDB 3.0 installation package from SWSoft.
+@item @uref{http://www.mysql.com/Downloads/Win32/mysql-oledb-3.0.0.zip}
+Source for MyOLEDB 3.0.
+@item @uref{http://www.mysql.com/Downloads/Win32/MySamples.zip}
+Examples and documentation for MyOLEDB.
+@item @uref{http://www.mysql.com/Downloads/Win32/MyOLEDB.chm}
Help files for MyOLEDB.
-@item @uref{http://www.mysql.com/Downloads/Win32/libmyodbc.zip, libmyodbc.zip}
+@item @uref{http://www.mysql.com/Downloads/Win32/libmyodbc.zip}
Static MyODBC library used for build MyOLEDB. Based on MyODBC code.
@end itemize
@@ -45507,83 +47148,86 @@ Static MyODBC library used for build MyOLEDB. Based on MyODBC code.
@item C++
@itemize @bullet
-@item @uref{http://www.mysql.com/Downloads/Contrib/mysql-c++-0.02.tar.gz, mysql-c++-0.02.tar.gz}
+@item @uref{http://www.mysql.com/Downloads/Contrib/mysql-c++-0.02.tar.gz}
MySQL C++ wrapper library. By Roland Haenel,
@email{rh@@ginster.net}.
-@item @uref{http://www.mysql.com/Downloads/Contrib/MyDAO.tar.gz, MyDAO}
+@item @uref{http://www.mysql.com/Downloads/Contrib/MyDAO.tar.gz}
MySQL C++ API. By Satish @email{spitfire@@pn3.vsnl.net.in}. Inspired
by Roland Haenel's C++ API and Ed Carp's MyC library.
-@item @uref{http://www.mysql.com/download_mysql++.html, mysql++}
-MySQL C++ API (More than just a wrapper library.) Originally by
+@item @uref{http://www.mysql.com/download_mysql++.html}
+MySQL C++ API (more than just a wrapper library). Originally by
@email{kevina@@clark.net}. Nowadays maintained by Sinisa at MySQL AB.
-@item @uref{http://nelsonjr.homepage.com/NJrAPI,NJrAPI}
+@item @uref{http://nelsonjr.homepage.com/NJrAPI/}
A C++ database independent library that supports MySQL.
@end itemize
@cindex Delphi
@item Delphi
@itemize @bullet
-@item @uref{http://www.mysql.com/Downloads/Contrib/delphi-interface.gz, delphi-interface.gz}
-Delphi interface to @code{libmysql.dll}, by Blestan Tabakov,
-@email{root@@tdg.bis.bg}.
-@item @uref{http://www.mysql.com/Downloads/Contrib/DelphiMySQL2.zip, DelphiMySQL2.zip}
+@item @uref{http://www.mysql.com/Downloads/Contrib/DelphiMySQL2.zip}
Delphi interface to @code{libmysql.dll}, by @email{bsilva@@umesd.k12.or.us}.
-@item @uref{http://www.mysql.com/Downloads/Contrib/Udmysel.pas, Udmysql.pas}
+@item @uref{http://www.mysql.com/Downloads/Contrib/Udmysel.pas}
A wrapper for libmysql.dll for usage in Delphi. By Reiner Sombrowsky.
-@item @uref{http://www.fichtner.net/delphi/mysql.delphi.phtml, A Delphi interface to MySQL.}
-With source code. By Matthias Fichtner.
+@item @uref{http://www.fichtner.net/delphi/mysql.delphi.phtml}
+A Delphi Interface to MySQL, with source code. By Matthias Fichtner.
-@item @uref{http://www.productivity.org/projects/tmysql/, @strong{TmySQL}
-A library to use MySQL with Delphi}.
+@item @uref{http://www.productivity.org/projects/tmysql/}
+@code{TmySQL}, a library to use MySQL with Delphi.
-@item @uref{http://www.geocities.com/CapeCanaveral/2064/mysql.html, Delphi TDataset-component}.
-@item
-@item @uref{http://www.mysql.com/Downloads/Contrib/Win32/SBMySQL50Share.exe, Delphi 5 Shareware MySQL Dataset Components}
+@item @uref{https://sourceforge.net/projects/zeoslib/}
+Zeos Library is a set of delphi native datasets and database
+components for MySql, PostgreSql, Interbase, MS SQL, Oracle,
+DB/2. Also it includes development tools such as Database
+Explorer and Database Designer.
+
+@item @uref{http://www.mysql.com/Downloads/Contrib/Win32/SBMySQL50Share.exe}
+Delphi 5 Shareware MySQL Dataset Components.
@end itemize
-@item @uref{http://www.mysql.com/Downloads/Contrib/mysql-ruby-2.2.0.tar.gz, mysql-ruby-2.2.0.tar.gz}
+@item @uref{http://www.mysql.com/Downloads/Contrib/mysql-ruby-2.2.0.tar.gz}
MySQL Ruby module. By TOMITA Masahiro @email{tommy@@tmtm.org}
-@uref{http://www.netlab.co.jp/ruby/. Ruby} is an Object-Oriented Interpreter Language.
+Ruby is an Object-Oriented Interpreter Language
+(@uref{http://www.netlab.co.jp/ruby/}).
-@item @uref{http://www.mysql.com/Downloads/Contrib/JdmMysqlDriver-0.1.0.tar.gz,JdmMysqlDriver-0.1.0.tar.gz}
+@item @uref{http://www.mysql.com/Downloads/Contrib/JdmMysqlDriver-0.1.0.tar.gz}
A VisualWorks 3.0 Smalltalk driver for MySQL. By
@email{joshmiller@@earthlink.net}.
-@item @uref{http://www.mysql.com/Downloads/Contrib/Db.py, Db.py}
+@item @uref{http://www.mysql.com/Downloads/Contrib/Db.py}
Python module with caching. By @email{gandalf@@rosmail.com}.
-@item @uref{http://www.mysql.com/Downloads/Contrib/MySQLmodule-1.4.tar.gz, MySQLmodule-1.4.tar.gz}
+@item @uref{http://www.mysql.com/Downloads/Contrib/MySQLmodule-1.4.tar.gz}
Python interface for MySQL. By Joseph Skinner @email{joe@@earthlight.co.nz}. Modified by Joerg Senekowitsch @email{senekow@@ibm.net}.
-@item @uref{http://www.mysql.com/Downloads/Contrib/MySQL-python-0.3.0.tar.gz, MySQL-python-0.3.0.tar.gz}
+@item @uref{http://www.mysql.com/Downloads/Contrib/MySQL-python-0.3.0.tar.gz}
MySQLdb Python is an DB-API v2.0-compliant interface to MySQL. Transactions
are supported if the server and tables support them. It is
-thread-safe, and contains a compatibility module for older code
+thread safe, and contains a compatibility module for older code
written for the no-longer-maintained MySQLmodule interface.
-@item @uref{http://www.mysql.com/Downloads/Contrib/mysql_mex_12.tar.gz, mysql_mex_1_12.tar.gz}
+@item @uref{http://www.mysql.com/Downloads/Contrib/mysql_mex_12.tar.gz}
An interface program for the Matlab program by MathWorks. The interface
is done by Kimmo Uutela and John Fisher (not by Mathworks).
-Check @uref{http://boojum.hut.fi/~kuutela/mysqlmex.html,mysqlmex.html}
+Check @uref{http://boojum.hut.fi/~kuutela/mysqlmex.html}
for more information.
-@item @uref{http://www.mysql.com/Downloads/Contrib/mysqltcl-1.53.tar.gz, mysqltcl-1.53.tar.gz}
+@item @uref{http://www.mysql.com/Downloads/Contrib/mysqltcl-1.53.tar.gz}
Tcl interface for MySQL. Based on @file{msqltcl-1.50.tar.gz}.
Updated by Tobias Ritzau, @email{tobri@@ida.liu.se}.
-@item @uref{http://www.mysql.com/Downloads/Contrib/MyC-0.1.tar.gz, MyC-0.1.tar.gz}
+@item @uref{http://www.mysql.com/Downloads/Contrib/MyC-0.1.tar.gz}
A Visual Basic-like API, by Ed Carp.
-@item @uref{http://www.mysql.com/Downloads/Contrib/sqlscreens-1.0.1.tar.gz, sqlscreens-1.0.1.tar.gz}
+@item @uref{http://www.mysql.com/Downloads/Contrib/sqlscreens-1.0.1.tar.gz}
Tcl/Tk code to generate database screens. By Jean-Francois Dockes.
-@item @uref{http://www.mysql.com/Downloads/Contrib/Vdb-dflts-2.1.tar.gz, Vdb-dflts-2.1.tar.gz}
+@item @uref{http://www.mysql.com/Downloads/Contrib/Vdb-dflts-2.1.tar.gz}
This is a new version of a set of library utilities intended
to provide a generic interface to SQL database engines such that your
application becomes a 3-tiered application. The advantage is that you
@@ -45591,60 +47235,60 @@ can easily switch between and move to other database engines by
implementing one file for the new backend without making any
changes to your applications. By @email{damian@@cablenet.net}.
-@item @uref{http://www.mysql.com/Downloads/Contrib/DbFramework-1.10.tar.gz, DbFramework-1.10.tar.gz}
+@item @uref{http://www.mysql.com/Downloads/Contrib/DbFramework-1.10.tar.gz}
DbFramework is a collection of classes for manipulating MySQL
databases. The classes are loosely based on the CDIF Data Model
Subject Area. By Paul Sharpe @email{paul@@miraclefish.com}.
-@item @uref{http://www.mysql.com/Downloads/Contrib/pike-mysql-1.4.tar.gz, pike-mysql-1.4.tar.gz}
+@item @uref{http://www.mysql.com/Downloads/Contrib/pike-mysql-1.4.tar.gz}
MySQL module for pike. For use with the Roxen web server.
-@item @uref{http://www.mysql.com/Downloads/Contrib/squile.tar.gz, squile.tar.gz}
+@item @uref{http://www.mysql.com/Downloads/Contrib/squile.tar.gz}
Module for @code{guile} that allows @code{guile} to interact with SQL
databases. By Hal Roberts.
-@item @uref{http://www.mysql.com/Downloads/Contrib/stk-mysql.tar.gz, stk-mysql.tar.gz}
+@item @uref{http://www.mysql.com/Downloads/Contrib/stk-mysql.tar.gz}
Interface for Stk. Stk is the Tk widgets with Scheme underneath instead of Tcl.
By Terry Jones.
-@item @uref{http://www.mysql.com/Downloads/Contrib/eiffel-wrapper-1.0.tar.gz,eiffel-wrapper-1.0.tar.gz}
+@item @uref{http://www.mysql.com/Downloads/Contrib/eiffel-wrapper-1.0.tar.gz}
Eiffel wrapper by Michael Ravits.
-@item @uref{http://www.mysql.com/Downloads/Contrib/SQLmy0.06.tgz,SQLmy0.06.tgz}
+@item @uref{http://www.mysql.com/Downloads/Contrib/SQLmy0.06.tgz}
FlagShip Replaceable Database Driver (RDD) for MySQL. By Alejandro
Fernandez Herrero.
-@uref{http://www.fship.com/rdds.html, Flagship RDD home page}
+The Flagship RDD homepage is at @uref{http://www.fship.com/rdds.html}.
-@item @uref{http://www.mysql.com/Downloads/Contrib/mydsn-1.0.zip,mydsn-1.0.zip}
+@item @uref{http://www.mysql.com/Downloads/Contrib/mydsn-1.0.zip}
Binary and source for @code{mydsn.dll}. mydsn should be used to build
and remove the DSN registry file for the MyODBC driver in Coldfusion
applications. By Miguel Angel Solórzano.
-@item @uref{http://www.mysql.com/Downloads/Contrib/MySQL-ADA95_API.zip, MySQL-ADA95_API.zip}
+@item @uref{http://www.mysql.com/Downloads/Contrib/MySQL-ADA95_API.zip}
An ADA95 interface to the MySQL API. By Francois Fabien.
-@item @uref{http://www.mysql.com/Downloads/Contrib/MyTool-DLL_for_VB_and_MySQL.zip, MyTool-DLL_for_VB_and_MySQL.zip}
+@item @uref{http://www.mysql.com/Downloads/Contrib/MyTool-DLL_for_VB_and_MySQL.zip}
A DLL with MySQL C API for Visual Basic.
By Ken Menzel @email{kenm@@icarz.com}.
-@item @uref{http://www.mysql.com/Downloads/Contrib/MYSQLX.EXE, MYSQL.EXE}
+@item @uref{http://www.mysql.com/Downloads/Contrib/MYSQLX.EXE}
MySQL ActiveX Object for directly accessing your MySQL
servers from IIS/ASP, VB, VC++ skipping the slower ODBC methods. Fully
updatable, multithreaded with full support for all MySQL fieldtypes
(version 2001.1.1). By SciBit @uref{http://www.scibit.com/}.
-@item @uref{http://www.fastflow.it/mylua/, MyLUA home page}
-How to use the LUA language to write MySQL @code{PROCEDURE} that can
-be loaded runtime.
+@item @uref{http://www.fastflow.it/mylua/}
+MyLUA home page; how to use the LUA language to write MySQL
+@code{PROCEDURE} that can be loaded runtime.
@itemize @bullet
-@item @uref{http://www.mysql.com/Downloads/Contrib/lua-4.0.tar.gz, Lua 4.0}
+@item @uref{http://www.mysql.com/Downloads/Contrib/lua-4.0.tar.gz}
LUA 4.0
-@item @uref{http://www.mysql.com/Downloads/Contrib/mylua-3.23.32.1.tar.gz, mylua-3.23.32.1.tar.gz}
+@item @uref{http://www.mysql.com/Downloads/Contrib/mylua-3.23.32.1.tar.gz}
Patch for MySQL 3.23.32 to use LUA 4.0. By Cristian Giussani.
@end itemize
-@item @uref{http://www.mysql.com/Downloads/Contrib/patched_myodbc.zip, patched_myodbc.zip}
+@item @uref{http://www.mysql.com/Downloads/Contrib/patched_myodbc.zip}
Patch (for Omniform 4.0 support) to the MyODBC driver.
By Thomas Thaele @email{tthaele@@papenmeier.de}
@@ -45655,59 +47299,61 @@ By Thomas Thaele @email{tthaele@@papenmeier.de}
@itemize @bullet
@item Graphical clients
@itemize @minus
-@item @uref{http://www.ideit.com/products/dbvis/, DbVisualizer}.
-Freeware JDBC client to graphically visualize the data and structure
-of several databases simultaneously. By Innovative-IT Development AB.
+@item @uref{http://www.ideit.com/products/dbvis/}
+DbVisualizer, a freeware JDBC client to graphically visualise
+the data and structure of several databases simultaneously.
+By Innovative-IT Development AB.
-@item @uref{http://www.mysql.com/downloads/gui-clients.html, MySQLGUI}
-The MySQL GUI client homepage. By Sinisa at MySQL AB.
+@item @uref{http://www.mysql.com/downloads/gui-clients.html}
+MySQLGUI, the MySQL GUI client homepage. By Sinisa at MySQL AB.
-@item @uref{http://www.mysql.com/Downloads/Contrib/mysql_navigator_0.9.0.tar.gz, MySQL navigator 0.9}
+@item @uref{http://www.mysql.com/Downloads/Contrib/mysql_navigator_0.9.0.tar.gz}
MySQL Navigator is a MySQL database server GUI client program. The purpose
of MySQL Navigator is to provide a useful client interface to MySQL
database servers, whilst supporting multiple operating systems and
languages. You can currently import/export database, enter queries, get
result sets, edit scripts, run scripts, add, alter, and delete users,
and retrieve client and server information. Uses QT 2.2. GPL
-@uref{http://sql.kldp.org/mysql, Home page for MySQL Navigator}.
+The homepage for MySQL Navigator is at @uref{http://sql.kldp.org/mysql/}.
-@item @uref{http://www.mysql.com/Downloads/Win32/secman.zip, MySQL Security GUI}
+@item @uref{http://www.mysql.com/Downloads/Win32/secman.zip}
A user and security management GUI for MySQL on Windows.
By Martin Jeremic.
-@uref{http://jsoft.webjump.com/, Home page for MySQL Security GUI}.
+The homepage for MySQL Security GUI is at @uref{http://jsoft.webjump.com/}.
-@item @uref{http://www.mysql.com/Downloads/Contrib/kmysqladmin-0.4.1.tar.gz, kmysqladmin-0.4.1.tar.gz}.
-@item @uref{http://www.mysql.com/Downloads/Contrib/kmysqladmin-0.4.1-1.src.rpm, kmysqladmin-0.4.1-1.src.rpm}.
-@item @uref{http://www.mysql.com/Downloads/Contrib/kmysqladmin-0.4.1-1.i386.rpm, kmysqladmin-0.4.1-1.i386.rpm}
+@item @uref{http://www.mysql.com/Downloads/Contrib/kmysqladmin-0.4.1.tar.gz}.
+@item @uref{http://www.mysql.com/Downloads/Contrib/kmysqladmin-0.4.1-1.src.rpm}.
+@item @uref{http://www.mysql.com/Downloads/Contrib/kmysqladmin-0.4.1-1.i386.rpm}
An administration tool for the MySQL server using QT / KDE. Tested
only on Linux.
-@item @uref{http://www.mysql.com/Downloads/Contrib/mysql-admin-using-java+swing.tar.gz, Java client using Swing} By Fredy Fischer, @email{se-afs@@dial.eunet.ch}.
-You can always find the latest version
-@uref{http://www.trash.net/~ffischer/admin/index.html, here}.
+@item @uref{http://www.mysql.com/Downloads/Contrib/mysql-admin-using-java+swing.tar.gz}
+Java client using Swing, by Fredy Fischer (@email{se-afs@@dial.eunet.ch}).
+You can always find the latest version at
+@uref{http://www.trash.net/~ffischer/admin/}.
-@item @uref{http://www.mysql.com/Downloads/Win32/MySQL-Maker-1.0.zip,MySQL-Maker 1.0}.
+@item @uref{http://www.mysql.com/Downloads/Win32/MySQL-Maker-1.0.zip}.
Shareware MySQL client for Windows. It's a WYSIWYG tool which allows
you to create, change and delete databases and tables.
You can change field - structure and add, change and delete data in
these tables directly without ODBC-driver.
-@uref{http://www.presult.de/presult/frames/fs_mysqlmaker.html, MySQL Maker homepage}
+The MySQL Maker homepage is at @uref{http://www.presult.de/presult/frames/fs_mysqlmaker.html}.
-@item @uref{http://www.mysql.com/Downloads/Contrib/mysqlwinadmn.zip, mysqlwinadmn.zip}
+@item @uref{http://www.mysql.com/Downloads/Contrib/mysqlwinadmn.zip}
Windows GUI (binary only) to administrate a database, by David B. Mansel,
@email{david@@zhadum.org}.
-@item @uref{http://home.online.no/~runeberg/myqa, MyQA}
-is a Linux-based query client for the MySQL database server. MyQA
+@item @uref{http://home.online.no/~runeberg/myqa/}
+MyQA is a Linux-based query client for the MySQL database server. MyQA
lets you enter SQL queries, execute them, and view the results, all in a
graphical user interface. The GUI is roughly similar to that of the
'Query Analyzer' client that comes with MS SQL Server.
-@item @uref{http://members.xoom.com/_opex_/mysqlmanager/index.html, MySQL Manager}
-a graphical MySQL server manager for MySQL server written in Java, for Windows
+@item @uref{http://www.opex.atnet.ru/mysqlmanager/}
+MySQL Manager is a graphical MySQL server manager for MySQL server
+written in Java.
-
-@item @uref{http://www.mysql.com/Downloads/Win32/netadmin.zip, netadmin.zip}
+@item @uref{http://www.mysql.com/Downloads/Win32/netadmin.zip}
An administrator tool for MySQL on Windows 95/98 and Windows NT
4.0. Only tested with MySQL Versions 3.23.5 - 3.23.7. Written
using the Tmysql components.
@@ -45716,68 +47362,70 @@ You can write queries and show tables, indexes, table syntax, and
administrate user, host, and database and so on. This is beta and
still has some bugs. You can test the program with all features. Please
send bugs and hints to Marco Suess @email{ms@@it-netservice.de}. Original
-URL @url{http://www.it-netservice.de/pages/software/index.html}.
+URL @uref{http://www.it-netservice.de/pages/software/}.
-@item @uref{http://www.mysql.com/Downloads/Win32/netadmin2.zip, netadmin2.zip}
+@item @uref{http://www.mysql.com/Downloads/Win32/netadmin2.zip}
New version of netadmin. See above for details.
-@item @uref{http://www.mysql.com/Downloads/Win32/ARTADMIN203.EXE,Atronic's MySQL client for Windows 2.0.3.0}.
-Home page for this can be found at: @uref{http://www.artronic.hr}.
-
-@item @uref{http://www.mysql.com/Downloads/Win32/mysqlfront.zip, mysqlfront}
-Home page: @uref{http://www.mysqlfront.de/}.
-Win32-Client for accessing and managing dbs, tables, table-data, indexes,
-import-/export-files. (Freeware). By Ansgar Becker.
+@item @uref{http://www.mysql.com/Downloads/Win32/ARTADMIN203.EXE}
+Atronic's MySQL client for Windows 2.0.3.0.
+The home page for this can be found at @uref{http://www.artronic.hr/}.
-@item @uref{http://www.mysql.com/Downloads/Win32/W9xstop.zip,Utility from Artronic to stop MySQL on win9x}.
+@item @uref{http://www.mysql.com/Downloads/Win32/W9xstop.zip}
+Utility from Artronic to stop MySQL on win9x.
-@item @uref{http://bardo.hyperlink.cz/mysqlmon,a light weight GUI client for Windows}.
+@item @uref{http://bardo.hyperlink.cz/mysqlmon/}
+A light weight GUI client for Windows.
-@item @uref{http://dbtools.vila.bol.com.br/, Dbtools}
-A tool to manage MySQL databases. Currently only for Windows.
+@item @uref{http://www.dbtools.com.br/}
+Dbtools, a tool to manage MySQL databases. Currently only for Windows.
Some features:
@itemize @bullet
@item Manage servers, databases, tables, columns, indexes, and users
@item Import wizard to import structure and data from MS Access, MS Excel, Dbase, FoxPro, Paradox, and ODBC Databases.
-@item @uref{http://www.mysql.com/Downloads/Contrib/KMYENG113.zip,KMYENG113.zip}
-An administrator GUI for MySQL. Works only on windows, no source.
+@item @uref{http://www.mysql.com/Downloads/Contrib/KMYENG113.zip}
+An administrator GUI for MySQL. Works only on Windows, no source.
Available in English and Japanese. By Mitunobu Kaneko.
Home page: @uref{http://sql.jnts.ne.jp/}
@end itemize
-@item @uref{http://www.mysql.com/Downloads/Contrib/xmysqladmin-1.0.tar.gz, xmysqladmin-1.0.tar.gz}
+@item @uref{http://www.mysql.com/Downloads/Contrib/xmysqladmin-1.0.tar.gz}
An X-based front end to the MySQL database engine. It allows reloads,
status check, process control, myisamchk, grant/revoke privileges,
creating databases, dropping databases, create, alter, browse, and drop
tables. Originally by Gilbert Therrien, @email{gilbert@@ican.net} but
now in public domain and supported by MySQL AB.
-@item @uref{http://www.mysql.com/Downloads/Contrib/xmysql-1.9.tar.gz, xmysql-1.9.tar.gz}.
-@item @uref{http://web.wt.net/~dblhack, xmysql home page}
-A front end to the MySQL database engine. It allows for simple
+@item @uref{http://www.mysql.com/Downloads/Contrib/xmysql-1.9.tar.gz}.
+xmysqlA front end to the MySQL database engine. It allows for simple
queries and table maintenance, as well as batch queries. By Rick
Mehalick, @email{dblhack@@wt.net}.
-Requires @uref{http://bragg.phys.uwm.edu/xforms,xforms 0.88} to work.
-@item @uref{http://www.tamos.net/sw/dbMetrix,dbMetrix}
-An open source client for exploring databases and executing SQL. Supports
-MySQL, Oracle, PostgreSQL, and mSQL.
-@item @uref{http://www.multimania.com/bbrox/GtkSQL,GtkSQL}
-A query tool for MySQL and PostgreSQL.
-@item @uref{http://dbman.linux.cz/,dbMan}
-A query tool written in Perl. Uses DBI and Tk.
-@item @uref{http://www.mysql.com/Downloads/Win32/Msc201.EXE, Mascon 202}
-@item @uref{http://www.mysql.com/Downloads/Win32/FrMsc202.EXE, Free Mascon 202}
+The xmysql homepage is at @uref{http://web.wt.net/~dblhack/}
+Requires @uref{http://bragg.phys.uwm.edu/xforms/} (xforms 0.88) to work.
+
+@item @uref{http://www.tamos.net/sw/dbMetrix/}
+dbMatrix is an Open Source client for exploring databases and executing
+SQL. Supports MySQL, Oracle, PostgreSQL, and mSQL.
+
+@item @uref{http://www.multimania.com/bbrox/GtkSQL/}
+GtkSQL is a query tool for MySQL and PostgreSQL.
+
+@item @uref{http://dbman.linux.cz/}
+dbMan is a query tool written in Perl. Uses DBI and Tk.
+
+@item @uref{http://www.mysql.com/Downloads/Win32/Msc201.EXE} (Mascon 202)
+@item @uref{http://www.mysql.com/Downloads/Win32/FrMsc202.EXE} (Free Mascon 202)
Mascon is a powerful Win32 GUI for the administering MySQL server
databases. Mascon's features include visual table design, connections to
multiple servers, data and blob editing of tables, security setting, SQL
color coding, dump functionality and much more.
-@uref{http://www.scibit.com/Products/Software/Utils/Mascon.asp,Mascon home page}.
-@item @uref{http://www.virtualbeer.net/dbui/,DBUI}
+The Mascon homepage is at @uref{http://www.scibit.com/Products/Software/Utils/Mascon.asp}.
+@item @uref{http://www.virtualbeer.net/dbui/}
DBUI is a Gtk graphical database editor.
-@item @uref{http://www.rtlabs.com/, MacSQL}
-GUI for MySQL, ODBC, and JDBC databases for the Mac OS.
-@item @uref{http://www.caleb.com.au/, JRetriever}
+@item @uref{http://www.rtlabs.com/}
+MacSQL is a GUI for MySQL, ODBC, and JDBC databases for the Mac OS.
+@item @uref{http://www.caleb.com.au/}
JRetriever is a generic database front-end tool for JDBC compliant
databases written with Java 2. JRetriever displays database
tables/views in a Windows explorer-like front end. Users can retrieve
@@ -45785,18 +47433,18 @@ data either by clicking on the table folder or by composing their own SQL
statements with our built-in SQL editor. The tool has been tested with
Oracle 8 and MySQL as the back-end databases. It requires JDK 1.3 from
JavaSoft.
-@item @uref{http://www.jetools.com/products/databrowser/, DataBrowser}
+@item @uref{http://www.jetools.com/products/databrowser/}
The DataBrowser is a cross-database, cross-platform data access tool. It is more
user friendly than tools like SQL Plus, psql (command line based tools). It is more
flexible than TOAD, ISQL, PGAccess which are GUI's that are limitied to a single
platform or database.
-@item @uref{http://www.intrex.net/amit/software/, SQLC}
+@item @uref{http://www.intrex.net/amit/software/}
The SQL Console is a standalone java application that allows you to connect to a
SQL database system and issue SQL queries and updates. It has an easy-to use
graphical user interface. The SQL Console uses JDBC to connect to the database
systems and, therefore, with proper JDBC drivers, you can use this utility to
connect to some of the most popular database systems.
-@item @uref{http://www.mysql.com/Downloads/Contrib/mysql_mmc.zip, MySQL MMC}
+@item @uref{http://www.mysql.com/Downloads/Contrib/mysql_mmc.zip}
MySQL MMC is a GUI Management Tool developed using kdevelop
with a very good interface completely like Microsoft
Enterprise Tool (for SQL Server) or Sybase Central. We
@@ -45808,52 +47456,52 @@ by Query Analysis.
@cindex Web clients
@item Web Clients
@itemize @minus
-@item @uref{http://www.mysql.com/Downloads/Contrib/mysqladmin-atif-1.0.tar.gz, mysqladmin-atif-1.0.tar.gz}
+@item @uref{http://www.mysql.com/Downloads/Contrib/mysqladmin-atif-1.0.tar.gz}
WWW MySQL administrator for the @code{user,} @code{db} and
@code{host} tables. By Tim Sailer, modified by Atif Ghaffar
@email{aghaffar@@artemedia.ch}.
-@item @uref{http://www.mysql.com/Downloads/Contrib/mysql-webadmin-1.0a8-rz.tar.gz, mysql-webadmin-1.0a8-rz.tar.gz}
+@item @uref{http://www.mysql.com/Downloads/Contrib/mysql-webadmin-1.0a8-rz.tar.gz}
A tool written in PHP-FI to administrate MySQL databases
remotely over the web within a Web-Browser. By Peter Kuppelwieser,
@email{peter.kuppelwieser@@kantea.it}. Updated by Wim Bonis,
@email{bonis@@kiss.de}. Not maintained anymore!
-@item @uref{http://www.mysql.com/Downloads/Contrib/mysqladm.tar.gz, mysqladm.tar.gz}
+@item @uref{http://www.mysql.com/Downloads/Contrib/mysqladm.tar.gz}
MySQL Web Database Administration written in Perl. By Tim Sailer.
-@item @uref{http://www.mysql.com/Downloads/Contrib/mysqladm-2.tar.gz, mysqladm-2.tar.gz}
+@item @uref{http://www.mysql.com/Downloads/Contrib/mysqladm-2.tar.gz}
Updated version of @file{mysqladm.tar.gz}, by High Tide.
-@item @uref{http://www.mysql.com/Downloads/Contrib/billowmysql.zip, billowmysql.zip}
+@item @uref{http://www.mysql.com/Downloads/Contrib/billowmysql.zip}
Updated version of @file{mysqladm.tar.gz}, by Ying Gao. You can get the
-newest version from @uref{http://civeng.com/sqldemo/, the home site}.
+newest version from @uref{http://civeng.com/sqldemo/} (the home site).
-@item @uref{http://www.mysql.com/Downloads/Contrib/myadmin-0.4.tar.gz, myadmin-0.4.tar.gz}.
-@item @uref{http://myadmin.cheapnet.net/, MyAdmin home page}
-A Web-based MySQL administrator by Mike Machado.
+@item @uref{http://www.mysql.com/Downloads/Contrib/myadmin-0.4.tar.gz}.
+MyAdmin is a web-based MySQL administrator by Mike Machado.
+TheMyAdmin homepage is at @uref{http://myadmin.cheapnet.net/}
-@item @uref{http://www.mysql.com/Downloads/Contrib/phpMyAdmin_2.0.1.tar.gz,phpMyAdmin_2.0.1.tar.gz}
+@item @uref{http://www.mysql.com/Downloads/Contrib/phpMyAdmin_2.2.0.tar.gz}
A set of PHP3-scripts to adminstrate MySQL over the WWW.
-@item @uref{http://www.phpwizard.net/projects/phpMyAdmin/, phpMyAdmin home page}
-A PHP3 tool in the spirit of mysql-webadmin, by Tobias Ratschiller, tobias@@dnet.it.
+@item @uref{http://www.phpwizard.net/projects/phpMyAdmin/}
+phpMyAdmin is a PHP3 tool in the spirit of mysql-webadmin, by Tobias Ratschiller, tobias@@dnet.it.
-@item @uref{http://www.mysql.com/Downloads/Contrib/useradm.tar.gz, useradm.tar.gz}
+@item @uref{http://www.mysql.com/Downloads/Contrib/useradm.tar.gz}
MySQL administrator in PHP. By Ofni Thomas
@email{othomas@@vaidsystems.com}.
-@item @uref{http://gossamer-threads.com/perl/mysqlman/mysql.cgi, MySQLMan}
-Similar functionality as phpmyadmin, but written with Perl and using
-html templates. By Alex Krohn.
+@item @uref{http://gossamer-threads.com/perl/mysqlman/mysql.cgi}
+MySQLMan has similar functionality to phpmyadmin, but written with
+Perl and using html templates. By Alex Krohn.
@end itemize
-@item @uref{http://www.mysql.com/Downloads/Contrib/mysql-editor.tar.gz,mysql-editor.tar.gz}
+@item @uref{http://www.mysql.com/Downloads/Contrib/mysql-editor.tar.gz}
This cgi scripts in Perl enables you to edit content of Mysql
database. By Tomas Zeman.
-@item
-@uref{http://worldcommunity.com/opensource/futuresql, FutureSQL Web Database Administration Tool}.
-FutureSQL by Peter F. Brown, is a free, open source rapid application
+
+@item @uref{http://worldcommunity.com/opensource/futuresql/}
+FutureSQL by Peter F. Brown, is a free, Open Source rapid application
development Web database administration tool, written in Perl,
using MySQL. It uses @code{DBI:DBD} and @code{CGI.pm}.
@@ -45869,12 +47517,13 @@ and "post-processing" on both fields, records, and operations.
@itemize @bullet
-@item @uref{http://www.mysql.com/Downloads/Contrib/mod_mysql_include_1.0.tar.gz, mod_mysql_include_1.0.tar.gz}
+@item @uref{http://www.mysql.com/Downloads/Contrib/mod_mysql_include_1.0.tar.gz}
Apache module to include HTML from MySQL queries into your pages,
and run update queries. Originally written to implement a simple fast
low-overhead banner-rotation system. By Sasha Pachev.
-@item @uref{http://htcheck.sourceforge.net, htCheck} - URL checker with
+@item @uref{http://htcheck.sourceforge.net/}
+htCheck is a URL checker with
MySQL backend. Spidered URLs can later be queried using SQL to retrieve
various kinds of information, eg. broken links. Written by Gabriele Bartolini.
@@ -45885,35 +47534,35 @@ Update, Delete) from an html form. You can build a complete forms
interface to a SQL database (query, add, update, delete) without any
programming! By Marc Beneteau, @email{marc@@odbsoft.com}.
-@item @uref{http://www.mysql.com/Downloads/Contrib/sqlhtml.tar.gz, sqlhtml.tar.gz}
+@item @uref{http://www.mysql.com/Downloads/Contrib/sqlhtml.tar.gz}
SQL/HTML is an HTML database manager for MySQL using @code{DBI} 1.06.
-@item @uref{http://www.mysql.com/Downloads/Contrib/udmsearch-3.0.23.tar.gz, UdmSearch 3.0.23 (stable version)}.
-@item @uref{http://www.mysql.com/Downloads/Contrib/mnogosearch-3.1.12.tar.gz, mnogosearch 3.1.12 (development but recommended version)}.
-@item @uref{http://search.mnoGo.ru, UdmSearch home page}
+@item @uref{http://www.mysql.com/Downloads/Contrib/udmsearch-3.0.23.tar.gz} (UdmSearch 3.0.23, stable version).
+@item @uref{http://www.mysql.com/Downloads/Contrib/mnogosearch-3.1.12.tar.gz} (mnogosearch 3.1.12, development but recommended version)
+@item @uref{http://search.mnoGo.ru/} (UdmSearch home page)
A SQL-based search engine for Internet. By
Alexander I. Barkov @email{bar@@izhcom.ru}.
-@item @uref{http://www.mysql.com/Downloads/Contrib/wmtcl.doc, wmtcl.doc}.
-@item @uref{http://www.mysql.com/Downloads/Contrib/wmtcl.lex, wmtcl.lex}
+@item @uref{http://www.mysql.com/Downloads/Contrib/wmtcl.doc}
+@item @uref{http://www.mysql.com/Downloads/Contrib/wmtcl.lex}
With this you can write HTML files with inclusions of Tcl code. By
@email{vvs@@scil.npi.msu.su}.
-@item @uref{http://www.mysql.com/Downloads/Contrib/www-sql-0.5.7.lsm, www-sql-0.5.7.lsm}.
-@item @uref{http://www.mysql.com/Downloads/Contrib/www-sql-0.5.7.tar.gz, www-sql-0.5.7.tar.gz}
+@item @uref{http://www.mysql.com/Downloads/Contrib/www-sql-0.5.7.lsm}
+@item @uref{http://www.mysql.com/Downloads/Contrib/www-sql-0.5.7.tar.gz}
A CGI program that parses an HTML file containing special tags, parses
them, and inserts data from a MySQL database.
-@item @uref{http://www.mysql.com/Downloads/Contrib/genquery.zip, genquery.zip}
+@item @uref{http://www.mysql.com/Downloads/Contrib/genquery.zip}
Perl SQL database interface package for html.
-@item @uref{http://www.mysql.com/Downloads/Contrib/cgi++-0.8.tar.gz, cgi++-0.8.tar.gz}
+@item @uref{http://www.mysql.com/Downloads/Contrib/cgi++-0.8.tar.gz}
A macro-processor to simply writing CGI/Database programs in C++ by Sasha Pachev.
-@item @uref{http://www.mysql.com/Downloads/Contrib/webboard-1.0.zip, WebBoard 1.0}
-EU-Industries Internet-Message-Board.
+@item @uref{http://www.mysql.com/Downloads/Contrib/webboard-1.0.zip}
+WebBoard 1.0, EU-Industries Internet-Message-Board.
-@item @uref{http://www.mysql.com/Downloads/Contrib/DBIx-TextIndex-0.02.tar.gz, DBIx-TextIndex-0.02.tar.gz}
+@item @uref{http://www.mysql.com/Downloads/Contrib/DBIx-TextIndex-0.02.tar.gz}
Full-text searching with Perl on @code{BLOB}/@code{TEXT} columns by Daniel Koch.
@end itemize
@@ -45922,9 +47571,8 @@ Full-text searching with Perl on @code{BLOB}/@code{TEXT} columns by Daniel Koch.
@appendixsec Performance Benchmarking Tools
@itemize @bullet
-@item @uref{http://www.mysql.com/Downloads/super-smack/super-smack-1.0.tar.gz,
- super-smack}
-Multi-threaded benchmarking tool for MySQL and
+@item @uref{http://www.mysql.com/Downloads/super-smack/super-smack-1.0.tar.gz}
+super-smack is a multi-threaded benchmarking tool for MySQL and
@strong{PostgreSQL}. Written in C++. Easy to extend to support other
databases that have C/C++ client libraries. By Sasha Pachev.
@end itemize
@@ -45934,61 +47582,56 @@ databases that have C/C++ client libraries. By Sasha Pachev.
@appendixsec Authentication Tools
@itemize @bullet
-@item @uref{http://www.mysql.com/Downloads/Contrib/ascend-radius-mysql-0.7.2.patch.gz,ascend-radius-mysql-0.7.2.patch.gz}
+@item @uref{http://www.mysql.com/Downloads/Contrib/ascend-radius-mysql-0.7.2.patch.gz}
This is an authentication and logging patch using MySQL for
Ascend-Radius. By @email{takeshi@@SoftAgency.co.jp}.
-@item @uref{http://www.mysql.com/Downloads/Contrib/icradius-0.10.tar.gz, icradius 0.10}
-@uref{http://www.mysql.com/Downloads/Contrib/icradius.README, icradius readme file}.
+@item @uref{http://www.mysql.com/Downloads/Contrib/icradius-0.10.tar.gz} (icradius 0.10)
+@uref{http://www.mysql.com/Downloads/Contrib/icradius.README} (icradius readme)
-@item @uref{http://www.mysql.com/Downloads/Contrib/checkpassword-0.81-mysql-0.6.6.patch.gz,
-checkpassword-0.81-mysql-0.6.6.patch.gz}
+@item @uref{http://www.mysql.com/Downloads/Contrib/checkpassword-0.81-mysql-0.6.6.patch.gz}
MySQL authentication patch for QMAIL and checkpassword. These are
useful for management user (mail, pop account) by MySQL.
By @email{takeshi@@SoftAgency.co.jp}.
-@item @uref{http://www.mysql.com/Downloads/Contrib/jradius-diff.gz, jradius-diff.gz}
+@item @uref{http://www.mysql.com/Downloads/Contrib/jradius-diff.gz}
MySQL support for Livingston's Radius 2.01. Authentication and
Accounting. By Jose de Leon, @email{jdl@@thevision.net}.
-@item @uref{http://www.mysql.com/Downloads/Contrib/mod_auth_mysql-2.20.tar.gz, mod_auth_mysql-2.20.tar.gz}
+@item @uref{http://www.mysql.com/Downloads/Contrib/mod_auth_mysql-2.20.tar.gz}
Apache authentication module for MySQL. By Zeev Suraski,
@email{bourbon@@netvision.net.il}.
@c @strong{Please} register this module at:
-@c @url{http://bourbon.netvision.net.il/mysql/mod_auth_mysql/register.html}. The
+@c @uref{http://bourbon.netvision.net.il/mysql/mod_auth_mysql/register.html}. The
@c registering information is only used for statistical purposes and will
@c encourage further development of this module!
-@item @uref{http://www.mysql.com/Downloads/Contrib/mod_log_mysql-1.05.tar.gz, mod_log_mysql-1.05.tar.gz}
-MySQL logging module for Apache. By Zeev Suraski,
-@email{bourbon@@netvision.net.il}.
-
-@item @uref{http://www.mysql.com/Downloads/Contrib/mypasswd-2.0.tar.gz, mypasswd-2.0.tar.gz}
+@item @uref{http://www.mysql.com/Downloads/Contrib/mypasswd-2.0.tar.gz}
Extra for @code{mod_auth_mysql}. This is a little tool that allows you
to add/change user records storing group and/or password entries in
MySQL tables. By Harry Brueckner, @email{brueckner@@respublica.de}.
-@item @uref{http://www.mysql.com/Downloads/Contrib/mysql-passwd.README, mysql-passwd.README}.
-@item @uref{http://www.mysql.com/Downloads/Contrib/mysql-passwd-1.2.tar.gz, mysql-passwd-1.2.tar.gz}
+@item @uref{http://www.mysql.com/Downloads/Contrib/mysql-passwd.README}
+@item @uref{http://www.mysql.com/Downloads/Contrib/mysql-passwd-1.2.tar.gz}
Extra for @code{mod_auth_mysql}. This is a two-part system for use with
@code{mod_auth_mysql}.
-@item @uref{http://www.mysql.com/Downloads/Contrib/pam_mysql.tar.gz, pam_mysql.tar.gz}
+@item @uref{http://www.mysql.com/Downloads/Contrib/pam_mysql.tar.gz}
This module authenticates users via @code{pam}, using MySQL.
-@item @uref{http://www.mysql.com/Downloads/Contrib/nsapi_auth_mysql.tar, nsapi_auth_mysql.tar}
+@item @uref{http://www.mysql.com/Downloads/Contrib/nsapi_auth_mysql.tar}
Netscape Web Server API (NSAPI) functions to authenticate (BASIC) users
against MySQL tables. By Yuan John Jiang.
-@item @uref{http://www.mysql.com/Downloads/Contrib/qmail-1.03-mysql-0.6.6.patch.gz,qmail-1.03-mysql-0.6.6.patch.gz}
+@item @uref{http://www.mysql.com/Downloads/Contrib/qmail-1.03-mysql-0.6.6.patch.gz}
Patch for qmail to authenticate users from a MySQL table.
By @email{takeshi@@SoftAgency.co.jp}.
-@item @uref{http://www.mysql.com/Downloads/Contrib/proftpd-1.2.0rc2-fix-mysql.patch, proftpd-1.2.0rc2-fix-mysql.patch}
+@item @uref{http://www.mysql.com/Downloads/Contrib/proftpd-1.2.0rc2-fix-mysql.patch}
Patch for proftpd1.2.0rc2. By @email{takeshi@@SoftAgency.co.jp}.
-@item @uref{http://www.mysql.com/Downloads/Contrib/pwcheck_mysql-0.1.tar.gz,pwcheck_mysql-0.1.tar.gz}
+@item @uref{http://www.mysql.com/Downloads/Contrib/pwcheck_mysql-0.1.tar.gz}
An authentication module for the Cyrus IMAP server. By Aaron Newsome.
@@ -45998,34 +47641,35 @@ An authentication module for the Cyrus IMAP server. By Aaron Newsome.
@appendixsec Converters
@itemize @bullet
-@item @uref{http://www.mysql.com/Downloads/Contrib/mssql2mysql.txt, mssql2mysql.txt}
+@item @uref{http://www.mysql.com/Downloads/Contrib/mssql2mysql.txt}
Converter from MS-SQL to MySQL. By Michael Kofler.
-@uref{http://www.kofler.cc/mysql/mssql2mysql.html, mssql2mysql home page}.
+The mssql2mysql home page is at
+@uref{http://www.kofler.cc/mysql/mssql2mysql.html}.
-@item @uref{http://www.mysql.com/Downloads/Contrib/dbf2mysql-1.14.tar.gz, dbf2mysql-1.14.tar.gz}
+@item @uref{http://www.mysql.com/Downloads/Contrib/dbf2mysql-1.14.tar.gz}
Convert between @file{.dbf} files and MySQL tables. By Maarten
Boekhold (@email{boekhold@@cindy.et.tudelft.nl}), William Volkman, and
Michael Widenius. This converter includes rudimentary read-only support
for MEMO fields.
-@item @uref{http://www.mysql.com/Downloads/Contrib/dbf2mysql-1.13.tgz, dbf2mysql-1.13.tgz}
+@item @uref{http://www.mysql.com/Downloads/Contrib/dbf2mysql-1.13.tgz}
Convert between @file{.dbf} files and MySQL tables. By Maarten
Boekhold, @email{boekhold@@cindy.et.tudelft.nl}, and Michael Widenius.
This converter can't handle MEMO fields.
-@item @uref{http://www.mysql.com/Downloads/Contrib/dbf2mysql.zip, dbf2mysql.zip}
+@item @uref{http://www.mysql.com/Downloads/Contrib/dbf2mysql.zip}
Convert between FoxPro @file{.dbf} files and MySQL tables on Windows.
By Alexander Eltsyn, @email{ae@@nica.ru} or @email{ae@@usa.net}.
-@item @uref{http://www.mysql.com/Downloads/Contrib/dbf2sql.zip, dbf2sql.zip}
+@item @uref{http://www.mysql.com/Downloads/Contrib/dbf2sql.zip}
Short and simple prg that can help you transport your data from foxpro
table into MySQL table. By Danko Josic.
-@item @uref{http://www.mysql.com/Downloads/Contrib/dump2h-1.20.gz, dump2h-1.20.gz}
+@item @uref{http://www.mysql.com/Downloads/Contrib/dump2h-1.20.gz}
Convert from @code{mysqldump} output to a C header file. By Harry Brueckner,
@email{brueckner@@mail.respublica.de}.
-@item @uref{http://www.mysql.com/Downloads/Contrib/exportsql.txt, exportsql.txt}
+@item @uref{http://www.mysql.com/Downloads/Contrib/exportsql.txt}
A script that is similar to @code{access_to_mysql.txt}, except that this
one is fully configurable, has better type conversion (including
detection of @code{TIMESTAMP} fields), provides warnings and suggestions
@@ -46035,28 +47679,29 @@ and is free of charge for anyone. See
@uref{http://www.cynergi.net/exportsql/} for the latest version. By
Pedro Freire, @email{support@@cynergi.net}. NOTE: Doesn't work with
Access2!
-@item @uref{http://www.mysql.com/Downloads/Contrib/access_to_mysql.txt, access_to_mysql.txt}
+
+@item @uref{http://www.mysql.com/Downloads/Contrib/access_to_mysql.txt}
Paste this function into an Access module of a database that has the
tables you want to export. See also @code{exportsql}. By Brian Andrews.
NOTE: Doesn't work with Access2!
-@item @uref{http://www.mysql.com/Downloads/Contrib/importsql.txt, importsql.txt}
+@item @uref{http://www.mysql.com/Downloads/Contrib/importsql.txt}
A script that does the exact reverse of @code{exportsql.txt}. That is,
it imports data from MySQL into an Access database via
ODBC. This is very handy when combined with exportsql, because it lets you
-use Access for all DB design and administration, and synchronize with
+use Access for all DB design and administration, and synchronise with
your actual MySQL server either way. Free of charge. See
@uref{http://www.netdive.com/freebies/importsql/} for any updates.
Created by Laurent Bossavit of NetDIVE.
@strong{NOTE:} Doesn't work with Access2!
-@item @uref{http://www.mysql.com/Downloads/Contrib/mdb2sql.bas, mdb2sql.bas}
+@item @uref{http://www.mysql.com/Downloads/Contrib/mdb2sql.bas}
Converter from Access97 to MySQL by Moshe Gurvich.
-@item @uref{http://www.mysql.com/Downloads/Contrib/msql2mysqlWrapper-1.0.tgz, msql2mysqlWrapper 1.0}
+@item @uref{http://www.mysql.com/Downloads/Contrib/msql2mysqlWrapper-1.0.tgz}
A C wrapper from @code{mSQL} to MySQL. By @email{alfred@@sb.net}
-@item @uref{http://www.mysql.com/Downloads/Contrib/sqlconv.pl, sqlconv.pl}
+@item @uref{http://www.mysql.com/Downloads/Contrib/sqlconv.pl}
A simple script that can be used to copy fields from one MySQL table
to another in bulk. Basically, you can run @code{mysqldump} and pipe it to
the @code{sqlconv.pl} script. The script will parse through the
@@ -46065,14 +47710,14 @@ inserted into a new table. An example is when you want to create a new
table for a different site you are working on, but the table is just a
bit different (that is - fields in different order, etc.).
By Steve Shreeve.
-@item @uref{http://www.mysql.com/Downloads/Contrib/oracledump, oracledump}
+@item @uref{http://www.mysql.com/Downloads/Contrib/oracledump}
Perl program to convert Oracle databases to MySQL. Has same
output format as mysqldump. By Johan Andersson.
-@item @uref{http://www.mysql.com/Downloads/Contrib/excel2mysql.pl, excel2mysql.pl}
+@item @uref{http://www.mysql.com/Downloads/Contrib/excel2mysql.pl}
Perl program to import Excel spreadsheets into a MySQL database. By Stephen Hurd @email{shurd@@sk.sympatico.ca}
-@item @uref{http://www.mysql.com/Downloads/Contrib/T2S_100.ZIP, T2S_100.ZIP}.
+@item @uref{http://www.mysql.com/Downloads/Contrib/T2S_100.ZIP}.
Windows program to convert text files to MySQL databases. By
Asaf Azulay.
@@ -46081,13 +47726,13 @@ Asaf Azulay.
@appendixsec Using MySQL with Other Products
@itemize @bullet
-@item @uref{http://www.mysql.com/Downloads/Contrib/emacs-sql-mode.tar.gz, emacs-sql-mode.tar.gz}
+@item @uref{http://www.mysql.com/Downloads/Contrib/emacs-sql-mode.tar.gz}
Raw port of a SQL mode for XEmacs. Supports completion. Original by
Peter D. Pezaris @email{pez@@atlantic2.sbi.com} and partial
MySQL port by David Axmark.
-@item @uref{http://www.mysql.com/Downloads/Win32/myaccess97_1_4.zip, MyAccess97 1.4}.
-@item @uref{http://www.mysql.com/Downloads/Win32/myaccess2000_1_4.zip, MyAccess2000 1.4}.
+@item @uref{http://www.mysql.com/Downloads/Win32/myaccess97_1_4.zip} (MyAccess97 1.4)
+@item @uref{http://www.mysql.com/Downloads/Win32/myaccess2000_1_4.zip} (MyAccess2000 1.4)
MyAccess is an AddIn for MS Access 97/2000 that allows you to manage
MySQL databases from within Access. Main functions are:
@@ -46100,67 +47745,66 @@ MySQL databases from within Access. Main functions are:
@item Show a "Database Definition Report
@end itemize
-Written by Hubertus Hiden. @uref{http://www.accessmysql.com, MyAccess homepage}.
+Written by Hubertus Hiden.
+The MyAccess homepage is at @uref{http://www.accessmysql.com/}.
-@item @uref{http://www.mysql.com/Downloads/Contrib/radius-0.3.tar.gz, radius-0.3.tar.gz}
+@item @uref{http://www.mysql.com/Downloads/Contrib/radius-0.3.tar.gz}
Patches for @code{radiusd} to make it support MySQL. By Wim Bonis,
@email{bonis@@kiss.de}.
@end itemize
-@cindex tools, useful
-@appendixsec Useful Tools
+@cindex utilities
+@appendixsec Utilities
@itemize @bullet
-@item @uref{http://worldcommunity.com/opensource/utilities/mysql_backup.html, MySQL Backup}.
-
-A backup script for MySQL. By Peter F. Brown.
+@item @uref{http://worldcommunity.com/opensource/utilities/mysql_backup.html}
+MySQL Backup is a backup script for MySQL. By Peter F. Brown.
-@item @uref{http://www.mysql.com/Downloads/Contrib/mytop, mytop}
-@item @uref{http://public.yahoo.com/~jzawodn/mytop/, mytop home page}
+@item @uref{http://www.mysql.com/Downloads/Contrib/mytop}
+@item @uref{http://public.yahoo.com/~jzawodn/mytop/} (mytop home page)
mytop is a Perl program that allows you to monitor MySQL servers by
viewing active threads, queries, and overall server performance
numbers. By Jeremy D. Zawodny.
-@item @uref{http://www.mysql.com/Downloads/Contrib/mysql_watchdog.pl, mysql_watchdog.pl}
+@item @uref{http://www.mysql.com/Downloads/Contrib/mysql_watchdog.pl}
Monitor the MySQL daemon for possible lockups. By Yermo Lamers,
@email{yml@@yml.com}.
-@item @uref{http://www.mysql.com/Downloads/Contrib/mysqltop.tar.gz, mysqltop.tar.gz}
+@item @uref{http://www.mysql.com/Downloads/Contrib/mysqltop.tar.gz}
Sends a query in a fixed time interval to the server and shows the
resulting table. By Thomas Wana.
-@item @uref{http://www.mysql.com/Downloads/Contrib/mysql_structure_dumper.tar.gz,mysql_structure_dumper.tar.gz}
-Prints out the structure of the all tables in a database. By Thomas Wana.
-@item @uref{http://www.mysql.com/Downloads/Contrib/mysql_structure_dumper.tgz, structure_dumper.tgz}
+@item @uref{http://www.mysql.com/Downloads/Contrib/mysql_structure_dumper.tar.gz}
+@item @uref{http://www.mysql.com/Downloads/Contrib/mysql_structure_dumper.tgz}
Prints the structure of every table in a database. By Thomas Wana.
-@item @uref{http://www.mysql.com/Downloads/Contrib/mysqlsync, mysqlsync-1.0-alpha.tar.gz}.
+@item @uref{http://www.mysql.com/Downloads/Contrib/mysqlsync}.
A Perl script to keep remote copies of a MySQL database in sync with a
central master copy. By Mark Jeftovic. @email{markjr@@easydns.com}.
-@item @uref{http://www.mysql.com/Downloads/Contrib/MySQLTutor-0.2.tar.gz, MySQLTutor}.
+@item @uref{http://www.mysql.com/Downloads/Contrib/MySQLTutor-0.2.tar.gz}.
MySQLTutor. A MySQL tutorial for beginners.
-@item @uref{http://www.mysql.com/Downloads/Contrib/MySQLDB.zip, MySQLDB.zip}
+@item @uref{http://www.mysql.com/Downloads/Contrib/MySQLDB.zip}
+@item @uref{http://www.mysql.com/Downloads/Contrib/MySQLDB-readme.html}.
A COM library for MySQL by Alok Singh.
-@item @uref{http://www.mysql.com/Downloads/Contrib/MySQLDB-readme.html, MySQLDB-readme.html}.
-@item @uref{http://www.mysql.com/Downloads/Contrib/mysql_replicate.pl, mysql_replicate.pl}
+@item @uref{http://www.mysql.com/Downloads/Contrib/mysql_replicate.pl}
Perl program that handles replication. By @email{elble@@icculus.nsg.nwu.edu}
-@item @uref{http://www.mysql.com/Downloads/Contrib/DBIx-TextIndex-0.02.tar.gz, DBIx-TextIndex-0.02.tar.gz}
+@item @uref{http://www.mysql.com/Downloads/Contrib/DBIx-TextIndex-0.02.tar.gz}
Perl script that uses reverse indexing to handle text searching.
By Daniel Koch.
-@item @uref{http://www.mysql.com/Downloads/Contrib/dbcheck, dbcheck}
+@item @uref{http://www.mysql.com/Downloads/Contrib/dbcheck}
Perl script that takes a backup of tables before running isamchk on them.
By Elizabeth.
@item @uref{http://www.mysql.com/Downloads/Contrib/mybackup}.
-@item @uref{http://www.mswanson.com/mybackup, mybackup home page}
+@item @uref{http://www.mswanson.com/mybackup} (mybackup home page)
Wrapper for mysqldump to backup all databases. By Marc Swanson.
-@item @uref{http://www.mysql.com/Downloads/Contrib/mdu.pl.gz,mdu.pl.gz}
+@item @uref{http://www.mysql.com/Downloads/Contrib/mdu.pl.gz}
Prints the storage usage of a MySQL database.
@end itemize
@@ -46169,55 +47813,55 @@ Prints the storage usage of a MySQL database.
@appendixsec RPMs for Common Tools (Most Are for RedHat 6.1)
@itemize @bullet
-@item @uref{http://www.mysql.com/Downloads/Contrib/perl-Data-ShowTable-3.3-2.i386.rpm,perl-Data-ShowTable-3.3-2.i386.rpm}
-@item @uref{http://www.mysql.com/Downloads/Contrib/perl-Msql-Mysql-modules-1.2210-2.i386.rpm,perl-Msql-Mysql-modules-1.2210-2.i386.rpm}
-@item @uref{http://www.mysql.com/Downloads/Contrib/php-pg-3.0.13-1.i386.rpm,php-pg-3.0.13-1.i386.rpm}
-@item @uref{http://www.mysql.com/Downloads/Contrib/php-pg-manual-3.0.13-1.i386.rpm,php-pg-manual-3.0.13-1.i386.rpm}
-@item @uref{http://www.mysql.com/Downloads/Contrib/php-pg-mysql-3.0.13-1.i386.rpm,php-pg-mysql-3.0.13-1.i386.rpm}
-@item @uref{http://www.mysql.com/Downloads/Contrib/phpMyAdmin-2.0.5-1.noarch.rpm,phpMyAdmin-2.0.5-1.noarch.rpm}
+@item @uref{http://www.mysql.com/Downloads/Contrib/perl-Data-ShowTable-3.3-2.i386.rpm}
+@item @uref{http://www.mysql.com/Downloads/Contrib/perl-Msql-Mysql-modules-1.2210-2.i386.rpm}
+@item @uref{http://www.mysql.com/Downloads/Contrib/php-pg-3.0.13-1.i386.rpm}
+@item @uref{http://www.mysql.com/Downloads/Contrib/php-pg-manual-3.0.13-1.i386.rpm}
+@item @uref{http://www.mysql.com/Downloads/Contrib/php-pg-mysql-3.0.13-1.i386.rpm}
+@item @uref{http://www.mysql.com/Downloads/Contrib/phpMyAdmin-2.0.5-1.noarch.rpm}
@end itemize
@cindex functions, useful
@appendixsec Useful Functions
@itemize @bullet
-@item @uref{http://www.mysql.com/Downloads/Contrib/mysnprintf.c,mysnprintf.c}
+@item @uref{http://www.mysql.com/Downloads/Contrib/mysnprintf.c}
sprintf() function for SQL queries that can escape blobs. By Chunhua Liu.
@end itemize
-@appendixsec Windows programs
+@appendixsec Windows Programs
@itemize @bullet
-@item @uref{http://www.mysql.com/Downloads/Contrib/LaunchMySQL.zip, LaunchMySQL.zip}
+@item @uref{http://www.mysql.com/Downloads/Contrib/LaunchMySQL.zip}
The program launches the MySQL server, shuts it down, and
display status information. By Bill Thompson
@end itemize
-@appendixsec Uncategorized
+@appendixsec Uncategorised
@itemize @bullet
-@item @uref{http://www.mysql.com/Downloads/Contrib/findres.pl, findres.pl}
+@item @uref{http://www.mysql.com/Downloads/Contrib/findres.pl}
Find reserved words in tables. By Nem W Schlecht.
-@item @uref{http://www.mysql.com/Downloads/Contrib/handicap.tar.gz, handicap.tar.gz}
+@item @uref{http://www.mysql.com/Downloads/Contrib/handicap.tar.gz}
Performance handicapping system for yachts. Uses PHP. By
@email{rhill@@stobyn.ml.org}.
-@item @uref{http://www.mysql.com/Downloads/Contrib/hylalog-1.0.tar.gz, hylalog-1.0.tar.gz}
+@item @uref{http://www.mysql.com/Downloads/Contrib/hylalog-1.0.tar.gz}
Store @code{hylafax} outgoing faxes in a MySQL database. By Sinisa
Milivojevic, @email{sinisa@@mysql.com}.
-@item @uref{http://www.mysql.com/Downloads/Contrib/mrtg-mysql-1.0.tar.gz, mrtg-mysql-1.0.tar.gz}
+@item @uref{http://www.mysql.com/Downloads/Contrib/mrtg-mysql-1.0.tar.gz}
MySQL status plotting with MRTG, by Luuk de Boer, @email{luuk@@wxs.nl}.
-@item @uref{http://www.mysql.com/Downloads/Contrib/wuftpd-2.4.2.18-mysql_support.2.tar.gz, wuftpd-2.4.2.18-mysql_support.2.tar.gz}
+@item @uref{http://www.mysql.com/Downloads/Contrib/wuftpd-2.4.2.18-mysql_support.2.tar.gz}
Patches to add logging to MySQL for WU-ftpd. By Zeev Suraski,
@email{bourbon@@netvision.net.il}.
-@item @uref{http://www.mysql.com/Downloads/Contrib/wu-ftpd-2.6.0-mysql.4.tar.gz,wu-ftpd-2.6.0-mysql.4.tar.gz}
+@item @uref{http://www.mysql.com/Downloads/Contrib/wu-ftpd-2.6.0-mysql.4.tar.gz}
Patches to add logging to MySQL for WU-ftpd 2.6.0. By
@email{takeshi@@SoftAgency.co.jp}, based on Zeev Suraski wuftpd patches.
-@item @uref{http://www.mysql.com/Downloads/Contrib/Old-Versions, Old-Versions}
+@item @uref{http://www.mysql.com/Downloads/Contrib/Old-Versions}
Previous versions of things found here that you probably won't be
interested in.
@end itemize
@@ -46244,14 +47888,15 @@ helped to make MySQL what it is today.
@node Developers, Contributors, Credits, Credits
@appendixsec Developers at MySQL AB
-These are the developers that are or have been employed by MySQL AB
-to work on MySQL, roughly in the order they started to work with us.
-Following each developer is a small list of the tasks that the developer is
-responsible for, or the accomplishments they have made.
+These are the developers that are or have been employed by @code{MySQL AB}
+to work on the @code{MySQL} database software, roughly in the order they
+started to work with us. Following each developer is a small list of the
+tasks that the developer is responsible for, or the accomplishments they
+have made.
@table @asis
@item Michael (Monty) Widenius
-Has written the following parts of MySQL:
+Has written the following parts of the MySQL database software:
@itemize @bullet
@item
All the main code in @code{mysqld}.
@@ -46266,11 +47911,11 @@ handlers with index compression and different record formats).
The @code{HEAP} library. A memory table system with our superior full dynamic
hashing. In use since 1981 and published around 1984.
@item
-The @code{replace} program (look into it, it's COOL!).
+The @code{replace} program (take a look at it, it's @strong{COOL}!).
@item
@strong{MyODBC}, the ODBC driver for Windows95.
@item
-Fixing bugs in MIT-pthreads to get it to work for MySQL. And
+Fixing bugs in MIT-pthreads to get it to work for MySQL Server. And
also Unireg, a curses-based application tool with many utilities.
@item
Porting of @code{mSQL} tools like @code{msqlperl}, @code{DBD}/@code{DBI}, and
@@ -46285,7 +47930,7 @@ Most of crash-me and the foundation for the MySQL benchmarks.
Coordinator and initial main writer of the @strong{Reference Manual},
including enhancements to @code{texi2html}.
@item
-Automatic Web site updating from the manual.
+Automatic web site updating from the manual.
@item
Initial Autoconf, Automake, and Libtool support.
@item
@@ -46298,7 +47943,7 @@ Lots of testing of new features.
@item
Our in-house ``free'' software lawyer.
@item
-Mailing list maintainer (who never has the time to do it right...)
+Mailing list maintainer (who never has the time to do it right...).
@item
Our original portability code (more than 10 years old now). Nowadays
only some parts of @code{mysys} are left.
@@ -46314,7 +47959,7 @@ that new feature to work.
@item
A lot of extensions to the @code{mysql} client.
@item
-@code{procedure analyse()}
+@code{PROCEDURE ANALYSE()}
@end itemize
@item Sinisa Milivojevic
@@ -46322,11 +47967,31 @@ A lot of extensions to the @code{mysql} client.
@item
Compression (with @code{zlib}) in the client/server protocol.
@item
-Perfect hashing for the lexical analyzer phase.
+Perfect hashing for the lexical analyser phase.
+@item
+Multi-row @code{INSERT}
+@item
+@code{mysqldump} -e option
+@item
+@code{LOAD DATA INFILE LOCAL}
@item
-The MySQLGUI client.
+@code{SQL_CALC_FOUND_ROWS} @code{SELECT} option
@item
-Maintainer of mysql++.
+@code{--max-user-connections=...} option
+@item
+@code{net_read} and @code{net_write_timeout}
+@item
+@code{GRANT}/@code{REVOKE} and @code{SHOW GRANTS FOR}
+@item
+New client-server protocol for 4.0
+@item
+@code{UNION}.
+@item
+Multi-table @code{DELETE}/@code{UPDATE}
+@item
+The @code{MySQLGUI} client.
+@item
+Maintainer of @code{MySQL++}.
@end itemize
@item Tonu Samuel
@@ -46334,9 +47999,9 @@ Maintainer of mysql++.
@item
Our security expert.
@item
-Vio interface (The foundation for the encrypted client/server protocol).
+Vio interface (the foundation for the encrypted client/server protocol).
@item
-MySQL Filesystem (A way to use MySQL databases as files
+MySQL Filesystem (a way to use MySQL databases as files
and directories).
@item
The CASE Expression.
@@ -46371,6 +48036,8 @@ Our webmaster.
@item Miguel Solorzano
@itemize @bullet
@item
+Win32 development.
+@item
Winmysqladmin.
@end itemize
@@ -46402,32 +48069,21 @@ Proofreading and editing this fine manual.
@code{DELETE ... ORDER BY ...}.
@end itemize
-@item John Dean
-@itemize @bullet
-@item
-The new MySQL GUI client.
-@end itemize
-
@item Indrek Siitan
@itemize @bullet
@item
Designer/programmer of our web interface.
@end itemize
-@end table
-
-The following non-developers are also working in/with MySQL AB:
-@table @asis
-@item
-Hans Kierkegaard - Responsible for MySQL license handling.
-@item
-Antti Halonen - Sales manager.
+@item Jorge del Conde
+@itemize @bullet
@item
-Jonas Norrman - Handles licensing questions sent to @email{info@@mysql.com}.
+@code{MyCC} @code{MySQL Control Center}.
@item
-Erik Granberg - Handles MySQL partners (and a lot of other stuff).
+Web portals.
@item
-Allan Larsson (The BOSS for TCX DataKonsult AB).
+Win32 development.
+@end itemize
@end table
@@ -46436,8 +48092,10 @@ Allan Larsson (The BOSS for TCX DataKonsult AB).
@cindex contributors, list of
-Contributors to the MySQL distribution are listed here, in
-somewhat random order:
+While @code{MySQL AB} owns all copyrights in the @code{MySQL server}
+and the @code{MySQL manual}, we wish to recognise those who have made
+contributions of one kind or another to the @code{MySQL distribution}.
+Contributors are listed here, in somewhat random order:
@table @asis
@item Paul DuBois
@@ -46456,18 +48114,19 @@ record format.
Win32 port with Borland compiler. @code{mysqlshutdown.exe} and
@code{mysqlwatch.exe}
@item David J. Hughes
-For the effort to make a shareware SQL database. We at TcX started with
-@code{mSQL}, but found that it couldn't satisfy our purposes so instead we
-wrote a SQL interface to our application builder Unireg. @code{mysqladmin}
-and @code{mysql} are programs that were largely influenced by their
-@code{mSQL} counterparts. We have put a lot of effort into making the
-MySQL syntax a superset of @code{mSQL}. Many of the API's ideas are
-borrowed from @code{mSQL} to make it easy to port free @code{mSQL} programs
-to MySQL. MySQL doesn't contain any code from @code{mSQL}.
+For the effort to make a shareware SQL database. At TcX, the predecessor
+of MySQL AB, we started with @code{mSQL}, but found that it couldn't
+satisfy our purposes so instead we wrote a SQL interface to our
+application builder Unireg. @code{mysqladmin} and @code{mysql} client are
+programs that were largely influenced by their @code{mSQL} counterparts.
+We have put a lot of effort into making the MySQL syntax a superset of
+@code{mSQL}. Many of the API's ideas are borrowed from @code{mSQL} to
+make it easy to port free @code{mSQL} programs to the MySQL API.
+The MySQL software doesn't contain any code from @code{mSQL}.
Two files in the distribution (@file{client/insert_test.c} and
@file{client/select_test.c}) are based on the corresponding (non-copyrighted)
files in the @code{mSQL} distribution, but are modified as examples showing
-the changes necessary to convert code from @code{mSQL} to MySQL.
+the changes necessary to convert code from @code{mSQL} to MySQL Server.
(@code{mSQL} is copyrighted David J. Hughes.)
@item Fred Fish
For his excellent C debugging and trace library. Monty has made a number
@@ -46482,9 +48141,9 @@ From whom we got an excellent compiler (@code{gcc}), the @code{libc} library
and the @code{readline} library (for the @code{mysql} client).
@item Free Software Foundation & The XEmacs development team
For a really great editor/environment used by almost everybody at
-TcX/MySQL AB/detron.
+MySQL AB/TcX/detron.
@item Patrick Lynch
-For helping us acquire @code{http://www.mysql.com/}.
+For helping us acquire @uref{http://www.mysql.com/}.
@item Fred Lindberg
For setting up qmail to handle the MySQL mailing list and for the
incredible help we got in managing the MySQL mailing lists.
@@ -46498,9 +48157,9 @@ For the @code{DBD} (Perl) interface.
@item Tim Bunce
Author of @code{mysqlhotcopy}.
@item Andreas Koenig @email{a.koenig@@mind.de}
-For the Perl interface to MySQL.
+For the Perl interface for MySQL Server.
@item Eugene Chan @email{eugene@@acenet.com.sg}
-For porting PHP to MySQL.
+For porting PHP for MySQL Server.
@item Michael J. Miller Jr. @email{mke@@terrapin.turbolift.com}
For the first MySQL manual. And a lot of spelling/language
fixes for the FAQ (that turned into the MySQL manual a long
@@ -46508,7 +48167,7 @@ time ago).
@item Yan Cailin
First translator of the MySQL Reference Manual into simplified
chinese in early 2000 on which the Big5 and HK coded
-(@uref{http://mysql.hitstar.com, mysql.hitstar.com}) versions were
+(@uref{http://mysql.hitstar.com/}) versions were
based. @uref{http://linuxdb.yeah.net, Personal home page at
linuxdb.yeah.net}.
@item Giovanni Maruzzelli @email{maruzz@@matrice.it}
@@ -46519,7 +48178,7 @@ software developed by Chris Provenzano, the University of California,
Berkeley, and contributors. We are currently using version 1_60_beta6
patched by Monty (see @file{mit-pthreads/Changes-mysql}).
@item Xavier Leroy @email{Xavier.Leroy@@inria.fr}
-The author of LinuxThreads (used by MySQL on Linux).
+The author of LinuxThreads (used by the MySQL Server on Linux).
@item Zarko Mocnik @email{zarko.mocnik@@dem.si}
Sorting for Slovenian language and the @file{cset.tar.gz} module that makes
it easier to add other character sets.
@@ -46531,15 +48190,14 @@ answering on the MySQL mailing list.
@item Yves Carlier @email{Yves.Carlier@@rug.ac.be}
@code{mysqlaccess}, a program to show the access rights for a user.
@item Rhys Jones @email{rhys@@wales.com} (And GWE Technologies Limited)
-For the JDBC, a module to extract data from MySQL with a Java
-client.
+For the JDBC, a module to extract data from a MySQL Database with a Java client.
@item Dr Xiaokun Kelvin ZHU @email{X.Zhu@@brad.ac.uk}
Further development of the JDBC driver and other MySQL-related
Java tools.
@item James Cooper @email{pixel@@organic.com}
For setting up a searchable mailing list archive at his site.
@item Rick Mehalick @email{Rick_Mehalick@@i-o.com}
-For @code{xmysql}, a graphical X client for MySQL.
+For @code{xmysql}, a graphical X client for MySQL Server.
@item Doug Sisk @email{sisk@@wix.com}
For providing RPM packages of MySQL for RedHat Linux.
@item Diemand Alexander V. @email{axeld@@vial.ethz.ch}
@@ -46563,7 +48221,7 @@ Spanish error messages.
Norwegian error messages and testing of Version 3.21.#.
@item Timur I. Bakeyev @email{root@@timur.tatarstan.ru}
Russian error messages.
-@item @email{brenno@@dewinter.com} && Filippo Grassilli @email{phil@@hyppo.com}
+@item @email{brenno@@dewinter.com} & Filippo Grassilli @email{phil@@hyppo.com}
Italian error messages.
@item Dirk Munzinger @email{dirk@@trinity.saar.de}
German error messages.
@@ -46605,11 +48263,11 @@ Help to set up InstallShield for MySQL-Win32.
@item Jethro Wright III @email{jetman@@li.net}
The @file{libmysql.dll} library.
@item James Pereria @email{jpereira@@iafrica.com}
-Mysqlmanager, a Win32 GUI tool for administrating MySQL.
+Mysqlmanager, a Win32 GUI tool for administrating MySQL Server.
@item Curt Sampson @email{cjs@@portal.ca}
Porting of MIT-pthreads to NetBSD/Alpha and NetBSD 1.3/i386.
@item Antony T. Curtis @email{antony.curtis@@olcs.net}
-Porting of MySQL to OS/2.
+Porting of the MySQL Database software to OS/2.
@item Martin Ramsch @email{m.ramsch@@computer.org}
Examples in the MySQL Tutorial.
@item Steve Harvey
@@ -46622,6 +48280,9 @@ Configure updates for Tru64, large file support and better TCP wrappers
support.
@item John Birrell
Emulation of pthread_mutex() for OS/2.
+@item Benjamin Pflugmann
+Extended @code{MERGE} tables to handle @code{INSERTS}. Active member
+on the MySQL mailing lists.
@end table
Other contributors, bugfinders, and testers: James H. Thompson, Maurizio
@@ -46676,10 +48337,11 @@ ODBC and VisualC++ interface questions.
@cindex contributing companies, list of
-The following companies has helped us finance development of
-MySQL by either paying us for developing a new feature,
-developed a MySQL feature themselves or by giving us hardware for
-MySQL development.
+While @code{MySQL AB} owns all copyrights in the @code{MySQL server}
+and the @code{MySQL manual}, we wish to recognise the following companies,
+which helped us finance the development of the @code{MySQL server},
+such as by paying us for developing a new feature or giving us hardware
+for development of the @code{MySQL server}.
@table @asis
@item VA Linux / Andover.net
@@ -46713,8 +48375,8 @@ source code.
Note that we tend to update the manual at the same time we make changes to
MySQL. If you find a version listed below that you can't
-find on the
-@uref{http://www.mysql.com/downloads/,MySQL download page},
+find on the MySQL download page
+(@uref{http://www.mysql.com/downloads/}),
this means that the version has not yet been released!
@menu
@@ -46730,49 +48392,256 @@ this means that the version has not yet been released!
@node News-4.0.x, News-3.23.x, News, News
@appendixsec Changes in release 4.0.x (Development; Alpha)
-We have now started to work on MySQL 4.0. We will update this
-section as we add new features, so that others can follow our development.
+We are now working actively on MySQL 4.0 and will only provide critical
+bug fixes for MySQL 3.23. We will update this section as we add new
+features, so that others can follow our development.
Our TODO section contains what we plan to have in 4.0. @xref{TODO MySQL 4.0}.
+@cindex changes, version 4.0
+
@menu
+* News-4.0.2:: Changes in release 4.0.2
+* News-4.0.1:: Changes in release 4.0.1
* News-4.0.0:: Changes in release 4.0.0
@end menu
+@node News-4.0.2, News-4.0.1, News-4.0.x, News-4.0.x
+@appendixsubsec Changes in release 4.0.2
-@node News-4.0.0, , News-4.0.x, News-4.0.x
-@appendixsubsec Changes in release 4.0.0
+@itemize @bullet
+@item
+Allow numeric user id to @code{mysqld --user=#}.
+@item
+Fixed a bug where @code{SQL_CALC_ROWS} returned a wrong value when used
+with one table and @code{ORDER BY} and with InnoDB tables.
+@item
+Fixed that @code{SELECT 0 LIMIT 0} doesn't hang thread.
+@item
+Fixed some problems with @code{USE KEYS} / @code{IGNORE KEYS} when using
+many keys with the same start column.
+@item
+Don't use table scan with BerkeleyDB and InnoDB tables when we can use
+an index that covers the whole row.
+@item
+Optimized InnoDB sort-buffer handling to take less memory.
+@item
+Fixed bug in multi table @code{DELETE} and InnoDB tables.
+@item
+Fixed problem with @code{TRUNCATE} and InnoDB that gave the error
+@code{Can't execute the given command because you have active locked
+tables or an active transaction}.
+@item
+Added sql-mode flag @code{NO_UNSIGNED_SUBTRACTION} to disable unsigned
+arithmetic rules when it comes to subtraction. (This will make MySQL 4.0
+behave more closely to 3.23 with @code{UNSIGNED} columns).
+@item
+Added @code{WITH MAX_QUERIES_PER_HOUR=#} to @code{GRANT} command.
+@item
+The type returned for all bit functions (@code{|}, @code{<<} ...) is now of
+type @code{unsigned integer}.
+@item
+Added detection of @code{nan} values in MyISAM to make it possible to
+repair tables with @code{nan} in float or double columns.
+@item
+Fixed new bug in @code{myisamchk} where it didn't correctly update number of
+``parts'' in the MyISAM index file.
+@item
+Changed to use @code{autoconf} 2.52 (from @code{autoconf} 2.13).
+@item
+Fixed optimization problem where the MySQL Server was in ``preparing'' state
+for a long time when selecting from an empty table which had contained
+a lot of rows.
+@item
+Fixed bug in complicated join with @code{const} tables. This fix also
+improves performance a bit when referring to another table from a
+@code{const} table.
+@item
+First pre-version of multi table @code{UPDATE}s.
+@item
+Fixed bug in multi table @code{DELETE}.
+@item
+Fixed bug in @code{SELECT CONCAT(argument-list) ... GROUP BY 1}.
+@item
+@code{INSERT ... SELECT} did a full rollback in case of an error. Fixed
+so that we only roll back the last statement in the current transaction.
+@item
+Fixed bug with empty expression for boolean fulltext search.
+@item
+Fixed core dump bug in updating fulltext key from/to @code{NULL}.
+@item
+ODBC compatibility: Added @code{BIT_LENGTH()}.
+@item
+Fixed core dump bug in @code{GROUP BY BINARY column}.
+@item
+Added support for @code{NULL} keys in HEAP tables.
+@item
+Use index for @code{ORDER BY} in queries of type:
+@code{SELECT * FROM t WHERE key_part1=1 ORDER BY key_part1 DESC,key_part2 DESC}
+@item
+Fixed bug in @code{FLUSH QUERY CACHE}.
+@item
+Added @code{CAST()} and @code{CONVERT()} functions. The @code{CAST} and
+@code{CONVERT} functions are nearly identical and mainly useful when you
+want to create a column with a specific type in a @code{CREATE ... SELECT}.
+For more information, read @ref{Cast Functions}.
+@item
+@code{CREATE ... SELECT} on @code{DATE} and @code{TIME} functions now
+create columns of the expected type.
+@item
+Changed order in which keys are created in tables.
+@item
+Added a new columns @code{Null} and @code{Index_type} to @code{SHOW INDEX}.
+@end itemize
-@cindex changes, version 4.0
+@node News-4.0.1, News-4.0.0, News-4.0.2, News-4.0.x
+@appendixsubsec Changes in release 4.0.1
@itemize @bullet
@item
-Multi-table @code{DELETE}.
+Fixed bug when @code{HANDLER} was used with some unsupported table type.
@item
-Don't support old client protocols prior to MySQL 3.21 any more.
+@code{mysqldump} now puts @code{ALTER TABLE table_name DISABLE KEYS} and
+@code{ALTER TABLE table_name DISABLE KEYS} in the sql dump.
@item
-Don't include the old C API functions @code{mysql_drop_db},
-@code{mysql_create_db} and @code{mysql_connect}, unless compiled with
-@code{USE_OLD_FUNCTIONS}.
+Added @code{mysql_fix_extensions} script.
@item
-Renamed @code{safe_mysqld} to @code{mysqld_safe}.
+Fixed stack overrun problem @code{LOAD DATA FROM MASTER} on OSF1.
@item
-Allow @code{IN} as a synonym for @code{FROM} in @code{SHOW} commands.
+Fixed shutdown problem on HP-UX.
@item
-@code{SHOW INDEXES} is now a synonym for @code{SHOW INDEX}.
+Added functions @code{des_encrypt()} and @code{des_decrypt()}.
@item
-Added support for symbolic links to @code{MyISAM} tables. Symlink handling is
-now enabled by default for Windows.
+Added statement @code{FLUSH DES_KEY_FILE}.
@item
-@code{LOAD DATA FROM MASTER} ``auto-magically'' sets up a slave.
+Added @code{mysqld} option @code{--des-key-file}.
+@item
+@code{HEX(string)} now returns the characters in string converted to
+hexadecimal.
+@item
+Fixed problem with @code{GRANT} when using @code{lower_case_table_names == 1}.
+@item
+Changed @code{SELECT ... IN SHARE MODE} to
+@code{SELECT ... LOCK IN SHARE MODE} (as in MySQL 3.23).
+@item
+A new query cache to cache results from identical @code{SELECT} queries.
+@item
+Fixed core dump bug on 64-bit machines when it got an incorrect communication
+packet.
+@item
+@code{MATCH ... AGAINST(... IN BOOLEAN MODE)} can now work
+without @code{FULLTEXT} index.
+@item
+Fixed slave to replicate from 3.23 master.
+@item
+Miscellaneous replication fixes/cleanup.
+@item
+Got shutdown to work on Mac OS X.
+@item
+Added @file{myisam/ft_dump} utility for low-level inspection
+of @code{FULLTEXT} indexes.
+@item
+Fixed bug in @code{DELETE ... WHERE ... MATCH ...}.
+@item
+Added support for @code{MATCH ... AGAINST(... IN BOOLEAN MODE)}.
+@strong{Note: you must rebuild your tables with
+@code{ALTER TABLE tablename TYPE=MyISAM} to be
+able to use boolean fulltext search}.
+@item
+@code{LOCATE()} and @code{INSTR()} are now case sensitive if either
+argument is a binary string.
+@item
+Changed @code{RAND()} initialization so that @code{RAND(N)} and
+@code{RAND(N+1)} are more distinct.
+@item
+Fixed core dump bug in @code{UPDATE ... ORDER BY}.
+@item
+Changed @code{INSERT INTO ... SELECT} to stop on errors by default.
+@item
+Ignore @code{DATA DIRECTORY} and @code{INDEX DIRECTORY} directives on Windows.
+@item
+Added boolean fulltext search code. It should be considered early alpha.
+@item
+Extended @code{MODIFY} and @code{CHANGE} in @code{ALTER TABLE} to accept
+the @code{AFTER} keyword.
+@item
+Indexes are now used with @code{ORDER BY} on a whole @code{InnoDB} table.
+@end itemize
+
+@node News-4.0.0, , News-4.0.1, News-4.0.x
+@appendixsubsec Changes in release 4.0.0
+
+@itemize @bullet
+@item
+Added variables @code{ft_min_word_len}, @code{ft_max_word_len}, and
+@code{ft_max_word_len_for_sort}.
+@item
+Added documentation for @code{libmysqld}, the embedded MySQL server
+library. Also added example programs (a @code{mysql} client and
+@code{mysqltest} test program) which use @code{libmysqld}.
+@item
+Removed all Gemini hooks from MySQL server.
+@item
+Removed @code{my_thread_init()} and @code{my_thread_end()}
+from mysql_com.h, and added @code{mysql_thread_init()} and
+@code{mysql_thread_end()} to mysql.h.
+@item
+Support for communication packets > 16M. In 4.0.1 we will extend MyISAM to
+be able to handle these.
+@item
+Secure connections (with SSL).
+@item
+Unsigned @code{BIGINT} constants now work. @code{MIN()} and @code{MAX()}
+now handle signed and unsigned @code{BIGINT} numbers correctly.
+@item
+New character set @code{latin_de} which provides correct German sorting.
+@item
+@code{TRUNCATE TABLE} and @code{DELETE FROM table_name} are now separate
+functions. One bonus is that @code{DELETE FROM table_name} now returns
+the number of deleted rows.
+@item
+@code{DROP DATABASE} now executes a @code{DROP TABLE} on all tables in
+the database, which fixes a problem with @code{InnoDB} tables.
+@item
+Added support for @code{UNION}.
+@item
+@code{DELETE} can now operate on multiple tables.
@item
A new @code{HANDLER} interface to @code{MyISAM} tables.
@item
+Added support for @code{INSERT} on @code{MERGE} tables. Patch from
+Benjamin Pflugmann.
+@item
+Changed @code{WEEK(#,0)} to match the calendar in the USA.
+@item
@code{COUNT(DISTINCT)} is about 30% faster.
@item
-@code{FULLTEXT} index creation now is much faster.
+Speed up all internal list handling.
+@item
+Speed up @code{IS NULL}, @code{ISNULL()} and some other internal primitives.
+@item
+Full text index creation now is much faster.
+@item
+Tree-like cache to speed up bulk inserts and
+@code{myisam_bulk_insert_tree_size} variable.
@item
-Searching on packed (@code{CHAR}/@code{VARCHAR}) keys now is much faster.
+Searching on packed (@code{CHAR}/@code{VARCHAR}) keys is now much faster.
+@item
+Optimised queries of type:
+@code{SELECT DISTINCT * from table_name ORDER by key_part1 LIMIT #}.
+@item
+@code{SHOW CREATE TABLE} now shows all table attributes.
+@item
+@code{ORDER BY ... DESC} can now use keys.
+@item
+@code{LOAD DATA FROM MASTER} ``auto-magically'' sets up a slave.
+@item
+Renamed @code{safe_mysqld} to @code{mysqld_safe}.
+@item
+Added support for symbolic links to @code{MyISAM} tables. Symlink handling is
+now enabled by default for Windows.
+@item
+@code{LOAD DATA FROM MASTER} ``auto-magically'' sets up a slave.
@item
Added @code{SQL_CALC_FOUND_ROWS} and @code{FOUND_ROWS()}. This makes it
possible to know how many rows a query would have returned
@@ -46786,8 +48655,28 @@ Added @code{IDENTITY} as a synonym for @code{AUTO_INCREMENT} (like Sybase).
@item
Added @code{ORDER BY} syntax to @code{UPDATE} and @code{DELETE}.
@item
-Optimized queries of type:
-@code{SELECT DISTINCT * from table_name ORDER by key_part1 LIMIT #}
+@code{SHOW INDEXES} is now a synonym for @code{SHOW INDEX}.
+@item
+Added @code{ALTER TABLE table_name DISABLE KEYS} and
+@code{ALTER TABLE table_name ENABLE KEYS} commands.
+@item
+Allow use of @code{IN} as a synonym for @code{FROM} in @code{SHOW} commands.
+@item
+Implemented ``repair by sort'' for @code{FULLTEXT} indexes.
+@code{REPAIR TABLE}, @code{ALTER TABLE}, and @code{OPTIMIZE TABLE}
+for tables with @code{FULLTEXT} indexes are now up to 100 times faster.
+@item
+Allow ANSI SQL syntax @code{X'hexadecimal-number'}.
+@item
+Cleaned up global lock handling for @code{FLUSH TABLES WITH READ LOCK}.
+@item
+Fixed problem with @code{DATETIME = constant} in @code{WHERE} optimisation.
+@item
+Added options @code{--master-data} and @code{--no-autocommit} to
+@code{mysqldump} (Thanks to Brian Aker for this).
+@item
+Added script @code{mysql_explain_log.sh} to distribution.
+(Thanks to mobile.de).
@end itemize
@@ -46960,20 +48849,20 @@ this situation.
@appendixsubsec Changes in release 3.23.47
@itemize @bullet
@item
-Fixed in when using the following construct:
+Fixed bug when using the following construct:
@code{SELECT ... WHERE key=@@var_name OR $key=@@var_name2}
@item
Restrict InnoDB keys to 500 bytes.
@item
InnoDB now supports @code{NULL} in keys.
@item
-Fixed shutdown problem on HPUX. (Introduced in 3.23.46)
+Fixed shutdown problem on HP-UX. (Introduced in 3.23.46)
@item
-Fixed core-dump bug in replication when using SELECT RELEASE_LOCK();
+Fixed core-dump bug in replication when using @code{SELECT RELEASE_LOCK()}.
@item
Added new command: @code{DO expression,[expression]}
@item
-Added @code{slave-skip-errors} option
+Added @code{slave-skip-errors} option.
@item
Added statistics variables for all MySQL commands. (@code{SHOW STATUS} is
now much longer).
@@ -46984,7 +48873,7 @@ Fixed that @code{GROUP BY expr DESC} works.
@item
Fixed bug when using @code{t1 LEFT JOIN t2 ON t2.key=constant}.
@item
-@code{mysql_config} now also work with binary (relocated) distributions.
+@code{mysql_config} now also works with binary (relocated) distributions.
@end itemize
@node News-3.23.46, News-3.23.45, News-3.23.47, News-3.23.x
@@ -47071,7 +48960,7 @@ Fixed problem with sjis character strings used within quoted table names.
Fixed coredump when using @code{CREATE ... FULLTEXT} keys with other table
handlers than MyISAM.
@item
-Don't use @code{signal()} on windows because this appears to not be
+Don't use @code{signal()} on Windows because this appears to not be
100 % reliable.
@item
Fixed bug when doing @code{WHERE column_name=NULL} on an indexed column
@@ -47145,26 +49034,27 @@ Fixed a bug in purge which could cause crashes.
Fixed a bug in @code{INSERT DELAYED} and @code{FLUSH TABLES} introduced
in 3.23.42.
@item
-Fixed unlikely bug, which returned not matching rows, in SELECT with
+Fixed unlikely bug, which returned non-matching rows, in @code{SELECT} with
many tables and multi-column indexes and 'range' type.
@item
-Fixed a unlikely core-dump bug when doing @code{EXPLAIN SELECT} when using
+Fixed an unlikely core-dump bug when doing @code{EXPLAIN SELECT} when using
many tables and @code{ORDER BY}.
@item
Fixed bug in @code{LOAD DATA FROM MASTER} when using table with
@code{CHECKSUM=1}.
@item
Added unique error message when one gets a DEADLOCK during a transaction with
-BDB tables.
+@code{BDB} tables.
@item
Fixed problem with @code{BDB} tables and @code{UNIQUE} columns defined
as @code{NULL}.
@item
-Fixed problem with @code{myisampack} when using pre-space filled CHAR columns.
+Fixed problem with @code{myisampack} when using pre-space filled @code{CHAR}
+columns.
@item
Applied patch from Yuri Dario for OS2.
@item
-Fixed bug in @code{--safe-user-create}
+Fixed bug in @code{--safe-user-create}.
@end itemize
@node News-3.23.42, News-3.23.41, News-3.23.43, News-3.23.x
@@ -47221,7 +49111,7 @@ Don't force everything to lower cases on Windows. (To fix problem
with Windows and @code{ALTER TABLE}). Now @code{--lower_case_names}
also works on Unix.
@item
-Fixed that automatic rollback that is done when thread end doesn't lock
+Fixed that automatic rollback is done when thread end doesn't lock
other threads.
@end itemize
@@ -47253,7 +49143,7 @@ Split @code{record_buffer} to @code{record_buffer} and
versions, if @code{record_rnd_buffer} is not set, then it takes the
value of @code{record_buffer}.
@item
-Fixed optimizing bug in @code{ORDER BY} where some @code{ORDER BY} parts
+Fixed optimising bug in @code{ORDER BY} where some @code{ORDER BY} parts
where wrongly removed.
@item
Fixed overflow bug with @code{ALTER TABLE} and @code{MERGE} tables.
@@ -47407,7 +49297,7 @@ Added database name to output for administrative commands like @code{CHECK},
@item
Lots of portability fixes for @code{InnoDB}.
@item
-Changed optimizer so that queries like
+Changed optimiser so that queries like
@code{SELECT * FROM table_name,table_name2 ... ORDER BY key_part1 LIMIT #}
will use index on @code{key_part1} instead of @code{filesort}.
@item
@@ -47469,16 +49359,16 @@ Fixed performance bug where reopened tables (tables that had been
waiting for @code{FLUSH} or @code{REPAIR}) would not use indexes for the
next query.
@item
-Fixed problem with @code{ALTER TABLE} to Innobase tables on FreeBSD.
+Fixed problem with @code{ALTER TABLE} to InnoDB tables on FreeBSD.
@item
Added @code{mysqld} variables @code{myisam_max_sort_file_size} and
@code{myisam_max_extra_sort_file_size}.
@item
-Initialize signals early to avoid problem with signals in Innobase.
+Initialise signals early to avoid problem with signals in InnoDB.
@item
Applied patch for the @code{tis620} character set to make comparisons
case-independent and to fix a bug in @code{LIKE} for this character set.
-@strong{NOTE}: All tables that uses the @code{tis620} character set must be
+@strong{Note}: All tables that uses the @code{tis620} character set must be
fixed with @code{myisamchk -r} or @code{REPAIR TABLE} !
@item
Added @code{--skip-safemalloc} option to @code{mysqld}.
@@ -47494,13 +49384,13 @@ Fixed a bug that allowed you to use database names containing a @samp{.}
character. This fixes a serious security issue when @code{mysqld} is run
as root.
@item
-Fixed bug when thread creation failed (could happen when doing a LOT
+Fixed bug when thread creation failed (could happen when doing a @strong{lot}
of connections in a short time).
@item
Fixed some problems with @code{FLUSH TABLES} and @code{TEMPORARY} tables.
-(Problem with freeing the key cache and error @code{Can't reopen table...}).
+(Problem with freeing the key cache and error @code{Can't reopen table...}.)
@item
-Fixed a problem in Innobase with other character sets than @code{latin1}
+Fixed a problem in InnoDB with other character sets than @code{latin1}
and another problem when using many columns.
@item
Fixed bug that caused a core dump when using a very complex query involving
@@ -47520,7 +49410,7 @@ Fixed a bug in @code{CONCAT_WS()} where it returned wrong results.
@item
Changed @code{CREATE ... INSERT} and @code{INSERT ... SELECT} to not
allow concurrent inserts as this could make the binary log hard to repeat.
-(Concurrent inserts are enabled if you are not using the binary or update log).
+(Concurrent inserts are enabled if you are not using the binary or update log.)
@item
Changed some macros to be able to use fast mutex with glibc 2.2.
@end itemize
@@ -47606,7 +49496,7 @@ Fixed bug in bidirectional replication.
Fixed bug in the @code{BDB} table handler that occurred when using an index
on multi-part key where a key part may be @code{NULL}.
@item
-Fixed @code{MAX()} optimization on sub-key for @code{BDB} tables.
+Fixed @code{MAX()} optimisation on sub-key for @code{BDB} tables.
@item
Fixed problem where garbage results were returned when using @code{BDB}
tables and @code{BLOB} or @code{TEXT} fields when joining many tables.
@@ -47804,7 +49694,7 @@ Fixed bug when using expression of type:
@example
SELECT ... FROM t1 LEFT JOIN t2 ON (t1.a=t2.a) WHERE t1.a=t2.a
@end example
-In this case the test in the @code{WHERE} clause was wrongly optimized away.
+In this case the test in the @code{WHERE} clause was wrongly optimised away.
@item
Fixed bug in @code{MyISAM} when deleting keys with possible @code{NULL}
values, but the first key-column was not a prefix-compressed text column.
@@ -47847,7 +49737,7 @@ Allow hex constants in the @code{--fields-*-by} and
Added option @code{--safe-show-database} to @code{mysqld}.
@item
Added @code{have_bdb}, @code{have_gemini}, @code{have_innobase},
-@code{have_raid} and @code{have_ssl} to @code{SHOW VARIABLES} to make it
+@code{have_raid} and @code{have_openssl} to @code{SHOW VARIABLES} to make it
easy to test for supported extensions.
@item
Added option @code{--open-files-limit} to @code{mysqld}.
@@ -47928,7 +49818,7 @@ Added support for @code{auto_increment} on sub-fields for BDB tables.
@item
Added @code{ANALYZE} of BDB tables.
@item
-In BDB tables, we now store the number of rows; This helps to optimize queries
+In BDB tables, we now store the number of rows; This helps to optimise queries
when we need an approximation of the number of rows.
@item
If we get an error in a multi-row statement, we now only rollback the
@@ -47993,7 +49883,7 @@ that caused @code{mysql_install_db} to core dump on some Linux machines.
@item
Changed @code{mi_create()} to use less stack space.
@item
-Fixed bug with optimizer trying to over-optimize @code{MATCH} when used
+Fixed bug with optimiser trying to over-optimise @code{MATCH} when used
with @code{UNIQUE} key.
@item
Changed @code{crash-me} and the MySQL benchmarks to also work
@@ -48025,7 +49915,7 @@ and the interactive help for more information.
Fixed crash when automatic repair of @code{MyISAM} table failed.
@item
Fixed a major performance bug in the table locking code when one
-constantly had a LOT of @code{SELECT}, @code{UPDATE} and @code{INSERT}
+constantly had a lot of @code{SELECT}, @code{UPDATE} and @code{INSERT}
statements running. The symptom was that the @code{UPDATE} and
@code{INSERT} queries were locked for a long time while new @code{SELECT}
statements were executed before the updates.
@@ -48119,7 +50009,7 @@ shortage when compiled @code{--with-debug=full}.
@item
Fixed several coredumps in out-of-memory conditions.
@item
-@code{SHOW SLAVE STATUS} was using an uninitialized mutex if the slave had
+@code{SHOW SLAVE STATUS} was using an uninitialised mutex if the slave had
not been started yet.
@item
Fixed bug in @code{ELT()} and @code{MAKE_SET()} when the query used
@@ -48169,7 +50059,7 @@ if the table exists.
If you don't create a @code{PRIMARY KEY} in a BDB table, a hidden
@code{PRIMARY KEY} will be created.
@item
-Added read-only-key optimization to BDB tables.
+Added read-only-key optimisation to BDB tables.
@item
@code{LEFT JOIN} in some cases preferred a full table scan when there was
no @code{WHERE} clause.
@@ -48207,7 +50097,7 @@ Added @code{--skip-slave-start} option to @code{mysqld}.
Updates that generated an error code (such as @code{INSERT INTO foo(some_key)
values (1),(1)}) erroneously terminated the slave thread.
@item
-Added optimization of queries where @code{DISTINCT} is only used on columns
+Added optimisation of queries where @code{DISTINCT} is only used on columns
from some of the tables.
@item
Allow floating-point numbers where there is no sign after the exponent
@@ -48217,7 +50107,7 @@ Allow floating-point numbers where there is no sign after the exponent
@item
Added @code{--default-extra-file=#} to all MySQL clients.
@item
-Columns referenced in @code{INSERT} statements now are initialized properly.
+Columns referenced in @code{INSERT} statements now are initialised properly.
@item
@code{UPDATE} didn't always work when used with a range on a timestamp that
was part of the key that was used to find rows.
@@ -48365,7 +50255,7 @@ still work from the first line.
Fixed a problem when using many pending @code{DROP TABLE} statements at
the same time.
@item
-Optimizer didn't use keys properly when using @code{LEFT JOIN} on an
+Optimiser didn't use keys properly when using @code{LEFT JOIN} on an
empty table.
@item
Added shorter help text when invoking @code{mysqld} with incorrect options.
@@ -48387,7 +50277,7 @@ that both non-threaded (@code{-lmysqlclient}) and threaded
against a threaded @code{-lmysqlclient} will need to link against
@code{libmysqlclient_r} now.
@item
-Added atomic @code{RENAME} command.
+Added atomic @code{RENAME TABLE} command.
@item
Don't count entries with @code{NULL} in @code{COUNT(DISTINCT ...)}.
@item
@@ -48413,7 +50303,7 @@ that don't have the @code{pthread_rwlock_rdlock} code.
When deleting rows with a non-unique key in a HEAP table, all rows weren't
always deleted.
@item
-Fixed bug in range optimizer for HEAP tables for searches on a part index.
+Fixed bug in range optimiser for HEAP tables for searches on a part index.
@item
Fixed that @code{SELECT} on part keys works with BDB tables.
@item
@@ -48423,7 +50313,7 @@ Fixed @code{INSERT INTO bdb_table ... SELECT} to work with BDB tables.
@item
@code{ANALYZE TABLE} will now only update tables that have been changed
since thee last @code{ANALYZE}. Note that this is a new feature and tables
-will not be marked to be analyzed until they are updated in any way with
+will not be marked to be analysed until they are updated in any way with
3.23.23 or newer. For older tables, you have to do @code{CHECK TABLE}
to update the key distribution.
@item
@@ -48449,8 +50339,8 @@ More variables in @code{SHOW SLAVE STATUS} and @code{SHOW MASTER STATUS}.
@item
@code{SLAVE STOP} now will not return until the slave thread actually exits.
@item
-Full text search via the @code{MATCH} function and @code{FULLTEXT} index type.
-(For MyISAM files). This makes @code{FULLTEXT} a reserved word.
+Full text search via the @code{MATCH} function and @code{FULLTEXT} index type
+(for MyISAM files). This makes @code{FULLTEXT} a reserved word.
@end itemize
@@ -48475,7 +50365,7 @@ Added workaround for a bug in @code{gcc} 2.96 (intel) and @code{gcc} 2.9
Fixed memory leak in the client library when using @code{host=} in the
@code{my.cnf} file.
@item
-Optimized functions that manipulate the hours/minutes/seconds.
+Optimised functions that manipulate the hours/minutes/seconds.
@item
Fixed bug when comparing the result of @code{DATE_ADD()}/@code{DATE_SUB()}
against a number.
@@ -48522,14 +50412,14 @@ Fixed @code{chown} warning in @code{safe_mysqld}.
@item
Fixed a bug in @code{ORDER BY} that was introduced in 3.23.19.
@item
-Only optimize the @code{DELETE FROM tbl_name} to do a drop+create of
-the table if we are in @code{AUTOCOMMIT} mode. (Needed for BDB tables).
+Only optimise the @code{DELETE FROM tbl_name} to do a drop+create of
+the table if we are in @code{AUTOCOMMIT} mode (needed for BDB tables).
@item
Added extra checks to avoid index corruption when the @code{ISAM}/@code{MyISAM}
index files gets full during an @code{INSERT}/@code{UPDATE}.
@item
@code{myisamchk} didn't correctly update row checksum when used with
-@code{-ro} (This only gave an warning in subsequent runs).
+@code{-ro} (this only gave an warning in subsequent runs).
@item
Fixed bug in @code{REPAIR TABLE} so that it works with tables without indexes.
@item
@@ -48632,7 +50522,7 @@ Added 4 sample @code{my.cnf} example files in the @file{support-files}
directory.
@item
Fixed @code{duplicated key} problem when doing big @code{GROUP BY}'s.
-(This bug was probably introduced in 3.23.15).
+(This bug was probably introduced in 3.23.15.)
@item
Changed syntax for @code{INNER JOIN} to match ANSI SQL.
@item
@@ -48763,7 +50653,7 @@ Optimised MyISAM to be faster when inserting keys in sorted order.
@code{EXPLAIN SELECT ...} now also prints out whether MySQL needs to
create a temporary table or use file sorting when resolving the @code{SELECT}.
@item
-Added optimization to skip @code{ORDER BY} parts where the part is a
+Added optimisation to skip @code{ORDER BY} parts where the part is a
constant expression in the @code{WHERE} part. Indexes can now be used
even if the @code{ORDER BY} doesn't match the index exactly, as long as
all the not used index parts and all the extra @code{ORDER BY}
@@ -48910,7 +50800,7 @@ join parameters in @code{SELECT}.
@item
Allow the @code{ALTER TABLE tbl_name ADD (field_list)} syntax.
@item
-Fixed problem with optimizer that could sometimes use wrong keys.
+Fixed problem with optimiser that could sometimes use wrong keys.
@item
Fixed that @code{GRANT/REVOKE ALL PRIVILEGES} doesn't affect
@code{GRANT OPTION}.
@@ -48935,7 +50825,7 @@ Added variables @code{select_limit} and @code{max_join_size} to @code{mysql}.
Added sql variables: @code{SQL_MAX_JOIN_SIZE} and @code{SQL_SAFE_UPDATES}.
@item
Added @code{READ LOCAL} lock that doesn't lock the table for concurrent
-inserts. (This is used by @code{mysqldump}).
+inserts. (This is used by @code{mysqldump}.)
@item
Changed that @code{LOCK TABLES ... READ} doesn't anymore allow concurrent
inserts.
@@ -48976,7 +50866,7 @@ Fixed that @code{date_column BETWEEN const_date AND const_date} works.
Fixed problem when only changing a 0 to @code{NULL} in a table with
@code{BLOB/TEXT} columns.
@item
-Fixed bug in range optimizer when using many key parts and or on the middle
+Fixed bug in range optimiser when using many key parts and or on the middle
key parts: @code{WHERE K1=1 and K3=2 and (K2=2 and K4=4 or K2=3 and K4=5)}
@item
Added command @code{source} to @code{mysql} to allow reading of batch files
@@ -48990,13 +50880,13 @@ databases in the same query.
Added VIO wrapper (needed for SSL support ; By Andrei Errapart and
Tõnu Samuel).
@item
-Fixed optimizer problem on @code{SELECT} when using many overlapping indexes.
+Fixed optimiser problem on @code{SELECT} when using many overlapping indexes.
MySQL should now be able to choose keys even better when there
is many keys to choose from.
@item
-Changed optimizer to prefer a range key instead of a ref key when the
+Changed optimiser to prefer a range key instead of a ref key when the
range key can uses more columns than the ref key (which only can use
-columns with =). For example, the following type of queries should now
+columns with @code{=}). For example, the following type of queries should now
be faster: @code{SELECT * from key_part_1=const and key_part_2 > const2}
@item
Fixed bug that a change of all @code{VARCHAR} columns to @code{CHAR} columns
@@ -49018,7 +50908,7 @@ long time to a separate log file with a time of how long the query took.
@item
Fixed core dump when doing @code{WHERE key_column=RAND(...)}
@item
-Fixed optimization bug in @code{SELECT ... LEFT JOIN ... key_column IS NULL},
+Fixed optimisation bug in @code{SELECT ... LEFT JOIN ... key_column IS NULL},
when @code{key_column} could contain @code{NULL} values.
@item
Fixed problem with 8-bit characters as separators in @code{LOAD DATA INFILE}.
@@ -49299,7 +51189,7 @@ an empty value list to insert a row in which each column is set to its
default value.
@item
Changed @code{SUBSTRING(text FROM pos)} to conform to ANSI SQL. (Before this
-construct returned the rightmost 'pos' characters).
+construct returned the rightmost 'pos' characters.)
@item
@code{SUM()} with @code{GROUP BY} returned 0 on some systems.
@item
@@ -49322,7 +51212,7 @@ New function @code{COALESCE()}.
@itemize @bullet
@item
-Fixed range optimizer bug: @code{SELECT * FROM table_name WHERE
+Fixed range optimiser bug: @code{SELECT * FROM table_name WHERE
key_part1 >= const AND (key_part2 = const OR key_part2 = const)}. The
bug was that some rows could be duplicated in the result.
@item
@@ -49339,11 +51229,11 @@ Date handling should now be a bit faster.
Added handling of fuzzy dates (dates where day or month is 0):
(Like: 1999-01-00)
@item
-Fixed optimization of @code{SELECT ... WHERE key_part1=const1 AND
+Fixed optimisation of @code{SELECT ... WHERE key_part1=const1 AND
key_part_2=const2 AND key_part1=const4 AND key_part2=const4} ; Indextype
should be @code{range} instead of @code{ref}.
@item
-Fixed @code{egcs} 1.1.2 optimizer bug (when using @code{BLOB}s) on Linux Alpha.
+Fixed @code{egcs} 1.1.2 optimiser bug (when using @code{BLOB}s) on Linux Alpha.
@item
Fixed problem with @code{LOCK TABLES} combined with @code{DELETE FROM table}.
@item
@@ -49471,7 +51361,7 @@ You can specify a netmask using the @code{IP/NETMASK} syntax.
@item
If you compare a @code{NOT NULL DATE/DATETIME} column with @code{IS
NULL}, this is changed to a compare against @code{0} to satisfy some ODBC
-applications. (By @email{shreeve@@uci.edu}).
+applications. (By @email{shreeve@@uci.edu}.)
@item
@code{NULL IN (...)} now returns @code{NULL} instead of @code{0}. This will
ensure that @code{null_column NOT IN (...)} doesn't match
@@ -49482,10 +51372,10 @@ Fix storage of floating-point values in @code{TIME} columns.
Changed parsing of @code{TIME} strings to be more strict. Now the
fractional second part is detected (and currently skipped). The
following formats are supported:
-@table @code
+@itemize
@item [[DAYS] [H]H:]MM:]SS[.fraction]
@item [[[[[H]H]H]H]MM]SS[.fraction]
-@end table
+@end itemize
@item
Detect (and ignore) second fraction part from @code{DATETIME}.
@item
@@ -49504,7 +51394,7 @@ Added aggregate UDF functions. Thanks to Andreas F. Bobak
@item
@code{LAST_INSERT_ID()} is now updated for @code{INSERT INTO ... SELECT}.
@item
-Some small changes to the join table optimizer to make some joins faster.
+Some small changes to the join table optimiser to make some joins faster.
@item
@code{SELECT DISTINCT} is much faster; It uses the new @code{UNIQUE}
functionality in @code{MyISAM}. One difference compared to MySQL Version 3.22
@@ -49547,7 +51437,7 @@ Added @code{mysqld} option @code{--default-table-type}.
The 3.22 version has faster and safer connect code than version 3.21, as well
as a lot of new nice enhancements. The reason for not including these changes
-As there aren't really any MAJOR changes, upgrading from 3.21 to 3.22 should
+As there aren't really any major changes, upgrading from 3.21 to 3.22 should
be very easy and painless. @xref{Upgrading-from-3.21}.
@menu
@@ -49667,7 +51557,7 @@ A few small fixes for the Windows version.
@itemize @bullet
@item
-Fixed optimizer problem on @code{SELECT} when using many overlapping indexes.
+Fixed optimiser problem on @code{SELECT} when using many overlapping indexes.
@item
Disabled floating-point exceptions for FreeBSD to fix core dump when
doing @code{SELECT floor(pow(2,63))}.
@@ -49748,7 +51638,7 @@ Fixed core dump with empty @code{BLOB/TEXT} column to @code{REVERSE()}.
Extended @code{/*! */} with version numbers.
@item
Changed @code{SUBSTRING(text FROM pos)} to conform to ANSI SQL. (Before this
-construct returned the rightmost 'pos' characters).
+construct returned the rightmost 'pos' characters.)
@item
Fixed problem with @code{LOCK TABLES} combined with @code{DELETE FROM table}
@item
@@ -49759,7 +51649,7 @@ Fixed problem that INSERT ... SELECT didn't use SQL_BIG_TABLES.
Password wasn't updated correctly if privileges didn't change on:
@code{GRANT ... IDENTIFIED BY}
@item
-Fixed range optimizer bug in
+Fixed range optimiser bug in
@code{SELECT * FROM table_name WHERE key_part1 >= const AND (key_part2 = const OR key_part2 = const)}
@item
Fixed bug in compression key handling in ISAM.
@@ -49782,7 +51672,7 @@ Fixed some small problems with the installation.
@item
@code{DATA} is not a reserved word anymore.
@item
-Fixed optimizer bug with tables with only one row.
+Fixed optimiser bug with tables with only one row.
@item
Fixed bug when using @code{LOCK TABLES table_name READ; FLUSH TABLES;}
@item
@@ -49869,7 +51759,7 @@ Fixed a problem with @code{Host '...' is not allowed to connect to this MySQL
server} after one had inserted a new MySQL user with a @code{GRANT}
command.
@item
-Changed to use @code{TCP_NODELAY} also on Linux (Should give faster TCP/IP
+Changed to use @code{TCP_NODELAY} also on Linux (should give faster TCP/IP
connections).
@end itemize
@@ -49950,7 +51840,7 @@ rows. Fixed.
Extended @code{ENCRYPT()} to take longer salt strings than 2 characters.
@item
@code{longlong2str} is now much faster than before. For @code{Intel x86}
-platforms, this function is written in optimized assembler.
+platforms, this function is written in optimised assembler.
@item
Added the @code{MODIFY} keyword to @code{ALTER TABLE}.
@end itemize
@@ -49966,7 +51856,7 @@ were flushed.
@item
Name change of some variables in @code{SHOW STATUS}.
@item
-Fixed problem with @code{ORDER BY} with 'only index' optimization when there
+Fixed problem with @code{ORDER BY} with 'only index' optimisation when there
were multiple key definitions for a used column.
@item
@code{DATE} and @code{DATETIME} columns are now up to 5 times faster than
@@ -50086,7 +51976,7 @@ Fix for @code{isamchk} for tables which need big temporary files.
@itemize @bullet
@item
-@strong{IMPORTANT}: You must run the @code{mysql_fix_privilege_tables} script
+@strong{Important}: You must run the @code{mysql_fix_privilege_tables} script
when you upgrade to this version! This is needed because of the new
@code{GRANT} system. If you don't do this, you will get @code{Access
denied} when you try to use @code{ALTER TABLE}, @code{CREATE INDEX} or
@@ -50147,7 +52037,7 @@ Changed @code{+}, @code{-} (sign and minus), @code{*}, @code{/}, @code{%},
Fixed a bug in @code{ALTER TABLE} that caused @code{mysqld} to crash.
@item
MySQL now always reports the conflicting key values when a
-duplicate key entry occurs. (Before this was only reported for @code{INSERT}).
+duplicate key entry occurs. (Before this was only reported for @code{INSERT}.)
@item
New syntax: @code{INSERT INTO tbl_name SET col_name=value, col_name=value, ...}
@item
@@ -50167,7 +52057,7 @@ Added @code{maybe_null} to the UDF structure.
Added option @code{IGNORE} to @code{INSERT} statements with many rows.
@item
Fixed some problems with sorting of the koi8 character sets; Users of koi8
-@strong{MUST} run @code{isamchk -rq} on each table that has an index on
+@strong{must} run @code{isamchk -rq} on each table that has an index on
a @code{CHAR} or @code{VARCHAR} column.
@item
New script @code{mysql_setpermission}, by Luuk de Boer, allows one
@@ -50216,7 +52106,7 @@ Added a lot more output to @code{mysqladmin debug}.
@item
You can now start @code{mysqld} on Windows with the @code{--flush} option.
This will flush all tables to disk after each update. This makes things
-much safer on NT/Win98 but also @strong{MUCH} slower.
+much safer on NT/Win98 but also @strong{much} slower.
@end itemize
@@ -50283,7 +52173,7 @@ Upgraded @code{libtool} to get the configure more portable.
Fixed slow @code{UPDATE} and @code{DELETE} operations when using
@code{DATETIME} or @code{DATE} keys.
@item
-Changed optimizer to make it better at deciding when to do a full join
+Changed optimiser to make it better at deciding when to do a full join
and when using keys.
@item
You can now use @code{mysqladmin proc} to display information about your own
@@ -50303,7 +52193,7 @@ and INSERT_ID's in the update log.
@item
Added @code{--where} option to @code{mysqldump} (patch by Jim Faucette).
@item
-The lexical analyzer now uses ``perfect hashing'' for faster parsing of SQL
+The lexical analyser now uses ``perfect hashing'' for faster parsing of SQL
statements.
@end itemize
@@ -50319,7 +52209,7 @@ For the @code{LOAD DATA INFILE} statement, you can now use the new @code{LOCAL}
keyword to read the file from the client. @code{mysqlimport} will
automatically use @code{LOCAL} when importing with the TCP/IP protocol.
@item
-Fixed small optimize problem when updating keys.
+Fixed small optimise problem when updating keys.
@item
Changed makefiles to support shared libraries.
@item
@@ -50384,7 +52274,7 @@ the @strong{process} privilege to bypass the update log.
@item
Fixed fatal bug in @code{LPAD()}.
@item
-Initialize line buffer in @file{mysql.cc} to make @code{BLOB} reading from
+Initialise line buffer in @file{mysql.cc} to make @code{BLOB} reading from
pipes safer.
@item
Added @code{-O max_connect_errors=#} option to @code{mysqld}.
@@ -50419,13 +52309,13 @@ trailing @samp{;}.
@item
Fix for corrupted fixed-format output generated by @code{SELECT INTO OUTFILE}.
@item
-@strong{WARNING: INCOMPATIBLE CHANGE!!}
+@strong{Warning: Incompatible change!}
Added Oracle @code{GREATEST()} and @code{LEAST()} functions. You must now use
these instead of the @code{MAX()} and @code{MIN()} functions to get the
largest/smallest value from a list of values. These can now handle @code{REAL},
@code{BIGINT} and string (@code{CHAR} or @code{VARCHAR}) values.
@item
-@strong{WARNING: INCOMPATIBLE CHANGE!!}
+@strong{Warning: Incompatible change!}
@code{DAYOFWEEK()} had offset 0 for Sunday. Changed the offset to 1.
@item
Give an error for queries that mix @code{GROUP BY} columns and fields when
@@ -50434,7 +52324,7 @@ there is no @code{GROUP BY} specification.
Added @code{--vertical} option to @code{mysql}, for printing results in
vertical mode.
@item
-Index-only optimization; some queries are now resolved using
+Index-only optimisation; some queries are now resolved using
only indexes. Until MySQL 4.0, this works only for numeric columns.
@xref{MySQL indexes, , MySQL indexes}.
@item
@@ -50475,7 +52365,7 @@ Added function @code{SUBSTRING()} with 2 arguments.
If you created a table with a record length smaller than 5, you couldn't
delete rows from the table.
@item
-Added optimization to remove const reference tables from @code{ORDER BY} and
+Added optimisation to remove const reference tables from @code{ORDER BY} and
@code{GROUP BY}.
@item
@code{mysqld} now automatically disables system locking on Linux and Windows,
@@ -50533,7 +52423,7 @@ a chroot environment (by Nikki Chumakov @email{nikkic@@cityline.ru}).
Trailing spaces are now ignored when comparing case-sensitive strings;
this should fix some problems with ODBC and flag 512!
@item
-Fixed a core-dump bug in the range optimizer.
+Fixed a core-dump bug in the range optimiser.
@item
Added @code{--one-thread} option to @code{mysqld}, for debugging with
LinuxThreads (or @code{glibc}). (This replaces the @code{-T32} flag)
@@ -50664,10 +52554,10 @@ Added @code{-T32} option to @code{mysqld}, for running all queries under the
main thread. This makes it possible to debug @code{mysqld} under Linux with
@code{gdb}!
@item
-Added optimization of @code{not_null_column IS NULL} (needed for some Access
+Added optimisation of @code{not_null_column IS NULL} (needed for some Access
queries).
@item
-Allow @code{STRAIGHT_JOIN} to be used between two tables to force the optimizer
+Allow @code{STRAIGHT_JOIN} to be used between two tables to force the optimiser
to join them in a specific order.
@item
String functions now return @code{VARCHAR} rather than @code{CHAR} and
@@ -50795,7 +52685,7 @@ returned a row in some contexts (bug only in 3.21.31).
@code{GROUP BY} + @code{ORDER BY} returned one empty row when no rows where
found.
@item
-Fixed a bug in the range optimizer that wrote
+Fixed a bug in the range optimiser that wrote
@code{Use_count: Wrong count for ...} in the error log file.
@end itemize
@@ -50882,12 +52772,12 @@ Fixed permission problem with @code{umask()} and creating new databases.
@item
Fixed permission problem on result file with @code{SELECT ... INTO OUTFILE ...}
@item
-Fixed problem in range optimizer (core dump) for a very complex query.
+Fixed problem in range optimiser (core dump) for a very complex query.
@item
Fixed problem when using @code{MIN(integer)} or @code{MAX(integer)} in
@code{GROUP BY}.
@item
-Fixed bug on Alpha when using integer keys. (Other keys worked on Alpha).
+Fixed bug on Alpha when using integer keys. (Other keys worked on Alpha.)
@item
Fixed bug in @code{WEEK("XXXX-xx-01")}.
@end itemize
@@ -50913,12 +52803,12 @@ Fixed bug in record caches; for some queries, you could get
Added user level lock functions @code{GET_LOCK(string,timeout)},
@code{RELEASE_LOCK(string)}.
@item
-Added @code{opened_tables} to @code{show status}.
+Added @code{Opened_tables} to @code{show status}.
@item
Changed connect timeout to 3 seconds to make it somewhat harder
for crackers to kill @code{mysqld} through telnet + TCP/IP.
@item
-Fixed bug in range optimizer when using
+Fixed bug in range optimiser when using
@code{WHERE key_part_1 >= something AND key_part_2 <= something_else}.
@item
Changed @code{configure} for detection of FreeBSD 3.0 9803xx and above
@@ -50957,10 +52847,10 @@ An @code{ENUM} field that is not declared @code{NOT NULL} has @code{NULL} as
the default value.
(Previously, the default value was the first enumeration value.)
@item
-Fixed bug in the join optimizer code when using many part keys
-on the same key: @code{INDEX (Organization,Surname(35),Initials(35))}.
+Fixed bug in the join optimiser code when using many part keys
+on the same key: @code{INDEX (Organisation,Surname(35),Initials(35))}.
@item
-Added some tests to the table order optimizer to get some cases with
+Added some tests to the table order optimiser to get some cases with
@code{SELECT ... FROM many_tables} much faster.
@item
Added a retry loop around @code{accept()} to possibly fix some problems on some
@@ -50998,7 +52888,7 @@ Dynamic loadable functions. Based on source from Alexis Mikhailov.
You couldn't delete from a table if no one had done a @code{SELECT} on the
table.
@item
-Fixed problem with range optimizer with many @code{OR} operators on key parts
+Fixed problem with range optimiser with many @code{OR} operators on key parts
inside each other.
@item
Recoded @code{MIN()} and @code{MAX()} to work properly with strings and
@@ -51013,7 +52903,7 @@ Added Italian error messages from @email{brenno@@dewinter.com}.
@item
@code{configure} now works better on OSF1 (tested on 4.0D).
@item
-Added hooks to allow @code{LIKE} optimization with international character
+Added hooks to allow @code{LIKE} optimisation with international character
support.
@item
Upgraded @code{DBI} to 0.93.
@@ -51034,7 +52924,7 @@ The following symbols are now reserved words:
Setting a @code{TIMESTAMP} to @code{NULL} in @code{LOAD DATA INFILE ...} didn't
set the current time for the @code{TIMESTAMP}.
@item
-Fix @code{BETWEEN} to recognize binary strings. Now @code{BETWEEN} is
+Fix @code{BETWEEN} to recognise binary strings. Now @code{BETWEEN} is
case sensitive.
@item
Added @code{--skip-thread-priority} option to @code{mysqld}, for systems
@@ -51045,7 +52935,7 @@ Added ODBC functions @code{DAYNAME()} and @code{MONTHNAME()}.
Added function @code{TIME_FORMAT()}. This works like @code{DATE_FORMAT()},
but takes a time string (@code{'HH:MM:DD'}) as argument.
@item
-Fixed unlikely(?) key optimizer bug when using @code{OR}s of key parts
+Fixed unlikely(?) key optimiser bug when using @code{OR}s of key parts
inside @code{AND}s.
@item
Added command @code{variables} to @code{mysqladmin}.
@@ -51087,7 +52977,7 @@ Fixed bug that core dumped when using many @code{LEFT OUTER JOIN} clauses.
@item
Fixed bug in @code{ORDER BY} on string formula with possible @code{NULL} values.
@item
-Fixed problem in range optimizer when using <= on sub index.
+Fixed problem in range optimiser when using <= on sub index.
@item
Added functions @code{DAYOFYEAR()}, @code{DAYOFMONTH()}, @code{MONTH()},
@code{YEAR()}, @code{WEEK()}, @code{QUARTER()}, @code{HOUR()}, @code{MINUTE()},
@@ -51126,7 +53016,7 @@ Configure changes for some operating systems.
@itemize @bullet
@item
-Fixed optimizer bug when using
+Fixed optimiser bug when using
@code{WHERE data_field = date_field2 AND date_field2 = constant}.
@item
Added command @code{SHOW STATUS}.
@@ -51231,7 +53121,7 @@ restart if one thread was reading data that another thread modified.
@item
@code{LIMIT offset,count} didn't work in @code{INSERT ... SELECT}.
@item
-Optimized key block caching. This will be quicker than the old algorithm when
+Optimised key block caching. This will be quicker than the old algorithm when
using bigger key caches.
@end itemize
@@ -51245,7 +53135,7 @@ Added ODBC 2.0 & 3.0 functions @code{POWER()}, @code{SPACE()},
@code{COT()}, @code{DEGREES()}, @code{RADIANS()}, @code{ROUND(2 arg)}
and @code{TRUNCATE()}.
@item
-@strong{WARNING: INCOMPATIBLE CHANGE!!} @code{LOCATE()} parameters were
+@strong{Warning: Incompatible change!} @code{LOCATE()} parameters were
swapped according to ODBC standard. Fixed.
@item
Added function @code{TIME_TO_SEC()}.
@@ -51264,14 +53154,14 @@ be compatible with @code{mysqldump}.
@itemize @bullet
@item
-@strong{WARNING: INCOMPATIBLE CHANGE!!} @code{mysqlperl} is now from
+@strong{Warning: Incompatible change!} @code{mysqlperl} is now from
Msql-Mysql-modules. This means that @code{connect()} now takes
@code{host}, @code{database}, @code{user}, @code{password} arguments! The old
version took @code{host}, @code{database}, @code{password}, @code{user}.
@item
Allow @code{DATE '1997-01-01'}, @code{TIME '12:10:10'} and
@code{TIMESTAMP '1997-01-01 12:10:10'} formats required by ANSI SQL.
-@strong{WARNING: INCOMPATIBLE CHANGE!!} This has the unfortunate
+@strong{Warning: Incompatible change!} This has the unfortunate
side-effect that you no longer can have columns named @code{DATE}, @code{TIME}
or @code{TIMESTAMP}. :( Old columns can still be accessed through
@code{tablename.columnname}!)
@@ -51295,7 +53185,7 @@ New portable benchmark suite with @code{DBD}, with test results from
designed to find as many limits as possible in a SQL server. Tested with
@code{mSQL}, PostgreSQL, Solid and MySQL.
@item
-Fixed bug in range-optimizer that crashed MySQL on some queries.
+Fixed bug in range-optimiser that crashed MySQL on some queries.
@item
Table and column name completion for @code{mysql} command line tool, by Zeev
Suraski and Andi Gutmans.
@@ -51537,7 +53427,7 @@ Fixed some @code{configure} issues.
Made the locking code a bit safer. Fixed very unlikely
deadlock situation.
@item
-Fixed a couple of bugs in the range optimizer. Now the new range benchmark
+Fixed a couple of bugs in the range optimiser. Now the new range benchmark
@code{test-select} works.
@end itemize
@@ -51587,7 +53477,7 @@ Fixed bug with @code{GROUP BY} and @code{SELECT} on key with many values.
@code{mysql_use_result()}. This affected at least some cases of
@code{mysqldump --quick}.
@item
-Fixed bug in optimization of @code{WHERE const op field}.
+Fixed bug in optimisation of @code{WHERE const op field}.
@item
Fixed problem when sorting on @code{NULL} fields.
@item
@@ -51597,7 +53487,7 @@ Added @code{--pid-file=#} option to @code{mysqld}.
@item
Added date formatting to @code{FROM_UNIXTIME()}, originally by Zeev Suraski.
@item
-Fixed bug in @code{BETWEEN} in range optimizer (Did only test = of the first
+Fixed bug in @code{BETWEEN} in range optimiser (did only test = of the first
argument).
@item
Added machine-dependent files for MIT-pthreads i386-SCO. There is probably
@@ -51739,7 +53629,7 @@ Changed the default sort buffer size from 2M to 1M.
@itemize @bullet
@item
-The range optimizer is coded, but only 85% tested. It can be enabled with
+The range optimiser is coded, but only 85% tested. It can be enabled with
@code{--new}, but it crashes core a lot yet...
@item
More portable. Should compile on AIX and alpha-digital.
@@ -51816,7 +53706,7 @@ Added @code{--log-update} option to @code{mysqld}, to get a log suitable for
incremental updates.
@item
New command @code{EXPLAIN SELECT ...} to get information about how the
-optimizer will do the join.
+optimiser will do the join.
@item
For easier client code, the client should no longer use
@code{FIELD_TYPE_TINY_BLOB}, @code{FIELD_TYPE_MEDIUM_BLOB},
@@ -51861,7 +53751,7 @@ will also work with @code{NULL} values.
@item
Full @code{WHERE} with expressions.
@item
-New range optimizer that can resolve ranges when some keypart prefix is
+New range optimiser that can resolve ranges when some keypart prefix is
constant. Example:
@example
mysql> SELECT * FROM tbl_name
@@ -51943,7 +53833,7 @@ Arithmetic error on Sparc-386.
Added @code{--unbuffered} option to @code{mysql}, for new @code{mysqlaccess}.
@item
When using overlapping (unnecessary) keys and join over many tables,
-the optimizer could get confused and return 0 records.
+the optimiser could get confused and return 0 records.
@end itemize
@@ -51975,7 +53865,7 @@ works.
@item
A couple of bugs fixed in @code{SELECT ... GROUP BY}.
@item
-Fixed memory overrun bug in @code{WHERE} with many unoptimizable brace levels.
+Fixed memory overrun bug in @code{WHERE} with many unoptimisable brace levels.
@item
Fixed some small bugs in the grant code.
@item
@@ -52026,7 +53916,7 @@ bugs that appear during the build with it.
Changed @file{libmysql.c} to prefer @code{getpwuid()} instead of
@code{cuserid()}.
@item
-Fixed bug in @code{SELECT} optimizer when using many tables with the same
+Fixed bug in @code{SELECT} optimiser when using many tables with the same
column used as key to different tables.
@item
Added new latin2 and Russian KOI8 character tables.
@@ -52309,10 +54199,10 @@ returns an array of column lengths (of type @code{uint}).
@item
Fixed bug with @code{IS NULL} in @code{WHERE} clause.
@item
-Changed the optimizer a little to get better results when searching on a key
+Changed the optimiser a little to get better results when searching on a key
part.
@item
-Added @code{SELECT} option @code{STRAIGHT_JOIN} to tell the optimizer that
+Added @code{SELECT} option @code{STRAIGHT_JOIN} to tell the optimiser that
it should join tables in the given order.
@item
Added support for comments starting with @code{'--'} in @file{mysql.cc}
@@ -52472,7 +54362,7 @@ information is kept here for historical purposes only.
@itemize @bullet
@item
-Some new functions, some more optimization on joins.
+Some new functions, some more optimisation on joins.
@item
Should now compile clean on Linux (2.0.x).
@item
@@ -52540,10 +54430,21 @@ Fixed @code{DISTINCT} with calculated columns.
@node Porting, Environment variables, News, Top
-@appendix Comments on porting to other systems
+@appendix Comments on Porting to Other Systems
@cindex porting, to other systems
+This appendix will help you port MySQL to other operationg systems.
+Do check the list of currently supported operating systems first.
+@xref{Which OS}.
+If you have created a new port of MySQL, please let us know so that
+we can list it here and on our web site (@uref{http://www.mysql.com/}),
+recommending it to other users.
+
+Note: If you create a new port of MySQL, you are free to copy and
+distribute it under the GPL license, but it does not make you a
+copyright holder of MySQL.
+
A working Posix thread library is needed for the server. On Solaris 2.5
we use Sun PThreads (the native thread support in 2.4 and earlier
versions are not good enough) and on Linux we use LinuxThreads by Xavier
@@ -52551,13 +54452,13 @@ Leroy, @email{Xavier.Leroy@@inria.fr}.
The hard part of porting to a new Unix variant without good native
thread support is probably to port MIT-pthreads. See
-@file{mit-pthreads/README} and
-@uref{http://www.humanfactor.com/pthreads/, Programming POSIX Threads}.
+@file{mit-pthreads/README} and Programming POSIX Threads
+(@uref{http://www.humanfactor.com/pthreads/}).
The MySQL distribution includes a patched version of
-Provenzano's Pthreads from MIT (see
-@uref{http://www.mit.edu:8001/people/proven/pthreads.html, MIT Pthreads
-web page}). This can be used for some operating systems that do not
+Provenzano's Pthreads from MIT (see the MIT Pthreads web page at
+@uref{http://www.mit.edu:8001/people/proven/pthreads.html}).
+This can be used for some operating systems that do not
have POSIX threads.
It is also possible to use another user level thread package named
@@ -52626,7 +54527,7 @@ will ensure that your thread installation has even a remote chance to work!
If you are using some functionality that is very new in MySQL,
you can try to run @code{mysqld} with the @code{--skip-new} (which will disable all
new, potentially unsafe functionality) or with @code{--safe-mode} which
-disables a lot of optimization that may cause problems.
+disables a lot of optimisation that may cause problems.
@xref{Crashing}.
If @code{mysqld} doesn't want to start, you should check that you don't have
@@ -52646,7 +54547,7 @@ may help solve some problems. This command also provides some useful
information even if you haven't compiled MySQL for debugging!
If the problem is that some tables are getting slower and slower you
-should try to optimize the table with @code{OPTIMIZE TABLE} or
+should try to optimise the table with @code{OPTIMIZE TABLE} or
@code{myisamchk}. @xref{MySQL Database Administration}. You should also
check the slow queries with @code{EXPLAIN}.
@@ -52655,7 +54556,7 @@ problems that may be unique to your environment.
@xref{Operating System Specific Notes}.
@menu
-* Compiling for debugging:: Compiling MYSQL for debugging.
+* Compiling for debugging:: Compiling MYSQL for debugging
* Making trace files:: Creating trace files
* Using gdb on mysqld:: Debugging mysqld under gdb
* Using stack trace:: Using a stack trace
@@ -52665,7 +54566,7 @@ problems that may be unique to your environment.
@node Compiling for debugging, Making trace files, Debugging server, Debugging server
-@appendixsubsec Compiling MYSQL for debugging.
+@appendixsubsec Compiling MYSQL for debugging
If you have some very specific problem, you can always try to debug
MySQL. To do this you must configure MySQL with the
@@ -52745,7 +54646,7 @@ After this you can use the @code{mysql.exe} command line tool in a
second DOS window to reproduce the problem. You can take down the above
@code{mysqld} server with @code{mysqladmin shutdown}.
-Note that the trace file will get very @emph{BIG}!
+Note that the trace file will get @strong{very big}!
If you want to have a smaller trace file, you can use something like:
@code{mysqld --debug=d,info,error,query,general,where:O,/tmp/mysqld.trace}
@@ -52757,7 +54658,7 @@ If you make a bug report about this, please only send the lines from the
trace file to the appropriate mailing list where something seems to go
wrong! If you can't locate the wrong place, you can ftp the trace file,
together with a full bug report, to
-@uref{ftp://support.mysql.com/pub/mysql/secret} so that a MySQL
+@uref{ftp://support.mysql.com/pub/mysql/secret/} so that a MySQL
developer can take a look a this.
The trace file is made with the @strong{DBUG} package by Fred Fish.
@@ -52774,7 +54675,9 @@ more information if @code{mysqld} crashes.
With some older @code{gdb} versions on Linux you must use @code{run
--one-thread} if you want to be able to debug @code{mysqld} threads. In
-this case you can only have one thread active at a time.
+this case you can only have one thread active at a time. We recommend you
+to upgrade to gdb 5.1 ASAP as thread debugging works much better with this
+version!
When running @code{mysqld} under gdb, you should disable the stack trace
with @code{--skip-stack-trace} to be able to catch segfaults within gdb.
@@ -52854,7 +54757,7 @@ setting the @code{DBI_TRACE} environment variable.
On some operating systems, the error log will contain a stack trace if
@code{mysqld} dies unexpectedly. You can use this to find out where (and
maybe why) @code{mysqld} died. @xref{Error log}. To get a stack trace,
-you should NOT compile @code{mysqld} with the @code{-fomit-frame-pointer}
+you must not compile @code{mysqld} with the @code{-fomit-frame-pointer}
option to gcc. @xref{Compiling for debugging}.
If the error file contains something like the following:
@@ -52951,10 +54854,9 @@ work. If you find such a query, try first upgrading to the newest
MySQL version. If this doesn't help and you can't find anything
in the @code{mysql} mail archive, you should report the bug to
@email{mysql@@lists.mysql.com}. Links to mail archives are available
-online at the @uref{http://www.mysql.com/documentation/, MySQL
-documentation page}.
+online at @uref{http://lists.mysql.com/}.
-If you have started @code{mysqld} with @code{--with-myisam-recover},
+If you have started @code{mysqld} with @code{myisam-recover},
MySQL will automatically check and try to repair @code{MyISAM}
tables if they are marked as 'not closed properly' or 'crashed'. If
this happens, MySQL will write an entry in the
@@ -53008,7 +54910,7 @@ the name @code{hostname-bin.#}.
If the tables are corrupted again or you can get @code{mysqld} to die with the
above command, you have found reproducible bug that should be easy to
fix! FTP the tables and the binary log to
-@uref{ftp://support.mysql.com/pub/mysql/secret} and send a mail to
+@uref{ftp://support.mysql.com/pub/mysql/secret/} and send a mail to
@email{bugs@@lists.mysql.com} or (if you are a support customer) to
@email{support@@mysql.com} about the problem and the MySQL team
will fix it as soon as possible.
@@ -53025,8 +54927,8 @@ update statements if you want to narrow down the problem.
@cindex clients, debugging
To be able to debug a MySQL client with the integrated debug package,
-you should configure MySQL with @code{--with-debug}.
-@xref{configure options}.
+you should configure MySQL with @code{--with-debug} or
+@code{--with-debug=full}. @xref{configure options}.
@tindex MYSQL_DEBUG environment variable
@tindex Environment variable, MYSQL_DEBUG
@@ -53090,9 +54992,10 @@ an optional "," and comma-separated list of modifiers:
flag[,modifier,modifier,...,modifier]
@end example
-The currently recognized flag characters are:
+The currently recognised flag characters are:
@multitable @columnfractions .1 .9
+@item @strong{Flag} @tab @strong{Description}
@item d @tab Enable output from DBUG_<N> macros for the current state. May be followed by a list of keywords which selects output only for the DBUG macros with that keyword. An empty list of keywords implies output for all macros.
@item D @tab Delay after each debugger output line. The argument is the number of tenths of seconds to delay, subject to machine capabilities. That is, @code{-#D,20} is delay two seconds.
@item f @tab Limit debugging and/or tracing, and profiling to the list of named functions. Note that a null list will disable all functions. The appropriate "d" or "t" flags must still be given, this flag only limits their actions if they are enabled.
@@ -53134,12 +55037,14 @@ In MySQL, common tags to print (with the @code{d} option) are:
@cindex methods, locking
Currently MySQL only supports table locking for
-@code{ISAM}/@code{MyISAM} and @code{HEAP} tables and page level locking
-for @code{BDB} tables. @xref{Internal locking}. With @code{MyISAM}
+@code{ISAM}/@code{MyISAM} and @code{HEAP} tables.
+@code{InnoDB} tables use row level locking,
+and @code{BDB} tables page level locking. @xref{Internal locking}.
+With @code{MyISAM}
tables one can freely mix @code{INSERT} and @code{SELECT} without locks
(@code{Versioning}).
-Starting in version 3.23.33, you can analyze the table lock contention
+Starting in version 3.23.33, you can analyse the table lock contention
on your system by checking @code{Table_locks_waited} and
@code{Table_locks_immediate} environment variables.
@@ -53155,7 +55060,7 @@ Pros for row locking:
@item
Fewer lock conflicts when accessing different rows in many threads.
@item
-Less changes for rollbacks.
+Fewer changes for rollbacks.
@item
Makes it possible to lock a single row a long time.
@end itemize
@@ -53209,8 +55114,8 @@ Copy on demand is in many case much better than page or row level
locking; The worst case does, however, use much more memory than
when using normal locks.
-Instead of using row level locks one can use application level locks.
-(Like get_lock/release_lock in MySQL). This works of course
+Instead of using row level locks one can use application level locks
+(like get_lock/release_lock in MySQL). This works of course
only in well-behaved applications.
In many cases one can do an educated guess which locking type is best
@@ -53222,7 +55127,7 @@ Here are some tips about locking in MySQL:
On web application most applications do lots of selects, very few
deletes, updates mainly on keys and inserts in some specific tables.
-The base MySQL setup is VERY tuned for this.
+The base MySQL setup is very well tuned for this.
Concurrent users is not a problem if one doesn't mix updates and selects
that needs to examine many rows in the same table.
@@ -53235,10 +55140,11 @@ a single lock is much faster than updates without locks). Splitting
thing to different tables will also helps.
If you get speed problems with the table locks in MySQL, you
-may be able to solve these to convert some of your tables to @code{BDB} tables.
-@xref{BDB}.
+may be able to solve these by converting some of your tables to @code{InnoDB}
+or @code{BDB} tables.
+@xref{InnoDB}. @xref{BDB}.
-The optimization section in the manual covers a lot of different aspects of
+The optimisation section in the manual covers a lot of different aspects of
how to tune ones application. @xref{Tips}.
@@ -53393,7 +55299,7 @@ really ``thread aware''.
@node Environment variables, Regexp, Porting, Top
-@appendix Environment Variables
+@appendix Environment Variables
@cindex environment variables, list of
@@ -53451,6 +55357,7 @@ variables to modify the behavior of MySQL. @xref{Option files}.
@tindex Environment variable, USER
@multitable @columnfractions .2 .8
+@item @strong{Variable} @tab @strong{Description}
@item @code{CCX} @tab Set this to your C++ compiler when running configure.
@item @code{CC} @tab Set this to your C compiler when running configure.
@item @code{CFLAGS} @tab Flags for your C compiler when running configure.
@@ -53476,7 +55383,7 @@ variables to modify the behavior of MySQL. @xref{Option files}.
-@node Regexp, Unireg, Environment variables, Top
+@node Regexp, GPL license, Environment variables, Top
@appendix Description of MySQL regular expression syntax
@cindex regex
@@ -53629,6 +55536,7 @@ Within a bracket expression, the name of a character class enclosed in
to that class. Standard character class names are:
@multitable @columnfractions .33 .33 .33
+@item @strong{Name} @tab @strong{Name} @tab @strong{Name}
@item alnum @tab digit @tab punct
@item alpha @tab graph @tab space
@item blank @tab lower @tab upper
@@ -53663,77 +55571,7 @@ mysql> select "weeknights" REGEXP "^(wee|week)(knights|nights)$"; -> 1
-@node Unireg, GPL license, Regexp, Top
-@appendix What is Unireg?
-
-@cindex Unireg, described
-@cindex interface builder
-
-Unireg is our tty interface builder, but it uses a low-level connection
-to our ISAM (which is used by MySQL) and because of this it is
-very quick. It has existed since 1979 (on Unix in C since ~1986).
-
-Unireg has the following components:
-
-@itemize @bullet
-@item
-One table viewer with updates/browsing.
-@item
-Multi table viewer (with one scrolling region).
-@item
-Table creator. (With lots of column tags you can't create with MySQL)
-This is WYSIWYG (for a tty). You design a screen and Unireg prompts for
-the column specification.
-@item
-Report generator.
-@item
-A lot of utilities (quick import/export of tables to/from text files,
-analysis of table contents...).
-@item
-Powerful multi-table updates (which we use a lot) with a BASIC-like
-language with LOTS of functions.
-@item
-Dynamic languages (at present in Swedish and Finnish). If somebody wants
-an English version there are a few files that would have to be translated.
-@item
-The ability to run updates interactively or in a batch.
-@item
-Emacs-like key definitions with keyboard macros.
-@item
-All this in a binary of 800K.
-@item
-The @code{convform} utility. Converts @file{.frm} and text files between
-different character sets.
-@item
-The @code{myisampack} utility. Packs an ISAM table (makes it 50-80%
-smaller). The table can be read by MySQL like an ordinary
-table. Only one record has to be decompressed per access. Cannot handle
-@code{BLOB} or @code{TEXT} columns or updates (yet).
-@end itemize
-
-We update most of our production databases with the Unireg interface and
-serve web pages through MySQL (and in some extreme cases the Unireg
-report generator).
-
-Unireg takes about 3M of disk space and works on at least the following
-platforms: SunOS 4.x, Solaris, Linux, HP-UX, ICL Unix, DNIX, SCO and
-MS-DOS.
-
-Unireg is currently only available in Swedish and Finnish.
-
-The price tag for Unireg is 10,000 Swedish kr (about $1500 US), but this
-includes support. Unireg is distributed as a binary. (But all the ISAM
-sources can be found in MySQL). Usually we compile the binary for the
-customer at their site.
-
-All new development is concentrated to MySQL.
-
-@page
-@c This node name is special
-
-
-
-@node GPL license, LGPL license, Unireg, Top
+@node GPL license, LGPL license, Regexp, Top
@appendix GNU GENERAL PUBLIC LICENSE
@cindex GPL, General Public License
@@ -54134,7 +55972,7 @@ Public License instead of this License.
-@node LGPL license, Placeholder, GPL license, Top
+@node LGPL license, Function Index, GPL license, Top
@appendix GNU LESSER GENERAL PUBLIC LICENSE
@cindex LGPL, Lesser General Public License
@@ -54705,690 +56543,7 @@ That's all there is to it!
-@node Placeholder, Function Index, LGPL license, Top
-@appendix Pieces of the manual in transit
-
-@menu
-* Installing binary:: Installing a MySQL Binary Distribution
-* Perl support:: Perl Installation Comments
-* Group by functions:: Functions for Use with @code{GROUP BY} Clauses
-@end menu
-
-
-@node Installing binary, Perl support, Placeholder, Placeholder
-@appendixsec Installing a MySQL Binary Distribution
-
-@cindex installing, binary distribution
-@cindex binary distributions, installing
-
-@menu
-* Linux-RPM:: Linux RPM files
-* Building clients:: Building client programs
-@end menu
-
-You need the following tools to install a MySQL binary distribution:
-
-@itemize @bullet
-@item
-GNU @code{gunzip} to uncompress the distribution.
-
-@item
-A reasonable @code{tar} to unpack the distribution. GNU @code{tar} is
-known to work. Sun @code{tar} is known to have problems.
-@end itemize
-
-@cindex RPM, defined
-@cindex RedHat Package Manager
-An alternative installation method under Linux is to use RPM (RedHat Package
-Manager) distributions. @xref{Linux-RPM}.
-
-@c texi2html fails to split chapters if I use strong for all of this.
-If you run into problems, @strong{PLEASE ALWAYS USE} @code{mysqlbug} when
-posting questions to @email{mysql@@lists.mysql.com}. Even if the problem
-isn't a bug, @code{mysqlbug} gathers system information that will help others
-solve your problem. By not using @code{mysqlbug}, you lessen the likelihood
-of getting a solution to your problem! You will find @code{mysqlbug} in the
-@file{bin} directory after you unpack the distribution. @xref{Bug reports}.
-
-@cindex commands, for binary distribution
-The basic commands you must execute to install and use a MySQL
-binary distribution are:
-
-@example
-shell> groupadd mysql
-shell> useradd -g mysql mysql
-shell> cd /usr/local
-shell> gunzip < /path/to/mysql-VERSION-OS.tar.gz | tar xvf -
-shell> ln -s mysql-VERSION-OS mysql
-shell> cd mysql
-shell> scripts/mysql_install_db
-shell> chown -R root /usr/local/mysql
-shell> chown -R mysql /usr/local/mysql/data
-shell> chgrp -R mysql /usr/local/mysql
-shell> chown -R root /usr/local/mysql/bin
-shell> bin/safe_mysqld --user=mysql &
-@end example
-
-@cindex adding, new users
-@cindex new users, adding
-@cindex users, adding
-
-You can add new users using the @code{bin/mysql_setpermission} script if
-you install the @code{DBI} and @code{Msql-Mysql-modules} Perl modules.
-
-A more detailed description follows.
-
-To install a binary distribution, follow the steps below, then proceed
-to @ref{Post-installation}, for post-installation setup and testing:
-
-@enumerate
-@item
-Pick the directory under which you want to unpack the distribution, and move
-into it. In the example below, we unpack the distribution under
-@file{/usr/local} and create a directory @file{/usr/local/mysql} into which
-MySQL is installed. (The following instructions therefore assume
-you have permission to create files in @file{/usr/local}. If that directory
-is protected, you will need to perform the installation as @code{root}.)
-
-@item
-Obtain a distribution file from one of the sites listed in
-@ref{Getting MySQL, , Getting MySQL}.
-
-MySQL binary distributions are provided as compressed @code{tar}
-archives and have names like @file{mysql-VERSION-OS.tar.gz}, where
-@code{VERSION} is a number (for example, @code{3.21.15}), and @code{OS}
-indicates the type of operating system for which the distribution is intended
-(for example, @code{pc-linux-gnu-i586}).
-
-@item
-If you see a binary distribution marked with the @code{-max} prefix, this
-means that the binary has support for transaction-safe tables and other
-features. @xref{mysqld-max, , @code{mysqld-max}}. Note that all binaries
-are built from the same MySQL source distribution.
-
-@item
-Add a user and group for @code{mysqld} to run as:
-
-@example
-shell> groupadd mysql
-shell> useradd -g mysql mysql
-@end example
-
-These commands add the @code{mysql} group and the @code{mysql} user. The
-syntax for @code{useradd} and @code{groupadd} may differ slightly on different
-versions of Unix. They may also be called @code{adduser} and @code{addgroup}.
-You may wish to call the user and group something else instead of @code{mysql}.
-
-@item
-Change into the intended installation directory:
-
-@example
-shell> cd /usr/local
-@end example
-
-@item
-Unpack the distribution and create the installation directory:
-
-@example
-shell> gunzip < /path/to/mysql-VERSION-OS.tar.gz | tar xvf -
-shell> ln -s mysql-VERSION-OS mysql
-@end example
-
-The first command creates a directory named @file{mysql-VERSION-OS}. The
-second command makes a symbolic link to that directory. This lets you refer
-more easily to the installation directory as @file{/usr/local/mysql}.
-
-@item
-Change into the installation directory:
-
-@example
-shell> cd mysql
-@end example
-
-You will find several files and subdirectories in the @code{mysql} directory.
-The most important for installation purposes are the @file{bin} and
-@file{scripts} subdirectories.
-
-@table @file
-@item bin
-@tindex PATH environment variable
-@tindex environment variable, PATH
-This directory contains client programs and the server
-You should add the full pathname of this directory to your
-@code{PATH} environment variable so that your shell finds the MySQL
-programs properly. @xref{Environment variables}.
-
-@item scripts
-This directory contains the @code{mysql_install_db} script used to initialize
-the @code{mysql} database containing the grant tables that store the server
-access permissions.
-@end table
-
-@item
-If you would like to use @code{mysqlaccess} and have the MySQL
-distribution in some non-standard place, you must change the location where
-@code{mysqlaccess} expects to find the @code{mysql} client. Edit the
-@file{bin/mysqlaccess} script at approximately line 18. Search for a line
-that looks like this:
-
-@example
-$MYSQL = '/usr/local/bin/mysql'; # path to mysql executable
-@end example
-
-Change the path to reflect the location where @code{mysql} actually is
-stored on your system. If you do not do this, you will get a @code{Broken
-pipe} error when you run @code{mysqlaccess}.
-
-@item
-Create the MySQL grant tables (necessary only if you haven't
-installed MySQL before):
-@example
-shell> scripts/mysql_install_db
-@end example
-
-Note that MySQL versions older than Version 3.22.10 started the
-MySQL server when you run @code{mysql_install_db}. This is no
-longer true!
-
-@item
-Change ownership of binaries to @code{root} and ownership of the data
-directory to the user that you will run @code{mysqld} as:
-
-@example
-shell> chown -R root /usr/local/mysql
-shell> chown -R mysql /usr/local/mysql/data
-shell> chgrp -R mysql /usr/local/mysql
-@end example
-
-The first command changes the @code{owner} attribute of the files to the
-@code{root} user, the second one changes the @code{owner} attribute of the
-data directory to the @code{mysql} user, and the third one changes the
-@code{group} attribute to the @code{mysql} group.
-
-@item
-If you want to install support for the Perl @code{DBI}/@code{DBD} interface,
-see @ref{Perl support}.
-
-@item
-If you would like MySQL to start automatically when you boot your
-machine, you can copy @code{support-files/mysql.server} to the location where
-your system has its startup files. More information can be found in the
-@code{support-files/mysql.server} script itself and in
-@ref{Automatic start}.
-
-@end enumerate
-
-After everything has been unpacked and installed, you should initialize
-and test your distribution.
-
-You can start the MySQL server with the following command:
-
-@example
-shell> bin/safe_mysqld --user=mysql &
-@end example
-
-@xref{safe_mysqld, , @code{safe_mysqld}}.
-
-@xref{Post-installation}.
-
-
-
-
-
-
-
-@node Perl support, Group by functions, Installing binary, Placeholder
-@appendixsec Perl Installation Comments
-
-@cindex Perl, installing
-@cindex installing, Perl
-
-@menu
-* Perl installation:: Installing Perl on Unix
-* ActiveState Perl:: Installing ActiveState Perl on Windows
-* Windows Perl:: Installing the MySQL Perl distribution on Windows
-* Perl support problems:: Problems using the Perl @code{DBI}/@code{DBD} interface
-@end menu
-
-
-@node Perl installation, ActiveState Perl, Perl support, Perl support
-@appendixsubsec Installing Perl on Unix
-
-Perl support for MySQL is provided by means of the
-@code{DBI}/@code{DBD} client interface. @xref{Perl}. The Perl
-@code{DBD}/@code{DBI} client code requires Perl Version 5.004 or later. The
-interface @strong{will not work} if you have an older version of Perl.
-
-MySQL Perl support also requires that you've installed
-MySQL client programming support. If you installed MySQL
-from RPM files, client programs are in the client RPM, but client programming
-support is in the developer RPM. Make sure you've installed the latter RPM.
-
-As of Version 3.22.8, Perl support is distributed separately from the main
-MySQL distribution. If you want to install Perl support, the files
-you will need can be obtained from
-@uref{http://www.mysql.com/Downloads/Contrib/}.
-
-The Perl distributions are provided as compressed @code{tar} archives and
-have names like @file{MODULE-VERSION.tar.gz}, where @code{MODULE} is the
-module name and @code{VERSION} is the version number. You should get the
-@code{Data-Dumper}, @code{DBI}, and @code{Msql-Mysql-modules} distributions
-and install them in that order. The installation procedure is shown below.
-The example shown is for the @code{Data-Dumper} module, but the procedure is
-the same for all three distributions:
-
-@enumerate
-@item
-Unpack the distribution into the current directory:
-@example
-shell> gunzip < Data-Dumper-VERSION.tar.gz | tar xvf -
-@end example
-This command creates a directory named @file{Data-Dumper-VERSION}.
-
-@item
-Change into the top-level directory of the unpacked distribution:
-@example
-shell> cd Data-Dumper-VERSION
-@end example
-
-@item
-Build the distribution and compile everything:
-@example
-shell> perl Makefile.PL
-shell> make
-shell> make test
-shell> make install
-@end example
-@end enumerate
-
-The @code{make test} command is important because it verifies that the
-module is working. Note that when you run that command during the
-@code{Msql-Mysql-modules} installation to exercise the interface code, the
-MySQL server must be running or the test will fail.
-
-It is a good idea to rebuild and reinstall the @code{Msql-Mysql-modules}
-distribution whenever you install a new release of MySQL,
-particularly if you notice symptoms such as all your @code{DBI} scripts
-dumping core after you upgrade MySQL.
-
-If you don't have the right to install Perl modules in the system directory
-or if you to install local Perl modules, the following reference may help
-you:
-
-@example
-@uref{http://www.iserver.com/support/contrib/perl5/modules.html}
-@end example
-
-Look under the heading
-@code{Installing New Modules that Require Locally Installed Modules}.
-
-
-@node ActiveState Perl, Windows Perl, Perl installation, Perl support
-@appendixsubsec Installing ActiveState Perl on Windows
-
-@cindex installing, Perl on Windows
-@cindex Perl, installing on Windows
-@cindex ActiveState Perl
-
-To install the MySQL @code{DBD} module with ActiveState Perl on
-Windows, you should do the following:
-
-@itemize @bullet
-@item
-Get ActiveState Perl from
-@uref{http://www.activestate.com/Products/ActivePerl/index.html}
-and install it.
-
-@item
-Open a DOS shell.
-
-@item
-If required, set the HTTP_proxy variable. For example, you might try:
-
-@example
-set HTTP_proxy=my.proxy.com:3128
-@end example
-
-@item
-Start the PPM program:
-
-@example
-C:\> c:\perl\bin\ppm.pl
-@end example
-
-@item
-If you have not already done so, install @code{DBI}:
-
-@example
-ppm> install DBI
-@end example
-
-@item
-If this succeeds, run the following command:
-
-@example
-install ftp://ftp.de.uu.net/pub/CPAN/authors/id/JWIED/DBD-mysql-1.2212.x86.ppd
-@end example
-@end itemize
-
-The above should work at least with ActiveState Perl Version 5.6.
-
-If you can't get the above to work, you should instead install the
-@strong{MyODBC} driver and connect to MySQL server through
-ODBC:
-
-@example
-use DBI;
-$dbh= DBI->connect("DBI:ODBC:$dsn","$user","$password") ||
- die "Got error $DBI::errstr when connecting to $dsn\n";
-@end example
-
-
-@node Windows Perl, Perl support problems, ActiveState Perl, Perl support
-@appendixsubsec Installing the MySQL Perl Distribution on Windows
-
-The MySQL Perl distribution contains @code{DBI},
-@code{DBD:MySQL} and @code{DBD:ODBC}.
-
-@itemize @bullet
-@item
-Get the Perl distribution for Windows from
-@uref{http://www.mysql.com/download.html}.
-
-@item
-Unzip the distribution in @code{C:} so that you get a @file{C:\PERL} directory.
-
-@item
-Add the directory @file{C:\PERL\BIN} to your path.
-
-@item
-Add the directory @file{C:\PERL\BIN\MSWIN32-x86-thread} or
-@file{C:\PERL\BIN\MSWIN32-x86} to your path.
-
-@item
-Test that @code{perl} works by executing @code{perl -v} in a DOS shell.
-@end itemize
-
-
-@node Perl support problems, , Windows Perl, Perl support
-@appendixsubsec Problems Using the Perl @code{DBI}/@code{DBD} Interface
-
-@cindex problems, installing Perl
-@cindex Perl DBI/DBD, installation problems
-
-If Perl reports that it can't find the @file{../mysql/mysql.so} module,
-then the problem is probably that Perl can't locate the shared library
-@file{libmysqlclient.so}.
-
-You can fix this by any of the following methods:
-
-@itemize @bullet
-@item
-Compile the @code{Msql-Mysql-modules} distribution with @code{perl
-Makefile.PL -static -config} rather than @code{perl Makefile.PL}.
-
-@item
-Copy @code{libmysqlclient.so} to the directory where your other shared
-libraries are located (probably @file{/usr/lib} or @file{/lib}).
-
-@item
-On Linux you can add the pathname of the directory where
-@file{libmysqlclient.so} is located to the @file{/etc/ld.so.conf} file.
-
-@tindex LD_RUN_PATH environment variable
-@tindex Environment variable, LD_RUN_PATH
-@item
-Add the pathname of the directory where @file{libmysqlclient.so} is located
-to the @code{LD_RUN_PATH} environment variable.
-@end itemize
-
-If you get the following errors from @code{DBD-mysql},
-you are probably using @code{gcc} (or using an old binary compiled with
-@code{gcc}):
-
-@example
-/usr/bin/perl: can't resolve symbol '__moddi3'
-/usr/bin/perl: can't resolve symbol '__divdi3'
-@end example
-
-Add @code{-L/usr/lib/gcc-lib/... -lgcc} to the link command when the
-@file{mysql.so} library gets built (check the output from @code{make} for
-@file{mysql.so} when you compile the Perl client). The @code{-L} option
-should specify the pathname of the directory where @file{libgcc.a} is located
-on your system.
-
-Another cause of this problem may be that Perl and MySQL aren't both
-compiled with @code{gcc}. In this case, you can solve the mismatch by
-compiling both with @code{gcc}.
-
-If you get the following error from @code{Msql-Mysql-modules}
-when you run the tests:
-
-@example
-t/00base............install_driver(mysql) failed: Can't load '../blib/arch/auto/DBD/mysql/mysql.so' for module DBD::mysql: ../blib/arch/auto/DBD/mysql/mysql.so: undefined symbol: uncompress at /usr/lib/perl5/5.00503/i586-linux/DynaLoader.pm line 169.
-@end example
-
-it means that you need to include the compression library, -lz, to the
-link line. This can be doing the following change in the file
-@file{lib/DBD/mysql/Install.pm}:
-
-@example
-$sysliblist .= " -lm";
-
-to
-
-$sysliblist .= " -lm -lz";
-@end example
-
-After this, you MUST run 'make realclean' and then proceed with the
-installation from the beginning.
-
-If you want to use the Perl module on a system that doesn't support dynamic
-linking (like SCO) you can generate a static version of Perl that includes
-@code{DBI} and @code{DBD-mysql}. The way this works is that you generate a
-version of Perl with the @code{DBI} code linked in and install it on top of
-your current Perl. Then you use that to build a version of Perl that
-additionally has the @code{DBD} code linked in, and install that.
-
-On SCO, you must have the following environment variables set:
-
-@example
-shell> LD_LIBRARY_PATH=/lib:/usr/lib:/usr/local/lib:/usr/progressive/lib
-or
-shell> LD_LIBRARY_PATH=/usr/lib:/lib:/usr/local/lib:/usr/ccs/lib:/usr/progressive/lib:/usr/skunk/lib
-shell> LIBPATH=/usr/lib:/lib:/usr/local/lib:/usr/ccs/lib:/usr/progressive/lib:/usr/skunk/lib
-shell> MANPATH=scohelp:/usr/man:/usr/local1/man:/usr/local/man:/usr/skunk/man:
-@end example
-
-First, create a Perl that includes a statically linked @code{DBI} by running
-these commands in the directory where your @code{DBI} distribution is
-located:
-
-@example
-shell> perl Makefile.PL -static -config
-shell> make
-shell> make install
-shell> make perl
-@end example
-
-Then you must install the new Perl. The output of @code{make perl} will
-indicate the exact @code{make} command you will need to execute to perform
-the installation. On SCO, this is @code{make -f Makefile.aperl inst_perl
-MAP_TARGET=perl}.
-
-Next, use the just-created Perl to create another Perl that also includes a
-statically-linked @code{DBD::mysql} by running these commands in the
-directory where your @code{Msql-Mysql-modules} distribution is located:
-
-@example
-shell> perl Makefile.PL -static -config
-shell> make
-shell> make install
-shell> make perl
-@end example
-
-Finally, you should install this new Perl. Again, the output of @code{make
-perl} indicates the command to use.
-
-
-@node Group by functions, , Perl support, Placeholder
-@appendixsec Functions for Use with @code{GROUP BY} Clauses
-
-@findex GROUP BY functions
-@findex functions, GROUP BY
-
-If you use a group function in a statement containing no @code{GROUP BY}
-clause, it is equivalent to grouping on all rows.
-
-@table @code
-@findex COUNT()
-@item COUNT(expr)
-Returns a count of the number of non-@code{NULL} values in the rows
-retrieved by a @code{SELECT} statement:
-
-@example
-mysql> select student.student_name,COUNT(*)
- from student,course
- where student.student_id=course.student_id
- GROUP BY student_name;
-
-@end example
-
-@code{COUNT(*)} is somewhat different in that it returns a count of
-the number of rows retrieved, whether or not they contain @code{NULL}
-values.
-
-@code{COUNT(*)} is optimized to
-return very quickly if the @code{SELECT} retrieves from one table, no
-other columns are retrieved, and there is no @code{WHERE} clause.
-For example:
-
-@example
-mysql> select COUNT(*) from student;
-@end example
-
-@findex COUNT(DISTINCT)
-@findex DISTINCT
-@item COUNT(DISTINCT expr,[expr...])
-Returns a count of the number of different non-@code{NULL} values:
-
-@example
-mysql> select COUNT(DISTINCT results) from student;
-@end example
-
-In MySQL you can get the number of distinct expression
-combinations that don't contain NULL by giving a list of expressions.
-In ANSI SQL you would have to do a concatenation of all expressions
-inside @code{CODE(DISTINCT ..)}.
-
-@findex AVG()
-@item AVG(expr)
-Returns the average value of @code{expr}:
-
-@example
-mysql> select student_name, AVG(test_score)
- from student
- GROUP BY student_name;
-@end example
-
-@findex MIN()
-@findex MAX()
-@item MIN(expr)
-@itemx MAX(expr)
-Returns the minimum or maximum value of @code{expr}. @code{MIN()} and
-@code{MAX()} may take a string argument; in such cases they return the
-minimum or maximum string value. @xref{MySQL indexes}.
-
-@example
-mysql> select student_name, MIN(test_score), MAX(test_score)
- from student
- GROUP BY student_name;
-@end example
-
-@findex SUM()
-@item SUM(expr)
-Returns the sum of @code{expr}. Note that if the return set has no rows,
-it returns NULL!
-
-@findex STD()
-@findex STDDEV()
-@cindex Oracle compatibility
-@cindex compatibility, with Oracle
-@item STD(expr)
-@itemx STDDEV(expr)
-Returns the standard deviation of @code{expr}. This is an extension to
-ANSI SQL. The @code{STDDEV()} form of this function is provided for Oracle
-compatibility.
-
-@findex BIT_OR()
-@item BIT_OR(expr)
-Returns the bitwise @code{OR} of all bits in @code{expr}. The calculation is
-performed with 64-bit (@code{BIGINT}) precision.
-
-@findex BIT_AND()
-@item BIT_AND(expr)
-Returns the bitwise @code{AND} of all bits in @code{expr}. The calculation is
-performed with 64-bit (@code{BIGINT}) precision.
-@end table
-
-@cindex @code{GROUP BY}, extensions to ANSI SQL
-MySQL has extended the use of @code{GROUP BY}. You can use columns or
-calculations in the @code{SELECT} expressions that don't appear in
-the @code{GROUP BY} part. This stands for @emph{any possible value for this
-group}. You can use this to get better performance by avoiding sorting and
-grouping on unnecessary items. For example, you don't need to group on
-@code{customer.name} in the following query:
-
-@example
-mysql> select order.custid,customer.name,max(payments)
- from order,customer
- where order.custid = customer.custid
- GROUP BY order.custid;
-@end example
-
-In ANSI SQL, you would have to add @code{customer.name} to the @code{GROUP
-BY} clause. In MySQL, the name is redundant if you don't run in
-ANSI mode.
-
-@strong{Don't use this feature} if the columns you omit from the
-@code{GROUP BY} part aren't unique in the group! You will get
-unpredictable results.
-
-In some cases, you can use @code{MIN()} and @code{MAX()} to obtain a specific
-column value even if it isn't unique. The following gives the value of
-@code{column} from the row containing the smallest value in the @code{sort}
-column:
-
-@example
-substr(MIN(concat(rpad(sort,6,' '),column)),7)
-@end example
-
-@xref{example-Maximum-column-group-row}.
-
-@cindex @code{ORDER BY}, aliases in
-@cindex aliases, in @code{ORDER BY} clauses
-@cindex @code{GROUP BY}, aliases in
-@cindex aliases, in @code{GROUP BY} clauses
-@cindex expression aliases
-@cindex aliases, for expressions
-Note that if you are using MySQL Version 3.22 (or earlier) or if
-you are trying to follow ANSI SQL, you can't use expressions in @code{GROUP
-BY} or @code{ORDER BY} clauses. You can work around this limitation by
-using an alias for the expression:
-
-@example
-mysql> SELECT id,FLOOR(value/100) AS val FROM tbl_name
- GROUP BY id,val ORDER BY val;
-@end example
-
-In MySQL Version 3.23 you can do:
-
-@example
-mysql> SELECT id,FLOOR(value/100) FROM tbl_name ORDER BY RAND();
-@end example
-
-
-@node Function Index, Concept Index, Placeholder, Top
+@node Function Index, Concept Index, LGPL license, Top
@unnumbered SQL command, type and function index
@printindex fn
diff --git a/Docs/mirrors.texi b/Docs/mirrors.texi
new file mode 100644
index 00000000000..3296b83ff37
--- /dev/null
+++ b/Docs/mirrors.texi
@@ -0,0 +1,392 @@
+@strong{Europe:}
+
+@itemize @bullet
+
+@item
+@image{Flags/austria} Austria [Univ. of Technology/Vienna] @@
+WWW (@uref{http://gd.tuwien.ac.at/db/mysql/})
+FTP (@uref{ftp://gd.tuwien.ac.at/db/mysql/})
+
+@item
+@image{Flags/belgium} Belgium [BELNET] @@
+WWW (@uref{http://mysql.belnet.be/})
+FTP (@uref{ftp://ftp.belnet.be/mirror/ftp.mysql.com/pub/mysql/})
+
+@item
+@image{Flags/bulgaria} Bulgaria [online.bg/Sofia] @@
+WWW (@uref{http://mysql.online.bg/})
+FTP (@uref{ftp://mysql.online.bg/})
+
+@item
+@image{Flags/czech-republic} Czech Republic [Masaryk University in Brno] @@
+WWW (@uref{http://mysql.linux.cz/})
+FTP (@uref{ftp://ftp.fi.muni.cz/pub/mysql/})
+
+@item
+@image{Flags/czech-republic} Czech Republic [www.gin.cz] @@
+WWW (@uref{http://mysql.gin.cz/})
+FTP (@uref{ftp://ftp.gin.cz/pub/MIRRORS/www.mysql.com/})
+
+@item
+@image{Flags/czech-republic} Czech Republic [www.sopik.cz] @@
+WWW (@uref{http://www.mysql.cz/})
+
+@item
+@image{Flags/denmark} Denmark [Borsen] @@
+WWW (@uref{http://mysql.borsen.dk/})
+
+@item
+@image{Flags/denmark} Denmark [SunSITE] @@
+WWW (@uref{http://mirrors.sunsite.dk/mysql/})
+FTP (@uref{ftp://sunsite.dk/mirrors/mysql/})
+
+@item
+@image{Flags/estonia} Estonia [OK Interactive] @@
+WWW (@uref{http://mysql.mirror.ok.ee/})
+
+@item
+@image{Flags/finland} Finland [KPNQwest] @@
+WWW (@uref{http://mysql.kpnqwest.fi/})
+
+@item
+@image{Flags/finland} Finland [tonnikala.net] @@
+WWW (@uref{http://mysql.tonnikala.org/})
+
+@item
+@image{Flags/france} France [free.fr] @@
+WWW (@uref{http://mysql-mirror.free.fr/})
+FTP (@uref{ftp://ftp.free.fr/pub/MySQL/})
+
+@item
+@image{Flags/france} France [Omegatomic] @@
+WWW (@uref{http://mysql.omegatomic.com/})
+
+@item
+@image{Flags/germany} Germany [GWDG] @@
+WWW (@uref{http://ftp.gwdg.de/pub/misc/mysql/})
+FTP (@uref{ftp://ftp.gwdg.de/pub/misc/mysql/})
+
+@item
+@image{Flags/germany} Germany [SunSITE Central Europe] @@
+WWW (@uref{http://sunsite.informatik.rwth-aachen.de/mysql/})
+FTP (@uref{ftp://sunsite.informatik.rwth-aachen.de/pub/mirror/www.mysql.com/})
+
+@item
+@image{Flags/germany} Germany [Wolfenbuettel] @@
+WWW (@uref{http://www.fh-wolfenbuettel.de/ftp/pub/database/mysql/})
+FTP (@uref{ftp://ftp.fh-wolfenbuettel.de/pub/database/mysql/})
+
+@item
+@image{Flags/greece} Greece [NTUA, Athens] @@
+WWW (@uref{http://www.ntua.gr/mysql/})
+FTP (@uref{ftp://ftp.ntua.gr/pub/databases/mysql/})
+
+@item
+@image{Flags/hungary} Hungary [stop.hu] @@
+WWW (@uref{http://mysql.mirror.stop.hu/})
+
+@item
+@image{Flags/hungary} Hungary [TiszaneT] @@
+WWW (@uref{http://mysql.tiszanet.hu/})
+FTP (@uref{ftp://mysql.tiszanet.hu/pub/mirrors/mysql/})
+
+@item
+@image{Flags/hungary} Hungary [Xenia] @@
+WWW (@uref{http://mysql.sote.hu/})
+FTP (@uref{ftp://xenia.sote.hu/pub/mirrors/www.mysql.com/})
+
+@item
+@image{Flags/iceland} Iceland [GM] @@
+WWW (@uref{http://mysql.gm.is/})
+FTP (@uref{ftp://ftp.gm.is/pub/mysql/})
+
+@item
+@image{Flags/ireland} Ireland [Esat Net] @@
+WWW (@uref{http://ftp.esat.net/mirrors/download.sourceforge.net/pub/mirrors/mysql/})
+FTP (@uref{ftp://ftp.esat.net/mirrors/download.sourceforge.net/pub/mirrors/mysql/})
+
+@item
+@image{Flags/italy} Italy [feelinglinux.com] @@
+WWW (@uref{http://mysql.feelinglinux.com/})
+
+@item
+@image{Flags/italy} Italy [Teta Srl] @@
+WWW (@uref{http://www.teta.it/mysql/})
+
+@item
+@image{Flags/italy} Italy [tzone.it] @@
+WWW (@uref{http://mysql.tzone.it/})
+
+@item
+@image{Flags/latvia} Latvia [linux.lv] @@
+FTP (@uref{ftp://ftp.linux.lv/pub/software/mysql/})
+
+@item
+@image{Flags/netherlands} Netherlands [OMS-Net] @@
+WWW (@uref{http://mysql.oms-net.nl/})
+
+@item
+@image{Flags/netherlands} Netherlands [ProServe] @@
+WWW (@uref{http://mysql.proserve.nl/})
+
+@item
+@image{Flags/netherlands} Netherlands [WideXS BV] @@
+WWW (@uref{http://mysql.mirror.widexs.nl/})
+FTP (@uref{ftp://mirror.widexs.nl/pub/mysql/})
+
+@item
+@image{Flags/poland} Poland [ncservice.com/Gdansk] @@
+WWW (@uref{http://mysql.service.net.pl/})
+
+@item
+@image{Flags/poland} Poland [SunSITE] @@
+WWW (@uref{http://sunsite.icm.edu.pl/mysql/})
+FTP (@uref{ftp://sunsite.icm.edu.pl/pub/unix/mysql/})
+
+@item
+@image{Flags/portugal} Portugal [Instituto Supertior Técnico] @@
+WWW (@uref{http://darkstar.ist.utl.pt/mysql/})
+FTP (@uref{ftp://darkstar.ist.utl.pt/pub/mysql/})
+
+@item
+@image{Flags/portugal} Portugal [Netc] @@
+WWW (@uref{http://ftp.netc.pt/pub/mysql/})
+FTP (@uref{ftp://ftp.netc.pt/pub/mysql/})
+
+@item
+@image{Flags/romania} Romania [roedu.net/Bucharest] @@
+FTP (@uref{ftp://ftp.roedu.net/pub/mirrors/ftp.mysql.com/})
+
+@item
+@image{Flags/russia} Russia [DirectNet] @@
+WWW (@uref{http://mysql.directnet.ru/})
+FTP (@uref{ftp://ftp.dn.ru/pub/MySQL/})
+
+@item
+@image{Flags/russia} Russia [Scientific Center/Chernogolovka] @@
+FTP (@uref{ftp://ftp.chg.ru/pub/databases/mysql/})
+
+@item
+@image{Flags/slovenia} Slovenia [ARNES] @@
+WWW (@uref{http://ftp.arnes.si/mysql/})
+FTP (@uref{ftp://ftp.arnes.si/packages/mysql/})
+
+@item
+@image{Flags/spain} Spain [GMC Control Systems] @@
+WWW (@uref{http://mysql.neptuno2000.com/})
+FTP (@uref{ftp://ftp.neptuno2000.com/pub/mysql/})
+
+@item
+@image{Flags/sweden} Sweden [Sunet] @@
+WWW (@uref{http://ftp.sunet.se/pub/unix/databases/relational/mysql/})
+FTP (@uref{ftp://ftp.sunet.se/pub/unix/databases/relational/mysql/})
+
+@item
+@image{Flags/switzerland} Switzerland [SunSITE] @@
+WWW (@uref{http://sunsite.cnlab-switch.ch/ftp/mirror/mysql/})
+FTP (@uref{ftp://sunsite.cnlab-switch.ch/mirror/mysql/})
+
+@item
+@image{Flags/turkey} Turkey [proGEN] @@
+WWW (@uref{http://mysql.progen.com.tr/})
+
+@item
+@image{Flags/great-britain} UK [PLiG/UK] @@
+WWW (@uref{http://ftp.plig.org/pub/mysql/})
+FTP (@uref{ftp://ftp.plig.org/pub/mysql/})
+
+@item
+@image{Flags/ukraine} Ukraine [ISP Alkar Teleport/Dnepropetrovsk] @@
+WWW (@uref{http://mysql.dp.ua/})
+FTP (@uref{ftp://ftp.tlk-l.net/pub/mirrors/mysql.com/})
+
+@item
+@image{Flags/ukraine} Ukraine [PACO] @@
+WWW (@uref{http://mysql.paco.net.ua/})
+FTP (@uref{ftp://mysql.paco.net.ua/})
+
+@item
+@image{Flags/yugoslavia} Yugoslavia [Open Source Network of Yugoslavia] @@
+WWW (@uref{http://mysql.boa.org.yu/})
+FTP (@uref{ftp://ftp.linux.org.yu/pub/MySQL/})
+
+@end itemize
+
+@strong{North America:}
+
+@itemize @bullet
+
+@item
+@image{Flags/canada} Canada [Tryc] @@
+WWW (@uref{http://web.tryc.on.ca/mysql/})
+
+@item
+@image{Flags/mexico} Mexico [UAM] @@
+WWW (@uref{http://mysql.azc.uam.mx/})
+FTP (@uref{ftp://mysql.azc.uam.mx/mirrors/mysql/})
+
+@item
+@image{Flags/mexico} Mexico [UNAM] @@
+WWW (@uref{http://mysql.unam.mx/})
+FTP (@uref{ftp://mysql.unam.mx/pub/mysql/})
+
+@item
+@image{Flags/usa} USA [adgrafix.com / Boston, MA] @@
+WWW (@uref{http://mysql.adgrafix.com/})
+
+@item
+@image{Flags/usa} USA [Ahaza Systems / Seattle, WA] @@
+WWW (@uref{http://mysql.mirrortree.com/})
+FTP (@uref{ftp://mysql.mirrortree.com/pub/mysql/})
+
+@item
+@image{Flags/usa} USA [Hurricane Electric / San Jose, CA] @@
+WWW (@uref{http://mysql.he.net/})
+
+@item
+@image{Flags/usa} USA [netNumina / Cambridge, MA] @@
+WWW (@uref{http://mysql.mirrors.netnumina.com/})
+
+@item
+@image{Flags/usa} USA [NIXC / Vienna, VA] @@
+WWW (@uref{http://mysql.nixc.net/})
+FTP (@uref{ftp://mysql.nixc.net/pub/mysql/})
+
+@item
+@image{Flags/usa} USA [Oregon State University / Corvallis, OR] @@
+WWW (@uref{http://mysql.orst.edu/})
+FTP (@uref{ftp://ftp.orst.edu/pub/mysql/})
+
+@item
+@image{Flags/usa} USA [University of Wisconsin / Wisconsin] @@
+WWW (@uref{http://mirror.sit.wisc.edu/mysql/})
+FTP (@uref{ftp://mirror.sit.wisc.edu/mirrors/mysql/})
+
+@item
+@image{Flags/usa} USA [ValueClick / Los Angeles, CA] @@
+WWW (@uref{http://mysql.valueclick.com/})
+FTP (@uref{ftp://mysql.valueclick.com/pub/mysql/})
+
+@end itemize
+
+@strong{South America:}
+
+@itemize @bullet
+
+@item
+@image{Flags/argentina} Argentina [bannerlandia.com] @@
+WWW (@uref{http://mysql.bannerlandia.com.ar/})
+FTP (@uref{ftp://mysql.bannerlandia.com.ar/mirrors/mysql/})
+
+@item
+@image{Flags/chile} Chile [PSINet] @@
+WWW (@uref{http://mysql.psinet.cl/})
+FTP (@uref{ftp://ftp.psinet.cl/pub/database/mysql/})
+
+@item
+@image{Flags/chile} Chile [Tecnoera] @@
+WWW (@uref{http://mysql.tecnoera.com/})
+
+@item
+@image{Flags/chile} Chile [Vision] @@
+WWW (@uref{http://mysql.vision.cl/})
+
+@end itemize
+
+@strong{Asia:}
+
+@itemize @bullet
+
+@item
+@image{Flags/china} China [Gremlins/Hong Kong] @@
+WWW (@uref{http://mysql.gremlins.com.hk/})
+FTP (@uref{ftp://ftp.mirrors.gremlins.com.hk/mysql/})
+
+@item
+@image{Flags/china} China [HKLPG/Hong Kong] @@
+WWW (@uref{http://mysql.hklpg.org/})
+
+@item
+@image{Flags/china} China [linuxforum.net] @@
+FTP (@uref{http://www2.linuxforum.net/mirror/mysql/})
+
+@item
+@image{Flags/china} China [shellhung.org/Hong Kong] @@
+WWW (@uref{http://mysql.shellhung.org/})
+FTP (@uref{ftp://ftp.shellhung.org/pub/Mirror/mysql/})
+
+@item
+@image{Flags/indonesia} Indonesia [incaf.net] @@
+WWW (@uref{http://mysql.incaf.net/})
+FTP (@uref{ftp://mysql.incaf.net/})
+
+@item
+@image{Flags/indonesia} Indonesia [M-Web] @@
+WWW (@uref{http://mysql.mweb.net.id/})
+
+@item
+@image{Flags/indonesia} Indonesia [web.id] @@
+WWW (@uref{http://mysql.itb.web.id/})
+FTP (@uref{ftp://mysql.itb.web.id/pub/MySQL/})
+
+@item
+@image{Flags/japan} Japan [Soft Agency] @@
+WWW (@uref{http://www.softagency.co.jp/MySQL/})
+
+@item
+@image{Flags/japan} Japan [u-aizu.ac.jp/Aizu] @@
+FTP (@uref{ftp://ftp.u-aizu.ac.jp/ftp/pub/dbms/mysql/mysql.com/})
+
+@item
+@image{Flags/philippines} Philippines [Ateneo de Zamboanga University] @@
+WWW (@uref{http://mysql.adzu.edu.ph/})
+
+@item
+@image{Flags/singapore} Singapore [HJC] @@
+WWW (@uref{http://mysql.hjc.edu.sg/})
+FTP (@uref{ftp://ftp.hjc.edu.sg/mysql/})
+
+@item
+@image{Flags/south-korea} South Korea [HolyNet] @@
+WWW (@uref{http://mysql.holywar.net/})
+
+@item
+@image{Flags/south-korea} South Korea [Webiiz] @@
+WWW (@uref{http://mysql.webiiz.com/})
+
+@item
+@image{Flags/taiwan} Taiwan [nctu.edu/HsinChu] @@
+WWW (@uref{http://mysql.nctu.edu.tw/})
+
+@item
+@image{Flags/taiwan} Taiwan [TTN] @@
+WWW (@uref{http://mysql.ttn.net/})
+
+@end itemize
+
+@strong{Australia:}
+
+@itemize @bullet
+
+@item
+@image{Flags/australia} Australia [planetmirror.com] @@
+WWW (@uref{http://mysql.planetmirror.com/})
+FTP (@uref{ftp://planetmirror.com/pub/mysql/})
+
+@end itemize
+
+@strong{Africa:}
+
+@itemize @bullet
+
+@item
+@image{Flags/south-africa1} South African Republic [Mweb] @@
+WWW (@uref{http://www.mysql.mweb.co.za/})
+
+@item
+@image{Flags/south-africa1} South African Republic [The Internet Solution/Johannesburg] @@
+FTP (@uref{ftp://ftp.is.co.za/linux/mysql/})
+
+@end itemize
+
+
diff --git a/Docs/my_sys.txt b/Docs/my_sys.txt
new file mode 100644
index 00000000000..85ffc13ecb4
--- /dev/null
+++ b/Docs/my_sys.txt
@@ -0,0 +1,140 @@
+Functions i mysys: (For flags se my_sys.h)
+
+ int my_copy _A((const char *from,const char *to,myf MyFlags));
+ - Copy file
+
+ int my_delete _A((const char *name,myf MyFlags));
+ - Delete file
+
+ int my_getwd _A((string buf,uint size,myf MyFlags));
+ int my_setwd _A((const char *dir,myf MyFlags));
+ - Get and set working directory
+
+ string my_tempnam _A((const char *pfx,myf MyFlags));
+ - Make a uniq temp file name by using dir and adding something after
+ pfx to make name uniq. Name is made by adding a uniq 6 length-string
+ and TMP_EXT after pfx.
+ Returns pointer to malloced area for filename. Should be freed by
+ free().
+
+ File my_open _A((const char *FileName,int Flags,myf MyFlags));
+ File my_create _A((const char *FileName,int CreateFlags,
+ int AccsesFlags, myf MyFlags));
+ int my_close _A((File Filedes,myf MyFlags));
+ uint my_read _A((File Filedes,byte *Buffer,uint Count,myf MyFlags));
+ uint my_write _A((File Filedes,const byte *Buffer,uint Count,
+ myf MyFlags));
+ ulong my_seek _A((File fd,ulong pos,int whence,myf MyFlags));
+ ulong my_tell _A((File fd,myf MyFlags));
+ - Use instead of open,open-with-create-flag, close read and write
+ to get automatic error-messages (flag: MYF_WME) and only have
+ to test for != 0 if error (flag: MY_NABP).
+
+ int my_rename _A((const char *from,const char *to,myf MyFlags));
+ - Rename file
+
+ FILE *my_fopen _A((const char *FileName,int Flags,myf MyFlags));
+ FILE *my_fdopen _A((File Filedes,int Flags,myf MyFlags));
+ int my_fclose _A((FILE *fd,myf MyFlags));
+ uint my_fread _A((FILE *stream,byte *Buffer,uint Count,myf MyFlags));
+ uint my_fwrite _A((FILE *stream,const byte *Buffer,uint Count,
+ myf MyFlags));
+ ulong my_fseek _A((FILE *stream,ulong pos,int whence,myf MyFlags));
+ ulong my_ftell _A((FILE *stream,myf MyFlags));
+ - Same read-interface for streams as for files
+
+ gptr _mymalloc _A((uint uSize,const char *sFile,
+ uint uLine, myf MyFlag));
+ gptr _myrealloc _A((string pPtr,uint uSize,const char *sFile,
+ uint uLine, myf MyFlag));
+ void _myfree _A((gptr pPtr,const char *sFile,uint uLine));
+ int _sanity _A((const char *sFile,unsigned int uLine));
+ gptr _myget_copy_of_memory _A((const byte *from,uint length,
+ const char *sFile, uint uLine,
+ myf MyFlag));
+ - malloc(size,myflag) is mapped to this functions if not compiled
+ with -DSAFEMALLOC
+
+ void TERMINATE _A((void));
+ - Writes malloc-info on stdout if compiled with -DSAFEMALLOC.
+
+ int my_chsize _A((File fd,ulong newlength,myf MyFlags));
+ - Change size of file
+
+ void my_error _D((int nr,myf MyFlags, ...));
+ - Writes message using error number (se mysys/errors.h) on
+ stdout or curses if MYSYS_PROGRAM_USES_CURSES() is called.
+
+ void my_message _A((const char *str,myf MyFlags));
+ - Writes message-string on
+ stdout or curses if MYSYS_PROGRAM_USES_CURSES() is called.
+
+ void my_init _A((void ));
+ - Start each program (in main) with this.
+ void my_end _A((int infoflag));
+ - Gives info about program.
+ - If infoflag & MY_CHECK_ERROR prints if some files are left open
+ - If infoflag & MY_GIVE_INFO prints timing info and malloc info
+ about prog.
+
+ int my_redel _A((const char *from, const char *to, int MyFlags));
+ - Delete from before rename of to to from. Copyes state from old
+ file to new file. If MY_COPY_TIME is set sets old time.
+
+ int my_copystat _A((const char *from, const char *to, int MyFlags));
+ - Copye state from old file to new file.
+ If MY_COPY_TIME is set sets copy also time.
+
+ string my_filename _A((File fd));
+ - Give filename of open file.
+
+ int dirname _A((string to,const char *name));
+ - Copy name of directory from filename.
+
+ int test_if_hard_path _A((const char *dir_name));
+ - Test if dirname is a hard path (Starts from root)
+
+ void convert_dirname _A((string name));
+ - Convert dirname acording to system.
+ - In MSDOS changes all caracters to capitals and changes '/' to
+ '\'
+ string fn_ext _A((const char *name));
+ - Returns pointer to extension in filename
+ string fn_format _A((string to,const char *name,const char *dsk,
+ const char *form,int flag));
+ format a filename with replace of library and extension and
+ converts between different systems.
+ params to and name may be identicall
+ function dosn't change name if name != to
+ Flag may be: 1 force replace filnames library with 'dsk'
+ 2 force replace extension with 'form' */
+ 4 force Unpack filename (replace ~ with home)
+ 8 Pack filename as short as possibly for output to
+ user.
+ All open requests should allways use at least:
+ "open(fn_format(temp_buffe,name,"","",4),...)" to unpack home and
+ convert filename to system-form.
+
+ string fn_same _A((string toname,const char *name,int flag));
+ - Copys directory and extension from name to toname if neaded.
+ copy can be forced by same flags that in fn_format.
+
+ int wild_compare _A((const char *str,const char *wildstr));
+ - Compare if str matches wildstr. Wildstr can contain "*" and "?"
+ as match-characters.
+ Returns 0 if match.
+
+ void get_date _A((string to,int timeflag));
+ - Get current date in a form ready for printing.
+
+ void soundex _A((string out_pntr, string in_pntr))
+ - Makes in_pntr to a 5 chars long string. All words that sounds
+ alike have the same string.
+
+ int init_key_cache _A((ulong use_mem,ulong leave_this_much_mem));
+ - Use cacheing of keys in MISAM, PISAM, and ISAM.
+ KEY_CACHE_SIZE is a good size.
+ - Remember to lock databases for optimal cacheing
+
+ void end_key_cache _A((void));
+ - End key-cacheing.
diff --git a/Docs/mysqld_error.txt b/Docs/mysqld_error.txt
index b8f0ba72ba5..7a5b6cf38d0 100644
--- a/Docs/mysqld_error.txt
+++ b/Docs/mysqld_error.txt
@@ -1,355 +1,457 @@
/* Copyright Abandoned 1997 TCX DataKonsult AB & Monty Program KB & Detron HB
This file is public domain and comes with NO WARRANTY of any kind */
-#define ER_HASHCHK 1000
+#define ER_HASHCHK 0
"hashchk",
-#define ER_NISAMCHK 1001
+#define ER_NISAMCHK 1
"isamchk",
-#define ER_NO 1002
+#define ER_NO 2
"NO",
-#define ER_YES 1003
+#define ER_YES 3
"YES",
-#define ER_CANT_CREATE_FILE 1004
+#define ER_CANT_CREATE_FILE 4
"Can't create file '%-.64s' (errno: %d)",
-#define ER_CANT_CREATE_TABLE 1005
+#define ER_CANT_CREATE_TABLE 5
"Can't create table '%-.64s' (errno: %d)",
-#define ER_CANT_CREATE_DB 1006
+#define ER_CANT_CREATE_DB 6
"Can't create database '%-.64s'. (errno: %d)",
-#define ER_DB_CREATE_EXISTS 1007
+#define ER_DB_CREATE_EXISTS 7
"Can't create database '%-.64s'. Database exists",
-#define ER_DB_DROP_EXISTS 1008
+#define ER_DB_DROP_EXISTS 8
"Can't drop database '%-.64s'. Database doesn't exist",
-#define ER_DB_DROP_DELETE 1009
+#define ER_DB_DROP_DELETE 9
"Error dropping database (can't delete '%-.64s', errno: %d)",
-#define ER_DB_DROP_RMDIR 1010
+#define ER_DB_DROP_RMDIR 10
"Error dropping database (can't rmdir '%-.64s', errno: %d)",
-#define ER_CANT_DELETE_FILE 1011
+#define ER_CANT_DELETE_FILE 11
"Error on delete of '%-.64s' (errno: %d)",
-#define ER_CANT_FIND_SYSTEM_REC 1012
+#define ER_CANT_FIND_SYSTEM_REC 12
"Can't read record in system table",
-#define ER_CANT_GET_STAT 1013
+#define ER_CANT_GET_STAT 13
"Can't get status of '%-.64s' (errno: %d)",
-#define ER_CANT_GET_WD 1014
+#define ER_CANT_GET_WD 14
"Can't get working directory (errno: %d)",
-#define ER_CANT_LOCK 1015
+#define ER_CANT_LOCK 15
"Can't lock file (errno: %d)",
-#define ER_CANT_OPEN_FILE 1016
+#define ER_CANT_OPEN_FILE 16
"Can't open file: '%-.64s'. (errno: %d)",
-#define ER_FILE_NOT_FOUND 1017
+#define ER_FILE_NOT_FOUND 17
"Can't find file: '%-.64s' (errno: %d)",
-#define ER_CANT_READ_DIR 1018
+#define ER_CANT_READ_DIR 18
"Can't read dir of '%-.64s' (errno: %d)",
-#define ER_CANT_SET_WD 1019
+#define ER_CANT_SET_WD 19
"Can't change dir to '%-.64s' (errno: %d)",
-#define ER_CHECKREAD 1020
+#define ER_CHECKREAD 20
"Record has changed since last read in table '%-.64s'",
-#define ER_DISK_FULL 1021
+#define ER_DISK_FULL 21
"Disk full (%s). Waiting for someone to free some space....",
-#define ER_DUP_KEY 1022
+#define ER_DUP_KEY 22
"Can't write, duplicate key in table '%-.64s'",
-#define ER_ERROR_ON_CLOSE 1023
+#define ER_ERROR_ON_CLOSE 23
"Error on close of '%-.64s' (errno: %d)",
-#define ER_ERROR_ON_READ 1024
+#define ER_ERROR_ON_READ 24
"Error reading file '%-.64s' (errno: %d)",
-#define ER_ERROR_ON_RENAME 1025
+#define ER_ERROR_ON_RENAME 25
"Error on rename of '%-.64s' to '%-.64s' (errno: %d)",
-#define ER_ERROR_ON_WRITE 1026
+#define ER_ERROR_ON_WRITE 26
"Error writing file '%-.64s' (errno: %d)",
-#define ER_FILE_USED 1027
+#define ER_FILE_USED 27
"'%-.64s' is locked against change",
-#define ER_FILSORT_ABORT 1028
+#define ER_FILSORT_ABORT 28
"Sort aborted",
-#define ER_FORM_NOT_FOUND 1029
+#define ER_FORM_NOT_FOUND 29
"View '%-.64s' doesn't exist for '%-.64s'",
-#define ER_GET_ERRNO 1030
+#define ER_GET_ERRNO 30
"Got error %d from table handler",
-#define ER_ILLEGAL_HA 1031
+#define ER_ILLEGAL_HA 31
"Table handler for '%-.64s' doesn't have this option",
-#define ER_KEY_NOT_FOUND 1032
+#define ER_KEY_NOT_FOUND 32
"Can't find record in '%-.64s'",
-#define ER_NOT_FORM_FILE 1033
+#define ER_NOT_FORM_FILE 33
"Incorrect information in file: '%-.64s'",
-#define ER_NOT_KEYFILE 1034
+#define ER_NOT_KEYFILE 34
"Incorrect key file for table: '%-.64s'. Try to repair it",
-#define ER_OLD_KEYFILE 1035
+#define ER_OLD_KEYFILE 35
"Old key file for table '%-.64s'; Repair it!",
-#define ER_OPEN_AS_READONLY 1036
+#define ER_OPEN_AS_READONLY 36
"Table '%-.64s' is read only",
-#define ER_OUTOFMEMORY 1037
+#define ER_OUTOFMEMORY 37
"Out of memory. Restart daemon and try again (needed %d bytes)",
-#define ER_OUT_OF_SORTMEMORY 1038
+#define ER_OUT_OF_SORTMEMORY 38
"Out of sort memory. Increase daemon sort buffer size",
-#define ER_UNEXPECTED_EOF 1039
+#define ER_UNEXPECTED_EOF 39
"Unexpected eof found when reading file '%-.64s' (errno: %d)",
-#define ER_CON_COUNT_ERROR 1040
+#define ER_CON_COUNT_ERROR 40
"Too many connections",
-#define ER_OUT_OF_RESOURCES 1041
+#define ER_OUT_OF_RESOURCES 41
"Out of memory; Check if mysqld or some other process uses all available memory. If not you may have to use 'ulimit' to allow mysqld to use more memory or you can add more swap space",
-#define ER_BAD_HOST_ERROR 1042
+#define ER_BAD_HOST_ERROR 42
"Can't get hostname for your address",
-#define ER_HANDSHAKE_ERROR 1043
+#define ER_HANDSHAKE_ERROR 43
"Bad handshake",
-#define ER_DBACCESS_DENIED_ERROR 1044
+#define ER_DBACCESS_DENIED_ERROR 44
"Access denied for user: '%-.32s@%-.64s' to database '%-.64s'",
-#define ER_ACCESS_DENIED_ERROR 1045
+#define ER_ACCESS_DENIED_ERROR 45
"Access denied for user: '%-.32s@%-.64s' (Using password: %s)",
-#define ER_NO_DB_ERROR 1046
+#define ER_NO_DB_ERROR 46
"No Database Selected",
-#define ER_UNKNOWN_COM_ERROR 1047
+#define ER_UNKNOWN_COM_ERROR 47
"Unknown command",
-#define ER_BAD_NULL_ERROR 1048
+#define ER_BAD_NULL_ERROR 48
"Column '%-.64s' cannot be null",
-#define ER_BAD_DB_ERROR 1049
+#define ER_BAD_DB_ERROR 49
"Unknown database '%-.64s'",
-#define ER_TABLE_EXISTS_ERROR 1050
+#define ER_TABLE_EXISTS_ERROR 50
"Table '%-.64s' already exists",
-#define ER_BAD_TABLE_ERROR 1051
+#define ER_BAD_TABLE_ERROR 51
"Unknown table '%-.64s'",
-#define ER_NON_UNIQ_ERROR 1052
+#define ER_NON_UNIQ_ERROR 52
"Column: '%-.64s' in %-.64s is ambiguous",
-#define ER_SERVER_SHUTDOWN 1053
+#define ER_SERVER_SHUTDOWN 53
"Server shutdown in progress",
-#define ER_BAD_FIELD_ERROR 1054
+#define ER_BAD_FIELD_ERROR 54
"Unknown column '%-.64s' in '%-.64s'",
-#define ER_WRONG_FIELD_WITH_GROUP 1055
+#define ER_WRONG_FIELD_WITH_GROUP 55
"'%-.64s' isn't in GROUP BY",
-#define ER_WRONG_GROUP_FIELD 1056
+#define ER_WRONG_GROUP_FIELD 56
"Can't group on '%-.64s'",
-#define ER_WRONG_SUM_SELECT 1057
+#define ER_WRONG_SUM_SELECT 57
"Statement has sum functions and columns in same statement",
-#define ER_WRONG_VALUE_COUNT 1058
+#define ER_WRONG_VALUE_COUNT 58
"Column count doesn't match value count",
-#define ER_TOO_LONG_IDENT 1059
+#define ER_TOO_LONG_IDENT 59
"Identifier name '%-.100s' is too long",
-#define ER_DUP_FIELDNAME 1060
+#define ER_DUP_FIELDNAME 60
"Duplicate column name '%-.64s'",
-#define ER_DUP_KEYNAME 1061
+#define ER_DUP_KEYNAME 61
"Duplicate key name '%-.64s'",
-#define ER_DUP_ENTRY 1062
+#define ER_DUP_ENTRY 62
"Duplicate entry '%-.64s' for key %d",
-#define ER_WRONG_FIELD_SPEC 1063
+#define ER_WRONG_FIELD_SPEC 63
"Incorrect column specifier for column '%-.64s'",
-#define ER_PARSE_ERROR 1064
+#define ER_PARSE_ERROR 64
"%s near '%-.80s' at line %d",
-#define ER_EMPTY_QUERY 1065
+#define ER_EMPTY_QUERY 65
"Query was empty",
-#define ER_NONUNIQ_TABLE 1066
+#define ER_NONUNIQ_TABLE 66
"Not unique table/alias: '%-.64s'",
-#define ER_INVALID_DEFAULT 1067
+#define ER_INVALID_DEFAULT 67
"Invalid default value for '%-.64s'",
-#define ER_MULTIPLE_PRI_KEY 1068
+#define ER_MULTIPLE_PRI_KEY 68
"Multiple primary key defined",
-#define ER_TOO_MANY_KEYS 1069
+#define ER_TOO_MANY_KEYS 69
"Too many keys specified. Max %d keys allowed",
-#define ER_TOO_MANY_KEY_PARTS 1070
+#define ER_TOO_MANY_KEY_PARTS 70
"Too many key parts specified. Max %d parts allowed",
-#define ER_TOO_LONG_KEY 1071
+#define ER_TOO_LONG_KEY 71
"Specified key was too long. Max key length is %d",
-#define ER_KEY_COLUMN_DOES_NOT_EXITS 1072
+#define ER_KEY_COLUMN_DOES_NOT_EXITS 72
"Key column '%-.64s' doesn't exist in table",
-#define ER_BLOB_USED_AS_KEY 1073
+#define ER_BLOB_USED_AS_KEY 73
"BLOB column '%-.64s' can't be used in key specification with the used table type",
-#define ER_TOO_BIG_FIELDLENGTH 1074
+#define ER_TOO_BIG_FIELDLENGTH 74
"Too big column length for column '%-.64s' (max = %d). Use BLOB instead",
-#define ER_WRONG_AUTO_KEY 1075
+#define ER_WRONG_AUTO_KEY 75
"Incorrect table definition; There can only be one auto column and it must be defined as a key",
-#define ER_READY 1076
+#define ER_READY 76
"%s: ready for connections\n",
-#define ER_NORMAL_SHUTDOWN 1077
+#define ER_NORMAL_SHUTDOWN 77
"%s: Normal shutdown\n",
-#define ER_GOT_SIGNAL 1078
+#define ER_GOT_SIGNAL 78
"%s: Got signal %d. Aborting!\n",
-#define ER_SHUTDOWN_COMPLETE 1079
+#define ER_SHUTDOWN_COMPLETE 79
"%s: Shutdown Complete\n",
-#define ER_FORCING_CLOSE 1080
+#define ER_FORCING_CLOSE 80
"%s: Forcing close of thread %ld user: '%-.32s'\n",
-#define ER_IPSOCK_ERROR 1081
+#define ER_IPSOCK_ERROR 81
"Can't create IP socket",
-#define ER_NO_SUCH_INDEX 1082
+#define ER_NO_SUCH_INDEX 82
"Table '%-.64s' has no index like the one used in CREATE INDEX. Recreate the table",
-#define ER_WRONG_FIELD_TERMINATORS 1083
-"Field separator argument is not what is expected. Check the manual","
-#define ER_BLOBS_AND_NO_TERMINATED 1084
+#define ER_WRONG_FIELD_TERMINATORS 83
+"Field separator argument is not what is expected. Check the manual",
+#define ER_BLOBS_AND_NO_TERMINATED 84
"You can't use fixed rowlength with BLOBs. Please use 'fields terminated by'.",
-#define ER_TEXTFILE_NOT_READABLE 1085
+#define ER_TEXTFILE_NOT_READABLE 85
"The file '%-.64s' must be in the database directory or be readable by all",
-#define ER_FILE_EXISTS_ERROR 1086
+#define ER_FILE_EXISTS_ERROR 86
"File '%-.80s' already exists",
-#define ER_LOAD_INFO 1087
+#define ER_LOAD_INFO 87
"Records: %ld Deleted: %ld Skipped: %ld Warnings: %ld",
-#define ER_ALTER_INFO 1088
+#define ER_ALTER_INFO 88
"Records: %ld Duplicates: %ld",
-#define ER_WRONG_SUB_KEY 1089
-"Incorrect sub part key. The used key part isn't a string or the used length is longer than the key part",
-#define ER_CANT_REMOVE_ALL_FIELDS 1090
+#define ER_WRONG_SUB_KEY 89
+"Incorrect sub part key. The used key part isn't a string, the used length is longer than the key part or the table handler doesn't support unique sub keys",
+#define ER_CANT_REMOVE_ALL_FIELDS 90
"You can't delete all columns with ALTER TABLE. Use DROP TABLE instead",
-#define ER_CANT_DROP_FIELD_OR_KEY 1091
+#define ER_CANT_DROP_FIELD_OR_KEY 91
"Can't DROP '%-.64s'. Check that column/key exists",
-#define ER_INSERT_INFO 1092
+#define ER_INSERT_INFO 92
"Records: %ld Duplicates: %ld Warnings: %ld",
-#define ER_INSERT_TABLE_USED 1093
+#define ER_INSERT_TABLE_USED 93
"INSERT TABLE '%-.64s' isn't allowed in FROM table list",
-#define ER_NO_SUCH_THREAD 1094
+#define ER_NO_SUCH_THREAD 94
"Unknown thread id: %lu",
-#define ER_KILL_DENIED_ERROR 1095
+#define ER_KILL_DENIED_ERROR 95
"You are not owner of thread %lu",
-#define ER_NO_TABLES_USED 1096
+#define ER_NO_TABLES_USED 96
"No tables used",
-#define ER_TOO_BIG_SET 1097
+#define ER_TOO_BIG_SET 97
"Too many strings for column %-.64s and SET",
-#define ER_NO_UNIQUE_LOGFILE 1098
+#define ER_NO_UNIQUE_LOGFILE 98
"Can't generate a unique log-filename %-.64s.(1-999)\n",
-#define ER_TABLE_NOT_LOCKED_FOR_WRITE 1099
+#define ER_TABLE_NOT_LOCKED_FOR_WRITE 99
"Table '%-.64s' was locked with a READ lock and can't be updated",
-#define ER_TABLE_NOT_LOCKED 1100
+#define ER_TABLE_NOT_LOCKED 100
"Table '%-.64s' was not locked with LOCK TABLES",
-#define ER_BLOB_CANT_HAVE_DEFAULT 1101
+#define ER_BLOB_CANT_HAVE_DEFAULT 101
"BLOB column '%-.64s' can't have a default value",
-#define ER_WRONG_DB_NAME 1102
+#define ER_WRONG_DB_NAME 102
"Incorrect database name '%-.100s'",
-#define ER_WRONG_TABLE_NAME 1103
+#define ER_WRONG_TABLE_NAME 103
"Incorrect table name '%-.100s'",
-#define ER_TOO_BIG_SELECT 1104
+#define ER_TOO_BIG_SELECT 104
"The SELECT would examine too many records and probably take a very long time. Check your WHERE and use SET OPTION SQL_BIG_SELECTS=1 if the SELECT is ok",
-#define ER_UNKNOWN_ERROR 1105
+#define ER_UNKNOWN_ERROR 105
"Unknown error",
-#define ER_UNKNOWN_PROCEDURE 1106
+#define ER_UNKNOWN_PROCEDURE 106
"Unknown procedure '%-.64s'",
-#define ER_WRONG_PARAMCOUNT_TO_PROCEDURE 1107
+#define ER_WRONG_PARAMCOUNT_TO_PROCEDURE 107
"Incorrect parameter count to procedure '%-.64s'",
-#define ER_WRONG_PARAMETERS_TO_PROCEDURE 1108
+#define ER_WRONG_PARAMETERS_TO_PROCEDURE 108
"Incorrect parameters to procedure '%-.64s'",
-#define ER_UNKNOWN_TABLE 1109
+#define ER_UNKNOWN_TABLE 109
"Unknown table '%-.64s' in %-.32s",
-#define ER_FIELD_SPECIFIED_TWICE 1110
+#define ER_FIELD_SPECIFIED_TWICE 110
"Column '%-.64s' specified twice",
-#define ER_INVALID_GROUP_FUNC_USE 1111
+#define ER_INVALID_GROUP_FUNC_USE 111
"Invalid use of group function",
-#define ER_UNSUPPORTED_EXTENSION 1112
+#define ER_UNSUPPORTED_EXTENSION 112
"Table '%-.64s' uses an extension that doesn't exist in this MySQL version",
-#define ER_TABLE_MUST_HAVE_COLUMNS 1113
+#define ER_TABLE_MUST_HAVE_COLUMNS 113
"A table must have at least 1 column",
-#define ER_RECORD_FILE_FULL 1114
+#define ER_RECORD_FILE_FULL 114
"The table '%-.64s' is full",
-#define ER_UNKNOWN_CHARACTER_SET 1115
+#define ER_UNKNOWN_CHARACTER_SET 115
"Unknown character set: '%-.64s'",
-#define ER_TOO_MANY_TABLES 1116
+#define ER_TOO_MANY_TABLES 116
"Too many tables. MySQL can only use %d tables in a join",
-#define ER_TOO_MANY_FIELDS 1117
+#define ER_TOO_MANY_FIELDS 117
"Too many columns",
-#define ER_TOO_BIG_ROWSIZE 1118
+#define ER_TOO_BIG_ROWSIZE 118
"Too big row size. The maximum row size, not counting BLOBs, is %d. You have to change some fields to BLOBs",
-#define ER_STACK_OVERRUN 1119
+#define ER_STACK_OVERRUN 119
"Thread stack overrun: Used: %ld of a %ld stack. Use 'mysqld -O thread_stack=#' to specify a bigger stack if needed",
-#define ER_WRONG_OUTER_JOIN 1120
+#define ER_WRONG_OUTER_JOIN 120
"Cross dependency found in OUTER JOIN. Examine your ON conditions",
-#define ER_NULL_COLUMN_IN_INDEX 1121
+#define ER_NULL_COLUMN_IN_INDEX 121
"Column '%-.64s' is used with UNIQUE or INDEX but is not defined as NOT NULL",
-#define ER_CANT_FIND_UDF 1122
+#define ER_CANT_FIND_UDF 122
"Can't load function '%-.64s'",
-#define ER_CANT_INITIALIZE_UDF 1123
+#define ER_CANT_INITIALIZE_UDF 123
"Can't initialize function '%-.64s'; %-.80s",
-#define ER_UDF_NO_PATHS 1124
+#define ER_UDF_NO_PATHS 124
"No paths allowed for shared library",
-#define ER_UDF_EXISTS 1125
+#define ER_UDF_EXISTS 125
"Function '%-.64s' already exist",
-#define ER_CANT_OPEN_LIBRARY 1126
+#define ER_CANT_OPEN_LIBRARY 126
"Can't open shared library '%-.64s' (errno: %d %-.64s)",
-#define ER_CANT_FIND_DL_ENTRY 1127
+#define ER_CANT_FIND_DL_ENTRY 127
"Can't find function '%-.64s' in library'",
-#define ER_FUNCTION_NOT_DEFINED 1128
+#define ER_FUNCTION_NOT_DEFINED 128
"Function '%-.64s' is not defined",
-#define ER_HOST_IS_BLOCKED 1129
+#define ER_HOST_IS_BLOCKED 129
"Host '%-.64s' is blocked because of many connection errors. Unblock with 'mysqladmin flush-hosts'",
-#define ER_HOST_NOT_PRIVILEGED 1130
+#define ER_HOST_NOT_PRIVILEGED 130
"Host '%-.64s' is not allowed to connect to this MySQL server",
-#define ER_PASSWORD_ANONYMOUS_USER 1131
+#define ER_PASSWORD_ANONYMOUS_USER 131
"You are using MySQL as an anonymous users and anonymous users are not allowed to change passwords",
-#define ER_PASSWORD_NOT_ALLOWED 1132
+#define ER_PASSWORD_NOT_ALLOWED 132
"You must have privileges to update tables in the mysql database to be able to change passwords for others",
-#define ER_PASSWORD_NO_MATCH 1133
+#define ER_PASSWORD_NO_MATCH 133
"Can't find any matching row in the user table",
-#define ER_UPDATE_INFO 1134
+#define ER_UPDATE_INFO 134
"Rows matched: %ld Changed: %ld Warnings: %ld",
-#define ER_CANT_CREATE_THREAD 1135
+#define ER_CANT_CREATE_THREAD 135
"Can't create a new thread (errno %d). If you are not out of available memory, you can consult the manual for a possible OS-dependent bug",
-#define ER_WRONG_VALUE_COUNT_ON_ROW 1136
+#define ER_WRONG_VALUE_COUNT_ON_ROW 136
"Column count doesn't match value count at row %ld",
-#define ER_CANT_REOPEN_TABLE 1137
+#define ER_CANT_REOPEN_TABLE 137
"Can't reopen table: '%-.64s'",
-#define ER_INVALID_USE_OF_NULL 1138
+#define ER_INVALID_USE_OF_NULL 138
"Invalid use of NULL value",
-#define ER_REGEXP_ERROR 1139
+#define ER_REGEXP_ERROR 139
"Got error '%-.64s' from regexp",
-#define ER_MIX_OF_GROUP_FUNC_AND_FIELDS 1140
+#define ER_MIX_OF_GROUP_FUNC_AND_FIELDS 140
"Mixing of GROUP columns (MIN(),MAX(),COUNT()...) with no GROUP columns is illegal if there is no GROUP BY clause",
-#define ER_NONEXISTING_GRANT 1141
+#define ER_NONEXISTING_GRANT 141
"There is no such grant defined for user '%-.32s' on host '%-.64s'",
-#define ER_TABLEACCESS_DENIED_ERROR 1142
+#define ER_TABLEACCESS_DENIED_ERROR 142
"%-.16s command denied to user: '%-.32s@%-.64s' for table '%-.64s'",
-#define ER_COLUMNACCESS_DENIED_ERROR 1143
+#define ER_COLUMNACCESS_DENIED_ERROR 143
"%-.16s command denied to user: '%-.32s@%-.64s' for column '%-.64s' in table '%-.64s'",
-#define ER_ILLEGAL_GRANT_FOR_TABLE 1144
+#define ER_ILLEGAL_GRANT_FOR_TABLE 144
"Illegal GRANT/REVOKE command. Please consult the manual which privileges can be used.",
-#define ER_GRANT_WRONG_HOST_OR_USER 1145
+#define ER_GRANT_WRONG_HOST_OR_USER 145
"The host or user argument to GRANT is too long",
-#define ER_NO_SUCH_TABLE 1146
+#define ER_NO_SUCH_TABLE 146
"Table '%-.64s.%-.64s' doesn't exist",
-#define ER_NONEXISTING_TABLE_GRANT 1147
+#define ER_NONEXISTING_TABLE_GRANT 147
"There is no such grant defined for user '%-.32s' on host '%-.64s' on table '%-.64s'",
-#define ER_NOT_ALLOWED_COMMAND 1148
+#define ER_NOT_ALLOWED_COMMAND 148
"The used command is not allowed with this MySQL version",
-#define ER_SYNTAX_ERROR 1149
+#define ER_SYNTAX_ERROR 149
"You have an error in your SQL syntax",
-#define ER_DELAYED_CANT_CHANGE_LOCK 1150
+#define ER_DELAYED_CANT_CHANGE_LOCK 150
"Delayed insert thread couldn't get requested lock for table %-.64s",
-#define ER_TOO_MANY_DELAYED_THREADS 1151
+#define ER_TOO_MANY_DELAYED_THREADS 151
"Too many delayed threads in use",
-#define ER_ABORTING_CONNECTION 1152
+#define ER_ABORTING_CONNECTION 152
"Aborted connection %ld to db: '%-.64s' user: '%-.32s' (%-.64s)",
-#define ER_NET_PACKET_TOO_LARGE 1153
+#define ER_NET_PACKET_TOO_LARGE 153
"Got a packet bigger than 'max_allowed_packet'",
-#define ER_NET_READ_ERROR_FROM_PIPE 1154
+#define ER_NET_READ_ERROR_FROM_PIPE 154
"Got a read error from the connection pipe",
-#define ER_NET_FCNTL_ERROR 1155
+#define ER_NET_FCNTL_ERROR 155
"Got an error from fcntl()",
-#define ER_NET_PACKETS_OUT_OF_ORDER 1156
+#define ER_NET_PACKETS_OUT_OF_ORDER 156
"Got packets out of order",
-#define ER_NET_UNCOMPRESS_ERROR 1157
+#define ER_NET_UNCOMPRESS_ERROR 157
"Couldn't uncompress communication packet",
-#define ER_NET_READ_ERROR 1158
+#define ER_NET_READ_ERROR 158
"Got an error reading communication packets",
-#define ER_NET_READ_INTERRUPTED 1159
+#define ER_NET_READ_INTERRUPTED 159
"Got timeout reading communication packets",
-#define ER_NET_ERROR_ON_WRITE 1160
+#define ER_NET_ERROR_ON_WRITE 160
"Got an error writing communication packets",
-#define ER_NET_WRITE_INTERRUPTED 1161
+#define ER_NET_WRITE_INTERRUPTED 161
"Got timeout writing communication packets",
-#define ER_TOO_LONG_STRING 1162
+#define ER_TOO_LONG_STRING 162
"Result string is longer than max_allowed_packet",
-#define ER_TABLE_CANT_HANDLE_BLOB 1163
+#define ER_TABLE_CANT_HANDLE_BLOB 163
"The used table type doesn't support BLOB/TEXT columns",
-#define ER_TABLE_CANT_HANDLE_AUTO_INCREMENT 1164
+#define ER_TABLE_CANT_HANDLE_AUTO_INCREMENT 164
"The used table type doesn't support AUTO_INCREMENT columns",
-#define ER_DELAYED_INSERT_TABLE_LOCKED 1165
+#define ER_DELAYED_INSERT_TABLE_LOCKED 165
"INSERT DELAYED can't be used with table '%-.64s', because it is locked with LOCK TABLES",
-#define ER_WRONG_COLUMN_NAME 1166
+#define ER_WRONG_COLUMN_NAME 166
"Incorrect column name '%-.100s'",
-#define ER_WRONG_KEY_COLUMN 1167
+#define ER_WRONG_KEY_COLUMN 167
"The used table handler can't index column '%-.64s'",
-#define ER_WRONG_MRG_TABLE 1168
+#define ER_WRONG_MRG_TABLE 168
"All tables in the MERGE table are not identically defined",
-#define ER_DUP_UNIQUE 1169
+#define ER_DUP_UNIQUE 169
"Can't write, because of unique constraint, to table '%-.64s'",
-#define ER_BLOB_KEY_WITHOUT_LENGTH 1170
+#define ER_BLOB_KEY_WITHOUT_LENGTH 170
"BLOB column '%-.64s' used in key specification without a key length",
-#define ER_PRIMARY_CANT_HAVE_NULL 1171
+#define ER_PRIMARY_CANT_HAVE_NULL 171
"All parts of a PRIMARY KEY must be NOT NULL; If you need NULL in a key, use UNIQUE instead",
-#define ER_TOO_MANY_ROWS 1172
+#define ER_TOO_MANY_ROWS 172
"Result consisted of more than one row",
-#define ER_REQUIRES_PRIMARY_KEY 1173
+#define ER_REQUIRES_PRIMARY_KEY 173
"This table type requires a primary key",
-#define ER_NO_RAID_COMPILED 1174
+#define ER_NO_RAID_COMPILED 174
"This version of MySQL is not compiled with RAID support",
-#define ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE 1175
+#define ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE 175
"You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column",
+#define ER_KEY_DOES_NOT_EXITS 176
+"Key '%-.64s' doesn't exist in table '%-.64s'",
+#define ER_CHECK_NO_SUCH_TABLE 177
+"Can't open table",
+#define ER_CHECK_NOT_IMPLEMENTED 178
+"The handler for the table doesn't support check/repair",
+#define ER_CANT_DO_THIS_DURING_AN_TRANSACTION 179
+"You are not allowed to execute this command in a transaction",
+#define ER_ERROR_DURING_COMMIT 180
+"Got error %d during COMMIT",
+#define ER_ERROR_DURING_ROLLBACK 181
+"Got error %d during ROLLBACK",
+#define ER_ERROR_DURING_FLUSH_LOGS 182
+"Got error %d during FLUSH_LOGS",
+#define ER_ERROR_DURING_CHECKPOINT 183
+"Got error %d during CHECKPOINT",
+#define ER_NEW_ABORTING_CONNECTION 184
+"Aborted connection %ld to db: '%-.64s' user: '%-.32s' host: `%-.64s' (%-.64s)",
+#define ER_DUMP_NOT_IMPLEMENTED 185
+"The handler for the table does not support binary table dump",
+#define ER_FLUSH_MASTER_BINLOG_CLOSED 186
+"Binlog closed, cannot RESET MASTER",
+#define ER_INDEX_REBUILD 187
+"Failed rebuilding the index of dumped table '%-.64s'",
+#define ER_MASTER 188
+"Error from master: '%-.64s'",
+#define ER_MASTER_NET_READ 189
+"Net error reading from master",
+#define ER_MASTER_NET_WRITE 190
+"Net error writing to master",
+#define ER_FT_MATCHING_KEY_NOT_FOUND 191
+"Can't find FULLTEXT index matching the column list",
+#define ER_LOCK_OR_ACTIVE_TRANSACTION 192
+"Can't execute the given command because you have active locked tables or an active transaction",
+#define ER_UNKNOWN_SYSTEM_VARIABLE 193
+"Unknown system variable '%-.64'",
+#define ER_CRASHED_ON_USAGE 194
+"Table '%-.64s' is marked as crashed and should be repaired",
+#define ER_CRASHED_ON_REPAIR 195
+"Table '%-.64s' is marked as crashed and last (automatic?) repair failed",
+#define ER_WARNING_NOT_COMPLETE_ROLLBACK 196
+"Warning: Some non-transactional changed tables couldn't be rolled back",
+#define ER_TRANS_CACHE_FULL 197
+"Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage. Increase this mysqld variable and try again',
+#define ER_SLAVE_MUST_STOP 198
+"This operation cannot be performed with a running slave, run SLAVE STOP first",
+#define ER_SLAVE_NOT_RUNNING 199
+"This operation requires a running slave, configure slave and do SLAVE START",
+#define ER_BAD_SLAVE 200
+"The server is not configured as slave, fix in config file or with CHANGE MASTER TO",
+#define ER_MASTER_INFO 201
+"Could not initialize master info structure, check permisions on master.info",
+#define ER_SLAVE_THREAD 202
+"Could not create slave thread, check system resources",
+#define ER_TOO_MANY_USER_CONNECTIONS 203
+"User %-.64s has already more than 'max_user_connections' active connections",
+#define ER_SET_CONSTANTS_ONLY 204
+"You may only use constant expressions with SET",
+#define ER_LOCK_WAIT_TIMEOUT 205
+"Lock wait timeout exceeded; Try restarting transaction",
+#define ER_LOCK_TABLE_FULL 206
+"The total number of locks exceeds the lock table size",
+#define ER_READ_ONLY_TRANSACTION 207
+"Update locks cannot be acquired during a READ UNCOMMITTED transaction",
+#define ER_DROP_DB_WITH_READ_LOCK 208
+"DROP DATABASE not allowed while thread is holding global read lock",
+#define ER_CREATE_DB_WITH_READ_LOCK 209
+"CREATE DATABASE not allowed while thread is holding global read lock",
+#define ER_WRONG_ARGUMENTS 210
+"Wrong arguments to %s",
+#define ER_NO_PERMISSION_TO_CREATE_USER 211
+"%-.32s@%-.64s is not allowed to create new users",
+#define ER_UNION_TABLES_IN_DIFFERENT_DIR 212
+"Incorrect table definition; All MERGE tables must be in the same database",
+#define ER_LOCK_DEADLOCK 213
+"Deadlock found when trying to get lock; Try restarting transaction",
+#define ER_TABLE_CANT_HANDLE_FULLTEXT 214
+"The used table type doesn't support FULLTEXT indexes",
+#define ER_CANNOT_ADD_FOREIGN 215
+"Cannot add foreign key constraint",
+#define ER_NO_REFERENCED_ROW 216
+"Cannot add a child row: a foreign key constraint fails",
+#define ER_ROW_IS_REFERENCED 217
+"Cannot delete a parent row: a foreign key constraint fails",
+#define ER_CONNECT_TO_MASTER 218
+"Error connecting to master: %-.128s",
+#define ER_QUERY_ON_MASTER 219
+"Error running query on master: %-.128s",
+#define ER_ERROR_WHEN_EXECUTING_COMMAND 220
+"Error when executing command %s: %-.128s",
+#define ER_WRONG_USAGE 221
+"Wrong usage of %s and %s",
+#define ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT 222
+"The used SELECT statements have a different number of columns",
+#define ER_CANT_UPDATE_WITH_READLOCK 223
+"Can't execute the query because you have a conflicting read lock",
+#define ER_MIXING_NOT_ALLOWED 224
+"Mixing of transactional and non-transactional tables is disabled",
+#define ER_DUP_ARGUMENT 225
+"Option '%s' used twice in statement",
+#define ER_TOO_MANY_USER_CONNECTIONS 203
+"User %-.64s has already more than 'max_user_connections' active connections",
diff --git a/Docs/section.Infolinks.texi b/Docs/section.Infolinks.texi
new file mode 100644
index 00000000000..828722e0e56
--- /dev/null
+++ b/Docs/section.Infolinks.texi
@@ -0,0 +1,880 @@
+@c FIX AGL 20011108 Extracted from manual.texi.
+@c Contains links to MySQL related info (books, articles). To web portals!
+
+
+@node MySQL-Books, General-SQL, Questions, MySQL Information Sources
+@subsection Books About MySQL
+
+For the latest book information, with user comments, please visit
+@uref{http://www.mysql.com/portal/books/html/}.
+
+While this manual is still the right place for up to date technical
+information, its primary goal is to contain everything there is to know
+about MySQL. It is sometimes nice to have a bound book to read
+in bed or while you travel. Here is a list of books about MySQL and
+related subjects (in English).
+
+By purchasing a book through these hyperlinks provided herein, you are
+contributing to the development of MySQL.
+
+@emph{MySQL}
+@multitable @columnfractions .3 .7
+@item Available @tab @uref{http://service.bfast.com/bfast/click?bfmid=2181&sourceid=34233559&bfpid=0735709211&bfmtype=book} (Barnes and Noble)
+@item Publisher @tab New Riders
+@item Author @tab Paul DuBois
+@item Pub Date @tab 1st Edition December 1999
+@item ISBN @tab 0735709211
+@item Pages @tab 800
+@item Price @tab $49.99 US
+@item Downloadable examples @tab
+ @uref{http://www.kitebird.com/mysql-book/} (@code{samp_db} distribution)
+@item Errata @tab
+@uref{http://www.kitebird.com/mysql-book/errata.html}
+@end multitable
+
+Foreword by Michael ``Monty'' Widenius, MySQL Moderator.
+@*
+
+In @emph{MySQL}, Paul DuBois provides you with a comprehensive guide to
+one of the most popular relational database systems. Paul has
+contributed to the online documentation for MySQL and is an
+active member of the MySQL community. The principal MySQL
+developer, Monty Widenius, and a network of his fellow developers
+reviewed the manuscript, and provided Paul with the kind of insight
+no one else could supply.
+@*
+
+Instead of merely giving you a general overview of MySQL, Paul
+teaches you how to make the most of its capabilities. Through two
+sample database applications that run throughout the book, he
+gives you solutions to problems you're sure to face. He helps you
+integrate MySQL efficiently with third-party tools, such as PHP
+and Perl, enabling you to generate dynamic Web pages through
+database queries. He teaches you to write programs that access
+MySQL databases, and also provides a comprehensive set of
+references to column types, operators, functions, SQL syntax,
+MySQL programming, C API, Perl @code{DBI}, and PHP API.
+@emph{MySQL} simply gives you the kind of information you won't find
+anywhere else.
+@*
+
+If you use MySQL, this book provides you with:
+@itemize @bullet
+@item
+An introduction to MySQL and SQL.
+@item
+Coverage of MySQL's data types and how to use them.
+@item
+Thorough treatment of how to write client programs in C.
+@item
+A guide to using the Perl @code{DBI} and PHP APIs for developing
+command-line and Web-based applications.
+@item
+Tips on administrative issues such as user accounts, backup,
+crash recovery, and security.
+@item
+Help in choosing an ISP for MySQL access.
+@item
+A comprehensive reference for MySQL's data types, operators,
+functions, and SQL statements and utilities.
+@item
+Complete reference guides for MySQL's C API, the Perl @code{DBI} API,
+and PHP's MySQL-related functions.
+@end itemize
+@*
+
+@emph{MySQL & mSQL}
+@multitable @columnfractions .3 .7
+@item Available @tab @uref{http://service.bfast.com/bfast/click?bfmid=2181&sourceid=34233559&bfpid=1565924347&bfmtype=book} (Barnes and Noble)
+@item Publisher @tab O'Reilly
+@item Authors @tab Randy Jay Yarger, George Reese & Tim King
+@item Pub Date @tab 1st Edition July 1999
+@item ISBN @tab 1-56592-434-7, Order Number: 4347
+@item Pages @tab 506
+@item Price @tab $34.95
+@end multitable
+
+This book teaches you how to use MySQL and @code{mSQL}, two popular
+and robust database products that support key subsets of SQL on both Linux
+and Unix systems. Anyone who knows basic C, Java, Perl, or Python can
+write a program to interact with a database, either as a stand-alone
+application or through a Web page. This book takes you through the
+whole process, from installation and configuration to programming
+interfaces and basic administration. Includes plenty of tutorial
+material.
+@*
+
+@emph{Sams' Teach Yourself MySQL in 21 Days}
+@multitable @columnfractions .3 .7
+@item Available @tab @uref{http://service.bfast.com/bfast/click?bfmid=2181&sourceid=34233559&bfpid=0672319144&bfmtype=book} (Barnes and Noble)
+@item Publisher @tab Sams
+@item Authors @tab Mark Maslakowski and Tony Butcher
+@item Pub Date @tab June 2000
+@item ISBN @tab 0672319144
+@item Pages @tab 650
+@item Price @tab $39.99
+@end multitable
+
+Sams' @emph{Teach Yourself MySQL in 21 Days} is for intermediate Linux users
+who want to move into databases. A large share of the audience is Web
+developers who need a database to store large amounts of information that
+can be retrieved via the Web.
+
+Sams' @emph{Teach Yourself MySQL in 21 Days} is a practical, step-by-step
+tutorial. The reader will learn to design and employ this open source
+database technology into his or her website using practical, hands-on
+examples to follow.
+@*
+
+@emph{E-Commerce Solutions with MySQL}
+@multitable @columnfractions .3 .7
+@item Available @tab @uref{http://service.bfast.com/bfast/click?bfmid=2181&sourceid=34233559&bfpid=0761524452&bfmtype=book} (Barnes and Noble)
+@item Publisher @tab Prima Communications, Inc.
+@item Authors @tab N/A
+@item Pub Date @tab January 2000
+@item ISBN @tab 0761524452
+@item Pages @tab 500
+@item Price @tab $39.99
+@end multitable
+
+No description available.
+@*
+
+@emph{MySQL and PHP from Scratch}
+@multitable @columnfractions .3 .7
+@item Available @tab @uref{http://service.bfast.com/bfast/click?bfmid=2181&sourceid=34233559&bfpid=0789724405&bfmtype=book} (Barnes and Noble)
+@item Publisher @tab Que
+@item Authors @tab N/A
+@item Pub Date @tab September 2000
+@item ISBN @tab 0789724405
+@item Pages @tab 550
+@item Price @tab $34.99
+@end multitable
+
+This book puts together information on installing, setting up, and
+troubleshooting Apache, MySQL, PHP3, and IMP into one complete
+volume. You also learn how each piece is part of a whole by learning,
+step-by-step, how to create a web-based e-mail system. Learn to run
+the equivalent of Active Server Pages (ASP) using PHP3, set up an
+e-commerce site using a database and the Apache web server, and create
+a data entry system (such as sales, product quality tracking, customer
+preferences, etc) that no installation in the PC.
+@*
+
+@emph{Professional MySQL Programming}
+@multitable @columnfractions .3 .7
+@item Available @tab @uref{http://shop.barnesandnoble.com/bookSearch/isbnInquiry.asp?isbn=1861005164} (Barnes and Noble)
+@item Publisher @tab Wrox Press, Inc.
+@item Authors @tab N/A
+@item Pub Date @tab Late 2001
+@item ISBN @tab 1861005164
+@item Pages @tab 1000
+@item Price @tab $49.99
+@end multitable
+
+No description available.
+@*
+
+@emph{Professional Linux Programming}
+@multitable @columnfractions .3 .7
+@item Available @tab @uref{http://service.bfast.com/bfast/click?bfmid=2181&sourceid=34233559&bfpid=1861003013&bfmtype=book} (Barnes and Noble)
+@item Publisher @tab Wrox Press, Inc.
+@item Authors @tab N/A
+@item Pub Date @tab September 2000
+@item ISBN @tab 1861003013
+@item Pages @tab 1155
+@item Price @tab $47.99
+@end multitable
+
+In this follow-up to the best-selling @emph{Beginning Linux Programming},
+you will learn from the authors' real-world knowledge and experience of
+developing software for Linux; you'll be taken through the development
+of a sample 'DVD Store' application, with 'theme' chapters addressing
+different aspects of its implementation. Meanwhile, individual
+``take-a-break'' chapters cover important topics that go beyond the
+bounds of the central theme. All focus on the practical aspects of
+programming, showing how crucial it is to choose the right tools for
+the job, use them as they should be used, and get things right first
+time.
+@*
+
+@emph{PHP and MySQL Web Development}
+@multitable @columnfractions .3 .7
+@item Available @tab @uref{http://service.bfast.com/bfast/click?bfmid=2181&sourceid=34233559&bfpid=0672317842&bfmtype=book} (Barnes and Noble)
+@item Publisher @tab Sams
+@item Authors @tab Luke Welling, Laura Thomson
+@item Pub Date @tab March 2001
+@item ISBN @tab 0672317842
+@item Pages @tab 700
+@item Price @tab $49.99
+@end multitable
+
+@emph{PHP and MySQL Web Development} introduces you to the advantages
+of implementing both MySQL and PHP. These advantages are detailed
+through the provision of both statistics and several case studies. A
+practical web application is developed throughout the book, providing
+you with the tools necessary to implement a functional online
+database. Each function is developed separately, allowing you the
+choice to incorporate only those parts that you would like to
+implement. Programming concepts of the PHP language are highlighted,
+including functions which tie MySQL support into a PHP script and
+advanced topics regarding table manipulation.
+@*
+
+@strong{Books recommended by the MySQL Developers}
+
+@emph{SQL-99 Complete, Really}
+@multitable @columnfractions .3 .7
+@item Available @tab @uref{http://service.bfast.com/bfast/click?bfmid=2181&sourceid=34233559&bfpid=0879305681&bfmtype=book} (Barnes and Noble)
+@item Publisher @tab CMP Books
+@item Authors @tab Peter Gulutzan, Trudy Pelzer
+@item Pub Date @tab April 1999
+@item ISBN @tab 0879305681
+@item Pages @tab 1104
+@item Price @tab $55.96
+@end multitable
+
+This book contains complete descriptions of the new standards for
+syntax, data structures, and retrieval processes of SQL databases. As
+an example-based reference manual, it includes all of the CLI
+functions, information, schema tables, and status codes, as well as a
+working SQL database provided on the companion disk.
+@*
+
+@emph{C, A reference manual}
+@multitable @columnfractions .3 .7
+@item Available @tab @uref{http://service.bfast.com/bfast/click?bfmid=2181&sourceid=34233559&bfpid=0133262243&bfmtype=book} (Barnes and Noble)
+@item Publisher @tab Prentice Hall
+@item Authors @tab Samuel P. Harbison, Guy L. Steele
+@item Pub Date @tab September 1994
+@item ISBN @tab 0133262243
+@item Pages @tab 480
+@item Price @tab $35.99
+@end multitable
+
+A new and improved revision of the bestselling C language
+reference. This manual introduces the notion of "Clean C", writing C
+code that can be compiled as a C++ program, C programming style that
+emphasizes correctness, portability, maintainability, and
+incorporates the ISO C Amendment 1 (1994) which specifies new
+facilities for writing portable, international programs in C.
+@*
+
+@emph{C++ for Real Programmers}
+@multitable @columnfractions .3 .7
+@item Available @tab @uref{http://service.bfast.com/bfast/click?bfmid=2181&sourceid=34233559&bfpid=0120499428&bfmtype=book} (Barnes and Noble)
+@item Publisher @tab Academic Press, Incorporated
+@item Authors @tab Jeff Alger, Jim Keogh
+@item Pub Date @tab February 1998
+@item ISBN @tab 0120499428
+@item Pages @tab 388
+@item Price @tab $39.95
+@end multitable
+
+@emph{C++ For Real Programmers} bridges the gap between C++ as described
+in beginner and intermediate-level books and C++ as it is practiced by
+experts. Numerous valuable techniques are described, organised into
+three simple themes: indirection, class hierarchies, and memory
+management. It also provides in-depth coverage of template creation,
+exception handling, pointers and optimisation techniques. The focus of
+the book is on ANSI C++ and, as such, is compiler independent.
+
+@emph{C++ For Real Programmers} is a revision of
+@emph{Secrets of the C++ Masters} and includes a new appendix comparing C++
+with Java. The book comes with a 3.5" disk for Windows with source code.
+@*
+
+@emph{Algorithms in C}
+@multitable @columnfractions .3 .7
+@item Available @tab @uref{http://service.bfast.com/bfast/click?bfmid=2181&sourceid=34233559&bfpid=0201514257&bfmtype=book} (Barnes and Noble)
+@item Publisher @tab Addison Wesley Longman, Inc.
+@item Authors @tab Robert Sedgewick
+@item Pub Date @tab April 1990
+@item ISBN @tab 0201514257
+@item Pages @tab 648
+@item Price @tab $45.75
+@end multitable
+
+@emph{Algorithms in C} describes a variety of algorithms in a number of
+areas of interest, including: sorting, searching, string-processing, and
+geometric, graph and mathematical algorithms. The book emphasizes
+fundamental techniques, providing readers with the tools to confidently
+implement, run, and debug useful algorithms.
+@*
+
+@emph{Multithreaded Programming with Pthreads}
+@multitable @columnfractions .3 .7
+@item Available @tab @uref{http://service.bfast.com/bfast/click?bfmid=2181&sourceid=34233559&bfpid=0136807291&bfmtype=book} (Barnes and Noble)
+@item Publisher @tab Prentice Hall
+@item Authors @tab Bil Lewis, Daniel J. Berg
+@item Pub Date @tab October 1997
+@item ISBN @tab 0136807291
+@item Pages @tab 432
+@item Price @tab $34.95
+@end multitable
+
+Based on the best-selling @emph{Threads Primer},
+@emph{Multithreaded Programming with Pthreads} gives you a solid
+understanding of Posix threads: what they are, how they work, when to use
+them, and how to optimise them. It retains the clarity and humor of
+@emph{Threads Primer}, but includes expanded comparisons to Win32 and OS/2
+implementations. Code examples tested on all of the major UNIX platforms
+are featured along with detailed explanations of how and why they use threads.
+@*
+
+@emph{Programming the PERL DBI: Database Programming with PERL}
+@multitable @columnfractions .3 .7
+@item Available @tab @uref{http://service.bfast.com/bfast/click?bfmid=2181&sourceid=34233559&bfpid=1565926994&bfmtype=book} (Barnes and Noble)
+@item Publisher @tab O'Reilly & Associates, Incorporated
+@item Authors @tab Alligator Descartes, Tim Bunce
+@item Pub Date @tab February 2000
+@item ISBN @tab 1565926994
+@item Pages @tab 400
+@item Price @tab $27.96
+@end multitable
+
+@emph{Programming the Perl DBI} is coauthored by Alligator Descartes, one
+of the most active members of the DBI community, and by Tim Bunce, the
+inventor of DBI. For the uninitiated, the book explains the architecture
+of DBI and shows you how to write DBI-based programs. For the experienced
+DBI dabbler, this book explains DBI's nuances and the peculiarities of each
+individual DBD.
+
+The book includes:
+@itemize @bullet
+@item
+An introduction to DBI and its design.
+@item
+How to construct queries and bind parameters.
+@item
+Working with database, driver, and statement handles.
+@item
+Debugging techniques.
+@item
+Coverage of each existing DBD.
+@item
+A complete reference to DBI.
+@end itemize
+@*
+
+
+@node General-SQL, Useful Links, MySQL-Books, MySQL Information Sources
+@subsection General SQL Information and Tutorials
+
+The MySQL book portal is split into different sections to make it easy
+to locate books for various purposes.
+@uref{http://www.mysql.com/portal/books/html/}
+
+Tutorials can be found at:
+@uref{http://www.mysql.com/portal/development/html/development-61-1.html}
+
+@node Useful Links, , General-SQL, MySQL Information Sources
+@subsection Useful MySQL-related Links
+
+The MySQL development portal is the ultimate source of MySQL related
+links. @uref{http://www.mysql.com/portal/development/html/}
+
+Apart from the following links, you can find and download a lot of
+MySQL programs, tools and APIs in the Contrib directory
+(@uref{http://www.mysql.com/Downloads/Contrib/}).
+@cindex @code{Contrib} directory
+
+@cindex URLs to MySQL information
+@cindex MySQL related information URLs
+@subheading Tutorials and Manuals
+
+@table @asis
+@item @uref{http://michael.bacarella.com/research/mysqlmyths.html} (MySQL Myths Debunked)
+MySQL used in the real world.
+
+@item @uref{http://www.4t2.com/mysql/}
+Information about the German MySQL mailing list.
+
+@item @uref{http://www2.rent-a-database.de/mysql/}
+MySQL handbook in German.
+
+@item @uref{http://www.bitmover.com:8888/home/bk/mysql/}
+Web access to the MySQL BitKeeper repository.
+
+@item @uref{http://www.analysisandsolutions.com/code/mybasic.htm}
+Beginners MySQL Tutorial on how to install and set up
+MySQL on a Windows machine.
+
+@item @uref{http://www.devshed.com/Server_Side/MySQL/}
+A lot of MySQL tutorials.
+
+@item @uref{http://mysql.hitstar.com/}
+MySQL manual in Chinese.
+
+@item @uref{http://www.linuxplanet.com/linuxplanet/tutorials/1046/1/}
+Setting Up a MySQL-based website.
+
+@item @uref{http://www.hotwired.com/webmonkey/backend/tutorials/tutorial1.html}
+MySQL-Perl tutorial.
+
+@item @uref{http://www.iserver.com/support/contrib/perl5/modules.html}
+Installing new Perl modules that require locally installed modules.
+
+@item @uref{http://www.hotwired.com/webmonkey/databases/tutorials/tutorial4.html}
+PHP/MySQL Tutorial.
+
+@item @uref{http://www.useractive.com/}
+Hands on tutorial for MySQL.
+@end table
+
+@subheading MySQL Discussion Forums
+
+@table @asis
+@item @uref{http://www.weberdev.com/}
+Examples using MySQL; (check Top 20)
+
+@item @uref{http://futurerealm.com/forum/futureforum.htm}
+FutureForum Web Discussion Software.
+@end table
+
+@subheading Porting MySQL/Using MySQL on Different Systems
+
+@table @asis
+@item @uref{http://www.entropy.ch/software/macosx/mysql/}
+Binary of MySQL for Mac OS X Client. Includes information of how to
+build and use MySQL on Mac OS X.
+
+@item @uref{http://xclave.macnn.com/MySQL/}
+The Mac OS Xclave. Running MySQL on Mac OS X.
+
+@item @uref{http://www.prnet.de/RegEx/mysql.html}
+MySQL for Mac OS X Server.
+
+@item @uref{http://www.latencyzero.com/macosx/mysql.html}
+Building MySQL for Mac OS X.
+
+@item @uref{http://www.essencesw.com/Software/mysqllib.html}
+New Client libraries for the Mac OS Classic (Macintosh).
+
+@item @uref{http://www.lilback.com/macsql/}
+Client libraries for Mac OS Classic (Macintosh).
+
+@item @uref{http://sixk.maniasys.com/index_en.html}
+MySQL for Amiga
+@end table
+
+@subheading Perl-related Links
+
+@table @asis
+@item @uref{http://dbimysql.photoflux.com/}
+Perl DBI with MySQL FAQ.
+@end table
+
+@c FIX We should get longer descriptions for things in this category!
+@subheading Commercial Applications that Support MySQL
+
+@table @asis
+@item @uref{http://www.supportwizard.com/}
+SupportWizard; Interactive helpdesk on the Web. This product includes a
+licensed copy of MySQL.
+
+@item @uref{http://www.sonork.com/}
+Sonork, Instant Messenger that is not only Internet oriented. It's
+focused on private networks and on small to medium companies. Client
+is free, server is free for up to 5 seats.
+
+@item @uref{http://www.stweb.org/}
+StWeb - Stratos Web and Application server - An easy-to-use, cross
+platform, Internet/Intranet development and deployment system for
+development of web-enabled applications. The standard version of StWeb
+has a native interface to MySQL database.
+
+@item @uref{http://www.rightnowtech.com/}
+Right Now Web; Web automation for customer service.
+
+@item @uref{http://www.icaap.org/Bazaar/}
+Bazaar; Interactive Discussion Forums with Web interface.
+
+@cindex PhoneSweep
+@item @uref{http://www.phonesweep.com/}
+PhoneSweepT is the world's first commercial Telephone Scanner. Many break-ins
+in recent years have come not through the Internet, but through unauthorised
+dial-up modems. PhoneSweep lets you find these modems by repeatedly placing
+phone calls to every phone number that your organisation
+controls. PhoneSweep has a built-in expert system that can recognise
+more than 250 different kinds of remote-access programs, including
+Carbon Copy(TM), pcANYWHERE(TM), and Windows NT RAS. All information is stored
+in the SQL database. It then generates a comprehensive report detailing
+which services were discovered on which dial-up numbers in your organisation.
+@end table
+
+@subheading SQL Clients and Report Writers
+
+@table @asis
+@item @uref{http://www.urbanresearch.com/software/utils/urbsql/} (urSQL)
+SQL Editor and Query Utility. Custom syntax highlighting, editable
+results grid, exportable result-sets, basic MySQL admin functions,
+Etc.. For Windows.
+
+@item @uref{http://www.edatanew.com/} (MySQL Data Manager)
+MySQL Data Manager * is platform independent web client
+(written in perl) for MySQL server over TCP/IP.
+
+@item @uref{http://ksql.sourceforge.net/}
+KDE MySQL client.
+
+@item @uref{http://www.ecker-software.de/}
+A Windows GUI client by David Ecker.
+
+@item @uref{http://www.icaap.org/software/kiosk/}
+Kiosk; a MySQL client for database management. Written in Perl.
+Will be a part of Bazaar.
+
+@item @uref{http://www.casestudio.com/}
+Db design tool that supports MySQL 3.23.
+
+@item @uref{http://home.skif.net/~voland/zeos/eng/}
+Zeos - A client that supports MySQL, Interbase and PostgreSQL.
+
+@item @uref{http://www.geocities.com/SiliconValley/Ridge/4280/GenericReportWriter/grwhome.html}
+A free report writer in Java
+
+@item @uref{http://www.javaframework.de/}
+MySQLExport - Export of MySQL create statements and data in a lot of
+different formats (SQL, HTML, CVS, text, ZIP, GZIP...).
+
+@item @uref{http://dlabs.4t2.com/}
+M2D, a MySQL Administration client for Windows. M2D supports
+administration of MySQL databases, creation of new databases and
+tables, editing, and more.
+
+@item @uref{http://dlabs.4t2.com/}
+Dexter, a small server written in Perl which can be used as a proxy server for
+MySQL or as a database extender.
+
+@item @uref{http://www.scibit.com/Products/Software/Utils/Mascon.asp}
+Mascon is a powerful Win32 GUI for administering MySQL databases.
+
+@item @uref{http://www.rtlabs.com/}
+MacSQL Monitor. GUI for MySQL, ODBC, and JDBC databases for the Mac OS.
+@end table
+
+@subheading Distributions that Include MySQL
+
+@c FIX add the rest (at least a couple more Linuxes)
+
+@table @asis
+@item @uref{http://www.suse.com/}
+SuSE Linux (6.1 and above)
+
+@item @uref{http://www.redhat.com/}
+RedHat Linux (7.0 and above)
+
+@item @uref{http://distro.conectiva.com.br/}
+Conectiva Linux (4.0 and above)
+@end table
+
+@subheading Web Development Tools that Support MySQL
+
+@table @asis
+@item @uref{http://www.php.net/}
+PHP: A server-side HTML-embedded scripting language.
+
+@item @uref{http://www.midgard-project.org/}
+The Midgard Application Server; a powerful Web development environment
+based on MySQL and PHP.
+
+@cindex dbServ
+@item @uref{http://www.dbServ.de/}
+dbServ is an extension to a web server to integrate database output into
+your HTML code. You may use any HTML function in your output. Only the
+client will stop you. It works as standalone server or as Java servlet.
+
+@item @uref{http://www.chilisoft.com/}
+Platform independent ASP from Chili!Soft
+
+@item @uref{http://www.voicenet.com/~zellert/tjFM/}
+A JDBC driver for MySQL.
+
+@item @uref{http://www.wernhart.priv.at/php/}
+MySQL + PHP demos.
+
+@item @uref{http://www.dbwww.com/}
+ForwardSQL: HTML interface to manipulate MySQL databases.
+
+@item @uref{http://www.daa.com.au/~james/www-sql/}
+WWW-SQL: Display database information.
+
+@item @uref{http://www.heitml.com/}
+HeiTML: A server-side extension of HTML and a 4GL language at the same time.
+
+@item @uref{http://hawkeye.net/}
+Hawkeye Internet Server Suite.
+
+@item @uref{http://www.webgroove.com/}
+WebGroove Script: HTML compiler and server-side scripting language.
+
+@item @uref{http://www.ihtml.com/}
+A server-side website scripting language.
+
+@item @uref{ftp://ftp.igc.apc.org/pub/myodbc/README}
+How to use MySQL with ColdFusion on Solaris.
+
+@item @uref{http://calistra.com/MySQL/}
+Calistra's ODBC MySQL Administrator.
+
+@item @uref{http://phpclub.net/}
+PHPclub - Tips and tricks for PHP.
+
+@item @uref{http://www.widgetchuck.com/}
+The Widgetchuck; Website Tools and Gadgets
+
+@item @uref{http://www.adcycle.com/}
+AdCycle - advertising management software.
+
+@cindex pwPage
+@item @uref{http://sourceforge.net/projects/pwpage/}
+pwPage - provides an extremely fast and simple approach to the creation
+of database forms. That is, if a database table exists and an HTML page
+has been constructed using a few simple guidelines, pwPage can be
+immediately used for table data selections, insertions, updates, deletions
+and selectable table content reviewing.
+
+@item @uref{http://www.omnis-software.com/products/studio/studio.html}
+OMNIS Studio is a rapid application development (RAD) tool.
+@end table
+
+@subheading Database Design Tools with MySQL Support
+
+@table @asis
+@item @uref{http://www.mysql.com/documentation/dezign/}
+"DeZign for databases" is a database development tool that uses an
+entity relationship diagram (ERD).
+@end table
+
+@subheading Web Servers with MySQL Tools
+
+@table @asis
+@item @uref{ftp://ftp.kcilink.com/pub/}
+mod_auth_mysql, An Apache authentication module.
+
+@item @uref{http://www.roxen.com/}
+The Roxen Challenger Web server.
+@end table
+
+@subheading Extensions for Other Programs
+
+@table @asis
+@item @uref{http://www.seawood.org/msql_bind/}
+MySQL support for BIND (The Internet Domain Name Server).
+
+@item @uref{http://www.inet-interactive.com/sendmail/}
+MySQL support for Sendmail and Procmail.
+@end table
+
+@subheading Using MySQL with Other Programs
+
+@table @asis
+@item @uref{http://www.iserver.com/support/addonhelp/database/mysql/msaccess.html}
+Using MySQL with Access.
+
+@item @uref{http://www.iserver.com/support/contrib/perl5/modules.html}
+Installing new Perl modules that require locally installed modules.
+@end table
+
+@subheading ODBC-related Links
+
+@table @asis
+@item @uref{http://www.iodbc.org/}
+Popular iODBC Driver Manager (libiodbc) now available as Open Source.
+
+@item @uref{http://users.ids.net/~bjepson/freeODBC/}
+The FreeODBC Pages.
+
+@item @uref{http://genix.net/unixODBC/}
+The unixODBC Project goals are to develop and promote unixODBC to be the
+definitive standard for ODBC on the Linux platform. This is to include GUI
+support for KDE.
+
+@item @uref{http://www.sw-soft.com/products/BtrieveODBC/}
+A MySQL-based ODBC driver for Btrieve.
+@end table
+
+@subheading @strong{API}-related Links
+
+@table @asis
+@item @uref{http://www.jppp.com/}
+Partially implemented TDataset-compatible components for MySQL.
+
+@item @uref{http://www.riverstyx.net/qpopmysql/}
+qpopmysql - A patch to allow POP3 authentication from a MySQL
+database. There's also a link to Paul Khavkine's patch for Procmail to
+allow any MTA to deliver to users in a MySQL database.
+
+@item @uref{http://www.essencesw.com/Software/mysqllib.html}
+New Client libraries for the Mac OS Classic (Macintosh).
+
+@item @uref{http://www.lilback.com/macsql/}
+Client libraries for the Macintosh.
+
+@item @uref{http://www.essencesw.com/Plugins/mysqlplug.html}
+Plugin for REALbasic (for Macintosh)
+
+@item @uref{http://www.iis.ee.ethz.ch/~neeri/macintosh/gusi-qa.html}
+A library that emulates BSD sockets and pthreads on Macintosh. This can
+be used if you want to compile the MySQL client library on Mac.
+It could probably even be sued to port MySQL to Macintosh, but we
+don't know of anyone that has tried that.
+
+@cindex SCMDB
+@item @uref{http://www.dedecker.net/jessie/scmdb/}
+SCMDB - an add-on for SCM that ports the MySQL C library to scheme
+(SCM). With this library scheme developers can make connections to a
+MySQL database and use embedded SQL in their programs.
+@end table
+
+@subheading Other MySQL-related Links
+
+@table @asis
+@item @uref{http://www.satisoft.com/} (SAT)
+The Small Application Toolkit (SAT) is a collection of utilities
+intended to simplify the development of small, multi-user, GUI based
+applications in a (Microsoft -or- X) Windows Client / Unix Server
+environment.
+
+@item @uref{http://www.wix.com/mysql-hosting/}
+Registry of Web providers who support MySQL.
+
+@item @uref{http://www.softagency.co.jp/mysql/index.en.html}
+Links about using MySQL in Japan/Asia.
+
+@item @uref{http://abattoir.cc.ndsu.nodak.edu/~nem/mysql/udf/}
+MySQL UDF Registry.
+
+@item @uref{http://www.open.com.au/products.html}
+Commercial Web defect tracking system.
+
+@item @uref{http://www.stonekeep.com/pts/}
+PTS: Project Tracking System.
+
+@item @uref{http://tomato.nvgc.vt.edu/~hroberts/mot/}
+Job and software tracking system.
+
+@item @uref{http://www.cynergi.net/exportsql/}
+ExportSQL: A script to export data from Access95+.
+
+@item @uref{http://SAL.KachinaTech.COM/H/1/MYSQL.html}
+SAL (Scientific Applications on Linux) MySQL entry.
+
+@item @uref{http://www.infotech-nj.com/itech/index.shtml}
+A consulting company which mentions MySQL in the right company.
+
+@item @uref{http://www.pmpcs.com/}
+PMP Computer Solutions. Database developers using MySQL and
+@code{mSQL}.
+
+@item @uref{http://www.dedserius.com/y2kmatrix/}
+Y2K tester.
+@end table
+
+@subheading SQL and Database Interfaces
+
+@table @asis
+@item @uref{http://java.sun.com/products/jdbc/}
+The JDBC database access API.
+
+@item @uref{http://www.gagme.com/mysql/}
+Patch for @code{mSQL} Tcl.
+
+@item @uref{http://www.amsoft.ru/easysql/}
+EasySQL: An ODBC-like driver manager.
+
+@item @uref{http://www.lightlink.com/hessling/rexxsql.html}
+A REXX interface to SQL databases.
+
+@c @item @uref{http://www.mytcl.cx/}
+@c Tcl interface based on tcl-sql with many bugfixes.
+
+@item @uref{http://www.binevolve.com/~tdarugar/tcl-sql/}
+Tcl interface for MySQL.
+
+@item @uref{http://www.contrib.andrew.cmu.edu/~shadow/sql.html}
+SQL Reference Page with a lot of interesting links.
+
+@end table
+
+@subheading Examples of MySQL Use
+
+@table @asis
+@c Added 990601
+@c EMAIL: thuss@little6.com (Todd Huss)
+@item @uref{http://www.little6.com/about/linux/}
+Little6 Inc., An online contract and job finding site that is powered by
+MySQL, PHP3, and Linux.
+
+@c Added 990521
+@c EMAIL: info@worldrecords.com (Jim Rota)
+@item @uref{http://www.worldrecords.com/}
+World Records - A search engine for information about music that uses
+MySQL and PHP.
+
+@item @uref{http://www.webtechniques.com/archives/1998/01/note/}
+A Contact Database using MySQL and PHP.
+
+@item @uref{http://modems.rosenet.net/mysql/}
+Web based interface and Community Calendar with PHP.
+
+@item @uref{http://www.odbsoft.com/cook/sources.htm}
+Perl package to generate html from a SQL table structure and for generating
+SQL statements from an html form.
+
+@item @uref{http://www.gusnet.cx/proj/telsql/}
+Basic telephone database using @code{DBI}/@code{DBD}.
+
+@item @uref{http://tecfa.unige.ch/guides/java/staf2x/ex/jdbc/coffee-break/}
+JDBC examples by Daniel K. Schneider.
+
+@item @uref{http://www.ooc.com/}
+Object Oriented Concepts Inc; CORBA applications with examples in source.
+
+@c EMAIL: paul@sword.damocles.com (Paul Bannister)
+@item @uref{http://www.stopbit.com/}
+Stopbit - A technology news site using MySQL and PHP.
+
+@item @uref{http://www.penguinservices.com/scripts/}
+Online shopping cart system.
+
+@c Added 990928 from editor@city-gallery.com
+@cindex Old Photo Album
+@item @uref{http://www.city-gallery.com/album/}
+Old Photo Album - The album is a collaborative popular history of photography
+project that generates all pages from data stored in a MySQL
+database. Pages are dynamically generated through a php3 interface to the
+database content. Users contribute images and descriptions. Contributed
+images are stored on the web server to avoid storing them in the database
+as BLOBs. All other information is stored on the shared MySQL server.
+@end table
+
+@subheading General Database Links
+
+@table @asis
+@item @uref{http://black.hole-in-the.net/guy/webdb/}
+Homepage of the webdb-l (Web Databases) mailing list.
+
+@item @uref{http://www.symbolstone.org/technology/perl/DBI/}
+Perl @code{DBI}/@code{DBD} modules homepage.
+
+@item @uref{http://www.student.uni-koeln.de/cygwin/}
+Cygwin tools. Unix on top of Windows.
+
+@cindex Tek-Tips forums
+@cindex forums, Tek-Tips
+@item @uref{http://www.tek-tips.com/}
+Tek-Tips Forums are 800+ independent peer-to-peer non-commercial support
+forums for Computer Professionals. Features include automatic e-mail
+notification of responses, a links library, and member confidentiality
+guaranteed.
+
+@item @uref{http://www.public.asu.edu/~peterjn/btree/}
+B-Trees: Balanced Tree Data Structures.
+
+@item @uref{http://www.fit.qut.edu.au/~maire/baobab/lecture/sld001.htm}
+A lecture about B-Trees.
+@end table
+
+
diff --git a/Docs/section.Testimonials.texi b/Docs/section.Testimonials.texi
new file mode 100644
index 00000000000..e757a6a92d0
--- /dev/null
+++ b/Docs/section.Testimonials.texi
@@ -0,0 +1,31 @@
+@c FIX AGL 20011108 Extracted from manual.texi.
+@c Should only be on website with new submits by webform.
+
+
+@node MySQL Testimonials, Contrib, Users, Top
+@appendix MySQL Testimonials
+
+@cindex MySQL Testimonials
+
+The section 'MySQL Users' contains a lot of different links to
+MySQL users but doesn't provide that much information about how
+they are using MySQL. @xref{Users}. This section gives you an idea
+of how other MySQL users are using MySQL to solve their problems.
+
+Please note that all new stories are added on the MySQL website,
+@uref{http://www.mysql.com/}.
+Do let us know about @emph{your} success story too!
+
+@itemize @bullet
+@item
+@strong{Peter Zaitsev of Spylog.ru} writes:
+I think you might be interested in my database size. The whole database
+is currently on 15 servers and I think it's about 60.000 of tables
+containing about 5.000.000.000 of rows. My mostly loaded server
+currently holds about 10.000 of tables with 1.000.000.000 of rows in it.
+Hugest tables have about 50.000.000 of rows, and this value will raise
+as soon as I'll move to 2.4 kernel with large files. Currently I have to
+delete much of logs for large sites to hold table sizes in 2Gb.
+
+@item
+
diff --git a/Docs/section.Users.texi b/Docs/section.Users.texi
new file mode 100644
index 00000000000..3c8d219fa16
--- /dev/null
+++ b/Docs/section.Users.texi
@@ -0,0 +1,414 @@
+@c FIX AGL 20011108 Extracted from manual.texi.
+@c Should only be on website.
+
+
+@node Users, Contrib, Problems, Top
+@appendix MySQL Users
+
+@cindex users, of MySQL
+@cindex news sites
+
+This appendix lists users of MySQL that have given us permission
+to list them in our documentation. It is by far not a complete list, but
+should give you a general idea of who uses MySQL and what it can
+be used for.
+
+@appendixsec General News Sites
+
+@itemize @bullet
+
+@item @uref{http://www.yahoo.com/} (Yahoo!)
+
+@item @uref{http://slashdot.org/} (Slashdot: A pro-Linux/tech news and comment/discussion site)
+
+@item @uref{http://www.linux.com/} (All about Linux)
+
+@item @uref{http://www.linuxtoday.com/} (Linuxtoday)
+
+@item @uref{http://www.32bitsonline.com/} (32Bits Online: because there's
+more than one way to compute)
+
+@item @uref{http://www.freshmeat.net/} (Freshmeat: News about new versions of computer-related stuff)
+
+@end itemize
+
+@cindex search engines, web
+@cindex web search engines
+@appendixsec Web Search Engines
+
+@itemize @bullet
+
+@item @uref{http://www.aaa.com.au/} (AAA Matilda Web Search)
+@item @uref{http://www.whatsnu.com/} (What's New)
+@item @uref{http://www.aladin.de/} (Aladin)
+@item @uref{http://www.columbus-finder.de/} (Columbus Finder)
+@item @uref{http://www.spider.de/} (Spider)
+@item @uref{http://www.blitzsuche.de/} (Blitzsuche)
+@item @uref{http://www.indoseek.co.id/} (Indoseek Indonesia)
+@item @uref{http://www.yaboo.dk/} (Yaboo - Yet Another BOOkmarker)
+@item @uref{http://www.ozsearch.com.au/} (OzSearch Internet Guide)
+@item @uref{http://www.splatsearch.com/} (Splat! Search)
+@item @uref{http://osdls.library.arizona.edu/} (The Open Source Digital Library System Project)
+@end itemize
+
+@appendixsec Information Search Engines Specialising in a Particular Area
+
+@itemize @bullet
+
+@item @uref{http://www.spylog.ru/} (SpyLOG ; A very popular Web counter site)
+
+@item @uref{http://www.tucows.com/} (TuCows Network; Free Software archive)
+
+@item @uref{http://www.jobvertise.com/} (Jobvertise: Post and search for jobs)
+
+@item @uref{http://www.musicdatabase.com/} (The Music Database)
+
+@item @uref{http://www.soccersearch.com/} (Football -Soccer- search page)
+
+@item @uref{http://www.headrush.net/takedown} (TAKEDOWN - wrestling)
+
+@item @uref{http://www.lyrics.net/} (The International Lyrics Network)
+
+@item @uref{http://TheMatrix.com/~matrix/band_search.phtml} (Musicians looking for other musicians; free service)
+
+@item @uref{http://www.addall.com/AddBooks/Stores.html} (AddALL books searching and price comparison)
+
+@item @uref{http://www.herbaria.harvard.edu/Data/Gray/gray.html} (Harvard's Gray Herbarium Index of Plant Names)
+
+@item @uref{http://www.game-developer.com/} (The Game Development Search Engine)
+
+@item @uref{http://www.theinnkeeper.com/} (The Innkeeper Vacation Guides)
+
+@item @uref{http://www.macgamedatabase.com/} (The Mac Game Database uses PHP and MySQL)
+@c From: Marc Antony Vose <suzerain@suzerain.com>
+
+@item @uref{http://www.csse.monash.edu.au/publications/} (Research
+Publications at Monash University in Australia)
+
+@item @uref{http://www.ipielle.emr.it/bts/}
+(Occupational Health & Safety Website database; a project for the ECC)
+@c c.presutti@ipielle.emr.it
+
+@item @uref{http://data.mch.mcgill.ca/} (Bioinformatics databases at the
+Montreal Children's Hospital using MySQL)
+@c saeed@www.debelle.mcgill.ca
+@end itemize
+
+@cindex online magazines
+@cindex magazines, online
+@appendixsec Online Magazines
+
+@itemize @bullet
+@item @uref{http://www.spoiler.com/} (Spoiler Webzine)
+An online magazine featuring music, literature, arts, and design content.
+@item @uref{http://www.linux-magazin.de/newsflash/} (Daily news about Linux in German language)
+@item @uref{http://www.betazine.com/} (Betazine - The Ultimate Online Beta Tester's Magazine)
+@item @uref{http://www.currents.net/ccinfo/aboutcc.html} (Computer Currents Magazine)
+@end itemize
+
+@cindex websites
+@appendixsec Websites that Use MySQL as a Backend
+
+@itemize @bullet
+
+@item @uref{http://liftoff.msfc.nasa.gov/} (NASA)
+@item @uref{http://kids.msfc.nasa.gov/} (NASA KIDS)
+@item @uref{http://science.nasa.gov/} (Sience@@NASA)
+
+@item @uref{http://www.handy.de/} (handy.de)
+
+@item @uref{http://lindev.jmc.tju.edu/qwor/} (Qt Widget and Object Repository)
+
+@item @uref{http://www.samba-choro.com.br/} (Brazilian samba site; in Portuguese)
+
+@item @uref{http://pgss.iss.uw.edu.pl/en_index.ISS} (Polish General Social Survey)
+
+@item @uref{http://www.expo2000.com/} Expo2000 - world-wide distribution of
+tickets for this event is implemented using MySQL and Tcl/Tk. More than
+5000 travel agencies all over the world have access to it.
+
+@item @uref{http://www.freevote.com/} FreeVote.com is a free voting
+service with millions of users.
+
+@item @uref{http://f1.tauzero.se/} (Forza Motorsport)
+
+@item @uref{http://www.dreamhost.com/} (DreamHost Web Hosting)
+
+@end itemize
+
+@cindex services
+@appendixsec Domain/Internet/Web and Related Services
+
+@itemize @bullet
+
+@item @uref{http://www.wix.com/mysql-hosting/} (Registry of Web providers that
+support MySQL)
+
+@item @uref{http://www.yi.org/} (Dynamic DNS Services)
+
+@item @uref{http://www.dynodns.net/} (Dynamic domain name service)
+
+@item @uref{http://www.ods.org/} (Open DNS Project; free dynamic DNS service)
+
+@c @item @uref{http://dynodns.net/} (Free dynamic DNS implementation)
+@c EMAIL: A Moore <amoore@mooresystems.com>
+
+@item @uref{http://www.hn.org/} (Hammernode; Public DNS Servers)
+
+@item @uref{http://www.fdns.net/} (Free 3rd level domains)
+
+@item @uref{http://worldcommunity.com/} (Online Database)
+
+@item @uref{http://www.bigbiz.com/} (BigBiz Internet Services)
+
+@item @uref{http://virt.circle.net/} (The Virt Gazette)
+
+@item @uref{http://www.california.com/} (Global InfoNet Inc)
+
+@item @uref{http://www.webhosters.com/} (WebHosters - A Guide to WWW Providers)
+
+@item @uref{http://online.dn.ru/} (Internet information server)
+
+@item @uref{http://www.worldnetla.net/} (WorldNet Communications - An Internet Services Provider)
+
+@item @uref{http://www.netizen.com.au/} (Netizen: Australian-based Web consultancy)
+
+@item @uref{http://www.trainingpages.co.uk/} (Search site for training courses in the UK)
+
+@item @uref{http://chat.nitco.com/} (Gannon Chat; GPL. Written in Perl and Javascript)
+
+@item @uref{http://www.addurls.com/} (A general links directory)
+
+@item @uref{http://www.bookmarktracker.com/} (A Web-based bookmark management service)
+
+@item @uref{http://www.cdrom.com/} (Walnut Creek CDROM)
+
+@item @uref{http://www.wwwthreads.org/} (WWWThreads; Interactive discussion Forums)
+
+@item @uref{http://pvmon.portici.enea.it/Meteo/} (In Italian; Storage data from meteo station)
+
+@item @uref{http://www.buysell.net/} (Online "Person To Person" Auction)
+
+@item @uref{http://tips.pair.com/} (Tips on Web development)
+
+@item @uref{http://www.mailfriends.com/} (Mailfriends.com is a FREE service for
+everybody who wants to find friends over the internet)
+
+@item @uref{http://www.uninova.com/cgi-bin/wctelnets?list} (Web Page Telnet BBS List)
+
+@item @uref{http://www.uninova.com/cnc.html} (UniNova Digital Postcards)
+
+@c @item @uref{http://cabinboy.powersurfr.com/} (An Internet RFC search engine)
+
+@item @uref{http://www.dslreports.com/} (DSL-provider search with reviews)
+Made with MySQL and Modperl, all pages are generated dynamically out of
+the MySQL database
+@end itemize
+
+@cindex PHP, websites
+@appendixsec Websites that Use @code{PHP} and MySQL
+
+@itemize @bullet
+@c @item @uref{http://www.wh200th.com/} (White House 200th Anniversary site)
+
+@item @uref{http://support.jgaa.com/} (Jgaa's Internet - Official Support Site)
+
+@item @uref{http://io.incluso.com/} (Ionline - online publication) MySQL,
+PHP, Java, Web programming, DB development
+
+@item @uref{http://www.baboo.com/} (BaBoo - Browse and Bookmark. Free Web-based bookmark manager and Calendar)
+
+@item @uref{http://www.courses.pjc.cc.fl.us/Schedule/}
+(Course Schedule System at Pensacola Junior College)
+
+@item @uref{http://www.fccj.org/} (Florida Community College at Jacksonville)
+
+@item @uref{http://www.32bit.com/} (32bit.com; An extensive shareware / freeware archive)
+
+@item @uref{http://www.jokes2000.com/} (Jokes 2000)
+@c Added 990604; EMAIL: ah@dybdahl.dk
+
+@item @uref{http://www.burken.nu/}
+Burken is a webhotel that provides scripts, among other things,
+for remote users, like counters, guestbooks etc.
+@c Added 990608; EMAIL: spacedmp@SpaceDump.Burken.NU (Anders Olausson)
+
+@item @uref{http://tips.pair.com/}
+Contains tips on html, javascript, 2d/3d graphics, and PHP3/MySQL.
+All pages are generated from a database.
+@c Added 990614; EMAIL: downey@image.dk (Rune Madsen)
+
+@item @uref{http://www.softwarezrus.com/}
+Ecommerce site that is selling computers.
+@end itemize
+
+@cindex consultants, list of
+@appendixsec MySQL Consultants
+
+@itemize @bullet
+
+@item @uref{http://www.ayni.com/} (Ayni AG)
+
+@item @uref{http://worldcommunity.com/} (Online Database)
+
+@item @uref{http://www2.dataguard.no/} (DataGuard; Uses MySQL and PHP)
+
+@item @uref{http://wwits.net/programs/mysql.phtml} (WWITS; uses MySQL and PHP)
+
+@item @uref{http://www.worldcommunity.com/} (WCN - The World Community Network)
+
+@item @uref{http://www.chipcastle.com/} (Chip Castle Dot Com Inc)
+@c Added 990603 EMAIL: chip@chipcastle.com (Chip Castle)
+
+@item @uref{http://www.cyber.com.au/} (Cybersource Pty. Ltd)
+
+@item @uref{http://www.spring.de/} (Spring infotainment gmbh & co. kg)
+@c added 990905 "Oliver Pischke" <opischke@spring.de>
+
+@item @uref{http://www.wamdesign.com/} (Wam Design develops websites using MySQL)
+@c Added 990905; max@wamdesign.com
+
+@item @uref{http://www.berkeleyconsultants.com/} (Berkeley Consultants Group)
+
+@item @uref{http://www.jammconsulting.com/} (JAMM Consulting Inc)
+
+@end itemize
+
+@c Commented out by Arjen 011018, section is empty!
+@c appendixsec Programming
+
+@cindex web pages, miscellaneous
+@appendixsec Uncategorised Pages
+
+@itemize @bullet
+
+@item @uref{http://www.feature-showcase.com/htmls/demo_mysql.sql} (AZC.COM's Feature Showcase)
+
+@item @uref{http://www.teach.org.uk/subjects/trainingcourse/g.html} (Course Search)
+
+@item @uref{http://www.northerbys.com/} (Northerbys Online Auctions)
+
+@item @uref{http://www.schiphol.nl/flights/home.htm} (Amsterdam Airport Schiphol)
+
+@item @uref{http://TheMatrix.com/seventhsin/query.phtml} (CD database)
+
+@item @uref{http://TheMatrix.com/~flmm/GEAR.html} (Used Audio Gear Database)
+
+@item @uref{http://www.kiss.de/musik-mueller/} (Musical note-sheets)
+
+@item @uref{http://www.bagism.com/} (Bagism; A John Lennon fan page)
+
+@item @uref{http://www.selftaught.com/} (US Folk art broker)
+
+@item @uref{http://organizer.net/} (Mail reading on the Web)
+
+@item @uref{http://www.mypage.org/} (Free home pages on www.somecoolname.mypage.org)
+
+@item @uref{http://www.schulweb.de/} (Der Server f@"ur Schulen im Web - in German)
+
+@item @uref{http://www.ald.net/} (Auldhaefen Online Services)
+
+@item @uref{http://www.cary.net/} (CaryNET Information Center)
+
+@item @uref{http://www.dataden.com/} (Dataden Computer Systems)
+
+@item @uref{http://andree.grm.se/} (Andr@'emuseet; in Swedish)
+
+@item @uref{http://www.him.net/} (HOMESITE Internet Marketing)
+
+@item @uref{http://www.jade-v.com/techinfo.html} (Jade-V Network Services)
+
+@item @uref{http://ww2010.atmos.uiuc.edu/(Gl)/abt/aknw/tech.rxml}
+Weather World 2010 Technical Credits
+
+@item @uref{http://gimp.foebud.org/registry/doc/}
+About The Gimp plugin registry
+
+@item @uref{http://www.fast-inc.com/Products/Archiver/database.html}
+Java tool; archiver technical detail (Slightly optimistic about MySQL
+ANSI-92 compliance)
+
+@item @uref{http://www.gamesdomain.com/cheats/usrcheat.phtml} (Games Domain Cheats Database)
+
+@item @uref{http://www.kcilink.com/poweredby/} (The "Powered By" Page; Kcilink)
+
+@item @uref{http://www.netcasting.net/index.whtml} (Netcasting)
+
+@item @uref{http://homepages.tig.com.au/~mjj/nbltips} (NBL: Australian National Basketball League; tipping)
+
+@item @uref{http://www.cgishop.com/} (CGI shop)
+
+@item @uref{http://www.whirlycott.com/} (Whirlycott: Website Design)
+
+@item @uref{http://www.mtp.dk/} (Museum Tusculanum Press)
+
+@item @uref{http://csdgi.historie.ku.dk/biblio/} (Centro Siciliano di Documentazione)
+
+@item @uref{http://caribou.dyn.ml.org:8000/} (Quake statistics database)
+
+@item @uref{http://www.astroforum.ch/} (Astroforum: Astrologie and related things; in German)
+
+@item @uref{http://www.opendebate.com/} (OpenDebate - Interactive Polls & Open Discussion)
+
+@item @uref{http://vermeer.organik.uni-erlangen.de/dissertationen/} (Online chemical dissertation server)
+
+@item @uref{http://www.freschinfo.com/} (FreSch! The Free Scholarship Search Service)
+
+@item @uref{http://www.nada.kth.se/~staffanu/pinball/} (Stockholm Pinball Locator)
+
+@item @uref{http://www.hek.com/} (HEK - a construction company)
+
+@item @uref{http://www.ebi.nl/} (Elsevier Business Information)
+
+@item @uref{http://vaccination.medicallink.se/} (Medical Links; using ColdFusion and MySQL)
+
+@item @uref{http://www.joblink-usa.com/} (Search for jobs & people at JobLink-USA)
+
+@item @uref{http://www.skydive.net/competfs/} (Competition Formation Skydiving)
+
+@item @uref{http://www.galaxy-net.net/} (Galaxy-NET Telecommunications; E-commerce and internal accounting)
+
+@item @uref{http://www.borsen.dk/} (Denmark's leading business daily newspaper B@o{}rsen)
+
+@item @uref{http://tmmm.simplenet.com/indb/} (The Internet NES Database)
+
+@item @uref{http://www.russia.cz/} (Travel agency in Prague in 3 languages)
+
+@item @uref{http://www.linkstation.de/} (Linkstation)
+
+@item @uref{http://www.peoplestaff.com/} (Searchable online database at Peoplestaff)
+
+@item @uref{http://www.dreamhorse.com/} (A searchable database system for horse classified ads)
+
+@item @uref{http://pootpoot.com/} (The Poot site)
+
+@item @uref{http://grateful.net/hw_html/} ("Playin' in the LAN"; a network monitoring suite)
+
+@c Update from Christopher Milton <cmilton@bwn.net> 1999-12-21
+@item @uref{http://www.usapa.army.mil/} (U.S. Army Publishing Agency)
+
+@item @uref{http://www.nekretnine.co.yu/} (Realestate handling in Yugoslavia)
+
+@item @uref{http://demo.cpsoft.com/pims/devFAQ.html} (PIMS; a Patient Information Management System)
+
+@item @uref{http://cpsoft.com/} (Pilkington Software Inc)
+
+@item @uref{http://www.no-quarter.org/} (A Vietnam Veteran's Memorial - The Wall - database)
+
+@item @uref{http://www.gamers-union.com/} (Gamer's Union specializes in auctions of used & out-of-print gaming material)
+
+@item @uref{http://www.montereyhigh.com/office/dbul.php3} (A daily bulletin at Monterey High school)
+
+@item @uref{http://www.myEastside.com/} (Community-owned site serving Lake
+Washington's Eastside residents and businesses)
+
+@item @uref{http://bowling-france.net/} (French bowling site)
+@end itemize
+
+Send any additions to this list to @email{webmaster@@mysql.com}.
+
+@page
+
+
+
+
diff --git a/Docs/template.texi b/Docs/template.texi
new file mode 100644
index 00000000000..36633da6269
--- /dev/null
+++ b/Docs/template.texi
@@ -0,0 +1,522 @@
+\input texinfo @c -*-texinfo-*-
+@c Copyright 1995-2002 MySQL AB
+@c
+@c This manual is NOT distributed under a GPL style license.
+@c Use of the manual is subject to the following terms:
+@c - Conversion to other formats is allowed, but the actual
+@c content may not be altered or edited in any way.
+@c - You may create a printed copy for your own personal use.
+@c - For all other uses, such as selling printed copies or
+@c using (parts of) the manual in another publication,
+@c prior written agreement from MySQL AB is required.
+@c
+@c Please e-mail docs@mysql.com for more information or if
+@c you are interested in doing a translation.
+@c
+@c *********************************************************
+@c
+@c %**start of header
+
+@setfilename mysql.info
+
+@c We want the types in the same index
+@syncodeindex tp fn
+
+@c Get version information. This file is generated by the Makefile!!
+@include include.texi
+
+@ifclear tex-debug
+@c This removes the black squares in the right margin
+@finalout
+@end ifclear
+
+@c Set background for HTML
+@set _body_tags BGCOLOR=silver TEXT=#000000 LINK=#101090 VLINK=#7030B0
+@c Set some style elements for the manual in HTML form. 'suggested'
+@c natural language colors: aqua, black, blue, fuchsia, gray, green,
+@c lime, maroon, navy, olive, purple, red, silver, teal, white, and
+@c yellow. From Steeve Buehler <ahr@YogElements.com>
+@set _extra_head <style> code {color:purple} tt {color:green} samp {color:navy} pre {color:maroon} </style>
+
+@settitle MySQL Reference Manual for version @value{mysql_version}.
+
+@c We want single-sided heading format, with chapters on new pages. To
+@c get double-sided format change 'on' below to 'odd'
+@setchapternewpage on
+
+@paragraphindent 0
+
+@c %**end of header
+
+@ifinfo
+@format
+START-INFO-DIR-ENTRY
+* mysql: (mysql). MySQL documentation.
+END-INFO-DIR-ENTRY
+@end format
+@end ifinfo
+
+@titlepage
+@sp 10
+@center @titlefont{MySQL Reference Manual}
+@sp 10
+@center Copyright @copyright{} 1995-2002 MySQL AB
+@c blank page after title page makes page 1 be a page front.
+@c also makes the back of the title page blank.
+@page
+@end titlepage
+
+@c Short contents, blank page, long contents.
+@c until i can figure out the blank page, no short contents.
+@c @shortcontents
+@c @page
+@c @page
+@contents
+
+@c This should be added. The HTML conversion also needs a MySQL version
+@c number somewhere.
+
+@iftex
+@c change this to double if you want formatting for double-sided
+@c printing
+@headings single
+
+@oddheading @thischapter @| @| @thispage
+@evenheading @thispage @| @| MySQL Technical Reference for Version @value{mysql_version}
+
+@end iftex
+
+
+@node Top, Introduction, (dir), (dir)
+
+@ifinfo
+This is a manual for the MySQL Database System.
+This version is about the @value{mysql_version} version of MySQL Server.
+You can find a specific manual for any older version of MySQL Server
+in the binary or source distribution for that version.
+@end ifinfo
+
+@node Introduction, Installing, Top, Top
+@chapter General Information About MySQL
+
+
+
+
+
+@node GPL license, LGPL license, Regexp, Top
+@appendix GNU GENERAL PUBLIC LICENSE
+
+@cindex GPL, General Public License
+@cindex GPL, GNU General Public License
+
+@center Version 2, June 1991
+
+@display
+Copyright @copyright{} 1989, 1991 Free Software Foundation, Inc.
+59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+
+Everyone is permitted to copy and distribute verbatim copies
+of this license document, but changing it is not allowed.
+@end display
+
+@appendixsec Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software---to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+@iftex
+@appendixsec TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+@end iftex
+@ifinfo
+@center GNU GENERAL PUBLIC LICENSE
+@center TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+@end ifinfo
+
+@enumerate 0
+@item
+This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The ``Program'', below,
+refers to any such program or work, and a ``work based on the Program''
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term ``modification''.) Each licensee is addressed as ``you''.
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+@item
+You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+@item
+You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+@enumerate a
+@item
+You must cause the modified files to carry prominent notices
+stating that you changed the files and the date of any change.
+
+@item
+You must cause any work that you distribute or publish, that in
+whole or in part contains or is derived from the Program or any
+part thereof, to be licensed as a whole at no charge to all third
+parties under the terms of this License.
+
+@item
+If the modified program normally reads commands interactively
+when run, you must cause it, when started running for such
+interactive use in the most ordinary way, to print or display an
+announcement including an appropriate copyright notice and a
+notice that there is no warranty (or else, saying that you provide
+a warranty) and that users may redistribute the program under
+these conditions, and telling the user how to view a copy of this
+License. (Exception: if the Program itself is interactive but
+does not normally print such an announcement, your work based on
+the Program is not required to print an announcement.)
+@end enumerate
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+@item
+You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+@enumerate a
+@item
+Accompany it with the complete corresponding machine-readable
+source code, which must be distributed under the terms of Sections
+1 and 2 above on a medium customarily used for software interchange; or,
+
+@item
+Accompany it with a written offer, valid for at least three
+years, to give any third party, for a charge no more than your
+cost of physically performing source distribution, a complete
+machine-readable copy of the corresponding source code, to be
+distributed under the terms of Sections 1 and 2 above on a medium
+customarily used for software interchange; or,
+
+@item
+Accompany it with the information you received as to the offer
+to distribute corresponding source code. (This alternative is
+allowed only for noncommercial distribution and only if you
+received the program in object code or executable form with such
+an offer, in accord with Subsection b above.)
+@end enumerate
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+@item
+You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+@item
+You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+@item
+Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+@item
+If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+@item
+If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+@item
+The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and ``any
+later version'', you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+@item
+If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+@iftex
+@heading NO WARRANTY
+@end iftex
+@ifinfo
+@center NO WARRANTY
+@end ifinfo
+
+@item
+BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM ``AS IS'' WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+@item
+IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+@end enumerate
+
+@iftex
+@heading END OF TERMS AND CONDITIONS
+@end iftex
+@ifinfo
+@center END OF TERMS AND CONDITIONS
+@end ifinfo
+
+@page
+@appendixsec How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the ``copyright'' line and a pointer to where the full notice is found.
+
+@smallexample
+@var{one line to give the program's name and a brief idea of what it does.}
+Copyright (C) @var{yyyy} @var{name of author}
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+@end smallexample
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+@smallexample
+Gnomovision version 69, Copyright (C) 19@var{yy} @var{name of author}
+Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+This is free software, and you are welcome to redistribute it
+under certain conditions; type `show c' for details.
+@end smallexample
+
+The hypothetical commands @samp{show w} and @samp{show c} should show
+the appropriate parts of the General Public License. Of course, the
+commands you use may be called something other than @samp{show w} and
+@samp{show c}; they could even be mouse-clicks or menu items---whatever
+suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a ``copyright disclaimer'' for the program, if
+necessary. Here is a sample; alter the names:
+
+@example
+Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+`Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+@var{signature of Ty Coon}, 1 April 1989
+Ty Coon, President of Vice
+@end example
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
+
+
+
+@node Function Index, Concept Index, LGPL license, Top
+@unnumbered SQL command, type and function index
+
+@printindex fn
+
+@page
+
+
+@node Concept Index, , Function Index, Top
+@unnumbered Concept Index
+
+@printindex cp
+
+
+
+
+
+@bye
+
diff --git a/Docs/world.sql b/Docs/world.sql
new file mode 100644
index 00000000000..7ddd3787ec6
--- /dev/null
+++ b/Docs/world.sql
@@ -0,0 +1,5386 @@
+-- MySQL dump 8.19
+--
+-- Host: localhost Database: world
+---------------------------------------------------------
+-- Server version 4.0.1-alpha-Max
+
+--
+-- Table structure for table 'City'
+--
+
+CREATE TABLE City (
+ ID int(11) NOT NULL auto_increment,
+ name char(35) NOT NULL default '',
+ Country char(3) NOT NULL default '',
+ District char(20) NOT NULL default '',
+ Population int(11) NOT NULL default '0',
+ PRIMARY KEY (ID)
+) TYPE=MyISAM;
+
+/*!40000 ALTER TABLE City DISABLE KEYS */;
+
+--
+-- Dumping data for table 'City'
+--
+
+
+INSERT INTO City VALUES (1,'Kabul','AFG','Kabol',1780000);
+INSERT INTO City VALUES (2,'Qandahar','AFG','Qandahar',237500);
+INSERT INTO City VALUES (3,'Herat','AFG','Herat',186800);
+INSERT INTO City VALUES (4,'Mazar-e-Sharif','AFG','Balkh',127800);
+INSERT INTO City VALUES (5,'Amsterdam','NLD','Noord-Holland',731200);
+INSERT INTO City VALUES (6,'Rotterdam','NLD','Zuid-Holland',593321);
+INSERT INTO City VALUES (7,'Haag','NLD','Zuid-Holland',440900);
+INSERT INTO City VALUES (8,'Utrecht','NLD','Utrecht',234323);
+INSERT INTO City VALUES (9,'Eindhoven','NLD','Noord-Brabant',201843);
+INSERT INTO City VALUES (10,'Tilburg','NLD','Noord-Brabant',193238);
+INSERT INTO City VALUES (11,'Groningen','NLD','Groningen',172701);
+INSERT INTO City VALUES (12,'Breda','NLD','Noord-Brabant',160398);
+INSERT INTO City VALUES (13,'Apeldoorn','NLD','Gelderland',153491);
+INSERT INTO City VALUES (14,'Nijmegen','NLD','Gelderland',152463);
+INSERT INTO City VALUES (15,'Enschede','NLD','Overijssel',149544);
+INSERT INTO City VALUES (16,'Haarlem','NLD','Noord-Holland',148772);
+INSERT INTO City VALUES (17,'Almere','NLD','Flevoland',142465);
+INSERT INTO City VALUES (18,'Arnhem','NLD','Gelderland',138020);
+INSERT INTO City VALUES (19,'Zaanstad','NLD','Noord-Holland',135621);
+INSERT INTO City VALUES (20,'´s-Hertogenbosch','NLD','Noord-Brabant',129170);
+INSERT INTO City VALUES (21,'Amersfoort','NLD','Utrecht',126270);
+INSERT INTO City VALUES (22,'Maastricht','NLD','Limburg',122087);
+INSERT INTO City VALUES (23,'Dordrecht','NLD','Zuid-Holland',119811);
+INSERT INTO City VALUES (24,'Leiden','NLD','Zuid-Holland',117196);
+INSERT INTO City VALUES (25,'Haarlemmermeer','NLD','Noord-Holland',110722);
+INSERT INTO City VALUES (26,'Zoetermeer','NLD','Zuid-Holland',110214);
+INSERT INTO City VALUES (27,'Emmen','NLD','Drenthe',105853);
+INSERT INTO City VALUES (28,'Zwolle','NLD','Overijssel',105819);
+INSERT INTO City VALUES (29,'Ede','NLD','Gelderland',101574);
+INSERT INTO City VALUES (30,'Delft','NLD','Zuid-Holland',95268);
+INSERT INTO City VALUES (31,'Heerlen','NLD','Limburg',95052);
+INSERT INTO City VALUES (32,'Alkmaar','NLD','Noord-Holland',92713);
+INSERT INTO City VALUES (33,'Willemstad','ANT','Curaçao',2345);
+INSERT INTO City VALUES (34,'Tirana','ALB','Tirana',270000);
+INSERT INTO City VALUES (35,'Alger','DZA','Alger',2168000);
+INSERT INTO City VALUES (36,'Oran','DZA','Oran',609823);
+INSERT INTO City VALUES (37,'Constantine','DZA','Constantine',443727);
+INSERT INTO City VALUES (38,'Annaba','DZA','Annaba',222518);
+INSERT INTO City VALUES (39,'Batna','DZA','Batna',183377);
+INSERT INTO City VALUES (40,'Sétif','DZA','Sétif',179055);
+INSERT INTO City VALUES (41,'Sidi Bel Abbès','DZA','Sidi Bel Abbès',153106);
+INSERT INTO City VALUES (42,'Skikda','DZA','Skikda',128747);
+INSERT INTO City VALUES (43,'Biskra','DZA','Biskra',128281);
+INSERT INTO City VALUES (44,'Blida (el-Boulaida)','DZA','Blida',127284);
+INSERT INTO City VALUES (45,'Béjaïa','DZA','Béjaïa',117162);
+INSERT INTO City VALUES (46,'Mostaganem','DZA','Mostaganem',115212);
+INSERT INTO City VALUES (47,'Tébessa','DZA','Tébessa',112007);
+INSERT INTO City VALUES (48,'Tlemcen (Tilimsen)','DZA','Tlemcen',110242);
+INSERT INTO City VALUES (49,'Béchar','DZA','Béchar',107311);
+INSERT INTO City VALUES (50,'Tiaret','DZA','Tiaret',100118);
+INSERT INTO City VALUES (51,'Ech-Chleff (el-Asnam)','DZA','Chlef',96794);
+INSERT INTO City VALUES (52,'Ghardaïa','DZA','Ghardaïa',89415);
+INSERT INTO City VALUES (53,'Tafuna','ASM','Tutuila',5200);
+INSERT INTO City VALUES (54,'Fagatogo','ASM','Tutuila',2323);
+INSERT INTO City VALUES (55,'Andorra la Vella','AND','Andorra la Vella',21189);
+INSERT INTO City VALUES (56,'Luanda','AGO','Luanda',2022000);
+INSERT INTO City VALUES (57,'Huambo','AGO','Huambo',163100);
+INSERT INTO City VALUES (58,'Lobito','AGO','Benguela',130000);
+INSERT INTO City VALUES (59,'Benguela','AGO','Benguela',128300);
+INSERT INTO City VALUES (60,'Namibe','AGO','Namibe',118200);
+INSERT INTO City VALUES (61,'South Hill','AIA','–',961);
+INSERT INTO City VALUES (62,'The Valley','AIA','–',595);
+INSERT INTO City VALUES (63,'Saint John´s','ATG','St John',24000);
+INSERT INTO City VALUES (64,'Dubai','ARE','Dubai',669181);
+INSERT INTO City VALUES (65,'Abu Dhabi','ARE','Abu Dhabi',398695);
+INSERT INTO City VALUES (66,'Sharja','ARE','Sharja',320095);
+INSERT INTO City VALUES (67,'al-Ayn','ARE','Abu Dhabi',225970);
+INSERT INTO City VALUES (68,'Ajman','ARE','Ajman',114395);
+INSERT INTO City VALUES (69,'Buenos Aires','ARG','Distrito Federal',2982146);
+INSERT INTO City VALUES (70,'La Matanza','ARG','Buenos Aires',1266461);
+INSERT INTO City VALUES (71,'Córdoba','ARG','Córdoba',1157507);
+INSERT INTO City VALUES (72,'Rosario','ARG','Santa Fé',907718);
+INSERT INTO City VALUES (73,'Lomas de Zamora','ARG','Buenos Aires',622013);
+INSERT INTO City VALUES (74,'Quilmes','ARG','Buenos Aires',559249);
+INSERT INTO City VALUES (75,'Almirante Brown','ARG','Buenos Aires',538918);
+INSERT INTO City VALUES (76,'La Plata','ARG','Buenos Aires',521936);
+INSERT INTO City VALUES (77,'Mar del Plata','ARG','Buenos Aires',512880);
+INSERT INTO City VALUES (78,'San Miguel de Tucumán','ARG','Tucumán',470809);
+INSERT INTO City VALUES (79,'Lanús','ARG','Buenos Aires',469735);
+INSERT INTO City VALUES (80,'Merlo','ARG','Buenos Aires',463846);
+INSERT INTO City VALUES (81,'General San Martín','ARG','Buenos Aires',422542);
+INSERT INTO City VALUES (82,'Salta','ARG','Salta',367550);
+INSERT INTO City VALUES (83,'Moreno','ARG','Buenos Aires',356993);
+INSERT INTO City VALUES (84,'Santa Fé','ARG','Santa Fé',353063);
+INSERT INTO City VALUES (85,'Avellaneda','ARG','Buenos Aires',353046);
+INSERT INTO City VALUES (86,'Tres de Febrero','ARG','Buenos Aires',352311);
+INSERT INTO City VALUES (87,'Morón','ARG','Buenos Aires',349246);
+INSERT INTO City VALUES (88,'Florencio Varela','ARG','Buenos Aires',315432);
+INSERT INTO City VALUES (89,'San Isidro','ARG','Buenos Aires',306341);
+INSERT INTO City VALUES (90,'Tigre','ARG','Buenos Aires',296226);
+INSERT INTO City VALUES (91,'Malvinas Argentinas','ARG','Buenos Aires',290335);
+INSERT INTO City VALUES (92,'Vicente López','ARG','Buenos Aires',288341);
+INSERT INTO City VALUES (93,'Berazategui','ARG','Buenos Aires',276916);
+INSERT INTO City VALUES (94,'Corrientes','ARG','Corrientes',258103);
+INSERT INTO City VALUES (95,'San Miguel','ARG','Buenos Aires',248700);
+INSERT INTO City VALUES (96,'Bahía Blanca','ARG','Buenos Aires',239810);
+INSERT INTO City VALUES (97,'Esteban Echeverría','ARG','Buenos Aires',235760);
+INSERT INTO City VALUES (98,'Resistencia','ARG','Chaco',229212);
+INSERT INTO City VALUES (99,'José C. Paz','ARG','Buenos Aires',221754);
+INSERT INTO City VALUES (100,'Paraná','ARG','Entre Rios',207041);
+INSERT INTO City VALUES (101,'Godoy Cruz','ARG','Mendoza',206998);
+INSERT INTO City VALUES (102,'Posadas','ARG','Misiones',201273);
+INSERT INTO City VALUES (103,'Guaymallén','ARG','Mendoza',200595);
+INSERT INTO City VALUES (104,'Santiago del Estero','ARG','Santiago del Estero',189947);
+INSERT INTO City VALUES (105,'San Salvador de Jujuy','ARG','Jujuy',178748);
+INSERT INTO City VALUES (106,'Hurlingham','ARG','Buenos Aires',170028);
+INSERT INTO City VALUES (107,'Neuquén','ARG','Neuquén',167296);
+INSERT INTO City VALUES (108,'Ituzaingó','ARG','Buenos Aires',158197);
+INSERT INTO City VALUES (109,'San Fernando','ARG','Buenos Aires',153036);
+INSERT INTO City VALUES (110,'Formosa','ARG','Formosa',147636);
+INSERT INTO City VALUES (111,'Las Heras','ARG','Mendoza',145823);
+INSERT INTO City VALUES (112,'La Rioja','ARG','La Rioja',138117);
+INSERT INTO City VALUES (113,'San Fernando del Valle de Cata','ARG','Catamarca',134935);
+INSERT INTO City VALUES (114,'Río Cuarto','ARG','Córdoba',134355);
+INSERT INTO City VALUES (115,'Comodoro Rivadavia','ARG','Chubut',124104);
+INSERT INTO City VALUES (116,'Mendoza','ARG','Mendoza',123027);
+INSERT INTO City VALUES (117,'San Nicolás de los Arroyos','ARG','Buenos Aires',119302);
+INSERT INTO City VALUES (118,'San Juan','ARG','San Juan',119152);
+INSERT INTO City VALUES (119,'Escobar','ARG','Buenos Aires',116675);
+INSERT INTO City VALUES (120,'Concordia','ARG','Entre Rios',116485);
+INSERT INTO City VALUES (121,'Pilar','ARG','Buenos Aires',113428);
+INSERT INTO City VALUES (122,'San Luis','ARG','San Luis',110136);
+INSERT INTO City VALUES (123,'Ezeiza','ARG','Buenos Aires',99578);
+INSERT INTO City VALUES (124,'San Rafael','ARG','Mendoza',94651);
+INSERT INTO City VALUES (125,'Tandil','ARG','Buenos Aires',91101);
+INSERT INTO City VALUES (126,'Yerevan','ARM','Yerevan',1248700);
+INSERT INTO City VALUES (127,'Gjumri','ARM','Širak',211700);
+INSERT INTO City VALUES (128,'Vanadzor','ARM','Lori',172700);
+INSERT INTO City VALUES (129,'Oranjestad','ABW','–',29034);
+INSERT INTO City VALUES (130,'Sydney','AUS','New South Wales',3276207);
+INSERT INTO City VALUES (131,'Melbourne','AUS','Victoria',2865329);
+INSERT INTO City VALUES (132,'Brisbane','AUS','Queensland',1291117);
+INSERT INTO City VALUES (133,'Perth','AUS','West Australia',1096829);
+INSERT INTO City VALUES (134,'Adelaide','AUS','South Australia',978100);
+INSERT INTO City VALUES (135,'Canberra','AUS','Capital Region',322723);
+INSERT INTO City VALUES (136,'Gold Coast','AUS','Queensland',311932);
+INSERT INTO City VALUES (137,'Newcastle','AUS','New South Wales',270324);
+INSERT INTO City VALUES (138,'Central Coast','AUS','New South Wales',227657);
+INSERT INTO City VALUES (139,'Wollongong','AUS','New South Wales',219761);
+INSERT INTO City VALUES (140,'Hobart','AUS','Tasmania',126118);
+INSERT INTO City VALUES (141,'Geelong','AUS','Victoria',125382);
+INSERT INTO City VALUES (142,'Townsville','AUS','Queensland',109914);
+INSERT INTO City VALUES (143,'Cairns','AUS','Queensland',92273);
+INSERT INTO City VALUES (144,'Baku','AZE','Baki',1787800);
+INSERT INTO City VALUES (145,'Gäncä','AZE','Gäncä',299300);
+INSERT INTO City VALUES (146,'Sumqayit','AZE','Sumqayit',283000);
+INSERT INTO City VALUES (147,'Mingäçevir','AZE','Mingäçevir',93900);
+INSERT INTO City VALUES (148,'Nassau','BHS','New Providence',172000);
+INSERT INTO City VALUES (149,'al-Manama','BHR','al-Manama',148000);
+INSERT INTO City VALUES (150,'Dhaka','BGD','Dhaka',3612850);
+INSERT INTO City VALUES (151,'Chittagong','BGD','Chittagong',1392860);
+INSERT INTO City VALUES (152,'Khulna','BGD','Khulna',663340);
+INSERT INTO City VALUES (153,'Rajshahi','BGD','Rajshahi',294056);
+INSERT INTO City VALUES (154,'Narayanganj','BGD','Dhaka',202134);
+INSERT INTO City VALUES (155,'Rangpur','BGD','Rajshahi',191398);
+INSERT INTO City VALUES (156,'Mymensingh','BGD','Dhaka',188713);
+INSERT INTO City VALUES (157,'Barisal','BGD','Barisal',170232);
+INSERT INTO City VALUES (158,'Tungi','BGD','Dhaka',168702);
+INSERT INTO City VALUES (159,'Jessore','BGD','Khulna',139710);
+INSERT INTO City VALUES (160,'Comilla','BGD','Chittagong',135313);
+INSERT INTO City VALUES (161,'Nawabganj','BGD','Rajshahi',130577);
+INSERT INTO City VALUES (162,'Dinajpur','BGD','Rajshahi',127815);
+INSERT INTO City VALUES (163,'Bogra','BGD','Rajshahi',120170);
+INSERT INTO City VALUES (164,'Sylhet','BGD','Sylhet',117396);
+INSERT INTO City VALUES (165,'Brahmanbaria','BGD','Chittagong',109032);
+INSERT INTO City VALUES (166,'Tangail','BGD','Dhaka',106004);
+INSERT INTO City VALUES (167,'Jamalpur','BGD','Dhaka',103556);
+INSERT INTO City VALUES (168,'Pabna','BGD','Rajshahi',103277);
+INSERT INTO City VALUES (169,'Naogaon','BGD','Rajshahi',101266);
+INSERT INTO City VALUES (170,'Sirajganj','BGD','Rajshahi',99669);
+INSERT INTO City VALUES (171,'Narsinghdi','BGD','Dhaka',98342);
+INSERT INTO City VALUES (172,'Saidpur','BGD','Rajshahi',96777);
+INSERT INTO City VALUES (173,'Gazipur','BGD','Dhaka',96717);
+INSERT INTO City VALUES (174,'Bridgetown','BRB','St Michael',6070);
+INSERT INTO City VALUES (175,'Antwerpen','BEL','Antwerpen',446525);
+INSERT INTO City VALUES (176,'Gent','BEL','East Flanderi',224180);
+INSERT INTO City VALUES (177,'Charleroi','BEL','Hainaut',200827);
+INSERT INTO City VALUES (178,'Liège','BEL','Liège',185639);
+INSERT INTO City VALUES (179,'Bruxelles [Brussel]','BEL','Bryssel',133859);
+INSERT INTO City VALUES (180,'Brugge','BEL','West Flanderi',116246);
+INSERT INTO City VALUES (181,'Schaerbeek','BEL','Bryssel',105692);
+INSERT INTO City VALUES (182,'Namur','BEL','Namur',105419);
+INSERT INTO City VALUES (183,'Mons','BEL','Hainaut',90935);
+INSERT INTO City VALUES (184,'Belize City','BLZ','Belize City',55810);
+INSERT INTO City VALUES (185,'Belmopan','BLZ','Cayo',7105);
+INSERT INTO City VALUES (186,'Cotonou','BEN','Atlantique',536827);
+INSERT INTO City VALUES (187,'Porto-Novo','BEN','Ouémé',194000);
+INSERT INTO City VALUES (188,'Djougou','BEN','Atacora',134099);
+INSERT INTO City VALUES (189,'Parakou','BEN','Borgou',103577);
+INSERT INTO City VALUES (190,'Saint George','BMU','Saint George´s',1800);
+INSERT INTO City VALUES (191,'Hamilton','BMU','Hamilton',1200);
+INSERT INTO City VALUES (192,'Thimphu','BTN','Thimphu',22000);
+INSERT INTO City VALUES (193,'Santa Cruz de la Sierra','BOL','Santa Cruz',935361);
+INSERT INTO City VALUES (194,'La Paz','BOL','La Paz',758141);
+INSERT INTO City VALUES (195,'El Alto','BOL','La Paz',534466);
+INSERT INTO City VALUES (196,'Cochabamba','BOL','Cochabamba',482800);
+INSERT INTO City VALUES (197,'Oruro','BOL','Oruro',223553);
+INSERT INTO City VALUES (198,'Sucre','BOL','Chuquisaca',178426);
+INSERT INTO City VALUES (199,'Potosí','BOL','Potosí',140642);
+INSERT INTO City VALUES (200,'Tarija','BOL','Tarija',125255);
+INSERT INTO City VALUES (201,'Sarajevo','BIH','Federaatio',360000);
+INSERT INTO City VALUES (202,'Banja Luka','BIH','Republika Srpska',143079);
+INSERT INTO City VALUES (203,'Zenica','BIH','Federaatio',96027);
+INSERT INTO City VALUES (204,'Gaborone','BWA','Gaborone',213017);
+INSERT INTO City VALUES (205,'Francistown','BWA','Francistown',101805);
+INSERT INTO City VALUES (206,'São Paulo','BRA','São Paulo',9968485);
+INSERT INTO City VALUES (207,'Rio de Janeiro','BRA','Rio de Janeiro',5598953);
+INSERT INTO City VALUES (208,'Salvador','BRA','Bahia',2302832);
+INSERT INTO City VALUES (209,'Belo Horizonte','BRA','Minas Gerais',2139125);
+INSERT INTO City VALUES (210,'Fortaleza','BRA','Ceará',2097757);
+INSERT INTO City VALUES (211,'Brasília','BRA','Distrito Federal',1969868);
+INSERT INTO City VALUES (212,'Curitiba','BRA','Paraná',1584232);
+INSERT INTO City VALUES (213,'Recife','BRA','Pernambuco',1378087);
+INSERT INTO City VALUES (214,'Porto Alegre','BRA','Rio Grande do Sul',1314032);
+INSERT INTO City VALUES (215,'Manaus','BRA','Amazonas',1255049);
+INSERT INTO City VALUES (216,'Belém','BRA','Pará',1186926);
+INSERT INTO City VALUES (217,'Guarulhos','BRA','São Paulo',1095874);
+INSERT INTO City VALUES (218,'Goiânia','BRA','Goiás',1056330);
+INSERT INTO City VALUES (219,'Campinas','BRA','São Paulo',950043);
+INSERT INTO City VALUES (220,'São Gonçalo','BRA','Rio de Janeiro',869254);
+INSERT INTO City VALUES (221,'Nova Iguaçu','BRA','Rio de Janeiro',862225);
+INSERT INTO City VALUES (222,'São Luís','BRA','Maranhão',837588);
+INSERT INTO City VALUES (223,'Maceió','BRA','Alagoas',786288);
+INSERT INTO City VALUES (224,'Duque de Caxias','BRA','Rio de Janeiro',746758);
+INSERT INTO City VALUES (225,'São Bernardo do Campo','BRA','São Paulo',723132);
+INSERT INTO City VALUES (226,'Teresina','BRA','Piauí',691942);
+INSERT INTO City VALUES (227,'Natal','BRA','Rio Grande do Norte',688955);
+INSERT INTO City VALUES (228,'Osasco','BRA','São Paulo',659604);
+INSERT INTO City VALUES (229,'Campo Grande','BRA','Mato Grosso do Sul',649593);
+INSERT INTO City VALUES (230,'Santo André','BRA','São Paulo',630073);
+INSERT INTO City VALUES (231,'João Pessoa','BRA','Paraíba',584029);
+INSERT INTO City VALUES (232,'Jaboatão dos Guararapes','BRA','Pernambuco',558680);
+INSERT INTO City VALUES (233,'Contagem','BRA','Minas Gerais',520801);
+INSERT INTO City VALUES (234,'São José dos Campos','BRA','São Paulo',515553);
+INSERT INTO City VALUES (235,'Uberlândia','BRA','Minas Gerais',487222);
+INSERT INTO City VALUES (236,'Feira de Santana','BRA','Bahia',479992);
+INSERT INTO City VALUES (237,'Ribeirão Preto','BRA','São Paulo',473276);
+INSERT INTO City VALUES (238,'Sorocaba','BRA','São Paulo',466823);
+INSERT INTO City VALUES (239,'Niterói','BRA','Rio de Janeiro',459884);
+INSERT INTO City VALUES (240,'Cuiabá','BRA','Mato Grosso',453813);
+INSERT INTO City VALUES (241,'Juiz de Fora','BRA','Minas Gerais',450288);
+INSERT INTO City VALUES (242,'Aracaju','BRA','Sergipe',445555);
+INSERT INTO City VALUES (243,'São João de Meriti','BRA','Rio de Janeiro',440052);
+INSERT INTO City VALUES (244,'Londrina','BRA','Paraná',432257);
+INSERT INTO City VALUES (245,'Joinville','BRA','Santa Catarina',428011);
+INSERT INTO City VALUES (246,'Belford Roxo','BRA','Rio de Janeiro',425194);
+INSERT INTO City VALUES (247,'Santos','BRA','São Paulo',408748);
+INSERT INTO City VALUES (248,'Ananindeua','BRA','Pará',400940);
+INSERT INTO City VALUES (249,'Campos dos Goytacazes','BRA','Rio de Janeiro',398418);
+INSERT INTO City VALUES (250,'Mauá','BRA','São Paulo',375055);
+INSERT INTO City VALUES (251,'Carapicuíba','BRA','São Paulo',357552);
+INSERT INTO City VALUES (252,'Olinda','BRA','Pernambuco',354732);
+INSERT INTO City VALUES (253,'Campina Grande','BRA','Paraíba',352497);
+INSERT INTO City VALUES (254,'São José do Rio Preto','BRA','São Paulo',351944);
+INSERT INTO City VALUES (255,'Caxias do Sul','BRA','Rio Grande do Sul',349581);
+INSERT INTO City VALUES (256,'Moji das Cruzes','BRA','São Paulo',339194);
+INSERT INTO City VALUES (257,'Diadema','BRA','São Paulo',335078);
+INSERT INTO City VALUES (258,'Aparecida de Goiânia','BRA','Goiás',324662);
+INSERT INTO City VALUES (259,'Piracicaba','BRA','São Paulo',319104);
+INSERT INTO City VALUES (260,'Cariacica','BRA','Espírito Santo',319033);
+INSERT INTO City VALUES (261,'Vila Velha','BRA','Espírito Santo',318758);
+INSERT INTO City VALUES (262,'Pelotas','BRA','Rio Grande do Sul',315415);
+INSERT INTO City VALUES (263,'Bauru','BRA','São Paulo',313670);
+INSERT INTO City VALUES (264,'Porto Velho','BRA','Rondônia',309750);
+INSERT INTO City VALUES (265,'Serra','BRA','Espírito Santo',302666);
+INSERT INTO City VALUES (266,'Betim','BRA','Minas Gerais',302108);
+INSERT INTO City VALUES (267,'Jundíaí','BRA','São Paulo',296127);
+INSERT INTO City VALUES (268,'Canoas','BRA','Rio Grande do Sul',294125);
+INSERT INTO City VALUES (269,'Franca','BRA','São Paulo',290139);
+INSERT INTO City VALUES (270,'São Vicente','BRA','São Paulo',286848);
+INSERT INTO City VALUES (271,'Maringá','BRA','Paraná',286461);
+INSERT INTO City VALUES (272,'Montes Claros','BRA','Minas Gerais',286058);
+INSERT INTO City VALUES (273,'Anápolis','BRA','Goiás',282197);
+INSERT INTO City VALUES (274,'Florianópolis','BRA','Santa Catarina',281928);
+INSERT INTO City VALUES (275,'Petrópolis','BRA','Rio de Janeiro',279183);
+INSERT INTO City VALUES (276,'Itaquaquecetuba','BRA','São Paulo',270874);
+INSERT INTO City VALUES (277,'Vitória','BRA','Espírito Santo',270626);
+INSERT INTO City VALUES (278,'Ponta Grossa','BRA','Paraná',268013);
+INSERT INTO City VALUES (279,'Rio Branco','BRA','Acre',259537);
+INSERT INTO City VALUES (280,'Foz do Iguaçu','BRA','Paraná',259425);
+INSERT INTO City VALUES (281,'Macapá','BRA','Amapá',256033);
+INSERT INTO City VALUES (282,'Ilhéus','BRA','Bahia',254970);
+INSERT INTO City VALUES (283,'Vitória da Conquista','BRA','Bahia',253587);
+INSERT INTO City VALUES (284,'Uberaba','BRA','Minas Gerais',249225);
+INSERT INTO City VALUES (285,'Paulista','BRA','Pernambuco',248473);
+INSERT INTO City VALUES (286,'Limeira','BRA','São Paulo',245497);
+INSERT INTO City VALUES (287,'Blumenau','BRA','Santa Catarina',244379);
+INSERT INTO City VALUES (288,'Caruaru','BRA','Pernambuco',244247);
+INSERT INTO City VALUES (289,'Santarém','BRA','Pará',241771);
+INSERT INTO City VALUES (290,'Volta Redonda','BRA','Rio de Janeiro',240315);
+INSERT INTO City VALUES (291,'Novo Hamburgo','BRA','Rio Grande do Sul',239940);
+INSERT INTO City VALUES (292,'Caucaia','BRA','Ceará',238738);
+INSERT INTO City VALUES (293,'Santa Maria','BRA','Rio Grande do Sul',238473);
+INSERT INTO City VALUES (294,'Cascavel','BRA','Paraná',237510);
+INSERT INTO City VALUES (295,'Guarujá','BRA','São Paulo',237206);
+INSERT INTO City VALUES (296,'Ribeirão das Neves','BRA','Minas Gerais',232685);
+INSERT INTO City VALUES (297,'Governador Valadares','BRA','Minas Gerais',231724);
+INSERT INTO City VALUES (298,'Taubaté','BRA','São Paulo',229130);
+INSERT INTO City VALUES (299,'Imperatriz','BRA','Maranhão',224564);
+INSERT INTO City VALUES (300,'Gravataí','BRA','Rio Grande do Sul',223011);
+INSERT INTO City VALUES (301,'Embu','BRA','São Paulo',222223);
+INSERT INTO City VALUES (302,'Mossoró','BRA','Rio Grande do Norte',214901);
+INSERT INTO City VALUES (303,'Várzea Grande','BRA','Mato Grosso',214435);
+INSERT INTO City VALUES (304,'Petrolina','BRA','Pernambuco',210540);
+INSERT INTO City VALUES (305,'Barueri','BRA','São Paulo',208426);
+INSERT INTO City VALUES (306,'Viamão','BRA','Rio Grande do Sul',207557);
+INSERT INTO City VALUES (307,'Ipatinga','BRA','Minas Gerais',206338);
+INSERT INTO City VALUES (308,'Juazeiro','BRA','Bahia',201073);
+INSERT INTO City VALUES (309,'Juazeiro do Norte','BRA','Ceará',199636);
+INSERT INTO City VALUES (310,'Taboão da Serra','BRA','São Paulo',197550);
+INSERT INTO City VALUES (311,'São José dos Pinhais','BRA','Paraná',196884);
+INSERT INTO City VALUES (312,'Magé','BRA','Rio de Janeiro',196147);
+INSERT INTO City VALUES (313,'Suzano','BRA','São Paulo',195434);
+INSERT INTO City VALUES (314,'São Leopoldo','BRA','Rio Grande do Sul',189258);
+INSERT INTO City VALUES (315,'Marília','BRA','São Paulo',188691);
+INSERT INTO City VALUES (316,'São Carlos','BRA','São Paulo',187122);
+INSERT INTO City VALUES (317,'Sumaré','BRA','São Paulo',186205);
+INSERT INTO City VALUES (318,'Presidente Prudente','BRA','São Paulo',185340);
+INSERT INTO City VALUES (319,'Divinópolis','BRA','Minas Gerais',185047);
+INSERT INTO City VALUES (320,'Sete Lagoas','BRA','Minas Gerais',182984);
+INSERT INTO City VALUES (321,'Rio Grande','BRA','Rio Grande do Sul',182222);
+INSERT INTO City VALUES (322,'Itabuna','BRA','Bahia',182148);
+INSERT INTO City VALUES (323,'Jequié','BRA','Bahia',179128);
+INSERT INTO City VALUES (324,'Arapiraca','BRA','Alagoas',178988);
+INSERT INTO City VALUES (325,'Colombo','BRA','Paraná',177764);
+INSERT INTO City VALUES (326,'Americana','BRA','São Paulo',177409);
+INSERT INTO City VALUES (327,'Alvorada','BRA','Rio Grande do Sul',175574);
+INSERT INTO City VALUES (328,'Araraquara','BRA','São Paulo',174381);
+INSERT INTO City VALUES (329,'Itaboraí','BRA','Rio de Janeiro',173977);
+INSERT INTO City VALUES (330,'Santa Bárbara d´Oeste','BRA','São Paulo',171657);
+INSERT INTO City VALUES (331,'Nova Friburgo','BRA','Rio de Janeiro',170697);
+INSERT INTO City VALUES (332,'Jacareí','BRA','São Paulo',170356);
+INSERT INTO City VALUES (333,'Araçatuba','BRA','São Paulo',169303);
+INSERT INTO City VALUES (334,'Barra Mansa','BRA','Rio de Janeiro',168953);
+INSERT INTO City VALUES (335,'Praia Grande','BRA','São Paulo',168434);
+INSERT INTO City VALUES (336,'Marabá','BRA','Pará',167795);
+INSERT INTO City VALUES (337,'Criciúma','BRA','Santa Catarina',167661);
+INSERT INTO City VALUES (338,'Boa Vista','BRA','Roraima',167185);
+INSERT INTO City VALUES (339,'Passo Fundo','BRA','Rio Grande do Sul',166343);
+INSERT INTO City VALUES (340,'Dourados','BRA','Mato Grosso do Sul',164716);
+INSERT INTO City VALUES (341,'Santa Luzia','BRA','Minas Gerais',164704);
+INSERT INTO City VALUES (342,'Rio Claro','BRA','São Paulo',163551);
+INSERT INTO City VALUES (343,'Maracanaú','BRA','Ceará',162022);
+INSERT INTO City VALUES (344,'Guarapuava','BRA','Paraná',160510);
+INSERT INTO City VALUES (345,'Rondonópolis','BRA','Mato Grosso',155115);
+INSERT INTO City VALUES (346,'São José','BRA','Santa Catarina',155105);
+INSERT INTO City VALUES (347,'Cachoeiro de Itapemirim','BRA','Espírito Santo',155024);
+INSERT INTO City VALUES (348,'Nilópolis','BRA','Rio de Janeiro',153383);
+INSERT INTO City VALUES (349,'Itapevi','BRA','São Paulo',150664);
+INSERT INTO City VALUES (350,'Cabo de Santo Agostinho','BRA','Pernambuco',149964);
+INSERT INTO City VALUES (351,'Camaçari','BRA','Bahia',149146);
+INSERT INTO City VALUES (352,'Sobral','BRA','Ceará',146005);
+INSERT INTO City VALUES (353,'Itajaí','BRA','Santa Catarina',145197);
+INSERT INTO City VALUES (354,'Chapecó','BRA','Santa Catarina',144158);
+INSERT INTO City VALUES (355,'Cotia','BRA','São Paulo',140042);
+INSERT INTO City VALUES (356,'Lages','BRA','Santa Catarina',139570);
+INSERT INTO City VALUES (357,'Ferraz de Vasconcelos','BRA','São Paulo',139283);
+INSERT INTO City VALUES (358,'Indaiatuba','BRA','São Paulo',135968);
+INSERT INTO City VALUES (359,'Hortolândia','BRA','São Paulo',135755);
+INSERT INTO City VALUES (360,'Caxias','BRA','Maranhão',133980);
+INSERT INTO City VALUES (361,'São Caetano do Sul','BRA','São Paulo',133321);
+INSERT INTO City VALUES (362,'Itu','BRA','São Paulo',132736);
+INSERT INTO City VALUES (363,'Nossa Senhora do Socorro','BRA','Sergipe',131351);
+INSERT INTO City VALUES (364,'Parnaíba','BRA','Piauí',129756);
+INSERT INTO City VALUES (365,'Poços de Caldas','BRA','Minas Gerais',129683);
+INSERT INTO City VALUES (366,'Teresópolis','BRA','Rio de Janeiro',128079);
+INSERT INTO City VALUES (367,'Barreiras','BRA','Bahia',127801);
+INSERT INTO City VALUES (368,'Castanhal','BRA','Pará',127634);
+INSERT INTO City VALUES (369,'Alagoinhas','BRA','Bahia',126820);
+INSERT INTO City VALUES (370,'Itapecerica da Serra','BRA','São Paulo',126672);
+INSERT INTO City VALUES (371,'Uruguaiana','BRA','Rio Grande do Sul',126305);
+INSERT INTO City VALUES (372,'Paranaguá','BRA','Paraná',126076);
+INSERT INTO City VALUES (373,'Ibirité','BRA','Minas Gerais',125982);
+INSERT INTO City VALUES (374,'Timon','BRA','Maranhão',125812);
+INSERT INTO City VALUES (375,'Luziânia','BRA','Goiás',125597);
+INSERT INTO City VALUES (376,'Macaé','BRA','Rio de Janeiro',125597);
+INSERT INTO City VALUES (377,'Teófilo Otoni','BRA','Minas Gerais',124489);
+INSERT INTO City VALUES (378,'Moji-Guaçu','BRA','São Paulo',123782);
+INSERT INTO City VALUES (379,'Palmas','BRA','Tocantins',121919);
+INSERT INTO City VALUES (380,'Pindamonhangaba','BRA','São Paulo',121904);
+INSERT INTO City VALUES (381,'Francisco Morato','BRA','São Paulo',121197);
+INSERT INTO City VALUES (382,'Bagé','BRA','Rio Grande do Sul',120793);
+INSERT INTO City VALUES (383,'Sapucaia do Sul','BRA','Rio Grande do Sul',120217);
+INSERT INTO City VALUES (384,'Cabo Frio','BRA','Rio de Janeiro',119503);
+INSERT INTO City VALUES (385,'Itapetininga','BRA','São Paulo',119391);
+INSERT INTO City VALUES (386,'Patos de Minas','BRA','Minas Gerais',119262);
+INSERT INTO City VALUES (387,'Camaragibe','BRA','Pernambuco',118968);
+INSERT INTO City VALUES (388,'Bragança Paulista','BRA','São Paulo',116929);
+INSERT INTO City VALUES (389,'Queimados','BRA','Rio de Janeiro',115020);
+INSERT INTO City VALUES (390,'Araguaína','BRA','Tocantins',114948);
+INSERT INTO City VALUES (391,'Garanhuns','BRA','Pernambuco',114603);
+INSERT INTO City VALUES (392,'Vitória de Santo Antão','BRA','Pernambuco',113595);
+INSERT INTO City VALUES (393,'Santa Rita','BRA','Paraíba',113135);
+INSERT INTO City VALUES (394,'Barbacena','BRA','Minas Gerais',113079);
+INSERT INTO City VALUES (395,'Abaetetuba','BRA','Pará',111258);
+INSERT INTO City VALUES (396,'Jaú','BRA','São Paulo',109965);
+INSERT INTO City VALUES (397,'Lauro de Freitas','BRA','Bahia',109236);
+INSERT INTO City VALUES (398,'Franco da Rocha','BRA','São Paulo',108964);
+INSERT INTO City VALUES (399,'Teixeira de Freitas','BRA','Bahia',108441);
+INSERT INTO City VALUES (400,'Varginha','BRA','Minas Gerais',108314);
+INSERT INTO City VALUES (401,'Ribeirão Pires','BRA','São Paulo',108121);
+INSERT INTO City VALUES (402,'Sabará','BRA','Minas Gerais',107781);
+INSERT INTO City VALUES (403,'Catanduva','BRA','São Paulo',107761);
+INSERT INTO City VALUES (404,'Rio Verde','BRA','Goiás',107755);
+INSERT INTO City VALUES (405,'Botucatu','BRA','São Paulo',107663);
+INSERT INTO City VALUES (406,'Colatina','BRA','Espírito Santo',107354);
+INSERT INTO City VALUES (407,'Santa Cruz do Sul','BRA','Rio Grande do Sul',106734);
+INSERT INTO City VALUES (408,'Linhares','BRA','Espírito Santo',106278);
+INSERT INTO City VALUES (409,'Apucarana','BRA','Paraná',105114);
+INSERT INTO City VALUES (410,'Barretos','BRA','São Paulo',104156);
+INSERT INTO City VALUES (411,'Guaratinguetá','BRA','São Paulo',103433);
+INSERT INTO City VALUES (412,'Cachoeirinha','BRA','Rio Grande do Sul',103240);
+INSERT INTO City VALUES (413,'Codó','BRA','Maranhão',103153);
+INSERT INTO City VALUES (414,'Jaraguá do Sul','BRA','Santa Catarina',102580);
+INSERT INTO City VALUES (415,'Cubatão','BRA','São Paulo',102372);
+INSERT INTO City VALUES (416,'Itabira','BRA','Minas Gerais',102217);
+INSERT INTO City VALUES (417,'Itaituba','BRA','Pará',101320);
+INSERT INTO City VALUES (418,'Araras','BRA','São Paulo',101046);
+INSERT INTO City VALUES (419,'Resende','BRA','Rio de Janeiro',100627);
+INSERT INTO City VALUES (420,'Atibaia','BRA','São Paulo',100356);
+INSERT INTO City VALUES (421,'Pouso Alegre','BRA','Minas Gerais',100028);
+INSERT INTO City VALUES (422,'Toledo','BRA','Paraná',99387);
+INSERT INTO City VALUES (423,'Crato','BRA','Ceará',98965);
+INSERT INTO City VALUES (424,'Passos','BRA','Minas Gerais',98570);
+INSERT INTO City VALUES (425,'Araguari','BRA','Minas Gerais',98399);
+INSERT INTO City VALUES (426,'São José de Ribamar','BRA','Maranhão',98318);
+INSERT INTO City VALUES (427,'Pinhais','BRA','Paraná',98198);
+INSERT INTO City VALUES (428,'Sertãozinho','BRA','São Paulo',98140);
+INSERT INTO City VALUES (429,'Conselheiro Lafaiete','BRA','Minas Gerais',97507);
+INSERT INTO City VALUES (430,'Paulo Afonso','BRA','Bahia',97291);
+INSERT INTO City VALUES (431,'Angra dos Reis','BRA','Rio de Janeiro',96864);
+INSERT INTO City VALUES (432,'Eunápolis','BRA','Bahia',96610);
+INSERT INTO City VALUES (433,'Salto','BRA','São Paulo',96348);
+INSERT INTO City VALUES (434,'Ourinhos','BRA','São Paulo',96291);
+INSERT INTO City VALUES (435,'Parnamirim','BRA','Rio Grande do Norte',96210);
+INSERT INTO City VALUES (436,'Jacobina','BRA','Bahia',96131);
+INSERT INTO City VALUES (437,'Coronel Fabriciano','BRA','Minas Gerais',95933);
+INSERT INTO City VALUES (438,'Birigui','BRA','São Paulo',94685);
+INSERT INTO City VALUES (439,'Tatuí','BRA','São Paulo',93897);
+INSERT INTO City VALUES (440,'Ji-Paraná','BRA','Rondônia',93346);
+INSERT INTO City VALUES (441,'Bacabal','BRA','Maranhão',93121);
+INSERT INTO City VALUES (442,'Cametá','BRA','Pará',92779);
+INSERT INTO City VALUES (443,'Guaíba','BRA','Rio Grande do Sul',92224);
+INSERT INTO City VALUES (444,'São Lourenço da Mata','BRA','Pernambuco',91999);
+INSERT INTO City VALUES (445,'Santana do Livramento','BRA','Rio Grande do Sul',91779);
+INSERT INTO City VALUES (446,'Votorantim','BRA','São Paulo',91777);
+INSERT INTO City VALUES (447,'Campo Largo','BRA','Paraná',91203);
+INSERT INTO City VALUES (448,'Patos','BRA','Paraíba',90519);
+INSERT INTO City VALUES (449,'Ituiutaba','BRA','Minas Gerais',90507);
+INSERT INTO City VALUES (450,'Corumbá','BRA','Mato Grosso do Sul',90111);
+INSERT INTO City VALUES (451,'Palhoça','BRA','Santa Catarina',89465);
+INSERT INTO City VALUES (452,'Barra do Piraí','BRA','Rio de Janeiro',89388);
+INSERT INTO City VALUES (453,'Bento Gonçalves','BRA','Rio Grande do Sul',89254);
+INSERT INTO City VALUES (454,'Poá','BRA','São Paulo',89236);
+INSERT INTO City VALUES (455,'Águas Lindas de Goiás','BRA','Goiás',89200);
+INSERT INTO City VALUES (456,'London','GBR','England',7285000);
+INSERT INTO City VALUES (457,'Birmingham','GBR','England',1013000);
+INSERT INTO City VALUES (458,'Glasgow','GBR','Scotland',619680);
+INSERT INTO City VALUES (459,'Liverpool','GBR','England',461000);
+INSERT INTO City VALUES (460,'Edinburgh','GBR','Scotland',450180);
+INSERT INTO City VALUES (461,'Sheffield','GBR','England',431607);
+INSERT INTO City VALUES (462,'Manchester','GBR','England',430000);
+INSERT INTO City VALUES (463,'Leeds','GBR','England',424194);
+INSERT INTO City VALUES (464,'Bristol','GBR','England',402000);
+INSERT INTO City VALUES (465,'Cardiff','GBR','Wales',321000);
+INSERT INTO City VALUES (466,'Coventry','GBR','England',304000);
+INSERT INTO City VALUES (467,'Leicester','GBR','England',294000);
+INSERT INTO City VALUES (468,'Bradford','GBR','England',289376);
+INSERT INTO City VALUES (469,'Belfast','GBR','North Ireland',287500);
+INSERT INTO City VALUES (470,'Nottingham','GBR','England',287000);
+INSERT INTO City VALUES (471,'Kingston upon Hull','GBR','England',262000);
+INSERT INTO City VALUES (472,'Plymouth','GBR','England',253000);
+INSERT INTO City VALUES (473,'Stoke-on-Trent','GBR','England',252000);
+INSERT INTO City VALUES (474,'Wolverhampton','GBR','England',242000);
+INSERT INTO City VALUES (475,'Derby','GBR','England',236000);
+INSERT INTO City VALUES (476,'Swansea','GBR','Wales',230000);
+INSERT INTO City VALUES (477,'Southampton','GBR','England',216000);
+INSERT INTO City VALUES (478,'Aberdeen','GBR','Scotland',213070);
+INSERT INTO City VALUES (479,'Northampton','GBR','England',196000);
+INSERT INTO City VALUES (480,'Dudley','GBR','England',192171);
+INSERT INTO City VALUES (481,'Portsmouth','GBR','England',190000);
+INSERT INTO City VALUES (482,'Newcastle upon Tyne','GBR','England',189150);
+INSERT INTO City VALUES (483,'Sunderland','GBR','England',183310);
+INSERT INTO City VALUES (484,'Luton','GBR','England',183000);
+INSERT INTO City VALUES (485,'Swindon','GBR','England',180000);
+INSERT INTO City VALUES (486,'Southend-on-Sea','GBR','England',176000);
+INSERT INTO City VALUES (487,'Walsall','GBR','England',174739);
+INSERT INTO City VALUES (488,'Bournemouth','GBR','England',162000);
+INSERT INTO City VALUES (489,'Peterborough','GBR','England',156000);
+INSERT INTO City VALUES (490,'Brighton','GBR','England',156124);
+INSERT INTO City VALUES (491,'Blackpool','GBR','England',151000);
+INSERT INTO City VALUES (492,'Dundee','GBR','Scotland',146690);
+INSERT INTO City VALUES (493,'West Bromwich','GBR','England',146386);
+INSERT INTO City VALUES (494,'Reading','GBR','England',148000);
+INSERT INTO City VALUES (495,'Oldbury/Smethwick (Warley)','GBR','England',145542);
+INSERT INTO City VALUES (496,'Middlesbrough','GBR','England',145000);
+INSERT INTO City VALUES (497,'Huddersfield','GBR','England',143726);
+INSERT INTO City VALUES (498,'Oxford','GBR','England',144000);
+INSERT INTO City VALUES (499,'Poole','GBR','England',141000);
+INSERT INTO City VALUES (500,'Bolton','GBR','England',139020);
+INSERT INTO City VALUES (501,'Blackburn','GBR','England',140000);
+INSERT INTO City VALUES (502,'Newport','GBR','Wales',139000);
+INSERT INTO City VALUES (503,'Preston','GBR','England',135000);
+INSERT INTO City VALUES (504,'Stockport','GBR','England',132813);
+INSERT INTO City VALUES (505,'Norwich','GBR','England',124000);
+INSERT INTO City VALUES (506,'Rotherham','GBR','England',121380);
+INSERT INTO City VALUES (507,'Cambridge','GBR','England',121000);
+INSERT INTO City VALUES (508,'Watford','GBR','England',113080);
+INSERT INTO City VALUES (509,'Ipswich','GBR','England',114000);
+INSERT INTO City VALUES (510,'Slough','GBR','England',112000);
+INSERT INTO City VALUES (511,'Exeter','GBR','England',111000);
+INSERT INTO City VALUES (512,'Cheltenham','GBR','England',106000);
+INSERT INTO City VALUES (513,'Gloucester','GBR','England',107000);
+INSERT INTO City VALUES (514,'Saint Helens','GBR','England',106293);
+INSERT INTO City VALUES (515,'Sutton Coldfield','GBR','England',106001);
+INSERT INTO City VALUES (516,'York','GBR','England',104425);
+INSERT INTO City VALUES (517,'Oldham','GBR','England',103931);
+INSERT INTO City VALUES (518,'Basildon','GBR','England',100924);
+INSERT INTO City VALUES (519,'Worthing','GBR','England',100000);
+INSERT INTO City VALUES (520,'Chelmsford','GBR','England',97451);
+INSERT INTO City VALUES (521,'Colchester','GBR','England',96063);
+INSERT INTO City VALUES (522,'Crawley','GBR','England',97000);
+INSERT INTO City VALUES (523,'Gillingham','GBR','England',92000);
+INSERT INTO City VALUES (524,'Solihull','GBR','England',94531);
+INSERT INTO City VALUES (525,'Rochdale','GBR','England',94313);
+INSERT INTO City VALUES (526,'Birkenhead','GBR','England',93087);
+INSERT INTO City VALUES (527,'Worcester','GBR','England',95000);
+INSERT INTO City VALUES (528,'Hartlepool','GBR','England',92000);
+INSERT INTO City VALUES (529,'Halifax','GBR','England',91069);
+INSERT INTO City VALUES (530,'Woking/Byfleet','GBR','England',92000);
+INSERT INTO City VALUES (531,'Southport','GBR','England',90959);
+INSERT INTO City VALUES (532,'Maidstone','GBR','England',90878);
+INSERT INTO City VALUES (533,'Eastbourne','GBR','England',90000);
+INSERT INTO City VALUES (534,'Grimsby','GBR','England',89000);
+INSERT INTO City VALUES (535,'Saint Helier','GBR','Jersey',27523);
+INSERT INTO City VALUES (536,'Douglas','GBR','–',23487);
+INSERT INTO City VALUES (537,'Road Town','VGB','Tortola',8000);
+INSERT INTO City VALUES (538,'Bandar Seri Begawan','BRN','Brunei and Muara',21484);
+INSERT INTO City VALUES (539,'Sofija','BGR','Grad Sofija',1122302);
+INSERT INTO City VALUES (540,'Plovdiv','BGR','Plovdiv',342584);
+INSERT INTO City VALUES (541,'Varna','BGR','Varna',299801);
+INSERT INTO City VALUES (542,'Burgas','BGR','Burgas',195255);
+INSERT INTO City VALUES (543,'Ruse','BGR','Ruse',166467);
+INSERT INTO City VALUES (544,'Stara Zagora','BGR','Haskovo',147939);
+INSERT INTO City VALUES (545,'Pleven','BGR','Lovec',121952);
+INSERT INTO City VALUES (546,'Sliven','BGR','Burgas',105530);
+INSERT INTO City VALUES (547,'Dobric','BGR','Varna',100399);
+INSERT INTO City VALUES (548,'Šumen','BGR','Varna',94686);
+INSERT INTO City VALUES (549,'Ouagadougou','BFA','Kadiogo',824000);
+INSERT INTO City VALUES (550,'Bobo-Dioulasso','BFA','Houet',300000);
+INSERT INTO City VALUES (551,'Koudougou','BFA','Boulkiemdé',105000);
+INSERT INTO City VALUES (552,'Bujumbura','BDI','Bujumbura',300000);
+INSERT INTO City VALUES (553,'George Town','CYM','Grand Cayman',19600);
+INSERT INTO City VALUES (554,'Santiago de Chile','CHL','Santiago',4703954);
+INSERT INTO City VALUES (555,'Puente Alto','CHL','Santiago',386236);
+INSERT INTO City VALUES (556,'Viña del Mar','CHL','Valparaíso',312493);
+INSERT INTO City VALUES (557,'Valparaíso','CHL','Valparaíso',293800);
+INSERT INTO City VALUES (558,'Talcahuano','CHL','Bíobío',277752);
+INSERT INTO City VALUES (559,'Antofagasta','CHL','Antofagasta',251429);
+INSERT INTO City VALUES (560,'San Bernardo','CHL','Santiago',241910);
+INSERT INTO City VALUES (561,'Temuco','CHL','La Araucanía',233041);
+INSERT INTO City VALUES (562,'Concepción','CHL','Bíobío',217664);
+INSERT INTO City VALUES (563,'Rancagua','CHL','O´Higgins',212977);
+INSERT INTO City VALUES (564,'Arica','CHL','Tarapacá',189036);
+INSERT INTO City VALUES (565,'Talca','CHL','Maule',187557);
+INSERT INTO City VALUES (566,'Chillán','CHL','Bíobío',178182);
+INSERT INTO City VALUES (567,'Iquique','CHL','Tarapacá',177892);
+INSERT INTO City VALUES (568,'Los Angeles','CHL','Bíobío',158215);
+INSERT INTO City VALUES (569,'Puerto Montt','CHL','Los Lagos',152194);
+INSERT INTO City VALUES (570,'Coquimbo','CHL','Coquimbo',143353);
+INSERT INTO City VALUES (571,'Osorno','CHL','Los Lagos',141468);
+INSERT INTO City VALUES (572,'La Serena','CHL','Coquimbo',137409);
+INSERT INTO City VALUES (573,'Calama','CHL','Antofagasta',137265);
+INSERT INTO City VALUES (574,'Valdivia','CHL','Los Lagos',133106);
+INSERT INTO City VALUES (575,'Punta Arenas','CHL','Magallanes',125631);
+INSERT INTO City VALUES (576,'Copiapó','CHL','Atacama',120128);
+INSERT INTO City VALUES (577,'Quilpué','CHL','Valparaíso',118857);
+INSERT INTO City VALUES (578,'Curicó','CHL','Maule',115766);
+INSERT INTO City VALUES (579,'Ovalle','CHL','Coquimbo',94854);
+INSERT INTO City VALUES (580,'Coronel','CHL','Bíobío',93061);
+INSERT INTO City VALUES (581,'San Pedro de la Paz','CHL','Bíobío',91684);
+INSERT INTO City VALUES (582,'Melipilla','CHL','Santiago',91056);
+INSERT INTO City VALUES (583,'Avarua','COK','Rarotonga',11900);
+INSERT INTO City VALUES (584,'San José','CRI','San José',339131);
+INSERT INTO City VALUES (585,'Djibouti','DJI','Djibouti',383000);
+INSERT INTO City VALUES (586,'Roseau','DMA','St George',16243);
+INSERT INTO City VALUES (587,'Santo Domingo de Guzmán','DOM','Distrito Nacional',1609966);
+INSERT INTO City VALUES (588,'Santiago de los Caballeros','DOM','Santiago',365463);
+INSERT INTO City VALUES (589,'La Romana','DOM','La Romana',140204);
+INSERT INTO City VALUES (590,'San Pedro de Macorís','DOM','San Pedro de Macorís',124735);
+INSERT INTO City VALUES (591,'San Francisco de Macorís','DOM','Duarte',108485);
+INSERT INTO City VALUES (592,'San Felipe de Puerto Plata','DOM','Puerto Plata',89423);
+INSERT INTO City VALUES (593,'Guayaquil','ECU','Guayas',2070040);
+INSERT INTO City VALUES (594,'Quito','ECU','Pichincha',1573458);
+INSERT INTO City VALUES (595,'Cuenca','ECU','Azuay',270353);
+INSERT INTO City VALUES (596,'Machala','ECU','El Oro',210368);
+INSERT INTO City VALUES (597,'Santo Domingo de los Colorados','ECU','Pichincha',202111);
+INSERT INTO City VALUES (598,'Portoviejo','ECU','Manabí',176413);
+INSERT INTO City VALUES (599,'Ambato','ECU','Tungurahua',169612);
+INSERT INTO City VALUES (600,'Manta','ECU','Manabí',164739);
+INSERT INTO City VALUES (601,'Duran [Eloy Alfaro]','ECU','Guayas',152514);
+INSERT INTO City VALUES (602,'Ibarra','ECU','Imbabura',130643);
+INSERT INTO City VALUES (603,'Quevedo','ECU','Los Ríos',129631);
+INSERT INTO City VALUES (604,'Milagro','ECU','Guayas',124177);
+INSERT INTO City VALUES (605,'Loja','ECU','Loja',123875);
+INSERT INTO City VALUES (606,'Ríobamba','ECU','Chimborazo',123163);
+INSERT INTO City VALUES (607,'Esmeraldas','ECU','Esmeraldas',123045);
+INSERT INTO City VALUES (608,'Cairo','EGY','Kairo',6789479);
+INSERT INTO City VALUES (609,'Alexandria','EGY','Aleksandria',3328196);
+INSERT INTO City VALUES (610,'Giza','EGY','Giza',2221868);
+INSERT INTO City VALUES (611,'Shubra al-Khayma','EGY','al-Qalyubiya',870716);
+INSERT INTO City VALUES (612,'Port Said','EGY','Port Said',469533);
+INSERT INTO City VALUES (613,'Suez','EGY','Suez',417610);
+INSERT INTO City VALUES (614,'al-Mahallat al-Kubra','EGY','al-Gharbiya',395402);
+INSERT INTO City VALUES (615,'Tanta','EGY','al-Gharbiya',371010);
+INSERT INTO City VALUES (616,'al-Mansura','EGY','al-Daqahliya',369621);
+INSERT INTO City VALUES (617,'Luxor','EGY','Luxor',360503);
+INSERT INTO City VALUES (618,'Asyut','EGY','Asyut',343498);
+INSERT INTO City VALUES (619,'Bahtim','EGY','al-Qalyubiya',275807);
+INSERT INTO City VALUES (620,'Zagazig','EGY','al-Sharqiya',267351);
+INSERT INTO City VALUES (621,'al-Faiyum','EGY','al-Faiyum',260964);
+INSERT INTO City VALUES (622,'Ismailia','EGY','Ismailia',254477);
+INSERT INTO City VALUES (623,'Kafr al-Dawwar','EGY','al-Buhayra',231978);
+INSERT INTO City VALUES (624,'Assuan','EGY','Assuan',219017);
+INSERT INTO City VALUES (625,'Damanhur','EGY','al-Buhayra',212203);
+INSERT INTO City VALUES (626,'al-Minya','EGY','al-Minya',201360);
+INSERT INTO City VALUES (627,'Bani Suwayf','EGY','Bani Suwayf',172032);
+INSERT INTO City VALUES (628,'Qina','EGY','Qina',171275);
+INSERT INTO City VALUES (629,'Sawhaj','EGY','Sawhaj',170125);
+INSERT INTO City VALUES (630,'Shibin al-Kawm','EGY','al-Minufiya',159909);
+INSERT INTO City VALUES (631,'Bulaq al-Dakrur','EGY','Giza',148787);
+INSERT INTO City VALUES (632,'Banha','EGY','al-Qalyubiya',145792);
+INSERT INTO City VALUES (633,'Warraq al-Arab','EGY','Giza',127108);
+INSERT INTO City VALUES (634,'Kafr al-Shaykh','EGY','Kafr al-Shaykh',124819);
+INSERT INTO City VALUES (635,'Mallawi','EGY','al-Minya',119283);
+INSERT INTO City VALUES (636,'Bilbays','EGY','al-Sharqiya',113608);
+INSERT INTO City VALUES (637,'Mit Ghamr','EGY','al-Daqahliya',101801);
+INSERT INTO City VALUES (638,'al-Arish','EGY','Shamal Sina',100447);
+INSERT INTO City VALUES (639,'Talkha','EGY','al-Daqahliya',97700);
+INSERT INTO City VALUES (640,'Qalyub','EGY','al-Qalyubiya',97200);
+INSERT INTO City VALUES (641,'Jirja','EGY','Sawhaj',95400);
+INSERT INTO City VALUES (642,'Idfu','EGY','Qina',94200);
+INSERT INTO City VALUES (643,'al-Hawamidiya','EGY','Giza',91700);
+INSERT INTO City VALUES (644,'Disuq','EGY','Kafr al-Shaykh',91300);
+INSERT INTO City VALUES (645,'San Salvador','SLV','San Salvador',415346);
+INSERT INTO City VALUES (646,'Santa Ana','SLV','Santa Ana',139389);
+INSERT INTO City VALUES (647,'Mejicanos','SLV','San Salvador',138800);
+INSERT INTO City VALUES (648,'Soyapango','SLV','San Salvador',129800);
+INSERT INTO City VALUES (649,'San Miguel','SLV','San Miguel',127696);
+INSERT INTO City VALUES (650,'Nueva San Salvador','SLV','La Libertad',98400);
+INSERT INTO City VALUES (651,'Apopa','SLV','San Salvador',88800);
+INSERT INTO City VALUES (652,'Asmara','ERI','Maekel',431000);
+INSERT INTO City VALUES (653,'Madrid','ESP','Madrid',2879052);
+INSERT INTO City VALUES (654,'Barcelona','ESP','Katalonia',1503451);
+INSERT INTO City VALUES (655,'Valencia','ESP','Valencia',739412);
+INSERT INTO City VALUES (656,'Sevilla','ESP','Andalusia',701927);
+INSERT INTO City VALUES (657,'Zaragoza','ESP','Aragonia',603367);
+INSERT INTO City VALUES (658,'Málaga','ESP','Andalusia',530553);
+INSERT INTO City VALUES (659,'Bilbao','ESP','Baskimaa',357589);
+INSERT INTO City VALUES (660,'Las Palmas de Gran Canaria','ESP','Canary Islands',354757);
+INSERT INTO City VALUES (661,'Murcia','ESP','Murcia',353504);
+INSERT INTO City VALUES (662,'Palma de Mallorca','ESP','Balears',326993);
+INSERT INTO City VALUES (663,'Valladolid','ESP','Castilla and León',319998);
+INSERT INTO City VALUES (664,'Córdoba','ESP','Andalusia',311708);
+INSERT INTO City VALUES (665,'Vigo','ESP','Galicia',283670);
+INSERT INTO City VALUES (666,'Alicante [Alacant]','ESP','Valencia',272432);
+INSERT INTO City VALUES (667,'Gijón','ESP','Asturia',267980);
+INSERT INTO City VALUES (668,'L´Hospitalet de Llobregat','ESP','Katalonia',247986);
+INSERT INTO City VALUES (669,'Granada','ESP','Andalusia',244767);
+INSERT INTO City VALUES (670,'A Coruña (La Coruña)','ESP','Galicia',243402);
+INSERT INTO City VALUES (671,'Vitoria-Gasteiz','ESP','Baskimaa',217154);
+INSERT INTO City VALUES (672,'Santa Cruz de Tenerife','ESP','Canary Islands',213050);
+INSERT INTO City VALUES (673,'Badalona','ESP','Katalonia',209635);
+INSERT INTO City VALUES (674,'Oviedo','ESP','Asturia',200453);
+INSERT INTO City VALUES (675,'Móstoles','ESP','Madrid',195351);
+INSERT INTO City VALUES (676,'Elche [Elx]','ESP','Valencia',193174);
+INSERT INTO City VALUES (677,'Sabadell','ESP','Katalonia',184859);
+INSERT INTO City VALUES (678,'Santander','ESP','Cantabria',184165);
+INSERT INTO City VALUES (679,'Jerez de la Frontera','ESP','Andalusia',182660);
+INSERT INTO City VALUES (680,'Pamplona [Iruña]','ESP','Navarra',180483);
+INSERT INTO City VALUES (681,'Donostia-San Sebastián','ESP','Baskimaa',179208);
+INSERT INTO City VALUES (682,'Cartagena','ESP','Murcia',177709);
+INSERT INTO City VALUES (683,'Leganés','ESP','Madrid',173163);
+INSERT INTO City VALUES (684,'Fuenlabrada','ESP','Madrid',171173);
+INSERT INTO City VALUES (685,'Almería','ESP','Andalusia',169027);
+INSERT INTO City VALUES (686,'Terrassa','ESP','Katalonia',168695);
+INSERT INTO City VALUES (687,'Alcalá de Henares','ESP','Madrid',164463);
+INSERT INTO City VALUES (688,'Burgos','ESP','Castilla and León',162802);
+INSERT INTO City VALUES (689,'Salamanca','ESP','Castilla and León',158720);
+INSERT INTO City VALUES (690,'Albacete','ESP','Kastilia-La Mancha',147527);
+INSERT INTO City VALUES (691,'Getafe','ESP','Madrid',145371);
+INSERT INTO City VALUES (692,'Cádiz','ESP','Andalusia',142449);
+INSERT INTO City VALUES (693,'Alcorcón','ESP','Madrid',142048);
+INSERT INTO City VALUES (694,'Huelva','ESP','Andalusia',140583);
+INSERT INTO City VALUES (695,'León','ESP','Castilla and León',139809);
+INSERT INTO City VALUES (696,'Castellón de la Plana [Castell','ESP','Valencia',139712);
+INSERT INTO City VALUES (697,'Badajoz','ESP','Extremadura',136613);
+INSERT INTO City VALUES (698,'[San Cristóbal de] la Laguna','ESP','Canary Islands',127945);
+INSERT INTO City VALUES (699,'Logroño','ESP','La Rioja',127093);
+INSERT INTO City VALUES (700,'Santa Coloma de Gramenet','ESP','Katalonia',120802);
+INSERT INTO City VALUES (701,'Tarragona','ESP','Katalonia',113016);
+INSERT INTO City VALUES (702,'Lleida (Lérida)','ESP','Katalonia',112207);
+INSERT INTO City VALUES (703,'Jaén','ESP','Andalusia',109247);
+INSERT INTO City VALUES (704,'Ourense (Orense)','ESP','Galicia',109120);
+INSERT INTO City VALUES (705,'Mataró','ESP','Katalonia',104095);
+INSERT INTO City VALUES (706,'Algeciras','ESP','Andalusia',103106);
+INSERT INTO City VALUES (707,'Marbella','ESP','Andalusia',101144);
+INSERT INTO City VALUES (708,'Barakaldo','ESP','Baskimaa',98212);
+INSERT INTO City VALUES (709,'Dos Hermanas','ESP','Andalusia',94591);
+INSERT INTO City VALUES (710,'Santiago de Compostela','ESP','Galicia',93745);
+INSERT INTO City VALUES (711,'Torrejón de Ardoz','ESP','Madrid',92262);
+INSERT INTO City VALUES (712,'Cape Town','ZAF','Western Cape',2352121);
+INSERT INTO City VALUES (713,'Soweto','ZAF','Gauteng',904165);
+INSERT INTO City VALUES (714,'Johannesburg','ZAF','Gauteng',756653);
+INSERT INTO City VALUES (715,'Port Elizabeth','ZAF','Eastern Cape',752319);
+INSERT INTO City VALUES (716,'Pretoria','ZAF','Gauteng',658630);
+INSERT INTO City VALUES (717,'Inanda','ZAF','KwaZulu-Natal',634065);
+INSERT INTO City VALUES (718,'Durban','ZAF','KwaZulu-Natal',566120);
+INSERT INTO City VALUES (719,'Vanderbijlpark','ZAF','Gauteng',468931);
+INSERT INTO City VALUES (720,'Kempton Park','ZAF','Gauteng',442633);
+INSERT INTO City VALUES (721,'Alberton','ZAF','Gauteng',410102);
+INSERT INTO City VALUES (722,'Pinetown','ZAF','KwaZulu-Natal',378810);
+INSERT INTO City VALUES (723,'Pietermaritzburg','ZAF','KwaZulu-Natal',370190);
+INSERT INTO City VALUES (724,'Benoni','ZAF','Gauteng',365467);
+INSERT INTO City VALUES (725,'Randburg','ZAF','Gauteng',341288);
+INSERT INTO City VALUES (726,'Umlazi','ZAF','KwaZulu-Natal',339233);
+INSERT INTO City VALUES (727,'Bloemfontein','ZAF','Free State',334341);
+INSERT INTO City VALUES (728,'Vereeniging','ZAF','Gauteng',328535);
+INSERT INTO City VALUES (729,'Wonderboom','ZAF','Gauteng',283289);
+INSERT INTO City VALUES (730,'Roodepoort','ZAF','Gauteng',279340);
+INSERT INTO City VALUES (731,'Boksburg','ZAF','Gauteng',262648);
+INSERT INTO City VALUES (732,'Klerksdorp','ZAF','North West',261911);
+INSERT INTO City VALUES (733,'Soshanguve','ZAF','Gauteng',242727);
+INSERT INTO City VALUES (734,'Newcastle','ZAF','KwaZulu-Natal',222993);
+INSERT INTO City VALUES (735,'East London','ZAF','Eastern Cape',221047);
+INSERT INTO City VALUES (736,'Welkom','ZAF','Free State',203296);
+INSERT INTO City VALUES (737,'Kimberley','ZAF','Northern Cape',197254);
+INSERT INTO City VALUES (738,'Uitenhage','ZAF','Eastern Cape',192120);
+INSERT INTO City VALUES (739,'Chatsworth','ZAF','KwaZulu-Natal',189885);
+INSERT INTO City VALUES (740,'Mdantsane','ZAF','Eastern Cape',182639);
+INSERT INTO City VALUES (741,'Krugersdorp','ZAF','Gauteng',181503);
+INSERT INTO City VALUES (742,'Botshabelo','ZAF','Free State',177971);
+INSERT INTO City VALUES (743,'Brakpan','ZAF','Gauteng',171363);
+INSERT INTO City VALUES (744,'Witbank','ZAF','Mpumalanga',167183);
+INSERT INTO City VALUES (745,'Oberholzer','ZAF','Gauteng',164367);
+INSERT INTO City VALUES (746,'Germiston','ZAF','Gauteng',164252);
+INSERT INTO City VALUES (747,'Springs','ZAF','Gauteng',162072);
+INSERT INTO City VALUES (748,'Westonaria','ZAF','Gauteng',159632);
+INSERT INTO City VALUES (749,'Randfontein','ZAF','Gauteng',120838);
+INSERT INTO City VALUES (750,'Paarl','ZAF','Western Cape',105768);
+INSERT INTO City VALUES (751,'Potchefstroom','ZAF','North West',101817);
+INSERT INTO City VALUES (752,'Rustenburg','ZAF','North West',97008);
+INSERT INTO City VALUES (753,'Nigel','ZAF','Gauteng',96734);
+INSERT INTO City VALUES (754,'George','ZAF','Western Cape',93818);
+INSERT INTO City VALUES (755,'Ladysmith','ZAF','KwaZulu-Natal',89292);
+INSERT INTO City VALUES (756,'Addis Abeba','ETH','Addis Abeba',2495000);
+INSERT INTO City VALUES (757,'Dire Dawa','ETH','Dire Dawa',164851);
+INSERT INTO City VALUES (758,'Nazret','ETH','Oromia',127842);
+INSERT INTO City VALUES (759,'Gonder','ETH','Amhara',112249);
+INSERT INTO City VALUES (760,'Dese','ETH','Amhara',97314);
+INSERT INTO City VALUES (761,'Mekele','ETH','Tigray',96938);
+INSERT INTO City VALUES (762,'Bahir Dar','ETH','Amhara',96140);
+INSERT INTO City VALUES (763,'Stanley','FLK','East Falkland',1636);
+INSERT INTO City VALUES (764,'Suva','FJI','Central',77366);
+INSERT INTO City VALUES (765,'Quezon','PHL','National Capital Reg',2173831);
+INSERT INTO City VALUES (766,'Manila','PHL','National Capital Reg',1581082);
+INSERT INTO City VALUES (767,'Kalookan','PHL','National Capital Reg',1177604);
+INSERT INTO City VALUES (768,'Davao','PHL','Southern Mindanao',1147116);
+INSERT INTO City VALUES (769,'Cebu','PHL','Central Visayas',718821);
+INSERT INTO City VALUES (770,'Zamboanga','PHL','Western Mindanao',601794);
+INSERT INTO City VALUES (771,'Pasig','PHL','National Capital Reg',505058);
+INSERT INTO City VALUES (772,'Valenzuela','PHL','National Capital Reg',485433);
+INSERT INTO City VALUES (773,'Las Piñas','PHL','National Capital Reg',472780);
+INSERT INTO City VALUES (774,'Antipolo','PHL','Southern Tagalog',470866);
+INSERT INTO City VALUES (775,'Taguig','PHL','National Capital Reg',467375);
+INSERT INTO City VALUES (776,'Cagayan de Oro','PHL','Northern Mindanao',461877);
+INSERT INTO City VALUES (777,'Parañaque','PHL','National Capital Reg',449811);
+INSERT INTO City VALUES (778,'Makati','PHL','National Capital Reg',444867);
+INSERT INTO City VALUES (779,'Bacolod','PHL','Western Visayas',429076);
+INSERT INTO City VALUES (780,'General Santos','PHL','Southern Mindanao',411822);
+INSERT INTO City VALUES (781,'Marikina','PHL','National Capital Reg',391170);
+INSERT INTO City VALUES (782,'Dasmariñas','PHL','Southern Tagalog',379520);
+INSERT INTO City VALUES (783,'Muntinlupa','PHL','National Capital Reg',379310);
+INSERT INTO City VALUES (784,'Iloilo','PHL','Western Visayas',365820);
+INSERT INTO City VALUES (785,'Pasay','PHL','National Capital Reg',354908);
+INSERT INTO City VALUES (786,'Malabon','PHL','National Capital Reg',338855);
+INSERT INTO City VALUES (787,'San José del Monte','PHL','Central Luzon',315807);
+INSERT INTO City VALUES (788,'Bacoor','PHL','Southern Tagalog',305699);
+INSERT INTO City VALUES (789,'Iligan','PHL','Central Mindanao',285061);
+INSERT INTO City VALUES (790,'Calamba','PHL','Southern Tagalog',281146);
+INSERT INTO City VALUES (791,'Mandaluyong','PHL','National Capital Reg',278474);
+INSERT INTO City VALUES (792,'Butuan','PHL','Caraga',267279);
+INSERT INTO City VALUES (793,'Angeles','PHL','Central Luzon',263971);
+INSERT INTO City VALUES (794,'Tarlac','PHL','Central Luzon',262481);
+INSERT INTO City VALUES (795,'Mandaue','PHL','Central Visayas',259728);
+INSERT INTO City VALUES (796,'Baguio','PHL','CAR',252386);
+INSERT INTO City VALUES (797,'Batangas','PHL','Southern Tagalog',247588);
+INSERT INTO City VALUES (798,'Cainta','PHL','Southern Tagalog',242511);
+INSERT INTO City VALUES (799,'San Pedro','PHL','Southern Tagalog',231403);
+INSERT INTO City VALUES (800,'Navotas','PHL','National Capital Reg',230403);
+INSERT INTO City VALUES (801,'Cabanatuan','PHL','Central Luzon',222859);
+INSERT INTO City VALUES (802,'San Fernando','PHL','Central Luzon',221857);
+INSERT INTO City VALUES (803,'Lipa','PHL','Southern Tagalog',218447);
+INSERT INTO City VALUES (804,'Lapu-Lapu','PHL','Central Visayas',217019);
+INSERT INTO City VALUES (805,'San Pablo','PHL','Southern Tagalog',207927);
+INSERT INTO City VALUES (806,'Biñan','PHL','Southern Tagalog',201186);
+INSERT INTO City VALUES (807,'Taytay','PHL','Southern Tagalog',198183);
+INSERT INTO City VALUES (808,'Lucena','PHL','Southern Tagalog',196075);
+INSERT INTO City VALUES (809,'Imus','PHL','Southern Tagalog',195482);
+INSERT INTO City VALUES (810,'Olongapo','PHL','Central Luzon',194260);
+INSERT INTO City VALUES (811,'Binangonan','PHL','Southern Tagalog',187691);
+INSERT INTO City VALUES (812,'Santa Rosa','PHL','Southern Tagalog',185633);
+INSERT INTO City VALUES (813,'Tagum','PHL','Southern Mindanao',179531);
+INSERT INTO City VALUES (814,'Tacloban','PHL','Eastern Visayas',178639);
+INSERT INTO City VALUES (815,'Malolos','PHL','Central Luzon',175291);
+INSERT INTO City VALUES (816,'Mabalacat','PHL','Central Luzon',171045);
+INSERT INTO City VALUES (817,'Cotabato','PHL','Central Mindanao',163849);
+INSERT INTO City VALUES (818,'Meycauayan','PHL','Central Luzon',163037);
+INSERT INTO City VALUES (819,'Puerto Princesa','PHL','Southern Tagalog',161912);
+INSERT INTO City VALUES (820,'Legazpi','PHL','Bicol',157010);
+INSERT INTO City VALUES (821,'Silang','PHL','Southern Tagalog',156137);
+INSERT INTO City VALUES (822,'Ormoc','PHL','Eastern Visayas',154297);
+INSERT INTO City VALUES (823,'San Carlos','PHL','Ilocos',154264);
+INSERT INTO City VALUES (824,'Kabankalan','PHL','Western Visayas',149769);
+INSERT INTO City VALUES (825,'Talisay','PHL','Central Visayas',148110);
+INSERT INTO City VALUES (826,'Valencia','PHL','Northern Mindanao',147924);
+INSERT INTO City VALUES (827,'Calbayog','PHL','Eastern Visayas',147187);
+INSERT INTO City VALUES (828,'Santa Maria','PHL','Central Luzon',144282);
+INSERT INTO City VALUES (829,'Pagadian','PHL','Western Mindanao',142515);
+INSERT INTO City VALUES (830,'Cadiz','PHL','Western Visayas',141954);
+INSERT INTO City VALUES (831,'Bago','PHL','Western Visayas',141721);
+INSERT INTO City VALUES (832,'Toledo','PHL','Central Visayas',141174);
+INSERT INTO City VALUES (833,'Naga','PHL','Bicol',137810);
+INSERT INTO City VALUES (834,'San Mateo','PHL','Southern Tagalog',135603);
+INSERT INTO City VALUES (835,'Panabo','PHL','Southern Mindanao',133950);
+INSERT INTO City VALUES (836,'Koronadal','PHL','Southern Mindanao',133786);
+INSERT INTO City VALUES (837,'Marawi','PHL','Central Mindanao',131090);
+INSERT INTO City VALUES (838,'Dagupan','PHL','Ilocos',130328);
+INSERT INTO City VALUES (839,'Sagay','PHL','Western Visayas',129765);
+INSERT INTO City VALUES (840,'Roxas','PHL','Western Visayas',126352);
+INSERT INTO City VALUES (841,'Lubao','PHL','Central Luzon',125699);
+INSERT INTO City VALUES (842,'Digos','PHL','Southern Mindanao',125171);
+INSERT INTO City VALUES (843,'San Miguel','PHL','Central Luzon',123824);
+INSERT INTO City VALUES (844,'Malaybalay','PHL','Northern Mindanao',123672);
+INSERT INTO City VALUES (845,'Tuguegarao','PHL','Cagayan Valley',120645);
+INSERT INTO City VALUES (846,'Ilagan','PHL','Cagayan Valley',119990);
+INSERT INTO City VALUES (847,'Baliuag','PHL','Central Luzon',119675);
+INSERT INTO City VALUES (848,'Surigao','PHL','Caraga',118534);
+INSERT INTO City VALUES (849,'San Carlos','PHL','Western Visayas',118259);
+INSERT INTO City VALUES (850,'San Juan del Monte','PHL','National Capital Reg',117680);
+INSERT INTO City VALUES (851,'Tanauan','PHL','Southern Tagalog',117539);
+INSERT INTO City VALUES (852,'Concepcion','PHL','Central Luzon',115171);
+INSERT INTO City VALUES (853,'Rodriguez (Montalban)','PHL','Southern Tagalog',115167);
+INSERT INTO City VALUES (854,'Sariaya','PHL','Southern Tagalog',114568);
+INSERT INTO City VALUES (855,'Malasiqui','PHL','Ilocos',113190);
+INSERT INTO City VALUES (856,'General Mariano Alvarez','PHL','Southern Tagalog',112446);
+INSERT INTO City VALUES (857,'Urdaneta','PHL','Ilocos',111582);
+INSERT INTO City VALUES (858,'Hagonoy','PHL','Central Luzon',111425);
+INSERT INTO City VALUES (859,'San Jose','PHL','Southern Tagalog',111009);
+INSERT INTO City VALUES (860,'Polomolok','PHL','Southern Mindanao',110709);
+INSERT INTO City VALUES (861,'Santiago','PHL','Cagayan Valley',110531);
+INSERT INTO City VALUES (862,'Tanza','PHL','Southern Tagalog',110517);
+INSERT INTO City VALUES (863,'Ozamis','PHL','Northern Mindanao',110420);
+INSERT INTO City VALUES (864,'Mexico','PHL','Central Luzon',109481);
+INSERT INTO City VALUES (865,'San Jose','PHL','Central Luzon',108254);
+INSERT INTO City VALUES (866,'Silay','PHL','Western Visayas',107722);
+INSERT INTO City VALUES (867,'General Trias','PHL','Southern Tagalog',107691);
+INSERT INTO City VALUES (868,'Tabaco','PHL','Bicol',107166);
+INSERT INTO City VALUES (869,'Cabuyao','PHL','Southern Tagalog',106630);
+INSERT INTO City VALUES (870,'Calapan','PHL','Southern Tagalog',105910);
+INSERT INTO City VALUES (871,'Mati','PHL','Southern Mindanao',105908);
+INSERT INTO City VALUES (872,'Midsayap','PHL','Central Mindanao',105760);
+INSERT INTO City VALUES (873,'Cauayan','PHL','Cagayan Valley',103952);
+INSERT INTO City VALUES (874,'Gingoog','PHL','Northern Mindanao',102379);
+INSERT INTO City VALUES (875,'Dumaguete','PHL','Central Visayas',102265);
+INSERT INTO City VALUES (876,'San Fernando','PHL','Ilocos',102082);
+INSERT INTO City VALUES (877,'Arayat','PHL','Central Luzon',101792);
+INSERT INTO City VALUES (878,'Bayawan (Tulong)','PHL','Central Visayas',101391);
+INSERT INTO City VALUES (879,'Kidapawan','PHL','Central Mindanao',101205);
+INSERT INTO City VALUES (880,'Daraga (Locsin)','PHL','Bicol',101031);
+INSERT INTO City VALUES (881,'Marilao','PHL','Central Luzon',101017);
+INSERT INTO City VALUES (882,'Malita','PHL','Southern Mindanao',100000);
+INSERT INTO City VALUES (883,'Dipolog','PHL','Western Mindanao',99862);
+INSERT INTO City VALUES (884,'Cavite','PHL','Southern Tagalog',99367);
+INSERT INTO City VALUES (885,'Danao','PHL','Central Visayas',98781);
+INSERT INTO City VALUES (886,'Bislig','PHL','Caraga',97860);
+INSERT INTO City VALUES (887,'Talavera','PHL','Central Luzon',97329);
+INSERT INTO City VALUES (888,'Guagua','PHL','Central Luzon',96858);
+INSERT INTO City VALUES (889,'Bayambang','PHL','Ilocos',96609);
+INSERT INTO City VALUES (890,'Nasugbu','PHL','Southern Tagalog',96113);
+INSERT INTO City VALUES (891,'Baybay','PHL','Eastern Visayas',95630);
+INSERT INTO City VALUES (892,'Capas','PHL','Central Luzon',95219);
+INSERT INTO City VALUES (893,'Sultan Kudarat','PHL','ARMM',94861);
+INSERT INTO City VALUES (894,'Laoag','PHL','Ilocos',94466);
+INSERT INTO City VALUES (895,'Bayugan','PHL','Caraga',93623);
+INSERT INTO City VALUES (896,'Malungon','PHL','Southern Mindanao',93232);
+INSERT INTO City VALUES (897,'Santa Cruz','PHL','Southern Tagalog',92694);
+INSERT INTO City VALUES (898,'Sorsogon','PHL','Bicol',92512);
+INSERT INTO City VALUES (899,'Candelaria','PHL','Southern Tagalog',92429);
+INSERT INTO City VALUES (900,'Ligao','PHL','Bicol',90603);
+INSERT INTO City VALUES (901,'Tórshavn','FRO','Streymoyar',14542);
+INSERT INTO City VALUES (902,'Libreville','GAB','Estuaire',419000);
+INSERT INTO City VALUES (903,'Serekunda','GMB','Kombo St Mary',102600);
+INSERT INTO City VALUES (904,'Banjul','GMB','Banjul',42326);
+INSERT INTO City VALUES (905,'Tbilisi','GEO','Tbilisi',1235200);
+INSERT INTO City VALUES (906,'Kutaisi','GEO','Imereti',240900);
+INSERT INTO City VALUES (907,'Rustavi','GEO','Kvemo Kartli',155400);
+INSERT INTO City VALUES (908,'Batumi','GEO','Adzaria [Atšara]',137700);
+INSERT INTO City VALUES (909,'Sohumi','GEO','Abhasia [Aphazeti]',111700);
+INSERT INTO City VALUES (910,'Accra','GHA','Greater Accra',1070000);
+INSERT INTO City VALUES (911,'Kumasi','GHA','Ashanti',385192);
+INSERT INTO City VALUES (912,'Tamale','GHA','Northern',151069);
+INSERT INTO City VALUES (913,'Tema','GHA','Greater Accra',109975);
+INSERT INTO City VALUES (914,'Sekondi-Takoradi','GHA','Western',103653);
+INSERT INTO City VALUES (915,'Gibraltar','GIB','–',27025);
+INSERT INTO City VALUES (916,'Saint George´s','GRD','St George',4621);
+INSERT INTO City VALUES (917,'Nuuk','GRL','Kitaa',13445);
+INSERT INTO City VALUES (918,'Les Abymes','GLP','Grande-Terre',62947);
+INSERT INTO City VALUES (919,'Basse-Terre','GLP','Basse-Terre',12433);
+INSERT INTO City VALUES (920,'Tamuning','GUM','–',9500);
+INSERT INTO City VALUES (921,'Agaña','GUM','–',1139);
+INSERT INTO City VALUES (922,'Ciudad de Guatemala','GTM','Guatemala',823301);
+INSERT INTO City VALUES (923,'Mixco','GTM','Guatemala',209791);
+INSERT INTO City VALUES (924,'Villa Nueva','GTM','Guatemala',101295);
+INSERT INTO City VALUES (925,'Quetzaltenango','GTM','Quetzaltenango',90801);
+INSERT INTO City VALUES (926,'Conakry','GIN','Conakry',1090610);
+INSERT INTO City VALUES (927,'Bissau','GNB','Bissau',241000);
+INSERT INTO City VALUES (928,'Georgetown','GUY','Georgetown',254000);
+INSERT INTO City VALUES (929,'Port-au-Prince','HTI','Ouest',884472);
+INSERT INTO City VALUES (930,'Carrefour','HTI','Ouest',290204);
+INSERT INTO City VALUES (931,'Delmas','HTI','Ouest',240429);
+INSERT INTO City VALUES (932,'Le-Cap-Haïtien','HTI','Nord',102233);
+INSERT INTO City VALUES (933,'Tegucigalpa','HND','Distrito Central',813900);
+INSERT INTO City VALUES (934,'San Pedro Sula','HND','Cortés',383900);
+INSERT INTO City VALUES (935,'La Ceiba','HND','Atlántida',89200);
+INSERT INTO City VALUES (936,'Kowloon and New Kowloon','HKG','Kowloon and New Kowl',1987996);
+INSERT INTO City VALUES (937,'Victoria','HKG','Hongkong',1312637);
+INSERT INTO City VALUES (938,'Longyearbyen','SJM','Länsimaa',1438);
+INSERT INTO City VALUES (939,'Jakarta','IDN','Jakarta Raya',9604900);
+INSERT INTO City VALUES (940,'Surabaya','IDN','East Java',2663820);
+INSERT INTO City VALUES (941,'Bandung','IDN','West Java',2429000);
+INSERT INTO City VALUES (942,'Medan','IDN','Sumatera Utara',1843919);
+INSERT INTO City VALUES (943,'Palembang','IDN','Sumatera Selatan',1222764);
+INSERT INTO City VALUES (944,'Tangerang','IDN','West Java',1198300);
+INSERT INTO City VALUES (945,'Semarang','IDN','Central Java',1104405);
+INSERT INTO City VALUES (946,'Ujung Pandang','IDN','Sulawesi Selatan',1060257);
+INSERT INTO City VALUES (947,'Malang','IDN','East Java',716862);
+INSERT INTO City VALUES (948,'Bandar Lampung','IDN','Lampung',680332);
+INSERT INTO City VALUES (949,'Bekasi','IDN','West Java',644300);
+INSERT INTO City VALUES (950,'Padang','IDN','Sumatera Barat',534474);
+INSERT INTO City VALUES (951,'Surakarta','IDN','Central Java',518600);
+INSERT INTO City VALUES (952,'Banjarmasin','IDN','Kalimantan Selatan',482931);
+INSERT INTO City VALUES (953,'Pekan Baru','IDN','Riau',438638);
+INSERT INTO City VALUES (954,'Denpasar','IDN','Bali',435000);
+INSERT INTO City VALUES (955,'Yogyakarta','IDN','Yogyakarta',418944);
+INSERT INTO City VALUES (956,'Pontianak','IDN','Kalimantan Barat',409632);
+INSERT INTO City VALUES (957,'Samarinda','IDN','Kalimantan Timur',399175);
+INSERT INTO City VALUES (958,'Jambi','IDN','Jambi',385201);
+INSERT INTO City VALUES (959,'Depok','IDN','West Java',365200);
+INSERT INTO City VALUES (960,'Cimahi','IDN','West Java',344600);
+INSERT INTO City VALUES (961,'Balikpapan','IDN','Kalimantan Timur',338752);
+INSERT INTO City VALUES (962,'Manado','IDN','Sulawesi Utara',332288);
+INSERT INTO City VALUES (963,'Mataram','IDN','Nusa Tenggara Barat',306600);
+INSERT INTO City VALUES (964,'Pekalongan','IDN','Central Java',301504);
+INSERT INTO City VALUES (965,'Tegal','IDN','Central Java',289744);
+INSERT INTO City VALUES (966,'Bogor','IDN','West Java',285114);
+INSERT INTO City VALUES (967,'Ciputat','IDN','West Java',270800);
+INSERT INTO City VALUES (968,'Pondokgede','IDN','West Java',263200);
+INSERT INTO City VALUES (969,'Cirebon','IDN','West Java',254406);
+INSERT INTO City VALUES (970,'Kediri','IDN','East Java',253760);
+INSERT INTO City VALUES (971,'Ambon','IDN','Molukit',249312);
+INSERT INTO City VALUES (972,'Jember','IDN','East Java',218500);
+INSERT INTO City VALUES (973,'Cilacap','IDN','Central Java',206900);
+INSERT INTO City VALUES (974,'Cimanggis','IDN','West Java',205100);
+INSERT INTO City VALUES (975,'Pematang Siantar','IDN','Sumatera Utara',203056);
+INSERT INTO City VALUES (976,'Purwokerto','IDN','Central Java',202500);
+INSERT INTO City VALUES (977,'Ciomas','IDN','West Java',187400);
+INSERT INTO City VALUES (978,'Tasikmalaya','IDN','West Java',179800);
+INSERT INTO City VALUES (979,'Madiun','IDN','East Java',171532);
+INSERT INTO City VALUES (980,'Bengkulu','IDN','Bengkulu',146439);
+INSERT INTO City VALUES (981,'Karawang','IDN','West Java',145000);
+INSERT INTO City VALUES (982,'Banda Aceh','IDN','Aceh',143409);
+INSERT INTO City VALUES (983,'Palu','IDN','Sulawesi Tengah',142800);
+INSERT INTO City VALUES (984,'Pasuruan','IDN','East Java',134019);
+INSERT INTO City VALUES (985,'Kupang','IDN','Nusa Tenggara Timur',129300);
+INSERT INTO City VALUES (986,'Tebing Tinggi','IDN','Sumatera Utara',129300);
+INSERT INTO City VALUES (987,'Percut Sei Tuan','IDN','Sumatera Utara',129000);
+INSERT INTO City VALUES (988,'Binjai','IDN','Sumatera Utara',127222);
+INSERT INTO City VALUES (989,'Sukabumi','IDN','West Java',125766);
+INSERT INTO City VALUES (990,'Waru','IDN','East Java',124300);
+INSERT INTO City VALUES (991,'Pangkal Pinang','IDN','Sumatera Selatan',124000);
+INSERT INTO City VALUES (992,'Magelang','IDN','Central Java',123800);
+INSERT INTO City VALUES (993,'Blitar','IDN','East Java',122600);
+INSERT INTO City VALUES (994,'Serang','IDN','West Java',122400);
+INSERT INTO City VALUES (995,'Probolinggo','IDN','East Java',120770);
+INSERT INTO City VALUES (996,'Cilegon','IDN','West Java',117000);
+INSERT INTO City VALUES (997,'Cianjur','IDN','West Java',114300);
+INSERT INTO City VALUES (998,'Ciparay','IDN','West Java',111500);
+INSERT INTO City VALUES (999,'Lhokseumawe','IDN','Aceh',109600);
+INSERT INTO City VALUES (1000,'Taman','IDN','East Java',107000);
+INSERT INTO City VALUES (1001,'Depok','IDN','Yogyakarta',106800);
+INSERT INTO City VALUES (1002,'Citeureup','IDN','West Java',105100);
+INSERT INTO City VALUES (1003,'Pemalang','IDN','Central Java',103500);
+INSERT INTO City VALUES (1004,'Klaten','IDN','Central Java',103300);
+INSERT INTO City VALUES (1005,'Salatiga','IDN','Central Java',103000);
+INSERT INTO City VALUES (1006,'Cibinong','IDN','West Java',101300);
+INSERT INTO City VALUES (1007,'Palangka Raya','IDN','Kalimantan Tengah',99693);
+INSERT INTO City VALUES (1008,'Mojokerto','IDN','East Java',96626);
+INSERT INTO City VALUES (1009,'Purwakarta','IDN','West Java',95900);
+INSERT INTO City VALUES (1010,'Garut','IDN','West Java',95800);
+INSERT INTO City VALUES (1011,'Kudus','IDN','Central Java',95300);
+INSERT INTO City VALUES (1012,'Kendari','IDN','Sulawesi Tenggara',94800);
+INSERT INTO City VALUES (1013,'Jaya Pura','IDN','West Irian',94700);
+INSERT INTO City VALUES (1014,'Gorontalo','IDN','Sulawesi Utara',94058);
+INSERT INTO City VALUES (1015,'Majalaya','IDN','West Java',93200);
+INSERT INTO City VALUES (1016,'Pondok Aren','IDN','West Java',92700);
+INSERT INTO City VALUES (1017,'Jombang','IDN','East Java',92600);
+INSERT INTO City VALUES (1018,'Sunggal','IDN','Sumatera Utara',92300);
+INSERT INTO City VALUES (1019,'Batam','IDN','Riau',91871);
+INSERT INTO City VALUES (1020,'Padang Sidempuan','IDN','Sumatera Utara',91200);
+INSERT INTO City VALUES (1021,'Sawangan','IDN','West Java',91100);
+INSERT INTO City VALUES (1022,'Banyuwangi','IDN','East Java',89900);
+INSERT INTO City VALUES (1023,'Tanjung Pinang','IDN','Riau',89900);
+INSERT INTO City VALUES (1024,'Mumbai (Bombay)','IND','Maharashtra',10500000);
+INSERT INTO City VALUES (1025,'Delhi','IND','Delhi',7206704);
+INSERT INTO City VALUES (1026,'Calcutta [Kolkata]','IND','West Bengali',4399819);
+INSERT INTO City VALUES (1027,'Chennai (Madras)','IND','Tamil Nadu',3841396);
+INSERT INTO City VALUES (1028,'Hyderabad','IND','Andhra Pradesh',2964638);
+INSERT INTO City VALUES (1029,'Ahmedabad','IND','Gujarat',2876710);
+INSERT INTO City VALUES (1030,'Bangalore','IND','Karnataka',2660088);
+INSERT INTO City VALUES (1031,'Kanpur','IND','Uttar Pradesh',1874409);
+INSERT INTO City VALUES (1032,'Nagpur','IND','Maharashtra',1624752);
+INSERT INTO City VALUES (1033,'Lucknow','IND','Uttar Pradesh',1619115);
+INSERT INTO City VALUES (1034,'Pune','IND','Maharashtra',1566651);
+INSERT INTO City VALUES (1035,'Surat','IND','Gujarat',1498817);
+INSERT INTO City VALUES (1036,'Jaipur','IND','Rajasthan',1458483);
+INSERT INTO City VALUES (1037,'Indore','IND','Madhya Pradesh',1091674);
+INSERT INTO City VALUES (1038,'Bhopal','IND','Madhya Pradesh',1062771);
+INSERT INTO City VALUES (1039,'Ludhiana','IND','Punjab',1042740);
+INSERT INTO City VALUES (1040,'Vadodara (Baroda)','IND','Gujarat',1031346);
+INSERT INTO City VALUES (1041,'Kalyan','IND','Maharashtra',1014557);
+INSERT INTO City VALUES (1042,'Madurai','IND','Tamil Nadu',977856);
+INSERT INTO City VALUES (1043,'Haora (Howrah)','IND','West Bengali',950435);
+INSERT INTO City VALUES (1044,'Varanasi (Benares)','IND','Uttar Pradesh',929270);
+INSERT INTO City VALUES (1045,'Patna','IND','Bihar',917243);
+INSERT INTO City VALUES (1046,'Srinagar','IND','Jammu and Kashmir',892506);
+INSERT INTO City VALUES (1047,'Agra','IND','Uttar Pradesh',891790);
+INSERT INTO City VALUES (1048,'Coimbatore','IND','Tamil Nadu',816321);
+INSERT INTO City VALUES (1049,'Thane (Thana)','IND','Maharashtra',803389);
+INSERT INTO City VALUES (1050,'Allahabad','IND','Uttar Pradesh',792858);
+INSERT INTO City VALUES (1051,'Meerut','IND','Uttar Pradesh',753778);
+INSERT INTO City VALUES (1052,'Vishakhapatnam','IND','Andhra Pradesh',752037);
+INSERT INTO City VALUES (1053,'Jabalpur','IND','Madhya Pradesh',741927);
+INSERT INTO City VALUES (1054,'Amritsar','IND','Punjab',708835);
+INSERT INTO City VALUES (1055,'Faridabad','IND','Haryana',703592);
+INSERT INTO City VALUES (1056,'Vijayawada','IND','Andhra Pradesh',701827);
+INSERT INTO City VALUES (1057,'Gwalior','IND','Madhya Pradesh',690765);
+INSERT INTO City VALUES (1058,'Jodhpur','IND','Rajasthan',666279);
+INSERT INTO City VALUES (1059,'Nashik (Nasik)','IND','Maharashtra',656925);
+INSERT INTO City VALUES (1060,'Hubli-Dharwad','IND','Karnataka',648298);
+INSERT INTO City VALUES (1061,'Solapur (Sholapur)','IND','Maharashtra',604215);
+INSERT INTO City VALUES (1062,'Ranchi','IND','Jharkhand',599306);
+INSERT INTO City VALUES (1063,'Bareilly','IND','Uttar Pradesh',587211);
+INSERT INTO City VALUES (1064,'Guwahati (Gauhati)','IND','Assam',584342);
+INSERT INTO City VALUES (1065,'Shambajinagar (Aurangabad)','IND','Maharashtra',573272);
+INSERT INTO City VALUES (1066,'Cochin (Kochi)','IND','Kerala',564589);
+INSERT INTO City VALUES (1067,'Rajkot','IND','Gujarat',559407);
+INSERT INTO City VALUES (1068,'Kota','IND','Rajasthan',537371);
+INSERT INTO City VALUES (1069,'Thiruvananthapuram (Trivandrum','IND','Kerala',524006);
+INSERT INTO City VALUES (1070,'Pimpri-Chinchwad','IND','Maharashtra',517083);
+INSERT INTO City VALUES (1071,'Jalandhar (Jullundur)','IND','Punjab',509510);
+INSERT INTO City VALUES (1072,'Gorakhpur','IND','Uttar Pradesh',505566);
+INSERT INTO City VALUES (1073,'Chandigarh','IND','Chandigarh',504094);
+INSERT INTO City VALUES (1074,'Mysore','IND','Karnataka',480692);
+INSERT INTO City VALUES (1075,'Aligarh','IND','Uttar Pradesh',480520);
+INSERT INTO City VALUES (1076,'Guntur','IND','Andhra Pradesh',471051);
+INSERT INTO City VALUES (1077,'Jamshedpur','IND','Jharkhand',460577);
+INSERT INTO City VALUES (1078,'Ghaziabad','IND','Uttar Pradesh',454156);
+INSERT INTO City VALUES (1079,'Warangal','IND','Andhra Pradesh',447657);
+INSERT INTO City VALUES (1080,'Raipur','IND','Chhatisgarh',438639);
+INSERT INTO City VALUES (1081,'Moradabad','IND','Uttar Pradesh',429214);
+INSERT INTO City VALUES (1082,'Durgapur','IND','West Bengali',425836);
+INSERT INTO City VALUES (1083,'Amravati','IND','Maharashtra',421576);
+INSERT INTO City VALUES (1084,'Calicut (Kozhikode)','IND','Kerala',419831);
+INSERT INTO City VALUES (1085,'Bikaner','IND','Rajasthan',416289);
+INSERT INTO City VALUES (1086,'Bhubaneswar','IND','Orissa',411542);
+INSERT INTO City VALUES (1087,'Kolhapur','IND','Maharashtra',406370);
+INSERT INTO City VALUES (1088,'Kataka (Cuttack)','IND','Orissa',403418);
+INSERT INTO City VALUES (1089,'Ajmer','IND','Rajasthan',402700);
+INSERT INTO City VALUES (1090,'Bhavnagar','IND','Gujarat',402338);
+INSERT INTO City VALUES (1091,'Tiruchirapalli','IND','Tamil Nadu',387223);
+INSERT INTO City VALUES (1092,'Bhilai','IND','Chhatisgarh',386159);
+INSERT INTO City VALUES (1093,'Bhiwandi','IND','Maharashtra',379070);
+INSERT INTO City VALUES (1094,'Saharanpur','IND','Uttar Pradesh',374945);
+INSERT INTO City VALUES (1095,'Ulhasnagar','IND','Maharashtra',369077);
+INSERT INTO City VALUES (1096,'Salem','IND','Tamil Nadu',366712);
+INSERT INTO City VALUES (1097,'Ujjain','IND','Madhya Pradesh',362266);
+INSERT INTO City VALUES (1098,'Malegaon','IND','Maharashtra',342595);
+INSERT INTO City VALUES (1099,'Jamnagar','IND','Gujarat',341637);
+INSERT INTO City VALUES (1100,'Bokaro Steel City','IND','Jharkhand',333683);
+INSERT INTO City VALUES (1101,'Akola','IND','Maharashtra',328034);
+INSERT INTO City VALUES (1102,'Belgaum','IND','Karnataka',326399);
+INSERT INTO City VALUES (1103,'Rajahmundry','IND','Andhra Pradesh',324851);
+INSERT INTO City VALUES (1104,'Nellore','IND','Andhra Pradesh',316606);
+INSERT INTO City VALUES (1105,'Udaipur','IND','Rajasthan',308571);
+INSERT INTO City VALUES (1106,'New Bombay','IND','Maharashtra',307297);
+INSERT INTO City VALUES (1107,'Bhatpara','IND','West Bengali',304952);
+INSERT INTO City VALUES (1108,'Gulbarga','IND','Karnataka',304099);
+INSERT INTO City VALUES (1109,'New Delhi','IND','Delhi',301297);
+INSERT INTO City VALUES (1110,'Jhansi','IND','Uttar Pradesh',300850);
+INSERT INTO City VALUES (1111,'Gaya','IND','Bihar',291675);
+INSERT INTO City VALUES (1112,'Kakinada','IND','Andhra Pradesh',279980);
+INSERT INTO City VALUES (1113,'Dhule (Dhulia)','IND','Maharashtra',278317);
+INSERT INTO City VALUES (1114,'Panihati','IND','West Bengali',275990);
+INSERT INTO City VALUES (1115,'Nanded (Nander)','IND','Maharashtra',275083);
+INSERT INTO City VALUES (1116,'Mangalore','IND','Karnataka',273304);
+INSERT INTO City VALUES (1117,'Dehra Dun','IND','Uttaranchal',270159);
+INSERT INTO City VALUES (1118,'Kamarhati','IND','West Bengali',266889);
+INSERT INTO City VALUES (1119,'Davangere','IND','Karnataka',266082);
+INSERT INTO City VALUES (1120,'Asansol','IND','West Bengali',262188);
+INSERT INTO City VALUES (1121,'Bhagalpur','IND','Bihar',253225);
+INSERT INTO City VALUES (1122,'Bellary','IND','Karnataka',245391);
+INSERT INTO City VALUES (1123,'Barddhaman (Burdwan)','IND','West Bengali',245079);
+INSERT INTO City VALUES (1124,'Rampur','IND','Uttar Pradesh',243742);
+INSERT INTO City VALUES (1125,'Jalgaon','IND','Maharashtra',242193);
+INSERT INTO City VALUES (1126,'Muzaffarpur','IND','Bihar',241107);
+INSERT INTO City VALUES (1127,'Nizamabad','IND','Andhra Pradesh',241034);
+INSERT INTO City VALUES (1128,'Muzaffarnagar','IND','Uttar Pradesh',240609);
+INSERT INTO City VALUES (1129,'Patiala','IND','Punjab',238368);
+INSERT INTO City VALUES (1130,'Shahjahanpur','IND','Uttar Pradesh',237713);
+INSERT INTO City VALUES (1131,'Kurnool','IND','Andhra Pradesh',236800);
+INSERT INTO City VALUES (1132,'Tiruppur (Tirupper)','IND','Tamil Nadu',235661);
+INSERT INTO City VALUES (1133,'Rohtak','IND','Haryana',233400);
+INSERT INTO City VALUES (1134,'South Dum Dum','IND','West Bengali',232811);
+INSERT INTO City VALUES (1135,'Mathura','IND','Uttar Pradesh',226691);
+INSERT INTO City VALUES (1136,'Chandrapur','IND','Maharashtra',226105);
+INSERT INTO City VALUES (1137,'Barahanagar (Baranagar)','IND','West Bengali',224821);
+INSERT INTO City VALUES (1138,'Darbhanga','IND','Bihar',218391);
+INSERT INTO City VALUES (1139,'Siliguri (Shiliguri)','IND','West Bengali',216950);
+INSERT INTO City VALUES (1140,'Raurkela','IND','Orissa',215489);
+INSERT INTO City VALUES (1141,'Ambattur','IND','Tamil Nadu',215424);
+INSERT INTO City VALUES (1142,'Panipat','IND','Haryana',215218);
+INSERT INTO City VALUES (1143,'Firozabad','IND','Uttar Pradesh',215128);
+INSERT INTO City VALUES (1144,'Ichalkaranji','IND','Maharashtra',214950);
+INSERT INTO City VALUES (1145,'Jammu','IND','Jammu and Kashmir',214737);
+INSERT INTO City VALUES (1146,'Ramagundam','IND','Andhra Pradesh',214384);
+INSERT INTO City VALUES (1147,'Eluru','IND','Andhra Pradesh',212866);
+INSERT INTO City VALUES (1148,'Brahmapur','IND','Orissa',210418);
+INSERT INTO City VALUES (1149,'Alwar','IND','Rajasthan',205086);
+INSERT INTO City VALUES (1150,'Pondicherry','IND','Pondicherry',203065);
+INSERT INTO City VALUES (1151,'Thanjavur','IND','Tamil Nadu',202013);
+INSERT INTO City VALUES (1152,'Bihar Sharif','IND','Bihar',201323);
+INSERT INTO City VALUES (1153,'Tuticorin','IND','Tamil Nadu',199854);
+INSERT INTO City VALUES (1154,'Imphal','IND','Manipur',198535);
+INSERT INTO City VALUES (1155,'Latur','IND','Maharashtra',197408);
+INSERT INTO City VALUES (1156,'Sagar','IND','Madhya Pradesh',195346);
+INSERT INTO City VALUES (1157,'Farrukhabad-cum-Fatehgarh','IND','Uttar Pradesh',194567);
+INSERT INTO City VALUES (1158,'Sangli','IND','Maharashtra',193197);
+INSERT INTO City VALUES (1159,'Parbhani','IND','Maharashtra',190255);
+INSERT INTO City VALUES (1160,'Nagar Coil','IND','Tamil Nadu',190084);
+INSERT INTO City VALUES (1161,'Bijapur','IND','Karnataka',186939);
+INSERT INTO City VALUES (1162,'Kukatpalle','IND','Andhra Pradesh',185378);
+INSERT INTO City VALUES (1163,'Bally','IND','West Bengali',184474);
+INSERT INTO City VALUES (1164,'Bhilwara','IND','Rajasthan',183965);
+INSERT INTO City VALUES (1165,'Ratlam','IND','Madhya Pradesh',183375);
+INSERT INTO City VALUES (1166,'Avadi','IND','Tamil Nadu',183215);
+INSERT INTO City VALUES (1167,'Dindigul','IND','Tamil Nadu',182477);
+INSERT INTO City VALUES (1168,'Ahmadnagar','IND','Maharashtra',181339);
+INSERT INTO City VALUES (1169,'Bilaspur','IND','Chhatisgarh',179833);
+INSERT INTO City VALUES (1170,'Shimoga','IND','Karnataka',179258);
+INSERT INTO City VALUES (1171,'Kharagpur','IND','West Bengali',177989);
+INSERT INTO City VALUES (1172,'Mira Bhayandar','IND','Maharashtra',175372);
+INSERT INTO City VALUES (1173,'Vellore','IND','Tamil Nadu',175061);
+INSERT INTO City VALUES (1174,'Jalna','IND','Maharashtra',174985);
+INSERT INTO City VALUES (1175,'Burnpur','IND','West Bengali',174933);
+INSERT INTO City VALUES (1176,'Anantapur','IND','Andhra Pradesh',174924);
+INSERT INTO City VALUES (1177,'Allappuzha (Alleppey)','IND','Kerala',174666);
+INSERT INTO City VALUES (1178,'Tirupati','IND','Andhra Pradesh',174369);
+INSERT INTO City VALUES (1179,'Karnal','IND','Haryana',173751);
+INSERT INTO City VALUES (1180,'Burhanpur','IND','Madhya Pradesh',172710);
+INSERT INTO City VALUES (1181,'Hisar (Hissar)','IND','Haryana',172677);
+INSERT INTO City VALUES (1182,'Tiruvottiyur','IND','Tamil Nadu',172562);
+INSERT INTO City VALUES (1183,'Mirzapur-cum-Vindhyachal','IND','Uttar Pradesh',169336);
+INSERT INTO City VALUES (1184,'Secunderabad','IND','Andhra Pradesh',167461);
+INSERT INTO City VALUES (1185,'Nadiad','IND','Gujarat',167051);
+INSERT INTO City VALUES (1186,'Dewas','IND','Madhya Pradesh',164364);
+INSERT INTO City VALUES (1187,'Murwara (Katni)','IND','Madhya Pradesh',163431);
+INSERT INTO City VALUES (1188,'Ganganagar','IND','Rajasthan',161482);
+INSERT INTO City VALUES (1189,'Vizianagaram','IND','Andhra Pradesh',160359);
+INSERT INTO City VALUES (1190,'Erode','IND','Tamil Nadu',159232);
+INSERT INTO City VALUES (1191,'Machilipatnam (Masulipatam)','IND','Andhra Pradesh',159110);
+INSERT INTO City VALUES (1192,'Bhatinda (Bathinda)','IND','Punjab',159042);
+INSERT INTO City VALUES (1193,'Raichur','IND','Karnataka',157551);
+INSERT INTO City VALUES (1194,'Agartala','IND','Tripura',157358);
+INSERT INTO City VALUES (1195,'Arrah (Ara)','IND','Bihar',157082);
+INSERT INTO City VALUES (1196,'Satna','IND','Madhya Pradesh',156630);
+INSERT INTO City VALUES (1197,'Lalbahadur Nagar','IND','Andhra Pradesh',155500);
+INSERT INTO City VALUES (1198,'Aizawl','IND','Mizoram',155240);
+INSERT INTO City VALUES (1199,'Uluberia','IND','West Bengali',155172);
+INSERT INTO City VALUES (1200,'Katihar','IND','Bihar',154367);
+INSERT INTO City VALUES (1201,'Cuddalore','IND','Tamil Nadu',153086);
+INSERT INTO City VALUES (1202,'Hugli-Chinsurah','IND','West Bengali',151806);
+INSERT INTO City VALUES (1203,'Dhanbad','IND','Jharkhand',151789);
+INSERT INTO City VALUES (1204,'Raiganj','IND','West Bengali',151045);
+INSERT INTO City VALUES (1205,'Sambhal','IND','Uttar Pradesh',150869);
+INSERT INTO City VALUES (1206,'Durg','IND','Chhatisgarh',150645);
+INSERT INTO City VALUES (1207,'Munger (Monghyr)','IND','Bihar',150112);
+INSERT INTO City VALUES (1208,'Kanchipuram','IND','Tamil Nadu',150100);
+INSERT INTO City VALUES (1209,'North Dum Dum','IND','West Bengali',149965);
+INSERT INTO City VALUES (1210,'Karimnagar','IND','Andhra Pradesh',148583);
+INSERT INTO City VALUES (1211,'Bharatpur','IND','Rajasthan',148519);
+INSERT INTO City VALUES (1212,'Sikar','IND','Rajasthan',148272);
+INSERT INTO City VALUES (1213,'Hardwar (Haridwar)','IND','Uttaranchal',147305);
+INSERT INTO City VALUES (1214,'Dabgram','IND','West Bengali',147217);
+INSERT INTO City VALUES (1215,'Morena','IND','Madhya Pradesh',147124);
+INSERT INTO City VALUES (1216,'Noida','IND','Uttar Pradesh',146514);
+INSERT INTO City VALUES (1217,'Hapur','IND','Uttar Pradesh',146262);
+INSERT INTO City VALUES (1218,'Bhusawal','IND','Maharashtra',145143);
+INSERT INTO City VALUES (1219,'Khandwa','IND','Madhya Pradesh',145133);
+INSERT INTO City VALUES (1220,'Yamuna Nagar','IND','Haryana',144346);
+INSERT INTO City VALUES (1221,'Sonipat (Sonepat)','IND','Haryana',143922);
+INSERT INTO City VALUES (1222,'Tenali','IND','Andhra Pradesh',143726);
+INSERT INTO City VALUES (1223,'Raurkela Civil Township','IND','Orissa',140408);
+INSERT INTO City VALUES (1224,'Kollam (Quilon)','IND','Kerala',139852);
+INSERT INTO City VALUES (1225,'Kumbakonam','IND','Tamil Nadu',139483);
+INSERT INTO City VALUES (1226,'Ingraj Bazar (English Bazar)','IND','West Bengali',139204);
+INSERT INTO City VALUES (1227,'Timkur','IND','Karnataka',138903);
+INSERT INTO City VALUES (1228,'Amroha','IND','Uttar Pradesh',137061);
+INSERT INTO City VALUES (1229,'Serampore','IND','West Bengali',137028);
+INSERT INTO City VALUES (1230,'Chapra','IND','Bihar',136877);
+INSERT INTO City VALUES (1231,'Pali','IND','Rajasthan',136842);
+INSERT INTO City VALUES (1232,'Maunath Bhanjan','IND','Uttar Pradesh',136697);
+INSERT INTO City VALUES (1233,'Adoni','IND','Andhra Pradesh',136182);
+INSERT INTO City VALUES (1234,'Jaunpur','IND','Uttar Pradesh',136062);
+INSERT INTO City VALUES (1235,'Tirunelveli','IND','Tamil Nadu',135825);
+INSERT INTO City VALUES (1236,'Bahraich','IND','Uttar Pradesh',135400);
+INSERT INTO City VALUES (1237,'Gadag Betigeri','IND','Karnataka',134051);
+INSERT INTO City VALUES (1238,'Proddatur','IND','Andhra Pradesh',133914);
+INSERT INTO City VALUES (1239,'Chittoor','IND','Andhra Pradesh',133462);
+INSERT INTO City VALUES (1240,'Barrackpur','IND','West Bengali',133265);
+INSERT INTO City VALUES (1241,'Bharuch (Broach)','IND','Gujarat',133102);
+INSERT INTO City VALUES (1242,'Naihati','IND','West Bengali',132701);
+INSERT INTO City VALUES (1243,'Shillong','IND','Meghalaya',131719);
+INSERT INTO City VALUES (1244,'Sambalpur','IND','Orissa',131138);
+INSERT INTO City VALUES (1245,'Junagadh','IND','Gujarat',130484);
+INSERT INTO City VALUES (1246,'Rae Bareli','IND','Uttar Pradesh',129904);
+INSERT INTO City VALUES (1247,'Rewa','IND','Madhya Pradesh',128981);
+INSERT INTO City VALUES (1248,'Gurgaon','IND','Haryana',128608);
+INSERT INTO City VALUES (1249,'Khammam','IND','Andhra Pradesh',127992);
+INSERT INTO City VALUES (1250,'Bulandshahr','IND','Uttar Pradesh',127201);
+INSERT INTO City VALUES (1251,'Navsari','IND','Gujarat',126089);
+INSERT INTO City VALUES (1252,'Malkajgiri','IND','Andhra Pradesh',126066);
+INSERT INTO City VALUES (1253,'Midnapore (Medinipur)','IND','West Bengali',125498);
+INSERT INTO City VALUES (1254,'Miraj','IND','Maharashtra',125407);
+INSERT INTO City VALUES (1255,'Raj Nandgaon','IND','Chhatisgarh',125371);
+INSERT INTO City VALUES (1256,'Alandur','IND','Tamil Nadu',125244);
+INSERT INTO City VALUES (1257,'Puri','IND','Orissa',125199);
+INSERT INTO City VALUES (1258,'Navadwip','IND','West Bengali',125037);
+INSERT INTO City VALUES (1259,'Sirsa','IND','Haryana',125000);
+INSERT INTO City VALUES (1260,'Korba','IND','Chhatisgarh',124501);
+INSERT INTO City VALUES (1261,'Faizabad','IND','Uttar Pradesh',124437);
+INSERT INTO City VALUES (1262,'Etawah','IND','Uttar Pradesh',124072);
+INSERT INTO City VALUES (1263,'Pathankot','IND','Punjab',123930);
+INSERT INTO City VALUES (1264,'Gandhinagar','IND','Gujarat',123359);
+INSERT INTO City VALUES (1265,'Palghat (Palakkad)','IND','Kerala',123289);
+INSERT INTO City VALUES (1266,'Veraval','IND','Gujarat',123000);
+INSERT INTO City VALUES (1267,'Hoshiarpur','IND','Punjab',122705);
+INSERT INTO City VALUES (1268,'Ambala','IND','Haryana',122596);
+INSERT INTO City VALUES (1269,'Sitapur','IND','Uttar Pradesh',121842);
+INSERT INTO City VALUES (1270,'Bhiwani','IND','Haryana',121629);
+INSERT INTO City VALUES (1271,'Cuddapah','IND','Andhra Pradesh',121463);
+INSERT INTO City VALUES (1272,'Bhimavaram','IND','Andhra Pradesh',121314);
+INSERT INTO City VALUES (1273,'Krishnanagar','IND','West Bengali',121110);
+INSERT INTO City VALUES (1274,'Chandannagar','IND','West Bengali',120378);
+INSERT INTO City VALUES (1275,'Mandya','IND','Karnataka',120265);
+INSERT INTO City VALUES (1276,'Dibrugarh','IND','Assam',120127);
+INSERT INTO City VALUES (1277,'Nandyal','IND','Andhra Pradesh',119813);
+INSERT INTO City VALUES (1278,'Balurghat','IND','West Bengali',119796);
+INSERT INTO City VALUES (1279,'Neyveli','IND','Tamil Nadu',118080);
+INSERT INTO City VALUES (1280,'Fatehpur','IND','Uttar Pradesh',117675);
+INSERT INTO City VALUES (1281,'Mahbubnagar','IND','Andhra Pradesh',116833);
+INSERT INTO City VALUES (1282,'Budaun','IND','Uttar Pradesh',116695);
+INSERT INTO City VALUES (1283,'Porbandar','IND','Gujarat',116671);
+INSERT INTO City VALUES (1284,'Silchar','IND','Assam',115483);
+INSERT INTO City VALUES (1285,'Berhampore (Baharampur)','IND','West Bengali',115144);
+INSERT INTO City VALUES (1286,'Purnea (Purnia)','IND','Jharkhand',114912);
+INSERT INTO City VALUES (1287,'Bankura','IND','West Bengali',114876);
+INSERT INTO City VALUES (1288,'Rajapalaiyam','IND','Tamil Nadu',114202);
+INSERT INTO City VALUES (1289,'Titagarh','IND','West Bengali',114085);
+INSERT INTO City VALUES (1290,'Halisahar','IND','West Bengali',114028);
+INSERT INTO City VALUES (1291,'Hathras','IND','Uttar Pradesh',113285);
+INSERT INTO City VALUES (1292,'Bhir (Bid)','IND','Maharashtra',112434);
+INSERT INTO City VALUES (1293,'Pallavaram','IND','Tamil Nadu',111866);
+INSERT INTO City VALUES (1294,'Anand','IND','Gujarat',110266);
+INSERT INTO City VALUES (1295,'Mango','IND','Jharkhand',110024);
+INSERT INTO City VALUES (1296,'Santipur','IND','West Bengali',109956);
+INSERT INTO City VALUES (1297,'Bhind','IND','Madhya Pradesh',109755);
+INSERT INTO City VALUES (1298,'Gondiya','IND','Maharashtra',109470);
+INSERT INTO City VALUES (1299,'Tiruvannamalai','IND','Tamil Nadu',109196);
+INSERT INTO City VALUES (1300,'Yeotmal (Yavatmal)','IND','Maharashtra',108578);
+INSERT INTO City VALUES (1301,'Kulti-Barakar','IND','West Bengali',108518);
+INSERT INTO City VALUES (1302,'Moga','IND','Punjab',108304);
+INSERT INTO City VALUES (1303,'Shivapuri','IND','Madhya Pradesh',108277);
+INSERT INTO City VALUES (1304,'Bidar','IND','Karnataka',108016);
+INSERT INTO City VALUES (1305,'Guntakal','IND','Andhra Pradesh',107592);
+INSERT INTO City VALUES (1306,'Unnao','IND','Uttar Pradesh',107425);
+INSERT INTO City VALUES (1307,'Barasat','IND','West Bengali',107365);
+INSERT INTO City VALUES (1308,'Tambaram','IND','Tamil Nadu',107187);
+INSERT INTO City VALUES (1309,'Abohar','IND','Punjab',107163);
+INSERT INTO City VALUES (1310,'Pilibhit','IND','Uttar Pradesh',106605);
+INSERT INTO City VALUES (1311,'Valparai','IND','Tamil Nadu',106523);
+INSERT INTO City VALUES (1312,'Gonda','IND','Uttar Pradesh',106078);
+INSERT INTO City VALUES (1313,'Surendranagar','IND','Gujarat',105973);
+INSERT INTO City VALUES (1314,'Qutubullapur','IND','Andhra Pradesh',105380);
+INSERT INTO City VALUES (1315,'Beawar','IND','Rajasthan',105363);
+INSERT INTO City VALUES (1316,'Hindupur','IND','Andhra Pradesh',104651);
+INSERT INTO City VALUES (1317,'Gandhidham','IND','Gujarat',104585);
+INSERT INTO City VALUES (1318,'Haldwani-cum-Kathgodam','IND','Uttaranchal',104195);
+INSERT INTO City VALUES (1319,'Tellicherry (Thalassery)','IND','Kerala',103579);
+INSERT INTO City VALUES (1320,'Wardha','IND','Maharashtra',102985);
+INSERT INTO City VALUES (1321,'Rishra','IND','West Bengali',102649);
+INSERT INTO City VALUES (1322,'Bhuj','IND','Gujarat',102176);
+INSERT INTO City VALUES (1323,'Modinagar','IND','Uttar Pradesh',101660);
+INSERT INTO City VALUES (1324,'Gudivada','IND','Andhra Pradesh',101656);
+INSERT INTO City VALUES (1325,'Basirhat','IND','West Bengali',101409);
+INSERT INTO City VALUES (1326,'Uttarpara-Kotrung','IND','West Bengali',100867);
+INSERT INTO City VALUES (1327,'Ongole','IND','Andhra Pradesh',100836);
+INSERT INTO City VALUES (1328,'North Barrackpur','IND','West Bengali',100513);
+INSERT INTO City VALUES (1329,'Guna','IND','Madhya Pradesh',100490);
+INSERT INTO City VALUES (1330,'Haldia','IND','West Bengali',100347);
+INSERT INTO City VALUES (1331,'Habra','IND','West Bengali',100223);
+INSERT INTO City VALUES (1332,'Kanchrapara','IND','West Bengali',100194);
+INSERT INTO City VALUES (1333,'Tonk','IND','Rajasthan',100079);
+INSERT INTO City VALUES (1334,'Champdani','IND','West Bengali',98818);
+INSERT INTO City VALUES (1335,'Orai','IND','Uttar Pradesh',98640);
+INSERT INTO City VALUES (1336,'Pudukkottai','IND','Tamil Nadu',98619);
+INSERT INTO City VALUES (1337,'Sasaram','IND','Bihar',98220);
+INSERT INTO City VALUES (1338,'Hazaribag','IND','Jharkhand',97712);
+INSERT INTO City VALUES (1339,'Palayankottai','IND','Tamil Nadu',97662);
+INSERT INTO City VALUES (1340,'Banda','IND','Uttar Pradesh',97227);
+INSERT INTO City VALUES (1341,'Godhra','IND','Gujarat',96813);
+INSERT INTO City VALUES (1342,'Hospet','IND','Karnataka',96322);
+INSERT INTO City VALUES (1343,'Ashoknagar-Kalyangarh','IND','West Bengali',96315);
+INSERT INTO City VALUES (1344,'Achalpur','IND','Maharashtra',96216);
+INSERT INTO City VALUES (1345,'Patan','IND','Gujarat',96109);
+INSERT INTO City VALUES (1346,'Mandasor','IND','Madhya Pradesh',95758);
+INSERT INTO City VALUES (1347,'Damoh','IND','Madhya Pradesh',95661);
+INSERT INTO City VALUES (1348,'Satara','IND','Maharashtra',95133);
+INSERT INTO City VALUES (1349,'Meerut Cantonment','IND','Uttar Pradesh',94876);
+INSERT INTO City VALUES (1350,'Dehri','IND','Bihar',94526);
+INSERT INTO City VALUES (1351,'Delhi Cantonment','IND','Delhi',94326);
+INSERT INTO City VALUES (1352,'Chhindwara','IND','Madhya Pradesh',93731);
+INSERT INTO City VALUES (1353,'Bansberia','IND','West Bengali',93447);
+INSERT INTO City VALUES (1354,'Nagaon','IND','Assam',93350);
+INSERT INTO City VALUES (1355,'Kanpur Cantonment','IND','Uttar Pradesh',93109);
+INSERT INTO City VALUES (1356,'Vidisha','IND','Madhya Pradesh',92917);
+INSERT INTO City VALUES (1357,'Bettiah','IND','Bihar',92583);
+INSERT INTO City VALUES (1358,'Purulia','IND','Jharkhand',92574);
+INSERT INTO City VALUES (1359,'Hassan','IND','Karnataka',90803);
+INSERT INTO City VALUES (1360,'Ambala Sadar','IND','Haryana',90712);
+INSERT INTO City VALUES (1361,'Baidyabati','IND','West Bengali',90601);
+INSERT INTO City VALUES (1362,'Morvi','IND','Gujarat',90357);
+INSERT INTO City VALUES (1363,'Raigarh','IND','Chhatisgarh',89166);
+INSERT INTO City VALUES (1364,'Vejalpur','IND','Gujarat',89053);
+INSERT INTO City VALUES (1365,'Baghdad','IRQ','Baghdad',4336000);
+INSERT INTO City VALUES (1366,'Mosul','IRQ','Ninawa',879000);
+INSERT INTO City VALUES (1367,'Irbil','IRQ','Irbil',485968);
+INSERT INTO City VALUES (1368,'Kirkuk','IRQ','al-Tamim',418624);
+INSERT INTO City VALUES (1369,'Basra','IRQ','Basra',406296);
+INSERT INTO City VALUES (1370,'al-Sulaymaniya','IRQ','al-Sulaymaniya',364096);
+INSERT INTO City VALUES (1371,'al-Najaf','IRQ','al-Najaf',309010);
+INSERT INTO City VALUES (1372,'Karbala','IRQ','Karbala',296705);
+INSERT INTO City VALUES (1373,'al-Hilla','IRQ','Babil',268834);
+INSERT INTO City VALUES (1374,'al-Nasiriya','IRQ','DhiQar',265937);
+INSERT INTO City VALUES (1375,'al-Amara','IRQ','Maysan',208797);
+INSERT INTO City VALUES (1376,'al-Diwaniya','IRQ','al-Qadisiya',196519);
+INSERT INTO City VALUES (1377,'al-Ramadi','IRQ','al-Anbar',192556);
+INSERT INTO City VALUES (1378,'al-Kut','IRQ','Wasit',183183);
+INSERT INTO City VALUES (1379,'Baquba','IRQ','Diyala',114516);
+INSERT INTO City VALUES (1380,'Teheran','IRN','Teheran',6758845);
+INSERT INTO City VALUES (1381,'Mashhad','IRN','Khorasan',1887405);
+INSERT INTO City VALUES (1382,'Esfahan','IRN','Esfahan',1266072);
+INSERT INTO City VALUES (1383,'Tabriz','IRN','East Azerbaidzan',1191043);
+INSERT INTO City VALUES (1384,'Shiraz','IRN','Fars',1053025);
+INSERT INTO City VALUES (1385,'Karaj','IRN','Teheran',940968);
+INSERT INTO City VALUES (1386,'Ahvaz','IRN','Khuzestan',804980);
+INSERT INTO City VALUES (1387,'Qom','IRN','Qom',777677);
+INSERT INTO City VALUES (1388,'Kermanshah','IRN','Kermanshah',692986);
+INSERT INTO City VALUES (1389,'Urmia','IRN','West Azerbaidzan',435200);
+INSERT INTO City VALUES (1390,'Zahedan','IRN','Sistan va Baluchesta',419518);
+INSERT INTO City VALUES (1391,'Rasht','IRN','Gilan',417748);
+INSERT INTO City VALUES (1392,'Hamadan','IRN','Hamadan',401281);
+INSERT INTO City VALUES (1393,'Kerman','IRN','Kerman',384991);
+INSERT INTO City VALUES (1394,'Arak','IRN','Markazi',380755);
+INSERT INTO City VALUES (1395,'Ardebil','IRN','Ardebil',340386);
+INSERT INTO City VALUES (1396,'Yazd','IRN','Yazd',326776);
+INSERT INTO City VALUES (1397,'Qazvin','IRN','Qazvin',291117);
+INSERT INTO City VALUES (1398,'Zanjan','IRN','Zanjan',286295);
+INSERT INTO City VALUES (1399,'Sanandaj','IRN','Kordestan',277808);
+INSERT INTO City VALUES (1400,'Bandar-e-Abbas','IRN','Hormozgan',273578);
+INSERT INTO City VALUES (1401,'Khorramabad','IRN','Lorestan',272815);
+INSERT INTO City VALUES (1402,'Eslamshahr','IRN','Teheran',265450);
+INSERT INTO City VALUES (1403,'Borujerd','IRN','Lorestan',217804);
+INSERT INTO City VALUES (1404,'Abadan','IRN','Khuzestan',206073);
+INSERT INTO City VALUES (1405,'Dezful','IRN','Khuzestan',202639);
+INSERT INTO City VALUES (1406,'Kashan','IRN','Esfahan',201372);
+INSERT INTO City VALUES (1407,'Sari','IRN','Mazandaran',195882);
+INSERT INTO City VALUES (1408,'Gorgan','IRN','Golestan',188710);
+INSERT INTO City VALUES (1409,'Najafabad','IRN','Esfahan',178498);
+INSERT INTO City VALUES (1410,'Sabzevar','IRN','Khorasan',170738);
+INSERT INTO City VALUES (1411,'Khomeynishahr','IRN','Esfahan',165888);
+INSERT INTO City VALUES (1412,'Amol','IRN','Mazandaran',159092);
+INSERT INTO City VALUES (1413,'Neyshabur','IRN','Khorasan',158847);
+INSERT INTO City VALUES (1414,'Babol','IRN','Mazandaran',158346);
+INSERT INTO City VALUES (1415,'Khoy','IRN','West Azerbaidzan',148944);
+INSERT INTO City VALUES (1416,'Malayer','IRN','Hamadan',144373);
+INSERT INTO City VALUES (1417,'Bushehr','IRN','Bushehr',143641);
+INSERT INTO City VALUES (1418,'Qaemshahr','IRN','Mazandaran',143286);
+INSERT INTO City VALUES (1419,'Qarchak','IRN','Teheran',142690);
+INSERT INTO City VALUES (1420,'Qods','IRN','Teheran',138278);
+INSERT INTO City VALUES (1421,'Sirjan','IRN','Kerman',135024);
+INSERT INTO City VALUES (1422,'Bojnurd','IRN','Khorasan',134835);
+INSERT INTO City VALUES (1423,'Maragheh','IRN','East Azerbaidzan',132318);
+INSERT INTO City VALUES (1424,'Birjand','IRN','Khorasan',127608);
+INSERT INTO City VALUES (1425,'Ilam','IRN','Ilam',126346);
+INSERT INTO City VALUES (1426,'Bukan','IRN','West Azerbaidzan',120020);
+INSERT INTO City VALUES (1427,'Masjed-e-Soleyman','IRN','Khuzestan',116883);
+INSERT INTO City VALUES (1428,'Saqqez','IRN','Kordestan',115394);
+INSERT INTO City VALUES (1429,'Gonbad-e Qabus','IRN','Mazandaran',111253);
+INSERT INTO City VALUES (1430,'Saveh','IRN','Qom',111245);
+INSERT INTO City VALUES (1431,'Mahabad','IRN','West Azerbaidzan',107799);
+INSERT INTO City VALUES (1432,'Varamin','IRN','Teheran',107233);
+INSERT INTO City VALUES (1433,'Andimeshk','IRN','Khuzestan',106923);
+INSERT INTO City VALUES (1434,'Khorramshahr','IRN','Khuzestan',105636);
+INSERT INTO City VALUES (1435,'Shahrud','IRN','Semnan',104765);
+INSERT INTO City VALUES (1436,'Marv Dasht','IRN','Fars',103579);
+INSERT INTO City VALUES (1437,'Zabol','IRN','Sistan va Baluchesta',100887);
+INSERT INTO City VALUES (1438,'Shahr-e Kord','IRN','Chaharmahal va Bakht',100477);
+INSERT INTO City VALUES (1439,'Bandar-e Anzali','IRN','Gilan',98500);
+INSERT INTO City VALUES (1440,'Rafsanjan','IRN','Kerman',98300);
+INSERT INTO City VALUES (1441,'Marand','IRN','East Azerbaidzan',96400);
+INSERT INTO City VALUES (1442,'Torbat-e Heydariyeh','IRN','Khorasan',94600);
+INSERT INTO City VALUES (1443,'Jahrom','IRN','Fars',94200);
+INSERT INTO City VALUES (1444,'Semnan','IRN','Semnan',91045);
+INSERT INTO City VALUES (1445,'Miandoab','IRN','West Azerbaidzan',90100);
+INSERT INTO City VALUES (1446,'Qomsheh','IRN','Esfahan',89800);
+INSERT INTO City VALUES (1447,'Dublin','IRL','Leinster',481854);
+INSERT INTO City VALUES (1448,'Cork','IRL','Munster',127187);
+INSERT INTO City VALUES (1449,'Reykjavík','ISL','Höfuðborgarsvæði',109184);
+INSERT INTO City VALUES (1450,'Jerusalem','ISR','Jerusalem',633700);
+INSERT INTO City VALUES (1451,'Tel Aviv-Jaffa','ISR','Tel Aviv',348100);
+INSERT INTO City VALUES (1452,'Haifa','ISR','Haifa',265700);
+INSERT INTO City VALUES (1453,'Rishon Le Ziyyon','ISR','Ha Merkaz',188200);
+INSERT INTO City VALUES (1454,'Beerseba','ISR','Ha Darom',163700);
+INSERT INTO City VALUES (1455,'Holon','ISR','Tel Aviv',163100);
+INSERT INTO City VALUES (1456,'Petah Tiqwa','ISR','Ha Merkaz',159400);
+INSERT INTO City VALUES (1457,'Ashdod','ISR','Ha Darom',155800);
+INSERT INTO City VALUES (1458,'Netanya','ISR','Ha Merkaz',154900);
+INSERT INTO City VALUES (1459,'Bat Yam','ISR','Tel Aviv',137000);
+INSERT INTO City VALUES (1460,'Bene Beraq','ISR','Tel Aviv',133900);
+INSERT INTO City VALUES (1461,'Ramat Gan','ISR','Tel Aviv',126900);
+INSERT INTO City VALUES (1462,'Ashqelon','ISR','Ha Darom',92300);
+INSERT INTO City VALUES (1463,'Rehovot','ISR','Ha Merkaz',90300);
+INSERT INTO City VALUES (1464,'Roma','ITA','Latium',2643581);
+INSERT INTO City VALUES (1465,'Milano','ITA','Lombardia',1300977);
+INSERT INTO City VALUES (1466,'Napoli','ITA','Campania',1002619);
+INSERT INTO City VALUES (1467,'Torino','ITA','Piemonte',903705);
+INSERT INTO City VALUES (1468,'Palermo','ITA','Sisilia',683794);
+INSERT INTO City VALUES (1469,'Genova','ITA','Liguria',636104);
+INSERT INTO City VALUES (1470,'Bologna','ITA','Emilia-Romagna',381161);
+INSERT INTO City VALUES (1471,'Firenze','ITA','Toscana',376662);
+INSERT INTO City VALUES (1472,'Catania','ITA','Sisilia',337862);
+INSERT INTO City VALUES (1473,'Bari','ITA','Apulia',331848);
+INSERT INTO City VALUES (1474,'Venezia','ITA','Veneto',277305);
+INSERT INTO City VALUES (1475,'Messina','ITA','Sisilia',259156);
+INSERT INTO City VALUES (1476,'Verona','ITA','Veneto',255268);
+INSERT INTO City VALUES (1477,'Trieste','ITA','Friuli-Venezia Giuli',216459);
+INSERT INTO City VALUES (1478,'Padova','ITA','Veneto',211391);
+INSERT INTO City VALUES (1479,'Taranto','ITA','Apulia',208214);
+INSERT INTO City VALUES (1480,'Brescia','ITA','Lombardia',191317);
+INSERT INTO City VALUES (1481,'Reggio di Calabria','ITA','Calabria',179617);
+INSERT INTO City VALUES (1482,'Modena','ITA','Emilia-Romagna',176022);
+INSERT INTO City VALUES (1483,'Prato','ITA','Toscana',172473);
+INSERT INTO City VALUES (1484,'Parma','ITA','Emilia-Romagna',168717);
+INSERT INTO City VALUES (1485,'Cagliari','ITA','Sardinia',165926);
+INSERT INTO City VALUES (1486,'Livorno','ITA','Toscana',161673);
+INSERT INTO City VALUES (1487,'Perugia','ITA','Umbria',156673);
+INSERT INTO City VALUES (1488,'Foggia','ITA','Apulia',154891);
+INSERT INTO City VALUES (1489,'Reggio nell´ Emilia','ITA','Emilia-Romagna',143664);
+INSERT INTO City VALUES (1490,'Salerno','ITA','Campania',142055);
+INSERT INTO City VALUES (1491,'Ravenna','ITA','Emilia-Romagna',138418);
+INSERT INTO City VALUES (1492,'Ferrara','ITA','Emilia-Romagna',132127);
+INSERT INTO City VALUES (1493,'Rimini','ITA','Emilia-Romagna',131062);
+INSERT INTO City VALUES (1494,'Syrakusa','ITA','Sisilia',126282);
+INSERT INTO City VALUES (1495,'Sassari','ITA','Sardinia',120803);
+INSERT INTO City VALUES (1496,'Monza','ITA','Lombardia',119516);
+INSERT INTO City VALUES (1497,'Bergamo','ITA','Lombardia',117837);
+INSERT INTO City VALUES (1498,'Pescara','ITA','Abruzzit',115698);
+INSERT INTO City VALUES (1499,'Latina','ITA','Latium',114099);
+INSERT INTO City VALUES (1500,'Vicenza','ITA','Veneto',109738);
+INSERT INTO City VALUES (1501,'Terni','ITA','Umbria',107770);
+INSERT INTO City VALUES (1502,'Forlì','ITA','Emilia-Romagna',107475);
+INSERT INTO City VALUES (1503,'Trento','ITA','Trentino-Alto Adige',104906);
+INSERT INTO City VALUES (1504,'Novara','ITA','Piemonte',102037);
+INSERT INTO City VALUES (1505,'Piacenza','ITA','Emilia-Romagna',98384);
+INSERT INTO City VALUES (1506,'Ancona','ITA','Marche',98329);
+INSERT INTO City VALUES (1507,'Lecce','ITA','Apulia',98208);
+INSERT INTO City VALUES (1508,'Bolzano','ITA','Trentino-Alto Adige',97232);
+INSERT INTO City VALUES (1509,'Catanzaro','ITA','Calabria',96700);
+INSERT INTO City VALUES (1510,'La Spezia','ITA','Liguria',95504);
+INSERT INTO City VALUES (1511,'Udine','ITA','Friuli-Venezia Giuli',94932);
+INSERT INTO City VALUES (1512,'Torre del Greco','ITA','Campania',94505);
+INSERT INTO City VALUES (1513,'Andria','ITA','Apulia',94443);
+INSERT INTO City VALUES (1514,'Brindisi','ITA','Apulia',93454);
+INSERT INTO City VALUES (1515,'Giugliano in Campania','ITA','Campania',93286);
+INSERT INTO City VALUES (1516,'Pisa','ITA','Toscana',92379);
+INSERT INTO City VALUES (1517,'Barletta','ITA','Apulia',91904);
+INSERT INTO City VALUES (1518,'Arezzo','ITA','Toscana',91729);
+INSERT INTO City VALUES (1519,'Alessandria','ITA','Piemonte',90289);
+INSERT INTO City VALUES (1520,'Cesena','ITA','Emilia-Romagna',89852);
+INSERT INTO City VALUES (1521,'Pesaro','ITA','Marche',88987);
+INSERT INTO City VALUES (1522,'Dili','TMP','Dili',47900);
+INSERT INTO City VALUES (1523,'Wien','AUT','Wien',1608144);
+INSERT INTO City VALUES (1524,'Graz','AUT','Steiermark',240967);
+INSERT INTO City VALUES (1525,'Linz','AUT','North Austria',188022);
+INSERT INTO City VALUES (1526,'Salzburg','AUT','Salzburg',144247);
+INSERT INTO City VALUES (1527,'Innsbruck','AUT','Tiroli',111752);
+INSERT INTO City VALUES (1528,'Klagenfurt','AUT','Kärnten',91141);
+INSERT INTO City VALUES (1529,'Spanish Town','JAM','St. Catherine',110379);
+INSERT INTO City VALUES (1530,'Kingston','JAM','St. Andrew',103962);
+INSERT INTO City VALUES (1531,'Portmore','JAM','St. Andrew',99799);
+INSERT INTO City VALUES (1532,'Tokyo','JPN','Tokyo-to',7980230);
+INSERT INTO City VALUES (1533,'Jokohama [Yokohama]','JPN','Kanagawa',3339594);
+INSERT INTO City VALUES (1534,'Osaka','JPN','Osaka',2595674);
+INSERT INTO City VALUES (1535,'Nagoya','JPN','Aichi',2154376);
+INSERT INTO City VALUES (1536,'Sapporo','JPN','Hokkaido',1790886);
+INSERT INTO City VALUES (1537,'Kioto','JPN','Kyoto',1461974);
+INSERT INTO City VALUES (1538,'Kobe','JPN','Hyogo',1425139);
+INSERT INTO City VALUES (1539,'Fukuoka','JPN','Fukuoka',1308379);
+INSERT INTO City VALUES (1540,'Kawasaki','JPN','Kanagawa',1217359);
+INSERT INTO City VALUES (1541,'Hiroshima','JPN','Hiroshima',1119117);
+INSERT INTO City VALUES (1542,'Kitakyushu','JPN','Fukuoka',1016264);
+INSERT INTO City VALUES (1543,'Sendai','JPN','Miyagi',989975);
+INSERT INTO City VALUES (1544,'Chiba','JPN','Chiba',863930);
+INSERT INTO City VALUES (1545,'Sakai','JPN','Osaka',797735);
+INSERT INTO City VALUES (1546,'Kumamoto','JPN','Kumamoto',656734);
+INSERT INTO City VALUES (1547,'Okayama','JPN','Okayama',624269);
+INSERT INTO City VALUES (1548,'Sagamihara','JPN','Kanagawa',586300);
+INSERT INTO City VALUES (1549,'Hamamatsu','JPN','Shizuoka',568796);
+INSERT INTO City VALUES (1550,'Kagoshima','JPN','Kagoshima',549977);
+INSERT INTO City VALUES (1551,'Funabashi','JPN','Chiba',545299);
+INSERT INTO City VALUES (1552,'Higashiosaka','JPN','Osaka',517785);
+INSERT INTO City VALUES (1553,'Hachioji','JPN','Tokyo-to',513451);
+INSERT INTO City VALUES (1554,'Niigata','JPN','Niigata',497464);
+INSERT INTO City VALUES (1555,'Amagasaki','JPN','Hyogo',481434);
+INSERT INTO City VALUES (1556,'Himeji','JPN','Hyogo',475167);
+INSERT INTO City VALUES (1557,'Shizuoka','JPN','Shizuoka',473854);
+INSERT INTO City VALUES (1558,'Urawa','JPN','Saitama',469675);
+INSERT INTO City VALUES (1559,'Matsuyama','JPN','Ehime',466133);
+INSERT INTO City VALUES (1560,'Matsudo','JPN','Chiba',461126);
+INSERT INTO City VALUES (1561,'Kanazawa','JPN','Ishikawa',455386);
+INSERT INTO City VALUES (1562,'Kawaguchi','JPN','Saitama',452155);
+INSERT INTO City VALUES (1563,'Ichikawa','JPN','Chiba',441893);
+INSERT INTO City VALUES (1564,'Omiya','JPN','Saitama',441649);
+INSERT INTO City VALUES (1565,'Utsunomiya','JPN','Tochigi',440353);
+INSERT INTO City VALUES (1566,'Oita','JPN','Oita',433401);
+INSERT INTO City VALUES (1567,'Nagasaki','JPN','Nagasaki',432759);
+INSERT INTO City VALUES (1568,'Yokosuka','JPN','Kanagawa',430200);
+INSERT INTO City VALUES (1569,'Kurashiki','JPN','Okayama',425103);
+INSERT INTO City VALUES (1570,'Gifu','JPN','Gifu',408007);
+INSERT INTO City VALUES (1571,'Hirakata','JPN','Osaka',403151);
+INSERT INTO City VALUES (1572,'Nishinomiya','JPN','Hyogo',397618);
+INSERT INTO City VALUES (1573,'Toyonaka','JPN','Osaka',396689);
+INSERT INTO City VALUES (1574,'Wakayama','JPN','Wakayama',391233);
+INSERT INTO City VALUES (1575,'Fukuyama','JPN','Hiroshima',376921);
+INSERT INTO City VALUES (1576,'Fujisawa','JPN','Kanagawa',372840);
+INSERT INTO City VALUES (1577,'Asahikawa','JPN','Hokkaido',364813);
+INSERT INTO City VALUES (1578,'Machida','JPN','Tokyo-to',364197);
+INSERT INTO City VALUES (1579,'Nara','JPN','Nara',362812);
+INSERT INTO City VALUES (1580,'Takatsuki','JPN','Osaka',361747);
+INSERT INTO City VALUES (1581,'Iwaki','JPN','Fukushima',361737);
+INSERT INTO City VALUES (1582,'Nagano','JPN','Nagano',361391);
+INSERT INTO City VALUES (1583,'Toyohashi','JPN','Aichi',360066);
+INSERT INTO City VALUES (1584,'Toyota','JPN','Aichi',346090);
+INSERT INTO City VALUES (1585,'Suita','JPN','Osaka',345750);
+INSERT INTO City VALUES (1586,'Takamatsu','JPN','Kagawa',332471);
+INSERT INTO City VALUES (1587,'Koriyama','JPN','Fukushima',330335);
+INSERT INTO City VALUES (1588,'Okazaki','JPN','Aichi',328711);
+INSERT INTO City VALUES (1589,'Kawagoe','JPN','Saitama',327211);
+INSERT INTO City VALUES (1590,'Tokorozawa','JPN','Saitama',325809);
+INSERT INTO City VALUES (1591,'Toyama','JPN','Toyama',325790);
+INSERT INTO City VALUES (1592,'Kochi','JPN','Kochi',324710);
+INSERT INTO City VALUES (1593,'Kashiwa','JPN','Chiba',320296);
+INSERT INTO City VALUES (1594,'Akita','JPN','Akita',314440);
+INSERT INTO City VALUES (1595,'Miyazaki','JPN','Miyazaki',303784);
+INSERT INTO City VALUES (1596,'Koshigaya','JPN','Saitama',301446);
+INSERT INTO City VALUES (1597,'Naha','JPN','Okinawa',299851);
+INSERT INTO City VALUES (1598,'Aomori','JPN','Aomori',295969);
+INSERT INTO City VALUES (1599,'Hakodate','JPN','Hokkaido',294788);
+INSERT INTO City VALUES (1600,'Akashi','JPN','Hyogo',292253);
+INSERT INTO City VALUES (1601,'Yokkaichi','JPN','Mie',288173);
+INSERT INTO City VALUES (1602,'Fukushima','JPN','Fukushima',287525);
+INSERT INTO City VALUES (1603,'Morioka','JPN','Iwate',287353);
+INSERT INTO City VALUES (1604,'Maebashi','JPN','Gumma',284473);
+INSERT INTO City VALUES (1605,'Kasugai','JPN','Aichi',282348);
+INSERT INTO City VALUES (1606,'Otsu','JPN','Shiga',282070);
+INSERT INTO City VALUES (1607,'Ichihara','JPN','Chiba',279280);
+INSERT INTO City VALUES (1608,'Yao','JPN','Osaka',276421);
+INSERT INTO City VALUES (1609,'Ichinomiya','JPN','Aichi',270828);
+INSERT INTO City VALUES (1610,'Tokushima','JPN','Tokushima',269649);
+INSERT INTO City VALUES (1611,'Kakogawa','JPN','Hyogo',266281);
+INSERT INTO City VALUES (1612,'Ibaraki','JPN','Osaka',261020);
+INSERT INTO City VALUES (1613,'Neyagawa','JPN','Osaka',257315);
+INSERT INTO City VALUES (1614,'Shimonoseki','JPN','Yamaguchi',257263);
+INSERT INTO City VALUES (1615,'Yamagata','JPN','Yamagata',255617);
+INSERT INTO City VALUES (1616,'Fukui','JPN','Fukui',254818);
+INSERT INTO City VALUES (1617,'Hiratsuka','JPN','Kanagawa',254207);
+INSERT INTO City VALUES (1618,'Mito','JPN','Ibaragi',246559);
+INSERT INTO City VALUES (1619,'Sasebo','JPN','Nagasaki',244240);
+INSERT INTO City VALUES (1620,'Hachinohe','JPN','Aomori',242979);
+INSERT INTO City VALUES (1621,'Takasaki','JPN','Gumma',239124);
+INSERT INTO City VALUES (1622,'Shimizu','JPN','Shizuoka',239123);
+INSERT INTO City VALUES (1623,'Kurume','JPN','Fukuoka',235611);
+INSERT INTO City VALUES (1624,'Fuji','JPN','Shizuoka',231527);
+INSERT INTO City VALUES (1625,'Soka','JPN','Saitama',222768);
+INSERT INTO City VALUES (1626,'Fuchu','JPN','Tokyo-to',220576);
+INSERT INTO City VALUES (1627,'Chigasaki','JPN','Kanagawa',216015);
+INSERT INTO City VALUES (1628,'Atsugi','JPN','Kanagawa',212407);
+INSERT INTO City VALUES (1629,'Numazu','JPN','Shizuoka',211382);
+INSERT INTO City VALUES (1630,'Ageo','JPN','Saitama',209442);
+INSERT INTO City VALUES (1631,'Yamato','JPN','Kanagawa',208234);
+INSERT INTO City VALUES (1632,'Matsumoto','JPN','Nagano',206801);
+INSERT INTO City VALUES (1633,'Kure','JPN','Hiroshima',206504);
+INSERT INTO City VALUES (1634,'Takarazuka','JPN','Hyogo',205993);
+INSERT INTO City VALUES (1635,'Kasukabe','JPN','Saitama',201838);
+INSERT INTO City VALUES (1636,'Chofu','JPN','Tokyo-to',201585);
+INSERT INTO City VALUES (1637,'Odawara','JPN','Kanagawa',200171);
+INSERT INTO City VALUES (1638,'Kofu','JPN','Yamanashi',199753);
+INSERT INTO City VALUES (1639,'Kushiro','JPN','Hokkaido',197608);
+INSERT INTO City VALUES (1640,'Kishiwada','JPN','Osaka',197276);
+INSERT INTO City VALUES (1641,'Hitachi','JPN','Ibaragi',196622);
+INSERT INTO City VALUES (1642,'Nagaoka','JPN','Niigata',192407);
+INSERT INTO City VALUES (1643,'Itami','JPN','Hyogo',190886);
+INSERT INTO City VALUES (1644,'Uji','JPN','Kyoto',188735);
+INSERT INTO City VALUES (1645,'Suzuka','JPN','Mie',184061);
+INSERT INTO City VALUES (1646,'Hirosaki','JPN','Aomori',177522);
+INSERT INTO City VALUES (1647,'Ube','JPN','Yamaguchi',175206);
+INSERT INTO City VALUES (1648,'Kodaira','JPN','Tokyo-to',174984);
+INSERT INTO City VALUES (1649,'Takaoka','JPN','Toyama',174380);
+INSERT INTO City VALUES (1650,'Obihiro','JPN','Hokkaido',173685);
+INSERT INTO City VALUES (1651,'Tomakomai','JPN','Hokkaido',171958);
+INSERT INTO City VALUES (1652,'Saga','JPN','Saga',170034);
+INSERT INTO City VALUES (1653,'Sakura','JPN','Chiba',168072);
+INSERT INTO City VALUES (1654,'Kamakura','JPN','Kanagawa',167661);
+INSERT INTO City VALUES (1655,'Mitaka','JPN','Tokyo-to',167268);
+INSERT INTO City VALUES (1656,'Izumi','JPN','Osaka',166979);
+INSERT INTO City VALUES (1657,'Hino','JPN','Tokyo-to',166770);
+INSERT INTO City VALUES (1658,'Hadano','JPN','Kanagawa',166512);
+INSERT INTO City VALUES (1659,'Ashikaga','JPN','Tochigi',165243);
+INSERT INTO City VALUES (1660,'Tsu','JPN','Mie',164543);
+INSERT INTO City VALUES (1661,'Sayama','JPN','Saitama',162472);
+INSERT INTO City VALUES (1662,'Yachiyo','JPN','Chiba',161222);
+INSERT INTO City VALUES (1663,'Tsukuba','JPN','Ibaragi',160768);
+INSERT INTO City VALUES (1664,'Tachikawa','JPN','Tokyo-to',159430);
+INSERT INTO City VALUES (1665,'Kumagaya','JPN','Saitama',157171);
+INSERT INTO City VALUES (1666,'Moriguchi','JPN','Osaka',155941);
+INSERT INTO City VALUES (1667,'Otaru','JPN','Hokkaido',155784);
+INSERT INTO City VALUES (1668,'Anjo','JPN','Aichi',153823);
+INSERT INTO City VALUES (1669,'Narashino','JPN','Chiba',152849);
+INSERT INTO City VALUES (1670,'Oyama','JPN','Tochigi',152820);
+INSERT INTO City VALUES (1671,'Ogaki','JPN','Gifu',151758);
+INSERT INTO City VALUES (1672,'Matsue','JPN','Shimane',149821);
+INSERT INTO City VALUES (1673,'Kawanishi','JPN','Hyogo',149794);
+INSERT INTO City VALUES (1674,'Hitachinaka','JPN','Tokyo-to',148006);
+INSERT INTO City VALUES (1675,'Niiza','JPN','Saitama',147744);
+INSERT INTO City VALUES (1676,'Nagareyama','JPN','Chiba',147738);
+INSERT INTO City VALUES (1677,'Tottori','JPN','Tottori',147523);
+INSERT INTO City VALUES (1678,'Tama','JPN','Ibaragi',146712);
+INSERT INTO City VALUES (1679,'Iruma','JPN','Saitama',145922);
+INSERT INTO City VALUES (1680,'Ota','JPN','Gumma',145317);
+INSERT INTO City VALUES (1681,'Omuta','JPN','Fukuoka',142889);
+INSERT INTO City VALUES (1682,'Komaki','JPN','Aichi',139827);
+INSERT INTO City VALUES (1683,'Ome','JPN','Tokyo-to',139216);
+INSERT INTO City VALUES (1684,'Kadoma','JPN','Osaka',138953);
+INSERT INTO City VALUES (1685,'Yamaguchi','JPN','Yamaguchi',138210);
+INSERT INTO City VALUES (1686,'Higashimurayama','JPN','Tokyo-to',136970);
+INSERT INTO City VALUES (1687,'Yonago','JPN','Tottori',136461);
+INSERT INTO City VALUES (1688,'Matsubara','JPN','Osaka',135010);
+INSERT INTO City VALUES (1689,'Musashino','JPN','Tokyo-to',134426);
+INSERT INTO City VALUES (1690,'Tsuchiura','JPN','Ibaragi',134072);
+INSERT INTO City VALUES (1691,'Joetsu','JPN','Niigata',133505);
+INSERT INTO City VALUES (1692,'Miyakonojo','JPN','Miyazaki',133183);
+INSERT INTO City VALUES (1693,'Misato','JPN','Saitama',132957);
+INSERT INTO City VALUES (1694,'Kakamigahara','JPN','Gifu',131831);
+INSERT INTO City VALUES (1695,'Daito','JPN','Osaka',130594);
+INSERT INTO City VALUES (1696,'Seto','JPN','Aichi',130470);
+INSERT INTO City VALUES (1697,'Kariya','JPN','Aichi',127969);
+INSERT INTO City VALUES (1698,'Urayasu','JPN','Chiba',127550);
+INSERT INTO City VALUES (1699,'Beppu','JPN','Oita',127486);
+INSERT INTO City VALUES (1700,'Niihama','JPN','Ehime',127207);
+INSERT INTO City VALUES (1701,'Minoo','JPN','Osaka',127026);
+INSERT INTO City VALUES (1702,'Fujieda','JPN','Shizuoka',126897);
+INSERT INTO City VALUES (1703,'Abiko','JPN','Chiba',126670);
+INSERT INTO City VALUES (1704,'Nobeoka','JPN','Miyazaki',125547);
+INSERT INTO City VALUES (1705,'Tondabayashi','JPN','Osaka',125094);
+INSERT INTO City VALUES (1706,'Ueda','JPN','Nagano',124217);
+INSERT INTO City VALUES (1707,'Kashihara','JPN','Nara',124013);
+INSERT INTO City VALUES (1708,'Matsusaka','JPN','Mie',123582);
+INSERT INTO City VALUES (1709,'Isesaki','JPN','Gumma',123285);
+INSERT INTO City VALUES (1710,'Zama','JPN','Kanagawa',122046);
+INSERT INTO City VALUES (1711,'Kisarazu','JPN','Chiba',121967);
+INSERT INTO City VALUES (1712,'Noda','JPN','Chiba',121030);
+INSERT INTO City VALUES (1713,'Ishinomaki','JPN','Miyagi',120963);
+INSERT INTO City VALUES (1714,'Fujinomiya','JPN','Shizuoka',119714);
+INSERT INTO City VALUES (1715,'Kawachinagano','JPN','Osaka',119666);
+INSERT INTO City VALUES (1716,'Imabari','JPN','Ehime',119357);
+INSERT INTO City VALUES (1717,'Aizuwakamatsu','JPN','Fukushima',119287);
+INSERT INTO City VALUES (1718,'Higashihiroshima','JPN','Hiroshima',119166);
+INSERT INTO City VALUES (1719,'Habikino','JPN','Osaka',118968);
+INSERT INTO City VALUES (1720,'Ebetsu','JPN','Hokkaido',118805);
+INSERT INTO City VALUES (1721,'Hofu','JPN','Yamaguchi',118751);
+INSERT INTO City VALUES (1722,'Kiryu','JPN','Gumma',118326);
+INSERT INTO City VALUES (1723,'Okinawa','JPN','Okinawa',117748);
+INSERT INTO City VALUES (1724,'Yaizu','JPN','Shizuoka',117258);
+INSERT INTO City VALUES (1725,'Toyokawa','JPN','Aichi',115781);
+INSERT INTO City VALUES (1726,'Ebina','JPN','Kanagawa',115571);
+INSERT INTO City VALUES (1727,'Asaka','JPN','Saitama',114815);
+INSERT INTO City VALUES (1728,'Higashikurume','JPN','Tokyo-to',111666);
+INSERT INTO City VALUES (1729,'Ikoma','JPN','Nara',111645);
+INSERT INTO City VALUES (1730,'Kitami','JPN','Hokkaido',111295);
+INSERT INTO City VALUES (1731,'Koganei','JPN','Tokyo-to',110969);
+INSERT INTO City VALUES (1732,'Iwatsuki','JPN','Saitama',110034);
+INSERT INTO City VALUES (1733,'Mishima','JPN','Shizuoka',109699);
+INSERT INTO City VALUES (1734,'Handa','JPN','Aichi',108600);
+INSERT INTO City VALUES (1735,'Muroran','JPN','Hokkaido',108275);
+INSERT INTO City VALUES (1736,'Komatsu','JPN','Ishikawa',107937);
+INSERT INTO City VALUES (1737,'Yatsushiro','JPN','Kumamoto',107661);
+INSERT INTO City VALUES (1738,'Iida','JPN','Nagano',107583);
+INSERT INTO City VALUES (1739,'Tokuyama','JPN','Yamaguchi',107078);
+INSERT INTO City VALUES (1740,'Kokubunji','JPN','Tokyo-to',106996);
+INSERT INTO City VALUES (1741,'Akishima','JPN','Tokyo-to',106914);
+INSERT INTO City VALUES (1742,'Iwakuni','JPN','Yamaguchi',106647);
+INSERT INTO City VALUES (1743,'Kusatsu','JPN','Shiga',106232);
+INSERT INTO City VALUES (1744,'Kuwana','JPN','Mie',106121);
+INSERT INTO City VALUES (1745,'Sanda','JPN','Hyogo',105643);
+INSERT INTO City VALUES (1746,'Hikone','JPN','Shiga',105508);
+INSERT INTO City VALUES (1747,'Toda','JPN','Saitama',103969);
+INSERT INTO City VALUES (1748,'Tajimi','JPN','Gifu',103171);
+INSERT INTO City VALUES (1749,'Ikeda','JPN','Osaka',102710);
+INSERT INTO City VALUES (1750,'Fukaya','JPN','Saitama',102156);
+INSERT INTO City VALUES (1751,'Ise','JPN','Mie',101732);
+INSERT INTO City VALUES (1752,'Sakata','JPN','Yamagata',101651);
+INSERT INTO City VALUES (1753,'Kasuga','JPN','Fukuoka',101344);
+INSERT INTO City VALUES (1754,'Kamagaya','JPN','Chiba',100821);
+INSERT INTO City VALUES (1755,'Tsuruoka','JPN','Yamagata',100713);
+INSERT INTO City VALUES (1756,'Hoya','JPN','Tokyo-to',100313);
+INSERT INTO City VALUES (1757,'Nishio','JPN','Chiba',100032);
+INSERT INTO City VALUES (1758,'Tokai','JPN','Aichi',99738);
+INSERT INTO City VALUES (1759,'Inazawa','JPN','Aichi',98746);
+INSERT INTO City VALUES (1760,'Sakado','JPN','Saitama',98221);
+INSERT INTO City VALUES (1761,'Isehara','JPN','Kanagawa',98123);
+INSERT INTO City VALUES (1762,'Takasago','JPN','Hyogo',97632);
+INSERT INTO City VALUES (1763,'Fujimi','JPN','Saitama',96972);
+INSERT INTO City VALUES (1764,'Urasoe','JPN','Okinawa',96002);
+INSERT INTO City VALUES (1765,'Yonezawa','JPN','Yamagata',95592);
+INSERT INTO City VALUES (1766,'Konan','JPN','Aichi',95521);
+INSERT INTO City VALUES (1767,'Yamatokoriyama','JPN','Nara',95165);
+INSERT INTO City VALUES (1768,'Maizuru','JPN','Kyoto',94784);
+INSERT INTO City VALUES (1769,'Onomichi','JPN','Hiroshima',93756);
+INSERT INTO City VALUES (1770,'Higashimatsuyama','JPN','Saitama',93342);
+INSERT INTO City VALUES (1771,'Kimitsu','JPN','Chiba',93216);
+INSERT INTO City VALUES (1772,'Isahaya','JPN','Nagasaki',93058);
+INSERT INTO City VALUES (1773,'Kanuma','JPN','Tochigi',93053);
+INSERT INTO City VALUES (1774,'Izumisano','JPN','Osaka',92583);
+INSERT INTO City VALUES (1775,'Kameoka','JPN','Kyoto',92398);
+INSERT INTO City VALUES (1776,'Mobara','JPN','Chiba',91664);
+INSERT INTO City VALUES (1777,'Narita','JPN','Chiba',91470);
+INSERT INTO City VALUES (1778,'Kashiwazaki','JPN','Niigata',91229);
+INSERT INTO City VALUES (1779,'Tsuyama','JPN','Okayama',91170);
+INSERT INTO City VALUES (1780,'Sanaa','YEM','Sanaa',503600);
+INSERT INTO City VALUES (1781,'Aden','YEM','Aden',398300);
+INSERT INTO City VALUES (1782,'Taizz','YEM','Taizz',317600);
+INSERT INTO City VALUES (1783,'Hodeida','YEM','Hodeida',298500);
+INSERT INTO City VALUES (1784,'al-Mukalla','YEM','Hadramawt',122400);
+INSERT INTO City VALUES (1785,'Ibb','YEM','Ibb',103300);
+INSERT INTO City VALUES (1786,'Amman','JOR','Amman',1000000);
+INSERT INTO City VALUES (1787,'al-Zarqa','JOR','al-Zarqa',389815);
+INSERT INTO City VALUES (1788,'Irbid','JOR','Irbid',231511);
+INSERT INTO City VALUES (1789,'al-Rusayfa','JOR','al-Zarqa',137247);
+INSERT INTO City VALUES (1790,'Wadi al-Sir','JOR','Amman',89104);
+INSERT INTO City VALUES (1791,'Flying Fish Cove','CXR','–',700);
+INSERT INTO City VALUES (1792,'Beograd','YUG','Central Serbia',1204000);
+INSERT INTO City VALUES (1793,'Novi Sad','YUG','Vojvodina',179626);
+INSERT INTO City VALUES (1794,'Niš','YUG','Central Serbia',175391);
+INSERT INTO City VALUES (1795,'Priština','YUG','Kosovo and Metohija',155496);
+INSERT INTO City VALUES (1796,'Kragujevac','YUG','Central Serbia',147305);
+INSERT INTO City VALUES (1797,'Podgorica','YUG','Montenegro',135000);
+INSERT INTO City VALUES (1798,'Subotica','YUG','Vojvodina',100386);
+INSERT INTO City VALUES (1799,'Prizren','YUG','Kosovo and Metohija',92303);
+INSERT INTO City VALUES (1800,'Phnom Penh','KHM','Phnom Penh',570155);
+INSERT INTO City VALUES (1801,'Battambang','KHM','Battambang',129800);
+INSERT INTO City VALUES (1802,'Siem Reap','KHM','Siem Reap',105100);
+INSERT INTO City VALUES (1803,'Douala','CMR','Littoral',1448300);
+INSERT INTO City VALUES (1804,'Yaoundé','CMR','Centre',1372800);
+INSERT INTO City VALUES (1805,'Garoua','CMR','Nord',177000);
+INSERT INTO City VALUES (1806,'Maroua','CMR','Extrême-Nord',143000);
+INSERT INTO City VALUES (1807,'Bamenda','CMR','Nord-Ouest',138000);
+INSERT INTO City VALUES (1808,'Bafoussam','CMR','Ouest',131000);
+INSERT INTO City VALUES (1809,'Nkongsamba','CMR','Littoral',112454);
+INSERT INTO City VALUES (1810,'Montréal','CAN','Québec',1016376);
+INSERT INTO City VALUES (1811,'Calgary','CAN','Alberta',768082);
+INSERT INTO City VALUES (1812,'Toronto','CAN','Ontario',688275);
+INSERT INTO City VALUES (1813,'North York','CAN','Ontario',622632);
+INSERT INTO City VALUES (1814,'Winnipeg','CAN','Manitoba',618477);
+INSERT INTO City VALUES (1815,'Edmonton','CAN','Alberta',616306);
+INSERT INTO City VALUES (1816,'Mississauga','CAN','Ontario',608072);
+INSERT INTO City VALUES (1817,'Scarborough','CAN','Ontario',594501);
+INSERT INTO City VALUES (1818,'Vancouver','CAN','British Colombia',514008);
+INSERT INTO City VALUES (1819,'Etobicoke','CAN','Ontario',348845);
+INSERT INTO City VALUES (1820,'London','CAN','Ontario',339917);
+INSERT INTO City VALUES (1821,'Hamilton','CAN','Ontario',335614);
+INSERT INTO City VALUES (1822,'Ottawa','CAN','Ontario',335277);
+INSERT INTO City VALUES (1823,'Laval','CAN','Québec',330393);
+INSERT INTO City VALUES (1824,'Surrey','CAN','British Colombia',304477);
+INSERT INTO City VALUES (1825,'Brampton','CAN','Ontario',296711);
+INSERT INTO City VALUES (1826,'Windsor','CAN','Ontario',207588);
+INSERT INTO City VALUES (1827,'Saskatoon','CAN','Saskatchewan',193647);
+INSERT INTO City VALUES (1828,'Kitchener','CAN','Ontario',189959);
+INSERT INTO City VALUES (1829,'Markham','CAN','Ontario',189098);
+INSERT INTO City VALUES (1830,'Regina','CAN','Saskatchewan',180400);
+INSERT INTO City VALUES (1831,'Burnaby','CAN','British Colombia',179209);
+INSERT INTO City VALUES (1832,'Québec','CAN','Québec',167264);
+INSERT INTO City VALUES (1833,'York','CAN','Ontario',154980);
+INSERT INTO City VALUES (1834,'Richmond','CAN','British Colombia',148867);
+INSERT INTO City VALUES (1835,'Vaughan','CAN','Ontario',147889);
+INSERT INTO City VALUES (1836,'Burlington','CAN','Ontario',145150);
+INSERT INTO City VALUES (1837,'Oshawa','CAN','Ontario',140173);
+INSERT INTO City VALUES (1838,'Oakville','CAN','Ontario',139192);
+INSERT INTO City VALUES (1839,'Saint Catharines','CAN','Ontario',136216);
+INSERT INTO City VALUES (1840,'Longueuil','CAN','Québec',127977);
+INSERT INTO City VALUES (1841,'Richmond Hill','CAN','Ontario',116428);
+INSERT INTO City VALUES (1842,'Thunder Bay','CAN','Ontario',115913);
+INSERT INTO City VALUES (1843,'Nepean','CAN','Ontario',115100);
+INSERT INTO City VALUES (1844,'Cape Breton','CAN','Nova Scotia',114733);
+INSERT INTO City VALUES (1845,'East York','CAN','Ontario',114034);
+INSERT INTO City VALUES (1846,'Halifax','CAN','Nova Scotia',113910);
+INSERT INTO City VALUES (1847,'Cambridge','CAN','Ontario',109186);
+INSERT INTO City VALUES (1848,'Gloucester','CAN','Ontario',107314);
+INSERT INTO City VALUES (1849,'Abbotsford','CAN','British Colombia',105403);
+INSERT INTO City VALUES (1850,'Guelph','CAN','Ontario',103593);
+INSERT INTO City VALUES (1851,'Saint John´s','CAN','Newfoundland',101936);
+INSERT INTO City VALUES (1852,'Coquitlam','CAN','British Colombia',101820);
+INSERT INTO City VALUES (1853,'Saanich','CAN','British Colombia',101388);
+INSERT INTO City VALUES (1854,'Gatineau','CAN','Québec',100702);
+INSERT INTO City VALUES (1855,'Delta','CAN','British Colombia',95411);
+INSERT INTO City VALUES (1856,'Sudbury','CAN','Ontario',92686);
+INSERT INTO City VALUES (1857,'Kelowna','CAN','British Colombia',89442);
+INSERT INTO City VALUES (1858,'Barrie','CAN','Ontario',89269);
+INSERT INTO City VALUES (1859,'Praia','CPV','São Tiago',94800);
+INSERT INTO City VALUES (1860,'Almaty','KAZ','Almaty Qalasy',1129400);
+INSERT INTO City VALUES (1861,'Qaraghandy','KAZ','Qaraghandy',436900);
+INSERT INTO City VALUES (1862,'Shymkent','KAZ','South Kazakstan',360100);
+INSERT INTO City VALUES (1863,'Taraz','KAZ','Taraz',330100);
+INSERT INTO City VALUES (1864,'Astana','KAZ','Astana',311200);
+INSERT INTO City VALUES (1865,'Öskemen','KAZ','East Kazakstan',311000);
+INSERT INTO City VALUES (1866,'Pavlodar','KAZ','Pavlodar',300500);
+INSERT INTO City VALUES (1867,'Semey','KAZ','East Kazakstan',269600);
+INSERT INTO City VALUES (1868,'Aqtöbe','KAZ','Aqtöbe',253100);
+INSERT INTO City VALUES (1869,'Qostanay','KAZ','Qostanay',221400);
+INSERT INTO City VALUES (1870,'Petropavl','KAZ','North Kazakstan',203500);
+INSERT INTO City VALUES (1871,'Oral','KAZ','West Kazakstan',195500);
+INSERT INTO City VALUES (1872,'Temirtau','KAZ','Qaraghandy',170500);
+INSERT INTO City VALUES (1873,'Qyzylorda','KAZ','Qyzylorda',157400);
+INSERT INTO City VALUES (1874,'Aqtau','KAZ','Mangghystau',143400);
+INSERT INTO City VALUES (1875,'Atyrau','KAZ','Atyrau',142500);
+INSERT INTO City VALUES (1876,'Ekibastuz','KAZ','Pavlodar',127200);
+INSERT INTO City VALUES (1877,'Kökshetau','KAZ','North Kazakstan',123400);
+INSERT INTO City VALUES (1878,'Rudnyy','KAZ','Qostanay',109500);
+INSERT INTO City VALUES (1879,'Taldyqorghan','KAZ','Almaty',98000);
+INSERT INTO City VALUES (1880,'Zhezqazghan','KAZ','Qaraghandy',90000);
+INSERT INTO City VALUES (1881,'Nairobi','KEN','Nairobi',2290000);
+INSERT INTO City VALUES (1882,'Mombasa','KEN','Coast',461753);
+INSERT INTO City VALUES (1883,'Kisumu','KEN','Nyanza',192733);
+INSERT INTO City VALUES (1884,'Nakuru','KEN','Rift Valley',163927);
+INSERT INTO City VALUES (1885,'Machakos','KEN','Eastern',116293);
+INSERT INTO City VALUES (1886,'Eldoret','KEN','Rift Valley',111882);
+INSERT INTO City VALUES (1887,'Meru','KEN','Eastern',94947);
+INSERT INTO City VALUES (1888,'Nyeri','KEN','Central',91258);
+INSERT INTO City VALUES (1889,'Bangui','CAF','Bangui',524000);
+INSERT INTO City VALUES (1890,'Shanghai','CHN','Shanghai',9696300);
+INSERT INTO City VALUES (1891,'Peking','CHN','Peking',7472000);
+INSERT INTO City VALUES (1892,'Chongqing','CHN','Chongqing',6351600);
+INSERT INTO City VALUES (1893,'Tianjin','CHN','Tianjin',5286800);
+INSERT INTO City VALUES (1894,'Wuhan','CHN','Hubei',4344600);
+INSERT INTO City VALUES (1895,'Harbin','CHN','Heilongjiang',4289800);
+INSERT INTO City VALUES (1896,'Shenyang','CHN','Liaoning',4265200);
+INSERT INTO City VALUES (1897,'Kanton [Guangzhou]','CHN','Guangdong',4256300);
+INSERT INTO City VALUES (1898,'Chengdu','CHN','Sichuan',3361500);
+INSERT INTO City VALUES (1899,'Nanking [Nanjing]','CHN','Jiangsu',2870300);
+INSERT INTO City VALUES (1900,'Changchun','CHN','Jilin',2812000);
+INSERT INTO City VALUES (1901,'Xi´an','CHN','Shaanxi',2761400);
+INSERT INTO City VALUES (1902,'Dalian','CHN','Liaoning',2697000);
+INSERT INTO City VALUES (1903,'Qingdao','CHN','Shandong',2596000);
+INSERT INTO City VALUES (1904,'Jinan','CHN','Shandong',2278100);
+INSERT INTO City VALUES (1905,'Hangzhou','CHN','Zhejiang',2190500);
+INSERT INTO City VALUES (1906,'Zhengzhou','CHN','Henan',2107200);
+INSERT INTO City VALUES (1907,'Shijiazhuang','CHN','Hebei',2041500);
+INSERT INTO City VALUES (1908,'Taiyuan','CHN','Shanxi',1968400);
+INSERT INTO City VALUES (1909,'Kunming','CHN','Yunnan',1829500);
+INSERT INTO City VALUES (1910,'Changsha','CHN','Hunan',1809800);
+INSERT INTO City VALUES (1911,'Nanchang','CHN','Jiangxi',1691600);
+INSERT INTO City VALUES (1912,'Fuzhou','CHN','Fujian',1593800);
+INSERT INTO City VALUES (1913,'Lanzhou','CHN','Gansu',1565800);
+INSERT INTO City VALUES (1914,'Guiyang','CHN','Guizhou',1465200);
+INSERT INTO City VALUES (1915,'Ningbo','CHN','Zhejiang',1371200);
+INSERT INTO City VALUES (1916,'Hefei','CHN','Anhui',1369100);
+INSERT INTO City VALUES (1917,'Urumtši [Ürümqi]','CHN','Xinxiang',1310100);
+INSERT INTO City VALUES (1918,'Anshan','CHN','Liaoning',1200000);
+INSERT INTO City VALUES (1919,'Fushun','CHN','Liaoning',1200000);
+INSERT INTO City VALUES (1920,'Nanning','CHN','Guangxi',1161800);
+INSERT INTO City VALUES (1921,'Zibo','CHN','Shandong',1140000);
+INSERT INTO City VALUES (1922,'Qiqihar','CHN','Heilongjiang',1070000);
+INSERT INTO City VALUES (1923,'Jilin','CHN','Jilin',1040000);
+INSERT INTO City VALUES (1924,'Tangshan','CHN','Hebei',1040000);
+INSERT INTO City VALUES (1925,'Baotou','CHN','Inner Mongolia',980000);
+INSERT INTO City VALUES (1926,'Shenzhen','CHN','Guangdong',950500);
+INSERT INTO City VALUES (1927,'Hohhot','CHN','Inner Mongolia',916700);
+INSERT INTO City VALUES (1928,'Handan','CHN','Hebei',840000);
+INSERT INTO City VALUES (1929,'Wuxi','CHN','Jiangsu',830000);
+INSERT INTO City VALUES (1930,'Xuzhou','CHN','Jiangsu',810000);
+INSERT INTO City VALUES (1931,'Datong','CHN','Shanxi',800000);
+INSERT INTO City VALUES (1932,'Yichun','CHN','Heilongjiang',800000);
+INSERT INTO City VALUES (1933,'Benxi','CHN','Liaoning',770000);
+INSERT INTO City VALUES (1934,'Luoyang','CHN','Henan',760000);
+INSERT INTO City VALUES (1935,'Suzhou','CHN','Jiangsu',710000);
+INSERT INTO City VALUES (1936,'Xining','CHN','Qinghai',700200);
+INSERT INTO City VALUES (1937,'Huainan','CHN','Anhui',700000);
+INSERT INTO City VALUES (1938,'Jixi','CHN','Heilongjiang',683885);
+INSERT INTO City VALUES (1939,'Daqing','CHN','Heilongjiang',660000);
+INSERT INTO City VALUES (1940,'Fuxin','CHN','Liaoning',640000);
+INSERT INTO City VALUES (1941,'Amoy [Xiamen]','CHN','Fujian',627500);
+INSERT INTO City VALUES (1942,'Liuzhou','CHN','Guangxi',610000);
+INSERT INTO City VALUES (1943,'Shantou','CHN','Guangdong',580000);
+INSERT INTO City VALUES (1944,'Jinzhou','CHN','Liaoning',570000);
+INSERT INTO City VALUES (1945,'Mudanjiang','CHN','Heilongjiang',570000);
+INSERT INTO City VALUES (1946,'Yinchuan','CHN','Ningxia',544500);
+INSERT INTO City VALUES (1947,'Changzhou','CHN','Jiangsu',530000);
+INSERT INTO City VALUES (1948,'Zhangjiakou','CHN','Hebei',530000);
+INSERT INTO City VALUES (1949,'Dandong','CHN','Liaoning',520000);
+INSERT INTO City VALUES (1950,'Hegang','CHN','Heilongjiang',520000);
+INSERT INTO City VALUES (1951,'Kaifeng','CHN','Henan',510000);
+INSERT INTO City VALUES (1952,'Jiamusi','CHN','Heilongjiang',493409);
+INSERT INTO City VALUES (1953,'Liaoyang','CHN','Liaoning',492559);
+INSERT INTO City VALUES (1954,'Hengyang','CHN','Hunan',487148);
+INSERT INTO City VALUES (1955,'Baoding','CHN','Hebei',483155);
+INSERT INTO City VALUES (1956,'Hunjiang','CHN','Jilin',482043);
+INSERT INTO City VALUES (1957,'Xinxiang','CHN','Henan',473762);
+INSERT INTO City VALUES (1958,'Huangshi','CHN','Hubei',457601);
+INSERT INTO City VALUES (1959,'Haikou','CHN','Hainan',454300);
+INSERT INTO City VALUES (1960,'Yantai','CHN','Shandong',452127);
+INSERT INTO City VALUES (1961,'Bengbu','CHN','Anhui',449245);
+INSERT INTO City VALUES (1962,'Xiangtan','CHN','Hunan',441968);
+INSERT INTO City VALUES (1963,'Weifang','CHN','Shandong',428522);
+INSERT INTO City VALUES (1964,'Wuhu','CHN','Anhui',425740);
+INSERT INTO City VALUES (1965,'Pingxiang','CHN','Jiangxi',425579);
+INSERT INTO City VALUES (1966,'Yingkou','CHN','Liaoning',421589);
+INSERT INTO City VALUES (1967,'Anyang','CHN','Henan',420332);
+INSERT INTO City VALUES (1968,'Panzhihua','CHN','Sichuan',415466);
+INSERT INTO City VALUES (1969,'Pingdingshan','CHN','Henan',410775);
+INSERT INTO City VALUES (1970,'Xiangfan','CHN','Hubei',410407);
+INSERT INTO City VALUES (1971,'Zhuzhou','CHN','Hunan',409924);
+INSERT INTO City VALUES (1972,'Jiaozuo','CHN','Henan',409100);
+INSERT INTO City VALUES (1973,'Wenzhou','CHN','Zhejiang',401871);
+INSERT INTO City VALUES (1974,'Zhangjiang','CHN','Guangdong',400997);
+INSERT INTO City VALUES (1975,'Zigong','CHN','Sichuan',393184);
+INSERT INTO City VALUES (1976,'Shuangyashan','CHN','Heilongjiang',386081);
+INSERT INTO City VALUES (1977,'Zaozhuang','CHN','Shandong',380846);
+INSERT INTO City VALUES (1978,'Yakeshi','CHN','Inner Mongolia',377869);
+INSERT INTO City VALUES (1979,'Yichang','CHN','Hubei',371601);
+INSERT INTO City VALUES (1980,'Zhenjiang','CHN','Jiangsu',368316);
+INSERT INTO City VALUES (1981,'Huaibei','CHN','Anhui',366549);
+INSERT INTO City VALUES (1982,'Qinhuangdao','CHN','Hebei',364972);
+INSERT INTO City VALUES (1983,'Guilin','CHN','Guangxi',364130);
+INSERT INTO City VALUES (1984,'Liupanshui','CHN','Guizhou',363954);
+INSERT INTO City VALUES (1985,'Panjin','CHN','Liaoning',362773);
+INSERT INTO City VALUES (1986,'Yangquan','CHN','Shanxi',362268);
+INSERT INTO City VALUES (1987,'Jinxi','CHN','Liaoning',357052);
+INSERT INTO City VALUES (1988,'Liaoyuan','CHN','Jilin',354141);
+INSERT INTO City VALUES (1989,'Lianyungang','CHN','Jiangsu',354139);
+INSERT INTO City VALUES (1990,'Xianyang','CHN','Shaanxi',352125);
+INSERT INTO City VALUES (1991,'Tai´an','CHN','Shandong',350696);
+INSERT INTO City VALUES (1992,'Chifeng','CHN','Inner Mongolia',350077);
+INSERT INTO City VALUES (1993,'Shaoguan','CHN','Guangdong',350043);
+INSERT INTO City VALUES (1994,'Nantong','CHN','Jiangsu',343341);
+INSERT INTO City VALUES (1995,'Leshan','CHN','Sichuan',341128);
+INSERT INTO City VALUES (1996,'Baoji','CHN','Shaanxi',337765);
+INSERT INTO City VALUES (1997,'Linyi','CHN','Shandong',324720);
+INSERT INTO City VALUES (1998,'Tonghua','CHN','Jilin',324600);
+INSERT INTO City VALUES (1999,'Siping','CHN','Jilin',317223);
+INSERT INTO City VALUES (2000,'Changzhi','CHN','Shanxi',317144);
+INSERT INTO City VALUES (2001,'Tengzhou','CHN','Shandong',315083);
+INSERT INTO City VALUES (2002,'Chaozhou','CHN','Guangdong',313469);
+INSERT INTO City VALUES (2003,'Yangzhou','CHN','Jiangsu',312892);
+INSERT INTO City VALUES (2004,'Dongwan','CHN','Guangdong',308669);
+INSERT INTO City VALUES (2005,'Ma´anshan','CHN','Anhui',305421);
+INSERT INTO City VALUES (2006,'Foshan','CHN','Guangdong',303160);
+INSERT INTO City VALUES (2007,'Yueyang','CHN','Hunan',302800);
+INSERT INTO City VALUES (2008,'Xingtai','CHN','Hebei',302789);
+INSERT INTO City VALUES (2009,'Changde','CHN','Hunan',301276);
+INSERT INTO City VALUES (2010,'Shihezi','CHN','Xinxiang',299676);
+INSERT INTO City VALUES (2011,'Yancheng','CHN','Jiangsu',296831);
+INSERT INTO City VALUES (2012,'Jiujiang','CHN','Jiangxi',291187);
+INSERT INTO City VALUES (2013,'Dongying','CHN','Shandong',281728);
+INSERT INTO City VALUES (2014,'Shashi','CHN','Hubei',281352);
+INSERT INTO City VALUES (2015,'Xintai','CHN','Shandong',281248);
+INSERT INTO City VALUES (2016,'Jingdezhen','CHN','Jiangxi',281183);
+INSERT INTO City VALUES (2017,'Tongchuan','CHN','Shaanxi',280657);
+INSERT INTO City VALUES (2018,'Zhongshan','CHN','Guangdong',278829);
+INSERT INTO City VALUES (2019,'Shiyan','CHN','Hubei',273786);
+INSERT INTO City VALUES (2020,'Tieli','CHN','Heilongjiang',265683);
+INSERT INTO City VALUES (2021,'Jining','CHN','Shandong',265248);
+INSERT INTO City VALUES (2022,'Wuhai','CHN','Inner Mongolia',264081);
+INSERT INTO City VALUES (2023,'Mianyang','CHN','Sichuan',262947);
+INSERT INTO City VALUES (2024,'Luzhou','CHN','Sichuan',262892);
+INSERT INTO City VALUES (2025,'Zunyi','CHN','Guizhou',261862);
+INSERT INTO City VALUES (2026,'Shizuishan','CHN','Ningxia',257862);
+INSERT INTO City VALUES (2027,'Neijiang','CHN','Sichuan',256012);
+INSERT INTO City VALUES (2028,'Tongliao','CHN','Inner Mongolia',255129);
+INSERT INTO City VALUES (2029,'Tieling','CHN','Liaoning',254842);
+INSERT INTO City VALUES (2030,'Wafangdian','CHN','Liaoning',251733);
+INSERT INTO City VALUES (2031,'Anqing','CHN','Anhui',250718);
+INSERT INTO City VALUES (2032,'Shaoyang','CHN','Hunan',247227);
+INSERT INTO City VALUES (2033,'Laiwu','CHN','Shandong',246833);
+INSERT INTO City VALUES (2034,'Chengde','CHN','Hebei',246799);
+INSERT INTO City VALUES (2035,'Tianshui','CHN','Gansu',244974);
+INSERT INTO City VALUES (2036,'Nanyang','CHN','Henan',243303);
+INSERT INTO City VALUES (2037,'Cangzhou','CHN','Hebei',242708);
+INSERT INTO City VALUES (2038,'Yibin','CHN','Sichuan',241019);
+INSERT INTO City VALUES (2039,'Huaiyin','CHN','Jiangsu',239675);
+INSERT INTO City VALUES (2040,'Dunhua','CHN','Jilin',235100);
+INSERT INTO City VALUES (2041,'Yanji','CHN','Jilin',230892);
+INSERT INTO City VALUES (2042,'Jiangmen','CHN','Guangdong',230587);
+INSERT INTO City VALUES (2043,'Tongling','CHN','Anhui',228017);
+INSERT INTO City VALUES (2044,'Suihua','CHN','Heilongjiang',227881);
+INSERT INTO City VALUES (2045,'Gongziling','CHN','Jilin',226569);
+INSERT INTO City VALUES (2046,'Xiantao','CHN','Hubei',222884);
+INSERT INTO City VALUES (2047,'Chaoyang','CHN','Liaoning',222394);
+INSERT INTO City VALUES (2048,'Ganzhou','CHN','Jiangxi',220129);
+INSERT INTO City VALUES (2049,'Huzhou','CHN','Zhejiang',218071);
+INSERT INTO City VALUES (2050,'Baicheng','CHN','Jilin',217987);
+INSERT INTO City VALUES (2051,'Shangzi','CHN','Heilongjiang',215373);
+INSERT INTO City VALUES (2052,'Yangjiang','CHN','Guangdong',215196);
+INSERT INTO City VALUES (2053,'Qitaihe','CHN','Heilongjiang',214957);
+INSERT INTO City VALUES (2054,'Gejiu','CHN','Yunnan',214294);
+INSERT INTO City VALUES (2055,'Jiangyin','CHN','Jiangsu',213659);
+INSERT INTO City VALUES (2056,'Hebi','CHN','Henan',212976);
+INSERT INTO City VALUES (2057,'Jiaxing','CHN','Zhejiang',211526);
+INSERT INTO City VALUES (2058,'Wuzhou','CHN','Guangxi',210452);
+INSERT INTO City VALUES (2059,'Meihekou','CHN','Jilin',209038);
+INSERT INTO City VALUES (2060,'Xuchang','CHN','Henan',208815);
+INSERT INTO City VALUES (2061,'Liaocheng','CHN','Shandong',207844);
+INSERT INTO City VALUES (2062,'Haicheng','CHN','Liaoning',205560);
+INSERT INTO City VALUES (2063,'Qianjiang','CHN','Hubei',205504);
+INSERT INTO City VALUES (2064,'Baiyin','CHN','Gansu',204970);
+INSERT INTO City VALUES (2065,'Bei´an','CHN','Heilongjiang',204899);
+INSERT INTO City VALUES (2066,'Yixing','CHN','Jiangsu',200824);
+INSERT INTO City VALUES (2067,'Laizhou','CHN','Shandong',198664);
+INSERT INTO City VALUES (2068,'Qaramay','CHN','Xinxiang',197602);
+INSERT INTO City VALUES (2069,'Acheng','CHN','Heilongjiang',197595);
+INSERT INTO City VALUES (2070,'Dezhou','CHN','Shandong',195485);
+INSERT INTO City VALUES (2071,'Nanping','CHN','Fujian',195064);
+INSERT INTO City VALUES (2072,'Zhaoqing','CHN','Guangdong',194784);
+INSERT INTO City VALUES (2073,'Beipiao','CHN','Liaoning',194301);
+INSERT INTO City VALUES (2074,'Fengcheng','CHN','Jiangxi',193784);
+INSERT INTO City VALUES (2075,'Fuyu','CHN','Jilin',192981);
+INSERT INTO City VALUES (2076,'Xinyang','CHN','Henan',192509);
+INSERT INTO City VALUES (2077,'Dongtai','CHN','Jiangsu',192247);
+INSERT INTO City VALUES (2078,'Yuci','CHN','Shanxi',191356);
+INSERT INTO City VALUES (2079,'Honghu','CHN','Hubei',190772);
+INSERT INTO City VALUES (2080,'Ezhou','CHN','Hubei',190123);
+INSERT INTO City VALUES (2081,'Heze','CHN','Shandong',189293);
+INSERT INTO City VALUES (2082,'Daxian','CHN','Sichuan',188101);
+INSERT INTO City VALUES (2083,'Linfen','CHN','Shanxi',187309);
+INSERT INTO City VALUES (2084,'Tianmen','CHN','Hubei',186332);
+INSERT INTO City VALUES (2085,'Yiyang','CHN','Hunan',185818);
+INSERT INTO City VALUES (2086,'Quanzhou','CHN','Fujian',185154);
+INSERT INTO City VALUES (2087,'Rizhao','CHN','Shandong',185048);
+INSERT INTO City VALUES (2088,'Deyang','CHN','Sichuan',182488);
+INSERT INTO City VALUES (2089,'Guangyuan','CHN','Sichuan',182241);
+INSERT INTO City VALUES (2090,'Changshu','CHN','Jiangsu',181805);
+INSERT INTO City VALUES (2091,'Zhangzhou','CHN','Fujian',181424);
+INSERT INTO City VALUES (2092,'Hailar','CHN','Inner Mongolia',180650);
+INSERT INTO City VALUES (2093,'Nanchong','CHN','Sichuan',180273);
+INSERT INTO City VALUES (2094,'Jiutai','CHN','Jilin',180130);
+INSERT INTO City VALUES (2095,'Zhaodong','CHN','Heilongjiang',179976);
+INSERT INTO City VALUES (2096,'Shaoxing','CHN','Zhejiang',179818);
+INSERT INTO City VALUES (2097,'Fuyang','CHN','Anhui',179572);
+INSERT INTO City VALUES (2098,'Maoming','CHN','Guangdong',178683);
+INSERT INTO City VALUES (2099,'Qujing','CHN','Yunnan',178669);
+INSERT INTO City VALUES (2100,'Ghulja','CHN','Xinxiang',177193);
+INSERT INTO City VALUES (2101,'Jiaohe','CHN','Jilin',176367);
+INSERT INTO City VALUES (2102,'Puyang','CHN','Henan',175988);
+INSERT INTO City VALUES (2103,'Huadian','CHN','Jilin',175873);
+INSERT INTO City VALUES (2104,'Jiangyou','CHN','Sichuan',175753);
+INSERT INTO City VALUES (2105,'Qashqar','CHN','Xinxiang',174570);
+INSERT INTO City VALUES (2106,'Anshun','CHN','Guizhou',174142);
+INSERT INTO City VALUES (2107,'Fuling','CHN','Sichuan',173878);
+INSERT INTO City VALUES (2108,'Xinyu','CHN','Jiangxi',173524);
+INSERT INTO City VALUES (2109,'Hanzhong','CHN','Shaanxi',169930);
+INSERT INTO City VALUES (2110,'Danyang','CHN','Jiangsu',169603);
+INSERT INTO City VALUES (2111,'Chenzhou','CHN','Hunan',169400);
+INSERT INTO City VALUES (2112,'Xiaogan','CHN','Hubei',166280);
+INSERT INTO City VALUES (2113,'Shangqiu','CHN','Henan',164880);
+INSERT INTO City VALUES (2114,'Zhuhai','CHN','Guangdong',164747);
+INSERT INTO City VALUES (2115,'Qingyuan','CHN','Guangdong',164641);
+INSERT INTO City VALUES (2116,'Aqsu','CHN','Xinxiang',164092);
+INSERT INTO City VALUES (2117,'Jining','CHN','Inner Mongolia',163552);
+INSERT INTO City VALUES (2118,'Xiaoshan','CHN','Zhejiang',162930);
+INSERT INTO City VALUES (2119,'Zaoyang','CHN','Hubei',162198);
+INSERT INTO City VALUES (2120,'Xinghua','CHN','Jiangsu',161910);
+INSERT INTO City VALUES (2121,'Hami','CHN','Xinxiang',161315);
+INSERT INTO City VALUES (2122,'Huizhou','CHN','Guangdong',161023);
+INSERT INTO City VALUES (2123,'Jinmen','CHN','Hubei',160794);
+INSERT INTO City VALUES (2124,'Sanming','CHN','Fujian',160691);
+INSERT INTO City VALUES (2125,'Ulanhot','CHN','Inner Mongolia',159538);
+INSERT INTO City VALUES (2126,'Korla','CHN','Xinxiang',159344);
+INSERT INTO City VALUES (2127,'Wanxian','CHN','Sichuan',156823);
+INSERT INTO City VALUES (2128,'Rui´an','CHN','Zhejiang',156468);
+INSERT INTO City VALUES (2129,'Zhoushan','CHN','Zhejiang',156317);
+INSERT INTO City VALUES (2130,'Liangcheng','CHN','Shandong',156307);
+INSERT INTO City VALUES (2131,'Jiaozhou','CHN','Shandong',153364);
+INSERT INTO City VALUES (2132,'Taizhou','CHN','Jiangsu',152442);
+INSERT INTO City VALUES (2133,'Suzhou','CHN','Anhui',151862);
+INSERT INTO City VALUES (2134,'Yichun','CHN','Jiangxi',151585);
+INSERT INTO City VALUES (2135,'Taonan','CHN','Jilin',150168);
+INSERT INTO City VALUES (2136,'Pingdu','CHN','Shandong',150123);
+INSERT INTO City VALUES (2137,'Ji´an','CHN','Jiangxi',148583);
+INSERT INTO City VALUES (2138,'Longkou','CHN','Shandong',148362);
+INSERT INTO City VALUES (2139,'Langfang','CHN','Hebei',148105);
+INSERT INTO City VALUES (2140,'Zhoukou','CHN','Henan',146288);
+INSERT INTO City VALUES (2141,'Suining','CHN','Sichuan',146086);
+INSERT INTO City VALUES (2142,'Yulin','CHN','Guangxi',144467);
+INSERT INTO City VALUES (2143,'Jinhua','CHN','Zhejiang',144280);
+INSERT INTO City VALUES (2144,'Liu´an','CHN','Anhui',144248);
+INSERT INTO City VALUES (2145,'Shuangcheng','CHN','Heilongjiang',142659);
+INSERT INTO City VALUES (2146,'Suizhou','CHN','Hubei',142302);
+INSERT INTO City VALUES (2147,'Ankang','CHN','Shaanxi',142170);
+INSERT INTO City VALUES (2148,'Weinan','CHN','Shaanxi',140169);
+INSERT INTO City VALUES (2149,'Longjing','CHN','Jilin',139417);
+INSERT INTO City VALUES (2150,'Da´an','CHN','Jilin',138963);
+INSERT INTO City VALUES (2151,'Lengshuijiang','CHN','Hunan',137994);
+INSERT INTO City VALUES (2152,'Laiyang','CHN','Shandong',137080);
+INSERT INTO City VALUES (2153,'Xianning','CHN','Hubei',136811);
+INSERT INTO City VALUES (2154,'Dali','CHN','Yunnan',136554);
+INSERT INTO City VALUES (2155,'Anda','CHN','Heilongjiang',136446);
+INSERT INTO City VALUES (2156,'Jincheng','CHN','Shanxi',136396);
+INSERT INTO City VALUES (2157,'Longyan','CHN','Fujian',134481);
+INSERT INTO City VALUES (2158,'Xichang','CHN','Sichuan',134419);
+INSERT INTO City VALUES (2159,'Wendeng','CHN','Shandong',133910);
+INSERT INTO City VALUES (2160,'Hailun','CHN','Heilongjiang',133565);
+INSERT INTO City VALUES (2161,'Binzhou','CHN','Shandong',133555);
+INSERT INTO City VALUES (2162,'Linhe','CHN','Inner Mongolia',133183);
+INSERT INTO City VALUES (2163,'Wuwei','CHN','Gansu',133101);
+INSERT INTO City VALUES (2164,'Duyun','CHN','Guizhou',132971);
+INSERT INTO City VALUES (2165,'Mishan','CHN','Heilongjiang',132744);
+INSERT INTO City VALUES (2166,'Shangrao','CHN','Jiangxi',132455);
+INSERT INTO City VALUES (2167,'Changji','CHN','Xinxiang',132260);
+INSERT INTO City VALUES (2168,'Meixian','CHN','Guangdong',132156);
+INSERT INTO City VALUES (2169,'Yushu','CHN','Jilin',131861);
+INSERT INTO City VALUES (2170,'Tiefa','CHN','Liaoning',131807);
+INSERT INTO City VALUES (2171,'Huai´an','CHN','Jiangsu',131149);
+INSERT INTO City VALUES (2172,'Leiyang','CHN','Hunan',130115);
+INSERT INTO City VALUES (2173,'Zalantun','CHN','Inner Mongolia',130031);
+INSERT INTO City VALUES (2174,'Weihai','CHN','Shandong',128888);
+INSERT INTO City VALUES (2175,'Loudi','CHN','Hunan',128418);
+INSERT INTO City VALUES (2176,'Qingzhou','CHN','Shandong',128258);
+INSERT INTO City VALUES (2177,'Qidong','CHN','Jiangsu',126872);
+INSERT INTO City VALUES (2178,'Huaihua','CHN','Hunan',126785);
+INSERT INTO City VALUES (2179,'Luohe','CHN','Henan',126438);
+INSERT INTO City VALUES (2180,'Chuzhou','CHN','Anhui',125341);
+INSERT INTO City VALUES (2181,'Kaiyuan','CHN','Liaoning',124219);
+INSERT INTO City VALUES (2182,'Linqing','CHN','Shandong',123958);
+INSERT INTO City VALUES (2183,'Chaohu','CHN','Anhui',123676);
+INSERT INTO City VALUES (2184,'Laohekou','CHN','Hubei',123366);
+INSERT INTO City VALUES (2185,'Dujiangyan','CHN','Sichuan',123357);
+INSERT INTO City VALUES (2186,'Zhumadian','CHN','Henan',123232);
+INSERT INTO City VALUES (2187,'Linchuan','CHN','Jiangxi',121949);
+INSERT INTO City VALUES (2188,'Jiaonan','CHN','Shandong',121397);
+INSERT INTO City VALUES (2189,'Sanmenxia','CHN','Henan',120523);
+INSERT INTO City VALUES (2190,'Heyuan','CHN','Guangdong',120101);
+INSERT INTO City VALUES (2191,'Manzhouli','CHN','Inner Mongolia',120023);
+INSERT INTO City VALUES (2192,'Lhasa','CHN','Tibet',120000);
+INSERT INTO City VALUES (2193,'Lianyuan','CHN','Hunan',118858);
+INSERT INTO City VALUES (2194,'Kuytun','CHN','Xinxiang',118553);
+INSERT INTO City VALUES (2195,'Puqi','CHN','Hubei',117264);
+INSERT INTO City VALUES (2196,'Hongjiang','CHN','Hunan',116188);
+INSERT INTO City VALUES (2197,'Qinzhou','CHN','Guangxi',114586);
+INSERT INTO City VALUES (2198,'Renqiu','CHN','Hebei',114256);
+INSERT INTO City VALUES (2199,'Yuyao','CHN','Zhejiang',114065);
+INSERT INTO City VALUES (2200,'Guigang','CHN','Guangxi',114025);
+INSERT INTO City VALUES (2201,'Kaili','CHN','Guizhou',113958);
+INSERT INTO City VALUES (2202,'Yan´an','CHN','Shaanxi',113277);
+INSERT INTO City VALUES (2203,'Beihai','CHN','Guangxi',112673);
+INSERT INTO City VALUES (2204,'Xuangzhou','CHN','Anhui',112673);
+INSERT INTO City VALUES (2205,'Quzhou','CHN','Zhejiang',112373);
+INSERT INTO City VALUES (2206,'Yong´an','CHN','Fujian',111762);
+INSERT INTO City VALUES (2207,'Zixing','CHN','Hunan',110048);
+INSERT INTO City VALUES (2208,'Liyang','CHN','Jiangsu',109520);
+INSERT INTO City VALUES (2209,'Yizheng','CHN','Jiangsu',109268);
+INSERT INTO City VALUES (2210,'Yumen','CHN','Gansu',109234);
+INSERT INTO City VALUES (2211,'Liling','CHN','Hunan',108504);
+INSERT INTO City VALUES (2212,'Yuncheng','CHN','Shanxi',108359);
+INSERT INTO City VALUES (2213,'Shanwei','CHN','Guangdong',107847);
+INSERT INTO City VALUES (2214,'Cixi','CHN','Zhejiang',107329);
+INSERT INTO City VALUES (2215,'Yuanjiang','CHN','Hunan',107004);
+INSERT INTO City VALUES (2216,'Bozhou','CHN','Anhui',106346);
+INSERT INTO City VALUES (2217,'Jinchang','CHN','Gansu',105287);
+INSERT INTO City VALUES (2218,'Fu´an','CHN','Fujian',105265);
+INSERT INTO City VALUES (2219,'Suqian','CHN','Jiangsu',105021);
+INSERT INTO City VALUES (2220,'Shishou','CHN','Hubei',104571);
+INSERT INTO City VALUES (2221,'Hengshui','CHN','Hebei',104269);
+INSERT INTO City VALUES (2222,'Danjiangkou','CHN','Hubei',103211);
+INSERT INTO City VALUES (2223,'Fujin','CHN','Heilongjiang',103104);
+INSERT INTO City VALUES (2224,'Sanya','CHN','Hainan',102820);
+INSERT INTO City VALUES (2225,'Guangshui','CHN','Hubei',102770);
+INSERT INTO City VALUES (2226,'Huangshan','CHN','Anhui',102628);
+INSERT INTO City VALUES (2227,'Xingcheng','CHN','Liaoning',102384);
+INSERT INTO City VALUES (2228,'Zhucheng','CHN','Shandong',102134);
+INSERT INTO City VALUES (2229,'Kunshan','CHN','Jiangsu',102052);
+INSERT INTO City VALUES (2230,'Haining','CHN','Zhejiang',100478);
+INSERT INTO City VALUES (2231,'Pingliang','CHN','Gansu',99265);
+INSERT INTO City VALUES (2232,'Fuqing','CHN','Fujian',99193);
+INSERT INTO City VALUES (2233,'Xinzhou','CHN','Shanxi',98667);
+INSERT INTO City VALUES (2234,'Jieyang','CHN','Guangdong',98531);
+INSERT INTO City VALUES (2235,'Zhangjiagang','CHN','Jiangsu',97994);
+INSERT INTO City VALUES (2236,'Tong Xian','CHN','Peking',97168);
+INSERT INTO City VALUES (2237,'Ya´an','CHN','Sichuan',95900);
+INSERT INTO City VALUES (2238,'Jinzhou','CHN','Liaoning',95761);
+INSERT INTO City VALUES (2239,'Emeishan','CHN','Sichuan',94000);
+INSERT INTO City VALUES (2240,'Enshi','CHN','Hubei',93056);
+INSERT INTO City VALUES (2241,'Bose','CHN','Guangxi',93009);
+INSERT INTO City VALUES (2242,'Yuzhou','CHN','Henan',92889);
+INSERT INTO City VALUES (2243,'Kaiyuan','CHN','Yunnan',91999);
+INSERT INTO City VALUES (2244,'Tumen','CHN','Jilin',91471);
+INSERT INTO City VALUES (2245,'Putian','CHN','Fujian',91030);
+INSERT INTO City VALUES (2246,'Linhai','CHN','Zhejiang',90870);
+INSERT INTO City VALUES (2247,'Xilin Hot','CHN','Inner Mongolia',90646);
+INSERT INTO City VALUES (2248,'Shaowu','CHN','Fujian',90286);
+INSERT INTO City VALUES (2249,'Junan','CHN','Shandong',90222);
+INSERT INTO City VALUES (2250,'Huaying','CHN','Sichuan',89400);
+INSERT INTO City VALUES (2251,'Pingyi','CHN','Shandong',89373);
+INSERT INTO City VALUES (2252,'Huangyan','CHN','Zhejiang',89288);
+INSERT INTO City VALUES (2253,'Bishkek','KGZ','Bishkek shaary',589400);
+INSERT INTO City VALUES (2254,'Osh','KGZ','Osh',222700);
+INSERT INTO City VALUES (2255,'Bikenibeu','KIR','South Tarawa',5055);
+INSERT INTO City VALUES (2256,'Bairiki','KIR','South Tarawa',2226);
+INSERT INTO City VALUES (2257,'Santafé de Bogotá','COL','Santafé de Bogotá',6260862);
+INSERT INTO City VALUES (2258,'Cali','COL','Valle',2077386);
+INSERT INTO City VALUES (2259,'Medellín','COL','Antioquia',1861265);
+INSERT INTO City VALUES (2260,'Barranquilla','COL','Atlántico',1223260);
+INSERT INTO City VALUES (2261,'Cartagena','COL','Bolívar',805757);
+INSERT INTO City VALUES (2262,'Cúcuta','COL','Norte de Santander',606932);
+INSERT INTO City VALUES (2263,'Bucaramanga','COL','Santander',515555);
+INSERT INTO City VALUES (2264,'Ibagué','COL','Tolima',393664);
+INSERT INTO City VALUES (2265,'Pereira','COL','Risaralda',381725);
+INSERT INTO City VALUES (2266,'Santa Marta','COL','Magdalena',359147);
+INSERT INTO City VALUES (2267,'Manizales','COL','Caldas',337580);
+INSERT INTO City VALUES (2268,'Bello','COL','Antioquia',333470);
+INSERT INTO City VALUES (2269,'Pasto','COL','Nariño',332396);
+INSERT INTO City VALUES (2270,'Neiva','COL','Huila',300052);
+INSERT INTO City VALUES (2271,'Soledad','COL','Atlántico',295058);
+INSERT INTO City VALUES (2272,'Armenia','COL','Quindío',288977);
+INSERT INTO City VALUES (2273,'Villavicencio','COL','Meta',273140);
+INSERT INTO City VALUES (2274,'Soacha','COL','Cundinamarca',272058);
+INSERT INTO City VALUES (2275,'Valledupar','COL','Cesar',263247);
+INSERT INTO City VALUES (2276,'Montería','COL','Córdoba',248245);
+INSERT INTO City VALUES (2277,'Itagüí','COL','Antioquia',228985);
+INSERT INTO City VALUES (2278,'Palmira','COL','Valle',226509);
+INSERT INTO City VALUES (2279,'Buenaventura','COL','Valle',224336);
+INSERT INTO City VALUES (2280,'Floridablanca','COL','Santander',221913);
+INSERT INTO City VALUES (2281,'Sincelejo','COL','Sucre',220704);
+INSERT INTO City VALUES (2282,'Popayán','COL','Cauca',200719);
+INSERT INTO City VALUES (2283,'Barrancabermeja','COL','Santander',178020);
+INSERT INTO City VALUES (2284,'Dos Quebradas','COL','Risaralda',159363);
+INSERT INTO City VALUES (2285,'Tuluá','COL','Valle',152488);
+INSERT INTO City VALUES (2286,'Envigado','COL','Antioquia',135848);
+INSERT INTO City VALUES (2287,'Cartago','COL','Valle',125884);
+INSERT INTO City VALUES (2288,'Girardot','COL','Cundinamarca',110963);
+INSERT INTO City VALUES (2289,'Buga','COL','Valle',110699);
+INSERT INTO City VALUES (2290,'Tunja','COL','Boyacá',109740);
+INSERT INTO City VALUES (2291,'Florencia','COL','Caquetá',108574);
+INSERT INTO City VALUES (2292,'Maicao','COL','La Guajira',108053);
+INSERT INTO City VALUES (2293,'Sogamoso','COL','Boyacá',107728);
+INSERT INTO City VALUES (2294,'Giron','COL','Santander',90688);
+INSERT INTO City VALUES (2295,'Moroni','COM','Njazidja',36000);
+INSERT INTO City VALUES (2296,'Brazzaville','COG','Brazzaville',950000);
+INSERT INTO City VALUES (2297,'Pointe-Noire','COG','Kouilou',500000);
+INSERT INTO City VALUES (2298,'Kinshasa','COD','Kinshasa',5064000);
+INSERT INTO City VALUES (2299,'Lubumbashi','COD','Shaba',851381);
+INSERT INTO City VALUES (2300,'Mbuji-Mayi','COD','East Kasai',806475);
+INSERT INTO City VALUES (2301,'Kolwezi','COD','Shaba',417810);
+INSERT INTO City VALUES (2302,'Kisangani','COD','Haute-Zaïre',417517);
+INSERT INTO City VALUES (2303,'Kananga','COD','West Kasai',393030);
+INSERT INTO City VALUES (2304,'Likasi','COD','Shaba',299118);
+INSERT INTO City VALUES (2305,'Bukavu','COD','South Kivu',201569);
+INSERT INTO City VALUES (2306,'Kikwit','COD','Bandundu',182142);
+INSERT INTO City VALUES (2307,'Tshikapa','COD','West Kasai',180860);
+INSERT INTO City VALUES (2308,'Matadi','COD','Bas-Zaïre',172730);
+INSERT INTO City VALUES (2309,'Mbandaka','COD','Equateur',169841);
+INSERT INTO City VALUES (2310,'Mwene-Ditu','COD','East Kasai',137459);
+INSERT INTO City VALUES (2311,'Boma','COD','Bas-Zaïre',135284);
+INSERT INTO City VALUES (2312,'Uvira','COD','South Kivu',115590);
+INSERT INTO City VALUES (2313,'Butembo','COD','North Kivu',109406);
+INSERT INTO City VALUES (2314,'Goma','COD','North Kivu',109094);
+INSERT INTO City VALUES (2315,'Kalemie','COD','Shaba',101309);
+INSERT INTO City VALUES (2316,'Bantam','CCK','Home Island',503);
+INSERT INTO City VALUES (2317,'West Island','CCK','West Island',167);
+INSERT INTO City VALUES (2318,'Pyongyang','PRK','Pyongyang-si',2484000);
+INSERT INTO City VALUES (2319,'Hamhung','PRK','Hamgyong N',709730);
+INSERT INTO City VALUES (2320,'Chongjin','PRK','Hamgyong P',582480);
+INSERT INTO City VALUES (2321,'Nampo','PRK','Nampo-si',566200);
+INSERT INTO City VALUES (2322,'Sinuiju','PRK','Pyongan P',326011);
+INSERT INTO City VALUES (2323,'Wonsan','PRK','Kangwon',300148);
+INSERT INTO City VALUES (2324,'Phyongsong','PRK','Pyongan N',272934);
+INSERT INTO City VALUES (2325,'Sariwon','PRK','Hwanghae P',254146);
+INSERT INTO City VALUES (2326,'Haeju','PRK','Hwanghae N',229172);
+INSERT INTO City VALUES (2327,'Kanggye','PRK','Chagang',223410);
+INSERT INTO City VALUES (2328,'Kimchaek','PRK','Hamgyong P',179000);
+INSERT INTO City VALUES (2329,'Hyesan','PRK','Yanggang',178020);
+INSERT INTO City VALUES (2330,'Kaesong','PRK','Kaesong-si',171500);
+INSERT INTO City VALUES (2331,'Seoul','KOR','Seoul',9981619);
+INSERT INTO City VALUES (2332,'Pusan','KOR','Pusan',3804522);
+INSERT INTO City VALUES (2333,'Inchon','KOR','Inchon',2559424);
+INSERT INTO City VALUES (2334,'Taegu','KOR','Taegu',2548568);
+INSERT INTO City VALUES (2335,'Taejon','KOR','Taejon',1425835);
+INSERT INTO City VALUES (2336,'Kwangju','KOR','Kwangju',1368341);
+INSERT INTO City VALUES (2337,'Ulsan','KOR','Kyongsangnam',1084891);
+INSERT INTO City VALUES (2338,'Songnam','KOR','Kyonggi',869094);
+INSERT INTO City VALUES (2339,'Puchon','KOR','Kyonggi',779412);
+INSERT INTO City VALUES (2340,'Suwon','KOR','Kyonggi',755550);
+INSERT INTO City VALUES (2341,'Anyang','KOR','Kyonggi',591106);
+INSERT INTO City VALUES (2342,'Chonju','KOR','Chollabuk',563153);
+INSERT INTO City VALUES (2343,'Chongju','KOR','Chungchongbuk',531376);
+INSERT INTO City VALUES (2344,'Koyang','KOR','Kyonggi',518282);
+INSERT INTO City VALUES (2345,'Ansan','KOR','Kyonggi',510314);
+INSERT INTO City VALUES (2346,'Pohang','KOR','Kyongsangbuk',508899);
+INSERT INTO City VALUES (2347,'Chang-won','KOR','Kyongsangnam',481694);
+INSERT INTO City VALUES (2348,'Masan','KOR','Kyongsangnam',441242);
+INSERT INTO City VALUES (2349,'Kwangmyong','KOR','Kyonggi',350914);
+INSERT INTO City VALUES (2350,'Chonan','KOR','Chungchongnam',330259);
+INSERT INTO City VALUES (2351,'Chinju','KOR','Kyongsangnam',329886);
+INSERT INTO City VALUES (2352,'Iksan','KOR','Chollabuk',322685);
+INSERT INTO City VALUES (2353,'Pyongtaek','KOR','Kyonggi',312927);
+INSERT INTO City VALUES (2354,'Kumi','KOR','Kyongsangbuk',311431);
+INSERT INTO City VALUES (2355,'Uijongbu','KOR','Kyonggi',276111);
+INSERT INTO City VALUES (2356,'Kyongju','KOR','Kyongsangbuk',272968);
+INSERT INTO City VALUES (2357,'Kunsan','KOR','Chollabuk',266569);
+INSERT INTO City VALUES (2358,'Cheju','KOR','Cheju',258511);
+INSERT INTO City VALUES (2359,'Kimhae','KOR','Kyongsangnam',256370);
+INSERT INTO City VALUES (2360,'Sunchon','KOR','Chollanam',249263);
+INSERT INTO City VALUES (2361,'Mokpo','KOR','Chollanam',247452);
+INSERT INTO City VALUES (2362,'Yong-in','KOR','Kyonggi',242643);
+INSERT INTO City VALUES (2363,'Wonju','KOR','Kang-won',237460);
+INSERT INTO City VALUES (2364,'Kunpo','KOR','Kyonggi',235233);
+INSERT INTO City VALUES (2365,'Chunchon','KOR','Kang-won',234528);
+INSERT INTO City VALUES (2366,'Namyangju','KOR','Kyonggi',229060);
+INSERT INTO City VALUES (2367,'Kangnung','KOR','Kang-won',220403);
+INSERT INTO City VALUES (2368,'Chungju','KOR','Chungchongbuk',205206);
+INSERT INTO City VALUES (2369,'Andong','KOR','Kyongsangbuk',188443);
+INSERT INTO City VALUES (2370,'Yosu','KOR','Chollanam',183596);
+INSERT INTO City VALUES (2371,'Kyongsan','KOR','Kyongsangbuk',173746);
+INSERT INTO City VALUES (2372,'Paju','KOR','Kyonggi',163379);
+INSERT INTO City VALUES (2373,'Yangsan','KOR','Kyongsangnam',163351);
+INSERT INTO City VALUES (2374,'Ichon','KOR','Kyonggi',155332);
+INSERT INTO City VALUES (2375,'Asan','KOR','Chungchongnam',154663);
+INSERT INTO City VALUES (2376,'Koje','KOR','Kyongsangnam',147562);
+INSERT INTO City VALUES (2377,'Kimchon','KOR','Kyongsangbuk',147027);
+INSERT INTO City VALUES (2378,'Nonsan','KOR','Chungchongnam',146619);
+INSERT INTO City VALUES (2379,'Kuri','KOR','Kyonggi',142173);
+INSERT INTO City VALUES (2380,'Chong-up','KOR','Chollabuk',139111);
+INSERT INTO City VALUES (2381,'Chechon','KOR','Chungchongbuk',137070);
+INSERT INTO City VALUES (2382,'Sosan','KOR','Chungchongnam',134746);
+INSERT INTO City VALUES (2383,'Shihung','KOR','Kyonggi',133443);
+INSERT INTO City VALUES (2384,'Tong-yong','KOR','Kyongsangnam',131717);
+INSERT INTO City VALUES (2385,'Kongju','KOR','Chungchongnam',131229);
+INSERT INTO City VALUES (2386,'Yongju','KOR','Kyongsangbuk',131097);
+INSERT INTO City VALUES (2387,'Chinhae','KOR','Kyongsangnam',125997);
+INSERT INTO City VALUES (2388,'Sangju','KOR','Kyongsangbuk',124116);
+INSERT INTO City VALUES (2389,'Poryong','KOR','Chungchongnam',122604);
+INSERT INTO City VALUES (2390,'Kwang-yang','KOR','Chollanam',122052);
+INSERT INTO City VALUES (2391,'Miryang','KOR','Kyongsangnam',121501);
+INSERT INTO City VALUES (2392,'Hanam','KOR','Kyonggi',115812);
+INSERT INTO City VALUES (2393,'Kimje','KOR','Chollabuk',115427);
+INSERT INTO City VALUES (2394,'Yongchon','KOR','Kyongsangbuk',113511);
+INSERT INTO City VALUES (2395,'Sachon','KOR','Kyongsangnam',113494);
+INSERT INTO City VALUES (2396,'Uiwang','KOR','Kyonggi',108788);
+INSERT INTO City VALUES (2397,'Naju','KOR','Chollanam',107831);
+INSERT INTO City VALUES (2398,'Namwon','KOR','Chollabuk',103544);
+INSERT INTO City VALUES (2399,'Tonghae','KOR','Kang-won',95472);
+INSERT INTO City VALUES (2400,'Mun-gyong','KOR','Kyongsangbuk',92239);
+INSERT INTO City VALUES (2401,'Athenai','GRC','Attika',772072);
+INSERT INTO City VALUES (2402,'Thessaloniki','GRC','Central Macedonia',383967);
+INSERT INTO City VALUES (2403,'Pireus','GRC','Attika',182671);
+INSERT INTO City VALUES (2404,'Patras','GRC','West Greece',153344);
+INSERT INTO City VALUES (2405,'Peristerion','GRC','Attika',137288);
+INSERT INTO City VALUES (2406,'Herakleion','GRC','Crete',116178);
+INSERT INTO City VALUES (2407,'Kallithea','GRC','Attika',114233);
+INSERT INTO City VALUES (2408,'Larisa','GRC','Thessalia',113090);
+INSERT INTO City VALUES (2409,'Zagreb','HRV','Grad Zagreb',706770);
+INSERT INTO City VALUES (2410,'Split','HRV','Split-Dalmatia',189388);
+INSERT INTO City VALUES (2411,'Rijeka','HRV','Primorje-Gorski Kota',167964);
+INSERT INTO City VALUES (2412,'Osijek','HRV','Osijek-Baranja',104761);
+INSERT INTO City VALUES (2413,'La Habana','CUB','La Habana',2256000);
+INSERT INTO City VALUES (2414,'Santiago de Cuba','CUB','Santiago de Cuba',433180);
+INSERT INTO City VALUES (2415,'Camagüey','CUB','Camagüey',298726);
+INSERT INTO City VALUES (2416,'Holguín','CUB','Holguín',249492);
+INSERT INTO City VALUES (2417,'Santa Clara','CUB','Villa Clara',207350);
+INSERT INTO City VALUES (2418,'Guantánamo','CUB','Guantánamo',205078);
+INSERT INTO City VALUES (2419,'Pinar del Río','CUB','Pinar del Río',142100);
+INSERT INTO City VALUES (2420,'Bayamo','CUB','Granma',141000);
+INSERT INTO City VALUES (2421,'Cienfuegos','CUB','Cienfuegos',132770);
+INSERT INTO City VALUES (2422,'Victoria de las Tunas','CUB','Las Tunas',132350);
+INSERT INTO City VALUES (2423,'Matanzas','CUB','Matanzas',123273);
+INSERT INTO City VALUES (2424,'Manzanillo','CUB','Granma',109350);
+INSERT INTO City VALUES (2425,'Sancti-Spíritus','CUB','Sancti-Spíritus',100751);
+INSERT INTO City VALUES (2426,'Ciego de Ávila','CUB','Ciego de Ávila',98505);
+INSERT INTO City VALUES (2427,'al-Salimiya','KWT','Hawalli',130215);
+INSERT INTO City VALUES (2428,'Jalib al-Shuyukh','KWT','Hawalli',102178);
+INSERT INTO City VALUES (2429,'Kuwait','KWT','al-Asima',28859);
+INSERT INTO City VALUES (2430,'Nicosia','CYP','Nicosia',195000);
+INSERT INTO City VALUES (2431,'Limassol','CYP','Limassol',154400);
+INSERT INTO City VALUES (2432,'Vientiane','LAO','Viangchan',531800);
+INSERT INTO City VALUES (2433,'Savannakhet','LAO','Savannakhet',96652);
+INSERT INTO City VALUES (2434,'Riga','LVA','Riika',764328);
+INSERT INTO City VALUES (2435,'Daugavpils','LVA','Daugavpils',114829);
+INSERT INTO City VALUES (2436,'Liepaja','LVA','Liepaja',89439);
+INSERT INTO City VALUES (2437,'Maseru','LSO','Maseru',297000);
+INSERT INTO City VALUES (2438,'Beirut','LBN','Beirut',1100000);
+INSERT INTO City VALUES (2439,'Tripoli','LBN','al-Shamal',240000);
+INSERT INTO City VALUES (2440,'Monrovia','LBR','Montserrado',850000);
+INSERT INTO City VALUES (2441,'Tripoli','LBY','Tripoli',1682000);
+INSERT INTO City VALUES (2442,'Bengasi','LBY','Bengasi',804000);
+INSERT INTO City VALUES (2443,'Misrata','LBY','Misrata',121669);
+INSERT INTO City VALUES (2444,'al-Zawiya','LBY','al-Zawiya',89338);
+INSERT INTO City VALUES (2445,'Schaan','LIE','Schaan',5346);
+INSERT INTO City VALUES (2446,'Vaduz','LIE','Vaduz',5043);
+INSERT INTO City VALUES (2447,'Vilnius','LTU','Vilna',577969);
+INSERT INTO City VALUES (2448,'Kaunas','LTU','Kaunas',412639);
+INSERT INTO City VALUES (2449,'Klaipeda','LTU','Klaipeda',202451);
+INSERT INTO City VALUES (2450,'Šiauliai','LTU','Šiauliai',146563);
+INSERT INTO City VALUES (2451,'Panevezys','LTU','Panevezys',133695);
+INSERT INTO City VALUES (2452,'Luxembourg [Luxemburg/Lëtzebuerg]','LUX','Luxembourg',80700);
+INSERT INTO City VALUES (2453,'El-Aaiún','ESH','El-Aaiún',169000);
+INSERT INTO City VALUES (2454,'Macao','MAC','Macau',437500);
+INSERT INTO City VALUES (2455,'Antananarivo','MDG','Antananarivo',675669);
+INSERT INTO City VALUES (2456,'Toamasina','MDG','Toamasina',127441);
+INSERT INTO City VALUES (2457,'Antsirabé','MDG','Antananarivo',120239);
+INSERT INTO City VALUES (2458,'Mahajanga','MDG','Mahajanga',100807);
+INSERT INTO City VALUES (2459,'Fianarantsoa','MDG','Fianarantsoa',99005);
+INSERT INTO City VALUES (2460,'Skopje','MKD','Skopje',444299);
+INSERT INTO City VALUES (2461,'Blantyre','MWI','Blantyre',478155);
+INSERT INTO City VALUES (2462,'Lilongwe','MWI','Lilongwe',435964);
+INSERT INTO City VALUES (2463,'Male','MDV','Maale',71000);
+INSERT INTO City VALUES (2464,'Kuala Lumpur','MYS','Wilayah Persekutuan',1297526);
+INSERT INTO City VALUES (2465,'Ipoh','MYS','Perak',382853);
+INSERT INTO City VALUES (2466,'Johor Baharu','MYS','Johor',328436);
+INSERT INTO City VALUES (2467,'Petaling Jaya','MYS','Selangor',254350);
+INSERT INTO City VALUES (2468,'Kelang','MYS','Selangor',243355);
+INSERT INTO City VALUES (2469,'Kuala Terengganu','MYS','Terengganu',228119);
+INSERT INTO City VALUES (2470,'Pinang','MYS','Pulau Pinang',219603);
+INSERT INTO City VALUES (2471,'Kota Bharu','MYS','Kelantan',219582);
+INSERT INTO City VALUES (2472,'Kuantan','MYS','Pahang',199484);
+INSERT INTO City VALUES (2473,'Taiping','MYS','Perak',183261);
+INSERT INTO City VALUES (2474,'Seremban','MYS','Negeri Sembilan',182869);
+INSERT INTO City VALUES (2475,'Kuching','MYS','Sarawak',148059);
+INSERT INTO City VALUES (2476,'Sibu','MYS','Sarawak',126381);
+INSERT INTO City VALUES (2477,'Sandakan','MYS','Sabah',125841);
+INSERT INTO City VALUES (2478,'Alor Setar','MYS','Kedah',124412);
+INSERT INTO City VALUES (2479,'Selayang Baru','MYS','Selangor',124228);
+INSERT INTO City VALUES (2480,'Sungai Petani','MYS','Kedah',114763);
+INSERT INTO City VALUES (2481,'Shah Alam','MYS','Selangor',102019);
+INSERT INTO City VALUES (2482,'Bamako','MLI','Bamako',809552);
+INSERT INTO City VALUES (2483,'Birkirkara','MLT','Outer Harbour',21445);
+INSERT INTO City VALUES (2484,'Valletta','MLT','Inner Harbour',7073);
+INSERT INTO City VALUES (2485,'Casablanca','MAR','Casablanca',2940623);
+INSERT INTO City VALUES (2486,'Rabat','MAR','Rabat-Salé-Zammour-Z',623457);
+INSERT INTO City VALUES (2487,'Marrakech','MAR','Marrakech-Tensift-Al',621914);
+INSERT INTO City VALUES (2488,'Fès','MAR','Fès-Boulemane',541162);
+INSERT INTO City VALUES (2489,'Tanger','MAR','Tanger-Tétouan',521735);
+INSERT INTO City VALUES (2490,'Salé','MAR','Rabat-Salé-Zammour-Z',504420);
+INSERT INTO City VALUES (2491,'Meknès','MAR','Meknès-Tafilalet',460000);
+INSERT INTO City VALUES (2492,'Oujda','MAR','Oriental',365382);
+INSERT INTO City VALUES (2493,'Kénitra','MAR','Gharb-Chrarda-Béni H',292600);
+INSERT INTO City VALUES (2494,'Tétouan','MAR','Tanger-Tétouan',277516);
+INSERT INTO City VALUES (2495,'Safi','MAR','Doukkala-Abda',262300);
+INSERT INTO City VALUES (2496,'Agadir','MAR','Souss Massa-Draâ',155244);
+INSERT INTO City VALUES (2497,'Mohammedia','MAR','Casablanca',154706);
+INSERT INTO City VALUES (2498,'Khouribga','MAR','Chaouia-Ouardigha',152090);
+INSERT INTO City VALUES (2499,'Beni-Mellal','MAR','Tadla-Azilal',140212);
+INSERT INTO City VALUES (2500,'Témara','MAR','Rabat-Salé-Zammour-Z',126303);
+INSERT INTO City VALUES (2501,'El Jadida','MAR','Doukkala-Abda',119083);
+INSERT INTO City VALUES (2502,'Nador','MAR','Oriental',112450);
+INSERT INTO City VALUES (2503,'Ksar el Kebir','MAR','Tanger-Tétouan',107065);
+INSERT INTO City VALUES (2504,'Settat','MAR','Chaouia-Ouardigha',96200);
+INSERT INTO City VALUES (2505,'Taza','MAR','Taza-Al Hoceima-Taou',92700);
+INSERT INTO City VALUES (2506,'El Araich','MAR','Tanger-Tétouan',90400);
+INSERT INTO City VALUES (2507,'Dalap-Uliga-Darrit','MHL','Majuro',28000);
+INSERT INTO City VALUES (2508,'Fort-de-France','MTQ','Fort-de-France',94050);
+INSERT INTO City VALUES (2509,'Nouakchott','MRT','Nouakchott',667300);
+INSERT INTO City VALUES (2510,'Nouâdhibou','MRT','Dakhlet Nouâdhibou',97600);
+INSERT INTO City VALUES (2511,'Port-Louis','MUS','Port-Louis',138200);
+INSERT INTO City VALUES (2512,'Beau Bassin-Rose Hill','MUS','Plaines Wilhelms',100616);
+INSERT INTO City VALUES (2513,'Vacoas-Phoenix','MUS','Plaines Wilhelms',98464);
+INSERT INTO City VALUES (2514,'Mamoutzou','MYT','Mamoutzou',12000);
+INSERT INTO City VALUES (2515,'Ciudad de México','MEX','Distrito Federal',8591309);
+INSERT INTO City VALUES (2516,'Guadalajara','MEX','Jalisco',1647720);
+INSERT INTO City VALUES (2517,'Ecatepec de Morelos','MEX','México',1620303);
+INSERT INTO City VALUES (2518,'Puebla','MEX','Puebla',1346176);
+INSERT INTO City VALUES (2519,'Nezahualcóyotl','MEX','México',1224924);
+INSERT INTO City VALUES (2520,'Juárez','MEX','Chihuahua',1217818);
+INSERT INTO City VALUES (2521,'Tijuana','MEX','Baja California',1212232);
+INSERT INTO City VALUES (2522,'León','MEX','Guanajuato',1133576);
+INSERT INTO City VALUES (2523,'Monterrey','MEX','Nuevo León',1108499);
+INSERT INTO City VALUES (2524,'Zapopan','MEX','Jalisco',1002239);
+INSERT INTO City VALUES (2525,'Naucalpan de Juárez','MEX','México',857511);
+INSERT INTO City VALUES (2526,'Mexicali','MEX','Baja California',764902);
+INSERT INTO City VALUES (2527,'Culiacán','MEX','Sinaloa',744859);
+INSERT INTO City VALUES (2528,'Acapulco de Juárez','MEX','Guerrero',721011);
+INSERT INTO City VALUES (2529,'Tlalnepantla de Baz','MEX','México',720755);
+INSERT INTO City VALUES (2530,'Mérida','MEX','Yucatán',703324);
+INSERT INTO City VALUES (2531,'Chihuahua','MEX','Chihuahua',670208);
+INSERT INTO City VALUES (2532,'San Luis Potosí','MEX','San Luis Potosí',669353);
+INSERT INTO City VALUES (2533,'Guadalupe','MEX','Nuevo León',668780);
+INSERT INTO City VALUES (2534,'Toluca','MEX','México',665617);
+INSERT INTO City VALUES (2535,'Aguascalientes','MEX','Aguascalientes',643360);
+INSERT INTO City VALUES (2536,'Querétaro','MEX','Querétaro de Arteaga',639839);
+INSERT INTO City VALUES (2537,'Morelia','MEX','Michoacán de Ocampo',619958);
+INSERT INTO City VALUES (2538,'Hermosillo','MEX','Sonora',608697);
+INSERT INTO City VALUES (2539,'Saltillo','MEX','Coahuila de Zaragoza',577352);
+INSERT INTO City VALUES (2540,'Torreón','MEX','Coahuila de Zaragoza',529093);
+INSERT INTO City VALUES (2541,'Centro (Villahermosa)','MEX','Tabasco',519873);
+INSERT INTO City VALUES (2542,'San Nicolás de los Garza','MEX','Nuevo León',495540);
+INSERT INTO City VALUES (2543,'Durango','MEX','Durango',490524);
+INSERT INTO City VALUES (2544,'Chimalhuacán','MEX','México',490245);
+INSERT INTO City VALUES (2545,'Tlaquepaque','MEX','Jalisco',475472);
+INSERT INTO City VALUES (2546,'Atizapán de Zaragoza','MEX','México',467262);
+INSERT INTO City VALUES (2547,'Veracruz','MEX','Veracruz',457119);
+INSERT INTO City VALUES (2548,'Cuautitlán Izcalli','MEX','México',452976);
+INSERT INTO City VALUES (2549,'Irapuato','MEX','Guanajuato',440039);
+INSERT INTO City VALUES (2550,'Tuxtla Gutiérrez','MEX','Chiapas',433544);
+INSERT INTO City VALUES (2551,'Tultitlán','MEX','México',432411);
+INSERT INTO City VALUES (2552,'Reynosa','MEX','Tamaulipas',419776);
+INSERT INTO City VALUES (2553,'Benito Juárez','MEX','Quintana Roo',419276);
+INSERT INTO City VALUES (2554,'Matamoros','MEX','Tamaulipas',416428);
+INSERT INTO City VALUES (2555,'Xalapa','MEX','Veracruz',390058);
+INSERT INTO City VALUES (2556,'Celaya','MEX','Guanajuato',382140);
+INSERT INTO City VALUES (2557,'Mazatlán','MEX','Sinaloa',380265);
+INSERT INTO City VALUES (2558,'Ensenada','MEX','Baja California',369573);
+INSERT INTO City VALUES (2559,'Ahome','MEX','Sinaloa',358663);
+INSERT INTO City VALUES (2560,'Cajeme','MEX','Sonora',355679);
+INSERT INTO City VALUES (2561,'Cuernavaca','MEX','Morelos',337966);
+INSERT INTO City VALUES (2562,'Tonalá','MEX','Jalisco',336109);
+INSERT INTO City VALUES (2563,'Valle de Chalco Solidaridad','MEX','México',323113);
+INSERT INTO City VALUES (2564,'Nuevo Laredo','MEX','Tamaulipas',310277);
+INSERT INTO City VALUES (2565,'Tepic','MEX','Nayarit',305025);
+INSERT INTO City VALUES (2566,'Tampico','MEX','Tamaulipas',294789);
+INSERT INTO City VALUES (2567,'Ixtapaluca','MEX','México',293160);
+INSERT INTO City VALUES (2568,'Apodaca','MEX','Nuevo León',282941);
+INSERT INTO City VALUES (2569,'Guasave','MEX','Sinaloa',277201);
+INSERT INTO City VALUES (2570,'Gómez Palacio','MEX','Durango',272806);
+INSERT INTO City VALUES (2571,'Tapachula','MEX','Chiapas',271141);
+INSERT INTO City VALUES (2572,'Nicolás Romero','MEX','México',269393);
+INSERT INTO City VALUES (2573,'Coatzacoalcos','MEX','Veracruz',267037);
+INSERT INTO City VALUES (2574,'Uruapan','MEX','Michoacán de Ocampo',265211);
+INSERT INTO City VALUES (2575,'Victoria','MEX','Tamaulipas',262686);
+INSERT INTO City VALUES (2576,'Oaxaca de Juárez','MEX','Oaxaca',256848);
+INSERT INTO City VALUES (2577,'Coacalco de Berriozábal','MEX','México',252270);
+INSERT INTO City VALUES (2578,'Pachuca de Soto','MEX','Hidalgo',244688);
+INSERT INTO City VALUES (2579,'General Escobedo','MEX','Nuevo León',232961);
+INSERT INTO City VALUES (2580,'Salamanca','MEX','Guanajuato',226864);
+INSERT INTO City VALUES (2581,'Santa Catarina','MEX','Nuevo León',226573);
+INSERT INTO City VALUES (2582,'Tehuacán','MEX','Puebla',225943);
+INSERT INTO City VALUES (2583,'Chalco','MEX','México',222201);
+INSERT INTO City VALUES (2584,'Cárdenas','MEX','Tabasco',216903);
+INSERT INTO City VALUES (2585,'Campeche','MEX','Campeche',216735);
+INSERT INTO City VALUES (2586,'La Paz','MEX','México',213045);
+INSERT INTO City VALUES (2587,'Othón P. Blanco (Chetumal)','MEX','Quintana Roo',208014);
+INSERT INTO City VALUES (2588,'Texcoco','MEX','México',203681);
+INSERT INTO City VALUES (2589,'La Paz','MEX','Baja California Sur',196708);
+INSERT INTO City VALUES (2590,'Metepec','MEX','México',194265);
+INSERT INTO City VALUES (2591,'Monclova','MEX','Coahuila de Zaragoza',193657);
+INSERT INTO City VALUES (2592,'Huixquilucan','MEX','México',193156);
+INSERT INTO City VALUES (2593,'Chilpancingo de los Bravo','MEX','Guerrero',192509);
+INSERT INTO City VALUES (2594,'Puerto Vallarta','MEX','Jalisco',183741);
+INSERT INTO City VALUES (2595,'Fresnillo','MEX','Zacatecas',182744);
+INSERT INTO City VALUES (2596,'Ciudad Madero','MEX','Tamaulipas',182012);
+INSERT INTO City VALUES (2597,'Soledad de Graciano Sánchez','MEX','San Luis Potosí',179956);
+INSERT INTO City VALUES (2598,'San Juan del Río','MEX','Querétaro',179300);
+INSERT INTO City VALUES (2599,'San Felipe del Progreso','MEX','México',177330);
+INSERT INTO City VALUES (2600,'Córdoba','MEX','Veracruz',176952);
+INSERT INTO City VALUES (2601,'Tecámac','MEX','México',172410);
+INSERT INTO City VALUES (2602,'Ocosingo','MEX','Chiapas',171495);
+INSERT INTO City VALUES (2603,'Carmen','MEX','Campeche',171367);
+INSERT INTO City VALUES (2604,'Lázaro Cárdenas','MEX','Michoacán de Ocampo',170878);
+INSERT INTO City VALUES (2605,'Jiutepec','MEX','Morelos',170428);
+INSERT INTO City VALUES (2606,'Papantla','MEX','Veracruz',170123);
+INSERT INTO City VALUES (2607,'Comalcalco','MEX','Tabasco',164640);
+INSERT INTO City VALUES (2608,'Zamora','MEX','Michoacán de Ocampo',161191);
+INSERT INTO City VALUES (2609,'Nogales','MEX','Sonora',159103);
+INSERT INTO City VALUES (2610,'Huimanguillo','MEX','Tabasco',158335);
+INSERT INTO City VALUES (2611,'Cuautla','MEX','Morelos',153132);
+INSERT INTO City VALUES (2612,'Minatitlán','MEX','Veracruz',152983);
+INSERT INTO City VALUES (2613,'Poza Rica de Hidalgo','MEX','Veracruz',152678);
+INSERT INTO City VALUES (2614,'Ciudad Valles','MEX','San Luis Potosí',146411);
+INSERT INTO City VALUES (2615,'Navolato','MEX','Sinaloa',145396);
+INSERT INTO City VALUES (2616,'San Luis Río Colorado','MEX','Sonora',145276);
+INSERT INTO City VALUES (2617,'Pénjamo','MEX','Guanajuato',143927);
+INSERT INTO City VALUES (2618,'San Andrés Tuxtla','MEX','Veracruz',142251);
+INSERT INTO City VALUES (2619,'Guanajuato','MEX','Guanajuato',141215);
+INSERT INTO City VALUES (2620,'Navojoa','MEX','Sonora',140495);
+INSERT INTO City VALUES (2621,'Zitácuaro','MEX','Michoacán de Ocampo',137970);
+INSERT INTO City VALUES (2622,'Boca del Río','MEX','Veracruz-Llave',135721);
+INSERT INTO City VALUES (2623,'Allende','MEX','Guanajuato',134645);
+INSERT INTO City VALUES (2624,'Silao','MEX','Guanajuato',134037);
+INSERT INTO City VALUES (2625,'Macuspana','MEX','Tabasco',133795);
+INSERT INTO City VALUES (2626,'San Juan Bautista Tuxtepec','MEX','Oaxaca',133675);
+INSERT INTO City VALUES (2627,'San Cristóbal de las Casas','MEX','Chiapas',132317);
+INSERT INTO City VALUES (2628,'Valle de Santiago','MEX','Guanajuato',130557);
+INSERT INTO City VALUES (2629,'Guaymas','MEX','Sonora',130108);
+INSERT INTO City VALUES (2630,'Colima','MEX','Colima',129454);
+INSERT INTO City VALUES (2631,'Dolores Hidalgo','MEX','Guanajuato',128675);
+INSERT INTO City VALUES (2632,'Lagos de Moreno','MEX','Jalisco',127949);
+INSERT INTO City VALUES (2633,'Piedras Negras','MEX','Coahuila de Zaragoza',127898);
+INSERT INTO City VALUES (2634,'Altamira','MEX','Tamaulipas',127490);
+INSERT INTO City VALUES (2635,'Túxpam','MEX','Veracruz',126475);
+INSERT INTO City VALUES (2636,'San Pedro Garza García','MEX','Nuevo León',126147);
+INSERT INTO City VALUES (2637,'Cuauhtémoc','MEX','Chihuahua',124279);
+INSERT INTO City VALUES (2638,'Manzanillo','MEX','Colima',124014);
+INSERT INTO City VALUES (2639,'Iguala de la Independencia','MEX','Guerrero',123883);
+INSERT INTO City VALUES (2640,'Zacatecas','MEX','Zacatecas',123700);
+INSERT INTO City VALUES (2641,'Tlajomulco de Zúñiga','MEX','Jalisco',123220);
+INSERT INTO City VALUES (2642,'Tulancingo de Bravo','MEX','Hidalgo',121946);
+INSERT INTO City VALUES (2643,'Zinacantepec','MEX','México',121715);
+INSERT INTO City VALUES (2644,'San Martín Texmelucan','MEX','Puebla',121093);
+INSERT INTO City VALUES (2645,'Tepatitlán de Morelos','MEX','Jalisco',118948);
+INSERT INTO City VALUES (2646,'Martínez de la Torre','MEX','Veracruz',118815);
+INSERT INTO City VALUES (2647,'Orizaba','MEX','Veracruz',118488);
+INSERT INTO City VALUES (2648,'Apatzingán','MEX','Michoacán de Ocampo',117849);
+INSERT INTO City VALUES (2649,'Atlixco','MEX','Puebla',117019);
+INSERT INTO City VALUES (2650,'Delicias','MEX','Chihuahua',116132);
+INSERT INTO City VALUES (2651,'Ixtlahuaca','MEX','México',115548);
+INSERT INTO City VALUES (2652,'El Mante','MEX','Tamaulipas',112453);
+INSERT INTO City VALUES (2653,'Lerdo','MEX','Durango',112272);
+INSERT INTO City VALUES (2654,'Almoloya de Juárez','MEX','México',110550);
+INSERT INTO City VALUES (2655,'Acámbaro','MEX','Guanajuato',110487);
+INSERT INTO City VALUES (2656,'Acuña','MEX','Coahuila de Zaragoza',110388);
+INSERT INTO City VALUES (2657,'Guadalupe','MEX','Zacatecas',108881);
+INSERT INTO City VALUES (2658,'Huejutla de Reyes','MEX','Hidalgo',108017);
+INSERT INTO City VALUES (2659,'Hidalgo','MEX','Michoacán de Ocampo',106198);
+INSERT INTO City VALUES (2660,'Los Cabos','MEX','Baja California Sur',105199);
+INSERT INTO City VALUES (2661,'Comitán de Domínguez','MEX','Chiapas',104986);
+INSERT INTO City VALUES (2662,'Cunduacán','MEX','Tabasco',104164);
+INSERT INTO City VALUES (2663,'Río Bravo','MEX','Tamaulipas',103901);
+INSERT INTO City VALUES (2664,'Temapache','MEX','Veracruz',102824);
+INSERT INTO City VALUES (2665,'Chilapa de Alvarez','MEX','Guerrero',102716);
+INSERT INTO City VALUES (2666,'Hidalgo del Parral','MEX','Chihuahua',100881);
+INSERT INTO City VALUES (2667,'San Francisco del Rincón','MEX','Guanajuato',100149);
+INSERT INTO City VALUES (2668,'Taxco de Alarcón','MEX','Guerrero',99907);
+INSERT INTO City VALUES (2669,'Zumpango','MEX','México',99781);
+INSERT INTO City VALUES (2670,'San Pedro Cholula','MEX','Puebla',99734);
+INSERT INTO City VALUES (2671,'Lerma','MEX','México',99714);
+INSERT INTO City VALUES (2672,'Tecomán','MEX','Colima',99296);
+INSERT INTO City VALUES (2673,'Las Margaritas','MEX','Chiapas',97389);
+INSERT INTO City VALUES (2674,'Cosoleacaque','MEX','Veracruz',97199);
+INSERT INTO City VALUES (2675,'San Luis de la Paz','MEX','Guanajuato',96763);
+INSERT INTO City VALUES (2676,'José Azueta','MEX','Guerrero',95448);
+INSERT INTO City VALUES (2677,'Santiago Ixcuintla','MEX','Nayarit',95311);
+INSERT INTO City VALUES (2678,'San Felipe','MEX','Guanajuato',95305);
+INSERT INTO City VALUES (2679,'Tejupilco','MEX','México',94934);
+INSERT INTO City VALUES (2680,'Tantoyuca','MEX','Veracruz',94709);
+INSERT INTO City VALUES (2681,'Salvatierra','MEX','Guanajuato',94322);
+INSERT INTO City VALUES (2682,'Tultepec','MEX','México',93364);
+INSERT INTO City VALUES (2683,'Temixco','MEX','Morelos',92686);
+INSERT INTO City VALUES (2684,'Matamoros','MEX','Coahuila de Zaragoza',91858);
+INSERT INTO City VALUES (2685,'Pánuco','MEX','Veracruz',90551);
+INSERT INTO City VALUES (2686,'El Fuerte','MEX','Sinaloa',89556);
+INSERT INTO City VALUES (2687,'Tierra Blanca','MEX','Veracruz',89143);
+INSERT INTO City VALUES (2688,'Weno','FSM','Chuuk',22000);
+INSERT INTO City VALUES (2689,'Palikir','FSM','Pohnpei',8600);
+INSERT INTO City VALUES (2690,'Chisinau','MDA','Chisinau',719900);
+INSERT INTO City VALUES (2691,'Tiraspol','MDA','Dnjestria',194300);
+INSERT INTO City VALUES (2692,'Balti','MDA','Balti',153400);
+INSERT INTO City VALUES (2693,'Bender (Tîghina)','MDA','Bender (Tîghina)',125700);
+INSERT INTO City VALUES (2694,'Monte-Carlo','MCO','–',13154);
+INSERT INTO City VALUES (2695,'Monaco-Ville','MCO','–',1234);
+INSERT INTO City VALUES (2696,'Ulan Bator','MNG','Ulaanbaatar',773700);
+INSERT INTO City VALUES (2697,'Plymouth','MSR','Plymouth',2000);
+INSERT INTO City VALUES (2698,'Maputo','MOZ','Maputo',1018938);
+INSERT INTO City VALUES (2699,'Matola','MOZ','Maputo',424662);
+INSERT INTO City VALUES (2700,'Beira','MOZ','Sofala',397368);
+INSERT INTO City VALUES (2701,'Nampula','MOZ','Nampula',303346);
+INSERT INTO City VALUES (2702,'Chimoio','MOZ','Manica',171056);
+INSERT INTO City VALUES (2703,'Naçala-Porto','MOZ','Nampula',158248);
+INSERT INTO City VALUES (2704,'Quelimane','MOZ','Zambézia',150116);
+INSERT INTO City VALUES (2705,'Mocuba','MOZ','Zambézia',124700);
+INSERT INTO City VALUES (2706,'Tete','MOZ','Tete',101984);
+INSERT INTO City VALUES (2707,'Xai-Xai','MOZ','Gaza',99442);
+INSERT INTO City VALUES (2708,'Gurue','MOZ','Zambézia',99300);
+INSERT INTO City VALUES (2709,'Maxixe','MOZ','Inhambane',93985);
+INSERT INTO City VALUES (2710,'Rangoon (Yangon)','MMR','Rangoon [Yangon]',3361700);
+INSERT INTO City VALUES (2711,'Mandalay','MMR','Mandalay',885300);
+INSERT INTO City VALUES (2712,'Moulmein (Mawlamyine)','MMR','Mon',307900);
+INSERT INTO City VALUES (2713,'Pegu (Bago)','MMR','Pegu [Bago]',190900);
+INSERT INTO City VALUES (2714,'Bassein (Pathein)','MMR','Irrawaddy [Ayeyarwad',183900);
+INSERT INTO City VALUES (2715,'Monywa','MMR','Sagaing',138600);
+INSERT INTO City VALUES (2716,'Sittwe (Akyab)','MMR','Rakhine',137600);
+INSERT INTO City VALUES (2717,'Taunggyi (Taunggye)','MMR','Shan',131500);
+INSERT INTO City VALUES (2718,'Meikhtila','MMR','Mandalay',129700);
+INSERT INTO City VALUES (2719,'Mergui (Myeik)','MMR','Tenasserim [Tanintha',122700);
+INSERT INTO City VALUES (2720,'Lashio (Lasho)','MMR','Shan',107600);
+INSERT INTO City VALUES (2721,'Prome (Pyay)','MMR','Pegu [Bago]',105700);
+INSERT INTO City VALUES (2722,'Henzada (Hinthada)','MMR','Irrawaddy [Ayeyarwad',104700);
+INSERT INTO City VALUES (2723,'Myingyan','MMR','Mandalay',103600);
+INSERT INTO City VALUES (2724,'Tavoy (Dawei)','MMR','Tenasserim [Tanintha',96800);
+INSERT INTO City VALUES (2725,'Pagakku (Pakokku)','MMR','Magwe [Magway]',94800);
+INSERT INTO City VALUES (2726,'Windhoek','NAM','Khomas',169000);
+INSERT INTO City VALUES (2727,'Yangor','NRU','–',4050);
+INSERT INTO City VALUES (2728,'Yaren','NRU','–',559);
+INSERT INTO City VALUES (2729,'Kathmandu','NPL','Central',591835);
+INSERT INTO City VALUES (2730,'Biratnagar','NPL','Eastern',157764);
+INSERT INTO City VALUES (2731,'Pokhara','NPL','Western',146318);
+INSERT INTO City VALUES (2732,'Lalitapur','NPL','Central',145847);
+INSERT INTO City VALUES (2733,'Birgunj','NPL','Central',90639);
+INSERT INTO City VALUES (2734,'Managua','NIC','Managua',959000);
+INSERT INTO City VALUES (2735,'León','NIC','León',123865);
+INSERT INTO City VALUES (2736,'Chinandega','NIC','Chinandega',97387);
+INSERT INTO City VALUES (2737,'Masaya','NIC','Masaya',88971);
+INSERT INTO City VALUES (2738,'Niamey','NER','Niamey',420000);
+INSERT INTO City VALUES (2739,'Zinder','NER','Zinder',120892);
+INSERT INTO City VALUES (2740,'Maradi','NER','Maradi',112965);
+INSERT INTO City VALUES (2741,'Lagos','NGA','Lagos',1518000);
+INSERT INTO City VALUES (2742,'Ibadan','NGA','Oyo & Osun',1432000);
+INSERT INTO City VALUES (2743,'Ogbomosho','NGA','Oyo & Osun',730000);
+INSERT INTO City VALUES (2744,'Kano','NGA','Kano & Jigawa',674100);
+INSERT INTO City VALUES (2745,'Oshogbo','NGA','Oyo & Osun',476800);
+INSERT INTO City VALUES (2746,'Ilorin','NGA','Kwara & Kogi',475800);
+INSERT INTO City VALUES (2747,'Abeokuta','NGA','Ogun',427400);
+INSERT INTO City VALUES (2748,'Port Harcourt','NGA','Rivers & Bayelsa',410000);
+INSERT INTO City VALUES (2749,'Zaria','NGA','Kaduna',379200);
+INSERT INTO City VALUES (2750,'Ilesha','NGA','Oyo & Osun',378400);
+INSERT INTO City VALUES (2751,'Onitsha','NGA','Anambra & Enugu & Eb',371900);
+INSERT INTO City VALUES (2752,'Iwo','NGA','Oyo & Osun',362000);
+INSERT INTO City VALUES (2753,'Ado-Ekiti','NGA','Ondo & Ekiti',359400);
+INSERT INTO City VALUES (2754,'Abuja','NGA','Federal Capital Dist',350100);
+INSERT INTO City VALUES (2755,'Kaduna','NGA','Kaduna',342200);
+INSERT INTO City VALUES (2756,'Mushin','NGA','Lagos',333200);
+INSERT INTO City VALUES (2757,'Maiduguri','NGA','Borno & Yobe',320000);
+INSERT INTO City VALUES (2758,'Enugu','NGA','Anambra & Enugu & Eb',316100);
+INSERT INTO City VALUES (2759,'Ede','NGA','Oyo & Osun',307100);
+INSERT INTO City VALUES (2760,'Aba','NGA','Imo & Abia',298900);
+INSERT INTO City VALUES (2761,'Ife','NGA','Oyo & Osun',296800);
+INSERT INTO City VALUES (2762,'Ila','NGA','Oyo & Osun',264000);
+INSERT INTO City VALUES (2763,'Oyo','NGA','Oyo & Osun',256400);
+INSERT INTO City VALUES (2764,'Ikerre','NGA','Ondo & Ekiti',244600);
+INSERT INTO City VALUES (2765,'Benin City','NGA','Edo & Delta',229400);
+INSERT INTO City VALUES (2766,'Iseyin','NGA','Oyo & Osun',217300);
+INSERT INTO City VALUES (2767,'Katsina','NGA','Katsina',206500);
+INSERT INTO City VALUES (2768,'Jos','NGA','Plateau & Nassarawa',206300);
+INSERT INTO City VALUES (2769,'Sokoto','NGA','Sokoto & Kebbi & Zam',204900);
+INSERT INTO City VALUES (2770,'Ilobu','NGA','Oyo & Osun',199000);
+INSERT INTO City VALUES (2771,'Offa','NGA','Kwara & Kogi',197200);
+INSERT INTO City VALUES (2772,'Ikorodu','NGA','Lagos',184900);
+INSERT INTO City VALUES (2773,'Ilawe-Ekiti','NGA','Ondo & Ekiti',184500);
+INSERT INTO City VALUES (2774,'Owo','NGA','Ondo & Ekiti',183500);
+INSERT INTO City VALUES (2775,'Ikirun','NGA','Oyo & Osun',181400);
+INSERT INTO City VALUES (2776,'Shaki','NGA','Oyo & Osun',174500);
+INSERT INTO City VALUES (2777,'Calabar','NGA','Cross River',174400);
+INSERT INTO City VALUES (2778,'Ondo','NGA','Ondo & Ekiti',173600);
+INSERT INTO City VALUES (2779,'Akure','NGA','Ondo & Ekiti',162300);
+INSERT INTO City VALUES (2780,'Gusau','NGA','Sokoto & Kebbi & Zam',158000);
+INSERT INTO City VALUES (2781,'Ijebu-Ode','NGA','Ogun',156400);
+INSERT INTO City VALUES (2782,'Effon-Alaiye','NGA','Oyo & Osun',153100);
+INSERT INTO City VALUES (2783,'Kumo','NGA','Bauchi & Gombe',148000);
+INSERT INTO City VALUES (2784,'Shomolu','NGA','Lagos',147700);
+INSERT INTO City VALUES (2785,'Oka-Akoko','NGA','Ondo & Ekiti',142900);
+INSERT INTO City VALUES (2786,'Ikare','NGA','Ondo & Ekiti',140800);
+INSERT INTO City VALUES (2787,'Sapele','NGA','Edo & Delta',139200);
+INSERT INTO City VALUES (2788,'Deba Habe','NGA','Bauchi & Gombe',138600);
+INSERT INTO City VALUES (2789,'Minna','NGA','Niger',136900);
+INSERT INTO City VALUES (2790,'Warri','NGA','Edo & Delta',126100);
+INSERT INTO City VALUES (2791,'Bida','NGA','Niger',125500);
+INSERT INTO City VALUES (2792,'Ikire','NGA','Oyo & Osun',123300);
+INSERT INTO City VALUES (2793,'Makurdi','NGA','Benue',123100);
+INSERT INTO City VALUES (2794,'Lafia','NGA','Plateau & Nassarawa',122500);
+INSERT INTO City VALUES (2795,'Inisa','NGA','Oyo & Osun',119800);
+INSERT INTO City VALUES (2796,'Shagamu','NGA','Ogun',117200);
+INSERT INTO City VALUES (2797,'Awka','NGA','Anambra & Enugu & Eb',111200);
+INSERT INTO City VALUES (2798,'Gombe','NGA','Bauchi & Gombe',107800);
+INSERT INTO City VALUES (2799,'Igboho','NGA','Oyo & Osun',106800);
+INSERT INTO City VALUES (2800,'Ejigbo','NGA','Oyo & Osun',105900);
+INSERT INTO City VALUES (2801,'Agege','NGA','Lagos',105000);
+INSERT INTO City VALUES (2802,'Ise-Ekiti','NGA','Ondo & Ekiti',103400);
+INSERT INTO City VALUES (2803,'Ugep','NGA','Cross River',102600);
+INSERT INTO City VALUES (2804,'Epe','NGA','Lagos',101000);
+INSERT INTO City VALUES (2805,'Alofi','NIU','–',682);
+INSERT INTO City VALUES (2806,'Kingston','NFK','–',800);
+INSERT INTO City VALUES (2807,'Oslo','NOR','Oslo',508726);
+INSERT INTO City VALUES (2808,'Bergen','NOR','Hordaland',230948);
+INSERT INTO City VALUES (2809,'Trondheim','NOR','Sør-Trøndelag',150166);
+INSERT INTO City VALUES (2810,'Stavanger','NOR','Rogaland',108848);
+INSERT INTO City VALUES (2811,'Bærum','NOR','Akershus',101340);
+INSERT INTO City VALUES (2812,'Abidjan','CIV','Abidjan',2500000);
+INSERT INTO City VALUES (2813,'Bouaké','CIV','Bouaké',329850);
+INSERT INTO City VALUES (2814,'Yamoussoukro','CIV','Yamoussoukro',130000);
+INSERT INTO City VALUES (2815,'Daloa','CIV','Daloa',121842);
+INSERT INTO City VALUES (2816,'Korhogo','CIV','Korhogo',109445);
+INSERT INTO City VALUES (2817,'al-Sib','OMN','Masqat',155000);
+INSERT INTO City VALUES (2818,'Salala','OMN','Zufar',131813);
+INSERT INTO City VALUES (2819,'Bawshar','OMN','Masqat',107500);
+INSERT INTO City VALUES (2820,'Suhar','OMN','al-Batina',90814);
+INSERT INTO City VALUES (2821,'Masqat','OMN','Masqat',51969);
+INSERT INTO City VALUES (2822,'Karachi','PAK','Sindh',9269265);
+INSERT INTO City VALUES (2823,'Lahore','PAK','Punjab',5063499);
+INSERT INTO City VALUES (2824,'Faisalabad','PAK','Punjab',1977246);
+INSERT INTO City VALUES (2825,'Rawalpindi','PAK','Punjab',1406214);
+INSERT INTO City VALUES (2826,'Multan','PAK','Punjab',1182441);
+INSERT INTO City VALUES (2827,'Hyderabad','PAK','Sindh',1151274);
+INSERT INTO City VALUES (2828,'Gujranwala','PAK','Punjab',1124749);
+INSERT INTO City VALUES (2829,'Peshawar','PAK','Nothwest Border Prov',988005);
+INSERT INTO City VALUES (2830,'Quetta','PAK','Baluchistan',560307);
+INSERT INTO City VALUES (2831,'Islamabad','PAK','Islamabad',524500);
+INSERT INTO City VALUES (2832,'Sargodha','PAK','Punjab',455360);
+INSERT INTO City VALUES (2833,'Sialkot','PAK','Punjab',417597);
+INSERT INTO City VALUES (2834,'Bahawalpur','PAK','Punjab',403408);
+INSERT INTO City VALUES (2835,'Sukkur','PAK','Sindh',329176);
+INSERT INTO City VALUES (2836,'Jhang','PAK','Punjab',292214);
+INSERT INTO City VALUES (2837,'Sheikhupura','PAK','Punjab',271875);
+INSERT INTO City VALUES (2838,'Larkana','PAK','Sindh',270366);
+INSERT INTO City VALUES (2839,'Gujrat','PAK','Punjab',250121);
+INSERT INTO City VALUES (2840,'Mardan','PAK','Nothwest Border Prov',244511);
+INSERT INTO City VALUES (2841,'Kasur','PAK','Punjab',241649);
+INSERT INTO City VALUES (2842,'Rahim Yar Khan','PAK','Punjab',228479);
+INSERT INTO City VALUES (2843,'Sahiwal','PAK','Punjab',207388);
+INSERT INTO City VALUES (2844,'Okara','PAK','Punjab',200901);
+INSERT INTO City VALUES (2845,'Wah','PAK','Punjab',198400);
+INSERT INTO City VALUES (2846,'Dera Ghazi Khan','PAK','Punjab',188100);
+INSERT INTO City VALUES (2847,'Mirpur Khas','PAK','Sind',184500);
+INSERT INTO City VALUES (2848,'Nawabshah','PAK','Sind',183100);
+INSERT INTO City VALUES (2849,'Mingora','PAK','Nothwest Border Prov',174500);
+INSERT INTO City VALUES (2850,'Chiniot','PAK','Punjab',169300);
+INSERT INTO City VALUES (2851,'Kamoke','PAK','Punjab',151000);
+INSERT INTO City VALUES (2852,'Mandi Burewala','PAK','Punjab',149900);
+INSERT INTO City VALUES (2853,'Jhelum','PAK','Punjab',145800);
+INSERT INTO City VALUES (2854,'Sadiqabad','PAK','Punjab',141500);
+INSERT INTO City VALUES (2855,'Jacobabad','PAK','Sind',137700);
+INSERT INTO City VALUES (2856,'Shikarpur','PAK','Sind',133300);
+INSERT INTO City VALUES (2857,'Khanewal','PAK','Punjab',133000);
+INSERT INTO City VALUES (2858,'Hafizabad','PAK','Punjab',130200);
+INSERT INTO City VALUES (2859,'Kohat','PAK','Nothwest Border Prov',125300);
+INSERT INTO City VALUES (2860,'Muzaffargarh','PAK','Punjab',121600);
+INSERT INTO City VALUES (2861,'Khanpur','PAK','Punjab',117800);
+INSERT INTO City VALUES (2862,'Gojra','PAK','Punjab',115000);
+INSERT INTO City VALUES (2863,'Bahawalnagar','PAK','Punjab',109600);
+INSERT INTO City VALUES (2864,'Muridke','PAK','Punjab',108600);
+INSERT INTO City VALUES (2865,'Pak Pattan','PAK','Punjab',107800);
+INSERT INTO City VALUES (2866,'Abottabad','PAK','Nothwest Border Prov',106000);
+INSERT INTO City VALUES (2867,'Tando Adam','PAK','Sind',103400);
+INSERT INTO City VALUES (2868,'Jaranwala','PAK','Punjab',103300);
+INSERT INTO City VALUES (2869,'Khairpur','PAK','Sind',102200);
+INSERT INTO City VALUES (2870,'Chishtian Mandi','PAK','Punjab',101700);
+INSERT INTO City VALUES (2871,'Daska','PAK','Punjab',101500);
+INSERT INTO City VALUES (2872,'Dadu','PAK','Sind',98600);
+INSERT INTO City VALUES (2873,'Mandi Bahauddin','PAK','Punjab',97300);
+INSERT INTO City VALUES (2874,'Ahmadpur East','PAK','Punjab',96000);
+INSERT INTO City VALUES (2875,'Kamalia','PAK','Punjab',95300);
+INSERT INTO City VALUES (2876,'Khuzdar','PAK','Baluchistan',93100);
+INSERT INTO City VALUES (2877,'Vihari','PAK','Punjab',92300);
+INSERT INTO City VALUES (2878,'Dera Ismail Khan','PAK','Nothwest Border Prov',90400);
+INSERT INTO City VALUES (2879,'Wazirabad','PAK','Punjab',89700);
+INSERT INTO City VALUES (2880,'Nowshera','PAK','Nothwest Border Prov',89400);
+INSERT INTO City VALUES (2881,'Koror','PLW','Koror',12000);
+INSERT INTO City VALUES (2882,'Ciudad de Panamá','PAN','Panamá',471373);
+INSERT INTO City VALUES (2883,'San Miguelito','PAN','San Miguelito',315382);
+INSERT INTO City VALUES (2884,'Port Moresby','PNG','National Capital Dis',247000);
+INSERT INTO City VALUES (2885,'Asunción','PRY','Asunción',557776);
+INSERT INTO City VALUES (2886,'Ciudad del Este','PRY','Alto Paraná',133881);
+INSERT INTO City VALUES (2887,'San Lorenzo','PRY','Central',133395);
+INSERT INTO City VALUES (2888,'Lambaré','PRY','Central',99681);
+INSERT INTO City VALUES (2889,'Fernando de la Mora','PRY','Central',95287);
+INSERT INTO City VALUES (2890,'Lima','PER','Lima',6464693);
+INSERT INTO City VALUES (2891,'Arequipa','PER','Arequipa',762000);
+INSERT INTO City VALUES (2892,'Trujillo','PER','La Libertad',652000);
+INSERT INTO City VALUES (2893,'Chiclayo','PER','Lambayeque',517000);
+INSERT INTO City VALUES (2894,'Callao','PER','Callao',424294);
+INSERT INTO City VALUES (2895,'Iquitos','PER','Loreto',367000);
+INSERT INTO City VALUES (2896,'Chimbote','PER','Ancash',336000);
+INSERT INTO City VALUES (2897,'Huancayo','PER','Junín',327000);
+INSERT INTO City VALUES (2898,'Piura','PER','Piura',325000);
+INSERT INTO City VALUES (2899,'Cusco','PER','Cusco',291000);
+INSERT INTO City VALUES (2900,'Pucallpa','PER','Ucayali',220866);
+INSERT INTO City VALUES (2901,'Tacna','PER','Tacna',215683);
+INSERT INTO City VALUES (2902,'Ica','PER','Ica',194820);
+INSERT INTO City VALUES (2903,'Sullana','PER','Piura',147361);
+INSERT INTO City VALUES (2904,'Juliaca','PER','Puno',142576);
+INSERT INTO City VALUES (2905,'Huánuco','PER','Huanuco',129688);
+INSERT INTO City VALUES (2906,'Ayacucho','PER','Ayacucho',118960);
+INSERT INTO City VALUES (2907,'Chincha Alta','PER','Ica',110016);
+INSERT INTO City VALUES (2908,'Cajamarca','PER','Cajamarca',108009);
+INSERT INTO City VALUES (2909,'Puno','PER','Puno',101578);
+INSERT INTO City VALUES (2910,'Ventanilla','PER','Callao',101056);
+INSERT INTO City VALUES (2911,'Castilla','PER','Piura',90642);
+INSERT INTO City VALUES (2912,'Adamstown','PCN','–',42);
+INSERT INTO City VALUES (2913,'Garapan','MNP','Saipan',9200);
+INSERT INTO City VALUES (2914,'Lisboa','PRT','Lisboa',563210);
+INSERT INTO City VALUES (2915,'Porto','PRT','Porto',273060);
+INSERT INTO City VALUES (2916,'Amadora','PRT','Lisboa',122106);
+INSERT INTO City VALUES (2917,'Coímbra','PRT','Coímbra',96100);
+INSERT INTO City VALUES (2918,'Braga','PRT','Braga',90535);
+INSERT INTO City VALUES (2919,'San Juan','PRI','San Juan',434374);
+INSERT INTO City VALUES (2920,'Bayamón','PRI','Bayamón',224044);
+INSERT INTO City VALUES (2921,'Ponce','PRI','Ponce',186475);
+INSERT INTO City VALUES (2922,'Carolina','PRI','Carolina',186076);
+INSERT INTO City VALUES (2923,'Caguas','PRI','Caguas',140502);
+INSERT INTO City VALUES (2924,'Arecibo','PRI','Arecibo',100131);
+INSERT INTO City VALUES (2925,'Guaynabo','PRI','Guaynabo',100053);
+INSERT INTO City VALUES (2926,'Mayagüez','PRI','Mayagüez',98434);
+INSERT INTO City VALUES (2927,'Toa Baja','PRI','Toa Baja',94085);
+INSERT INTO City VALUES (2928,'Warszawa','POL','Mazowieckie',1615369);
+INSERT INTO City VALUES (2929,'Lódz','POL','Lodzkie',800110);
+INSERT INTO City VALUES (2930,'Kraków','POL','Malopolskie',738150);
+INSERT INTO City VALUES (2931,'Wroclaw','POL','Dolnoslaskie',636765);
+INSERT INTO City VALUES (2932,'Poznan','POL','Wielkopolskie',576899);
+INSERT INTO City VALUES (2933,'Gdansk','POL','Pomorskie',458988);
+INSERT INTO City VALUES (2934,'Szczecin','POL','Zachodnio-Pomorskie',416988);
+INSERT INTO City VALUES (2935,'Bydgoszcz','POL','Kujawsko-Pomorskie',386855);
+INSERT INTO City VALUES (2936,'Lublin','POL','Lubelskie',356251);
+INSERT INTO City VALUES (2937,'Katowice','POL','Slaskie',345934);
+INSERT INTO City VALUES (2938,'Bialystok','POL','Podlaskie',283937);
+INSERT INTO City VALUES (2939,'Czestochowa','POL','Slaskie',257812);
+INSERT INTO City VALUES (2940,'Gdynia','POL','Pomorskie',253521);
+INSERT INTO City VALUES (2941,'Sosnowiec','POL','Slaskie',244102);
+INSERT INTO City VALUES (2942,'Radom','POL','Mazowieckie',232262);
+INSERT INTO City VALUES (2943,'Kielce','POL','Swietokrzyskie',212383);
+INSERT INTO City VALUES (2944,'Gliwice','POL','Slaskie',212164);
+INSERT INTO City VALUES (2945,'Torun','POL','Kujawsko-Pomorskie',206158);
+INSERT INTO City VALUES (2946,'Bytom','POL','Slaskie',205560);
+INSERT INTO City VALUES (2947,'Zabrze','POL','Slaskie',200177);
+INSERT INTO City VALUES (2948,'Bielsko-Biala','POL','Slaskie',180307);
+INSERT INTO City VALUES (2949,'Olsztyn','POL','Warminsko-Mazurskie',170904);
+INSERT INTO City VALUES (2950,'Rzeszów','POL','Podkarpackie',162049);
+INSERT INTO City VALUES (2951,'Ruda Slaska','POL','Slaskie',159665);
+INSERT INTO City VALUES (2952,'Rybnik','POL','Slaskie',144582);
+INSERT INTO City VALUES (2953,'Walbrzych','POL','Dolnoslaskie',136923);
+INSERT INTO City VALUES (2954,'Tychy','POL','Slaskie',133178);
+INSERT INTO City VALUES (2955,'Dabrowa Górnicza','POL','Slaskie',131037);
+INSERT INTO City VALUES (2956,'Plock','POL','Mazowieckie',131011);
+INSERT INTO City VALUES (2957,'Elblag','POL','Warminsko-Mazurskie',129782);
+INSERT INTO City VALUES (2958,'Opole','POL','Opolskie',129553);
+INSERT INTO City VALUES (2959,'Gorzów Wielkopolski','POL','Lubuskie',126019);
+INSERT INTO City VALUES (2960,'Wloclawek','POL','Kujawsko-Pomorskie',123373);
+INSERT INTO City VALUES (2961,'Chorzów','POL','Slaskie',121708);
+INSERT INTO City VALUES (2962,'Tarnów','POL','Malopolskie',121494);
+INSERT INTO City VALUES (2963,'Zielona Góra','POL','Lubuskie',118182);
+INSERT INTO City VALUES (2964,'Koszalin','POL','Zachodnio-Pomorskie',112375);
+INSERT INTO City VALUES (2965,'Legnica','POL','Dolnoslaskie',109335);
+INSERT INTO City VALUES (2966,'Kalisz','POL','Wielkopolskie',106641);
+INSERT INTO City VALUES (2967,'Grudziadz','POL','Kujawsko-Pomorskie',102434);
+INSERT INTO City VALUES (2968,'Slupsk','POL','Pomorskie',102370);
+INSERT INTO City VALUES (2969,'Jastrzebie-Zdrój','POL','Slaskie',102294);
+INSERT INTO City VALUES (2970,'Jaworzno','POL','Slaskie',97929);
+INSERT INTO City VALUES (2971,'Jelenia Góra','POL','Dolnoslaskie',93901);
+INSERT INTO City VALUES (2972,'Malabo','GNQ','Bioko',40000);
+INSERT INTO City VALUES (2973,'Doha','QAT','Doha',355000);
+INSERT INTO City VALUES (2974,'Paris','FRA','Île-de-France',2125246);
+INSERT INTO City VALUES (2975,'Marseille','FRA','Provence-Alpes-Côte',798430);
+INSERT INTO City VALUES (2976,'Lyon','FRA','Rhône-Alpes',445452);
+INSERT INTO City VALUES (2977,'Toulouse','FRA','Midi-Pyrénées',390350);
+INSERT INTO City VALUES (2978,'Nice','FRA','Provence-Alpes-Côte',342738);
+INSERT INTO City VALUES (2979,'Nantes','FRA','Pays de la Loire',270251);
+INSERT INTO City VALUES (2980,'Strasbourg','FRA','Alsace',264115);
+INSERT INTO City VALUES (2981,'Montpellier','FRA','Languedoc-Roussillon',225392);
+INSERT INTO City VALUES (2982,'Bordeaux','FRA','Aquitaine',215363);
+INSERT INTO City VALUES (2983,'Rennes','FRA','Haute-Normandie',206229);
+INSERT INTO City VALUES (2984,'Le Havre','FRA','Champagne-Ardenne',190905);
+INSERT INTO City VALUES (2985,'Reims','FRA','Nord-Pas-de-Calais',187206);
+INSERT INTO City VALUES (2986,'Lille','FRA','Rhône-Alpes',184657);
+INSERT INTO City VALUES (2987,'St-Étienne','FRA','Bretagne',180210);
+INSERT INTO City VALUES (2988,'Toulon','FRA','Provence-Alpes-Côte',160639);
+INSERT INTO City VALUES (2989,'Grenoble','FRA','Rhône-Alpes',153317);
+INSERT INTO City VALUES (2990,'Angers','FRA','Pays de la Loire',151279);
+INSERT INTO City VALUES (2991,'Dijon','FRA','Bourgogne',149867);
+INSERT INTO City VALUES (2992,'Brest','FRA','Bretagne',149634);
+INSERT INTO City VALUES (2993,'Le Mans','FRA','Pays de la Loire',146105);
+INSERT INTO City VALUES (2994,'Clermont-Ferrand','FRA','Auvergne',137140);
+INSERT INTO City VALUES (2995,'Amiens','FRA','Picardie',135501);
+INSERT INTO City VALUES (2996,'Aix-en-Provence','FRA','Provence-Alpes-Côte',134222);
+INSERT INTO City VALUES (2997,'Limoges','FRA','Limousin',133968);
+INSERT INTO City VALUES (2998,'Nîmes','FRA','Languedoc-Roussillon',133424);
+INSERT INTO City VALUES (2999,'Tours','FRA','Centre',132820);
+INSERT INTO City VALUES (3000,'Villeurbanne','FRA','Rhône-Alpes',124215);
+INSERT INTO City VALUES (3001,'Metz','FRA','Lorraine',123776);
+INSERT INTO City VALUES (3002,'Besançon','FRA','Franche-Comté',117733);
+INSERT INTO City VALUES (3003,'Caen','FRA','Basse-Normandie',113987);
+INSERT INTO City VALUES (3004,'Orléans','FRA','Centre',113126);
+INSERT INTO City VALUES (3005,'Mulhouse','FRA','Alsace',110359);
+INSERT INTO City VALUES (3006,'Rouen','FRA','Haute-Normandie',106592);
+INSERT INTO City VALUES (3007,'Boulogne-Billancourt','FRA','Île-de-France',106367);
+INSERT INTO City VALUES (3008,'Perpignan','FRA','Languedoc-Roussillon',105115);
+INSERT INTO City VALUES (3009,'Nancy','FRA','Lorraine',103605);
+INSERT INTO City VALUES (3010,'Roubaix','FRA','Nord-Pas-de-Calais',96984);
+INSERT INTO City VALUES (3011,'Argenteuil','FRA','Île-de-France',93961);
+INSERT INTO City VALUES (3012,'Tourcoing','FRA','Nord-Pas-de-Calais',93540);
+INSERT INTO City VALUES (3013,'Montreuil','FRA','Île-de-France',90674);
+INSERT INTO City VALUES (3014,'Cayenne','GUF','Cayenne',50699);
+INSERT INTO City VALUES (3015,'Faaa','PYF','Tahiti',25888);
+INSERT INTO City VALUES (3016,'Papeete','PYF','Tahiti',25553);
+INSERT INTO City VALUES (3017,'Saint-Denis','REU','Saint-Denis',131480);
+INSERT INTO City VALUES (3018,'Bucuresti','ROM','Bukarest',2016131);
+INSERT INTO City VALUES (3019,'Iasi','ROM','Iasi',348070);
+INSERT INTO City VALUES (3020,'Constanta','ROM','Constanta',342264);
+INSERT INTO City VALUES (3021,'Cluj-Napoca','ROM','Cluj',332498);
+INSERT INTO City VALUES (3022,'Galati','ROM','Galati',330276);
+INSERT INTO City VALUES (3023,'Timisoara','ROM','Timis',324304);
+INSERT INTO City VALUES (3024,'Brasov','ROM','Brasov',314225);
+INSERT INTO City VALUES (3025,'Craiova','ROM','Dolj',313530);
+INSERT INTO City VALUES (3026,'Ploiesti','ROM','Prahova',251348);
+INSERT INTO City VALUES (3027,'Braila','ROM','Braila',233756);
+INSERT INTO City VALUES (3028,'Oradea','ROM','Bihor',222239);
+INSERT INTO City VALUES (3029,'Bacau','ROM','Bacau',209235);
+INSERT INTO City VALUES (3030,'Pitesti','ROM','Arges',187170);
+INSERT INTO City VALUES (3031,'Arad','ROM','Arad',184408);
+INSERT INTO City VALUES (3032,'Sibiu','ROM','Sibiu',169611);
+INSERT INTO City VALUES (3033,'Târgu Mures','ROM','Mures',165153);
+INSERT INTO City VALUES (3034,'Baia Mare','ROM','Maramures',149665);
+INSERT INTO City VALUES (3035,'Buzau','ROM','Buzau',148372);
+INSERT INTO City VALUES (3036,'Satu Mare','ROM','Satu Mare',130059);
+INSERT INTO City VALUES (3037,'Botosani','ROM','Botosani',128730);
+INSERT INTO City VALUES (3038,'Piatra Neamt','ROM','Neamt',125070);
+INSERT INTO City VALUES (3039,'Râmnicu Vâlcea','ROM','Vâlcea',119741);
+INSERT INTO City VALUES (3040,'Suceava','ROM','Suceava',118549);
+INSERT INTO City VALUES (3041,'Drobeta-Turnu Severin','ROM','Mehedinti',117865);
+INSERT INTO City VALUES (3042,'Târgoviste','ROM','Dâmbovita',98980);
+INSERT INTO City VALUES (3043,'Focsani','ROM','Vrancea',98979);
+INSERT INTO City VALUES (3044,'Târgu Jiu','ROM','Gorj',98524);
+INSERT INTO City VALUES (3045,'Tulcea','ROM','Tulcea',96278);
+INSERT INTO City VALUES (3046,'Resita','ROM','Caras-Severin',93976);
+INSERT INTO City VALUES (3047,'Kigali','RWA','Kigali',286000);
+INSERT INTO City VALUES (3048,'Stockholm','SWE','Lisboa',750348);
+INSERT INTO City VALUES (3049,'Gothenburg [Göteborg]','SWE','West Götanmaan län',466990);
+INSERT INTO City VALUES (3050,'Malmö','SWE','Skåne län',259579);
+INSERT INTO City VALUES (3051,'Uppsala','SWE','Uppsala län',189569);
+INSERT INTO City VALUES (3052,'Linköping','SWE','East Götanmaan län',133168);
+INSERT INTO City VALUES (3053,'Västerås','SWE','Västmanlands län',126328);
+INSERT INTO City VALUES (3054,'Örebro','SWE','Örebros län',124207);
+INSERT INTO City VALUES (3055,'Norrköping','SWE','East Götanmaan län',122199);
+INSERT INTO City VALUES (3056,'Helsingborg','SWE','Skåne län',117737);
+INSERT INTO City VALUES (3057,'Jönköping','SWE','Jönköpings län',117095);
+INSERT INTO City VALUES (3058,'Umeå','SWE','Västerbottens län',104512);
+INSERT INTO City VALUES (3059,'Lund','SWE','Skåne län',98948);
+INSERT INTO City VALUES (3060,'Borås','SWE','West Götanmaan län',96883);
+INSERT INTO City VALUES (3061,'Sundsvall','SWE','Västernorrlands län',93126);
+INSERT INTO City VALUES (3062,'Gävle','SWE','Gävleborgs län',90742);
+INSERT INTO City VALUES (3063,'Jamestown','SHN','Saint Helena',1500);
+INSERT INTO City VALUES (3064,'Basseterre','KNA','St George Basseterre',11600);
+INSERT INTO City VALUES (3065,'Castries','LCA','Castries',2301);
+INSERT INTO City VALUES (3066,'Kingstown','VCT','St George',17100);
+INSERT INTO City VALUES (3067,'Saint-Pierre','SPM','Saint-Pierre',5808);
+INSERT INTO City VALUES (3068,'Berlin','DEU','Berliini',3386667);
+INSERT INTO City VALUES (3069,'Hamburg','DEU','Hamburg',1704735);
+INSERT INTO City VALUES (3070,'Munich [München]','DEU','Baijeri',1194560);
+INSERT INTO City VALUES (3071,'Köln','DEU','Nordrhein-Westfalen',962507);
+INSERT INTO City VALUES (3072,'Frankfurt am Main','DEU','Hessen',643821);
+INSERT INTO City VALUES (3073,'Essen','DEU','Nordrhein-Westfalen',599515);
+INSERT INTO City VALUES (3074,'Dortmund','DEU','Nordrhein-Westfalen',590213);
+INSERT INTO City VALUES (3075,'Stuttgart','DEU','Baden-Württemberg',582443);
+INSERT INTO City VALUES (3076,'Düsseldorf','DEU','Nordrhein-Westfalen',568855);
+INSERT INTO City VALUES (3077,'Bremen','DEU','Bremen',540330);
+INSERT INTO City VALUES (3078,'Duisburg','DEU','Nordrhein-Westfalen',519793);
+INSERT INTO City VALUES (3079,'Hannover','DEU','Niedersachsen',514718);
+INSERT INTO City VALUES (3080,'Leipzig','DEU','Saksi',489532);
+INSERT INTO City VALUES (3081,'Nürnberg','DEU','Baijeri',486628);
+INSERT INTO City VALUES (3082,'Dresden','DEU','Saksi',476668);
+INSERT INTO City VALUES (3083,'Bochum','DEU','Nordrhein-Westfalen',392830);
+INSERT INTO City VALUES (3084,'Wuppertal','DEU','Nordrhein-Westfalen',368993);
+INSERT INTO City VALUES (3085,'Bielefeld','DEU','Nordrhein-Westfalen',321125);
+INSERT INTO City VALUES (3086,'Mannheim','DEU','Baden-Württemberg',307730);
+INSERT INTO City VALUES (3087,'Bonn','DEU','Nordrhein-Westfalen',301048);
+INSERT INTO City VALUES (3088,'Gelsenkirchen','DEU','Nordrhein-Westfalen',281979);
+INSERT INTO City VALUES (3089,'Karlsruhe','DEU','Baden-Württemberg',277204);
+INSERT INTO City VALUES (3090,'Wiesbaden','DEU','Hessen',268716);
+INSERT INTO City VALUES (3091,'Münster','DEU','Nordrhein-Westfalen',264670);
+INSERT INTO City VALUES (3092,'Mönchengladbach','DEU','Nordrhein-Westfalen',263697);
+INSERT INTO City VALUES (3093,'Chemnitz','DEU','Saksi',263222);
+INSERT INTO City VALUES (3094,'Augsburg','DEU','Baijeri',254867);
+INSERT INTO City VALUES (3095,'Halle/Saale','DEU','Anhalt Sachsen',254360);
+INSERT INTO City VALUES (3096,'Braunschweig','DEU','Niedersachsen',246322);
+INSERT INTO City VALUES (3097,'Aachen','DEU','Nordrhein-Westfalen',243825);
+INSERT INTO City VALUES (3098,'Krefeld','DEU','Nordrhein-Westfalen',241769);
+INSERT INTO City VALUES (3099,'Magdeburg','DEU','Anhalt Sachsen',235073);
+INSERT INTO City VALUES (3100,'Kiel','DEU','Schleswig-Holstein',233795);
+INSERT INTO City VALUES (3101,'Oberhausen','DEU','Nordrhein-Westfalen',222349);
+INSERT INTO City VALUES (3102,'Lübeck','DEU','Schleswig-Holstein',213326);
+INSERT INTO City VALUES (3103,'Hagen','DEU','Nordrhein-Westfalen',205201);
+INSERT INTO City VALUES (3104,'Rostock','DEU','Mecklenburg-Vorpomme',203279);
+INSERT INTO City VALUES (3105,'Freiburg im Breisgau','DEU','Baden-Württemberg',202455);
+INSERT INTO City VALUES (3106,'Erfurt','DEU','Thüringen',201267);
+INSERT INTO City VALUES (3107,'Kassel','DEU','Hessen',196211);
+INSERT INTO City VALUES (3108,'Saarbrücken','DEU','Saarland',183836);
+INSERT INTO City VALUES (3109,'Mainz','DEU','Rheinland-Pfalz',183134);
+INSERT INTO City VALUES (3110,'Hamm','DEU','Nordrhein-Westfalen',181804);
+INSERT INTO City VALUES (3111,'Herne','DEU','Nordrhein-Westfalen',175661);
+INSERT INTO City VALUES (3112,'Mülheim an der Ruhr','DEU','Nordrhein-Westfalen',173895);
+INSERT INTO City VALUES (3113,'Solingen','DEU','Nordrhein-Westfalen',165583);
+INSERT INTO City VALUES (3114,'Osnabrück','DEU','Niedersachsen',164539);
+INSERT INTO City VALUES (3115,'Ludwigshafen am Rhein','DEU','Rheinland-Pfalz',163771);
+INSERT INTO City VALUES (3116,'Leverkusen','DEU','Nordrhein-Westfalen',160841);
+INSERT INTO City VALUES (3117,'Oldenburg','DEU','Niedersachsen',154125);
+INSERT INTO City VALUES (3118,'Neuss','DEU','Nordrhein-Westfalen',149702);
+INSERT INTO City VALUES (3119,'Heidelberg','DEU','Baden-Württemberg',139672);
+INSERT INTO City VALUES (3120,'Darmstadt','DEU','Hessen',137776);
+INSERT INTO City VALUES (3121,'Paderborn','DEU','Nordrhein-Westfalen',137647);
+INSERT INTO City VALUES (3122,'Potsdam','DEU','Brandenburg',128983);
+INSERT INTO City VALUES (3123,'Würzburg','DEU','Baijeri',127350);
+INSERT INTO City VALUES (3124,'Regensburg','DEU','Baijeri',125236);
+INSERT INTO City VALUES (3125,'Recklinghausen','DEU','Nordrhein-Westfalen',125022);
+INSERT INTO City VALUES (3126,'Göttingen','DEU','Niedersachsen',124775);
+INSERT INTO City VALUES (3127,'Bremerhaven','DEU','Bremen',122735);
+INSERT INTO City VALUES (3128,'Wolfsburg','DEU','Niedersachsen',121954);
+INSERT INTO City VALUES (3129,'Bottrop','DEU','Nordrhein-Westfalen',121097);
+INSERT INTO City VALUES (3130,'Remscheid','DEU','Nordrhein-Westfalen',120125);
+INSERT INTO City VALUES (3131,'Heilbronn','DEU','Baden-Württemberg',119526);
+INSERT INTO City VALUES (3132,'Pforzheim','DEU','Baden-Württemberg',117227);
+INSERT INTO City VALUES (3133,'Offenbach am Main','DEU','Hessen',116627);
+INSERT INTO City VALUES (3134,'Ulm','DEU','Baden-Württemberg',116103);
+INSERT INTO City VALUES (3135,'Ingolstadt','DEU','Baijeri',114826);
+INSERT INTO City VALUES (3136,'Gera','DEU','Thüringen',114718);
+INSERT INTO City VALUES (3137,'Salzgitter','DEU','Niedersachsen',112934);
+INSERT INTO City VALUES (3138,'Cottbus','DEU','Brandenburg',110894);
+INSERT INTO City VALUES (3139,'Reutlingen','DEU','Baden-Württemberg',110343);
+INSERT INTO City VALUES (3140,'Fürth','DEU','Baijeri',109771);
+INSERT INTO City VALUES (3141,'Siegen','DEU','Nordrhein-Westfalen',109225);
+INSERT INTO City VALUES (3142,'Koblenz','DEU','Rheinland-Pfalz',108003);
+INSERT INTO City VALUES (3143,'Moers','DEU','Nordrhein-Westfalen',106837);
+INSERT INTO City VALUES (3144,'Bergisch Gladbach','DEU','Nordrhein-Westfalen',106150);
+INSERT INTO City VALUES (3145,'Zwickau','DEU','Saksi',104146);
+INSERT INTO City VALUES (3146,'Hildesheim','DEU','Niedersachsen',104013);
+INSERT INTO City VALUES (3147,'Witten','DEU','Nordrhein-Westfalen',103384);
+INSERT INTO City VALUES (3148,'Schwerin','DEU','Mecklenburg-Vorpomme',102878);
+INSERT INTO City VALUES (3149,'Erlangen','DEU','Baijeri',100750);
+INSERT INTO City VALUES (3150,'Kaiserslautern','DEU','Rheinland-Pfalz',100025);
+INSERT INTO City VALUES (3151,'Trier','DEU','Rheinland-Pfalz',99891);
+INSERT INTO City VALUES (3152,'Jena','DEU','Thüringen',99779);
+INSERT INTO City VALUES (3153,'Iserlohn','DEU','Nordrhein-Westfalen',99474);
+INSERT INTO City VALUES (3154,'Gütersloh','DEU','Nordrhein-Westfalen',95028);
+INSERT INTO City VALUES (3155,'Marl','DEU','Nordrhein-Westfalen',93735);
+INSERT INTO City VALUES (3156,'Lünen','DEU','Nordrhein-Westfalen',92044);
+INSERT INTO City VALUES (3157,'Düren','DEU','Nordrhein-Westfalen',91092);
+INSERT INTO City VALUES (3158,'Ratingen','DEU','Nordrhein-Westfalen',90951);
+INSERT INTO City VALUES (3159,'Velbert','DEU','Nordrhein-Westfalen',89881);
+INSERT INTO City VALUES (3160,'Esslingen am Neckar','DEU','Baden-Württemberg',89667);
+INSERT INTO City VALUES (3161,'Honiara','SLB','Honiara',50100);
+INSERT INTO City VALUES (3162,'Lusaka','ZMB','Lusaka',1317000);
+INSERT INTO City VALUES (3163,'Ndola','ZMB','Copperbelt',329200);
+INSERT INTO City VALUES (3164,'Kitwe','ZMB','Copperbelt',288600);
+INSERT INTO City VALUES (3165,'Kabwe','ZMB','Central',154300);
+INSERT INTO City VALUES (3166,'Chingola','ZMB','Copperbelt',142400);
+INSERT INTO City VALUES (3167,'Mufulira','ZMB','Copperbelt',123900);
+INSERT INTO City VALUES (3168,'Luanshya','ZMB','Copperbelt',118100);
+INSERT INTO City VALUES (3169,'Apia','WSM','Upolu',35900);
+INSERT INTO City VALUES (3170,'Serravalle','SMR','Serravalle/Dogano',4802);
+INSERT INTO City VALUES (3171,'San Marino','SMR','San Marino',2294);
+INSERT INTO City VALUES (3172,'São Tomé','STP','Aqua Grande',49541);
+INSERT INTO City VALUES (3173,'Riyadh','SAU','Riyadh',3324000);
+INSERT INTO City VALUES (3174,'Jedda','SAU','Mekka',2046300);
+INSERT INTO City VALUES (3175,'Mekka','SAU','Mekka',965700);
+INSERT INTO City VALUES (3176,'Medina','SAU','Medina',608300);
+INSERT INTO City VALUES (3177,'al-Dammam','SAU','al-Sharqiya',482300);
+INSERT INTO City VALUES (3178,'al-Taif','SAU','Mekka',416100);
+INSERT INTO City VALUES (3179,'Tabuk','SAU','Tabuk',292600);
+INSERT INTO City VALUES (3180,'Burayda','SAU','al-Qasim',248600);
+INSERT INTO City VALUES (3181,'al-Hufuf','SAU','al-Sharqiya',225800);
+INSERT INTO City VALUES (3182,'al-Mubarraz','SAU','al-Sharqiya',219100);
+INSERT INTO City VALUES (3183,'Khamis Mushayt','SAU','Asir',217900);
+INSERT INTO City VALUES (3184,'Hail','SAU','Hail',176800);
+INSERT INTO City VALUES (3185,'al-Kharj','SAU','Riad',152100);
+INSERT INTO City VALUES (3186,'al-Khubar','SAU','al-Sharqiya',141700);
+INSERT INTO City VALUES (3187,'Jubayl','SAU','al-Sharqiya',140800);
+INSERT INTO City VALUES (3188,'Hafar al-Batin','SAU','al-Sharqiya',137800);
+INSERT INTO City VALUES (3189,'al-Tuqba','SAU','al-Sharqiya',125700);
+INSERT INTO City VALUES (3190,'Yanbu','SAU','Medina',119800);
+INSERT INTO City VALUES (3191,'Abha','SAU','Asir',112300);
+INSERT INTO City VALUES (3192,'Ara´ar','SAU','al-Khudud al-Samaliy',108100);
+INSERT INTO City VALUES (3193,'al-Qatif','SAU','al-Sharqiya',98900);
+INSERT INTO City VALUES (3194,'al-Hawiya','SAU','Mekka',93900);
+INSERT INTO City VALUES (3195,'Unayza','SAU','Qasim',91100);
+INSERT INTO City VALUES (3196,'Najran','SAU','Najran',91000);
+INSERT INTO City VALUES (3197,'Pikine','SEN','Cap-Vert',855287);
+INSERT INTO City VALUES (3198,'Dakar','SEN','Cap-Vert',785071);
+INSERT INTO City VALUES (3199,'Thiès','SEN','Thiès',248000);
+INSERT INTO City VALUES (3200,'Kaolack','SEN','Kaolack',199000);
+INSERT INTO City VALUES (3201,'Ziguinchor','SEN','Ziguinchor',192000);
+INSERT INTO City VALUES (3202,'Rufisque','SEN','Cap-Vert',150000);
+INSERT INTO City VALUES (3203,'Saint-Louis','SEN','Saint-Louis',132400);
+INSERT INTO City VALUES (3204,'Mbour','SEN','Thiès',109300);
+INSERT INTO City VALUES (3205,'Diourbel','SEN','Diourbel',99400);
+INSERT INTO City VALUES (3206,'Victoria','SYC','Mahé',41000);
+INSERT INTO City VALUES (3207,'Freetown','SLE','Western',850000);
+INSERT INTO City VALUES (3208,'Singapore','SGP','–',4017733);
+INSERT INTO City VALUES (3209,'Bratislava','SVK','Bratislava',448292);
+INSERT INTO City VALUES (3210,'Košice','SVK','Východné Slovensko',241874);
+INSERT INTO City VALUES (3211,'Prešov','SVK','Východné Slovensko',93977);
+INSERT INTO City VALUES (3212,'Ljubljana','SVN','Osrednjeslovenska',270986);
+INSERT INTO City VALUES (3213,'Maribor','SVN','Podravska',115532);
+INSERT INTO City VALUES (3214,'Mogadishu','SOM','Banaadir',997000);
+INSERT INTO City VALUES (3215,'Hargeysa','SOM','Woqooyi Galbeed',90000);
+INSERT INTO City VALUES (3216,'Kismaayo','SOM','Jubbada Hoose',90000);
+INSERT INTO City VALUES (3217,'Colombo','LKA','Western',645000);
+INSERT INTO City VALUES (3218,'Dehiwala','LKA','Western',203000);
+INSERT INTO City VALUES (3219,'Moratuwa','LKA','Western',190000);
+INSERT INTO City VALUES (3220,'Jaffna','LKA','Northern',149000);
+INSERT INTO City VALUES (3221,'Kandy','LKA','Central',140000);
+INSERT INTO City VALUES (3222,'Sri Jayawardenepura Kotte','LKA','Western',118000);
+INSERT INTO City VALUES (3223,'Negombo','LKA','Western',100000);
+INSERT INTO City VALUES (3224,'Omdurman','SDN','Khartum',1271403);
+INSERT INTO City VALUES (3225,'Khartum','SDN','Khartum',947483);
+INSERT INTO City VALUES (3226,'Sharq al-Nil','SDN','Khartum',700887);
+INSERT INTO City VALUES (3227,'Port Sudan','SDN','al-Bahr al-Ahmar',308195);
+INSERT INTO City VALUES (3228,'Kassala','SDN','Kassala',234622);
+INSERT INTO City VALUES (3229,'Obeid','SDN','Kurdufan al-Shamaliy',229425);
+INSERT INTO City VALUES (3230,'Nyala','SDN','Darfur al-Janubiya',227183);
+INSERT INTO City VALUES (3231,'Wad Madani','SDN','al-Jazira',211362);
+INSERT INTO City VALUES (3232,'al-Qadarif','SDN','al-Qadarif',191164);
+INSERT INTO City VALUES (3233,'Kusti','SDN','al-Bahr al-Abyad',173599);
+INSERT INTO City VALUES (3234,'al-Fashir','SDN','Darfur al-Shamaliya',141884);
+INSERT INTO City VALUES (3235,'Juba','SDN','Bahr al-Jabal',114980);
+INSERT INTO City VALUES (3236,'Helsinki [Helsingfors]','FIN','Newmaa',555474);
+INSERT INTO City VALUES (3237,'Espoo','FIN','Newmaa',213271);
+INSERT INTO City VALUES (3238,'Tampere','FIN','Pirkanmaa',195468);
+INSERT INTO City VALUES (3239,'Vantaa','FIN','Newmaa',178471);
+INSERT INTO City VALUES (3240,'Turku [Åbo]','FIN','Varsinais-Suomi',172561);
+INSERT INTO City VALUES (3241,'Oulu','FIN','Pohjois-Pohjanmaa',120753);
+INSERT INTO City VALUES (3242,'Lahti','FIN','Päijät-Häme',96921);
+INSERT INTO City VALUES (3243,'Paramaribo','SUR','Paramaribo',112000);
+INSERT INTO City VALUES (3244,'Mbabane','SWZ','Hhohho',61000);
+INSERT INTO City VALUES (3245,'Zürich','CHE','Zürich',336800);
+INSERT INTO City VALUES (3246,'Geneve','CHE','Geneve',173500);
+INSERT INTO City VALUES (3247,'Basel','CHE','Basel-Stadt',166700);
+INSERT INTO City VALUES (3248,'Bern','CHE','Bern',122700);
+INSERT INTO City VALUES (3249,'Lausanne','CHE','Vaud',114500);
+INSERT INTO City VALUES (3250,'Damascus','SYR','Damascus',1347000);
+INSERT INTO City VALUES (3251,'Aleppo','SYR','Aleppo',1261983);
+INSERT INTO City VALUES (3252,'Hims','SYR','Hims',507404);
+INSERT INTO City VALUES (3253,'Hama','SYR','Hama',343361);
+INSERT INTO City VALUES (3254,'Latakia','SYR','Latakia',264563);
+INSERT INTO City VALUES (3255,'al-Qamishliya','SYR','al-Hasaka',144286);
+INSERT INTO City VALUES (3256,'Dayr al-Zawr','SYR','Dayr al-Zawr',140459);
+INSERT INTO City VALUES (3257,'Jaramana','SYR','Damaskos',138469);
+INSERT INTO City VALUES (3258,'Duma','SYR','Damaskos',131158);
+INSERT INTO City VALUES (3259,'al-Raqqa','SYR','al-Raqqa',108020);
+INSERT INTO City VALUES (3260,'Idlib','SYR','Idlib',91081);
+INSERT INTO City VALUES (3261,'Dushanbe','TJK','Karotegin',524000);
+INSERT INTO City VALUES (3262,'Khujand','TJK','Khujand',161500);
+INSERT INTO City VALUES (3263,'Taipei','TWN','Taipei',2641312);
+INSERT INTO City VALUES (3264,'Kaohsiung','TWN','Kaohsiung',1475505);
+INSERT INTO City VALUES (3265,'Taichung','TWN','Taichung',940589);
+INSERT INTO City VALUES (3266,'Tainan','TWN','Tainan',728060);
+INSERT INTO City VALUES (3267,'Panchiao','TWN','Taipei',523850);
+INSERT INTO City VALUES (3268,'Chungho','TWN','Taipei',392176);
+INSERT INTO City VALUES (3269,'Keelung (Chilung)','TWN','Keelung',385201);
+INSERT INTO City VALUES (3270,'Sanchung','TWN','Taipei',380084);
+INSERT INTO City VALUES (3271,'Hsinchuang','TWN','Taipei',365048);
+INSERT INTO City VALUES (3272,'Hsinchu','TWN','Hsinchu',361958);
+INSERT INTO City VALUES (3273,'Chungli','TWN','Taoyuan',318649);
+INSERT INTO City VALUES (3274,'Fengshan','TWN','Kaohsiung',318562);
+INSERT INTO City VALUES (3275,'Taoyuan','TWN','Taoyuan',316438);
+INSERT INTO City VALUES (3276,'Chiayi','TWN','Chiayi',265109);
+INSERT INTO City VALUES (3277,'Hsintien','TWN','Taipei',263603);
+INSERT INTO City VALUES (3278,'Changhwa','TWN','Changhwa',227715);
+INSERT INTO City VALUES (3279,'Yungho','TWN','Taipei',227700);
+INSERT INTO City VALUES (3280,'Tucheng','TWN','Taipei',224897);
+INSERT INTO City VALUES (3281,'Pingtung','TWN','Pingtung',214727);
+INSERT INTO City VALUES (3282,'Yungkang','TWN','Tainan',193005);
+INSERT INTO City VALUES (3283,'Pingchen','TWN','Taoyuan',188344);
+INSERT INTO City VALUES (3284,'Tali','TWN','Taichung',171940);
+INSERT INTO City VALUES (3285,'Taiping','TWN','',165524);
+INSERT INTO City VALUES (3286,'Pate','TWN','Taoyuan',161700);
+INSERT INTO City VALUES (3287,'Fengyuan','TWN','Taichung',161032);
+INSERT INTO City VALUES (3288,'Luchou','TWN','Taipei',160516);
+INSERT INTO City VALUES (3289,'Hsichuh','TWN','Taipei',154976);
+INSERT INTO City VALUES (3290,'Shulin','TWN','Taipei',151260);
+INSERT INTO City VALUES (3291,'Yuanlin','TWN','Changhwa',126402);
+INSERT INTO City VALUES (3292,'Yangmei','TWN','Taoyuan',126323);
+INSERT INTO City VALUES (3293,'Taliao','TWN','',115897);
+INSERT INTO City VALUES (3294,'Kueishan','TWN','',112195);
+INSERT INTO City VALUES (3295,'Tanshui','TWN','Taipei',111882);
+INSERT INTO City VALUES (3296,'Taitung','TWN','Taitung',111039);
+INSERT INTO City VALUES (3297,'Hualien','TWN','Hualien',108407);
+INSERT INTO City VALUES (3298,'Nantou','TWN','Nantou',104723);
+INSERT INTO City VALUES (3299,'Lungtan','TWN','Taipei',103088);
+INSERT INTO City VALUES (3300,'Touliu','TWN','Yünlin',98900);
+INSERT INTO City VALUES (3301,'Tsaotun','TWN','Nantou',96800);
+INSERT INTO City VALUES (3302,'Kangshan','TWN','Kaohsiung',92200);
+INSERT INTO City VALUES (3303,'Ilan','TWN','Ilan',92000);
+INSERT INTO City VALUES (3304,'Miaoli','TWN','Miaoli',90000);
+INSERT INTO City VALUES (3305,'Dar es Salaam','TZA','Dar es Salaam',1747000);
+INSERT INTO City VALUES (3306,'Dodoma','TZA','Dodoma',189000);
+INSERT INTO City VALUES (3307,'Mwanza','TZA','Mwanza',172300);
+INSERT INTO City VALUES (3308,'Zanzibar','TZA','Zanzibar West',157634);
+INSERT INTO City VALUES (3309,'Tanga','TZA','Tanga',137400);
+INSERT INTO City VALUES (3310,'Mbeya','TZA','Mbeya',130800);
+INSERT INTO City VALUES (3311,'Morogoro','TZA','Morogoro',117800);
+INSERT INTO City VALUES (3312,'Arusha','TZA','Arusha',102500);
+INSERT INTO City VALUES (3313,'Moshi','TZA','Kilimanjaro',96800);
+INSERT INTO City VALUES (3314,'Tabora','TZA','Tabora',92800);
+INSERT INTO City VALUES (3315,'København','DNK','København',495699);
+INSERT INTO City VALUES (3316,'Århus','DNK','Århus',284846);
+INSERT INTO City VALUES (3317,'Odense','DNK','Fyn',183912);
+INSERT INTO City VALUES (3318,'Aalborg','DNK','Nordjylland',161161);
+INSERT INTO City VALUES (3319,'Frederiksberg','DNK','Frederiksberg',90327);
+INSERT INTO City VALUES (3320,'Bangkok','THA','Bangkok',6320174);
+INSERT INTO City VALUES (3321,'Nonthaburi','THA','Nonthaburi',292100);
+INSERT INTO City VALUES (3322,'Nakhon Ratchasima','THA','Nakhon Ratchasima',181400);
+INSERT INTO City VALUES (3323,'Chiang Mai','THA','Chiang Mai',171100);
+INSERT INTO City VALUES (3324,'Udon Thani','THA','Udon Thani',158100);
+INSERT INTO City VALUES (3325,'Hat Yai','THA','Songkhla',148632);
+INSERT INTO City VALUES (3326,'Khon Kaen','THA','Khon Kaen',126500);
+INSERT INTO City VALUES (3327,'Pak Kret','THA','Nonthaburi',126055);
+INSERT INTO City VALUES (3328,'Nakhon Sawan','THA','Nakhon Sawan',123800);
+INSERT INTO City VALUES (3329,'Ubon Ratchathani','THA','Ubon Ratchathani',116300);
+INSERT INTO City VALUES (3330,'Songkhla','THA','Songkhla',94900);
+INSERT INTO City VALUES (3331,'Nakhon Pathom','THA','Nakhon Pathom',94100);
+INSERT INTO City VALUES (3332,'Lomé','TGO','Maritime',375000);
+INSERT INTO City VALUES (3333,'Fakaofo','TKL','Fakaofo',300);
+INSERT INTO City VALUES (3334,'Nuku´alofa','TON','Tongatapu',22400);
+INSERT INTO City VALUES (3335,'Chaguanas','TTO','Caroni',56601);
+INSERT INTO City VALUES (3336,'Port-of-Spain','TTO','Port-of-Spain',43396);
+INSERT INTO City VALUES (3337,'N´Djaména','TCD','Chari-Baguirmi',530965);
+INSERT INTO City VALUES (3338,'Moundou','TCD','Logone Occidental',99500);
+INSERT INTO City VALUES (3339,'Praha','CZE','Hlavní mesto Praha',1181126);
+INSERT INTO City VALUES (3340,'Brno','CZE','Jizní Morava',381862);
+INSERT INTO City VALUES (3341,'Ostrava','CZE','Severní Morava',320041);
+INSERT INTO City VALUES (3342,'Plzen','CZE','Zapadní Cechy',166759);
+INSERT INTO City VALUES (3343,'Olomouc','CZE','Severní Morava',102702);
+INSERT INTO City VALUES (3344,'Liberec','CZE','Severní Cechy',99155);
+INSERT INTO City VALUES (3345,'Ceské Budejovice','CZE','Jizní Cechy',98186);
+INSERT INTO City VALUES (3346,'Hradec Králové','CZE','Východní Cechy',98080);
+INSERT INTO City VALUES (3347,'Ústí nad Labem','CZE','Severní Cechy',95491);
+INSERT INTO City VALUES (3348,'Pardubice','CZE','Východní Cechy',91309);
+INSERT INTO City VALUES (3349,'Tunis','TUN','Tunis',690600);
+INSERT INTO City VALUES (3350,'Sfax','TUN','Sfax',257800);
+INSERT INTO City VALUES (3351,'Ariana','TUN','Ariana',197000);
+INSERT INTO City VALUES (3352,'Ettadhamen','TUN','Ariana',178600);
+INSERT INTO City VALUES (3353,'Sousse','TUN','Sousse',145900);
+INSERT INTO City VALUES (3354,'Kairouan','TUN','Kairouan',113100);
+INSERT INTO City VALUES (3355,'Biserta','TUN','Biserta',108900);
+INSERT INTO City VALUES (3356,'Gabès','TUN','Gabès',106600);
+INSERT INTO City VALUES (3357,'Istanbul','TUR','Istanbul',8787958);
+INSERT INTO City VALUES (3358,'Ankara','TUR','Ankara',3038159);
+INSERT INTO City VALUES (3359,'Izmir','TUR','Izmir',2130359);
+INSERT INTO City VALUES (3360,'Adana','TUR','Adana',1131198);
+INSERT INTO City VALUES (3361,'Bursa','TUR','Bursa',1095842);
+INSERT INTO City VALUES (3362,'Gaziantep','TUR','Gaziantep',789056);
+INSERT INTO City VALUES (3363,'Konya','TUR','Konya',628364);
+INSERT INTO City VALUES (3364,'Mersin (Içel)','TUR','Içel',587212);
+INSERT INTO City VALUES (3365,'Antalya','TUR','Antalya',564914);
+INSERT INTO City VALUES (3366,'Diyarbakir','TUR','Diyarbakir',479884);
+INSERT INTO City VALUES (3367,'Kayseri','TUR','Kayseri',475657);
+INSERT INTO City VALUES (3368,'Eskisehir','TUR','Eskisehir',470781);
+INSERT INTO City VALUES (3369,'Sanliurfa','TUR','Sanliurfa',405905);
+INSERT INTO City VALUES (3370,'Samsun','TUR','Samsun',339871);
+INSERT INTO City VALUES (3371,'Malatya','TUR','Malatya',330312);
+INSERT INTO City VALUES (3372,'Gebze','TUR','Kocaeli',264170);
+INSERT INTO City VALUES (3373,'Denizli','TUR','Denizli',253848);
+INSERT INTO City VALUES (3374,'Sivas','TUR','Sivas',246642);
+INSERT INTO City VALUES (3375,'Erzurum','TUR','Erzurum',246535);
+INSERT INTO City VALUES (3376,'Tarsus','TUR','Adana',246206);
+INSERT INTO City VALUES (3377,'Kahramanmaras','TUR','Kahramanmaras',245772);
+INSERT INTO City VALUES (3378,'Elâzig','TUR','Elâzig',228815);
+INSERT INTO City VALUES (3379,'Van','TUR','Van',219319);
+INSERT INTO City VALUES (3380,'Sultanbeyli','TUR','Istanbul',211068);
+INSERT INTO City VALUES (3381,'Izmit (Kocaeli)','TUR','Kocaeli',210068);
+INSERT INTO City VALUES (3382,'Manisa','TUR','Manisa',207148);
+INSERT INTO City VALUES (3383,'Batman','TUR','Batman',203793);
+INSERT INTO City VALUES (3384,'Balikesir','TUR','Balikesir',196382);
+INSERT INTO City VALUES (3385,'Sakarya (Adapazari)','TUR','Sakarya',190641);
+INSERT INTO City VALUES (3386,'Iskenderun','TUR','Hatay',153022);
+INSERT INTO City VALUES (3387,'Osmaniye','TUR','Osmaniye',146003);
+INSERT INTO City VALUES (3388,'Çorum','TUR','Çorum',145495);
+INSERT INTO City VALUES (3389,'Kütahya','TUR','Kütahya',144761);
+INSERT INTO City VALUES (3390,'Hatay (Antakya)','TUR','Hatay',143982);
+INSERT INTO City VALUES (3391,'Kirikkale','TUR','Kirikkale',142044);
+INSERT INTO City VALUES (3392,'Adiyaman','TUR','Adiyaman',141529);
+INSERT INTO City VALUES (3393,'Trabzon','TUR','Trabzon',138234);
+INSERT INTO City VALUES (3394,'Ordu','TUR','Ordu',133642);
+INSERT INTO City VALUES (3395,'Aydin','TUR','Aydin',128651);
+INSERT INTO City VALUES (3396,'Usak','TUR','Usak',128162);
+INSERT INTO City VALUES (3397,'Edirne','TUR','Edirne',123383);
+INSERT INTO City VALUES (3398,'Çorlu','TUR','Tekirdag',123300);
+INSERT INTO City VALUES (3399,'Isparta','TUR','Isparta',121911);
+INSERT INTO City VALUES (3400,'Karabük','TUR','Karabük',118285);
+INSERT INTO City VALUES (3401,'Kilis','TUR','Kilis',118245);
+INSERT INTO City VALUES (3402,'Alanya','TUR','Antalya',117300);
+INSERT INTO City VALUES (3403,'Kiziltepe','TUR','Mardin',112000);
+INSERT INTO City VALUES (3404,'Zonguldak','TUR','Zonguldak',111542);
+INSERT INTO City VALUES (3405,'Siirt','TUR','Siirt',107100);
+INSERT INTO City VALUES (3406,'Viransehir','TUR','Sanliurfa',106400);
+INSERT INTO City VALUES (3407,'Tekirdag','TUR','Tekirdag',106077);
+INSERT INTO City VALUES (3408,'Karaman','TUR','Karaman',104200);
+INSERT INTO City VALUES (3409,'Afyon','TUR','Afyon',103984);
+INSERT INTO City VALUES (3410,'Aksaray','TUR','Aksaray',102681);
+INSERT INTO City VALUES (3411,'Ceyhan','TUR','Adana',102412);
+INSERT INTO City VALUES (3412,'Erzincan','TUR','Erzincan',102304);
+INSERT INTO City VALUES (3413,'Bismil','TUR','Diyarbakir',101400);
+INSERT INTO City VALUES (3414,'Nazilli','TUR','Aydin',99900);
+INSERT INTO City VALUES (3415,'Tokat','TUR','Tokat',99500);
+INSERT INTO City VALUES (3416,'Kars','TUR','Kars',93000);
+INSERT INTO City VALUES (3417,'Inegöl','TUR','Bursa',90500);
+INSERT INTO City VALUES (3418,'Bandirma','TUR','Balikesir',90200);
+INSERT INTO City VALUES (3419,'Ashgabat','TKM','Ahal',540600);
+INSERT INTO City VALUES (3420,'Chärjew','TKM','Lebap',189200);
+INSERT INTO City VALUES (3421,'Dashhowuz','TKM','Dashhowuz',141800);
+INSERT INTO City VALUES (3422,'Mary','TKM','Mary',101000);
+INSERT INTO City VALUES (3423,'Cockburn Town','TCA','Grand Turk',4800);
+INSERT INTO City VALUES (3424,'Funafuti','TUV','Funafuti',4600);
+INSERT INTO City VALUES (3425,'Kampala','UGA','Central',890800);
+INSERT INTO City VALUES (3426,'Kyiv','UKR','Kiova',2624000);
+INSERT INTO City VALUES (3427,'Harkova [Harkiv]','UKR','Harkova',1500000);
+INSERT INTO City VALUES (3428,'Dnipropetrovsk','UKR','Dnipropetrovsk',1103000);
+INSERT INTO City VALUES (3429,'Donetsk','UKR','Donetsk',1050000);
+INSERT INTO City VALUES (3430,'Odesa','UKR','Odesa',1011000);
+INSERT INTO City VALUES (3431,'Zaporizzja','UKR','Zaporizzja',848000);
+INSERT INTO City VALUES (3432,'Lviv','UKR','Lviv',788000);
+INSERT INTO City VALUES (3433,'Kryvyi Rig','UKR','Dnipropetrovsk',703000);
+INSERT INTO City VALUES (3434,'Mykolajiv','UKR','Mykolajiv',508000);
+INSERT INTO City VALUES (3435,'Mariupol','UKR','Donetsk',490000);
+INSERT INTO City VALUES (3436,'Lugansk','UKR','Lugansk',469000);
+INSERT INTO City VALUES (3437,'Vinnytsja','UKR','Vinnytsja',391000);
+INSERT INTO City VALUES (3438,'Makijivka','UKR','Donetsk',384000);
+INSERT INTO City VALUES (3439,'Herson','UKR','Herson',353000);
+INSERT INTO City VALUES (3440,'Sevastopol','UKR','Krim',348000);
+INSERT INTO City VALUES (3441,'Simferopol','UKR','Krim',339000);
+INSERT INTO City VALUES (3442,'Pultava [Poltava]','UKR','Pultava',313000);
+INSERT INTO City VALUES (3443,'Tšernigiv','UKR','Tšernigiv',313000);
+INSERT INTO City VALUES (3444,'Tšerkasy','UKR','Tšerkasy',309000);
+INSERT INTO City VALUES (3445,'Gorlivka','UKR','Donetsk',299000);
+INSERT INTO City VALUES (3446,'Zytomyr','UKR','Zytomyr',297000);
+INSERT INTO City VALUES (3447,'Sumy','UKR','Sumy',294000);
+INSERT INTO City VALUES (3448,'Dniprodzerzynsk','UKR','Dnipropetrovsk',270000);
+INSERT INTO City VALUES (3449,'Kirovograd','UKR','Kirovograd',265000);
+INSERT INTO City VALUES (3450,'Hmelnytskyi','UKR','Hmelnytskyi',262000);
+INSERT INTO City VALUES (3451,'Tšernivtsi','UKR','Tšernivtsi',259000);
+INSERT INTO City VALUES (3452,'Rivne','UKR','Rivne',245000);
+INSERT INTO City VALUES (3453,'Krementšuk','UKR','Pultava',239000);
+INSERT INTO City VALUES (3454,'Ivano-Frankivsk','UKR','Ivano-Frankivsk',237000);
+INSERT INTO City VALUES (3455,'Ternopil','UKR','Ternopil',236000);
+INSERT INTO City VALUES (3456,'Lutsk','UKR','Volynia',217000);
+INSERT INTO City VALUES (3457,'Bila Tserkva','UKR','Kiova',215000);
+INSERT INTO City VALUES (3458,'Kramatorsk','UKR','Donetsk',186000);
+INSERT INTO City VALUES (3459,'Melitopol','UKR','Zaporizzja',169000);
+INSERT INTO City VALUES (3460,'Kertš','UKR','Krim',162000);
+INSERT INTO City VALUES (3461,'Nikopol','UKR','Dnipropetrovsk',149000);
+INSERT INTO City VALUES (3462,'Berdjansk','UKR','Zaporizzja',130000);
+INSERT INTO City VALUES (3463,'Pavlograd','UKR','Dnipropetrovsk',127000);
+INSERT INTO City VALUES (3464,'Sjeverodonetsk','UKR','Lugansk',127000);
+INSERT INTO City VALUES (3465,'Slovjansk','UKR','Donetsk',127000);
+INSERT INTO City VALUES (3466,'Uzgorod','UKR','Taka-Karpatia',127000);
+INSERT INTO City VALUES (3467,'Altševsk','UKR','Lugansk',119000);
+INSERT INTO City VALUES (3468,'Lysytšansk','UKR','Lugansk',116000);
+INSERT INTO City VALUES (3469,'Jevpatorija','UKR','Krim',112000);
+INSERT INTO City VALUES (3470,'Kamjanets-Podilskyi','UKR','Hmelnytskyi',109000);
+INSERT INTO City VALUES (3471,'Jenakijeve','UKR','Donetsk',105000);
+INSERT INTO City VALUES (3472,'Krasnyi Lutš','UKR','Lugansk',101000);
+INSERT INTO City VALUES (3473,'Stahanov','UKR','Lugansk',101000);
+INSERT INTO City VALUES (3474,'Oleksandrija','UKR','Kirovograd',99000);
+INSERT INTO City VALUES (3475,'Konotop','UKR','Sumy',96000);
+INSERT INTO City VALUES (3476,'Kostjantynivka','UKR','Donetsk',95000);
+INSERT INTO City VALUES (3477,'Berdytšiv','UKR','Zytomyr',90000);
+INSERT INTO City VALUES (3478,'Izmajil','UKR','Odesa',90000);
+INSERT INTO City VALUES (3479,'Šostka','UKR','Sumy',90000);
+INSERT INTO City VALUES (3480,'Uman','UKR','Tšerkasy',90000);
+INSERT INTO City VALUES (3481,'Brovary','UKR','Kiova',89000);
+INSERT INTO City VALUES (3482,'Mukatševe','UKR','Taka-Karpatia',89000);
+INSERT INTO City VALUES (3483,'Budapest','HUN','Budapest',1811552);
+INSERT INTO City VALUES (3484,'Debrecen','HUN','Hajdú-Bihar',203648);
+INSERT INTO City VALUES (3485,'Miskolc','HUN','Borsod-Abaúj-Zemplén',172357);
+INSERT INTO City VALUES (3486,'Szeged','HUN','Csongrád',158158);
+INSERT INTO City VALUES (3487,'Pécs','HUN','Baranya',157332);
+INSERT INTO City VALUES (3488,'Györ','HUN','Györ-Moson-Sopron',127119);
+INSERT INTO City VALUES (3489,'Nyiregyháza','HUN','Szabolcs-Szatmár-Ber',112419);
+INSERT INTO City VALUES (3490,'Kecskemét','HUN','Bács-Kiskun',105606);
+INSERT INTO City VALUES (3491,'Székesfehérvár','HUN','Fejér',105119);
+INSERT INTO City VALUES (3492,'Montevideo','URY','Montevideo',1236000);
+INSERT INTO City VALUES (3493,'Nouméa','NCL','–',76293);
+INSERT INTO City VALUES (3494,'Auckland','NZL','Auckland',381800);
+INSERT INTO City VALUES (3495,'Christchurch','NZL','Canterbury',324200);
+INSERT INTO City VALUES (3496,'Manukau','NZL','Auckland',281800);
+INSERT INTO City VALUES (3497,'North Shore','NZL','Auckland',187700);
+INSERT INTO City VALUES (3498,'Waitakere','NZL','Auckland',170600);
+INSERT INTO City VALUES (3499,'Wellington','NZL','Wellington',166700);
+INSERT INTO City VALUES (3500,'Dunedin','NZL','Dunedin',119600);
+INSERT INTO City VALUES (3501,'Hamilton','NZL','Hamilton',117100);
+INSERT INTO City VALUES (3502,'Lower Hutt','NZL','Wellington',98100);
+INSERT INTO City VALUES (3503,'Toskent','UZB','Toskent Shahri',2117500);
+INSERT INTO City VALUES (3504,'Namangan','UZB','Namangan',370500);
+INSERT INTO City VALUES (3505,'Samarkand','UZB','Samarkand',361800);
+INSERT INTO City VALUES (3506,'Andijon','UZB','Andijon',318600);
+INSERT INTO City VALUES (3507,'Buhoro','UZB','Buhoro',237100);
+INSERT INTO City VALUES (3508,'Karsi','UZB','Qashqadaryo',194100);
+INSERT INTO City VALUES (3509,'Nukus','UZB','Karakalpakistan',194100);
+INSERT INTO City VALUES (3510,'Kükon','UZB','Fargona',190100);
+INSERT INTO City VALUES (3511,'Fargona','UZB','Fargona',180500);
+INSERT INTO City VALUES (3512,'Circik','UZB','Toskent',146400);
+INSERT INTO City VALUES (3513,'Margilon','UZB','Fargona',140800);
+INSERT INTO City VALUES (3514,'Ürgenc','UZB','Khorazm',138900);
+INSERT INTO City VALUES (3515,'Angren','UZB','Toskent',128000);
+INSERT INTO City VALUES (3516,'Cizah','UZB','Cizah',124800);
+INSERT INTO City VALUES (3517,'Navoi','UZB','Navoi',116300);
+INSERT INTO City VALUES (3518,'Olmalik','UZB','Toskent',114900);
+INSERT INTO City VALUES (3519,'Termiz','UZB','Surkhondaryo',109500);
+INSERT INTO City VALUES (3520,'Minsk','BLR','Horad Minsk',1674000);
+INSERT INTO City VALUES (3521,'Gomel','BLR','Gomel',475000);
+INSERT INTO City VALUES (3522,'Mogiljov','BLR','Mogiljov',356000);
+INSERT INTO City VALUES (3523,'Vitebsk','BLR','Vitebsk',340000);
+INSERT INTO City VALUES (3524,'Grodno','BLR','Grodno',302000);
+INSERT INTO City VALUES (3525,'Brest','BLR','Brest',286000);
+INSERT INTO City VALUES (3526,'Bobruisk','BLR','Mogiljov',221000);
+INSERT INTO City VALUES (3527,'Baranovitši','BLR','Brest',167000);
+INSERT INTO City VALUES (3528,'Borisov','BLR','Minsk',151000);
+INSERT INTO City VALUES (3529,'Pinsk','BLR','Brest',130000);
+INSERT INTO City VALUES (3530,'Orša','BLR','Vitebsk',124000);
+INSERT INTO City VALUES (3531,'Mozyr','BLR','Gomel',110000);
+INSERT INTO City VALUES (3532,'Novopolotsk','BLR','Vitebsk',106000);
+INSERT INTO City VALUES (3533,'Lida','BLR','Grodno',101000);
+INSERT INTO City VALUES (3534,'Soligorsk','BLR','Minsk',101000);
+INSERT INTO City VALUES (3535,'Molodetšno','BLR','Minsk',97000);
+INSERT INTO City VALUES (3536,'Mata-Utu','WLF','Wallis',1137);
+INSERT INTO City VALUES (3537,'Port-Vila','VUT','Shefa',33700);
+INSERT INTO City VALUES (3538,'Città del Vaticano','VAT','–',455);
+INSERT INTO City VALUES (3539,'Caracas','VEN','Distrito Federal',1975294);
+INSERT INTO City VALUES (3540,'Maracaíbo','VEN','Zulia',1304776);
+INSERT INTO City VALUES (3541,'Barquisimeto','VEN','Lara',877239);
+INSERT INTO City VALUES (3542,'Valencia','VEN','Carabobo',794246);
+INSERT INTO City VALUES (3543,'Ciudad Guayana','VEN','Bolívar',663713);
+INSERT INTO City VALUES (3544,'Petare','VEN','Miranda',488868);
+INSERT INTO City VALUES (3545,'Maracay','VEN','Aragua',444443);
+INSERT INTO City VALUES (3546,'Barcelona','VEN','Anzoátegui',322267);
+INSERT INTO City VALUES (3547,'Maturín','VEN','Monagas',319726);
+INSERT INTO City VALUES (3548,'San Cristóbal','VEN','Táchira',319373);
+INSERT INTO City VALUES (3549,'Ciudad Bolívar','VEN','Bolívar',301107);
+INSERT INTO City VALUES (3550,'Cumaná','VEN','Sucre',293105);
+INSERT INTO City VALUES (3551,'Mérida','VEN','Mérida',224887);
+INSERT INTO City VALUES (3552,'Cabimas','VEN','Zulia',221329);
+INSERT INTO City VALUES (3553,'Barinas','VEN','Barinas',217831);
+INSERT INTO City VALUES (3554,'Turmero','VEN','Aragua',217499);
+INSERT INTO City VALUES (3555,'Baruta','VEN','Miranda',207290);
+INSERT INTO City VALUES (3556,'Puerto Cabello','VEN','Carabobo',187722);
+INSERT INTO City VALUES (3557,'Santa Ana de Coro','VEN','Falcón',185766);
+INSERT INTO City VALUES (3558,'Los Teques','VEN','Miranda',178784);
+INSERT INTO City VALUES (3559,'Punto Fijo','VEN','Falcón',167215);
+INSERT INTO City VALUES (3560,'Guarenas','VEN','Miranda',165889);
+INSERT INTO City VALUES (3561,'Acarigua','VEN','Portuguesa',158954);
+INSERT INTO City VALUES (3562,'Puerto La Cruz','VEN','Anzoátegui',155700);
+INSERT INTO City VALUES (3563,'Ciudad Losada','VEN','',134501);
+INSERT INTO City VALUES (3564,'Guacara','VEN','Carabobo',131334);
+INSERT INTO City VALUES (3565,'Valera','VEN','Trujillo',130281);
+INSERT INTO City VALUES (3566,'Guanare','VEN','Portuguesa',125621);
+INSERT INTO City VALUES (3567,'Carúpano','VEN','Sucre',119639);
+INSERT INTO City VALUES (3568,'Catia La Mar','VEN','Distrito Federal',117012);
+INSERT INTO City VALUES (3569,'El Tigre','VEN','Anzoátegui',116256);
+INSERT INTO City VALUES (3570,'Guatire','VEN','Miranda',109121);
+INSERT INTO City VALUES (3571,'Calabozo','VEN','Guárico',107146);
+INSERT INTO City VALUES (3572,'Pozuelos','VEN','Anzoátegui',105690);
+INSERT INTO City VALUES (3573,'Ciudad Ojeda','VEN','Zulia',99354);
+INSERT INTO City VALUES (3574,'Ocumare del Tuy','VEN','Miranda',97168);
+INSERT INTO City VALUES (3575,'Valle de la Pascua','VEN','Guárico',95927);
+INSERT INTO City VALUES (3576,'Araure','VEN','Portuguesa',94269);
+INSERT INTO City VALUES (3577,'San Fernando de Apure','VEN','Apure',93809);
+INSERT INTO City VALUES (3578,'San Felipe','VEN','Yaracuy',90940);
+INSERT INTO City VALUES (3579,'El Limón','VEN','Aragua',90000);
+INSERT INTO City VALUES (3580,'Moscow','RUS','Moscow (City)',8389200);
+INSERT INTO City VALUES (3581,'St Petersburg','RUS','Pietari',4694000);
+INSERT INTO City VALUES (3582,'Novosibirsk','RUS','Novosibirsk',1398800);
+INSERT INTO City VALUES (3583,'Nizni Novgorod','RUS','Nizni Novgorod',1357000);
+INSERT INTO City VALUES (3584,'Jekaterinburg','RUS','Sverdlovsk',1266300);
+INSERT INTO City VALUES (3585,'Samara','RUS','Samara',1156100);
+INSERT INTO City VALUES (3586,'Omsk','RUS','Omsk',1148900);
+INSERT INTO City VALUES (3587,'Kazan','RUS','Tatarstan',1101000);
+INSERT INTO City VALUES (3588,'Ufa','RUS','Baškortostan',1091200);
+INSERT INTO City VALUES (3589,'Tšeljabinsk','RUS','Tšeljabinsk',1083200);
+INSERT INTO City VALUES (3590,'Rostov-na-Donu','RUS','Rostov-na-Donu',1012700);
+INSERT INTO City VALUES (3591,'Perm','RUS','Perm',1009700);
+INSERT INTO City VALUES (3592,'Volgograd','RUS','Volgograd',993400);
+INSERT INTO City VALUES (3593,'Voronez','RUS','Voronez',907700);
+INSERT INTO City VALUES (3594,'Krasnojarsk','RUS','Krasnojarsk',875500);
+INSERT INTO City VALUES (3595,'Saratov','RUS','Saratov',874000);
+INSERT INTO City VALUES (3596,'Toljatti','RUS','Samara',722900);
+INSERT INTO City VALUES (3597,'Uljanovsk','RUS','Uljanovsk',667400);
+INSERT INTO City VALUES (3598,'Izevsk','RUS','Udmurtia',652800);
+INSERT INTO City VALUES (3599,'Krasnodar','RUS','Krasnodar',639000);
+INSERT INTO City VALUES (3600,'Jaroslavl','RUS','Jaroslavl',616700);
+INSERT INTO City VALUES (3601,'Habarovsk','RUS','Habarovsk',609400);
+INSERT INTO City VALUES (3602,'Vladivostok','RUS','Primorje',606200);
+INSERT INTO City VALUES (3603,'Irkutsk','RUS','Irkutsk',593700);
+INSERT INTO City VALUES (3604,'Barnaul','RUS','Altai',580100);
+INSERT INTO City VALUES (3605,'Novokuznetsk','RUS','Kemerovo',561600);
+INSERT INTO City VALUES (3606,'Penza','RUS','Penza',532200);
+INSERT INTO City VALUES (3607,'Rjazan','RUS','Rjazan',529900);
+INSERT INTO City VALUES (3608,'Orenburg','RUS','Orenburg',523600);
+INSERT INTO City VALUES (3609,'Lipetsk','RUS','Lipetsk',521000);
+INSERT INTO City VALUES (3610,'Nabereznyje Tšelny','RUS','Tatarstan',514700);
+INSERT INTO City VALUES (3611,'Tula','RUS','Tula',506100);
+INSERT INTO City VALUES (3612,'Tjumen','RUS','Tjumen',503400);
+INSERT INTO City VALUES (3613,'Kemerovo','RUS','Kemerovo',492700);
+INSERT INTO City VALUES (3614,'Astrahan','RUS','Astrahan',486100);
+INSERT INTO City VALUES (3615,'Tomsk','RUS','Tomsk',482100);
+INSERT INTO City VALUES (3616,'Kirov','RUS','Kirov',466200);
+INSERT INTO City VALUES (3617,'Ivanovo','RUS','Ivanovo',459200);
+INSERT INTO City VALUES (3618,'Tšeboksary','RUS','Tšuvassia',459200);
+INSERT INTO City VALUES (3619,'Brjansk','RUS','Brjansk',457400);
+INSERT INTO City VALUES (3620,'Tver','RUS','Tver',454900);
+INSERT INTO City VALUES (3621,'Kursk','RUS','Kursk',443500);
+INSERT INTO City VALUES (3622,'Magnitogorsk','RUS','Tšeljabinsk',427900);
+INSERT INTO City VALUES (3623,'Kaliningrad','RUS','Kaliningrad',424400);
+INSERT INTO City VALUES (3624,'Nizni Tagil','RUS','Sverdlovsk',390900);
+INSERT INTO City VALUES (3625,'Murmansk','RUS','Murmansk',376300);
+INSERT INTO City VALUES (3626,'Ulan-Ude','RUS','Burjatia',370400);
+INSERT INTO City VALUES (3627,'Kurgan','RUS','Kurgan',364700);
+INSERT INTO City VALUES (3628,'Arkangeli','RUS','Arkangeli',361800);
+INSERT INTO City VALUES (3629,'Sotši','RUS','Krasnodar',358600);
+INSERT INTO City VALUES (3630,'Smolensk','RUS','Smolensk',353400);
+INSERT INTO City VALUES (3631,'Orjol','RUS','Orjol',344500);
+INSERT INTO City VALUES (3632,'Stavropol','RUS','Stavropol',343300);
+INSERT INTO City VALUES (3633,'Belgorod','RUS','Belgorod',342000);
+INSERT INTO City VALUES (3634,'Kaluga','RUS','Kaluga',339300);
+INSERT INTO City VALUES (3635,'Vladimir','RUS','Vladimir',337100);
+INSERT INTO City VALUES (3636,'Mahatškala','RUS','Dagestan',332800);
+INSERT INTO City VALUES (3637,'Tšerepovets','RUS','Vologda',324400);
+INSERT INTO City VALUES (3638,'Saransk','RUS','Mordva',314800);
+INSERT INTO City VALUES (3639,'Tambov','RUS','Tambov',312000);
+INSERT INTO City VALUES (3640,'Vladikavkaz','RUS','North Ossetia-Alania',310100);
+INSERT INTO City VALUES (3641,'Tšita','RUS','Tšita',309900);
+INSERT INTO City VALUES (3642,'Vologda','RUS','Vologda',302500);
+INSERT INTO City VALUES (3643,'Veliki Novgorod','RUS','Novgorod',299500);
+INSERT INTO City VALUES (3644,'Komsomolsk-na-Amure','RUS','Habarovsk',291600);
+INSERT INTO City VALUES (3645,'Kostroma','RUS','Kostroma',288100);
+INSERT INTO City VALUES (3646,'Volzski','RUS','Volgograd',286900);
+INSERT INTO City VALUES (3647,'Taganrog','RUS','Rostov-na-Donu',284400);
+INSERT INTO City VALUES (3648,'Petroskoi','RUS','Karjala',282100);
+INSERT INTO City VALUES (3649,'Bratsk','RUS','Irkutsk',277600);
+INSERT INTO City VALUES (3650,'Dzerzinsk','RUS','Nizni Novgorod',277100);
+INSERT INTO City VALUES (3651,'Surgut','RUS','Hanti-Mansia',274900);
+INSERT INTO City VALUES (3652,'Orsk','RUS','Orenburg',273900);
+INSERT INTO City VALUES (3653,'Sterlitamak','RUS','Baškortostan',265200);
+INSERT INTO City VALUES (3654,'Angarsk','RUS','Irkutsk',264700);
+INSERT INTO City VALUES (3655,'Joškar-Ola','RUS','Marinmaa',249200);
+INSERT INTO City VALUES (3656,'Rybinsk','RUS','Jaroslavl',239600);
+INSERT INTO City VALUES (3657,'Prokopjevsk','RUS','Kemerovo',237300);
+INSERT INTO City VALUES (3658,'Niznevartovsk','RUS','Hanti-Mansia',233900);
+INSERT INTO City VALUES (3659,'Naltšik','RUS','Kabardi-Balkaria',233400);
+INSERT INTO City VALUES (3660,'Syktyvkar','RUS','Komi',229700);
+INSERT INTO City VALUES (3661,'Severodvinsk','RUS','Arkangeli',229300);
+INSERT INTO City VALUES (3662,'Bijsk','RUS','Altai',225000);
+INSERT INTO City VALUES (3663,'Niznekamsk','RUS','Tatarstan',223400);
+INSERT INTO City VALUES (3664,'Blagoveštšensk','RUS','Amur',222000);
+INSERT INTO City VALUES (3665,'Šahty','RUS','Rostov-na-Donu',221800);
+INSERT INTO City VALUES (3666,'Staryi Oskol','RUS','Belgorod',213800);
+INSERT INTO City VALUES (3667,'Zelenograd','RUS','Moscow (City)',207100);
+INSERT INTO City VALUES (3668,'Balakovo','RUS','Saratov',206000);
+INSERT INTO City VALUES (3669,'Novorossijsk','RUS','Krasnodar',203300);
+INSERT INTO City VALUES (3670,'Pihkova','RUS','Pihkova',201500);
+INSERT INTO City VALUES (3671,'Zlatoust','RUS','Tšeljabinsk',196900);
+INSERT INTO City VALUES (3672,'Jakutsk','RUS','Saha (Jakutia)',195400);
+INSERT INTO City VALUES (3673,'Podolsk','RUS','Moskova',194300);
+INSERT INTO City VALUES (3674,'Petropavlovsk-Kamtšatski','RUS','Kamtšatka',194100);
+INSERT INTO City VALUES (3675,'Kamensk-Uralski','RUS','Sverdlovsk',190600);
+INSERT INTO City VALUES (3676,'Engels','RUS','Saratov',189000);
+INSERT INTO City VALUES (3677,'Syzran','RUS','Samara',186900);
+INSERT INTO City VALUES (3678,'Grozny','RUS','Tšetšenia',186000);
+INSERT INTO City VALUES (3679,'Novotšerkassk','RUS','Rostov-na-Donu',184400);
+INSERT INTO City VALUES (3680,'Berezniki','RUS','Perm',181900);
+INSERT INTO City VALUES (3681,'Juzno-Sahalinsk','RUS','Sahalin',179200);
+INSERT INTO City VALUES (3682,'Volgodonsk','RUS','Rostov-na-Donu',178200);
+INSERT INTO City VALUES (3683,'Abakan','RUS','Hakassia',169200);
+INSERT INTO City VALUES (3684,'Maikop','RUS','Adygea',167300);
+INSERT INTO City VALUES (3685,'Miass','RUS','Tšeljabinsk',166200);
+INSERT INTO City VALUES (3686,'Armavir','RUS','Krasnodar',164900);
+INSERT INTO City VALUES (3687,'Ljubertsy','RUS','Moskova',163900);
+INSERT INTO City VALUES (3688,'Rubtsovsk','RUS','Altai',162600);
+INSERT INTO City VALUES (3689,'Kovrov','RUS','Vladimir',159900);
+INSERT INTO City VALUES (3690,'Nahodka','RUS','Primorje',157700);
+INSERT INTO City VALUES (3691,'Ussurijsk','RUS','Primorje',157300);
+INSERT INTO City VALUES (3692,'Salavat','RUS','Baškortostan',156800);
+INSERT INTO City VALUES (3693,'Mytištši','RUS','Moskova',155700);
+INSERT INTO City VALUES (3694,'Kolomna','RUS','Moskova',150700);
+INSERT INTO City VALUES (3695,'Elektrostal','RUS','Moskova',147000);
+INSERT INTO City VALUES (3696,'Murom','RUS','Vladimir',142400);
+INSERT INTO City VALUES (3697,'Kolpino','RUS','Pietari',141200);
+INSERT INTO City VALUES (3698,'Norilsk','RUS','Krasnojarsk',140800);
+INSERT INTO City VALUES (3699,'Almetjevsk','RUS','Tatarstan',140700);
+INSERT INTO City VALUES (3700,'Novomoskovsk','RUS','Tula',138100);
+INSERT INTO City VALUES (3701,'Dimitrovgrad','RUS','Uljanovsk',137000);
+INSERT INTO City VALUES (3702,'Pervouralsk','RUS','Sverdlovsk',136100);
+INSERT INTO City VALUES (3703,'Himki','RUS','Moskova',133700);
+INSERT INTO City VALUES (3704,'Balašiha','RUS','Moskova',132900);
+INSERT INTO City VALUES (3705,'Nevinnomyssk','RUS','Stavropol',132600);
+INSERT INTO City VALUES (3706,'Pjatigorsk','RUS','Stavropol',132500);
+INSERT INTO City VALUES (3707,'Korolev','RUS','Moskova',132400);
+INSERT INTO City VALUES (3708,'Serpuhov','RUS','Moskova',132000);
+INSERT INTO City VALUES (3709,'Odintsovo','RUS','Moskova',127400);
+INSERT INTO City VALUES (3710,'Orehovo-Zujevo','RUS','Moskova',124900);
+INSERT INTO City VALUES (3711,'Kamyšin','RUS','Volgograd',124600);
+INSERT INTO City VALUES (3712,'Novotšeboksarsk','RUS','Tšuvassia',123400);
+INSERT INTO City VALUES (3713,'Tšerkessk','RUS','Karatšai-Tšerkessia',121700);
+INSERT INTO City VALUES (3714,'Atšinsk','RUS','Krasnojarsk',121600);
+INSERT INTO City VALUES (3715,'Magadan','RUS','Magadan',121000);
+INSERT INTO City VALUES (3716,'Mitšurinsk','RUS','Tambov',120700);
+INSERT INTO City VALUES (3717,'Kislovodsk','RUS','Stavropol',120400);
+INSERT INTO City VALUES (3718,'Jelets','RUS','Lipetsk',119400);
+INSERT INTO City VALUES (3719,'Seversk','RUS','Tomsk',118600);
+INSERT INTO City VALUES (3720,'Noginsk','RUS','Moskova',117200);
+INSERT INTO City VALUES (3721,'Velikije Luki','RUS','Pihkova',116300);
+INSERT INTO City VALUES (3722,'Novokuibyševsk','RUS','Samara',116200);
+INSERT INTO City VALUES (3723,'Neftekamsk','RUS','Baškortostan',115700);
+INSERT INTO City VALUES (3724,'Leninsk-Kuznetski','RUS','Kemerovo',113800);
+INSERT INTO City VALUES (3725,'Oktjabrski','RUS','Baškortostan',111500);
+INSERT INTO City VALUES (3726,'Sergijev Posad','RUS','Moskova',111100);
+INSERT INTO City VALUES (3727,'Arzamas','RUS','Nizni Novgorod',110700);
+INSERT INTO City VALUES (3728,'Kiseljovsk','RUS','Kemerovo',110000);
+INSERT INTO City VALUES (3729,'Novotroitsk','RUS','Orenburg',109600);
+INSERT INTO City VALUES (3730,'Obninsk','RUS','Kaluga',108300);
+INSERT INTO City VALUES (3731,'Kansk','RUS','Krasnojarsk',107400);
+INSERT INTO City VALUES (3732,'Glazov','RUS','Udmurtia',106300);
+INSERT INTO City VALUES (3733,'Solikamsk','RUS','Perm',106000);
+INSERT INTO City VALUES (3734,'Sarapul','RUS','Udmurtia',105700);
+INSERT INTO City VALUES (3735,'Ust-Ilimsk','RUS','Irkutsk',105200);
+INSERT INTO City VALUES (3736,'Štšolkovo','RUS','Moskova',104900);
+INSERT INTO City VALUES (3737,'Mezduretšensk','RUS','Kemerovo',104400);
+INSERT INTO City VALUES (3738,'Usolje-Sibirskoje','RUS','Irkutsk',103500);
+INSERT INTO City VALUES (3739,'Elista','RUS','Kalmykia',103300);
+INSERT INTO City VALUES (3740,'Novošahtinsk','RUS','Rostov-na-Donu',101900);
+INSERT INTO City VALUES (3741,'Votkinsk','RUS','Udmurtia',101700);
+INSERT INTO City VALUES (3742,'Kyzyl','RUS','Tyva',101100);
+INSERT INTO City VALUES (3743,'Serov','RUS','Sverdlovsk',100400);
+INSERT INTO City VALUES (3744,'Zelenodolsk','RUS','Tatarstan',100200);
+INSERT INTO City VALUES (3745,'Zeleznodoroznyi','RUS','Moskova',100100);
+INSERT INTO City VALUES (3746,'Kinešma','RUS','Ivanovo',100000);
+INSERT INTO City VALUES (3747,'Kuznetsk','RUS','Penza',98200);
+INSERT INTO City VALUES (3748,'Uhta','RUS','Komi',98000);
+INSERT INTO City VALUES (3749,'Jessentuki','RUS','Stavropol',97900);
+INSERT INTO City VALUES (3750,'Tobolsk','RUS','Tjumen',97600);
+INSERT INTO City VALUES (3751,'Neftejugansk','RUS','Hanti-Mansia',97400);
+INSERT INTO City VALUES (3752,'Bataisk','RUS','Rostov-na-Donu',97300);
+INSERT INTO City VALUES (3753,'Nojabrsk','RUS','Yamalin Nenetsia',97300);
+INSERT INTO City VALUES (3754,'Balašov','RUS','Saratov',97100);
+INSERT INTO City VALUES (3755,'Zeleznogorsk','RUS','Kursk',96900);
+INSERT INTO City VALUES (3756,'Zukovski','RUS','Moskova',96500);
+INSERT INTO City VALUES (3757,'Anzero-Sudzensk','RUS','Kemerovo',96100);
+INSERT INTO City VALUES (3758,'Bugulma','RUS','Tatarstan',94100);
+INSERT INTO City VALUES (3759,'Zeleznogorsk','RUS','Krasnojarsk',94000);
+INSERT INTO City VALUES (3760,'Novouralsk','RUS','Sverdlovsk',93300);
+INSERT INTO City VALUES (3761,'Puškin','RUS','Pietari',92900);
+INSERT INTO City VALUES (3762,'Vorkuta','RUS','Komi',92600);
+INSERT INTO City VALUES (3763,'Derbent','RUS','Dagestan',92300);
+INSERT INTO City VALUES (3764,'Kirovo-Tšepetsk','RUS','Kirov',91600);
+INSERT INTO City VALUES (3765,'Krasnogorsk','RUS','Moskova',91000);
+INSERT INTO City VALUES (3766,'Klin','RUS','Moskova',90000);
+INSERT INTO City VALUES (3767,'Tšaikovski','RUS','Perm',90000);
+INSERT INTO City VALUES (3768,'Novyi Urengoi','RUS','Yamalin Nenetsia',89800);
+INSERT INTO City VALUES (3769,'Ho Chi Minh City','VNM','Ho Chi Minh City',3980000);
+INSERT INTO City VALUES (3770,'Hanoi','VNM','Hanoi',1410000);
+INSERT INTO City VALUES (3771,'Haiphong','VNM','Haiphong',783133);
+INSERT INTO City VALUES (3772,'Da Nang','VNM','Quang Nam-Da Nang',382674);
+INSERT INTO City VALUES (3773,'Biên Hoa','VNM','Dong Nai',282095);
+INSERT INTO City VALUES (3774,'Nha Trang','VNM','Khanh Hoa',221331);
+INSERT INTO City VALUES (3775,'Hue','VNM','Thua Thien-Hue',219149);
+INSERT INTO City VALUES (3776,'Can Tho','VNM','Can Tho',215587);
+INSERT INTO City VALUES (3777,'Cam Pha','VNM','Quang Binh',209086);
+INSERT INTO City VALUES (3778,'Nam Dinh','VNM','Nam Ha',171699);
+INSERT INTO City VALUES (3779,'Quy Nhon','VNM','Binh Dinh',163385);
+INSERT INTO City VALUES (3780,'Vung Tau','VNM','Ba Ria-Vung Tau',145145);
+INSERT INTO City VALUES (3781,'Rach Gia','VNM','Kien Giang',141132);
+INSERT INTO City VALUES (3782,'Long Xuyen','VNM','An Giang',132681);
+INSERT INTO City VALUES (3783,'Thai Nguyen','VNM','Bac Thai',127643);
+INSERT INTO City VALUES (3784,'Hong Gai','VNM','Quang Ninh',127484);
+INSERT INTO City VALUES (3785,'Phan Thiêt','VNM','Binh Thuan',114236);
+INSERT INTO City VALUES (3786,'Cam Ranh','VNM','Khanh Hoa',114041);
+INSERT INTO City VALUES (3787,'Vinh','VNM','Nghe An',112455);
+INSERT INTO City VALUES (3788,'My Tho','VNM','Tien Giang',108404);
+INSERT INTO City VALUES (3789,'Da Lat','VNM','Lam Dong',106409);
+INSERT INTO City VALUES (3790,'Buon Ma Thuot','VNM','Dac Lac',97044);
+INSERT INTO City VALUES (3791,'Tallinn','EST','Harjumaa',403981);
+INSERT INTO City VALUES (3792,'Tartu','EST','Tartumaa',101246);
+INSERT INTO City VALUES (3793,'New York','USA','New York',8008278);
+INSERT INTO City VALUES (3794,'Los Angeles','USA','California',3694820);
+INSERT INTO City VALUES (3795,'Chicago','USA','Illinois',2896016);
+INSERT INTO City VALUES (3796,'Houston','USA','Texas',1953631);
+INSERT INTO City VALUES (3797,'Philadelphia','USA','Pennsylvania',1517550);
+INSERT INTO City VALUES (3798,'Phoenix','USA','Arizona',1321045);
+INSERT INTO City VALUES (3799,'San Diego','USA','California',1223400);
+INSERT INTO City VALUES (3800,'Dallas','USA','Texas',1188580);
+INSERT INTO City VALUES (3801,'San Antonio','USA','Texas',1144646);
+INSERT INTO City VALUES (3802,'Detroit','USA','Michigan',951270);
+INSERT INTO City VALUES (3803,'San Jose','USA','California',894943);
+INSERT INTO City VALUES (3804,'Indianapolis','USA','Indiana',791926);
+INSERT INTO City VALUES (3805,'San Francisco','USA','California',776733);
+INSERT INTO City VALUES (3806,'Jacksonville','USA','Florida',735167);
+INSERT INTO City VALUES (3807,'Columbus','USA','Ohio',711470);
+INSERT INTO City VALUES (3808,'Austin','USA','Texas',656562);
+INSERT INTO City VALUES (3809,'Baltimore','USA','Maryland',651154);
+INSERT INTO City VALUES (3810,'Memphis','USA','Tennessee',650100);
+INSERT INTO City VALUES (3811,'Milwaukee','USA','Wisconsin',596974);
+INSERT INTO City VALUES (3812,'Boston','USA','Massachusetts',589141);
+INSERT INTO City VALUES (3813,'Washington','USA','District of Columbia',572059);
+INSERT INTO City VALUES (3814,'Nashville-Davidson','USA','Tennessee',569891);
+INSERT INTO City VALUES (3815,'El Paso','USA','Texas',563662);
+INSERT INTO City VALUES (3816,'Seattle','USA','Washington',563374);
+INSERT INTO City VALUES (3817,'Denver','USA','Colorado',554636);
+INSERT INTO City VALUES (3818,'Charlotte','USA','North Carolina',540828);
+INSERT INTO City VALUES (3819,'Fort Worth','USA','Texas',534694);
+INSERT INTO City VALUES (3820,'Portland','USA','Oregon',529121);
+INSERT INTO City VALUES (3821,'Oklahoma City','USA','Oklahoma',506132);
+INSERT INTO City VALUES (3822,'Tucson','USA','Arizona',486699);
+INSERT INTO City VALUES (3823,'New Orleans','USA','Louisiana',484674);
+INSERT INTO City VALUES (3824,'Las Vegas','USA','Nevada',478434);
+INSERT INTO City VALUES (3825,'Cleveland','USA','Ohio',478403);
+INSERT INTO City VALUES (3826,'Long Beach','USA','California',461522);
+INSERT INTO City VALUES (3827,'Albuquerque','USA','New Mexico',448607);
+INSERT INTO City VALUES (3828,'Kansas City','USA','Missouri',441545);
+INSERT INTO City VALUES (3829,'Fresno','USA','California',427652);
+INSERT INTO City VALUES (3830,'Virginia Beach','USA','Virginia',425257);
+INSERT INTO City VALUES (3831,'Atlanta','USA','Georgia',416474);
+INSERT INTO City VALUES (3832,'Sacramento','USA','California',407018);
+INSERT INTO City VALUES (3833,'Oakland','USA','California',399484);
+INSERT INTO City VALUES (3834,'Mesa','USA','Arizona',396375);
+INSERT INTO City VALUES (3835,'Tulsa','USA','Oklahoma',393049);
+INSERT INTO City VALUES (3836,'Omaha','USA','Nebraska',390007);
+INSERT INTO City VALUES (3837,'Minneapolis','USA','Minnesota',382618);
+INSERT INTO City VALUES (3838,'Honolulu','USA','Hawaii',371657);
+INSERT INTO City VALUES (3839,'Miami','USA','Florida',362470);
+INSERT INTO City VALUES (3840,'Colorado Springs','USA','Colorado',360890);
+INSERT INTO City VALUES (3841,'Saint Louis','USA','Missouri',348189);
+INSERT INTO City VALUES (3842,'Wichita','USA','Kansas',344284);
+INSERT INTO City VALUES (3843,'Santa Ana','USA','California',337977);
+INSERT INTO City VALUES (3844,'Pittsburgh','USA','Pennsylvania',334563);
+INSERT INTO City VALUES (3845,'Arlington','USA','Texas',332969);
+INSERT INTO City VALUES (3846,'Cincinnati','USA','Ohio',331285);
+INSERT INTO City VALUES (3847,'Anaheim','USA','California',328014);
+INSERT INTO City VALUES (3848,'Toledo','USA','Ohio',313619);
+INSERT INTO City VALUES (3849,'Tampa','USA','Florida',303447);
+INSERT INTO City VALUES (3850,'Buffalo','USA','New York',292648);
+INSERT INTO City VALUES (3851,'Saint Paul','USA','Minnesota',287151);
+INSERT INTO City VALUES (3852,'Corpus Christi','USA','Texas',277454);
+INSERT INTO City VALUES (3853,'Aurora','USA','Colorado',276393);
+INSERT INTO City VALUES (3854,'Raleigh','USA','North Carolina',276093);
+INSERT INTO City VALUES (3855,'Newark','USA','New Jersey',273546);
+INSERT INTO City VALUES (3856,'Lexington-Fayette','USA','Kentucky',260512);
+INSERT INTO City VALUES (3857,'Anchorage','USA','Alaska',260283);
+INSERT INTO City VALUES (3858,'Louisville','USA','Kentucky',256231);
+INSERT INTO City VALUES (3859,'Riverside','USA','California',255166);
+INSERT INTO City VALUES (3860,'Saint Petersburg','USA','Florida',248232);
+INSERT INTO City VALUES (3861,'Bakersfield','USA','California',247057);
+INSERT INTO City VALUES (3862,'Stockton','USA','California',243771);
+INSERT INTO City VALUES (3863,'Birmingham','USA','Alabama',242820);
+INSERT INTO City VALUES (3864,'Jersey City','USA','New Jersey',240055);
+INSERT INTO City VALUES (3865,'Norfolk','USA','Virginia',234403);
+INSERT INTO City VALUES (3866,'Baton Rouge','USA','Louisiana',227818);
+INSERT INTO City VALUES (3867,'Hialeah','USA','Florida',226419);
+INSERT INTO City VALUES (3868,'Lincoln','USA','Nebraska',225581);
+INSERT INTO City VALUES (3869,'Greensboro','USA','North Carolina',223891);
+INSERT INTO City VALUES (3870,'Plano','USA','Texas',222030);
+INSERT INTO City VALUES (3871,'Rochester','USA','New York',219773);
+INSERT INTO City VALUES (3872,'Glendale','USA','Arizona',218812);
+INSERT INTO City VALUES (3873,'Akron','USA','Ohio',217074);
+INSERT INTO City VALUES (3874,'Garland','USA','Texas',215768);
+INSERT INTO City VALUES (3875,'Madison','USA','Wisconsin',208054);
+INSERT INTO City VALUES (3876,'Fort Wayne','USA','Indiana',205727);
+INSERT INTO City VALUES (3877,'Fremont','USA','California',203413);
+INSERT INTO City VALUES (3878,'Scottsdale','USA','Arizona',202705);
+INSERT INTO City VALUES (3879,'Montgomery','USA','Alabama',201568);
+INSERT INTO City VALUES (3880,'Shreveport','USA','Louisiana',200145);
+INSERT INTO City VALUES (3881,'Augusta-Richmond County','USA','Georgia',199775);
+INSERT INTO City VALUES (3882,'Lubbock','USA','Texas',199564);
+INSERT INTO City VALUES (3883,'Chesapeake','USA','Virginia',199184);
+INSERT INTO City VALUES (3884,'Mobile','USA','Alabama',198915);
+INSERT INTO City VALUES (3885,'Des Moines','USA','Iowa',198682);
+INSERT INTO City VALUES (3886,'Grand Rapids','USA','Michigan',197800);
+INSERT INTO City VALUES (3887,'Richmond','USA','Virginia',197790);
+INSERT INTO City VALUES (3888,'Yonkers','USA','New York',196086);
+INSERT INTO City VALUES (3889,'Spokane','USA','Washington',195629);
+INSERT INTO City VALUES (3890,'Glendale','USA','California',194973);
+INSERT INTO City VALUES (3891,'Tacoma','USA','Washington',193556);
+INSERT INTO City VALUES (3892,'Irving','USA','Texas',191615);
+INSERT INTO City VALUES (3893,'Huntington Beach','USA','California',189594);
+INSERT INTO City VALUES (3894,'Modesto','USA','California',188856);
+INSERT INTO City VALUES (3895,'Durham','USA','North Carolina',187035);
+INSERT INTO City VALUES (3896,'Columbus','USA','Georgia',186291);
+INSERT INTO City VALUES (3897,'Orlando','USA','Florida',185951);
+INSERT INTO City VALUES (3898,'Boise City','USA','Idaho',185787);
+INSERT INTO City VALUES (3899,'Winston-Salem','USA','North Carolina',185776);
+INSERT INTO City VALUES (3900,'San Bernardino','USA','California',185401);
+INSERT INTO City VALUES (3901,'Jackson','USA','Mississippi',184256);
+INSERT INTO City VALUES (3902,'Little Rock','USA','Arkansas',183133);
+INSERT INTO City VALUES (3903,'Salt Lake City','USA','Utah',181743);
+INSERT INTO City VALUES (3904,'Reno','USA','Nevada',180480);
+INSERT INTO City VALUES (3905,'Newport News','USA','Virginia',180150);
+INSERT INTO City VALUES (3906,'Chandler','USA','Arizona',176581);
+INSERT INTO City VALUES (3907,'Laredo','USA','Texas',176576);
+INSERT INTO City VALUES (3908,'Henderson','USA','Nevada',175381);
+INSERT INTO City VALUES (3909,'Arlington','USA','Virginia',174838);
+INSERT INTO City VALUES (3910,'Knoxville','USA','Tennessee',173890);
+INSERT INTO City VALUES (3911,'Amarillo','USA','Texas',173627);
+INSERT INTO City VALUES (3912,'Providence','USA','Rhode Island',173618);
+INSERT INTO City VALUES (3913,'Chula Vista','USA','California',173556);
+INSERT INTO City VALUES (3914,'Worcester','USA','Massachusetts',172648);
+INSERT INTO City VALUES (3915,'Oxnard','USA','California',170358);
+INSERT INTO City VALUES (3916,'Dayton','USA','Ohio',166179);
+INSERT INTO City VALUES (3917,'Garden Grove','USA','California',165196);
+INSERT INTO City VALUES (3918,'Oceanside','USA','California',161029);
+INSERT INTO City VALUES (3919,'Tempe','USA','Arizona',158625);
+INSERT INTO City VALUES (3920,'Huntsville','USA','Alabama',158216);
+INSERT INTO City VALUES (3921,'Ontario','USA','California',158007);
+INSERT INTO City VALUES (3922,'Chattanooga','USA','Tennessee',155554);
+INSERT INTO City VALUES (3923,'Fort Lauderdale','USA','Florida',152397);
+INSERT INTO City VALUES (3924,'Springfield','USA','Massachusetts',152082);
+INSERT INTO City VALUES (3925,'Springfield','USA','Missouri',151580);
+INSERT INTO City VALUES (3926,'Santa Clarita','USA','California',151088);
+INSERT INTO City VALUES (3927,'Salinas','USA','California',151060);
+INSERT INTO City VALUES (3928,'Tallahassee','USA','Florida',150624);
+INSERT INTO City VALUES (3929,'Rockford','USA','Illinois',150115);
+INSERT INTO City VALUES (3930,'Pomona','USA','California',149473);
+INSERT INTO City VALUES (3931,'Metairie','USA','Louisiana',149428);
+INSERT INTO City VALUES (3932,'Paterson','USA','New Jersey',149222);
+INSERT INTO City VALUES (3933,'Overland Park','USA','Kansas',149080);
+INSERT INTO City VALUES (3934,'Santa Rosa','USA','California',147595);
+INSERT INTO City VALUES (3935,'Syracuse','USA','New York',147306);
+INSERT INTO City VALUES (3936,'Kansas City','USA','Kansas',146866);
+INSERT INTO City VALUES (3937,'Hampton','USA','Virginia',146437);
+INSERT INTO City VALUES (3938,'Lakewood','USA','Colorado',144126);
+INSERT INTO City VALUES (3939,'Vancouver','USA','Washington',143560);
+INSERT INTO City VALUES (3940,'Irvine','USA','California',143072);
+INSERT INTO City VALUES (3941,'Aurora','USA','Illinois',142990);
+INSERT INTO City VALUES (3942,'Moreno Valley','USA','California',142381);
+INSERT INTO City VALUES (3943,'Pasadena','USA','California',141674);
+INSERT INTO City VALUES (3944,'Hayward','USA','California',140030);
+INSERT INTO City VALUES (3945,'Brownsville','USA','Texas',139722);
+INSERT INTO City VALUES (3946,'Bridgeport','USA','Connecticut',139529);
+INSERT INTO City VALUES (3947,'Hollywood','USA','Florida',139357);
+INSERT INTO City VALUES (3948,'Warren','USA','Michigan',138247);
+INSERT INTO City VALUES (3949,'Torrance','USA','California',137946);
+INSERT INTO City VALUES (3950,'Eugene','USA','Oregon',137893);
+INSERT INTO City VALUES (3951,'Pembroke Pines','USA','Florida',137427);
+INSERT INTO City VALUES (3952,'Salem','USA','Oregon',136924);
+INSERT INTO City VALUES (3953,'Pasadena','USA','Texas',133936);
+INSERT INTO City VALUES (3954,'Escondido','USA','California',133559);
+INSERT INTO City VALUES (3955,'Sunnyvale','USA','California',131760);
+INSERT INTO City VALUES (3956,'Savannah','USA','Georgia',131510);
+INSERT INTO City VALUES (3957,'Fontana','USA','California',128929);
+INSERT INTO City VALUES (3958,'Orange','USA','California',128821);
+INSERT INTO City VALUES (3959,'Naperville','USA','Illinois',128358);
+INSERT INTO City VALUES (3960,'Alexandria','USA','Virginia',128283);
+INSERT INTO City VALUES (3961,'Rancho Cucamonga','USA','California',127743);
+INSERT INTO City VALUES (3962,'Grand Prairie','USA','Texas',127427);
+INSERT INTO City VALUES (3963,'East Los Angeles','USA','California',126379);
+INSERT INTO City VALUES (3964,'Fullerton','USA','California',126003);
+INSERT INTO City VALUES (3965,'Corona','USA','California',124966);
+INSERT INTO City VALUES (3966,'Flint','USA','Michigan',124943);
+INSERT INTO City VALUES (3967,'Paradise','USA','Nevada',124682);
+INSERT INTO City VALUES (3968,'Mesquite','USA','Texas',124523);
+INSERT INTO City VALUES (3969,'Sterling Heights','USA','Michigan',124471);
+INSERT INTO City VALUES (3970,'Sioux Falls','USA','South Dakota',123975);
+INSERT INTO City VALUES (3971,'New Haven','USA','Connecticut',123626);
+INSERT INTO City VALUES (3972,'Topeka','USA','Kansas',122377);
+INSERT INTO City VALUES (3973,'Concord','USA','California',121780);
+INSERT INTO City VALUES (3974,'Evansville','USA','Indiana',121582);
+INSERT INTO City VALUES (3975,'Hartford','USA','Connecticut',121578);
+INSERT INTO City VALUES (3976,'Fayetteville','USA','North Carolina',121015);
+INSERT INTO City VALUES (3977,'Cedar Rapids','USA','Iowa',120758);
+INSERT INTO City VALUES (3978,'Elizabeth','USA','New Jersey',120568);
+INSERT INTO City VALUES (3979,'Lansing','USA','Michigan',119128);
+INSERT INTO City VALUES (3980,'Lancaster','USA','California',118718);
+INSERT INTO City VALUES (3981,'Fort Collins','USA','Colorado',118652);
+INSERT INTO City VALUES (3982,'Coral Springs','USA','Florida',117549);
+INSERT INTO City VALUES (3983,'Stamford','USA','Connecticut',117083);
+INSERT INTO City VALUES (3984,'Thousand Oaks','USA','California',117005);
+INSERT INTO City VALUES (3985,'Vallejo','USA','California',116760);
+INSERT INTO City VALUES (3986,'Palmdale','USA','California',116670);
+INSERT INTO City VALUES (3987,'Columbia','USA','South Carolina',116278);
+INSERT INTO City VALUES (3988,'El Monte','USA','California',115965);
+INSERT INTO City VALUES (3989,'Abilene','USA','Texas',115930);
+INSERT INTO City VALUES (3990,'North Las Vegas','USA','Nevada',115488);
+INSERT INTO City VALUES (3991,'Ann Arbor','USA','Michigan',114024);
+INSERT INTO City VALUES (3992,'Beaumont','USA','Texas',113866);
+INSERT INTO City VALUES (3993,'Waco','USA','Texas',113726);
+INSERT INTO City VALUES (3994,'Macon','USA','Georgia',113336);
+INSERT INTO City VALUES (3995,'Independence','USA','Missouri',113288);
+INSERT INTO City VALUES (3996,'Peoria','USA','Illinois',112936);
+INSERT INTO City VALUES (3997,'Inglewood','USA','California',112580);
+INSERT INTO City VALUES (3998,'Springfield','USA','Illinois',111454);
+INSERT INTO City VALUES (3999,'Simi Valley','USA','California',111351);
+INSERT INTO City VALUES (4000,'Lafayette','USA','Louisiana',110257);
+INSERT INTO City VALUES (4001,'Gilbert','USA','Arizona',109697);
+INSERT INTO City VALUES (4002,'Carrollton','USA','Texas',109576);
+INSERT INTO City VALUES (4003,'Bellevue','USA','Washington',109569);
+INSERT INTO City VALUES (4004,'West Valley City','USA','Utah',108896);
+INSERT INTO City VALUES (4005,'Clarksville','USA','Tennessee',108787);
+INSERT INTO City VALUES (4006,'Costa Mesa','USA','California',108724);
+INSERT INTO City VALUES (4007,'Peoria','USA','Arizona',108364);
+INSERT INTO City VALUES (4008,'South Bend','USA','Indiana',107789);
+INSERT INTO City VALUES (4009,'Downey','USA','California',107323);
+INSERT INTO City VALUES (4010,'Waterbury','USA','Connecticut',107271);
+INSERT INTO City VALUES (4011,'Manchester','USA','New Hampshire',107006);
+INSERT INTO City VALUES (4012,'Allentown','USA','Pennsylvania',106632);
+INSERT INTO City VALUES (4013,'McAllen','USA','Texas',106414);
+INSERT INTO City VALUES (4014,'Joliet','USA','Illinois',106221);
+INSERT INTO City VALUES (4015,'Lowell','USA','Massachusetts',105167);
+INSERT INTO City VALUES (4016,'Provo','USA','Utah',105166);
+INSERT INTO City VALUES (4017,'West Covina','USA','California',105080);
+INSERT INTO City VALUES (4018,'Wichita Falls','USA','Texas',104197);
+INSERT INTO City VALUES (4019,'Erie','USA','Pennsylvania',103717);
+INSERT INTO City VALUES (4020,'Daly City','USA','California',103621);
+INSERT INTO City VALUES (4021,'Citrus Heights','USA','California',103455);
+INSERT INTO City VALUES (4022,'Norwalk','USA','California',103298);
+INSERT INTO City VALUES (4023,'Gary','USA','Indiana',102746);
+INSERT INTO City VALUES (4024,'Berkeley','USA','California',102743);
+INSERT INTO City VALUES (4025,'Santa Clara','USA','California',102361);
+INSERT INTO City VALUES (4026,'Green Bay','USA','Wisconsin',102313);
+INSERT INTO City VALUES (4027,'Cape Coral','USA','Florida',102286);
+INSERT INTO City VALUES (4028,'Arvada','USA','Colorado',102153);
+INSERT INTO City VALUES (4029,'Pueblo','USA','Colorado',102121);
+INSERT INTO City VALUES (4030,'Sandy','USA','Utah',101853);
+INSERT INTO City VALUES (4031,'Athens-Clarke County','USA','Georgia',101489);
+INSERT INTO City VALUES (4032,'Cambridge','USA','Massachusetts',101355);
+INSERT INTO City VALUES (4033,'Westminster','USA','Colorado',100940);
+INSERT INTO City VALUES (4034,'San Buenaventura','USA','California',100916);
+INSERT INTO City VALUES (4035,'Portsmouth','USA','Virginia',100565);
+INSERT INTO City VALUES (4036,'Livonia','USA','Michigan',100545);
+INSERT INTO City VALUES (4037,'Burbank','USA','California',100316);
+INSERT INTO City VALUES (4038,'Clearwater','USA','Florida',99936);
+INSERT INTO City VALUES (4039,'Midland','USA','Texas',98293);
+INSERT INTO City VALUES (4040,'Davenport','USA','Iowa',98256);
+INSERT INTO City VALUES (4041,'Mission Viejo','USA','California',98049);
+INSERT INTO City VALUES (4042,'Miami Beach','USA','Florida',97855);
+INSERT INTO City VALUES (4043,'Sunrise Manor','USA','Nevada',95362);
+INSERT INTO City VALUES (4044,'New Bedford','USA','Massachusetts',94780);
+INSERT INTO City VALUES (4045,'El Cajon','USA','California',94578);
+INSERT INTO City VALUES (4046,'Norman','USA','Oklahoma',94193);
+INSERT INTO City VALUES (4047,'Richmond','USA','California',94100);
+INSERT INTO City VALUES (4048,'Albany','USA','New York',93994);
+INSERT INTO City VALUES (4049,'Brockton','USA','Massachusetts',93653);
+INSERT INTO City VALUES (4050,'Roanoke','USA','Virginia',93357);
+INSERT INTO City VALUES (4051,'Billings','USA','Montana',92988);
+INSERT INTO City VALUES (4052,'Compton','USA','California',92864);
+INSERT INTO City VALUES (4053,'Gainesville','USA','Florida',92291);
+INSERT INTO City VALUES (4054,'Fairfield','USA','California',92256);
+INSERT INTO City VALUES (4055,'Arden-Arcade','USA','California',92040);
+INSERT INTO City VALUES (4056,'San Mateo','USA','California',91799);
+INSERT INTO City VALUES (4057,'Visalia','USA','California',91762);
+INSERT INTO City VALUES (4058,'Boulder','USA','Colorado',91238);
+INSERT INTO City VALUES (4059,'Cary','USA','North Carolina',91213);
+INSERT INTO City VALUES (4060,'Santa Monica','USA','California',91084);
+INSERT INTO City VALUES (4061,'Fall River','USA','Massachusetts',90555);
+INSERT INTO City VALUES (4062,'Kenosha','USA','Wisconsin',89447);
+INSERT INTO City VALUES (4063,'Elgin','USA','Illinois',89408);
+INSERT INTO City VALUES (4064,'Odessa','USA','Texas',89293);
+INSERT INTO City VALUES (4065,'Carson','USA','California',89089);
+INSERT INTO City VALUES (4066,'Charleston','USA','South Carolina',89063);
+INSERT INTO City VALUES (4067,'Charlotte Amalie','VIR','St Thomas',13000);
+INSERT INTO City VALUES (4068,'Harare','ZWE','Harare',1410000);
+INSERT INTO City VALUES (4069,'Bulawayo','ZWE','Bulawayo',621742);
+INSERT INTO City VALUES (4070,'Chitungwiza','ZWE','Harare',274912);
+INSERT INTO City VALUES (4071,'Mount Darwin','ZWE','Harare',164362);
+INSERT INTO City VALUES (4072,'Mutare','ZWE','Manicaland',131367);
+INSERT INTO City VALUES (4073,'Gweru','ZWE','Midlands',128037);
+INSERT INTO City VALUES (4074,'Gaza','PSE','Gaza',353632);
+INSERT INTO City VALUES (4075,'Khan Yunis','PSE','Khan Yunis',123175);
+INSERT INTO City VALUES (4076,'Hebron','PSE','Hebron',119401);
+INSERT INTO City VALUES (4077,'Jabaliya','PSE','North Gaza',113901);
+INSERT INTO City VALUES (4078,'Nablus','PSE','Nablus',100231);
+INSERT INTO City VALUES (4079,'Rafah','PSE','Rafah',92020);
+
+/*!40000 ALTER TABLE City ENABLE KEYS */;
+
+--
+-- Table structure for table 'Country'
+--
+
+CREATE TABLE Country (
+ Code char(3) NOT NULL default '',
+ Name char(52) NOT NULL default '',
+ Continent enum('Asia','Europe','North America','Africa','Oceania','Antarctica','South America') NOT NULL default 'Asia',
+ Region char(26) NOT NULL default '',
+ SurfaceArea float(10,2) NOT NULL default '0.00',
+ IndepYear smallint(6) default NULL,
+ Population int(11) NOT NULL default '0',
+ LifeExpectancy float(3,1) default NULL,
+ GNP float(10,2) default NULL,
+ GNPOld float(10,2) default NULL,
+ LocalName char(45) NOT NULL default '',
+ GovernmentForm char(45) NOT NULL default '',
+ HeadOfState char(60) default NULL,
+ Capital int(11) default NULL,
+ Code2 char(2) NOT NULL default '',
+ PRIMARY KEY (Code)
+) TYPE=MyISAM;
+
+/*!40000 ALTER TABLE Country DISABLE KEYS */;
+
+--
+-- Dumping data for table 'Country'
+--
+
+
+INSERT INTO Country VALUES ('AFG','Afghanistan','Asia','Southern and Central Asia',652090.00,1919,22720000,45.9,5976.00,NULL,'Afganistan/Afqanestan','Islamic Emirate','Mohammad Omar',1,'AF');
+INSERT INTO Country VALUES ('NLD','Netherlands','Europe','Western Europe',41526.00,1581,15864000,78.3,371362.00,360478.00,'Nederland','Constitutional Monarchy','Beatrix',5,'NL');
+INSERT INTO Country VALUES ('ANT','Netherlands Antilles','North America','Caribbean',800.00,0,217000,74.7,1941.00,NULL,'Nederlandse Antillen','Nonmetropolitan Territory of The Netherlands','Beatrix',33,'AN');
+INSERT INTO Country VALUES ('ALB','Albania','Europe','Southern Europe',28748.00,1912,3401200,71.6,3205.00,2500.00,'Shqipëria','Republic','Rexhep Mejdani',34,'AL');
+INSERT INTO Country VALUES ('DZA','Algeria','Africa','Northern Africa',2381741.00,1962,31471000,69.7,49982.00,46966.00,'Al-Jaza’ir/Algérie','Republic','Abdelaziz Bouteflika',35,'DZ');
+INSERT INTO Country VALUES ('ASM','American Samoa','Oceania','Polynesia',199.00,0,68000,75.1,334.00,NULL,'Amerika Samoa','US Territory','George W. Bush',54,'AS');
+INSERT INTO Country VALUES ('AND','Andorra','Europe','Southern Europe',468.00,1278,78000,83.5,1630.00,NULL,'Andorra','Parliamentary Coprincipality','',55,'AD');
+INSERT INTO Country VALUES ('AGO','Angola','Africa','Central Africa',1246700.00,1975,12878000,38.3,6648.00,7984.00,'Angola','Republic','José Eduardo dos Santos',56,'AO');
+INSERT INTO Country VALUES ('AIA','Anguilla','North America','Caribbean',96.00,0,8000,76.1,63.20,NULL,'Anguilla','Dependent Territory of the UK','Elisabeth II',62,'AI');
+INSERT INTO Country VALUES ('ATG','Antigua and Barbuda','North America','Caribbean',442.00,1981,68000,70.5,612.00,584.00,'Antigua and Barbuda','Constitutional Monarchy','Elisabeth II',63,'AG');
+INSERT INTO Country VALUES ('ARE','United Arab Emirates','Asia','Middle East',83600.00,1971,2441000,74.1,37966.00,36846.00,'Al-Imarat al-´Arabiya al-Muttahida','Emirate Federation','Zayid bin Sultan al-Nahayan',65,'AE');
+INSERT INTO Country VALUES ('ARG','Argentina','South America','South America',2780400.00,1816,37032000,75.1,340238.00,323310.00,'Argentina','Federal Republic','Fernando de la Rúa',69,'AR');
+INSERT INTO Country VALUES ('ARM','Armenia','Asia','Middle East',29800.00,1991,3520000,66.4,1813.00,1627.00,'Hajastan','Republic','Robert Kotšarjan',126,'AM');
+INSERT INTO Country VALUES ('ABW','Aruba','North America','Caribbean',193.00,0,103000,78.4,828.00,793.00,'Aruba','Nonmetropolitan Territory of The Netherlands','Beatrix',129,'AW');
+INSERT INTO Country VALUES ('AUS','Australia','Oceania','Australia and New Zealand',7741220.00,1901,18886000,79.8,351182.00,392911.00,'Australia','Constitutional Monarchy, Federation','Elisabeth II',135,'AU');
+INSERT INTO Country VALUES ('AZE','Azerbaijan','Asia','Middle East',86600.00,1991,7734000,62.9,4127.00,4100.00,'Azärbaycan','Federal Republic','Heydär Äliyev',144,'AZ');
+INSERT INTO Country VALUES ('BHS','Bahamas','North America','Caribbean',13878.00,1973,307000,71.1,3527.00,3347.00,'The Bahamas','Constitutional Monarchy','Elisabeth II',148,'BS');
+INSERT INTO Country VALUES ('BHR','Bahrain','Asia','Middle East',694.00,1971,617000,73.0,6366.00,6097.00,'Al-Bahrayn','Monarchy (Emirate)','Hamad ibn Isa al-Khalifa',149,'BH');
+INSERT INTO Country VALUES ('BGD','Bangladesh','Asia','Southern and Central Asia',143998.00,1971,129155000,60.2,32852.00,31966.00,'Bangladesh','Republic','Shahabuddin Ahmad',150,'BD');
+INSERT INTO Country VALUES ('BRB','Barbados','North America','Caribbean',430.00,1966,270000,73.0,2223.00,2186.00,'Barbados','Constitutional Monarchy','Elisabeth II',174,'BB');
+INSERT INTO Country VALUES ('BEL','Belgium','Europe','Western Europe',30518.00,1830,10239000,77.8,249704.00,243948.00,'België/Belgique','Constitutional Monarchy, Federation','Albert II',179,'BE');
+INSERT INTO Country VALUES ('BLZ','Belize','North America','Central America',22696.00,1981,241000,70.9,630.00,616.00,'Belize','Constitutional Monarchy','Elisabeth II',185,'BZ');
+INSERT INTO Country VALUES ('BEN','Benin','Africa','Western Africa',112622.00,1960,6097000,50.2,2357.00,2141.00,'Bénin','Republic','Mathieu Kérékou',187,'BJ');
+INSERT INTO Country VALUES ('BMU','Bermuda','North America','North America',53.00,0,65000,76.9,2328.00,2190.00,'Bermuda','Dependent Territory of the UK','Elisabeth II',191,'BM');
+INSERT INTO Country VALUES ('BTN','Bhutan','Asia','Southern and Central Asia',47000.00,1910,2124000,52.4,372.00,383.00,'Druk-Yul','Monarchy','Jigme Singye Wangchuk',192,'BT');
+INSERT INTO Country VALUES ('BOL','Bolivia','South America','South America',1098581.00,1825,8329000,63.7,8571.00,7967.00,'Bolivia','Republic','Hugo Bánzer Suárez',194,'BO');
+INSERT INTO Country VALUES ('BIH','Bosnia and Herzegovina','Europe','Southern Europe',51197.00,1992,3972000,71.5,2841.00,NULL,'Bosna i Hercegovina','Federal Republic','Ante Jelavic',201,'BA');
+INSERT INTO Country VALUES ('BWA','Botswana','Africa','Southern Africa',581730.00,1966,1622000,39.3,4834.00,4935.00,'Botswana','Republic','Festus G. Mogae',204,'BW');
+INSERT INTO Country VALUES ('BRA','Brazil','South America','South America',8547403.00,1822,170115000,62.9,776739.00,804108.00,'Brasil','Federal Republic','Fernando Henrique Cardoso',211,'BR');
+INSERT INTO Country VALUES ('GBR','United Kingdom','Europe','British Islands',242900.00,1066,59623400,77.7,1378330.00,1296830.00,'United Kingdom','Constitutional Monarchy','Elisabeth II',456,'GB');
+INSERT INTO Country VALUES ('VGB','Virgin Islands, British','North America','Caribbean',151.00,0,21000,75.4,612.00,573.00,'British Virgin Islands','Dependent Territory of the UK','Elisabeth II',537,'VG');
+INSERT INTO Country VALUES ('BRN','Brunei','Asia','Southeast Asia',5765.00,1984,328000,73.6,11705.00,12460.00,'Brunei Darussalam','Monarchy (Sultanate)','Haji Hassan al-Bolkiah',538,'BN');
+INSERT INTO Country VALUES ('BGR','Bulgaria','Europe','Eastern Europe',110994.00,1908,8190900,70.9,12178.00,10169.00,'Balgarija','Republic','Petar Stojanov',539,'BG');
+INSERT INTO Country VALUES ('BFA','Burkina Faso','Africa','Western Africa',274000.00,1960,11937000,46.7,2425.00,2201.00,'Burkina Faso','Republic','Blaise Compaoré',549,'BF');
+INSERT INTO Country VALUES ('BDI','Burundi','Africa','Eastern Africa',27834.00,1962,6695000,46.2,903.00,982.00,'Burundi/Uburundi','Republic','Pierre Buyoya',552,'BI');
+INSERT INTO Country VALUES ('CYM','Cayman Islands','North America','Caribbean',264.00,0,38000,78.9,1263.00,1186.00,'Cayman Islands','Dependent Territory of the UK','Elisabeth II',553,'KY');
+INSERT INTO Country VALUES ('CHL','Chile','South America','South America',756626.00,1810,15211000,75.7,72949.00,75780.00,'Chile','Republic','Ricardo Lagos Escobar',554,'CL');
+INSERT INTO Country VALUES ('COK','Cook Islands','Oceania','Polynesia',236.00,0,20000,71.1,100.00,NULL,'The Cook Islands','Nonmetropolitan Territory of New Zealand','Elisabeth II',583,'CK');
+INSERT INTO Country VALUES ('CRI','Costa Rica','North America','Central America',51100.00,1821,4023000,75.8,10226.00,9757.00,'Costa Rica','Republic','Miguel Ángel Rodríguez Echeverría',584,'CR');
+INSERT INTO Country VALUES ('DJI','Djibouti','Africa','Eastern Africa',23200.00,1977,638000,50.8,382.00,373.00,'Djibouti/Jibuti','Republic','Ismail Omar Guelleh',585,'DJ');
+INSERT INTO Country VALUES ('DMA','Dominica','North America','Caribbean',751.00,1978,71000,73.4,256.00,243.00,'Dominica','Republic','Vernon Shaw',586,'DM');
+INSERT INTO Country VALUES ('DOM','Dominican Republic','North America','Caribbean',48511.00,1844,8495000,73.2,15846.00,15076.00,'República Dominicana','Republic','Hipólito Mejía Domínguez',587,'DO');
+INSERT INTO Country VALUES ('ECU','Ecuador','South America','South America',283561.00,1822,12646000,71.1,19770.00,19769.00,'Ecuador','Republic','Gustavo Noboa Bejarano',594,'EC');
+INSERT INTO Country VALUES ('EGY','Egypt','Africa','Northern Africa',1001449.00,1922,68470000,63.3,82710.00,75617.00,'Misr','Republic','Hosni Mubarak',608,'EG');
+INSERT INTO Country VALUES ('SLV','El Salvador','North America','Central America',21041.00,1841,6276000,69.7,11863.00,11203.00,'El Salvador','Republic','Francisco Guillermo Flores Pérez',645,'SV');
+INSERT INTO Country VALUES ('ERI','Eritrea','Africa','Eastern Africa',117600.00,1993,3850000,55.8,650.00,755.00,'Ertra','Republic','Isayas Afewerki [Isaias Afwerki]',652,'ER');
+INSERT INTO Country VALUES ('ESP','Spain','Europe','Southern Europe',505992.00,1492,39441700,78.8,553233.00,532031.00,'España','Constitutional Monarchy','Juan Carlos I',653,'ES');
+INSERT INTO Country VALUES ('ZAF','South Africa','Africa','Southern Africa',1221037.00,1910,40377000,51.1,116729.00,129092.00,'South Africa','Republic','Thabo Mbeki',716,'ZA');
+INSERT INTO Country VALUES ('ETH','Ethiopia','Africa','Eastern Africa',1104300.00,-1000,62565000,45.2,6353.00,6180.00,'YeItyop´iya','Republic','Negasso Gidada',756,'ET');
+INSERT INTO Country VALUES ('FLK','Falkland Islands','South America','South America',12173.00,0,2000,NULL,0.00,NULL,'Falkland Islands','Dependent Territory of the UK','Elisabeth II',763,'FK');
+INSERT INTO Country VALUES ('FJI','Fiji Islands','Oceania','Melanesia',18274.00,1970,817000,67.9,1536.00,2149.00,'Fiji Islands','Republic','Josefa Iloilo',764,'FJ');
+INSERT INTO Country VALUES ('PHL','Philippines','Asia','Southeast Asia',300000.00,1946,75967000,67.5,65107.00,82239.00,'Pilipinas','Republic','Gloria Macapagal-Arroyo',766,'PH');
+INSERT INTO Country VALUES ('FRO','Faroe Islands','Europe','Nordic Countries',1399.00,0,43000,78.4,0.00,NULL,'Føroyar','Part of Denmark','Margrethe II',901,'FO');
+INSERT INTO Country VALUES ('GAB','Gabon','Africa','Central Africa',267668.00,1960,1226000,50.1,5493.00,5279.00,'Le Gabon','Republic','Omar Bongo',902,'GA');
+INSERT INTO Country VALUES ('GMB','Gambia','Africa','Western Africa',11295.00,1965,1305000,53.2,320.00,325.00,'The Gambia','Republic','Yahya Jammeh',904,'GM');
+INSERT INTO Country VALUES ('GEO','Georgia','Asia','Middle East',69700.00,1991,4968000,64.5,6064.00,5924.00,'Sakartvelo','Republic','Eduard Ševardnadze',905,'GE');
+INSERT INTO Country VALUES ('GHA','Ghana','Africa','Western Africa',238533.00,1957,20212000,57.4,7137.00,6884.00,'Ghana','Republic','John Kufuor',910,'GH');
+INSERT INTO Country VALUES ('GIB','Gibraltar','Europe','Southern Europe',6.00,0,25000,79.0,258.00,NULL,'Gibraltar','Dependent Territory of the UK','Elisabeth II',915,'GI');
+INSERT INTO Country VALUES ('GRD','Grenada','North America','Caribbean',344.00,1974,94000,64.5,318.00,NULL,'Grenada','Constitutional Monarchy','Elisabeth II',916,'GD');
+INSERT INTO Country VALUES ('GRL','Greenland','North America','North America',2166090.00,0,56000,68.1,0.00,NULL,'Kalaallit Nunaat/Grønland','Part of Denmark','Margrethe II',917,'GL');
+INSERT INTO Country VALUES ('GLP','Guadeloupe','North America','Caribbean',1705.00,0,456000,77.0,3501.00,NULL,'Guadeloupe','Overseas Department of France','Jacques Chirac',919,'GP');
+INSERT INTO Country VALUES ('GUM','Guam','Oceania','Micronesia',549.00,0,168000,77.8,1197.00,1136.00,'Guam','US Territory','George W. Bush',921,'GU');
+INSERT INTO Country VALUES ('GTM','Guatemala','North America','Central America',108889.00,1821,11385000,66.2,19008.00,17797.00,'Guatemala','Republic','Alfonso Portillo Cabrera',922,'GT');
+INSERT INTO Country VALUES ('GIN','Guinea','Africa','Western Africa',245857.00,1958,7430000,45.6,2352.00,2383.00,'Guinée','Republic','Lansana Conté',926,'GN');
+INSERT INTO Country VALUES ('GNB','Guinea-Bissau','Africa','Western Africa',36125.00,1974,1213000,49.0,293.00,272.00,'Guiné-Bissau','Republic','Kumba Ialá',927,'GW');
+INSERT INTO Country VALUES ('GUY','Guyana','South America','South America',214969.00,1966,861000,64.0,722.00,743.00,'Guyana','Republic','Bharrat Jagdeo',928,'GY');
+INSERT INTO Country VALUES ('HTI','Haiti','North America','Caribbean',27750.00,1804,8222000,49.2,3459.00,3107.00,'Haïti/Dayti','Republic','Jean-Bertrand Aristide',929,'HT');
+INSERT INTO Country VALUES ('HND','Honduras','North America','Central America',112088.00,1838,6485000,69.9,5333.00,4697.00,'Honduras','Republic','Carlos Roberto Flores Facussé',933,'HN');
+INSERT INTO Country VALUES ('HKG','Hong Kong','Asia','Eastern Asia',1075.00,0,6782000,79.5,166448.00,173610.00,'Xianggang/Hong Kong','Special Administrative Region of China','Jiang Zemin',937,'HK');
+INSERT INTO Country VALUES ('SJM','Svalbard and Jan Mayen','Europe','Nordic Countries',62422.00,0,3200,NULL,0.00,NULL,'Svalbard og Jan Mayen','Dependent Territory of Norway','Harald V',938,'SJ');
+INSERT INTO Country VALUES ('IDN','Indonesia','Asia','Southeast Asia',1904569.00,1945,212107000,68.0,84982.00,215002.00,'Indonesia','Republic','Abdurrahman Wahid',939,'ID');
+INSERT INTO Country VALUES ('IND','India','Asia','Southern and Central Asia',3287263.00,1947,1013662000,62.5,447114.00,430572.00,'Bharat/India','Federal Republic','Kocheril Raman Narayanan',1109,'IN');
+INSERT INTO Country VALUES ('IRQ','Iraq','Asia','Middle East',438317.00,1932,23115000,66.5,11500.00,NULL,'Al-´Iraq','Republic','Saddam Hussein al-Takriti',1365,'IQ');
+INSERT INTO Country VALUES ('IRN','Iran','Asia','Southern and Central Asia',1648195.00,1906,67702000,69.7,195746.00,160151.00,'Iran','Islamic Republic','Ali Mohammad Khatami-Ardakani',1380,'IR');
+INSERT INTO Country VALUES ('IRL','Ireland','Europe','British Islands',70273.00,1921,3775100,76.8,75921.00,73132.00,'Ireland/Éire','Republic','Mary McAleese',1447,'IE');
+INSERT INTO Country VALUES ('ISL','Iceland','Europe','Nordic Countries',103000.00,1944,279000,79.4,8255.00,7474.00,'Ísland','Republic','Ólafur Ragnar Grímsson',1449,'IS');
+INSERT INTO Country VALUES ('ISR','Israel','Asia','Middle East',21056.00,1948,6217000,78.6,97477.00,98577.00,'Yisra’el/Isra’il','Republic','Moshe Katzav',1450,'IL');
+INSERT INTO Country VALUES ('ITA','Italy','Europe','Southern Europe',301316.00,1861,57680000,79.0,1161755.00,1145372.00,'Italia','Republic','Carlo Azeglio Ciampi',1464,'IT');
+INSERT INTO Country VALUES ('TMP','East Timor','Asia','Southeast Asia',14874.00,0,885000,46.0,0.00,NULL,'Timor Timur','Administrated by the UN','José Alexandre Gusmão',1522,'TP');
+INSERT INTO Country VALUES ('AUT','Austria','Europe','Western Europe',83859.00,1918,8091800,77.7,211860.00,206025.00,'Österreich','Federal Republic','Thomas Klestil',1523,'AT');
+INSERT INTO Country VALUES ('JAM','Jamaica','North America','Caribbean',10990.00,1962,2583000,75.2,6871.00,6722.00,'Jamaica','Constitutional Monarchy','Elisabeth II',1530,'JM');
+INSERT INTO Country VALUES ('JPN','Japan','Asia','Eastern Asia',377829.00,-660,126714000,80.7,3787042.00,4192638.00,'Nihon/Nippon','Constitutional Monarchy','Akihito',1532,'JP');
+INSERT INTO Country VALUES ('YEM','Yemen','Asia','Middle East',527968.00,1918,18112000,59.8,6041.00,5729.00,'Al-Yaman','Republic','Ali Abdallah Salih',1780,'YE');
+INSERT INTO Country VALUES ('JOR','Jordan','Asia','Middle East',88946.00,1946,5083000,77.4,7526.00,7051.00,'Al-Urdunn','Constitutional Monarchy','Abdullah II',1786,'JO');
+INSERT INTO Country VALUES ('CXR','Christmas Island','Oceania','Australia and New Zealand',135.00,0,2500,NULL,0.00,NULL,'Christmas Island','Territory of Australia','Elisabeth II',1791,'CX');
+INSERT INTO Country VALUES ('YUG','Yugoslavia','Europe','Southern Europe',102173.00,1918,10640000,72.4,17000.00,NULL,'Jugoslavija','Federal Republic','Vojislav Koštunica',1792,'YU');
+INSERT INTO Country VALUES ('KHM','Cambodia','Asia','Southeast Asia',181035.00,1953,11168000,56.5,5121.00,5670.00,'Kâmpuchéa','Constitutional Monarchy','Norodom Sihanouk',1800,'KH');
+INSERT INTO Country VALUES ('CMR','Cameroon','Africa','Central Africa',475442.00,1960,15085000,54.8,9174.00,8596.00,'Cameroun/Cameroon','Republic','Paul Biya',1804,'CM');
+INSERT INTO Country VALUES ('CAN','Canada','North America','North America',9970610.00,1867,31147000,79.4,598862.00,625626.00,'Canada','Constitutional Monarchy, Federation','Elisabeth II',1822,'CA');
+INSERT INTO Country VALUES ('CPV','Cape Verde','Africa','Western Africa',4033.00,1975,428000,68.9,435.00,420.00,'Cabo Verde','Republic','António Mascarenhas Monteiro',1859,'CV');
+INSERT INTO Country VALUES ('KAZ','Kazakstan','Asia','Southern and Central Asia',2724900.00,1991,16223000,63.2,24375.00,23383.00,'Qazaqstan','Republic','Nursultan Nazarbajev',1864,'KZ');
+INSERT INTO Country VALUES ('KEN','Kenya','Africa','Eastern Africa',580367.00,1963,30080000,48.0,9217.00,10241.00,'Kenya','Republic','Daniel arap Moi',1881,'KE');
+INSERT INTO Country VALUES ('CAF','Central African Republic','Africa','Central Africa',622984.00,1960,3615000,44.0,1054.00,993.00,'Centrafrique/Bê-Afrîka','Republic','Ange-Félix Patassé',1889,'CF');
+INSERT INTO Country VALUES ('CHN','China','Asia','Eastern Asia',9572900.00,-1523,1277558000,71.4,982268.00,917719.00,'Zhongquo','People\'sRepublic','Jiang Zemin',1891,'CN');
+INSERT INTO Country VALUES ('KGZ','Kyrgyzstan','Asia','Southern and Central Asia',199900.00,1991,4699000,63.4,1626.00,1767.00,'Kyrgyzstan','Republic','Askar Akajev',2253,'KG');
+INSERT INTO Country VALUES ('KIR','Kiribati','Oceania','Micronesia',726.00,1979,83000,59.8,40.70,NULL,'Kiribati','Republic','Teburoro Tito',2256,'KI');
+INSERT INTO Country VALUES ('COL','Colombia','South America','South America',1138914.00,1810,42321000,70.3,102896.00,105116.00,'Colombia','Republic','Andrés Pastrana Arango',2257,'CO');
+INSERT INTO Country VALUES ('COM','Comoros','Africa','Eastern Africa',1862.00,1975,578000,60.0,4401.00,4361.00,'Komori/Comores','Republic','Azali Assoumani',2295,'KM');
+INSERT INTO Country VALUES ('COG','Congo','Africa','Central Africa',342000.00,1960,2943000,47.4,2108.00,2287.00,'Congo','Republic','Denis Sassou-Nguesso',2296,'CG');
+INSERT INTO Country VALUES ('COD','Congo, The Democratic Republic of the','Africa','Central Africa',2344858.00,1960,51654000,48.8,6964.00,2474.00,'République Démocratique du Congo','Republic','Joseph Kabila',2298,'CD');
+INSERT INTO Country VALUES ('CCK','Cocos (Keeling) Islands','Oceania','Australia and New Zealand',14.00,0,600,NULL,0.00,NULL,'Cocos (Keeling) Islands','Territory of Australia','Elisabeth II',2317,'CC');
+INSERT INTO Country VALUES ('PRK','North Korea','Asia','Eastern Asia',120538.00,1948,24039000,70.7,5332.00,NULL,'Choson Minjujuui In´min Konghwaguk (Bukhan)','Socialistic Republic','Kim Jong-il',2318,'KP');
+INSERT INTO Country VALUES ('KOR','South Korea','Asia','Eastern Asia',99434.00,1948,46844000,74.4,320749.00,442544.00,'Taehan Min’guk (Namhan)','Republic','Kim Dae-jung',2331,'KR');
+INSERT INTO Country VALUES ('GRC','Greece','Europe','Southern Europe',131626.00,1830,10545700,78.4,120724.00,119946.00,'Elláda','Republic','Kostis Stefanopoulos',2401,'GR');
+INSERT INTO Country VALUES ('HRV','Croatia','Europe','Southern Europe',56538.00,1991,4473000,73.7,20208.00,19300.00,'Hrvatska','Republic','Štipe Mesic',2409,'HR');
+INSERT INTO Country VALUES ('CUB','Cuba','North America','Caribbean',110861.00,1902,11201000,76.2,17843.00,18862.00,'Cuba','Socialistic Republic','Fidel Castro Ruz',2413,'CU');
+INSERT INTO Country VALUES ('KWT','Kuwait','Asia','Middle East',17818.00,1961,1972000,76.1,27037.00,30373.00,'Al-Kuwayt','Constitutional Monarchy (Emirate)','Jabir al-Ahmad al-Jabir al-Sabah',2429,'KW');
+INSERT INTO Country VALUES ('CYP','Cyprus','Asia','Middle East',9251.00,1960,754700,76.7,9333.00,8246.00,'Kýpros/Kibris','Republic','Glafkos Klerides',2430,'CY');
+INSERT INTO Country VALUES ('LAO','Laos','Asia','Southeast Asia',236800.00,1953,5433000,53.1,1292.00,1746.00,'Lao','Republic','Khamtay Siphandone',2432,'LA');
+INSERT INTO Country VALUES ('LVA','Latvia','Europe','Baltic Countries',64589.00,1991,2424200,68.4,6398.00,5639.00,'Latvija','Republic','Vaira Vike-Freiberga',2434,'LV');
+INSERT INTO Country VALUES ('LSO','Lesotho','Africa','Southern Africa',30355.00,1966,2153000,50.8,1061.00,1161.00,'Lesotho','Constitutional Monarchy','Letsie III',2437,'LS');
+INSERT INTO Country VALUES ('LBN','Lebanon','Asia','Middle East',10400.00,1941,3282000,71.3,17121.00,15129.00,'Lubnan','Republic','Émile Lahoud',2438,'LB');
+INSERT INTO Country VALUES ('LBR','Liberia','Africa','Western Africa',111369.00,1847,3154000,51.0,2012.00,NULL,'Liberia','Republic','Charles Taylor',2440,'LR');
+INSERT INTO Country VALUES ('LBY','Libyan Arab Jamahiriya','Africa','Northern Africa',1759540.00,1951,5605000,75.5,44806.00,40562.00,'Libiya','Socialistic State','Muammar al-Qadhafi',2441,'LY');
+INSERT INTO Country VALUES ('LIE','Liechtenstein','Europe','Western Europe',160.00,1806,32300,78.8,1119.00,1084.00,'Liechtenstein','Constitutional Monarchy','Hans-Adam II',2446,'LI');
+INSERT INTO Country VALUES ('LTU','Lithuania','Europe','Baltic Countries',65301.00,1991,3698500,69.1,10692.00,9585.00,'Lietuva','Republic','Valdas Adamkus',2447,'LT');
+INSERT INTO Country VALUES ('LUX','Luxembourg','Europe','Western Europe',2586.00,1867,435700,77.1,16321.00,15519.00,'Luxembourg/Lëtzebuerg','Constitutional Monarchy','Henri',2452,'LU');
+INSERT INTO Country VALUES ('ESH','Western Sahara','Africa','Northern Africa',266000.00,0,293000,49.8,60.00,NULL,'As-Sahrawiya','Occupied by Marocco','Mohammed Abdel Aziz',2453,'EH');
+INSERT INTO Country VALUES ('MAC','Macao','Asia','Eastern Asia',18.00,0,473000,81.6,5749.00,5940.00,'Macau/Aomen','Special Administrative Region of China','Jiang Zemin',2454,'MO');
+INSERT INTO Country VALUES ('MDG','Madagascar','Africa','Eastern Africa',587041.00,1960,15942000,55.0,3750.00,3545.00,'Madagasikara/Madagascar','Federal Republic','Didier Ratsiraka',2455,'MG');
+INSERT INTO Country VALUES ('MKD','Macedonia','Europe','Southern Europe',25713.00,1991,2024000,73.8,1694.00,1915.00,'Makedonija','Republic','Boris Trajkovski',2460,'MK');
+INSERT INTO Country VALUES ('MWI','Malawi','Africa','Eastern Africa',118484.00,1964,10925000,37.6,1687.00,2527.00,'Malawi','Republic','Bakili Muluzi',2462,'MW');
+INSERT INTO Country VALUES ('MDV','Maldives','Asia','Southern and Central Asia',298.00,1965,286000,62.2,199.00,NULL,'Dhivehi Raajje/Maldives','Republic','Maumoon Abdul Gayoom',2463,'MV');
+INSERT INTO Country VALUES ('MYS','Malaysia','Asia','Southeast Asia',329758.00,1957,22244000,70.8,69213.00,97884.00,'Malaysia','Constitutional Monarchy, Federation','Salahuddin Abdul Aziz Shah Alhaj',2464,'MY');
+INSERT INTO Country VALUES ('MLI','Mali','Africa','Western Africa',1240192.00,1960,11234000,46.7,2642.00,2453.00,'Mali','Republic','Alpha Oumar Konaré',2482,'ML');
+INSERT INTO Country VALUES ('MLT','Malta','Europe','Southern Europe',316.00,1964,380200,77.9,3512.00,3338.00,'Malta','Republic','Guido de Marco',2484,'MT');
+INSERT INTO Country VALUES ('MAR','Morocco','Africa','Northern Africa',446550.00,1956,28351000,69.1,36124.00,33514.00,'Al-Maghrib','Constitutional Monarchy','Mohammed VI',2486,'MA');
+INSERT INTO Country VALUES ('MHL','Marshall Islands','Oceania','Micronesia',181.00,1990,64000,65.5,97.00,NULL,'Marshall Islands/Majol','Republic','Kessai Note',2507,'MH');
+INSERT INTO Country VALUES ('MTQ','Martinique','North America','Caribbean',1102.00,0,395000,78.3,2731.00,2559.00,'Martinique','Overseas Department of France','Jacques Chirac',2508,'MQ');
+INSERT INTO Country VALUES ('MRT','Mauritania','Africa','Western Africa',1025520.00,1960,2670000,50.8,998.00,1081.00,'Muritaniya/Mauritanie','Republic','Maaouiya Ould Sid´Ahmad Taya',2509,'MR');
+INSERT INTO Country VALUES ('MUS','Mauritius','Africa','Eastern Africa',2040.00,1968,1158000,71.0,4251.00,4186.00,'Mauritius','Republic','Cassam Uteem',2511,'MU');
+INSERT INTO Country VALUES ('MYT','Mayotte','Africa','Eastern Africa',373.00,0,149000,59.5,0.00,NULL,'Mayotte','Territorial Collectivity of France','Jacques Chirac',2514,'YT');
+INSERT INTO Country VALUES ('MEX','Mexico','North America','Central America',1958201.00,1810,98881000,71.5,414972.00,401461.00,'México','Federal Republic','Vicente Fox Quesada',2515,'MX');
+INSERT INTO Country VALUES ('FSM','Micronesia, Federated States of','Oceania','Micronesia',702.00,1990,119000,68.6,212.00,NULL,'Micronesia','Federal Republic','Leo A. Falcam',2689,'FM');
+INSERT INTO Country VALUES ('MDA','Moldova','Europe','Eastern Europe',33851.00,1991,4380000,64.5,1579.00,1872.00,'Moldova','Republic','Vladimir Voronin',2690,'MD');
+INSERT INTO Country VALUES ('MCO','Monaco','Europe','Western Europe',1.50,1861,34000,78.8,776.00,NULL,'Monaco','Constitutional Monarchy','Rainier III',2695,'MC');
+INSERT INTO Country VALUES ('MNG','Mongolia','Asia','Eastern Asia',1566500.00,1921,2662000,67.3,1043.00,933.00,'Mongol Uls','Republic','Natsagiin Bagabandi',2696,'MN');
+INSERT INTO Country VALUES ('MSR','Montserrat','North America','Caribbean',102.00,0,11000,78.0,109.00,NULL,'Montserrat','Dependent Territory of the UK','Elisabeth II',2697,'MS');
+INSERT INTO Country VALUES ('MOZ','Mozambique','Africa','Eastern Africa',801590.00,1975,19680000,37.5,2891.00,2711.00,'Moçambique','Republic','Joaquím A. Chissano',2698,'MZ');
+INSERT INTO Country VALUES ('MMR','Myanmar','Asia','Southeast Asia',676578.00,1948,45611000,54.9,180375.00,171028.00,'Myanma Pye','Republic','kenraali Than Shwe',2710,'MM');
+INSERT INTO Country VALUES ('NAM','Namibia','Africa','Southern Africa',824292.00,1990,1726000,42.5,3101.00,3384.00,'Namibia','Republic','Sam Nujoma',2726,'NA');
+INSERT INTO Country VALUES ('NRU','Nauru','Oceania','Micronesia',21.00,1968,12000,60.8,197.00,NULL,'Naoero/Nauru','Republic','Bernard Dowiyogo',2728,'NR');
+INSERT INTO Country VALUES ('NPL','Nepal','Asia','Southern and Central Asia',147181.00,1769,23930000,57.8,4768.00,4837.00,'Nepal','Constitutional Monarchy','Gyanendra Bir Bikram',2729,'NP');
+INSERT INTO Country VALUES ('NIC','Nicaragua','North America','Central America',130000.00,1838,5074000,68.7,1988.00,2023.00,'Nicaragua','Republic','Arnoldo Alemán Lacayo',2734,'NI');
+INSERT INTO Country VALUES ('NER','Niger','Africa','Western Africa',1267000.00,1960,10730000,41.3,1706.00,1580.00,'Niger','Republic','Mamadou Tandja',2738,'NE');
+INSERT INTO Country VALUES ('NGA','Nigeria','Africa','Western Africa',923768.00,1960,111506000,51.6,65707.00,58623.00,'Nigeria','Federal Republic','Olusegun Obasanjo',2754,'NG');
+INSERT INTO Country VALUES ('NIU','Niue','Oceania','Polynesia',260.00,0,2000,NULL,0.00,NULL,'Niue','Nonmetropolitan Territory of New Zealand','Elisabeth II',2805,'NU');
+INSERT INTO Country VALUES ('NFK','Norfolk Island','Oceania','Australia and New Zealand',36.00,0,2000,NULL,0.00,NULL,'Norfolk Island','Territory of Australia','Elisabeth II',2806,'NF');
+INSERT INTO Country VALUES ('NOR','Norway','Europe','Nordic Countries',323877.00,1905,4478500,78.7,145895.00,153370.00,'Norge','Constitutional Monarchy','Harald V',2807,'NO');
+INSERT INTO Country VALUES ('CIV','Côte d’Ivoire','Africa','Western Africa',322463.00,1960,14786000,45.2,11345.00,10285.00,'Côte d’Ivoire','Republic','Laurent Gbagbo',2814,'CI');
+INSERT INTO Country VALUES ('OMN','Oman','Asia','Middle East',309500.00,1951,2542000,71.8,16904.00,16153.00,'´Uman','Monarchy (Sultanate)','Qabus ibn Sa´id',2821,'OM');
+INSERT INTO Country VALUES ('PAK','Pakistan','Asia','Southern and Central Asia',796095.00,1947,156483000,61.1,61289.00,58549.00,'Pakistan','Republic','Mohammad Rafiq Tarar',2831,'PK');
+INSERT INTO Country VALUES ('PLW','Palau','Oceania','Micronesia',459.00,1994,19000,68.6,105.00,NULL,'Belau/Palau','Republic','Kuniwo Nakamura',2881,'PW');
+INSERT INTO Country VALUES ('PAN','Panama','North America','Central America',75517.00,1903,2856000,75.5,9131.00,8700.00,'Panamá','Republic','Mireya Elisa Moscoso Rodríguez',2882,'PA');
+INSERT INTO Country VALUES ('PNG','Papua New Guinea','Oceania','Melanesia',462840.00,1975,4807000,63.1,4988.00,6328.00,'Papua New Guinea/Papua Niugini','Constitutional Monarchy','Elisabeth II',2884,'PG');
+INSERT INTO Country VALUES ('PRY','Paraguay','South America','South America',406752.00,1811,5496000,73.7,8444.00,9555.00,'Paraguay','Republic','Luis Ángel González Macchi',2885,'PY');
+INSERT INTO Country VALUES ('PER','Peru','South America','South America',1285216.00,1821,25662000,70.0,64140.00,65186.00,'Perú/Piruw','Republic','Valentin Paniagua Corazao',2890,'PE');
+INSERT INTO Country VALUES ('PCN','Pitcairn','Oceania','Polynesia',49.00,0,50,NULL,0.00,NULL,'Pitcairn','Dependent Territory of the UK','Elisabeth II',2912,'PN');
+INSERT INTO Country VALUES ('MNP','Northern Mariana Islands','Oceania','Micronesia',464.00,0,78000,75.5,0.00,NULL,'Northern Mariana Islands','Commonwealth of the US','George W. Bush',2913,'MP');
+INSERT INTO Country VALUES ('PRT','Portugal','Europe','Southern Europe',91982.00,1143,9997600,75.8,105954.00,102133.00,'Portugal','Republic','Jorge Sampãio',2914,'PT');
+INSERT INTO Country VALUES ('PRI','Puerto Rico','North America','Caribbean',8875.00,0,3869000,75.6,34100.00,32100.00,'Puerto Rico','Commonwealth of the US','George W. Bush',2919,'PR');
+INSERT INTO Country VALUES ('POL','Poland','Europe','Eastern Europe',323250.00,1918,38653600,73.2,151697.00,135636.00,'Polska','Republic','Aleksander Kwasniewski',2928,'PL');
+INSERT INTO Country VALUES ('GNQ','Equatorial Guinea','Africa','Central Africa',28051.00,1968,453000,53.6,283.00,542.00,'Guinea Ecuatorial','Republic','Teodoro Obiang Nguema Mbasogo',2972,'GQ');
+INSERT INTO Country VALUES ('QAT','Qatar','Asia','Middle East',11000.00,1971,599000,72.4,9472.00,8920.00,'Qatar','Monarchy','Hamad ibn Khalifa al-Thani',2973,'QA');
+INSERT INTO Country VALUES ('FRA','France','Europe','Western Europe',551500.00,843,59225700,78.8,1424285.00,1392448.00,'France','Republic','Jacques Chirac',2974,'FR');
+INSERT INTO Country VALUES ('GUF','French Guiana','South America','South America',90000.00,0,181000,76.1,681.00,NULL,'Guyane française','Overseas Department of France','Jacques Chirac',3014,'GF');
+INSERT INTO Country VALUES ('PYF','French Polynesia','Oceania','Polynesia',4000.00,0,235000,74.8,818.00,781.00,'Polynésie française','Nonmetropolitan Territory of France','Jacques Chirac',3016,'PF');
+INSERT INTO Country VALUES ('REU','Réunion','Africa','Eastern Africa',2510.00,0,699000,72.7,8287.00,7988.00,'Réunion','Overseas Department of France','Jacques Chirac',3017,'RE');
+INSERT INTO Country VALUES ('ROM','Romania','Europe','Eastern Europe',238391.00,1878,22455500,69.9,38158.00,34843.00,'România','Republic','Ion Iliescu',3018,'RO');
+INSERT INTO Country VALUES ('RWA','Rwanda','Africa','Eastern Africa',26338.00,1962,7733000,39.3,2036.00,1863.00,'Rwanda/Urwanda','Republic','Paul Kagame',3047,'RW');
+INSERT INTO Country VALUES ('SWE','Sweden','Europe','Nordic Countries',449964.00,836,8861400,79.6,226492.00,227757.00,'Sverige','Constitutional Monarchy','Carl XVI Gustaf',3048,'SE');
+INSERT INTO Country VALUES ('SHN','Saint Helena','Africa','Western Africa',314.00,0,6000,76.8,0.00,NULL,'Saint Helena','Dependent Territory of the UK','Elisabeth II',3063,'SH');
+INSERT INTO Country VALUES ('KNA','Saint Kitts and Nevis','North America','Caribbean',261.00,1983,38000,70.7,299.00,NULL,'Saint Kitts and Nevis','Constitutional Monarchy','Elisabeth II',3064,'KN');
+INSERT INTO Country VALUES ('LCA','Saint Lucia','North America','Caribbean',622.00,1979,154000,72.3,571.00,NULL,'Saint Lucia','Constitutional Monarchy','Elisabeth II',3065,'LC');
+INSERT INTO Country VALUES ('VCT','Saint Vincent and the Grenadines','North America','Caribbean',388.00,1979,114000,72.3,285.00,NULL,'Saint Vincent and the Grenadines','Constitutional Monarchy','Elisabeth II',3066,'VC');
+INSERT INTO Country VALUES ('SPM','Saint Pierre and Miquelon','North America','North America',242.00,0,7000,77.6,0.00,NULL,'Saint-Pierre-et-Miquelon','Territorial Collectivity of France','Jacques Chirac',3067,'PM');
+INSERT INTO Country VALUES ('DEU','Germany','Europe','Western Europe',357022.00,1955,82164700,77.4,2133367.00,2102826.00,'Deutschland','Federal Republic','Johannes Rau',3068,'DE');
+INSERT INTO Country VALUES ('SLB','Solomon Islands','Oceania','Melanesia',28896.00,1978,444000,71.3,182.00,220.00,'Solomon Islands','Constitutional Monarchy','Elisabeth II',3161,'SB');
+INSERT INTO Country VALUES ('ZMB','Zambia','Africa','Eastern Africa',752618.00,1964,9169000,37.2,3377.00,3922.00,'Zambia','Republic','Frederick Chiluba',3162,'ZM');
+INSERT INTO Country VALUES ('WSM','Samoa','Oceania','Polynesia',2831.00,1962,180000,69.2,141.00,157.00,'Samoa','Parlementary Monarchy','Malietoa Tanumafili II',3169,'WS');
+INSERT INTO Country VALUES ('SMR','San Marino','Europe','Southern Europe',61.00,885,27000,81.1,510.00,NULL,'San Marino','Republic',NULL,3171,'SM');
+INSERT INTO Country VALUES ('STP','Sao Tome and Principe','Africa','Central Africa',964.00,1975,147000,65.3,6.00,NULL,'São Tomé e Príncipe','Republic','Miguel Trovoada',3172,'ST');
+INSERT INTO Country VALUES ('SAU','Saudi Arabia','Asia','Middle East',2149690.00,1932,21607000,67.8,137635.00,146171.00,'Al-´Arabiya as-Sa´udiya','Monarchy','Fahd ibn Abdul-Aziz al-Sa´ud',3173,'SA');
+INSERT INTO Country VALUES ('SEN','Senegal','Africa','Western Africa',196722.00,1960,9481000,62.2,4787.00,4542.00,'Sénégal/Sounougal','Republic','Abdoulaye Wade',3198,'SN');
+INSERT INTO Country VALUES ('SYC','Seychelles','Africa','Eastern Africa',455.00,1976,77000,70.4,536.00,539.00,'Sesel/Seychelles','Republic','France-Albert René',3206,'SC');
+INSERT INTO Country VALUES ('SLE','Sierra Leone','Africa','Western Africa',71740.00,1961,4854000,45.3,746.00,858.00,'Sierra Leone','Republic','Ahmed Tejan Kabbah',3207,'SL');
+INSERT INTO Country VALUES ('SGP','Singapore','Asia','Southeast Asia',618.00,1965,3567000,80.1,86503.00,96318.00,'Singapore/Singapura/Xinjiapo/Singapur','Republic','Sellapan Rama Nathan',3208,'SG');
+INSERT INTO Country VALUES ('SVK','Slovakia','Europe','Eastern Europe',49012.00,1993,5398700,73.7,20594.00,19452.00,'Slovensko','Republic','Rudolf Schuster',3209,'SK');
+INSERT INTO Country VALUES ('SVN','Slovenia','Europe','Southern Europe',20256.00,1991,1987800,74.9,19756.00,18202.00,'Slovenija','Republic','Milan Kucan',3212,'SI');
+INSERT INTO Country VALUES ('SOM','Somalia','Africa','Eastern Africa',637657.00,1960,10097000,46.2,935.00,NULL,'Soomaaliya','Republic','Abdiqassim Salad Hassan',3214,'SO');
+INSERT INTO Country VALUES ('LKA','Sri Lanka','Asia','Southern and Central Asia',65610.00,1948,18827000,71.8,15706.00,15091.00,'Sri Lanka/Ilankai','Republic','Chandrika Kumaratunga',3217,'LK');
+INSERT INTO Country VALUES ('SDN','Sudan','Africa','Northern Africa',2505813.00,1956,29490000,56.6,10162.00,NULL,'As-Sudan','Islamic Republic','Omar Hassan Ahmad al-Bashir',3225,'SD');
+INSERT INTO Country VALUES ('FIN','Finland','Europe','Nordic Countries',338145.00,1917,5171300,77.4,121914.00,119833.00,'Suomi','Republic','Tarja Halonen',3236,'FI');
+INSERT INTO Country VALUES ('SUR','Suriname','South America','South America',163265.00,1975,417000,71.4,870.00,706.00,'Suriname','Republic','Ronald Venetiaan',3243,'SR');
+INSERT INTO Country VALUES ('SWZ','Swaziland','Africa','Southern Africa',17364.00,1968,1008000,40.4,1206.00,1312.00,'kaNgwane','Monarchy','Mswati III',3244,'SZ');
+INSERT INTO Country VALUES ('CHE','Switzerland','Europe','Western Europe',41284.00,1499,7160400,79.6,264478.00,256092.00,'Schweiz/Suisse/Svizzera/Svizra','Federation','Adolf Ogi',3248,'CH');
+INSERT INTO Country VALUES ('SYR','Syria','Asia','Middle East',185180.00,1941,16125000,68.5,65984.00,64926.00,'Suriya','Republic','Bashar al-Assad',3250,'SY');
+INSERT INTO Country VALUES ('TJK','Tajikistan','Asia','Southern and Central Asia',143100.00,1991,6188000,64.1,1990.00,1056.00,'Toçikiston','Republic','Emomali Rahmonov',3261,'TJ');
+INSERT INTO Country VALUES ('TWN','Taiwan, Province of China','Asia','Eastern Asia',36188.00,1945,22256000,76.4,256254.00,263451.00,'T’ai-wan','Republic','Chen Shui-bian',3263,'TW');
+INSERT INTO Country VALUES ('TZA','Tanzania','Africa','Eastern Africa',883749.00,1961,33517000,52.3,8005.00,7388.00,'Tanzania','Republic','Benjamin William Mkapa',3306,'TZ');
+INSERT INTO Country VALUES ('DNK','Denmark','Europe','Nordic Countries',43094.00,800,5330000,76.5,174099.00,169264.00,'Danmark','Constitutional Monarchy','Margrethe II',3315,'DK');
+INSERT INTO Country VALUES ('THA','Thailand','Asia','Southeast Asia',513115.00,1350,61399000,68.6,116416.00,153907.00,'Prathet Thai','Constitutional Monarchy','Bhumibol Adulyadej',3320,'TH');
+INSERT INTO Country VALUES ('TGO','Togo','Africa','Western Africa',56785.00,1960,4629000,54.7,1449.00,1400.00,'Togo','Republic','Gnassingbé Eyadéma',3332,'TG');
+INSERT INTO Country VALUES ('TKL','Tokelau','Oceania','Polynesia',12.00,0,2000,NULL,0.00,NULL,'Tokelau','Nonmetropolitan Territory of New Zealand','Elisabeth II',3333,'TK');
+INSERT INTO Country VALUES ('TON','Tonga','Oceania','Polynesia',650.00,1970,99000,67.9,146.00,170.00,'Tonga','Monarchy','Taufa\'ahau Tupou IV',3334,'TO');
+INSERT INTO Country VALUES ('TTO','Trinidad and Tobago','North America','Caribbean',5130.00,1962,1295000,68.0,6232.00,5867.00,'Trinidad and Tobago','Republic','Arthur N. R. Robinson',3336,'TT');
+INSERT INTO Country VALUES ('TCD','Chad','Africa','Central Africa',1284000.00,1960,7651000,50.5,1208.00,1102.00,'Tchad/Tshad','Republic','Idriss Déby',3337,'TD');
+INSERT INTO Country VALUES ('CZE','Czech Republic','Europe','Eastern Europe',78866.00,1993,10278100,74.5,55017.00,52037.00,'¸esko','Republic','Václav Havel',3339,'CZ');
+INSERT INTO Country VALUES ('TUN','Tunisia','Africa','Northern Africa',163610.00,1956,9586000,73.7,20026.00,18898.00,'Tunis/Tunisie','Republic','Zine al-Abidine Ben Ali',3349,'TN');
+INSERT INTO Country VALUES ('TUR','Turkey','Asia','Middle East',774815.00,1923,66591000,71.0,210721.00,189122.00,'Türkiye','Republic','Ahmet Necdet Sezer',3358,'TR');
+INSERT INTO Country VALUES ('TKM','Turkmenistan','Asia','Southern and Central Asia',488100.00,1991,4459000,60.9,4397.00,2000.00,'Türkmenostan','Republic','Saparmurad Nijazov',3419,'TM');
+INSERT INTO Country VALUES ('TCA','Turks and Caicos Islands','North America','Caribbean',430.00,0,17000,73.3,96.00,NULL,'The Turks and Caicos Islands','Dependent Territory of the UK','Elisabeth II',3423,'TC');
+INSERT INTO Country VALUES ('TUV','Tuvalu','Oceania','Polynesia',26.00,1978,12000,66.3,6.00,NULL,'Tuvalu','Constitutional Monarchy','Elisabeth II',3424,'TV');
+INSERT INTO Country VALUES ('UGA','Uganda','Africa','Eastern Africa',241038.00,1962,21778000,42.9,6313.00,6887.00,'Uganda','Republic','Yoweri Museveni',3425,'UG');
+INSERT INTO Country VALUES ('UKR','Ukraine','Europe','Eastern Europe',603700.00,1991,50456000,66.0,42168.00,49677.00,'Ukrajina','Republic','Leonid Kutšma',3426,'UA');
+INSERT INTO Country VALUES ('HUN','Hungary','Europe','Eastern Europe',93030.00,1918,10043200,71.4,48267.00,45914.00,'Magyarország','Republic','Ferenc Mádl',3483,'HU');
+INSERT INTO Country VALUES ('URY','Uruguay','South America','South America',175016.00,1828,3337000,75.2,20831.00,19967.00,'Uruguay','Republic','Jorge Batlle Ibáñez',3492,'UY');
+INSERT INTO Country VALUES ('NCL','New Caledonia','Oceania','Melanesia',18575.00,0,214000,72.8,3563.00,NULL,'Nouvelle-Calédonie','Nonmetropolitan Territory of France','Jacques Chirac',3493,'NC');
+INSERT INTO Country VALUES ('NZL','New Zealand','Oceania','Australia and New Zealand',270534.00,1907,3862000,77.8,54669.00,64960.00,'New Zealand/Aotearoa','Constitutional Monarchy','Elisabeth II',3499,'NZ');
+INSERT INTO Country VALUES ('UZB','Uzbekistan','Asia','Southern and Central Asia',447400.00,1991,24318000,63.7,14194.00,21300.00,'Uzbekiston','Republic','Islam Karimov',3503,'UZ');
+INSERT INTO Country VALUES ('BLR','Belarus','Europe','Eastern Europe',207600.00,1991,10236000,68.0,13714.00,NULL,'Belarus','Republic','Aljaksandr Lukašenka',3520,'BY');
+INSERT INTO Country VALUES ('WLF','Wallis and Futuna','Oceania','Polynesia',200.00,0,15000,NULL,0.00,NULL,'Wallis-et-Futuna','Nonmetropolitan Territory of France','Jacques Chirac',3536,'WF');
+INSERT INTO Country VALUES ('VUT','Vanuatu','Oceania','Melanesia',12189.00,1980,190000,60.6,261.00,246.00,'Vanuatu','Republic','John Bani',3537,'VU');
+INSERT INTO Country VALUES ('VAT','Holy See (Vatican City State)','Europe','Southern Europe',0.40,1929,1000,NULL,9.00,NULL,'Santa Sede/Città del Vaticano','Independent Church State','Johannes Paavali II',3538,'VA');
+INSERT INTO Country VALUES ('VEN','Venezuela','South America','South America',912050.00,1811,24170000,73.1,95023.00,88434.00,'Venezuela','Federal Republic','Hugo Chávez Frías',3539,'VE');
+INSERT INTO Country VALUES ('RUS','Russian Federation','Europe','Eastern Europe',17075400.00,1991,146934000,67.2,276608.00,442989.00,'Rossija','Federal Republic','Vladimir Putin',3580,'RU');
+INSERT INTO Country VALUES ('VNM','Vietnam','Asia','Southeast Asia',331689.00,1945,79832000,69.3,21929.00,22834.00,'Viêt Nam','Socialistic Republic','Trân Duc Luong',3770,'VN');
+INSERT INTO Country VALUES ('EST','Estonia','Europe','Baltic Countries',45227.00,1991,1439200,69.5,5328.00,3371.00,'Eesti','Republic','Lennart Meri',3791,'EE');
+INSERT INTO Country VALUES ('USA','United States','North America','North America',9363520.00,1776,278357000,77.1,8510700.00,8110900.00,'United States','Federal Republic','George W. Bush',3813,'US');
+INSERT INTO Country VALUES ('VIR','Virgin Islands, U.S.','North America','Caribbean',347.00,0,93000,78.1,0.00,NULL,'Virgin Islands of the United States','US Territory','George W. Bush',4067,'VI');
+INSERT INTO Country VALUES ('ZWE','Zimbabwe','Africa','Eastern Africa',390757.00,1980,11669000,37.8,5951.00,8670.00,'Zimbabwe','Republic','Robert G. Mugabe',4068,'ZW');
+INSERT INTO Country VALUES ('PSE','Palestine','Asia','Middle East',6257.00,0,3101000,71.4,4173.00,NULL,'Filastin','Autonomous Area','Yasser (Yasir) Arafat',4074,'PS');
+INSERT INTO Country VALUES ('ATA','Antarctica','Antarctica','Antarctica',13120000.00,0,0,NULL,0.00,NULL,'–','Co-administrated','',NULL,'AQ');
+INSERT INTO Country VALUES ('BVT','Bouvet Island','Antarctica','Antarctica',59.00,0,0,NULL,0.00,NULL,'Bouvetøya','Dependent Territory of Norway','Harald V',NULL,'BV');
+INSERT INTO Country VALUES ('IOT','British Indian Ocean Territory','Africa','Eastern Africa',78.00,0,0,NULL,0.00,NULL,'British Indian Ocean Territory','Dependent Territory of the UK','Elisabeth II',NULL,'IO');
+INSERT INTO Country VALUES ('SGS','South Georgia and the South Sandwich Islands','Antarctica','Antarctica',3903.00,0,0,NULL,0.00,NULL,'South Georgia and the South Sandwich Islands','Dependent Territory of the UK','Elisabeth II',NULL,'GS');
+INSERT INTO Country VALUES ('HMD','Heard Island and McDonald Islands','Antarctica','Antarctica',359.00,0,0,NULL,0.00,NULL,'Heard and McDonald Islands','Territory of Australia','Elisabeth II',NULL,'HM');
+INSERT INTO Country VALUES ('ATF','French Southern territories','Antarctica','Antarctica',7780.00,0,0,NULL,0.00,NULL,'Terres australes françaises','Nonmetropolitan Territory of France','Jacques Chirac',NULL,'TF');
+INSERT INTO Country VALUES ('UMI','United States Minor Outlying Islands','Oceania','Micronesia/Caribbean',16.00,0,0,NULL,0.00,NULL,'United States Minor Outlying Islands','Dependent Territory of the US','George W. Bush',NULL,'UM');
+
+/*!40000 ALTER TABLE Country ENABLE KEYS */;
+
+--
+-- Table structure for table 'CountryLanguage'
+--
+
+CREATE TABLE CountryLanguage (
+ Country char(3) NOT NULL default '',
+ Language char(30) NOT NULL default '',
+ IsOfficial enum('T','F') NOT NULL default 'F',
+ Percentage float(3,1) NOT NULL default '0.0',
+ PRIMARY KEY (Country,Language)
+) TYPE=MyISAM;
+
+/*!40000 ALTER TABLE CountryLanguage DISABLE KEYS */;
+
+--
+-- Dumping data for table 'CountryLanguage'
+--
+
+
+INSERT INTO CountryLanguage VALUES ('AFG','Pashto','T',52.4);
+INSERT INTO CountryLanguage VALUES ('NLD','Dutch','T',95.6);
+INSERT INTO CountryLanguage VALUES ('ANT','Papiamento','T',86.2);
+INSERT INTO CountryLanguage VALUES ('ALB','Albaniana','T',97.9);
+INSERT INTO CountryLanguage VALUES ('DZA','Arabic','T',86.0);
+INSERT INTO CountryLanguage VALUES ('ASM','Samoan','T',90.6);
+INSERT INTO CountryLanguage VALUES ('AND','Spanish','F',44.6);
+INSERT INTO CountryLanguage VALUES ('AGO','Ovimbundu','F',37.2);
+INSERT INTO CountryLanguage VALUES ('AIA','English','T',0.0);
+INSERT INTO CountryLanguage VALUES ('ATG','Creole English','F',95.7);
+INSERT INTO CountryLanguage VALUES ('ARE','Arabic','T',42.0);
+INSERT INTO CountryLanguage VALUES ('ARG','Spanish','T',96.8);
+INSERT INTO CountryLanguage VALUES ('ARM','Armenian','T',93.4);
+INSERT INTO CountryLanguage VALUES ('ABW','Papiamento','F',76.7);
+INSERT INTO CountryLanguage VALUES ('AUS','English','T',81.2);
+INSERT INTO CountryLanguage VALUES ('AZE','Azerbaijani','T',89.0);
+INSERT INTO CountryLanguage VALUES ('BHS','Creole English','F',89.7);
+INSERT INTO CountryLanguage VALUES ('BHR','Arabic','T',67.7);
+INSERT INTO CountryLanguage VALUES ('BGD','Bengali','T',97.7);
+INSERT INTO CountryLanguage VALUES ('BRB','Bajan','F',95.1);
+INSERT INTO CountryLanguage VALUES ('BEL','Dutch','T',59.2);
+INSERT INTO CountryLanguage VALUES ('BLZ','English','T',50.8);
+INSERT INTO CountryLanguage VALUES ('BEN','Fon','F',39.8);
+INSERT INTO CountryLanguage VALUES ('BMU','English','T',100.0);
+INSERT INTO CountryLanguage VALUES ('BTN','Dzongkha','T',50.0);
+INSERT INTO CountryLanguage VALUES ('BOL','Spanish','T',87.7);
+INSERT INTO CountryLanguage VALUES ('BIH','Serbo-Croatian','T',99.2);
+INSERT INTO CountryLanguage VALUES ('BWA','Tswana','F',75.5);
+INSERT INTO CountryLanguage VALUES ('BRA','Portuguese','T',97.5);
+INSERT INTO CountryLanguage VALUES ('GBR','English','T',97.3);
+INSERT INTO CountryLanguage VALUES ('VGB','English','T',0.0);
+INSERT INTO CountryLanguage VALUES ('BRN','Malay','T',45.5);
+INSERT INTO CountryLanguage VALUES ('BGR','Bulgariana','T',83.2);
+INSERT INTO CountryLanguage VALUES ('BFA','Mossi','F',50.2);
+INSERT INTO CountryLanguage VALUES ('BDI','Kirundi','T',98.1);
+INSERT INTO CountryLanguage VALUES ('CYM','English','T',0.0);
+INSERT INTO CountryLanguage VALUES ('CHL','Spanish','T',89.7);
+INSERT INTO CountryLanguage VALUES ('COK','Maori','T',0.0);
+INSERT INTO CountryLanguage VALUES ('CRI','Spanish','T',97.5);
+INSERT INTO CountryLanguage VALUES ('DJI','Somali','F',43.9);
+INSERT INTO CountryLanguage VALUES ('DMA','Creole English','F',100.0);
+INSERT INTO CountryLanguage VALUES ('DOM','Spanish','T',98.0);
+INSERT INTO CountryLanguage VALUES ('ECU','Spanish','T',93.0);
+INSERT INTO CountryLanguage VALUES ('EGY','Arabic','T',98.8);
+INSERT INTO CountryLanguage VALUES ('SLV','Spanish','T',100.0);
+INSERT INTO CountryLanguage VALUES ('ERI','Tigrinja','T',49.1);
+INSERT INTO CountryLanguage VALUES ('ESP','Spanish','T',74.4);
+INSERT INTO CountryLanguage VALUES ('ZAF','Zulu','T',22.7);
+INSERT INTO CountryLanguage VALUES ('ETH','Oromo','F',31.0);
+INSERT INTO CountryLanguage VALUES ('FLK','English','T',0.0);
+INSERT INTO CountryLanguage VALUES ('FJI','Fijian','T',50.8);
+INSERT INTO CountryLanguage VALUES ('PHL','Pilipino','T',29.3);
+INSERT INTO CountryLanguage VALUES ('FRO','Faroese','T',100.0);
+INSERT INTO CountryLanguage VALUES ('GAB','Fang','F',35.8);
+INSERT INTO CountryLanguage VALUES ('GMB','Malinke','F',34.1);
+INSERT INTO CountryLanguage VALUES ('GEO','Georgiana','T',71.7);
+INSERT INTO CountryLanguage VALUES ('GHA','Akan','F',52.4);
+INSERT INTO CountryLanguage VALUES ('GIB','English','T',88.9);
+INSERT INTO CountryLanguage VALUES ('GRD','Creole English','F',100.0);
+INSERT INTO CountryLanguage VALUES ('GRL','Greenlandic','T',87.5);
+INSERT INTO CountryLanguage VALUES ('GLP','Creole French','F',95.0);
+INSERT INTO CountryLanguage VALUES ('GUM','English','T',37.5);
+INSERT INTO CountryLanguage VALUES ('GTM','Spanish','T',64.7);
+INSERT INTO CountryLanguage VALUES ('GIN','Ful','F',38.6);
+INSERT INTO CountryLanguage VALUES ('GNB','Crioulo','F',36.4);
+INSERT INTO CountryLanguage VALUES ('GUY','Creole English','F',96.4);
+INSERT INTO CountryLanguage VALUES ('HTI','Haiti Creole','F',100.0);
+INSERT INTO CountryLanguage VALUES ('HND','Spanish','T',97.2);
+INSERT INTO CountryLanguage VALUES ('HKG','Canton Chinese','F',88.7);
+INSERT INTO CountryLanguage VALUES ('SJM','Norwegian','T',0.0);
+INSERT INTO CountryLanguage VALUES ('IDN','Javanese','F',39.4);
+INSERT INTO CountryLanguage VALUES ('IND','Hindi','T',39.9);
+INSERT INTO CountryLanguage VALUES ('IRQ','Arabic','T',77.2);
+INSERT INTO CountryLanguage VALUES ('IRN','Persian','T',45.7);
+INSERT INTO CountryLanguage VALUES ('IRL','English','T',98.4);
+INSERT INTO CountryLanguage VALUES ('ISL','Icelandic','T',95.7);
+INSERT INTO CountryLanguage VALUES ('ISR','Hebrew','T',63.1);
+INSERT INTO CountryLanguage VALUES ('ITA','Italian','T',94.1);
+INSERT INTO CountryLanguage VALUES ('TMP','Sunda','F',0.0);
+INSERT INTO CountryLanguage VALUES ('AUT','German','T',92.0);
+INSERT INTO CountryLanguage VALUES ('JAM','Creole English','F',94.2);
+INSERT INTO CountryLanguage VALUES ('JPN','Japanese','T',99.1);
+INSERT INTO CountryLanguage VALUES ('YEM','Arabic','T',99.6);
+INSERT INTO CountryLanguage VALUES ('JOR','Arabic','T',97.9);
+INSERT INTO CountryLanguage VALUES ('CXR','Chinese','F',0.0);
+INSERT INTO CountryLanguage VALUES ('YUG','Serbo-Croatian','T',75.2);
+INSERT INTO CountryLanguage VALUES ('KHM','Khmer','T',88.6);
+INSERT INTO CountryLanguage VALUES ('CMR','Fang','F',19.7);
+INSERT INTO CountryLanguage VALUES ('CAN','English','T',60.4);
+INSERT INTO CountryLanguage VALUES ('CPV','Crioulo','F',100.0);
+INSERT INTO CountryLanguage VALUES ('KAZ','Kazakh','T',46.0);
+INSERT INTO CountryLanguage VALUES ('KEN','Kikuyu','F',20.9);
+INSERT INTO CountryLanguage VALUES ('CAF','Gbaya','F',23.8);
+INSERT INTO CountryLanguage VALUES ('CHN','Chinese','T',92.0);
+INSERT INTO CountryLanguage VALUES ('KGZ','Kirgiz','T',59.7);
+INSERT INTO CountryLanguage VALUES ('KIR','Kiribati','T',98.9);
+INSERT INTO CountryLanguage VALUES ('COL','Spanish','T',99.0);
+INSERT INTO CountryLanguage VALUES ('COM','Comorian','T',75.0);
+INSERT INTO CountryLanguage VALUES ('COG','Kongo','F',51.5);
+INSERT INTO CountryLanguage VALUES ('COD','Luba','F',18.0);
+INSERT INTO CountryLanguage VALUES ('CCK','Malay','F',0.0);
+INSERT INTO CountryLanguage VALUES ('PRK','Korean','T',99.9);
+INSERT INTO CountryLanguage VALUES ('KOR','Korean','T',99.9);
+INSERT INTO CountryLanguage VALUES ('GRC','Greek','T',98.5);
+INSERT INTO CountryLanguage VALUES ('HRV','Serbo-Croatian','T',95.9);
+INSERT INTO CountryLanguage VALUES ('CUB','Spanish','T',100.0);
+INSERT INTO CountryLanguage VALUES ('KWT','Arabic','T',78.1);
+INSERT INTO CountryLanguage VALUES ('CYP','Greek','T',74.1);
+INSERT INTO CountryLanguage VALUES ('LAO','Lao','T',67.2);
+INSERT INTO CountryLanguage VALUES ('LVA','Latvian','T',55.1);
+INSERT INTO CountryLanguage VALUES ('LSO','Sotho','T',85.0);
+INSERT INTO CountryLanguage VALUES ('LBN','Arabic','T',93.0);
+INSERT INTO CountryLanguage VALUES ('LBR','Kpelle','F',19.5);
+INSERT INTO CountryLanguage VALUES ('LBY','Arabic','T',96.0);
+INSERT INTO CountryLanguage VALUES ('LIE','German','T',89.0);
+INSERT INTO CountryLanguage VALUES ('LTU','Lithuanian','T',81.6);
+INSERT INTO CountryLanguage VALUES ('LUX','Luxembourgish','T',64.4);
+INSERT INTO CountryLanguage VALUES ('ESH','Arabic','T',100.0);
+INSERT INTO CountryLanguage VALUES ('MAC','Canton Chinese','F',85.6);
+INSERT INTO CountryLanguage VALUES ('MDG','Malagasy','T',98.9);
+INSERT INTO CountryLanguage VALUES ('MKD','Macedonian','T',66.5);
+INSERT INTO CountryLanguage VALUES ('MWI','Chichewa','T',58.3);
+INSERT INTO CountryLanguage VALUES ('MDV','Dhivehi','T',100.0);
+INSERT INTO CountryLanguage VALUES ('MYS','Malay','T',58.4);
+INSERT INTO CountryLanguage VALUES ('MLI','Bambara','F',31.8);
+INSERT INTO CountryLanguage VALUES ('MLT','Maltese','T',95.8);
+INSERT INTO CountryLanguage VALUES ('MAR','Arabic','T',65.0);
+INSERT INTO CountryLanguage VALUES ('MHL','Marshallese','T',96.8);
+INSERT INTO CountryLanguage VALUES ('MTQ','Creole French','F',96.6);
+INSERT INTO CountryLanguage VALUES ('MRT','Hassaniya','F',81.7);
+INSERT INTO CountryLanguage VALUES ('MUS','Creole French','F',70.6);
+INSERT INTO CountryLanguage VALUES ('MYT','Mahoré','F',41.9);
+INSERT INTO CountryLanguage VALUES ('MEX','Spanish','T',92.1);
+INSERT INTO CountryLanguage VALUES ('FSM','Trukese','F',41.6);
+INSERT INTO CountryLanguage VALUES ('MDA','Romanian','T',61.9);
+INSERT INTO CountryLanguage VALUES ('MCO','French','T',41.9);
+INSERT INTO CountryLanguage VALUES ('MNG','Mongolian','T',78.8);
+INSERT INTO CountryLanguage VALUES ('MSR','English','T',0.0);
+INSERT INTO CountryLanguage VALUES ('MOZ','Makua','F',27.8);
+INSERT INTO CountryLanguage VALUES ('MMR','Burmese','T',69.0);
+INSERT INTO CountryLanguage VALUES ('NAM','Ovambo','F',50.7);
+INSERT INTO CountryLanguage VALUES ('NRU','Nauru','T',57.5);
+INSERT INTO CountryLanguage VALUES ('NPL','Nepali','T',50.4);
+INSERT INTO CountryLanguage VALUES ('NIC','Spanish','T',97.6);
+INSERT INTO CountryLanguage VALUES ('NER','Hausa','F',53.1);
+INSERT INTO CountryLanguage VALUES ('NGA','Joruba','F',21.4);
+INSERT INTO CountryLanguage VALUES ('NIU','Niue','F',0.0);
+INSERT INTO CountryLanguage VALUES ('NFK','English','T',0.0);
+INSERT INTO CountryLanguage VALUES ('NOR','Norwegian','T',96.6);
+INSERT INTO CountryLanguage VALUES ('CIV','Akan','F',30.0);
+INSERT INTO CountryLanguage VALUES ('OMN','Arabic','T',76.7);
+INSERT INTO CountryLanguage VALUES ('PAK','Punjabi','F',48.2);
+INSERT INTO CountryLanguage VALUES ('PLW','Palau','T',82.2);
+INSERT INTO CountryLanguage VALUES ('PAN','Spanish','T',76.8);
+INSERT INTO CountryLanguage VALUES ('PNG','Papuan Languages','F',78.1);
+INSERT INTO CountryLanguage VALUES ('PRY','Spanish','T',55.1);
+INSERT INTO CountryLanguage VALUES ('PER','Spanish','T',79.8);
+INSERT INTO CountryLanguage VALUES ('PCN','Pitcairnese','F',0.0);
+INSERT INTO CountryLanguage VALUES ('MNP','Philippene Languages','F',34.1);
+INSERT INTO CountryLanguage VALUES ('PRT','Portuguese','T',99.0);
+INSERT INTO CountryLanguage VALUES ('PRI','Spanish','T',51.3);
+INSERT INTO CountryLanguage VALUES ('POL','Polish','T',97.6);
+INSERT INTO CountryLanguage VALUES ('GNQ','Fang','F',84.8);
+INSERT INTO CountryLanguage VALUES ('QAT','Arabic','T',40.7);
+INSERT INTO CountryLanguage VALUES ('FRA','French','T',93.6);
+INSERT INTO CountryLanguage VALUES ('GUF','Creole French','F',94.3);
+INSERT INTO CountryLanguage VALUES ('PYF','Tahitian','F',46.4);
+INSERT INTO CountryLanguage VALUES ('REU','Creole French','F',91.5);
+INSERT INTO CountryLanguage VALUES ('ROM','Romanian','T',90.7);
+INSERT INTO CountryLanguage VALUES ('RWA','Rwanda','T',100.0);
+INSERT INTO CountryLanguage VALUES ('SWE','Swedish','T',89.5);
+INSERT INTO CountryLanguage VALUES ('SHN','English','T',0.0);
+INSERT INTO CountryLanguage VALUES ('KNA','Creole English','F',100.0);
+INSERT INTO CountryLanguage VALUES ('LCA','Creole French','F',80.0);
+INSERT INTO CountryLanguage VALUES ('VCT','Creole English','F',99.1);
+INSERT INTO CountryLanguage VALUES ('SPM','French','T',0.0);
+INSERT INTO CountryLanguage VALUES ('DEU','German','T',91.3);
+INSERT INTO CountryLanguage VALUES ('SLB','Malenasian Languages','F',85.6);
+INSERT INTO CountryLanguage VALUES ('ZMB','Bemba','F',29.7);
+INSERT INTO CountryLanguage VALUES ('WSM','Samoan-English','F',52.0);
+INSERT INTO CountryLanguage VALUES ('SMR','Italian','T',100.0);
+INSERT INTO CountryLanguage VALUES ('STP','Crioulo','F',86.3);
+INSERT INTO CountryLanguage VALUES ('SAU','Arabic','T',95.0);
+INSERT INTO CountryLanguage VALUES ('SEN','Wolof','T',48.1);
+INSERT INTO CountryLanguage VALUES ('SYC','Seselwa','F',91.3);
+INSERT INTO CountryLanguage VALUES ('SLE','Mende','F',34.8);
+INSERT INTO CountryLanguage VALUES ('SGP','Chinese','T',77.1);
+INSERT INTO CountryLanguage VALUES ('SVK','Slovak','T',85.6);
+INSERT INTO CountryLanguage VALUES ('SVN','Slovene','T',87.9);
+INSERT INTO CountryLanguage VALUES ('SOM','Somali','T',98.3);
+INSERT INTO CountryLanguage VALUES ('LKA','Singali','T',60.3);
+INSERT INTO CountryLanguage VALUES ('SDN','Arabic','T',49.4);
+INSERT INTO CountryLanguage VALUES ('FIN','Finnish','T',92.7);
+INSERT INTO CountryLanguage VALUES ('SUR','Sranantonga','F',81.0);
+INSERT INTO CountryLanguage VALUES ('SWZ','Swazi','T',89.9);
+INSERT INTO CountryLanguage VALUES ('CHE','German','T',63.6);
+INSERT INTO CountryLanguage VALUES ('SYR','Arabic','T',90.0);
+INSERT INTO CountryLanguage VALUES ('TJK','Tadzhik','T',62.2);
+INSERT INTO CountryLanguage VALUES ('TWN','Min','F',66.7);
+INSERT INTO CountryLanguage VALUES ('TZA','Nyamwesi','F',21.1);
+INSERT INTO CountryLanguage VALUES ('DNK','Danish','T',93.5);
+INSERT INTO CountryLanguage VALUES ('THA','Thai','T',52.6);
+INSERT INTO CountryLanguage VALUES ('TGO','Ewe','T',23.2);
+INSERT INTO CountryLanguage VALUES ('TKL','Tokelau','F',0.0);
+INSERT INTO CountryLanguage VALUES ('TON','Tongan','T',98.3);
+INSERT INTO CountryLanguage VALUES ('TTO','English','F',93.5);
+INSERT INTO CountryLanguage VALUES ('TCD','Sara','F',27.7);
+INSERT INTO CountryLanguage VALUES ('CZE','Czech','T',81.2);
+INSERT INTO CountryLanguage VALUES ('TUN','Arabic','T',69.9);
+INSERT INTO CountryLanguage VALUES ('TUR','Turkish','T',87.6);
+INSERT INTO CountryLanguage VALUES ('TKM','Turkmenian','T',76.7);
+INSERT INTO CountryLanguage VALUES ('TCA','English','T',0.0);
+INSERT INTO CountryLanguage VALUES ('TUV','Tuvalu','T',92.5);
+INSERT INTO CountryLanguage VALUES ('UGA','Ganda','F',18.1);
+INSERT INTO CountryLanguage VALUES ('UKR','Ukrainian','T',64.7);
+INSERT INTO CountryLanguage VALUES ('HUN','Hungarian','T',98.5);
+INSERT INTO CountryLanguage VALUES ('URY','Spanish','T',95.7);
+INSERT INTO CountryLanguage VALUES ('NCL','Malenasian Languages','F',45.4);
+INSERT INTO CountryLanguage VALUES ('NZL','English','T',87.0);
+INSERT INTO CountryLanguage VALUES ('UZB','Uzbek','T',72.6);
+INSERT INTO CountryLanguage VALUES ('BLR','Belorussian','T',65.6);
+INSERT INTO CountryLanguage VALUES ('WLF','Wallis','F',0.0);
+INSERT INTO CountryLanguage VALUES ('VUT','Bislama','T',56.6);
+INSERT INTO CountryLanguage VALUES ('VAT','Italian','T',0.0);
+INSERT INTO CountryLanguage VALUES ('VEN','Spanish','T',96.9);
+INSERT INTO CountryLanguage VALUES ('RUS','Russian','T',86.6);
+INSERT INTO CountryLanguage VALUES ('VNM','Vietnamese','T',86.8);
+INSERT INTO CountryLanguage VALUES ('EST','Estonian','T',65.3);
+INSERT INTO CountryLanguage VALUES ('USA','English','T',86.2);
+INSERT INTO CountryLanguage VALUES ('VIR','English','T',81.7);
+INSERT INTO CountryLanguage VALUES ('UMI','English','T',0.0);
+INSERT INTO CountryLanguage VALUES ('ZWE','Shona','F',72.1);
+INSERT INTO CountryLanguage VALUES ('PSE','Arabic','F',95.9);
+INSERT INTO CountryLanguage VALUES ('AFG','Dari','T',32.1);
+INSERT INTO CountryLanguage VALUES ('NLD','Fries','F',3.7);
+INSERT INTO CountryLanguage VALUES ('ANT','English','F',7.8);
+INSERT INTO CountryLanguage VALUES ('ALB','Greek','F',1.8);
+INSERT INTO CountryLanguage VALUES ('DZA','Berberi','F',14.0);
+INSERT INTO CountryLanguage VALUES ('ASM','English','T',3.1);
+INSERT INTO CountryLanguage VALUES ('AND','Catalan','T',32.3);
+INSERT INTO CountryLanguage VALUES ('AGO','Mbundu','F',21.6);
+INSERT INTO CountryLanguage VALUES ('ATG','English','T',0.0);
+INSERT INTO CountryLanguage VALUES ('ARE','Hindi','F',0.0);
+INSERT INTO CountryLanguage VALUES ('ARG','Italian','F',1.7);
+INSERT INTO CountryLanguage VALUES ('ARM','Azerbaijani','F',2.6);
+INSERT INTO CountryLanguage VALUES ('ABW','English','F',9.5);
+INSERT INTO CountryLanguage VALUES ('AUS','Italian','F',2.2);
+INSERT INTO CountryLanguage VALUES ('AZE','Russian','F',3.0);
+INSERT INTO CountryLanguage VALUES ('BHS','Creole French','F',10.3);
+INSERT INTO CountryLanguage VALUES ('BHR','English','F',0.0);
+INSERT INTO CountryLanguage VALUES ('BGD','Chakma','F',0.4);
+INSERT INTO CountryLanguage VALUES ('BRB','English','T',0.0);
+INSERT INTO CountryLanguage VALUES ('BEL','French','T',32.6);
+INSERT INTO CountryLanguage VALUES ('BLZ','Spanish','F',31.6);
+INSERT INTO CountryLanguage VALUES ('BEN','Joruba','F',12.2);
+INSERT INTO CountryLanguage VALUES ('BTN','Nepali','F',34.8);
+INSERT INTO CountryLanguage VALUES ('BOL','Ketšua','T',8.1);
+INSERT INTO CountryLanguage VALUES ('BWA','Shona','F',12.3);
+INSERT INTO CountryLanguage VALUES ('BRA','German','F',0.5);
+INSERT INTO CountryLanguage VALUES ('GBR','Kymri','F',0.9);
+INSERT INTO CountryLanguage VALUES ('BRN','Malay-English','F',28.8);
+INSERT INTO CountryLanguage VALUES ('BGR','Turkish','F',9.4);
+INSERT INTO CountryLanguage VALUES ('BFA','Ful','F',9.7);
+INSERT INTO CountryLanguage VALUES ('BDI','French','T',0.0);
+INSERT INTO CountryLanguage VALUES ('CHL','Araucan','F',9.6);
+INSERT INTO CountryLanguage VALUES ('COK','English','F',0.0);
+INSERT INTO CountryLanguage VALUES ('CRI','Creole English','F',2.0);
+INSERT INTO CountryLanguage VALUES ('DJI','Afar','F',34.8);
+INSERT INTO CountryLanguage VALUES ('DMA','Creole French','F',0.0);
+INSERT INTO CountryLanguage VALUES ('DOM','Creole French','F',2.0);
+INSERT INTO CountryLanguage VALUES ('ECU','Ketšua','F',7.0);
+INSERT INTO CountryLanguage VALUES ('EGY','Sinaberberi','F',0.0);
+INSERT INTO CountryLanguage VALUES ('SLV','Nahua','F',0.0);
+INSERT INTO CountryLanguage VALUES ('ERI','Tigre','F',31.7);
+INSERT INTO CountryLanguage VALUES ('ESP','Catalan','F',16.9);
+INSERT INTO CountryLanguage VALUES ('ZAF','Xhosa','T',17.7);
+INSERT INTO CountryLanguage VALUES ('ETH','Amhara','F',30.0);
+INSERT INTO CountryLanguage VALUES ('FJI','Hindi','F',43.7);
+INSERT INTO CountryLanguage VALUES ('PHL','Cebuano','F',23.3);
+INSERT INTO CountryLanguage VALUES ('FRO','Danish','T',0.0);
+INSERT INTO CountryLanguage VALUES ('GAB','Punu-sira-nzebi','F',17.1);
+INSERT INTO CountryLanguage VALUES ('GMB','Ful','F',16.2);
+INSERT INTO CountryLanguage VALUES ('GEO','Russian','F',8.8);
+INSERT INTO CountryLanguage VALUES ('GHA','Mossi','F',15.8);
+INSERT INTO CountryLanguage VALUES ('GIB','Arabic','F',7.4);
+INSERT INTO CountryLanguage VALUES ('GRL','Danish','T',12.5);
+INSERT INTO CountryLanguage VALUES ('GLP','French','T',0.0);
+INSERT INTO CountryLanguage VALUES ('GUM','Chamorro','T',29.6);
+INSERT INTO CountryLanguage VALUES ('GTM','Quiché','F',10.1);
+INSERT INTO CountryLanguage VALUES ('GIN','Malinke','F',23.2);
+INSERT INTO CountryLanguage VALUES ('GNB','Ful','F',16.6);
+INSERT INTO CountryLanguage VALUES ('GUY','Caribbean','F',2.2);
+INSERT INTO CountryLanguage VALUES ('HTI','French','T',0.0);
+INSERT INTO CountryLanguage VALUES ('HND','Garifuna','F',1.3);
+INSERT INTO CountryLanguage VALUES ('HKG','English','T',2.2);
+INSERT INTO CountryLanguage VALUES ('SJM','Russian','F',0.0);
+INSERT INTO CountryLanguage VALUES ('IDN','Sunda','F',15.8);
+INSERT INTO CountryLanguage VALUES ('IND','Bengali','F',8.2);
+INSERT INTO CountryLanguage VALUES ('IRQ','Kurdish','F',19.0);
+INSERT INTO CountryLanguage VALUES ('IRN','Azerbaijani','F',16.8);
+INSERT INTO CountryLanguage VALUES ('IRL','Irish','T',1.6);
+INSERT INTO CountryLanguage VALUES ('ISL','English','F',0.0);
+INSERT INTO CountryLanguage VALUES ('ISR','Arabic','T',18.0);
+INSERT INTO CountryLanguage VALUES ('ITA','Sardinian','F',2.7);
+INSERT INTO CountryLanguage VALUES ('TMP','Portuguese','T',0.0);
+INSERT INTO CountryLanguage VALUES ('AUT','Serbo-Croatian','F',2.2);
+INSERT INTO CountryLanguage VALUES ('JAM','Hindi','F',1.9);
+INSERT INTO CountryLanguage VALUES ('JPN','Korean','F',0.5);
+INSERT INTO CountryLanguage VALUES ('YEM','Soqutri','F',0.0);
+INSERT INTO CountryLanguage VALUES ('JOR','Circassian','F',1.0);
+INSERT INTO CountryLanguage VALUES ('CXR','English','T',0.0);
+INSERT INTO CountryLanguage VALUES ('YUG','Albaniana','F',16.5);
+INSERT INTO CountryLanguage VALUES ('KHM','Vietnamese','F',5.5);
+INSERT INTO CountryLanguage VALUES ('CMR','Bamileke-bamum','F',18.6);
+INSERT INTO CountryLanguage VALUES ('CAN','French','T',23.4);
+INSERT INTO CountryLanguage VALUES ('CPV','Portuguese','T',0.0);
+INSERT INTO CountryLanguage VALUES ('KAZ','Russian','F',34.7);
+INSERT INTO CountryLanguage VALUES ('KEN','Luhya','F',13.8);
+INSERT INTO CountryLanguage VALUES ('CAF','Banda','F',23.5);
+INSERT INTO CountryLanguage VALUES ('CHN','Zhuang','F',1.4);
+INSERT INTO CountryLanguage VALUES ('KGZ','Russian','T',16.2);
+INSERT INTO CountryLanguage VALUES ('KIR','Tuvalu','F',0.5);
+INSERT INTO CountryLanguage VALUES ('COL','Chibcha','F',0.4);
+INSERT INTO CountryLanguage VALUES ('COM','Comorian-French','F',12.9);
+INSERT INTO CountryLanguage VALUES ('COG','Teke','F',17.3);
+INSERT INTO CountryLanguage VALUES ('COD','Kongo','F',16.0);
+INSERT INTO CountryLanguage VALUES ('CCK','English','T',0.0);
+INSERT INTO CountryLanguage VALUES ('PRK','Chinese','F',0.1);
+INSERT INTO CountryLanguage VALUES ('KOR','Chinese','F',0.1);
+INSERT INTO CountryLanguage VALUES ('GRC','Turkish','F',0.9);
+INSERT INTO CountryLanguage VALUES ('HRV','Slovene','F',0.0);
+INSERT INTO CountryLanguage VALUES ('KWT','English','F',0.0);
+INSERT INTO CountryLanguage VALUES ('CYP','Turkish','T',22.4);
+INSERT INTO CountryLanguage VALUES ('LAO','Mon-khmer','F',16.5);
+INSERT INTO CountryLanguage VALUES ('LVA','Russian','F',32.5);
+INSERT INTO CountryLanguage VALUES ('LSO','Zulu','F',15.0);
+INSERT INTO CountryLanguage VALUES ('LBN','Armenian','F',5.9);
+INSERT INTO CountryLanguage VALUES ('LBR','Bassa','F',13.7);
+INSERT INTO CountryLanguage VALUES ('LBY','Berberi','F',1.0);
+INSERT INTO CountryLanguage VALUES ('LIE','Italian','F',2.5);
+INSERT INTO CountryLanguage VALUES ('LTU','Russian','F',8.1);
+INSERT INTO CountryLanguage VALUES ('LUX','Portuguese','F',13.0);
+INSERT INTO CountryLanguage VALUES ('MAC','Portuguese','T',2.3);
+INSERT INTO CountryLanguage VALUES ('MDG','French','T',0.0);
+INSERT INTO CountryLanguage VALUES ('MKD','Albaniana','F',22.9);
+INSERT INTO CountryLanguage VALUES ('MWI','Lomwe','F',18.4);
+INSERT INTO CountryLanguage VALUES ('MDV','English','F',0.0);
+INSERT INTO CountryLanguage VALUES ('MYS','Chinese','F',9.0);
+INSERT INTO CountryLanguage VALUES ('MLI','Ful','F',13.9);
+INSERT INTO CountryLanguage VALUES ('MLT','English','T',2.1);
+INSERT INTO CountryLanguage VALUES ('MAR','Berberi','F',33.0);
+INSERT INTO CountryLanguage VALUES ('MHL','English','T',0.0);
+INSERT INTO CountryLanguage VALUES ('MTQ','French','T',0.0);
+INSERT INTO CountryLanguage VALUES ('MRT','Wolof','F',6.6);
+INSERT INTO CountryLanguage VALUES ('MUS','Bhojpuri','F',21.1);
+INSERT INTO CountryLanguage VALUES ('MYT','French','T',20.3);
+INSERT INTO CountryLanguage VALUES ('MEX','Náhuatl','F',1.8);
+INSERT INTO CountryLanguage VALUES ('FSM','Pohnpei','F',23.8);
+INSERT INTO CountryLanguage VALUES ('MDA','Russian','F',23.2);
+INSERT INTO CountryLanguage VALUES ('MCO','Monegasque','F',16.1);
+INSERT INTO CountryLanguage VALUES ('MNG','Kazakh','F',5.9);
+INSERT INTO CountryLanguage VALUES ('MOZ','Tsonga','F',12.4);
+INSERT INTO CountryLanguage VALUES ('MMR','Shan','F',8.5);
+INSERT INTO CountryLanguage VALUES ('NAM','Nama','F',12.4);
+INSERT INTO CountryLanguage VALUES ('NRU','Kiribati','F',17.9);
+INSERT INTO CountryLanguage VALUES ('NPL','Maithili','F',11.9);
+INSERT INTO CountryLanguage VALUES ('NIC','Miskito','F',1.6);
+INSERT INTO CountryLanguage VALUES ('NER','Songhai-zerma','F',21.2);
+INSERT INTO CountryLanguage VALUES ('NGA','Hausa','F',21.1);
+INSERT INTO CountryLanguage VALUES ('NIU','English','T',0.0);
+INSERT INTO CountryLanguage VALUES ('NOR','English','F',0.5);
+INSERT INTO CountryLanguage VALUES ('CIV','Gur','F',11.7);
+INSERT INTO CountryLanguage VALUES ('OMN','Balochi','F',0.0);
+INSERT INTO CountryLanguage VALUES ('PAK','Pashto','F',13.1);
+INSERT INTO CountryLanguage VALUES ('PLW','Philippene Languages','F',9.2);
+INSERT INTO CountryLanguage VALUES ('PAN','Creole English','F',14.0);
+INSERT INTO CountryLanguage VALUES ('PNG','Malenasian Languages','F',20.0);
+INSERT INTO CountryLanguage VALUES ('PRY','Guaraní','T',40.1);
+INSERT INTO CountryLanguage VALUES ('PER','Ketšua','T',16.4);
+INSERT INTO CountryLanguage VALUES ('MNP','Chamorro','F',30.0);
+INSERT INTO CountryLanguage VALUES ('PRI','English','F',47.4);
+INSERT INTO CountryLanguage VALUES ('POL','German','F',1.3);
+INSERT INTO CountryLanguage VALUES ('GNQ','Bubi','F',8.7);
+INSERT INTO CountryLanguage VALUES ('QAT','Urdu','F',0.0);
+INSERT INTO CountryLanguage VALUES ('FRA','Arabic','F',2.5);
+INSERT INTO CountryLanguage VALUES ('GUF','Indian Languages','F',1.9);
+INSERT INTO CountryLanguage VALUES ('PYF','French','T',40.8);
+INSERT INTO CountryLanguage VALUES ('REU','Chinese','F',2.8);
+INSERT INTO CountryLanguage VALUES ('ROM','Hungarian','F',7.2);
+INSERT INTO CountryLanguage VALUES ('RWA','French','T',0.0);
+INSERT INTO CountryLanguage VALUES ('SWE','Finnish','F',2.4);
+INSERT INTO CountryLanguage VALUES ('KNA','English','T',0.0);
+INSERT INTO CountryLanguage VALUES ('LCA','English','T',20.0);
+INSERT INTO CountryLanguage VALUES ('VCT','English','T',0.0);
+INSERT INTO CountryLanguage VALUES ('DEU','Turkish','F',2.6);
+INSERT INTO CountryLanguage VALUES ('SLB','Papuan Languages','F',8.6);
+INSERT INTO CountryLanguage VALUES ('ZMB','Tongan','F',11.0);
+INSERT INTO CountryLanguage VALUES ('WSM','Samoan','T',47.5);
+INSERT INTO CountryLanguage VALUES ('STP','French','F',0.7);
+INSERT INTO CountryLanguage VALUES ('SEN','Ful','F',21.7);
+INSERT INTO CountryLanguage VALUES ('SYC','English','T',3.8);
+INSERT INTO CountryLanguage VALUES ('SLE','Temne','F',31.8);
+INSERT INTO CountryLanguage VALUES ('SGP','Malay','T',14.1);
+INSERT INTO CountryLanguage VALUES ('SVK','Hungarian','F',10.5);
+INSERT INTO CountryLanguage VALUES ('SVN','Serbo-Croatian','F',7.9);
+INSERT INTO CountryLanguage VALUES ('SOM','Arabic','T',0.0);
+INSERT INTO CountryLanguage VALUES ('LKA','Tamil','T',19.6);
+INSERT INTO CountryLanguage VALUES ('SDN','Dinka','F',11.5);
+INSERT INTO CountryLanguage VALUES ('FIN','Swedish','T',5.7);
+INSERT INTO CountryLanguage VALUES ('SUR','Hindi','F',0.0);
+INSERT INTO CountryLanguage VALUES ('SWZ','Zulu','F',2.0);
+INSERT INTO CountryLanguage VALUES ('CHE','French','T',19.2);
+INSERT INTO CountryLanguage VALUES ('SYR','Kurdish','F',9.0);
+INSERT INTO CountryLanguage VALUES ('TJK','Uzbek','F',23.2);
+INSERT INTO CountryLanguage VALUES ('TWN','Mandarin Chinese','T',20.1);
+INSERT INTO CountryLanguage VALUES ('TZA','Swahili','T',8.8);
+INSERT INTO CountryLanguage VALUES ('DNK','Turkish','F',0.8);
+INSERT INTO CountryLanguage VALUES ('THA','Lao','F',26.9);
+INSERT INTO CountryLanguage VALUES ('TGO','Kabyé','T',13.8);
+INSERT INTO CountryLanguage VALUES ('TKL','English','T',0.0);
+INSERT INTO CountryLanguage VALUES ('TON','English','T',0.0);
+INSERT INTO CountryLanguage VALUES ('TTO','Hindi','F',3.4);
+INSERT INTO CountryLanguage VALUES ('TCD','Arabic','T',12.3);
+INSERT INTO CountryLanguage VALUES ('CZE','Moravian','F',12.9);
+INSERT INTO CountryLanguage VALUES ('TUN','Arabic-French','F',26.3);
+INSERT INTO CountryLanguage VALUES ('TUR','Kurdish','F',10.6);
+INSERT INTO CountryLanguage VALUES ('TKM','Uzbek','F',9.2);
+INSERT INTO CountryLanguage VALUES ('TUV','Kiribati','F',7.5);
+INSERT INTO CountryLanguage VALUES ('UGA','Nkole','F',10.7);
+INSERT INTO CountryLanguage VALUES ('UKR','Russian','F',32.9);
+INSERT INTO CountryLanguage VALUES ('HUN','Romani','F',0.5);
+INSERT INTO CountryLanguage VALUES ('NCL','French','T',34.3);
+INSERT INTO CountryLanguage VALUES ('NZL','Maori','F',4.3);
+INSERT INTO CountryLanguage VALUES ('UZB','Russian','F',10.9);
+INSERT INTO CountryLanguage VALUES ('BLR','Russian','T',32.0);
+INSERT INTO CountryLanguage VALUES ('WLF','Futuna','F',0.0);
+INSERT INTO CountryLanguage VALUES ('VUT','English','T',28.3);
+INSERT INTO CountryLanguage VALUES ('VEN','Goajiro','F',0.4);
+INSERT INTO CountryLanguage VALUES ('RUS','Tatar','F',3.2);
+INSERT INTO CountryLanguage VALUES ('VNM','Tho','F',1.8);
+INSERT INTO CountryLanguage VALUES ('EST','Russian','F',27.8);
+INSERT INTO CountryLanguage VALUES ('USA','Spanish','F',7.5);
+INSERT INTO CountryLanguage VALUES ('VIR','Spanish','F',13.3);
+INSERT INTO CountryLanguage VALUES ('ZWE','Ndebele','F',16.2);
+INSERT INTO CountryLanguage VALUES ('PSE','Hebrew','F',4.1);
+INSERT INTO CountryLanguage VALUES ('AFG','Uzbek','F',8.8);
+INSERT INTO CountryLanguage VALUES ('NLD','Arabic','F',0.9);
+INSERT INTO CountryLanguage VALUES ('ANT','Dutch','T',0.0);
+INSERT INTO CountryLanguage VALUES ('ALB','Macedonian','F',0.1);
+INSERT INTO CountryLanguage VALUES ('ASM','Tongan','F',3.1);
+INSERT INTO CountryLanguage VALUES ('AND','Portuguese','F',10.8);
+INSERT INTO CountryLanguage VALUES ('AGO','Kongo','F',13.2);
+INSERT INTO CountryLanguage VALUES ('ARG','Indian Languages','F',0.3);
+INSERT INTO CountryLanguage VALUES ('ABW','Spanish','F',7.4);
+INSERT INTO CountryLanguage VALUES ('AUS','Greek','F',1.6);
+INSERT INTO CountryLanguage VALUES ('AZE','Lezgian','F',2.3);
+INSERT INTO CountryLanguage VALUES ('BGD','Marma','F',0.2);
+INSERT INTO CountryLanguage VALUES ('BEL','Italian','F',2.4);
+INSERT INTO CountryLanguage VALUES ('BLZ','Maya Languages','F',9.6);
+INSERT INTO CountryLanguage VALUES ('BEN','Adja','F',11.1);
+INSERT INTO CountryLanguage VALUES ('BTN','Asami','F',15.2);
+INSERT INTO CountryLanguage VALUES ('BOL','Aimará','T',3.2);
+INSERT INTO CountryLanguage VALUES ('BWA','San','F',3.5);
+INSERT INTO CountryLanguage VALUES ('BRA','Italian','F',0.4);
+INSERT INTO CountryLanguage VALUES ('GBR','Gaeli','F',0.1);
+INSERT INTO CountryLanguage VALUES ('BRN','Chinese','F',9.3);
+INSERT INTO CountryLanguage VALUES ('BGR','Romani','F',3.7);
+INSERT INTO CountryLanguage VALUES ('BFA','Gurma','F',5.7);
+INSERT INTO CountryLanguage VALUES ('BDI','Swahili','F',0.0);
+INSERT INTO CountryLanguage VALUES ('CHL','Aimará','F',0.5);
+INSERT INTO CountryLanguage VALUES ('CRI','Chibcha','F',0.3);
+INSERT INTO CountryLanguage VALUES ('DJI','Arabic','T',10.6);
+INSERT INTO CountryLanguage VALUES ('ERI','Afar','F',4.3);
+INSERT INTO CountryLanguage VALUES ('ESP','Galecian','F',6.4);
+INSERT INTO CountryLanguage VALUES ('ZAF','Afrikaans','T',14.3);
+INSERT INTO CountryLanguage VALUES ('ETH','Tigrinja','F',7.2);
+INSERT INTO CountryLanguage VALUES ('PHL','Ilocano','F',9.3);
+INSERT INTO CountryLanguage VALUES ('GAB','Mpongwe','F',14.6);
+INSERT INTO CountryLanguage VALUES ('GMB','Wolof','F',12.6);
+INSERT INTO CountryLanguage VALUES ('GEO','Armenian','F',6.8);
+INSERT INTO CountryLanguage VALUES ('GHA','Ewe','F',11.9);
+INSERT INTO CountryLanguage VALUES ('GUM','Philippene Languages','F',19.7);
+INSERT INTO CountryLanguage VALUES ('GTM','Cakchiquel','F',8.9);
+INSERT INTO CountryLanguage VALUES ('GIN','Susu','F',11.0);
+INSERT INTO CountryLanguage VALUES ('GNB','Balante','F',14.6);
+INSERT INTO CountryLanguage VALUES ('GUY','Arawakan','F',1.4);
+INSERT INTO CountryLanguage VALUES ('HND','Creole English','F',0.2);
+INSERT INTO CountryLanguage VALUES ('HKG','Fukien','F',1.9);
+INSERT INTO CountryLanguage VALUES ('IDN','Malay','T',12.1);
+INSERT INTO CountryLanguage VALUES ('IND','Telugu','F',7.8);
+INSERT INTO CountryLanguage VALUES ('IRQ','Azerbaijani','F',1.7);
+INSERT INTO CountryLanguage VALUES ('IRN','Kurdish','F',9.1);
+INSERT INTO CountryLanguage VALUES ('ISR','Russian','F',8.9);
+INSERT INTO CountryLanguage VALUES ('ITA','Friuli','F',1.2);
+INSERT INTO CountryLanguage VALUES ('AUT','Turkish','F',1.5);
+INSERT INTO CountryLanguage VALUES ('JPN','Chinese','F',0.2);
+INSERT INTO CountryLanguage VALUES ('JOR','Armenian','F',1.0);
+INSERT INTO CountryLanguage VALUES ('YUG','Hungarian','F',3.4);
+INSERT INTO CountryLanguage VALUES ('KHM','Chinese','F',3.1);
+INSERT INTO CountryLanguage VALUES ('CMR','Duala','F',10.9);
+INSERT INTO CountryLanguage VALUES ('CAN','Chinese','F',2.5);
+INSERT INTO CountryLanguage VALUES ('KAZ','Ukrainian','F',5.0);
+INSERT INTO CountryLanguage VALUES ('KEN','Luo','F',12.8);
+INSERT INTO CountryLanguage VALUES ('CAF','Mandjia','F',14.8);
+INSERT INTO CountryLanguage VALUES ('CHN','Mantšu','F',0.9);
+INSERT INTO CountryLanguage VALUES ('KGZ','Uzbek','F',14.1);
+INSERT INTO CountryLanguage VALUES ('COL','Creole English','F',0.1);
+INSERT INTO CountryLanguage VALUES ('COM','Comorian-madagassi','F',5.5);
+INSERT INTO CountryLanguage VALUES ('COG','Mboshi','F',11.4);
+INSERT INTO CountryLanguage VALUES ('COD','Mongo','F',13.5);
+INSERT INTO CountryLanguage VALUES ('LAO','Thai','F',7.8);
+INSERT INTO CountryLanguage VALUES ('LVA','Belorussian','F',4.1);
+INSERT INTO CountryLanguage VALUES ('LSO','English','T',0.0);
+INSERT INTO CountryLanguage VALUES ('LBN','French','F',0.0);
+INSERT INTO CountryLanguage VALUES ('LBR','Grebo','F',8.9);
+INSERT INTO CountryLanguage VALUES ('LIE','Turkish','F',2.5);
+INSERT INTO CountryLanguage VALUES ('LTU','Polish','F',7.0);
+INSERT INTO CountryLanguage VALUES ('LUX','Italian','F',4.6);
+INSERT INTO CountryLanguage VALUES ('MAC','Mandarin Chinese','F',1.2);
+INSERT INTO CountryLanguage VALUES ('MKD','Turkish','F',4.0);
+INSERT INTO CountryLanguage VALUES ('MWI','Yao','F',13.2);
+INSERT INTO CountryLanguage VALUES ('MYS','Tamil','F',3.9);
+INSERT INTO CountryLanguage VALUES ('MLI','Senufo and Minianka','F',12.0);
+INSERT INTO CountryLanguage VALUES ('MRT','Tukulor','F',5.4);
+INSERT INTO CountryLanguage VALUES ('MUS','French','F',3.4);
+INSERT INTO CountryLanguage VALUES ('MYT','Malagasy','F',16.1);
+INSERT INTO CountryLanguage VALUES ('MEX','Yucatec','F',1.1);
+INSERT INTO CountryLanguage VALUES ('FSM','Mortlock','F',7.6);
+INSERT INTO CountryLanguage VALUES ('MDA','Ukrainian','F',8.6);
+INSERT INTO CountryLanguage VALUES ('MCO','Italian','F',16.1);
+INSERT INTO CountryLanguage VALUES ('MNG','Dorbet','F',2.7);
+INSERT INTO CountryLanguage VALUES ('MOZ','Sena','F',9.4);
+INSERT INTO CountryLanguage VALUES ('MMR','Karen','F',6.2);
+INSERT INTO CountryLanguage VALUES ('NAM','Kavango','F',9.7);
+INSERT INTO CountryLanguage VALUES ('NRU','Chinese','F',8.5);
+INSERT INTO CountryLanguage VALUES ('NPL','Bhojpuri','F',7.5);
+INSERT INTO CountryLanguage VALUES ('NIC','Creole English','F',0.5);
+INSERT INTO CountryLanguage VALUES ('NER','Tamashek','F',10.4);
+INSERT INTO CountryLanguage VALUES ('NGA','Ibo','F',18.1);
+INSERT INTO CountryLanguage VALUES ('NOR','Danish','F',0.4);
+INSERT INTO CountryLanguage VALUES ('CIV','Malinke','F',11.4);
+INSERT INTO CountryLanguage VALUES ('PAK','Sindhi','F',11.8);
+INSERT INTO CountryLanguage VALUES ('PLW','English','T',3.2);
+INSERT INTO CountryLanguage VALUES ('PAN','Guaymí','F',5.3);
+INSERT INTO CountryLanguage VALUES ('PRY','Portuguese','F',3.2);
+INSERT INTO CountryLanguage VALUES ('PER','Aimará','T',2.3);
+INSERT INTO CountryLanguage VALUES ('MNP','Chinese','F',7.1);
+INSERT INTO CountryLanguage VALUES ('POL','Ukrainian','F',0.6);
+INSERT INTO CountryLanguage VALUES ('FRA','Portuguese','F',1.2);
+INSERT INTO CountryLanguage VALUES ('PYF','Chinese','F',2.9);
+INSERT INTO CountryLanguage VALUES ('REU','Comorian','F',2.8);
+INSERT INTO CountryLanguage VALUES ('ROM','Romani','T',0.7);
+INSERT INTO CountryLanguage VALUES ('SWE','Southern Slavic Languages','F',1.3);
+INSERT INTO CountryLanguage VALUES ('DEU','Southern Slavic Languages','F',1.4);
+INSERT INTO CountryLanguage VALUES ('SLB','Polynesian Languages','F',3.8);
+INSERT INTO CountryLanguage VALUES ('ZMB','Nyanja','F',7.8);
+INSERT INTO CountryLanguage VALUES ('WSM','English','T',0.6);
+INSERT INTO CountryLanguage VALUES ('SEN','Serer','F',12.5);
+INSERT INTO CountryLanguage VALUES ('SYC','French','T',1.3);
+INSERT INTO CountryLanguage VALUES ('SLE','Limba','F',8.3);
+INSERT INTO CountryLanguage VALUES ('SGP','Tamil','T',7.4);
+INSERT INTO CountryLanguage VALUES ('SVK','Romani','F',1.7);
+INSERT INTO CountryLanguage VALUES ('SVN','Hungarian','F',0.5);
+INSERT INTO CountryLanguage VALUES ('LKA','Mixed Languages','F',19.6);
+INSERT INTO CountryLanguage VALUES ('SDN','Nubian Languages','F',8.1);
+INSERT INTO CountryLanguage VALUES ('FIN','Russian','F',0.4);
+INSERT INTO CountryLanguage VALUES ('CHE','Italian','T',7.7);
+INSERT INTO CountryLanguage VALUES ('TJK','Russian','F',9.7);
+INSERT INTO CountryLanguage VALUES ('TWN','Hakka','F',11.0);
+INSERT INTO CountryLanguage VALUES ('TZA','Hehet','F',6.9);
+INSERT INTO CountryLanguage VALUES ('DNK','Arabic','F',0.7);
+INSERT INTO CountryLanguage VALUES ('THA','Chinese','F',12.1);
+INSERT INTO CountryLanguage VALUES ('TGO','Watyi','F',10.3);
+INSERT INTO CountryLanguage VALUES ('TTO','Creole English','F',2.9);
+INSERT INTO CountryLanguage VALUES ('TCD','Mayo-kebbi','F',11.5);
+INSERT INTO CountryLanguage VALUES ('CZE','Slovak','F',3.1);
+INSERT INTO CountryLanguage VALUES ('TUN','Arabic-French-English','F',3.2);
+INSERT INTO CountryLanguage VALUES ('TUR','Arabic','F',1.4);
+INSERT INTO CountryLanguage VALUES ('TKM','Russian','F',6.7);
+INSERT INTO CountryLanguage VALUES ('TUV','English','T',0.0);
+INSERT INTO CountryLanguage VALUES ('UGA','Kiga','F',8.3);
+INSERT INTO CountryLanguage VALUES ('UKR','Romanian','F',0.7);
+INSERT INTO CountryLanguage VALUES ('HUN','German','F',0.4);
+INSERT INTO CountryLanguage VALUES ('NCL','Polynesian Languages','F',11.6);
+INSERT INTO CountryLanguage VALUES ('UZB','Tadzhik','F',4.4);
+INSERT INTO CountryLanguage VALUES ('BLR','Ukrainian','F',1.3);
+INSERT INTO CountryLanguage VALUES ('VUT','French','T',14.2);
+INSERT INTO CountryLanguage VALUES ('VEN','Warrau','F',0.1);
+INSERT INTO CountryLanguage VALUES ('RUS','Ukrainian','F',1.3);
+INSERT INTO CountryLanguage VALUES ('VNM','Thai','F',1.6);
+INSERT INTO CountryLanguage VALUES ('EST','Ukrainian','F',2.8);
+INSERT INTO CountryLanguage VALUES ('USA','French','F',0.7);
+INSERT INTO CountryLanguage VALUES ('VIR','French','F',2.5);
+INSERT INTO CountryLanguage VALUES ('ZWE','English','T',2.2);
+INSERT INTO CountryLanguage VALUES ('AFG','Turkmenian','F',1.9);
+INSERT INTO CountryLanguage VALUES ('NLD','Turkish','F',0.8);
+INSERT INTO CountryLanguage VALUES ('AND','French','F',6.2);
+INSERT INTO CountryLanguage VALUES ('AGO','Luimbe-nganguela','F',5.4);
+INSERT INTO CountryLanguage VALUES ('ABW','Dutch','T',5.3);
+INSERT INTO CountryLanguage VALUES ('AUS','Canton Chinese','F',1.1);
+INSERT INTO CountryLanguage VALUES ('AZE','Armenian','F',2.0);
+INSERT INTO CountryLanguage VALUES ('BGD','Garo','F',0.1);
+INSERT INTO CountryLanguage VALUES ('BEL','Arabic','F',1.6);
+INSERT INTO CountryLanguage VALUES ('BLZ','Garifuna','F',6.8);
+INSERT INTO CountryLanguage VALUES ('BEN','Aizo','F',8.7);
+INSERT INTO CountryLanguage VALUES ('BOL','Guaraní','F',0.1);
+INSERT INTO CountryLanguage VALUES ('BWA','Khoekhoe','F',2.5);
+INSERT INTO CountryLanguage VALUES ('BRA','Japanese','F',0.4);
+INSERT INTO CountryLanguage VALUES ('BRN','English','F',3.1);
+INSERT INTO CountryLanguage VALUES ('BGR','Macedonian','F',2.6);
+INSERT INTO CountryLanguage VALUES ('BFA','Busansi','F',3.5);
+INSERT INTO CountryLanguage VALUES ('CHL','Rapa nui','F',0.2);
+INSERT INTO CountryLanguage VALUES ('CRI','Chinese','F',0.2);
+INSERT INTO CountryLanguage VALUES ('ERI','Hadareb','F',3.8);
+INSERT INTO CountryLanguage VALUES ('ESP','Basque','F',1.6);
+INSERT INTO CountryLanguage VALUES ('ZAF','Northsotho','F',9.1);
+INSERT INTO CountryLanguage VALUES ('ETH','Gurage','F',4.7);
+INSERT INTO CountryLanguage VALUES ('PHL','Hiligaynon','F',9.1);
+INSERT INTO CountryLanguage VALUES ('GAB','Mbete','F',13.8);
+INSERT INTO CountryLanguage VALUES ('GMB','Diola','F',9.2);
+INSERT INTO CountryLanguage VALUES ('GEO','Azerbaijani','F',5.5);
+INSERT INTO CountryLanguage VALUES ('GHA','Ga-adangme','F',7.8);
+INSERT INTO CountryLanguage VALUES ('GUM','Korean','F',3.3);
+INSERT INTO CountryLanguage VALUES ('GTM','Kekchí','F',4.9);
+INSERT INTO CountryLanguage VALUES ('GIN','Kissi','F',6.0);
+INSERT INTO CountryLanguage VALUES ('GNB','Portuguese','T',8.1);
+INSERT INTO CountryLanguage VALUES ('HND','Miskito','F',0.2);
+INSERT INTO CountryLanguage VALUES ('HKG','Hakka','F',1.6);
+INSERT INTO CountryLanguage VALUES ('IDN','Madura','F',4.3);
+INSERT INTO CountryLanguage VALUES ('IND','Marathi','F',7.4);
+INSERT INTO CountryLanguage VALUES ('IRQ','Assyrian','F',0.8);
+INSERT INTO CountryLanguage VALUES ('IRN','Gilaki','F',5.3);
+INSERT INTO CountryLanguage VALUES ('ITA','French','F',0.5);
+INSERT INTO CountryLanguage VALUES ('AUT','Hungarian','F',0.4);
+INSERT INTO CountryLanguage VALUES ('JPN','English','F',0.1);
+INSERT INTO CountryLanguage VALUES ('YUG','Romani','F',1.4);
+INSERT INTO CountryLanguage VALUES ('KHM','Tšam','F',2.4);
+INSERT INTO CountryLanguage VALUES ('CMR','Ful','F',9.6);
+INSERT INTO CountryLanguage VALUES ('CAN','Italian','F',1.7);
+INSERT INTO CountryLanguage VALUES ('KAZ','German','F',3.1);
+INSERT INTO CountryLanguage VALUES ('KEN','Kamba','F',11.2);
+INSERT INTO CountryLanguage VALUES ('CAF','Ngbaka','F',7.5);
+INSERT INTO CountryLanguage VALUES ('CHN','Hui','F',0.8);
+INSERT INTO CountryLanguage VALUES ('KGZ','Ukrainian','F',1.7);
+INSERT INTO CountryLanguage VALUES ('COL','Arawakan','F',0.1);
+INSERT INTO CountryLanguage VALUES ('COM','Comorian-Arabic','F',1.6);
+INSERT INTO CountryLanguage VALUES ('COG','Mbete','F',4.8);
+INSERT INTO CountryLanguage VALUES ('COD','Rwanda','F',10.3);
+INSERT INTO CountryLanguage VALUES ('LAO','Lao-Soung','F',5.2);
+INSERT INTO CountryLanguage VALUES ('LVA','Ukrainian','F',2.9);
+INSERT INTO CountryLanguage VALUES ('LBR','Gio','F',7.9);
+INSERT INTO CountryLanguage VALUES ('LTU','Belorussian','F',1.4);
+INSERT INTO CountryLanguage VALUES ('LUX','French','T',4.2);
+INSERT INTO CountryLanguage VALUES ('MAC','English','F',0.5);
+INSERT INTO CountryLanguage VALUES ('MKD','Romani','F',2.3);
+INSERT INTO CountryLanguage VALUES ('MWI','Ngoni','F',6.7);
+INSERT INTO CountryLanguage VALUES ('MYS','Iban','F',2.8);
+INSERT INTO CountryLanguage VALUES ('MLI','Soninke','F',8.7);
+INSERT INTO CountryLanguage VALUES ('MRT','Soninke','F',2.7);
+INSERT INTO CountryLanguage VALUES ('MUS','Hindi','F',1.2);
+INSERT INTO CountryLanguage VALUES ('MEX','Zapotec','F',0.6);
+INSERT INTO CountryLanguage VALUES ('FSM','Kosrean','F',7.3);
+INSERT INTO CountryLanguage VALUES ('MDA','Gagauzi','F',3.2);
+INSERT INTO CountryLanguage VALUES ('MCO','English','F',6.5);
+INSERT INTO CountryLanguage VALUES ('MNG','Bajad','F',1.9);
+INSERT INTO CountryLanguage VALUES ('MOZ','Lomwe','F',7.8);
+INSERT INTO CountryLanguage VALUES ('MMR','Rakhine','F',4.5);
+INSERT INTO CountryLanguage VALUES ('NAM','Afrikaans','F',9.5);
+INSERT INTO CountryLanguage VALUES ('NRU','Tuvalu','F',8.5);
+INSERT INTO CountryLanguage VALUES ('NPL','Tharu','F',5.4);
+INSERT INTO CountryLanguage VALUES ('NIC','Sumo','F',0.2);
+INSERT INTO CountryLanguage VALUES ('NER','Ful','F',9.7);
+INSERT INTO CountryLanguage VALUES ('NGA','Ful','F',11.3);
+INSERT INTO CountryLanguage VALUES ('NOR','Swedish','F',0.3);
+INSERT INTO CountryLanguage VALUES ('CIV','Kru','F',10.5);
+INSERT INTO CountryLanguage VALUES ('PAK','Saraiki','F',9.8);
+INSERT INTO CountryLanguage VALUES ('PLW','Chinese','F',1.6);
+INSERT INTO CountryLanguage VALUES ('PAN','Cuna','F',2.0);
+INSERT INTO CountryLanguage VALUES ('PRY','German','F',0.9);
+INSERT INTO CountryLanguage VALUES ('MNP','Korean','F',6.5);
+INSERT INTO CountryLanguage VALUES ('POL','Belorussian','F',0.5);
+INSERT INTO CountryLanguage VALUES ('FRA','Italian','F',0.4);
+INSERT INTO CountryLanguage VALUES ('REU','Malagasy','F',1.4);
+INSERT INTO CountryLanguage VALUES ('ROM','German','F',0.4);
+INSERT INTO CountryLanguage VALUES ('SWE','Arabic','F',0.8);
+INSERT INTO CountryLanguage VALUES ('DEU','Italian','F',0.7);
+INSERT INTO CountryLanguage VALUES ('ZMB','Lozi','F',6.4);
+INSERT INTO CountryLanguage VALUES ('SEN','Diola','F',5.0);
+INSERT INTO CountryLanguage VALUES ('SLE','Kono-vai','F',5.1);
+INSERT INTO CountryLanguage VALUES ('SVK','Czech and Moravian','F',1.1);
+INSERT INTO CountryLanguage VALUES ('SDN','Beja','F',6.4);
+INSERT INTO CountryLanguage VALUES ('FIN','Estonian','F',0.2);
+INSERT INTO CountryLanguage VALUES ('CHE','Romansh','T',0.6);
+INSERT INTO CountryLanguage VALUES ('TWN','Ami','F',0.6);
+INSERT INTO CountryLanguage VALUES ('TZA','Haya','F',5.9);
+INSERT INTO CountryLanguage VALUES ('DNK','German','F',0.5);
+INSERT INTO CountryLanguage VALUES ('THA','Malay','F',3.6);
+INSERT INTO CountryLanguage VALUES ('TGO','Kotokoli','F',5.7);
+INSERT INTO CountryLanguage VALUES ('TCD','Kanem-bornu','F',9.0);
+INSERT INTO CountryLanguage VALUES ('CZE','Polish','F',0.6);
+INSERT INTO CountryLanguage VALUES ('TKM','Kazakh','F',2.0);
+INSERT INTO CountryLanguage VALUES ('UGA','Soga','F',8.2);
+INSERT INTO CountryLanguage VALUES ('UKR','Bulgariana','F',0.3);
+INSERT INTO CountryLanguage VALUES ('HUN','Serbo-Croatian','F',0.2);
+INSERT INTO CountryLanguage VALUES ('UZB','Kazakh','F',3.8);
+INSERT INTO CountryLanguage VALUES ('BLR','Polish','F',0.6);
+INSERT INTO CountryLanguage VALUES ('RUS','Chuvash','F',0.9);
+INSERT INTO CountryLanguage VALUES ('VNM','Muong','F',1.5);
+INSERT INTO CountryLanguage VALUES ('EST','Belorussian','F',1.4);
+INSERT INTO CountryLanguage VALUES ('USA','German','F',0.7);
+INSERT INTO CountryLanguage VALUES ('ZWE','Nyanja','F',2.2);
+INSERT INTO CountryLanguage VALUES ('AFG','Balochi','F',0.9);
+INSERT INTO CountryLanguage VALUES ('AGO','Nyaneka-nkhumbi','F',5.4);
+INSERT INTO CountryLanguage VALUES ('AUS','Arabic','F',1.0);
+INSERT INTO CountryLanguage VALUES ('BGD','Khasi','F',0.1);
+INSERT INTO CountryLanguage VALUES ('BEL','German','T',1.0);
+INSERT INTO CountryLanguage VALUES ('BEN','Bariba','F',8.7);
+INSERT INTO CountryLanguage VALUES ('BWA','Ndebele','F',1.3);
+INSERT INTO CountryLanguage VALUES ('BRA','Indian Languages','F',0.2);
+INSERT INTO CountryLanguage VALUES ('BFA','Dagara','F',3.1);
+INSERT INTO CountryLanguage VALUES ('ERI','Bilin','F',3.0);
+INSERT INTO CountryLanguage VALUES ('ZAF','English','T',8.5);
+INSERT INTO CountryLanguage VALUES ('ETH','Somali','F',4.1);
+INSERT INTO CountryLanguage VALUES ('PHL','Bicol','F',5.7);
+INSERT INTO CountryLanguage VALUES ('GMB','Soninke','F',7.6);
+INSERT INTO CountryLanguage VALUES ('GEO','Osseetti','F',2.4);
+INSERT INTO CountryLanguage VALUES ('GHA','Gurma','F',3.3);
+INSERT INTO CountryLanguage VALUES ('GUM','Japanese','F',2.0);
+INSERT INTO CountryLanguage VALUES ('GTM','Mam','F',2.7);
+INSERT INTO CountryLanguage VALUES ('GIN','Kpelle','F',4.6);
+INSERT INTO CountryLanguage VALUES ('GNB','Malinke','F',6.9);
+INSERT INTO CountryLanguage VALUES ('HKG','Chiu chau','F',1.4);
+INSERT INTO CountryLanguage VALUES ('IDN','Minangkabau','F',2.4);
+INSERT INTO CountryLanguage VALUES ('IND','Tamil','F',6.3);
+INSERT INTO CountryLanguage VALUES ('IRQ','Persian','F',0.8);
+INSERT INTO CountryLanguage VALUES ('IRN','Luri','F',4.3);
+INSERT INTO CountryLanguage VALUES ('ITA','German','F',0.5);
+INSERT INTO CountryLanguage VALUES ('AUT','Slovene','F',0.4);
+INSERT INTO CountryLanguage VALUES ('JPN','Philippene Languages','F',0.1);
+INSERT INTO CountryLanguage VALUES ('YUG','Slovak','F',0.7);
+INSERT INTO CountryLanguage VALUES ('CMR','Tikar','F',7.4);
+INSERT INTO CountryLanguage VALUES ('CAN','German','F',1.6);
+INSERT INTO CountryLanguage VALUES ('KAZ','Uzbek','F',2.3);
+INSERT INTO CountryLanguage VALUES ('KEN','Kalenjin','F',10.8);
+INSERT INTO CountryLanguage VALUES ('CAF','Sara','F',6.4);
+INSERT INTO CountryLanguage VALUES ('CHN','Miao','F',0.7);
+INSERT INTO CountryLanguage VALUES ('KGZ','Tatar','F',1.3);
+INSERT INTO CountryLanguage VALUES ('COL','Caribbean','F',0.1);
+INSERT INTO CountryLanguage VALUES ('COM','Comorian-Swahili','F',0.5);
+INSERT INTO CountryLanguage VALUES ('COG','Punu','F',2.9);
+INSERT INTO CountryLanguage VALUES ('COD','Zande','F',6.1);
+INSERT INTO CountryLanguage VALUES ('LVA','Polish','F',2.1);
+INSERT INTO CountryLanguage VALUES ('LBR','Kru','F',7.2);
+INSERT INTO CountryLanguage VALUES ('LTU','Ukrainian','F',1.1);
+INSERT INTO CountryLanguage VALUES ('LUX','German','T',2.3);
+INSERT INTO CountryLanguage VALUES ('MKD','Serbo-Croatian','F',2.0);
+INSERT INTO CountryLanguage VALUES ('MYS','English','F',1.6);
+INSERT INTO CountryLanguage VALUES ('MLI','Tamashek','F',7.3);
+INSERT INTO CountryLanguage VALUES ('MRT','Ful','F',1.2);
+INSERT INTO CountryLanguage VALUES ('MUS','Tamil','F',0.8);
+INSERT INTO CountryLanguage VALUES ('MEX','Mixtec','F',0.6);
+INSERT INTO CountryLanguage VALUES ('FSM','Yap','F',5.8);
+INSERT INTO CountryLanguage VALUES ('MDA','Bulgariana','F',1.6);
+INSERT INTO CountryLanguage VALUES ('MNG','Buryat','F',1.7);
+INSERT INTO CountryLanguage VALUES ('MOZ','Shona','F',6.5);
+INSERT INTO CountryLanguage VALUES ('MMR','Mon','F',2.4);
+INSERT INTO CountryLanguage VALUES ('NAM','Herero','F',8.0);
+INSERT INTO CountryLanguage VALUES ('NRU','English','T',7.5);
+INSERT INTO CountryLanguage VALUES ('NPL','Tamang','F',4.9);
+INSERT INTO CountryLanguage VALUES ('NER','Kanuri','F',4.4);
+INSERT INTO CountryLanguage VALUES ('NGA','Ibibio','F',5.6);
+INSERT INTO CountryLanguage VALUES ('NOR','Saame','F',0.0);
+INSERT INTO CountryLanguage VALUES ('CIV','[South]Mande','F',7.7);
+INSERT INTO CountryLanguage VALUES ('PAK','Urdu','T',7.6);
+INSERT INTO CountryLanguage VALUES ('PAN','Embera','F',0.6);
+INSERT INTO CountryLanguage VALUES ('MNP','English','T',4.8);
+INSERT INTO CountryLanguage VALUES ('FRA','Spanish','F',0.4);
+INSERT INTO CountryLanguage VALUES ('REU','Tamil','F',0.0);
+INSERT INTO CountryLanguage VALUES ('ROM','Ukrainian','F',0.3);
+INSERT INTO CountryLanguage VALUES ('SWE','Spanish','F',0.6);
+INSERT INTO CountryLanguage VALUES ('DEU','Greek','F',0.4);
+INSERT INTO CountryLanguage VALUES ('ZMB','Chewa','F',5.7);
+INSERT INTO CountryLanguage VALUES ('SEN','Malinke','F',3.8);
+INSERT INTO CountryLanguage VALUES ('SLE','Bullom-sherbro','F',3.8);
+INSERT INTO CountryLanguage VALUES ('SVK','Ukrainian and Russian','F',0.6);
+INSERT INTO CountryLanguage VALUES ('SDN','Nuer','F',4.9);
+INSERT INTO CountryLanguage VALUES ('FIN','Saame','F',0.0);
+INSERT INTO CountryLanguage VALUES ('TWN','Atayal','F',0.4);
+INSERT INTO CountryLanguage VALUES ('TZA','Makonde','F',5.9);
+INSERT INTO CountryLanguage VALUES ('DNK','English','F',0.3);
+INSERT INTO CountryLanguage VALUES ('THA','Khmer','F',1.3);
+INSERT INTO CountryLanguage VALUES ('TGO','Ane','F',5.7);
+INSERT INTO CountryLanguage VALUES ('TCD','Ouaddai','F',8.7);
+INSERT INTO CountryLanguage VALUES ('CZE','German','F',0.5);
+INSERT INTO CountryLanguage VALUES ('UGA','Teso','F',6.0);
+INSERT INTO CountryLanguage VALUES ('UKR','Hungarian','F',0.3);
+INSERT INTO CountryLanguage VALUES ('HUN','Romanian','F',0.1);
+INSERT INTO CountryLanguage VALUES ('UZB','Karakalpak','F',2.0);
+INSERT INTO CountryLanguage VALUES ('RUS','Bashkir','F',0.7);
+INSERT INTO CountryLanguage VALUES ('VNM','Chinese','F',1.4);
+INSERT INTO CountryLanguage VALUES ('EST','Finnish','F',0.7);
+INSERT INTO CountryLanguage VALUES ('USA','Italian','F',0.6);
+INSERT INTO CountryLanguage VALUES ('AGO','Chokwe','F',4.2);
+INSERT INTO CountryLanguage VALUES ('AUS','Vietnamese','F',0.8);
+INSERT INTO CountryLanguage VALUES ('BGD','Santhali','F',0.1);
+INSERT INTO CountryLanguage VALUES ('BEL','Turkish','F',0.9);
+INSERT INTO CountryLanguage VALUES ('BEN','Somba','F',6.7);
+INSERT INTO CountryLanguage VALUES ('BFA','Dyula','F',2.6);
+INSERT INTO CountryLanguage VALUES ('ERI','Saho','F',3.0);
+INSERT INTO CountryLanguage VALUES ('ZAF','Tswana','F',8.1);
+INSERT INTO CountryLanguage VALUES ('ETH','Sidamo','F',3.2);
+INSERT INTO CountryLanguage VALUES ('PHL','Waray-waray','F',3.8);
+INSERT INTO CountryLanguage VALUES ('GEO','Abhyasi','F',1.7);
+INSERT INTO CountryLanguage VALUES ('GHA','Joruba','F',1.3);
+INSERT INTO CountryLanguage VALUES ('GIN','Yalunka','F',2.9);
+INSERT INTO CountryLanguage VALUES ('GNB','Mandyako','F',4.9);
+INSERT INTO CountryLanguage VALUES ('IDN','Batakki','F',2.2);
+INSERT INTO CountryLanguage VALUES ('IND','Urdu','F',5.1);
+INSERT INTO CountryLanguage VALUES ('IRN','Mazandarani','F',3.6);
+INSERT INTO CountryLanguage VALUES ('ITA','Albaniana','F',0.2);
+INSERT INTO CountryLanguage VALUES ('AUT','Polish','F',0.2);
+INSERT INTO CountryLanguage VALUES ('JPN','Ainu','F',0.0);
+INSERT INTO CountryLanguage VALUES ('YUG','Macedonian','F',0.5);
+INSERT INTO CountryLanguage VALUES ('CMR','Mandara','F',5.7);
+INSERT INTO CountryLanguage VALUES ('CAN','Polish','F',0.7);
+INSERT INTO CountryLanguage VALUES ('KAZ','Tatar','F',2.0);
+INSERT INTO CountryLanguage VALUES ('KEN','Gusii','F',6.1);
+INSERT INTO CountryLanguage VALUES ('CAF','Mbum','F',6.4);
+INSERT INTO CountryLanguage VALUES ('CHN','Uighur','F',0.6);
+INSERT INTO CountryLanguage VALUES ('KGZ','Kazakh','F',0.8);
+INSERT INTO CountryLanguage VALUES ('COG','Sango','F',2.6);
+INSERT INTO CountryLanguage VALUES ('COD','Ngala and Bangi','F',5.8);
+INSERT INTO CountryLanguage VALUES ('LVA','Lithuanian','F',1.2);
+INSERT INTO CountryLanguage VALUES ('LBR','Mano','F',7.2);
+INSERT INTO CountryLanguage VALUES ('MYS','Dusun','F',1.1);
+INSERT INTO CountryLanguage VALUES ('MLI','Songhai','F',6.9);
+INSERT INTO CountryLanguage VALUES ('MRT','Zenaga','F',1.2);
+INSERT INTO CountryLanguage VALUES ('MUS','Marathi','F',0.7);
+INSERT INTO CountryLanguage VALUES ('MEX','Otomí','F',0.4);
+INSERT INTO CountryLanguage VALUES ('FSM','Wolea','F',3.7);
+INSERT INTO CountryLanguage VALUES ('MNG','Dariganga','F',1.4);
+INSERT INTO CountryLanguage VALUES ('MOZ','Tswa','F',6.0);
+INSERT INTO CountryLanguage VALUES ('MMR','Chin','F',2.2);
+INSERT INTO CountryLanguage VALUES ('NAM','Caprivi','F',4.7);
+INSERT INTO CountryLanguage VALUES ('NPL','Newari','F',3.7);
+INSERT INTO CountryLanguage VALUES ('NGA','Kanuri','F',4.1);
+INSERT INTO CountryLanguage VALUES ('PAK','Balochi','F',3.0);
+INSERT INTO CountryLanguage VALUES ('PAN','Arabic','F',0.6);
+INSERT INTO CountryLanguage VALUES ('MNP','Carolinian','F',4.8);
+INSERT INTO CountryLanguage VALUES ('FRA','Turkish','F',0.4);
+INSERT INTO CountryLanguage VALUES ('ROM','Serbo-Croatian','F',0.1);
+INSERT INTO CountryLanguage VALUES ('SWE','Norwegian','F',0.5);
+INSERT INTO CountryLanguage VALUES ('DEU','Polish','F',0.3);
+INSERT INTO CountryLanguage VALUES ('ZMB','Nsenga','F',4.3);
+INSERT INTO CountryLanguage VALUES ('SEN','Soninke','F',1.3);
+INSERT INTO CountryLanguage VALUES ('SLE','Ful','F',3.8);
+INSERT INTO CountryLanguage VALUES ('SDN','Zande','F',2.7);
+INSERT INTO CountryLanguage VALUES ('TWN','Paiwan','F',0.3);
+INSERT INTO CountryLanguage VALUES ('TZA','Nyakusa','F',5.4);
+INSERT INTO CountryLanguage VALUES ('DNK','Swedish','F',0.3);
+INSERT INTO CountryLanguage VALUES ('THA','Kuy','F',1.1);
+INSERT INTO CountryLanguage VALUES ('TGO','Moba','F',5.4);
+INSERT INTO CountryLanguage VALUES ('TCD','Hadjarai','F',6.7);
+INSERT INTO CountryLanguage VALUES ('CZE','Silesiana','F',0.4);
+INSERT INTO CountryLanguage VALUES ('UGA','Lango','F',5.9);
+INSERT INTO CountryLanguage VALUES ('UKR','Belorussian','F',0.3);
+INSERT INTO CountryLanguage VALUES ('HUN','Slovak','F',0.1);
+INSERT INTO CountryLanguage VALUES ('UZB','Tatar','F',1.8);
+INSERT INTO CountryLanguage VALUES ('RUS','Chechen','F',0.6);
+INSERT INTO CountryLanguage VALUES ('VNM','Khmer','F',1.4);
+INSERT INTO CountryLanguage VALUES ('USA','Chinese','F',0.6);
+INSERT INTO CountryLanguage VALUES ('AGO','Luvale','F',3.6);
+INSERT INTO CountryLanguage VALUES ('AUS','Serbo-Croatian','F',0.6);
+INSERT INTO CountryLanguage VALUES ('BGD','Tripuri','F',0.1);
+INSERT INTO CountryLanguage VALUES ('BEN','Ful','F',5.6);
+INSERT INTO CountryLanguage VALUES ('ZAF','Southsotho','F',7.6);
+INSERT INTO CountryLanguage VALUES ('ETH','Walaita','F',2.8);
+INSERT INTO CountryLanguage VALUES ('PHL','Pampango','F',3.0);
+INSERT INTO CountryLanguage VALUES ('GIN','Loma','F',2.3);
+INSERT INTO CountryLanguage VALUES ('IDN','Bugi','F',2.2);
+INSERT INTO CountryLanguage VALUES ('IND','Gujarati','F',4.8);
+INSERT INTO CountryLanguage VALUES ('IRN','Balochi','F',2.3);
+INSERT INTO CountryLanguage VALUES ('ITA','Slovene','F',0.2);
+INSERT INTO CountryLanguage VALUES ('AUT','Czech','F',0.2);
+INSERT INTO CountryLanguage VALUES ('CMR','Maka','F',4.9);
+INSERT INTO CountryLanguage VALUES ('CAN','Spanish','F',0.7);
+INSERT INTO CountryLanguage VALUES ('KEN','Meru','F',5.5);
+INSERT INTO CountryLanguage VALUES ('CHN','Yi','F',0.6);
+INSERT INTO CountryLanguage VALUES ('KGZ','Tadzhik','F',0.8);
+INSERT INTO CountryLanguage VALUES ('COD','Rundi','F',3.8);
+INSERT INTO CountryLanguage VALUES ('LBR','Loma','F',5.8);
+INSERT INTO CountryLanguage VALUES ('MOZ','Chuabo','F',5.7);
+INSERT INTO CountryLanguage VALUES ('MMR','Kachin','F',1.4);
+INSERT INTO CountryLanguage VALUES ('NAM','San','F',1.9);
+INSERT INTO CountryLanguage VALUES ('NPL','Hindi','F',3.0);
+INSERT INTO CountryLanguage VALUES ('NGA','Edo','F',3.3);
+INSERT INTO CountryLanguage VALUES ('PAK','Hindko','F',2.4);
+INSERT INTO CountryLanguage VALUES ('SLE','Kuranko','F',3.4);
+INSERT INTO CountryLanguage VALUES ('SDN','Bari','F',2.5);
+INSERT INTO CountryLanguage VALUES ('TZA','Chaga and Pare','F',4.9);
+INSERT INTO CountryLanguage VALUES ('DNK','Norwegian','F',0.3);
+INSERT INTO CountryLanguage VALUES ('TGO','Naudemba','F',4.1);
+INSERT INTO CountryLanguage VALUES ('TCD','Tandjile','F',6.5);
+INSERT INTO CountryLanguage VALUES ('CZE','Romani','F',0.3);
+INSERT INTO CountryLanguage VALUES ('UGA','Lugbara','F',4.7);
+INSERT INTO CountryLanguage VALUES ('UKR','Polish','F',0.1);
+INSERT INTO CountryLanguage VALUES ('RUS','Mordva','F',0.5);
+INSERT INTO CountryLanguage VALUES ('VNM','Nung','F',1.1);
+INSERT INTO CountryLanguage VALUES ('USA','Tagalog','F',0.4);
+INSERT INTO CountryLanguage VALUES ('AGO','Ambo','F',2.4);
+INSERT INTO CountryLanguage VALUES ('AUS','German','F',0.6);
+INSERT INTO CountryLanguage VALUES ('ZAF','Tsonga','F',4.3);
+INSERT INTO CountryLanguage VALUES ('PHL','Pangasinan','F',1.8);
+INSERT INTO CountryLanguage VALUES ('IDN','Banja','F',1.8);
+INSERT INTO CountryLanguage VALUES ('IND','Kannada','F',3.9);
+INSERT INTO CountryLanguage VALUES ('IRN','Arabic','F',2.2);
+INSERT INTO CountryLanguage VALUES ('ITA','Romani','F',0.2);
+INSERT INTO CountryLanguage VALUES ('AUT','Romanian','F',0.2);
+INSERT INTO CountryLanguage VALUES ('CMR','Masana','F',3.9);
+INSERT INTO CountryLanguage VALUES ('CAN','Portuguese','F',0.7);
+INSERT INTO CountryLanguage VALUES ('KEN','Nyika','F',4.8);
+INSERT INTO CountryLanguage VALUES ('CHN','Tujia','F',0.5);
+INSERT INTO CountryLanguage VALUES ('COD','Teke','F',2.7);
+INSERT INTO CountryLanguage VALUES ('LBR','Malinke','F',5.1);
+INSERT INTO CountryLanguage VALUES ('MOZ','Ronga','F',3.7);
+INSERT INTO CountryLanguage VALUES ('MMR','Kayah','F',0.4);
+INSERT INTO CountryLanguage VALUES ('NAM','German','F',0.9);
+INSERT INTO CountryLanguage VALUES ('NGA','Tiv','F',2.3);
+INSERT INTO CountryLanguage VALUES ('PAK','Brahui','F',1.2);
+INSERT INTO CountryLanguage VALUES ('SLE','Yalunka','F',3.4);
+INSERT INTO CountryLanguage VALUES ('SDN','Fur','F',2.1);
+INSERT INTO CountryLanguage VALUES ('TZA','Luguru','F',4.9);
+INSERT INTO CountryLanguage VALUES ('TGO','Gurma','F',3.4);
+INSERT INTO CountryLanguage VALUES ('TCD','Gorane','F',6.2);
+INSERT INTO CountryLanguage VALUES ('CZE','Hungarian','F',0.2);
+INSERT INTO CountryLanguage VALUES ('UGA','Gisu','F',4.5);
+INSERT INTO CountryLanguage VALUES ('RUS','Kazakh','F',0.4);
+INSERT INTO CountryLanguage VALUES ('VNM','Miao','F',0.9);
+INSERT INTO CountryLanguage VALUES ('USA','Polish','F',0.3);
+INSERT INTO CountryLanguage VALUES ('AGO','Luchazi','F',2.4);
+INSERT INTO CountryLanguage VALUES ('ZAF','Swazi','F',2.5);
+INSERT INTO CountryLanguage VALUES ('PHL','Maguindanao','F',1.4);
+INSERT INTO CountryLanguage VALUES ('IDN','Bali','F',1.7);
+INSERT INTO CountryLanguage VALUES ('IND','Malajalam','F',3.6);
+INSERT INTO CountryLanguage VALUES ('IRN','Bakhtyari','F',1.7);
+INSERT INTO CountryLanguage VALUES ('CAN','Punjabi','F',0.7);
+INSERT INTO CountryLanguage VALUES ('KEN','Masai','F',1.6);
+INSERT INTO CountryLanguage VALUES ('CHN','Mongolian','F',0.4);
+INSERT INTO CountryLanguage VALUES ('COD','Boa','F',2.3);
+INSERT INTO CountryLanguage VALUES ('MOZ','Marendje','F',3.5);
+INSERT INTO CountryLanguage VALUES ('NGA','Ijo','F',1.8);
+INSERT INTO CountryLanguage VALUES ('SDN','Chilluk','F',1.7);
+INSERT INTO CountryLanguage VALUES ('TZA','Shambala','F',4.3);
+INSERT INTO CountryLanguage VALUES ('UGA','Acholi','F',4.4);
+INSERT INTO CountryLanguage VALUES ('RUS','Avarian','F',0.4);
+INSERT INTO CountryLanguage VALUES ('VNM','Man','F',0.7);
+INSERT INTO CountryLanguage VALUES ('USA','Korean','F',0.3);
+INSERT INTO CountryLanguage VALUES ('ZAF','Venda','F',2.2);
+INSERT INTO CountryLanguage VALUES ('PHL','Maranao','F',1.3);
+INSERT INTO CountryLanguage VALUES ('IND','Orija','F',3.3);
+INSERT INTO CountryLanguage VALUES ('IRN','Turkmenian','F',1.6);
+INSERT INTO CountryLanguage VALUES ('CAN','Ukrainian','F',0.6);
+INSERT INTO CountryLanguage VALUES ('KEN','Turkana','F',1.4);
+INSERT INTO CountryLanguage VALUES ('CHN','Tibetan','F',0.4);
+INSERT INTO CountryLanguage VALUES ('COD','Chokwe','F',1.8);
+INSERT INTO CountryLanguage VALUES ('MOZ','Nyanja','F',3.3);
+INSERT INTO CountryLanguage VALUES ('NGA','Bura','F',1.6);
+INSERT INTO CountryLanguage VALUES ('SDN','Lotuko','F',1.5);
+INSERT INTO CountryLanguage VALUES ('TZA','Gogo','F',3.9);
+INSERT INTO CountryLanguage VALUES ('UGA','Rwanda','F',3.2);
+INSERT INTO CountryLanguage VALUES ('RUS','Mari','F',0.4);
+INSERT INTO CountryLanguage VALUES ('USA','Vietnamese','F',0.2);
+INSERT INTO CountryLanguage VALUES ('ZAF','Ndebele','F',1.5);
+INSERT INTO CountryLanguage VALUES ('IND','Punjabi','F',2.8);
+INSERT INTO CountryLanguage VALUES ('CAN','Dutch','F',0.5);
+INSERT INTO CountryLanguage VALUES ('CHN','Puyi','F',0.2);
+INSERT INTO CountryLanguage VALUES ('TZA','Ha','F',3.5);
+INSERT INTO CountryLanguage VALUES ('RUS','Udmur','F',0.3);
+INSERT INTO CountryLanguage VALUES ('USA','Japanese','F',0.2);
+INSERT INTO CountryLanguage VALUES ('IND','Asami','F',1.5);
+INSERT INTO CountryLanguage VALUES ('CAN','Eskimo Languages','F',0.1);
+INSERT INTO CountryLanguage VALUES ('CHN','Dong','F',0.2);
+INSERT INTO CountryLanguage VALUES ('RUS','Belorussian','F',0.3);
+INSERT INTO CountryLanguage VALUES ('USA','Portuguese','F',0.2);
+
+/*!40000 ALTER TABLE CountryLanguage ENABLE KEYS */;
+
diff --git a/Makefile.am b/Makefile.am
index 22e066ac9d4..8cb67521a4a 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -22,15 +22,21 @@ TAR = gtar
EXTRA_DIST = INSTALL-SOURCE README \
COPYING COPYING.LIB MIRRORS
SUBDIRS = include @docs_dirs@ @readline_dir@ \
- @thread_dirs@ @sql_client_dirs@ \
- @sql_server_dirs@ scripts tests man \
- @bench_dirs@ support-files
+ @thread_dirs@ pstack @sql_client_dirs@ \
+ @sql_server_dirs@ @libmysqld_dirs@ scripts man \
+ tests BUILD \
+ @bench_dirs@ support-files @fs_dirs@ @tools_dirs@
# Relink after clean
-CLEANFILES = linked_client_sources linked_server_sources linked_libmysql_sources linked_libmysql_r_sources linked_include_sources
+linked_sources = linked_client_sources linked_server_sources \
+ linked_libmysql_sources linked_libmysql_r_sources \
+ linked_libmysqld_sources linked_libmysqldex_sources \
+ linked_include_sources
+
+CLEANFILES = $(linked_sources)
# This is just so that the linking is done early.
-config.h: linked_include_sources linked_client_sources linked_server_sources linked_libmysql_sources linked_libmysql_r_sources
+config.h: $(linked_sources)
linked_include_sources:
cd include; $(MAKE) link_sources
@@ -48,6 +54,14 @@ linked_libmysql_r_sources: linked_libmysql_sources
cd libmysql_r; $(MAKE) link_sources
echo timestamp > linked_libmysql_r_sources
+linked_libmysqld_sources:
+ cd libmysqld; $(MAKE) link_sources
+ echo timestamp > linked_libmysqld_sources
+
+linked_libmysqldex_sources:
+ cd libmysqld/examples; $(MAKE) link_sources
+ echo timestamp > linked_libmysqldex_sources
+
#avoid recursive make calls in sql directory
linked_server_sources:
cd sql; rm -f mini_client_errors.c;@LN_CP_F@ ../libmysql/errmsg.c mini_client_errors.c
@@ -60,9 +74,12 @@ init-db: all
bin-dist: all
$(top_builddir)/scripts/make_binary_distribution
+tags:
+ support-files/build-tags
.PHONY: init-db bin-dist
# Test installation
test:
cd mysql-test ; ./mysql-test-run
+
diff --git a/SSL/NOTES b/SSL/NOTES
new file mode 100644
index 00000000000..413c724c583
--- /dev/null
+++ b/SSL/NOTES
@@ -0,0 +1,376 @@
+Quick notes:
+--------------------------------------------
+[tonu@x153 mysql-4.0]$ cat /etc/my.cnf
+[mysqld]
+ssl-ca=SSL/cacert.pem
+ssl-cert=SSL/server-cert.pem
+ssl-key=SSL/server-key.pem
+
+[mysql]
+ssl-ca=SSL/cacert.pem
+ssl-cert=SSL/client-cert.pem
+ssl-key=SSL/client-key.pem
+
+[mysqldump]
+ssl-ca=SSL/cacert.pem
+ssl-cert=SSL/client-cert.pem
+ssl-key=SSL/client-key.pem
+
+[tonu@x153 mysql-4.0]$
+--------------------------------------------
+To remove passwords from keyfiles:
+[tonu@x153 SSL]$ openssl rsa -inform pem < server-req.pem > server-key.pem
+read RSA key
+Enter PEM pass phrase:
+writing RSA key
+[tonu@x153 SSL]$
+--------------------------------------------
+To run server:
+
+sql/mysqld --ssl-ca=SSL/cacert.pem --ssl-cert=SSL/server-cert.pem --ssl-key=SSL/server-key.pem --skip-grant --debug='d:t:O,-' > /tmp/mysqld.trace
+--------------------------------------------
+To run client:
+
+client/mysql --ssl-ca=SSL/cacert.pem --ssl-cert=SSL/server-cert.pem --ssl-key=SSL/server-key.pem --debug='d:t:O,/tmp/client.trace' -h 127.0.0.1
+--------------------------------------------
+openssl s_client -host 127.0.0.1 -port 1111 -debug -verify 1 -cert ../SSL/client-cert.pem -key ../SSL/client-key.pem -CAfile ../SSL/cacert.pem -pause -showcerts -state
+
+--------------------------------------------
+openssl s_server -port 1111 -cert ../SSL/server-cert.pem -key ../SSL/server-key.pem
+
+
+
+
+--------------------------------------------
+
+CA stuff:
+
+[tonu@x153 bin]$ pwd
+/usr/local/ssl/bin
+[tonu@x153 bin]$
+[tonu@x153 bin]$ ./CA.sh
+[tonu@x153 bin]$ ./CA.sh -h
+usage: CA -newcert|-newreq|-newca|-sign|-verify
+[tonu@x153 bin]$
+[root@x153 bin]# ./CA.sh -newca
+CA certificate filename (or enter to create)
+
+Making CA certificate ...
+Using configuration from /usr/lib/ssl/openssl.cnf
+Generating a 1024 bit RSA private key
+.++++++
+................++++++
+writing new private key to './demoCA/private/./cakey.pem'
+Enter PEM pass phrase:
+Verifying password - Enter PEM pass phrase:
+phrase is too short, needs to be at least 4 chars
+Enter PEM pass phrase:
+Verifying password - Enter PEM pass phrase:
+-----
+You are about to be asked to enter information that will be incorporated
+into your certificate request.
+What you are about to enter is what is called a Distinguished Name or a DN.
+There are quite a few fields but you can leave some blank
+For some fields there will be a default value,
+If you enter '.', the field will be left blank.
+-----
+ountry Name (2 letter code) [AU]:FI
+State or Province Name (full name) [Some-State]:
+Locality Name (eg, city) []:Helsinki
+Organization Name (eg, company) [Internet Widgits Pty Ltd]:MySQL Finland AB
+Organizational Unit Name (eg, section) []:
+Common Name (eg, YOUR name) []:Tonu Samuel
+Email Address []:tonu@mysql.com
+[root@x153 bin]#
+[root@x153 bin]# ls -la demoCA/
+total 13
+drwxr-xr-x 6 root root 232 Jun 24 18:50 ./
+drwxr-xr-x 3 root root 2136 Jun 24 18:41 ../
+-rw-r--r-- 1 root root 1241 Jun 24 18:50 cacert.pem
+drwxr-xr-x 2 root root 48 Jun 24 18:41 certs/
+drwxr-xr-x 2 root root 48 Jun 24 18:41 crl/
+-rw-r--r-- 1 root root 0 Jun 24 18:44 index.txt
+drwxr-xr-x 2 root root 48 Jun 24 18:41 newcerts/
+drwxr-xr-x 2 root root 80 Jun 24 18:44 private/
+-rw-r--r-- 1 root root 3 Jun 24 18:44 serial
+[root@x153 bin]#
+[root@x153 bin]# ls -la demoCA/private/
+total 5
+drwxr-xr-x 2 root root 80 Jun 24 18:44 ./
+drwxr-xr-x 6 root root 232 Jun 24 18:50 ../
+-rw-r--r-- 1 root root 963 Jun 24 18:50 cakey.pem
+[root@x153 bin]#
+[root@x153 bin]# ./CA.sh -newreq
+Using configuration from /usr/lib/ssl/openssl.cnf
+Generating a 1024 bit RSA private key
+..................++++++
+........................++++++
+writing new private key to 'newreq.pem'
+Enter PEM pass phrase: <- new key password, not CA
+Verifying password - Enter PEM pass phrase:
+-----
+You are about to be asked to enter information that will be incorporated
+into your certificate request.
+What you are about to enter is what is called a Distinguished Name or a DN.
+There are quite a few fields but you can leave some blank
+For some fields there will be a default value,
+If you enter '.', the field will be left blank.
+-----
+Country Name (2 letter code) [AU]:EE
+State or Province Name (full name) [Some-State]:
+Locality Name (eg, city) []:Tallinn
+Organization Name (eg, company) [Internet Widgits Pty Ltd]:Noname
+Organizational Unit Name (eg, section) []:
+Common Name (eg, YOUR name) []:Mr Noname
+Email Address []:a@b.c
+
+Please enter the following 'extra' attributes
+to be sent with your certificate request
+A challenge password []:
+An optional company name []:
+Request (and private key) is in newreq.pem
+[root@x153 bin]#
+[root@x153 bin]# ls -la newreq.pem
+-rw-r--r-- 1 root root 1623 Jun 24 18:54 newreq.pem
+[root@x153 bin]#
+[root@x153 bin]# ./CA.sh -sign
+Using configuration from /usr/lib/ssl/openssl.cnf
+Enter PEM pass phrase: <- CA's one!
+Check that the request matches the signature
+Signature ok
+The Subjects Distinguished Name is as follows
+countryName :PRINTABLE:'EE'
+stateOrProvinceName :PRINTABLE:'Some-State'
+localityName :PRINTABLE:'Tallinn'
+organizationName :PRINTABLE:'Noname'
+commonName :PRINTABLE:'Mr Noname'
+emailAddress :IA5STRING:'a@b.c'
+Certificate is to be certified until Jun 24 15:50:23 2002 GMT (365 days)
+Sign the certificate? [y/n]:y
+
+
+1 out of 1 certificate requests certified, commit? [y/n]y
+Write out database with 1 new entries
+Data Base Updated
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 1 (0x1)
+ Signature Algorithm: md5WithRSAEncryption
+ Issuer: C=FI, ST=Some-State, L=Helsinki, O=MySQL Finland AB, CN=Tonu Samuel/Email=tonu@mysql.com
+ Validity
+ Not Before: Jun 24 15:50:23 2001 GMT
+ Not After : Jun 24 15:50:23 2002 GMT
+ Subject: C=EE, ST=Some-State, L=Tallinn, O=Noname, CN=Mr Noname/Email=a@b.c
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:ab:3b:7d:5b:6c:93:f6:46:1a:2c:46:73:6f:89:
+ 8a:99:bb:e9:6b:94:0d:74:aa:aa:c4:5c:a2:61:cf:
+ 56:bb:a1:a9:5a:37:c4:4e:b2:ec:5c:18:3a:a4:8d:
+ af:3d:23:66:7c:85:7f:d1:f2:e3:fc:16:a7:4c:a2:
+ d6:45:06:92:75:d8:a2:3b:f9:aa:77:da:26:b9:87:
+ e0:df:50:54:e4:36:9f:35:87:39:8e:a6:7c:3e:a8:
+ e4:49:1a:76:c2:6f:73:0b:22:93:2a:04:67:0d:7d:
+ ae:34:5c:fe:7c:29:b8:a2:fe:1e:ef:d1:0c:4d:dd:
+ 5b:7a:67:b0:0a:22:88:a0:af
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints:
+ CA:FALSE
+ Netscape Comment:
+ OpenSSL Generated Certificate
+ X509v3 Subject Key Identifier:
+ 83:D1:0D:52:0F:DE:61:2D:A6:10:20:B8:46:0C:77:D5:D2:D0:BE:20
+ X509v3 Authority Key Identifier:
+ keyid:A5:0A:D6:72:B5:DF:E4:C2:2B:7B:07:5E:D3:4D:52:07:E1:83:6B:7F
+ DirName:/C=FI/ST=Some-State/L=Helsinki/O=MySQL Finland AB/CN=Tonu Samuel/Email=tonu@mysql.com
+ serial:00
+
+ Signature Algorithm: md5WithRSAEncryption
+ 60:85:f7:d0:54:2a:67:88:0e:37:a6:a8:8e:fd:a0:c9:a1:d7:
+ c6:fc:4c:2e:59:8d:88:6d:69:0a:b8:b2:67:5f:81:94:39:0e:
+ ab:67:fc:8b:62:de:85:f6:b3:8c:2d:1a:e3:dc:28:fc:f5:99:
+ 39:f0:3d:50:ca:88:c0:8e:f8:c2:02:5d:34:19:63:9f:c4:a2:
+ f6:a8:81:c9:8d:6d:bd:c4:42:4a:0c:49:5a:cc:24:ea:65:80:
+ dd:79:20:89:9e:ea:6b:80:7a:86:f9:bb:6d:24:3c:80:13:5b:
+ e6:16:fc:3d:8d:f6:16:ea:33:25:c6:90:20:81:a4:b0:15:2e:
+ 9c:1c
+-----BEGIN CERTIFICATE-----
+MIIDfjCCAuegAwIBAgIBATANBgkqhkiG9w0BAQQFADCBhTELMAkGA1UEBhMCRkkx
+EzARBgNVBAgTClNvbWUtU3RhdGUxETAPBgNVBAcTCEhlbHNpbmtpMRkwFwYDVQQK
+ExBNeVNRTCBGaW5sYW5kIEFCMRQwEgYDVQQDEwtUb251IFNhbXVlbDEdMBsGCSqG
+SIb3DQEJARYOdG9udUBteXNxbC5jb20wHhcNMDEwNjI0MTU1MDIzWhcNMDIwNjI0
+MTU1MDIzWjBvMQswCQYDVQQGEwJFRTETMBEGA1UECBMKU29tZS1TdGF0ZTEQMA4G
+A1UEBxMHVGFsbGlubjEPMA0GA1UEChMGTm9uYW1lMRIwEAYDVQQDEwlNciBOb25h
+bWUxFDASBgkqhkiG9w0BCQEWBWFAYi5jMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCB
+iQKBgQCrO31bbJP2RhosRnNviYqZu+lrlA10qqrEXKJhz1a7oalaN8ROsuxcGDqk
+ja89I2Z8hX/R8uP8FqdMotZFBpJ12KI7+ap32ia5h+DfUFTkNp81hzmOpnw+qORJ
+GnbCb3MLIpMqBGcNfa40XP58Kbii/h7v0QxN3Vt6Z7AKIoigrwIDAQABo4IBETCC
+AQ0wCQYDVR0TBAIwADAsBglghkgBhvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQg
+Q2VydGlmaWNhdGUwHQYDVR0OBBYEFIPRDVIP3mEtphAguEYMd9XS0L4gMIGyBgNV
+HSMEgaowgaeAFKUK1nK13+TCK3sHXtNNUgfhg2t/oYGLpIGIMIGFMQswCQYDVQQG
+EwJGSTETMBEGA1UECBMKU29tZS1TdGF0ZTERMA8GA1UEBxMISGVsc2lua2kxGTAX
+BgNVBAoTEE15U1FMIEZpbmxhbmQgQUIxFDASBgNVBAMTC1RvbnUgU2FtdWVsMR0w
+GwYJKoZIhvcNAQkBFg50b251QG15c3FsLmNvbYIBADANBgkqhkiG9w0BAQQFAAOB
+gQBghffQVCpniA43pqiO/aDJodfG/EwuWY2IbWkKuLJnX4GUOQ6rZ/yLYt6F9rOM
+LRrj3Cj89Zk58D1QyojAjvjCAl00GWOfxKL2qIHJjW29xEJKDElazCTqZYDdeSCJ
+nuprgHqG+bttJDyAE1vmFvw9jfYW6jMlxpAggaSwFS6cHA==
+-----END CERTIFICATE-----
+Signed certificate is in newcert.pem
+[root@x153 bin]# ls -la demoCA/newcerts/
+total 5
+drwxr-xr-x 2 root root 72 Jun 24 18:58 ./
+drwxr-xr-x 6 root root 296 Jun 24 18:58 ../
+-rw-r--r-- 1 root root 3533 Jun 24 18:58 01.pem
+[root@x153 bin]#
+[root@x153 mysql-4.0]# ./sql/mysqld --ssl-cert=SSL/server-cert.pem --ssl-ca=SSL/cacert.pem --ssl-ke
+y=SSL/server-req.pem -L /home/tonu/mysql-4.0/sql/share/english/ -u root
+Enter PEM pass phrase:
+./sql/mysqld: ready for connections
+[tonu@x153 mysql-4.0]$ client/mysql --ssl-key=SSL/client-req.pem --ssl-ca=SSL/cacert.pem --ssl-cert
+=SSL/client-cert.pem
+Enter PEM pass phrase:
+ERROR:
+
+[tonu@x153 mysql-4.0]$
+
+
+
+
+-8<------------------------
+SSL encrypts data between MySQL server and client.
+
+You need openssl (formerly SSLeay) for MySQL SSL support. Development
+and testing was done on openssl version 0.9.3a
+
+To compile MySQL one must do:
+./configure --with-openssl=/usr
+
+or
+
+./configure --with-openssl=yes
+
+There are sample keys and certificates included with MySQL tarball in
+directory ./SSL. They are meant to be for quick start and
+testing only. Using them in production environment means same as not
+using encryption. This is because private keys are publicly
+accessible for everyone. You must use openssl distribution for new key
+and certificate generation for both client and server.
+
+----------- for manual: ---------------------
+*New API calls:*
+
+mysql_ssl_set() - Set SSL properties (key, certificate,
+certificates authority certificate). Must be called before
+mysql_real_connect();
+mysql_ssl_clear() - Clear and free resources occupied by
+mysql_ssl_set() API call.
+char *mysql_ssl_cipher(MYSQL *) - returns cipher in use. For example
+"DES-CDC3-SHA" means that you have combined triple DES symmetric
+algorithm and SHA
+hashing algorithm.
+
+
+*New command line switches:*
+--ssl Use SSL for connection (automatically set with
+other flags. This means one can use encrypted connection without strong
+cryptological authentication. Normally one must use all switches
+together including ssl-key, ssl-cert and ssl-ca and never mind about
+--ssl because this is assumed by defult if any of them (--ssl-...)
+included.
+--ssl-key X509 key in PEM format (implies --ssl)
+--ssl-cert X509 cert in PEM format (implies --ssl)
+--ssl-ca CA file in PEM format (check OpenSSL docs,
+implies --ssl)
+--ssl-capath CA directory (check OpenSSL docs, implies --ssl
+ ----------------
+ This is about using SSL in MySQL privilege system. My idea is to make
+ possible use of x509 certificates and keys instead of MySQL native
+ passwords
+Some basic theory about crypt, SSL and x509:
+x509 is standard for certificates. SSL is standard for secure
+communication. Certificates are issued by someone anyone can trust. This
+trusted party is called "Certificate Authority" or "CA". This is
+someone, we MUST trust. Everyone must have some "fingerprint" of CA (so
+called "CA certificate" or "CA cert") using which one can verify
+authenticity of other
+certificates issued by this CA. CA uses his power to give certificates
+to persons (they can be physical (like "monty") or logical (like some
+process). Person is identified by "subject" like
+"/C=EE/ST=Harjumaa/L=Tallinn/O=MySQL client bogus certificate/CN=Tonu
+Samuel/Email=<EMAIL: PROTECTED>". and signed cryptologically. This sign can be
+verified using CA-cert. So, if we trust CA, then we can trust identity
+of user.
+There can be many CA-s (usually not but who knows). Also there can be
+some users we don`t trust or have different privileges. This means we
+must have one table to hold CA-certs and other table to hold so called
+"subjects" (users). I think it`s a good idea to use existing structure
+of host/user/db/field and add some x509 relationship. Then we can
+use usual simple user/host pair or x509 subject/CA pair.
+So I think user must grant rights using old method GRANT blabla ON
+blabla TO blabla IDENTIFIED BY blabla
+or new way:
+-----------8<---------------------------
+GRANT blabla ON blabla TO blabla
+IDENTIFIED BY X509 SUBJECT "/C=EE/ST=Harjumaa/L=Tallinn/O=MySQL client
+bogus certificate/CN=Tonu Samuel/Email=<EMAIL: PROTECTED>" AND ISSUER
+"/C=EE/ST=Harjumaa/L=Tallinn/O=TCX AB/CN=Tonu
+Samuel/Email=<EMAIL: PROTECTED>";
+-----------8<---------------------------
+Please note the difference in Subject and Issuer. This command requests
+user to authenticate itself with exact subject and exact certificate
+issuer. Next possibility is just have any certificate of some good CA:
+-----------8<---------------------------
+GRANT blabla ON blabla TO blabla IDENTIFIED BY X509 ISSUER
+"/C=EE/ST=Harjumaa/L=Tallinn/O=TCX
+AB/CN=Tonu Samuel/Email=<EMAIL: PROTECTED>";
+-----------8<---------------------------
+or if any registered CA is good enough (usual case when only one CA is
+registered)
+but we care about exact user, then something like:
+-----------8<---------------------------
+GRANT blabla ON blabla TO blabla IDENTIFIED BY X509 SUBJECT
+"/C=EE/ST=Harjumaa/L=Tallinn/O=MySQL client
+bogus certificate/CN=Tonu Samuel/Email=<EMAIL: PROTECTED>";
+-----------8<---------------------------
+And case if user must authenticate itself but we don`t care about exact
+person until he have some certificate issued by CA registered in our
+system:
+-----------8<---------------------------
+GRANT blabla ON blabla TO blabla IDENTIFIED BY X509;
+-----------8<---------------------------
+Then additionally we need one exception. Let`s assume we need SSL
+encryption
+for preventing eavesdropping but we don`t care who it is at all. We need
+privilege to exclude all non-SSL users but we accept anyone using SSL.
+How
+this must be done in GRANT syntax? Maybe:
+-----------8<---------------------------
+GRANT blabla ON blabla TO blabla
+IDENTIFIED BY blabla AND USING SSL
+-----------8<---------------------------
+But maybe we want to add in future possibility to check different
+algorithms and key lengths? Something like:
+-----------8<---------------------------
+GRANT blabla ON blabla TO blabla IDENTIFIED BY blabla AND USING SSL WITH
+CIPHER "DES-CBC3-SHA" OR "DES-CBC3-MD5"
+-----------8<---------------------------
+Also we need some command to include/exclude CA certificates. This must
+be some commands like INSERT/DELETE/UPDATE/REPLACE to do it.
+All examples is given for clarify my problem. I asking for help because
+I don`t know
+any similar command in other SQL-s.
+------------8<------------------------
+
+So, at moment SSL communications is ready and working. I don`t have this
+command iterface at moment yet and this can be changed a lot if someone
+can suggest good idea or reason to change them. We are ready to listen
+every opinion.
+About Kerberos: I just don`t know much about it. I have to read this
+again before I can comment. I never used it itself and forgot most of
+theory. Sorry. Anyway now the problem/need is known and I will put
+thinking about this in personal TODO.
+
+
diff --git a/SSL/cacert.pem b/SSL/cacert.pem
new file mode 100644
index 00000000000..862e07114c5
--- /dev/null
+++ b/SSL/cacert.pem
@@ -0,0 +1,21 @@
+-----BEGIN CERTIFICATE-----
+MIIDaDCCAtGgAwIBAgIBADANBgkqhkiG9w0BAQQFADCBhTELMAkGA1UEBhMCRkkx
+EzARBgNVBAgTClNvbWUtU3RhdGUxETAPBgNVBAcTCEhlbHNpbmtpMRkwFwYDVQQK
+ExBNeVNRTCBGaW5sYW5kIEFCMRQwEgYDVQQDEwtUb251IFNhbXVlbDEdMBsGCSqG
+SIb3DQEJARYOdG9udUBteXNxbC5jb20wHhcNMDEwNjI0MTU0MzE4WhcNMDIwNjI0
+MTU0MzE4WjCBhTELMAkGA1UEBhMCRkkxEzARBgNVBAgTClNvbWUtU3RhdGUxETAP
+BgNVBAcTCEhlbHNpbmtpMRkwFwYDVQQKExBNeVNRTCBGaW5sYW5kIEFCMRQwEgYD
+VQQDEwtUb251IFNhbXVlbDEdMBsGCSqGSIb3DQEJARYOdG9udUBteXNxbC5jb20w
+gZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAJz9FCvWX8c+Xr6mxzfZvPainIPT
+ODNsQ0f2kAs0epP+peUn4LHxLybp2dkUHTtJLXyUyk7cXfnUd+0fRazK2/Vz48bZ
+swGwg9Rhg3P02Ku+CMWYulHzN6uVRzfrDUSkDoky2DGL3A6B8P4JRc2qcr+kjhh5
+6r1VJlXs9N3DqeEdAgMBAAGjgeUwgeIwHQYDVR0OBBYEFKUK1nK13+TCK3sHXtNN
+Ugfhg2t/MIGyBgNVHSMEgaowgaeAFKUK1nK13+TCK3sHXtNNUgfhg2t/oYGLpIGI
+MIGFMQswCQYDVQQGEwJGSTETMBEGA1UECBMKU29tZS1TdGF0ZTERMA8GA1UEBxMI
+SGVsc2lua2kxGTAXBgNVBAoTEE15U1FMIEZpbmxhbmQgQUIxFDASBgNVBAMTC1Rv
+bnUgU2FtdWVsMR0wGwYJKoZIhvcNAQkBFg50b251QG15c3FsLmNvbYIBADAMBgNV
+HRMEBTADAQH/MA0GCSqGSIb3DQEBBAUAA4GBAI+YJKoa+IP3WYr8iLcVk5j7lZ9D
+GS8reuALafnE7VX1xMlXP5EnJjT7YYYmtiB2tYj7+eQ+ajRXWWyY5NtO5ob+dm8z
+OBX43v08C5vNSAFpwZWTutzb0nSd8kOABGJ04MBDJZk8QNkTfU6C7c3ZJ/gW8Guv
+I+cxfz6oCYEfKLBN
+-----END CERTIFICATE-----
diff --git a/SSL/client-cert.pem b/SSL/client-cert.pem
new file mode 100644
index 00000000000..cab2a635d9f
--- /dev/null
+++ b/SSL/client-cert.pem
@@ -0,0 +1,67 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 3 (0x3)
+ Signature Algorithm: md5WithRSAEncryption
+ Issuer: C=FI, ST=Some-State, L=Helsinki, O=MySQL Finland AB, CN=Tonu Samuel/Email=tonu@mysql.com
+ Validity
+ Not Before: Jun 24 16:03:20 2001 GMT
+ Not After : Jun 24 16:03:20 2002 GMT
+ Subject: C=EE, ST=Some-State, L=Tallinn, O=MySQL demo client certificate, CN=Tonu Samuel/Email=tonu@mysql.com
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:e8:d4:52:cd:4e:bb:96:16:3a:f0:89:6b:90:4c:
+ db:e0:30:75:5a:02:72:62:bf:ed:da:be:09:e8:80:
+ db:80:54:30:d6:75:ed:e3:10:a5:15:44:5b:29:91:
+ 12:fe:0c:b7:76:4d:e9:5f:56:5c:45:3c:ad:b2:71:
+ 2d:6a:7a:cb:bc:04:80:08:74:d6:7d:f6:7c:5c:76:
+ db:35:c4:f6:f5:d8:d4:89:9f:9d:cc:3f:4e:3f:73:
+ c1:3e:41:7e:4e:09:bf:ea:1a:d9:a2:13:0d:d1:0c:
+ da:d8:f4:9b:b8:54:21:17:ae:d7:b3:02:61:87:a9:
+ 01:ff:f4:fe:9c:7a:fc:67:43
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints:
+ CA:FALSE
+ Netscape Comment:
+ OpenSSL Generated Certificate
+ X509v3 Subject Key Identifier:
+ BC:FB:BB:8F:C4:85:BA:5F:A8:F2:C3:3D:C9:0F:DB:16:E7:13:BC:B2
+ X509v3 Authority Key Identifier:
+ keyid:A5:0A:D6:72:B5:DF:E4:C2:2B:7B:07:5E:D3:4D:52:07:E1:83:6B:7F
+ DirName:/C=FI/ST=Some-State/L=Helsinki/O=MySQL Finland AB/CN=Tonu Samuel/Email=tonu@mysql.com
+ serial:00
+
+ Signature Algorithm: md5WithRSAEncryption
+ 1c:e0:87:2c:2f:b3:a4:39:44:7f:96:7b:2f:c9:1f:91:84:0b:
+ 9f:d0:0a:f8:40:70:d0:dd:bd:91:0a:c6:d5:ac:8f:51:77:9c:
+ 35:28:e8:b6:5f:57:9e:5c:b5:9b:ae:5d:3d:7c:05:45:2e:89:
+ 3a:03:e1:f2:00:cb:c1:ed:3e:48:3b:5f:4e:50:d2:b4:a5:36:
+ 0f:1a:dc:79:49:1e:03:2f:27:c1:e4:62:d6:ef:3f:ab:2e:ab:
+ dd:e5:bc:cb:20:a3:dd:ab:81:69:26:9c:03:42:1b:4c:b7:aa:
+ 57:6d:2a:de:c0:5e:6e:74:d0:83:90:ec:ad:bb:ba:f0:cc:cf:
+ 41:3d
+-----BEGIN CERTIFICATE-----
+MIIDoTCCAwqgAwIBAgIBAzANBgkqhkiG9w0BAQQFADCBhTELMAkGA1UEBhMCRkkx
+EzARBgNVBAgTClNvbWUtU3RhdGUxETAPBgNVBAcTCEhlbHNpbmtpMRkwFwYDVQQK
+ExBNeVNRTCBGaW5sYW5kIEFCMRQwEgYDVQQDEwtUb251IFNhbXVlbDEdMBsGCSqG
+SIb3DQEJARYOdG9udUBteXNxbC5jb20wHhcNMDEwNjI0MTYwMzIwWhcNMDIwNjI0
+MTYwMzIwWjCBkTELMAkGA1UEBhMCRUUxEzARBgNVBAgTClNvbWUtU3RhdGUxEDAO
+BgNVBAcTB1RhbGxpbm4xJjAkBgNVBAoTHU15U1FMIGRlbW8gY2xpZW50IGNlcnRp
+ZmljYXRlMRQwEgYDVQQDEwtUb251IFNhbXVlbDEdMBsGCSqGSIb3DQEJARYOdG9u
+dUBteXNxbC5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOjUUs1Ou5YW
+OvCJa5BM2+AwdVoCcmK/7dq+CeiA24BUMNZ17eMQpRVEWymREv4Mt3ZN6V9WXEU8
+rbJxLWp6y7wEgAh01n32fFx22zXE9vXY1Imfncw/Tj9zwT5Bfk4Jv+oa2aITDdEM
+2tj0m7hUIReu17MCYYepAf/0/px6/GdDAgMBAAGjggERMIIBDTAJBgNVHRMEAjAA
+MCwGCWCGSAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAd
+BgNVHQ4EFgQUvPu7j8SFul+o8sM9yQ/bFucTvLIwgbIGA1UdIwSBqjCBp4AUpQrW
+crXf5MIrewde001SB+GDa3+hgYukgYgwgYUxCzAJBgNVBAYTAkZJMRMwEQYDVQQI
+EwpTb21lLVN0YXRlMREwDwYDVQQHEwhIZWxzaW5raTEZMBcGA1UEChMQTXlTUUwg
+RmlubGFuZCBBQjEUMBIGA1UEAxMLVG9udSBTYW11ZWwxHTAbBgkqhkiG9w0BCQEW
+DnRvbnVAbXlzcWwuY29tggEAMA0GCSqGSIb3DQEBBAUAA4GBABzghywvs6Q5RH+W
+ey/JH5GEC5/QCvhAcNDdvZEKxtWsj1F3nDUo6LZfV55ctZuuXT18BUUuiToD4fIA
+y8HtPkg7X05Q0rSlNg8a3HlJHgMvJ8HkYtbvP6suq93lvMsgo92rgWkmnANCG0y3
+qldtKt7AXm500IOQ7K27uvDMz0E9
+-----END CERTIFICATE-----
diff --git a/SSL/client-key.pem b/SSL/client-key.pem
new file mode 100644
index 00000000000..7672939b60a
--- /dev/null
+++ b/SSL/client-key.pem
@@ -0,0 +1,15 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIICXgIBAAKBgQDo1FLNTruWFjrwiWuQTNvgMHVaAnJiv+3avgnogNuAVDDWde3j
+EKUVRFspkRL+DLd2TelfVlxFPK2ycS1qesu8BIAIdNZ99nxcdts1xPb12NSJn53M
+P04/c8E+QX5OCb/qGtmiEw3RDNrY9Ju4VCEXrtezAmGHqQH/9P6cevxnQwIDAQAB
+AoGBANxd4cUaaOfkQILbvigE5vMpSlkYCcW3XNv1lJEwLREoHlVNpwuL/IPFf/c2
+rWAxDw/1LBYlOg36IXjMMC0g7mRHHoJhdJaFLGdlfclYQvqQ+8JAsAv6UNC63+pn
+B5sZOxOuoj7lYN+D9mFVD4qTo3eTUYEOvvmS1j3hCsD2nNNBAkEA+lJUs7Y3KjCF
+COZ7XQCkC47rVzkdZ5ey1Z+vVw5SrnUvj6n9i0NEax1jX6JPIhPU7+x90KFkt0ki
+pKHd7UQ04wJBAO4caWNnYvmIorCRDy9Q/iAAow5WC6fQlkSlBIe3lRme6Ne8Yxaq
+BzlSGYu1ndPkTGEa9PFNNCJm7RtvCBFx8iECQQCkdUzi2Rc7J69vnoV0H8SnN1mU
+75hLBBZhVU1MY8OcjK8XsvY59ZLQ0PkFzswwtljS3Ev4suBJrsoM4a+9f29DAkEA
+5NTrN3vZc6SrbXLLHBcDUrAqBBIPe4SLlYbdVqzInunILeS/eb2H2b+cC1dMSaHj
+AYONmQUwMEuoXTAUmede4QJARK6jEslg/ev8BtMvITP2b6pRCb1w8lOtT5u5Bwnc
+NpI3suqSQSQPtRSWQYcdyxrKr2TQEZU7h8R9bVB4b0qAmQ==
+-----END RSA PRIVATE KEY-----
diff --git a/SSL/client-req.pem b/SSL/client-req.pem
new file mode 100644
index 00000000000..ef11a22165f
--- /dev/null
+++ b/SSL/client-req.pem
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,8CE2AB38FB50D4B9
+
+rrnYZLUKlzV4U7+wqe5CWzTd4RLJb5h4M77aBRQfuHGejSaRsskN2ffpO8uQEAYM
+WTJSRC+NO+jDMBZhzt1ktWqCs8d6l6azHoBybIrMJsbUhwybm+OiOfp23RrbNoS/
+S4fsgNdAAGhsRvKDdsItCyYvdH8nTzn+g9r/z2V4tOOXd6MYuT42XA6Uz2tis2SZ
+GWEGa7mAweApzSiibE+pzjPS+fdX4E12n6NCVYLhn1JuvzVva/KFSebs4Wh75miC
+WvRgkt/5eDQn+vkV67hE3I6p9pPcLh1+PMfaQ25U8VM/r7ejnVFWm7teGH6GKPKJ
+cU+PYfblyWcgtiO/fwfGMIqSyNtHj/C3VFVie5D1MTJzBopiPGEcfz00LjBccjjh
+j1meTRVN8pMZTgkxlnIFwbU6TPPvx8a9urFVQIJ4z8r2EMvYh5Cqpq87+lH9Pn0C
+vzCl78Tz5QLghXNnMbbdD2aPP0PwPEXgh86iZxo06g85n0l26WUzYJlWzBYD4DrF
+SbnEUAftTujEOm6MqJNLpJN6UPOtq/HvSaHl1bykGK+zU4gqHj0ur03HlF0l4xNg
+OfsoNsJV+O9RUUJ0+D5eqUALJjN8TCV1wNMXOVzr/ue3QCVdlWVfZY4RPffwK9Yp
+Fh52T7a2v+shhqZUQNtFDAg50Ac7deUthSWNmi5N680POnJg9KdtBdMhYLa1j3rP
+D9oasSK0ugevHuQ6wUiD/95CzZlJXE9K4kTTYmaRk5MTWXhFQxdqHZo1v+pGtaNI
+f+/E7q7BiNesSt31U/vkX0Tm3oJ1dgOnS8M2uxiYiKH2mJ/E32tZKw==
+-----END RSA PRIVATE KEY-----
+-----BEGIN CERTIFICATE REQUEST-----
+MIIB0jCCATsCAQAwgZExCzAJBgNVBAYTAkVFMRMwEQYDVQQIEwpTb21lLVN0YXRl
+MRAwDgYDVQQHEwdUYWxsaW5uMSYwJAYDVQQKEx1NeVNRTCBkZW1vIGNsaWVudCBj
+ZXJ0aWZpY2F0ZTEUMBIGA1UEAxMLVG9udSBTYW11ZWwxHTAbBgkqhkiG9w0BCQEW
+DnRvbnVAbXlzcWwuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDo1FLN
+TruWFjrwiWuQTNvgMHVaAnJiv+3avgnogNuAVDDWde3jEKUVRFspkRL+DLd2Telf
+VlxFPK2ycS1qesu8BIAIdNZ99nxcdts1xPb12NSJn53MP04/c8E+QX5OCb/qGtmi
+Ew3RDNrY9Ju4VCEXrtezAmGHqQH/9P6cevxnQwIDAQABoAAwDQYJKoZIhvcNAQEE
+BQADgYEAvENK1JAQfC8xnrFGw2IxfUmUwlRidiRtYTgtVfTr7vA+m4WaaKioni6E
+PQXjcvl6kfyRoxc4qWsGi3T7QM2RnvCtbwR2NGSIKX1cBTS31RMr12NSAeXn6Twz
+ZwSZ55EHj9N2hArTPNlVjxvDQX3D6/ZBi6JnHAxXigzDqhArgjU=
+-----END CERTIFICATE REQUEST-----
diff --git a/SSL/run-client b/SSL/run-client
new file mode 100755
index 00000000000..f3b29eb273b
--- /dev/null
+++ b/SSL/run-client
@@ -0,0 +1,10 @@
+#! /bin/sh
+
+cmd () {
+ echo $*
+ $*
+}
+
+client/mysql --port=4407 --socket=/tmp/test.mysql.sock --ssl-ca=SSL/cacert.pem --ssl-cert=SSL/client-cert.pem --ssl-key=SSL/client-key.pem --debug='d:t:O,/tmp/client.trace' -h 127.0.0.1 -u root
+#--execute="select version();show status"
+
diff --git a/SSL/run-server b/SSL/run-server
new file mode 100755
index 00000000000..e90a7644b83
--- /dev/null
+++ b/SSL/run-server
@@ -0,0 +1,9 @@
+#! /bin/sh
+
+cmd () {
+ echo $*
+ $*
+}
+
+cmd sql/mysqld --port=4407 --socket=/tmp/test.mysql.sock --ssl-ca=SSL/cacert.pem --ssl-cert=SSL/server-cert.pem --ssl-key=SSL/server-key.pem --debug='d:t:O,/tmp/mysqld.trace' -uroot >& /tmp/mysqld.output
+
diff --git a/SSL/server-cert.pem b/SSL/server-cert.pem
new file mode 100644
index 00000000000..069063a9de9
--- /dev/null
+++ b/SSL/server-cert.pem
@@ -0,0 +1,67 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 2 (0x2)
+ Signature Algorithm: md5WithRSAEncryption
+ Issuer: C=FI, ST=Some-State, L=Helsinki, O=MySQL Finland AB, CN=Tonu Samuel/Email=tonu@mysql.com
+ Validity
+ Not Before: Jun 24 16:02:28 2001 GMT
+ Not After : Jun 24 16:02:28 2002 GMT
+ Subject: C=EE, ST=Some-State, L=Tallinn, O=MySQL server demo certificate, CN=Tonu Samuel/Email=tonu@mysql.com
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:9e:ac:8d:d8:1d:9c:b2:fd:88:96:2c:ba:42:53:
+ fa:5d:bd:85:8a:e5:ca:d3:0f:c0:01:3c:f2:92:46:
+ 4f:d9:80:ae:2a:89:cf:ef:e8:d4:65:fc:f6:f5:3a:
+ 26:4c:29:db:06:fa:34:a1:87:f3:97:b5:3c:94:f1:
+ 84:05:ac:ad:57:25:d9:02:db:00:71:e0:a9:aa:b4:
+ 1d:29:36:5e:a9:a4:0d:f2:45:b9:83:74:2b:45:f3:
+ e2:23:bc:e7:5c:e6:11:b6:f6:dd:c4:ac:ed:65:42:
+ 2c:39:47:2a:c9:eb:5f:45:03:10:ab:23:bc:ca:5c:
+ 82:9a:b7:b3:6d:67:18:d2:c7
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints:
+ CA:FALSE
+ Netscape Comment:
+ OpenSSL Generated Certificate
+ X509v3 Subject Key Identifier:
+ 94:68:BF:DA:F6:E2:09:EF:3A:C8:27:AE:D7:B7:02:F0:DC:4B:C1:3B
+ X509v3 Authority Key Identifier:
+ keyid:A5:0A:D6:72:B5:DF:E4:C2:2B:7B:07:5E:D3:4D:52:07:E1:83:6B:7F
+ DirName:/C=FI/ST=Some-State/L=Helsinki/O=MySQL Finland AB/CN=Tonu Samuel/Email=tonu@mysql.com
+ serial:00
+
+ Signature Algorithm: md5WithRSAEncryption
+ 8c:1a:90:70:f6:1a:70:0e:c9:28:93:74:e2:2b:b8:2a:d0:ce:
+ 40:15:e8:af:44:f8:89:16:20:f5:c2:b9:ed:aa:4e:3c:40:e2:
+ 9c:62:aa:48:98:ac:17:84:ef:35:72:59:43:09:35:17:c5:9a:
+ 3e:3d:ef:97:bf:57:f2:2a:f6:56:5d:a4:7c:68:58:b9:d6:9b:
+ 0f:57:0e:55:22:17:b0:b7:77:27:4f:da:b3:88:c1:6d:d6:8f:
+ 31:ec:0d:a2:25:60:66:2f:0f:86:8a:d6:08:b8:71:b1:b5:70:
+ 60:04:56:96:ff:bd:5e:ed:94:bc:44:bd:24:e0:2f:90:e5:23:
+ 51:4e
+-----BEGIN CERTIFICATE-----
+MIIDoTCCAwqgAwIBAgIBAjANBgkqhkiG9w0BAQQFADCBhTELMAkGA1UEBhMCRkkx
+EzARBgNVBAgTClNvbWUtU3RhdGUxETAPBgNVBAcTCEhlbHNpbmtpMRkwFwYDVQQK
+ExBNeVNRTCBGaW5sYW5kIEFCMRQwEgYDVQQDEwtUb251IFNhbXVlbDEdMBsGCSqG
+SIb3DQEJARYOdG9udUBteXNxbC5jb20wHhcNMDEwNjI0MTYwMjI4WhcNMDIwNjI0
+MTYwMjI4WjCBkTELMAkGA1UEBhMCRUUxEzARBgNVBAgTClNvbWUtU3RhdGUxEDAO
+BgNVBAcTB1RhbGxpbm4xJjAkBgNVBAoTHU15U1FMIHNlcnZlciBkZW1vIGNlcnRp
+ZmljYXRlMRQwEgYDVQQDEwtUb251IFNhbXVlbDEdMBsGCSqGSIb3DQEJARYOdG9u
+dUBteXNxbC5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAJ6sjdgdnLL9
+iJYsukJT+l29hYrlytMPwAE88pJGT9mAriqJz+/o1GX89vU6Jkwp2wb6NKGH85e1
+PJTxhAWsrVcl2QLbAHHgqaq0HSk2XqmkDfJFuYN0K0Xz4iO851zmEbb23cSs7WVC
+LDlHKsnrX0UDEKsjvMpcgpq3s21nGNLHAgMBAAGjggERMIIBDTAJBgNVHRMEAjAA
+MCwGCWCGSAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAd
+BgNVHQ4EFgQUlGi/2vbiCe86yCeu17cC8NxLwTswgbIGA1UdIwSBqjCBp4AUpQrW
+crXf5MIrewde001SB+GDa3+hgYukgYgwgYUxCzAJBgNVBAYTAkZJMRMwEQYDVQQI
+EwpTb21lLVN0YXRlMREwDwYDVQQHEwhIZWxzaW5raTEZMBcGA1UEChMQTXlTUUwg
+RmlubGFuZCBBQjEUMBIGA1UEAxMLVG9udSBTYW11ZWwxHTAbBgkqhkiG9w0BCQEW
+DnRvbnVAbXlzcWwuY29tggEAMA0GCSqGSIb3DQEBBAUAA4GBAIwakHD2GnAOySiT
+dOIruCrQzkAV6K9E+IkWIPXCue2qTjxA4pxiqkiYrBeE7zVyWUMJNRfFmj4975e/
+V/Iq9lZdpHxoWLnWmw9XDlUiF7C3dydP2rOIwW3WjzHsDaIlYGYvD4aK1gi4cbG1
+cGAEVpb/vV7tlLxEvSTgL5DlI1FO
+-----END CERTIFICATE-----
diff --git a/SSL/server-key.pem b/SSL/server-key.pem
new file mode 100644
index 00000000000..44137ca1c94
--- /dev/null
+++ b/SSL/server-key.pem
@@ -0,0 +1,15 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIICXAIBAAKBgQCerI3YHZyy/YiWLLpCU/pdvYWK5crTD8ABPPKSRk/ZgK4qic/v
+6NRl/Pb1OiZMKdsG+jShh/OXtTyU8YQFrK1XJdkC2wBx4KmqtB0pNl6ppA3yRbmD
+dCtF8+IjvOdc5hG29t3ErO1lQiw5RyrJ619FAxCrI7zKXIKat7NtZxjSxwIDAQAB
+AoGAA51gudyq1jUKaIlqUNqC6KHJqglkHnzMXfrad9ScOxNAZH2xPADs3cnuglWp
+y7BkaftHOarUNM+PKsF5xXtSk5F9UUV+7h2FtPZYUshUgn5hkGZP12otxJMP0cpg
+Yt6brQxuOIe/r/Kt5r3nKpp4pyFLX2fGWQq7pSjdkgSZSOECQQDJ9MgbCXd81yde
+eo3+YmUPBEQ9d7mivQsyPHMOHLPJKR42N4npdR1zLDBYK5lFzJeQH1y0Uce3O8eL
+hM8hkA1XAkEAySKvNTaosbLhShkRazQyQQJYJg0F/93lkQ33ou4crru7Mvi2OZK9
+B3BGAmNpSv6ZOZYjM0aE8lGlTaoYJ9GQEQJAGJDyFnfcVQ9G9rMpupv1dxIpyuBZ
+cHZWelHoHPtY00txJV80I3Xfkzb42oDTMC5m8V0fRb/870kSSOJq38ZKGQJBAIgq
+wxLzfiFPSNYxQmmhXKRGQgcAqh8eylv5aL0VFrX0wjcvya4QeYifqcXUJ2RuGK2z
+xwDfrQGf5Jk/njrW1QECQAUofd1l9DLDifRP1j9sjUdwz0fvqQ0o6sbt39PBl1ot
+IHdc3nf9z0ft+KOG1CT/M9jYo9SzE9Z6IfwmHxxpY0s=
+-----END RSA PRIVATE KEY-----
diff --git a/SSL/server-req.pem b/SSL/server-req.pem
new file mode 100644
index 00000000000..4cd6610e735
--- /dev/null
+++ b/SSL/server-req.pem
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,6CBD09E71246DC01
+
+byRzq5+j3r8FX2kQerTUZT5Bw/N6zrN3cmH6NHGJcrqD+vcPdtWf+Rk+mpNXgSQn
+ldkfmniU/htzJ0cUV+KE229Qx10Hx9mIJIbf0Y/rBCUBuaXWVrQB36W9w3rkNPFA
+EEuRMkreOJF42RD16+NBJv+RcHIGzGejXecJKUGF5DKlN0U8YHXnkXTQl54kIdr0
+H7rTrvJygwPk9/ik0M9/vmwduAMvTaHDmvgeolpMlJkxwz8vYkbUnFFJZhB6XNCb
+1w3lJ0EmRJicK5BnZmCEmgt8xiv0PAtg00jBbwddQbn1reAyViBtBT9iXdusHXS5
+Po63rSt7r3MO8aetcMQ6FkklH+ChuS/vFoNY57AwrzF4uEI4GSoZP0ESrRC5Ar5W
+Lzg/HrQAWbPCRlb6Jj3db1woRzFS8joOashROsZdeV/5P4Emhc6J7QMTvB1OHAhQ
+ugOJazJtxjg0DN8+9cM1wtHI7N89PLHhOg13LZNLeeehzIlPwKI2JLqXUc6oR407
+i+S7GCqu7wU+if0Enux8Dj7yrvnTUiqVCL2dyKTS3sBq0Cm2UhbecHclor13y6no
+y1o50TKKD6Zig2hZmSpqKznMxGMVIT36BE0aOMQUmk+aVnRuROclwTTL0ZNLzA+g
+QRTRfQ6iNMf34ypqAMdAMPzDGLPycKuFdxVQxFEVaM2/mrdWFwVAqFsLvzyGvdrh
+nkNyRgTWR/pfH9b3mXLqf6gMPNs764WhFIcZIDk9a4XBBUm2YDb2CxDzDCo/EUMA
+jvIiU0Jt132SEHHF/wAka6d2DnwZ3vexRp6Tebv/uy9IlMLPE+68dw==
+-----END RSA PRIVATE KEY-----
+-----BEGIN CERTIFICATE REQUEST-----
+MIIB0jCCATsCAQAwgZExCzAJBgNVBAYTAkVFMRMwEQYDVQQIEwpTb21lLVN0YXRl
+MRAwDgYDVQQHEwdUYWxsaW5uMSYwJAYDVQQKEx1NeVNRTCBzZXJ2ZXIgZGVtbyBj
+ZXJ0aWZpY2F0ZTEUMBIGA1UEAxMLVG9udSBTYW11ZWwxHTAbBgkqhkiG9w0BCQEW
+DnRvbnVAbXlzcWwuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCerI3Y
+HZyy/YiWLLpCU/pdvYWK5crTD8ABPPKSRk/ZgK4qic/v6NRl/Pb1OiZMKdsG+jSh
+h/OXtTyU8YQFrK1XJdkC2wBx4KmqtB0pNl6ppA3yRbmDdCtF8+IjvOdc5hG29t3E
+rO1lQiw5RyrJ619FAxCrI7zKXIKat7NtZxjSxwIDAQABoAAwDQYJKoZIhvcNAQEE
+BQADgYEAlrUnGX4LYIiVjztHA4gUcOSVeEHCci2qEUq+7yY1JhAw54YDa2MLTTwa
+cH+rXLHjN0MTNfv9tRxdSX+trk3pyvhgFjssD100dJkF83RfVv2tKg9kscVOGQp7
+MkwOnJjfAjQBlTbTOQM46BTjv2FgvsppkO3ViryI//YxKvj/628=
+-----END CERTIFICATE REQUEST-----
diff --git a/VC++Files/InstallShield/Script Files/Setup.dbg b/VC++Files/InstallShield/Script Files/Setup.dbg
new file mode 100644
index 00000000000..0c6d4e6b708
--- /dev/null
+++ b/VC++Files/InstallShield/Script Files/Setup.dbg
Binary files differ
diff --git a/VC++Files/InstallShield/Script Files/Setup.ino b/VC++Files/InstallShield/Script Files/Setup.ino
new file mode 100644
index 00000000000..204d8ea0f36
--- /dev/null
+++ b/VC++Files/InstallShield/Script Files/Setup.ino
Binary files differ
diff --git a/VC++Files/InstallShield/Script Files/Setup.ins b/VC++Files/InstallShield/Script Files/Setup.ins
new file mode 100644
index 00000000000..759009b5c84
--- /dev/null
+++ b/VC++Files/InstallShield/Script Files/Setup.ins
Binary files differ
diff --git a/VC++Files/InstallShield/Script Files/Setup.obs b/VC++Files/InstallShield/Script Files/Setup.obs
new file mode 100644
index 00000000000..5fcfcb62c4e
--- /dev/null
+++ b/VC++Files/InstallShield/Script Files/Setup.obs
Binary files differ
diff --git a/VC++Files/InstallShield/Script Files/Setup.rul b/VC++Files/InstallShield/Script Files/Setup.rul
new file mode 100644
index 00000000000..df143b493c4
--- /dev/null
+++ b/VC++Files/InstallShield/Script Files/Setup.rul
@@ -0,0 +1,640 @@
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// IIIIIII SSSSSS
+// II SS InstallShield (R)
+// II SSSSSS (c) 1996-1997, InstallShield Software Corporation
+// II SS (c) 1990-1996, InstallShield Corporation
+// IIIIIII SSSSSS All Rights Reserved.
+//
+//
+// This code is generated as a starting setup template. You should
+// modify it to provide all necessary steps for your setup.
+//
+//
+// File Name: Setup.rul
+//
+// Description: InstallShield script
+//
+// Comments: This template script performs a basic setup on a
+// Windows 95 or Windows NT 4.0 platform. With minor
+// modifications, this template can be adapted to create
+// new, customized setups.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+
+ // Include header file
+#include "sdlang.h"
+#include "sddialog.h"
+
+////////////////////// string defines ////////////////////////////
+
+#define UNINST_LOGFILE_NAME "Uninst.isu"
+
+//////////////////// installation declarations ///////////////////
+
+ // ----- DLL prototypes -----
+
+
+ // your DLL prototypes
+
+
+ // ---- script prototypes -----
+
+ // generated
+ prototype ShowDialogs();
+ prototype MoveFileData();
+ prototype HandleMoveDataError( NUMBER );
+ prototype ProcessBeforeDataMove();
+ prototype ProcessAfterDataMove();
+ prototype SetupRegistry();
+ prototype SetupFolders();
+ prototype CleanUpInstall();
+ prototype SetupInstall();
+ prototype SetupScreen();
+ prototype CheckRequirements();
+ prototype DialogShowSdWelcome();
+ prototype DialogShowSdShowInfoList();
+ prototype DialogShowSdAskDestPath();
+ prototype DialogShowSdSetupType();
+ prototype DialogShowSdComponentDialog2();
+ prototype DialogShowSdFinishReboot();
+
+ // your prototypes
+
+
+ // ----- global variables ------
+
+ // generated
+ BOOL bWinNT, bIsShellExplorer, bInstallAborted, bIs32BitSetup;
+ STRING svDir;
+ STRING svName, svCompany, svSerial;
+ STRING szAppPath;
+ STRING svSetupType;
+
+
+ // your global variables
+
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// MAIN PROGRAM
+//
+// The setup begins here by hiding the visible setup
+// window. This is done to allow all the titles, images, etc. to
+// be established before showing the main window. The following
+// logic then performs the setup in a series of steps.
+//
+///////////////////////////////////////////////////////////////////////////////
+program
+ Disable( BACKGROUND );
+
+ CheckRequirements();
+
+ SetupInstall();
+
+ SetupScreen();
+
+ if (ShowDialogs()<0) goto end_install;
+
+ if (ProcessBeforeDataMove()<0) goto end_install;
+
+ if (MoveFileData()<0) goto end_install;
+
+ if (ProcessAfterDataMove()<0) goto end_install;
+
+ if (SetupRegistry()<0) goto end_install;
+
+ if (SetupFolders()<0) goto end_install;
+
+
+ end_install:
+
+ CleanUpInstall();
+
+ // If an unrecoverable error occurred, clean up the partial installation.
+ // Otherwise, exit normally.
+
+ if (bInstallAborted) then
+ abort;
+ endif;
+
+endprogram
+
+///////////////////////////////////////////////////////////////////////////////
+// //
+// Function: ShowDialogs //
+// //
+// Purpose: This function manages the display and navigation //
+// the standard dialogs that exist in a setup. //
+// //
+///////////////////////////////////////////////////////////////////////////////
+function ShowDialogs()
+ NUMBER nResult;
+ begin
+
+ Dlg_Start:
+ // beginning of dialogs label
+
+ Dlg_SdWelcome:
+ nResult = DialogShowSdWelcome();
+ if (nResult = BACK) goto Dlg_Start;
+
+ Dlg_SdShowInfoList:
+ nResult = DialogShowSdShowInfoList();
+ if (nResult = BACK) goto Dlg_SdWelcome;
+
+ Dlg_SdAskDestPath:
+ nResult = DialogShowSdAskDestPath();
+ if (nResult = BACK) goto Dlg_SdShowInfoList;
+
+ Dlg_SdSetupType:
+ nResult = DialogShowSdSetupType();
+ if (nResult = BACK) goto Dlg_SdAskDestPath;
+
+ Dlg_SdComponentDialog2:
+ if ((nResult = BACK) && (svSetupType != "Custom") && (svSetupType != "")) then
+ goto Dlg_SdSetupType;
+ endif;
+ nResult = DialogShowSdComponentDialog2();
+ if (nResult = BACK) goto Dlg_SdSetupType;
+
+ return 0;
+
+ end;
+
+///////////////////////////////////////////////////////////////////////////////
+// //
+// Function: ProcessBeforeDataMove //
+// //
+// Purpose: This function performs any necessary operations prior to the //
+// actual data move operation. //
+// //
+///////////////////////////////////////////////////////////////////////////////
+function ProcessBeforeDataMove()
+ STRING svLogFile;
+ NUMBER nResult;
+ begin
+
+ InstallationInfo( @COMPANY_NAME, @PRODUCT_NAME, @PRODUCT_VERSION, @PRODUCT_KEY );
+
+ svLogFile = UNINST_LOGFILE_NAME;
+
+ nResult = DeinstallStart( svDir, svLogFile, @UNINST_KEY, 0 );
+ if (nResult < 0) then
+ MessageBox( @ERROR_UNINSTSETUP, WARNING );
+ endif;
+
+ szAppPath = TARGETDIR; // TODO : if your application .exe is in a subdir of TARGETDIR then add subdir
+
+ if ((bIs32BitSetup) && (bIsShellExplorer)) then
+ RegDBSetItem( REGDB_APPPATH, szAppPath );
+ RegDBSetItem( REGDB_APPPATH_DEFAULT, szAppPath ^ @PRODUCT_KEY );
+ RegDBSetItem( REGDB_UNINSTALL_NAME, @UNINST_DISPLAY_NAME );
+ endif;
+
+ // TODO : update any items you want to process before moving the data
+ //
+
+ return 0;
+ end;
+
+///////////////////////////////////////////////////////////////////////////////
+// //
+// Function: MoveFileData //
+// //
+// Purpose: This function handles the data movement for //
+// the setup. //
+// //
+///////////////////////////////////////////////////////////////////////////////
+function MoveFileData()
+ NUMBER nResult, nDisk;
+ begin
+
+ nDisk = 1;
+ SetStatusWindow( 0, "" );
+ Disable( DIALOGCACHE );
+ Enable( STATUS );
+ StatusUpdate( ON, 100 );
+ nResult = ComponentMoveData( MEDIA, nDisk, 0 );
+
+ HandleMoveDataError( nResult );
+
+ Disable( STATUS );
+
+ return nResult;
+
+ end;
+
+
+///////////////////////////////////////////////////////////////////////////////
+// //
+// Function: HandleMoveDataError //
+// //
+// Purpose: This function handles the error (if any) during the move data //
+// operation. //
+// //
+///////////////////////////////////////////////////////////////////////////////
+function HandleMoveDataError( nResult )
+ STRING szErrMsg, svComponent , svFileGroup , svFile;
+ begin
+
+ svComponent = "";
+ svFileGroup = "";
+ svFile = "";
+
+ switch (nResult)
+ case 0:
+ return 0;
+ default:
+ ComponentError ( MEDIA , svComponent , svFileGroup , svFile , nResult );
+ szErrMsg = @ERROR_MOVEDATA + "\n\n" +
+ @ERROR_COMPONENT + " " + svComponent + "\n" +
+ @ERROR_FILEGROUP + " " + svFileGroup + "\n" +
+ @ERROR_FILE + " " + svFile;
+ SprintfBox( SEVERE, @TITLE_CAPTIONBAR, szErrMsg, nResult );
+ bInstallAborted = TRUE;
+ return nResult;
+ endswitch;
+
+ end;
+
+///////////////////////////////////////////////////////////////////////////////
+// //
+// Function: ProcessAfterDataMove //
+// //
+// Purpose: This function performs any necessary operations needed after //
+// all data has been moved. //
+// //
+///////////////////////////////////////////////////////////////////////////////
+function ProcessAfterDataMove()
+ begin
+
+ // TODO : update self-registered files and other processes that
+ // should be performed after the data has been moved.
+
+
+ return 0;
+ end;
+
+///////////////////////////////////////////////////////////////////////////////
+// //
+// Function: SetupRegistry //
+// //
+// Purpose: This function makes the registry entries for this setup. //
+// //
+///////////////////////////////////////////////////////////////////////////////
+function SetupRegistry()
+ NUMBER nResult;
+
+ begin
+
+ // TODO : Add all your registry entry keys here
+ //
+ //
+ // RegDBCreateKeyEx, RegDBSetKeyValueEx....
+ //
+
+ nResult = CreateRegistrySet( "" );
+
+ return nResult;
+ end;
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Function: SetupFolders
+//
+// Purpose: This function creates all the folders and shortcuts for the
+// setup. This includes program groups and items for Windows 3.1.
+//
+///////////////////////////////////////////////////////////////////////////////
+function SetupFolders()
+ NUMBER nResult;
+
+ begin
+
+
+ // TODO : Add all your folder (program group) along with shortcuts (program items)
+ //
+ //
+ // CreateProgramFolder, AddFolderIcon....
+ //
+
+ nResult = CreateShellObjects( "" );
+
+ return nResult;
+ end;
+
+///////////////////////////////////////////////////////////////////////////////
+// //
+// Function: CleanUpInstall //
+// //
+// Purpose: This cleans up the setup. Anything that should //
+// be released or deleted at the end of the setup should //
+// be done here. //
+// //
+///////////////////////////////////////////////////////////////////////////////
+function CleanUpInstall()
+ begin
+
+
+ if (bInstallAborted) then
+ return 0;
+ endif;
+
+ DialogShowSdFinishReboot();
+
+ if (BATCH_INSTALL) then // ensure locked files are properly written
+ CommitSharedFiles(0);
+ endif;
+
+ return 0;
+ end;
+
+///////////////////////////////////////////////////////////////////////////////
+// //
+// Function: SetupInstall //
+// //
+// Purpose: This will setup the installation. Any general initialization //
+// needed for the installation should be performed here. //
+// //
+///////////////////////////////////////////////////////////////////////////////
+function SetupInstall()
+ begin
+
+ Enable( CORECOMPONENTHANDLING );
+
+ bInstallAborted = FALSE;
+
+ if (bIs32BitSetup) then
+ svDir = "C:\\mysql"; //PROGRAMFILES ^ @COMPANY_NAME ^ @PRODUCT_NAME;
+ else
+ svDir = "C:\\mysql"; //PROGRAMFILES ^ @COMPANY_NAME16 ^ @PRODUCT_NAME16; // use shorten names
+ endif;
+
+ TARGETDIR = svDir;
+
+ SdProductName( @PRODUCT_NAME );
+
+ Enable( DIALOGCACHE );
+
+ return 0;
+ end;
+
+///////////////////////////////////////////////////////////////////////////////
+// //
+// Function: SetupScreen //
+// //
+// Purpose: This function establishes the screen look. This includes //
+// colors, fonts, and text to be displayed. //
+// //
+///////////////////////////////////////////////////////////////////////////////
+function SetupScreen()
+ begin
+
+ Enable( FULLWINDOWMODE );
+ Enable( INDVFILESTATUS );
+ SetTitle( @TITLE_MAIN, 24, WHITE );
+
+ SetTitle( @TITLE_CAPTIONBAR, 0, BACKGROUNDCAPTION ); // Caption bar text.
+
+ Enable( BACKGROUND );
+
+ Delay( 1 );
+ end;
+
+///////////////////////////////////////////////////////////////////////////////
+// //
+// Function: CheckRequirements //
+// //
+// Purpose: This function checks all minimum requirements for the //
+// application being installed. If any fail, then the user //
+// is informed and the setup is terminated. //
+// //
+///////////////////////////////////////////////////////////////////////////////
+function CheckRequirements()
+ NUMBER nvDx, nvDy, nvResult;
+ STRING svResult;
+
+ begin
+
+ bWinNT = FALSE;
+ bIsShellExplorer = FALSE;
+
+ // Check screen resolution.
+ GetExtents( nvDx, nvDy );
+
+ if (nvDy < 480) then
+ MessageBox( @ERROR_VGARESOLUTION, WARNING );
+ abort;
+ endif;
+
+ // set 'setup' operation mode
+ bIs32BitSetup = TRUE;
+ GetSystemInfo( ISTYPE, nvResult, svResult );
+ if (nvResult = 16) then
+ bIs32BitSetup = FALSE; // running 16-bit setup
+ return 0; // no additional information required
+ endif;
+
+ // --- 32-bit testing after this point ---
+
+ // Determine the target system's operating system.
+ GetSystemInfo( OS, nvResult, svResult );
+
+ if (nvResult = IS_WINDOWSNT) then
+ // Running Windows NT.
+ bWinNT = TRUE;
+
+ // Check to see if the shell being used is EXPLORER shell.
+ if (GetSystemInfo( OSMAJOR, nvResult, svResult ) = 0) then
+ if (nvResult >= 4) then
+ bIsShellExplorer = TRUE;
+ endif;
+ endif;
+
+ elseif (nvResult = IS_WINDOWS95 ) then
+ bIsShellExplorer = TRUE;
+
+ endif;
+
+end;
+
+
+///////////////////////////////////////////////////////////////////////////////
+// //
+// Function: DialogShowSdWelcome //
+// //
+// Purpose: This function handles the standard welcome dialog. //
+// //
+// //
+///////////////////////////////////////////////////////////////////////////////
+function DialogShowSdWelcome()
+ NUMBER nResult;
+ STRING szTitle, szMsg;
+ begin
+
+ szTitle = "";
+ szMsg = "";
+ nResult = SdWelcome( szTitle, szMsg );
+
+ return nResult;
+ end;
+
+
+///////////////////////////////////////////////////////////////////////////////
+// //
+// Function: DialogShowSdShowInfoList //
+// //
+// Purpose: This function displays the general information list dialog. //
+// //
+// //
+///////////////////////////////////////////////////////////////////////////////
+function DialogShowSdShowInfoList()
+ NUMBER nResult;
+ LIST list;
+ STRING szTitle, szMsg, szFile;
+ begin
+
+ szFile = SUPPORTDIR ^ "infolist.txt";
+
+ list = ListCreate( STRINGLIST );
+ ListReadFromFile( list, szFile );
+ szTitle = "";
+ szMsg = " ";
+ nResult = SdShowInfoList( szTitle, szMsg, list );
+
+ ListDestroy( list );
+
+ return nResult;
+ end;
+
+
+///////////////////////////////////////////////////////////////////////////////
+// //
+// Function: DialogShowSdAskDestPath //
+// //
+// Purpose: This function asks the user for the destination directory. //
+// //
+///////////////////////////////////////////////////////////////////////////////
+function DialogShowSdAskDestPath()
+ NUMBER nResult;
+ STRING szTitle, szMsg;
+ begin
+
+ szTitle = "";
+ szMsg = "";
+ nResult = SdAskDestPath( szTitle, szMsg, svDir, 0 );
+
+ TARGETDIR = svDir;
+
+ return nResult;
+ end;
+
+
+///////////////////////////////////////////////////////////////////////////////
+// //
+// Function: DialogShowSdSetupType //
+// //
+// Purpose: This function displays the standard setup type dialog. //
+// //
+///////////////////////////////////////////////////////////////////////////////
+function DialogShowSdSetupType()
+ NUMBER nResult, nType;
+ STRING szTitle, szMsg;
+ begin
+
+ switch (svSetupType)
+ case "Typical":
+ nType = TYPICAL;
+ case "Custom":
+ nType = CUSTOM;
+ case "Compact":
+ nType = COMPACT;
+ case "":
+ svSetupType = "Typical";
+ nType = TYPICAL;
+ endswitch;
+
+ szTitle = "";
+ szMsg = "";
+ nResult = SetupType( szTitle, szMsg, "", nType, 0 );
+
+ switch (nResult)
+ case COMPACT:
+ svSetupType = "Compact";
+ case TYPICAL:
+ svSetupType = "Typical";
+ case CUSTOM:
+ svSetupType = "Custom";
+ endswitch;
+
+ return nResult;
+ end;
+
+
+///////////////////////////////////////////////////////////////////////////////
+// //
+// Function: DialogShowSdComponentDialog2 //
+// //
+// Purpose: This function displays the custom component dialog. //
+// //
+// //
+///////////////////////////////////////////////////////////////////////////////
+function DialogShowSdComponentDialog2()
+ NUMBER nResult;
+ STRING szTitle, szMsg;
+ begin
+
+ if ((svSetupType != "Custom") && (svSetupType != "")) then
+ return 0;
+ endif;
+
+ szTitle = "";
+ szMsg = "";
+ nResult = SdComponentDialog2( szTitle, szMsg, svDir, "" );
+
+ return nResult;
+ end;
+
+
+///////////////////////////////////////////////////////////////////////////////
+// //
+// Function: DialogShowSdFinishReboot //
+// //
+// Purpose: This function will show the last dialog of the product. //
+// It will allow the user to reboot and/or show some readme text. //
+// //
+///////////////////////////////////////////////////////////////////////////////
+function DialogShowSdFinishReboot()
+ NUMBER nResult, nDefOptions;
+ STRING szTitle, szMsg1, szMsg2, szOption1, szOption2;
+ NUMBER bOpt1, bOpt2;
+ begin
+
+ if (!BATCH_INSTALL) then
+ bOpt1 = FALSE;
+ bOpt2 = FALSE;
+ szMsg1 = "";
+ szMsg2 = "";
+ szOption1 = "";
+ szOption2 = "";
+ nResult = SdFinish( szTitle, szMsg1, szMsg2, szOption1, szOption2, bOpt1, bOpt2 );
+ return 0;
+ endif;
+
+ nDefOptions = SYS_BOOTMACHINE;
+ szTitle = "";
+ szMsg1 = "";
+ szMsg2 = "";
+ nResult = SdFinishReboot( szTitle, szMsg1, nDefOptions, szMsg2, 0 );
+
+ return nResult;
+ end;
+
+ // --- include script file section ---
+
+#include "sddialog.rul"
+
+
diff --git a/VC++Files/client/mysql.dsp b/VC++Files/client/mysql.dsp
new file mode 100644
index 00000000000..1cefdd2b67b
--- /dev/null
+++ b/VC++Files/client/mysql.dsp
@@ -0,0 +1,102 @@
+# Microsoft Developer Studio Project File - Name="mysql" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=mysql - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "mysql.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "mysql.mak" CFG="mysql - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "mysql - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "mysql - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "mysql - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "release"
+# PROP Intermediate_Dir "release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /G6 /MT /W3 /WX /O2 /I "../include" /I "../" /D "NDEBUG" /D "DBUG_OFF" /D "_CONSOLE" /D "_MBCS" /D "_WINDOWS" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 mysqlclient.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"../client_release/mysql.exe" /libpath:"..\lib_release\\"
+# SUBTRACT LINK32 /incremental:yes
+
+!ELSEIF "$(CFG)" == "mysql - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "mysql___"
+# PROP BASE Intermediate_Dir "mysql___"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "debug"
+# PROP Intermediate_Dir "debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /G6 /MTd /W3 /Gm /ZI /Od /I "../include" /I "../" /D "_DEBUG" /D "SAFEMALLOC" /D "SAFE_MUTEX" /D "_CONSOLE" /D "_MBCS" /D "_WINDOWS" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 mysqlclient.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /incremental:no /debug /machine:I386 /out:"../client_debug/mysql.exe" /pdbtype:sept /libpath:"..\lib_debug\\"
+
+!ENDIF
+
+# Begin Target
+
+# Name "mysql - Win32 Release"
+# Name "mysql - Win32 Debug"
+# Begin Source File
+
+SOURCE=.\mysql.cpp
+
+!IF "$(CFG)" == "mysql - Win32 Release"
+
+# ADD CPP /Zi /O2
+
+!ELSEIF "$(CFG)" == "mysql - Win32 Debug"
+
+!ENDIF
+
+# End Source File
+# End Target
+# End Project
diff --git a/VC++Files/client/mysqladmin.dsp b/VC++Files/client/mysqladmin.dsp
new file mode 100644
index 00000000000..82794da57cb
--- /dev/null
+++ b/VC++Files/client/mysqladmin.dsp
@@ -0,0 +1,92 @@
+# Microsoft Developer Studio Project File - Name="mysqladmin" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=mysqladmin - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "mysqladmin.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "mysqladmin.mak" CFG="mysqladmin - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "mysqladmin - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "mysqladmin - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "mysqladmin - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "release"
+# PROP Intermediate_Dir "release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../" /D "NDEBUG" /D "DBUG_OFF" /D "_CONSOLE" /D "_MBCS" /D "_WINDOWS" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 mysqlclient.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"../client_release/mysqladmin.exe" /libpath:"..\lib_release\\"
+
+!ELSEIF "$(CFG)" == "mysqladmin - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "mysqladm"
+# PROP BASE Intermediate_Dir "mysqladm"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "debug"
+# PROP Intermediate_Dir "debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /G6 /MTd /W3 /Gm /ZI /Od /I "../include" /I "../" /D "_DEBUG" /D "SAFEMALLOC" /D "SAFE_MUTEX" /D "_CONSOLE" /D "_MBCS" /D "_WINDOWS" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 mysqlclient.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /incremental:no /debug /machine:I386 /out:"../client_debug/mysqladmin.exe" /pdbtype:sept /libpath:"..\lib_debug\\"
+
+!ENDIF
+
+# Begin Target
+
+# Name "mysqladmin - Win32 Release"
+# Name "mysqladmin - Win32 Debug"
+# Begin Source File
+
+SOURCE=.\mysqladmin.c
+# End Source File
+# End Target
+# End Project
diff --git a/VC++Files/client/mysqlclient.dsp b/VC++Files/client/mysqlclient.dsp
new file mode 100644
index 00000000000..376febc6d36
--- /dev/null
+++ b/VC++Files/client/mysqlclient.dsp
@@ -0,0 +1,494 @@
+# Microsoft Developer Studio Project File - Name="mysqlclient" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=mysqlclient - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "mysqlclient.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "mysqlclient.mak" CFG="mysqlclient - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "mysqlclient - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "mysqlclient - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "mysqlclient - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "release"
+# PROP Intermediate_Dir "release"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../" /D "NDEBUG" /D "DBUG_OFF" /D "_WINDOWS" /D "USE_TLS" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409
+# ADD RSC /l 0x409
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\lib_release\mysqlclient.lib"
+
+!ELSEIF "$(CFG)" == "mysqlclient - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "debug"
+# PROP Intermediate_Dir "debug"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /Z7 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /G6 /MTd /W3 /ZI /Od /I "../include" /I "../" /D "_DEBUG" /D "SAFEMALLOC" /D "SAFE_MUTEX" /D "_WINDOWS" /D "USE_TLS" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409
+# ADD RSC /l 0x409
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\lib_debug\mysqlclient.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "mysqlclient - Win32 Release"
+# Name "mysqlclient - Win32 Debug"
+# Begin Source File
+
+SOURCE=..\mysys\array.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\strings\bchange.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\strings\bmove.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\strings\bmove_upp.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\charset.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\completion_hash.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\completion_hash.h
+# End Source File
+# Begin Source File
+
+SOURCE="..\strings\ctype-big5.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\strings\ctype-czech.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\strings\ctype-euc_kr.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\strings\ctype-gb2312.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\strings\ctype-gbk.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\strings\ctype-latin1_de.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\strings\ctype-sjis.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\strings\ctype-tis620.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\strings\ctype-ujis.c"
+# End Source File
+# Begin Source File
+
+SOURCE=..\strings\ctype.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\dbug\dbug.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\default.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\libmysql\errmsg.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\errors.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\libmysql\get_password.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\getopt.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\getopt1.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\getvar.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\strings\int2str.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\strings\is_prefix.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\libmysql\libmysql.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\list.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\strings\llstr.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\strings\longlong2str.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\mf_cache.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\mf_casecnv.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\mf_dirname.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\mf_fn_ext.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\mf_format.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\mf_iocache.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\mf_loadpath.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\mf_pack.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\mf_path.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\mf_tempfile.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\mf_unixpath.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\mf_wcomp.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\mulalloc.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\my_alloc.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\my_compress.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\my_create.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\my_delete.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\my_div.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\my_error.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\my_fopen.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\my_fstream.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\my_getwd.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\my_init.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\my_lib.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\my_malloc.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\my_messnc.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\my_net.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\my_once.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\my_open.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\my_pread.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\my_pthread.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\my_read.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\my_realloc.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\my_rename.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\my_seek.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\my_static.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\my_symlink.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\my_symlink2.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\my_tempnam.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\my_thr_init.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\my_wincond.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\my_winthread.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\my_write.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mysys_priv.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\libmysql\net.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\libmysql\password.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\readline.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\safemalloc.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\select_test.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\sql_string.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\sql_string.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\strings\str2int.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\strings\strcend.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\strings\strcont.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\strings\strend.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\strings\strfill.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\string.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\strings\strinstr.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\strings\strmake.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\strings\strmov.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\strings\strnlen.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\strings\strnmov.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\strings\strtoll.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\strings\strtoull.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\strings\strxmov.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\thr_mutex.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\typelib.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\vio\vio.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\vio\viosocket.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\vio\viossl.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\vio\viosslfactories.c
+# End Source File
+# End Target
+# End Project
diff --git a/VC++Files/client/mysqlclient.dsw b/VC++Files/client/mysqlclient.dsw
new file mode 100644
index 00000000000..9c08bbf0407
--- /dev/null
+++ b/VC++Files/client/mysqlclient.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 5.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "mysqlclient"=".\mysqlclient.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/VC++Files/client/mysqldump.dsp b/VC++Files/client/mysqldump.dsp
new file mode 100644
index 00000000000..dcf1c1435a6
--- /dev/null
+++ b/VC++Files/client/mysqldump.dsp
@@ -0,0 +1,102 @@
+# Microsoft Developer Studio Project File - Name="mysqldump" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=mysqldump - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "mysqldump.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "mysqldump.mak" CFG="mysqldump - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "mysqldump - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "mysqldump - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "mysqldump - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "release"
+# PROP Intermediate_Dir "release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /G6 /MT /W3 /GX- /O2 /I "../include" /I "../" /D "NDEBUG" /D "DBUG_OFF" /D "_CONSOLE" /D "_MBCS" /D "_WINDOWS" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 mysqlclient.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"../client_release/mysqldump.exe" /libpath:"..\lib_release\\"
+
+!ELSEIF "$(CFG)" == "mysqldump - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "mysqldum"
+# PROP BASE Intermediate_Dir "mysqldum"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "debug"
+# PROP Intermediate_Dir "debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /G6 /MTd /W3 /Gm /GX- /ZI /Od /I "../include" /I "../" /D "_DEBUG" /D "SAFEMALLOC" /D "SAFE_MUTEX" /D "_CONSOLE" /D "_MBCS" /D "_WINDOWS" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 mysqlclient.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"../client_debug/mysqldump.exe" /pdbtype:sept /libpath:"..\lib_debug\\"
+
+!ENDIF
+
+# Begin Target
+
+# Name "mysqldump - Win32 Release"
+# Name "mysqldump - Win32 Debug"
+# Begin Source File
+
+SOURCE=.\mysqldump.c
+
+!IF "$(CFG)" == "mysqldump - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqldump - Win32 Debug"
+
+# ADD CPP /W3
+# SUBTRACT CPP /YX
+
+!ENDIF
+
+# End Source File
+# End Target
+# End Project
diff --git a/VC++Files/client/mysqlimport.dsp b/VC++Files/client/mysqlimport.dsp
new file mode 100644
index 00000000000..f10c1f90f58
--- /dev/null
+++ b/VC++Files/client/mysqlimport.dsp
@@ -0,0 +1,93 @@
+# Microsoft Developer Studio Project File - Name="mysqlimport" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=mysqlimport - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "mysqlimport.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "mysqlimport.mak" CFG="mysqlimport - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "mysqlimport - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "mysqlimport - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "mysqlimport - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "release"
+# PROP Intermediate_Dir "release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /G6 /MT /W3 /GX- /O2 /I "../include" /I "../" /D "NDEBUG" /D "DBUG_OFF" /D "_CONSOLE" /D "_MBCS" /D "_WINDOWS" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 mysqlclient.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"../client_release/mysqlimport.exe" /libpath:"..\lib_release\\"
+# SUBTRACT LINK32 /incremental:yes
+
+!ELSEIF "$(CFG)" == "mysqlimport - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "mysqlimp"
+# PROP BASE Intermediate_Dir "mysqlimp"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "debug"
+# PROP Intermediate_Dir "debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /G6 /MTd /W3 /Gm /GX- /ZI /Od /I "../include" /I "../" /D "_DEBUG" /D "SAFEMALLOC" /D "SAFE_MUTEX" /D "_CONSOLE" /D "_MBCS" /D "_WINDOWS" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 mysqlclient.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib setargv.obj /nologo /subsystem:console /incremental:no /debug /machine:I386 /out:"../client_debug/mysqlimport.exe" /pdbtype:sept /libpath:"..\lib_debug\\"
+
+!ENDIF
+
+# Begin Target
+
+# Name "mysqlimport - Win32 Release"
+# Name "mysqlimport - Win32 Debug"
+# Begin Source File
+
+SOURCE=.\mysqlimport.c
+# End Source File
+# End Target
+# End Project
diff --git a/VC++Files/client/mysqlshow.dsp b/VC++Files/client/mysqlshow.dsp
new file mode 100644
index 00000000000..dd0fc09c70f
--- /dev/null
+++ b/VC++Files/client/mysqlshow.dsp
@@ -0,0 +1,92 @@
+# Microsoft Developer Studio Project File - Name="mysqlshow" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=mysqlshow - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "mysqlshow.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "mysqlshow.mak" CFG="mysqlshow - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "mysqlshow - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "mysqlshow - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "mysqlshow - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "release"
+# PROP Intermediate_Dir "release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /G6 /MT /W3 /GX- /O2 /I "../include" /I "../" /D "NDEBUG" /D "DBUG_OFF" /D "_CONSOLE" /D "_MBCS" /D "_WINDOWS" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 mysqlclient.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"../client_release/mysqlshow.exe" /libpath:"..\lib_release\\"
+
+!ELSEIF "$(CFG)" == "mysqlshow - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "mysqlsho"
+# PROP BASE Intermediate_Dir "mysqlsho"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "debug"
+# PROP Intermediate_Dir "debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /G6 /MTd /W3 /Gm /GX- /ZI /Od /I "../include" /I "../" /D "_DEBUG" /D "SAFEMALLOC" /D "SAFE_MUTEX" /D "_CONSOLE" /D "_MBCS" /D "_WINDOWS" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 mysqlclient.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"../client_debug/mysqlshow.exe" /pdbtype:sept /libpath:"..\lib_debug\\"
+
+!ENDIF
+
+# Begin Target
+
+# Name "mysqlshow - Win32 Release"
+# Name "mysqlshow - Win32 Debug"
+# Begin Source File
+
+SOURCE=.\mysqlshow.c
+# End Source File
+# End Target
+# End Project
diff --git a/VC++Files/dbug/dbug.dsp b/VC++Files/dbug/dbug.dsp
new file mode 100644
index 00000000000..11721da98d6
--- /dev/null
+++ b/VC++Files/dbug/dbug.dsp
@@ -0,0 +1,98 @@
+# Microsoft Developer Studio Project File - Name="dbug" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=dbug - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "dbug.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "dbug.mak" CFG="dbug - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "dbug - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "dbug - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "dbug - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "release"
+# PROP Intermediate_Dir "release"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /D "NDEBUG" /D "DBUG_OFF" /D "_WINDOWS" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409
+# ADD RSC /l 0x409
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\lib_release\dbug.lib"
+
+!ELSEIF "$(CFG)" == "dbug - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "debug"
+# PROP Intermediate_Dir "debug"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /Z7 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /G6 /MTd /W3 /Z7 /Od /Gf /I "../include" /D "__WIN32__" /D "_DEBUG" /D "SAFEMALLOC" /D "SAFE_MUTEX" /D "_WINDOWS" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409
+# ADD RSC /l 0x409
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\lib_debug\dbug.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "dbug - Win32 Release"
+# Name "dbug - Win32 Debug"
+# Begin Source File
+
+SOURCE=.\dbug.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\factorial.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\sanity.c
+# End Source File
+# End Target
+# End Project
diff --git a/VC++Files/dbug/dbug.dsw b/VC++Files/dbug/dbug.dsw
new file mode 100644
index 00000000000..a0cd4da7891
--- /dev/null
+++ b/VC++Files/dbug/dbug.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 5.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "dbug"=".\dbug.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/VC++Files/heap/heap.dsp b/VC++Files/heap/heap.dsp
new file mode 100644
index 00000000000..c21c3139519
--- /dev/null
+++ b/VC++Files/heap/heap.dsp
@@ -0,0 +1,195 @@
+# Microsoft Developer Studio Project File - Name="heap" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=heap - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "heap.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "heap.mak" CFG="heap - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "heap - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "heap - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "heap - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "release"
+# PROP Intermediate_Dir "release"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /D "NDEBUG" /D "DBUG_OFF" /D "_WINDOWS" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409
+# ADD RSC /l 0x409
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\lib_release\heap.lib"
+
+!ELSEIF "$(CFG)" == "heap - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "debug"
+# PROP Intermediate_Dir "debug"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /Z7 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /G6 /MTd /W3 /Z7 /Od /Gf /I "../include" /D "_DEBUG" /D "SAFEMALLOC" /D "SAFE_MUTEX" /D "_WINDOWS" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409
+# ADD RSC /l 0x409
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\lib_debug\heap.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "heap - Win32 Release"
+# Name "heap - Win32 Debug"
+# Begin Source File
+
+SOURCE=.\_check.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\_rectest.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\heapdef.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\hp_block.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\hp_clear.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\hp_close.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\hp_create.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\hp_delete.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\hp_extra.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\hp_hash.c
+
+!IF "$(CFG)" == "heap - Win32 Release"
+
+!ELSEIF "$(CFG)" == "heap - Win32 Debug"
+
+# SUBTRACT CPP /YX
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\hp_info.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\hp_open.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\hp_panic.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\hp_rename.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\hp_rfirst.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\hp_rkey.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\hp_rlast.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\hp_rnext.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\hp_rprev.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\hp_rrnd.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\hp_rsame.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\hp_scan.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\hp_static.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\hp_update.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\hp_write.c
+# End Source File
+# End Target
+# End Project
diff --git a/VC++Files/innobase/innobase.dsp b/VC++Files/innobase/innobase.dsp
new file mode 100644
index 00000000000..5159d513e87
--- /dev/null
+++ b/VC++Files/innobase/innobase.dsp
@@ -0,0 +1,441 @@
+# Microsoft Developer Studio Project File - Name="innobase" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=innobase - Win32 Max
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "innobase.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "innobase.mak" CFG="innobase - Win32 Max"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "innobase - Win32 Max" (based on "Win32 (x86) Static Library")
+!MESSAGE "innobase - Win32 Max nt" (based on "Win32 (x86) Static Library")
+!MESSAGE "innobase - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "innobase - Win32 Max"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "innobase___Win32_Max"
+# PROP BASE Intermediate_Dir "innobase___Win32_Max"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "innobase___Win32_Max"
+# PROP Intermediate_Dir "innobase___Win32_Max"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /G6 /MT /W3 /GX /O2 /I "../innobase/include" /D "NDEBUG" /D "_LIB" /D "_WIN32" /D "__NT__" /D "WIN32" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /G6 /MT /W3 /GX /O2 /I "../innobase/include" /I "../include" /D "NDEBUG" /D "_LIB" /D "_WIN32" /D "WIN32" /D "_MBCS" /D "MYSQL_SERVER" /YX /FD /c
+# ADD BASE RSC /l 0x416 /d "NDEBUG"
+# ADD RSC /l 0x416 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo /out:"..\lib_release\innobase-nt.lib"
+# ADD LIB32 /nologo /out:"..\lib_release\innodb.lib"
+
+!ELSEIF "$(CFG)" == "innobase - Win32 Max nt"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "innobase___Win32_Max_nt"
+# PROP BASE Intermediate_Dir "innobase___Win32_Max_nt"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "innobase___Win32_Max_nt"
+# PROP Intermediate_Dir "innobase___Win32_Max_nt"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /G6 /MT /W3 /GX /O2 /I "../innobase/include" /D "NDEBUG" /D "_LIB" /D "_WIN32" /D "__NT__" /D "WIN32" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /G6 /MT /W3 /GX /O2 /I "../innobase/include" /I "../include" /D "NDEBUG" /D "_LIB" /D "_WIN32" /D "__NT__" /D "WIN32" /D "_MBCS" /D "MYSQL_SERVER" /YX /FD /c
+# ADD BASE RSC /l 0x416 /d "NDEBUG"
+# ADD RSC /l 0x416 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo /out:"..\lib_release\innobase-nt.lib"
+# ADD LIB32 /nologo /out:"..\lib_release\innodb-nt.lib"
+
+!ELSEIF "$(CFG)" == "innobase - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "innobase___Win32_Debug"
+# PROP BASE Intermediate_Dir "innobase___Win32_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "innobase___Win32_Debug"
+# PROP Intermediate_Dir "innobase___Win32_Debug"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /G6 /MT /W3 /GX /O2 /I "../innobase/include" /D "NDEBUG" /D "_LIB" /D "_WIN32" /D "__NT__" /D "WIN32" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /G6 /MTd /W3 /GX /Z7 /O2 /I "../innobase/include" /I "../include" /D "NDEBUG" /D "_LIB" /D "_WIN32" /D "__NT__" /D "WIN32" /D "_MBCS" /D "MYSQL_SERVER" /YX /FD /c
+# ADD BASE RSC /l 0x416 /d "NDEBUG"
+# ADD RSC /l 0x416 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo /out:"..\lib_release\innobase-nt.lib"
+# ADD LIB32 /nologo /out:"..\lib_debug\innodb.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "innobase - Win32 Max"
+# Name "innobase - Win32 Max nt"
+# Name "innobase - Win32 Debug"
+# Begin Source File
+
+SOURCE=.\btr\btr0btr.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\btr\btr0cur.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\btr\btr0pcur.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\btr\btr0sea.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\buf\buf0buf.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\buf\buf0flu.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\buf\buf0lru.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\buf\buf0rea.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\com\com0com.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\com\com0shm.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\data\data0data.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\data\data0type.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\dict\dict0boot.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\dict\dict0crea.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\dict\dict0dict.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\dict\dict0load.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\dict\dict0mem.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\dyn\dyn0dyn.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\eval\eval0eval.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\eval\eval0proc.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\fil\fil0fil.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\fsp\fsp0fsp.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\fut\fut0fut.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\fut\fut0lst.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\ha\ha0ha.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\ha\hash0hash.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\ibuf\ibuf0ibuf.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\pars\lexyy.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\lock\lock0lock.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\log\log0log.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\log\log0recv.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mach\mach0data.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mem\mem0mem.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mem\mem0pool.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mtr\mtr0log.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mtr\mtr0mtr.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\odbc\odbc0odbc.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\os\os0file.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\os\os0proc.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\os\os0shm.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\os\os0sync.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\os\os0thread.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\page\page0cur.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\page\page0page.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\pars\pars0grm.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\pars\pars0opt.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\pars\pars0pars.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\pars\pars0sym.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\que\que0que.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\read\read0read.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\rem\rem0cmp.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\rem\rem0rec.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\row\row0ins.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\row\row0mysql.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\row\row0purge.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\row\row0row.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\row\row0sel.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\row\row0uins.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\row\row0umod.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\row\row0undo.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\row\row0upd.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\row\row0vers.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\srv\srv0que.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\srv\srv0srv.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\srv\srv0start.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\sync\sync0arr.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\sync\sync0ipm.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\sync\sync0rw.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\sync\sync0sync.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\thr\thr0loc.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\trx\trx0purge.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\trx\trx0rec.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\trx\trx0roll.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\trx\trx0rseg.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\trx\trx0sys.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\trx\trx0trx.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\trx\trx0undo.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\usr\usr0sess.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\ut\ut0byte.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\ut\ut0dbg.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\ut\ut0mem.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\ut\ut0rnd.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\ut\ut0ut.c
+# End Source File
+# End Target
+# End Project
diff --git a/VC++Files/isam/isam.dsp b/VC++Files/isam/isam.dsp
new file mode 100644
index 00000000000..32832919654
--- /dev/null
+++ b/VC++Files/isam/isam.dsp
@@ -0,0 +1,206 @@
+# Microsoft Developer Studio Project File - Name="isam" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=isam - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "isam.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "isam.mak" CFG="isam - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "isam - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "isam - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "isam - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "release"
+# PROP Intermediate_Dir "release"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /D "NDEBUG" /D "DBUG_OFF" /D "_WINDOWS" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409
+# ADD RSC /l 0x409
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\lib_release\isam.lib"
+
+!ELSEIF "$(CFG)" == "isam - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "debug"
+# PROP Intermediate_Dir "debug"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /Z7 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /G6 /MTd /W3 /Z7 /Od /Gf /I "../include" /D "_DEBUG" /D "SAFEMALLOC" /D "SAFE_MUTEX" /D "_WINDOWS" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409
+# ADD RSC /l 0x409
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\lib_Debug\isam.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "isam - Win32 Release"
+# Name "isam - Win32 Debug"
+# Begin Source File
+
+SOURCE=.\_cache.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\_dbug.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\_dynrec.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\_key.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\_locking.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\_packrec.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\_page.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\_search.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\_statrec.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\changed.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\close.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\create.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\delete.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\extra.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\info.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\log.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\open.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\panic.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\range.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\rfirst.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\rkey.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\rlast.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\rnext.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\rprev.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\rrnd.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\rsame.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\rsamepos.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\static.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\update.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\write.c
+# End Source File
+# End Target
+# End Project
diff --git a/VC++Files/isam/isam.dsw b/VC++Files/isam/isam.dsw
new file mode 100644
index 00000000000..6874c8cf4c3
--- /dev/null
+++ b/VC++Files/isam/isam.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 5.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "isam"=".\isam.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/VC++Files/isamchk/isamchk.dsp b/VC++Files/isamchk/isamchk.dsp
new file mode 100644
index 00000000000..7b9c03f23f4
--- /dev/null
+++ b/VC++Files/isamchk/isamchk.dsp
@@ -0,0 +1,98 @@
+# Microsoft Developer Studio Project File - Name="isamchk" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=isamchk - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "isamchk.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "isamchk.mak" CFG="isamchk - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "isamchk - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "isamchk - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "isamchk - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "release"
+# PROP Intermediate_Dir "release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../isam" /D "NDEBUG" /D "DBUG_OFF" /D "_CONSOLE" /D "_MBCS" /D "_WINDOWS" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x41d /d "NDEBUG"
+# ADD RSC /l 0x41d /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib setargv.obj /nologo /subsystem:console /machine:I386 /out:"../client_release/isamchk.exe"
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF "$(CFG)" == "isamchk - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "isamchk_"
+# PROP BASE Intermediate_Dir "isamchk_"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "debug"
+# PROP Intermediate_Dir "debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /G6 /MTd /W3 /Gm /ZI /Od /I "../include" /I "../isam" /D "_DEBUG" /D "SAFEMALLOC" /D "SAFE_MUTEX" /D "_CONSOLE" /D "_MBCS" /D "_WINDOWS" /FD /c
+# SUBTRACT CPP /Fr /YX
+# ADD BASE RSC /l 0x41d /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib wsock32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib setargv.obj /nologo /subsystem:console /incremental:no /debug /machine:I386 /out:"../client_debug/isamchk.exe" /pdbtype:sept
+# SUBTRACT LINK32 /verbose /pdb:none
+
+!ENDIF
+
+# Begin Target
+
+# Name "isamchk - Win32 Release"
+# Name "isamchk - Win32 Debug"
+# Begin Source File
+
+SOURCE=..\isam\isamchk.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\isam\sort.c
+# End Source File
+# End Target
+# End Project
diff --git a/VC++Files/libmysql/libmySQL.dsp b/VC++Files/libmysql/libmySQL.dsp
new file mode 100644
index 00000000000..9ea68943a97
--- /dev/null
+++ b/VC++Files/libmysql/libmySQL.dsp
@@ -0,0 +1,465 @@
+# Microsoft Developer Studio Project File - Name="libmySQL" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=libmySQL - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "libmySQL.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "libmySQL.mak" CFG="libmySQL - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "libmySQL - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "libmySQL - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "libmySQL - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "release"
+# PROP Intermediate_Dir "release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /G6 /MT /W3 /O2 /I "." /I "..\include" /D "NDEBUG" /D "DBUG_OFF" /D "_WINDOWS" /D "USE_TLS" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386
+# ADD LINK32 wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386 /def:"libmysql.def" /out:"../lib_release/libmySQL.dll" /libpath:"." /libpath:"..\lib_release"
+# SUBTRACT LINK32 /pdb:none
+# Begin Special Build Tool
+SOURCE="$(InputPath)"
+PostBuild_Desc=Move DLL export lib
+PostBuild_Cmds=copy release\libmysql.lib ..\lib_release
+# End Special Build Tool
+
+!ELSEIF "$(CFG)" == "libmySQL - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "debug"
+# PROP Intermediate_Dir "debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /G6 /MTd /W3 /Gm /ZI /Od /I "." /I "..\include" /D "_DEBUG" /D "_WINDOWS" /D "SAFE_MUTEX" /D "USE_TLS" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 zlib.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /incremental:no /map /debug /machine:I386 /def:"libmysql.def" /out:"../lib_debug/libmySQL.dll" /pdbtype:sept /libpath:"." /libpath:"..\lib_debug"
+# SUBTRACT LINK32 /pdb:none
+# Begin Special Build Tool
+SOURCE="$(InputPath)"
+PostBuild_Desc=Move DLL export lib
+PostBuild_Cmds=copy ..\lib_debug\libmysql.dll C:\winnt\system32 copy debug\libmysql.lib ..\lib_debug
+# End Special Build Tool
+
+!ENDIF
+
+# Begin Target
+
+# Name "libmySQL - Win32 Release"
+# Name "libmySQL - Win32 Debug"
+# Begin Source File
+
+SOURCE=..\mysys\array.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\strings\bchange.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\strings\bmove.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\strings\bmove_upp.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\charset.c
+# End Source File
+# Begin Source File
+
+SOURCE="..\strings\ctype-big5.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\strings\ctype-czech.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\strings\ctype-euc_kr.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\strings\ctype-gb2312.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\strings\ctype-gbk.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\strings\ctype-latin1_de.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\strings\ctype-sjis.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\strings\ctype-tis620.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\strings\ctype-ujis.c"
+# End Source File
+# Begin Source File
+
+SOURCE=..\strings\ctype.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\dbug\dbug.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\default.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\dll.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\errmsg.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\errors.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\get_password.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\strings\int2str.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\strings\is_prefix.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\libmysql.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\Libmysql.def
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\list.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\strings\llstr.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\strings\longlong2str.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\mf_casecnv.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\mf_dirname.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\mf_fn_ext.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\mf_format.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\mf_loadpath.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\mf_pack.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\mf_unixpath.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\mf_wcomp.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\mulalloc.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\my_alloc.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\my_compress.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\my_create.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\my_delete.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\my_div.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\my_error.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\my_fopen.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\my_fstream.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\my_getwd.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\my_init.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\my_lib.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\my_malloc.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\my_messnc.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\my_net.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\my_once.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\my_open.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\my_pthread.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\my_read.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\my_realloc.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\my_rename.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\my_static.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\my_symlink.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\my_symlink2.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\my_tempnam.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\my_thr_init.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\my_wincond.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\my_winthread.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\my_write.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\client\mysys_priv.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\net.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\password.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\safemalloc.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\client\select_test.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\client\sql_string.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\client\sql_string.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\strings\str2int.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\strings\strcend.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\strings\strcont.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\strings\strend.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\strings\strfill.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\string.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\strings\strinstr.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\strings\strmake.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\strings\strmov.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\strings\strnlen.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\strings\strnmov.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\strings\strxmov.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\thr_mutex.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\typelib.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\vio\vio.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\vio\viosocket.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\vio\viossl.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\vio\viosslfactories.c
+# End Source File
+# End Target
+# End Project
diff --git a/VC++Files/libmysql/libmysql.dsw b/VC++Files/libmysql/libmysql.dsw
new file mode 100644
index 00000000000..fe121fa65cc
--- /dev/null
+++ b/VC++Files/libmysql/libmysql.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 5.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "libmySQL"=".\libmySQL.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/VC++Files/libmysqltest/myTest.dsp b/VC++Files/libmysqltest/myTest.dsp
new file mode 100644
index 00000000000..fec250e7a40
--- /dev/null
+++ b/VC++Files/libmysqltest/myTest.dsp
@@ -0,0 +1,92 @@
+# Microsoft Developer Studio Project File - Name="myTest" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=myTest - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "myTest.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "myTest.mak" CFG="myTest - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "myTest - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "myTest - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "myTest - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "release"
+# PROP Intermediate_Dir "release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /G6 /W3 /O2 /I "..\include" /D "NDEBUG" /D "DBUG_UFF" /D "_CONSOLE" /D "_MBCS" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 libmysql.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /libpath:"..\lib_release"
+
+!ELSEIF "$(CFG)" == "myTest - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "debug"
+# PROP Intermediate_Dir "debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /G6 /MTd /W3 /Gm /ZI /Od /I "..\include" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FD /c
+# SUBTRACT CPP /Fr /YX
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 libmysql.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /incremental:no /debug /machine:I386 /pdbtype:sept /libpath:"..\lib_debug"
+
+!ENDIF
+
+# Begin Target
+
+# Name "myTest - Win32 Release"
+# Name "myTest - Win32 Debug"
+# Begin Source File
+
+SOURCE=.\Mytest.c
+# End Source File
+# End Target
+# End Project
diff --git a/VC++Files/libmysqltest/mytest.dsw b/VC++Files/libmysqltest/mytest.dsw
new file mode 100644
index 00000000000..621899eb4d0
--- /dev/null
+++ b/VC++Files/libmysqltest/mytest.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 5.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "myTest"=".\myTest.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/VC++Files/merge/merge.dsp b/VC++Files/merge/merge.dsp
new file mode 100644
index 00000000000..cb6042e6b68
--- /dev/null
+++ b/VC++Files/merge/merge.dsp
@@ -0,0 +1,142 @@
+# Microsoft Developer Studio Project File - Name="merge" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=merge - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "merge.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "merge.mak" CFG="merge - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "merge - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "merge - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "merge - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "release"
+# PROP Intermediate_Dir "release"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /D "NDEBUG" /D "DBUG_OFF" /D "_WINDOWS" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409
+# ADD RSC /l 0x409
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\lib_release\merge.lib"
+
+!ELSEIF "$(CFG)" == "merge - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "debug"
+# PROP Intermediate_Dir "debug"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /Z7 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /G6 /MTd /W3 /Z7 /Od /Gf /I "../include" /D "_DEBUG" /D "SAFEMALLOC" /D "SAFE_MUTEX" /D "_WINDOWS" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409
+# ADD RSC /l 0x409
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\lib_debug\merge.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "merge - Win32 Release"
+# Name "merge - Win32 Debug"
+# Begin Source File
+
+SOURCE=.\mrg_close.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mrg_create.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mrg_def.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\mrg_delete.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mrg_extra.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mrg_info.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mrg_locking.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mrg_open.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mrg_panic.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mrg_rrnd.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mrg_rsame.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mrg_static.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mrg_update.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mrgdef.h
+# End Source File
+# End Target
+# End Project
diff --git a/VC++Files/merge/merge.dsw b/VC++Files/merge/merge.dsw
new file mode 100644
index 00000000000..a2d5ccb2ff2
--- /dev/null
+++ b/VC++Files/merge/merge.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 5.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "merge"=".\merge.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/VC++Files/myisam/myisam.dsp b/VC++Files/myisam/myisam.dsp
new file mode 100644
index 00000000000..5c13f5eb206
--- /dev/null
+++ b/VC++Files/myisam/myisam.dsp
@@ -0,0 +1,292 @@
+# Microsoft Developer Studio Project File - Name="myisam" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=myisam - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "myisam.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "myisam.mak" CFG="myisam - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "myisam - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "myisam - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "myisam - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "release"
+# PROP Intermediate_Dir "release"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /D "NDEBUG" /D "DBUG_OFF" /D "_WINDOWS" /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\lib_release\myisam.lib"
+
+!ELSEIF "$(CFG)" == "myisam - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "debug"
+# PROP Intermediate_Dir "debug"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD CPP /nologo /G6 /MTd /W3 /Z7 /Od /Gf /I "../include" /D "_DEBUG" /D "SAFEMALLOC" /D "SAFE_MUTEX" /D "_WINDOWS" /Fo".\Debug/" /Fd".\Debug/" /FD /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\lib_Debug\myisam.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "myisam - Win32 Release"
+# Name "myisam - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\ft_boolean_search.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\ft_eval.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\ft_nlq_search.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\ft_parser.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\ft_search.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\ft_static.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\ft_stem.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\ft_stopwords.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\ft_update.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mi_cache.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mi_changed.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mi_check.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mi_checksum.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mi_close.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mi_create.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mi_dbug.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mi_delete.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mi_delete_all.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mi_delete_table.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mi_dynrec.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mi_extra.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mi_info.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mi_key.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mi_locking.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mi_log.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mi_open.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mi_packrec.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mi_page.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mi_panic.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mi_range.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mi_rename.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mi_rfirst.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mi_rkey.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mi_rlast.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mi_rnext.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mi_rnext_same.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mi_rprev.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mi_rrnd.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mi_rsame.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mi_rsamepos.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mi_scan.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mi_search.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mi_static.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mi_statrec.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mi_unique.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mi_update.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mi_write.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\sort.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\ft_eval.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\myisamdef.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/VC++Files/myisamchk/myisamchk.dsp b/VC++Files/myisamchk/myisamchk.dsp
new file mode 100644
index 00000000000..7f0459d21d0
--- /dev/null
+++ b/VC++Files/myisamchk/myisamchk.dsp
@@ -0,0 +1,104 @@
+# Microsoft Developer Studio Project File - Name="myisamchk" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=myisamchk - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "myisamchk.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "myisamchk.mak" CFG="myisamchk - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "myisamchk - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "myisamchk - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "myisamchk - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "release"
+# PROP Intermediate_Dir "release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../myisam" /D "NDEBUG" /D "DBUG_OFF" /D "_CONSOLE" /D "_MBCS" /D "_WINDOWS" /FR /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib uuid.lib setargv.obj /nologo /subsystem:console /machine:I386 /out:"../client_release/myisamchk.exe"
+
+!ELSEIF "$(CFG)" == "myisamchk - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "debug"
+# PROP Intermediate_Dir "debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /G6 /MTd /W3 /Z7 /Od /I "../include" /I "../myisam" /D "_DEBUG" /D "SAFEMALLOC" /D "SAFE_MUTEX" /D "_CONSOLE" /D "_MBCS" /D "_WINDOWS" /FD /c
+# SUBTRACT CPP /Fr
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib wsock32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib setargv.obj /nologo /subsystem:console /incremental:no /debug /machine:I386 /out:"../client_debug/myisamchk.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "myisamchk - Win32 Release"
+# Name "myisamchk - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\myisam\myisamchk.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/VC++Files/myisamlog/myisamlog.dsp b/VC++Files/myisamlog/myisamlog.dsp
new file mode 100644
index 00000000000..efc43914759
--- /dev/null
+++ b/VC++Files/myisamlog/myisamlog.dsp
@@ -0,0 +1,105 @@
+# Microsoft Developer Studio Project File - Name="myisamlog" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=myisamlog - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "myisamlog.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "myisamlog.mak" CFG="myisamlog - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "myisamlog - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "myisamlog - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "myisamlog - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../myisam" /D "NDEBUG" /D "DBUG_OFF" /D "_CONSOLE" /D "_MBCS" /D "_WINDOWS" /FR /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib uuid.lib setargv.obj /nologo /subsystem:console /pdb:"release/myisamchk.pdb" /machine:I386 /out:"../client_release/myisamlog.exe"
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF "$(CFG)" == "myisamlog - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /G6 /MTd /W3 /Z7 /Od /I "../include" /I "../myisam" /D "_DEBUG" /D "SAFEMALLOC" /D "SAFE_MUTEX" /D "_CONSOLE" /D "_MBCS" /D "_WINDOWS" /FD /c
+# SUBTRACT CPP /Fr
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib wsock32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib setargv.obj /nologo /subsystem:console /incremental:no /pdb:"debug/myisamchk.pdb" /debug /machine:I386 /out:"../client_debug/myisamlog.exe" /pdbtype:sept
+# SUBTRACT LINK32 /pdb:none
+
+!ENDIF
+
+# Begin Target
+
+# Name "myisamlog - Win32 Release"
+# Name "myisamlog - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\myisam\myisamlog.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/VC++Files/myisammrg/myisammrg.dsp b/VC++Files/myisammrg/myisammrg.dsp
new file mode 100644
index 00000000000..e91d1f4e696
--- /dev/null
+++ b/VC++Files/myisammrg/myisammrg.dsp
@@ -0,0 +1,173 @@
+# Microsoft Developer Studio Project File - Name="myisammrg" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=myisammrg - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "myisammrg.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "myisammrg.mak" CFG="myisammrg - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "myisammrg - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "myisammrg - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "myisammrg - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "release"
+# PROP Intermediate_Dir "release"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /D "NDEBUG" /D "DBUG_OFF" /D "_WINDOWS" /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\lib_release\myisammrg.lib"
+
+!ELSEIF "$(CFG)" == "myisammrg - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "debug"
+# PROP Intermediate_Dir "debug"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD CPP /nologo /G6 /MTd /W3 /Z7 /Od /Gf /I "../include" /D "_DEBUG" /D "SAFEMALLOC" /D "SAFE_MUTEX" /D "_WINDOWS" /Fo".\Debug/" /Fd".\Debug/" /FD /c
+# SUBTRACT CPP /Fr
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\lib_Debug\myisammrg.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "myisammrg - Win32 Release"
+# Name "myisammrg - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\myrg_close.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\myrg_create.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\myrg_delete.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\myrg_extra.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\myrg_info.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\myrg_locking.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\myrg_open.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\myrg_panic.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\myrg_queue.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\myrg_rfirst.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\myrg_rkey.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\myrg_rlast.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\myrg_rnext.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\myrg_rprev.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\myrg_rrnd.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\myrg_rsame.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\myrg_static.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\myrg_update.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\myrg_write.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\mymrgdef.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/VC++Files/myisampack/myisampack.dsp b/VC++Files/myisampack/myisampack.dsp
new file mode 100644
index 00000000000..5ea392e1b41
--- /dev/null
+++ b/VC++Files/myisampack/myisampack.dsp
@@ -0,0 +1,107 @@
+# Microsoft Developer Studio Project File - Name="myisampack" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=myisampack - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "myisampack.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "myisampack.mak" CFG="myisampack - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "myisampack - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "myisampack - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "myisampack - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "release"
+# PROP Intermediate_Dir "release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../myisam" /D "NDEBUG" /D "DBUG_OFF" /D "_CONSOLE" /D "_MBCS" /D "_WINDOWS" /FR /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib uuid.lib setargv.obj /nologo /subsystem:console /machine:I386
+
+!ELSEIF "$(CFG)" == "myisampack - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "debug"
+# PROP Intermediate_Dir "debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /G6 /MTd /W3 /Z7 /Od /I "../include" /I "../myisam" /D "_DEBUG" /D "SAFEMALLOC" /D "SAFE_MUTEX" /D "_CONSOLE" /D "_MBCS" /D "_WINDOWS" /FD /c
+# SUBTRACT CPP /Fr
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib wsock32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib setargv.obj /nologo /subsystem:console /incremental:no /debug /machine:I386 /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "myisampack - Win32 Release"
+# Name "myisampack - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\myisampack.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\myisampack.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/VC++Files/mysql.dsp b/VC++Files/mysql.dsp
new file mode 100644
index 00000000000..41f2538a7e5
--- /dev/null
+++ b/VC++Files/mysql.dsp
@@ -0,0 +1,80 @@
+# Microsoft Developer Studio Project File - Name="mysql" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 5.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) External Target" 0x0106
+
+CFG=mysql - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "mysql.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "mysql.mak" CFG="mysql - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "mysql - Win32 Release" (based on "Win32 (x86) External Target")
+!MESSAGE "mysql - Win32 Debug" (based on "Win32 (x86) External Target")
+!MESSAGE
+
+# Begin Project
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+
+!IF "$(CFG)" == "mysql - Win32 Release"
+
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Cmd_Line "NMAKE /f mysql.mak"
+# PROP BASE Rebuild_Opt "/a"
+# PROP BASE Target_File "mysql.exe"
+# PROP BASE Bsc_Name "mysql.bsc"
+# PROP BASE Target_Dir ""
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Cmd_Line "NMAKE /f mysql.mak"
+# PROP Rebuild_Opt "/a"
+# PROP Target_File "mysql.exe"
+# PROP Bsc_Name "mysql.bsc"
+# PROP Target_Dir ""
+
+!ELSEIF "$(CFG)" == "mysql - Win32 Debug"
+
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Cmd_Line "NMAKE /f mysql.mak"
+# PROP BASE Rebuild_Opt "/a"
+# PROP BASE Target_File "mysql.exe"
+# PROP BASE Bsc_Name "mysql.bsc"
+# PROP BASE Target_Dir ""
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Cmd_Line "NMAKE /f mysql.mak"
+# PROP Rebuild_Opt "/a"
+# PROP Target_File "mysql.exe"
+# PROP Bsc_Name "mysql.bsc"
+# PROP Target_Dir ""
+
+!ENDIF
+
+# Begin Target
+
+# Name "mysql - Win32 Release"
+# Name "mysql - Win32 Debug"
+
+!IF "$(CFG)" == "mysql - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysql - Win32 Debug"
+
+!ENDIF
+
+# End Target
+# End Project
diff --git a/VC++Files/mysql.dsw b/VC++Files/mysql.dsw
new file mode 100644
index 00000000000..7713b28d978
--- /dev/null
+++ b/VC++Files/mysql.dsw
@@ -0,0 +1,656 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "MySqlManager"=".\mysqlmanager\MySqlManager.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name mysqlclient
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "bdb"=".\bdb\bdb.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "dbug"=".\dbug\dbug.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "heap"=".\heap\heap.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "innobase"=".\innobase\innobase.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "isam"=".\isam\isam.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "isamchk"=".\isamchk\isamchk.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name isam
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name mysys
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name strings
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name dbug
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "libmySQL"=".\libmysql\libmySQL.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name zlib
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "merge"=".\merge\merge.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "myTest"=".\libmysqltest\myTest.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name libmySQL
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "myisam"=".\myisam\myisam.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "myisamchk"=".\myisamchk\myisamchk.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name dbug
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name myisam
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name mysys
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name strings
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "myisamlog"=".\myisamlog\myisamlog.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name dbug
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name myisam
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name mysys
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name strings
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "myisammrg"=".\myisammrg\myisammrg.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "myisampack"=".\myisampack\myisampack.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name dbug
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name myisam
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name mysys
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name strings
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "mysql"=".\client\mysql.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name mysqlclient
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "mysqladmin"=".\client\mysqladmin.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name mysqlclient
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name zlib
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "mysqlbinlog"=".\mysqlbinlog\mysqlbinlog.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name mysqlclient
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "mysqlcheck"=".\mysqlcheck\mysqlcheck.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name mysqlclient
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "mysqlclient"=".\client\mysqlclient.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name zlib
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "mysqld"=".\sql\mysqld.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name heap
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name isam
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name merge
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name mysys
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name regex
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name strings
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name dbug
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name mysql
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name mysqladmin
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name mysqldump
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name mysqlimport
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name MySqlManager
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name mysqlshow
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name myTest
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name thr_test
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name replace
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name zlib
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name myisam
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name myisammrg
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name innobase
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name bdb
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name vio
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "mysqldump"=".\client\mysqldump.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name mysqlclient
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "mysqlimport"=".\client\mysqlimport.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name mysqlclient
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "mysqlshow"=".\client\mysqlshow.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name mysqlclient
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "mysqlshutdown"=".\mysqlshutdown\mysqlshutdown.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "mysqlwatch"=".\mysqlwatch\mysqlwatch.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "mysys"=".\mysys\mysys.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "pack_isam"=".\pack_isam\pack_isam.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name dbug
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name isam
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name mysys
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name strings
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "perror"=".\perror\perror.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name dbug
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name mysys
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name strings
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "regex"=".\regex\regex.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "replace"=".\replace\replace.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name dbug
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name mysys
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name strings
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "strings"=".\strings\strings.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "test1"=".\test1\test1.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name libmySQL
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "thr_insert_test"=".\thr_insert_test\thr_insert_test.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name mysqlclient
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "thr_test"=".\thr_test\thr_test.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name dbug
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name mysys
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name strings
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "vio"=".\vio\vio.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "zlib"=".\zlib\zlib.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/VC++Files/mysqlbinlog/mysqlbinlog.dsp b/VC++Files/mysqlbinlog/mysqlbinlog.dsp
new file mode 100644
index 00000000000..4145585abc5
--- /dev/null
+++ b/VC++Files/mysqlbinlog/mysqlbinlog.dsp
@@ -0,0 +1,103 @@
+# Microsoft Developer Studio Project File - Name="mysqlbinlog" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=mysqlbinlog - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "mysqlbinlog.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "mysqlbinlog.mak" CFG="mysqlbinlog - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "mysqlbinlog - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "mysqlbinlog - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "mysqlbinlog - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../" /D "NDEBUG" /D "DBUG_OFF" /D "_CONSOLE" /D "_MBCS" /D "_WINDOWS" /D "MYSQL_SERVER" /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 mysqlclient.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"../client_release/mysqlbinlog.exe" /libpath:"..\lib_release\\"
+# SUBTRACT LINK32 /pdb:none /debug
+
+!ELSEIF "$(CFG)" == "mysqlbinlog - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /G6 /MTd /W3 /Gm /ZI /Od /I "../include" /I "../" /D "_DEBUG" /D "SAFEMALLOC" /D "SAFE_MUTEX" /D "_CONSOLE" /D "_MBCS" /D "_WINDOWS" /D "MYSQL_SERVER" /FD /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 mysqlclient.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /incremental:no /debug /machine:I386 /out:"../client_debug/mysqlbinlog.exe" /pdbtype:sept /libpath:"..\lib_debug\\"
+
+!ENDIF
+
+# Begin Target
+
+# Name "mysqlbinlog - Win32 Release"
+# Name "mysqlbinlog - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\mysqlbinlog.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/VC++Files/mysqlcheck/mysqlcheck.dsp b/VC++Files/mysqlcheck/mysqlcheck.dsp
new file mode 100644
index 00000000000..49c3fc2b702
--- /dev/null
+++ b/VC++Files/mysqlcheck/mysqlcheck.dsp
@@ -0,0 +1,102 @@
+# Microsoft Developer Studio Project File - Name="mysqlcheck" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=mysqlcheck - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "mysqlcheck.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "mysqlcheck.mak" CFG="mysqlcheck - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "mysqlcheck - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "mysqlcheck - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "mysqlcheck - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../" /D "NDEBUG" /D "DBUG_OFF" /D "_CONSOLE" /D "_MBCS" /D "_WINDOWS" /D "MYSQL_SERVER" /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 mysqlclient.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"../client_release/mysqlcheck.exe" /libpath:"..\lib_release\\"
+
+!ELSEIF "$(CFG)" == "mysqlcheck - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /G6 /MTd /W3 /Gm /ZI /Od /I "../include" /I "../" /D "_DEBUG" /D "SAFEMALLOC" /D "SAFE_MUTEX" /D "_CONSOLE" /D "_MBCS" /D "_WINDOWS" /D "MYSQL_SERVER" /FD /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 mysqlclient.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /incremental:no /debug /machine:I386 /out:"../client_debug/mysqlcheck.exe" /pdbtype:sept /libpath:"..\lib_debug\\"
+
+!ENDIF
+
+# Begin Target
+
+# Name "mysqlcheck - Win32 Release"
+# Name "mysqlcheck - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\client\mysqlcheck.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/VC++Files/mysqlmanager/MySqlManager.dsp b/VC++Files/mysqlmanager/MySqlManager.dsp
new file mode 100644
index 00000000000..60ee700b00c
--- /dev/null
+++ b/VC++Files/mysqlmanager/MySqlManager.dsp
@@ -0,0 +1,253 @@
+# Microsoft Developer Studio Project File - Name="MySqlManager" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+
+CFG=MySqlManager - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "MySqlManager.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "MySqlManager.mak" CFG="MySqlManager - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "MySqlManager - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "MySqlManager - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "MySqlManager - Win32 Release"
+
+# PROP BASE Use_MFC 6
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 6
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "release"
+# PROP Intermediate_Dir "release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_AFXDLL" /Yu"stdafx.h" /FD /c
+# ADD CPP /nologo /G6 /MT /W3 /GX /O1 /I "../include" /D "NDEBUG" /D "DBUG_OFF" /D "_WINDOWS" /FD /c
+# SUBTRACT CPP /YX /Yc /Yu
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG" /d "_AFXDLL"
+# ADD RSC /l 0x409 /d "NDEBUG" /d "_AFXDLL"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 /nologo /subsystem:windows /machine:I386
+# ADD LINK32 /nologo /subsystem:windows /machine:I386 /out:"../client_release/MySqlManager.exe"
+# SUBTRACT LINK32 /nodefaultlib
+
+!ELSEIF "$(CFG)" == "MySqlManager - Win32 Debug"
+
+# PROP BASE Use_MFC 6
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 6
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "debug"
+# PROP Intermediate_Dir "debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_AFXDLL" /Yu"stdafx.h" /FD /c
+# ADD CPP /nologo /G6 /MTd /W3 /Gm /GX /ZI /Od /I "../include" /D "_DEBUG" /D "_WINDOWS" /FD /c
+# SUBTRACT CPP /Fr /YX /Yc /Yu
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32
+# ADD MTL /nologo /D "_DEBUG" /o "NUL" /win32
+# SUBTRACT MTL /mktyplib203
+# ADD BASE RSC /l 0x409 /d "_DEBUG" /d "_AFXDLL"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib uuid.lib /nologo /subsystem:windows /incremental:no /debug /machine:I386 /out:"../client_debug/MySqlManager.exe" /pdbtype:sept /libpath:"..\lib_debug\\"
+# SUBTRACT LINK32 /pdb:none
+
+!ENDIF
+
+# Begin Target
+
+# Name "MySqlManager - Win32 Release"
+# Name "MySqlManager - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\ChildFrm.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\MainFrm.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\MySqlManager.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\MySqlManager.rc
+# End Source File
+# Begin Source File
+
+SOURCE=.\MySqlManagerDoc.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\MySqlManagerView.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\RegisterServer.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\StdAfx.cpp
+# ADD CPP /Yc"stdafx.h"
+# End Source File
+# Begin Source File
+
+SOURCE=.\ToolSql.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\ToolSqlQuery.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\ToolSqlResults.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\ToolSqlStatus.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\ChildFrm.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\MainFrm.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\MySqlManager.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\MySqlManagerDoc.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\MySqlManagerView.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\RegisterServer.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Resource.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\StdAfx.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\ToolSqlQuery.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\ToolSqlResults.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\ToolSqlStatus.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe"
+# Begin Source File
+
+SOURCE=.\res\bitmap1.bmp
+# End Source File
+# Begin Source File
+
+SOURCE=.\res\bitmap3.bmp
+# End Source File
+# Begin Source File
+
+SOURCE=.\res\bmp00001.bmp
+# End Source File
+# Begin Source File
+
+SOURCE=.\res\bmp00002.bmp
+# End Source File
+# Begin Source File
+
+SOURCE=.\res\database.bmp
+# End Source File
+# Begin Source File
+
+SOURCE=.\res\fontd.bmp
+# End Source File
+# Begin Source File
+
+SOURCE=.\res\fontu.bmp
+# End Source File
+# Begin Source File
+
+SOURCE=.\res\MySqlManager.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\res\MySqlManager.rc2
+# End Source File
+# Begin Source File
+
+SOURCE=.\res\MySqlManagerDoc.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\res\query_ex.bmp
+# End Source File
+# Begin Source File
+
+SOURCE=.\res\Toolbar.bmp
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=.\ReadMe.txt
+# End Source File
+# End Target
+# End Project
diff --git a/VC++Files/mysqlmanager/mysqlmanager.dsw b/VC++Files/mysqlmanager/mysqlmanager.dsw
new file mode 100644
index 00000000000..02ec9a86dc5
--- /dev/null
+++ b/VC++Files/mysqlmanager/mysqlmanager.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 5.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "MySqlManager"=.\MySqlManager.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/VC++Files/mysqlshutdown/myshutdown.dsp b/VC++Files/mysqlshutdown/myshutdown.dsp
new file mode 100644
index 00000000000..390921f599c
--- /dev/null
+++ b/VC++Files/mysqlshutdown/myshutdown.dsp
@@ -0,0 +1,101 @@
+# Microsoft Developer Studio Project File - Name="myshutdown" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+
+CFG=myshutdown - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "myshutdown.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "myshutdown.mak" CFG="myshutdown - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "myshutdown - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "myshutdown - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "myshutdown - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
+
+!ELSEIF "$(CFG)" == "myshutdown - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "myshutdown - Win32 Release"
+# Name "myshutdown - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/VC++Files/mysqlshutdown/mysqlshutdown.dsp b/VC++Files/mysqlshutdown/mysqlshutdown.dsp
new file mode 100644
index 00000000000..1489a5547ed
--- /dev/null
+++ b/VC++Files/mysqlshutdown/mysqlshutdown.dsp
@@ -0,0 +1,119 @@
+# Microsoft Developer Studio Project File - Name="mysqlshutdown" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+
+CFG=mysqlshutdown - Win32 Release
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "mysqlshutdown.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "mysqlshutdown.mak" CFG="mysqlshutdown - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "mysqlshutdown - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "mysqlshutdown - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "mysqlshutdown - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "release"
+# PROP Intermediate_Dir "release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /G6 /W3 /GX- /O2 /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"../client_release/mysqlshutdown.exe"
+
+!ELSEIF "$(CFG)" == "mysqlshutdown - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "mysqlshutdown___Win32_Debug"
+# PROP BASE Intermediate_Dir "mysqlshutdown___Win32_Debug"
+# PROP BASE Ignore_Export_Lib 0
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "debug"
+# PROP Intermediate_Dir "debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /G6 /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /FD /c
+# SUBTRACT BASE CPP /YX
+# ADD CPP /nologo /G6 /W3 /GX- /O2 /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"../client_release/mysqlshutdown.exe"
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"../client_debug/mysqlshutdown.exe"
+
+!ENDIF
+
+# Begin Target
+
+# Name "mysqlshutdown - Win32 Release"
+# Name "mysqlshutdown - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\mysqlshutdown.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mysqlshutdown.rc
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# Begin Source File
+
+SOURCE=.\mysql.ico
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/VC++Files/mysqlwatch/mysqlwatch.dsp b/VC++Files/mysqlwatch/mysqlwatch.dsp
new file mode 100644
index 00000000000..004f444e09b
--- /dev/null
+++ b/VC++Files/mysqlwatch/mysqlwatch.dsp
@@ -0,0 +1,70 @@
+# Microsoft Developer Studio Project File - Name="mysqlwatch" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=mysqlwatch - Win32 Release
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "mysqlwatch.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "mysqlwatch.mak" CFG="mysqlwatch - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "mysqlwatch - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "release"
+# PROP Intermediate_Dir "release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /G6 /W3 /GX- /O2 /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"../client_release/mysqlwatch.exe"
+# Begin Target
+
+# Name "mysqlwatch - Win32 Release"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\mysqlwatch.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/VC++Files/mysys/mysys.dsp b/VC++Files/mysys/mysys.dsp
new file mode 100644
index 00000000000..eb467e55892
--- /dev/null
+++ b/VC++Files/mysys/mysys.dsp
@@ -0,0 +1,507 @@
+# Microsoft Developer Studio Project File - Name="mysys" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=mysys - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "mysys.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "mysys.mak" CFG="mysys - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "mysys - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "mysys - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "mysys - Win32 Max" (based on "Win32 (x86) Static Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "mysys - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "release"
+# PROP Intermediate_Dir "release"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /D "NDEBUG" /D "DBUG_OFF" /D "_WINDOWS" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409
+# ADD RSC /l 0x409
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\lib_release\mysys.lib"
+
+!ELSEIF "$(CFG)" == "mysys - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "debug"
+# PROP Intermediate_Dir "debug"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /Z7 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /G6 /MTd /W3 /ZI /Od /I "../include" /D "_DEBUG" /D "SAFEMALLOC" /D "SAFE_MUTEX" /D "_WINDOWS" /D "USE_SYMDIR" /FD /c
+# SUBTRACT CPP /Fr
+# ADD BASE RSC /l 0x409
+# ADD RSC /l 0x409
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\lib_debug\mysys.lib"
+
+!ELSEIF "$(CFG)" == "mysys - Win32 Max"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "mysys___Win32_Max"
+# PROP BASE Intermediate_Dir "mysys___Win32_Max"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "mysys___Win32_Max"
+# PROP Intermediate_Dir "mysys___Win32_Max"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /G6 /MT /W3 /O2 /I "../include" /D "NDEBUG" /D "DBUG_OFF" /D "_WINDOWS" /FD /c
+# SUBTRACT BASE CPP /YX
+# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /D "NDEBUG" /D "DBUG_OFF" /D "_WINDOWS" /D "USE_SYMDIR" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409
+# ADD RSC /l 0x409
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo /out:"..\lib_release\mysys.lib"
+# ADD LIB32 /nologo /out:"..\lib_release\mysys-max.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "mysys - Win32 Release"
+# Name "mysys - Win32 Debug"
+# Name "mysys - Win32 Max"
+# Begin Source File
+
+SOURCE=.\array.c
+
+!IF "$(CFG)" == "mysys - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysys - Win32 Debug"
+
+# ADD CPP /FR
+
+!ELSEIF "$(CFG)" == "mysys - Win32 Max"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\charset.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\checksum.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\default.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\errors.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\getopt.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\getopt1.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\getvar.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\hash.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\list.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mf_brkhant.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mf_cache.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mf_casecnv.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mf_dirname.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mf_fn_ext.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mf_format.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mf_getdate.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mf_iocache.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mf_iocache2.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mf_keycache.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mf_loadpath.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mf_pack.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mf_pack2.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mf_path.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mf_qsort.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mf_qsort2.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mf_radix.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mf_same.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mf_sort.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mf_soundex.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mf_stripp.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mf_tempfile.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mf_wcomp.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mf_wfile.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mulalloc.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\my_alarm.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\my_alloc.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\my_append.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\my_bit.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\my_bitmap.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\my_chsize.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\my_clock.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\my_compress.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\my_copy.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\my_create.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\my_delete.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\my_div.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\my_error.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\my_fopen.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\my_fstream.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\my_getwd.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\my_init.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\my_lib.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\my_lock.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\my_lockmem.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\my_lread.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\my_lwrite.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\my_malloc.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\my_messnc.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\my_mkdir.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\my_net.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\my_once.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\my_open.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\my_pread.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\my_pthread.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\my_quick.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\my_read.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\my_realloc.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\my_redel.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\my_rename.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\my_seek.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\my_static.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\my_static.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\my_symlink.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\my_symlink2.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\my_tempnam.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\my_thr_init.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\my_vsnprintf.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\my_wincond.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\my_winthread.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\my_write.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mysys_priv.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\ptr_cmp.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\queues.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\raid.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\safemalloc.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\string.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\thr_alarm.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\thr_lock.c
+
+!IF "$(CFG)" == "mysys - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysys - Win32 Debug"
+
+# ADD CPP /D "EXTRA_DEBUG"
+
+!ELSEIF "$(CFG)" == "mysys - Win32 Max"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\thr_mutex.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\thr_rwlock.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\tree.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\typelib.c
+# End Source File
+# End Target
+# End Project
diff --git a/VC++Files/mysys/mysys.dsw b/VC++Files/mysys/mysys.dsw
new file mode 100644
index 00000000000..d5064051fc9
--- /dev/null
+++ b/VC++Files/mysys/mysys.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 5.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "mysys"=".\mysys.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/VC++Files/pack_isam/pack_isam.dsp b/VC++Files/pack_isam/pack_isam.dsp
new file mode 100644
index 00000000000..20c832c96d0
--- /dev/null
+++ b/VC++Files/pack_isam/pack_isam.dsp
@@ -0,0 +1,103 @@
+# Microsoft Developer Studio Project File - Name="pack_isam" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=pack_isam - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "pack_isam.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "pack_isam.mak" CFG="pack_isam - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "pack_isam - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "pack_isam - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "pack_isam - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "release"
+# PROP Intermediate_Dir "release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../isam" /D "NDEBUG" /D "DBUG_OFF" /D "_CONSOLE" /D "_MBCS" /D "_WINDOWS" /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib setargv.obj /nologo /subsystem:console /machine:I386 /out:"../client_release/pack_isam.exe"
+
+!ELSEIF "$(CFG)" == "pack_isam - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "debug"
+# PROP Intermediate_Dir "debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /G6 /MTd /W3 /Gm /ZI /Od /I "../include" /I "../isam" /D "_DEBUG" /D "SAFEMALLOC" /D "SAFE_MUTEX" /D "_CONSOLE" /D "_MBCS" /D "_WINDOWS" /FD /c
+# SUBTRACT CPP /Fr
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib wsock32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib setargv.obj /nologo /subsystem:console /debug /machine:I386 /out:"../client_debug/pack_isam.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "pack_isam - Win32 Release"
+# Name "pack_isam - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\pack_isam.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/VC++Files/perror/perror.dsp b/VC++Files/perror/perror.dsp
new file mode 100644
index 00000000000..439fcef1547
--- /dev/null
+++ b/VC++Files/perror/perror.dsp
@@ -0,0 +1,109 @@
+# Microsoft Developer Studio Project File - Name="perror" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+
+CFG=perror - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "perror.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "perror.mak" CFG="perror - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "perror - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "perror - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "perror - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /G6 /MT /W3 /GX- /O2 /I "../include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
+# ADD LINK32 wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"../client_release/perror.exe"
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF "$(CFG)" == "perror - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /G6 /MTd /W3 /Gm /GX- /ZI /Od /I "../include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib wsock32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /incremental:no /debug /machine:I386 /pdbtype:sept
+# SUBTRACT LINK32 /pdb:none
+
+!ENDIF
+
+# Begin Target
+
+# Name "perror - Win32 Release"
+# Name "perror - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\extra\perror.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/VC++Files/regex/regex.dsp b/VC++Files/regex/regex.dsp
new file mode 100644
index 00000000000..5ee617c58b7
--- /dev/null
+++ b/VC++Files/regex/regex.dsp
@@ -0,0 +1,114 @@
+# Microsoft Developer Studio Project File - Name="regex" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=regex - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "regex.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "regex.mak" CFG="regex - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "regex - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "regex - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "regex - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "release"
+# PROP Intermediate_Dir "release"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "./" /D "NDEBUG" /D "DBUG_OFF" /D "_WINDOWS" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409
+# ADD RSC /l 0x409
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\lib_release\regex.lib"
+
+!ELSEIF "$(CFG)" == "regex - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "debug"
+# PROP Intermediate_Dir "debug"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /Z7 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /G6 /MTd /W3 /Z7 /Od /Gf /I "../include" /I "./" /D "_DEBUG" /D "SAFEMALLOC" /D "SAFE_MUTEX" /D "_WINDOWS" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409
+# ADD RSC /l 0x409
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\lib_debug\regex.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "regex - Win32 Release"
+# Name "regex - Win32 Debug"
+# Begin Source File
+
+SOURCE=.\debug.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\regcomp.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\regerror.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\regexec.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\regfree.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\reginit.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\split.c
+# End Source File
+# End Target
+# End Project
diff --git a/VC++Files/regex/regex.dsw b/VC++Files/regex/regex.dsw
new file mode 100644
index 00000000000..102e07af409
--- /dev/null
+++ b/VC++Files/regex/regex.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 5.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "regex"=".\regex.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/VC++Files/replace/replace.dsp b/VC++Files/replace/replace.dsp
new file mode 100644
index 00000000000..011b62d08ec
--- /dev/null
+++ b/VC++Files/replace/replace.dsp
@@ -0,0 +1,93 @@
+# Microsoft Developer Studio Project File - Name="replace" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=replace - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "replace.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "replace.mak" CFG="replace - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "replace - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "replace - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "replace - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "release"
+# PROP Intermediate_Dir "release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /D "NDEBUG" /D "DBUG_OFF" /D "_CONSOLE" /D "_MBCS" /D "_WINDOWS" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x40b /d "NDEBUG"
+# ADD RSC /l 0x40b /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib setargv.obj /nologo /subsystem:console /machine:I386 /out:"../client_release/replace.exe"
+
+!ELSEIF "$(CFG)" == "replace - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "debug"
+# PROP Intermediate_Dir "debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /G6 /MTd /W3 /Gm /ZI /Od /I "../include" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "_WINDOWS" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x40b /d "_DEBUG"
+# ADD RSC /l 0x40b /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib wsock32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib setargv.obj /nologo /subsystem:console /incremental:no /machine:I386 /out:"../client_debug/replace.exe" /pdbtype:sept
+# SUBTRACT LINK32 /debug
+
+!ENDIF
+
+# Begin Target
+
+# Name "replace - Win32 Release"
+# Name "replace - Win32 Debug"
+# Begin Source File
+
+SOURCE=..\extra\replace.c
+# End Source File
+# End Target
+# End Project
diff --git a/VC++Files/sql/mysqld.dsp b/VC++Files/sql/mysqld.dsp
new file mode 100644
index 00000000000..ec4722d7f27
--- /dev/null
+++ b/VC++Files/sql/mysqld.dsp
@@ -0,0 +1,1281 @@
+# Microsoft Developer Studio Project File - Name="mysqld" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=mysqld - Win32 Release
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "mysqld.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "mysqld.mak" CFG="mysqld - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "mysqld - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "mysqld - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE "mysqld - Win32 nt" (based on "Win32 (x86) Console Application")
+!MESSAGE "mysqld - Win32 Max nt" (based on "Win32 (x86) Console Application")
+!MESSAGE "mysqld - Win32 Max" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "mysqld - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "release"
+# PROP Intermediate_Dir "release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../regex" /D "NDEBUG" /D "DBUG_OFF" /D "MYSQL_SERVER" /D "_WINDOWS" /D "_CONSOLE" /D "_MBCS" /D "SIGNAL_WITH_VIO_CLOSE" /D "HAVE_DLOPEN" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x410 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib Wsock32.lib ..\lib_release\vio.lib ..\lib_release\isam.lib ..\lib_release\merge.lib ..\lib_release\mysys.lib ..\lib_release\strings.lib ..\lib_release\regex.lib ..\lib_release\heap.lib /nologo /subsystem:console /pdb:none /machine:I386 /out:"../client_release/mysqld-opt.exe"
+# SUBTRACT LINK32 /debug
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "debug"
+# PROP Intermediate_Dir "debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /G6 /MTd /W3 /Gm /ZI /Od /I "../include" /I "../regex" /I "../bdb/build_win32" /D "_DEBUG" /D "SAFEMALLOC" /D "SAFE_MUTEX" /D "MYSQL_SERVER" /D "_WINDOWS" /D "_CONSOLE" /D "_MBCS" /D "HAVE_INNOBASE_DB" /D "HAVE_BERKELEY_DB" /D "USE_SYMDIR" /D "SIGNAL_WITH_VIO_CLOSE" /D "HAVE_DLOPEN" /FD /c
+# SUBTRACT CPP /Fr /YX
+# ADD BASE RSC /l 0x410 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib Wsock32.lib ..\lib_debug\dbug.lib ..\lib_debug\vio.lib ..\lib_debug\isam.lib ..\lib_debug\merge.lib ..\lib_debug\mysys.lib ..\lib_debug\strings.lib ..\lib_debug\regex.lib ..\lib_debug\heap.lib ..\lib_debug\bdb.lib ..\lib_debug\innodb.lib /nologo /subsystem:console /incremental:no /debug /machine:I386 /out:"../client_debug/mysqld.exe" /pdbtype:sept
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 nt"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "mysqld__"
+# PROP BASE Intermediate_Dir "mysqld__"
+# PROP BASE Ignore_Export_Lib 0
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "NT"
+# PROP Intermediate_Dir "NT"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /G5 /MT /W3 /O2 /I "../include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /D "__WIN32__" /D "DBUG_OFF" /FD /c
+# SUBTRACT BASE CPP /YX
+# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../regex" /D "NDEBUG" /D "__NT__" /D "DBUG_OFF" /D "MYSQL_SERVER" /D "_WINDOWS" /D "_CONSOLE" /D "_MBCS" /D "SIGNAL_WITH_VIO_CLOSE" /D "HAVE_DLOPEN" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x410 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib Wsock32.lib ..\lib_release\dbug.lib ..\lib_release\isam.lib ..\lib_release\merge.lib ..\lib_release\mysys.lib ..\lib_release\strings.lib ..\lib_release\regex.lib ..\lib_release\heap.lib /nologo /subsystem:console /debug /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib Wsock32.lib ..\lib_release\vio.lib ..\lib_release\isam.lib ..\lib_release\merge.lib ..\lib_release\myisam.lib ..\lib_release\myisammrg.lib ..\lib_release\mysys.lib ..\lib_release\strings.lib ..\lib_release\regex.lib ..\lib_release\heap.lib ..\lib_release\zlib.lib /nologo /subsystem:console /map /machine:I386 /out:"../client_release/mysqld-nt.exe"
+# SUBTRACT LINK32 /pdb:none /debug
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max nt"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "mysqld___Win32_Max_nt"
+# PROP BASE Intermediate_Dir "mysqld___Win32_Max_nt"
+# PROP BASE Ignore_Export_Lib 0
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "mysqld___Win32_Max_nt"
+# PROP Intermediate_Dir "mysqld___Win32_Max_nt"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../regex" /D "NDEBUG" /D "__NT__" /D "DBUG_OFF" /D "MYSQL_SERVER" /D "_WINDOWS" /D "_CONSOLE" /D "_MBCS" /FD /c
+# SUBTRACT BASE CPP /YX
+# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../regex" /I "../bdb/build_win32" /D "NDEBUG" /D "__NT__" /D "DBUG_OFF" /D "MYSQL_SERVER" /D "_WINDOWS" /D "_CONSOLE" /D "_MBCS" /D "USE_SYMDIR" /D "HAVE_INNOBASE_DB" /D "HAVE_BERKELEY_DB" /D "SIGNAL_WITH_VIO_CLOSE" /D "HAVE_DLOPEN" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib Wsock32.lib ..\lib_release\isam.lib ..\lib_release\merge.lib ..\lib_release\myisam.lib ..\lib_release\myisammrg.lib ..\lib_release\mysys.lib ..\lib_release\strings.lib ..\lib_release\regex.lib ..\lib_release\heap.lib ..\lib_release\zlib.lib /nologo /subsystem:console /map /machine:I386 /out:"../client_release/mysqld-nt.exe"
+# SUBTRACT BASE LINK32 /pdb:none /debug
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib Wsock32.lib ..\lib_release\vio.lib ..\lib_release\isam.lib ..\lib_release\merge.lib ..\lib_release\myisam.lib ..\lib_release\myisammrg.lib ..\lib_release\mysys-max.lib ..\lib_release\strings.lib ..\lib_release\regex.lib ..\lib_release\heap.lib ..\lib_release\zlib.lib ..\lib_release\innodb-nt.lib ..\lib_release\bdb.lib /nologo /subsystem:console /map /machine:I386 /out:"../client_release/mysqld-max-nt.exe"
+# SUBTRACT LINK32 /pdb:none /debug
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "mysqld___Win32_Max"
+# PROP BASE Intermediate_Dir "mysqld___Win32_Max"
+# PROP BASE Ignore_Export_Lib 0
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "mysqld___Win32_Max"
+# PROP Intermediate_Dir "mysqld___Win32_Max"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../regex" /D "NDEBUG" /D "DBUG_OFF" /D "MYSQL_SERVER" /D "_WINDOWS" /D "_CONSOLE" /D "_MBCS" /FD /c
+# SUBTRACT BASE CPP /YX
+# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../regex" /I "../bdb/build_win32" /D "NDEBUG" /D "DBUG_OFF" /D "MYSQL_SERVER" /D "_WINDOWS" /D "_CONSOLE" /D "_MBCS" /D "USE_SYMDIR" /D "HAVE_INNOBASE_DB" /D "HAVE_BERKELEY_DB" /D "SIGNAL_WITH_VIO_CLOSE" /D "HAVE_DLOPEN" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib Wsock32.lib ..\lib_release\isam.lib ..\lib_release\merge.lib ..\lib_release\mysys.lib ..\lib_release\strings.lib ..\lib_release\regex.lib ..\lib_release\heap.lib /nologo /subsystem:console /pdb:none /debug /machine:I386 /out:"../client_release/mysqld-opt.exe"
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib Wsock32.lib ..\lib_release\vio.lib ..\lib_release\isam.lib ..\lib_release\merge.lib ..\lib_release\myisam.lib ..\lib_release\myisammrg.lib ..\lib_release\mysys-max.lib ..\lib_release\strings.lib ..\lib_release\regex.lib ..\lib_release\heap.lib ..\lib_release\innodb.lib ..\lib_release\bdb.lib ..\lib_release\zlib.lib /nologo /subsystem:console /pdb:none /machine:I386 /out:"../client_release/mysqld-max.exe"
+# SUBTRACT LINK32 /debug
+
+!ENDIF
+
+# Begin Target
+
+# Name "mysqld - Win32 Release"
+# Name "mysqld - Win32 Debug"
+# Name "mysqld - Win32 nt"
+# Name "mysqld - Win32 Max nt"
+# Name "mysqld - Win32 Max"
+# Begin Source File
+
+SOURCE=.\convert.cpp
+
+!IF "$(CFG)" == "mysqld - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Debug"
+
+# ADD CPP /G5
+# SUBTRACT CPP /YX /Yc
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\derror.cpp
+
+!IF "$(CFG)" == "mysqld - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Debug"
+
+# ADD CPP /G5
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\field.cpp
+
+!IF "$(CFG)" == "mysqld - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Debug"
+
+# ADD CPP /G5
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\field_conv.cpp
+
+!IF "$(CFG)" == "mysqld - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Debug"
+
+# ADD CPP /G5
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\filesort.cpp
+
+!IF "$(CFG)" == "mysqld - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Debug"
+
+# ADD CPP /G5
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\ha_berkeley.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\ha_heap.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\ha_innobase.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\ha_isam.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\ha_isammrg.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\ha_myisam.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\ha_myisammrg.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\handler.cpp
+
+!IF "$(CFG)" == "mysqld - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Debug"
+
+# ADD CPP /G5
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\hash_filo.cpp
+
+!IF "$(CFG)" == "mysqld - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Debug"
+
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\hash_filo.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\hostname.cpp
+
+!IF "$(CFG)" == "mysqld - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Debug"
+
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\init.cpp
+
+!IF "$(CFG)" == "mysqld - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Debug"
+
+# ADD CPP /G5
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\item.cpp
+
+!IF "$(CFG)" == "mysqld - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Debug"
+
+# ADD CPP /G5
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\item_buff.cpp
+
+!IF "$(CFG)" == "mysqld - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Debug"
+
+# ADD CPP /G5
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\item_cmpfunc.cpp
+
+!IF "$(CFG)" == "mysqld - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Debug"
+
+# ADD CPP /G5
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\item_create.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\item_func.cpp
+
+!IF "$(CFG)" == "mysqld - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Debug"
+
+# ADD CPP /G5
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\item_strfunc.cpp
+
+!IF "$(CFG)" == "mysqld - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Debug"
+
+# ADD CPP /G5
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\item_sum.cpp
+
+!IF "$(CFG)" == "mysqld - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Debug"
+
+# ADD CPP /G5
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\item_timefunc.cpp
+
+!IF "$(CFG)" == "mysqld - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Debug"
+
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\item_uniq.cpp
+
+!IF "$(CFG)" == "mysqld - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Debug"
+
+# ADD CPP /G5
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\key.cpp
+
+!IF "$(CFG)" == "mysqld - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Debug"
+
+# ADD CPP /G5
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\lock.cpp
+
+!IF "$(CFG)" == "mysqld - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Debug"
+
+# ADD CPP /G5
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\log.cpp
+
+!IF "$(CFG)" == "mysqld - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Debug"
+
+# ADD CPP /G5
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\log_event.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\md5.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mf_iocache.cpp
+
+!IF "$(CFG)" == "mysqld - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Debug"
+
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\mini_client.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\mini_client_errors.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mysqld.cpp
+
+!IF "$(CFG)" == "mysqld - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Debug"
+
+# ADD CPP /G5
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\net_pkg.cpp
+
+!IF "$(CFG)" == "mysqld - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Debug"
+
+# ADD CPP /G5
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\net_serv.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\nt_servc.cpp
+
+!IF "$(CFG)" == "mysqld - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Debug"
+
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\nt_servc.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\opt_ft.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\opt_range.cpp
+
+!IF "$(CFG)" == "mysqld - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Debug"
+
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\opt_range.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\OPT_SUM.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\password.c
+
+!IF "$(CFG)" == "mysqld - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Debug"
+
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\procedure.cpp
+
+!IF "$(CFG)" == "mysqld - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Debug"
+
+# ADD CPP /G5
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\records.cpp
+
+!IF "$(CFG)" == "mysqld - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Debug"
+
+# ADD CPP /G5
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\repl_failsafe.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\slave.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\sql_acl.cpp
+
+!IF "$(CFG)" == "mysqld - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Debug"
+
+# ADD CPP /G5
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\sql_analyse.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\sql_base.cpp
+
+!IF "$(CFG)" == "mysqld - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Debug"
+
+# ADD CPP /G5
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\sql_cache.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\sql_class.cpp
+
+!IF "$(CFG)" == "mysqld - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Debug"
+
+# ADD CPP /G5
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\sql_crypt.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\sql_crypt.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\sql_db.cpp
+
+!IF "$(CFG)" == "mysqld - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Debug"
+
+# ADD CPP /G5
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\sql_delete.cpp
+
+!IF "$(CFG)" == "mysqld - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Debug"
+
+# ADD CPP /G5
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\sql_handler.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\sql_insert.cpp
+
+!IF "$(CFG)" == "mysqld - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Debug"
+
+# ADD CPP /G5
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\sql_lex.cpp
+
+!IF "$(CFG)" == "mysqld - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Debug"
+
+# ADD CPP /G5
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\sql_list.cpp
+
+!IF "$(CFG)" == "mysqld - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Debug"
+
+# ADD CPP /G5
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\sql_load.cpp
+
+!IF "$(CFG)" == "mysqld - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Debug"
+
+# ADD CPP /G5
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\sql_manager.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\sql_map.cpp
+
+!IF "$(CFG)" == "mysqld - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Debug"
+
+# ADD CPP /G5
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\sql_parse.cpp
+
+!IF "$(CFG)" == "mysqld - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Debug"
+
+# ADD CPP /G5
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\sql_rename.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\sql_repl.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\sql_select.cpp
+
+!IF "$(CFG)" == "mysqld - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Debug"
+
+# ADD CPP /G5
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\sql_show.cpp
+
+!IF "$(CFG)" == "mysqld - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Debug"
+
+# ADD CPP /G5
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\sql_string.cpp
+
+!IF "$(CFG)" == "mysqld - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Debug"
+
+# ADD CPP /G5
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\sql_table.cpp
+
+!IF "$(CFG)" == "mysqld - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Debug"
+
+# ADD CPP /G5
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\sql_test.cpp
+
+!IF "$(CFG)" == "mysqld - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Debug"
+
+# ADD CPP /G5
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\sql_udf.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\sql_union.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\sql_update.cpp
+
+!IF "$(CFG)" == "mysqld - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Debug"
+
+# ADD CPP /G5
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\sql_yacc.cpp
+
+!IF "$(CFG)" == "mysqld - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Debug"
+
+# ADD CPP /G5
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\table.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\thr_malloc.cpp
+
+!IF "$(CFG)" == "mysqld - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Debug"
+
+# ADD CPP /G5
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\time.cpp
+
+!IF "$(CFG)" == "mysqld - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Debug"
+
+# ADD CPP /G5
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\uniques.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\unireg.cpp
+
+!IF "$(CFG)" == "mysqld - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Debug"
+
+# ADD CPP /G5
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max nt"
+
+!ELSEIF "$(CFG)" == "mysqld - Win32 Max"
+
+!ENDIF
+
+# End Source File
+# End Target
+# End Project
diff --git a/VC++Files/sql/mysqldmax.dsp b/VC++Files/sql/mysqldmax.dsp
new file mode 100644
index 00000000000..4d24d033c51
--- /dev/null
+++ b/VC++Files/sql/mysqldmax.dsp
@@ -0,0 +1,1003 @@
+# Microsoft Developer Studio Project File - Name="mysqldmax" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=mysqldmax - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "mysqldmax.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "mysqldmax.mak" CFG="mysqldmax - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "mysqldmax - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "mysqldmax - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE "mysqldmax - Win32 nt" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "mysqldmax - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../regex" /D "NDEBUG" /D "DBUG_OFF" /D "MYSQL_SERVER" /D "_WINDOWS" /D "_CONSOLE" /D "_MBCS" /D "HAVE_BERKELEY_DB" /D "HAVE_INNOBASE_DB" /FD /c
+# ADD BASE RSC /l 0x416 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib Wsock32.lib ..\lib_release\isam.lib ..\lib_release\merge.lib ..\lib_release\mysys.lib ..\lib_release\strings.lib ..\lib_release\regex.lib ..\lib_release\heap.lib ..\lib_release\innobase-opt.lib ..\lib_release\libdb32s.lib /nologo /subsystem:console /pdb:none /debug /machine:I386 /nodefaultlib:"LIBC" /out:"../client_release/mysqld-max-opt.exe"
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /G6 /MTd /W3 /Gm /ZI /Od /I "../include" /I "../regex" /D "_DEBUG" /D "SAFEMALLOC" /D "SAFE_MUTEX" /D "MYSQL_SERVER" /D "_WINDOWS" /D "_CONSOLE" /D "_MBCS" /D "HAVE_BERKELEY_DB" /D "HAVE_INNOBASE_DB" /FR /FD /c
+# ADD BASE RSC /l 0x416 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib Wsock32.lib ..\lib_debug\dbug.lib ..\lib_debug\isam.lib ..\lib_debug\merge.lib ..\lib_debug\mysys.lib ..\lib_debug\strings.lib ..\lib_debug\regex.lib ..\lib_debug\heap.lib ..\lib_release\innobase-opt.lib ..\lib_release\libdb32s.lib /nologo /subsystem:console /incremental:no /pdb:"debug/mysqld.pdb" /debug /machine:I386 /nodefaultlib:"LIBC" /out:"../client_debug/mysqld-max.exe" /pdbtype:sept
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "nt"
+# PROP BASE Intermediate_Dir "nt"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "nt"
+# PROP Intermediate_Dir "nt"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../regex" /D "NDEBUG" /D "__NT__" /D "DBUG_OFF" /D "MYSQL_SERVER" /D "_WINDOWS" /D "_CONSOLE" /D "_MBCS" /D "HAVE_BERKELEY_DB" /D "HAVE_INNOBASE_DB" /FD /c
+# ADD BASE RSC /l 0x416 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib Wsock32.lib ..\lib_release\isam.lib ..\lib_release\merge.lib ..\lib_release\myisam.lib ..\lib_release\myisammrg.lib ..\lib_release\mysys.lib ..\lib_release\strings.lib ..\lib_release\regex.lib ..\lib_release\heap.lib ..\lib_release\zlib.lib ..\lib_release\innobase-nt.lib ..\lib_release\libdb32s.lib /nologo /subsystem:console /pdb:"NT/mysqld-nt.pdb" /map:"NT/mysqld-nt.map" /machine:I386 /nodefaultlib:"LIBC" /out:"../client_release/mysqld-max-nt.exe"
+# SUBTRACT LINK32 /pdb:none
+
+!ENDIF
+
+# Begin Target
+
+# Name "mysqldmax - Win32 Release"
+# Name "mysqldmax - Win32 Debug"
+# Name "mysqldmax - Win32 nt"
+# Begin Source File
+
+SOURCE=.\convert.cpp
+
+!IF "$(CFG)" == "mysqldmax - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 Debug"
+
+# ADD CPP /G5
+# SUBTRACT CPP /YX /Yc
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\derror.cpp
+
+!IF "$(CFG)" == "mysqldmax - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 Debug"
+
+# ADD CPP /G5
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\field.cpp
+
+!IF "$(CFG)" == "mysqldmax - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 Debug"
+
+# ADD CPP /G5
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\field_conv.cpp
+
+!IF "$(CFG)" == "mysqldmax - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 Debug"
+
+# ADD CPP /G5
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\filesort.cpp
+
+!IF "$(CFG)" == "mysqldmax - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 Debug"
+
+# ADD CPP /G5
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\ha_berkeley.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\ha_heap.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\ha_innobase.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\ha_isam.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\ha_isammrg.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\ha_myisam.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\ha_myisammrg.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\handler.cpp
+
+!IF "$(CFG)" == "mysqldmax - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 Debug"
+
+# ADD CPP /G5
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\hash_filo.cpp
+
+!IF "$(CFG)" == "mysqldmax - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 Debug"
+
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\hash_filo.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\hostname.cpp
+
+!IF "$(CFG)" == "mysqldmax - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 Debug"
+
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\init.cpp
+
+!IF "$(CFG)" == "mysqldmax - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 Debug"
+
+# ADD CPP /G5
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\item.cpp
+
+!IF "$(CFG)" == "mysqldmax - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 Debug"
+
+# ADD CPP /G5
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\item_buff.cpp
+
+!IF "$(CFG)" == "mysqldmax - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 Debug"
+
+# ADD CPP /G5
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\item_cmpfunc.cpp
+
+!IF "$(CFG)" == "mysqldmax - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 Debug"
+
+# ADD CPP /G5
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\item_create.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\item_func.cpp
+
+!IF "$(CFG)" == "mysqldmax - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 Debug"
+
+# ADD CPP /G5
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\item_strfunc.cpp
+
+!IF "$(CFG)" == "mysqldmax - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 Debug"
+
+# ADD CPP /G5
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\item_sum.cpp
+
+!IF "$(CFG)" == "mysqldmax - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 Debug"
+
+# ADD CPP /G5
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\item_timefunc.cpp
+
+!IF "$(CFG)" == "mysqldmax - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 Debug"
+
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\item_uniq.cpp
+
+!IF "$(CFG)" == "mysqldmax - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 Debug"
+
+# ADD CPP /G5
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\key.cpp
+
+!IF "$(CFG)" == "mysqldmax - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 Debug"
+
+# ADD CPP /G5
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\lock.cpp
+
+!IF "$(CFG)" == "mysqldmax - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 Debug"
+
+# ADD CPP /G5
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\log.cpp
+
+!IF "$(CFG)" == "mysqldmax - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 Debug"
+
+# ADD CPP /G5
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\log_event.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\md5.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mf_iocache.cpp
+
+!IF "$(CFG)" == "mysqldmax - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 Debug"
+
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\mini_client.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\mini_client_errors.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mysqld.cpp
+
+!IF "$(CFG)" == "mysqldmax - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 Debug"
+
+# ADD CPP /G5
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\net_pkg.cpp
+
+!IF "$(CFG)" == "mysqldmax - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 Debug"
+
+# ADD CPP /G5
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\net_serv.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\nt_servc.cpp
+
+!IF "$(CFG)" == "mysqldmax - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 Debug"
+
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\nt_servc.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\opt_ft.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\opt_range.cpp
+
+!IF "$(CFG)" == "mysqldmax - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 Debug"
+
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\opt_range.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\opt_sum.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\password.c
+
+!IF "$(CFG)" == "mysqldmax - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 Debug"
+
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\procedure.cpp
+
+!IF "$(CFG)" == "mysqldmax - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 Debug"
+
+# ADD CPP /G5
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\records.cpp
+
+!IF "$(CFG)" == "mysqldmax - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 Debug"
+
+# ADD CPP /G5
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\slave.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\sql_acl.cpp
+
+!IF "$(CFG)" == "mysqldmax - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 Debug"
+
+# ADD CPP /G5
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\sql_analyse.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\sql_base.cpp
+
+!IF "$(CFG)" == "mysqldmax - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 Debug"
+
+# ADD CPP /G5
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\sql_cache.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\sql_class.cpp
+
+!IF "$(CFG)" == "mysqldmax - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 Debug"
+
+# ADD CPP /G5
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\sql_crypt.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\sql_crypt.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\sql_db.cpp
+
+!IF "$(CFG)" == "mysqldmax - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 Debug"
+
+# ADD CPP /G5
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\sql_delete.cpp
+
+!IF "$(CFG)" == "mysqldmax - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 Debug"
+
+# ADD CPP /G5
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\sql_insert.cpp
+
+!IF "$(CFG)" == "mysqldmax - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 Debug"
+
+# ADD CPP /G5
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\sql_lex.cpp
+
+!IF "$(CFG)" == "mysqldmax - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 Debug"
+
+# ADD CPP /G5
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\sql_list.cpp
+
+!IF "$(CFG)" == "mysqldmax - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 Debug"
+
+# ADD CPP /G5
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\sql_load.cpp
+
+!IF "$(CFG)" == "mysqldmax - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 Debug"
+
+# ADD CPP /G5
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\sql_manager.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\sql_map.cpp
+
+!IF "$(CFG)" == "mysqldmax - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 Debug"
+
+# ADD CPP /G5
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\sql_parse.cpp
+
+!IF "$(CFG)" == "mysqldmax - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 Debug"
+
+# ADD CPP /G5
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\sql_rename.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\sql_repl.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\sql_select.cpp
+
+!IF "$(CFG)" == "mysqldmax - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 Debug"
+
+# ADD CPP /G5
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\sql_show.cpp
+
+!IF "$(CFG)" == "mysqldmax - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 Debug"
+
+# ADD CPP /G5
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\sql_string.cpp
+
+!IF "$(CFG)" == "mysqldmax - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 Debug"
+
+# ADD CPP /G5
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\sql_table.cpp
+
+!IF "$(CFG)" == "mysqldmax - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 Debug"
+
+# ADD CPP /G5
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\sql_test.cpp
+
+!IF "$(CFG)" == "mysqldmax - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 Debug"
+
+# ADD CPP /G5
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\sql_update.cpp
+
+!IF "$(CFG)" == "mysqldmax - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 Debug"
+
+# ADD CPP /G5
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\sql_yacc.cpp
+
+!IF "$(CFG)" == "mysqldmax - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 Debug"
+
+# ADD CPP /G5
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\table.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\thr_malloc.cpp
+
+!IF "$(CFG)" == "mysqldmax - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 Debug"
+
+# ADD CPP /G5
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\time.cpp
+
+!IF "$(CFG)" == "mysqldmax - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 Debug"
+
+# ADD CPP /G5
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\unireg.cpp
+
+!IF "$(CFG)" == "mysqldmax - Win32 Release"
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 Debug"
+
+# ADD CPP /G5
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\violite.c
+# End Source File
+# End Target
+# End Project
diff --git a/VC++Files/sql/old/mysqld.dsw b/VC++Files/sql/old/mysqld.dsw
new file mode 100644
index 00000000000..ed820ed7a90
--- /dev/null
+++ b/VC++Files/sql/old/mysqld.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 5.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "mysqld"=".\mysqld.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/VC++Files/strings/backup/strings.dsp b/VC++Files/strings/backup/strings.dsp
new file mode 100644
index 00000000000..45b22c52e21
--- /dev/null
+++ b/VC++Files/strings/backup/strings.dsp
@@ -0,0 +1,244 @@
+# Microsoft Developer Studio Project File - Name="strings" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=strings - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "strings.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "strings.mak" CFG="strings - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "strings - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "strings - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "strings - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "release"
+# PROP Intermediate_Dir "release"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /D "NDEBUG" /D "DBUG_OFF" /D "_WINDOWS" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409
+# ADD RSC /l 0x409
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\lib_release\strings.lib"
+
+!ELSEIF "$(CFG)" == "strings - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "debug"
+# PROP Intermediate_Dir "debug"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /Z7 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /G6 /MTd /W3 /Z7 /Od /Gf /I "../include" /D "_DEBUG" /D "SAFEMALLOC" /D "_WINDOWS" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409
+# ADD RSC /l 0x409
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\lib_debug\strings.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "strings - Win32 Release"
+# Name "strings - Win32 Debug"
+# Begin Source File
+
+SOURCE=.\atof.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bchange.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bcmp.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bfill.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bmove512.c
+# End Source File
+# Begin Source File
+
+SOURCE=".\ctype-big5.c"
+# End Source File
+# Begin Source File
+
+SOURCE=".\ctype-czech.c"
+# End Source File
+# Begin Source File
+
+SOURCE=".\ctype-euc_kr.c"
+# End Source File
+# Begin Source File
+
+SOURCE=".\ctype-gb2312.c"
+# End Source File
+# Begin Source File
+
+SOURCE=".\ctype-gbk.c"
+# End Source File
+# Begin Source File
+
+SOURCE=".\ctype-sjis.c"
+# End Source File
+# Begin Source File
+
+SOURCE=".\ctype-tis620.c"
+# End Source File
+# Begin Source File
+
+SOURCE=".\ctype-ujis.c"
+# End Source File
+# Begin Source File
+
+SOURCE=.\ctype.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\int2str.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\llstr.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\longlong2str.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\r_strinstr.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\str2int.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\Strings.asm
+
+!IF "$(CFG)" == "strings - Win32 Release"
+
+# Begin Custom Build
+OutDir=.\release
+InputPath=.\Strings.asm
+InputName=Strings
+
+"$(OutDir)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ C:\masm\masm -Mx -t -DDOS386 -DM_I386 $(InputPath),$(OutDir)\$(InputName).obj,,,
+
+# End Custom Build
+
+!ELSEIF "$(CFG)" == "strings - Win32 Debug"
+
+# Begin Custom Build
+OutDir=.\debug
+InputPath=.\Strings.asm
+InputName=Strings
+
+"$(OutDir)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ C:\masm\masm -Mx -t -DDOS386 -DM_I386 $(InputPath),$(Outdir)\$(InputName).obj,,,
+
+# End Custom Build
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\strtol.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\strtoll.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\strtoul.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\strtoull.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\Strxmov.asm
+
+!IF "$(CFG)" == "strings - Win32 Release"
+
+# Begin Custom Build
+OutDir=.\release
+InputPath=.\Strxmov.asm
+InputName=Strxmov
+
+"$(OutDir)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ C:\masm\masm -Mx -t -DDOS386 -DM_I386 $(InputPath),$(OutDir)\$(InputName).obj,,,
+
+# End Custom Build
+
+!ELSEIF "$(CFG)" == "strings - Win32 Debug"
+
+# Begin Custom Build
+OutDir=.\debug
+InputPath=.\Strxmov.asm
+InputName=Strxmov
+
+"$(OutDir)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ C:\masm\masm -Mx -t -DDOS386 -DM_I386 $(InputPath),$(Outdir)\$(InputName).obj,,,
+
+# End Custom Build
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\strxnmov.c
+# End Source File
+# End Target
+# End Project
diff --git a/VC++Files/strings/backup/strings.dsw b/VC++Files/strings/backup/strings.dsw
new file mode 100644
index 00000000000..e3777b8e7d5
--- /dev/null
+++ b/VC++Files/strings/backup/strings.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 5.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "strings"=".\strings.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/VC++Files/strings/noMASM/strings.dsp b/VC++Files/strings/noMASM/strings.dsp
new file mode 100644
index 00000000000..a84fb1b7835
--- /dev/null
+++ b/VC++Files/strings/noMASM/strings.dsp
@@ -0,0 +1,246 @@
+# Microsoft Developer Studio Project File - Name="strings" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=strings - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "strings.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "strings.mak" CFG="strings - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "strings - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "strings - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "strings - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "release"
+# PROP Intermediate_Dir "release"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /D "NDEBUG" /D "DBUG_OFF" /D "_WINDOWS" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409
+# ADD RSC /l 0x409
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\lib_release\strings.lib"
+
+!ELSEIF "$(CFG)" == "strings - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "debug"
+# PROP Intermediate_Dir "debug"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /Z7 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /G6 /MTd /W3 /Z7 /Od /Gf /I "../include" /D "_DEBUG" /D "SAFEMALLOC" /D "_WINDOWS" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409
+# ADD RSC /l 0x409
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\lib_debug\strings.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "strings - Win32 Release"
+# Name "strings - Win32 Debug"
+# Begin Source File
+
+SOURCE=.\atof.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bchange.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bcmp.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bfill.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bmove.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bmove512.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bmove_upp.c
+# End Source File
+# Begin Source File
+
+SOURCE=".\ctype-big5.c"
+# End Source File
+# Begin Source File
+
+SOURCE=".\ctype-czech.c"
+# End Source File
+# Begin Source File
+
+SOURCE=".\ctype-euc_kr.c"
+# End Source File
+# Begin Source File
+
+SOURCE=".\ctype-gb2312.c"
+# End Source File
+# Begin Source File
+
+SOURCE=".\ctype-gbk.c"
+# End Source File
+# Begin Source File
+
+SOURCE=".\ctype-latin1_de.c"
+# End Source File
+# Begin Source File
+
+SOURCE=".\ctype-sjis.c"
+# End Source File
+# Begin Source File
+
+SOURCE=".\ctype-tis620.c"
+# End Source File
+# Begin Source File
+
+SOURCE=".\ctype-ujis.c"
+# End Source File
+# Begin Source File
+
+SOURCE=.\ctype.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\int2str.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\is_prefix.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\llstr.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\longlong2str.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\r_strinstr.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\str2int.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\strappend.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\strcend.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\strcont.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\strend.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\strfill.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\strinstr.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\strmake.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\strmov.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\strnlen.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\strnmov.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\strstr.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\strtol.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\strtoll.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\strtoul.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\strtoull.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\strxmov.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\strxnmov.c
+# End Source File
+# End Target
+# End Project
diff --git a/VC++Files/strings/strings.dsp b/VC++Files/strings/strings.dsp
new file mode 100644
index 00000000000..52655947790
--- /dev/null
+++ b/VC++Files/strings/strings.dsp
@@ -0,0 +1,248 @@
+# Microsoft Developer Studio Project File - Name="strings" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=strings - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "strings.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "strings.mak" CFG="strings - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "strings - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "strings - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "strings - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "release"
+# PROP Intermediate_Dir "release"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /D "NDEBUG" /D "DBUG_OFF" /D "_WINDOWS" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409
+# ADD RSC /l 0x409
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\lib_release\strings.lib"
+
+!ELSEIF "$(CFG)" == "strings - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "debug"
+# PROP Intermediate_Dir "debug"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /Z7 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /G6 /MTd /W3 /Z7 /Od /Gf /I "../include" /D "_DEBUG" /D "SAFEMALLOC" /D "SAFE_MUTEX" /D "_WINDOWS" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409
+# ADD RSC /l 0x409
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\lib_debug\strings.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "strings - Win32 Release"
+# Name "strings - Win32 Debug"
+# Begin Source File
+
+SOURCE=.\atof.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bchange.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bcmp.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bfill.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bmove512.c
+# End Source File
+# Begin Source File
+
+SOURCE=".\ctype-big5.c"
+# End Source File
+# Begin Source File
+
+SOURCE=".\ctype-czech.c"
+# End Source File
+# Begin Source File
+
+SOURCE=".\ctype-euc_kr.c"
+# End Source File
+# Begin Source File
+
+SOURCE=".\ctype-gb2312.c"
+# End Source File
+# Begin Source File
+
+SOURCE=".\ctype-gbk.c"
+# End Source File
+# Begin Source File
+
+SOURCE=".\ctype-latin1_de.c"
+# End Source File
+# Begin Source File
+
+SOURCE=".\ctype-sjis.c"
+# End Source File
+# Begin Source File
+
+SOURCE=".\ctype-tis620.c"
+# End Source File
+# Begin Source File
+
+SOURCE=".\ctype-ujis.c"
+# End Source File
+# Begin Source File
+
+SOURCE=.\ctype.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\int2str.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\llstr.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\longlong2str.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\r_strinstr.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\str2int.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\Strings.asm
+
+!IF "$(CFG)" == "strings - Win32 Release"
+
+# Begin Custom Build
+OutDir=.\release
+InputPath=.\Strings.asm
+InputName=Strings
+
+"$(OutDir)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ ml /Cx /nologo /DDOS386 /DM_I386 /Zm /coff /c /Fo $(Outdir)\$(InputName).obj $(InputPath)
+
+# End Custom Build
+
+!ELSEIF "$(CFG)" == "strings - Win32 Debug"
+
+# Begin Custom Build
+OutDir=.\debug
+InputPath=.\Strings.asm
+InputName=Strings
+
+"$(OutDir)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ ml /Cx /nologo /DDOS386 /DM_I386 /Zm /coff /c /Fo $(Outdir)\$(InputName).obj $(InputPath)
+
+# End Custom Build
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\strtol.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\strtoll.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\strtoul.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\strtoull.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\Strxmov.asm
+
+!IF "$(CFG)" == "strings - Win32 Release"
+
+# Begin Custom Build
+OutDir=.\release
+InputPath=.\Strxmov.asm
+InputName=Strxmov
+
+"$(OutDir)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ ml /Cx /nologo /DDOS386 /DM_I386 /Zm /coff /c /Fo $(Outdir)\$(InputName).obj $(InputPath)
+
+# End Custom Build
+
+!ELSEIF "$(CFG)" == "strings - Win32 Debug"
+
+# Begin Custom Build
+OutDir=.\debug
+InputPath=.\Strxmov.asm
+InputName=Strxmov
+
+"$(OutDir)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ ml /Cx /nologo /DDOS386 /DM_I386 /Zm /coff /c /Fo $(Outdir)\$(InputName).obj $(InputPath)
+
+# End Custom Build
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\strxnmov.c
+# End Source File
+# End Target
+# End Project
diff --git a/VC++Files/test1/test1.dsp b/VC++Files/test1/test1.dsp
new file mode 100644
index 00000000000..50a165e3e4d
--- /dev/null
+++ b/VC++Files/test1/test1.dsp
@@ -0,0 +1,102 @@
+# Microsoft Developer Studio Project File - Name="test1" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=test1 - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "test1.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "test1.mak" CFG="test1 - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "test1 - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "test1 - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "test1 - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "release"
+# PROP Intermediate_Dir "release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /G6 /W3 /O2 /I "../include" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /D "_WINDOWS" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+
+!ELSEIF "$(CFG)" == "test1 - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "debug"
+# PROP Intermediate_Dir "debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /G6 /MTd /W3 /Gm /ZI /Od /I "../include" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "_WINDOWS" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 libmysql.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\lib_debug"
+# SUBTRACT LINK32 /incremental:no
+
+!ENDIF
+
+# Begin Target
+
+# Name "test1 - Win32 Release"
+# Name "test1 - Win32 Debug"
+# Begin Source File
+
+SOURCE=.\mysql_thr.c
+
+!IF "$(CFG)" == "test1 - Win32 Release"
+
+# ADD CPP /MT
+
+!ELSEIF "$(CFG)" == "test1 - Win32 Debug"
+
+!ENDIF
+
+# End Source File
+# End Target
+# End Project
diff --git a/VC++Files/thr_insert_test/thr_insert_test.dsp b/VC++Files/thr_insert_test/thr_insert_test.dsp
new file mode 100644
index 00000000000..770125ab65b
--- /dev/null
+++ b/VC++Files/thr_insert_test/thr_insert_test.dsp
@@ -0,0 +1,109 @@
+# Microsoft Developer Studio Project File - Name="thr_insert_test" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+
+CFG=thr_insert_test - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "thr_insert_test.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "thr_insert_test.mak" CFG="thr_insert_test - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "thr_insert_test - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "thr_insert_test - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "thr_insert_test - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /G6 /MT /W3 /GX- /O2 /I "../include" /I "../" /D "NDEBUG" /D "DBUG_OFF" /D "_CONSOLE" /D "_MBCS" /D "_WINDOWS" /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
+# ADD LINK32 mysqlclient.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"../client_release/hr_insert_test.exe" /libpath:"..\lib_release\\"
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF "$(CFG)" == "thr_insert_test - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /G6 /MTd /W3 /Gm /GX- /ZI /Od /I "../include" /I "../" /D "_DEBUG" /D "SAFEMALLOC" /D "SAFE_MUTEX" /D "_CONSOLE" /D "_MBCS" /D "_WINDOWS" /FD /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 mysqlclient.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /pdb:"debug/mysqldump.pdb" /debug /machine:I386 /out:"../client_debug/thr_insert_test.exe" /pdbtype:sept /libpath:"..\lib_debug\\"
+# SUBTRACT LINK32 /pdb:none
+
+!ENDIF
+
+# Begin Target
+
+# Name "thr_insert_test - Win32 Release"
+# Name "thr_insert_test - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\tests\thr_insert_test.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/VC++Files/thr_test/thr_test.dsp b/VC++Files/thr_test/thr_test.dsp
new file mode 100644
index 00000000000..7256f8da2fa
--- /dev/null
+++ b/VC++Files/thr_test/thr_test.dsp
@@ -0,0 +1,104 @@
+# Microsoft Developer Studio Project File - Name="thr_test" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=thr_test - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "thr_test.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "thr_test.mak" CFG="thr_test - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "thr_test - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "thr_test - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "thr_test - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "release"
+# PROP Intermediate_Dir "release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /D "NDEBUG" /D "DBUG_OFF" /D "_CONSOLE" /D "_MBCS" /D "_WINDOWS" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x40b /d "NDEBUG"
+# ADD RSC /l 0x40b /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# SUBTRACT LINK32 /nodefaultlib
+
+!ELSEIF "$(CFG)" == "thr_test - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "debug"
+# PROP Intermediate_Dir "debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /G6 /MTd /W3 /Gm /ZI /Od /I "../include" /D "__WIN32__" /D "_DEBUG" /D "SAFEMALLOC" /D "SAFE_MUTEX" /D "_CONSOLE" /D "_MBCS" /D "_WINDOWS" /FD /c
+# SUBTRACT CPP /Fr /YX
+# ADD BASE RSC /l 0x40b /d "_DEBUG"
+# ADD RSC /l 0x40b /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /incremental:no /debug /machine:I386 /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "thr_test - Win32 Release"
+# Name "thr_test - Win32 Debug"
+# Begin Source File
+
+SOURCE=.\thr_test.c
+
+!IF "$(CFG)" == "thr_test - Win32 Release"
+
+# ADD CPP /G5
+
+!ELSEIF "$(CFG)" == "thr_test - Win32 Debug"
+
+# ADD CPP /FAcs
+
+!ENDIF
+
+# End Source File
+# End Target
+# End Project
diff --git a/VC++Files/vio/vio.dsp b/VC++Files/vio/vio.dsp
new file mode 100644
index 00000000000..d4b77aad391
--- /dev/null
+++ b/VC++Files/vio/vio.dsp
@@ -0,0 +1,108 @@
+# Microsoft Developer Studio Project File - Name="vio" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=vio - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "vio.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "vio.mak" CFG="vio - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "vio - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "vio - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "vio - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /D "NDEBUG" /D "DBUG_OFF" /D "_WINDOWS" /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\lib_release\vio.lib"
+
+!ELSEIF "$(CFG)" == "vio - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD CPP /nologo /G6 /MTd /W3 /ZI /Od /I "../include" /D "_DEBUG" /D "SAFEMALLOC" /D "SAFE_MUTEX" /D "_WINDOWS" /D "USE_SYMDIR" /FD /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\lib_debug\vio.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "vio - Win32 Release"
+# Name "vio - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\vio.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\viosocket.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\viossl.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\viosslfactories.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# End Target
+# End Project
diff --git a/VC++Files/zlib/contrib/asm386/zlibvc.dsp b/VC++Files/zlib/contrib/asm386/zlibvc.dsp
new file mode 100644
index 00000000000..a70d4d4a6b0
--- /dev/null
+++ b/VC++Files/zlib/contrib/asm386/zlibvc.dsp
@@ -0,0 +1,651 @@
+# Microsoft Developer Studio Project File - Name="zlibvc" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 5.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+# TARGTYPE "Win32 (ALPHA) Dynamic-Link Library" 0x0602
+
+CFG=zlibvc - Win32 Release
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "zlibvc.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "zlibvc.mak" CFG="zlibvc - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "zlibvc - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "zlibvc - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "zlibvc - Win32 ReleaseAxp" (based on\
+ "Win32 (ALPHA) Dynamic-Link Library")
+!MESSAGE "zlibvc - Win32 ReleaseWithoutAsm" (based on\
+ "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "zlibvc - Win32 ReleaseWithoutCrtdll" (based on\
+ "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+
+!IF "$(CFG)" == "zlibvc - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir ".\Release"
+# PROP BASE Intermediate_Dir ".\Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir ".\Release"
+# PROP Intermediate_Dir ".\Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+CPP=cl.exe
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_WINDLL" /D "_WIN32" /D "BUILD_ZLIBDLL" /D "ZLIB_DLL" /D "DYNAMIC_CRC_TABLE" /D "ASMV" /FAcs /FR /FD /c
+# SUBTRACT CPP /YX
+MTL=midl.exe
+# ADD BASE MTL /nologo /D "NDEBUG" /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+RSC=rc.exe
+# ADD BASE RSC /l 0x40c /d "NDEBUG"
+# ADD RSC /l 0x40c /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386
+# ADD LINK32 gvmat32.obj kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib crtdll.lib /nologo /subsystem:windows /dll /map /machine:I386 /nodefaultlib /out:".\Release\zlib.dll"
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir ".\Debug"
+# PROP BASE Intermediate_Dir ".\Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir ".\Debug"
+# PROP Intermediate_Dir ".\Debug"
+# PROP Target_Dir ""
+CPP=cl.exe
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_WINDLL" /D "_WIN32" /D "BUILD_ZLIBDLL" /D "ZLIB_DLL" /FD /c
+# SUBTRACT CPP /YX
+MTL=midl.exe
+# ADD BASE MTL /nologo /D "_DEBUG" /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+RSC=rc.exe
+# ADD BASE RSC /l 0x40c /d "_DEBUG"
+# ADD RSC /l 0x40c /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /subsystem:windows /dll /debug /machine:I386 /out:".\Debug\zlib.dll"
+
+!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "zlibvc__"
+# PROP BASE Intermediate_Dir "zlibvc__"
+# PROP BASE Ignore_Export_Lib 0
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "zlibvc__"
+# PROP Intermediate_Dir "zlibvc__"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+MTL=midl.exe
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+CPP=cl.exe
+# ADD BASE CPP /nologo /MT /Gt0 /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_WIN32" /D "BUILD_ZLIBDLL" /D "ZLIB_DLL" /D "DYNAMIC_CRC_TABLE" /FAcs /FR /YX /FD /c
+# ADD CPP /nologo /MT /Gt0 /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_WIN32" /D "BUILD_ZLIBDLL" /D "ZLIB_DLL" /D "DYNAMIC_CRC_TABLE" /FAcs /FR /FD /c
+# SUBTRACT CPP /YX
+RSC=rc.exe
+# ADD BASE RSC /l 0x40c /d "NDEBUG"
+# ADD RSC /l 0x40c /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 crtdll.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /subsystem:windows /dll /map /machine:ALPHA /nodefaultlib /out:".\Release\zlib.dll"
+# SUBTRACT BASE LINK32 /pdb:none
+# ADD LINK32 crtdll.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /subsystem:windows /dll /map /machine:ALPHA /nodefaultlib /out:"zlibvc__\zlib.dll"
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "zlibvc_0"
+# PROP BASE Intermediate_Dir "zlibvc_0"
+# PROP BASE Ignore_Export_Lib 0
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "zlibvc_0"
+# PROP Intermediate_Dir "zlibvc_0"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+CPP=cl.exe
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_WINDLL" /D "_WIN32" /D "BUILD_ZLIBDLL" /D "ZLIB_DLL" /D "DYNAMIC_CRC_TABLE" /FAcs /FR /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_WINDLL" /D "_WIN32" /D "BUILD_ZLIBDLL" /D "ZLIB_DLL" /D "DYNAMIC_CRC_TABLE" /FAcs /FR /FD /c
+# SUBTRACT CPP /YX
+MTL=midl.exe
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+RSC=rc.exe
+# ADD BASE RSC /l 0x40c /d "NDEBUG"
+# ADD RSC /l 0x40c /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib crtdll.lib /nologo /subsystem:windows /dll /map /machine:I386 /nodefaultlib /out:".\Release\zlib.dll"
+# SUBTRACT BASE LINK32 /pdb:none
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib crtdll.lib /nologo /subsystem:windows /dll /map /machine:I386 /nodefaultlib /out:".\zlibvc_0\zlib.dll"
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "zlibvc_1"
+# PROP BASE Intermediate_Dir "zlibvc_1"
+# PROP BASE Ignore_Export_Lib 0
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "zlibvc_1"
+# PROP Intermediate_Dir "zlibvc_1"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+CPP=cl.exe
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_WINDLL" /D "_WIN32" /D "BUILD_ZLIBDLL" /D "ZLIB_DLL" /D "DYNAMIC_CRC_TABLE" /D "ASMV" /FAcs /FR /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_WINDLL" /D "_WIN32" /D "BUILD_ZLIBDLL" /D "ZLIB_DLL" /D "DYNAMIC_CRC_TABLE" /D "ASMV" /FAcs /FR /FD /c
+# SUBTRACT CPP /YX
+MTL=midl.exe
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+RSC=rc.exe
+# ADD BASE RSC /l 0x40c /d "NDEBUG"
+# ADD RSC /l 0x40c /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 gvmat32.obj kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib crtdll.lib /nologo /subsystem:windows /dll /map /machine:I386 /nodefaultlib /out:".\Release\zlib.dll"
+# SUBTRACT BASE LINK32 /pdb:none
+# ADD LINK32 gvmat32.obj kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib crtdll.lib /nologo /subsystem:windows /dll /map /machine:I386 /nodefaultlib /out:".\zlibvc_1\zlib.dll"
+# SUBTRACT LINK32 /pdb:none
+
+!ENDIF
+
+# Begin Target
+
+# Name "zlibvc - Win32 Release"
+# Name "zlibvc - Win32 Debug"
+# Name "zlibvc - Win32 ReleaseAxp"
+# Name "zlibvc - Win32 ReleaseWithoutAsm"
+# Name "zlibvc - Win32 ReleaseWithoutCrtdll"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;hpj;bat;for;f90"
+# Begin Source File
+
+SOURCE=.\adler32.c
+
+!IF "$(CFG)" == "zlibvc - Win32 Release"
+
+!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug"
+
+!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp"
+
+DEP_CPP_ADLER=\
+ ".\zconf.h"\
+ ".\zlib.h"\
+
+
+!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm"
+
+!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\compress.c
+
+!IF "$(CFG)" == "zlibvc - Win32 Release"
+
+!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug"
+
+!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp"
+
+DEP_CPP_COMPR=\
+ ".\zconf.h"\
+ ".\zlib.h"\
+
+
+!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm"
+
+!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\crc32.c
+
+!IF "$(CFG)" == "zlibvc - Win32 Release"
+
+!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug"
+
+!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp"
+
+DEP_CPP_CRC32=\
+ ".\zconf.h"\
+ ".\zlib.h"\
+
+
+!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm"
+
+!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\deflate.c
+
+!IF "$(CFG)" == "zlibvc - Win32 Release"
+
+!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug"
+
+!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp"
+
+DEP_CPP_DEFLA=\
+ ".\deflate.h"\
+ ".\zconf.h"\
+ ".\zlib.h"\
+ ".\zutil.h"\
+
+
+!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm"
+
+!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\gvmat32c.c
+
+!IF "$(CFG)" == "zlibvc - Win32 Release"
+
+!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug"
+
+!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp"
+
+!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm"
+
+!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\gzio.c
+
+!IF "$(CFG)" == "zlibvc - Win32 Release"
+
+!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug"
+
+!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp"
+
+DEP_CPP_GZIO_=\
+ ".\zconf.h"\
+ ".\zlib.h"\
+ ".\zutil.h"\
+
+
+!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm"
+
+!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\infblock.c
+
+!IF "$(CFG)" == "zlibvc - Win32 Release"
+
+!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug"
+
+!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp"
+
+DEP_CPP_INFBL=\
+ ".\infblock.h"\
+ ".\infcodes.h"\
+ ".\inftrees.h"\
+ ".\infutil.h"\
+ ".\zconf.h"\
+ ".\zlib.h"\
+ ".\zutil.h"\
+
+
+!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm"
+
+!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\infcodes.c
+
+!IF "$(CFG)" == "zlibvc - Win32 Release"
+
+!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug"
+
+!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp"
+
+DEP_CPP_INFCO=\
+ ".\infblock.h"\
+ ".\infcodes.h"\
+ ".\inffast.h"\
+ ".\inftrees.h"\
+ ".\infutil.h"\
+ ".\zconf.h"\
+ ".\zlib.h"\
+ ".\zutil.h"\
+
+
+!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm"
+
+!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\inffast.c
+
+!IF "$(CFG)" == "zlibvc - Win32 Release"
+
+!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug"
+
+!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp"
+
+DEP_CPP_INFFA=\
+ ".\infblock.h"\
+ ".\infcodes.h"\
+ ".\inffast.h"\
+ ".\inftrees.h"\
+ ".\infutil.h"\
+ ".\zconf.h"\
+ ".\zlib.h"\
+ ".\zutil.h"\
+
+
+!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm"
+
+!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\inflate.c
+
+!IF "$(CFG)" == "zlibvc - Win32 Release"
+
+!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug"
+
+!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp"
+
+DEP_CPP_INFLA=\
+ ".\infblock.h"\
+ ".\zconf.h"\
+ ".\zlib.h"\
+ ".\zutil.h"\
+
+
+!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm"
+
+!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\inftrees.c
+
+!IF "$(CFG)" == "zlibvc - Win32 Release"
+
+!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug"
+
+!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp"
+
+DEP_CPP_INFTR=\
+ ".\inftrees.h"\
+ ".\zconf.h"\
+ ".\zlib.h"\
+ ".\zutil.h"\
+
+
+!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm"
+
+!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\infutil.c
+
+!IF "$(CFG)" == "zlibvc - Win32 Release"
+
+!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug"
+
+!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp"
+
+DEP_CPP_INFUT=\
+ ".\infblock.h"\
+ ".\infcodes.h"\
+ ".\inftrees.h"\
+ ".\infutil.h"\
+ ".\zconf.h"\
+ ".\zlib.h"\
+ ".\zutil.h"\
+
+
+!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm"
+
+!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\trees.c
+
+!IF "$(CFG)" == "zlibvc - Win32 Release"
+
+!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug"
+
+!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp"
+
+DEP_CPP_TREES=\
+ ".\deflate.h"\
+ ".\zconf.h"\
+ ".\zlib.h"\
+ ".\zutil.h"\
+
+
+!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm"
+
+!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\uncompr.c
+
+!IF "$(CFG)" == "zlibvc - Win32 Release"
+
+!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug"
+
+!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp"
+
+DEP_CPP_UNCOM=\
+ ".\zconf.h"\
+ ".\zlib.h"\
+
+
+!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm"
+
+!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\unzip.c
+
+!IF "$(CFG)" == "zlibvc - Win32 Release"
+
+!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug"
+
+!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp"
+
+!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm"
+
+!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\zip.c
+
+!IF "$(CFG)" == "zlibvc - Win32 Release"
+
+!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug"
+
+!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp"
+
+!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm"
+
+!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\zlib.rc
+# End Source File
+# Begin Source File
+
+SOURCE=.\zlibvc.def
+# End Source File
+# Begin Source File
+
+SOURCE=.\zutil.c
+
+!IF "$(CFG)" == "zlibvc - Win32 Release"
+
+!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug"
+
+!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp"
+
+DEP_CPP_ZUTIL=\
+ ".\zconf.h"\
+ ".\zlib.h"\
+ ".\zutil.h"\
+
+
+!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm"
+
+!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll"
+
+!ENDIF
+
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd"
+# Begin Source File
+
+SOURCE=.\deflate.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\infblock.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\infcodes.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\inffast.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\inftrees.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\infutil.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\zconf.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\zlib.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\zutil.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/VC++Files/zlib/contrib/asm386/zlibvc.dsw b/VC++Files/zlib/contrib/asm386/zlibvc.dsw
new file mode 100644
index 00000000000..493cd870365
--- /dev/null
+++ b/VC++Files/zlib/contrib/asm386/zlibvc.dsw
@@ -0,0 +1,41 @@
+Microsoft Developer Studio Workspace File, Format Version 5.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "zlibstat"=.\zlibstat.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "zlibvc"=.\zlibvc.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/VC++Files/zlib/zlib.dsp b/VC++Files/zlib/zlib.dsp
new file mode 100644
index 00000000000..5a596b41f32
--- /dev/null
+++ b/VC++Files/zlib/zlib.dsp
@@ -0,0 +1,186 @@
+# Microsoft Developer Studio Project File - Name="zlib" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=zlib - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "zlib.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "zlib.mak" CFG="zlib - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "zlib - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "zlib - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "zlib - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "release"
+# PROP Intermediate_Dir "release"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /G6 /MT /W3 /O2 /D "NDEBUG" /D "DBUG_OFF" /D "_WINDOWS" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409
+# ADD RSC /l 0x409
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\lib_release\zlib.lib"
+
+!ELSEIF "$(CFG)" == "zlib - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "debug"
+# PROP Intermediate_Dir "debug"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /Z7 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /G6 /MTd /W3 /ZI /Od /D "_DEBUG" /D "__WIN32__" /D "_WINDOWS" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409
+# ADD RSC /l 0x409
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\lib_debug\zlib.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "zlib - Win32 Release"
+# Name "zlib - Win32 Debug"
+# Begin Source File
+
+SOURCE=.\adler32.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\compress.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\crc32.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\deflate.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\deflate.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\gzio.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\infblock.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\infblock.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\infcodes.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\infcodes.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\inffast.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\inffast.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\inffixed.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\inflate.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\inftrees.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\inftrees.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\infutil.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\infutil.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\trees.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\trees.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\uncompr.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\zconf.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\zlib.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\zutil.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\zutil.h
+# End Source File
+# End Target
+# End Project
diff --git a/acconfig.h b/acconfig.h
index 3cea5bf4b73..02be1ace0c6 100644
--- a/acconfig.h
+++ b/acconfig.h
@@ -91,6 +91,9 @@
/* Using Innobase DB */
#undef HAVE_INNOBASE_DB
+/* Using old ISAM tables */
+#undef HAVE_ISAM
+
/* Define if we have GNU readline */
#undef HAVE_LIBREADLINE
@@ -121,6 +124,9 @@
/* sigwait with one argument */
#undef HAVE_NONPOSIX_SIGWAIT
+/* ORBIT */
+#undef HAVE_ORBIT
+
/* pthread_attr_setscope */
#undef HAVE_PTHREAD_ATTR_SETSCOPE
@@ -170,9 +176,15 @@
/* new UNIXWARE7 threads that are not yet posix */
#undef HAVE_UNIXWARE7_POSIX
+/* OpenSSL */
+#undef HAVE_OPENSSL
+
/* READLINE: */
#undef HAVE_USG_SIGHOLD
+/* Virtual IO */
+#undef HAVE_VIO
+
/* Handling of large files on Solaris 2.6 */
#undef _LARGEFILE_SOURCE
@@ -248,6 +260,9 @@
#undef USE_MB
#undef USE_MB_IDENT
+/* the pstack backtrace library */
+#undef USE_PSTACK
+
/* Use MySQL RAID */
#undef USE_RAID
diff --git a/acinclude.m4 b/acinclude.m4
index 0f8b076ff62..830157423c1 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -634,6 +634,209 @@ fi
AC_MSG_RESULT($ac_cv_conv_longlong_to_float)
])
+AC_DEFUN(MYSQL_CHECK_CPU,
+[AC_CACHE_CHECK([if compiler supports optimizations for current cpu],
+mysql_cv_cpu,[
+
+ac_save_CFLAGS="$CFLAGS"
+if test -r /proc/cpuinfo ; then
+ cpuinfo="cat /proc/cpuinfo"
+ cpu_family=`$cpuinfo | grep 'cpu family' | cut -d ':' -f 2 | cut -d ' ' -f 2 | head -1`
+ cpu_vendor=`$cpuinfo | grep 'vendor_id' | cut -d ':' -f 2 | cut -d ' ' -f 2 | head -1`
+fi
+if test "$cpu_vendor" = "AuthenticAMD"; then
+ if test $cpu_family -ge 6; then
+ cpu_set="athlon pentiumpro k5 pentium i486 i386";
+ elif test $cpu_family -eq 5; then
+ cpu_set="k5 pentium i486 i386";
+ elif test $cpu_family -eq 4; then
+ cpu_set="i486 i386"
+ else
+ cpu_set="i386"
+ fi
+elif test "$cpu_vendor" = "GenuineIntel"; then
+ if test $cpu_family -ge 6; then
+ cpu_set="pentiumpro pentium i486 i386";
+ elif test $cpu_family -eq 5; then
+ cpu_set="pentium i486 i386";
+ elif test $cpu_family -eq 4; then
+ cpu_set="i486 i386"
+ else
+ cpu_set="i386"
+ fi
+fi
+
+for ac_arg in $cpu_set;
+do
+ CFLAGS="$ac_save_CFLAGS -mcpu=$ac_arg -march=$ac_arg -DCPU=$ac_arg"
+ AC_TRY_COMPILE([],[int i],mysql_cv_cpu=$ac_arg; break;, mysql_cv_cpu="unknown")
+done
+
+if test "$mysql_cv_cpu" = "unknown"
+then
+ CFLAGS="$ac_save_CFLAGS"
+ AC_MSG_RESULT(none)
+else
+ AC_MSG_RESULT($mysql_cv_cpu)
+fi
+]]))
+
+AC_DEFUN(MYSQL_CHECK_VIO, [
+ AC_ARG_WITH([vio],
+ [ --with-vio Include the Virtual IO support],
+ [vio="$withval"],
+ [vio=no])
+
+ if test "$vio" = "yes"
+ then
+ vio_dir="vio"
+ vio_libs="../vio/libvio.la"
+ AC_DEFINE(HAVE_VIO)
+ else
+ vio_dir=""
+ vio_libs=""
+ fi
+ AC_SUBST([vio_dir])
+ AC_SUBST([vio_libs])
+])
+
+AC_DEFUN(MYSQL_FIND_OPENSSL, [
+ for d in /usr/ssl/include /usr/local/ssl/include /usr/include/openssl \
+/usr/include/ssl /opt/ssl/include /opt/openssl/include \
+/usr/local/ssl/include/openssl ; do
+ if test -f $d/ssl.h ; then
+ OPENSSL_INCLUDE=$d
+ fi
+ done
+
+ for d in /usr/ssl/lib /usr/local/ssl/lib /usr/lib/openssl \
+/usr/lib /opt/ssl/lib /opt/openssl/lib ; do
+ if test -f $d/libssl.a ; then
+ OPENSSL_LIB=$d
+ fi
+ done
+
+ if test -z "$OPENSSL_LIB" -o -z "$OPENSSL_INCLUDE" ; then
+ echo "Could not find an installation of OpenSSL"
+ if test -n "$OPENSSL_LIB" ; then
+ if test "$IS_LINUX" = "true"; then
+ echo "Looks like you've forgotted to install OpenSSL development RPM"
+ fi
+ fi
+ exit 1
+ fi
+
+])
+
+AC_DEFUN(MYSQL_CHECK_OPENSSL, [
+AC_MSG_CHECKING(for OpenSSL)
+ AC_ARG_WITH([openssl],
+ [ --with-openssl Include the OpenSSL support],
+ [openssl="$withval"],
+ [openssl=no])
+
+ openssl_libs=""
+ openssl_includes=""
+ if test "$openssl" = "yes"
+ then
+ MYSQL_FIND_OPENSSL
+ #force VIO use
+ vio_dir="vio"
+ vio_libs="../vio/libvio.la"
+ AC_DEFINE(HAVE_VIO)
+ AC_MSG_RESULT(yes)
+ openssl_libs="-L$OPENSSL_LIB -lssl -lcrypto"
+ openssl_includes="-I$OPENSSL_INCLUDE"
+ AC_DEFINE(HAVE_OPENSSL)
+
+ # openssl-devel-0.9.6 requires dlopen() and we can't link staticly
+ # on many platforms (We should actually test this here, but it's quite
+ # hard) to do as we are doing libtool for linking.
+ using_static=""
+ case "$CLIENT_EXTRA_LDFLAGS $MYSQLD_EXTRA_LDFLAGS" in
+ *-all-static*) using_static="yes" ;;
+ esac
+ if test $using_static = "yes"
+ then
+ echo "You can't use the --all-static link option when using openssl."
+ exit 1
+ fi
+ AC_MSG_RESULT(no)
+ fi
+ NON_THREADED_CLIENT_LIBS="$NON_THREADED_CLIENT_LIBS $openssl_libs"
+ AC_SUBST(openssl_libs)
+ AC_SUBST(openssl_includes)
+])
+
+
+AC_DEFUN(MYSQL_CHECK_MYSQLFS, [
+ AC_ARG_WITH([mysqlfs],
+ [\
+ --with-mysqlfs Include the corba-based MySQL file system],
+ [mysqlfs="$withval"],
+ [mysqlfs=no])
+
+dnl Call MYSQL_CHECK_ORBIT even if mysqlfs == no, so that @orbit_*@
+dnl get substituted.
+ MYSQL_CHECK_ORBIT
+
+ AC_MSG_CHECKING(if we should build MySQLFS)
+ fs_dirs=""
+ if test "$mysqlfs" = "yes"
+ then
+ if test -n "$orbit_exec_prefix"
+ then
+ fs_dirs=fs
+ AC_MSG_RESULT([yes])
+ else
+ AC_MSG_RESULT(disabled because ORBIT, the CORBA ORB, was not found)
+ fi
+ else
+ AC_MSG_RESULT([no])
+ fi
+ AC_SUBST([fs_dirs])
+])
+
+AC_DEFUN(MYSQL_CHECK_ORBIT, [
+AC_MSG_CHECKING(for ORBit)
+orbit_config_path=`which orbit-config`
+if test -n "$orbit_config_path"
+then
+ orbit_exec_prefix=`orbit-config --exec-prefix`
+ orbit_includes=`orbit-config --cflags server`
+ orbit_libs=`orbit-config --libs server`
+ orbit_idl="$orbit_exec_prefix/bin/orbit-idl"
+ AC_MSG_RESULT(found!)
+ AC_DEFINE(HAVE_ORBIT)
+else
+ orbit_exec_prefix=
+ orbit_includes=
+ orbit_libs=
+ orbit_idl=
+ AC_MSG_RESULT(not found)
+fi
+AC_SUBST(orbit_includes)
+AC_SUBST(orbit_libs)
+AC_SUBST(orbit_idl)
+])
+
+AC_DEFUN([MYSQL_CHECK_ISAM], [
+ AC_ARG_WITH([isam], [\
+ --without-isam Disable the ISAM table type],
+ [with_isam="$withval"],
+ [with_isam=yes])
+
+ isam_libs=
+ if test X"$with_isam" = X"yes"
+ then
+ AC_DEFINE(HAVE_ISAM)
+ isam_libs="\$(top_builddir)/isam/libnisam.a\
+ \$(top_builddir)/merge/libmerge.a"
+ fi
+ AC_SUBST(isam_libs)
+])
+
+
dnl ---------------------------------------------------------------------------
dnl Macro: MYSQL_CHECK_BDB
dnl Sets HAVE_BERKELEY_DB if inst library is found
@@ -906,9 +1109,9 @@ dnl ---------------------------------------------------------------------------
AC_DEFUN([MYSQL_CHECK_INNODB], [
AC_ARG_WITH([innodb],
[\
- --with-innodb Use Innodb],
+ --without-innodb Do not include the InnoDB table handler],
[innodb="$withval"],
- [innodb=no])
+ [innodb=yes])
AC_MSG_CHECKING([for Innodb])
@@ -979,48 +1182,6 @@ dnl END OF MYSQL_CHECK_INNODB SECTION
dnl ---------------------------------------------------------------------------
dnl ---------------------------------------------------------------------------
-dnl Macro: MYSQL_CHECK_GEMINI
-dnl Sets HAVE_GEMINI_DB if --with-gemini is used
-dnl ---------------------------------------------------------------------------
-
-AC_DEFUN([MYSQL_CHECK_GEMINI], [
- AC_ARG_WITH([gemini],
- [\
- --with-gemini[=DIR] Use Gemini DB located in DIR],
- [gemini="$withval"],
- [gemini=no])
-
- AC_MSG_CHECKING([for Gemini DB])
-
-dnl SORT OUT THE SUPPLIED ARGUMENTS TO DETERMINE WHAT TO DO
-dnl echo "DBG_GEM1: gemini='$gemini'"
- have_gemini_db=no
- gemini_includes=
- gemini_libs=
- case "$gemini" in
- no)
- AC_MSG_RESULT([Not using Gemini DB])
- ;;
- yes | default | *)
- have_gemini_db="yes"
- gemini_includes="-I../gemini/incl -I../gemini"
- gemini_libs="\
- ../gemini/api/libapi.a\
- ../gemini/db/libdb.a\
- ../gemini/dbut/libdbut.a"
- AC_MSG_RESULT([Using Gemini DB])
- ;;
- esac
-
- AC_SUBST(gemini_includes)
- AC_SUBST(gemini_libs)
-])
-
-dnl ---------------------------------------------------------------------------
-dnl END OF MYSQL_CHECK_GEMINI SECTION
-dnl ---------------------------------------------------------------------------
-
-dnl ---------------------------------------------------------------------------
dnl Got this from the GNU tar 1.13.11 distribution
dnl by Paul Eggert <eggert@twinsun.com>
dnl ---------------------------------------------------------------------------
diff --git a/bdb/include/btree_ext.h b/bdb/include/btree_ext.h
deleted file mode 100644
index 8a9866e0b5a..00000000000
--- a/bdb/include/btree_ext.h
+++ /dev/null
@@ -1,122 +0,0 @@
-/* DO NOT EDIT: automatically built by dist/s_include. */
-#ifndef _btree_ext_h_
-#define _btree_ext_h_
-#if defined(__cplusplus)
-extern "C" {
-#endif
-int __bam_cmp __P((DB *, const DBT *, PAGE *,
- u_int32_t, int (*)(DB *, const DBT *, const DBT *), int *));
-int __bam_defcmp __P((DB *, const DBT *, const DBT *));
-size_t __bam_defpfx __P((DB *, const DBT *, const DBT *));
-int __bam_pgin __P((DB_ENV *, db_pgno_t, void *, DBT *));
-int __bam_pgout __P((DB_ENV *, db_pgno_t, void *, DBT *));
-int __bam_mswap __P((PAGE *));
-void __bam_cprint __P((DBC *));
-int __bam_ca_delete __P((DB *, db_pgno_t, u_int32_t, int));
-int __ram_ca_delete __P((DB *, db_pgno_t));
-int __bam_ca_di __P((DBC *, db_pgno_t, u_int32_t, int));
-int __bam_ca_dup __P((DBC *,
- u_int32_t, db_pgno_t, u_int32_t, db_pgno_t, u_int32_t));
-int __bam_ca_undodup __P((DB *,
- u_int32_t, db_pgno_t, u_int32_t, u_int32_t));
-int __bam_ca_rsplit __P((DBC *, db_pgno_t, db_pgno_t));
-int __bam_ca_split __P((DBC *,
- db_pgno_t, db_pgno_t, db_pgno_t, u_int32_t, int));
-void __bam_ca_undosplit __P((DB *,
- db_pgno_t, db_pgno_t, db_pgno_t, u_int32_t));
-int __bam_c_init __P((DBC *, DBTYPE));
-int __bam_c_refresh __P((DBC *));
-int __bam_c_count __P((DBC *, db_recno_t *));
-int __bam_c_dup __P((DBC *, DBC *));
-int __bam_c_rget __P((DBC *, DBT *, u_int32_t));
-int __bam_delete __P((DB *, DB_TXN *, DBT *, u_int32_t));
-int __bam_ditem __P((DBC *, PAGE *, u_int32_t));
-int __bam_adjindx __P((DBC *, PAGE *, u_int32_t, u_int32_t, int));
-int __bam_dpages __P((DBC *, EPG *));
-int __bam_db_create __P((DB *));
-int __bam_db_close __P((DB *));
-int __bam_set_flags __P((DB *, u_int32_t *flagsp));
-int __ram_set_flags __P((DB *, u_int32_t *flagsp));
-int __bam_open __P((DB *, const char *, db_pgno_t, u_int32_t));
-int __bam_metachk __P((DB *, const char *, BTMETA *));
-int __bam_read_root __P((DB *, const char *, db_pgno_t, u_int32_t));
-int __bam_iitem __P((DBC *, DBT *, DBT *, u_int32_t, u_int32_t));
-u_int32_t __bam_partsize __P((u_int32_t, DBT *, PAGE *, u_int32_t));
-int __bam_build __P((DBC *, u_int32_t,
- DBT *, PAGE *, u_int32_t, u_int32_t));
-int __bam_ritem __P((DBC *, PAGE *, u_int32_t, DBT *));
-int __bam_pg_alloc_recover
- __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
-int __bam_pg_free_recover
- __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
-int __bam_split_recover
- __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
-int __bam_rsplit_recover
- __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
-int __bam_adj_recover
- __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
-int __bam_cadjust_recover
- __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
-int __bam_cdel_recover
- __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
-int __bam_repl_recover
- __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
-int __bam_root_recover
- __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
-int __bam_curadj_recover
- __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
-int __bam_rcuradj_recover
- __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
-int __bam_reclaim __P((DB *, DB_TXN *));
-int __ram_open __P((DB *, const char *, db_pgno_t, u_int32_t));
-int __ram_c_del __P((DBC *));
-int __ram_c_get
- __P((DBC *, DBT *, DBT *, u_int32_t, db_pgno_t *));
-int __ram_c_put __P((DBC *, DBT *, DBT *, u_int32_t, db_pgno_t *));
-int __ram_ca __P((DBC *, ca_recno_arg));
-int __ram_getno __P((DBC *, const DBT *, db_recno_t *, int));
-int __ram_writeback __P((DB *));
-int __bam_rsearch __P((DBC *, db_recno_t *, u_int32_t, int, int *));
-int __bam_adjust __P((DBC *, int32_t));
-int __bam_nrecs __P((DBC *, db_recno_t *));
-db_recno_t __bam_total __P((PAGE *));
-int __bam_search __P((DBC *,
- const DBT *, u_int32_t, int, db_recno_t *, int *));
-int __bam_stkrel __P((DBC *, u_int32_t));
-int __bam_stkgrow __P((DB_ENV *, BTREE_CURSOR *));
-int __bam_split __P((DBC *, void *));
-int __bam_copy __P((DB *, PAGE *, PAGE *, u_int32_t, u_int32_t));
-int __bam_stat __P((DB *, void *, void *(*)(size_t), u_int32_t));
-int __bam_traverse __P((DBC *, db_lockmode_t,
- db_pgno_t, int (*)(DB *, PAGE *, void *, int *), void *));
-int __bam_stat_callback __P((DB *, PAGE *, void *, int *));
-int __bam_key_range __P((DB *,
- DB_TXN *, DBT *, DB_KEY_RANGE *, u_int32_t));
-int __bam_30_btreemeta __P((DB *, char *, u_int8_t *));
-int __bam_31_btreemeta
- __P((DB *, char *, u_int32_t, DB_FH *, PAGE *, int *));
-int __bam_31_lbtree
- __P((DB *, char *, u_int32_t, DB_FH *, PAGE *, int *));
-int __bam_vrfy_meta __P((DB *, VRFY_DBINFO *, BTMETA *,
- db_pgno_t, u_int32_t));
-int __ram_vrfy_leaf __P((DB *, VRFY_DBINFO *, PAGE *, db_pgno_t,
- u_int32_t));
-int __bam_vrfy __P((DB *, VRFY_DBINFO *, PAGE *, db_pgno_t,
- u_int32_t));
-int __bam_vrfy_itemorder __P((DB *, VRFY_DBINFO *, PAGE *,
- db_pgno_t, u_int32_t, int, int, u_int32_t));
-int __bam_vrfy_structure __P((DB *, VRFY_DBINFO *, db_pgno_t,
- u_int32_t));
-int __bam_vrfy_subtree __P((DB *, VRFY_DBINFO *, db_pgno_t, void *,
- void *, u_int32_t, u_int32_t *, u_int32_t *, u_int32_t *));
-int __bam_salvage __P((DB *, VRFY_DBINFO *, db_pgno_t, u_int32_t,
- PAGE *, void *, int (*)(void *, const void *), DBT *,
- u_int32_t));
-int __bam_salvage_walkdupint __P((DB *, VRFY_DBINFO *, PAGE *,
- DBT *, void *, int (*)(void *, const void *), u_int32_t));
-int __bam_meta2pgset __P((DB *, VRFY_DBINFO *, BTMETA *,
- u_int32_t, DB *));
-#if defined(__cplusplus)
-}
-#endif
-#endif /* _btree_ext_h_ */
diff --git a/bdb/include/clib_ext.h b/bdb/include/clib_ext.h
deleted file mode 100644
index efd0796afe3..00000000000
--- a/bdb/include/clib_ext.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/* DO NOT EDIT: automatically built by dist/s_include. */
-#ifndef _clib_ext_h_
-#define _clib_ext_h_
-#if defined(__cplusplus)
-extern "C" {
-#endif
-#ifndef HAVE_GETCWD
-char *getcwd __P((char *, size_t));
-#endif
-#ifndef HAVE_GETOPT
-int getopt __P((int, char * const *, const char *));
-#endif
-#ifndef HAVE_MEMCMP
-int memcmp __P((const void *, const void *, size_t));
-#endif
-#ifndef HAVE_MEMCPY
-void *memcpy __P((void *, const void *, size_t));
-#endif
-#ifndef HAVE_MEMMOVE
-void *memmove __P((void *, const void *, size_t));
-#endif
-#ifndef HAVE_RAISE
-int raise __P((int));
-#endif
-#ifndef HAVE_SNPRINTF
-int snprintf __P((char *, size_t, const char *, ...));
-#endif
-int strcasecmp __P((const char *, const char *));
-#ifndef HAVE_STRERROR
-char *strerror __P((int));
-#endif
-#ifndef HAVE_VSNPRINTF
-int vsnprintf();
-#endif
-#if defined(__cplusplus)
-}
-#endif
-#endif /* _clib_ext_h_ */
diff --git a/bdb/include/common_ext.h b/bdb/include/common_ext.h
deleted file mode 100644
index a36d62cac4a..00000000000
--- a/bdb/include/common_ext.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/* DO NOT EDIT: automatically built by dist/s_include. */
-#ifndef _common_ext_h_
-#define _common_ext_h_
-#if defined(__cplusplus)
-extern "C" {
-#endif
-int __db_byteorder __P((DB_ENV *, int));
-int __db_fchk __P((DB_ENV *, const char *, u_int32_t, u_int32_t));
-int __db_fcchk
- __P((DB_ENV *, const char *, u_int32_t, u_int32_t, u_int32_t));
-int __db_ferr __P((const DB_ENV *, const char *, int));
-int __db_pgerr __P((DB *, db_pgno_t));
-int __db_pgfmt __P((DB *, db_pgno_t));
-int __db_eopnotsup __P((const DB_ENV *));
-#ifdef DIAGNOSTIC
-void __db_assert __P((const char *, const char *, int));
-#endif
-int __db_panic_msg __P((DB_ENV *));
-int __db_panic __P((DB_ENV *, int));
-void __db_err __P((const DB_ENV *, const char *, ...));
-void __db_real_err
- __P((const DB_ENV *, int, int, int, const char *, va_list));
-void __db_logmsg __P((const DB_ENV *,
- DB_TXN *, const char *, u_int32_t, const char *, ...));
-void __db_real_log __P((const DB_ENV *,
- DB_TXN *, const char *, u_int32_t, const char *, va_list ap));
-int __db_unknown_flag __P((DB_ENV *, char *, u_int32_t));
-int __db_unknown_type __P((DB_ENV *, char *, u_int32_t));
-#ifdef DIAGNOSTIC
-int __db_missing_txn_err __P((DB_ENV *));
-#endif
-int __db_getlong
- __P((DB *, const char *, char *, long, long, long *));
-int __db_getulong
- __P((DB *, const char *, char *, u_long, u_long, u_long *));
-u_int32_t __db_log2 __P((u_int32_t));
-int __db_util_logset __P((const char *, char *));
-void __db_util_siginit __P((void));
-int __db_util_interrupted __P((void));
-void __db_util_sigresend __P((void));
-#if defined(__cplusplus)
-}
-#endif
-#endif /* _common_ext_h_ */
diff --git a/bdb/include/env_ext.h b/bdb/include/env_ext.h
deleted file mode 100644
index 0e7313fde9d..00000000000
--- a/bdb/include/env_ext.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/* DO NOT EDIT: automatically built by dist/s_include. */
-#ifndef _env_ext_h_
-#define _env_ext_h_
-#if defined(__cplusplus)
-extern "C" {
-#endif
-void __db_shalloc_init __P((void *, size_t));
-int __db_shalloc_size __P((size_t, size_t));
-int __db_shalloc __P((void *, size_t, size_t, void *));
-void __db_shalloc_free __P((void *, void *));
-size_t __db_shalloc_count __P((void *));
-size_t __db_shsizeof __P((void *));
-void __db_shalloc_dump __P((void *, FILE *));
-int __db_tablesize __P((u_int32_t));
-void __db_hashinit __P((void *, u_int32_t));
-int __dbenv_init __P((DB_ENV *));
-int __db_mi_env __P((DB_ENV *, const char *));
-int __db_mi_open __P((DB_ENV *, const char *, int));
-int __db_env_config __P((DB_ENV *, int));
-int __dbenv_open __P((DB_ENV *, const char *, u_int32_t, int));
-int __dbenv_remove __P((DB_ENV *, const char *, u_int32_t));
-int __dbenv_close __P((DB_ENV *, u_int32_t));
-int __db_appname __P((DB_ENV *, APPNAME,
- const char *, const char *, u_int32_t, DB_FH *, char **));
-int __db_apprec __P((DB_ENV *, u_int32_t));
-int __db_e_attach __P((DB_ENV *, u_int32_t *));
-int __db_e_detach __P((DB_ENV *, int));
-int __db_e_remove __P((DB_ENV *, int));
-int __db_e_stat __P((DB_ENV *, REGENV *, REGION *, int *));
-int __db_r_attach __P((DB_ENV *, REGINFO *, size_t));
-int __db_r_detach __P((DB_ENV *, REGINFO *, int));
-#if defined(__cplusplus)
-}
-#endif
-#endif /* _env_ext_h_ */
diff --git a/bdb/include/hash_ext.h b/bdb/include/hash_ext.h
deleted file mode 100644
index babb77a7902..00000000000
--- a/bdb/include/hash_ext.h
+++ /dev/null
@@ -1,106 +0,0 @@
-/* DO NOT EDIT: automatically built by dist/s_include. */
-#ifndef _hash_ext_h_
-#define _hash_ext_h_
-#if defined(__cplusplus)
-extern "C" {
-#endif
-int __ham_metachk __P((DB *, const char *, HMETA *));
-int __ham_open __P((DB *, const char *, db_pgno_t, u_int32_t));
-int __ham_c_init __P((DBC *));
-int __ham_c_count __P((DBC *, db_recno_t *));
-int __ham_c_dup __P((DBC *, DBC *));
-u_int32_t __ham_call_hash __P((DBC *, u_int8_t *, int32_t));
-int __ham_init_dbt __P((DB_ENV *,
- DBT *, u_int32_t, void **, u_int32_t *));
-int __ham_c_update
- __P((DBC *, u_int32_t, int, int));
-int __ham_get_clist __P((DB *,
- db_pgno_t, u_int32_t, DBC ***));
-int __ham_c_chgpg
- __P((DBC *, db_pgno_t, u_int32_t, db_pgno_t, u_int32_t));
-int __ham_pgin __P((DB_ENV *, db_pgno_t, void *, DBT *));
-int __ham_pgout __P((DB_ENV *, db_pgno_t, void *, DBT *));
-int __ham_mswap __P((void *));
-int __ham_add_dup __P((DBC *, DBT *, u_int32_t, db_pgno_t *));
-int __ham_dup_convert __P((DBC *));
-int __ham_make_dup __P((DB_ENV *,
- const DBT *, DBT *d, void **, u_int32_t *));
-void __ham_move_offpage __P((DBC *, PAGE *, u_int32_t, db_pgno_t));
-void __ham_dsearch __P((DBC *, DBT *, u_int32_t *, int *));
-int __ham_cprint __P((DB *));
-u_int32_t __ham_func2 __P((DB *, const void *, u_int32_t));
-u_int32_t __ham_func3 __P((DB *, const void *, u_int32_t));
-u_int32_t __ham_func4 __P((DB *, const void *, u_int32_t));
-u_int32_t __ham_func5 __P((DB *, const void *, u_int32_t));
-int __ham_get_meta __P((DBC *));
-int __ham_release_meta __P((DBC *));
-int __ham_dirty_meta __P((DBC *));
-int __ham_db_create __P((DB *));
-int __ham_db_close __P((DB *));
-int __ham_item __P((DBC *, db_lockmode_t, db_pgno_t *));
-int __ham_item_reset __P((DBC *));
-void __ham_item_init __P((DBC *));
-int __ham_item_last __P((DBC *, db_lockmode_t, db_pgno_t *));
-int __ham_item_first __P((DBC *, db_lockmode_t, db_pgno_t *));
-int __ham_item_prev __P((DBC *, db_lockmode_t, db_pgno_t *));
-int __ham_item_next __P((DBC *, db_lockmode_t, db_pgno_t *));
-void __ham_putitem __P((PAGE *p, const DBT *, int));
-void __ham_reputpair
- __P((PAGE *p, u_int32_t, u_int32_t, const DBT *, const DBT *));
-int __ham_del_pair __P((DBC *, int));
-int __ham_replpair __P((DBC *, DBT *, u_int32_t));
-void __ham_onpage_replace __P((PAGE *, size_t, u_int32_t, int32_t,
- int32_t, DBT *));
-int __ham_split_page __P((DBC *, u_int32_t, u_int32_t));
-int __ham_add_el __P((DBC *, const DBT *, const DBT *, int));
-void __ham_copy_item __P((size_t, PAGE *, u_int32_t, PAGE *));
-int __ham_add_ovflpage __P((DBC *, PAGE *, int, PAGE **));
-int __ham_get_cpage __P((DBC *, db_lockmode_t));
-int __ham_next_cpage __P((DBC *, db_pgno_t, int));
-int __ham_lock_bucket __P((DBC *, db_lockmode_t));
-void __ham_dpair __P((DB *, PAGE *, u_int32_t));
-int __ham_insdel_recover
- __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
-int __ham_newpage_recover
- __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
-int __ham_replace_recover
- __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
-int __ham_splitdata_recover
- __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
-int __ham_copypage_recover
- __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
-int __ham_metagroup_recover
- __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
-int __ham_groupalloc_recover
- __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
-int __ham_curadj_recover
- __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
-int __ham_chgpg_recover
- __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
-int __ham_reclaim __P((DB *, DB_TXN *txn));
-int __ham_stat __P((DB *, void *, void *(*)(size_t), u_int32_t));
- int __ham_traverse __P((DB *, DBC *, db_lockmode_t,
- int (*)(DB *, PAGE *, void *, int *), void *));
-int __ham_30_hashmeta __P((DB *, char *, u_int8_t *));
-int __ham_30_sizefix __P((DB *, DB_FH *, char *, u_int8_t *));
-int __ham_31_hashmeta
- __P((DB *, char *, u_int32_t, DB_FH *, PAGE *, int *));
-int __ham_31_hash
- __P((DB *, char *, u_int32_t, DB_FH *, PAGE *, int *));
-int __ham_vrfy_meta __P((DB *, VRFY_DBINFO *, HMETA *,
- db_pgno_t, u_int32_t));
-int __ham_vrfy __P((DB *, VRFY_DBINFO *, PAGE *, db_pgno_t,
- u_int32_t));
-int __ham_vrfy_structure __P((DB *, VRFY_DBINFO *, db_pgno_t,
- u_int32_t));
-int __ham_vrfy_hashing __P((DB *,
- u_int32_t, HMETA *, u_int32_t, db_pgno_t, u_int32_t,
- u_int32_t (*) __P((DB *, const void *, u_int32_t))));
-int __ham_salvage __P((DB *, VRFY_DBINFO *, db_pgno_t, PAGE *,
- void *, int (*)(void *, const void *), u_int32_t));
-int __ham_meta2pgset __P((DB *, VRFY_DBINFO *, HMETA *, u_int32_t,
- DB *));
-#if defined(__cplusplus)
-}
-#endif
-#endif /* _hash_ext_h_ */
diff --git a/bdb/include/lock_ext.h b/bdb/include/lock_ext.h
deleted file mode 100644
index 7ed9b1c695b..00000000000
--- a/bdb/include/lock_ext.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/* DO NOT EDIT: automatically built by dist/s_include. */
-#ifndef _lock_ext_h_
-#define _lock_ext_h_
-#if defined(__cplusplus)
-extern "C" {
-#endif
-int __lock_downgrade __P((DB_ENV *,
- DB_LOCK *, db_lockmode_t, u_int32_t));
-int __lock_addfamilylocker __P((DB_ENV *, u_int32_t, u_int32_t));
-int __lock_freefamilylocker __P((DB_LOCKTAB *, u_int32_t));
-void __lock_freelocker __P((DB_LOCKTAB *,
- DB_LOCKREGION *, DB_LOCKER *, u_int32_t));
-int __lock_getlocker __P((DB_LOCKTAB *,
- u_int32_t, u_int32_t, int, DB_LOCKER **));
-int __lock_getobj __P((DB_LOCKTAB *,
- const DBT *, u_int32_t, int, DB_LOCKOBJ **));
-int __lock_promote __P((DB_LOCKTAB *, DB_LOCKOBJ *, int));
-void __lock_printlock __P((DB_LOCKTAB *, struct __db_lock *, int));
-int __lock_set_lk_conflicts __P((DB_ENV *, u_int8_t *, int));
-int __lock_set_lk_detect __P((DB_ENV *, u_int32_t));
-int __lock_set_lk_max __P((DB_ENV *, u_int32_t));
-int __lock_set_lk_max_locks __P((DB_ENV *, u_int32_t));
-int __lock_set_lk_max_lockers __P((DB_ENV *, u_int32_t));
-int __lock_set_lk_max_objects __P((DB_ENV *, u_int32_t));
-void __lock_dbenv_create __P((DB_ENV *));
-void __lock_dbenv_close __P((DB_ENV *));
-int __lock_open __P((DB_ENV *));
-int __lock_close __P((DB_ENV *));
-void __lock_region_destroy __P((DB_ENV *, REGINFO *));
-void __lock_dump_region __P((DB_ENV *, char *, FILE *));
-int __lock_cmp __P((const DBT *, DB_LOCKOBJ *));
-int __lock_locker_cmp __P((u_int32_t, DB_LOCKER *));
-u_int32_t __lock_ohash __P((const DBT *));
-u_int32_t __lock_lhash __P((DB_LOCKOBJ *));
-u_int32_t __lock_locker_hash __P((u_int32_t));
-#if defined(__cplusplus)
-}
-#endif
-#endif /* _lock_ext_h_ */
diff --git a/bdb/include/log_ext.h b/bdb/include/log_ext.h
deleted file mode 100644
index 985c5d7745b..00000000000
--- a/bdb/include/log_ext.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/* DO NOT EDIT: automatically built by dist/s_include. */
-#ifndef _log_ext_h_
-#define _log_ext_h_
-#if defined(__cplusplus)
-extern "C" {
-#endif
-int __log_open __P((DB_ENV *));
-int __log_find __P((DB_LOG *, int, int *, logfile_validity *));
-int __log_valid __P((DB_LOG *, u_int32_t, int, logfile_validity *));
-int __log_close __P((DB_ENV *));
-int __log_lastckp __P((DB_ENV *, DB_LSN *));
-int __log_findckp __P((DB_ENV *, DB_LSN *));
-int __log_get __P((DB_LOG *, DB_LSN *, DBT *, u_int32_t, int));
-void __log_dbenv_create __P((DB_ENV *));
-int __log_put __P((DB_ENV *, DB_LSN *, const DBT *, u_int32_t));
-int __log_name __P((DB_LOG *,
- u_int32_t, char **, DB_FH *, u_int32_t));
-int __log_register_recover
- __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
-int __log_reopen_file __P((DB_ENV *,
- char *, int32_t, u_int8_t *, db_pgno_t));
-int __log_add_logid __P((DB_ENV *, DB_LOG *, DB *, int32_t));
-int __db_fileid_to_db __P((DB_ENV *, DB **, int32_t, int));
-void __log_close_files __P((DB_ENV *));
-void __log_rem_logid __P((DB_LOG *, DB *, int32_t));
-int __log_lid_to_fname __P((DB_LOG *, int32_t, FNAME **));
-int __log_filelist_update
- __P((DB_ENV *, DB *, int32_t, const char *, int *));
-int __log_file_lock __P((DB *));
-#if defined(__cplusplus)
-}
-#endif
-#endif /* _log_ext_h_ */
diff --git a/bdb/include/mp_ext.h b/bdb/include/mp_ext.h
deleted file mode 100644
index 9f2b8c61f45..00000000000
--- a/bdb/include/mp_ext.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/* DO NOT EDIT: automatically built by dist/s_include. */
-#ifndef _mp_ext_h_
-#define _mp_ext_h_
-#if defined(__cplusplus)
-extern "C" {
-#endif
-int __memp_alloc __P((DB_MPOOL *,
- REGINFO *, MPOOLFILE *, size_t, roff_t *, void *));
-int __memp_bhwrite
- __P((DB_MPOOL *, MPOOLFILE *, BH *, int *, int *));
-int __memp_pgread __P((DB_MPOOLFILE *, BH *, int));
-int __memp_pgwrite
- __P((DB_MPOOL *, DB_MPOOLFILE *, BH *, int *, int *));
-int __memp_pg __P((DB_MPOOLFILE *, BH *, int));
-void __memp_bhfree __P((DB_MPOOL *, BH *, int));
-void __memp_set_unlink __P((DB_MPOOLFILE *));
-void __memp_clear_unlink __P((DB_MPOOLFILE *));
-int __memp_fopen __P((DB_MPOOL *, MPOOLFILE *, const char *,
- u_int32_t, int, size_t, int, DB_MPOOL_FINFO *, DB_MPOOLFILE **));
-void __memp_mf_discard __P((DB_MPOOL *, MPOOLFILE *));
-int __memp_fremove __P((DB_MPOOLFILE *));
-char * __memp_fn __P((DB_MPOOLFILE *));
-char * __memp_fns __P((DB_MPOOL *, MPOOLFILE *));
-void __memp_dbenv_create __P((DB_ENV *));
-int __memp_open __P((DB_ENV *));
-int __memp_close __P((DB_ENV *));
-void __mpool_region_destroy __P((DB_ENV *, REGINFO *));
-void __memp_dump_region __P((DB_ENV *, char *, FILE *));
-int __mp_xxx_fh __P((DB_MPOOLFILE *, DB_FH **));
-#if defined(__cplusplus)
-}
-#endif
-#endif /* _mp_ext_h_ */
diff --git a/bdb/include/os_ext.h b/bdb/include/os_ext.h
deleted file mode 100644
index ae9e3d304f2..00000000000
--- a/bdb/include/os_ext.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/* DO NOT EDIT: automatically built by dist/s_include. */
-#ifndef _os_ext_h_
-#define _os_ext_h_
-#if defined(__cplusplus)
-extern "C" {
-#endif
-int __os_abspath __P((const char *));
-int __os_strdup __P((DB_ENV *, const char *, void *));
-int __os_calloc __P((DB_ENV *, size_t, size_t, void *));
-int __os_malloc __P((DB_ENV *, size_t, void *(*)(size_t), void *));
-int __os_realloc __P((DB_ENV *,
- size_t, void *(*)(void *, size_t), void *));
-void __os_free __P((void *, size_t));
-void __os_freestr __P((void *));
-void *__ua_memcpy __P((void *, const void *, size_t));
-int __os_dirlist __P((DB_ENV *, const char *, char ***, int *));
-void __os_dirfree __P((char **, int));
-int __os_get_errno __P((void));
-void __os_set_errno __P((int));
-int __os_fileid __P((DB_ENV *, const char *, int, u_int8_t *));
-int __os_finit __P((DB_ENV *, DB_FH *, size_t, int));
-int __os_fpinit __P((DB_ENV *, DB_FH *, db_pgno_t, int, int));
-int __os_fsync __P((DB_ENV *, DB_FH *));
-int __os_openhandle __P((DB_ENV *, const char *, int, int, DB_FH *));
-int __os_closehandle __P((DB_FH *));
-int __os_r_sysattach __P((DB_ENV *, REGINFO *, REGION *));
-int __os_r_sysdetach __P((DB_ENV *, REGINFO *, int));
-int __os_mapfile __P((DB_ENV *,
- char *, DB_FH *, size_t, int, void **));
-int __os_unmapfile __P((DB_ENV *, void *, size_t));
-u_int32_t __db_oflags __P((int));
-int __db_omode __P((const char *));
-int __os_open __P((DB_ENV *, const char *, u_int32_t, int, DB_FH *));
-int __os_shmname __P((DB_ENV *, const char *, char **));
-int __os_r_attach __P((DB_ENV *, REGINFO *, REGION *));
-int __os_r_detach __P((DB_ENV *, REGINFO *, int));
-int __os_rename __P((DB_ENV *, const char *, const char *));
-int __os_isroot __P((void));
-char *__db_rpath __P((const char *));
-int __os_io __P((DB_ENV *, DB_IO *, int, size_t *));
-int __os_read __P((DB_ENV *, DB_FH *, void *, size_t, size_t *));
-int __os_write __P((DB_ENV *, DB_FH *, void *, size_t, size_t *));
-int __os_seek __P((DB_ENV *,
- DB_FH *, size_t, db_pgno_t, u_int32_t, int, DB_OS_SEEK));
-int __os_sleep __P((DB_ENV *, u_long, u_long));
-int __os_spin __P((void));
-void __os_yield __P((DB_ENV*, u_long));
-int __os_exists __P((const char *, int *));
-int __os_ioinfo __P((DB_ENV *, const char *,
- DB_FH *, u_int32_t *, u_int32_t *, u_int32_t *));
-int __os_tmpdir __P((DB_ENV *, u_int32_t));
-int __os_unlink __P((DB_ENV *, const char *));
-int __os_region_unlink __P((DB_ENV *, const char *));
-#if defined(DB_WIN32)
-int __os_win32_errno __P((void));
-#endif
-int __os_fpinit __P((DB_ENV *, DB_FH *, db_pgno_t, int, int));
-int __os_is_winnt __P((void));
-#if defined(__cplusplus)
-}
-#endif
-#endif /* _os_ext_h_ */
diff --git a/bdb/include/qam_ext.h b/bdb/include/qam_ext.h
deleted file mode 100644
index f6e95110c0e..00000000000
--- a/bdb/include/qam_ext.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/* DO NOT EDIT: automatically built by dist/s_include. */
-#ifndef _qam_ext_h_
-#define _qam_ext_h_
-#if defined(__cplusplus)
-extern "C" {
-#endif
-int __qam_position
- __P((DBC *, db_recno_t *, qam_position_mode, int *));
-int __qam_pitem
- __P((DBC *, QPAGE *, u_int32_t, db_recno_t, DBT *));
-int __qam_put __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t));
-int __qam_delete __P((DB *, DB_TXN *, DBT *, u_int32_t));
-int __qam_c_dup __P((DBC *, DBC *));
-int __qam_c_init __P((DBC *));
-int __qam_mswap __P((PAGE *));
-int __qam_pgin_out __P((DB_ENV *, db_pgno_t, void *, DBT *));
-int __qam_fprobe __P((DB *, db_pgno_t, void *, qam_probe_mode, int));
-int __qam_fclose __P((DB *, db_pgno_t));
-int __qam_fremove __P((DB *, db_pgno_t));
-int __qam_sync __P((DB *, u_int32_t));
-int __qam_gen_filelist __P(( DB *, QUEUE_FILELIST **));
-int __qam_db_create __P((DB *));
-int __qam_db_close __P((DB *));
-int __db_prqueue __P((DB *, u_int32_t));
-int __qam_remove __P((DB *, const char *,
- const char *, DB_LSN *, int (**)(DB *, void*), void **));
-int __qam_rename __P((DB *,
- const char *, const char *, const char *));
-int __qam_open __P((DB *, const char *, db_pgno_t, int, u_int32_t));
-int __qam_metachk __P((DB *, const char *, QMETA *));
-int __qam_inc_recover __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
-int __qam_incfirst_recover
- __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
-int __qam_mvptr_recover
- __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
-int __qam_del_recover
- __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
-int __qam_delext_recover __P((DB_ENV *,
- DBT *, DB_LSN *, db_recops, void *));
-int __qam_add_recover __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
-int __qam_delete_recover
- __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
-int __qam_rename_recover
- __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
-int __qam_stat __P((DB *, void *, void *(*)(size_t), u_int32_t));
-int __qam_31_qammeta __P((DB *, char *, u_int8_t *));
-int __qam_32_qammeta __P((DB *, char *, u_int8_t *));
-int __qam_vrfy_meta __P((DB *, VRFY_DBINFO *, QMETA *,
- db_pgno_t, u_int32_t));
-int __qam_vrfy_data __P((DB *, VRFY_DBINFO *, QPAGE *,
- db_pgno_t, u_int32_t));
-int __qam_vrfy_structure __P((DB *, VRFY_DBINFO *, u_int32_t));
-#if defined(__cplusplus)
-}
-#endif
-#endif /* _qam_ext_h_ */
diff --git a/bdb/include/tcl_ext.h b/bdb/include/tcl_ext.h
deleted file mode 100644
index 9baf7e4fdcf..00000000000
--- a/bdb/include/tcl_ext.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/* DO NOT EDIT: automatically built by dist/s_include. */
-#ifndef _tcl_ext_h_
-#define _tcl_ext_h_
-#if defined(__cplusplus)
-extern "C" {
-#endif
-int bdb_HCommand __P((Tcl_Interp *, int, Tcl_Obj * CONST*));
-#if DB_DBM_HSEARCH != 0
-int bdb_NdbmOpen __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DBM **));
-#endif
-#if DB_DBM_HSEARCH != 0
-int bdb_DbmCommand
- __P((Tcl_Interp *, int, Tcl_Obj * CONST*, int, DBM *));
-#endif
-int ndbm_Cmd __P((ClientData, Tcl_Interp *, int, Tcl_Obj * CONST*));
-int bdb_RandCommand __P((Tcl_Interp *, int, Tcl_Obj * CONST*));
-int tcl_Mutex __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB_ENV *,
- DBTCL_INFO *));
-int db_Cmd __P((ClientData, Tcl_Interp *, int, Tcl_Obj * CONST*));
-int dbc_Cmd __P((ClientData, Tcl_Interp *, int, Tcl_Obj * CONST*));
-int env_Cmd __P((ClientData, Tcl_Interp *, int, Tcl_Obj * CONST*));
-int tcl_EnvRemove __P((Tcl_Interp *, int, Tcl_Obj * CONST*,
- DB_ENV *, DBTCL_INFO *));
-int tcl_EnvVerbose __P((Tcl_Interp *, DB_ENV *, Tcl_Obj *,
- Tcl_Obj *));
-int tcl_EnvTest __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB_ENV *));
-DBTCL_INFO *_NewInfo __P((Tcl_Interp *,
- void *, char *, enum INFOTYPE));
-void *_NameToPtr __P((CONST char *));
-char *_PtrToName __P((CONST void *));
-DBTCL_INFO *_PtrToInfo __P((CONST void *));
-DBTCL_INFO *_NameToInfo __P((CONST char *));
-void _SetInfoData __P((DBTCL_INFO *, void *));
-void _DeleteInfo __P((DBTCL_INFO *));
-int _SetListElem __P((Tcl_Interp *,
- Tcl_Obj *, void *, int, void *, int));
-int _SetListElemInt __P((Tcl_Interp *, Tcl_Obj *, void *, int));
-int _SetListRecnoElem __P((Tcl_Interp *, Tcl_Obj *,
- db_recno_t, u_char *, int));
-int _GetGlobPrefix __P((char *, char **));
-int _ReturnSetup __P((Tcl_Interp *, int, char *));
-int _ErrorSetup __P((Tcl_Interp *, int, char *));
-void _ErrorFunc __P((CONST char *, char *));
-int _GetLsn __P((Tcl_Interp *, Tcl_Obj *, DB_LSN *));
-void _debug_check __P((void));
-int tcl_LockDetect __P((Tcl_Interp *, int,
- Tcl_Obj * CONST*, DB_ENV *));
-int tcl_LockGet __P((Tcl_Interp *, int,
- Tcl_Obj * CONST*, DB_ENV *));
-int tcl_LockStat __P((Tcl_Interp *, int,
- Tcl_Obj * CONST*, DB_ENV *));
-int tcl_LockVec __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB_ENV *));
-int tcl_LogArchive __P((Tcl_Interp *, int,
- Tcl_Obj * CONST*, DB_ENV *));
-int tcl_LogCompare __P((Tcl_Interp *, int,
- Tcl_Obj * CONST*));
-int tcl_LogFile __P((Tcl_Interp *, int,
- Tcl_Obj * CONST*, DB_ENV *));
-int tcl_LogFlush __P((Tcl_Interp *, int,
- Tcl_Obj * CONST*, DB_ENV *));
-int tcl_LogGet __P((Tcl_Interp *, int,
- Tcl_Obj * CONST*, DB_ENV *));
-int tcl_LogPut __P((Tcl_Interp *, int,
- Tcl_Obj * CONST*, DB_ENV *));
-int tcl_LogRegister __P((Tcl_Interp *, int,
- Tcl_Obj * CONST*, DB_ENV *));
-int tcl_LogStat __P((Tcl_Interp *, int,
- Tcl_Obj * CONST*, DB_ENV *));
-int tcl_LogUnregister __P((Tcl_Interp *, int,
- Tcl_Obj * CONST*, DB_ENV *));
-void _MpInfoDelete __P((Tcl_Interp *, DBTCL_INFO *));
-int tcl_MpSync __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB_ENV *));
-int tcl_MpTrickle __P((Tcl_Interp *, int,
- Tcl_Obj * CONST*, DB_ENV *));
-int tcl_Mp __P((Tcl_Interp *, int,
- Tcl_Obj * CONST*, DB_ENV *, DBTCL_INFO *));
-int tcl_MpStat __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB_ENV *));
-void _TxnInfoDelete __P((Tcl_Interp *, DBTCL_INFO *));
-int tcl_TxnCheckpoint __P((Tcl_Interp *, int,
- Tcl_Obj * CONST*, DB_ENV *));
-int tcl_Txn __P((Tcl_Interp *, int,
- Tcl_Obj * CONST*, DB_ENV *, DBTCL_INFO *));
-int tcl_TxnStat __P((Tcl_Interp *, int,
- Tcl_Obj * CONST*, DB_ENV *));
-int txn_Cmd __P((ClientData, Tcl_Interp *, int, Tcl_Obj * CONST*));
-#if defined(__cplusplus)
-}
-#endif
-#endif /* _tcl_ext_h_ */
diff --git a/bdb/include/txn_ext.h b/bdb/include/txn_ext.h
deleted file mode 100644
index ee6922d701c..00000000000
--- a/bdb/include/txn_ext.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/* DO NOT EDIT: automatically built by dist/s_include. */
-#ifndef _txn_ext_h_
-#define _txn_ext_h_
-#if defined(__cplusplus)
-extern "C" {
-#endif
-int __txn_xa_begin __P((DB_ENV *, DB_TXN *));
-int __txn_end __P((DB_TXN *, int));
-int __txn_activekids __P((DB_ENV *, u_int32_t, DB_TXN *));
-int __txn_regop_recover
- __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
-int __txn_xa_regop_recover
- __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
-int __txn_ckp_recover
-__P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
-int __txn_child_recover
- __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
-void __txn_dbenv_create __P((DB_ENV *));
-int __txn_open __P((DB_ENV *));
-int __txn_close __P((DB_ENV *));
-#if defined(__cplusplus)
-}
-#endif
-#endif /* _txn_ext_h_ */
diff --git a/bdb/include/xa_ext.h b/bdb/include/xa_ext.h
deleted file mode 100644
index cc16ba18337..00000000000
--- a/bdb/include/xa_ext.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/* DO NOT EDIT: automatically built by dist/s_include. */
-#ifndef _xa_ext_h_
-#define _xa_ext_h_
-#if defined(__cplusplus)
-extern "C" {
-#endif
-int __db_xa_create __P((DB *));
-int __db_rmid_to_env __P((int rmid, DB_ENV **envp));
-int __db_xid_to_txn __P((DB_ENV *, XID *, size_t *));
-int __db_map_rmid __P((int, DB_ENV *));
-int __db_unmap_rmid __P((int));
-int __db_map_xid __P((DB_ENV *, XID *, size_t));
-void __db_unmap_xid __P((DB_ENV *, XID *, size_t));
-#if defined(__cplusplus)
-}
-#endif
-#endif /* _xa_ext_h_ */
diff --git a/build-tags b/build-tags
deleted file mode 100755
index 90b957eb3bc..00000000000
--- a/build-tags
+++ /dev/null
@@ -1,11 +0,0 @@
-#! /bin/sh
-
-if [ ! -f configure.in ] ; then
- echo "$0 must be run from MySQL source root"
- exit 1
-fi
-
-rm -f TAGS
-find -not -path \*SCCS\* -and \
- \( -name \*.cc -or -name \*.h -or -name \*.yy -or -name \*.c \) \
- -print -exec etags -o TAGS --append {} \;
diff --git a/client/Makefile.am b/client/Makefile.am
index 1710e573d20..cccb612af98 100644
--- a/client/Makefile.am
+++ b/client/Makefile.am
@@ -16,13 +16,13 @@
# This file is public domain and comes with NO WARRANTY of any kind
-INCLUDES = -I$(srcdir)/../include \
+INCLUDES = -I$(srcdir)/../include $(openssl_includes) \
-I../include -I$(srcdir)/.. -I$(top_srcdir) \
-I..
LIBS = @CLIENT_LIBS@
LDADD = @CLIENT_EXTRA_LDFLAGS@ ../libmysql/libmysqlclient.la
bin_PROGRAMS = mysql mysqladmin mysqlcheck mysqlshow \
- mysqldump mysqlimport mysqltest mysqlbinlog
+ mysqldump mysqlimport mysqltest mysqlbinlog mysqlmanagerc mysqlmanager-pwgen
noinst_PROGRAMS = insert_test select_test thread_test
noinst_HEADERS = sql_string.h completion_hash.h my_readline.h \
client_priv.h
@@ -41,6 +41,8 @@ mysqltest_SOURCES= mysqltest.c
mysqltest_DEPENDENCIES= $(LIBRARIES) $(pkglib_LTLIBRARIES)
mysqlbinlog_SOURCES = mysqlbinlog.cc
mysqlbinlog_DEPENDENCIES= $(LIBRARIES) $(pkglib_LTLIBRARIES)
+mysqlmanagerc_SOURCES = mysqlmanagerc.c
+mysqlmanagerc_DEPENDENCIES= $(LIBRARIES) $(pkglib_LTLIBRARIES)
sql_src=log_event.h log_event.cc
# Fix for mit-threads
diff --git a/client/client_priv.h b/client/client_priv.h
index 56eaf311070..e8355e801a2 100644
--- a/client/client_priv.h
+++ b/client/client_priv.h
@@ -1,24 +1,25 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/* Common defines for all clients */
-#include <global.h>
+#include <my_global.h>
#include <my_sys.h>
#include <m_string.h>
+#include <mysql_embed.h>
#include <mysql.h>
#include <errmsg.h>
#include <getopt.h>
diff --git a/client/completion_hash.cc b/client/completion_hash.cc
index 006427f0295..ff5d0b28e41 100644
--- a/client/completion_hash.cc
+++ b/client/completion_hash.cc
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/* Quick & light hash implementation for tab completion purposes
*
@@ -22,7 +21,7 @@
* Small portability changes by Monty. Changed also to use my_malloc/my_free
*/
-#include <global.h>
+#include <my_global.h>
#include <m_string.h>
#undef SAFEMALLOC // Speed things up
#include <my_sys.h>
@@ -47,10 +46,12 @@ int completion_hash_init(HashTable *ht, uint nSize)
ht->arBuckets = (Bucket **) my_malloc(nSize* sizeof(Bucket *),
MYF(MY_ZEROFILL | MY_WME));
- if (!ht->arBuckets) {
+ if (!ht->arBuckets)
+ {
ht->initialized = 0;
return FAILURE;
}
+ init_alloc_root(&ht->mem_root, 8192, 0);
ht->pHashFunction = hashpjw;
ht->nTableSize = nSize;
ht->initialized = 1;
@@ -78,8 +79,7 @@ int completion_hash_update(HashTable *ht, char *arKey, uint nKeyLength,
if (!memcmp(p->arKey, arKey, nKeyLength)) {
entry *n;
- n = (entry *) my_malloc(sizeof(entry),
- MYF(MY_WME));
+ n = (entry *) alloc_root(&ht->mem_root,sizeof(entry));
n->pNext = p->pData;
n->str = str;
p->pData = n;
@@ -91,20 +91,16 @@ int completion_hash_update(HashTable *ht, char *arKey, uint nKeyLength,
p = p->pNext;
}
- p = (Bucket *) my_malloc(sizeof(Bucket),MYF(MY_WME));
-
- if (!p) {
+ if (!(p = (Bucket *) alloc_root(&ht->mem_root, sizeof(Bucket))))
return FAILURE;
- }
+
p->arKey = arKey;
p->nKeyLength = nKeyLength;
p->h = h;
- p->pData = (entry*) my_malloc(sizeof(entry),MYF(MY_WME));
- if (!p->pData) {
- my_free((gptr) p,MYF(0));
+ if (!(p->pData = (entry*) alloc_root(&ht->mem_root, sizeof(entry))))
return FAILURE;
- }
+
p->pData->str = str;
p->pData->pNext = 0;
p->count = 1;
@@ -209,24 +205,7 @@ Bucket *find_longest_match(HashTable *ht, char *str, uint length,
void completion_hash_clean(HashTable *ht)
{
- uint i;
- entry *e, *t;
- Bucket *b, *tmp;
-
- for (i=0; i<ht->nTableSize; i++) {
- b = ht->arBuckets[i];
- while (b) {
- e = b->pData;
- while (e) {
- t = e;
- e = e->pNext;
- my_free((gptr) t,MYF(0));
- }
- tmp = b;
- b = b->pNext;
- my_free((gptr) tmp,MYF(0));
- }
- }
+ free_root(&ht->mem_root,MYF(0));
bzero((char*) ht->arBuckets,ht->nTableSize*sizeof(Bucket *));
}
@@ -241,9 +220,7 @@ void completion_hash_free(HashTable *ht)
void add_word(HashTable *ht,char *str)
{
int i;
- int length= (int) strlen(str);
-
- for (i=1; i<=length; i++) {
+ char *pos=str;
+ for (i=1; *pos; i++, pos++)
completion_hash_update(ht, str, i, str);
- }
}
diff --git a/client/completion_hash.h b/client/completion_hash.h
index 583a42bbbe5..c0853fddfe7 100644
--- a/client/completion_hash.h
+++ b/client/completion_hash.h
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
-
+
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
-
+
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
@@ -22,26 +22,29 @@
#define FAILURE 1
#include <sys/types.h>
+#include <my_sys.h>
typedef struct _entry {
char *str;
struct _entry *pNext;
} entry;
-typedef struct bucket {
- uint h; /* Used for numeric indexing */
- char *arKey;
- uint nKeyLength;
- uint count;
- entry *pData;
- struct bucket *pNext;
+typedef struct bucket
+{
+ uint h; /* Used for numeric indexing */
+ char *arKey;
+ uint nKeyLength;
+ uint count;
+ entry *pData;
+ struct bucket *pNext;
} Bucket;
typedef struct hashtable {
- uint nTableSize;
- uint initialized;
- uint(*pHashFunction) (char *arKey, uint nKeyLength);
- Bucket **arBuckets;
+ uint nTableSize;
+ uint initialized;
+ MEM_ROOT mem_root;
+ uint(*pHashFunction) (char *arKey, uint nKeyLength);
+ Bucket **arBuckets;
} HashTable;
extern int completion_hash_init(HashTable *ht, uint nSize);
@@ -54,4 +57,4 @@ extern void completion_hash_clean(HashTable *ht);
extern int completion_hash_exists(HashTable *ht, char *arKey, uint nKeyLength);
extern void completion_hash_free(HashTable *ht);
-#endif /* _HASH_ */
+#endif /* _HASH_ */
diff --git a/client/connect_test.c b/client/connect_test.c
index 661d448fdb0..fd81ad635ad 100644
--- a/client/connect_test.c
+++ b/client/connect_test.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include <stdio.h>
#include <stdlib.h>
diff --git a/client/errmsg.c b/client/errmsg.c
index 67cfe874f77..6cb28f3f53e 100644
--- a/client/errmsg.c
+++ b/client/errmsg.c
@@ -1,24 +1,23 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/* Error messages for MySQL clients */
/* error messages for the demon is in share/language/errmsg.sys */
-#include <global.h>
+#include <my_global.h>
#include <my_sys.h>
#include "errmsg.h"
@@ -45,7 +44,13 @@ const char *client_errors[]=
"Kann Named Pipe nicht oeffnen. Host: %-.64s pipe: %-.32s (%lu)",
"Kann den Status der Named Pipe nicht setzen. Host: %-.64s pipe: %-.32s (%lu)",
"Can't initialize character set %-.64s (path: %-.64s)",
- "Got packet bigger than 'max_allowed_packet'"
+ "Got packet bigger than 'max_allowed_packet'",
+ "Embedded server",
+ "Error on SHOW SLAVE STATUS:",
+ "Error on SHOW SLAVE HOSTS:",
+ "Error connecting to slave:",
+ "Error connecting to master:"
+
};
/* Start of code added by Roberto M. Serqueira - martinsc@uol.com.br - 05.24.2001 */
@@ -73,7 +78,12 @@ const char *client_errors[]=
"Não pode abrir 'named pipe' para o 'host' %-.64s - 'pipe' %-.32s (%lu)",
"Não pode estabelecer o estado do 'named pipe' para o 'host' %-.64s - 'pipe' %-.32s (%lu)",
"Não pode inicializar conjunto de caracteres %-.64s (caminho %-.64s)",
- "Obteve pacote maior do que 'max_allowed_packet'"
+ "Obteve pacote maior do que 'max_allowed_packet'",
+ "Embedded server",
+ "Error on SHOW SLAVE STATUS:",
+ "Error on SHOW SLAVE HOSTS:",
+ "Error connecting to slave:",
+ "Error connecting to master:"
};
#else /* ENGLISH */
@@ -99,7 +109,12 @@ const char *client_errors[]=
"Can't open named pipe to host: %-.64s pipe: %-.32s (%lu)",
"Can't set state of named pipe to host: %-.64s pipe: %-.32s (%lu)",
"Can't initialize character set %-.64s (path: %-.64s)",
- "Got packet bigger than 'max_allowed_packet'"
+ "Got packet bigger than 'max_allowed_packet'",
+ "Embedded server",
+ "Error on SHOW SLAVE STATUS:",
+ "Error on SHOW SLAVE HOSTS:",
+ "Error connecting to slave:",
+ "Error connecting to master:"
};
#endif
diff --git a/client/get_password.c b/client/get_password.c
index 25069a14b75..9928d24de32 100644
--- a/client/get_password.c
+++ b/client/get_password.c
@@ -1,25 +1,24 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/*
** Ask for a password from tty
** This is an own file to avoid conflicts with curses
*/
-#include <global.h>
+#include <my_global.h>
#include <my_sys.h>
#include "mysql.h"
#include <m_string.h>
@@ -72,7 +71,7 @@ char *get_tty_password(char *opt_message)
char *pos=to,*end=to+sizeof(to)-1;
int i=0;
DBUG_ENTER("get_tty_password");
- fprintf(stdout,opt_message ? opt_message : "Enter password: ");
+ fprintf(stderr,opt_message ? opt_message : "Enter password: ");
for (;;)
{
char tmp;
@@ -125,8 +124,8 @@ static void get_password(char *to,uint length,int fd,bool echo)
{
if (echo)
{
- fputs("\b \b",stdout);
- fflush(stdout);
+ fputs("\b \b",stderr);
+ fflush(stderr);
}
pos--;
continue;
@@ -138,8 +137,8 @@ static void get_password(char *to,uint length,int fd,bool echo)
continue;
if (echo)
{
- fputc('*',stdout);
- fflush(stdout);
+ fputc('*',stderr);
+ fflush(stderr);
}
*(pos++) = tmp;
}
@@ -172,10 +171,10 @@ char *get_tty_password(char *opt_message)
memset(passbuff, 0, _PASSWORD_LEN);
#endif
#else
- if (isatty(fileno(stdout)))
+ if (isatty(fileno(stderr)))
{
- fputs(opt_message ? opt_message : "Enter password: ",stdout);
- fflush(stdout);
+ fputs(opt_message ? opt_message : "Enter password: ",stderr);
+ fflush(stderr);
}
#if defined(HAVE_TERMIOS_H)
tcgetattr(fileno(stdin), &org);
@@ -184,7 +183,7 @@ char *get_tty_password(char *opt_message)
tmp.c_cc[VMIN] = 1;
tmp.c_cc[VTIME] = 0;
tcsetattr(fileno(stdin), TCSADRAIN, &tmp);
- get_password(buff, sizeof(buff)-1, fileno(stdin), isatty(fileno(stdout)));
+ get_password(buff, sizeof(buff)-1, fileno(stdin), isatty(fileno(stderr)));
tcsetattr(fileno(stdin), TCSADRAIN, &org);
#elif defined(HAVE_TERMIO_H)
ioctl(fileno(stdin), (int) TCGETA, &org);
@@ -193,7 +192,7 @@ char *get_tty_password(char *opt_message)
tmp.c_cc[VMIN] = 1;
tmp.c_cc[VTIME]= 0;
ioctl(fileno(stdin),(int) TCSETA, &tmp);
- get_password(buff,sizeof(buff)-1,fileno(stdin),isatty(fileno(stdout)));
+ get_password(buff,sizeof(buff)-1,fileno(stdin),isatty(fileno(stderr)));
ioctl(fileno(stdin),(int) TCSETA, &org);
#else
gtty(fileno(stdin), &org);
@@ -201,11 +200,11 @@ char *get_tty_password(char *opt_message)
tmp.sg_flags &= ~ECHO;
tmp.sg_flags |= RAW;
stty(fileno(stdin), &tmp);
- get_password(buff,sizeof(buff)-1,fileno(stdin),isatty(fileno(stdout)));
+ get_password(buff,sizeof(buff)-1,fileno(stdin),isatty(fileno(stderr)));
stty(fileno(stdin), &org);
#endif
- if (isatty(fileno(stdout)))
- fputc('\n',stdout);
+ if (isatty(fileno(stderr)))
+ fputc('\n',stderr);
#endif /* HAVE_GETPASS */
DBUG_RETURN(my_strdup(buff,MYF(MY_FAE)));
diff --git a/client/insert_test.c b/client/insert_test.c
index 640935d63b2..42691df6875 100644
--- a/client/insert_test.c
+++ b/client/insert_test.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include <stdio.h>
#include <stdlib.h>
@@ -34,19 +33,13 @@ int main(int argc, char **argv)
exit(1);
}
- if (!(sock = mysql_connect(&mysql,NULL,0,0)))
+ if (!(sock = mysql_real_connect(&mysql,NULL,NULL,NULL,argv[1],0,NULL,0)))
{
fprintf(stderr,"Couldn't connect to engine!\n%s\n",mysql_error(&mysql));
perror("");
exit(1);
}
- if (mysql_select_db(sock,argv[1]))
- {
- fprintf(stderr,"Couldn't select database %s!\n%s\n",argv[1],
- mysql_error(sock));
- }
-
num = atoi(argv[2]);
count = 0;
while (count < num)
diff --git a/client/list_test.c b/client/list_test.c
index 718cc45e012..06bf16d2751 100644
--- a/client/list_test.c
+++ b/client/list_test.c
@@ -1,34 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+ 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
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#ifdef __WIN__
#include <windows.h>
diff --git a/client/my_readline.h b/client/my_readline.h
index 547587bc19d..2e716eec4cf 100644
--- a/client/my_readline.h
+++ b/client/my_readline.h
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/* readline for batch mode */
diff --git a/client/mysql.cc b/client/mysql.cc
index cfe6d823cac..769b4490096 100644
--- a/client/mysql.cc
+++ b/client/mysql.cc
@@ -1,15 +1,15 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+/* Copyright (C) 2000 MySQL AB
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -19,9 +19,12 @@
*
* Written by:
* Michael 'Monty' Widenius
- * Andi Gutmans <andi@zend.com>
+ * Andi Gutmans <andi@zend.com>
* Zeev Suraski <zeev@zend.com>
* Jani Tolonen <jani@mysql.com>
+ * Matt Wagner <matt@mysql.com>
+ * Jeremy Cole <jcole@mysql.com>
+ * Tonu Samuel <tonu@mysql.com>
*
**/
@@ -33,8 +36,9 @@
#endif
#include "my_readline.h"
#include <signal.h>
+#include <violite.h>
-const char *VER="11.16";
+const char *VER="11.20";
/* Don't try to make a nice table if the data is too big */
#define MAX_COLUMN_LENGTH 1024
@@ -71,7 +75,6 @@ extern "C" {
#endif
#undef bcmp // Fix problem with new readline
-#undef bzero
#if defined( __WIN__) || defined(OS2)
#include <conio.h>
#else
@@ -115,7 +118,7 @@ static bool info_flag=0,ignore_errors=0,wait_flag=0,quick=0,
no_rehash=0,skip_updates=0,safe_updates=0,one_database=0,
opt_compress=0, using_opt_local_infile=0,
vertical=0,skip_line_numbers=0,skip_column_names=0,opt_html=0,
- opt_nopager=1, opt_outfile=0, no_named_cmds=1;
+ opt_xml=0,opt_nopager=1, opt_outfile=0, no_named_cmds=1;
static uint verbose=0,opt_silent=0,opt_mysql_port=0, opt_local_infile=0;
static my_string opt_mysql_unix_port=0;
static int connect_flag=CLIENT_INTERACTIVE;
@@ -126,9 +129,16 @@ static String glob_buffer,old_buffer;
static int wait_time = 5;
static STATUS status;
static ulong select_limit,max_join_size,opt_connect_timeout=0;
+static char mysql_charsets_dir[FN_REFLEN+1];
+static const char *xmlmeta[] = {
+ "&", "&amp;",
+ "<", "&lt;",
+ 0, 0
+};
static char default_pager[FN_REFLEN];
char pager[FN_REFLEN], outfile[FN_REFLEN];
FILE *PAGER, *OUTFILE;
+MEM_ROOT hash_mem_root;
#include "sslopt-vars.h"
@@ -149,7 +159,7 @@ static int com_quit(String *str,char*),
com_connect(String *str,char*), com_status(String *str,char*),
com_use(String *str,char*), com_source(String *str, char*),
com_rehash(String *str, char*), com_tee(String *str, char*),
- com_notee(String *str, char*);
+ com_notee(String *str, char*), com_shell(String *str, char *);
#ifndef __WIN__
static int com_nopager(String *str, char*), com_pager(String *str, char*),
@@ -161,6 +171,7 @@ static int sql_connect(char *host,char *database,char *user,char *password,
uint silent);
static int put_info(const char *str,INFO_TYPE info,uint error=0);
static void safe_put_field(const char *pos,ulong length);
+static void xmlencode_print(const char *src, uint length);
static void init_pager();
static void end_pager();
static void init_tee();
@@ -204,6 +215,9 @@ static COMMANDS commands[] = {
{ "source", '.', com_source, 1,
"Execute a SQL script file. Takes a file name as an argument."},
{ "status", 's', com_status, 0, "Get status information from the server."},
+#ifndef __WIN__
+ { "system", '!', com_shell, 1, "Execute a system shell command."},
+#endif
{ "tee", 'T', com_tee, 1,
"Set outfile [to_outfile]. Append everything into given outfile." },
{ "use", 'u', com_use, 1,
@@ -232,6 +246,8 @@ static COMMANDS commands[] = {
};
static const char *load_default_groups[]= { "mysql","client",0 };
+static const char *server_default_groups[]=
+{ "server", "embedded", "mysql_SERVER", 0 };
#ifdef HAVE_READLINE
extern "C" void add_history(char *command); /* From readline directory */
@@ -245,6 +261,7 @@ static bool add_line(String &buffer,char *line,char *in_string);
static void remove_cntrl(String &buffer);
static void print_table_data(MYSQL_RES *result);
static void print_table_data_html(MYSQL_RES *result);
+static void print_table_data_xml(MYSQL_RES *result);
static void print_tab_data(MYSQL_RES *result);
static void print_table_data_vertically(MYSQL_RES *result);
static ulong start_timer(void);
@@ -288,7 +305,10 @@ int main(int argc,char *argv[])
!(status.line_buff=batch_readline_init(max_allowed_packet+512,stdin)))
exit(1);
glob_buffer.realloc(512);
- completion_hash_init(&ht,50);
+ mysql_server_init(0, NULL, (char**) server_default_groups);
+ completion_hash_init(&ht, 128);
+ init_alloc_root(&hash_mem_root, 16384, 0);
+ bzero((char*) &mysql, sizeof(mysql));
if (sql_connect(current_host,current_db,current_user,opt_password,
opt_silent))
{
@@ -311,9 +331,21 @@ int main(int argc,char *argv[])
mysql_thread_id(&mysql),mysql_get_server_info(&mysql));
put_info((char*) glob_buffer.ptr(),INFO_INFO);
+#ifdef HAVE_OPENSSL
+ if (mysql.net.vio->ssl_ && SSL_get_cipher(mysql.net.vio->ssl_))
+ {
+ sprintf((char*) glob_buffer.ptr(),
+ "SSL cipher in use is %s\n", SSL_get_cipher(mysql.net.vio->ssl_));
+ put_info((char*) glob_buffer.ptr(),INFO_INFO);
+ }
+ else
+ put_info("SSL is not in use\n",INFO_INFO);
+#endif /* HAVE_OPENSSL */
+
+
#ifdef HAVE_READLINE
initialize_readline(my_progname);
- if (!status.batch && !quick && !opt_html)
+ if (!status.batch && !quick && !opt_html && !opt_xml)
{
/*read-history from file, default ~/.mysql_history*/
if (getenv("MYSQL_HISTFILE"))
@@ -348,10 +380,16 @@ int main(int argc,char *argv[])
sig_handler mysql_end(int sig)
{
- if (connected)
- mysql_close(&mysql);
+ mysql_close(&mysql);
+#ifdef HAVE_OPENSSL
+ my_free(opt_ssl_key,MYF(MY_ALLOW_ZERO_PTR));
+ my_free(opt_ssl_cert,MYF(MY_ALLOW_ZERO_PTR));
+ my_free(opt_ssl_ca,MYF(MY_ALLOW_ZERO_PTR));
+ my_free(opt_ssl_capath,MYF(MY_ALLOW_ZERO_PTR));
+ my_free(opt_ssl_cipher,MYF(MY_ALLOW_ZERO_PTR));
+#endif
#ifdef HAVE_READLINE
- if (!status.batch && !quick && ! opt_html)
+ if (!status.batch && !quick && !opt_html && !opt_xml)
{
/* write-history */
if (verbose)
@@ -360,6 +398,8 @@ sig_handler mysql_end(int sig)
}
batch_readline_end(status.line_buff);
completion_hash_free(&ht);
+ free_root(&hash_mem_root,MYF(0));
+
#endif
if (sig >= 0)
put_info(sig ? "Aborted" : "Bye", INFO_RESULT);
@@ -371,6 +411,7 @@ sig_handler mysql_end(int sig)
my_free(current_db,MYF(MY_ALLOW_ZERO_PTR));
my_free(current_host,MYF(MY_ALLOW_ZERO_PTR));
my_free(current_user,MYF(MY_ALLOW_ZERO_PTR));
+ mysql_server_end();
my_end(info_flag ? MY_CHECK_ERROR | MY_GIVE_INFO : 0);
exit(status.exit_status);
}
@@ -392,6 +433,7 @@ static struct option long_options[] =
{"force", no_argument, 0, 'f'},
{"help", no_argument, 0, '?'},
{"html", no_argument, 0, 'H'},
+ {"xml", no_argument, 0, 'X'},
{"host", required_argument, 0, 'h'},
{"ignore-spaces", no_argument, 0, 'i'},
{"local-infile", optional_argument, 0, OPT_LOCAL_INFILE},
@@ -436,8 +478,8 @@ static struct option long_options[] =
CHANGEABLE_VAR changeable_vars[] = {
{ "connect_timeout", (long*) &opt_connect_timeout, 0, 0, 3600*12, 0, 1},
{ "max_allowed_packet", (long*) &max_allowed_packet,16*1024L*1024L,4096,
- 24*1024L*1024L, MALLOC_OVERHEAD,1024},
- { "net_buffer_length",(long*) &net_buffer_length,16384,1024,24*1024*1024L,
+ 512*1024L*1024L, MALLOC_OVERHEAD,1024},
+ { "net_buffer_length",(long*) &net_buffer_length,16384,1024,512*1024*1024L,
MALLOC_OVERHEAD,1024},
{ "select_limit", (long*) &select_limit, 1000L, 1, ~0L, 0, 1},
{ "max_join_size", (long*) &max_join_size, 1000000L, 1, ~0L, 0, 1},
@@ -487,6 +529,7 @@ static void usage(int version)
-i, --ignore-space Ignore space after function names.\n\
-h, --host=... Connect to host.\n\
-H, --html Produce HTML output.\n\
+ -X, --xml Produce XML output.\n\
-L, --skip-line-numbers\n\
Don't write line number for errors.\n");
#ifndef __WIN__
@@ -561,7 +604,7 @@ static int get_options(int argc, char **argv)
set_all_changeable_vars(changeable_vars);
while ((c=getopt_long(argc,argv,
- (char*) "?ABCD:LfgGHinNoqrstTU::vVw::WEe:h:O:P:S:u:#::p::",
+ (char*) "?ABCD:LfgGHXinNoqrstTU::vVw::WEe:h:O:P:S:u:#::p::",
long_options, &option_index)) != EOF)
{
switch(c) {
@@ -569,7 +612,8 @@ static int get_options(int argc, char **argv)
default_charset= optarg;
break;
case OPT_CHARSETS_DIR:
- charsets_dir= optarg;
+ strmov(mysql_charsets_dir, optarg);
+ charsets_dir = mysql_charsets_dir;
break;
case OPT_TEE:
if (!opt_outfile && strlen(optarg))
@@ -682,6 +726,7 @@ static int get_options(int argc, char **argv)
case 'G': no_named_cmds=0; break;
case 'g': no_named_cmds=1; break;
case 'H': opt_html=1; break;
+ case 'X': opt_xml=1; break;
case 'i': connect_flag|= CLIENT_IGNORE_SPACE; break;
case 'B':
if (!status.batch)
@@ -1144,7 +1189,8 @@ static char *new_command_generator(char *text,int state)
static void build_completion_hash(bool skip_rehash,bool write_info)
{
COMMANDS *cmd=commands;
- static MYSQL_RES *databases=0,*tables=0,*fields;
+ MYSQL_RES *databases=0,*tables=0;
+ MYSQL_RES *fields;
static char ***field_names= 0;
MYSQL_ROW database_row,table_row;
MYSQL_FIELD *sql_field;
@@ -1155,16 +1201,11 @@ static void build_completion_hash(bool skip_rehash,bool write_info)
if (status.batch || quick || !current_db)
DBUG_VOID_RETURN; // We don't need completion in batches
- completion_hash_clean(&ht);
if (tables)
{
mysql_free_result(tables);
tables=0;
}
- if (databases) {
- mysql_free_result(databases);
- databases=0;
- }
/* hash SQL commands */
while (cmd->name) {
@@ -1174,16 +1215,28 @@ static void build_completion_hash(bool skip_rehash,bool write_info)
if (skip_rehash)
DBUG_VOID_RETURN;
+ /* Free old used memory */
+ if (field_names)
+ field_names=0;
+ completion_hash_clean(&ht);
+ free_root(&hash_mem_root,MYF(0));
+
/* hash MySQL functions (to be implemented) */
/* hash all database names */
- if (mysql_query(&mysql,"show databases")==0) {
+ if (mysql_query(&mysql,"show databases") == 0)
+ {
if (!(databases = mysql_store_result(&mysql)))
put_info(mysql_error(&mysql),INFO_INFO);
else
{
while ((database_row=mysql_fetch_row(databases)))
- add_word(&ht,(char*) database_row[0]);
+ {
+ char *str=strdup_root(&hash_mem_root, (char*) database_row[0]);
+ if (str)
+ add_word(&ht,(char*) str);
+ }
+ mysql_free_result(databases);
}
}
/* hash all table names */
@@ -1201,22 +1254,13 @@ You can turn off this feature to get a quicker startup with -A\n\n");
}
while ((table_row=mysql_fetch_row(tables)))
{
- if (!completion_hash_exists(&ht,(char*) table_row[0],
- (uint) strlen((const char*) table_row[0])))
- add_word(&ht,table_row[0]);
- }
- }
- }
- if (field_names) {
- for (i=0; field_names[i]; i++) {
- for (j=0; field_names[i][j]; j++) {
- my_free(field_names[i][j],MYF(0));
+ char *str=strdup_root(&hash_mem_root, (char*) table_row[0]);
+ if (str &&
+ !completion_hash_exists(&ht,(char*) str, (uint) strlen(str)))
+ add_word(&ht,str);
}
- my_free((gptr) field_names[i],MYF(0));
}
- my_free((gptr) field_names,MYF(0));
}
- field_names=0;
/* hash all field names, both with the table prefix and without it */
if (!tables) /* no tables */
@@ -1224,36 +1268,37 @@ You can turn off this feature to get a quicker startup with -A\n\n");
DBUG_VOID_RETURN;
}
mysql_data_seek(tables,0);
- field_names = (char ***) my_malloc(sizeof(char **) *
- (uint) (mysql_num_rows(tables)+1),
- MYF(MY_WME));
- if (!field_names)
+ if (!(field_names= (char ***) alloc_root(&hash_mem_root,sizeof(char **) *
+ (uint) (mysql_num_rows(tables)+1))))
+ {
+ mysql_free_result(tables);
DBUG_VOID_RETURN;
+ }
i=0;
while ((table_row=mysql_fetch_row(tables)))
{
if ((fields=mysql_list_fields(&mysql,(const char*) table_row[0],NullS)))
{
num_fields=mysql_num_fields(fields);
- field_names[i] = (char **) my_malloc(sizeof(char *)*(num_fields*2+1),
- MYF(0));
- if (!field_names[i])
- {
- continue;
- }
+ if (!(field_names[i] = (char **) alloc_root(&hash_mem_root,
+ sizeof(char *) *
+ (num_fields*2+1))))
+ break;
field_names[i][num_fields*2]='\0';
j=0;
while ((sql_field=mysql_fetch_field(fields)))
{
sprintf(buf,"%s.%s",table_row[0],sql_field->name);
- field_names[i][j] = my_strdup(buf,MYF(0));
+ field_names[i][j] = strdup_root(&hash_mem_root,buf);
add_word(&ht,field_names[i][j]);
- field_names[i][num_fields+j] = my_strdup(sql_field->name,MYF(0));
+ field_names[i][num_fields+j] = strdup_root(&hash_mem_root,
+ sql_field->name);
if (!completion_hash_exists(&ht,field_names[i][num_fields+j],
(uint) strlen(field_names[i][num_fields+j])))
add_word(&ht,field_names[i][num_fields+j]);
j++;
}
+ mysql_free_result(fields);
}
else
{
@@ -1263,6 +1308,7 @@ You can turn off this feature to get a quicker startup with -A\n\n");
}
i++;
}
+ mysql_free_result(tables);
field_names[i]=0; // End pointer
DBUG_VOID_RETURN;
}
@@ -1453,6 +1499,8 @@ com_go(String *buffer,char *line __attribute__((unused)))
init_pager();
if (opt_html)
print_table_data_html(result);
+ else if (opt_xml)
+ print_table_data_xml(result);
else if (vertical)
print_table_data_vertically(result);
else if (opt_silent && verbose <= 2 && !output_tables)
@@ -1655,6 +1703,38 @@ print_table_data_html(MYSQL_RES *result)
}
+static void
+print_table_data_xml(MYSQL_RES *result)
+{
+ MYSQL_ROW cur;
+ MYSQL_FIELD *fields;
+
+ mysql_field_seek(result,0);
+
+ tee_fputs("<?xml version=\"1.0\"?>\n\n<resultset statement=\"", PAGER);
+ xmlencode_print(glob_buffer.ptr(), strlen(glob_buffer.ptr()) - 1);
+ tee_fputs("\">", PAGER);
+
+ fields = mysql_fetch_fields(result);
+ while ((cur = mysql_fetch_row(result)))
+ {
+ (void) tee_fputs("\n <row>\n", PAGER);
+ for (uint i=0; i < mysql_num_fields(result); i++)
+ {
+ ulong *lengths=mysql_fetch_lengths(result);
+ tee_fprintf(PAGER, "\t<%s>", (fields[i].name ?
+ (fields[i].name[0] ? fields[i].name :
+ " &nbsp; ") : "NULL"));
+ xmlencode_print(cur[i], lengths[i]);
+ tee_fprintf(PAGER, "</%s>\n", (fields[i].name ?
+ (fields[i].name[0] ? fields[i].name :
+ " &nbsp; ") : "NULL"));
+ }
+ (void) tee_fputs(" </row>\n", PAGER);
+ }
+ (void) tee_fputs("</resultset>\n", PAGER);
+}
+
static void
print_table_data_vertically(MYSQL_RES *result)
@@ -1687,6 +1767,36 @@ print_table_data_vertically(MYSQL_RES *result)
}
+static const char
+*array_value(const char **array, char key)
+{
+ int x;
+ for (x= 0; array[x]; x+= 2)
+ if (*array[x] == key)
+ return array[x + 1];
+ return 0;
+}
+
+
+static void
+xmlencode_print(const char *src, uint length)
+{
+ if (!src)
+ tee_fputs("NULL", PAGER);
+ else
+ {
+ for (const char *p = src; *p && length; *p++, length--)
+ {
+ const char *t;
+ if ((t = array_value(xmlmeta, *p)))
+ tee_fputs(t, PAGER);
+ else
+ tee_putc(*p, PAGER);
+ }
+ }
+}
+
+
static void
safe_put_field(const char *pos,ulong length)
{
@@ -1716,7 +1826,7 @@ safe_put_field(const char *pos,ulong length)
tee_fputs("\\n", PAGER); // This too
else if (*pos == '\\')
tee_fputs("\\\\", PAGER);
- else
+ else
tee_putc(*pos, PAGER);
}
}
@@ -1929,6 +2039,29 @@ com_rehash(String *buffer __attribute__((unused)),
return 0;
}
+
+#ifndef __WIN__
+static int
+com_shell(String *buffer, char *line __attribute__((unused)))
+{
+ char *shell_cmd;
+ if (!(shell_cmd = strchr(line, ' ')))
+ {
+ put_info("Usage: \\! shell-command", INFO_ERROR);
+ return -1;
+ }
+ /* The output of the shell command does not
+ get directed to the pager or the outfile */
+ if(system(shell_cmd) == -1)
+ {
+ put_info(strerror(errno), INFO_ERROR, errno);
+ return -1;
+ }
+ return 0;
+}
+#endif
+
+
static int
com_print(String *buffer,char *line __attribute__((unused)))
{
@@ -2096,11 +2229,8 @@ static int
sql_real_connect(char *host,char *database,char *user,char *password,
uint silent)
{
- if (connected)
- { /* if old is open, close it first */
- mysql_close(&mysql);
- connected= 0;
- }
+ mysql_close(&mysql);
+ connected= 0;
mysql_init(&mysql);
if (opt_connect_timeout)
{
@@ -2115,7 +2245,7 @@ sql_real_connect(char *host,char *database,char *user,char *password,
#ifdef HAVE_OPENSSL
if (opt_use_ssl)
mysql_ssl_set(&mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca,
- opt_ssl_capath);
+ opt_ssl_capath, opt_ssl_cipher);
#endif
if (safe_updates)
{
@@ -2274,7 +2404,7 @@ static int
put_info(const char *str,INFO_TYPE info_type,uint error)
{
static int inited=0;
-
+
if (status.batch)
{
if (info_type == INFO_ERROR)
@@ -2454,6 +2584,7 @@ static void mysql_end_timer(ulong start_time,char *buff)
strmov(strend(buff),")");
}
+#ifndef EMBEDDED_LIBRARY
/* Keep sql_string library happy */
gptr sql_alloc(unsigned int Size)
@@ -2465,3 +2596,4 @@ void sql_element_free(void *ptr)
{
my_free((gptr) ptr,MYF(0));
}
+#endif /* EMBEDDED_LIBRARY */
diff --git a/client/mysqladmin.c b/client/mysqladmin.c
index 0dd8cfb1bd0..f6ebffea087 100644
--- a/client/mysqladmin.c
+++ b/client/mysqladmin.c
@@ -1,15 +1,15 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+/* Copyright (C) 2000 MySQL AB
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -265,7 +265,7 @@ int main(int argc,char *argv[])
#ifdef HAVE_OPENSSL
if (opt_use_ssl)
mysql_ssl_set(&mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca,
- opt_ssl_capath);
+ opt_ssl_capath, opt_ssl_cipher);
#endif /* HAVE_OPENSSL */
if (sql_connect(&mysql,host,user,opt_password,option_wait))
error = 1;
@@ -337,7 +337,7 @@ static my_bool sql_connect(MYSQL *mysql,const char *host, const char *user,
}
return 0;
}
-
+
if (!wait)
{
if (!option_silent)
@@ -649,7 +649,7 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
}
else
print_top(res);
-
+
ex_status_printed = 1; /* From now on the output will be relative */
mysql_free_result(res);
break;
@@ -745,7 +745,7 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
else
puts("Slave stopped");
break;
-
+
case ADMIN_PING:
mysql->reconnect=0; /* We want to know of reconnects */
if (!mysql_ping(mysql))
@@ -928,7 +928,7 @@ static void print_header(MYSQL_RES *result)
putchar('|');
while ((field = mysql_fetch_field(result)))
{
- printf(" %-*s|",field->max_length+1,field->name);
+ printf(" %-*s|",(int) field->max_length+1,field->name);
}
putchar('\n');
print_top(result);
@@ -983,11 +983,11 @@ static void print_relative_row(MYSQL_RES *result, MYSQL_ROW cur, uint row)
mysql_field_seek(result, 0);
field = mysql_fetch_field(result);
- printf("| %-*s|", field->max_length + 1, cur[0]);
+ printf("| %-*s|", (int) field->max_length + 1, cur[0]);
field = mysql_fetch_field(result);
tmp = cur[1] ? strtoull(cur[1], NULL, 0) : (ulonglong) 0;
- printf(" %-*s|\n", field->max_length + 1,
+ printf(" %-*s|\n", (int) field->max_length + 1,
llstr((tmp - last_values[row]), buff));
last_values[row] = tmp;
}
@@ -1000,7 +1000,7 @@ static void print_relative_row_vert(MYSQL_RES *result __attribute__((unused)),
uint length;
ulonglong tmp;
char buff[22];
-
+
if (!row)
putchar('|');
@@ -1079,7 +1079,7 @@ static void truncate_names()
*ptr++='+';
*ptr=0;
puts(top_line);
-
+
for (i = 0 ; i < ex_var_count; i++)
{
uint sfx=1,j;
diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc
index ac2f3e4efda..3d30283d13a 100644
--- a/client/mysqlbinlog.cc
+++ b/client/mysqlbinlog.cc
@@ -1,36 +1,28 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+/* Copyright (C) 2000 MySQL AB
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
#define MYSQL_CLIENT
#undef MYSQL_SERVER
#include "client_priv.h"
#include <time.h>
#include "log_event.h"
-#define CLIENT_CAPABILITIES (CLIENT_LONG_PASSWORD | CLIENT_LONG_FLAG | CLIENT_LOCAL_FILES)
+#define PROBE_HEADER_LEN (4+EVENT_LEN_OFFSET+4)
-#ifndef OS2
-extern "C"
-{
- int simple_command(MYSQL *mysql,enum enum_server_command command,
- const char *arg, uint length, my_bool skipp_check);
- uint net_safe_read(MYSQL* mysql);
-}
-#endif
+#define CLIENT_CAPABILITIES (CLIENT_LONG_PASSWORD | CLIENT_LONG_FLAG | CLIENT_LOCAL_FILES)
char server_version[SERVER_VERSION_LENGTH];
uint32 server_id = 0;
@@ -110,7 +102,7 @@ static void die(const char* fmt, ...)
static void print_version()
{
- printf("%s Ver 1.6 for %s at %s\n",my_progname,SYSTEM_TYPE, MACHINE_TYPE);
+ printf("%s Ver 1.7 for %s at %s\n",my_progname,SYSTEM_TYPE, MACHINE_TYPE);
}
@@ -205,12 +197,12 @@ static int parse_args(int *argc, char*** argv)
use_remote = 1;
host = my_strdup(optarg, MYF(0));
break;
-
+
case 'P':
use_remote = 1;
port = atoi(optarg);
break;
-
+
case 'p':
use_remote = 1;
pass = my_strdup(optarg, MYF(0));
@@ -276,13 +268,13 @@ static void dump_remote_table(NET* net, const char* db, const char* table)
uint db_len = (uint) strlen(db);
if(table_len + db_len > sizeof(buf) - 2)
die("Buffer overrun");
-
+
*p++ = db_len;
memcpy(p, db, db_len);
p += db_len;
*p++ = table_len;
memcpy(p, table, table_len);
-
+
if(simple_command(mysql, COM_TABLE_DUMP, buf, p - buf + table_len, 1))
die("Error sending the table dump command");
@@ -297,6 +289,52 @@ static void dump_remote_table(NET* net, const char* db, const char* table)
}
}
+static int check_master_version(MYSQL* mysql)
+{
+ MYSQL_RES* res = 0;
+ MYSQL_ROW row;
+ const char* version;
+ int old_format = 0;
+
+ if (mysql_query(mysql, "SELECT VERSION()")
+ || !(res = mysql_store_result(mysql)))
+ {
+ mysql_close(mysql);
+ die("Error checking master version: %s",
+ mysql_error(mysql));
+ }
+ if (!(row = mysql_fetch_row(res)))
+ {
+ mysql_free_result(res);
+ mysql_close(mysql);
+ die("Master returned no rows for SELECT VERSION()");
+ return 1;
+ }
+ if (!(version = row[0]))
+ {
+ mysql_free_result(res);
+ mysql_close(mysql);
+ die("Master reported NULL for the version");
+ }
+
+ switch (*version)
+ {
+ case '3':
+ old_format = 1;
+ break;
+ case '4':
+ old_format = 0;
+ break;
+ default:
+ sql_print_error("Master reported unrecognized MySQL version '%s'",
+ version);
+ mysql_free_result(res);
+ mysql_close(mysql);
+ return 1;
+ }
+ mysql_free_result(res);
+ return old_format;
+}
static void dump_remote_log_entries(const char* logname)
{
@@ -304,6 +342,9 @@ static void dump_remote_log_entries(const char* logname)
char last_db[FN_REFLEN+1] = "";
uint len;
NET* net = &mysql->net;
+ int old_format;
+ old_format = check_master_version(mysql);
+
if(!position) position = 4; // protect the innocent from spam
if (position < 4)
{
@@ -316,11 +357,12 @@ static void dump_remote_log_entries(const char* logname)
len = (uint) strlen(logname);
int4store(buf + 6, 0);
memcpy(buf + 10, logname,len);
- if(simple_command(mysql, COM_BINLOG_DUMP, buf, len + 10, 1))
+ if (simple_command(mysql, COM_BINLOG_DUMP, buf, len + 10, 1))
die("Error sending the log dump command");
-
+
for(;;)
{
+ const char *error;
len = net_safe_read(mysql);
if (len == packet_error)
die("Error reading packet from server: %s", mysql_error(mysql));
@@ -330,8 +372,8 @@ static void dump_remote_log_entries(const char* logname)
len, net->read_pos[5]));
Log_event * ev = Log_event::read_log_event(
(const char*) net->read_pos + 1 ,
- len - 1);
- if(ev)
+ len - 1, &error, old_format);
+ if (ev)
{
ev->print(result_file, short_form, last_db);
if(ev->get_type_code() == LOAD_EVENT)
@@ -343,12 +385,34 @@ static void dump_remote_log_entries(const char* logname)
}
}
+static int check_header(IO_CACHE* file)
+{
+ byte buf[PROBE_HEADER_LEN];
+ int old_format;
+
+ my_off_t pos = my_b_tell(file);
+ my_b_seek(file, (my_off_t)0);
+ if (my_b_read(file, buf, sizeof(buf)))
+ die("Failed reading header");
+ if (buf[EVENT_TYPE_OFFSET+4] == START_EVENT)
+ {
+ uint event_len;
+ event_len = uint4korr(buf + EVENT_LEN_OFFSET + 4);
+ old_format = (event_len < LOG_EVENT_HEADER_LEN + START_HEADER_LEN);
+ }
+ else
+ old_format = 0;
+ my_b_seek(file, pos);
+ return old_format;
+}
+
static void dump_local_log_entries(const char* logname)
{
File fd = -1;
IO_CACHE cache,*file= &cache;
ulonglong rec_count = 0;
char last_db[FN_REFLEN+1] = "";
+ bool old_format = 0;
if (logname && logname[0] != '-')
{
@@ -357,12 +421,14 @@ static void dump_local_log_entries(const char* logname)
if (init_io_cache(file, fd, 0, READ_CACHE, (my_off_t) position, 0,
MYF(MY_WME | MY_NABP)))
exit(1);
+ old_format = check_header(file);
}
else
{
if (init_io_cache(file, fileno(result_file), 0, READ_CACHE, (my_off_t) 0,
0, MYF(MY_WME | MY_NABP | MY_DONT_CHECK_FILESIZE)))
exit(1);
+ old_format = check_header(file);
if (position)
{
/* skip 'position' characters from stdout */
@@ -387,13 +453,13 @@ static void dump_local_log_entries(const char* logname)
if(memcmp(magic, BINLOG_MAGIC, 4))
die("Bad magic number; The file is probably not a MySQL binary log");
}
-
+
for (;;)
{
char llbuff[21];
my_off_t old_off = my_b_tell(file);
- Log_event* ev = Log_event::read_log_event(file);
+ Log_event* ev = Log_event::read_log_event(file, old_format);
if (!ev)
{
if (file->error)
diff --git a/client/mysqlcheck.c b/client/mysqlcheck.c
index 0f7bfb37ecf..eccc08f59ec 100644
--- a/client/mysqlcheck.c
+++ b/client/mysqlcheck.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+/* Copyright (C) 2000 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -198,7 +198,7 @@ printf("\
print_defaults("my", load_default_groups);
} /* usage */
-
+
static int get_options(int *argc, char ***argv)
{
int c, option_index;
@@ -412,7 +412,7 @@ static int process_selected_tables(char *db, char **table_names, int tables)
for (i = 0; i < tables; i++)
tot_length += strlen(*(table_names + i)) + 1;
-
+
if (!(table_names_comma_sep = (char *)
my_malloc((sizeof(char) * tot_length) + 1, MYF(MY_WME))))
return 1;
@@ -445,7 +445,7 @@ static int process_all_tables_in_db(char *database)
if (!(mysql_query(sock, "SHOW TABLES") ||
(res = mysql_store_result(sock))))
return 1;
-
+
if (opt_all_in_1)
{
char *tables, *end;
@@ -454,7 +454,7 @@ static int process_all_tables_in_db(char *database)
while ((row = mysql_fetch_row(res)))
tot_length += strlen(row[0]) + 1;
mysql_data_seek(res, 0);
-
+
if (!(tables=(char *) my_malloc(sizeof(char)*tot_length+1, MYF(MY_WME))))
{
mysql_free_result(res);
@@ -591,7 +591,7 @@ static int dbConnect(char *host, char *user, char *passwd)
#ifdef HAVE_OPENSSL
if (opt_use_ssl)
mysql_ssl_set(&mysql_connection, opt_ssl_key, opt_ssl_cert, opt_ssl_ca,
- opt_ssl_capath);
+ opt_ssl_capath, opt_ssl_cipher);
#endif
if (!(sock = mysql_real_connect(&mysql_connection, host, user, passwd,
NULL, opt_mysql_port, opt_mysql_unix_port, 0)))
diff --git a/client/mysqldump.c b/client/mysqldump.c
index b1d3195eba9..da708849992 100644
--- a/client/mysqldump.c
+++ b/client/mysqldump.c
@@ -35,7 +35,7 @@
** and adapted to mysqldump 05/11/01 by Jani Tolonen
*/
-#define DUMP_VERSION "8.21"
+#define DUMP_VERSION "8.22"
#include <my_global.h>
#include <my_sys.h>
@@ -147,9 +147,9 @@ static const char *load_default_groups[]= { "mysqldump","client",0 };
CHANGEABLE_VAR md_changeable_vars[] = {
{ "max_allowed_packet", (long*) &max_allowed_packet,24*1024*1024,4096,
- 24*1024L*1024L,MALLOC_OVERHEAD,1024},
+ 512*1024L*1024L,MALLOC_OVERHEAD,1024},
{ "net_buffer_length", (long*) &net_buffer_length,1024*1024L-1025,4096,
- 24*1024L*1024L,MALLOC_OVERHEAD,1024},
+ 512*1024L*1024L,MALLOC_OVERHEAD,1024},
{ 0, 0, 0, 0, 0, 0, 0}
};
@@ -663,8 +663,7 @@ static uint getTableStructure(char *table, char* db)
if (path)
{
char filename[FN_REFLEN], tmp_path[FN_REFLEN];
- strmov(tmp_path,path);
- convert_dirname(tmp_path);
+ convert_dirname(tmp_path,path,NullS);
sql_file= my_fopen(fn_format(filename, table, tmp_path, ".sql", 4),
O_WRONLY, MYF(MY_WME));
if (!sql_file) /* If file couldn't be opened */
@@ -741,8 +740,7 @@ static uint getTableStructure(char *table, char* db)
if (path)
{
char filename[FN_REFLEN], tmp_path[FN_REFLEN];
- strmov(tmp_path,path);
- convert_dirname(tmp_path);
+ convert_dirname(tmp_path,path,NullS);
sql_file= my_fopen(fn_format(filename, table, tmp_path, ".sql", 4),
O_WRONLY, MYF(MY_WME));
if (!sql_file) /* If file couldn't be opened */
@@ -980,8 +978,7 @@ static void dumpTable(uint numFields, char *table)
if (path)
{
char filename[FN_REFLEN], tmp_path[FN_REFLEN];
- strmov(tmp_path,path);
- convert_dirname(tmp_path);
+ convert_dirname(tmp_path,path,NullS);
my_load_path(tmp_path, tmp_path, NULL);
fn_format(filename, table, tmp_path, ".txt", 4);
my_delete(filename, MYF(0)); /* 'INTO OUTFILE' doesn't work, if
@@ -1192,7 +1189,7 @@ static void dumpTable(uint numFields, char *table)
fputs(");\n", md_result_file);
}
- /*XML - close table tag and supress regular output*/
+ /* XML - close table tag and supress regular output */
if (opt_xml)
fprintf(md_result_file, "\t</%s>\n", table);
else if (extended_insert && row_break)
@@ -1295,7 +1292,7 @@ static int dump_databases(char **db_names)
int result=0;
for ( ; *db_names ; db_names++)
{
- /*XML edit - add database element*/
+ /* XML edit - add database element */
if (opt_xml)
fprintf(md_result_file, "<%s>\n", *db_names);
if (dump_all_tables_in_db(*db_names))
diff --git a/client/mysqlimport.c b/client/mysqlimport.c
index d8f763b9653..497197f0f89 100644
--- a/client/mysqlimport.c
+++ b/client/mysqlimport.c
@@ -1,15 +1,15 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+/* Copyright (C) 2000 MySQL AB
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -336,7 +336,7 @@ static int write_to_table(char *filename, MYSQL *sock)
if (ignore)
end= strmov(end, " IGNORE");
end= strmov(strmov(end, " INTO TABLE "), tablename);
-
+
if (fields_terminated || enclosed || opt_enclosed || escaped)
end= strmov(end, " FIELDS");
end= add_load_option(end, fields_terminated, " TERMINATED BY");
@@ -400,7 +400,7 @@ static MYSQL *db_connect(char *host, char *database, char *user, char *passwd)
#ifdef HAVE_OPENSSL
if (opt_use_ssl)
mysql_ssl_set(&mysql_connection, opt_ssl_key, opt_ssl_cert, opt_ssl_ca,
- opt_ssl_capath);
+ opt_ssl_capath, opt_ssl_cipher);
#endif
if (!(sock= mysql_real_connect(&mysql_connection,host,user,passwd,
database,opt_mysql_port,opt_mysql_unix_port,
@@ -482,7 +482,7 @@ static char *add_load_option(char *ptr, const char *object,
** This is done by doubleing ' and add a end -\ if needed to avoid
** syntax errors from the SQL parser.
*/
-
+
static char *field_escape(char *to,const char *from,uint length)
{
const char *end;
@@ -505,7 +505,7 @@ static char *field_escape(char *to,const char *from,uint length)
*to++= '\\';
return to;
}
-
+
int main(int argc, char **argv)
diff --git a/client/mysqlmanager-pwgen.c b/client/mysqlmanager-pwgen.c
new file mode 100644
index 00000000000..97eb31eb9c8
--- /dev/null
+++ b/client/mysqlmanager-pwgen.c
@@ -0,0 +1,157 @@
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#define MANAGER_PWGEN_VERSION "1.0"
+
+#include <my_global.h>
+#include <m_ctype.h>
+#include <my_sys.h>
+#include <m_string.h>
+#include <mysql_version.h>
+#include <errno.h>
+#include <getopt.h>
+#include <md5.h>
+
+const char* outfile=0,*user="root";
+
+struct option long_options[] =
+{
+ {"output-file",required_argument,0,'o'},
+ {"user",required_argument,0,'u'},
+ {"help",no_argument,0,'?'},
+ {"version",no_argument,0,'V'},
+ {0,0,0,0}
+};
+
+static void die(const char* fmt, ...)
+{
+ va_list args;
+ DBUG_ENTER("die");
+ va_start(args, fmt);
+ if (fmt)
+ {
+ fprintf(stderr, "%s: ", my_progname);
+ vfprintf(stderr, fmt, args);
+ fprintf(stderr, "\n");
+ fflush(stderr);
+ }
+ va_end(args);
+ exit(1);
+}
+
+static void print_version(void)
+{
+ printf("%s Ver %s Distrib %s, for %s (%s)\n",my_progname,
+ MANAGER_PWGEN_VERSION,
+ MYSQL_SERVER_VERSION,SYSTEM_TYPE,MACHINE_TYPE);
+}
+
+void usage()
+{
+ print_version();
+ printf("MySQL AB, by Sasha\n");
+ printf("This software comes with ABSOLUTELY NO WARRANTY\n\n");
+ printf("Generates a password file to be used by mysqltest.\n\n");
+ printf("Usage: %s [OPTIONS]\n", my_progname);
+ printf("-?,--help Display this message and exit\n\
+-V,--version Display version info\n\
+-u,--user= Put given user in the password file\n\
+-o,--output-file= Write the output to the file with the given name\n");
+}
+
+int parse_args(int argc, char** argv)
+{
+ int c,option_index=0;
+ while ((c=getopt_long(argc,argv,"?Vu:o:",long_options,&option_index))
+ != EOF)
+ {
+ switch (c)
+ {
+ case 'o':
+ outfile=optarg;
+ break;
+ case 'u':
+ user=optarg;
+ break;
+ case '?':
+ usage();
+ exit(0);
+ case 'V':
+ print_version();
+ exit(0);
+ default:
+ usage();
+ exit(1);
+ }
+ }
+ return 0;
+}
+
+void get_pass(char* pw, int len)
+{
+ FILE* fp;
+ char* pw_end=pw+len;
+/* /dev/random is more secure than rand() because the seed is easy to
+ predict, so we resort to rand() only if /dev/random is not available */
+ if ((fp=fopen("/dev/random","r")))
+ {
+ fread(pw,len,1,fp);
+ fclose(fp);
+ while (pw<pw_end)
+ {
+ char tmp= 'a'+((uint)*pw % 26);
+ *pw++= tmp;
+ }
+ }
+ else
+ {
+ srand(time(NULL));
+ while (pw<pw_end)
+ {
+ char tmp= 'a'+((uint)*pw % 26);
+ *pw++= tmp;
+ }
+ }
+ *pw_end=0;
+}
+
+int main(int argc, char** argv)
+{
+ FILE* fp;
+ my_MD5_CTX context;
+ uchar digest[16];
+ char pw[17];
+ uint i;
+
+ MY_INIT(argv[0]);
+ parse_args(argc,argv);
+ if (!outfile)
+ die("Missing --output-file");
+
+ if (!(fp=fopen(outfile,"w")))
+ die("Could not open '%s'(errno=%d)",outfile,errno);
+ get_pass(pw,sizeof(pw)-1);
+ my_MD5Init(&context);
+ my_MD5Update(&context,(uchar*) pw,sizeof(pw)-1);
+ my_MD5Final(digest,&context);
+ fprintf(fp,"%s:",user);
+ for (i=0;i<sizeof(digest);i++)
+ fprintf(fp,"%02x",digest[i]);
+ fprintf(fp,"\n");
+ fclose(fp);
+ printf("%s\n",pw);
+ return 0;
+}
diff --git a/client/mysqlmanagerc.c b/client/mysqlmanagerc.c
new file mode 100644
index 00000000000..a01f6c25f34
--- /dev/null
+++ b/client/mysqlmanagerc.c
@@ -0,0 +1,178 @@
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#define MANAGER_CLIENT_VERSION "1.1"
+
+#include <my_global.h>
+#include <mysql.h>
+#include <mysql_version.h>
+#include <mysqld_error.h>
+#include <my_sys.h>
+#include <m_string.h>
+#include <getopt.h>
+#include <stdarg.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#ifndef MYSQL_MANAGER_PORT
+#define MYSQL_MANAGER_PORT 9305
+#endif
+
+static void die(const char* fmt, ...);
+
+const char* user="root",*host="localhost";
+char* pass=0;
+int quiet=0;
+uint port=MYSQL_MANAGER_PORT;
+static const char *load_default_groups[]= { "mysqlmanagerc",0 };
+char** default_argv;
+MYSQL_MANAGER *manager;
+FILE* fp, *fp_out;
+
+struct option long_options[] =
+{
+ {"host",required_argument,0,'h'},
+ {"user",required_argument,0,'u'},
+ {"password",optional_argument,0,'p',},
+ {"port",required_argument,0,'P'},
+ {"help",no_argument,0,'?'},
+ {"version",no_argument,0,'V'},
+ {"quiet",no_argument,0,'q'},
+ {0,0,0,0}
+};
+
+static void die(const char* fmt, ...)
+{
+ va_list args;
+ DBUG_ENTER("die");
+ va_start(args, fmt);
+ if (fmt)
+ {
+ fprintf(stderr, "%s: ", my_progname);
+ vfprintf(stderr, fmt, args);
+ fprintf(stderr, "\n");
+ fflush(stderr);
+ }
+ va_end(args);
+ exit(1);
+}
+
+static void print_version(void)
+{
+ printf("%s Ver %s Distrib %s, for %s (%s)\n",my_progname,
+ MANAGER_CLIENT_VERSION,
+ MYSQL_SERVER_VERSION,SYSTEM_TYPE,MACHINE_TYPE);
+}
+
+void usage()
+{
+ print_version();
+ printf("MySQL AB, by Sasha\n");
+ printf("This software comes with ABSOLUTELY NO WARRANTY\n\n");
+ printf("Command-line client for MySQL manager daemon.\n\n");
+ printf("Usage: %s [OPTIONS] < command_file\n", my_progname);
+ printf("\n\
+ -?, --help Display this help and exit.\n");
+ printf("\
+ -h, --host=... Connect to host.\n\
+ -u, --user=... User for login.\n\
+ -p[password], --password[=...]\n\
+ Password to use when connecting to server.\n\
+ -P, --port=... Port number to use for connection.\n\
+ -q, --quiet, --silent Suppress all normal output.\n\
+ -V, --version Output version information and exit.\n\
+ --no-defaults Don't read default options from any options file.\n\n");
+}
+int parse_args(int argc, char **argv)
+{
+ int c, option_index = 0;
+ my_bool tty_password=0;
+
+ load_defaults("my",load_default_groups,&argc,&argv);
+ default_argv= argv;
+
+ while ((c = getopt_long(argc, argv, "h:p::u:P:?Vq",
+ long_options, &option_index)) != EOF)
+ {
+ switch (c)
+ {
+ case 'h':
+ host=optarg;
+ break;
+ case 'u':
+ user=optarg;
+ break;
+ case 'p':
+ if (optarg)
+ {
+ my_free(pass,MYF(MY_ALLOW_ZERO_PTR));
+ pass=my_strdup(optarg,MYF(MY_FAE));
+ while (*optarg) *optarg++= 'x'; /* Destroy argument */
+ }
+ else
+ tty_password=1;
+ break;
+ case 'P':
+ port=atoi(optarg);
+ break;
+ case 'q':
+ quiet=1;
+ break;
+ case 'V':
+ print_version();
+ exit(0);
+ case '?':
+ usage();
+ exit(0);
+ default:
+ usage();
+ exit(1);
+ }
+ }
+ return 0;
+}
+int main(int argc, char** argv)
+{
+ MY_INIT(argv[0]);
+ fp=stdin;
+ fp_out=stdout;
+ parse_args(argc,argv);
+ if (!(manager=mysql_manager_init(0)))
+ die("Failed in mysql_manager_init()");
+ if (!mysql_manager_connect(manager,host,user,pass,port))
+ die("Could not connect to MySQL manager: %s(%d)",manager->last_error,
+ manager->last_errno);
+ for (;!feof(fp);)
+ {
+ char buf[4096];
+ if (!fgets(buf,sizeof(buf),fp))
+ break;
+ if (!quiet)
+ fprintf(fp_out,"<<%s",buf);
+ if (mysql_manager_command(manager,buf,strlen(buf)))
+ die("Error in command: %s(%d)",manager->last_error,manager->last_errno);
+ while (!manager->eof)
+ {
+ if (mysql_manager_fetch_line(manager,buf,sizeof(buf)))
+ die("Error fetching result line: %s(%d)", manager->last_error,
+ manager->last_errno);
+ if (!quiet)
+ fprintf(fp_out,">>%s\n",buf);
+ }
+ }
+ mysql_manager_close(manager);
+ return 0;
+}
diff --git a/client/mysqlshow.c b/client/mysqlshow.c
index 199318abc2f..e5b7f239f97 100644
--- a/client/mysqlshow.c
+++ b/client/mysqlshow.c
@@ -1,15 +1,15 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+/* Copyright (C) 2000 MySQL AB
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -18,7 +18,7 @@
#define SHOW_VERSION "8.3"
-#include <global.h>
+#include <my_global.h>
#include <my_sys.h>
#include <m_string.h>
#include "mysql.h"
@@ -87,7 +87,7 @@ int main(int argc, char **argv)
#ifdef HAVE_OPENSSL
if (opt_use_ssl)
mysql_ssl_set(&mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca,
- opt_ssl_capath);
+ opt_ssl_capath, opt_ssl_cipher);
#endif
if (!(mysql_real_connect(&mysql,host,user,opt_password,
argv[0],opt_mysql_port,opt_mysql_unix_port,
@@ -713,7 +713,7 @@ static void print_res_header(MYSQL_RES *result)
putchar('|');
while ((field = mysql_fetch_field(result)))
{
- printf(" %-*s|",field->max_length+1,field->name);
+ printf(" %-*s|",(int) field->max_length+1,field->name);
}
putchar('\n');
print_res_top(result);
diff --git a/client/mysqltest.c b/client/mysqltest.c
index 4288b5d7871..4ae74d129b9 100644
--- a/client/mysqltest.c
+++ b/client/mysqltest.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+/* Copyright (C) 2000 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -15,7 +15,8 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/* mysqltest test tool
- * See man page for more information.
+ * See the manual for more information
+ * TODO: document better how mysqltest works
*
* Written by:
* Sasha Pachev <sasha@mysql.com>
@@ -26,9 +27,6 @@
/**********************************************************************
TODO:
-- Print also the queries that returns a result to the log file; This makes
- it much easier to find out what's wrong.
-
- Do comparison line by line, instead of doing a full comparison of
the text file. This will save space as we don't need to keep many
results in memory. It will also make it possible to do simple
@@ -43,22 +41,18 @@
**********************************************************************/
-#define MTEST_VERSION "1.10"
+#define MTEST_VERSION "1.14"
-#include <global.h>
+#include <my_global.h>
+#include <mysql_embed.h>
#include <my_sys.h>
#include <m_string.h>
#include <mysql.h>
#include <mysql_version.h>
+#include <mysqld_error.h>
#include <m_ctype.h>
-#ifdef OS2
-#include <config-os2.h>
-#else
- #include <my_config.h>
-#endif
#include <my_dir.h>
#include <hash.h>
-#include <mysqld_error.h>
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
@@ -79,17 +73,38 @@
#define MAX_EXPECTED_ERRORS 10
#define QUERY_SEND 1
#define QUERY_REAP 2
-#define CON_RETRY_SLEEP 1 /* how long to sleep before trying to connect again*/
-#define MAX_CON_TRIES 2 /* sometimes in a test the client starts before
- * the server - to solve the problem, we try again
- * after some sleep if connection fails the first
- * time */
+#ifndef MYSQL_MANAGER_PORT
+#define MYSQL_MANAGER_PORT 23546
+#endif
+
+/*
+ Sometimes in a test the client starts before
+ the server - to solve the problem, we try again
+ after some sleep if connection fails the first
+ time
+*/
+#define CON_RETRY_SLEEP 2
+#define MAX_CON_TRIES 5
+
+#ifndef OS2
+#define SLAVE_POLL_INTERVAL 300000 /* 0.3 of a sec */
+#else
+#defile SLAVE_POLL_INTERVAL 0.3
+#endif
+
+enum {OPT_MANAGER_USER=256,OPT_MANAGER_HOST,OPT_MANAGER_PASSWD,
+ OPT_MANAGER_PORT,OPT_MANAGER_WAIT_TIMEOUT};
static int record = 0, verbose = 0, silent = 0, opt_sleep=0;
static char *db = 0, *pass=0;
-const char* user = 0, *host = 0, *unix_sock = 0;
-static int port = 0, opt_big_test=0;
+const char* user = 0, *host = 0, *unix_sock = 0, *opt_basedir="./";
+static int port = 0, opt_big_test=0, opt_compress=0;
static uint start_lineno, *lineno;
+const char* manager_user="root",*manager_host=0;
+char *manager_pass=0;
+int manager_port=MYSQL_MANAGER_PORT;
+int manager_wait_timeout=3;
+MYSQL_MANAGER* manager=0;
static char **default_argv;
static const char *load_default_groups[]= { "mysqltest","client",0 };
@@ -106,7 +121,7 @@ static int block_stack[BLOCK_STACK_DEPTH];
static int block_ok_stack[BLOCK_STACK_DEPTH];
-static uint global_expected_errno[MAX_EXPECTED_ERRORS];
+static uint global_expected_errno[MAX_EXPECTED_ERRORS], global_expected_errors;
DYNAMIC_ARRAY q_lines;
@@ -127,27 +142,31 @@ typedef struct
int read_lines,current_line;
} PARSER;
+MYSQL_RES *last_result=0;
+
PARSER parser;
MASTER_POS master_pos;
-int* block_ok; /* set to 0 if the current block should not be executed */
+int *block_ok; /* set to 0 if the current block should not be executed */
int false_block_depth = 0;
-const char* result_file = 0; /* if set, all results are concated and
- compared against this file*/
+/* if set, all results are concated and compared against this file */
+const char *result_file = 0;
typedef struct
{
- char* name;
+ char *name;
int name_len;
- char* str_val;
+ char *str_val;
int str_val_len;
int int_val;
int alloced_len;
int int_dirty; /* do not update string if int is updated until first read */
+ int alloced;
} VAR;
VAR var_reg[10];
/*Perl/shell-like variable registers */
HASH var_hash;
+int disable_query_log=0, disable_result_log=0;
struct connection cons[MAX_CONS];
struct connection* cur_con, *next_con, *cons_end;
@@ -169,6 +188,11 @@ Q_DIRTY_CLOSE, Q_REPLACE,
Q_PING, Q_EVAL,
Q_RPL_PROBE, Q_ENABLE_RPL_PARSE,
Q_DISABLE_RPL_PARSE, Q_EVAL_RESULT,
+Q_ENABLE_QUERY_LOG, Q_DISABLE_QUERY_LOG,
+Q_ENABLE_RESULT_LOG, Q_DISABLE_RESULT_LOG,
+Q_SERVER_START, Q_SERVER_STOP,Q_REQUIRE_MANAGER,
+Q_WAIT_FOR_SLAVE_TO_STOP,
+Q_REQUIRE_VERSION,
Q_UNKNOWN, /* Unknown command. */
Q_COMMENT, /* Comments, ignored. */
Q_COMMENT_WITH_COMMAND
@@ -181,6 +205,7 @@ struct st_query
int first_word_len;
my_bool abort_on_error, require_file;
uint expected_errno[MAX_EXPECTED_ERRORS];
+ uint expected_errors;
char record_file[FN_REFLEN];
enum enum_commands type;
};
@@ -200,6 +225,11 @@ const char *command_names[] = {
"ping", "eval",
"rpl_probe", "enable_rpl_parse",
"disable_rpl_parse", "eval_result",
+ "enable_query_log", "disable_query_log",
+ "enable_result_log", "disable_result_log",
+ "server_start", "server_stop",
+ "require_manager", "wait_for_slave_to_stop",
+ "require_version",
0
};
@@ -207,21 +237,23 @@ TYPELIB command_typelib= {array_elements(command_names),"",
command_names};
DYNAMIC_STRING ds_res;
-static void die(const char* fmt, ...);
+static void die(const char *fmt, ...);
static void init_var_hash();
static byte* get_var_key(const byte* rec, uint* len,
my_bool __attribute__((unused)) t);
-static VAR* var_init(VAR* v, const char* name, int name_len, const char* val,
+static VAR* var_init(VAR* v, const char *name, int name_len, const char *val,
int val_len);
static void var_free(void* v);
-int dyn_string_cmp(DYNAMIC_STRING* ds, const char* fname);
-void reject_dump(const char* record_file, char* buf, int size);
+int dyn_string_cmp(DYNAMIC_STRING* ds, const char *fname);
+void reject_dump(const char *record_file, char *buf, int size);
int close_connection(struct st_query* q);
-VAR* var_get(const char* var_name, const char** var_name_end, int raw);
-int eval_expr(VAR* v, const char* p, const char** p_end);
+VAR* var_get(const char *var_name, const char** var_name_end, my_bool raw,
+ my_bool ignore_not_existing);
+int eval_expr(VAR* v, const char *p, const char** p_end);
+static int read_server_arguments(const char *name);
/* Definitions for replace */
@@ -237,12 +269,14 @@ struct st_replace *init_replace(my_string *from, my_string *to, uint count,
my_string word_end_chars);
uint replace_strings(struct st_replace *rep, my_string *start,
uint *max_length, my_string from);
+void free_replace();
static int insert_pointer_name(reg1 POINTER_ARRAY *pa,my_string name);
void free_pointer_array(POINTER_ARRAY *pa);
static int initialize_replace_buffer(void);
static void free_replace_buffer(void);
-static void do_eval(DYNAMIC_STRING* query_eval, const char* query);
-void str_to_file(const char* fname, char* str, int size);
+static void do_eval(DYNAMIC_STRING* query_eval, const char *query);
+void str_to_file(const char *fname, char *str, int size);
+int do_server_op(struct st_query* q,const char *op);
struct st_replace *glob_replace;
static char *out_buff;
@@ -250,13 +284,25 @@ static uint out_length;
static int eval_result = 0;
/* Disable functions that only exist in MySQL 4.0 */
-#if MYSQL_VERSION_ID < 40000
-static void mysql_enable_rpl_parse(MYSQL* mysql __attribute__((unused))) {}
-static void mysql_disable_rpl_parse(MYSQL* mysql __attribute__((unused))) {}
-static int mysql_rpl_parse_enabled(MYSQL* mysql __attribute__((unused))) { return 1; }
-static int mysql_rpl_probe(MYSQL *mysql __attribute__((unused))) { return 1; }
+#if MYSQL_VERSION_ID < 40000 || defined(EMBEDDED_LIBRARY)
+void mysql_enable_rpl_parse(MYSQL* mysql __attribute__((unused))) {}
+void mysql_disable_rpl_parse(MYSQL* mysql __attribute__((unused))) {}
+int mysql_rpl_parse_enabled(MYSQL* mysql __attribute__((unused))) { return 1; }
+int mysql_rpl_probe(MYSQL *mysql __attribute__((unused))) { return 1; }
#endif
+#define MAX_SERVER_ARGS 20
+
+static int embedded_server_arg_count=0;
+static char *embedded_server_args[MAX_SERVER_ARGS];
+
+static const char *embedded_server_groups[] = {
+ "server",
+ "embedded",
+ "mysqltest_SERVER",
+ NullS
+};
+
static void do_eval(DYNAMIC_STRING* query_eval, const char* query)
{
@@ -264,7 +310,7 @@ static void do_eval(DYNAMIC_STRING* query_eval, const char* query)
register char c;
register int escaped = 0;
VAR* v;
-
+
for(p = query; (c = *p); ++p)
{
switch(c)
@@ -277,7 +323,7 @@ static void do_eval(DYNAMIC_STRING* query_eval, const char* query)
}
else
{
- if(!(v = var_get(p, &p, 0)))
+ if(!(v = var_get(p, &p, 0, 0)))
die("Bad variable in eval");
dynstr_append_mem(query_eval, v->str_val, v->str_val_len);
}
@@ -301,6 +347,8 @@ static void do_eval(DYNAMIC_STRING* query_eval, const char* query)
static void close_cons()
{
DBUG_ENTER("close_cons");
+ if (last_result)
+ mysql_free_result(last_result);
for (--next_con; next_con >= cons; --next_con)
{
mysql_close(&next_con->mysql);
@@ -311,21 +359,27 @@ static void close_cons()
static void close_files()
{
- do
+ DBUG_ENTER("close_files");
+ for (; cur_file != file_stack ; cur_file--)
{
if (*cur_file != stdin && *cur_file)
my_fclose(*cur_file,MYF(0));
- } while (cur_file-- != file_stack);
+ }
+ DBUG_VOID_RETURN;
}
static void free_used_memory()
{
uint i;
DBUG_ENTER("free_used_memory");
+#ifndef EMBEDDED_LIBRARY
+ if (manager)
+ mysql_manager_close(manager);
+#endif
close_cons();
close_files();
hash_free(&var_hash);
-
+
for (i=0 ; i < q_lines.elements ; i++)
{
struct st_query **q= dynamic_element(&q_lines, i, struct st_query**);
@@ -337,10 +391,13 @@ static void free_used_memory()
if(var_reg[i].alloced_len)
my_free(var_reg[i].str_val, MYF(MY_WME));
}
+ while (embedded_server_arg_count > 1)
+ my_free(embedded_server_args[--embedded_server_arg_count],MYF(0));
delete_dynamic(&q_lines);
dynstr_free(&ds_res);
my_free(pass,MYF(MY_ALLOW_ZERO_PTR));
free_defaults(default_argv);
+ mysql_server_end();
my_end(MY_CHECK_ERROR);
DBUG_VOID_RETURN;
}
@@ -362,6 +419,8 @@ static void die(const char* fmt, ...)
exit(1);
}
+/* Note that we will get some memory leaks when calling this! */
+
static void abort_not_supported_test()
{
DBUG_ENTER("abort_not_supported_test");
@@ -416,13 +475,22 @@ int dyn_string_cmp(DYNAMIC_STRING* ds, const char* fname)
DYNAMIC_STRING res_ds;
DBUG_ENTER("dyn_string_cmp");
- if (!my_stat(fname, &stat_info, MYF(MY_WME)))
+ if (!test_if_hard_path(fname))
+ {
+ strxmov(eval_file, opt_basedir, fname, NullS);
+ fn_format(eval_file, eval_file,"","",4);
+ }
+ else
+ fn_format(eval_file, fname,"","",4);
+
+ if (!my_stat(eval_file, &stat_info, MYF(MY_WME)))
die(NullS);
if (!eval_result && stat_info.st_size != ds->length)
DBUG_RETURN(2);
if (!(tmp = (char*) my_malloc(stat_info.st_size + 1, MYF(MY_WME))))
die(NullS);
- if ((fd = my_open(fname, O_RDONLY, MYF(MY_WME))) < 0)
+
+ if ((fd = my_open(eval_file, O_RDONLY, MYF(MY_WME))) < 0)
die(NullS);
if (my_read(fd, (byte*)tmp, stat_info.st_size, MYF(MY_WME|MY_NABP)))
die(NullS);
@@ -443,18 +511,18 @@ int dyn_string_cmp(DYNAMIC_STRING* ds, const char* fname)
res_ptr = tmp;
res_len = stat_info.st_size;
}
-
+
res = (memcmp(res_ptr, ds->str, res_len)) ? 1 : 0;
-
+
err:
if(res && eval_result)
str_to_file(fn_format(eval_file, fname, "", ".eval",2), res_ptr,
res_len);
-
+
my_free((gptr) tmp, MYF(0));
my_close(fd, MYF(MY_WME));
dynstr_free(&res_ds);
-
+
DBUG_RETURN(res);
}
@@ -486,55 +554,58 @@ static int check_result(DYNAMIC_STRING* ds, const char* fname,
return error;
}
-VAR* var_get(const char* var_name, const char** var_name_end, int raw)
+VAR* var_get(const char* var_name, const char** var_name_end, my_bool raw,
+ my_bool ignore_not_existing)
{
int digit;
VAR* v;
- if (*var_name++ != '$')
- {
- --var_name;
+ DBUG_ENTER("var_get");
+ DBUG_PRINT("enter",("var_name: %s",var_name));
+
+ if (*var_name != '$')
goto err;
- }
- digit = *var_name - '0';
+ digit = *++var_name - '0';
if (!(digit < 10 && digit >= 0))
{
const char* save_var_name = var_name, *end;
end = (var_name_end) ? *var_name_end : 0;
- while (isvar(*var_name))
- {
- if(end && var_name == end)
- break;
+ while (isvar(*var_name) && var_name != end)
++var_name;
- }
- if(var_name == save_var_name)
+ if (var_name == save_var_name)
+ {
+ if (ignore_not_existing)
+ DBUG_RETURN(0);
die("Empty variable");
-
- if(!(v = (VAR*)hash_search(&var_hash, save_var_name,
+ }
+
+ if (!(v = (VAR*) hash_search(&var_hash, save_var_name,
var_name - save_var_name)))
- {
- if (end)
- *(char*)end = 0;
- die("Variable '%s' used uninitialized", save_var_name);
- }
- --var_name;
+ {
+ if (ignore_not_existing)
+ DBUG_RETURN(0);
+ if (end)
+ *(char*) end = 0;
+ die("Variable '%s' used uninitialized", save_var_name);
+ }
+ --var_name; /* Point at last character */
}
else
- v = var_reg + digit;
-
+ v = var_reg + digit;
+
if (!raw && v->int_dirty)
{
sprintf(v->str_val, "%d", v->int_val);
v->int_dirty = 0;
v->str_val_len = strlen(v->str_val);
}
- if(var_name_end)
+ if (var_name_end)
*var_name_end = var_name ;
- return v;
+ DBUG_RETURN(v);
err:
if (var_name_end)
*var_name_end = 0;
die("Unsupported variable name: %s", var_name);
- return 0;
+ DBUG_RETURN(0);
}
static VAR* var_obtain(char* name, int len)
@@ -565,15 +636,23 @@ int var_set(char* var_name, char* var_name_end, char* var_val,
}
else
v = var_reg + digit;
-
+
return eval_expr(v, var_val, (const char**)&var_val_end);
}
int open_file(const char* name)
{
+ char buff[FN_REFLEN];
+ if (!test_if_hard_path(name))
+ {
+ strxmov(buff, opt_basedir, name, NullS);
+ name=buff;
+ }
+ fn_format(buff,name,"","",4);
+
if (*cur_file && cur_file == file_stack_end)
die("Source directives are nesting too deep");
- if (!(*(cur_file+1) = my_fopen(name, O_RDONLY, MYF(MY_WME))))
+ if (!(*(cur_file+1) = my_fopen(buff, O_RDONLY, MYF(MY_WME))))
die(NullS);
cur_file++;
*++lineno=1;
@@ -581,6 +660,132 @@ int open_file(const char* name)
return 0;
}
+/* ugly long name, but we are following the convention */
+int do_wait_for_slave_to_stop(struct st_query* __attribute__((unused)) q)
+{
+ MYSQL* mysql = &cur_con->mysql;
+#ifndef OS2
+ struct timeval t;
+#endif
+ for (;;)
+ {
+ MYSQL_RES* res;
+ MYSQL_ROW row;
+ int done;
+ LINT_INIT(res);
+
+ if (mysql_query(mysql,"show status like 'Slave_running'")
+ || !(res=mysql_store_result(mysql)))
+ die("Query failed while probing slave for stop: %s",
+ mysql_error(mysql));
+ if (!(row=mysql_fetch_row(res)) || !row[1])
+ {
+ mysql_free_result(res);
+ die("Strange result from query while probing slave for stop");
+ }
+ done = !strcmp(row[1],"OFF");
+ mysql_free_result(res);
+ if (done)
+ break;
+#ifndef OS2
+ t.tv_sec=0;
+ t.tv_usec=SLAVE_POLL_INTERVAL;
+ select(0,0,0,0,&t); /* sleep */
+#else
+ DosSleep(OS2_SLAVE_POLL_INTERVAL);
+#endif
+ }
+
+ return 0;
+}
+
+int do_require_manager(struct st_query* __attribute__((unused)) q)
+{
+ if (!manager)
+ abort_not_supported_test();
+ return 0;
+}
+
+#ifndef EMBEDDED_LIBRARY
+int do_server_start(struct st_query* q)
+{
+ return do_server_op(q,"start");
+}
+
+int do_server_stop(struct st_query* q)
+{
+ return do_server_op(q,"stop");
+}
+
+int do_server_op(struct st_query* q,const char* op)
+{
+ char* p=q->first_argument;
+ char com_buf[256],*com_p;
+ if (!manager)
+ {
+ die("Manager is not initialized, manager commands are not possible");
+ }
+ com_p=strmov(com_buf,op);
+ com_p=strmov(com_p,"_exec ");
+ if (!*p)
+ die("Missing server name in server_%s\n",op);
+ while (*p && !isspace(*p))
+ {
+ *com_p++=*p++;
+ }
+ *com_p++=' ';
+ com_p=int10_to_str(manager_wait_timeout,com_p,10);
+ *com_p++ = '\n';
+ *com_p=0;
+ if (mysql_manager_command(manager,com_buf,(int)(com_p-com_buf)))
+ die("Error in command: %s(%d)",manager->last_error,manager->last_errno);
+ while (!manager->eof)
+ {
+ if (mysql_manager_fetch_line(manager,com_buf,sizeof(com_buf)))
+ die("Error fetching result line: %s(%d)", manager->last_error,
+ manager->last_errno);
+ }
+
+ return 0;
+}
+#endif
+
+int do_require_version(struct st_query* q)
+{
+ MYSQL* mysql = &cur_con->mysql;
+ MYSQL_RES* res;
+ MYSQL_ROW row;
+ char* p=q->first_argument, *ver_arg;
+ uint ver_arg_len,ver_len;
+ LINT_INIT(res);
+
+ if (!*p)
+ die("Missing version argument in require_version\n");
+ ver_arg = p;
+ while (*p && !isspace(*p))
+ p++;
+ *p = 0;
+ ver_arg_len = p - ver_arg;
+
+ if (mysql_query(mysql, "select version()") ||
+ !(res=mysql_store_result(mysql)))
+ die("Query failed while check server version: %s",
+ mysql_error(mysql));
+ if (!(row=mysql_fetch_row(res)) || !row[0])
+ {
+ mysql_free_result(res);
+ die("Strange result from query while checking version");
+ }
+ ver_len = strlen(row[0]);
+ if (ver_len < ver_arg_len || memcmp(row[0],ver_arg,ver_arg_len))
+ {
+ mysql_free_result(res);
+ abort_not_supported_test();
+ }
+ mysql_free_result(res);
+ return 0;
+}
+
int do_source(struct st_query* q)
{
char* p=q->first_argument, *name;
@@ -601,7 +806,7 @@ int var_query_set(VAR* v, const char* p, const char** p_end)
MYSQL_ROW row;
MYSQL* mysql = &cur_con->mysql;
LINT_INIT(res);
-
+
while (end > p && *end != '`')
--end;
if (p == end)
@@ -624,17 +829,29 @@ int var_query_set(VAR* v, const char* p, const char** p_end)
return 0;
}
+void var_copy(VAR* dest, VAR* src)
+{
+ dest->int_val=src->int_val;
+ dest->int_dirty=src->int_dirty;
+ if (dest->alloced_len < src->alloced_len &&
+ !(dest->str_val=my_realloc(dest->str_val,src->alloced_len+1,
+ MYF(MY_WME))))
+ die("Out of memory");
+ dest->str_val_len=src->str_val_len;
+ memcpy(dest->str_val,src->str_val,src->str_val_len+1);
+}
+
int eval_expr(VAR* v, const char* p, const char** p_end)
{
VAR* vp;
if (*p == '$')
+ {
+ if ((vp = var_get(p,p_end,0,0)))
{
- if ((vp = var_get(p,p_end,0)))
- {
- memcpy(v, vp, sizeof(*v));
- return 0;
- }
+ var_copy(v, vp);
+ return 0;
}
+ }
else if(*p == '`')
{
return var_query_set(v, p, p_end);
@@ -648,9 +865,9 @@ int eval_expr(VAR* v, const char* p, const char** p_end)
v->alloced_len = (new_val_len < MIN_VAR_ALLOC - 1) ?
MIN_VAR_ALLOC : new_val_len + 1;
if (!(v->str_val =
- v->str_val ? my_realloc(v->str_val, v->alloced_len,
+ v->str_val ? my_realloc(v->str_val, v->alloced_len+1,
MYF(MY_WME)) :
- my_malloc(v->alloced_len, MYF(MY_WME))))
+ my_malloc(v->alloced_len+1, MYF(MY_WME))))
die("Out of memory");
}
v->str_val_len = new_val_len;
@@ -671,7 +888,7 @@ int do_inc(struct st_query* q)
{
char* p=q->first_argument;
VAR* v;
- v = var_get(p, 0, 1);
+ v = var_get(p, 0, 1, 0);
v->int_val++;
v->int_dirty = 1;
return 0;
@@ -681,7 +898,7 @@ int do_dec(struct st_query* q)
{
char* p=q->first_argument;
VAR* v;
- v = var_get(p, 0, 1);
+ v = var_get(p, 0, 1, 0);
v->int_val--;
v->int_dirty = 1;
return 0;
@@ -704,6 +921,7 @@ int do_system(struct st_query* q)
if (system(expr_buf) && q->abort_on_error)
die("system command '%s' failed", expr_buf);
}
+ var_free(&v);
return 0;
}
@@ -719,6 +937,7 @@ int do_echo(struct st_query* q)
write(1, v.str_val, v.str_val_len);
}
write(1, "\n", 1);
+ var_free(&v);
return 0;
}
@@ -734,27 +953,26 @@ int do_sync_with_master(struct st_query* q)
rpl_parse = mysql_rpl_parse_enabled(mysql);
mysql_disable_rpl_parse(mysql);
-
+
if(*p)
offset = atoi(p);
-
+
sprintf(query_buf, "select master_pos_wait('%s', %ld)", master_pos.file,
master_pos.pos + offset);
if(mysql_query(mysql, query_buf))
die("At line %u: failed in %s: %d: %s", start_lineno, query_buf,
mysql_errno(mysql), mysql_error(mysql));
- if(!(res = mysql_store_result(mysql)))
+ if(!(last_result = res = mysql_store_result(mysql)))
die("line %u: mysql_store_result() retuned NULL", start_lineno);
if(!(row = mysql_fetch_row(res)))
die("line %u: empty result in %s", start_lineno, query_buf);
if(!row[0])
die("Error on slave while syncing with master");
- mysql_free_result(res);
-
+ mysql_free_result(res); last_result=0;
if(rpl_parse)
mysql_enable_rpl_parse(mysql);
-
+
return 0;
}
@@ -767,22 +985,22 @@ int do_save_master_pos()
rpl_parse = mysql_rpl_parse_enabled(mysql);
mysql_disable_rpl_parse(mysql);
-
+
if(mysql_query(mysql, "show master status"))
die("At line %u: failed in show master status: %d: %s", start_lineno,
mysql_errno(mysql), mysql_error(mysql));
- if(!(res = mysql_store_result(mysql)))
+ if(!(last_result =res = mysql_store_result(mysql)))
die("line %u: mysql_store_result() retuned NULL", start_lineno);
if(!(row = mysql_fetch_row(res)))
die("line %u: empty result in show master status", start_lineno);
strncpy(master_pos.file, row[0], sizeof(master_pos.file));
master_pos.pos = strtoul(row[1], (char**) 0, 10);
- mysql_free_result(res);
-
+ mysql_free_result(res); last_result=0;
+
if(rpl_parse)
mysql_enable_rpl_parse(mysql);
-
+
return 0;
}
@@ -887,10 +1105,11 @@ static void get_file_name(char *filename, struct st_query* q)
}
-static void get_ints(uint *to,struct st_query* q)
+static uint get_ints(uint *to,struct st_query* q)
{
char* p=q->first_argument;
long val;
+ uint count=0;
DBUG_ENTER("get_ints");
if (!*p)
@@ -898,25 +1117,28 @@ static void get_ints(uint *to,struct st_query* q)
for (; (p=str2int(p,10,(long) INT_MIN, (long) INT_MAX, &val)) ; p++)
{
+ count++;
*to++= (uint) val;
if (*p != ',')
break;
}
*to++=0; /* End of data */
- DBUG_VOID_RETURN;
+ DBUG_RETURN(count);
}
/*
Get a string; Return ptr to end of string
Strings may be surrounded by " or '
+
+ If string is a '$variable', return the value of the variable.
*/
-static void get_string(char **to_ptr, char **from_ptr,
- struct st_query* q)
+static char *get_string(char **to_ptr, char **from_ptr,
+ struct st_query* q)
{
reg1 char c,sep;
- char *to= *to_ptr, *from= *from_ptr;
+ char *to= *to_ptr, *from= *from_ptr, *start=to;
DBUG_ENTER("get_string");
/* Find separator */
@@ -966,9 +1188,22 @@ static void get_string(char **to_ptr, char **from_ptr,
while (isspace(*from)) /* Point to next string */
from++;
- *to++ =0; /* End of string marker */
- *to_ptr= to;
+ *to =0; /* End of string marker */
+ *to_ptr= to+1; /* Store pointer to end */
*from_ptr= from;
+
+ /* Check if this was a variable */
+ if (*start == '$')
+ {
+ const char *end= to;
+ VAR *var=var_get(start, &end, 0, 1);
+ if (var && to == (char*) end+1)
+ {
+ DBUG_PRINT("info",("var: %s -> %s", start, var->str_val));
+ DBUG_RETURN(var->str_val); /* return found variable value */
+ }
+ }
+ DBUG_RETURN(start);
}
@@ -976,6 +1211,8 @@ static void get_string(char **to_ptr, char **from_ptr,
Get arguments for replace. The syntax is:
replace from to [from to ...]
Where each argument may be quoted with ' or "
+ A argument may also be a variable, in which case the value of the
+ variable is replaced.
*/
static void get_replace(struct st_query *q)
@@ -987,6 +1224,9 @@ static void get_replace(struct st_query *q)
POINTER_ARRAY to_array,from_array;
DBUG_ENTER("get_replace");
+ if (glob_replace)
+ free_replace();
+
bzero((char*) &to_array,sizeof(to_array));
bzero((char*) &from_array,sizeof(from_array));
if (!*from)
@@ -995,12 +1235,11 @@ static void get_replace(struct st_query *q)
while (*from)
{
char *to=buff;
- get_string(&buff, &from, q);
+ to=get_string(&buff, &from, q);
if (!*from)
die("Wrong number of arguments to replace in %s\n", q->query);
insert_pointer_name(&from_array,to);
- to=buff;
- get_string(&buff, &from, q);
+ to=get_string(&buff, &from, q);
insert_pointer_name(&to_array,to);
}
for (i=1,pos=word_end_chars ; i < 256 ; i++)
@@ -1016,6 +1255,7 @@ static void get_replace(struct st_query *q)
free_pointer_array(&from_array);
free_pointer_array(&to_array);
my_free(start, MYF(0));
+ DBUG_VOID_RETURN;
}
void free_replace()
@@ -1068,19 +1308,19 @@ int close_connection(struct st_query* q)
p++;
*p = 0;
- for(con = cons; con < next_con; con++)
+ for (con = cons; con < next_con; con++)
{
if (!strcmp(con->name, name))
{
- if(q->type == Q_DIRTY_CLOSE)
+ if (q->type == Q_DIRTY_CLOSE)
+ {
+ if (con->mysql.net.vio)
{
- if(con->mysql.net.vio)
- {
- vio_delete(con->mysql.net.vio);
- con->mysql.net.vio = 0;
- }
+ vio_delete(con->mysql.net.vio);
+ con->mysql.net.vio = 0;
}
-
+ }
+
mysql_close(&con->mysql);
DBUG_RETURN(0);
}
@@ -1090,7 +1330,8 @@ int close_connection(struct st_query* q)
}
-/* this one now is a hack - we may want to improve in in the
+/*
+ This one now is a hack - we may want to improve in in the
future to handle quotes. For now we assume that anything that is not
a comma, a space or ) belongs to the argument. space is a chopper, comma or
) are delimiters/terminators
@@ -1112,6 +1353,37 @@ char* safe_get_param(char* str, char** arg, const char* msg)
DBUG_RETURN(str);
}
+#ifndef EMBEDDED_LIBRARY
+void init_manager()
+{
+ if (!(manager=mysql_manager_init(0)))
+ die("Failed in mysql_manager_init()");
+ if (!mysql_manager_connect(manager,manager_host,manager_user,
+ manager_pass,manager_port))
+ die("Could not connect to MySQL manager: %s(%d)",manager->last_error,
+ manager->last_errno);
+
+}
+#endif
+
+int safe_connect(MYSQL* con, const char* host, const char* user,
+ const char* pass,
+ const char* db, int port, const char* sock)
+{
+ int con_error = 1;
+ int i;
+ for (i = 0; i < MAX_CON_TRIES; ++i)
+ {
+ if (mysql_real_connect(con, host,user, pass, db, port, sock, 0))
+ {
+ con_error = 0;
+ break;
+ }
+ sleep(CON_RETRY_SLEEP);
+ }
+ return con_error;
+}
+
int do_connect(struct st_query* q)
{
@@ -1120,8 +1392,9 @@ int do_connect(struct st_query* q)
char* p=q->first_argument;
char buff[FN_REFLEN];
int con_port;
- int i, con_error;
-
+ int con_error;
+ int free_con_sock = 0;
+
DBUG_ENTER("do_connect");
DBUG_PRINT("enter",("connect: %s",p));
@@ -1140,40 +1413,54 @@ int do_connect(struct st_query* q)
}
else
{
+ VAR* var_port, *var_sock;
p = safe_get_param(p, &con_port_str, "missing connection port");
- con_port=atoi(con_port_str);
+ if (*con_port_str == '$')
+ {
+ if (!(var_port = var_get(con_port_str, 0, 0, 0)))
+ die("Unknown variable '%s'", con_port_str+1);
+ con_port = var_port->int_val;
+ }
+ else
+ con_port=atoi(con_port_str);
p = safe_get_param(p, &con_sock, "missing connection socket");
+ if (*con_sock == '$')
+ {
+ if (!(var_sock = var_get(con_sock, 0, 0, 0)))
+ die("Unknown variable '%s'", con_sock+1);
+ if (!(con_sock = (char*)my_malloc(var_sock->str_val_len+1, MYF(0))))
+ die("Out of memory");
+ free_con_sock = 1;
+ memcpy(con_sock, var_sock->str_val, var_sock->str_val_len);
+ con_sock[var_sock->str_val_len] = 0;
+ }
}
+
if (next_con == cons_end)
die("Connection limit exhausted - increase MAX_CONS in mysqltest.c");
if (!mysql_init(&next_con->mysql))
die("Failed on mysql_init()");
- if (con_sock)
+ if (opt_compress)
+ mysql_options(&next_con->mysql,MYSQL_OPT_COMPRESS,NullS);
+ if (con_sock && !free_con_sock && *con_sock && *con_sock != FN_LIBCHAR)
con_sock=fn_format(buff, con_sock, TMPDIR, "",0);
if (!con_db[0])
con_db=db;
- con_error = 1;
- for (i = 0; i < MAX_CON_TRIES; ++i)
- {
- if(mysql_real_connect(&next_con->mysql, con_host,
- con_user, con_pass,
- con_db, con_port, con_sock, 0))
- {
- con_error = 0;
- break;
- }
- sleep(CON_RETRY_SLEEP);
- }
-
- if(con_error)
+ /* Special database to allow one to connect without a database name */
+ if (!strcmp(con_db,"*NO-ONE*"))
+ con_db=0;
+ if ((con_error = safe_connect(&next_con->mysql, con_host,
+ con_user, con_pass,
+ con_db, con_port, con_sock ? con_sock: 0)))
die("Could not open connection '%s': %s", con_name,
mysql_error(&next_con->mysql));
if (!(next_con->name = my_strdup(con_name, MYF(MY_WME))))
die(NullS);
cur_con = next_con++;
-
+ if (free_con_sock)
+ my_free(con_sock, MYF(MY_WME));
DBUG_RETURN(0);
}
@@ -1187,10 +1474,10 @@ int do_done(struct st_query* q)
parser.current_line = *--cur_block;
}
else
- {
- ++parser.current_line;
- --cur_block;
- }
+ {
+ ++parser.current_line;
+ --cur_block;
+ }
return 0;
}
@@ -1199,7 +1486,6 @@ int do_while(struct st_query* q)
char* p=q->first_argument;
const char* expr_start, *expr_end;
VAR v;
- var_init(&v,0,0,0,0);
if (cur_block == block_stack_end)
die("Nesting too deeply");
if (!*block_ok)
@@ -1209,13 +1495,14 @@ int do_while(struct st_query* q)
*cur_block++ = parser.current_line++;
return 0;
}
-
+
expr_start = strchr(p, '(');
if (!expr_start)
die("missing '(' in while");
expr_end = strrchr(expr_start, ')');
if (!expr_end)
die("missing ')' in while");
+ var_init(&v,0,0,0,0);
eval_expr(&v, ++expr_start, &expr_end);
*cur_block++ = parser.current_line++;
if (!v.int_val)
@@ -1225,6 +1512,7 @@ int do_while(struct st_query* q)
}
else
*++block_ok = 1;
+ var_free(&v);
return 0;
}
@@ -1300,15 +1588,11 @@ int read_line(char* buf, int size)
{
if ((*cur_file) != stdin)
my_fclose(*cur_file,MYF(0));
-
+ cur_file--;
+ lineno--;
if (cur_file == file_stack)
return 1;
- else
- {
- cur_file--;
- lineno--;
- continue;
- }
+ continue;
}
switch(state) {
@@ -1439,8 +1723,11 @@ int read_query(struct st_query** q_ptr)
q->first_word_len = 0;
memcpy((gptr) q->expected_errno, (gptr) global_expected_errno,
sizeof(global_expected_errno));
+ q->expected_errors=global_expected_errors;
q->abort_on_error = global_expected_errno[0] == 0;
bzero((gptr) global_expected_errno,sizeof(global_expected_errno));
+ global_expected_errors=0;
+
q->type = Q_UNKNOWN;
q->query_buf=q->query=0;
if (read_line(read_query_buf, sizeof(read_query_buf)))
@@ -1469,6 +1756,7 @@ int read_query(struct st_query** q_ptr)
expected_errno = expected_errno * 10 + *p - '0';
q->expected_errno[0] = expected_errno;
q->expected_errno[1] = 0;
+ q->expected_errors=1;
}
}
@@ -1497,20 +1785,28 @@ int read_query(struct st_query** q_ptr)
return 0;
}
-
struct option long_options[] =
{
{"debug", optional_argument, 0, '#'},
{"database", required_argument, 0, 'D'},
+ {"basedir", required_argument, 0, 'b'},
{"big-test", no_argument, 0, 'B'},
+ {"compress", no_argument, 0, 'C'},
{"help", no_argument, 0, '?'},
{"host", required_argument, 0, 'h'},
+ {"manager-user",required_argument, 0, OPT_MANAGER_USER},
+ {"manager-host",required_argument, 0, OPT_MANAGER_HOST},
+ {"manager-password",required_argument,0,OPT_MANAGER_PASSWD},
+ {"manager-port",required_argument,0,OPT_MANAGER_PORT},
+ {"manager-wait-timeout",required_argument,0,OPT_MANAGER_WAIT_TIMEOUT},
{"password", optional_argument, 0, 'p'},
{"port", required_argument, 0, 'P'},
- {"quiet", no_argument, 0, 'q'},
+ {"quiet", no_argument, 0, 's'},
{"record", no_argument, 0, 'r'},
{"result-file", required_argument, 0, 'R'},
- {"silent", no_argument, 0, 'q'},
+ {"server-arg", required_argument, 0, 'A'},
+ {"server-file", required_argument, 0, 'F'},
+ {"silent", no_argument, 0, 's'},
{"sleep", required_argument, 0, 'T'},
{"socket", required_argument, 0, 'S'},
{"test-file", required_argument, 0, 'x'},
@@ -1546,9 +1842,14 @@ void usage()
-u, --user=... User for login.\n\
-p[password], --password[=...]\n\
Password to use when connecting to server.\n\
+ -b, --basedir=... Basedir for tests\n\
-B, --big-test Define BIG_TEST to 1\n\
+ -C, --compress Use the compressed server/client protocol\n\
-D, --database=... Database to use.\n\
-P, --port=... Port number to use for connection.\n\
+ --server-arg=... Send enbedded server this as a paramenter\n\
+ --server-file=... Read embedded server arguments from file\n\
+ -s, --silent, --quiet Suppress all normal output.\n\
-S, --socket=... Socket file to use for connection.\n\
-t, --tmpdir=... Temporary directory where sockets are put\n\
-T, --sleep=# Sleep always this many seconds on sleep commands\n\
@@ -1556,7 +1857,6 @@ void usage()
-R, --result-file=... Read/Store result from/in this file.\n\
-x, --test-file=... Read test from/in this file (default stdin).\n\
-v, --verbose Write more.\n\
- -q, --quiet, --silent Suppress all normal output.\n\
-V, --version Output version information and exit.\n\
--no-defaults Don't read default options from any options file.\n\n");
}
@@ -1569,12 +1869,12 @@ int parse_args(int argc, char **argv)
load_defaults("my",load_default_groups,&argc,&argv);
default_argv= argv;
- while((c = getopt_long(argc, argv, "h:p::u:BP:D:S:R:x:t:T:#:?rvVq",
- long_options, &option_index)) != EOF)
+ while ((c = getopt_long(argc, argv, "A:h:p::u:b:BCF:P:D:S:R:x:t:T:#:?rvVs",
+ long_options, &option_index)) != EOF)
{
switch(c) {
case '#':
- DBUG_PUSH(optarg ? optarg : "d:t:O,/tmp/mysqltest.trace");
+ DBUG_PUSH(optarg ? optarg : "d:t:S:i:O,/tmp/mysqltest.trace");
break;
case 'v':
verbose = 1;
@@ -1582,6 +1882,23 @@ int parse_args(int argc, char **argv)
case 'r':
record = 1;
break;
+ case (int)OPT_MANAGER_WAIT_TIMEOUT:
+ manager_wait_timeout=atoi(optarg);
+ break;
+ case (int)OPT_MANAGER_PORT:
+ manager_port=atoi(optarg);
+ break;
+ case (int)OPT_MANAGER_HOST:
+ manager_host=optarg;
+ break;
+ case (int)OPT_MANAGER_USER:
+ manager_user=optarg;
+ break;
+ case (int)OPT_MANAGER_PASSWD:
+ my_free(manager_pass,MYF(MY_ALLOW_ZERO_PTR));
+ manager_pass=my_strdup(optarg,MYF(MY_FAE));
+ while (*optarg) *optarg++= 'x'; /* Destroy argument */
+ break;
case 'u':
user = optarg;
break;
@@ -1589,9 +1906,18 @@ int parse_args(int argc, char **argv)
result_file = optarg;
break;
case 'x':
- if (!(*cur_file = my_fopen(optarg, O_RDONLY, MYF(MY_WME))))
+ {
+ char buff[FN_REFLEN];
+ if (!test_if_hard_path(optarg))
+ {
+ strxmov(buff, opt_basedir, optarg, NullS);
+ optarg=buff;
+ }
+ fn_format(buff,optarg,"","",4);
+ if (!(*++cur_file = my_fopen(buff, O_RDONLY, MYF(MY_WME))))
die("Could not open %s: errno = %d", optarg, errno);
break;
+ }
case 'p':
if (optarg)
{
@@ -1602,9 +1928,15 @@ int parse_args(int argc, char **argv)
else
tty_password=1;
break;
+ case 'b':
+ opt_basedir= optarg;
+ break;
case 'B':
opt_big_test=1;
break;
+ case 'C':
+ opt_compress=1;
+ break;
case 'P':
port = atoi(optarg);
break;
@@ -1617,7 +1949,7 @@ int parse_args(int argc, char **argv)
case 'h':
host = optarg;
break;
- case 'q':
+ case 's':
silent = 1;
break;
case 't':
@@ -1626,6 +1958,24 @@ int parse_args(int argc, char **argv)
case 'T':
opt_sleep=atoi(optarg);
break;
+ case 'A':
+ if (!embedded_server_arg_count)
+ {
+ embedded_server_arg_count=1;
+ embedded_server_args[0]= (char*) "";
+ }
+ embedded_server_args[embedded_server_arg_count++]=
+ my_strdup(optarg,MYF(MY_FAE));
+ if (embedded_server_arg_count == MAX_SERVER_ARGS ||
+ !embedded_server_args[embedded_server_arg_count-1])
+ {
+ die("Can't use server argument");
+ }
+ break;
+ case 'F':
+ if (read_server_arguments(optarg))
+ die(NullS);
+ break;
case 'V':
print_version();
exit(0);
@@ -1633,6 +1983,7 @@ int parse_args(int argc, char **argv)
usage();
exit(1); /* Unknown option */
default:
+ fprintf(stderr,"Unknown option '%c'\n",c);
usage();
exit(1);
}
@@ -1665,9 +2016,17 @@ char* safe_str_append(char* buf, const char* str, int size)
void str_to_file(const char* fname, char* str, int size)
{
int fd;
- if ((fd = my_open(fname, O_WRONLY | O_CREAT | O_TRUNC,
+ char buff[FN_REFLEN];
+ if (!test_if_hard_path(fname))
+ {
+ strxmov(buff, opt_basedir, fname, NullS);
+ fname=buff;
+ }
+ fn_format(buff,fname,"","",4);
+
+ if ((fd = my_open(buff, O_WRONLY | O_CREAT | O_TRUNC,
MYF(MY_WME | MY_FFNF))) < 0)
- die("Could not open %s: errno = %d", fname, errno);
+ die("Could not open %s: errno = %d", buff, errno);
if (my_write(fd, (byte*)str, size, MYF(MY_WME|MY_FNABP)))
die("write failed");
my_close(fd, MYF(0));
@@ -1679,6 +2038,22 @@ void reject_dump(const char* record_file, char* buf, int size)
str_to_file(fn_format(reject_file, record_file,"",".reject",2), buf, size);
}
+
+/* Append the string to ds, with optional replace */
+
+static void replace_dynstr_append_mem(DYNAMIC_STRING *ds, char *val, int len)
+{
+ if (glob_replace)
+ {
+ len=(int) replace_strings(glob_replace, &out_buff, &out_length, val);
+ if (len == -1)
+ die("Out of memory in replace\n");
+ val=out_buff;
+ }
+ dynstr_append_mem(ds, val, len);
+}
+
+
/*
* flags control the phased/stages of query execution to be performed
* if QUERY_SEND bit is on, the query will be sent. If QUERY_REAP is on
@@ -1701,54 +2076,82 @@ int run_query(MYSQL* mysql, struct st_query* q, int flags)
int query_len;
DBUG_ENTER("run_query");
- if(q->type != Q_EVAL)
- {
- query = q->query;
- query_len = strlen(query);
- }
+ if (q->type != Q_EVAL)
+ {
+ query = q->query;
+ query_len = strlen(query);
+ }
else
- {
- init_dynamic_string(&eval_query, "", 16384, 65536);
- do_eval(&eval_query, q->query);
- query = eval_query.str;
- query_len = eval_query.length;
- }
-
- if ( q->record_file[0])
+ {
+ init_dynamic_string(&eval_query, "", 16384, 65536);
+ do_eval(&eval_query, q->query);
+ query = eval_query.str;
+ query_len = eval_query.length;
+ }
+
+ if (q->record_file[0])
{
init_dynamic_string(&ds_tmp, "", 16384, 65536);
ds = &ds_tmp;
}
else
ds= &ds_res;
-
+
if ((flags & QUERY_SEND) && mysql_send_query(mysql, query, query_len))
- die("At line %u: unable to send query '%s'", start_lineno, query);
- if(!(flags & QUERY_REAP))
- return 0;
-
+ die("At line %u: unable to send query '%s'(mysql_errno=%d,errno=%d)",
+ start_lineno, query,
+ mysql_errno(mysql), errno);
+ if ((flags & QUERY_SEND) && !disable_query_log)
+ {
+ replace_dynstr_append_mem(ds,query, query_len);
+ dynstr_append_mem(ds,";\n",2);
+ }
+ if (!(flags & QUERY_REAP))
+ DBUG_RETURN(0);
+
if (mysql_read_query_result(mysql) ||
- (!(res = mysql_store_result(mysql)) && mysql_field_count(mysql)))
+ (!(last_result = res = mysql_store_result(mysql)) &&
+ mysql_field_count(mysql)))
{
if (q->require_file)
+ {
abort_not_supported_test();
+ }
if (q->abort_on_error)
die("At line %u: query '%s' failed: %d: %s", start_lineno, query,
mysql_errno(mysql), mysql_error(mysql));
else
{
- for (i=0 ; q->expected_errno[i] ; i++)
+ for (i=0 ; (uint) i < q->expected_errors ; i++)
{
if ((q->expected_errno[i] == mysql_errno(mysql)))
+ {
+ if (i == 0 && q->expected_errors == 1)
+ {
+ /* Only log error if there is one possible error */
+ replace_dynstr_append_mem(ds,mysql_error(mysql),
+ strlen(mysql_error(mysql)));
+ dynstr_append_mem(ds,"\n",1);
+ }
+ /* Don't log error if we may not get an error */
+ else if (q->expected_errno[0] != 0)
+ dynstr_append(ds,"Got one of the listed errors\n");
goto end; /* Ok */
+ }
}
if (i)
{
+ replace_dynstr_append_mem(ds, mysql_error(mysql),
+ strlen(mysql_error(mysql)));
+ dynstr_append_mem(ds,"\n",1);
verbose_msg("query '%s' failed with wrong errno %d instead of %d...",
q->query, mysql_errno(mysql), q->expected_errno[0]);
error=1;
goto end;
}
+ replace_dynstr_append_mem(ds,mysql_error(mysql),
+ strlen(mysql_error(mysql)));
+ dynstr_append_mem(ds,"\n",1);
verbose_msg("query '%s' failed: %d: %s", q->query, mysql_errno(mysql),
mysql_error(mysql));
/*
@@ -1773,51 +2176,45 @@ int run_query(MYSQL* mysql, struct st_query* q, int flags)
goto end;
}
- if (!res) goto end;
+ if (!res)
+ goto end;
- fields = mysql_fetch_fields(res);
- num_fields = mysql_num_fields(res);
- for( i = 0; i < num_fields; i++)
+ if (!disable_result_log)
{
- if (i)
- dynstr_append_mem(ds, "\t", 1);
- dynstr_append(ds, fields[i].name);
- }
-
- dynstr_append_mem(ds, "\n", 1);
+ fields = mysql_fetch_fields(res);
+ num_fields = mysql_num_fields(res);
+ for (i = 0; i < num_fields; i++)
+ {
+ if (i)
+ dynstr_append_mem(ds, "\t", 1);
+ dynstr_append(ds, fields[i].name);
+ }
+ dynstr_append_mem(ds, "\n", 1);
- while((row = mysql_fetch_row(res)))
- {
- lengths = mysql_fetch_lengths(res);
- for(i = 0; i < num_fields; i++)
+ while ((row = mysql_fetch_row(res)))
{
- val = (char*)row[i];
- len = lengths[i];
-
- if (!val)
+ lengths = mysql_fetch_lengths(res);
+ for(i = 0; i < num_fields; i++)
{
- val = (char*)"NULL";
- len = 4;
- }
+ val = (char*)row[i];
+ len = lengths[i];
- if (i)
- dynstr_append_mem(ds, "\t", 1);
- if (glob_replace)
- {
- len=(int) replace_strings(glob_replace, &out_buff, &out_length, val);
- if (len == -1)
- die("Out of memory in replace\n");
- val=out_buff;
+ if (!val)
+ {
+ val = (char*)"NULL";
+ len = 4;
+ }
+
+ if (i)
+ dynstr_append_mem(ds, "\t", 1);
+ replace_dynstr_append_mem(ds, val, len);
}
- dynstr_append_mem(ds, val, len);
+ dynstr_append_mem(ds, "\n", 1);
}
-
- dynstr_append_mem(ds, "\n", 1);
+ if (glob_replace)
+ free_replace();
}
- if (glob_replace)
- free_replace();
-
if (record)
{
if (!q->record_file[0] && !result_file)
@@ -1831,7 +2228,9 @@ int run_query(MYSQL* mysql, struct st_query* q, int flags)
}
end:
- if (res) mysql_free_result(res);
+ if (res)
+ mysql_free_result(res);
+ last_result=0;
if (ds == &ds_tmp)
dynstr_free(&ds_tmp);
if(q->type == Q_EVAL)
@@ -1874,23 +2273,27 @@ static VAR* var_init(VAR* v, const char* name, int name_len, const char* val,
{
int val_alloc_len;
VAR* tmp_var;
- if(!name_len && name)
+ if (!name_len && name)
name_len = strlen(name);
- if(!val_len && val)
+ if (!val_len && val)
val_len = strlen(val) ;
val_alloc_len = val_len + 16; /* room to grow */
- if(!(tmp_var=v) && !(tmp_var = (VAR*)my_malloc(sizeof(*tmp_var)
- + name_len, MYF(MY_WME))))
+ if (!(tmp_var=v) && !(tmp_var = (VAR*)my_malloc(sizeof(*tmp_var)
+ + name_len, MYF(MY_WME))))
die("Out of memory");
-
- tmp_var->name = (name) ? (char*)tmp_var + sizeof(*tmp_var) : 0;
- if(!(tmp_var->str_val = my_malloc(val_alloc_len, MYF(MY_WME))))
+ tmp_var->name = (name) ? (char*) tmp_var + sizeof(*tmp_var) : 0;
+ tmp_var->alloced = (v == 0);
+
+ if (!(tmp_var->str_val = my_malloc(val_alloc_len+1, MYF(MY_WME))))
die("Out of memory");
-
+
memcpy(tmp_var->name, name, name_len);
- if(val)
- memcpy(tmp_var->str_val, val, val_len + 1);
+ if (val)
+ {
+ memcpy(tmp_var->str_val, val, val_len);
+ tmp_var->str_val[val_len]=0;
+ }
tmp_var->name_len = name_len;
tmp_var->str_val_len = val_len;
tmp_var->alloced_len = val_alloc_len;
@@ -1902,7 +2305,8 @@ static VAR* var_init(VAR* v, const char* name, int name_len, const char* val,
static void var_free(void* v)
{
my_free(((VAR*) v)->str_val, MYF(MY_WME));
- my_free((char*) v, MYF(MY_WME));
+ if (((VAR*)v)->alloced)
+ my_free((char*) v, MYF(MY_WME));
}
@@ -1910,9 +2314,9 @@ static void var_from_env(const char* name, const char* def_val)
{
const char* tmp;
VAR* v;
- if(!(tmp = getenv(name)))
+ if (!(tmp = getenv(name)))
tmp = def_val;
-
+
v = var_init(0, name, 0, tmp, 0);
hash_insert(&var_hash, (byte*)v);
}
@@ -1920,14 +2324,18 @@ static void var_from_env(const char* name, const char* def_val)
static void init_var_hash()
{
+ VAR* v;
if (hash_init(&var_hash, 1024, 0, 0, get_var_key, var_free, MYF(0)))
die("Variable hash initialization failed");
var_from_env("MASTER_MYPORT", "9306");
var_from_env("SLAVE_MYPORT", "9307");
var_from_env("MYSQL_TEST_DIR", "/tmp");
var_from_env("BIG_TEST", opt_big_test ? "1" : "0");
+ v=var_init(0,"MAX_TABLES", 0, (sizeof(ulong) == 4) ? "31" : "63",0);
+ hash_insert(&var_hash, (byte*)v);
}
+
int main(int argc, char** argv)
{
int error = 0;
@@ -1935,6 +2343,9 @@ int main(int argc, char** argv)
my_bool require_file=0, q_send_flag=0;
char save_file[FN_REFLEN];
MY_INIT(argv[0]);
+ {
+ DBUG_ENTER("main");
+ DBUG_PROCESS(argv[0]);
save_file[0]=0;
TMPDIR[0]=0;
@@ -1942,7 +2353,7 @@ int main(int argc, char** argv)
cons_end = cons + MAX_CONS;
next_con = cons + 1;
cur_con = cons;
-
+
memset(file_stack, 0, sizeof(file_stack));
memset(&master_pos, 0, sizeof(master_pos));
file_stack_end = file_stack + MAX_INCLUDE_DEPTH;
@@ -1959,20 +2370,28 @@ int main(int argc, char** argv)
*block_ok = 1;
init_dynamic_string(&ds_res, "", 0, 65536);
parse_args(argc, argv);
+ if (mysql_server_init(embedded_server_arg_count,
+ embedded_server_args,
+ (char**) embedded_server_groups))
+ die("Can't initialize MySQL server");
init_var_hash();
- if (!*cur_file)
- *cur_file = stdin;
+ if (cur_file == file_stack)
+ *++cur_file = stdin;
*lineno=1;
-
+#ifndef EMBEDDED_LIBRARY
+ if (manager_host)
+ init_manager();
+#endif
if (!( mysql_init(&cur_con->mysql)))
die("Failed in mysql_init()");
+ if (opt_compress)
+ mysql_options(&cur_con->mysql,MYSQL_OPT_COMPRESS,NullS);
cur_con->name = my_strdup("default", MYF(MY_WME));
if (!cur_con->name)
die("Out of memory");
- if (!mysql_real_connect(&cur_con->mysql, host,
- user, pass, db, port, unix_sock,
- 0))
+ if (safe_connect(&cur_con->mysql, host,
+ user, pass, db, port, unix_sock))
die("Failed in mysql_real_connect(): %s", mysql_error(&cur_con->mysql));
while (!read_query(&q))
@@ -1990,10 +2409,21 @@ int main(int argc, char** argv)
case Q_DIRTY_CLOSE:
close_connection(q); break;
case Q_RPL_PROBE: do_rpl_probe(q); break;
- case Q_ENABLE_RPL_PARSE: do_enable_rpl_parse(q); break;
- case Q_DISABLE_RPL_PARSE: do_disable_rpl_parse(q); break;
+ case Q_ENABLE_RPL_PARSE: do_enable_rpl_parse(q); break;
+ case Q_DISABLE_RPL_PARSE: do_disable_rpl_parse(q); break;
+ case Q_ENABLE_QUERY_LOG: disable_query_log=0; break;
+ case Q_DISABLE_QUERY_LOG: disable_query_log=1; break;
+ case Q_ENABLE_RESULT_LOG: disable_result_log=0; break;
+ case Q_DISABLE_RESULT_LOG: disable_result_log=1; break;
case Q_SOURCE: do_source(q); break;
case Q_SLEEP: do_sleep(q); break;
+ case Q_REQUIRE_VERSION: do_require_version(q); break;
+ case Q_WAIT_FOR_SLAVE_TO_STOP: do_wait_for_slave_to_stop(q); break;
+ case Q_REQUIRE_MANAGER: do_require_manager(q); break;
+#ifndef EMBEDDED_LIBRARY
+ case Q_SERVER_START: do_server_start(q); break;
+ case Q_SERVER_STOP: do_server_stop(q); break;
+#endif
case Q_INC: do_inc(q); break;
case Q_DEC: do_dec(q); break;
case Q_ECHO: do_echo(q); break;
@@ -2002,7 +2432,7 @@ int main(int argc, char** argv)
case Q_EVAL_RESULT: eval_result = 1; break;
case Q_EVAL:
if (q->query == q->query_buf)
- q->query += q->first_word_len;
+ q->query= q->first_argument;
/* fall through */
case Q_QUERY:
case Q_REAP:
@@ -2048,7 +2478,7 @@ int main(int argc, char** argv)
require_file=0;
break;
case Q_ERROR:
- get_ints(global_expected_errno,q);
+ global_expected_errors=get_ints(global_expected_errno,q);
break;
case Q_REQUIRE:
get_file_name(save_file,q);
@@ -2092,7 +2522,7 @@ int main(int argc, char** argv)
dynstr_free(&ds_res);
if (!silent) {
- if(error)
+ if (error)
printf("not ok\n");
else
printf("ok\n");
@@ -2101,8 +2531,54 @@ int main(int argc, char** argv)
free_used_memory();
exit(error ? 1 : 0);
return error ? 1 : 0; /* Keep compiler happy */
+ }
}
+/*
+ Read arguments for embedded server and put them into
+ embedded_server_args_count and embedded_server_args[]
+*/
+
+
+static int read_server_arguments(const char* name)
+{
+ char argument[1024],buff[FN_REFLEN], *str=0;
+ FILE *file;
+
+ if (!test_if_hard_path(name))
+ {
+ strxmov(buff, opt_basedir, name, NullS);
+ name=buff;
+ }
+ fn_format(buff,name,"","",4);
+
+ if (!embedded_server_arg_count)
+ {
+ embedded_server_arg_count=1;
+ embedded_server_args[0]= (char*) ""; /* Progname */
+ }
+ if (!(file=my_fopen(buff, O_RDONLY | O_BINARY, MYF(MY_WME))))
+ return 1;
+ while (embedded_server_arg_count < MAX_SERVER_ARGS &&
+ (str=fgets(argument,sizeof(argument), file)))
+ {
+ *(strend(str)-1)=0; /* Remove end newline */
+ if (!(embedded_server_args[embedded_server_arg_count]=
+ (char*) my_strdup(str,MYF(MY_WME))))
+ {
+ my_fclose(file,MYF(0));
+ return 1;
+ }
+ embedded_server_arg_count++;
+ }
+ my_fclose(file,MYF(0));
+ if (str)
+ {
+ fprintf(stderr,"Too many arguments in option file: %s\n",name);
+ return 1;
+ }
+ return 0;
+}
/****************************************************************************
* Handle replacement of strings
diff --git a/client/password.c b/client/password.c
index 0fd5861873a..9b154603b98 100644
--- a/client/password.c
+++ b/client/password.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/* password checking routines */
/*****************************************************************************
@@ -35,7 +34,7 @@
This saves a hashed number as a string in the password field.
*****************************************************************************/
-#include <global.h>
+#include <my_global.h>
#include <my_sys.h>
#include <m_string.h>
#include "mysql.h"
diff --git a/client/readline.cc b/client/readline.cc
index f0312b089e5..f5fbfd8cd0c 100644
--- a/client/readline.cc
+++ b/client/readline.cc
@@ -1,23 +1,22 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/* readline for batch mode */
-#include <global.h>
+#include <my_global.h>
#include <my_sys.h>
#include <m_string.h>
#include "my_readline.h"
@@ -120,20 +119,11 @@ static bool init_line_buffer_from_string(LINE_BUFFER *buffer,my_string str)
}
-static void free_line_buffer(LINE_BUFFER *buffer)
-{
- if (buffer->buffer)
- {
- my_free((gptr) buffer->buffer,MYF(0));
- buffer->buffer=0;
- }
-}
-
-
-/* Fill the buffer retaining the last n bytes at the beginning of the
- newly filled buffer (for backward context). Returns the number of new
- bytes read from disk. */
-
+/*
+ Fill the buffer retaining the last n bytes at the beginning of the
+ newly filled buffer (for backward context). Returns the number of new
+ bytes read from disk.
+*/
static uint fill_buffer(LINE_BUFFER *buffer)
{
diff --git a/client/select_test.c b/client/select_test.c
index 049f2b908be..ee2a9192865 100644
--- a/client/select_test.c
+++ b/client/select_test.c
@@ -1,20 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
#if defined(_WIN32) || defined(_WIN64)
#include <windows.h>
diff --git a/client/showdb_test.c b/client/showdb_test.c
index f4c25999fe5..df2b3037c00 100644
--- a/client/showdb_test.c
+++ b/client/showdb_test.c
@@ -1,34 +1,20 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+/* Copyright (C) 2000 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
#ifdef __WIN__
#include <windows.h>
#endif
diff --git a/client/sql_string.cc b/client/sql_string.cc
index 4b9ebef21f1..3c5e481eaad 100644
--- a/client/sql_string.cc
+++ b/client/sql_string.cc
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This program file is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 is originally from the mysql distribution. Coded by monty */
@@ -21,7 +20,7 @@
#pragma implementation // gcc: Class implementation
#endif
-#include <global.h>
+#include <my_global.h>
#include <my_sys.h>
#include <m_string.h>
#include <m_ctype.h>
diff --git a/client/sql_string.h b/client/sql_string.h
index 74dbc4cc6bd..cffe78936a0 100644
--- a/client/sql_string.h
+++ b/client/sql_string.h
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 is originally from the mysql distribution. Coded by monty */
diff --git a/client/ssl_test.c b/client/ssl_test.c
index d1ec1776696..279c1e95fdc 100644
--- a/client/ssl_test.c
+++ b/client/ssl_test.c
@@ -1,34 +1,20 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+/* Copyright (C) 2000 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
#ifdef __WIN__
#include <windows.h>
#endif
diff --git a/client/thimble.cc b/client/thimble.cc
index 6d1e8a85559..94b75d8fb35 100644
--- a/client/thimble.cc
+++ b/client/thimble.cc
@@ -1,8 +1,24 @@
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
-#include "my_global.h"
+#include "my_my_global.h"
static void spawn_stern_thread(pthread_t *t);
static int act_goofy(void);
@@ -89,5 +105,3 @@ static void *be_stern(void *v __attribute__((unused)))
fputs("You are NOTHING!\n", stderr);
return NULL;
}
-
-
diff --git a/client/thread_test.c b/client/thread_test.c
index dbe2acee8db..f7e2a6fd32a 100644
--- a/client/thread_test.c
+++ b/client/thread_test.c
@@ -1,25 +1,24 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-#include <global.h>
+#include <my_global.h>
#ifndef THREAD
-int main(void)
+int main(int argc __attribute__((unused)), char **argv __attribute__((unused)))
{
printf("This test must be compiled with multithread support to work\n");
exit(1);
diff --git a/client/violite.c b/client/violite.c
deleted file mode 100644
index 224ba051d82..00000000000
--- a/client/violite.c
+++ /dev/null
@@ -1,394 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
-
-#include <global.h>
-
-#ifndef HAVE_VIO /* is Vio suppored by the Vio lib ? */
-
-#include <errno.h>
-#include <assert.h>
-#include <violite.h>
-#include <my_sys.h>
-#include <my_net.h>
-#include <m_string.h>
-
-#if defined(__EMX__)
-#include <sys/ioctl.h>
-#define ioctlsocket(A,B,C) ioctl((A),(B),(void *)(C),sizeof(*(C)))
-#undef HAVE_FCNTL
-#endif /* defined(__EMX__) */
-
-#if defined(MSDOS) || defined(__WIN__)
-#ifdef __WIN__
-#undef errno
-#undef EINTR
-#undef EAGAIN
-#define errno WSAGetLastError()
-#define EINTR WSAEINTR
-#define EAGAIN WSAEINPROGRESS
-#endif /* __WIN__ */
-#define O_NONBLOCK 1 /* For emulation of fcntl() */
-#endif
-#ifndef EWOULDBLOCK
-#define EWOULDBLOCK EAGAIN
-#endif
-
-#ifndef __WIN__
-#define HANDLE void *
-#endif
-
-struct st_vio
-{
- my_socket sd; /* my_socket - real or imaginary */
- HANDLE hPipe;
- my_bool localhost; /* Are we from localhost? */
- int fcntl_mode; /* Buffered fcntl(sd,F_GETFL) */
- my_bool fcntl_set; /* Have we done any fcntl yet?*/
- struct sockaddr_in local; /* Local internet address */
- struct sockaddr_in remote; /* Remote internet address */
- enum enum_vio_type type; /* Type of connection */
- char desc[30]; /* String description */
-};
-
-typedef void *vio_ptr;
-typedef char *vio_cstring;
-
-/*
- * Helper to fill most of the Vio* with defaults.
- */
-
-static void vio_reset(Vio* vio, enum enum_vio_type type,
- my_socket sd, HANDLE hPipe,
- my_bool localhost)
-{
- bzero((char*) vio, sizeof(*vio));
- vio->type = type;
- vio->sd = sd;
- vio->hPipe = hPipe;
- vio->localhost= localhost;
-}
-
-Vio *vio_new(my_socket sd, enum enum_vio_type type, my_bool localhost)
-{
- Vio *vio;
- DBUG_ENTER("vio_new");
- DBUG_PRINT("enter", ("sd=%d", sd));
- if ((vio = (Vio*) my_malloc(sizeof(*vio),MYF(MY_WME))))
- {
- vio_reset(vio, type, sd, 0, localhost);
- sprintf(vio->desc, "socket (%d)", vio->sd);
- }
- DBUG_RETURN(vio);
-}
-
-
-#ifdef __WIN__
-
-Vio *vio_new_win32pipe(HANDLE hPipe)
-{
- Vio *vio;
- DBUG_ENTER("vio_new_handle");
- if ((vio = (Vio*) my_malloc(sizeof(Vio),MYF(MY_WME))))
- {
- vio_reset(vio, VIO_TYPE_NAMEDPIPE, 0, hPipe, TRUE);
- strmov(vio->desc, "named pipe");
- }
- DBUG_RETURN(vio);
-}
-
-#endif
-
-void vio_delete(Vio * vio)
-{
- /* It must be safe to delete null pointers. */
- /* This matches the semantics of C++'s delete operator. */
- if (vio)
- {
- vio_close(vio);
- my_free((gptr) vio,MYF(0));
- }
-}
-
-int vio_errno(Vio *vio)
-{
- return errno; /* On Win32 this mapped to WSAGetLastError() */
-}
-
-
-int vio_read(Vio * vio, gptr buf, int size)
-{
- int r;
- DBUG_ENTER("vio_read");
- DBUG_PRINT("enter", ("sd=%d, buf=%p, size=%d", vio->sd, buf, size));
- assert(vio->sd >= 0);
-#ifdef __WIN__
- if (vio->type == VIO_TYPE_NAMEDPIPE)
- {
- DWORD length;
- if (!ReadFile(vio->hPipe, buf, size, &length, NULL))
- DBUG_RETURN(-1);
- DBUG_RETURN(length);
- }
- r = recv(vio->sd, buf, size,0);
-#else
- errno=0; /* For linux */
- r = read(vio->sd, buf, size);
-#endif /* __WIN__ */
-#ifndef DBUG_OFF
- if (r < 0)
- {
- DBUG_PRINT("error", ("Got error %d during read",errno));
- }
-#endif /* DBUG_OFF */
- DBUG_PRINT("exit", ("%d", r));
- DBUG_RETURN(r);
-}
-
-
-int vio_write(Vio * vio, const gptr buf, int size)
-{
- int r;
- DBUG_ENTER("vio_write");
- DBUG_PRINT("enter", ("sd=%d, buf=%p, size=%d", vio->sd, buf, size));
- assert(vio->sd >= 0);
-#ifdef __WIN__
- if ( vio->type == VIO_TYPE_NAMEDPIPE)
- {
- DWORD length;
- if (!WriteFile(vio->hPipe, (char*) buf, size, &length, NULL))
- DBUG_RETURN(-1);
- DBUG_RETURN(length);
- }
- r = send(vio->sd, buf, size,0);
-#else
- r = write(vio->sd, buf, size);
-#endif /* __WIN__ */
-#ifndef DBUG_OFF
- if (r < 0)
- {
- DBUG_PRINT("error", ("Got error on write: %d",errno));
- }
-#endif /* DBUG_OFF */
- DBUG_PRINT("exit", ("%d", r));
- DBUG_RETURN(r);
-}
-
-
-int vio_blocking(Vio * vio, my_bool set_blocking_mode)
-{
- int r=0;
- DBUG_ENTER("vio_blocking");
- DBUG_PRINT("enter", ("set_blocking_mode: %d", (int) set_blocking_mode));
-
-#if !defined(___WIN__) && !defined(__EMX__)
-#if !defined(NO_FCNTL_NONBLOCK)
-
- if (vio->sd >= 0)
- {
- int old_fcntl=vio->fcntl_mode;
- if (!vio->fcntl_set)
- {
- vio->fcntl_set = TRUE;
- old_fcntl=vio->fcntl_mode = fcntl(vio->sd, F_GETFL);
- }
- if (set_blocking_mode)
- vio->fcntl_mode &= ~O_NONBLOCK; /*clear bit */
- else
- vio->fcntl_mode |= O_NONBLOCK; /*set bit */
- if (old_fcntl != vio->fcntl_mode)
- r = fcntl(vio->sd, F_SETFL, vio->fcntl_mode);
- }
-#endif /* !defined(NO_FCNTL_NONBLOCK) */
-#else /* !defined(__WIN__) && !defined(__EMX__) */
-#ifndef __EMX__
- if (vio->type != VIO_TYPE_NAMEDPIPE)
-#endif
- {
- ulong arg;
- int old_fcntl=vio->fcntl_mode;
- if (!vio->fcntl_set)
- {
- vio->fcntl_set = TRUE;
- old_fnctl=vio->fcntl_mode=0;
- }
- if (set_blocking_mode)
- {
- arg = 0;
- vio->fcntl_mode &= ~O_NONBLOCK; /*clear bit */
- }
- else
- {
- arg = 1;
- vio->fcntl_mode |= O_NONBLOCK; /*set bit */
- }
- if (old_fcntl != vio->fcntl_mode)
- r = ioctlsocket(vio->sd,FIONBIO,(void*) &arg, sizeof(arg));
- }
-#endif /* !defined(__WIN__) && !defined(__EMX__) */
- DBUG_RETURN(r);
-}
-
-my_bool
-vio_is_blocking(Vio * vio)
-{
- my_bool r;
- DBUG_ENTER("vio_is_blocking");
- r = !(vio->fcntl_mode & O_NONBLOCK);
- DBUG_PRINT("exit", ("%d", (int) r));
- DBUG_RETURN(r);
-}
-
-
-int vio_fastsend(Vio * vio, my_bool onoff)
-{
- int r=0;
- DBUG_ENTER("vio_fastsend");
- DBUG_PRINT("enter", ("onoff:%d", (int) onoff));
- assert(vio->sd >= 0);
-
-#ifdef IPTOS_THROUGHPUT
- {
-#ifndef __EMX__
- int tos = IPTOS_THROUGHPUT;
- if (!setsockopt(vio->sd, IPPROTO_IP, IP_TOS, (void *) &tos, sizeof(tos)))
-#endif /* !__EMX__ */
- {
- int nodelay = 1;
- if (setsockopt(vio->sd, IPPROTO_TCP, TCP_NODELAY, (void *) &nodelay,
- sizeof(nodelay))) {
- DBUG_PRINT("warning",
- ("Couldn't set socket option for fast send"));
- r= -1;
- }
- }
- }
-#endif /* IPTOS_THROUGHPUT */
- DBUG_PRINT("exit", ("%d", r));
- DBUG_RETURN(r);
-}
-
-int vio_keepalive(Vio* vio, my_bool set_keep_alive)
-{
- int r=0;
- uint opt = 0;
- DBUG_ENTER("vio_keepalive");
- DBUG_PRINT("enter", ("sd=%d, set_keep_alive=%d", vio->sd, (int)
- set_keep_alive));
- if (vio->type != VIO_TYPE_NAMEDPIPE)
- {
- assert(vio->sd >= 0);
- if (set_keep_alive)
- opt = 1;
- r = setsockopt(vio->sd, SOL_SOCKET, SO_KEEPALIVE, (char *) &opt,
- sizeof(opt));
- }
- DBUG_RETURN(r);
-}
-
-
-my_bool
-vio_should_retry(Vio * vio)
-{
- int en = errno;
- return en == EAGAIN || en == EINTR || en == EWOULDBLOCK;
-}
-
-
-int vio_close(Vio * vio)
-{
- int r;
- DBUG_ENTER("vio_close");
- assert(vio->sd >= 0); /* Vill also work on PIPE:s */
-#ifdef __WIN__
- if (vio->type == VIO_TYPE_NAMEDPIPE)
- {
-#if defined(__NT__) && defined(MYSQL_SERVER)
- CancelIO(vio->hPipe);
- DisconnectNamedPipe(vio->hPipe);
-#endif
- r=CloseHandle(vio->hPipe);
- }
- else
-#endif /* __WIN__ */
- {
- r=0;
- if (shutdown(vio->sd,2))
- r= -1;
- if (closesocket(vio->sd))
- r= -1;
- }
- if (r)
- {
- DBUG_PRINT("error", ("close() failed, error: %d",errno));
- /* FIXME: error handling (not critical for MySQL) */
- }
- vio_reset(vio,VIO_CLOSED,-1,0,TRUE); /* For debugging */
- DBUG_RETURN(r);
-}
-
-
-const char *vio_description(Vio * vio)
-{
- return vio->desc;
-}
-
-enum enum_vio_type vio_type(Vio* vio)
-{
- return vio->type;
-}
-
-my_socket vio_fd(Vio* vio)
-{
- return vio->sd;
-}
-
-
-my_bool vio_peer_addr(Vio * vio, char *buf)
-{
- DBUG_ENTER("vio_peer_addr");
- DBUG_PRINT("enter", ("sd=%d", vio->sd));
- if (vio->localhost)
- {
- strmov(buf,"127.0.0.1");
- }
- else
- {
- size_socket addrLen = sizeof(struct sockaddr);
- if (getpeername(vio->sd, (struct sockaddr *) (& (vio->remote)),
- &addrLen) != 0)
- {
- DBUG_PRINT("exit", ("getpeername, error: %d", errno));
- DBUG_RETURN(1);
- }
- my_inet_ntoa(vio->remote.sin_addr,buf);
- }
- DBUG_PRINT("exit", ("addr=%s", buf));
- DBUG_RETURN(0);
-}
-
-
-void vio_in_addr(Vio *vio, struct in_addr *in)
-{
- DBUG_ENTER("vio_in_addr");
- if (vio->localhost)
- bzero((char*) in, sizeof(*in)); /* This should never be executed */
- else
- *in=vio->remote.sin_addr;
- DBUG_VOID_RETURN;
-}
-
-#endif /* HAVE_VIO */
diff --git a/configure.in b/configure.in
index f11e2354dfd..f8f5d88369b 100644
--- a/configure.in
+++ b/configure.in
@@ -4,13 +4,13 @@ dnl Process this file with autoconf to produce a configure script.
AC_INIT(sql/mysqld.cc)
AC_CANONICAL_SYSTEM
# The Docs Makefile.am parses this line!
-AM_INIT_AUTOMAKE(mysql, 3.23.49)
+AM_INIT_AUTOMAKE(mysql, 4.0.2-alpha)
AM_CONFIG_HEADER(config.h)
PROTOCOL_VERSION=10
DOT_FRM_VERSION=6
# See the libtool docs for information on how to do shared lib versions.
-SHARED_LIB_VERSION=10:0:0
+SHARED_LIB_VERSION=11:0:0
# Set all version vars based on $VERSION. How do we do this more elegant ?
# Remember that regexps needs to quote [ and ] since this is run through m4
@@ -618,9 +618,11 @@ AC_CHECK_HEADERS(fcntl.h float.h floatingpoint.h ieeefp.h limits.h \
#--------------------------------------------------------------------
AC_CHECK_LIB(m, floor, [], AC_CHECK_LIB(m, __infinity))
-AC_CHECK_FUNC(gethostbyname_r, [], [
- AC_CHECK_LIB(nsl_r, gethostbyname_r, [],
- AC_CHECK_LIB(nsl, gethostbyname_r))])
+
+AC_CHECK_LIB(nsl_r, gethostbyname_r, [],
+ AC_CHECK_LIB(nsl, gethostbyname_r))
+AC_CHECK_FUNC(gethostbyname_r)
+
AC_CHECK_FUNC(setsockopt, , AC_CHECK_LIB(socket, setsockopt))
AC_CHECK_FUNC(yp_get_default_domain, ,
AC_CHECK_LIB(nsl, yp_get_default_domain))
@@ -708,7 +710,46 @@ int main()
if test -z "$atom_ops"; then atom_ops="no"; fi
AC_MSG_RESULT($atom_ops)
+
+ AC_ARG_WITH(pstack,
+ [ --with-pstack Use the pstack backtrace library],
+ [ USE_PSTACK=$withval ],
+ [ USE_PSTACK=no ])
+ pstack_libs=
+ pstack_dirs=
+ if test "$USE_PSTACK" = yes -a "$IS_LINUX" = "true" -a "$BASE_MACHINE_TYPE" = "i386" -a "$with_mit_threads" = "no"
+ then
+ have_libiberty= have_libbfd=
+ my_save_LIBS="$LIBS"
+dnl I have no idea if this is a good test - can not find docs for libiberty
+ AC_CHECK_LIB([iberty], [fdmatch],
+ [have_libiberty=yes
+ AC_CHECK_LIB([bfd], [bfd_openr], [have_libbfd=yes], , [-liberty])])
+ LIBS="$my_save_LIBS"
+
+ if test x"$have_libiberty" = xyes -a x"$have_libbfd" = xyes
+ then
+ pstack_dirs='$(top_srcdir)'/pstack
+ pstack_libs="../pstack/libpstack.a -lbfd -liberty"
+ # We must link staticly when using pstack
+ with_mysqld_ldflags="-all-static"
+ AC_SUBST([pstack_dirs])
+ AC_SUBST([pstack_libs])
+ AC_DEFINE([USE_PSTACK])
+dnl This check isn't needed, but might be nice to give some feedback....
+dnl AC_CHECK_HEADER(libiberty.h,
+dnl have_libiberty_h=yes,
+dnl have_libiberty_h=no)
+ else
+ USE_PSTACK="no"
+ fi
+ else
+ USE_PSTACK="no"
+ fi
fi
+AM_CONDITIONAL(COMPILE_PSTACK, test "$USE_PSTACK" = "yes")
+AC_MSG_CHECKING([if we should use pstack])
+AC_MSG_RESULT([$USE_PSTACK])
# Check for gtty if termio.h doesn't exists
if test "$ac_cv_header_termio_h" = "no" -a "$ac_cv_header_termios_h" = "no"
@@ -890,7 +931,7 @@ then
AC_TRY_COMPILE([#include <sched.h>], [int a = sched_get_priority_min(1);], ,
AC_MSG_ERROR([Syntax error in sched.h. Change _P to __P in the /usr/include/sched.h file. See the Installation chapter in the Reference Manual]))
# RedHat 5.0 does not work with dynamic linking of this. -static also
- # gives a spped increase in linux so it does not hurt on other systems.
+ # gives a speed increase in linux so it does not hurt on other systems.
with_named_thread="-lpthread"
else
AC_MSG_RESULT("Not found")
@@ -1133,11 +1174,14 @@ then
fi
fi
+TOOLS_LIBS="$NON_THREADED_CLIENT_LIBS"
+
# Should we use named pthread library ?
AC_MSG_CHECKING("named thread libs:")
if test "$with_named_thread" != "no"
then
LIBS="$with_named_thread $LIBS $with_named_thread"
+ TOOLS_LIBS="$with_named_thread $TOOLS_LIBS $with_named_thread"
with_posix_threads="yes"
with_mit_threads="no"
AC_MSG_RESULT("$with_named_thread")
@@ -1156,7 +1200,9 @@ else
then
AC_MSG_CHECKING("for pthread_create in -lpthread");
ac_save_LIBS="$LIBS"
+ ac_save_TOOLS_LIBS="$TOOLS_LIBS"
LIBS="$LIBS -lpthread"
+ TOOLS_LIBS="$TOOLS_LIBS -lpthread"
AC_TRY_LINK(
[#include <pthread.h>],
[ (void) pthread_create((pthread_t*) 0,(pthread_attr_t*) 0, 0, 0); ],
@@ -1165,6 +1211,7 @@ else
if test "$with_posix_threads" = "no"
then
LIBS=" $ac_save_LIBS -lpthreads"
+ TOOLS_LIBS=" $ac_save_TOOLS_LIBS -lpthreads"
AC_MSG_CHECKING("for pthread_create in -lpthreads");
AC_TRY_LINK(
[#include <pthread.h>],
@@ -1175,6 +1222,7 @@ else
then
# This is for FreeBSD
LIBS="$ac_save_LIBS -pthread"
+ TOOLS_LIBS="$ac_save_TOOLS_LIBS -pthread"
AC_MSG_CHECKING("for pthread_create in -pthread");
AC_TRY_LINK(
[#include <pthread.h>],
@@ -1185,6 +1233,7 @@ else
then
with_mit_threads="yes"
LIBS="$ac_save_LIBS"
+ TOOLS_LIBS="$ac_save_TOOLS_LIBS"
fi
fi
fi
@@ -1715,6 +1764,48 @@ AC_ARG_WITH(server,
[with_server=yes]
)
+AC_ARG_WITH(embedded-server,
+ [ --with-embedded-server Build the embedded server (libmysqld).],
+ [with_embedded_server=$withval],
+ [with_embedded_server=no]
+)
+
+AC_ARG_WITH(extra-tools,
+ [ --without-extra-tools Skip building utilites in the tools directory.],
+ [with_tools=$withval],
+ [with_tools=yes]
+)
+
+tools_dirs=""
+if test "$with_tools" = "yes"
+then
+ if test "$THREAD_SAFE_CLIENT" = "no"
+ then
+ echo "Warning: extra-tools disabled because --enable-thread-safe-client wasn't used"
+ else
+ tools_dirs="tools"
+ fi
+fi
+AC_SUBST(tools_dirs)
+
+#MYSQL_CHECK_CPU
+MYSQL_CHECK_MYSQLFS
+MYSQL_CHECK_VIO
+MYSQL_CHECK_OPENSSL
+
+libmysqld_dirs=
+if test "$with_embedded_server" = "yes"
+then
+ libmysqld_dirs=libmysqld
+ # We can't build embedded library without building the server, because
+ # we depend on libmysys, libmystrings, libmyisam, etc.
+ with_server=yes
+fi
+# XXX: We need to add @libmysqld_extra_libs@ (or whatever) so that
+# mysql_config --libmysqld-libs will print out something like
+# -L/path/to/lib/mysql -lmysqld -lmyisam -lmysys -lmystrings -ldbug ...
+AC_SUBST([libmysqld_dirs])
+
# Shall we build the docs?
AC_ARG_WITH(docs,
[ --without-docs Skip building of the documentation.],
@@ -1771,17 +1862,17 @@ dnl If the character set uses strcoll or other special handling,
dnl you must also create strings/ctype-$charset_name.c
AC_DIVERT_PUSH(0)
-CHARSETS_AVAILABLE="big5 cp1251 cp1257 croat czech danish dec8 dos estonia euc_kr gb2312 gbk german1 greek hebrew hp8 hungarian koi8_ru koi8_ukr latin1 latin2 latin5 swe7 usa7 win1250 win1251 win1251ukr ujis sjis tis620"
+CHARSETS_AVAILABLE="big5 cp1251 cp1257
+ croat czech danish dec8 dos estonia euc_kr gb2312 gbk
+ german1 greek hebrew hp8 hungarian koi8_ru koi8_ukr
+ latin1 latin1_de latin2 latin5 sjis swe7 tis620 ujis
+ usa7 win1250 win1251ukr"
+CHARSETS_DEPRECATED="win1251"
DEFAULT_CHARSET=latin1
AC_DIVERT_POP
-dnl win1251 is deprecated - it's available, but not listed here in the help
AC_ARG_WITH(charset,
- [ --with-charset=CHARSET Use CHARSET by default (one of: big5 cp1251 cp1257
- croat czech danish dec8 dos estonia euc_kr gb2312 gbk
- german1 greek hebrew hp8 hungarian koi8_ru koi8_ukr
- latin1 latin2 latin5 swe7 usa7 win1250 win1251ukr
- ujis sjis tis620; Default is latin1)],
+ [ --with-charset=CHARSET Use CHARSET by default (one of: $CHARSETS_AVAILABLE; Default is $DEFAULT_CHARSET)],
[default_charset="$withval"],
[default_charset="$DEFAULT_CHARSET"])
@@ -1802,7 +1893,7 @@ elif test "$extra_charsets" = complex; then
CHARSETS=`echo $CHARSETS` # get rid of line breaks
else
if test "$extra_charsets" = all; then
- CHARSETS="$CHARSETS_AVAILABLE"
+ CHARSETS="$CHARSETS_AVAILABLE $CHARSETS_DEPRECATED"
else
CHARSETS=`echo $extra_charsets | sed -e 's/,/ /g'`
fi
@@ -1823,7 +1914,7 @@ CHARSETS=$TMP_CHARSETS
for cs in $CHARSETS
do
charset_okay=0
- for charset in $CHARSETS_AVAILABLE
+ for charset in $CHARSETS_AVAILABLE $CHARSETS_DEPRECATED
do
if test $cs = $charset; then charset_okay=1; fi
done
@@ -2003,9 +2094,9 @@ EOF
AC_MSG_RESULT([default: $default_charset; compiled in: $CHARSETS])
+MYSQL_CHECK_ISAM
MYSQL_CHECK_BDB
MYSQL_CHECK_INNODB
-MYSQL_CHECK_GEMINI
# If we have threads generate some library functions and test programs
sql_server_dirs=
@@ -2027,24 +2118,31 @@ AC_SUBST(CLIENT_LIBS)
AC_SUBST(sql_client_dirs)
AC_SUBST(linked_client_targets)
-if test "$with_server" = "yes" -o "$THREAD_SAFE_CLIENT" != "no"
-then
- AC_DEFINE(THREAD)
-fi
-
if test "$with_server" = "yes"
then
+ AC_DEFINE(THREAD)
# Avoid _PROGRAMS names
THREAD_LPROGRAMS="test_thr_alarm test_thr_lock"
AC_SUBST(THREAD_LPROGRAMS)
THREAD_LOBJECTS="thr_alarm.o thr_lock.o thr_mutex.o thr_rwlock.o my_pthread.o my_thr_init.o"
AC_SUBST(THREAD_LOBJECTS)
- sql_server_dirs="strings dbug mysys extra regex isam merge myisam myisammrg heap sql"
- server_scripts="safe_mysqld mysql_install_db"
+ server_scripts="mysqld_safe mysql_install_db"
+ sql_server_dirs="strings dbug mysys extra regex"
+
+
+ #
+ # Configuration for optional table handlers
+ #
+
+ if test X"$have_isam" != Xno
+ then
+ sql_server_dirs="$sql_server_dirs isam merge"
+ fi
+
if test X"$have_berkeley_db" != Xno; then
if test X"$have_berkeley_db" != Xyes; then
# we must build berkeley db from source
- sql_server_dirs="$have_berkeley_db $sql_server_dirs"
+ sql_server_dirs="$sql_server_dirs $have_berkeley_db"
echo "CONFIGURING FOR BERKELEY DB"
bdb_conf_flags=
@@ -2111,7 +2209,7 @@ EOF
if test X"$have_innodb" = Xyes
then
- sql_server_dirs="innobase $sql_server_dirs"
+ sql_server_dirs="$sql_server_dirs innobase"
echo "CONFIGURING FOR INNODB"
if test ! -d "innobase"; then
# This should only happen when doing a VPATH build
@@ -2128,21 +2226,11 @@ EOF
echo "END OF INNODB CONFIGURATION"
fi
+ #
+ # END of configuration for optional table handlers
+ #
+ sql_server_dirs="$sql_server_dirs myisam myisammrg heap vio sql"
- if test "X$have_gemini_db" = "Xyes"; then
- sql_server_dirs="gemini $sql_server_dirs"
- echo "CONFIGURING FOR GEMINI DB"
- (cd gemini && sh ./configure) \
- || AC_MSG_ERROR([could not configure Gemini DB])
-
- echo "END OF GEMINI DB CONFIGURATION"
-
- AC_DEFINE(HAVE_GEMINI_DB)
- fi
-fi
-
-if test "$with_server" = "yes" -o "$THREAD_SAFE_CLIENT" != "no"
-then
if test "$with_posix_threads" = "no" -o "$with_mit_threads" = "yes"
then
# MIT user level threads
@@ -2179,17 +2267,20 @@ AC_SUBST(server_scripts)
# Some usefull subst
AC_SUBST(CC)
AC_SUBST(GXX)
+#Remove TOOLS_LIBS, because this is included in LIBRARIES
+#AC_SUBST(TOOLS_LIBS)
# Output results
AC_OUTPUT(Makefile extra/Makefile mysys/Makefile isam/Makefile \
strings/Makefile regex/Makefile heap/Makefile \
bdb/Makefile \
myisam/Makefile myisammrg/Makefile \
- man/Makefile \
- readline/Makefile libmysql_r/Makefile libmysql/Makefile client/Makefile \
- sql/Makefile sql/share/Makefile \
+ man/Makefile BUILD/Makefile readline/Makefile vio/Makefile \
+ libmysql_r/Makefile libmysqld/Makefile libmysqld/examples/Makefile \
+ libmysql/Makefile client/Makefile \
+ pstack/Makefile pstack/aout/Makefile sql/Makefile sql/share/Makefile \
merge/Makefile dbug/Makefile scripts/Makefile \
- include/Makefile sql-bench/Makefile \
+ include/Makefile sql-bench/Makefile tools/Makefile \
tests/Makefile Docs/Makefile support-files/Makefile \
mysql-test/Makefile \
include/mysql_version.h
diff --git a/dbug/dbug.c b/dbug/dbug.c
index cfe4ca161c6..9e1e51d2404 100644
--- a/dbug/dbug.c
+++ b/dbug/dbug.c
@@ -69,7 +69,7 @@
#ifdef DBUG_OFF
#undef DBUG_OFF
#endif
-#include <global.h>
+#include <my_global.h>
#include <m_string.h>
#include <errno.h>
#if defined(MSDOS) || defined(__WIN__)
@@ -1928,7 +1928,7 @@ static void dbug_flush(CODE_STATE *state)
{
if (!(freopen(stack->name,"a",_db_fp_)))
{
- (void) fprintf(stderr, ERR_OPEN, _db_process_);
+ (void) fprintf(stderr, ERR_OPEN, _db_process_, stack->name);
fflush(stderr);
_db_fp_ = stdout;
stack -> out_file = _db_fp_;
diff --git a/dbug/dbug_analyze.c b/dbug/dbug_analyze.c
index bcee5230527..de228c64aa5 100644
--- a/dbug/dbug_analyze.c
+++ b/dbug/dbug_analyze.c
@@ -49,7 +49,7 @@
* if invoked with -v flag.
*/
-#include <global.h>
+#include <my_global.h>
#include <m_string.h>
static char *my_name;
diff --git a/dbug/example1.c b/dbug/example1.c
index 932e269cc4c..e468f065796 100644
--- a/dbug/example1.c
+++ b/dbug/example1.c
@@ -1,5 +1,5 @@
-#include <global.h>
+#include <my_global.h>
main (argc, argv)
int argc;
diff --git a/dbug/example2.c b/dbug/example2.c
index 482691a8a74..5e5f14f0e7e 100644
--- a/dbug/example2.c
+++ b/dbug/example2.c
@@ -1,5 +1,5 @@
-#include <global.h>
+#include <my_global.h>
int debug = 0;
diff --git a/dbug/example3.c b/dbug/example3.c
index b504edf2e61..f177c07425d 100644
--- a/dbug/example3.c
+++ b/dbug/example3.c
@@ -1,5 +1,5 @@
-#include <global.h>
+#include <my_global.h>
main (argc, argv)
int argc;
diff --git a/dbug/factorial.c b/dbug/factorial.c
index 0dda5c7459e..56197aef29e 100644
--- a/dbug/factorial.c
+++ b/dbug/factorial.c
@@ -2,7 +2,7 @@
#undef DBUG_OFF
#endif
-#include <global.h>
+#include <my_global.h>
int factorial (
register int value)
diff --git a/dbug/main.c b/dbug/main.c
index 863b4d319c2..da56c00feb3 100644
--- a/dbug/main.c
+++ b/dbug/main.c
@@ -2,7 +2,7 @@
#undef DBUG_OFF
#endif
-#include <global.h> /* This includes dbug.h */
+#include <my_global.h> /* This includes dbug.h */
int main (argc, argv)
int argc;
diff --git a/dbug/sanity.c b/dbug/sanity.c
index d287a468028..df43fc14ba9 100644
--- a/dbug/sanity.c
+++ b/dbug/sanity.c
@@ -1,6 +1,6 @@
/* Declarate _sanity() if not declared in main program */
-#include <global.h>
+#include <my_global.h>
extern int _sanity(const char *file,uint line);
diff --git a/div/deadlock_test.c b/div/deadlock_test.c
index be6d940cf1b..65a0df5c215 100644
--- a/div/deadlock_test.c
+++ b/div/deadlock_test.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -126,7 +126,7 @@ static void permute_aux(int *order, int num_queries, int* fixed)
}
/*printf("num_free = %d\n", num_free); */
-
+
if(num_free <= 1)
{
count++;
@@ -156,7 +156,7 @@ static void run_query_batch(int* order, int num_queries)
dump_result(q->mysql, q->query);
}
printf("\n");
-
+
}
static void safe_net_read(NET* net, char* query)
@@ -167,8 +167,8 @@ static void safe_net_read(NET* net, char* query)
die("Error running query '%s'", query);
if(net->read_pos[0] == 255)
die("Error running query '%s'", query);
-}
-
+}
+
static void safe_query(MYSQL* mysql, char* query, int read_ok)
{
@@ -230,7 +230,7 @@ int main()
permute(order, num_queries);
printf("count = %d\n", count);
-
+
mysql_close(&lock);
mysql_close(&sel);
mysql_close(&del_ins);
diff --git a/extra/Makefile.am b/extra/Makefile.am
index ee6c2ba92f2..25633a386e2 100644
--- a/extra/Makefile.am
+++ b/extra/Makefile.am
@@ -18,7 +18,7 @@ INCLUDES = @MT_INCLUDES@ -I$(srcdir)/../include -I../include -I..
LDADD = @CLIENT_EXTRA_LDFLAGS@ ../mysys/libmysys.a \
../dbug/libdbug.a ../strings/libmystrings.a
bin_PROGRAMS = replace comp_err perror resolveip my_print_defaults \
-resolve_stack_dump
+resolve_stack_dump mysql_install
OMIT_DEPENDENCIES = pthread.h stdio.h __stdio.h stdlib.h __stdlib.h math.h\
__math.h time.h __time.h unistd.h __unistd.h types.h \
diff --git a/extra/comp_err.c b/extra/comp_err.c
index f7b68ff0891..806fb5052b4 100644
--- a/extra/comp_err.c
+++ b/extra/comp_err.c
@@ -1,23 +1,22 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/* Saves all errmesg in a header file, updated by me, in a compact file */
-#include <global.h>
+#include <my_global.h>
#include <m_ctype.h>
#include <my_sys.h>
#include <m_string.h>
diff --git a/extra/my_print_defaults.c b/extra/my_print_defaults.c
index 316d91ef7b3..70ccb3797e6 100644
--- a/extra/my_print_defaults.c
+++ b/extra/my_print_defaults.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/*
** print_default.c:
@@ -22,7 +21,7 @@
** Written by Monty
*/
-#include <global.h>
+#include <my_global.h>
#include <my_sys.h>
#include <getopt.h>
@@ -59,7 +58,7 @@ static void usage(my_bool version)
-?, --help Display this help message and exit.\n\
-V, --version Output version information and exit.\n",
config_file);
- printf("\nExample usage: %s --config-file=my client mysql\n",my_progname);
+ printf("\nExample usage:\n%s --config-file=my client mysql\n",my_progname);
}
static int get_options(int *argc,char ***argv)
diff --git a/extra/mysql_install.c b/extra/mysql_install.c
index dfd71895647..1fa62f35b7e 100644
--- a/extra/mysql_install.c
+++ b/extra/mysql_install.c
@@ -21,7 +21,7 @@
#define INSTALL_VERSION "1.0"
#define DONT_USE_RAID
-#include <global.h>
+#include <my_global.h>
#include <m_ctype.h>
#include <my_sys.h>
#include <m_string.h>
@@ -29,13 +29,195 @@
#include <errno.h>
#include <getopt.h>
+#define ANSWERS_CHUNCK 32
+
+int have_gui=0;
+
struct option long_options[] =
{
- {"help", no_argument, 0, 'h'},
+ {"help", no_argument, 0, '?'},
{"version", no_argument, 0, 'V'},
{0, 0,0,0}
};
+/* For now, not much exciting here, but we'll add more once
+ we add GUI support
+ */
+typedef struct
+{
+ FILE* out;
+ FILE* in;
+ const char* question;
+ int default_ind;
+ DYNAMIC_ARRAY answers;
+} QUESTION_WIDGET;
+
+static void usage();
+static void die(const char* fmt, ...);
+static void print_version(void);
+static char get_answer_char(int ans_ind);
+static int ask_user(const char* question,int default_ind, ...);
+static void add_answer(QUESTION_WIDGET* w, const char* ans);
+static void display_question(QUESTION_WIDGET* w);
+static int init_question_widget(QUESTION_WIDGET* w, const char* question,
+ int default_ind);
+static void end_question_widget(QUESTION_WIDGET* w);
+static int get_answer(QUESTION_WIDGET* w);
+static char answer_from_char(char c);
+static void invalid_answer(QUESTION_WIDGET* w);
+
+enum {IMODE_STANDARD=0,IMODE_CUSTOM,IMODE_UPGRAGE} install_mode
+ = IMODE_STANDARD;
+
+static char get_answer_char(int ans_ind)
+{
+ return 'a' + ans_ind;
+}
+
+static void invalid_answer(QUESTION_WIDGET* w)
+{
+ if (!have_gui)
+ {
+ fprintf(w->out, "ERROR: invalid answer, try again...\a\n");
+ }
+}
+
+static char answer_from_char(char c)
+{
+ return c - 'a';
+}
+
+static void die(const char* fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+ fprintf(stderr, "%s: ", my_progname);
+ vfprintf(stderr, fmt, args);
+ fprintf(stderr, "\n");
+ va_end(args);
+ exit(1);
+}
+
+static void display_question(QUESTION_WIDGET* w)
+{
+ if (!have_gui)
+ {
+ uint i,num_answers=w->answers.elements;
+ DYNAMIC_ARRAY* answers = &w->answers;
+ fprintf(w->out,"\n%s\n\n",w->question);
+
+ for (i=0; i<num_answers; i++)
+ {
+ char* ans;
+ get_dynamic(answers,(gptr)&ans,i);
+ fprintf(w->out,"%c - %s\n",get_answer_char(i),ans);
+ }
+ fprintf(w->out,"q - Abort Install/Upgrade\n\n");
+ }
+}
+
+static void add_answer(QUESTION_WIDGET* w, const char* ans)
+{
+ insert_dynamic(&w->answers,(gptr)&ans);
+}
+
+static int init_question_widget(QUESTION_WIDGET* w, const char* question,
+ int default_ind)
+{
+ if (have_gui)
+ {
+ w->in = w->out = 0;
+ }
+ else
+ {
+ w->out = stdout;
+ w->in = stdin;
+ }
+ w->question = question;
+ w->default_ind = default_ind;
+ if (init_dynamic_array(&w->answers,sizeof(char*),
+ ANSWERS_CHUNCK,ANSWERS_CHUNCK))
+ die("Out of memory");
+ return 0;
+}
+
+static void end_question_widget(QUESTION_WIDGET* w)
+{
+ delete_dynamic(&w->answers);
+}
+
+static int get_answer(QUESTION_WIDGET* w)
+{
+ if (!have_gui)
+ {
+ char buf[32];
+ int ind;
+ char c;
+ if (!fgets(buf,sizeof(buf),w->in))
+ die("Failed fgets on input stream");
+ switch ((c=tolower(*buf)))
+ {
+ case '\n':
+ return w->default_ind;
+ case 'q':
+ die("Install/Upgrade aborted");
+ default:
+ ind = answer_from_char(c);
+ if (ind >= 0 && ind < (int)w->answers.elements)
+ return ind;
+ }
+ }
+ return -1;
+}
+
+static int ask_user(const char* question,int default_ind, ...)
+{
+ va_list args;
+ char* opt;
+ QUESTION_WIDGET w;
+ int ans;
+
+ va_start(args,default_ind);
+ init_question_widget(&w,question,default_ind);
+ for (;(opt=va_arg(args,char*));)
+ {
+ add_answer(&w,opt);
+ }
+ for (;;)
+ {
+ display_question(&w);
+ if ((ans = get_answer(&w)) >= 0)
+ break;
+ invalid_answer(&w);
+ }
+ end_question_widget(&w);
+ va_end(args);
+ return ans;
+}
+
+static int parse_args(int argc, char **argv)
+{
+ int c, option_index = 0;
+
+ while((c = getopt_long(argc, argv, "?V",
+ long_options, &option_index)) != EOF)
+ {
+ switch(c)
+ {
+ case 'V':
+ print_version();
+ exit(0);
+ case '?':
+ usage();
+ exit(0);
+ default:
+ usage();
+ exit(1);
+ }
+ }
+ return 0;
+}
+
static void print_version(void)
{
printf("%s Ver %s Distrib %s, for %s (%s)\n",my_progname,INSTALL_VERSION,
@@ -55,6 +237,16 @@ static void usage()
-V, --version Output version information and exit.\n");
}
+int main(int argc, char** argv)
+{
+ MY_INIT(argv[0]);
+ parse_args(argc,argv);
+ install_mode = ask_user("Please select install/upgrade mode",
+ install_mode, "Standard Install",
+ "Custom Install", "Upgrade",0);
+ printf("mode=%d\n", install_mode);
+ return 0;
+}
diff --git a/extra/perror.c b/extra/perror.c
index 6cb86eedf27..aa4ee71c7d1 100644
--- a/extra/perror.c
+++ b/extra/perror.c
@@ -1,25 +1,24 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/* Return error-text for system error messages and nisam messages */
#define PERROR_VERSION "2.7"
-#include <global.h>
+#include <my_global.h>
#include <my_sys.h>
#include <m_string.h>
#include <errno.h>
@@ -111,7 +110,7 @@ static void usage(void)
-s, --silent Only print the error message\n\
-v, --verbose Print error code and message (default).\n\
-V, --version Displays version information and exits.\n");
-}
+}
static int get_options(int *argc,char ***argv)
@@ -231,4 +230,3 @@ int main(int argc,char *argv[])
exit(error);
return error;
}
-
diff --git a/extra/replace.c b/extra/replace.c
index ef3abda5cc5..41312f5e3d4 100644
--- a/extra/replace.c
+++ b/extra/replace.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/* Replace strings in textfile
This program replace strings in a file or on stdin/stdout.
@@ -38,7 +37,7 @@
*/
#define DONT_USE_RAID
-#include <global.h>
+#include <my_global.h>
#include <m_ctype.h>
#include <my_sys.h>
#include <m_string.h>
diff --git a/extra/resolve_stack_dump.c b/extra/resolve_stack_dump.c
index fbb5ad5e378..6c2ddf66027 100644
--- a/extra/resolve_stack_dump.c
+++ b/extra/resolve_stack_dump.c
@@ -1,26 +1,25 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/* Resolve numeric stack dump produced by mysqld 3.23.30 and later
versions into symbolic names. By Sasha Pachev <sasha@mysql.com>
*/
#define DONT_USE_RAID
-#include <global.h>
+#include <my_global.h>
#include <m_ctype.h>
#include <my_sys.h>
#include <m_string.h>
@@ -163,7 +162,7 @@ static void open_files()
{
fp_out = stdout;
fp_dump = stdin;
-
+
if(dump_fname && !(fp_dump = my_fopen(dump_fname, O_RDONLY, MYF(MY_WME))))
die("Could not open %s", dump_fname);
/* if name not given, assume stdin*/
@@ -173,7 +172,7 @@ static void open_files()
trace dump and specify the path to it with -s or --symbols-file");
if(!(fp_sym = my_fopen(sym_fname, O_RDONLY, MYF(MY_WME))))
die("Could not open %s", sym_fname);
-
+
}
static uchar hex_val(char c)
@@ -192,10 +191,10 @@ static my_long_addr_t read_addr(char** buf)
uchar c;
char* p = *buf;
my_long_addr_t addr = 0;
-
+
while((c = hex_val(*p++)) != HEX_INVALID)
addr = (addr << 4) + c;
-
+
*buf = p;
return addr;
}
@@ -209,7 +208,7 @@ static int init_sym_entry(SYM_ENTRY* se, char* buf)
return -1;
while(isspace(*buf++))
/* empty */;
-
+
while(isspace(*buf++))
/* empty - skip more space */;
--buf;
@@ -256,7 +255,7 @@ static void verify_sort()
{
uint i;
uchar* last = 0;
-
+
for(i = 0; i < sym_table.elements; i++)
{
SYM_ENTRY se;
@@ -274,7 +273,7 @@ static SYM_ENTRY* resolve_addr(uchar* addr, SYM_ENTRY* se)
get_dynamic(&sym_table, (gptr)se, 0);
if(addr < se->addr)
return 0;
-
+
for(i = 1; i < sym_table.elements; i++)
{
get_dynamic(&sym_table, (gptr)se, i);
@@ -297,7 +296,7 @@ static void do_resolve()
while(isspace(*p))
++p;
/* skip space */;
-
+
if(*p++ == '0' && *p++ == 'x')
{
SYM_ENTRY se ;
@@ -307,7 +306,7 @@ static void do_resolve()
(int) (addr - se.addr));
else
fprintf(fp_out, "%p (?)\n", addr);
-
+
}
else
{
@@ -327,4 +326,3 @@ int main(int argc, char** argv)
clean_up();
return 0;
}
-
diff --git a/fs/CorbaFS.idl b/fs/CorbaFS.idl
new file mode 100644
index 00000000000..8fe089bd13c
--- /dev/null
+++ b/fs/CorbaFS.idl
@@ -0,0 +1,38 @@
+// -----------------------------------------------------------------------------
+// CorbaDS Module - Implement Kernel functionality in korbit
+// -----------------------------------------------------------------------------
+//
+// Main source of information:
+// http://www.cse.unsw.edu.au/~neilb/oss/linux-commentary/vfs.html
+//
+module CorbaFS {
+
+ struct dirent
+ {
+ long inode; // inode number
+ string name; // file name (null-terminated)
+ };
+
+ typedef sequence<dirent> DirEntSeq;
+ typedef sequence<octet> Buffer;
+
+ interface Inode {
+ void getStatus(out unsigned short mode, out unsigned long uid, out unsigned long gid,
+ out unsigned long size, out unsigned long inodeNum, out unsigned short numLinks,
+ out long atime, out long mtime, out long ctime);
+ void readpage(out Buffer buffer, in long size, in long offset);
+ void release();
+ };
+
+ interface FileSystem {
+ Inode getInode(in string path);
+
+ // DirectoryInode getStatus implementation must have S_IFDIR in the S_IFMT
+ // field of the mode value.
+ DirEntSeq readdir(in string path);
+
+ // SymlinkInode getStatus implementation must have S_IFLNK in the S_IFMT
+ // field of the mode value.
+ string readlink(in string filename);
+ };
+};
diff --git a/fs/Makefile.am b/fs/Makefile.am
new file mode 100644
index 00000000000..33d1acd913d
--- /dev/null
+++ b/fs/Makefile.am
@@ -0,0 +1,93 @@
+# Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+#called from the top level Makefile
+
+CFLAGS = $(ORBIT_CFLAGS) -g
+LFLAGS = $(ORBIT_LIBS)
+orbit_idl = @orbit_idl@
+orbit_includes = @orbit_includes@
+orbit_libs = @orbit_libs@
+
+DISTCLEANFILES = CorbaFS-common.* CorbaFS-stubs.* CorbaFS-skels.* CorbaFS.h
+
+MYSQLDATAdir = $(localstatedir)
+MYSQLSHAREdir = $(pkgdatadir)
+MYSQLBASEdir= $(prefix)
+INCLUDES = @MT_INCLUDES@ -I$(srcdir)/../include \
+ -I$(srcdir)/../regex \
+ -I$(srcdir) -I../include -I.. -I. \
+ -I$(srcdir) -I../include -I.. -I. \
+ $(orbit_includes)
+WRAPLIBS= @WRAPLIBS@
+libexec_PROGRAMS = mysqlcorbafsd
+noinst_PROGRAMS =mysqlfs_test
+LDADD = ../libmysql/libmysqlclient.la $(orbit_libs)
+mysqlcorbafsd_LDADD = $(LDADD) $(CXXLDFLAGS)
+noinst_HEADERS =
+mysqlfs_test_SOURCES = mysqlcorbafs_test.c CorbaFS-common.c CorbaFS-stubs.c libmysqlfs.c
+mysqlcorbafsd_SOURCES = mysqlcorbafs.c CorbaFS-skels.c database.c CorbaFS-common.c libmysqlfs.c
+
+DEFS = -DMYSQL_SERVER \
+ -DDEFAULT_MYSQL_HOME="\"$(MYSQLBASEdir)\"" \
+ -DDATADIR="\"$(MYSQLDATAdir)\"" \
+ -DSHAREDIR="\"$(MYSQLSHAREdir)\"" \
+ @DEFS@
+# Don't put lex_hash.h in BUILT_SOURCES as this will give infinite recursion
+BUILT_SOURCES = CorbaFS-common.c CorbaFS-stubs.c CorbaFS-skels.c CorbaFS.h
+EXTRA_DIST = $(BUILT_SOURCES)
+#YFLAGS = -d
+
+OMIT_DEPENDENCIES = pthread.h stdio.h __stdio.h stdlib.h __stdlib.h math.h\
+ __math.h time.h __time.h unistd.h __unistd.h types.h \
+ xtypes.h ac-types.h posix.h string.h __string.h \
+ errno.h socket.h inet.h dirent.h netdb.h \
+ cleanup.h cond.h debug_out.h fd.h kernel.h mutex.h \
+ prio_queue.h pthread_attr.h pthread_once.h queue.h\
+ sleep.h specific.h version.h pwd.h timers.h uio.h \
+ cdefs.h machdep.h signal.h __signal.h util.h lex.h \
+ wait.h
+
+link_sources:
+ rm -f mini_client_errors.c
+ @LN_CP_F@ ../libmysql/errmsg.c mini_client_errors.c
+
+
+# Don't update the files from bitkeeper
+%::SCCS/s.%
+
+idltargets : CorbaFS.idl
+ $(ORBIT_IDL) CorbaFS.idl
+ $(orbit_idl) CorbaFS.idl
+
+# individual rules
+
+CorbaFS-stubs.c : CorbaFS.idl
+ $(orbit_idl) CorbaFS.idl
+
+CorbaFS-common.c : CorbaFS.idl
+ $(orbit_idl) CorbaFS.idl
+
+CorbaFS-skels.c : CorbaFS.idl
+ $(orbit_idl) CorbaFS.idl
+
+#CorbaFS-client.c : CorbaFS.h
+
+#CorbaFS-server.c : CorbaFS.h
+
+CorbaFS.h : CorbaFS.idl
+ $(orbit_idl) CorbaFS.idl
+
diff --git a/fs/README b/fs/README
new file mode 100644
index 00000000000..5d86da3a7e4
--- /dev/null
+++ b/fs/README
@@ -0,0 +1,58 @@
+MySQL Filesystem
+Tõnu Samuel - tonu@mysql.com
+Some additional information is available on http://no.spam.ee/~tonu/mysqlfs.html
+
+WARNING: Experimental code and known to crash computer.
+
+Instructions, how to get this stuff working:
+1. Make sure you have ORBit, includeing development libraries installed. They should be version 0.5.3 or later.
+- I am lazy man and use default ones included with my RedHat:
+ [root@localhost /root]# rpm -qa | grep ORBit
+ ORBit-0.5.3-2
+ ORBit-devel-0.5.3-2
+ [root@localhost /root]#
+
+2. Prepare kernel to include korbit:
+- Get Linux 2.4.1 kernel source. (very possibly this patch works on 2.4.0 without modifications too)
+- unpack it
+- apply patch named "korbit-kernel-2.4.1-patch" on it.
+- make menuconfig
+- In section "Networking options":
+ ...
+ [*] Kernel ORB (EXPERIMENTAL)
+ ...
+ <M> CORBA User-space FileSystem (EXPERIMENTAL)
+ ...
+- make dep ; make bzlilo ; make modules ; make modules_install
+- reboot
+- Execute: insmod /lib/modules/$(uname -r)/kernel/net/korbit/modules/CorbaFS/client/corba-corbafs-client.o
+ You should see "gethostname() = localhost". Look at known bug 3 in the end of this doc.
+
+3. Make sure MySQL server is working on your system
+- On my RedHat 7.0 I execute "/etc/init.d/mysqld start"
+
+4. Prepare MySQL FS daemon
+- Get MySQL 4.0 from repository OR get MySQL FS source from http://no.spam.ee/~tonu/mysqlfs.html
+- unpack it. In MySQL 4.0 source this is located in directory named "fs". cd into it.
+- make
+- Execute command "./RunServer"
+
+5. mount MySQL server to disk tree
+- Execute command "mkdir /mnt/mysql"
+- Execute command "mount -t corbafs -o `cat /tmp/mysqlcorbafs.ior` none /mnt/mysql/"
+- Check you SQL server content by executing "ls -la /mnt/mysql/"
+
+Known bugs:
+
+1. User bugs. fix user ;)
+
+2. MySQL FS daemon will crash or will be stopped when cobrafs is mounted, then there is no way
+to unmount disks anymore. This is korbit business to handle such cases and I had no time to dig
+into korbit code.
+
+3. host name returned by gethostname() should be "localhost" or korbit will crash. Also "localhost"
+must be first string after 127.0.0.1 in /etc/hosts
+
+
+
+
diff --git a/fs/RunServer.sh b/fs/RunServer.sh
new file mode 100755
index 00000000000..22d152bb20b
--- /dev/null
+++ b/fs/RunServer.sh
@@ -0,0 +1,2 @@
+.libs/mysqlcorbafsd -ORBIIOPUSock=0 -ORBIIOPIPv4=1 --debug='d:t:o,~/mysqlfsd.trace' $*
+#.libs/mysqlcorbafsd -ORBIIOPUSock=0 -ORBIIOPIPv4=1 $*
diff --git a/fs/database.c b/fs/database.c
new file mode 100644
index 00000000000..4a328c41618
--- /dev/null
+++ b/fs/database.c
@@ -0,0 +1,628 @@
+/* Copyright (C) 2000 db AB & db Finland AB & TCX DataKonsult AB
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/*
+ * Database functions
+ *
+ * Using these functions we emulate filesystem behaviour on top of SQL
+ * database.
+ * Written by Tõnu Samuel <tonu@please.do.not.remove.this.spam.ee>
+ *
+ * FIXME:
+ * - Direct handling of database handlers without SQL parsing overhead
+ * - connection pool
+ * - configurable function name/file name mappings
+ */
+
+
+#include "libmysqlfs.h"
+#include "mysqlcorbafs.h"
+#include <unistd.h>
+#include <string.h>
+#include <my_sys.h>
+
+DYNAMIC_ARRAY field_array;
+
+/*
+ * ** dbConnect -- connects to the host and selects DB.
+ * ** Also checks whether the tablename is a valid table name.
+ * */
+int db_connect(char *host, char *user,char *passwd)
+{
+ DBUG_ENTER("db_connect");
+ DBUG_PRINT("enter",("host: '%s', user: '%s', passwd: '%s'", host, user, passwd));
+
+ if (verbose)
+ {
+ fprintf(stderr, "# Connecting to %s...\n", host ? host : "localhost");
+ }
+ mysql_init(&connection);
+ if (opt_compress)
+ mysql_options(&connection,MYSQL_OPT_COMPRESS,NullS);
+#ifdef HAVE_OPENSSL
+ if (opt_use_ssl)
+ mysql_ssl_set(&connection, opt_ssl_key, opt_ssl_cert, opt_ssl_ca,
+ opt_ssl_capath);
+#endif
+ if (!(sock= mysql_real_connect(&connection,host,user,passwd,
+ NULL,opt_mysql_port,opt_mysql_unix_port,0)))
+ {
+ DBerror(&connection, "when trying to connect");
+ DBUG_RETURN(1);
+ }
+ DBUG_RETURN(0);
+} /* dbConnect */
+
+
+/*
+ * ** dbDisconnect -- disconnects from the host.
+ * */
+void db_disconnect(char *host)
+{
+ DBUG_ENTER("db_disconnect");
+ DBUG_PRINT("enter",("host: '%s'", host));
+ if (verbose)
+ fprintf(stderr, "# Disconnecting from %s...\n", host ? host : "localhost");
+ mysql_close(sock);
+ DBUG_VOID_RETURN;
+} /* dbDisconnect */
+
+#define OUTPUT(x) strcpy(buffptr,x); buffptr+=strlen(x);
+#define OUTPUT_TOP(x) strcpy(topptr,x); topptr+=strlen(x);
+#define OUTPUT_MIDDLE(x) strcpy(midptr,x); midptr+=strlen(x);
+#define OUTPUT_BOTTOM(x) strcpy(botptr,x); botptr+=strlen(x);
+#define OUTPUT_HEADER(x) strcpy(hdrptr,x); hdrptr+=strlen(x);
+
+void db_show_result(MYSQL* sock, char *b, struct format *f)
+{
+ MYSQL_ROW row;
+ MYSQL_RES *result;
+ MYSQL_FIELD *field;
+ char *buffptr;
+ char topseparator[BUFLEN]="";
+ char middleseparator[BUFLEN]="";
+ char bottomseparator[BUFLEN]="";
+ char header[BUFLEN]="";
+ char *topptr=topseparator;
+ char *midptr=middleseparator;
+ char *botptr=bottomseparator;
+ char *hdrptr=header;
+ uint i,count, length;
+
+ DBUG_ENTER("db_show_result");
+ DBUG_PRINT("enter",("b: '%s', f '%x'", b, f));
+
+ result=mysql_store_result(sock);
+
+ buffptr=b;
+ OUTPUT(f->tablestart)
+
+ OUTPUT_TOP(f->leftuppercorner);
+ OUTPUT_MIDDLE(f->leftcross);
+ OUTPUT_BOTTOM(f->leftdowncorner);
+ OUTPUT_HEADER(f->headerrowstart);
+
+
+ count=mysql_num_fields(result);
+// while ((field = mysql_fetch_field(result)))
+ for(i=0 ; i < count ; ++i)
+ {
+ field = mysql_fetch_field(result);
+ length=(uint) strlen(field->name);
+ OUTPUT_HEADER(f->headercellstart);
+
+ length=max(length,field->max_length);
+ if (length < 4 && !IS_NOT_NULL(field->flags))
+ length=4; // Room for "NULL"
+ field->max_length=length;
+
+ memset(topptr,'=',field->max_length);
+ memset(midptr,'-',field->max_length);
+ memset(botptr,'=',field->max_length);
+
+ sprintf(hdrptr,"%-*s",field->max_length,field->name);
+ //num_flag[off]= IS_NUM(field->type);
+
+ topptr+=field->max_length;
+ midptr+=field->max_length;
+ botptr+=field->max_length;
+ hdrptr+=field->max_length;
+
+ if(i<count-1) {
+ OUTPUT_TOP(f->topcross);
+ OUTPUT_MIDDLE(f->middlecross);
+ OUTPUT_BOTTOM(f->bottomcross);
+ OUTPUT_HEADER(f->headercellseparator);
+ }
+ }
+ OUTPUT_TOP(f->rightuppercorner);
+ OUTPUT_MIDDLE(f->rightcross);
+ OUTPUT_BOTTOM(f->rightdowncorner);
+
+ OUTPUT_HEADER(f->headercellend);
+ OUTPUT_HEADER(f->headerrowend);
+
+ OUTPUT(topseparator);
+ OUTPUT(header);
+ OUTPUT(middleseparator);
+ while(row=mysql_fetch_row(result)) {
+ mysql_field_seek(result,0);
+
+ OUTPUT(f->contentrowstart);
+ for(i=0 ; i < mysql_field_count(sock); ++i) {
+ field = mysql_fetch_field(result);
+ OUTPUT(f->contentcellstart);
+ sprintf(buffptr,"%-*s",field->max_length,row[i]);
+ buffptr+=field->max_length;
+
+ if(i==mysql_field_count(sock))
+ {
+ OUTPUT(f->contentcellend);
+ } else {
+ OUTPUT(f->contentcellseparator);
+ }
+ }
+ OUTPUT(f->contentrowend);
+ }
+ OUTPUT(bottomseparator);
+ OUTPUT(f->tableend);
+
+ mysql_free_result(result);
+ DBUG_VOID_RETURN;
+}
+
+
+int db_function(char *b,const char *server, const char *database,const char *table,const char *field, const char *value, const char* path, struct func_st *function)
+{
+ char buff[BUFLEN];
+ int i;
+ DBUG_ENTER("db_function");
+ DBUG_PRINT("enter",("buffer: '%s', database: '%s', table: '%s', field: '%s', path: '%s'", b, database, table, field,path));
+
+ if(*database) {
+ if (mysql_select_db(sock,database))
+ {
+ printf("error when changing database to'%s'\n",database);
+ DBUG_RETURN(-1);
+ }
+ }
+
+ sprintf(buff,"%s",function->function);
+ search_and_replace("$database",database,buff);
+ search_and_replace("$table",table,buff);
+ search_and_replace("$field",field,buff);
+ search_and_replace("$value",value,buff);
+ DBUG_PRINT("info",("path: '%s'",path));
+ DBUG_PRINT("info",("sum: '%d'",(database[0] ? strlen(database)+1 : 0) +(table[0] ? strlen(table)+1 : 0) +(field[0] ? strlen(field)+1 : 0) +(value[0] ? strlen(value)+1 : 0) +1));
+ search_and_replace("$*",path+
+ (server[0] ? strlen(server)+1 : 0) +
+ (database[0] ? strlen(database)+1 : 0) +
+ (table[0] ? strlen(table)+1 : 0) +
+ (field[0] ? strlen(field)+1 : 0) +
+ (value[0] ? strlen(value)+1 : 0) +
+ function->length +
+ 1,buff);
+ DBUG_PRINT("info",("Executing constructed function query: '%s'", buff));
+ if (mysql_query(sock, buff))
+ {
+ printf("error when executing '%s'\n",buff);
+ sprintf(b,"ERROR %d: %s",mysql_error(sock),mysql_error(sock));
+ DBUG_VOID_RETURN;
+ }
+
+ db_show_result(sock, b, &Human);
+ DBUG_PRINT("info",("Returning: %s", b));
+ DBUG_RETURN(1);
+}
+
+int db_show_field(char *b,const char *database,const char *table, const char *field,const char *value, const char *param)
+{
+ MYSQL_RES *result;
+ MYSQL_ROW row;
+ char buff[BUFLEN];
+ int i=0;
+ my_string *ptr;
+ DBUG_ENTER("db_show_field");
+ DBUG_PRINT("enter",("buffer: '%s', database: '%s', table: '%s', field: '%s' value: '%s'", b, database, table, field, value));
+
+ /* We cant output fields when one of these variables is missing */
+ if (!(database[0] && table[0] && field[0]))
+ DBUG_RETURN(-1);
+
+ init_dynamic_array(&field_array, sizeof(buff), 4096, 1024);
+
+ if (mysql_select_db(sock,database))
+ {
+ printf("error when changing database to'%s'\n",database);
+ delete_dynamic(&field_array);
+ DBUG_RETURN(-1);
+ }
+
+ if(param) {
+ sprintf(buff,"%s",param);
+ } else {
+ sprintf(buff,"select %s from %s where %s='%s' LIMIT 1",field,table,field,value);
+ }
+ if (mysql_query(sock, buff))
+ {
+ printf("error when executing '%s'\n",buff);
+ delete_dynamic(&field_array);
+ DBUG_RETURN(-1);
+ }
+
+
+ db_show_result(sock,b,&Human);
+/* if(result=mysql_use_result(sock)) {
+ while(row=mysql_fetch_row(result))
+ {
+ strcpy(&b[i][BUFLEN],row[0]);
+ DBUG_PRINT("info",("field %s at %x", &b[i*BUFLEN],&b[i*BUFLEN]));
+// ptr = (*dynamic_element(&field_array,i,row[0]));
+ i++;
+ }
+ }
+// fix_filenames((char *)b);
+ mysql_free_result(result);
+ */
+ delete_dynamic(&field_array);
+ DBUG_RETURN(i);
+
+}
+int db_show_fields(char *b,const char *database,const char *table)
+{
+ MYSQL_RES *result;
+ MYSQL_ROW row;
+ MYSQL_FIELD *field;
+ char buff[BUFLEN];
+ int i=0;
+
+ DBUG_ENTER("show_fields");
+ DBUG_PRINT("enter",("buffer: '%s', database: '%s', table: '%s'", b, database, table));
+ if (mysql_select_db(sock,database))
+ {
+ printf("error when changing database to'%s'\n",database);
+ DBUG_RETURN(-1);
+ }
+ if(result=mysql_list_fields(sock,buff,NULL)) {
+
+ while(row=mysql_fetch_row(result))
+ {
+ strcpy(&b[i*BUFLEN],row[0]);
+ DBUG_PRINT("info",("field %s at %x", &b[i*BUFLEN],&b[i*BUFLEN]));
+ i++;
+ }
+ }
+ mysql_free_result(result);
+ DBUG_RETURN(i);
+}
+
+int db_show_primary_keys(char *b,const char *database, const char *table)
+{
+ MYSQL_RES *result;
+ MYSQL_ROW row;
+ char buff[BUFLEN];
+ char buff2[BUFLEN];
+ unsigned int i;
+
+ DBUG_ENTER("db_show_primary_keys");
+ DBUG_PRINT("enter",("buffer: '%s', database: '%s', table: '%s'", b, database, table));
+ if (mysql_select_db(sock,database))
+ {
+ printf("error when changing database to '%s'\n",database);
+ DBUG_RETURN(-1);
+ }
+ sprintf(buff,"show keys from %s",table);
+ if (mysql_query(sock, buff))
+ {
+ printf("error when executing '%s'\n",buff);
+ DBUG_RETURN(0);
+ }
+ buff2[0]='\0';
+ if(result=mysql_use_result(sock)) {
+ while(row=mysql_fetch_row(result)) {
+ if(!strcasecmp(row[2],"PRIMARY")) {
+ strcat(buff2,row[4]);
+ strcat(buff2,",\"_\",");
+ }
+ }
+ buff2[strlen(buff2)-5]='\0';
+ if(!buff2[0])
+ DBUG_RETURN(-1); // No PRIMARY keys in table
+ DBUG_PRINT("info",("Keys: %s<- \n", buff2));
+ } else
+ DBUG_RETURN(-1); // No keys in table
+
+ sprintf(buff,"SELECT CONCAT(%s) AS X FROM %s LIMIT 256",buff2,table);
+ if (mysql_query(sock, buff))
+ {
+ printf("error when executing '%s'\n",buff);
+ DBUG_RETURN(0);
+ }
+ i=0;
+ if(result=mysql_use_result(sock)) {
+ while(row=mysql_fetch_row(result))
+ {
+ strcpy(&b[i*BUFLEN],row[0]);
+ fix_filenames(&b[i*BUFLEN]);
+ DBUG_PRINT("info",("primarykey %s at %x, %i", &b[i*BUFLEN],&b[i*BUFLEN],i));
+ if(i++ >= MAXDIRS)
+ break;
+ }
+ }
+ mysql_free_result(result);
+ DBUG_RETURN(i);
+}
+
+
+int db_show_keys(char *b,const char *database, const char *table)
+{
+ MYSQL_RES *result;
+ MYSQL_ROW row;
+ char buff[BUFLEN];
+ int i=0;
+
+ DBUG_ENTER("show_keys");
+ DBUG_PRINT("enter",("buffer: '%s', database: '%s', table: '%s'", b, database, table));
+ if (mysql_select_db(sock,database))
+ {
+ printf("error when changing database to'%s'\n",database);
+ DBUG_RETURN(-1);
+ }
+ sprintf(buff,"show keys from %s",table);
+ if (mysql_query(sock, buff))
+ {
+ printf("error when executing '%s'\n",buff);
+ DBUG_RETURN(0);
+ }
+ if(result=mysql_use_result(sock)) {
+ while(row=mysql_fetch_row(result))
+ {
+ strcpy(&b[i*BUFLEN],row[0]);
+ DBUG_PRINT("info",("Key %s at %x", &b[i*BUFLEN],&b[i*BUFLEN]));
+ i++;
+ }
+ }
+ mysql_free_result(result);
+ DBUG_RETURN(i);
+}
+
+
+int db_show_tables(char *b,const char *database)
+{
+ MYSQL_RES *result;
+ MYSQL_ROW row;
+ char buff[BUFLEN];
+ int i=0;
+
+ DBUG_ENTER("db_show_tables");
+ DBUG_PRINT("enter",("buffer: '%s', database: '%s'", b, database));
+ if (mysql_select_db(sock,database))
+ {
+ printf("error when changing database to '%s'\n",database);
+ DBUG_RETURN(-1);
+ }
+
+ if(result=mysql_list_tables(sock,NULL)) {
+ while(row=mysql_fetch_row(result))
+ {
+ strcpy(&b[i*BUFLEN],row[0]);
+ DBUG_PRINT("info",("table %s at %x", &b[i*BUFLEN],&b[i*BUFLEN]));
+ i++;
+ }
+ }
+ mysql_free_result(result);
+ DBUG_RETURN(i);
+}
+
+/*
+ * Finds all servers we are connected to
+ * and stores them in array supplied.
+ * returns count of servers
+ */
+int
+db_show_servers(char *b,int size)
+{
+ char* bufptr;
+ char* buff[BUFLEN*2];
+ DBUG_ENTER("db_show_servers");
+ DBUG_PRINT("enter",("buffer: '%s', size: '%d'", b, size));
+ bufptr=mysql_get_host_info(sock);
+ // FIXME: Actually we need to escape prohibited symbols in filenames
+ fix_filenames(bufptr);
+ strcpy(b,bufptr);
+ DBUG_RETURN(1);
+}
+
+/*
+ * Finds all databases in server
+ * and stores them in array supplied.
+ * returns count of databases
+ */
+int
+db_show_databases(char *b,int size)
+{
+ MYSQL_RES *result;
+ MYSQL_ROW row;
+ char buff[BUFLEN];
+ int i=0;
+
+ DBUG_ENTER("db_show_databases");
+ DBUG_PRINT("enter",("buffer: '%s', size: '%d'", b, size));
+ result=mysql_list_dbs(sock,NULL);
+ while(row=mysql_fetch_row(result))
+ {
+ strcpy(&b[i*BUFLEN],row[0]);
+ DBUG_PRINT("info",("database %s at %x", &b[i*BUFLEN],&b[i*BUFLEN]));
+ i++;
+ }
+ mysql_free_result(result);
+ DBUG_RETURN(i);
+}
+
+void db_load_formats()
+{
+
+ /* In future we should read these variables
+ * from configuration file/database here */
+
+ /* HTML output */
+ HTML.tablestart="<table>\n";
+
+ HTML.headerrowstart="<tr>";
+ HTML.headercellstart="<th>";
+ HTML.headercellseparator="</th><th>";
+ HTML.headercellend="</th>";
+ HTML.headerrowend="</tr>\n";
+ HTML.headerformat=0;
+
+ HTML.leftuppercorner="";
+ HTML.rightuppercorner="";
+ HTML.leftdowncorner="";
+ HTML.rightdowncorner="";
+ HTML.topcross="";
+ HTML.middlecross="";
+ HTML.bottomcross="";
+ HTML.leftcross="";
+ HTML.rightcross="";
+ HTML.bottomcross="";
+
+ HTML.contentrowstart="<tr>";
+ HTML.contentcellstart="<td>";
+ HTML.contentcellseparator="</td><td>";
+ HTML.contentcellend="</td>";
+ HTML.contentrowend="</tr>\n";
+ HTML.headerformat=0;
+
+ HTML.footerrowstart="";
+ HTML.footercellstart="";
+ HTML.footercellseparator="";
+ HTML.footercellend="";
+ HTML.footerrowend="\n";
+ HTML.footerformat=0;
+
+ HTML.tableend="</table>\n";
+
+/* Nice to look mysql client like output */
+
+ Human.tablestart="\n";
+
+ Human.headerrowstart="| ";
+ Human.headercellstart="";
+ Human.headercellseparator=" | ";
+ Human.headercellend=" |";
+ Human.headerrowend="\n";
+ Human.headerformat=1;
+
+ Human.leftuppercorner="/=";
+ Human.rightuppercorner="=\\\n";
+ Human.leftdowncorner="\\=";
+ Human.rightdowncorner="=/\n";
+ Human.leftcross="+-";
+ Human.rightcross="-+\n";
+ Human.topcross="=T=";
+ Human.middlecross="-+-";
+ Human.bottomcross="=`=";
+
+ Human.contentrowstart="| ";
+ Human.contentcellstart="";
+ Human.contentcellseparator=" | ";
+ Human.contentcellend=" |";
+ Human.contentrowend="\n";
+ Human.contentformat=1;
+
+ Human.footerrowstart="";
+ Human.footercellstart="";
+ Human.footercellseparator="";
+ Human.footercellend="";
+ Human.footerrowend="\n";
+ Human.footerformat=1;
+
+ Human.tableend="\n";
+
+/* Comma-separated format. For machine reading */
+
+ /* XML */
+
+/*
+ tee_fprintf(PAGER,"<?xml version=\"1.0\"?>\n\n<resultset statement=\"%s\">", statement);
+ (void) tee_fputs("\n <row>\n", PAGER);
+ data=(char*) my_malloc(lengths[i]*5+1, MYF(MY_WME));
+ tee_fprintf(PAGER, "\t<%s>", (fields[i].name ?
+ (fields[i].name[0] ? fields[i].name :
+ " &nbsp; ") : "NULL"));
+ xmlencode(data, cur[i]);
+ tee_fprintf(PAGER, "</%s>\n", (fields[i].name ?
+ (fields[i].name[0] ? fields[i].name :
+ " &nbsp; ") : "NULL"));
+ </row>\n" </resultset>\n*/
+}
+
+gptr db_load_functions()
+{
+ char *functions[]={
+ "database",".tables","SHOW TABLES","0",
+ "table",".status","SHOW TABLE STATUS FROM $table","0",
+ "table",".count","SELECT COUNT(*) FROM $table","0",
+ "table",".table","SELECT * FROM $table","0",
+ "table",".check","CHECK TABLE $table","0",
+ "table",".repair","REPAIR TABLE $table","0",
+ "key",".min","SELECT MIN($key) FROM $table","0",
+ "key",".max","SELECT MAX($key) FROM $table","0",
+ "key",".avg","SELECT AVG($key) FROM $table","0",
+ "server",".uptime","SHOW STATUS like 'Uptime'","0",
+ "server",".version","SELECT VERSION()","0",
+ "server",".execute","$*","1",
+ "root",".connect","CONNECT $*","0",
+ NULL,NULL,NULL,NULL
+ };
+ char buff[BUFLEN];
+ int i=0;
+ struct func_st func;
+ DBUG_ENTER("db_load_functions");
+ init_dynamic_array(&functions_array, sizeof(struct func_st), 4096, 1024);
+ while(functions[i]) {
+ strcpy(func.type_s, functions[i]); /* Type in string: "table"` */
+ strcpy(func.filename, functions[i+1]); /* Name like it appears on FS: "count" */
+ strcpy(func.function, functions[i+2]); /* Query: "SELECT COUNT(*) FROM `%table`" */
+ func.continuous= atoi(functions[i+3]); /* Query: "If command can be continued" */
+
+ if(!strcasecmp(func.type_s,"server"))
+ func.type=SERVER_FUNCTION;
+ else if(!strcasecmp(func.type_s,"table"))
+ func.type=TABLE_FUNCTION;
+ else if(!strcasecmp(func.type_s,"key"))
+ func.type=KEY_FUNCTION;
+ else if(!strcasecmp(func.type_s,"database"))
+ func.type=DATABASE_FUNCTION;
+ else if(!strcasecmp(func.type_s,"field"))
+ func.type=FIELD_FUNCTION;
+ else if(!strcasecmp(func.type_s,"root"))
+ func.type=ROOT_FUNCTION;
+ else func.type=NONE_FUNCTION;
+
+ func.length=strlen(func.filename); /* Filename length */
+ DBUG_PRINT("info",("func.type_s: %s",func.type_s));
+ DBUG_PRINT("info",("func.filename: %s",func.filename));
+ DBUG_PRINT("info",("func.function: %s",func.function));
+ DBUG_PRINT("info",("func.type: %d",func.type));
+ DBUG_PRINT("info",("func.continuous: %d",func.continuous));
+ DBUG_PRINT("info",("i: %d",i));
+ insert_dynamic(&functions_array,(gptr)&func);
+ i+=4;
+ }
+ DBUG_RETURN((gptr)&functions_array);
+}
diff --git a/fs/dump.sql b/fs/dump.sql
new file mode 100644
index 00000000000..c61669cecb5
--- /dev/null
+++ b/fs/dump.sql
@@ -0,0 +1,28 @@
+# MySQL dump 8.12
+#
+# Host: localhost Database: mysqlfs
+#--------------------------------------------------------
+# Server version 3.23.33
+
+#
+# Table structure for table 'functions'
+#
+
+CREATE TABLE functions (
+ type enum('server','database','table','field','key') NOT NULL default 'server',
+ name char(20) NOT NULL default '',
+ sql char(128) NOT NULL default '',
+ PRIMARY KEY (type,name)
+) TYPE=MyISAM;
+
+#
+# Dumping data for table 'functions'
+#
+
+INSERT INTO functions VALUES ('server','uptime','SHOW STATUS like \'Uptime\'');
+INSERT INTO functions VALUES ('server','version','SELECT VERSION()');
+INSERT INTO functions VALUES ('table','count','SELECT COUNT(*) FROM `%table`');
+INSERT INTO functions VALUES ('key','min','SELECT MIN(%key) FROM `%table`');
+INSERT INTO functions VALUES ('key','max','SELECT MAX(%key) FROM `%table`');
+INSERT INTO functions VALUES ('key','avg','SELECT AVG(%key) FROM `%table`');
+
diff --git a/fs/korbit-kernel-2.4.1-patch b/fs/korbit-kernel-2.4.1-patch
new file mode 100644
index 00000000000..d97b1dac344
--- /dev/null
+++ b/fs/korbit-kernel-2.4.1-patch
@@ -0,0 +1,35661 @@
+diff -urN linux-2.4.1/.cvsignore linux-2.4.1-korbit/.cvsignore
+--- linux-2.4.1/.cvsignore Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/.cvsignore Thu Feb 1 11:46:48 2001
+@@ -0,0 +1 @@
++makekorbit.sh
+diff -urN linux-2.4.1/KORBit.Announce linux-2.4.1-korbit/KORBit.Announce
+--- linux-2.4.1/KORBit.Announce Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/KORBit.Announce Thu Feb 1 11:46:48 2001
+@@ -0,0 +1,62 @@
++From sabre@nondot.org Fri Dec 8 15:15:43 2000
++Date: Fri, 8 Dec 2000 17:10:47 -0600 (CST)
++From: Chris Lattner <sabre@nondot.org>
++To: linux-kernel@vger.kernel.org, orbit-list@gnome.org
++Cc: korbit-cvs@lists.sourceforge.net
++Subject: ANNOUNCE: Linux Kernel ORB: kORBit
++
++
++This email is here to announce the availability of a port of ORBit (the
++GNOME ORB) to the Linux kernel. This ORB, named kORBit, is available from
++our sourceforge web site (http://korbit.sourceforge.net/). A kernel ORB
++allows you to write kernel extensions in CORBA and have the kernel call
++into them, or to call into the kernel through CORBA. This opens the door
++to a wide range of experiments/hacks:
++
++* We can now write device drivers in perl, and let them run on the iMAC
++ across the hall from you. :)
++* Through the use of a LD_PRELOAD'd syscall wrapper library, you can
++ forward system calls through CORBA to an arbitrary local/remote machine.
++* CORBA servers are implemented as Linux kernel modules, so they may be
++ dynamically loaded or unloaded from a running system at any time. CORBA
++ servers expose their IOR's through a /proc/corba filesystem.
++* Filesystems may be implemented as remote CORBA objects and mounted on
++ the local machine, by using 'mount -t corbafs -o IOR:... none /mnt/corba'
++
++This are just some of the features available _RIGHT_NOW_ that are
++supported by kORBit. I'm sure that YOU can think of many more.
++
++Implementation:
++We implemented this port by providing a user->kernel mapping layer that
++consists of providing standard system header files for the "user" code to
++#include. In these header files, we do the mapping required. For
++example, we implement a <stdio.h> that #defines printf to printk (as a
++trivial example). Only user level code sees or uses these wrappers... all
++of our modifications to the Linux kernel are contained within the
++linux/net/korbit subdirectory.
++
++This is currently implemented with a 2.4.0test10 kernel, although forward
++porting should be very easy. This project was implemented as a cs423
++semester project by Chris Lattner, Fredrik Vraalsen, Andy Reitz, and Keith
++Wessel at the University of Illinois @ Urbana Champaign.
++
++Unresolved issues:
++* Our poll model is not optimial. Currently we actually do a real poll on
++ a (struct socket *) set. This causes relatively high latencies (on the
++ order 1 second, worst case) for CORBA requests. Our waitqueues are not
++ working quite as well as they should. :)
++* Security is completely unimplemented. Someone could use corba
++ interfaces to read any file on your system, for example (if the
++ CORBA-FileServer module is installed). Thus, this is really more for
++ prototyping and development than actual real world use. :)
++
++If you have any questions or comments, please feel free to contact us at:
++
++Chris Lattner, Fredrik Vraalsen, Andy Reitz, Keith Wessel
++<korbit-cvs@lists.sourceforge.net>
++
++btw, yes we are quite crazy, but what good is it to be normal and
++conformist afterall? :)
++
++
++
+diff -urN linux-2.4.1/Makefile linux-2.4.1-korbit/Makefile
+--- linux-2.4.1/Makefile Tue Jan 30 09:19:26 2001
++++ linux-2.4.1-korbit/Makefile Thu Feb 1 15:48:45 2001
+@@ -70,7 +70,7 @@
+ # images. Uncomment if you want to place them anywhere other than root.
+ #
+
+-#export INSTALL_PATH=/boot
++export INSTALL_PATH=/boot
+
+ #
+ # INSTALL_MOD_PATH specifies a prefix to MODLIB for module directory
+diff -urN linux-2.4.1/README.korbit linux-2.4.1-korbit/README.korbit
+--- linux-2.4.1/README.korbit Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/README.korbit Thu Feb 1 11:46:48 2001
+@@ -0,0 +1,83 @@
++ ====================
++ KORBit: A CORBA ORB
++ For The Linux Kernel
++ ====================
++
++ Submitted as a final project in CS423 by
++ Chris Lattner <lattner@uiuc.edu>,
++ Andy Reitz <areitz@uiuc.edu>,
++ Fredrik Vraalsen <vraalsen@uiuc.edu>, and
++ Keith Wessel <kwessel@uiuc.edu>
++
++ December 8, 2000
++
++
++About:
++======
++KORBit is a port of the CORBA Object Request Broker ORBit to the Linux
++kernel. For more information, see http://korbit.sourceforge.net/
++
++In order to use this code, you need to have ORBit-0.5.3 or later
++installed (including the development environment). The KORBit server
++modules make use of the ORBit IDL Compiler during the build process.
++
++Building The Code:
++==================
++In order to compile and run KORBit you need a recent 2.4.0-test
++version of the Linux kernel (KORBit is developed on 2.4.0-test10).
++
++To obtain a copy of the KORBit source code, see the webpage above.
++Once you have untar'ed the source code, copy the contents of the linux
++subdirectory of KORBit into the Linux root source directory
++(e.g. /usr/src/linux).
++
++Run your favourite configuration option for Linux (e.g. 'make
++menuconfig'). To enable KORBit support in the kernel, go into the
++'Networking options' section of the configuration and enable 'Kernel
++ORB'. Then add the various CORBA services that you wish to run in the
++kernel.
++
++NOTE: The Kernel ORB *must* be compiled statically into the kernel
++(answer 'Y') and CORBA services *must* be compiled as modules (answer
++'M') at the moment.
++
++Then compile and install the Linux kernel in the standard way, e.g.:
++
++make dep ; make clean ; make bzImage ; make modules ; make modules_install
++
++Copy System.map and arch/<i386|whatever>/boot/bzImage to the proper
++places (/boot), edit your lilo.conf, run lilo and reboot.
++
++You should now be able to use CORBA in your Linux kernel! Remember,
++this is *pre-alpha* software! Use on your own risk! Don't come to us
++crying if your machine blows up...
++
++Using Our Example KORBit Objects:
++=================================
++The "CORBA Echo Server" is effectively our "hello world" object. Once
++loaded into the kernel, module will instantiate an object that
++implements the "echoString()" interface. This method allows the client
++to send a string, which will be printed on the system console. Then,
++it will return a random number, which the client will print. Thus,
++after running this test, you will verify that two-way communication is
++working between KORBit and your ORB of choice.
++
++To insert this module into your newly-compiled kernel, type
++
++insmod /lib/modules/2.4.0-test10/kernel/net/korbit/modules/Echo/server/corba-echo-server.o
++
++Next verify that this module is actually loaded, by invoking
++"lsmod". You should see something like this:
++
++ Module Size Used by
++ corba-echo-server 3344 0 (unused)
++
++Now, you can grab the IOR to this object by typing "cat
++/proc/corba/echo-server". Now, you need to build the echo client,
++which will use this IOR in order to connect to the echo server. This
++can be accomplished by simply changing to the
++"/usr/src/linux/net/korbit/modules/Echo/client" directory, and then
++typing "make". Once finished, simply type "./echo-client `cat
++/proc/corba/echo-server`", and then cross your fingers!
++
++
+diff -urN linux-2.4.1/Rules.make linux-2.4.1-korbit/Rules.make
+--- linux-2.4.1/Rules.make Sat Dec 30 00:07:19 2000
++++ linux-2.4.1-korbit/Rules.make Thu Feb 1 15:46:07 2001
+@@ -222,9 +222,9 @@
+
+ $(MODINCL)/%.ver: %.c
+ @if [ ! -r $(MODINCL)/$*.stamp -o $(MODINCL)/$*.stamp -ot $< ]; then \
+- echo '$(CC) $(CFLAGS) -E -D__GENKSYMS__ $<'; \
++ echo '$(CC) $(CFLAGS) $(EXTRA_CFLAGS) -E -D__GENKSYMS__ $<'; \
+ echo '| $(GENKSYMS) $(genksyms_smp_prefix) -k $(VERSION).$(PATCHLEVEL).$(SUBLEVEL) > $@.tmp'; \
+- $(CC) $(CFLAGS) -E -D__GENKSYMS__ $< \
++ $(CC) $(CFLAGS) $(EXTRA_CFLAGS) -E -D__GENKSYMS__ $< \
+ | $(GENKSYMS) $(genksyms_smp_prefix) -k $(VERSION).$(PATCHLEVEL).$(SUBLEVEL) > $@.tmp; \
+ if [ -r $@ ] && cmp -s $@ $@.tmp; then echo $@ is unchanged; rm -f $@.tmp; \
+ else echo mv $@.tmp $@; mv -f $@.tmp $@; fi; \
+diff -urN linux-2.4.1/korbit.patch linux-2.4.1-korbit/korbit.patch
+--- linux-2.4.1/korbit.patch Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/korbit.patch Thu Feb 1 11:46:48 2001
+@@ -0,0 +1,43 @@
++--- linux/Rules.make.orig Wed Jan 31 22:50:40 2001
+++++ linux/Rules.make Thu Feb 1 01:39:46 2001
++@@ -222,9 +222,9 @@
++
++ $(MODINCL)/%.ver: %.c
++ @if [ ! -r $(MODINCL)/$*.stamp -o $(MODINCL)/$*.stamp -ot $< ]; then \
++- echo '$(CC) $(CFLAGS) -E -D__GENKSYMS__ $<'; \
+++ echo '$(CC) $(CFLAGS) $(EXTRA_CFLAGS) -E -D__GENKSYMS__ $<'; \
++ echo '| $(GENKSYMS) $(genksyms_smp_prefix) -k $(VERSION).$(PATCHLEVEL).$(SUBLEVEL) > $@.tmp'; \
++- $(CC) $(CFLAGS) -E -D__GENKSYMS__ $< \
+++ $(CC) $(CFLAGS) $(EXTRA_CFLAGS) -E -D__GENKSYMS__ $< \
++ | $(GENKSYMS) $(genksyms_smp_prefix) -k $(VERSION).$(PATCHLEVEL).$(SUBLEVEL) > $@.tmp; \
++ if [ -r $@ ] && cmp -s $@ $@.tmp; then echo $@ is unchanged; rm -f $@.tmp; \
++ else echo mv $@.tmp $@; mv -f $@.tmp $@; fi; \
++--- linux/net/Config.in.orig Wed Jan 31 22:39:32 2001
+++++ linux/net/Config.in Thu Feb 1 01:40:02 2001
++@@ -30,6 +30,7 @@
++ fi
++ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
++ source net/khttpd/Config.in
+++ source net/korbit/Config.in
++ fi
++ fi
++ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
++--- linux/net/Makefile.orig Thu Feb 1 01:41:42 2001
+++++ linux/net/Makefile Thu Feb 1 01:41:35 2001
++@@ -7,7 +7,7 @@
++
++ O_TARGET := network.o
++
++-mod-subdirs := ipv4/netfilter ipv6/netfilter ipx irda atm netlink sched
+++mod-subdirs := ipv4/netfilter ipv6/netfilter ipx irda atm netlink sched korbit
++ export-objs := netsyms.o
++
++ subdir-y := core ethernet
++@@ -27,6 +27,7 @@
++ endif
++
++ subdir-$(CONFIG_KHTTPD) += khttpd
+++subdir-$(CONFIG_KORBIT) += korbit
++ subdir-$(CONFIG_NETLINK) += netlink
++ subdir-$(CONFIG_PACKET) += packet
++ subdir-$(CONFIG_NET_SCHED) += sched
+diff -urN linux-2.4.1/makekorbit.sh linux-2.4.1-korbit/makekorbit.sh
+--- linux-2.4.1/makekorbit.sh Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/makekorbit.sh Thu Feb 1 11:46:48 2001
+@@ -0,0 +1,4 @@
++#!/bin/sh
++
++make CFLAGS="-D__KERNEL__ -I`pwd`/include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -fno-strict-aliasing -pipe -march=k6 -DHAVE_CONFIG_H -DHAVE_UNISTD_H -I. -I.. -I../include -nostdinc" -C net/korbit TOPDIR=`pwd`
++
+diff -urN linux-2.4.1/net/CVS/Entries linux-2.4.1-korbit/net/CVS/Entries
+--- linux-2.4.1/net/CVS/Entries Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/CVS/Entries Thu Feb 1 11:46:49 2001
+@@ -0,0 +1 @@
++D
+diff -urN linux-2.4.1/net/CVS/Entries.Log linux-2.4.1-korbit/net/CVS/Entries.Log
+--- linux-2.4.1/net/CVS/Entries.Log Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/CVS/Entries.Log Thu Feb 1 11:46:49 2001
+@@ -0,0 +1 @@
++A D/korbit////
+diff -urN linux-2.4.1/net/CVS/Repository linux-2.4.1-korbit/net/CVS/Repository
+--- linux-2.4.1/net/CVS/Repository Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/CVS/Repository Thu Feb 1 11:46:49 2001
+@@ -0,0 +1 @@
++/cvsroot/korbit/linux/net
+diff -urN linux-2.4.1/net/CVS/Root linux-2.4.1-korbit/net/CVS/Root
+--- linux-2.4.1/net/CVS/Root Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/CVS/Root Thu Feb 1 11:46:49 2001
+@@ -0,0 +1 @@
++vraalsen@cvs.korbit.sourceforge.net:/cvsroot/korbit
+diff -urN linux-2.4.1/net/Config.in linux-2.4.1-korbit/net/Config.in
+--- linux-2.4.1/net/Config.in Tue Oct 10 19:33:52 2000
++++ linux-2.4.1-korbit/net/Config.in Thu Feb 1 15:46:07 2001
+@@ -30,6 +30,7 @@
+ fi
+ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+ source net/khttpd/Config.in
++ source net/korbit/Config.in
+ fi
+ fi
+ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+diff -urN linux-2.4.1/net/Makefile linux-2.4.1-korbit/net/Makefile
+--- linux-2.4.1/net/Makefile Sat Dec 30 00:07:24 2000
++++ linux-2.4.1-korbit/net/Makefile Thu Feb 1 15:46:07 2001
+@@ -7,7 +7,7 @@
+
+ O_TARGET := network.o
+
+-mod-subdirs := ipv4/netfilter ipv6/netfilter ipx irda atm netlink sched
++mod-subdirs := ipv4/netfilter ipv6/netfilter ipx irda atm netlink sched korbit
+ export-objs := netsyms.o
+
+ subdir-y := core ethernet
+@@ -27,6 +27,7 @@
+ endif
+
+ subdir-$(CONFIG_KHTTPD) += khttpd
++subdir-$(CONFIG_KORBIT) += korbit
+ subdir-$(CONFIG_NETLINK) += netlink
+ subdir-$(CONFIG_PACKET) += packet
+ subdir-$(CONFIG_NET_SCHED) += sched
+diff -urN linux-2.4.1/net/korbit/CVS/Entries linux-2.4.1-korbit/net/korbit/CVS/Entries
+--- linux-2.4.1/net/korbit/CVS/Entries Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/CVS/Entries Thu Feb 1 11:46:49 2001
+@@ -0,0 +1,6 @@
++/Config.in/1.3/Thu Feb 1 09:46:49 2001//
++/Makefile/1.7/Thu Feb 1 09:46:49 2001//
++/config.h/1.2/Thu Feb 1 09:46:49 2001//
++/exported_symbols.c/1.8/Thu Feb 1 09:46:49 2001//
++/korbit.h/1.2/Thu Feb 1 09:46:49 2001//
++D
+diff -urN linux-2.4.1/net/korbit/CVS/Entries.Log linux-2.4.1-korbit/net/korbit/CVS/Entries.Log
+--- linux-2.4.1/net/korbit/CVS/Entries.Log Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/CVS/Entries.Log Thu Feb 1 11:47:15 2001
+@@ -0,0 +1,7 @@
++A D/IIOP////
++A D/ORBitutil////
++A D/include////
++A D/kglib////
++A D/modules////
++A D/orb////
++A D/sup////
+diff -urN linux-2.4.1/net/korbit/CVS/Repository linux-2.4.1-korbit/net/korbit/CVS/Repository
+--- linux-2.4.1/net/korbit/CVS/Repository Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/CVS/Repository Thu Feb 1 11:46:49 2001
+@@ -0,0 +1 @@
++/cvsroot/korbit/linux/net/korbit
+diff -urN linux-2.4.1/net/korbit/CVS/Root linux-2.4.1-korbit/net/korbit/CVS/Root
+--- linux-2.4.1/net/korbit/CVS/Root Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/CVS/Root Thu Feb 1 11:46:49 2001
+@@ -0,0 +1 @@
++vraalsen@cvs.korbit.sourceforge.net:/cvsroot/korbit
+diff -urN linux-2.4.1/net/korbit/Config.in linux-2.4.1-korbit/net/korbit/Config.in
+--- linux-2.4.1/net/korbit/Config.in Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/Config.in Thu Feb 1 11:46:49 2001
+@@ -0,0 +1,8 @@
++#
++# KORBit
++#
++
++#tristate ' Kernel ORB (EXPERIMENTAL)' CONFIG_KORBIT
++bool ' Kernel ORB (EXPERIMENTAL)' CONFIG_KORBIT
++
++source net/korbit/modules/Config.in
+diff -urN linux-2.4.1/net/korbit/IIOP/CVS/Entries linux-2.4.1-korbit/net/korbit/IIOP/CVS/Entries
+--- linux-2.4.1/net/korbit/IIOP/CVS/Entries Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/IIOP/CVS/Entries Thu Feb 1 11:46:51 2001
+@@ -0,0 +1,15 @@
++/IIOP-config.h/1.1.1.1/Thu Feb 1 09:46:50 2001//
++/IIOP-design.txt/1.1.1.1/Thu Feb 1 09:46:50 2001//
++/IIOP-private.h/1.2/Thu Feb 1 09:46:50 2001//
++/IIOP-types.h/1.1.1.1/Thu Feb 1 09:46:50 2001//
++/IIOP.h/1.1.1.1/Thu Feb 1 09:46:50 2001//
++/Makefile/1.4/Thu Feb 1 09:46:51 2001//
++/connection.c/1.19/Thu Feb 1 09:46:51 2001//
++/encoders.c/1.1.1.1/Thu Feb 1 09:46:51 2001//
++/giop-msg-buffer.c/1.12/Thu Feb 1 09:46:51 2001//
++/giop-msg-buffer.h/1.1.1.1/Thu Feb 1 09:46:51 2001//
++/iiop-encoders.h/1.1.1.1/Thu Feb 1 09:46:51 2001//
++/iiop-endian.c/1.1.1.1/Thu Feb 1 09:46:51 2001//
++/iiop-endian.h/1.1.1.1/Thu Feb 1 09:46:51 2001//
++/iiop-endianP.h/1.1.1.1/Thu Feb 1 09:46:51 2001//
++D
+diff -urN linux-2.4.1/net/korbit/IIOP/CVS/Repository linux-2.4.1-korbit/net/korbit/IIOP/CVS/Repository
+--- linux-2.4.1/net/korbit/IIOP/CVS/Repository Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/IIOP/CVS/Repository Thu Feb 1 11:46:50 2001
+@@ -0,0 +1 @@
++/cvsroot/korbit/linux/net/korbit/IIOP
+diff -urN linux-2.4.1/net/korbit/IIOP/CVS/Root linux-2.4.1-korbit/net/korbit/IIOP/CVS/Root
+--- linux-2.4.1/net/korbit/IIOP/CVS/Root Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/IIOP/CVS/Root Thu Feb 1 11:46:49 2001
+@@ -0,0 +1 @@
++vraalsen@cvs.korbit.sourceforge.net:/cvsroot/korbit
+diff -urN linux-2.4.1/net/korbit/IIOP/IIOP-config.h linux-2.4.1-korbit/net/korbit/IIOP/IIOP-config.h
+--- linux-2.4.1/net/korbit/IIOP/IIOP-config.h Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/IIOP/IIOP-config.h Thu Feb 1 11:46:50 2001
+@@ -0,0 +1,5 @@
++/* The size of the chunks that are used for indirect pieces of messages.
++ Too low, and you'll have a lot of malloc overhead. Too high, and you'll
++ get wasted mem.
++*/
++#define GIOP_INDIRECT_CHUNK_SIZE 1024
+diff -urN linux-2.4.1/net/korbit/IIOP/IIOP-design.txt linux-2.4.1-korbit/net/korbit/IIOP/IIOP-design.txt
+--- linux-2.4.1/net/korbit/IIOP/IIOP-design.txt Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/IIOP/IIOP-design.txt Thu Feb 1 11:46:50 2001
+@@ -0,0 +1,14 @@
++
++void Hello_hello(CORBA_Object anobj, const char *arg1, CORBA_Environment *ev)
++
++If we're doing a local call (i.e. shared library object activation),
++just do it.
++
++If we're doing a remote call, we need to setup generic header
++(utilfunc), setup request header (utilfunc), encode arguments (stubs),
++send the message headers & body (utilfunc) and wait for a reply (XXX
++define more clearly). When we get the reply, we need to read the
++reply(utilfunc), decode the return value & out/inout arguments(stubs)
++& fill them in (or decode the exception that resulted (utilfunc)), and
++return.
++
+diff -urN linux-2.4.1/net/korbit/IIOP/IIOP-private.h linux-2.4.1-korbit/net/korbit/IIOP/IIOP-private.h
+--- linux-2.4.1/net/korbit/IIOP/IIOP-private.h Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/IIOP/IIOP-private.h Thu Feb 1 11:46:50 2001
+@@ -0,0 +1,46 @@
++#ifndef IIOP_PRIVATE_H
++#define IIOP_PRIVATE_H 1
++
++
++#include "config.h"
++
++#if defined(HAVE_POLL) && defined(I_WANT_POLL)
++#define USE_POLL
++#else
++#undef USE_POLL
++#endif
++
++#ifdef HAVE_SYS_POLL_H
++#include <sys/poll.h>
++#endif
++
++#include <sys/time.h>
++#include <sys/types.h>
++#include <unistd.h>
++
++#include <glib.h>
++
++typedef struct {
++ GList *list;
++ gboolean connection_list_changed;
++#ifndef __KORBIT__
++ GPtrArray *fd_to_connection_mapping;
++#else /* __KORBIT__ */
++ GHashTable *fd_to_connection_mapping;
++#endif /* __KORBIT__ */
++# ifdef USE_POLL
++ GArray *pollset;
++# else
++ fd_set selectset_rd, selectset_ex;
++# endif
++ int max_fd;
++} GIOPConnectionList;
++
++extern GIOPConnectionList giop_connection_list;
++
++/* If you get a buffer that you didn't want, add it to the list! */
++void giop_received_list_push(GIOPRecvBuffer *recv_buffer);
++GIOPRecvBuffer *giop_received_list_pop(void);
++
++
++#endif
+diff -urN linux-2.4.1/net/korbit/IIOP/IIOP-types.h linux-2.4.1-korbit/net/korbit/IIOP/IIOP-types.h
+--- linux-2.4.1/net/korbit/IIOP/IIOP-types.h Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/IIOP/IIOP-types.h Thu Feb 1 11:46:50 2001
+@@ -0,0 +1,76 @@
++#ifndef IIOP_TYPES_H
++#define IIOP_TYPES_H 1
++
++/* XXX todo sync this up with basic_types.h if needed */
++#include <unistd.h>
++#include <netinet/in.h>
++#include <sys/un.h>
++
++#include <ORBitutil/basic_types.h>
++
++typedef enum {
++ GIOP_CONNECTION_SERVER, /* Not a real connection to any place - just
++ listening */
++ GIOP_CONNECTION_CLIENT
++} GIOPConnectionClass;
++
++typedef struct _GIOPConnection GIOPConnection;
++struct _GIOPConnection {
++ enum { GIOP_CONNECTION_NONE, GIOP_CONNECTION_IIOP } connection_type;
++ void (*destroy_func)(GIOPConnection *connection);
++
++ gint refcount;
++ GIOPConnectionClass connection_class;
++
++ int fd;
++
++ /* You can access these if you wish. */
++ gpointer orb_data;
++ gpointer user_data;
++ /* end accessable stuff */
++
++ guchar is_valid, was_initiated, is_auth;
++
++ gpointer incoming_msg; /* GIOPRecvBuffer */
++};
++
++#define GIOP_CONNECTION(x) ((GIOPConnection *)(x))
++#define GIOP_CONNECTION_GET_FD(x) (GIOP_CONNECTION((x))->fd)
++
++typedef enum { IIOP_IPV4, IIOP_IPV6, IIOP_USOCK } IIOPConnectionType;
++
++typedef struct {
++ GIOPConnection giop_connection;
++
++ gboolean is_serversock;
++ IIOPConnectionType icnxtype;
++ union {
++ struct {
++ char *hostname;
++ struct sockaddr_in location;
++ } ipv4;
++ struct sockaddr_un usock;
++ /* Yes this is a config.h define, and no it doesn't matter,
++ because this structure should only be used internally anyways */
++#ifdef HAVE_IPV6
++ struct {
++ char *hostname;
++ struct sockaddr_in6 location;
++ } ipv6;
++#endif
++ } u;
++} IIOPConnection;
++
++#define IIOP_CONNECTION(x) ((IIOPConnection *)(x))
++
++#if defined(DEBUG_sopwith_connection_refcounting)
++#define giop_connection_ref(x) G_STMT_START{ (GIOP_CONNECTION(x)->refcount++); g_print("! reffing fd %d in " __PRETTY_FUNCTION__ ":%d to %d\n", GIOP_CONNECTION_GET_FD(x), __LINE__, GIOP_CONNECTION(x)->refcount); }G_STMT_END
++
++#define giop_connection_unref(x) G_STMT_START{ GIOP_CONNECTION(x)->refcount--; g_print("! dereffing fd %d in " __PRETTY_FUNCTION__ ":%d to %d\n", GIOP_CONNECTION_GET_FD(x), __LINE__, GIOP_CONNECTION(x)->refcount); if(GIOP_CONNECTION(x)->refcount <= 0) giop_connection_free(x); }G_STMT_END
++#else
++#define giop_connection_ref(x) G_STMT_START{ (GIOP_CONNECTION(x)->refcount++); }G_STMT_END
++
++#define giop_connection_unref(x) G_STMT_START{ GIOP_CONNECTION(x)->refcount--; if(GIOP_CONNECTION(x)->refcount <= 0) giop_connection_free(x); }G_STMT_END
++#endif
++
++#endif /* IIOP_TYPES_H */
+diff -urN linux-2.4.1/net/korbit/IIOP/IIOP.h linux-2.4.1-korbit/net/korbit/IIOP/IIOP.h
+--- linux-2.4.1/net/korbit/IIOP/IIOP.h Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/IIOP/IIOP.h Thu Feb 1 16:19:47 2001
+@@ -0,0 +1,52 @@
++#ifndef IIOP_H
++#define IIOP_H 1
++
++#include <unistd.h>
++#include <ORBitutil/util.h>
++#include "IIOP-config.h"
++#include "IIOP-types.h"
++#include "giop-msg-buffer.h"
++#include "iiop-encoders.h"
++#include "iiop-endian.h"
++
++/* We don't speak GIOP 1.0, sosumi */
++#define GIOP_1_1
++
++
++void giop_init(const char *argv0);
++
++/* You use this to get a pointer to a new (or existing) connection
++ that has the specified host/port characteristics */
++IIOPConnection *iiop_connection_get(const char *host, gushort port,
++ gboolean existing_only);
++/* Similar, but for UNIX sockets */
++IIOPConnection *iiop_connection_unix_get(const char *sockpath,
++ gboolean existing_only);
++
++/* gives us a local socket that other people can connect to... */
++IIOPConnection *iiop_connection_server(void);
++IIOPConnection *iiop_connection_server_ipv6(void);
++IIOPConnection *iiop_connection_server_unix(const char *sockpath);
++
++void giop_main_quit(void);
++void giop_main(void); /* main loop for the program if none other is given,
++ and also used while waiting for a reply */
++void giop_main_iterate(gboolean blocking);
++void giop_main_handle_connection(GIOPConnection *connection);
++void giop_main_handle_connection_exception(GIOPConnection *connection);
++GIOPRecvBuffer *giop_main_next_message(gboolean blocking);
++GIOPRecvBuffer *giop_main_next_message_2(gboolean blocking,
++ GIOPConnection *monitor);
++GIOPConnection *giop_check_connections(gboolean block_for_reply);
++
++/* This assumes that the appropriate GIOP_CLOSECONNECTION message
++ has been sent to the peer */
++void giop_connection_free(GIOPConnection *connection);
++
++/* Called when a connection is created */
++extern void (*IIOPAddConnectionHandler)(GIOPConnection *newcnx);
++/* Called when a connection is about to be destroyed */
++extern void (*IIOPRemoveConnectionHandler)(GIOPConnection *oldcnx);
++extern void (*IIOPIncomingMessageHandler)(GIOPRecvBuffer *recv_buffer);
++
++#endif /* IIOP_H */
+diff -urN linux-2.4.1/net/korbit/IIOP/Makefile linux-2.4.1-korbit/net/korbit/IIOP/Makefile
+--- linux-2.4.1/net/korbit/IIOP/Makefile Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/IIOP/Makefile Thu Feb 1 11:46:51 2001
+@@ -0,0 +1,18 @@
++#
++# Makefile for KORBit/IIOP
++#
++# Note! Dependencies are done automagically by 'make dep', which also
++# removes any old dependencies. DON'T put your own dependencies here
++# unless it's something special (ie not a .o file).
++#
++# Note 2! The CFLAGS definition is now in the main makefile...
++
++O_TARGET := IIOPlib.o
++
++#obj-m := $(O_TARGET)
++obj-y := connection.o encoders.o giop-msg-buffer.o iiop-endian.o
++
++
++EXTRA_CFLAGS = -D__KORBIT__ -DHAVE_CONFIG_H -I. -I.. -I../include -I../kglib -I../ORBitutil -nostdinc
++
++include $(TOPDIR)/Rules.make
+diff -urN linux-2.4.1/net/korbit/IIOP/connection.c linux-2.4.1-korbit/net/korbit/IIOP/connection.c
+--- linux-2.4.1/net/korbit/IIOP/connection.c Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/IIOP/connection.c Thu Feb 1 19:26:07 2001
+@@ -0,0 +1,1565 @@
++#include "config.h"
++
++#if defined(HAVE_POLL) && defined(I_WANT_POLL)
++#define USE_POLL
++#else
++#undef USE_POLL
++#endif
++
++#ifndef _XOPEN_SOURCE_EXTENDED
++# define _XOPEN_SOURCE_EXTENDED 1
++# define WE_DEFINED_XOPEN_SOURCE_EXTENDED 1
++#endif
++#include "iiop-endianP.h"
++#ifdef WE_DEFINED_XOPEN_SOURCE_EXTENDED
++# undef _XOPEN_SOURCE_EXTENDED
++#endif
++#include "IIOP.h"
++#include "IIOP-private.h"
++#include "giop-msg-buffer.h"
++#include <stdlib.h>
++#include <unistd.h>
++#ifdef ORBIT_DEBUG
++#include <errno.h>
++#endif
++#include <sys/types.h>
++#include <fcntl.h>
++#include <sys/socket.h>
++#include <sys/un.h>
++#ifndef _XOPEN_SOURCE_EXTENDED
++# define _XOPEN_SOURCE_EXTENDED 1
++#endif
++#include <arpa/inet.h>
++#include <netdb.h>
++#ifdef WE_DEFINED_XOPEN_SOURCE_EXTENDED
++# undef _XOPEN_SOURCE_EXTENDED
++#endif
++#include <ctype.h>
++#include <string.h>
++#include <sys/time.h>
++#include <sys/ioctl.h>
++#include <signal.h>
++#include <syslog.h>
++#include <stdio.h>
++
++/*
++#ifdef O_NONBLOCK
++#undef O_NONBLOCK
++#endif
++#define O_NONBLOCK 0
++*/
++
++#if defined(HAVE_TCPD_H) && defined(HAVE_HOSTS_ACCESS)
++#include <tcpd.h>
++#endif
++
++#if 0
++#include <malloc.h>
++
++static struct mallinfo mi1, mi2;
++
++#define AM() mi1 = mallinfo();
++#define PM(x) mi2 = mallinfo(); printf(x ": used %d, now %d\n", \
++mi2.uordblks - mi1.uordblks, mi2.uordblks);
++#endif
++
++#ifdef HAVE_POLL
++#include <sys/poll.h>
++#endif
++
++#ifndef SUN_LEN
++/* This system is not POSIX.1g. */
++#define SUN_LEN(ptr) ((size_t) (((struct sockaddr_un *) 0)->sun_path) \
++ + strlen ((ptr)->sun_path))
++#endif
++
++void (*IIOPAddConnectionHandler)(GIOPConnection *newcnx) = NULL;
++void (*IIOPRemoveConnectionHandler)(GIOPConnection *oldcnx) = NULL;
++void (*IIOPIncomingMessageHandler)(GIOPRecvBuffer *recv_buffer) = NULL;
++
++static void giop_connection_add_to_list (GIOPConnection *cnx);
++static void giop_connection_remove_from_list (GIOPConnection *cnx);
++
++static void iiop_init (void);
++static void iiop_connection_server_accept (GIOPConnection *connection);
++static void iiop_connection_destroy (IIOPConnection *connection);
++static IIOPConnection *iiop_connection_new (const char *host, gushort port);
++static IIOPConnection *iiop_connection_unix_new (const char *sockpath);
++static void iiop_unlink_unix_sockets (void);
++
++DEFINE_LOCK(giop_connection_list);
++GIOPConnectionList giop_connection_list;
++static GSList *iiop_unix_socket_list = NULL;
++
++#if defined(HAVE_HOSTS_ACCESS) && defined (HAVE_TCPD_H)
++static const char *argv0_val = NULL;
++#endif
++
++struct fd_hash_elem
++{
++ guint fd;
++ GIOPConnection *cnx;
++};
++
++static guint fd_hash_func(gconstpointer key)
++{
++ const guint *key_ptr = (guint *)key;
++ guint result = *key_ptr >> 2;
++ return result;
++}
++
++static gint fd_compare_func(gconstpointer a, gconstpointer b)
++{
++ const guint *a_ptr = (guint *)a;
++ const guint *b_ptr = (guint *)b;
++ return *a_ptr == *b_ptr;
++}
++
++static gboolean fd_hash_clear(gpointer key, gpointer value, gpointer user_data)
++{
++ struct fd_hash_elem *el = (struct fd_hash_elem *)value;
++ g_free(el);
++ return TRUE;
++}
++
++/*
++ * giop_init
++ *
++ * Inputs: None
++ * Outputs: None
++ *
++ * Side effects: Initializes giop_connection_list
++ * Global data structures used: giop_connection_list
++ *
++ * Description: Initializes giop_connection_list. Calls
++ * giop_message_buffer_init() to initialize the
++ * message_buffer subsystem. Calls iiop_init()
++ * to perform IIOP-specific initialization.
++ */
++
++void giop_init(const char *argv0)
++{
++#ifndef __KERNEL__
++ struct sigaction mypipe;
++#endif
++ g_assert(sizeof(GIOPMessageHeader) == 12);
++
++#if defined(HAVE_HOSTS_ACCESS) && defined (HAVE_TCPD_H)
++ argv0_val = g_strdup(g_basename(argv0)); /* For TCP wrappers */
++#endif
++
++#ifndef __KERNEL__
++ memset(&mypipe, '\0', sizeof(mypipe));
++ mypipe.sa_handler = SIG_IGN;
++
++ sigaction(SIGPIPE, &mypipe, NULL);
++#endif
++
++ giop_message_buffer_init();
++
++ INIT_LOCK(giop_connection_list);
++
++ giop_connection_list.list = NULL;
++ giop_connection_list.connection_list_changed = FALSE;
++
++#ifdef USE_POLL
++ giop_connection_list.pollset = g_array_new(FALSE, FALSE,
++ sizeof(struct pollfd));
++#else
++ FD_ZERO(&giop_connection_list.selectset_rd);
++ FD_ZERO(&giop_connection_list.selectset_ex);
++#endif
++
++#ifndef __KORBIT__
++ giop_connection_list.fd_to_connection_mapping = g_ptr_array_new();
++#else
++ giop_connection_list.fd_to_connection_mapping =
++ g_hash_table_new(&fd_hash_func,
++ &fd_compare_func);
++#endif
++
++ /*
++ * This also needs to do any transport-specific initialization
++ * as appropriate
++ */
++ iiop_init();
++}
++
++/*** giop_connection_init
++ *
++ * Inputs: 'giop_connection' - memory region allocated for use as a
++ * GIOPConnection.
++ * 'cnxclass' - the class of connection that will be stored
++ * here (SERVER, CLIENT)
++ *
++ * Outputs: None
++ *
++ * Side effects: Initializes 'giop_connection'.
++ *
++ * Description: Basic setup of a GIOPConnection.
++ * Sets is_valid to FALSE because it is the responsibility of
++ * the transport-specific initialization routine to make
++ * a connection valid.
++ */
++
++static void giop_connection_init(GIOPConnection *giop_connection,
++ GIOPConnectionClass cnxclass)
++{
++ giop_connection->connection_type = GIOP_CONNECTION_NONE;
++ giop_connection->refcount = 0;
++ giop_connection->connection_class = cnxclass;
++ giop_connection->is_valid = FALSE;
++ giop_connection->is_auth = FALSE;
++ giop_connection->was_initiated = FALSE;
++}
++
++/*
++ * giop_connection_free
++ * Inputs: 'connection'
++ * Outputs: None
++ * Side effects: Makes the 'connection' invalid as a GIOPConnection
++ * and as a gpointer.
++ *
++ * Description: Calls giop_connection_remove_from_list() to
++ * stop the connection from being used for incoming.
++ *
++ * If a transport-specific finalization function has
++ * been provided, call it.
++ *
++ * Free the memory block at '*connection'.
++ *
++ */
++void giop_connection_free(GIOPConnection *connection)
++{
++ g_return_if_fail(connection != NULL);
++ giop_connection_remove_from_list(connection);
++
++ if(connection->is_valid && connection->destroy_func)
++ connection->destroy_func(connection);
++
++ connection->is_valid = FALSE;
++
++ if(connection->incoming_msg) {
++ GIOPRecvBuffer *buf;
++
++ buf = connection->incoming_msg;
++ connection->incoming_msg = NULL;
++ giop_recv_buffer_unuse(buf);
++ }
++
++ g_free(connection);
++}
++
++/*
++ * giop_connection_list_recreate
++ *
++ * Inputs: None
++ * Outputs: None
++ *
++ * Side effects: giop_connection_list changes.
++ *
++ * Global data structures used: giop_connection_list
++ *
++ * Description:
++ * When new connections are added to giop_connection_list.list,
++ * the data structures passed to poll() or select() (OS-dependant)
++ * must be recreated to match this list.
++ *
++ * [We do this at add-connection/remove-connection time
++ * instead of every time a poll/select is done in order to
++ * speed things up a little]
++ *
++ * This function reinitializes the OS-specific file
++ * descriptor data structure and then adds all the file
++ * descriptors in the list to it.
++ *
++ * It also regenerates the array that maps file descriptors
++ * into GIOPConnection*'s
++ *
++ */
++static void
++giop_connection_list_recreate(void)
++{
++ int curfd;
++ GList *item;
++ GIOPConnection *cnx;
++#ifdef USE_POLL
++ struct pollfd new_poll;
++
++ new_poll.revents = 0;
++#endif
++
++ giop_connection_list.max_fd = 0;
++ for(item = giop_connection_list.list; item; item = g_list_next(item))
++ {
++ cnx = item->data;
++ curfd = GIOP_CONNECTION_GET_FD(cnx);
++
++ if(curfd > giop_connection_list.max_fd)
++ giop_connection_list.max_fd = curfd;
++ }
++
++#ifndef __KORBIT__
++ g_ptr_array_set_size(giop_connection_list.fd_to_connection_mapping,
++ giop_connection_list.max_fd + 1);
++#else
++ g_hash_table_foreach_remove(giop_connection_list.fd_to_connection_mapping,
++ fd_hash_clear,
++ NULL);
++#endif
++
++#ifdef USE_POLL
++ g_array_set_size(giop_connection_list.pollset, 0);
++#else
++ FD_ZERO(&giop_connection_list.selectset_rd);
++ FD_ZERO(&giop_connection_list.selectset_ex);
++#endif
++
++ for(item = giop_connection_list.list; item; item = g_list_next(item))
++ {
++ struct fd_hash_elem *el;
++
++ cnx = item->data;
++ curfd = GIOP_CONNECTION_GET_FD(cnx);
++
++#ifndef __KORBIT__
++ giop_connection_list.fd_to_connection_mapping->pdata[curfd] = cnx;
++#else
++ el = g_new(struct fd_hash_elem, 1);
++ el->fd = curfd;
++ el->cnx = cnx;
++ g_hash_table_insert(giop_connection_list.fd_to_connection_mapping,
++ &(el->fd),
++ el);
++#endif
++
++# ifdef USE_POLL
++ new_poll.fd = curfd;
++ new_poll.events = POLLIN|POLLPRI;
++ g_array_append_val(giop_connection_list.pollset,
++ new_poll);
++# else
++ FD_SET(curfd, &giop_connection_list.selectset_rd);
++ FD_SET(curfd, &giop_connection_list.selectset_ex);
++# endif
++ }
++}
++
++/*
++ * giop_connection_add_to_list
++ *
++ * Inputs: 'cnx' - a GIOPConnection that the user wishes added to the list
++ * Outputs: None
++ *
++ * Side effects: Modifies giop_connection_list
++ * Global data structures used: giop_connection_list
++ * Bugs: Does not check for duplicate additions.
++ *
++ * Description:
++ * Adds a connection to the list of active connections.
++ */
++static void
++giop_connection_add_to_list(GIOPConnection *cnx)
++{
++ g_return_if_fail(cnx->is_valid == FALSE);
++
++ cnx->is_valid = TRUE;
++
++ GET_LOCK(giop_connection_list);
++ giop_connection_list.list = g_list_prepend(giop_connection_list.list, cnx);
++
++ giop_connection_list_recreate();
++
++ RELEASE_LOCK(giop_connection_list);
++
++ if(IIOPAddConnectionHandler)
++ IIOPAddConnectionHandler(cnx);
++
++ giop_connection_ref(cnx);
++}
++
++/*
++ * giop_connection_remove_from_list
++ *
++ * Inputs: 'cnx' - a GIOPConnection that the user wishes
++ * Outputs: None
++ *
++ * Side effects: Modifies giop_connection_list
++ * Global data structures used: giop_connection_list
++ *
++ * Description:
++ * Removes a connection from the list of active connections.
++ * Calls the library user's "I removed connection" handler if it
++ * exists.
++ *
++ * Bugs: Does not check for duplicate removals. This may not be "bad" though.
++ */
++void
++giop_connection_remove_from_list(GIOPConnection *cnx)
++{
++ GList *link;
++
++ GET_LOCK(giop_connection_list);
++
++ link = g_list_find(giop_connection_list.list, cnx);
++
++ if(!link)
++ goto out;
++
++ if(IIOPRemoveConnectionHandler && cnx->is_valid)
++ IIOPRemoveConnectionHandler(cnx);
++
++ giop_connection_list.list = g_list_remove_link(giop_connection_list.list,
++ link);
++ g_list_free_1(link);
++
++ giop_connection_unref(cnx);
++
++ giop_connection_list_recreate();
++ out:
++ RELEASE_LOCK(giop_connection_list);
++}
++
++/************************************************
++ * Routines specific to the IIOP/IPv4 transport *
++ ************************************************/
++
++/*
++ * iiop_init
++ *
++ * Inputs: None
++ * Outputs: None
++ *
++ * Side effects: Initializes iiop_unix_socket_list
++ * Global data structures used: iiop_unix_socket_list
++ *
++ * Description: Initializes iiop_unix_socket_list.
++ * Registers Unix domain sockets for
++ * removal at server termination.
++ */
++static void
++iiop_init(void)
++{
++#ifndef __KERNEL__
++ g_atexit(iiop_unlink_unix_sockets);
++#endif
++}
++
++/*
++ * iiop_connection_init
++ *
++ * Inputs: 'connection' - a memory region that needs to be initialized as
++ * an 'IIOPConnection'.
++ *
++ * Side effects: initializes 'connection'
++ *
++ * Description: Performs the IIOP-specific initialization of an
++ * IIOPConnection. giop_connection_init is called.
++ *
++ */
++void
++iiop_connection_init(IIOPConnection *connection,
++ GIOPConnectionClass cnxclass,
++ IIOPConnectionType iioptype)
++{
++ giop_connection_init(GIOP_CONNECTION(connection), cnxclass);
++
++ GIOP_CONNECTION(connection)->connection_type =
++ GIOP_CONNECTION_IIOP;
++
++ GIOP_CONNECTION(connection)->destroy_func =
++ (void (*)(GIOPConnection *))iiop_connection_destroy;
++
++ connection->icnxtype = iioptype;
++}
++
++/*
++ * iiop_connection_from_fd
++ *
++ * Inputs: 'fd' - a file descriptor that attention should be paid to
++ * Outputs: 'fd_cnx' - the created connection
++ *
++ * Description: This is intended to be used on a file descriptor
++ * that has been accept()'d. It creates the connection
++ * and fills in the connection information, then adds
++ * it to the active list.
++ */
++IIOPConnection *
++iiop_connection_from_fd(int fd, IIOPConnection *parent)
++{
++ IIOPConnection *fd_cnx;
++ struct hostent *hent;
++ socklen_t n;
++
++ g_assert(fd >= 0);
++
++ fd_cnx = g_new0(IIOPConnection, 1);
++
++ iiop_connection_init(fd_cnx, GIOP_CONNECTION_CLIENT, parent->icnxtype);
++
++ GIOP_CONNECTION(fd_cnx)->fd = fd;
++
++ switch(parent->icnxtype) {
++ case IIOP_IPV4:
++ n = sizeof(struct sockaddr_in);
++ if(getpeername(GIOP_CONNECTION_GET_FD(fd_cnx), (struct sockaddr *)&fd_cnx->u.ipv4.location, &n))
++ {
++ fd_cnx->u.ipv4.hostname = g_strdup("");
++ }
++ else
++ {
++ hent = gethostbyaddr((const char *)&fd_cnx->u.ipv4.location.sin_addr.s_addr, 4, AF_INET);
++ if(hent)
++ {
++ fd_cnx->u.ipv4.hostname = g_strdup(hent->h_name);
++ }
++ else
++ {
++ fd_cnx->u.ipv4.hostname = inet_ntoa(*((struct in_addr *)&fd_cnx->u.ipv4.location.sin_addr));
++ }
++ }
++ break;
++
++ case IIOP_USOCK:
++ n = sizeof(struct sockaddr_un);
++ fd_cnx->u.usock.sun_family = AF_UNIX;
++ getpeername(GIOP_CONNECTION_GET_FD(fd_cnx),
++ (struct sockaddr *)&fd_cnx->u.usock, &n);
++ break;
++
++#ifdef HAVE_IPV6
++ case IIOP_IPV6:
++ n = sizeof(struct sockaddr_in6);
++ getpeername(GIOP_CONNECTION_GET_FD(fd_cnx),
++ (struct sockaddr *)&fd_cnx->u.ipv6.location, &n);
++ hent = gethostbyaddr((const char *)&fd_cnx->u.ipv6.location.sin6_addr,
++ sizeof(fd_cnx->u.ipv6.location.sin6_addr), AF_INET6);
++ fd_cnx->u.ipv6.hostname = g_strdup(hent->h_name);
++ break;
++#endif
++
++ default:
++ g_error("Unsupported connection type %d", parent->icnxtype);
++ }
++
++ fcntl(GIOP_CONNECTION_GET_FD(fd_cnx), F_SETFD,
++ fcntl(GIOP_CONNECTION_GET_FD(fd_cnx), F_GETFD, 0)
++ | FD_CLOEXEC);
++ fcntl(GIOP_CONNECTION_GET_FD(fd_cnx), F_SETFL,
++ fcntl(GIOP_CONNECTION_GET_FD(fd_cnx), F_GETFL, 0)
++ | O_NONBLOCK);
++
++ ORBit_Trace(TraceMod_IIOP, TraceLevel_Debug,
++ "iiop_connection_from_fd connect [%d]\n",
++ GIOP_CONNECTION_GET_FD(fd_cnx));
++
++ giop_connection_add_to_list(GIOP_CONNECTION(fd_cnx));
++
++ return fd_cnx;
++}
++
++/*
++ * iiop_connection_server
++ *
++ * Outputs: 'server_cnx'
++ *
++ * Description: Creates a special IIOPConnection on which incoming
++ * connections come.
++ */
++IIOPConnection *
++iiop_connection_server(void)
++{
++ struct hostent *hent;
++ char hn_tmp[65];
++ socklen_t n;
++ IIOPConnection *server_cnx = g_new0(IIOPConnection, 1);
++
++ iiop_connection_init(server_cnx, GIOP_CONNECTION_SERVER, IIOP_IPV4);
++
++ server_cnx->is_serversock = TRUE;
++ GIOP_CONNECTION(server_cnx)->fd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
++
++ if(GIOP_CONNECTION_GET_FD(server_cnx) < 0) {
++ ORBit_Trace(TraceMod_IIOP, TraceLevel_Debug, "iiop_connection_server: socket_error: %s\n", strerror(errno));
++ goto failed;
++ }
++
++ server_cnx->u.ipv4.location.sin_family = AF_INET;
++ server_cnx->u.ipv4.location.sin_addr.s_addr = INADDR_ANY;
++ bind(GIOP_CONNECTION_GET_FD(server_cnx),
++ (struct sockaddr *)&server_cnx->u.ipv4.location,
++ sizeof(struct sockaddr_in));
++
++ fcntl(GIOP_CONNECTION_GET_FD(server_cnx), F_SETFD,
++ fcntl(GIOP_CONNECTION_GET_FD(server_cnx), F_GETFD, 0)
++ | FD_CLOEXEC);
++ fcntl(GIOP_CONNECTION_GET_FD(server_cnx), F_SETFL,
++ fcntl(GIOP_CONNECTION_GET_FD(server_cnx), F_GETFL, 0)
++ | O_NONBLOCK);
++
++ n = sizeof(struct sockaddr_in);
++ getsockname(GIOP_CONNECTION_GET_FD(server_cnx),
++ (struct sockaddr *)&server_cnx->u.ipv4.location, &n);
++
++ gethostname(hn_tmp, sizeof(hn_tmp) - 1);
++
++ hent = gethostbyname(hn_tmp);
++ if(hent)
++ {
++ if (strchr (hent->h_name, '.'))
++ server_cnx->u.ipv4.hostname = g_strdup(hent->h_name);
++ else
++ {
++ struct in_addr * addr = (struct in_addr *) hent->h_addr_list[0];
++ g_assert (hent->h_length == sizeof (struct in_addr) && addr);
++ server_cnx->u.ipv4.hostname = g_strdup (inet_ntoa (*addr));
++ }
++ }
++ else
++ server_cnx->u.ipv4.hostname = g_strdup(hn_tmp);
++
++ listen(GIOP_CONNECTION_GET_FD(server_cnx), 5);
++
++ giop_connection_add_to_list(GIOP_CONNECTION(server_cnx));
++
++ return server_cnx;
++
++failed:
++ close(GIOP_CONNECTION_GET_FD(server_cnx));
++ GIOP_CONNECTION(server_cnx)->fd = -1;
++ giop_connection_free(GIOP_CONNECTION(server_cnx));
++ server_cnx = NULL;
++ /*
++ * FIXME: GET_LOCK and DEFINE_LOCK never called for server_cnx
++ RELEASE_LOCK(server_cnx);
++ */
++ return NULL;
++}
++
++/*
++ * iiop_connection_server_ipv6
++ * Outputs: 'server_cnx'
++ *
++ * Description: Create a special IIOPConnection on which incoming
++ * connections come.
++ */
++IIOPConnection *
++iiop_connection_server_ipv6(void)
++{
++#ifdef HAVE_IPV6
++ struct hostent *hent, *hent2;
++
++ char hn_tmp[65];
++ int n;
++ IIOPConnection *server_cnx;
++
++ g_error("IPv6 support is baroquen! (Actually just never worked)");
++
++ server_cnx = g_new0(IIOPConnection, 1);
++
++ iiop_connection_init(server_cnx, GIOP_CONNECTION_SERVER, IIOP_IPV6);
++
++ server_cnx->is_serversock = TRUE;
++ GIOP_CONNECTION(server_cnx)->fd = socket(PF_INET6, SOCK_STREAM, IPPROTO_TCP);
++
++ if(GIOP_CONNECTION_GET_FD(server_cnx) < 0) {
++ ORBit_Trace(TraceMod_IIOP, TraceLevel_Debug, "iiop_connection_server_ipv6: socket_error: %s\n", strerror(errno));
++ goto failed;
++ }
++
++ server_cnx->u.ipv6.location.sin6_family = AF_INET6;
++ bind(GIOP_CONNECTION_GET_FD(server_cnx),
++ (struct sockaddr *)&server_cnx->u.ipv6.location,
++ sizeof(struct sockaddr_in6));
++
++ fcntl(GIOP_CONNECTION_GET_FD(server_cnx), F_SETFD,
++ fcntl(GIOP_CONNECTION_GET_FD(server_cnx), F_GETFD, 0)
++ | FD_CLOEXEC);
++ fcntl(GIOP_CONNECTION_GET_FD(server_cnx), F_SETFL,
++ fcntl(GIOP_CONNECTION_GET_FD(server_cnx), F_GETFL, 0)
++ | O_NONBLOCK);
++
++ n = sizeof(struct sockaddr_in6);
++ getsockname(GIOP_CONNECTION_GET_FD(server_cnx), &server_cnx->u.ipv6.location, &n);
++
++ gethostname(hn_tmp, sizeof(hn_tmp) - 1);
++
++ hent = gethostbyname(hn_tmp);
++ if(hent) {
++ hent2 = gethostbyaddr(hent->h_addr, sizeof(server_cnx->u.ipv6.location.sin6_addr), AF_INET6);
++ if(hent2)
++ server_cnx->hostname = g_strdup(hent2->h_name);
++ else
++ server_cnx->hostname = g_strdup(hn_tmp);
++ } else
++ server_cnx->hostname = g_strdup(hn_tmp);
++
++ listen(GIOP_CONNECTION_GET_FD(server_cnx), 5);
++
++ giop_connection_add_to_list(GIOP_CONNECTION(server_cnx));
++
++ return server_cnx;
++
++failed:
++ close(GIOP_CONNECTION_GET_FD(server_cnx));
++ GIOP_CONNECTION(server_cnx)->fd = -1;
++ giop_connection_free(GIOP_CONNECTION(server_cnx));
++ server_cnx = NULL;
++ /*
++ * FIXME: GET_LOCK and DEFINE_LOCK never called for server_cnx
++ RELEASE_LOCK(server_cnx);
++ */
++#endif
++ return NULL;
++}
++
++/*
++ * iiop_connection_server_unix
++ *
++ * Outputs: 'server_cnx_unix'
++ *
++ * Side effects: Initializes 'server_cnx_unix' if not initialized.
++ *
++ * Description: Return a special IIOPConnection on which incoming connections
++ * come. If not already initialized, it creates the connection,
++ * otherwise it returns the existing one.
++ * This is
++ */
++IIOPConnection *
++iiop_connection_server_unix(const char *sockpath)
++{
++ IIOPConnection *server_cnx_unix;
++
++ g_assert(sockpath && *sockpath);
++
++ server_cnx_unix = g_new0(IIOPConnection, 1);
++
++ iiop_connection_init(server_cnx_unix, GIOP_CONNECTION_SERVER, IIOP_USOCK);
++
++ server_cnx_unix->is_serversock = TRUE;
++ GIOP_CONNECTION(server_cnx_unix)->fd = socket(AF_UNIX, SOCK_STREAM, 0);
++
++ if(GIOP_CONNECTION_GET_FD(server_cnx_unix) < 0) {
++ ORBit_Trace(TraceMod_IIOP, TraceLevel_Debug, "iiop_connection_server_unix: socket_error: %s\n", strerror(errno));
++ goto failed;
++ }
++
++ strcpy(server_cnx_unix->u.usock.sun_path, sockpath);
++
++ server_cnx_unix->u.usock.sun_family = AF_UNIX;
++ if(bind(GIOP_CONNECTION_GET_FD(server_cnx_unix),
++ (struct sockaddr *)&server_cnx_unix->u.usock,
++ SUN_LEN(&server_cnx_unix->u.usock)) != 0) {
++ /* see the comment in iiop_connection_destroy switch as to why we
++ close it here. bad hack */
++ close(GIOP_CONNECTION_GET_FD(server_cnx_unix));
++ GIOP_CONNECTION(server_cnx_unix)->fd = -1;
++ goto failed;
++ }
++
++ fcntl(GIOP_CONNECTION_GET_FD(server_cnx_unix), F_SETFD,
++ fcntl(GIOP_CONNECTION_GET_FD(server_cnx_unix), F_GETFD, 0)
++ | FD_CLOEXEC);
++ fcntl(GIOP_CONNECTION_GET_FD(server_cnx_unix), F_SETFL,
++ fcntl(GIOP_CONNECTION_GET_FD(server_cnx_unix), F_GETFL, 0)
++ | O_NONBLOCK);
++
++ if(listen(GIOP_CONNECTION_GET_FD(server_cnx_unix), 5) != 0)
++ goto failed;
++
++ giop_connection_add_to_list(GIOP_CONNECTION(server_cnx_unix));
++ iiop_unix_socket_list = g_slist_prepend(iiop_unix_socket_list,
++ server_cnx_unix);
++
++ /*
++ * FIXME: GET_LOCK and DEFINE_LOCK never called for server_cnx_unix
++ RELEASE_LOCK(server_cnx_unix);
++ */
++
++ return server_cnx_unix;
++
++failed:
++ close(GIOP_CONNECTION_GET_FD(server_cnx_unix));
++ GIOP_CONNECTION(server_cnx_unix)->fd = -1;
++ giop_connection_free(GIOP_CONNECTION(server_cnx_unix));
++ server_cnx_unix = NULL;
++ /*
++ * FIXME: GET_LOCK and DEFINE_LOCK never called for server_cnx_unix
++ RELEASE_LOCK(server_cnx_unix);
++ */
++ return NULL;
++}
++
++/*
++ * iiop_unlink_unix_sockets(void)
++ *
++ * Inputs: None
++ * Outputs: None
++ *
++ * Side effects: Modifies iiop_unix_socket_list
++ * Global data structures used: iiop_unix_socket_list
++ *
++ * Description:
++ * Unlinks any Unix server sockets created.
++ * Called during program termination.
++ */
++static void
++iiop_unlink_unix_sockets(void)
++{
++ GSList *item;
++
++ for (item = iiop_unix_socket_list;
++ item; item = g_slist_next(item)) {
++ GIOPConnection *cnx;
++
++ cnx = GIOP_CONNECTION(item->data);
++ if(cnx->connection_class == GIOP_CONNECTION_SERVER)
++ unlink(IIOP_CONNECTION(cnx)->u.usock.sun_path);
++ }
++
++ if (iiop_unix_socket_list) {
++ g_slist_free(iiop_unix_socket_list);
++ iiop_unix_socket_list = NULL;
++ }
++}
++
++/*
++ * iiop_connection_get
++ *
++ * Inputs: 'host' - the hostname (or dotted quad) of the remote host that
++ * will be connected
++ * 'port' - the port number on the above host to connect to.
++ * 'existing_only' - don't create a new connection if
++ * an existing one with the specified host:port
++ * doesn't exist.
++ *
++ * Outputs: 'cnx' - the connection to the specified host:port, or
++ * NULL upon error.
++ *
++ * Description: Returns an IIOPConnection that is connected to the
++ * specified host:port. If a connection already exists to the
++ * host:port, just returns it. Otherwise, calls
++ * 'iiop_connection_new' to create a new connection
++ * to host:port.
++ */
++IIOPConnection *
++iiop_connection_get(const char *host, gushort port, gboolean existing_only)
++{
++ IIOPConnection *cnx = NULL, *tmp;
++ GList *link;
++
++ g_assert(host);
++ g_assert(port);
++
++ GET_LOCK(giop_connection_list);
++ for(link = giop_connection_list.list; link; link = link->next)
++ {
++ tmp = IIOP_CONNECTION(link->data);
++ if(GIOP_CONNECTION(tmp)->connection_type != GIOP_CONNECTION_IIOP)
++ continue;
++
++ if(!GIOP_CONNECTION(tmp)->is_valid)
++ continue;
++
++ if(GIOP_CONNECTION(tmp)->connection_class != GIOP_CONNECTION_CLIENT)
++ continue;
++
++ if(IIOP_CONNECTION(tmp)->icnxtype != IIOP_IPV4)
++ continue;
++
++ if(!strcmp(host, tmp->u.ipv4.hostname)
++ && htons(port) == tmp->u.ipv4.location.sin_port) {
++ cnx = tmp;
++ break;
++ }
++ }
++ RELEASE_LOCK(giop_connection_list);
++
++ if(!cnx && !existing_only)
++ cnx = iiop_connection_new(host, port);
++
++ return cnx;
++}
++
++
++/*
++ * iiop_connection_new
++ *
++ * Inputs: same meanings as in 'iiop_connection_get'
++ * Outputs: 'retval' - newly created IIOPConnection
++ *
++ * Description: Allocates and initializes a new IIOPConnection,
++ * turns 'host' into an IP address, and then makes a TCP
++ * connection to host:port. Adds it to the list of active
++ * connections.
++ */
++IIOPConnection *
++iiop_connection_new(const char *host, gushort port)
++{
++ IIOPConnection *retval;
++
++ g_return_val_if_fail(host != NULL && port != 0, NULL);
++
++ retval = g_new0(IIOPConnection, 1);
++
++ iiop_connection_init(retval, GIOP_CONNECTION_CLIENT, IIOP_IPV4);
++
++ GIOP_CONNECTION(retval)->fd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
++ if(GIOP_CONNECTION_GET_FD(retval) < 0) {
++ ORBit_Trace(TraceMod_IIOP, TraceLevel_Debug, "iiop_connection_new: socket_error: %s\n", strerror(errno));
++ goto failed;
++ }
++
++ retval->u.ipv4.hostname = g_strdup(host);
++
++ retval->u.ipv4.location.sin_port = htons(port);
++ retval->u.ipv4.location.sin_family = AF_INET;
++ if(!inet_aton(host, &retval->u.ipv4.location.sin_addr))
++ {
++ struct hostent *hent;
++ hent = gethostbyname(host);
++ if(!hent) {
++ /* a (char *)h_strerror(int) function would be nice here */
++ ORBit_Trace(TraceMod_IIOP, TraceLevel_Debug, "iiop_connection_new: gethostbyname error: %d\n", h_errno);
++ goto failed;
++ }
++ memcpy(&retval->u.ipv4.location.sin_addr, hent->h_addr, (size_t) sizeof(retval->u.ipv4.location.sin_addr));
++ }
++ if(connect(GIOP_CONNECTION_GET_FD(retval), (struct sockaddr *)&retval->u.ipv4.location, sizeof(retval->u.ipv4.location)) < 0) {
++ ORBit_Trace(TraceMod_IIOP, TraceLevel_Debug, "iiop_connection_new: connect error: %s\n", strerror(errno));
++ goto failed;
++ }
++
++ ORBit_Trace(TraceMod_IIOP, TraceLevel_Debug,
++ "iiop_connection_new connect [%d] to %s:%d\n",
++ GIOP_CONNECTION_GET_FD(retval),
++ host, (guint)port);
++
++
++ fcntl(GIOP_CONNECTION_GET_FD(retval), F_SETFD, FD_CLOEXEC);
++ fcntl(GIOP_CONNECTION_GET_FD(retval), F_SETFL,
++ fcntl(GIOP_CONNECTION_GET_FD(retval), F_GETFL, 0)
++ | O_NONBLOCK);
++
++ GIOP_CONNECTION(retval)->was_initiated = TRUE;
++ GIOP_CONNECTION(retval)->is_auth = TRUE;
++
++ giop_connection_add_to_list(GIOP_CONNECTION(retval));
++
++ return retval;
++
++failed:
++ close(GIOP_CONNECTION_GET_FD(retval));
++ GIOP_CONNECTION(retval)->fd = -1;
++ giop_connection_free(GIOP_CONNECTION(retval));
++ return NULL;
++}
++
++/*
++ * iiop_connection_unix_get
++ *
++ * Inputs: 'sockpath' - Of the format 'path'
++ *
++ * Outputs: 'cnx' - the connection to the specified path, or
++ * NULL upon error.
++ *
++ * Description: Returns an IIOPConnection that is connected to the
++ * specified UNIX socket, if possible. If a connection
++ * already exists, just returns it. Otherwise,
++ * calls 'iiop_connection_unix_new' to create a new
++ * connection to sockpath.
++ */
++IIOPConnection *
++iiop_connection_unix_get(const char *sockpath, gboolean existing_only)
++{
++ IIOPConnection *cnx = NULL, *tmp;
++ GList *link;
++
++ GET_LOCK(giop_connection_list);
++ for(link = giop_connection_list.list; link; link = link->next)
++ {
++ tmp = IIOP_CONNECTION(link->data);
++
++ if(GIOP_CONNECTION(tmp)->connection_type != GIOP_CONNECTION_IIOP)
++ continue;
++
++ if(!GIOP_CONNECTION(tmp)->is_valid)
++ continue;
++
++ if(GIOP_CONNECTION(tmp)->connection_class != GIOP_CONNECTION_CLIENT)
++ continue;
++
++ if(IIOP_CONNECTION(tmp)->icnxtype != IIOP_USOCK)
++ continue;
++
++ if(!strcmp(sockpath, tmp->u.usock.sun_path)) {
++ cnx = tmp;
++ break;
++ }
++ }
++ RELEASE_LOCK(giop_connection_list);
++
++ if(!cnx && !existing_only)
++ cnx = iiop_connection_unix_new(sockpath);
++
++ return cnx;
++}
++
++/*
++ * iiop_connection_unix_new
++ *
++ * Inputs:
++ *
++ * Outputs: 'retval' - newly created IIOPConnection, or NULL upon error
++ *
++ * Description: Creates a connection to a UNIX socket (if possible)
++ * Adds it to the list of active connections.
++ */
++static IIOPConnection *
++iiop_connection_unix_new(const char *sockpath)
++{
++ IIOPConnection *retval;
++
++ retval = g_new0(IIOPConnection, 1);
++
++ retval->u.usock.sun_family = AF_UNIX;
++
++ g_snprintf(retval->u.usock.sun_path,
++ sizeof(retval->u.usock.sun_path), "%s", sockpath);
++
++ iiop_connection_init(retval, GIOP_CONNECTION_CLIENT, IIOP_USOCK);
++
++ GIOP_CONNECTION(retval)->fd = socket(AF_UNIX, SOCK_STREAM, 0);
++ if(GIOP_CONNECTION_GET_FD(retval) < 0) {
++ ORBit_Trace(TraceMod_IIOP, TraceLevel_Debug, "iiop_connection_new: socket_error: %s\n", strerror(errno));
++ goto failed;
++ }
++
++ if(connect(GIOP_CONNECTION_GET_FD(retval), (struct sockaddr *)&retval->u.usock, SUN_LEN(&retval->u.usock)) < 0) {
++ ORBit_Trace(TraceMod_IIOP, TraceLevel_Debug, "iiop_connection_new: connect error: %s\n", strerror(errno));
++ goto failed;
++ }
++
++ GIOP_CONNECTION(retval)->was_initiated = TRUE;
++ GIOP_CONNECTION(retval)->is_auth = TRUE;
++
++ fcntl(GIOP_CONNECTION_GET_FD(retval), F_SETFD, FD_CLOEXEC);
++ fcntl(GIOP_CONNECTION_GET_FD(retval), F_SETFL,
++ fcntl(GIOP_CONNECTION_GET_FD(retval), F_GETFL, 0)
++ | O_NONBLOCK);
++
++ giop_connection_add_to_list(GIOP_CONNECTION(retval));
++
++ ORBit_Trace(TraceMod_IIOP, TraceLevel_Debug,
++ "iiop_connection_unix_new connect [%d] to %s\n",
++ GIOP_CONNECTION_GET_FD(retval),
++ sockpath);
++
++ return retval;
++
++failed:
++ close(GIOP_CONNECTION_GET_FD(retval));
++ GIOP_CONNECTION(retval)->fd = -1;
++ giop_connection_free(GIOP_CONNECTION(retval));
++ return NULL;
++}
++
++/*
++ * iiop_connection_server_accept
++ * Inputs: 'connection' - a server IIOPConnection.
++ *
++ * Description: Performs accept(), TCP wrapper, access checking and related
++ * duties on a connection
++ */
++int allow_severity = LOG_INFO, deny_severity = LOG_NOTICE;
++
++#if defined(HAVE_HOSTS_ACCESS) && defined(HAVE_TCPD_H)
++DEFINE_LOCK(tcp_wrappers_usage);
++
++#endif
++static void
++iiop_connection_server_accept(GIOPConnection *connection)
++{
++ struct sockaddr sock;
++ socklen_t n;
++ int newfd;
++ GIOPConnection *newcnx;
++
++// printk("iiop_conncetion_server_accept( %d )\n",
++// GIOP_CONNECTION_GET_FD(connection));
++
++ n = sizeof(sock);
++
++ switch(IIOP_CONNECTION(connection)->icnxtype) {
++ case IIOP_IPV4: sock.sa_family = AF_INET; break;
++ case IIOP_USOCK: sock.sa_family = AF_UNIX; break;
++ case IIOP_IPV6:
++#ifdef HAVE_IPV6
++ sock.sa_family = AF_INET6;
++#endif
++ break;
++ }
++
++ newfd = accept(GIOP_CONNECTION_GET_FD(connection), &sock, &n);
++
++#if defined(HAVE_HOSTS_ACCESS) && defined(HAVE_TCPD_H)
++ /* tcp wrappers access checking */
++ switch(IIOP_CONNECTION(connection)->icnxtype) {
++ case IIOP_IPV4:
++ {
++ struct request_info request;
++
++ GET_LOCK(tcp_wrappers_usage);
++
++ request_init(&request, RQ_DAEMON, argv0_val, RQ_FILE, newfd, 0);
++
++ fromhost(&request);
++ if(!hosts_access(&request)) {
++ syslog(deny_severity, "[orbit] refused connect from %s", eval_client(&request));
++ close(newfd); newfd = -1;
++ } else
++ syslog(allow_severity, "[orbit] connect from %s", eval_client(&request));
++
++ RELEASE_LOCK(tcp_wrappers_usage);
++ }
++ break;
++ default:
++ /* No access controls for these transports */
++ break;
++ }
++#endif
++
++ if(newfd >= 0) {
++ newcnx = GIOP_CONNECTION(iiop_connection_from_fd(newfd,
++ IIOP_CONNECTION(connection)));
++ GIOP_CONNECTION(newcnx)->orb_data = connection->orb_data;
++ switch(IIOP_CONNECTION(connection)->icnxtype) {
++ case IIOP_USOCK: newcnx->is_auth = TRUE; break;
++ default:
++ break;
++ }
++ }
++}
++
++/*
++ * iiop_connection_destroy
++ *
++ * Inputs: 'iiop_connection' - an IIOPConnection to be finalized
++ *
++ * Side effects: invalidates 'iiop_connection' for use as an IIOPConnection
++ *
++ * Description: Performs the IIOP-specific parts of connection shutdown,
++ * including sending a CLOSECONNECTION message to the remote side.
++ */
++static void
++iiop_connection_destroy(IIOPConnection *iiop_connection)
++{
++ const GIOPMessageHeader mh = {"GIOP", {1,0}, FLAG_ENDIANNESS,
++ GIOP_CLOSECONNECTION, 0};
++
++ switch(iiop_connection->icnxtype) {
++ case IIOP_IPV4:
++ ORBit_Trace(TraceMod_IIOP, TraceLevel_Debug,
++ "iiop_connection_destroy connect [%d] of %s:%d\n",
++ GIOP_CONNECTION_GET_FD(iiop_connection),
++ iiop_connection->u.ipv4.hostname,
++ ntohs(iiop_connection->u.ipv4.location.sin_port));
++ g_free(iiop_connection->u.ipv4.hostname);
++ break;
++ case IIOP_IPV6:
++#ifdef HAVE_IPV6
++ g_free(iiop_connection->u.ipv6.hostname);
++#else
++ g_warning("IPv6 unsupported, can't free it!");
++#endif
++ break;
++ case IIOP_USOCK:
++ /* why do we check if fd is > 0 here?
++ the orb code tries to reuse existing socket connection points.
++ If binding to any of those fails because another process is using it,
++ we don't want to unlink the other server's socket!
++ if the bind fails, iiop_connection_server_unix closes the fd for us */
++ if(GIOP_CONNECTION(iiop_connection)->connection_class == GIOP_CONNECTION_SERVER
++ && GIOP_CONNECTION(iiop_connection)->fd >= 0)
++ unlink(iiop_connection->u.usock.sun_path);
++ break;
++ default:
++ break;
++ }
++
++ if(GIOP_CONNECTION_GET_FD(iiop_connection) >= 0) {
++ if(GIOP_CONNECTION(iiop_connection)->is_valid
++ && !GIOP_CONNECTION(iiop_connection)->was_initiated)
++ {
++ write(GIOP_CONNECTION_GET_FD(iiop_connection), &mh, sizeof(mh));
++ }
++
++ shutdown(GIOP_CONNECTION_GET_FD(iiop_connection), 2);
++ close(GIOP_CONNECTION_GET_FD(iiop_connection));
++ GIOP_CONNECTION(iiop_connection)->fd = -1;
++ }
++}
++
++static int giop_nloops = 0;
++
++void giop_main_quit(void) { giop_nloops--; }
++
++void
++giop_main(void)
++{
++ int looplevel;
++
++ looplevel = ++giop_nloops;
++
++ while(giop_nloops > 0) {
++
++ giop_main_iterate(TRUE);
++
++ if(giop_nloops != looplevel) {
++ giop_nloops = --looplevel;
++ return;
++ }
++ }
++}
++
++GIOPRecvBuffer *
++giop_main_next_message(gboolean blocking)
++{
++ return giop_main_next_message_2(blocking, NULL);
++}
++
++GIOPRecvBuffer *
++giop_main_next_message_2(gboolean blocking,
++ GIOPConnection *monitor)
++{
++ GIOPConnection *connection;
++ GIOPRecvBuffer *recv_buffer = NULL;
++
++ do {
++ recv_buffer = giop_received_list_pop();
++// printk("giop_main_next_message_2 : recv_buffer = 0x%08X\n", recv_buffer);
++ if(recv_buffer)
++ break;
++
++ connection = giop_check_connections(blocking);
++// printk("giop_main_next_message_2 : connection = 0x%08X\n", connection);
++ if(!connection)
++ {
++ return NULL;
++ }
++
++ if(GIOP_CONNECTION_GET_FD(connection) < 0) {
++ g_assert(!"connection has -ve fd!");
++ }
++
++// printk("giop_main_next_message_2 : connection class = %d\n",
++// connection->connection_class);
++ if(connection->connection_class == GIOP_CONNECTION_SERVER)
++ iiop_connection_server_accept(connection);
++ else
++ recv_buffer = giop_recv_message_buffer_use(connection);
++
++ if(monitor && !monitor->is_valid)
++ {
++ return NULL;
++ }
++
++ } while(!recv_buffer);
++
++ return recv_buffer;
++}
++
++void
++giop_main_handle_connection(GIOPConnection *connection)
++{
++ GIOPRecvBuffer *recv_buffer;
++
++ //printk("giop_main_handle_connection\n");
++
++ g_return_if_fail(connection != NULL);
++ g_return_if_fail(connection->is_valid);
++
++ if(connection->connection_class == GIOP_CONNECTION_SERVER) {
++ iiop_connection_server_accept(connection);
++ return;
++ } else
++ recv_buffer = giop_recv_message_buffer_use(connection);
++
++ if(recv_buffer) {
++ if(IIOPIncomingMessageHandler)
++ IIOPIncomingMessageHandler(recv_buffer);
++ else
++ giop_received_list_push(recv_buffer);
++ }
++}
++
++/*
++ * giop_main_handle_connection_exception
++ *
++ * Input: GIOPConnection *connection
++ *
++ * Output:
++ *
++ * Side effects: invalidates connection
++ *
++ * Description:
++ * When poll() or select() indicates that a file descriptor
++ * has been closed at the remote end, we must invalidate the associated
++ * GIOPConnection structure.
++ */
++void
++giop_main_handle_connection_exception(GIOPConnection *connection)
++{
++ g_return_if_fail(connection != NULL);
++ g_return_if_fail(connection->is_valid);
++
++// printk("giop_main_handle_connection_exception(0x%X)\n", GIOP_CONNECTION_GET_FD(connection));
++
++ giop_connection_ref(connection);
++
++ giop_connection_remove_from_list(connection);
++
++ shutdown(GIOP_CONNECTION_GET_FD(connection), 2);
++ close(GIOP_CONNECTION_GET_FD(connection));
++ GIOP_CONNECTION(connection)->fd = -1;
++ connection->is_valid = FALSE;
++
++ if(connection->incoming_msg) {
++ giop_recv_buffer_unuse(connection->incoming_msg);
++ connection->incoming_msg = NULL;
++ }
++
++ giop_connection_unref(connection);
++}
++
++/*
++ * giop_main_iterate
++ *
++ * Input: 'blocking' - flag to indicate whether to wait for incoming
++ * messages (TRUE), or whether to return immediately if no
++ * incoming messages are available (FALSE).
++ * Output: None
++ * Description:
++ * Gets the next message into recv_buffer (see
++ * giop_main_next_message) If we have a handler for incoming
++ * messages, then pass recv_buffer to the handler (handler
++ * becomes the new owner of recv_buffer's contents). Otherwise,
++ * tosses it onto the list of received-but-unprocessed buffers.
++ *
++ * Warnings:
++ * If you don't have an IIOPIncomingMessageHandler set, you're
++ * probably really screwed in the long run.
++ */
++void
++giop_main_iterate(gboolean blocking)
++{
++ GIOPRecvBuffer *recv_buffer;
++
++// printk("giop_main_iterate: blocking: %d\n", blocking);
++schedule();
++
++ recv_buffer = giop_main_next_message(blocking);
++
++// printk("giop_main_iterate: recv_buffer = 0x%08X\n", recv_buffer);
++
++ if(recv_buffer) {
++ if(IIOPIncomingMessageHandler)
++ IIOPIncomingMessageHandler(recv_buffer);
++ else
++ giop_received_list_push(recv_buffer);
++ }
++}
++
++/*
++ * giop_check_connections
++ *
++ * Inputs: 'block_for_reply' - If no incoming data is immediately available
++ * should this routine wait for incoming data (TRUE) or return
++ * immediately (FALSE).
++ *
++ * Outputs: 'connection' - the first connection that has incoming
++ * data available for reading (supposedly a GIOP message, but
++ * could be anything).
++ *
++ * Side effects: Removes closed connections from the active list.
++ *
++ * Global data structures used: giop_connection_list
++ *
++ * Description: Does a poll or select (OS-dependant) on the list of file
++ * descriptors in giop_connection_list.
++ *
++ * If a file descriptor has been closed, call
++ * giop_connection_handle_exception() on it and (as
++ * appropriated by 'block_for_reply') either return
++ * NULL or do another poll/select.
++ *
++ * If a file descriptor has data available for
++ * reading, find the associated GIOPConnection (using
++ * giop_connection_list.fd_to_connection_mapping) and
++ * return that.
++ *
++ */
++GIOPConnection *
++giop_check_connections(gboolean block_for_reply)
++{
++ GIOPConnection *connection = NULL;
++ int pollret;
++ int numcnx_checks;
++ int i;
++#ifndef USE_POLL
++ fd_set selectset_rd, selectset_ex;
++
++ struct timeval immediate_timeout = {0,0};
++#endif
++
++// printk("giop_check_connections\n");
++
++ do_read_msg:
++
++ if(!giop_connection_list.list)
++ {
++// printk("giop_check_connections : list = NULL\n");
++ BUG();
++ return NULL;
++ }
++
++#if 0
++ giop_connection_list_recreate(); /* easiest way to get valid
++ select sets... */
++#endif
++
++#ifdef USE_POLL
++ numcnx_checks = giop_connection_list.pollset->len;
++#else
++ memcpy(&selectset_rd, &giop_connection_list.selectset_rd,
++ sizeof(selectset_rd));
++ memcpy(&selectset_ex, &giop_connection_list.selectset_ex,
++ sizeof(selectset_ex));
++
++ numcnx_checks = giop_connection_list.max_fd+1;
++#endif
++
++ restart:
++#ifdef USE_POLL
++ pollret = poll((struct pollfd *)giop_connection_list.pollset->data,
++ giop_connection_list.pollset->len,
++ block_for_reply?-1:0);
++
++#if KORBIT_DEBUG_WRITING
++{
++ int ix;
++ struct pollfd *fds = (struct pollfd *)giop_connection_list.pollset->data;
++// printk("back from poll(#fds = %d, block = %d) = %d)\n", giop_connection_list.pollset->len, block_for_reply, pollret);
++// for (ix = 0; ix < giop_connection_list.pollset->len; ix++)
++ // printk(" [fd = 0x%X, event = 0x%X, revent = 0x%X]\n",
++// fds[ix].fd, fds[ix].events, fds[ix].revents);
++
++}
++#endif /* KORBIT_DEBUG_WRITING */
++
++
++# else /* !USE_POLL */
++
++ {
++ pollret = select (giop_connection_list.max_fd + 1,
++ &selectset_rd,
++ NULL, &selectset_ex,
++ block_for_reply?NULL:&immediate_timeout);
++ }
++# endif /* !USE_POLL */
++
++// printk("giop_check_connections : pollret == %d\n", pollret);
++ if(pollret <= 0) {
++ if(pollret < 0) {
++ if(errno == EINTR)
++ goto restart;
++ else
++ g_warning("Error code from select/poll: %s", g_strerror(errno));
++ } else
++ return NULL;
++ }
++
++ /* Check for data to be read on the fd's.
++ Note we have to do the hangup/exception checking in a separate loop,
++ because there may be data waiting to be read on a connection that the
++ other end has closed. */
++ for(i = 0; i < numcnx_checks; i++) {
++ struct fd_hash_elem *el;
++
++#ifdef USE_POLL
++ struct pollfd *p =
++ &g_array_index(giop_connection_list.pollset,
++ struct pollfd,
++ i);
++ g_assert(p->fd <= giop_connection_list.max_fd);
++#ifndef __KORBIT__
++ connection = giop_connection_list.fd_to_connection_mapping->pdata[p->fd];
++#else
++ el = g_hash_table_lookup(giop_connection_list.fd_to_connection_mapping,
++ &(p->fd));
++ if (el)
++ connection = el->cnx;
++#endif
++ if(p->revents & POLLIN)
++ goto got_connection;
++#else
++#ifndef __KORBIT__
++ connection = giop_connection_list.fd_to_connection_mapping->pdata[i];
++#else
++ el = g_hash_table_lookup(giop_connection_list.fd_to_connection_mapping,
++ &i);
++ if (el)
++ connection = el->cnx;
++#endif
++ if (FD_ISSET(i, &selectset_rd)) {
++ goto got_connection;
++ }
++#endif
++ }
++
++ /* Handle fd exceptions */
++ for(i = 0; i < numcnx_checks; i++)
++ {
++ struct fd_hash_elem *el;
++#ifdef USE_POLL
++ struct pollfd *p =
++ &g_array_index(giop_connection_list.pollset,
++ struct pollfd,
++ i);
++
++ g_assert(p->fd <= giop_connection_list.max_fd);
++ if(p->revents & (POLLHUP|POLLNVAL)) {
++#ifndef __KORBIT__
++ connection = giop_connection_list.fd_to_connection_mapping->pdata[p->fd];
++#else
++ el = g_hash_table_lookup(giop_connection_list.fd_to_connection_mapping,
++ &(p->fd));
++ if (el)
++ connection = el->cnx;
++#endif
++ giop_main_handle_connection_exception(connection);
++ }
++#else /* !USE_POLL */
++ if(FD_ISSET(i, &selectset_ex)) {
++#ifndef __KORBIT__
++ connection = giop_connection_list.fd_to_connection_mapping->pdata[i];
++#else
++ el = g_hash_table_lookup(giop_connection_list.fd_to_connection_mapping,
++ &i);
++ if (el)
++ connection = el->cnx;
++#endif
++ giop_main_handle_connection_exception(connection);
++ }
++#endif /* !USE_POLL */
++ }
++
++ /* Only reached if we didn't find a connection to read data from */
++ if(block_for_reply)
++ goto do_read_msg;
++
++ got_connection:
++// printk("giop_check_connections : got connection\n");
++ return connection;
++}
++
+diff -urN linux-2.4.1/net/korbit/IIOP/encoders.c linux-2.4.1-korbit/net/korbit/IIOP/encoders.c
+--- linux-2.4.1/net/korbit/IIOP/encoders.c Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/IIOP/encoders.c Thu Feb 1 11:46:51 2001
+@@ -0,0 +1,46 @@
++#include "config.h"
++#include <string.h>
++#include "IIOP.h"
++
++ENCODER_DEC(IOP_ServiceContext)
++{
++ APA(&mem->context_id, sizeof(mem->context_id));
++ ENCODER_CALL(CORBA_sequence_octet, &mem->context_data);
++}
++
++ENCODER_DEC(IOP_ServiceContextList)
++{
++ int i;
++
++ if(!mem)
++ {
++ APA((gpointer)giop_scratch_space, sizeof(mem->_length));
++ return;
++ }
++
++ APA(&mem->_length, sizeof(mem->_length));
++
++ for(i = 0; i < mem->_length; i++)
++ ENCODER_CALL(IOP_ServiceContext, &mem->_buffer[i]);
++}
++
++ENCODER_DEC(CORBA_sequence_octet)
++{
++ if(!mem)
++ {
++ APA((gpointer)giop_scratch_space, sizeof(mem->_length));
++ return;
++ }
++
++ APIA(&mem->_length, sizeof(mem->_length));
++ if(mem->_length > 0)
++ AP(mem->_buffer, mem->_length);
++}
++
++ENCODER_DEC(CORBA_char)
++{
++ GIOP_unsigned_long len = strlen(mem) + 1;
++
++ APIA(&len, sizeof(len));
++ AP(mem, len);
++}
+diff -urN linux-2.4.1/net/korbit/IIOP/giop-msg-buffer.c linux-2.4.1-korbit/net/korbit/IIOP/giop-msg-buffer.c
+--- linux-2.4.1/net/korbit/IIOP/giop-msg-buffer.c Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/IIOP/giop-msg-buffer.c Fri Feb 2 01:23:46 2001
+@@ -0,0 +1,1443 @@
++/* The big picture:
++ * For every outgoing request, we have to have the network-ready data
++ * somewhere in memory.
++ *
++ * Using writev, any pieces that do not need endian conversion can
++ * be written in-place.
++ *
++ * The pieces that do need endian conversion can be put into one or more
++ * buffers.
++ *
++ * WHOA WHOA newsflash
++ * Because IIOP lets the message sender specify the endianness,
++ * we do not need to do endian conversion _ever_! The receiver can do all
++ * conversions if need be, or if they are the same endianness as sender they
++ * can just pull it in right off the wire :)
++ *
++ */
++
++#include "config.h"
++#include "iiop-endianP.h"
++#include <string.h>
++#include <unistd.h>
++#include <stdio.h>
++#include <errno.h>
++#include <sys/types.h>
++#include <fcntl.h>
++#include <string.h>
++
++#ifdef HAVE_POLL
++# include <sys/poll.h>
++#else
++# include <sys/types.h>
++# include <sys/time.h>
++#endif
++#include "IIOP.h"
++#include "IIOP-private.h"
++
++#ifdef HAVE_LIMITED_WRITEV
++#define writev g_writev
++#endif
++
++/*
++#ifdef O_NONBLOCK
++#undef O_NONBLOCK
++#endif
++#define O_NONBLOCK 0
++*/
++
++
++/* type defs */
++
++#ifdef __GNUC__
++#define PACKED __attribute__((packed))
++#else
++#define PACKED
++#endif
++
++/*
++ * Overlaps with struct _GIOPMessageHeader on purpose
++ * - we save time because this stuff never changes
++ */
++struct _GIOPMessageHeaderConstants {
++ GIOP_char magic[4];
++ GIOP_char GIOP_version[2];
++ GIOP_octet flags;
++} PACKED;
++
++/* functions */
++static gint giop_recv_decode_message(GIOPRecvBuffer *buf);
++static gboolean num_on_list(GIOP_unsigned_long num,
++ const GIOP_unsigned_long *request_ids,
++ GIOP_unsigned_long req_count);
++static gint giop_recv_reply_decode_message(GIOPRecvBuffer *buf);
++static gint giop_recv_request_decode_message(GIOPRecvBuffer *buf);
++static gint giop_recv_locate_reply_decode_message(GIOPRecvBuffer *buf);
++static gint giop_recv_locate_request_decode_message(GIOPRecvBuffer *buf);
++static GIOPRecvBuffer *giop_received_list_check_reply(GIOP_unsigned_long request_id);
++
++#ifdef NOT_REENTRANT
++extern DEFINE_LOCK(iiop_connection_list);
++#endif
++GList *iiop_connection_list = NULL;
++
++/* global variables */
++char giop_scratch_space[2048];
++
++static const struct _GIOPMessageHeaderConstants
++giop_message_header_constants = {
++ "GIOP",
++ {1,0},
++ FLAG_ENDIANNESS,
++};
++
++struct iovec
++giop_first_message_vec = {NULL,
++ sizeof(struct _GIOPMessageHeaderConstants)};
++
++DEFINE_LOCK(sendbufferlist);
++GSList *sendbufferlist = NULL;
++
++DEFINE_LOCK(recvbufferlist);
++GSList *recvbufferlist = NULL;
++
++DEFINE_LOCK(incoming_bufs);
++GList *incoming_bufs = NULL; /* List of incoming messages that had to be
++ shunted aside */
++
++DEFINE_LOCK(sendbuffers);
++DEFINE_LOCK(recvbuffers);
++GMemChunk *sendbuffers = NULL, *recvbuffers = NULL;
++
++DEFINE_LOCK(request_id_counter);
++GIOP_unsigned_long request_id_counter;
++
++#if 0
++inline
++void giop_message_buffer_append_iovec(GIOPMessageBuffer *msgbuf,
++ const struct iovec *iovec)
++{
++ /* g_print("Appending iovec %d bytes @ %p\n", iovec->iov_len, iovec->iov_base); */
++ g_array_append_val(msgbuf->iovecs, *iovec);
++}
++#else
++#define giop_message_buffer_append_iovec(msgbuf, iovec) g_array_append_val((msgbuf)->iovecs, *(iovec))
++#endif
++
++void
++giop_message_buffer_init(void)
++{
++ giop_first_message_vec.iov_base = (gpointer)&giop_message_header_constants;
++ INIT_LOCK(sendbufferlist);
++ INIT_LOCK(recvbufferlist);
++ request_id_counter = 1;
++ INIT_LOCK(request_id_counter);
++
++ INIT_LOCK(sendbuffers);
++ sendbuffers = g_mem_chunk_create(GIOPSendBuffer, 2, G_ALLOC_ONLY);
++ INIT_LOCK(recvbuffers);
++ recvbuffers = g_mem_chunk_create(GIOPRecvBuffer, 2, G_ALLOC_ONLY);
++}
++
++static void
++giop_message_buffer_new(GIOPMessageBuffer *buf)
++{
++ buf->iovecs = g_array_new(FALSE, FALSE, sizeof(struct iovec));
++}
++
++#define STRUCT_OFFSET(t, f) ((int) ((char*) &((t*) 0)->f))
++
++/* Send buffers only */
++static GIOPSendBuffer *
++giop_send_buffer_new(void)
++{
++ GIOPSendBuffer *msgbuf;
++ struct iovec firstvec;
++
++ GET_LOCK(sendbuffers);
++ msgbuf = g_chunk_new(GIOPSendBuffer, sendbuffers);
++ RELEASE_LOCK(sendbuffers);
++
++ giop_message_buffer_new(GIOP_MESSAGE_BUFFER(msgbuf));
++
++ giop_message_buffer_append_iovec(GIOP_MESSAGE_BUFFER(msgbuf),
++ &giop_first_message_vec);
++
++ firstvec.iov_base = &(GIOP_MESSAGE_BUFFER(msgbuf)->message_header.message_type);
++ firstvec.iov_len = sizeof(GIOPMessageHeader)
++ - STRUCT_OFFSET(GIOPMessageHeader, message_type);
++ GIOP_MESSAGE_BUFFER(msgbuf)->message_header.message_size = 0;
++
++ msgbuf->indirects = g_mem_chunk_create(char[GIOP_INDIRECT_CHUNK_SIZE],
++ 2, G_ALLOC_ONLY);
++
++ giop_message_buffer_append_iovec(GIOP_MESSAGE_BUFFER(msgbuf), &firstvec);
++
++ return msgbuf;
++}
++
++gint
++giop_send_buffer_write(GIOPSendBuffer *send_buffer)
++{
++ gulong nvecs;
++ glong res, sum, t;
++ struct iovec *curvec;
++ int fd;
++ GIOPConnection *cnx;
++ gint retval = -1;
++
++// printf("giop_send_buffer_write\n");
++
++ cnx = GIOP_MESSAGE_BUFFER(send_buffer)->connection;
++ if(!cnx->is_valid)
++ return -1;
++
++ fd = GIOP_CONNECTION_GET_FD(cnx);
++ nvecs = GIOP_MESSAGE_BUFFER(send_buffer)->iovecs->len;
++ curvec = (struct iovec *)GIOP_MESSAGE_BUFFER(send_buffer)->iovecs->data;
++
++#if defined(ORBIT_DEBUG) && 0
++ g_print("Message of length %d looks like:\n",
++ GIOP_MESSAGE_BUFFER(send_buffer)->message_header.message_size);
++{ int i = 0;
++ for(sum = 0; i < nvecs; i++) {
++ sum += curvec[i].iov_len;
++ g_print(" [%p, %d]: %d\n", curvec[i].iov_base, curvec[i].iov_len,
++ sum);
++ }
++}
++#endif
++
++ fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) & ~O_NONBLOCK);
++ res = writev(fd, curvec, nvecs);
++// printk("writev wrote %d byte\n", res);
++
++ sum = (GIOP_MESSAGE_BUFFER(send_buffer)->message_header.message_size + sizeof(GIOPMessageHeader));
++ if(res < sum) {
++ if(res < 0) {
++//printf("writev returned %d\n", res);
++ if(errno != EAGAIN) {
++ giop_main_handle_connection_exception(cnx);
++ goto out;
++ }
++
++ res = 0;
++ }
++
++ /* wrote 7, iovecs 3, 2, 2, 4:
++ 0 + 3 !> 7
++ 3 + 2 !> 7
++ 5 + 2 !> 7
++ */
++
++ for(t = 0; ; t += curvec->iov_len, curvec++, nvecs--) {
++ if((t + curvec->iov_len) > res)
++ break;
++ }
++ if((res - t) > 0) {
++ curvec->iov_len -= (res - t);
++ curvec->iov_base = (gpointer)((char *)curvec->iov_base + (res - t));
++ }
++
++
++ fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) & ~O_NONBLOCK);
++ t = writev(fd, curvec, nvecs);
++
++ fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK);
++
++ if((t < 0) || ((res + t) < sum)) {
++//printf("crap, t = %d res = %d sum = %d\n", t, res, sum);
++ giop_main_handle_connection_exception(cnx);
++ goto out;
++ }
++ }
++
++ retval = 0;
++
++ out:
++
++ return retval;
++}
++
++static GIOPSendBuffer *
++giop_send_buffer_use(GIOPConnection *connection)
++{
++ GIOPSendBuffer *retval;
++
++ if(!connection->is_valid)
++ return NULL;
++
++ GET_LOCK(sendbufferlist);
++
++ if(sendbufferlist)
++ {
++ GSList *head;
++
++ retval = sendbufferlist->data;
++
++ head = sendbufferlist;
++ sendbufferlist = g_slist_remove_link(sendbufferlist, sendbufferlist);
++ g_slist_free_1 (head);
++
++ g_array_set_size(GIOP_MESSAGE_BUFFER(retval)->iovecs, 2);
++ GIOP_MESSAGE_BUFFER(retval)->message_header.message_size = 0;
++ }
++ else
++ retval = giop_send_buffer_new();
++
++ RELEASE_LOCK(sendbufferlist);
++
++ giop_connection_ref(connection);
++ GIOP_MESSAGE_BUFFER(retval)->connection = connection;
++
++ g_mem_chunk_reset(retval->indirects);
++ retval->indirect = g_chunk_new(gpointer, retval->indirects);
++#ifdef ORBIT_DEBUG
++ memset(retval->indirect, '\xFE', GIOP_INDIRECT_CHUNK_SIZE);
++#endif
++ retval->indirect_used = 0;
++
++ return retval;
++}
++
++GIOPSendBuffer *
++giop_send_reply_buffer_use(GIOPConnection *connection,
++ const IOP_ServiceContextList *service_context,
++ GIOP_unsigned_long request_id,
++ GIOPReplyStatusType reply_status)
++{
++ GIOPSendBuffer *send_buffer;
++
++ send_buffer = giop_send_buffer_use(connection);
++
++ if(!send_buffer)
++ return NULL;
++
++ GIOP_MESSAGE_BUFFER(send_buffer)->message_header.message_type = GIOP_REPLY;
++
++ giop_message_buffer_do_alignment(GIOP_MESSAGE_BUFFER(send_buffer),
++ sizeof(GIOP_unsigned_long));
++ if(!service_context) {
++ static const GIOP_unsigned_long sc_zero_int = 0;
++ AP(&sc_zero_int, sizeof(service_context->_length));
++ } else {
++ int i, n;
++ n = service_context->_length;
++ AP(&service_context->_length, sizeof(service_context->_length));
++ for(i = 0; i < n; i++) {
++ int j, o;
++ CORBA_sequence_octet *seqo;
++
++ giop_message_buffer_do_alignment(GIOP_MESSAGE_BUFFER(send_buffer),
++ sizeof(GIOP_unsigned_long));
++ AP(&service_context->_buffer[i].context_id,
++ sizeof(service_context->_buffer[i].context_id));
++ seqo = &service_context->_buffer[i].context_data;
++ o = seqo->_length;
++ AP(&seqo->_length, sizeof(GIOP_unsigned_long));
++ for(j = 0; j < o; j++)
++ AP(seqo->_buffer, seqo->_length);
++ }
++ }
++ send_buffer->message.u.reply.request_id = request_id;
++ send_buffer->message.u.reply.reply_status = reply_status;
++ giop_message_buffer_do_alignment(GIOP_MESSAGE_BUFFER(send_buffer),
++ sizeof(GIOP_unsigned_long));
++ AP(&send_buffer->message.u.reply.request_id,
++ sizeof(GIOP_unsigned_long));
++ AP(&send_buffer->message.u.reply.reply_status,
++ sizeof(GIOP_unsigned_long));
++
++ return send_buffer;
++}
++
++GIOPSendBuffer *
++giop_send_locate_reply_buffer_use(GIOPConnection *connection,
++ GIOP_unsigned_long request_id,
++ GIOPLocateStatusType locate_reply_status)
++{
++ GIOPSendBuffer *send_buffer;
++
++ send_buffer = giop_send_buffer_use(connection);
++
++ if(!send_buffer)
++ return NULL;
++
++ GIOP_MESSAGE_BUFFER(send_buffer)->message_header.message_type = GIOP_LOCATEREPLY;
++
++ APIA(&request_id, sizeof(request_id));
++ APIA(&locate_reply_status, sizeof(locate_reply_status));
++
++ return send_buffer;
++}
++
++GIOPSendBuffer *
++giop_send_request_buffer_use(GIOPConnection *connection,
++ const IOP_ServiceContextList *service_context,
++ GIOP_unsigned_long request_id,
++ GIOP_boolean response_expected,
++ const struct iovec *object_key_vec,
++ const struct iovec *operation_vec,
++ const struct iovec *principal_vec)
++{
++ GIOPSendBuffer *send_buffer;
++#if 0
++ static const struct {
++ CORBA_unsigned_long _length;
++ char _buffer[7];
++ } default_principal = { sizeof("nobody"), "nobody" };
++ static const struct iovec default_principal_vec =
++ {(void *)&default_principal,
++ sizeof(CORBA_unsigned_long) + sizeof("nobody")};
++#endif
++
++ if (!connection)
++ return NULL;
++ if(!object_key_vec)
++ return NULL;
++ if(!operation_vec)
++ return NULL;
++
++ ORBit_Trace(TraceMod_IIOP, TraceLevel_Debug,
++ "Sending request %s id %d to %s\n",
++ ((guchar *)operation_vec->iov_base) + 4,
++ request_id, ((guchar *)object_key_vec->iov_base) + 4);
++
++ send_buffer = giop_send_buffer_use(connection);
++
++ if (!send_buffer)
++ return NULL;
++
++ GIOP_MESSAGE_BUFFER(send_buffer)->message_header.message_type = GIOP_REQUEST;
++
++ giop_message_buffer_do_alignment(GIOP_MESSAGE_BUFFER(send_buffer),
++ sizeof(GIOP_unsigned_long));
++ if(!service_context) {
++ static const GIOP_unsigned_long sc_zero_int = 0;
++ AP(&sc_zero_int, sizeof(GIOP_unsigned_long));
++ } else {
++ int i, n;
++ n = service_context->_length;
++ AP(&service_context->_length, sizeof(service_context->_length));
++ for(i = 0; i < n; i++) {
++ int j, o;
++ CORBA_sequence_octet *seqo;
++
++ giop_message_buffer_do_alignment(GIOP_MESSAGE_BUFFER(send_buffer),
++ sizeof(GIOP_unsigned_long));
++ AP(&service_context->_buffer[i].context_id,
++ sizeof(service_context->_buffer[i].context_id));
++ seqo = &service_context->_buffer[i].context_data;
++ o = seqo->_length;
++ AP(&seqo->_length, sizeof(GIOP_unsigned_long));
++ for(j = 0; j < o; j++)
++ AP(seqo->_buffer, seqo->_length);
++ }
++ }
++ send_buffer->message.u.request.request_id = request_id;
++ send_buffer->message.u.request.response_expected = response_expected;
++ giop_message_buffer_do_alignment(GIOP_MESSAGE_BUFFER(send_buffer),
++ sizeof(GIOP_unsigned_long));
++ AP(&send_buffer->message.u.request.request_id,
++ sizeof(GIOP_unsigned_long));
++ AP(&send_buffer->message.u.request.response_expected,
++ sizeof(GIOP_boolean));
++#if 0
++ API(&response_expected, 1);
++ AP((gpointer)giop_scratch_space, 3);
++#endif
++
++ giop_message_buffer_do_alignment(GIOP_MESSAGE_BUFFER(send_buffer),
++ sizeof(CORBA_unsigned_long));
++ giop_message_buffer_append_iovec(GIOP_MESSAGE_BUFFER(send_buffer),
++ object_key_vec);
++ GIOP_MESSAGE_BUFFER(send_buffer)->message_header.message_size +=
++ object_key_vec->iov_len;
++
++ /*
++ * We can know the length at compile time - don't calculate it at runtime
++ * if we can help it :)
++ */
++ /* ENCODER_CALL(CORBA_string, (CORBA_string *)operation); */
++ giop_message_buffer_do_alignment(GIOP_MESSAGE_BUFFER(send_buffer),
++ sizeof(CORBA_unsigned_long));
++ giop_message_buffer_append_iovec(GIOP_MESSAGE_BUFFER(send_buffer),
++ operation_vec);
++ GIOP_MESSAGE_BUFFER(send_buffer)->message_header.message_size +=
++ operation_vec->iov_len;
++
++ giop_message_buffer_do_alignment(GIOP_MESSAGE_BUFFER(send_buffer),
++ sizeof(CORBA_unsigned_long));
++ giop_message_buffer_append_iovec(GIOP_MESSAGE_BUFFER(send_buffer),
++ principal_vec);
++ GIOP_MESSAGE_BUFFER(send_buffer)->message_header.message_size +=
++ principal_vec->iov_len;
++
++ return send_buffer;
++}
++
++GIOPSendBuffer *
++giop_send_locate_request_buffer_use(GIOPConnection *connection,
++ GIOP_unsigned_long request_id,
++ const struct iovec *object_key_vec)
++{
++ GIOPSendBuffer *send_buffer;
++
++ if (!connection)
++ return NULL;
++ if (!object_key_vec)
++ return NULL;
++
++ ORBit_Trace(TraceMod_IIOP, TraceLevel_Debug,
++ "Sending locate request id %d to %s\n",
++ request_id, ((guchar *)object_key_vec->iov_base) + 4);
++
++ send_buffer = giop_send_buffer_use(connection);
++
++ if (!send_buffer)
++ return NULL;
++
++ GIOP_MESSAGE_BUFFER(send_buffer)->message_header.message_type = GIOP_LOCATEREQUEST;
++
++ APIA(&request_id, sizeof(request_id));
++
++ giop_message_buffer_do_alignment(GIOP_MESSAGE_BUFFER(send_buffer),
++ sizeof(CORBA_unsigned_long));
++ giop_message_buffer_append_iovec(GIOP_MESSAGE_BUFFER(send_buffer),
++ object_key_vec);
++ GIOP_MESSAGE_BUFFER(send_buffer)->message_header.message_size +=
++ object_key_vec->iov_len;
++
++ return send_buffer;
++}
++
++void
++giop_send_buffer_unuse(GIOPSendBuffer *send_buffer)
++{
++ if (send_buffer == NULL)
++ return;
++
++ giop_connection_unref(GIOP_MESSAGE_BUFFER(send_buffer)->connection);
++
++ GET_LOCK(sendbufferlist);
++ sendbufferlist = g_slist_prepend(sendbufferlist, send_buffer);
++ RELEASE_LOCK(sendbufferlist);
++}
++
++gulong
++giop_message_buffer_do_alignment(GIOPMessageBuffer *buffer,
++ gulong align_for)
++{
++ struct iovec newvec;
++ struct iovec *lastvec;
++ guint alignme;
++ gulong real_msgsize;
++ gulong align_diff;
++
++ if(align_for < 2) return 0;
++ if(align_for >
++ MAX(sizeof(GIOP_long_long),sizeof(GIOP_long_double)))
++ align_for = MAX(sizeof(GIOP_long_long), sizeof(GIOP_long_double));
++
++ real_msgsize = buffer->message_header.message_size+sizeof(GIOPMessageHeader);
++
++ alignme = (gulong)ALIGN_ADDRESS(real_msgsize, align_for);
++
++ align_diff = alignme - real_msgsize;
++ if(align_diff > 0)
++ {
++ lastvec = (struct iovec *)(buffer->iovecs->data)
++ + buffer->iovecs->len - 1;
++
++ if(lastvec->iov_base == giop_scratch_space)
++ {
++ newvec.iov_len = align_diff;
++ lastvec->iov_len += align_diff;
++ buffer->message_header.message_size += align_diff;
++ }
++ else
++ {
++ newvec.iov_base = (gpointer)giop_scratch_space;
++ newvec.iov_len = align_diff;
++ buffer->message_header.message_size += align_diff;
++ giop_message_buffer_append_iovec(buffer, &newvec);
++ }
++ return newvec.iov_len;
++ }
++ else
++ return 0;
++}
++
++void
++giop_message_buffer_append_mem_a(GIOPMessageBuffer *buffer,
++ gconstpointer mem_region,
++ gulong mem_region_length)
++{
++ struct iovec newvec;
++ struct iovec *lastvec;
++ gint alignfor;
++
++ alignfor = giop_message_buffer_do_alignment(buffer, mem_region_length);
++
++ lastvec = (struct iovec *)(buffer->iovecs->data) +
++ + buffer->iovecs->len - 1;
++
++ if((mem_region == giop_scratch_space && lastvec->iov_base == giop_scratch_space)
++ || (alignfor == 0 && (((guchar *)lastvec->iov_base) + lastvec->iov_len) == mem_region))
++ {
++ lastvec->iov_len += mem_region_length;
++ }
++ else
++ {
++ newvec.iov_base = (gpointer)mem_region;
++ newvec.iov_len = mem_region_length;
++ giop_message_buffer_append_iovec(buffer, &newvec);
++ }
++
++ buffer->message_header.message_size += mem_region_length;
++}
++
++void
++giop_message_buffer_append_mem(GIOPMessageBuffer *buffer,
++ gconstpointer mem_region,
++ gulong mem_region_length)
++{
++ struct iovec newvec;
++ struct iovec *lastvec;
++
++ lastvec = (struct iovec *)(buffer->iovecs->data)
++ + buffer->iovecs->len - 1;
++
++ if((mem_region == giop_scratch_space
++ && lastvec->iov_base == giop_scratch_space)
++ || ((((guchar *)lastvec->iov_base) + lastvec->iov_len) == mem_region))
++ {
++ lastvec->iov_len += mem_region_length;
++ }
++ else
++ {
++ newvec.iov_base = (gpointer)mem_region;
++ newvec.iov_len = mem_region_length;
++ giop_message_buffer_append_iovec(buffer, &newvec);
++ }
++
++ buffer->message_header.message_size += mem_region_length;
++}
++
++/* I think we need a WE_WANT_NEW_CRAPPY_BUGGY_CODE ifdef here - this
++ tiny routine seems to be horribly hard to get right.
++
++ Basically we have to paste the whole of 'mem_region' into our
++ memory chunks, possibly subdividing it up to fit it into multiple
++ 1K chunks. Because we have to return the first paste point in case
++ the client wants to manipulate it afterwards, if mem_region_length
++ >= sizeof(CORBA_unsigned_long), we also have to guarantee that the
++ pasted stuff doesn't get divided on a finer boundary than
++ sizeof(CORBA_unsigned_long).
++*/
++gpointer
++giop_send_buffer_append_mem_indirect(GIOPSendBuffer *send_buffer,
++ gconstpointer mem_region,
++ gulong mem_region_length)
++{
++ gulong offset = 0, thisblock_size;
++ gpointer blockstart = NULL;
++
++ while(offset < mem_region_length) {
++ thisblock_size = MIN(mem_region_length - offset,
++ GIOP_INDIRECT_CHUNK_SIZE - send_buffer->indirect_used);
++
++ if((thisblock_size >= sizeof(CORBA_unsigned_long))
++ || (mem_region_length - offset) < sizeof(CORBA_unsigned_long)) {
++ if (!blockstart)
++ blockstart =
++ ((guchar*) send_buffer->indirect) + send_buffer->indirect_used;
++
++ memcpy((guchar*)send_buffer->indirect + send_buffer->indirect_used,
++ (guchar*)mem_region + offset, thisblock_size);
++ giop_message_buffer_append_mem(GIOP_MESSAGE_BUFFER(send_buffer),
++ (guchar*)send_buffer->indirect +
++ send_buffer->indirect_used,
++ thisblock_size);
++ offset += thisblock_size;
++ send_buffer->indirect_used += thisblock_size;
++ }
++
++ if(send_buffer->indirect_used >= (GIOP_INDIRECT_CHUNK_SIZE - sizeof(CORBA_unsigned_long))) {
++#ifdef I_CANT_FIGURE_OUT_WHAT_THIS_LOGIC_WAS_MEANT_TO_DO
++ || (thisblock_size >= sizeof(CORBA_unsigned_long)
++ && (mem_region_length - offset) > 0)) {
++#endif
++ send_buffer->indirect_used = 0;
++ send_buffer->indirect = g_chunk_new(gpointer,
++ send_buffer->indirects);
++ }
++ }
++
++ return blockstart;
++}
++
++#ifdef WE_WANT_OLD_DEAD_CRAPPY_BUGGY_CODE
++gpointer
++_giop_send_buffer_append_mem_indirect(GIOPSendBuffer *send_buffer,
++ gconstpointer mem_region,
++ gulong mem_region_length)
++{
++ gpointer blockstart = NULL;
++ gulong offset, new_offset;
++
++ for(offset = new_offset = 0; new_offset < mem_region_length;)
++ {
++ new_offset =
++ MIN(mem_region_length - offset,
++ GIOP_INDIRECT_CHUNK_SIZE - send_buffer->indirect_used);
++
++ if((new_offset - offset) > sizeof(CORBA_unsigned_long)
++ || mem_region_length >= sizeof(CORBA_unsigned_long)) {
++
++ if(!blockstart)
++ blockstart = send_buffer->indirect + send_buffer->indirect_used;
++ }
++
++ memcpy(send_buffer->indirect + send_buffer->indirect_used,
++ mem_region + offset, new_offset - offset);
++
++ giop_message_buffer_append_mem(GIOP_MESSAGE_BUFFER(send_buffer),
++ send_buffer->indirect + send_buffer->indirect_used,
++ new_offset - offset);
++
++ send_buffer->indirect_used += new_offset - offset;
++
++ offset = new_offset;
++
++ if(new_offset >= GIOP_INDIRECT_CHUNK_SIZE)
++ {
++ send_buffer->indirect_used = 0;
++ send_buffer->indirect = g_chunk_new(gpointer,
++ send_buffer->indirects);
++#ifdef ORBIT_DEBUG
++ memset(send_buffer->indirect, '\xFE', GIOP_INDIRECT_CHUNK_SIZE);
++#endif
++ }
++ }
++
++ return blockstart;
++}
++#endif
++
++gpointer
++giop_send_buffer_append_mem_indirect_a(GIOPSendBuffer *send_buffer,
++ gconstpointer mem_region,
++ gulong mem_region_length)
++{
++ giop_message_buffer_do_alignment(GIOP_MESSAGE_BUFFER(send_buffer),
++ mem_region_length);
++ return giop_send_buffer_append_mem_indirect(send_buffer,
++ mem_region, mem_region_length);
++}
++
++GIOP_unsigned_long
++giop_get_request_id(void)
++{
++ GIOP_unsigned_long retval;
++ GET_LOCK(request_id_counter);
++ retval = request_id_counter++;
++ RELEASE_LOCK(request_id_counter);
++ return retval;
++}
++
++/****************************************************
++ * GIOPRecvBuffer routines
++ ****************************************************/
++
++static GIOPRecvBuffer *
++giop_recv_buffer_new(void)
++{
++ GIOPRecvBuffer *msgbuf;
++
++ GET_LOCK(recvbuffers);
++ msgbuf = g_chunk_new(GIOPRecvBuffer, recvbuffers);
++ RELEASE_LOCK(recvbuffers);
++
++ giop_message_buffer_new(GIOP_MESSAGE_BUFFER(msgbuf));
++ msgbuf->message_body = NULL;
++
++ return msgbuf;
++}
++
++void
++giop_recv_buffer_unuse(GIOPRecvBuffer *buffer)
++{
++ if (buffer == NULL)
++ return;
++
++ if(buffer->message_body) {
++ buffer->message_body = ((guchar *)buffer->message_body)
++ - sizeof(GIOPMessageHeader);
++
++ g_free(buffer->message_body);
++ buffer->message_body = NULL;
++ }
++
++ if(GIOP_MESSAGE_BUFFER(buffer)->connection->incoming_msg == buffer)
++ GIOP_MESSAGE_BUFFER(buffer)->connection->incoming_msg = NULL;
++
++ giop_connection_unref(GIOP_MESSAGE_BUFFER(buffer)->connection);
++
++ GET_LOCK(recvbufferlist);
++ recvbufferlist = g_slist_prepend(recvbufferlist, buffer);
++ RELEASE_LOCK(recvbufferlist);
++}
++
++static GIOPRecvBuffer *
++giop_recv_buffer_use(GIOPConnection *connection)
++{
++ GIOPRecvBuffer *retval;
++
++ if(!connection || !connection->is_valid)
++ return NULL;
++
++ GET_LOCK(recvbufferlist);
++
++ if(recvbufferlist)
++ {
++ GSList *head;
++
++ retval = recvbufferlist->data;
++
++ head = recvbufferlist;
++ recvbufferlist = g_slist_remove_link(recvbufferlist, recvbufferlist);
++ g_slist_free_1 (head);
++
++ GIOP_MESSAGE_BUFFER(retval)->message_header.message_size = 0;
++ retval->message_body = NULL;
++ }
++ else
++ retval = giop_recv_buffer_new();
++
++ retval->state = GIOP_MSG_READING_HEADER;
++ retval->left_to_read = sizeof(GIOPMessageHeader);
++
++ RELEASE_LOCK(recvbufferlist);
++
++ giop_connection_ref(connection);
++ GIOP_MESSAGE_BUFFER(retval)->connection = connection;
++
++ return retval;
++}
++
++GIOPRecvBuffer *
++giop_recv_message_buffer_use(GIOPConnection *connection)
++{
++ GIOPRecvBuffer *retval;
++ char *bptr;
++ int sysret;
++ guint message_size;
++
++// printf("giop_recv_message_buffer_use: connection = 0x%X\n", connection);
++
++ if(!connection || !connection->is_valid)
++ return NULL;
++
++ if(connection->incoming_msg)
++ retval = connection->incoming_msg;
++ else {
++ retval = giop_recv_buffer_use(connection);
++ connection->incoming_msg = retval;
++ }
++
++ if(!retval) return NULL;
++
++ do {
++ switch(retval->state) {
++ case GIOP_MSG_READING_HEADER:
++ bptr = ((char *)&(GIOP_MESSAGE_BUFFER(retval)->message_header));
++ bptr += sizeof(GIOP_MESSAGE_BUFFER(retval)->message_header)
++ - retval->left_to_read;
++ break;
++ case GIOP_MSG_READING_BODY:
++ bptr = retval->cur; /* Reason for not using retval->message_body:
++ See note XXX1 below */
++ bptr += GIOP_MESSAGE_BUFFER(retval)->message_header.message_size;
++ bptr -= retval->left_to_read;
++ break;
++ default:
++ bptr = NULL;
++ }
++
++//printf("#1p1: READ %d bytes: errno %d state = %d\n", retval->left_to_read, errno, retval->state);
++ sysret = read(GIOP_CONNECTION_GET_FD(connection), bptr,
++ retval->left_to_read);
++
++ if((sysret == 0)
++ || ((sysret < 0) && (errno != EAGAIN))) {
++//printf("#1: sysret = %d bptr = 0x%X errno = %d\n", sysret, bptr, errno);
++ goto errout;
++ }
++
++ if(sysret > 0)
++ retval->left_to_read -= sysret;
++
++ if(retval->left_to_read == 0) {
++ /* we change states here */
++
++ switch(retval->state) {
++ case GIOP_MSG_READING_HEADER:
++ /* Check the magic stuff */
++ if(strncmp(GIOP_MESSAGE_BUFFER(retval)->message_header.magic, "GIOP", 4)
++ || GIOP_MESSAGE_BUFFER(retval)->message_header.GIOP_version[0] != 1) {
++//printf("#2: Not a GIOP thinger? '%s'\n", GIOP_MESSAGE_BUFFER(retval)->message_header.magic);
++ goto errout;
++ }
++ if(GIOP_MESSAGE_BUFFER(retval)->message_header.message_size == 0
++ && GIOP_MESSAGE_BUFFER(retval)->message_header.message_type != GIOP_CLOSECONNECTION) {
++// printf("Unexpected 0-length IIOP message\n");
++ goto errout;
++ }
++
++ if(giop_msg_conversion_needed(GIOP_MESSAGE_BUFFER(retval))) {
++ CORBA_unsigned_long t = GIOP_MESSAGE_BUFFER(retval)->message_header.message_size;
++ retval->decoder = (void (*)(gpointer, gpointer, gulong))iiop_byteswap;
++
++ iiop_byteswap((gpointer)&GIOP_MESSAGE_BUFFER(retval)->message_header.message_size,
++ (gpointer)&t, sizeof(t));
++ } else {
++#ifdef __KERNEL__
++ retval->decoder = (void (*)(gpointer,gpointer,gulong))__memcpy;
++#else
++ retval->decoder = (void (*)(gpointer,gpointer,gulong))memcpy;
++#endif
++ }
++
++ message_size = GIOP_MESSAGE_BUFFER(retval)->message_header.message_size;
++ if(!connection->is_auth
++ && message_size > 131072) {
++// printf("message size is bigger than 128k (%d)\n", message_size);
++ goto errout;
++ }
++
++ retval->message_body = g_malloc(message_size+sizeof(GIOPMessageHeader));
++ /* XXX1 This is a lame hack to work with the fact that
++ alignment is relative to the MessageHeader, not the RequestHeader */
++ retval->message_body = ((guchar *)retval->message_body) + sizeof(GIOPMessageHeader);
++ retval->cur = retval->message_body;
++ retval->state = GIOP_MSG_READING_BODY;
++ retval->left_to_read = message_size;
++ break;
++ case GIOP_MSG_READING_BODY:
++ if(giop_recv_decode_message(retval)) {
++//printf("giop_recv_decode_message FAILURE!\n");
++ goto errout;
++ }
++ connection->incoming_msg = NULL;
++ retval->state = GIOP_MSG_READY;
++ break;
++ default:
++ break;
++ }
++ } else if(retval->left_to_read < 0) {
++// printf("Whoa, we overstepped the number of bytes we were supposed to read by %d\n", -retval->left_to_read);
++ goto errout;
++ } else /* retval->left_to_read > 0 */ {
++ /* couldn't read the whole piece, save it */
++ retval = NULL;
++ }
++ } while(retval && retval->state != GIOP_MSG_READY);
++
++ return retval;
++
++ errout:
++ giop_recv_buffer_unuse(retval);
++ giop_main_handle_connection_exception(connection);
++ return NULL;
++}
++
++void
++giop_received_list_push(GIOPRecvBuffer *recv_buffer)
++{
++ GET_LOCK(incoming_bufs);
++ incoming_bufs = g_list_prepend(incoming_bufs, recv_buffer);
++ RELEASE_LOCK(incoming_bufs);
++}
++
++GIOPRecvBuffer *giop_received_list_pop(void)
++{
++ GList *head;
++ GIOPRecvBuffer *retval;
++
++ GET_LOCK(incoming_bufs);
++
++ head = incoming_bufs;
++
++ if(!head)
++ return NULL;
++
++ retval = head->data;
++ incoming_bufs = g_list_remove_link(incoming_bufs, head);
++ g_list_free_1 (head);
++
++ RELEASE_LOCK(incoming_bufs);
++
++ return retval;
++}
++
++static GIOPRecvBuffer *
++giop_received_list_check_reply(GIOP_unsigned_long request_id)
++{
++ GIOPRecvBuffer *retval = NULL;
++ GList *item = NULL;
++
++ GET_LOCK(incoming_bufs);
++
++ for(item = incoming_bufs; item; item = g_list_next(item))
++ {
++ if(GIOP_MESSAGE_BUFFER(item->data)->message_header.message_type == GIOP_REPLY
++ && GIOP_RECV_BUFFER(item->data)->message.u.reply.request_id == request_id) {
++ retval = item->data;
++ break;
++ }
++ }
++
++ if(retval)
++ incoming_bufs = g_list_remove(incoming_bufs, retval);
++
++ RELEASE_LOCK(incoming_bufs);
++
++ return retval;
++}
++
++/** giop_recv_reply_buffer_use_multiple
++ */
++GIOPRecvBuffer *
++giop_recv_reply_buffer_use_multiple(GArray *request_ids,
++ gboolean block_for_reply)
++{
++ return giop_recv_reply_buffer_use_multiple_2(NULL, request_ids, block_for_reply);
++}
++
++/* here is how it will be:
++ one routine for getting next message with a specified reply ID.
++ */
++
++GIOPRecvBuffer *
++giop_recv_reply_buffer_use_multiple_2(GIOPConnection *request_cnx,
++ GArray *request_ids,
++ gboolean block_for_reply)
++{
++ int i;
++ GIOPRecvBuffer *retval = NULL;
++ GSList *pushme = NULL;
++
++ do {
++ /*
++ * We _do_ want to put this inside the loop,
++ * because we may call ourselves recursively for different request_id's
++ */
++ for(i = 0; i < request_ids->len && !retval; i++)
++ retval = giop_received_list_check_reply(g_array_index(request_ids, GIOP_unsigned_long, i));
++
++ if(retval)
++ break;
++
++ retval = giop_main_next_message_2(block_for_reply, request_cnx);
++
++ if(retval) {
++ if(GIOP_MESSAGE_BUFFER(retval)->message_header.message_type == GIOP_REPLY) {
++ if(num_on_list(retval->message.u.reply.request_id,
++ (GIOP_unsigned_long *)request_ids->data,
++ request_ids->len))
++ break;
++ else {
++ pushme = g_slist_prepend(pushme, retval); retval = NULL;
++ }
++ } else {
++ if(IIOPIncomingMessageHandler)
++ IIOPIncomingMessageHandler(retval);
++ else {
++ pushme = g_slist_prepend(pushme, retval); retval = NULL;
++ }
++ retval = NULL;
++ }
++ } else
++ return NULL;
++
++ } while(!retval && block_for_reply);
++
++ g_slist_foreach(pushme, (GFunc)giop_received_list_push, NULL);
++ g_slist_free(pushme);
++
++ return retval;
++}
++
++GIOPRecvBuffer *
++giop_recv_reply_buffer_use(GIOP_unsigned_long request_id,
++ gboolean block_for_reply)
++{
++ return giop_recv_reply_buffer_use_2(NULL, request_id, block_for_reply);
++}
++
++GIOPRecvBuffer *
++giop_recv_reply_buffer_use_2(GIOPConnection *request_cnx,
++ GIOP_unsigned_long request_id,
++ gboolean block_for_reply)
++{
++ GArray fakeme;
++
++ fakeme.len = 1;
++ fakeme.data = (gpointer)&request_id;
++
++ return giop_recv_reply_buffer_use_multiple_2(request_cnx,
++ &fakeme,
++ block_for_reply);
++}
++
++GIOPRecvBuffer *
++giop_recv_locate_reply_buffer_use(GIOP_unsigned_long request_id,
++ gboolean block_for_reply)
++{
++ GIOPRecvBuffer *retval = NULL;
++
++ do {
++ /*
++ * We _do_ want to put this inside the loop,
++ * because we may call ourselves recursively for different request_id's
++ */
++ retval = giop_received_list_check_reply(request_id);
++
++ if(retval)
++ break;
++
++ retval = giop_main_next_message_2(TRUE, NULL);
++
++ if(retval) {
++ if(GIOP_MESSAGE_BUFFER(retval)->message_header.message_type == GIOP_LOCATEREPLY
++ && retval->message.u.locate_reply.request_id == request_id)
++ break;
++ else {
++ if(IIOPIncomingMessageHandler)
++ IIOPIncomingMessageHandler(retval);
++ else
++ giop_received_list_push(retval);
++ retval = NULL;
++ }
++ } else
++ return NULL;
++ } while(!retval && block_for_reply);
++
++ return retval;
++}
++
++static gint
++giop_recv_decode_message(GIOPRecvBuffer *buf)
++{
++ switch(GIOP_MESSAGE_BUFFER(buf)->message_header.message_type)
++ {
++ case GIOP_REPLY:
++ return giop_recv_reply_decode_message(buf);
++ break;
++ case GIOP_REQUEST:
++ return giop_recv_request_decode_message(buf);
++ break;
++ case GIOP_LOCATEREQUEST:
++ return(giop_recv_locate_request_decode_message(buf));
++ break;
++ case GIOP_LOCATEREPLY:
++ return(giop_recv_locate_reply_decode_message(buf));
++ break;
++ case GIOP_CLOSECONNECTION:
++ return 0;
++ break;
++ default:
++// printf("Don't know how to decode message type %d\n",
++// GIOP_MESSAGE_BUFFER(buf)->message_header.message_type);
++ return -1;
++ }
++}
++
++/* if(currptr+len > end || currptr + len < currptr) */
++
++/* This whole mess needs redoing. */
++#define CHECK_NEW_POS(buf, requested_increment) \
++if(!( (( ((guchar*)GIOP_RECV_BUFFER(buf)->cur) \
++ + (requested_increment) ) \
++ <= ( ((guchar *)GIOP_RECV_BUFFER(buf)->message_body) \
++ + GIOP_MESSAGE_BUFFER(buf)->message_header.message_size)) \
++ && ( ( ((guchar*)GIOP_RECV_BUFFER(buf)->cur) \
++ + (requested_increment) ) \
++ >= ((guchar*)GIOP_RECV_BUFFER(buf)->cur) ))) goto out;
++
++#define NEW_POS_OUT out: return -1
++
++#define SAFE_ALIGN_ADDRESS(buf, amt) G_STMT_START { \
++guchar *newval; \
++newval = ALIGN_ADDRESS(GIOP_RECV_BUFFER(buf)->cur, amt); \
++CHECK_NEW_POS(buf, newval-((guchar *)GIOP_RECV_BUFFER(buf)->cur)); \
++GIOP_RECV_BUFFER(buf)->cur = newval; \
++} G_STMT_END
++
++#define GET_ULONG(x) G_STMT_START{ \
++ (x) = GUINT32_SWAP_LE_BE((*(CORBA_unsigned_long *)buf->cur)); \
++ CHECK_NEW_POS(buf, sizeof(CORBA_unsigned_long)); \
++ buf->cur = ((guchar *)buf->cur) + sizeof(CORBA_unsigned_long); \
++ }G_STMT_END
++
++#define GET_ULONG_NC(x) G_STMT_START{ \
++ *(x) = (*((CORBA_unsigned_long *)(buf->cur))); \
++ CHECK_NEW_POS(buf, sizeof(CORBA_unsigned_long)); \
++ buf->cur = ((guchar *)buf->cur) + sizeof(CORBA_unsigned_long); \
++ }G_STMT_END
++
++/* There be dragons in here. */
++static gint
++giop_recv_reply_decode_message(GIOPRecvBuffer *buf)
++{
++ /*
++ enum ReplyStatusType {
++ NO_EXCEPTION,
++ USER_EXCEPTION,
++ SYSTEM_EXCEPTION,
++ LOCATION_FORWARD
++ };
++
++ struct ReplyHeader {
++ IOP::ServiceContextList service_context;
++ unsigned long request_id;
++ ReplyStatusType reply_status;
++ };
++ */
++ int i;
++
++ buf->message.u.reply.service_context._maximum = 0;
++ if(giop_msg_conversion_needed(GIOP_MESSAGE_BUFFER(buf)))
++ {
++ GET_ULONG(buf->message.u.reply.service_context._length);
++/* XXX bad hardcoded hack until someone gives a "right answer" to how to
++solve this problem */
++ if(buf->message.u.reply.service_context._length > 128) return -1;
++ buf->message.u.reply.service_context._buffer =
++ g_new(IOP_ServiceContext, buf->message.u.reply.service_context._length);
++
++ for(i = 0; i < buf->message.u.reply.service_context._length; i++)
++ {
++ SAFE_ALIGN_ADDRESS(buf, sizeof(GIOP_unsigned_long));
++ GET_ULONG(buf->message.u.reply.service_context._buffer[i].context_id);
++ GET_ULONG(buf->message.u.reply.service_context._buffer[i].context_data._length);
++ buf->message.u.reply.service_context._buffer[i].context_data._buffer =
++ buf->cur;
++ CHECK_NEW_POS(buf, buf->message.u.reply.service_context._buffer[i].context_data._length);
++ buf->cur = ((guchar *)buf->cur) + buf->message.u.reply.service_context._buffer[i].context_data._length;
++ }
++ GET_ULONG(buf->message.u.reply.request_id);
++ GET_ULONG(buf->message.u.reply.reply_status);
++ }
++ else
++ {
++
++ GET_ULONG_NC(&buf->message.u.reply.service_context._length);
++/* XXX bad hardcoded hack until someone gives a "right answer" to how to
++solve this problem */
++ if(buf->message.u.reply.service_context._length > 128) return -1;
++ buf->message.u.reply.service_context._buffer =
++ g_new(IOP_ServiceContext, buf->message.u.reply.service_context._length);
++
++ for(i = 0; i < buf->message.u.reply.service_context._length; i++)
++ {
++ SAFE_ALIGN_ADDRESS(buf, sizeof(CORBA_unsigned_long));
++ GET_ULONG_NC(&buf->message.u.reply.service_context._buffer[i].context_id);
++ GET_ULONG_NC(&buf->message.u.reply.service_context._buffer[i].context_data._length);
++ buf->message.u.reply.service_context._buffer[i].context_data._buffer =
++ buf->cur;
++ CHECK_NEW_POS(buf, buf->message.u.reply.service_context._buffer[i].context_data._length);
++ buf->cur = ((guchar *)buf->cur) + buf->message.u.reply.service_context._buffer[i].context_data._length;
++ }
++ GET_ULONG_NC(&buf->message.u.reply.request_id);
++ GET_ULONG_NC(&buf->message.u.reply.reply_status);
++ }
++
++#if 0
++ g_message("[%d] Received reply %d size %d to request %d",
++ getpid(),
++ buf->message.u.reply.reply_status,
++ GIOP_MESSAGE_BUFFER(buf)->message_header.message_size,
++ buf->message.u.reply.request_id);
++#endif
++
++ return 0;
++
++ NEW_POS_OUT;
++}
++
++static gint
++giop_recv_locate_reply_decode_message(GIOPRecvBuffer *buf)
++{
++ if(giop_msg_conversion_needed(GIOP_MESSAGE_BUFFER(buf)))
++ {
++ GET_ULONG(buf->message.u.locate_reply.request_id);
++ GET_ULONG(buf->message.u.locate_reply.locate_status);
++ }
++ else
++ {
++ GET_ULONG_NC(&buf->message.u.locate_reply.request_id);
++ GET_ULONG_NC(&buf->message.u.locate_reply.locate_status);
++ }
++
++ return 0;
++ NEW_POS_OUT;
++}
++
++static gint
++giop_recv_request_decode_message(GIOPRecvBuffer *buf)
++{
++ GIOP_unsigned_long len;
++ int i;
++
++ buf->message.u.request.service_context._maximum = 0;
++ if(giop_msg_conversion_needed(GIOP_MESSAGE_BUFFER(buf)))
++ {
++ GET_ULONG(buf->message.u.request.service_context._length);
++
++ /* XXX bad hardcoded hack until someone gives a "right answer"
++ to how to solve this problem */
++
++ if(buf->message.u.request.service_context._length > 128) return -1;
++ buf->message.u.request.service_context._buffer =
++ g_new(IOP_ServiceContext, buf->message.u.request.service_context._length);
++
++ for(i = 0; i < buf->message.u.request.service_context._length; i++)
++ {
++ SAFE_ALIGN_ADDRESS(buf, sizeof(GIOP_unsigned_long));
++ GET_ULONG(buf->message.u.request.service_context._buffer[i].context_id);
++ GET_ULONG(buf->message.u.request.service_context._buffer[i].context_data._length);
++ buf->message.u.request.service_context._buffer[i].context_data._buffer =
++ buf->cur;
++ CHECK_NEW_POS(buf, buf->message.u.request.service_context._buffer[i].context_data._length);
++ buf->cur = ((guchar *)buf->cur) + buf->message.u.request.service_context._buffer[i].context_data._length;
++ }
++
++ SAFE_ALIGN_ADDRESS(buf, sizeof(GIOP_unsigned_long));
++ GET_ULONG(buf->message.u.request.request_id);
++ buf->message.u.request.response_expected = *((GIOP_boolean *)buf->cur);
++ CHECK_NEW_POS(buf, sizeof(GIOP_boolean));
++ buf->cur = ((guchar *)buf->cur) + sizeof(GIOP_boolean);
++
++ SAFE_ALIGN_ADDRESS(buf, sizeof(GIOP_unsigned_long));
++ GET_ULONG(buf->message.u.request.object_key._length);
++ buf->message.u.request.object_key._buffer = buf->cur;
++
++ CHECK_NEW_POS(buf, buf->message.u.request.object_key._length);
++ buf->cur = ((guchar *)buf->cur) + buf->message.u.request.object_key._length;
++
++ SAFE_ALIGN_ADDRESS(buf, sizeof(GIOP_unsigned_long));
++ GET_ULONG(len);
++ buf->message.u.request.operation = buf->cur;
++
++ CHECK_NEW_POS(buf, len);
++ buf->cur = ((guchar *)buf->cur) + len;
++
++ SAFE_ALIGN_ADDRESS(buf, sizeof(GIOP_unsigned_long));
++ GET_ULONG(buf->message.u.request.requesting_principal._length);
++ buf->message.u.request.requesting_principal._buffer = buf->cur;
++
++ CHECK_NEW_POS(buf, buf->message.u.request.requesting_principal._length);
++ buf->cur = ((guchar *)buf->cur) + buf->message.u.request.requesting_principal._length;
++ }
++ else
++ {
++ GET_ULONG_NC(&buf->message.u.request.service_context._length);
++
++ /* XXX bad hardcoded hack until someone gives a "right answer"
++ to how to solve this problem */
++ if(buf->message.u.request.service_context._length > 128) return -1;
++ buf->message.u.request.service_context._buffer =
++ g_new(IOP_ServiceContext, buf->message.u.request.service_context._length);
++
++ for(i = 0; i < buf->message.u.request.service_context._length; i++)
++ {
++ SAFE_ALIGN_ADDRESS(buf, sizeof(GIOP_unsigned_long));
++ GET_ULONG_NC(&buf->message.u.request.service_context._buffer[i].context_id);
++ GET_ULONG_NC(&buf->message.u.request.service_context._buffer[i].context_data._length);
++ buf->message.u.request.service_context._buffer[i].context_data._buffer =
++ buf->cur;
++ CHECK_NEW_POS(buf, buf->message.u.request.service_context._buffer[i].context_data._length);
++ buf->cur = ((guchar *)buf->cur) + buf->message.u.request.service_context._buffer[i].context_data._length;
++ }
++ SAFE_ALIGN_ADDRESS(buf, sizeof(GIOP_unsigned_long));
++ GET_ULONG_NC(&buf->message.u.request.request_id);
++ buf->message.u.request.response_expected = *((GIOP_boolean *)buf->cur);
++ CHECK_NEW_POS(buf, sizeof(GIOP_boolean));
++ buf->cur = ((guchar *)buf->cur) + sizeof(GIOP_boolean);
++ SAFE_ALIGN_ADDRESS(buf, sizeof(GIOP_unsigned_long));
++ GET_ULONG_NC(&buf->message.u.request.object_key._length);
++ buf->message.u.request.object_key._buffer = buf->cur;
++ CHECK_NEW_POS(buf, buf->message.u.request.object_key._length);
++ buf->cur = ((guchar *)buf->cur) + buf->message.u.request.object_key._length;
++
++ SAFE_ALIGN_ADDRESS(buf, sizeof(GIOP_unsigned_long));
++ GET_ULONG_NC(&len);
++ buf->message.u.request.operation = buf->cur;
++ CHECK_NEW_POS(buf, len);
++ buf->cur = ((guchar *)buf->cur) + len;
++
++ SAFE_ALIGN_ADDRESS(buf, sizeof(GIOP_unsigned_long));
++ GET_ULONG_NC(&buf->message.u.request.requesting_principal._length);
++ buf->message.u.request.requesting_principal._buffer = buf->cur;
++ CHECK_NEW_POS(buf, buf->message.u.request.requesting_principal._length);
++ buf->cur = ((guchar *)buf->cur) + buf->message.u.request.requesting_principal._length;
++ }
++
++#if 0
++ g_message("[%d] Received request %s size %d ID %d",
++ getpid(),
++ buf->message.u.request.operation,
++ GIOP_MESSAGE_BUFFER(buf)->message_header.message_size,
++ buf->message.u.request.request_id);
++#endif
++
++ return 0;
++
++ NEW_POS_OUT;
++}
++
++static gint
++giop_recv_locate_request_decode_message(GIOPRecvBuffer *buf)
++{
++ if(giop_msg_conversion_needed(GIOP_MESSAGE_BUFFER(buf)))
++ {
++ SAFE_ALIGN_ADDRESS(buf, sizeof(GIOP_unsigned_long));
++ GET_ULONG(buf->message.u.locate_request.request_id);
++ SAFE_ALIGN_ADDRESS(buf, sizeof(GIOP_unsigned_long));
++ GET_ULONG(buf->message.u.locate_request.object_key._length);
++ buf->message.u.locate_request.object_key._buffer = buf->cur;
++ CHECK_NEW_POS(buf, buf->message.u.locate_request.object_key._length);
++ buf->cur = ((guchar *)buf->cur) + buf->message.u.locate_request.object_key._length;
++ }
++ else
++ {
++ SAFE_ALIGN_ADDRESS(buf, sizeof(GIOP_unsigned_long));
++ GET_ULONG_NC(&buf->message.u.locate_request.request_id);
++ SAFE_ALIGN_ADDRESS(buf, sizeof(GIOP_unsigned_long));
++ GET_ULONG_NC(&buf->message.u.locate_request.object_key._length);
++ buf->message.u.locate_request.object_key._buffer = buf->cur;
++ CHECK_NEW_POS(buf, buf->message.u.locate_request.object_key._length);
++ buf->cur = ((guchar *)buf->cur) + buf->message.u.locate_request.object_key._length;
++ }
++
++ return 0;
++
++ NEW_POS_OUT;
++}
++
++gboolean
++num_on_list(GIOP_unsigned_long num,
++ const GIOP_unsigned_long *request_ids,
++ GIOP_unsigned_long req_count)
++{
++ int i;
++ for(i = 0; i < req_count; i++)
++ {
++ if(num == request_ids[i])
++ return TRUE;
++ }
++
++ return FALSE;
++}
+diff -urN linux-2.4.1/net/korbit/IIOP/giop-msg-buffer.h linux-2.4.1-korbit/net/korbit/IIOP/giop-msg-buffer.h
+--- linux-2.4.1/net/korbit/IIOP/giop-msg-buffer.h Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/IIOP/giop-msg-buffer.h Thu Feb 1 16:19:47 2001
+@@ -0,0 +1,228 @@
++#ifndef GIOP_MSG_BUFFER_H
++#define GIOP_MSG_BUFFER_H 1
++
++#include "IIOP.h"
++/* For struct iovec */
++#include <sys/uio.h>
++
++typedef enum {
++ GIOP_REQUEST,
++ GIOP_REPLY,
++ GIOP_CANCELREQUEST,
++ GIOP_LOCATEREQUEST,
++ GIOP_LOCATEREPLY,
++ GIOP_CLOSECONNECTION,
++ GIOP_MESSAGEERROR,
++ GIOP_FRAGMENT
++} GIOPMsgType;
++
++/* GIOP message header */
++typedef struct _GIOPMessageHeader {
++ GIOP_char magic[4];
++ GIOP_char GIOP_version[2];
++ GIOP_octet flags;
++
++ /*
++ * We should really use GIOPMsgType
++ * but that enum winds up being an int...
++ */
++ GIOP_octet message_type;
++
++ GIOP_unsigned_long message_size;
++} GIOPMessageHeader;
++
++#define GIOP_MESSAGE_BUFFER(x) ((GIOPMessageBuffer *)x)
++typedef struct _GIOPMessageBuffer
++{
++ /* The connection that this message will go out over... */
++ GIOPConnection *connection;
++
++ GArray *iovecs;
++ GIOPMessageHeader message_header;
++} GIOPMessageBuffer;
++
++#include "../orb/iop.h"
++
++/* GIOP_REQUEST header */
++typedef enum {
++ GIOP_NO_EXCEPTION,
++ GIOP_USER_EXCEPTION,
++ GIOP_SYSTEM_EXCEPTION,
++ GIOP_LOCATION_FORWARD
++} GIOPReplyStatusType;
++
++typedef struct _GIOPMessageRequest {
++ IOP_ServiceContextList service_context;
++ GIOP_unsigned_long request_id;
++ GIOP_boolean response_expected;
++ CORBA_sequence_octet object_key;
++ CORBA_char *operation;
++ CORBA_Principal requesting_principal;
++} GIOPMessageRequest;
++
++typedef struct _GIOPMessageReply {
++ IOP_ServiceContextList service_context;
++ GIOP_unsigned_long request_id;
++ GIOPReplyStatusType reply_status;
++} GIOPMessageReply;
++
++typedef struct _GIOPMessageCancelRequest {
++ GIOP_unsigned_long request_id;
++} GIOPMessageCancelRequest;
++
++typedef struct _GIOPMessageLocateRequest {
++ GIOP_unsigned_long request_id;
++ CORBA_sequence_octet object_key;
++} GIOPMessageLocateRequest;
++
++typedef enum {
++ GIOP_UNKNOWN_OBJECT,
++ GIOP_OBJECT_HERE,
++ GIOP_OBJECT_FORWARD
++} GIOPLocateStatusType;
++
++typedef struct _GIOPMessageLocateReply {
++ GIOP_unsigned_long request_id;
++ GIOPLocateStatusType locate_status;
++} GIOPMessageLocateReply;
++
++typedef struct _GIOPMessage
++{
++ union {
++ GIOPMessageRequest request;
++ GIOPMessageReply reply;
++ GIOPMessageCancelRequest cancel_request;
++ GIOPMessageLocateRequest locate_request;
++ GIOPMessageLocateReply locate_reply;
++ } u;
++} GIOPMessage;
++
++typedef enum {
++ GIOP_MSG_READING_HEADER,
++ GIOP_MSG_READING_BODY,
++ GIOP_MSG_READY
++} GIOPMessageBufferState;
++
++#define GIOP_SEND_BUFFER(x) ((GIOPSendBuffer *)x)
++typedef struct _GIOPSendBuffer
++{
++ GIOPMessageBuffer message_buffer;
++
++ gpointer indirect;
++
++ GMemChunk *indirects; /* Request buffers only (at present) */
++ gulong indirect_used;
++
++ GIOPMessage message;
++ CORBA_unsigned_long scontext_tmp;
++} GIOPSendBuffer;
++
++#define GIOP_RECV_BUFFER(x) ((GIOPRecvBuffer *)x)
++typedef struct _GIOPRecvBuffer
++{
++ GIOPMessageBuffer message_buffer;
++ GIOPMessage message;
++
++ gpointer message_body;
++ gpointer cur;
++
++ void (*decoder)(gpointer dest, gpointer src, gulong len);
++
++ GIOPMessageBufferState state;
++ gint left_to_read;
++} GIOPRecvBuffer;
++
++/* This function needs to be called before useful things happen */
++void giop_message_buffer_init(void);
++
++gint giop_send_buffer_write(GIOPSendBuffer *request_buffer);
++
++void
++giop_message_buffer_append_mem_a(GIOPMessageBuffer *request_buffer,
++ gconstpointer mem_region,
++ gulong mem_region_length);
++void
++giop_message_buffer_append_mem(GIOPMessageBuffer *request_buffer,
++ gconstpointer mem_region,
++ gulong mem_region_length);
++
++/*
++ * This copies the value into a request-specific buffer before
++ * adding it to the list
++ */
++gpointer
++giop_send_buffer_append_mem_indirect_a(GIOPSendBuffer *request_buffer,
++ gconstpointer mem_region,
++ gulong mem_region_length);
++gpointer
++giop_send_buffer_append_mem_indirect(GIOPSendBuffer *request_buffer,
++ gconstpointer mem_region,
++ gulong mem_region_length);
++
++GIOPSendBuffer *
++giop_send_request_buffer_use(GIOPConnection *connection,
++ const IOP_ServiceContextList *service_context,
++ GIOP_unsigned_long request_id,
++ GIOP_boolean response_expected,
++ const struct iovec *object_key_vec,
++ const struct iovec *operation_vec,
++ const struct iovec *principal_vec);
++GIOPSendBuffer *
++giop_send_reply_buffer_use(GIOPConnection *connection,
++ const IOP_ServiceContextList *service_context,
++ GIOP_unsigned_long request_id,
++ GIOPReplyStatusType reply_status);
++GIOPSendBuffer *
++giop_send_locate_request_buffer_use(GIOPConnection *connection,
++ GIOP_unsigned_long request_id,
++ const struct iovec *object_key_vec);
++GIOPSendBuffer *
++giop_send_locate_reply_buffer_use(GIOPConnection *connection,
++ GIOP_unsigned_long request_id,
++ GIOPLocateStatusType reply_status);
++
++void giop_send_buffer_unuse(GIOPSendBuffer *send_buffer);
++
++GIOP_unsigned_long giop_get_request_id(void);
++
++GIOPRecvBuffer *
++giop_recv_reply_buffer_use(GIOP_unsigned_long request_id,
++ gboolean block_for_reply);
++GIOPRecvBuffer *
++giop_recv_reply_buffer_use_2(GIOPConnection *request_cnx,
++ GIOP_unsigned_long request_id,
++ gboolean block_for_reply);
++
++/* For DII - hands back the first received request matching an id on the list */
++GIOPRecvBuffer *
++giop_recv_reply_buffer_use_multiple(GArray *request_ids,
++ gboolean block_for_reply);
++GIOPRecvBuffer *
++giop_recv_reply_buffer_use_multiple_2(GIOPConnection *request_cnx,
++ GArray *request_ids,
++ gboolean block_for_reply);
++
++GIOPRecvBuffer *
++giop_recv_locate_reply_buffer_use(GIOP_unsigned_long request_id,
++ gboolean block_for_reply);
++
++/*
++ * For server-side use. It's the responsibility of the caller to do
++ * any select()ion desired
++ */
++GIOPRecvBuffer *
++giop_recv_message_buffer_use(GIOPConnection *connection);
++
++void giop_recv_buffer_unuse(GIOPRecvBuffer *buffer);
++
++/*
++ * This is used for sending (and recving, if we ever
++ * get zero-copy receives implemented) alignment bytes
++ */
++extern char giop_scratch_space[2048];
++gulong giop_message_buffer_do_alignment(GIOPMessageBuffer *buffer,
++ gulong align_for);
++
++#define giop_msg_conversion_needed(msgbuf) (conversion_needed(GIOP_MESSAGE_BUFFER(msgbuf)->message_header.flags & 1))
++
++#endif /* GIOP_MSG_BUFFER_H */
+diff -urN linux-2.4.1/net/korbit/IIOP/iiop-encoders.h linux-2.4.1-korbit/net/korbit/IIOP/iiop-encoders.h
+--- linux-2.4.1/net/korbit/IIOP/iiop-encoders.h Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/IIOP/iiop-encoders.h Thu Feb 1 11:46:51 2001
+@@ -0,0 +1,25 @@
++#ifndef ENCODERS_H
++#define ENCODERS_H 1
++
++#define ENCODER_DEC(typename) \
++void giop_encoder_##typename##(GIOPSendBuffer *send_buffer, \
++ const typename *mem)
++
++#define ENCODER_CALL(typename, mem) \
++giop_encoder_##typename##(send_buffer, mem)
++
++#define AP(m, l) giop_message_buffer_append_mem(GIOP_MESSAGE_BUFFER(send_buffer), m, l)
++#define APA(m, l) giop_message_buffer_append_mem_a(GIOP_MESSAGE_BUFFER(send_buffer), m, l)
++
++#define API(m, l) giop_send_buffer_append_mem_indirect(send_buffer, m, l)
++#define APIA(m, l) giop_send_buffer_append_mem_indirect_a(send_buffer, m, l)
++
++ENCODER_DEC(IOP_ServiceContext);
++ENCODER_DEC(IOP_ServiceContextList);
++ENCODER_DEC(CORBA_sequence_octet);
++ENCODER_DEC(CORBA_Principal);
++#define giop_encoder_CORBA_Principal(rb, mem) \
++ giop_encoder_CORBA_sequence_octet(rb, mem)
++ENCODER_DEC(CORBA_char);
++
++#endif /* ENCODERS_H */
+diff -urN linux-2.4.1/net/korbit/IIOP/iiop-endian.c linux-2.4.1-korbit/net/korbit/IIOP/iiop-endian.c
+--- linux-2.4.1/net/korbit/IIOP/iiop-endian.c Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/IIOP/iiop-endian.c Thu Feb 1 11:46:51 2001
+@@ -0,0 +1,12 @@
++#define IIOP_DO_NOT_INLINE_IIOP_BYTESWAP
++#include "iiop-endian.h"
++
++void iiop_byteswap(guchar *outdata,
++ const guchar *data,
++ gulong datalen)
++{
++ const guchar *source_ptr = data;
++ guchar *dest_ptr = (guchar *)outdata + datalen - 1;
++ while(dest_ptr >= outdata)
++ *dest_ptr-- = *source_ptr++;
++}
+diff -urN linux-2.4.1/net/korbit/IIOP/iiop-endian.h linux-2.4.1-korbit/net/korbit/IIOP/iiop-endian.h
+--- linux-2.4.1/net/korbit/IIOP/iiop-endian.h Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/IIOP/iiop-endian.h Thu Feb 1 11:46:51 2001
+@@ -0,0 +1,42 @@
++#ifndef IIOP_ENDIAN_H
++#define IIOP_ENDIAN_H 1
++
++#include <glib.h>
++
++#if G_BYTE_ORDER == G_BIG_ENDIAN
++
++# define FLAG_ENDIANNESS FLAG_BIG_ENDIAN
++# define conversion_needed(to_endianness) ((to_endianness)!=FLAG_BIG_ENDIAN)
++
++#elif G_BYTE_ORDER == G_LITTLE_ENDIAN
++
++# define FLAG_ENDIANNESS FLAG_LITTLE_ENDIAN
++# define conversion_needed(to_endianness) ((to_endianness)!=FLAG_LITTLE_ENDIAN)
++
++#else
++
++#error "Unsupported endianness on this system."
++
++#endif
++
++#define FLAG_BIG_ENDIAN 0
++#define FLAG_LITTLE_ENDIAN 1
++
++/* This is also defined in IIOP-types.c */
++void iiop_byteswap(guchar *outdata,
++ const guchar *data,
++ gulong datalen);
++
++#if defined(G_CAN_INLINE) && !defined(IIOP_DO_NOT_INLINE_IIOP_BYTESWAP)
++G_INLINE_FUNC void iiop_byteswap(guchar *outdata,
++ const guchar *data,
++ gulong datalen)
++{
++ const guchar *source_ptr = data;
++ guchar *dest_ptr = outdata + datalen - 1;
++ while(dest_ptr >= outdata)
++ *dest_ptr-- = *source_ptr++;
++}
++#endif
++
++#endif
+diff -urN linux-2.4.1/net/korbit/IIOP/iiop-endianP.h linux-2.4.1-korbit/net/korbit/IIOP/iiop-endianP.h
+--- linux-2.4.1/net/korbit/IIOP/iiop-endianP.h Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/IIOP/iiop-endianP.h Thu Feb 1 16:19:47 2001
+@@ -0,0 +1,11 @@
++#ifndef IIOP_ENDIANP_H
++#define IIOP_ENDIANP_H 1
++
++/* This is pretty much "here" */
++
++#include "config.h"
++#include "IIOP.h"
++
++#include "iiop-endian.h"
++
++#endif /* !IIOP_ENDIANP_H */
+diff -urN linux-2.4.1/net/korbit/Makefile linux-2.4.1-korbit/net/korbit/Makefile
+--- linux-2.4.1/net/korbit/Makefile Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/Makefile Thu Feb 1 15:57:33 2001
+@@ -0,0 +1,22 @@
++#
++# Makefile for KORBit
++#
++# Note! Dependencies are done automagically by 'make dep', which also
++# removes any old dependencies. DON'T put your own dependencies here
++# unless it's something special (ie not a .c file).
++#
++# Note 2! The CFLAGS definition is now in the main makefile...
++
++O_TARGET := korbit.o
++
++subdir-y := kglib orb IIOP ORBitutil modules
++subdir-m := modules
++
++obj-y := kglib/kglib.o orb/orblib.o IIOP/IIOPlib.o ORBitutil/ORBitutillib.o exported_symbols.o
++
++export-objs := exported_symbols.o
++
++EXTRA_CFLAGS = -D__KORBIT__ -DHAVE_CONFIG_H -I. -I./include -I./kglib -I./ORBitutil -nostdinc
++
++include $(TOPDIR)/Rules.make
++
+diff -urN linux-2.4.1/net/korbit/ORBitutil/CVS/Entries linux-2.4.1-korbit/net/korbit/ORBitutil/CVS/Entries
+--- linux-2.4.1/net/korbit/ORBitutil/CVS/Entries Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/ORBitutil/CVS/Entries Thu Feb 1 11:46:52 2001
+@@ -0,0 +1,13 @@
++/Makefile/1.4/Thu Feb 1 09:46:52 2001//
++/basic_types.h/1.1.1.1/Thu Feb 1 09:46:52 2001//
++/compat.c/1.1.1.1/Thu Feb 1 09:46:52 2001//
++/compat.h/1.1.1.1/Thu Feb 1 09:46:52 2001//
++/orbit-os-config.h/1.2/Thu Feb 1 09:46:52 2001//
++/os-feature-alloca.h/1.1.1.1/Thu Feb 1 09:46:52 2001//
++/os-specifics.h/1.1.1.1/Thu Feb 1 09:46:52 2001//
++/thread-safety.c/1.1.1.1/Thu Feb 1 09:46:52 2001//
++/thread-safety.h/1.1.1.1/Thu Feb 1 09:46:52 2001//
++/trace.c/1.2/Thu Feb 1 09:46:52 2001//
++/trace.h/1.1.1.1/Thu Feb 1 09:46:52 2001//
++/util.h/1.1.1.1/Thu Feb 1 09:46:52 2001//
++D
+diff -urN linux-2.4.1/net/korbit/ORBitutil/CVS/Repository linux-2.4.1-korbit/net/korbit/ORBitutil/CVS/Repository
+--- linux-2.4.1/net/korbit/ORBitutil/CVS/Repository Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/ORBitutil/CVS/Repository Thu Feb 1 11:46:51 2001
+@@ -0,0 +1 @@
++/cvsroot/korbit/linux/net/korbit/ORBitutil
+diff -urN linux-2.4.1/net/korbit/ORBitutil/CVS/Root linux-2.4.1-korbit/net/korbit/ORBitutil/CVS/Root
+--- linux-2.4.1/net/korbit/ORBitutil/CVS/Root Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/ORBitutil/CVS/Root Thu Feb 1 11:46:51 2001
+@@ -0,0 +1 @@
++vraalsen@cvs.korbit.sourceforge.net:/cvsroot/korbit
+diff -urN linux-2.4.1/net/korbit/ORBitutil/Makefile linux-2.4.1-korbit/net/korbit/ORBitutil/Makefile
+--- linux-2.4.1/net/korbit/ORBitutil/Makefile Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/ORBitutil/Makefile Thu Feb 1 11:46:52 2001
+@@ -0,0 +1,17 @@
++#
++# Makefile for KORBit/ORBitutil
++#
++# Note! Dependencies are done automagically by 'make dep', which also
++# removes any old dependencies. DON'T put your own dependencies here
++# unless it's something special (ie not a .o file).
++#
++# Note 2! The CFLAGS definition is now in the main makefile...
++
++O_TARGET := ORBitutillib.o
++
++#obj-m := $(O_TARGET)
++obj-y := compat.o thread-safety.o trace.o
++
++EXTRA_CFLAGS = -D__KORBIT__ -DHAVE_CONFIG_H -I. -I.. -I../include -I../kglib -I../ORBitutil -nostdinc
++
++include $(TOPDIR)/Rules.make
+diff -urN linux-2.4.1/net/korbit/ORBitutil/basic_types.h linux-2.4.1-korbit/net/korbit/ORBitutil/basic_types.h
+--- linux-2.4.1/net/korbit/ORBitutil/basic_types.h Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/ORBitutil/basic_types.h Thu Feb 1 11:46:52 2001
+@@ -0,0 +1,46 @@
++#ifndef BASIC_TYPES_H
++#define BASIC_TYPES_H 1
++
++#include <glib.h>
++
++typedef gint16 CORBA_short;
++typedef gint32 CORBA_long;
++typedef guint16 CORBA_unsigned_short;
++typedef guint32 CORBA_unsigned_long;
++typedef gfloat CORBA_float;
++typedef gdouble CORBA_double;
++typedef char CORBA_char;
++typedef guchar CORBA_boolean;
++typedef guchar CORBA_octet;
++typedef gdouble CORBA_long_double;
++typedef guint16 CORBA_wchar; /* I'm not sure what size a wchar is supposed to be */
++
++/* Just a peeve */
++typedef CORBA_char GIOP_char;
++typedef CORBA_wchar GIOP_wchar;
++typedef CORBA_short GIOP_short;
++typedef CORBA_long GIOP_long;
++typedef CORBA_unsigned_short GIOP_unsigned_short;
++typedef CORBA_unsigned_long GIOP_unsigned_long;
++typedef CORBA_octet GIOP_octet;
++typedef CORBA_long GIOP_enum;
++typedef CORBA_boolean GIOP_boolean;
++typedef CORBA_float GIOP_float;
++typedef CORBA_double GIOP_double;
++typedef CORBA_long_double GIOP_long_double;
++
++#ifdef G_HAVE_GINT64
++#define HAVE_CORBA_LONG_LONG
++/* According to the spec, these two are optional. We support them if we can. */
++typedef gint64 CORBA_long_long;
++typedef guint64 CORBA_unsigned_long_long;
++typedef CORBA_long_long GIOP_long_long;
++typedef CORBA_unsigned_long_long GIOP_unsigned_long_long;
++#else
++#warning ""
++#warning "You don't G_HAVE_GINT64 defined in glib."
++#warning "Please make sure you don't have an old glibconfig.h lying around."
++#warning ""
++#endif
++
++#endif
+diff -urN linux-2.4.1/net/korbit/ORBitutil/compat.c linux-2.4.1-korbit/net/korbit/ORBitutil/compat.c
+--- linux-2.4.1/net/korbit/ORBitutil/compat.c Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/ORBitutil/compat.c Thu Feb 1 11:46:52 2001
+@@ -0,0 +1,43 @@
++#include "config.h"
++#include "util.h"
++
++#define MAX_IOVS 16
++
++int g_writev(int fd, const struct iovec * vector, size_t count)
++{
++ int retval = 0;
++
++ while(count > MAX_IOVS) {
++ retval += writev(fd, vector, MAX_IOVS);
++ vector += MAX_IOVS; count -= MAX_IOVS;
++ }
++
++ return writev(fd, vector, count) + retval;
++}
++
++#ifndef HAVE_INET_ATON
++#include <netinet/in.h>
++#include <string.h>
++int inet_aton(const char *cp, struct in_addr *inp)
++{
++ union {
++ unsigned int n;
++ char parts[4];
++ } u;
++ int a=0,b=0,c=0,d=0, i;
++
++ i = sscanf(cp, "%d.%d.%d.%d%*s", &a, &b, &c, &d);
++
++ if(i != 4)
++ return 0;
++
++ u.parts[0] = a;
++ u.parts[1] = b;
++ u.parts[2] = c;
++ u.parts[3] = d;
++
++ inp->s_addr = u.n;
++
++ return 1;
++}
++#endif
+diff -urN linux-2.4.1/net/korbit/ORBitutil/compat.h linux-2.4.1-korbit/net/korbit/ORBitutil/compat.h
+--- linux-2.4.1/net/korbit/ORBitutil/compat.h Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/ORBitutil/compat.h Thu Feb 1 11:46:52 2001
+@@ -0,0 +1,8 @@
++#ifndef ORBITUTIL_COMPAT_H
++#define ORBITUTIL_COMPAT_H 1
++#include <sys/types.h>
++#include <sys/uio.h>
++
++int g_writev(int fd, const struct iovec * vector, size_t count);
++
++#endif /*#define ORBITUTIL_COMPAT_H 1 */
+diff -urN linux-2.4.1/net/korbit/ORBitutil/orbit-os-config.h linux-2.4.1-korbit/net/korbit/ORBitutil/orbit-os-config.h
+--- linux-2.4.1/net/korbit/ORBitutil/orbit-os-config.h Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/ORBitutil/orbit-os-config.h Thu Feb 1 11:46:52 2001
+@@ -0,0 +1,8 @@
++#ifndef OS_CONFIG_H
++#define OS_CONFIG_H 1
++
++#ifndef __KORBIT__
++#define ORBIT_HAVE_ALLOCA_H 1
++#endif
++
++#endif
+diff -urN linux-2.4.1/net/korbit/ORBitutil/os-feature-alloca.h linux-2.4.1-korbit/net/korbit/ORBitutil/os-feature-alloca.h
+--- linux-2.4.1/net/korbit/ORBitutil/os-feature-alloca.h Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/ORBitutil/os-feature-alloca.h Thu Feb 1 11:46:52 2001
+@@ -0,0 +1,26 @@
++#ifndef OS_FEATURE_ALLOCA_H
++#define OS_FEATURE_ALLOCA_H 1
++
++# if ORBIT_HAVE_ALLOCA_H
++# include <alloca.h>
++# endif
++
++# include <string.h>
++
++# if defined(__GNUC__)
++
++# if defined(__STRICT_ANSI__)
++# define alloca __builtin_alloca
++# endif
++
++# elif !(ORBIT_HAVE_ALLOCA_H)
++
++# if defined(_AIX)
++ #pragma alloca
++# elif !defined(alloca) /* predefined by HP cc +Olibcalls */
++char *alloca ();
++# endif
++
++# endif /* __GNUC__ etc. */
++
++#endif /* OS_FEATURE_ALLOCA_H */
+diff -urN linux-2.4.1/net/korbit/ORBitutil/os-specifics.h linux-2.4.1-korbit/net/korbit/ORBitutil/os-specifics.h
+--- linux-2.4.1/net/korbit/ORBitutil/os-specifics.h Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/ORBitutil/os-specifics.h Thu Feb 1 11:46:52 2001
+@@ -0,0 +1,12 @@
++#ifndef ORBITUTIL_OS_SPECIFICS_H
++#define ORBITUTIL_OS_SPECIFICS_H 1
++
++#include <ORBitutil/orbit-os-config.h>
++
++#include <ORBitutil/os-feature-alloca.h>
++
++/* This file should be a bunch of #ifdef's to #include the
++ os-<osname>.h for the current OS. It is intended to abstract the
++ gunkiness necessary to get some OS's to build ORBit properly. */
++
++#endif
+diff -urN linux-2.4.1/net/korbit/ORBitutil/thread-safety.c linux-2.4.1-korbit/net/korbit/ORBitutil/thread-safety.c
+--- linux-2.4.1/net/korbit/ORBitutil/thread-safety.c Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/ORBitutil/thread-safety.c Thu Feb 1 11:46:52 2001
+@@ -0,0 +1,19 @@
++#include "util.h"
++
++#ifdef NOT_REENTRANT
++#include <pthread.h>
++
++pthread_key_t thread_data;
++
++void init_thread_data(void) __attribute__ ((constructor));
++
++void init_thread_data(void)
++{
++ pthread_key_create(&thread_data, NULL);
++}
++
++#else
++
++gpointer prog_data = NULL;
++
++#endif
+diff -urN linux-2.4.1/net/korbit/ORBitutil/thread-safety.h linux-2.4.1-korbit/net/korbit/ORBitutil/thread-safety.h
+--- linux-2.4.1/net/korbit/ORBitutil/thread-safety.h Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/ORBitutil/thread-safety.h Thu Feb 1 11:46:52 2001
+@@ -0,0 +1,36 @@
++#ifndef THREAD_SAFETY_H
++#define THREAD_SAFETY_H 1
++
++#ifdef NOT_REENTRANT
++
++#include <pthread.h>
++
++#define DEFINE_LOCK(x) pthread_mutex_t x##_lock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
++#define INIT_LOCK(x) /* We use static initialization, see above */
++#define GET_LOCK(x) pthread_mutex_lock(&x##_lock)
++#define RELEASE_LOCK(x) pthread_mutex_unlock(&x##_lock)
++#define PARAM_LOCK(x) pthread_mutex_t x##_lock
++#define LOCK_NAME(x) x##_lock
++#define EXTERN_LOCK(x) extern pthread_mutex_t x##_lock
++extern pthread_key_t thread_data;
++#define GET_THREAD_DATA() pthread_getspecific(thread_data)
++#define SET_THREAD_DATA(x) pthread_setspecific(thread_data, (x))
++
++#else
++
++/* stupid work around ANSI & empty semicolons. */
++#define DEFINE_LOCK(x)
++#define INIT_LOCK(x)
++#define GET_LOCK(x)
++#define RELEASE_LOCK(x)
++#define PARAM_LOCK(x) gpointer x##_lock
++#define LOCK_NAME(x) NULL
++#define EXTERN_LOCK(x)
++
++extern gpointer prog_data;
++#define GET_THREAD_DATA() prog_data
++#define SET_THREAD_DATA(x) (prog_data = (x))
++
++#endif
++
++#endif /* THREAD_SAFETY_H */
+diff -urN linux-2.4.1/net/korbit/ORBitutil/trace.c linux-2.4.1-korbit/net/korbit/ORBitutil/trace.c
+--- linux-2.4.1/net/korbit/ORBitutil/trace.c Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/ORBitutil/trace.c Thu Feb 1 11:46:52 2001
+@@ -0,0 +1,94 @@
++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
++
++/*
++ * ORBit: A CORBA v2.2 ORB
++ *
++ * Copyright (C) 1998 Richard H. Porter
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Library General Public
++ * License as published by the Free Software Foundation; either
++ * version 2 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Library General Public License for more details.
++ *
++ * You should have received a copy of the GNU Library General Public
++ * License along with this library; if not, write to the Free
++ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Author: Dick Porter <dick@acm.org>
++ *
++ */
++
++#include <stdio.h>
++#include <stdarg.h>
++
++#include "trace.h"
++
++/*
++ * The function to call to handle trace messages, or NULL to use the default
++ * of printing to stderr.
++ */
++#ifdef ORBIT_DEBUG
++static int (* TraceCallback)(char *, va_list)=NULL;
++static int TraceModules=0;
++static ORBit_TraceLevel TraceMaxLevel=0;
++
++const char *ORBit_Trace_levellist[] = {
++ "ALERT ",
++ "CRITICAL",
++ "ERROR ",
++ "WARNING ",
++ "NOTICE ",
++ "INFO ",
++ "DEBUG "
++};
++
++void ORBit_Trace_setCallback(int (*cbf)(char *, va_list))
++{
++ TraceCallback=cbf;
++}
++
++int (*ORBit_Trace_getCallback(void))(char *, va_list)
++{
++ return(TraceCallback);
++}
++
++void ORBit_Trace_setModules(int modules)
++{
++ TraceModules=modules;
++}
++
++void ORBit_Trace_setLevel(ORBit_TraceLevel level)
++{
++ TraceMaxLevel=level;
++}
++
++int ORBit_Trace(ORBit_TraceModule module, ORBit_TraceLevel level, char *fmt, ...)
++{
++ va_list args;
++
++ if(!BitTest(TraceModules, module))
++ return 0;
++ if(TraceMaxLevel < level)
++ return 0;
++
++ va_start(args, fmt);
++ if(TraceCallback!=NULL)
++ return((*TraceCallback)(fmt, args));
++
++#ifdef __KORBIT__
++ printf("[%s]: ", ORBit_Trace_levellist[level]);
++
++ printf("%s", g_strdup_vprintf(fmt, args));
++ return 0; // breaks semantics, but return value is never used
++#else /* !__KORBIT__ */
++ fprintf(stderr, "[%s]: ", ORBit_Trace_levellist[level]);
++
++ return vfprintf(stderr, fmt, args);
++#endif /* !__KORBIT__ */
++}
++#endif
+diff -urN linux-2.4.1/net/korbit/ORBitutil/trace.h linux-2.4.1-korbit/net/korbit/ORBitutil/trace.h
+--- linux-2.4.1/net/korbit/ORBitutil/trace.h Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/ORBitutil/trace.h Thu Feb 1 11:46:52 2001
+@@ -0,0 +1,68 @@
++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
++
++/*
++ * ORBit: A CORBA v2.2 ORB
++ *
++ * Copyright (C) 1998 Richard H. Porter and Red Hat Software
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Library General Public
++ * License as published by the Free Software Foundation; either
++ * version 2 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Library General Public License for more details.
++ *
++ * You should have received a copy of the GNU Library General Public
++ * License along with this library; if not, write to the Free
++ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Author: Dick Porter <dick@acm.org>
++ *
++ */
++
++#ifndef _ORBIT_TRACE_H_
++#define _ORBIT_TRACE_H_
++
++#include <stdarg.h>
++#include "util.h"
++
++typedef enum {
++ TraceMod_ORB,
++ TraceMod_CDR,
++ TraceMod_IIOP,
++ TraceMod_TC,
++ TraceMod_IR,
++ TraceMod_User=32
++} ORBit_TraceModule;
++
++typedef enum {
++ TraceLevel_Alert=0,
++ TraceLevel_Critical,
++ TraceLevel_Error,
++ TraceLevel_Warning,
++ TraceLevel_Notice,
++ TraceLevel_Info,
++ TraceLevel_Debug
++} ORBit_TraceLevel;
++
++extern const char *ORBit_Trace_levellist[];
++
++#ifdef ORBIT_DEBUG
++extern void ORBit_Trace_setCallback(int (*)(char *, va_list));
++extern int (*ORBit_Trace_getCallback(void))(char *, va_list);
++extern void ORBit_Trace_setModules(int);
++extern void ORBit_Trace_setLevel(ORBit_TraceLevel);
++extern int ORBit_Trace(ORBit_TraceModule, ORBit_TraceLevel, char *, ...);
++#else
++#define ORBit_Trace_setCallback(x)
++#define ORBit_Trace_getCallback() NULL
++#define ORBit_Trace_setModules(x)
++#define ORBit_Trace_setLevel(x)
++#define ORBit_Trace(module,level,fmt,args...)
++#endif
++
++
++#endif /* !_ORBIT_TRACE_H_ */
+diff -urN linux-2.4.1/net/korbit/ORBitutil/util.h linux-2.4.1-korbit/net/korbit/ORBitutil/util.h
+--- linux-2.4.1/net/korbit/ORBitutil/util.h Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/ORBitutil/util.h Thu Feb 1 11:46:52 2001
+@@ -0,0 +1,35 @@
++#ifndef UTIL_H
++#define UTIL_H 1
++
++#include <glib.h>
++
++#define ORBIT_DEBUG 1
++
++#ifdef ORBIT_DEBUG
++#define ORBIT_DEBUG_NOTE(x) (x)
++#else
++#define ORBIT_DEBUG_NOTE(x)
++#endif
++
++
++#define BitTest(f, bit) ((f) & (1<<(bit)))
++#define BitSet(f, bit) ((f) |= (1<<(bit)))
++#define BitClr(f, bit) ((f) &= ~(1<<(bit)))
++/* Align an address upward to a boundary, expressed as a number of bytes.
++ E.g. align to an 8-byte boundary with argument of 8. */
++
++/*
++ * (this + boundary - 1)
++ * &
++ * ~(boundary - 1)
++ */
++
++#define ALIGN_ADDRESS(this, boundary) \
++ ((gpointer)((( ((unsigned long)(this)) + (((unsigned long)(boundary)) -1)) & (~(((unsigned long)(boundary))-1)))))
++
++#include <ORBitutil/thread-safety.h>
++#include <ORBitutil/trace.h>
++#include <ORBitutil/compat.h>
++#include <ORBitutil/os-specifics.h>
++
++#endif
+diff -urN linux-2.4.1/net/korbit/config.h linux-2.4.1-korbit/net/korbit/config.h
+--- linux-2.4.1/net/korbit/config.h Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/config.h Thu Feb 1 11:46:49 2001
+@@ -0,0 +1,73 @@
++
++/* Define if you have alloca, as a function or macro. */
++#define HAVE_ALLOCA 1
++
++#define HAVE_ATEXIT 1
++#define NO_SYS_SIGLIST 1 /* reduce dependencies */
++#define NO_SYS_ERRLIST 1 /* reduce dependencies */
++
++/* Define if you have <alloca.h> and it should be used (not on Ultrix). */
++/* #define HAVE_ALLOCA_H 1 */
++
++/* Define if you have the vprintf function. */
++#define HAVE_VPRINTF 1
++
++/* Define if you have the ANSI C header files. */
++#define STDC_HEADERS 1
++
++#define HAVE_INET_ATON 1
++/* #undef ORBIT_SERIAL */
++
++/* Define to 'int' if it isn't defined in the header files. */
++/* #undef socklen_t */
++
++#define ALIGNOF_CORBA_BOOLEAN 1
++#define ALIGNOF_CORBA_CHAR 1
++#define ALIGNOF_CORBA_DOUBLE 4
++#define ALIGNOF_CORBA_FLOAT 4
++#define ALIGNOF_CORBA_LONG 4
++#define ALIGNOF_CORBA_LONG_DOUBLE 4
++#define ALIGNOF_CORBA_LONG_LONG 4
++#define ALIGNOF_CORBA_OCTET 1
++#define ALIGNOF_CORBA_SHORT 2
++#define ALIGNOF_CORBA_STRUCT 1
++#define ALIGNOF_CORBA_UNSIGNED_LONG 4
++#define ALIGNOF_CORBA_UNSIGNED_LONG_LONG 4
++#define ALIGNOF_CORBA_UNSIGNED_SHORT 2
++#define ALIGNOF_CORBA_WCHAR 2
++#define ALIGNOF_CORBA_POINTER 4
++
++/* TCP wrappers */
++#define HAVE_TCPD_H 1
++
++#ifdef HAVE_ALLOCA_H
++#include <alloca.h>
++#endif
++
++/* Define if you have the basename function. */
++#define HAVE_BASENAME 1
++
++/* Define if you have the poll function. */
++#define HAVE_POLL 1
++#define I_WANT_POLL 1
++
++/* Define if you have the <endian.h> header file. */
++#define HAVE_ENDIAN_H 1
++
++/* Define if you have the <fcntl.h> header file. */
++#define HAVE_FCNTL_H 1
++
++/* Define if you have the <stddef.h> header file. */
++#define HAVE_STDDEF_H 1
++
++/* Define if you have the <sys/poll.h> header file. */
++#define HAVE_SYS_POLL_H 1
++
++/* Define if you have the <tcpd.h> header file. */
++#define HAVE_TCPD_H 1
++
++/* Define if you have the <unistd.h> header file. */
++#define HAVE_UNISTD_H 1
++
++/* Define if you have the <wchar.h> header file. */
++#define HAVE_WCHAR_H 1
+diff -urN linux-2.4.1/net/korbit/exported_symbols.c linux-2.4.1-korbit/net/korbit/exported_symbols.c
+--- linux-2.4.1/net/korbit/exported_symbols.c Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/exported_symbols.c Thu Feb 1 11:46:49 2001
+@@ -0,0 +1,93 @@
++/*
++ * #include whatever it takes to get the EXPORT_SYMBOL macro, and
++ * whatever header files from korbit (for things that are being
++ * exported.
++ */
++#include <linux/config.h>
++#include <linux/module.h>
++#include "errno.h"
++#include "orb/orbit.h"
++
++/*
++ * Stuff that's good to export
++ */
++EXPORT_SYMBOL(errno);
++
++/*
++ * kglib exports...
++ */
++EXPORT_SYMBOL(g_malloc0);
++EXPORT_SYMBOL(g_free);
++EXPORT_SYMBOL(g_snprintf);
++
++/*
++ * Mainline CORBA symbols.
++ */
++EXPORT_SYMBOL(CORBA_exception_init);
++EXPORT_SYMBOL(CORBA_ORB_init);
++EXPORT_SYMBOL(CORBA_ORB_resolve_initial_references);
++EXPORT_SYMBOL(CORBA_ORB_object_to_string);
++EXPORT_SYMBOL(CORBA_free);
++EXPORT_SYMBOL(CORBA_ORB_run);
++EXPORT_SYMBOL(CORBA_Object_release);
++EXPORT_SYMBOL(CORBA_Object_duplicate);
++EXPORT_SYMBOL(CORBA_octet_allocbuf);
++EXPORT_SYMBOL(CORBA_exception_set);
++EXPORT_SYMBOL(CORBA_string__free);
++EXPORT_SYMBOL(CORBA_ORB_string_to_object);
++EXPORT_SYMBOL(CORBA_string_alloc);
++EXPORT_SYMBOL(CORBA_exception_set_system);
++
++/*
++ * ORBIT Specific symbols to export
++ */
++EXPORT_SYMBOL(ORBit_TypeCode_epv);
++EXPORT_SYMBOL(ORBit_send_system_exception);
++EXPORT_SYMBOL(ORBit_register_class);
++EXPORT_SYMBOL(ORBit_marshal_object);
++EXPORT_SYMBOL(ORBit_alloc);
++EXPORT_SYMBOL(ORBit_free);
++EXPORT_SYMBOL(ORBit_send_user_exception);
++EXPORT_SYMBOL(ORBit_delete_profiles);
++EXPORT_SYMBOL(ORBit_demarshal_object);
++EXPORT_SYMBOL(_ORBit_object_get_connection);
++EXPORT_SYMBOL(ORBit_handle_exception);
++EXPORT_SYMBOL(ORBit_object_get_forwarded_connection);
++EXPORT_SYMBOL(ORBit_default_principal_iovec);
++EXPORT_SYMBOL(ORBit_demarshal_IOR);
++
++/*
++ * CORBA giop functions
++ */
++EXPORT_SYMBOL(giop_send_buffer_write);
++EXPORT_SYMBOL(giop_send_buffer_unuse);
++EXPORT_SYMBOL(giop_message_buffer_do_alignment);
++EXPORT_SYMBOL(giop_message_buffer_append_mem);
++EXPORT_SYMBOL(giop_send_reply_buffer_use);
++EXPORT_SYMBOL(giop_send_request_buffer_use);
++EXPORT_SYMBOL(giop_recv_buffer_unuse);
++EXPORT_SYMBOL(giop_recv_reply_buffer_use_2);
++
++/*
++ * POA Symbols.
++ */
++EXPORT_SYMBOL(PortableServer_POAManager_activate);
++EXPORT_SYMBOL(PortableServer_POA_activate_object_with_id);
++EXPORT_SYMBOL(PortableServer_POA_servant_to_reference);
++EXPORT_SYMBOL(PortableServer_POA_deactivate_object);
++EXPORT_SYMBOL(PortableServer_POA__get_the_POAManager);
++EXPORT_SYMBOL(PortableServer_ServantBase__init);
++EXPORT_SYMBOL(PortableServer_ServantBase__fini);
++EXPORT_SYMBOL(PortableServer_POA_reference_to_servant);
++EXPORT_SYMBOL(PortableServer_POA_servant_to_id);
++EXPORT_SYMBOL(PortableServer_POA_activate_object);
++EXPORT_SYMBOL(PortableServer_POA_reference_to_id);
++
++/*
++ * TC Stuff (whatever that is)
++ */
++EXPORT_SYMBOL(TC_octet_struct);
++EXPORT_SYMBOL(TC_long_struct);
++EXPORT_SYMBOL(TC_ulong_struct);
++EXPORT_SYMBOL(TC_short_struct);
++EXPORT_SYMBOL(TC_string_struct);
+diff -urN linux-2.4.1/net/korbit/include/.cvsignore linux-2.4.1-korbit/net/korbit/include/.cvsignore
+--- linux-2.4.1/net/korbit/include/.cvsignore Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/include/.cvsignore Thu Feb 1 11:46:53 2001
+@@ -0,0 +1 @@
++stdarg.h
+diff -urN linux-2.4.1/net/korbit/include/CVS/Entries linux-2.4.1-korbit/net/korbit/include/CVS/Entries
+--- linux-2.4.1/net/korbit/include/CVS/Entries Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/include/CVS/Entries Thu Feb 1 11:46:54 2001
+@@ -0,0 +1,24 @@
++/.cvsignore/1.1/Thu Feb 1 09:46:53 2001//
++/alloca.h/1.3/Thu Feb 1 09:46:53 2001//
++/assert.h/1.1.1.1/Thu Feb 1 09:46:53 2001//
++/ctype.h/1.1.1.1/Thu Feb 1 09:46:53 2001//
++/dirent.h/1.1.1.1/Thu Feb 1 09:46:53 2001//
++/errno.h/1.2/Thu Feb 1 09:46:53 2001//
++/fcntl.h/1.3/Thu Feb 1 09:46:53 2001//
++/host_list.h/1.7/Thu Feb 1 09:46:53 2001//
++/limits.h/1.1.1.1/Thu Feb 1 09:46:53 2001//
++/locale.h/1.1.1.1/Thu Feb 1 09:46:53 2001//
++/math.h/1.2/Thu Feb 1 09:46:53 2001//
++/netdb.h/1.17/Thu Feb 1 09:46:53 2001//
++/pwd.h/1.1.1.1/Thu Feb 1 09:46:53 2001//
++/signal.h/1.1.1.1/Thu Feb 1 09:46:53 2001//
++/stdarg.h/1.3/Thu Feb 1 09:46:54 2001//
++/stddef.h/1.1.1.1/Thu Feb 1 09:46:54 2001//
++/stdio.h/1.19/Thu Feb 1 09:46:54 2001//
++/stdlib.h/1.4/Thu Feb 1 09:46:54 2001//
++/string.h/1.3/Thu Feb 1 09:46:54 2001//
++/syslog.h/1.1.1.1/Thu Feb 1 09:46:54 2001//
++/time.h/1.1.1.1/Thu Feb 1 09:46:54 2001//
++/unistd.h/1.3/Thu Feb 1 09:46:54 2001//
++/utime.h/1.1.1.1/Thu Feb 1 09:46:54 2001//
++D
+diff -urN linux-2.4.1/net/korbit/include/CVS/Entries.Log linux-2.4.1-korbit/net/korbit/include/CVS/Entries.Log
+--- linux-2.4.1/net/korbit/include/CVS/Entries.Log Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/include/CVS/Entries.Log Thu Feb 1 11:46:55 2001
+@@ -0,0 +1,3 @@
++A D/arpa////
++A D/netinet////
++A D/sys////
+diff -urN linux-2.4.1/net/korbit/include/CVS/Repository linux-2.4.1-korbit/net/korbit/include/CVS/Repository
+--- linux-2.4.1/net/korbit/include/CVS/Repository Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/include/CVS/Repository Thu Feb 1 11:46:53 2001
+@@ -0,0 +1 @@
++/cvsroot/korbit/linux/net/korbit/include
+diff -urN linux-2.4.1/net/korbit/include/CVS/Root linux-2.4.1-korbit/net/korbit/include/CVS/Root
+--- linux-2.4.1/net/korbit/include/CVS/Root Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/include/CVS/Root Thu Feb 1 11:46:53 2001
+@@ -0,0 +1 @@
++vraalsen@cvs.korbit.sourceforge.net:/cvsroot/korbit
+diff -urN linux-2.4.1/net/korbit/include/alloca.h linux-2.4.1-korbit/net/korbit/include/alloca.h
+--- linux-2.4.1/net/korbit/include/alloca.h Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/include/alloca.h Thu Feb 1 11:46:53 2001
+@@ -0,0 +1,6 @@
++#ifndef __KORBIT_ALLOCA_H__
++#define __KORBIT_ALLOCA_H__
++
++#include <stdlib.h>
++
++#endif
+diff -urN linux-2.4.1/net/korbit/include/arpa/CVS/Entries linux-2.4.1-korbit/net/korbit/include/arpa/CVS/Entries
+--- linux-2.4.1/net/korbit/include/arpa/CVS/Entries Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/include/arpa/CVS/Entries Thu Feb 1 11:46:55 2001
+@@ -0,0 +1,2 @@
++/inet.h/1.4/Thu Feb 1 09:46:54 2001//
++D
+diff -urN linux-2.4.1/net/korbit/include/arpa/CVS/Repository linux-2.4.1-korbit/net/korbit/include/arpa/CVS/Repository
+--- linux-2.4.1/net/korbit/include/arpa/CVS/Repository Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/include/arpa/CVS/Repository Thu Feb 1 11:46:54 2001
+@@ -0,0 +1 @@
++/cvsroot/korbit/linux/net/korbit/include/arpa
+diff -urN linux-2.4.1/net/korbit/include/arpa/CVS/Root linux-2.4.1-korbit/net/korbit/include/arpa/CVS/Root
+--- linux-2.4.1/net/korbit/include/arpa/CVS/Root Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/include/arpa/CVS/Root Thu Feb 1 11:46:54 2001
+@@ -0,0 +1 @@
++vraalsen@cvs.korbit.sourceforge.net:/cvsroot/korbit
+diff -urN linux-2.4.1/net/korbit/include/arpa/inet.h linux-2.4.1-korbit/net/korbit/include/arpa/inet.h
+--- linux-2.4.1/net/korbit/include/arpa/inet.h Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/include/arpa/inet.h Thu Feb 1 11:46:54 2001
+@@ -0,0 +1,50 @@
++#ifndef __KORBIT_ARPA_INET_H__
++#define __KORBIT_ARPA_INET_H__
++
++#include <linux/inet.h>
++#include <linux/in.h>
++
++static inline char* inet_ntoa(struct in_addr in)
++{
++ return in_ntoa(in.s_addr);
++}
++
++static inline int inet_aton(const char *cp, struct in_addr *inp)
++{
++ unsigned long l;
++ unsigned int val;
++ int i;
++
++ if (!cp || !inp)
++ return 0;
++
++ l = 0;
++ for (i = 0; i < 4; i++)
++ {
++ l <<= 8;
++ if (*cp != '\0')
++ {
++ val = 0;
++ while (*cp != '\0' && *cp != '.')
++ {
++ if (*cp < '0' || '9' < *cp)
++ return 0;
++
++ val *= 10;
++ val += *cp - '0';
++ cp++;
++ }
++ if (val > 255)
++ return 0;
++
++ l |= val;
++ if (*cp != '\0')
++ cp++;
++ }
++ }
++ inp->s_addr = htonl(l);
++
++ return 1;
++}
++
++#endif /* __KORBIT_ARPA_INET_H__ */
+diff -urN linux-2.4.1/net/korbit/include/assert.h linux-2.4.1-korbit/net/korbit/include/assert.h
+--- linux-2.4.1/net/korbit/include/assert.h Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/include/assert.h Thu Feb 1 11:46:53 2001
+@@ -0,0 +1,3 @@
++#ifndef __KORBIT_ASSERT_H__
++#define __KORBIT_ASSERT_H__
++#endif
+diff -urN linux-2.4.1/net/korbit/include/ctype.h linux-2.4.1-korbit/net/korbit/include/ctype.h
+--- linux-2.4.1/net/korbit/include/ctype.h Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/include/ctype.h Thu Feb 1 11:46:53 2001
+@@ -0,0 +1,4 @@
++#ifndef __KORBIT_CTYPE_H__
++#define __KORBIT_CTYPE_H__
++#include <linux/ctype.h>
++#endif
+diff -urN linux-2.4.1/net/korbit/include/dirent.h linux-2.4.1-korbit/net/korbit/include/dirent.h
+--- linux-2.4.1/net/korbit/include/dirent.h Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/include/dirent.h Thu Feb 1 11:46:53 2001
+@@ -0,0 +1,3 @@
++#ifndef __KORBIT_DIRENT_H__
++#define __KORBIT_DIRENT_H__
++#endif
+diff -urN linux-2.4.1/net/korbit/include/errno.h linux-2.4.1-korbit/net/korbit/include/errno.h
+--- linux-2.4.1/net/korbit/include/errno.h Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/include/errno.h Thu Feb 1 11:46:53 2001
+@@ -0,0 +1,9 @@
++#ifndef __KORBIT_ERRNO_H__
++#define __KORBIT_ERRNO_H__
++
++#include <asm/errno.h>
++
++#define errno korbit_errno
++extern int korbit_errno;
++
++#endif
+diff -urN linux-2.4.1/net/korbit/include/fcntl.h linux-2.4.1-korbit/net/korbit/include/fcntl.h
+--- linux-2.4.1/net/korbit/include/fcntl.h Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/include/fcntl.h Thu Feb 1 11:46:53 2001
+@@ -0,0 +1,49 @@
++#ifndef __KORBIT_FCNTL_H__
++#define __KORBIT_FCNTL_H__
++
++#include <linux/mm.h>
++#include <linux/file.h>
++#include <linux/smp_lock.h>
++
++#include <asm/fcntl.h>
++
++#include <stdio.h>
++
++#define SETFL_MASK (O_APPEND | O_NONBLOCK | O_NDELAY | FASYNC)
++
++static inline int fcntl(int fd, int cmd, long arg)
++{
++ struct file *filp = fd2file(fd);
++ long err = -EINVAL;
++
++ switch (cmd)
++ {
++ case F_SETFD:
++ case F_GETFD:
++ err = 0;
++ break;
++ case F_GETFL:
++ if (filp)
++ err = filp->f_flags;
++ break;
++ case F_SETFL:
++ if (filp)
++ {
++ lock_kernel();
++
++ /* required for strict SunOS emulation */
++ if (O_NONBLOCK != O_NDELAY)
++ if (arg & O_NDELAY)
++ arg |= O_NONBLOCK;
++
++ filp->f_flags = (arg & SETFL_MASK) |
++ (filp->f_flags & ~SETFL_MASK);
++ err = 0;
++ unlock_kernel();
++ }
++ break;
++ }
++ return err;
++}
++
++#endif
+diff -urN linux-2.4.1/net/korbit/include/host_list.h linux-2.4.1-korbit/net/korbit/include/host_list.h
+--- linux-2.4.1/net/korbit/include/host_list.h Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/include/host_list.h Thu Feb 1 11:46:53 2001
+@@ -0,0 +1,24 @@
++/*
++ * A statically-allocated list of Hostnames<->IPv4 addresses.
++ */
++#ifndef __KORBIT_HOST_LIST_H
++#define __KORBIT_HOST_LIST_H
++
++static struct {
++ char *name;
++ char *IP;
++} host_table[] = {
++ {"redefine.dyndns.org", "206.221.225.140"},
++ {"csil-sunb4.cs.uiuc.edu", "128.174.243.204"},
++ {"kazoo.cs.uiuc.edu", "128.174.237.133"},
++ {"opus0.cs.uiuc.edu", "128.174.236.20"},
++ {"wakeland-56.flexabit.net", "64.198.239.56"},
++ {"es-dcl-border1.cso.uiuc.edu", "127.0.0.1"},
++ {"es-dcl-border1", "127.0.0.1"}
++// {"es-dcl-border1.cso.uiuc.edu", "130.126.112.222"},
++// {"es-dcl-border1", "130.126.112.222"}
++};
++
++#define __MAX_STATIC_NAMES (sizeof(host_table) / sizeof(host_table[0]))
++
++#endif
+diff -urN linux-2.4.1/net/korbit/include/limits.h linux-2.4.1-korbit/net/korbit/include/limits.h
+--- linux-2.4.1/net/korbit/include/limits.h Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/include/limits.h Thu Feb 1 11:46:53 2001
+@@ -0,0 +1,7 @@
++#ifndef __KORBIT_LIMITS_H__
++#define __KORBIT_LIMITS_H__
++
++#include <linux/limits.h>
++#include <linux/kernel.h>
++
++#endif
+diff -urN linux-2.4.1/net/korbit/include/locale.h linux-2.4.1-korbit/net/korbit/include/locale.h
+--- linux-2.4.1/net/korbit/include/locale.h Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/include/locale.h Thu Feb 1 11:46:53 2001
+@@ -0,0 +1,3 @@
++#ifndef __KORBIT_LOCALE_H__
++#define __KORBIT_LOCALE_H__
++#endif
+diff -urN linux-2.4.1/net/korbit/include/math.h linux-2.4.1-korbit/net/korbit/include/math.h
+--- linux-2.4.1/net/korbit/include/math.h Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/include/math.h Thu Feb 1 11:46:53 2001
+@@ -0,0 +1,16 @@
++#ifndef __KORBIT_MATH_H__
++#define __KORBIT_MATH_H__
++
++#include <asm/page.h>
++
++static inline double pow(double x, double y) {
++ double Q = 1.0;
++ if (y < 0)
++ BUG();
++/* return 1.0/pow(x,-y);*/
++ while (y-- > 0)
++ Q *= x;
++ return Q;
++}
++
++#endif
+diff -urN linux-2.4.1/net/korbit/include/netdb.h linux-2.4.1-korbit/net/korbit/include/netdb.h
+--- linux-2.4.1/net/korbit/include/netdb.h Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/include/netdb.h Thu Feb 1 11:46:53 2001
+@@ -0,0 +1,197 @@
++#ifndef __KORBIT_NETDB_H__
++#define __KORBIT_NETDB_H__
++
++#include <sys/socket.h>
++#include <linux/in.h>
++#include <arpa/inet.h>
++#include "host_list.h"
++
++#define h_errno 0
++/* static int h_errno; */
++
++/* Description of data base entry for a single host. */
++struct hostent
++{
++ char *h_name; /* Official name of host. */
++ char **h_aliases; /* Alias list. */
++ int h_addrtype; /* Host address type. */
++ socklen_t h_length; /* Length of address. */
++ char **h_addr_list; /* List of addresses from name server. */
++#define h_addr h_addr_list[0] /* Address, for backward compatibility. */
++};
++
++/* Is this defined somewhere else? */
++/*struct in_addr {
++ __uint32_t s_addr;
++};*/
++
++/*
++ * Set h_errno?
++ * #define HOST_NOT_FOUND 1
++ * #define TRY_AGAIN 2
++ * #define NO_RECOVERY 3
++ * #define NO_DATA 4
++ */
++static inline struct hostent *gethostbyname (char *host)
++{
++ int c;
++ static struct in_addr tmp_in;
++ static struct hostent ret_host;
++ static char *aliases[2];
++ static char *addrs[2];
++
++ if (host == NULL)
++ {
++ printf ("** gethostbyname() Error: Got NULL parameter! **\n");
++ return (NULL);
++ }
++
++ /*
++ * The actual lookup.
++ */
++ for (c = 0; c < __MAX_STATIC_NAMES; c++)
++ {
++ if (host_table[c].name && strncmp (host, host_table[c].name, strlen(host_table[c].name)) == 0)
++ {
++/* printf ("Name '%s' found at position %d!\n", argv[1], c);*/
++/* printf ("IP address is: '%s'.\n", IPs[c]);*/
++ break;
++ }
++ }
++
++ if (c == __MAX_STATIC_NAMES)
++ {
++ /* Host not found, return NULL. */
++ return (NULL);
++ }
++ /* else, names[c] is gold! */
++
++ /* make a new hostent, ret_host */
++
++ ret_host.h_addrtype = AF_INET;
++ ret_host.h_aliases = aliases;
++ aliases[0] = host_table[c].name;
++ aliases[1] = NULL;
++ ret_host.h_name = host_table[c].name;
++ if (!inet_aton (host_table[c].IP, &tmp_in))
++ {
++ printf ("** gethostbyname() Error: Invalid IP address in table! **\n");
++ return (NULL);
++ }
++ ret_host.h_addr_list = addrs;
++ addrs[0] = (char *)&tmp_in.s_addr;
++ addrs[1] = NULL;
++ ret_host.h_length = sizeof (tmp_in.s_addr);
++ return (&ret_host);
++} /* End gethostbyname(). */
++
++/*
++ * TODO: getpeername(), gethostbyaddr(), getsockname(), gethostname()
++ * Everything from here-on has been untested (in userland). Buyer beware.
++ */
++static inline struct hostent *gethostbyaddr (const char *addr, int len, int type)
++{
++ struct in_addr tin;
++ char *inp_addr;
++ int c;
++ static struct hostent ret_host;
++ static char *aliases[1];
++ static char *addrs[2];
++ static struct in_addr tmp_in;
++
++
++ if ((type != AF_INET) || (len != 4))
++ {
++ printf ("** gethostbyaddr Error: Don't know how to deal with non-AF_INET addresses! **\n");
++ return (NULL);
++ }
++
++ tin.s_addr = *((__u32 *)addr);
++ inp_addr = inet_ntoa (tin);
++ if (inp_addr == NULL)
++ {
++ /* We got some invalid input, baby. */
++ return (NULL);
++
++ }
++
++ /*
++ * The actual lookup.
++ */
++ for (c = 0; c < __MAX_STATIC_NAMES; c++)
++ {
++ if (host_table[c].IP && strncmp (inp_addr, host_table[c].IP, strlen(host_table[c].IP)) == 0)
++ {
++ break;
++ }
++ }
++
++ if (c == __MAX_STATIC_NAMES)
++ {
++ /* Host not found, return NULL. */
++ return (NULL);
++ }
++ /* else, host_table[c].IP is gold! */
++
++ ret_host.h_addrtype = AF_INET;
++ ret_host.h_aliases = aliases;
++ aliases[0] = NULL;
++ ret_host.h_name = host_table[c].name;
++ if (!inet_aton (host_table[c].IP, &tmp_in))
++ {
++ printf ("** gethostbyname() Error: Invalid IP address in table! **\n");
++ return (NULL);
++ }
++ ret_host.h_addr_list = addrs;
++ addrs[0] = (char *)&tmp_in.s_addr;
++ addrs[1] = NULL;
++ ret_host.h_length = sizeof (tmp_in.s_addr);
++ return (&ret_host);
++} /* End gethostbyaddr(). */
++
++/*
++ * If successful, return 0. Else, return -1 and set errno.
++ * Errors:
++ * EBADF The argument s is not a valid file descriptor.
++ *
++ * ENOMEM
++ * There was insufficient memory available for the opera-
++ * tion to complete.
++ *
++ * ENOSR There were insufficient STREAMS resources available
++ * for the operation to complete.
++ *
++ * ENOTSOCK
++ * The argument s is not a socket.
++ */
++static inline int getsockname (int s, struct sockaddr *name, socklen_t *namelen)
++{
++ struct socket *sock = fd2sock(s);
++
++ if (sock == NULL)
++ return -1;
++
++ /*
++ * getname() wants an 'int *' for the length, will it by this
++ * 'socklen_t *' business? (even though it is just an 'int *'?).
++ */
++ if (sock->ops->getname(sock, name, namelen, 0) == 0)
++ return 0;
++ else
++ return -1; /* should normally also set errno */
++} /* End getsockname(). */
++
++static inline int getpeername (int s, struct sockaddr *name, socklen_t *namelen)
++{
++ struct socket *sock = fd2sock(s);
++
++ if (sock == NULL)
++ return -1;
++
++ if (sock->ops->getname(sock, name, namelen, 1) == 0)
++ return 0;
++ else
++ return -1; /* should normally also set errno */
++} /* End getpeername(). */
++
++#endif
+diff -urN linux-2.4.1/net/korbit/include/netinet/CVS/Entries linux-2.4.1-korbit/net/korbit/include/netinet/CVS/Entries
+--- linux-2.4.1/net/korbit/include/netinet/CVS/Entries Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/include/netinet/CVS/Entries Thu Feb 1 11:46:55 2001
+@@ -0,0 +1,2 @@
++/in.h/1.1.1.1/Thu Feb 1 09:46:55 2001//
++D
+diff -urN linux-2.4.1/net/korbit/include/netinet/CVS/Repository linux-2.4.1-korbit/net/korbit/include/netinet/CVS/Repository
+--- linux-2.4.1/net/korbit/include/netinet/CVS/Repository Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/include/netinet/CVS/Repository Thu Feb 1 11:46:55 2001
+@@ -0,0 +1 @@
++/cvsroot/korbit/linux/net/korbit/include/netinet
+diff -urN linux-2.4.1/net/korbit/include/netinet/CVS/Root linux-2.4.1-korbit/net/korbit/include/netinet/CVS/Root
+--- linux-2.4.1/net/korbit/include/netinet/CVS/Root Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/include/netinet/CVS/Root Thu Feb 1 11:46:55 2001
+@@ -0,0 +1 @@
++vraalsen@cvs.korbit.sourceforge.net:/cvsroot/korbit
+diff -urN linux-2.4.1/net/korbit/include/netinet/in.h linux-2.4.1-korbit/net/korbit/include/netinet/in.h
+--- linux-2.4.1/net/korbit/include/netinet/in.h Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/include/netinet/in.h Thu Feb 1 11:46:55 2001
+@@ -0,0 +1,5 @@
++#ifndef __KORBIT_NETINET_IN_H__
++#define __KORBIT_NETINET_IN_H__
++#include <linux/socket.h>
++#include <linux/in.h>
++#endif
+diff -urN linux-2.4.1/net/korbit/include/pwd.h linux-2.4.1-korbit/net/korbit/include/pwd.h
+--- linux-2.4.1/net/korbit/include/pwd.h Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/include/pwd.h Thu Feb 1 11:46:53 2001
+@@ -0,0 +1,3 @@
++#ifndef __KORBIT_PWD_H__
++#define __KORBIT_PWD_H__
++#endif
+diff -urN linux-2.4.1/net/korbit/include/signal.h linux-2.4.1-korbit/net/korbit/include/signal.h
+--- linux-2.4.1/net/korbit/include/signal.h Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/include/signal.h Thu Feb 1 11:46:53 2001
+@@ -0,0 +1,6 @@
++#ifndef __KORBIT_SIGNAL_H__
++#define __KORBIT_SIGNAL_H__
++
++#include <asm/signal.h>
++
++#endif
+diff -urN linux-2.4.1/net/korbit/include/stdarg.h linux-2.4.1-korbit/net/korbit/include/stdarg.h
+--- linux-2.4.1/net/korbit/include/stdarg.h Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/include/stdarg.h Thu Feb 1 11:46:54 2001
+@@ -0,0 +1,13 @@
++#ifndef __KORBIT_STDARG_H__
++#define __KORBIT_STDARG_H__
++
++#define ANDY 1
++
++#if FREDRIK
++#include "/usr/lib/gcc-lib/i386-glibc21-linux/egcs-2.91.66/include/stdarg.h"
++#elif CHRIS
++#include "/usr/lib/gcc-lib/i586-mandrake-linux/egcs-2.91.66/include/stdarg.h"
++#elif ANDY
++#include "/usr/lib/gcc-lib/i386-redhat-linux/egcs-2.91.66/include/stdarg.h"
++#endif
++#endif
+diff -urN linux-2.4.1/net/korbit/include/stddef.h linux-2.4.1-korbit/net/korbit/include/stddef.h
+--- linux-2.4.1/net/korbit/include/stddef.h Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/include/stddef.h Thu Feb 1 11:46:54 2001
+@@ -0,0 +1,3 @@
++#ifndef __KORBIT_STDDEF_H__
++#define __KORBIT_STDDEF_H__
++#endif
+diff -urN linux-2.4.1/net/korbit/include/stdio.h linux-2.4.1-korbit/net/korbit/include/stdio.h
+--- linux-2.4.1/net/korbit/include/stdio.h Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/include/stdio.h Thu Feb 1 11:46:54 2001
+@@ -0,0 +1,402 @@
++#ifndef __KORBIT_STDIO_H__
++#define __KORBIT_STDIO_H__
++
++#include <asm/segment.h>
++#include <asm/uaccess.h>
++#include <linux/smp_lock.h>
++#include <linux/kernel.h>
++#include <linux/fs.h>
++#include <linux/sched.h>
++#include <linux/uio.h>
++#include <linux/dcache.h>
++#include <linux/file.h>
++#include <linux/highuid.h>
++#include <sys/socket.h>
++
++#include <errno.h>
++
++#define KORBIT_DEBUG_WRITING 0
++
++
++#define printf(format,args...) printk(format,##args)
++#define fflush(x)
++
++#define SEEK_SET 0 /* Seek from beginning of file. */
++#define SEEK_CUR 1 /* Seek from current position. */
++#define SEEK_END 2 /* Seek from end of file. */
++
++static inline int unlink(const char *pathname) {
++ printf("KERNEL UNLINK('%s') CALLED!\n", pathname);
++ return -1;
++}
++
++static inline struct file *fd2file(int fd) {
++ if (fd & 1) /* can't convert a socket! */
++ return NULL;
++
++ return (struct file *)(-(fd & ~1));
++}
++
++static inline int open(const char *filename, int flags, int mode) {
++ struct file *RetVal = filp_open(filename, flags, mode);
++ if (IS_ERR(RetVal))
++ {
++ errno = PTR_ERR(RetVal);
++ return -1;
++ }
++ return -(int)RetVal;
++}
++
++static inline int creat(const char *filename, mode_t mode)
++{
++ return open(filename, O_CREAT | O_WRONLY | O_TRUNC, mode);
++}
++
++static inline int lseek(int fd, long offset, int whence)
++{
++ if ((fd & 1) == 1)
++ {
++ printk("KERNEL FSEEK() CALLED ON SOCKET!\n");
++ return -1;
++ }
++ else
++ {
++ struct file *F = fd2file(fd);
++ loff_t (*fn)(struct file *, loff_t, int);
++ int retval = -1;
++
++ if (whence <= 2)
++ {
++ fn = default_llseek;
++ if (F->f_op && F->f_op->llseek)
++ fn = F->f_op->llseek;
++
++ lock_kernel();
++ retval = fn(F, offset, whence);
++ unlock_kernel();
++ }
++ if (retval < 0)
++ {
++ errno = -retval;
++ retval = -1;
++ }
++ return retval;
++ }
++}
++
++
++asmlinkage long sys_newstat(char * filename, struct stat * statbuf);
++static inline int stat(char *filename, struct stat *buf)
++{
++ mm_segment_t oldfs;
++ int retval;
++
++ oldfs = get_fs(); set_fs(KERNEL_DS);
++ retval = sys_newstat(filename, buf);
++ set_fs(oldfs);
++ if (retval < 0)
++ {
++ errno = -retval;
++ retval = -1;
++ }
++ return retval;
++}
++
++asmlinkage long sys_newlstat(char * filename, struct stat * statbuf);
++static inline int lstat(char *filename, struct stat *buf)
++{
++ mm_segment_t oldfs;
++ int retval;
++
++ oldfs = get_fs(); set_fs(KERNEL_DS);
++ retval = sys_newlstat(filename, buf);
++ set_fs(oldfs);
++ if (retval < 0)
++ {
++ errno = -retval;
++ retval = -1;
++ }
++ return retval;
++}
++
++
++static inline int do_revalidate(struct dentry *dentry)
++{
++ struct inode * inode = dentry->d_inode;
++ if (inode->i_op && inode->i_op->revalidate)
++ return inode->i_op->revalidate(dentry);
++ return 0;
++}
++
++
++static inline int cp_new_stat(struct inode * inode, struct stat * statbuf)
++{
++ struct stat tmp;
++
++ memset(&tmp, 0, sizeof(tmp));
++ tmp.st_dev = kdev_t_to_nr(inode->i_dev);
++ tmp.st_ino = inode->i_ino;
++ tmp.st_mode = inode->i_mode;
++ tmp.st_nlink = inode->i_nlink;
++ SET_STAT_UID(tmp, inode->i_uid);
++ SET_STAT_GID(tmp, inode->i_gid);
++ tmp.st_rdev = kdev_t_to_nr(inode->i_rdev);
++#if BITS_PER_LONG == 32
++ if (inode->i_size > 0x7fffffff)
++ return -EOVERFLOW;
++ else
++#endif
++ {
++ tmp.st_size = inode->i_size;
++ tmp.st_atime = inode->i_atime;
++ tmp.st_mtime = inode->i_mtime;
++ tmp.st_ctime = inode->i_ctime;
++
++ tmp.st_blocks = inode->i_blocks;
++ tmp.st_blksize = inode->i_blksize;
++
++ memcpy(statbuf, &tmp, sizeof(tmp));
++ return 0;
++ }
++}
++
++
++static inline int fstat(int fd, struct stat *buf)
++{
++ if ((fd & 1) == 1)
++ {
++ printk("TODO : FSTAT FOR SOCKETS, DO WE WANT THIS?\n");
++ errno = EBADF;
++ return -1;
++ }
++ else
++ {
++ struct file *file = fd2file(fd);
++ struct dentry *dentry;
++ int retval = -EBADF;
++
++ if (file)
++ {
++ dentry = file->f_dentry;
++ retval = do_revalidate(dentry);
++
++ if (!retval)
++ retval = cp_new_stat(dentry->d_inode, buf);
++ }
++ if (retval < 0)
++ {
++ errno = -retval;
++ retval = -1;
++ }
++ return retval;
++ }
++}
++
++
++asmlinkage long sys_readlink(const char * path, char * buf, int bufsiz);
++static inline int readlink(const char *path, char *buf, size_t bufsiz)
++{
++ int retval;
++ mm_segment_t oldfs;
++
++ oldfs = get_fs(); set_fs(KERNEL_DS);
++ retval = sys_readlink(path, buf, bufsiz);
++ set_fs(oldfs);
++ if (retval < 0)
++ {
++ errno = -retval;
++ retval = -1;
++ }
++ return retval;
++}
++
++
++static inline int read(int fd, void *buffer, size_t count) {
++ if ((fd & 1) == 1)
++ {
++ struct socket *sock = fd2sock(fd);
++ struct iovec iov;
++ struct msghdr msg;
++ mm_segment_t oldfs;
++ int flags = 0;
++ int RetVal;
++
++ msg.msg_name = NULL;
++ msg.msg_namelen = 0;
++ msg.msg_iov = &iov;
++ msg.msg_iovlen = 1;
++ msg.msg_control = NULL;
++ msg.msg_controllen = 0;
++ msg.msg_flags = 0;
++ iov.iov_base = buffer;
++ iov.iov_len = count;
++ oldfs = get_fs(); set_fs(KERNEL_DS);
++ RetVal = sock_recvmsg(sock, &msg, count, flags);
++ set_fs(oldfs);
++ if (RetVal < 0)
++ {
++ errno = -RetVal;
++ RetVal = -1;
++ }
++ return RetVal;
++ }
++ else
++ {
++ struct file *F = fd2file(fd);
++ mm_segment_t oldfs;
++ int RetVal;
++
++ oldfs = get_fs();
++ set_fs(KERNEL_DS);
++ RetVal = F->f_op->read(F, buffer, count, &F->f_pos);
++ set_fs(oldfs);
++ if (RetVal < 0)
++ {
++ errno = -RetVal;
++ RetVal = -1;
++ }
++ return RetVal;
++ }
++}
++
++static inline int write(int fd, const void *buffer, size_t count) {
++ if ((fd & 1) == 1)
++ {
++ struct socket *sock = fd2sock(fd);
++ struct iovec iov;
++ struct msghdr msg;
++ mm_segment_t oldfs;
++ int RetVal;
++ msg.msg_name = NULL;
++ msg.msg_namelen = 0;
++ msg.msg_iov = &iov;
++ msg.msg_iovlen = 1;
++ msg.msg_control = NULL;
++ msg.msg_controllen = 0;
++ msg.msg_flags = MSG_NOSIGNAL;
++ if (sock->type == SOCK_SEQPACKET)
++ msg.msg_flags |= MSG_EOR;
++ iov.iov_base = (void *)buffer;
++ iov.iov_len = count;
++
++ oldfs = get_fs(); set_fs(KERNEL_DS);
++ RetVal = sock_sendmsg(sock, &msg, count);
++ set_fs(oldfs);
++ if (RetVal < 0)
++ {
++ errno = -RetVal;
++ RetVal = -1;
++ }
++ return RetVal;
++ }
++ else
++ {
++ struct file *F = fd2file(fd);
++ mm_segment_t oldfs;
++ int RetVal;
++
++ oldfs = get_fs();
++ set_fs(KERNEL_DS);
++ RetVal = F->f_op->write(F, buffer, count, &F->f_pos);
++ set_fs(oldfs);
++ if (RetVal < 0)
++ {
++ errno = -RetVal;
++ RetVal = -1;
++ }
++ return RetVal;
++ }
++}
++
++static inline int writev(int fd, const struct iovec *vector, int count) {
++#ifndef DONT_USE_SIMPLE_WRITEV
++ int i, amount = 0;
++#if KORBIT_DEBUG_WRITING
++ printk("writev (fd = 0x%X, vec=0x%p, count = %d)\n", fd, vector, count);
++#endif
++ for (i = 0; i < count; i++) {
++ char *Buf = vector[i].iov_base;
++ int Amount = vector[i].iov_len;
++ while (Amount > 0) {
++ int A = write(fd, Buf, Amount);
++//#if KORBIT_DEBUG_WRITING
++if (A < Amount)
++ printk(" write(fd = 0x%X, buf = 0x%p, size = 0x%X) "
++ "= 0x%X errno = 0x%X\n", fd, Buf, Amount, A, errno);
++//#endif
++ Amount -= A;
++ amount += A;
++ Buf += A;
++ if (Amount > 0) schedule(); // Behave somewhat nicely...
++ }
++ }
++
++#if KORBIT_DEBUG_WRITING
++ printk("writev returning 0x%X[%d]\n", amount, amount);
++#endif
++ return amount;
++
++#else
++ if ((fd & 1) == 1)
++ {
++ struct socket *sock = fd2sock(fd);
++ struct msghdr msg;
++ mm_segment_t oldfs;
++ int i, RetVal;
++ size_t tot_len = 0;
++
++ for (i = 0; i < count; i++)
++ tot_len += vector[i].iov_len;
++
++ msg.msg_name = NULL;
++ msg.msg_namelen = 0;
++ msg.msg_iov = (struct iovec *)vector;
++ msg.msg_iovlen = count;
++ msg.msg_control = NULL;
++ msg.msg_controllen = 0;
++ if (sock->type == SOCK_SEQPACKET)
++ msg.msg_flags |= MSG_EOR;
++
++ oldfs = get_fs(); set_fs(KERNEL_DS);
++ RetVal = sock_sendmsg(sock, &msg, tot_len);
++ set_fs(oldfs);
++ if (RetVal < 0)
++ {
++ errno = -RetVal;
++ RetVal = -1;
++ }
++ return RetVal;
++ }
++ else
++ {
++ struct file *F = fd2file(fd);
++ mm_segment_t oldfs;
++ int RetVal;
++
++ oldfs = get_fs();
++ set_fs(KERNEL_DS);
++ RetVal = F->f_op->writev(F, vector, (unsigned)count, &F->f_pos);
++ set_fs(oldfs);
++ if (RetVal < 0)
++ {
++ errno = -RetVal;
++ RetVal = -1;
++ }
++ return RetVal;
++ }
++#endif
++}
++
++static inline int close(int fd) {
++ int err = 0;
++ if ((fd & 1) == 1) {
++ struct socket *sock = fd2sock(fd);
++ sock_release(sock);
++ } else {
++ struct file *file = fd2file(fd);
++ fput(file);
++ }
++ return err;
++}
++
++#endif
+diff -urN linux-2.4.1/net/korbit/include/stdlib.h linux-2.4.1-korbit/net/korbit/include/stdlib.h
+--- linux-2.4.1/net/korbit/include/stdlib.h Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/include/stdlib.h Thu Feb 1 11:46:54 2001
+@@ -0,0 +1,99 @@
++#ifndef __KORBIT_STDLIB_H__
++#define __KORBIT_STDLIB_H__
++
++#include <linux/kernel.h>
++#include <linux/malloc.h>
++#include <linux/types.h>
++#include <asm/string.h>
++
++#define strtol(nptr,endptr,base) simple_strtol(nptr,endptr,base)
++
++#if 0
++#define malloc(size) kmalloc(size, GFP_KERNEL)
++#define free(ptr) kfree(ptr)
++#endif
++
++static inline void *malloc(size_t size)
++{
++ void *ptr = NULL;
++
++ if (size == 0)
++ size = 4;
++
++ ptr = kmalloc(size + sizeof(size), GFP_KERNEL);
++
++ if (ptr)
++ {
++ *((size_t *)ptr) = size;
++ ptr = (size_t *)ptr + 1;
++ }
++
++ return ptr;
++}
++
++static inline void free(void *ptr)
++{
++ if (ptr)
++ kfree((size_t *)ptr - 1);
++}
++
++#define alloca(size) malloc(size)
++
++/* freeca(ptr) - free a mem allocation if ptr points to one, otherwise do
++ * nothing.
++ */
++static inline void freeca(void *ptr)
++{
++ if (ptr != NULL) { /* Don't free it if it's already free */
++ free(ptr);
++ }
++}
++
++static inline void *calloc(size_t nmemb, size_t size)
++{
++ void *ptr = malloc(nmemb*size);
++ if (ptr)
++ memset(ptr,0,nmemb*size);
++ return ptr;
++}
++
++static inline void *realloc(void *ptr, size_t size)
++{
++ void *newptr = NULL;
++
++ if (size != 0)
++ newptr = malloc(size);
++
++ if (ptr && newptr) /* Copy old contents */
++ {
++ size_t *p1 = (size_t *)ptr - 1;
++ size_t *p2 = (size_t *)newptr - 1;
++ size_t n = *p1 < *p2 ? *p1 : *p2;
++ memcpy(newptr, ptr, n);
++ }
++
++ if (ptr)
++ free(ptr);
++
++ return newptr;
++}
++
++/* Returned by `div'. */
++typedef struct
++{
++ int quot; /* Quotient. */
++ int rem; /* Remainder. */
++} div_t;
++
++static inline div_t div(int number, int denom)
++{
++ div_t result;
++ result.quot = number/denom;
++ result.rem = number-(number*result.quot);
++ return result;
++}
++
++#define atexit(fn) -1
++#define getenv(name) 0
++
++#endif /* __KORBIT_STDLIB_H__ */
+diff -urN linux-2.4.1/net/korbit/include/string.h linux-2.4.1-korbit/net/korbit/include/string.h
+--- linux-2.4.1/net/korbit/include/string.h Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/include/string.h Thu Feb 1 11:46:54 2001
+@@ -0,0 +1,11 @@
++#ifndef __KORBIT_STRING_H__
++#define __KORBIT_STRING_H__
++
++#include <linux/types.h>
++#include <asm/string.h>
++
++#include <glib.h>
++
++#define strerror(errno) g_strerror(errno)
++
++#endif
+diff -urN linux-2.4.1/net/korbit/include/sys/CVS/Entries linux-2.4.1-korbit/net/korbit/include/sys/CVS/Entries
+--- linux-2.4.1/net/korbit/include/sys/CVS/Entries Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/include/sys/CVS/Entries Thu Feb 1 11:46:56 2001
+@@ -0,0 +1,10 @@
++/ioctl.h/1.1.1.1/Thu Feb 1 09:46:55 2001//
++/poll.h/1.25/Thu Feb 1 09:46:55 2001//
++/socket.h/1.20/Thu Feb 1 09:46:55 2001//
++/stat.h/1.1.1.1/Thu Feb 1 09:46:55 2001//
++/time.h/1.1.1.1/Thu Feb 1 09:46:55 2001//
++/types.h/1.1.1.1/Thu Feb 1 09:46:56 2001//
++/uio.h/1.1.1.1/Thu Feb 1 09:46:56 2001//
++/un.h/1.1.1.1/Thu Feb 1 09:46:56 2001//
++/wait.h/1.1.1.1/Thu Feb 1 09:46:56 2001//
++D
+diff -urN linux-2.4.1/net/korbit/include/sys/CVS/Repository linux-2.4.1-korbit/net/korbit/include/sys/CVS/Repository
+--- linux-2.4.1/net/korbit/include/sys/CVS/Repository Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/include/sys/CVS/Repository Thu Feb 1 11:46:55 2001
+@@ -0,0 +1 @@
++/cvsroot/korbit/linux/net/korbit/include/sys
+diff -urN linux-2.4.1/net/korbit/include/sys/CVS/Root linux-2.4.1-korbit/net/korbit/include/sys/CVS/Root
+--- linux-2.4.1/net/korbit/include/sys/CVS/Root Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/include/sys/CVS/Root Thu Feb 1 11:46:55 2001
+@@ -0,0 +1 @@
++vraalsen@cvs.korbit.sourceforge.net:/cvsroot/korbit
+diff -urN linux-2.4.1/net/korbit/include/sys/ioctl.h linux-2.4.1-korbit/net/korbit/include/sys/ioctl.h
+--- linux-2.4.1/net/korbit/include/sys/ioctl.h Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/include/sys/ioctl.h Thu Feb 1 11:46:55 2001
+@@ -0,0 +1,3 @@
++#ifndef __KORBIT_SYS_IOCTL_H__
++#define __KORBIT_SYS_IOCTL_H__
++#endif
+diff -urN linux-2.4.1/net/korbit/include/sys/poll.h linux-2.4.1-korbit/net/korbit/include/sys/poll.h
+--- linux-2.4.1/net/korbit/include/sys/poll.h Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/include/sys/poll.h Fri Feb 2 01:22:10 2001
+@@ -0,0 +1,112 @@
++#ifndef __KORBIT_SYS_POLL_H__
++#define __KORBIT_SYS_POLL_H__
++
++#include <asm/poll.h>
++#include <asm/param.h>
++#include <linux/net.h>
++#include <linux/tcp.h>
++#include <linux/socket.h>
++#include <net/tcp.h>
++#include <net/sock.h>
++#include <linux/skbuff.h>
++#include <linux/sched.h>
++#include "stdlib.h"
++#include "sys/socket.h"
++
++/* Poll the file descriptors described by the NFDS structures starting at
++ * FDS. If TIMEOUT is nonzero and not -1, allow TIMEOUT milliseconds for
++ * an event to occur; if TIMEOUT is -1, block until an event occurs.
++ * Returns the number of file descriptors with events, zero if timed
++ * out, or -1 for errors.
++ */
++
++/* This implementation of poll assumes that we are sitting on the wait
++ * queues for all of the file descriptors already. Therefore if we are about
++ * to block, all we have to do is perform the schedule call which will
++ * automatically cause us to "block".
++ */
++static int poll_CheckFDs(struct pollfd *fds, unsigned long int nfds)
++{
++ int NumReady = 0, i;
++
++ // Loop over the file descriptors seeing if there is already work to be
++ // done...
++ for (i = 0; i < nfds; i++) {
++ struct socket *sock = fd2sock(fds[i].fd);
++ fds[i].revents = 0;
++
++ // Check to see if stuff is available to read
++ if (sock) {
++ // It's a socket baby
++ fds[i].revents = tcp_poll(0, sock, 0);
++
++ // Apparently tcp_poll doesn't look at the CLOSE_WAIT value,
++ // and we have a lot of sockets that end up in this state.
++ // This is a hack to shortcircuit some read failures from
++ // later. This breaks "poll semantics" strictly speaking, but
++ // it's basically the "right thing to do" (tm).
++ if (sock->sk->state == TCP_CLOSE_WAIT)
++ fds[i].revents = POLLHUP;
++ fds[i].revents &= fds[i].events | POLLERR | POLLHUP;
++ } else {
++ // It's a file
++ //struct file *f = fd2file(fd);
++// printk("POLL NOT IMPLEMENTED FOR FILES YET\n");
++ BUG();
++ }
++
++ if (fds[i].revents) {
++ NumReady++;
++// printk("FD #%d: Event = 0x%X\n", i, fds[i].revents);
++ }
++
++ } /* for */
++
++ return NumReady;
++} /* End poll_CheckFDs(). */
++
++
++static int poll(struct pollfd *fds, unsigned long int nfds, int timeout) {
++ wait_queue_t *WaitQueues = 0;
++ int NumReady = poll_CheckFDs(fds, nfds);
++ int i;
++
++ if (NumReady || timeout == 0)
++ return NumReady;
++
++// printk("Starting to Poll... %d fds...\n", nfds);
++ WaitQueues = (wait_queue_t*)malloc(nfds*sizeof(wait_queue_t));
++ if (WaitQueues == 0) return 0; // Crap, nomem...
++
++ for (i = 0; i < nfds; i++) {
++ struct socket *sock = fd2sock(fds[i].fd);
++ init_waitqueue_entry(WaitQueues+i, current);
++
++ if (sock)
++ add_wait_queue_exclusive(sock->sk->sleep, WaitQueues+i);
++// else
++// printk("I don't know how to wait on fd #%d = 0x%X\n", i, fds[i].fd);
++ }
++
++ // Wait for us to get notified by one of the socket wait queue notifiers!
++ do {
++ // Change our task state so that we are not immediately rescheduled.
++ // This lets the scheduler know that we are waiting for something to happen
++ set_current_state(TASK_INTERRUPTIBLE);
++ schedule();
++ } while (!(NumReady = poll_CheckFDs(fds, nfds)));
++
++ set_current_state(TASK_RUNNING);
++
++ for (i = 0; i < nfds; i++) {
++ struct socket *sock = fd2sock(fds[i].fd);
++ if (sock)
++ remove_wait_queue(sock->sk->sleep, WaitQueues+i);
++ }
++
++ free(WaitQueues);
++// printk("Returning %d\n", NumReady);
++ return NumReady;
++}
++
++#endif
+diff -urN linux-2.4.1/net/korbit/include/sys/socket.h linux-2.4.1-korbit/net/korbit/include/sys/socket.h
+--- linux-2.4.1/net/korbit/include/sys/socket.h Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/include/sys/socket.h Thu Feb 1 11:46:55 2001
+@@ -0,0 +1,126 @@
++#ifndef __KORBIT_SYS_SOCKET_H__
++#define __KORBIT_SYS_SOCKET_H__
++typedef unsigned int socklen_t;
++
++#include <linux/socket.h>
++#include <linux/wait.h>
++#include <asm/semaphore.h>
++#include <net/sock.h>
++
++/* These functions are declared in net/socket.c */
++asmlinkage long sys_socket(int family, int type, int protocol);
++struct socket *sockfd_lookup(int fd, int *err);
++
++
++static inline int sock2fd(struct socket *s)
++{
++ return (-(int)s) | 1;
++}
++
++static inline struct socket *fd2sock(int sockfd)
++{
++ if ((sockfd & 1) == 0) /* can't convert a file! */
++ return NULL;
++
++ return (struct socket *)(-(sockfd & ~1));
++}
++
++
++static inline int socket(int domain, int type, int protocol) {
++ struct socket *sock;
++ int retval = sock_create(domain, type, protocol, &sock);
++
++ if (retval < 0) return (int)NULL;
++ return sock2fd(sock);
++}
++
++
++static inline int bind(int sockfd, struct sockaddr *my_addr, socklen_t addrlen)
++{
++ struct socket *sock = fd2sock(sockfd);
++
++ if (sock == NULL)
++ return -1;
++ if (!sock->ops->bind(sock, my_addr, addrlen))
++ return 0;
++ else
++ return -1; /* should normally also set errno */
++}
++
++
++static inline int connect(int sockfd, const struct sockaddr *serv_addr,
++ socklen_t addrlen)
++{
++ struct socket *sock = fd2sock(sockfd);
++ int flags = 0; /* TODO : what is flags supposed to be? */
++
++ if (sock == NULL)
++ return -1;
++
++ if (sock->ops->connect(sock, (struct sockaddr *)serv_addr, addrlen, flags) == 0)
++ return 0;
++ else
++ return -1; /* should normally also set errno */
++}
++
++
++static inline int listen(int sockfd, int backlog)
++{
++ struct socket *sock = fd2sock(sockfd);
++
++ if (sock == NULL)
++ return -1;
++
++ if (sock->ops->listen(sock, backlog) == 0)
++ return 0;
++ else
++ return -1; /* should normally also set errno */
++}
++
++
++static inline int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
++{
++ struct socket *sock = fd2sock(sockfd);
++ struct socket *newsock;
++ struct sockaddr_in *newaddr = (struct sockaddr_in *)addr; /* check? */
++ int flags = 0; /* Should be ok */
++
++ if (sock == 0)
++ return -1;
++
++ newsock = sock_alloc();
++ if (newsock == 0)
++ return -1;
++
++ newsock->type = sock->type;
++ newsock->ops = sock->ops;
++ if (sock->ops->accept(sock, newsock, flags) < 0)
++ {
++ sock_release(newsock);
++ return -1; /* should normally also set errno */
++ }
++
++ newaddr->sin_family = AF_INET;
++ newaddr->sin_port = newsock->sk->dport;
++ newaddr->sin_addr.s_addr = newsock->sk->daddr;
++
++ *addrlen = sizeof(newaddr);
++
++ return sock2fd(newsock);
++}
++
++
++static inline int shutdown(int sockfd, int how)
++{
++ struct socket *sock = fd2sock(sockfd);
++
++ if (sock == NULL)
++ return -1;
++
++ if (sock->ops->shutdown(sock, how) == 0)
++ return 0;
++ else
++ return -1; /* should normally also set errno */
++}
++
++#endif
+diff -urN linux-2.4.1/net/korbit/include/sys/stat.h linux-2.4.1-korbit/net/korbit/include/sys/stat.h
+--- linux-2.4.1/net/korbit/include/sys/stat.h Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/include/sys/stat.h Thu Feb 1 11:46:55 2001
+@@ -0,0 +1,3 @@
++#ifndef __KORBIT_SYS_STAT_H__
++#define __KORBIT_SYS_STAT_H__
++#endif
+diff -urN linux-2.4.1/net/korbit/include/sys/time.h linux-2.4.1-korbit/net/korbit/include/sys/time.h
+--- linux-2.4.1/net/korbit/include/sys/time.h Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/include/sys/time.h Thu Feb 1 11:46:55 2001
+@@ -0,0 +1,6 @@
++#ifndef __KORBIT_TIME_H__
++#define __KORBIT_TIME_H__
++
++#include <linux/time.h>
++
++#endif
+diff -urN linux-2.4.1/net/korbit/include/sys/types.h linux-2.4.1-korbit/net/korbit/include/sys/types.h
+--- linux-2.4.1/net/korbit/include/sys/types.h Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/include/sys/types.h Thu Feb 1 11:46:56 2001
+@@ -0,0 +1,4 @@
++#ifndef __KORBIT_SYS_TYPES_H__
++#define __KORBIT_SYS_TYPES_H__
++#include <linux/types.h>
++#endif
+diff -urN linux-2.4.1/net/korbit/include/sys/uio.h linux-2.4.1-korbit/net/korbit/include/sys/uio.h
+--- linux-2.4.1/net/korbit/include/sys/uio.h Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/include/sys/uio.h Thu Feb 1 11:46:56 2001
+@@ -0,0 +1,4 @@
++#ifndef __KORBIT_SYS_UIO_H__
++#define __KORBIT_SYS_UIO_H__
++#include <linux/uio.h>
++#endif
+diff -urN linux-2.4.1/net/korbit/include/sys/un.h linux-2.4.1-korbit/net/korbit/include/sys/un.h
+--- linux-2.4.1/net/korbit/include/sys/un.h Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/include/sys/un.h Thu Feb 1 11:46:56 2001
+@@ -0,0 +1,5 @@
++#ifndef __KORBIT_SYS_UN_H__
++#define __KORBIT_SYS_UN_H__
++#include <linux/socket.h>
++#include <linux/un.h>
++#endif
+diff -urN linux-2.4.1/net/korbit/include/sys/wait.h linux-2.4.1-korbit/net/korbit/include/sys/wait.h
+--- linux-2.4.1/net/korbit/include/sys/wait.h Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/include/sys/wait.h Thu Feb 1 11:46:56 2001
+@@ -0,0 +1,3 @@
++#ifndef __KORBIT_SYS_WAIT_H__
++#define __KORBIT_SYS_WAIT_H__
++#endif
+diff -urN linux-2.4.1/net/korbit/include/syslog.h linux-2.4.1-korbit/net/korbit/include/syslog.h
+--- linux-2.4.1/net/korbit/include/syslog.h Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/include/syslog.h Thu Feb 1 11:46:54 2001
+@@ -0,0 +1,7 @@
++#ifndef __KORBIT_SYSLOG_H__
++#define __KORBIT_SYSLOG_H__
++
++#define LOG_NOTICE 5 /* normal but significant condition */
++#define LOG_INFO 6 /* informational */
++
++#endif
+diff -urN linux-2.4.1/net/korbit/include/time.h linux-2.4.1-korbit/net/korbit/include/time.h
+--- linux-2.4.1/net/korbit/include/time.h Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/include/time.h Thu Feb 1 11:46:54 2001
+@@ -0,0 +1,4 @@
++#ifndef __KORBIT_TIME_H__
++#define __KORBIT_TIME_H__
++
++#endif
+diff -urN linux-2.4.1/net/korbit/include/unistd.h linux-2.4.1-korbit/net/korbit/include/unistd.h
+--- linux-2.4.1/net/korbit/include/unistd.h Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/include/unistd.h Thu Feb 1 11:46:54 2001
+@@ -0,0 +1,19 @@
++#ifndef __KORBIT_UNISTD_H__
++#define __KORBIT_UNISTD_H__
++
++#include <linux/types.h>
++#include <linux/utsname.h>
++#include <asm/string.h>
++#include <asm/semaphore.h>
++/* extern char *getcwd(char * buf, size_t size); */
++
++static inline int gethostname(char *name, size_t len) {
++ down_read(&uts_sem);
++ strncpy(name, system_utsname.nodename, len);
++ up_read(&uts_sem);
++printk("gethostname() = %s\n", name);
++ return 0;
++}
++
++
++#endif
+diff -urN linux-2.4.1/net/korbit/include/utime.h linux-2.4.1-korbit/net/korbit/include/utime.h
+--- linux-2.4.1/net/korbit/include/utime.h Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/include/utime.h Thu Feb 1 11:46:54 2001
+@@ -0,0 +1,4 @@
++#ifndef __KORBIT_UTIME_H__
++#define __KORBIT_UTIME_H__
++#include <linux/utime.h>
++#endif
+diff -urN linux-2.4.1/net/korbit/kglib/CVS/Entries linux-2.4.1-korbit/net/korbit/kglib/CVS/Entries
+--- linux-2.4.1/net/korbit/kglib/CVS/Entries Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/kglib/CVS/Entries Thu Feb 1 11:46:57 2001
+@@ -0,0 +1,15 @@
++/Makefile/1.4/Thu Feb 1 09:46:56 2001//
++/garray.c/1.3/Thu Feb 1 09:46:56 2001//
++/ghash.c/1.2/Thu Feb 1 09:46:56 2001//
++/glib.h/1.3/Thu Feb 1 09:46:56 2001//
++/glibconfig.h/1.2/Thu Feb 1 09:46:56 2001//
++/glist.c/1.1.1.1/Thu Feb 1 09:46:57 2001//
++/gmem.c/1.2/Thu Feb 1 09:46:57 2001//
++/gprimes.c/1.1.1.1/Thu Feb 1 09:46:57 2001//
++/gslist.c/1.1.1.1/Thu Feb 1 09:46:57 2001//
++/gstrfuncs.c/1.2/Thu Feb 1 09:46:57 2001//
++/gstring.c/1.1.1.1/Thu Feb 1 09:46:57 2001//
++/gtree.c/1.1.1.1/Thu Feb 1 09:46:57 2001//
++/gutils.c/1.2/Thu Feb 1 09:46:57 2001//
++/korbit_errno.c/1.1/Thu Feb 1 09:46:57 2001//
++D
+diff -urN linux-2.4.1/net/korbit/kglib/CVS/Repository linux-2.4.1-korbit/net/korbit/kglib/CVS/Repository
+--- linux-2.4.1/net/korbit/kglib/CVS/Repository Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/kglib/CVS/Repository Thu Feb 1 11:46:56 2001
+@@ -0,0 +1 @@
++/cvsroot/korbit/linux/net/korbit/kglib
+diff -urN linux-2.4.1/net/korbit/kglib/CVS/Root linux-2.4.1-korbit/net/korbit/kglib/CVS/Root
+--- linux-2.4.1/net/korbit/kglib/CVS/Root Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/kglib/CVS/Root Thu Feb 1 11:46:56 2001
+@@ -0,0 +1 @@
++vraalsen@cvs.korbit.sourceforge.net:/cvsroot/korbit
+diff -urN linux-2.4.1/net/korbit/kglib/Makefile linux-2.4.1-korbit/net/korbit/kglib/Makefile
+--- linux-2.4.1/net/korbit/kglib/Makefile Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/kglib/Makefile Thu Feb 1 11:46:56 2001
+@@ -0,0 +1,18 @@
++#
++# Makefile for KORBit/kglib
++#
++# Note! Dependencies are done automagically by 'make dep', which also
++# removes any old dependencies. DON'T put your own dependencies here
++# unless it's something special (ie not a .c file).
++#
++# Note 2! The CFLAGS definition is now in the main makefile...
++
++O_TARGET := kglib.o
++
++#obj-m := $(O_TARGET)
++obj-y := garray.o glist.o gprimes.o gstrfuncs.o gtree.o \
++ ghash.o gmem.o gslist.o gstring.o gutils.o korbit_errno.o
++
++EXTRA_CFLAGS = -D__KORBIT__ -DHAVE_CONFIG_H -DHAVE_UNISTD_H -I. -I.. -I../include -nostdinc
++include $(TOPDIR)/Rules.make
++
+diff -urN linux-2.4.1/net/korbit/kglib/garray.c linux-2.4.1-korbit/net/korbit/kglib/garray.c
+--- linux-2.4.1/net/korbit/kglib/garray.c Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/kglib/garray.c Thu Feb 1 11:46:56 2001
+@@ -0,0 +1,431 @@
++/* GLIB - Library of useful routines for C programming
++ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Library General Public
++ * License as published by the Free Software Foundation; either
++ * version 2 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Library General Public License for more details.
++ *
++ * You should have received a copy of the GNU Library General Public
++ * License along with this library; if not, write to the
++ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
++ * Boston, MA 02111-1307, USA.
++ */
++
++/*
++ * Modified by the GLib Team and others 1997-1999. See the AUTHORS
++ * file for a list of people on the GLib Team. See the ChangeLog
++ * files for a list of changes. These files are distributed with
++ * GLib at ftp://ftp.gtk.org/pub/gtk/.
++ */
++
++#include <string.h>
++#include "glib.h"
++
++
++#define MIN_ARRAY_SIZE 16
++
++
++typedef struct _GRealArray GRealArray;
++
++struct _GRealArray
++{
++ guint8 *data;
++ guint len;
++ guint alloc;
++ guint elt_size;
++ guint zero_terminated : 1;
++ guint clear : 1;
++};
++
++
++static gint g_nearest_pow (gint num);
++static void g_array_maybe_expand (GRealArray *array,
++ gint len);
++
++static GMemChunk *array_mem_chunk = NULL;
++G_LOCK_DEFINE_STATIC (array_mem_chunk);
++
++GArray*
++g_array_new (gboolean zero_terminated,
++ gboolean clear,
++ guint elt_size)
++{
++ GRealArray *array;
++
++ G_LOCK (array_mem_chunk);
++ if (!array_mem_chunk)
++ array_mem_chunk = g_mem_chunk_new ("array mem chunk",
++ sizeof (GRealArray),
++ 1024, G_ALLOC_AND_FREE);
++
++ array = g_chunk_new (GRealArray, array_mem_chunk);
++ G_UNLOCK (array_mem_chunk);
++
++ array->data = NULL;
++ array->len = 0;
++ array->alloc = 0;
++ array->zero_terminated = (zero_terminated ? 1 : 0);
++ array->clear = (clear ? 1 : 0);
++ array->elt_size = elt_size;
++
++ return (GArray*) array;
++}
++
++void
++g_array_free (GArray *array,
++ gboolean free_segment)
++{
++ if (free_segment)
++ g_free (array->data);
++
++ G_LOCK (array_mem_chunk);
++ g_mem_chunk_free (array_mem_chunk, array);
++ G_UNLOCK (array_mem_chunk);
++}
++
++GArray*
++g_array_append_vals (GArray *farray,
++ gconstpointer data,
++ guint len)
++{
++ GRealArray *array = (GRealArray*) farray;
++
++ g_array_maybe_expand (array, len);
++
++ memcpy (array->data + array->elt_size * array->len, data, array->elt_size * len);
++
++ array->len += len;
++
++ return farray;
++}
++
++GArray*
++g_array_prepend_vals (GArray *farray,
++ gconstpointer data,
++ guint len)
++{
++ GRealArray *array = (GRealArray*) farray;
++
++ g_array_maybe_expand (array, len);
++
++ g_memmove (array->data + array->elt_size * len, array->data, array->elt_size * array->len);
++
++ memcpy (array->data, data, len * array->elt_size);
++
++ array->len += len;
++
++ return farray;
++}
++
++GArray*
++g_array_insert_vals (GArray *farray,
++ guint index,
++ gconstpointer data,
++ guint len)
++{
++ GRealArray *array = (GRealArray*) farray;
++
++ g_array_maybe_expand (array, len);
++
++ g_memmove (array->data + array->elt_size * (len + index),
++ array->data + array->elt_size * index,
++ array->elt_size * (array->len - index));
++
++ memcpy (array->data + array->elt_size * index, data, len * array->elt_size);
++
++ array->len += len;
++
++ return farray;
++}
++
++GArray*
++g_array_set_size (GArray *farray,
++ guint length)
++{
++ GRealArray *array = (GRealArray*) farray;
++
++ if (array->len < length)
++ g_array_maybe_expand (array, length - array->len);
++
++ array->len = length;
++
++ return farray;
++}
++
++GArray*
++g_array_remove_index (GArray* farray,
++ guint index)
++{
++ GRealArray* array = (GRealArray*) farray;
++
++ g_return_val_if_fail (array, NULL);
++
++ g_return_val_if_fail (index < array->len, NULL);
++
++ if (index != array->len - 1)
++ g_memmove (array->data + array->elt_size * index,
++ array->data + array->elt_size * (index + 1),
++ array->elt_size * (array->len - index - 1));
++
++ if (array->zero_terminated)
++ memset (array->data + array->elt_size * (array->len - 1), 0,
++ array->elt_size);
++
++ array->len -= 1;
++
++ return farray;
++}
++
++GArray*
++g_array_remove_index_fast (GArray* farray,
++ guint index)
++{
++ GRealArray* array = (GRealArray*) farray;
++
++ g_return_val_if_fail (array, NULL);
++
++ g_return_val_if_fail (index < array->len, NULL);
++
++ if (index != array->len - 1)
++ g_memmove (array->data + array->elt_size * index,
++ array->data + array->elt_size * (array->len - 1),
++ array->elt_size);
++
++ if (array->zero_terminated)
++ memset (array->data + array->elt_size * (array->len - 1), 0,
++ array->elt_size);
++
++ array->len -= 1;
++
++ return farray;
++}
++
++static gint
++g_nearest_pow (gint num)
++{
++ gint n = 1;
++
++ while (n < num)
++ n <<= 1;
++
++ return n;
++}
++
++static void
++g_array_maybe_expand (GRealArray *array,
++ gint len)
++{
++ guint want_alloc = (array->len + len + array->zero_terminated) * array->elt_size;
++
++ if (want_alloc > array->alloc)
++ {
++ guint old_alloc = array->alloc;
++
++ array->alloc = g_nearest_pow (want_alloc);
++ array->alloc = MAX (array->alloc, MIN_ARRAY_SIZE);
++
++ array->data = g_realloc (array->data, array->alloc);
++
++ if (array->clear || array->zero_terminated)
++ memset (array->data + old_alloc, 0, array->alloc - old_alloc);
++ }
++}
++
++/* Pointer Array
++ */
++
++typedef struct _GRealPtrArray GRealPtrArray;
++
++struct _GRealPtrArray
++{
++ gpointer *pdata;
++ guint len;
++ guint alloc;
++};
++
++static void g_ptr_array_maybe_expand (GRealPtrArray *array,
++ gint len);
++
++static GMemChunk *ptr_array_mem_chunk = NULL;
++G_LOCK_DEFINE_STATIC (ptr_array_mem_chunk);
++
++
++GPtrArray*
++g_ptr_array_new (void)
++{
++ GRealPtrArray *array;
++
++ G_LOCK (ptr_array_mem_chunk);
++ if (!ptr_array_mem_chunk)
++ ptr_array_mem_chunk = g_mem_chunk_new ("array mem chunk",
++ sizeof (GRealPtrArray),
++ 1024, G_ALLOC_AND_FREE);
++
++ array = g_chunk_new (GRealPtrArray, ptr_array_mem_chunk);
++ G_UNLOCK (ptr_array_mem_chunk);
++
++ array->pdata = NULL;
++ array->len = 0;
++ array->alloc = 0;
++
++ return (GPtrArray*) array;
++}
++
++void
++g_ptr_array_free (GPtrArray *array,
++ gboolean free_segment)
++{
++ g_return_if_fail (array);
++
++ if (free_segment)
++ g_free (array->pdata);
++
++ G_LOCK (ptr_array_mem_chunk);
++ g_mem_chunk_free (ptr_array_mem_chunk, array);
++ G_UNLOCK (ptr_array_mem_chunk);
++}
++
++static void
++g_ptr_array_maybe_expand (GRealPtrArray *array,
++ gint len)
++{
++ guint old_alloc;
++
++ if ((array->len + len) > array->alloc)
++ {
++ old_alloc = array->alloc;
++
++ array->alloc = g_nearest_pow (array->len + len);
++ array->alloc = MAX (array->alloc, MIN_ARRAY_SIZE);
++ if (array->pdata)
++ array->pdata = g_realloc (array->pdata, sizeof(gpointer) * array->alloc);
++ else
++ array->pdata = g_new0 (gpointer, array->alloc);
++
++ memset (array->pdata + old_alloc, 0,
++ sizeof (gpointer) * (array->alloc - old_alloc));
++ }
++}
++
++void
++g_ptr_array_set_size (GPtrArray *farray,
++ gint length)
++{
++ GRealPtrArray* array = (GRealPtrArray*) farray;
++
++ g_return_if_fail (array);
++
++ if (length > array->len)
++ g_ptr_array_maybe_expand (array, (length - array->len));
++
++ array->len = length;
++}
++
++gpointer
++g_ptr_array_remove_index (GPtrArray* farray,
++ guint index)
++{
++ GRealPtrArray* array = (GRealPtrArray*) farray;
++ gpointer result;
++
++ g_return_val_if_fail (array, NULL);
++
++ g_return_val_if_fail (index < array->len, NULL);
++
++ result = array->pdata[index];
++
++ if (index != array->len - 1)
++ g_memmove (array->pdata + index, array->pdata + index + 1,
++ sizeof (gpointer) * (array->len - index - 1));
++
++ array->pdata[array->len - 1] = NULL;
++
++ array->len -= 1;
++
++ return result;
++}
++
++gpointer
++g_ptr_array_remove_index_fast (GPtrArray* farray,
++ guint index)
++{
++ GRealPtrArray* array = (GRealPtrArray*) farray;
++ gpointer result;
++
++ g_return_val_if_fail (array, NULL);
++
++ g_return_val_if_fail (index < array->len, NULL);
++
++ result = array->pdata[index];
++
++ if (index != array->len - 1)
++ array->pdata[index] = array->pdata[array->len - 1];
++
++ array->pdata[array->len - 1] = NULL;
++
++ array->len -= 1;
++
++ return result;
++}
++
++gboolean
++g_ptr_array_remove (GPtrArray* farray,
++ gpointer data)
++{
++ GRealPtrArray* array = (GRealPtrArray*) farray;
++ int i;
++
++ g_return_val_if_fail (array, FALSE);
++
++ for (i = 0; i < array->len; i += 1)
++ {
++ if (array->pdata[i] == data)
++ {
++ g_ptr_array_remove_index (farray, i);
++ return TRUE;
++ }
++ }
++
++ return FALSE;
++}
++
++gboolean
++g_ptr_array_remove_fast (GPtrArray* farray,
++ gpointer data)
++{
++ GRealPtrArray* array = (GRealPtrArray*) farray;
++ int i;
++
++ g_return_val_if_fail (array, FALSE);
++
++ for (i = 0; i < array->len; i += 1)
++ {
++ if (array->pdata[i] == data)
++ {
++ g_ptr_array_remove_index_fast (farray, i);
++ return TRUE;
++ }
++ }
++
++ return FALSE;
++}
++
++void
++g_ptr_array_add (GPtrArray* farray,
++ gpointer data)
++{
++ GRealPtrArray* array = (GRealPtrArray*) farray;
++
++ g_return_if_fail (array);
++
++ g_ptr_array_maybe_expand (array, 1);
++
++ array->pdata[array->len++] = data;
++}
++
+diff -urN linux-2.4.1/net/korbit/kglib/ghash.c linux-2.4.1-korbit/net/korbit/kglib/ghash.c
+--- linux-2.4.1/net/korbit/kglib/ghash.c Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/kglib/ghash.c Thu Feb 1 11:46:56 2001
+@@ -0,0 +1,404 @@
++/* GLIB - Library of useful routines for C programming
++ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Library General Public
++ * License as published by the Free Software Foundation; either
++ * version 2 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Library General Public License for more details.
++ *
++ * You should have received a copy of the GNU Library General Public
++ * License along with this library; if not, write to the
++ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
++ * Boston, MA 02111-1307, USA.
++ */
++
++/*
++ * Modified by the GLib Team and others 1997-1999. See the AUTHORS
++ * file for a list of people on the GLib Team. See the ChangeLog
++ * files for a list of changes. These files are distributed with
++ * GLib at ftp://ftp.gtk.org/pub/gtk/.
++ */
++
++#include "glib.h"
++
++
++#define HASH_TABLE_MIN_SIZE 11
++#define HASH_TABLE_MAX_SIZE 13845163
++
++
++typedef struct _GHashNode GHashNode;
++
++struct _GHashNode
++{
++ gpointer key;
++ gpointer value;
++ GHashNode *next;
++};
++
++struct _GHashTable
++{
++ gint size;
++ gint nnodes;
++ guint frozen;
++ GHashNode **nodes;
++ GHashFunc hash_func;
++ GCompareFunc key_compare_func;
++};
++
++
++static void g_hash_table_resize (GHashTable *hash_table);
++static GHashNode** g_hash_table_lookup_node (GHashTable *hash_table,
++ gconstpointer key);
++static GHashNode* g_hash_node_new (gpointer key,
++ gpointer value);
++static void g_hash_node_destroy (GHashNode *hash_node);
++static void g_hash_nodes_destroy (GHashNode *hash_node);
++
++
++G_LOCK_DEFINE_STATIC (g_hash_global);
++
++static GMemChunk *node_mem_chunk = NULL;
++static GHashNode *node_free_list = NULL;
++
++
++GHashTable*
++g_hash_table_new (GHashFunc hash_func,
++ GCompareFunc key_compare_func)
++{
++ GHashTable *hash_table;
++ guint i;
++
++ hash_table = g_new (GHashTable, 1);
++ hash_table->size = HASH_TABLE_MIN_SIZE;
++ hash_table->nnodes = 0;
++ hash_table->frozen = FALSE;
++ hash_table->hash_func = hash_func ? hash_func : g_direct_hash;
++ hash_table->key_compare_func = key_compare_func;
++ hash_table->nodes = g_new (GHashNode*, hash_table->size);
++
++ for (i = 0; i < hash_table->size; i++)
++ hash_table->nodes[i] = NULL;
++
++ return hash_table;
++}
++
++void
++g_hash_table_destroy (GHashTable *hash_table)
++{
++ guint i;
++
++ g_return_if_fail (hash_table != NULL);
++
++ for (i = 0; i < hash_table->size; i++)
++ g_hash_nodes_destroy (hash_table->nodes[i]);
++
++ g_free (hash_table->nodes);
++ g_free (hash_table);
++}
++
++static inline GHashNode**
++g_hash_table_lookup_node (GHashTable *hash_table,
++ gconstpointer key)
++{
++ GHashNode **node;
++
++ node = &hash_table->nodes
++ [(* hash_table->hash_func) (key) % hash_table->size];
++
++ /* Hash table lookup needs to be fast.
++ * We therefore remove the extra conditional of testing
++ * whether to call the key_compare_func or not from
++ * the inner loop.
++ */
++ if (hash_table->key_compare_func)
++ while (*node && !(*hash_table->key_compare_func) ((*node)->key, key))
++ node = &(*node)->next;
++ else
++ while (*node && (*node)->key != key)
++ node = &(*node)->next;
++
++ return node;
++}
++
++gpointer
++g_hash_table_lookup (GHashTable *hash_table,
++ gconstpointer key)
++{
++ GHashNode *node;
++
++ g_return_val_if_fail (hash_table != NULL, NULL);
++
++ node = *g_hash_table_lookup_node (hash_table, key);
++
++ return node ? node->value : NULL;
++}
++
++void
++g_hash_table_insert (GHashTable *hash_table,
++ gpointer key,
++ gpointer value)
++{
++ GHashNode **node;
++
++ g_return_if_fail (hash_table != NULL);
++
++ node = g_hash_table_lookup_node (hash_table, key);
++
++ if (*node)
++ {
++ /* do not reset node->key in this place, keeping
++ * the old key might be intended.
++ * a g_hash_table_remove/g_hash_table_insert pair
++ * can be used otherwise.
++ *
++ * node->key = key; */
++ (*node)->value = value;
++ }
++ else
++ {
++ *node = g_hash_node_new (key, value);
++ hash_table->nnodes++;
++ if (!hash_table->frozen)
++ g_hash_table_resize (hash_table);
++ }
++}
++
++void
++g_hash_table_remove (GHashTable *hash_table,
++ gconstpointer key)
++{
++ GHashNode **node, *dest;
++
++ g_return_if_fail (hash_table != NULL);
++
++ node = g_hash_table_lookup_node (hash_table, key);
++
++ if (*node)
++ {
++ dest = *node;
++ (*node) = dest->next;
++ g_hash_node_destroy (dest);
++ hash_table->nnodes--;
++
++ if (!hash_table->frozen)
++ g_hash_table_resize (hash_table);
++ }
++}
++
++gboolean
++g_hash_table_lookup_extended (GHashTable *hash_table,
++ gconstpointer lookup_key,
++ gpointer *orig_key,
++ gpointer *value)
++{
++ GHashNode *node;
++
++ g_return_val_if_fail (hash_table != NULL, FALSE);
++
++ node = *g_hash_table_lookup_node (hash_table, lookup_key);
++
++ if (node)
++ {
++ if (orig_key)
++ *orig_key = node->key;
++ if (value)
++ *value = node->value;
++ return TRUE;
++ }
++ else
++ return FALSE;
++}
++
++void
++g_hash_table_freeze (GHashTable *hash_table)
++{
++ g_return_if_fail (hash_table != NULL);
++
++ hash_table->frozen++;
++}
++
++void
++g_hash_table_thaw (GHashTable *hash_table)
++{
++ g_return_if_fail (hash_table != NULL);
++
++ if (hash_table->frozen)
++ if (!(--hash_table->frozen))
++ g_hash_table_resize (hash_table);
++}
++
++guint
++g_hash_table_foreach_remove (GHashTable *hash_table,
++ GHRFunc func,
++ gpointer user_data)
++{
++ GHashNode *node, *prev;
++ guint i;
++ guint deleted = 0;
++
++ g_return_val_if_fail (hash_table != NULL, 0);
++ g_return_val_if_fail (func != NULL, 0);
++
++ for (i = 0; i < hash_table->size; i++)
++ {
++ restart:
++
++ prev = NULL;
++
++ for (node = hash_table->nodes[i]; node; prev = node, node = node->next)
++ {
++ if ((* func) (node->key, node->value, user_data))
++ {
++ deleted += 1;
++
++ hash_table->nnodes -= 1;
++
++ if (prev)
++ {
++ prev->next = node->next;
++ g_hash_node_destroy (node);
++ node = prev;
++ }
++ else
++ {
++ hash_table->nodes[i] = node->next;
++ g_hash_node_destroy (node);
++ goto restart;
++ }
++ }
++ }
++ }
++
++ if (!hash_table->frozen)
++ g_hash_table_resize (hash_table);
++
++ return deleted;
++}
++
++void
++g_hash_table_foreach (GHashTable *hash_table,
++ GHFunc func,
++ gpointer user_data)
++{
++ GHashNode *node;
++ gint i;
++
++ g_return_if_fail (hash_table != NULL);
++ g_return_if_fail (func != NULL);
++
++ for (i = 0; i < hash_table->size; i++)
++ for (node = hash_table->nodes[i]; node; node = node->next)
++ (* func) (node->key, node->value, user_data);
++}
++
++/* Returns the number of elements contained in the hash table. */
++guint
++g_hash_table_size (GHashTable *hash_table)
++{
++ g_return_val_if_fail (hash_table != NULL, 0);
++
++ return hash_table->nnodes;
++}
++
++static void
++g_hash_table_resize (GHashTable *hash_table)
++{
++ GHashNode **new_nodes;
++ GHashNode *node;
++ GHashNode *next;
++#ifdef __KORBIT__
++ guint nodes_per_list;
++#else
++ gfloat nodes_per_list;
++#endif
++ guint hash_val;
++ gint new_size;
++ gint i;
++
++ nodes_per_list = (hash_table->nnodes * 10) / hash_table->size;
++
++ if ((nodes_per_list > 3 || hash_table->size <= HASH_TABLE_MIN_SIZE) &&
++ (nodes_per_list < 30 || hash_table->size >= HASH_TABLE_MAX_SIZE))
++ return;
++
++ new_size = CLAMP(g_spaced_primes_closest (hash_table->nnodes),
++ HASH_TABLE_MIN_SIZE,
++ HASH_TABLE_MAX_SIZE);
++ new_nodes = g_new0 (GHashNode*, new_size);
++
++ for (i = 0; i < hash_table->size; i++)
++ for (node = hash_table->nodes[i]; node; node = next)
++ {
++ next = node->next;
++
++ hash_val = (* hash_table->hash_func) (node->key) % new_size;
++
++ node->next = new_nodes[hash_val];
++ new_nodes[hash_val] = node;
++ }
++
++ g_free (hash_table->nodes);
++ hash_table->nodes = new_nodes;
++ hash_table->size = new_size;
++}
++
++static GHashNode*
++g_hash_node_new (gpointer key,
++ gpointer value)
++{
++ GHashNode *hash_node;
++
++ G_LOCK (g_hash_global);
++ if (node_free_list)
++ {
++ hash_node = node_free_list;
++ node_free_list = node_free_list->next;
++ }
++ else
++ {
++ if (!node_mem_chunk)
++ node_mem_chunk = g_mem_chunk_new ("hash node mem chunk",
++ sizeof (GHashNode),
++ 1024, G_ALLOC_ONLY);
++
++ hash_node = g_chunk_new (GHashNode, node_mem_chunk);
++ }
++ G_UNLOCK (g_hash_global);
++
++ hash_node->key = key;
++ hash_node->value = value;
++ hash_node->next = NULL;
++
++ return hash_node;
++}
++
++static void
++g_hash_node_destroy (GHashNode *hash_node)
++{
++ G_LOCK (g_hash_global);
++ hash_node->next = node_free_list;
++ node_free_list = hash_node;
++ G_UNLOCK (g_hash_global);
++}
++
++static void
++g_hash_nodes_destroy (GHashNode *hash_node)
++{
++ if (hash_node)
++ {
++ GHashNode *node = hash_node;
++
++ while (node->next)
++ node = node->next;
++
++ G_LOCK (g_hash_global);
++ node->next = node_free_list;
++ node_free_list = hash_node;
++ G_UNLOCK (g_hash_global);
++ }
++}
+diff -urN linux-2.4.1/net/korbit/kglib/glib.h linux-2.4.1-korbit/net/korbit/kglib/glib.h
+--- linux-2.4.1/net/korbit/kglib/glib.h Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/kglib/glib.h Thu Feb 1 11:46:56 2001
+@@ -0,0 +1,1671 @@
++/* GLIB - Library of useful routines for C programming
++ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Library General Public
++ * License as published by the Free Software Foundation; either
++ * version 2 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Library General Public License for more details.
++ *
++ * You should have received a copy of the GNU Library General Public
++ * License along with this library; if not, write to the
++ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
++ * Boston, MA 02111-1307, USA.
++ */
++
++#ifndef __G_LIB_H__
++#define __G_LIB_H__
++
++#ifdef __KORBIT__
++#define G_DISABLE_ASSERT 1
++#include <stdio.h>
++#endif
++
++#include "config.h"
++
++/* system specific config file glibconfig.h provides definitions for
++ * the extrema of many of the standard types. These are:
++ *
++ * G_MINSHORT, G_MAXSHORT
++ * G_MININT, G_MAXINT
++ * G_MINLONG, G_MAXLONG
++ * G_MINFLOAT, G_MAXFLOAT
++ * G_MINDOUBLE, G_MAXDOUBLE
++ *
++ * It also provides the following typedefs:
++ *
++ * gint8, guint8
++ * gint16, guint16
++ * gint32, guint32
++ * gint64, guint64
++ *
++ * It defines the G_BYTE_ORDER symbol to one of G_*_ENDIAN (see later in
++ * this file).
++ *
++ * And it provides a way to store and retrieve a `gint' in/from a `gpointer'.
++ * This is useful to pass an integer instead of a pointer to a callback.
++ *
++ * GINT_TO_POINTER(i), GUINT_TO_POINTER(i)
++ * GPOINTER_TO_INT(p), GPOINTER_TO_UINT(p)
++ *
++ * Finally, it provide the following wrappers to STDC functions:
++ *
++ * g_ATEXIT
++ * To register hooks which are executed on exit().
++ * Usually a wrapper for STDC atexit.
++ *
++ * void *g_memmove(void *dest, const void *src, guint count);
++ * A wrapper for STDC memmove, or an implementation, if memmove doesn't
++ * exist. The prototype looks like the above, give or take a const,
++ * or size_t.
++ */
++#include <glibconfig.h>
++
++/* include varargs functions for assertment macros
++ */
++#include <stdarg.h>
++
++#define G_DIR_SEPARATOR '/'
++#define G_DIR_SEPARATOR_S "/"
++#define G_SEARCHPATH_SEPARATOR ':'
++#define G_SEARCHPATH_SEPARATOR_S ":"
++
++#ifdef __cplusplus
++extern "C" {
++#endif /* __cplusplus */
++
++
++/* Provide definitions for some commonly used macros.
++ * Some of them are only provided if they haven't already
++ * been defined. It is assumed that if they are already
++ * defined then the current definition is correct.
++ */
++#ifndef NULL
++#define NULL ((void*) 0)
++#endif
++
++#ifndef FALSE
++#define FALSE (0)
++#endif
++
++#ifndef TRUE
++#define TRUE (!FALSE)
++#endif
++
++#undef MAX
++#define MAX(a, b) (((a) > (b)) ? (a) : (b))
++
++#undef MIN
++#define MIN(a, b) (((a) < (b)) ? (a) : (b))
++
++#undef ABS
++#define ABS(a) (((a) < 0) ? -(a) : (a))
++
++#undef CLAMP
++#define CLAMP(x, low, high) (((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x)))
++
++
++/* Define G_VA_COPY() to do the right thing for copying va_list variables.
++ * glibconfig.h may have already defined G_VA_COPY as va_copy or __va_copy.
++ */
++#if !defined (G_VA_COPY)
++# if defined (__GNUC__) && defined (__PPC__) && (defined (_CALL_SYSV) || defined (_WIN32))
++# define G_VA_COPY(ap1, ap2) (*(ap1) = *(ap2))
++# elif defined (G_VA_COPY_AS_ARRAY)
++# define G_VA_COPY(ap1, ap2) g_memmove ((ap1), (ap2), sizeof (va_list))
++# else /* va_list is a pointer */
++# define G_VA_COPY(ap1, ap2) ((ap1) = (ap2))
++# endif /* va_list is a pointer */
++#endif /* !G_VA_COPY */
++
++
++/* Provide convenience macros for handling structure
++ * fields through their offsets.
++ */
++#define G_STRUCT_OFFSET(struct_type, member) \
++ ((gulong) ((gchar*) &((struct_type*) 0)->member))
++#define G_STRUCT_MEMBER_P(struct_p, struct_offset) \
++ ((gpointer) ((gchar*) (struct_p) + (gulong) (struct_offset)))
++#define G_STRUCT_MEMBER(member_type, struct_p, struct_offset) \
++ (*(member_type*) G_STRUCT_MEMBER_P ((struct_p), (struct_offset)))
++
++
++/* inlining hassle. for compilers that don't allow the `inline' keyword,
++ * mostly because of strict ANSI C compliance or dumbness, we try to fall
++ * back to either `__inline__' or `__inline'.
++ * we define G_CAN_INLINE, if the compiler seems to be actually
++ * *capable* to do function inlining, in which case inline function bodys
++ * do make sense. we also define G_INLINE_FUNC to properly export the
++ * function prototypes if no inlining can be performed.
++ * we special case most of the stuff, so inline functions can have a normal
++ * implementation by defining G_INLINE_FUNC to extern and G_CAN_INLINE to 1.
++ */
++#ifndef G_INLINE_FUNC
++# define G_CAN_INLINE 1
++#endif
++#ifdef G_HAVE_INLINE
++# if defined (__GNUC__) && defined (__STRICT_ANSI__)
++# undef inline
++# define inline __inline__
++# endif
++#else /* !G_HAVE_INLINE */
++# undef inline
++# if defined (G_HAVE___INLINE__)
++# define inline __inline__
++# else /* !inline && !__inline__ */
++# if defined (G_HAVE___INLINE)
++# define inline __inline
++# else /* !inline && !__inline__ && !__inline */
++# define inline /* don't inline, then */
++# ifndef G_INLINE_FUNC
++# undef G_CAN_INLINE
++# endif
++# endif
++# endif
++#endif
++#ifndef G_INLINE_FUNC
++# ifdef __GNUC__
++# ifdef __OPTIMIZE__
++# define G_INLINE_FUNC extern inline
++# else
++# undef G_CAN_INLINE
++# define G_INLINE_FUNC extern
++# endif
++# else /* !__GNUC__ */
++# ifdef G_CAN_INLINE
++# define G_INLINE_FUNC static inline
++# else
++# define G_INLINE_FUNC extern
++# endif
++# endif /* !__GNUC__ */
++#endif /* !G_INLINE_FUNC */
++
++
++/* Provide simple macro statement wrappers (adapted from Perl):
++ * G_STMT_START { statements; } G_STMT_END;
++ * can be used as a single statement, as in
++ * if (x) G_STMT_START { ... } G_STMT_END; else ...
++ *
++ * For gcc we will wrap the statements within `({' and `})' braces.
++ * For SunOS they will be wrapped within `if (1)' and `else (void) 0',
++ * and otherwise within `do' and `while (0)'.
++ */
++#if !(defined (G_STMT_START) && defined (G_STMT_END))
++# if defined (__GNUC__) && !defined (__STRICT_ANSI__) && !defined (__cplusplus)
++# define G_STMT_START (void)(
++# define G_STMT_END )
++# else
++# if (defined (sun) || defined (__sun__))
++# define G_STMT_START if (1)
++# define G_STMT_END else (void)0
++# else
++# define G_STMT_START do
++# define G_STMT_END while (0)
++# endif
++# endif
++#endif
++
++
++/* Provide macros to feature the GCC function attribute.
++ */
++#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 4)
++#define G_GNUC_PRINTF( format_idx, arg_idx ) \
++ __attribute__((format (printf, format_idx, arg_idx)))
++#define G_GNUC_SCANF( format_idx, arg_idx ) \
++ __attribute__((format (scanf, format_idx, arg_idx)))
++#define G_GNUC_FORMAT( arg_idx ) \
++ __attribute__((format_arg (arg_idx)))
++#define G_GNUC_NORETURN \
++ __attribute__((noreturn))
++#define G_GNUC_CONST \
++ __attribute__((const))
++#define G_GNUC_UNUSED \
++ __attribute__((unused))
++#else /* !__GNUC__ */
++#define G_GNUC_PRINTF( format_idx, arg_idx )
++#define G_GNUC_SCANF( format_idx, arg_idx )
++#define G_GNUC_FORMAT( arg_idx )
++#define G_GNUC_NORETURN
++#define G_GNUC_CONST
++#define G_GNUC_UNUSED
++#endif /* !__GNUC__ */
++
++
++/* Wrap the gcc __PRETTY_FUNCTION__ and __FUNCTION__ variables with
++ * macros, so we can refer to them as strings unconditionally.
++ */
++#ifdef __GNUC__
++#define G_GNUC_FUNCTION __FUNCTION__
++#define G_GNUC_PRETTY_FUNCTION __PRETTY_FUNCTION__
++#else /* !__GNUC__ */
++#define G_GNUC_FUNCTION ""
++#define G_GNUC_PRETTY_FUNCTION ""
++#endif /* !__GNUC__ */
++
++/* we try to provide a usefull equivalent for ATEXIT if it is
++ * not defined, but use is actually abandoned. people should
++ * use g_atexit() instead.
++ */
++#ifndef ATEXIT
++# define ATEXIT(proc) g_ATEXIT(proc)
++#else
++# define G_NATIVE_ATEXIT
++#endif /* ATEXIT */
++
++/* Hacker macro to place breakpoints for elected machines.
++ * Actual use is strongly deprecated of course ;)
++ */
++#if defined (__i386__) && defined (__GNUC__) && __GNUC__ >= 2
++#define G_BREAKPOINT() G_STMT_START{ __asm__ __volatile__ ("int $03"); }G_STMT_END
++#elif defined (__alpha__) && defined (__GNUC__) && __GNUC__ >= 2
++#define G_BREAKPOINT() G_STMT_START{ __asm__ __volatile__ ("bpt"); }G_STMT_END
++#else /* !__i386__ && !__alpha__ */
++#define G_BREAKPOINT()
++#endif /* __i386__ */
++
++
++/* Provide macros for easily allocating memory. The macros
++ * will cast the allocated memory to the specified type
++ * in order to avoid compiler warnings. (Makes the code neater).
++ */
++
++#ifdef __DMALLOC_H__
++# define g_new(type, count) (ALLOC (type, count))
++# define g_new0(type, count) (CALLOC (type, count))
++# define g_renew(type, mem, count) (REALLOC (mem, type, count))
++#else /* __DMALLOC_H__ */
++# define g_new(type, count) \
++ ((type *) g_malloc ((unsigned) sizeof (type) * (count)))
++# define g_new0(type, count) \
++ ((type *) g_malloc0 ((unsigned) sizeof (type) * (count)))
++# define g_renew(type, mem, count) \
++ ((type *) g_realloc (mem, (unsigned) sizeof (type) * (count)))
++#endif /* __DMALLOC_H__ */
++
++#define g_mem_chunk_create(type, pre_alloc, alloc_type) ( \
++ g_mem_chunk_new (#type " mem chunks (" #pre_alloc ")", \
++ sizeof (type), \
++ sizeof (type) * (pre_alloc), \
++ (alloc_type)) \
++)
++#define g_chunk_new(type, chunk) ( \
++ (type *) g_mem_chunk_alloc (chunk) \
++)
++#define g_chunk_new0(type, chunk) ( \
++ (type *) g_mem_chunk_alloc0 (chunk) \
++)
++#define g_chunk_free(mem, mem_chunk) G_STMT_START { \
++ g_mem_chunk_free ((mem_chunk), (mem)); \
++} G_STMT_END
++
++
++#define g_string(x) #x
++
++
++/* Provide macros for error handling. The "assert" macros will
++ * exit on failure. The "return" macros will exit the current
++ * function. Two different definitions are given for the macros
++ * if G_DISABLE_ASSERT is not defined, in order to support gcc's
++ * __PRETTY_FUNCTION__ capability.
++ */
++
++#ifdef G_DISABLE_ASSERT
++
++#define g_assert(expr)
++#define g_assert_not_reached()
++
++#else /* !G_DISABLE_ASSERT */
++
++#ifdef __GNUC__
++
++#define g_assert(expr) G_STMT_START{ \
++ if (!(expr)) \
++ g_log (G_LOG_DOMAIN, \
++ G_LOG_LEVEL_ERROR, \
++ "file %s: line %d (%s): assertion failed: (%s)", \
++ __FILE__, \
++ __LINE__, \
++ __PRETTY_FUNCTION__, \
++ #expr); }G_STMT_END
++
++#define g_assert_not_reached() G_STMT_START{ \
++ g_log (G_LOG_DOMAIN, \
++ G_LOG_LEVEL_ERROR, \
++ "file %s: line %d (%s): should not be reached", \
++ __FILE__, \
++ __LINE__, \
++ __PRETTY_FUNCTION__); }G_STMT_END
++
++#else /* !__GNUC__ */
++
++#define g_assert(expr) G_STMT_START{ \
++ if (!(expr)) \
++ g_log (G_LOG_DOMAIN, \
++ G_LOG_LEVEL_ERROR, \
++ "file %s: line %d: assertion failed: (%s)", \
++ __FILE__, \
++ __LINE__, \
++ #expr); }G_STMT_END
++
++#define g_assert_not_reached() G_STMT_START{ \
++ g_log (G_LOG_DOMAIN, \
++ G_LOG_LEVEL_ERROR, \
++ "file %s: line %d: should not be reached", \
++ __FILE__, \
++ __LINE__); }G_STMT_END
++
++#endif /* __GNUC__ */
++
++#endif /* !G_DISABLE_ASSERT */
++
++
++#ifdef __KORBIT__
++
++#define g_return_if_fail(expr) G_STMT_START{ \
++ if (!(expr)) \
++ { \
++ return; \
++ }; }G_STMT_END
++
++#define g_return_val_if_fail(expr,val) G_STMT_START{ \
++ if (!(expr)) \
++ { \
++ return val; \
++ }; }G_STMT_END
++
++#else /* !__KORBIT__ */
++
++#ifdef G_DISABLE_CHECKS
++
++#define g_return_if_fail(expr)
++#define g_return_val_if_fail(expr,val)
++
++#else /* !G_DISABLE_CHECKS */
++
++#ifdef __GNUC__
++
++#define g_return_if_fail(expr) G_STMT_START{ \
++ if (!(expr)) \
++ { \
++ g_log (G_LOG_DOMAIN, \
++ G_LOG_LEVEL_CRITICAL, \
++ "file %s: line %d (%s): assertion `%s' failed.", \
++ __FILE__, \
++ __LINE__, \
++ __PRETTY_FUNCTION__, \
++ #expr); \
++ return; \
++ }; }G_STMT_END
++
++#define g_return_val_if_fail(expr,val) G_STMT_START{ \
++ if (!(expr)) \
++ { \
++ g_log (G_LOG_DOMAIN, \
++ G_LOG_LEVEL_CRITICAL, \
++ "file %s: line %d (%s): assertion `%s' failed.", \
++ __FILE__, \
++ __LINE__, \
++ __PRETTY_FUNCTION__, \
++ #expr); \
++ return val; \
++ }; }G_STMT_END
++
++#else /* !__GNUC__ */
++
++#define g_return_if_fail(expr) G_STMT_START{ \
++ if (!(expr)) \
++ { \
++ g_log (G_LOG_DOMAIN, \
++ G_LOG_LEVEL_CRITICAL, \
++ "file %s: line %d: assertion `%s' failed.", \
++ __FILE__, \
++ __LINE__, \
++ #expr); \
++ return; \
++ }; }G_STMT_END
++
++#define g_return_val_if_fail(expr, val) G_STMT_START{ \
++ if (!(expr)) \
++ { \
++ g_log (G_LOG_DOMAIN, \
++ G_LOG_LEVEL_CRITICAL, \
++ "file %s: line %d: assertion `%s' failed.", \
++ __FILE__, \
++ __LINE__, \
++ #expr); \
++ return val; \
++ }; }G_STMT_END
++
++#endif /* !__GNUC__ */
++
++#endif /* !G_DISABLE_CHECKS */
++
++#endif /* !__KORBIT__ */
++
++
++/* Provide type definitions for commonly used types.
++ * These are useful because a "gint8" can be adjusted
++ * to be 1 byte (8 bits) on all platforms. Similarly and
++ * more importantly, "gint32" can be adjusted to be
++ * 4 bytes (32 bits) on all platforms.
++ */
++
++typedef char gchar;
++typedef short gshort;
++typedef long glong;
++typedef int gint;
++typedef gint gboolean;
++
++typedef unsigned char guchar;
++typedef unsigned short gushort;
++typedef unsigned long gulong;
++typedef unsigned int guint;
++
++typedef float gfloat;
++typedef double gdouble;
++
++/* HAVE_LONG_DOUBLE doesn't work correctly on all platforms.
++ * Since gldouble isn't used anywhere, just disable it for now */
++
++#if 0
++#ifdef HAVE_LONG_DOUBLE
++typedef long double gldouble;
++#else /* HAVE_LONG_DOUBLE */
++typedef double gldouble;
++#endif /* HAVE_LONG_DOUBLE */
++#endif /* 0 */
++
++typedef void* gpointer;
++typedef const void *gconstpointer;
++
++
++typedef gint32 gssize;
++typedef guint32 gsize;
++typedef guint32 GQuark;
++typedef gint32 GTime;
++
++
++/* Portable endian checks and conversions
++ *
++ * glibconfig.h defines G_BYTE_ORDER which expands to one of
++ * the below macros.
++ */
++#define G_LITTLE_ENDIAN 1234
++#define G_BIG_ENDIAN 4321
++#define G_PDP_ENDIAN 3412 /* unused, need specific PDP check */
++
++
++/* Basic bit swapping functions
++ */
++#define GUINT16_SWAP_LE_BE_CONSTANT(val) ((guint16) ( \
++ (((guint16) (val) & (guint16) 0x00ffU) << 8) | \
++ (((guint16) (val) & (guint16) 0xff00U) >> 8)))
++#define GUINT32_SWAP_LE_BE_CONSTANT(val) ((guint32) ( \
++ (((guint32) (val) & (guint32) 0x000000ffU) << 24) | \
++ (((guint32) (val) & (guint32) 0x0000ff00U) << 8) | \
++ (((guint32) (val) & (guint32) 0x00ff0000U) >> 8) | \
++ (((guint32) (val) & (guint32) 0xff000000U) >> 24)))
++
++/* Intel specific stuff for speed
++ */
++#if defined (__i386__) && defined (__GNUC__) && __GNUC__ >= 2
++# define GUINT16_SWAP_LE_BE_X86(val) \
++ (__extension__ \
++ ({ register guint16 __v; \
++ if (__builtin_constant_p (val)) \
++ __v = GUINT16_SWAP_LE_BE_CONSTANT (val); \
++ else \
++ __asm__ __const__ ("rorw $8, %w0" \
++ : "=r" (__v) \
++ : "0" ((guint16) (val))); \
++ __v; }))
++# define GUINT16_SWAP_LE_BE(val) (GUINT16_SWAP_LE_BE_X86 (val))
++# if !defined(__i486__) && !defined(__i586__) \
++ && !defined(__pentium__) && !defined(__i686__) && !defined(__pentiumpro__)
++# define GUINT32_SWAP_LE_BE_X86(val) \
++ (__extension__ \
++ ({ register guint32 __v; \
++ if (__builtin_constant_p (val)) \
++ __v = GUINT32_SWAP_LE_BE_CONSTANT (val); \
++ else \
++ __asm__ __const__ ("rorw $8, %w0\n\t" \
++ "rorl $16, %0\n\t" \
++ "rorw $8, %w0" \
++ : "=r" (__v) \
++ : "0" ((guint32) (val))); \
++ __v; }))
++# else /* 486 and higher has bswap */
++# define GUINT32_SWAP_LE_BE_X86(val) \
++ (__extension__ \
++ ({ register guint32 __v; \
++ if (__builtin_constant_p (val)) \
++ __v = GUINT32_SWAP_LE_BE_CONSTANT (val); \
++ else \
++ __asm__ __const__ ("bswap %0" \
++ : "=r" (__v) \
++ : "0" ((guint32) (val))); \
++ __v; }))
++# endif /* processor specific 32-bit stuff */
++# define GUINT32_SWAP_LE_BE(val) (GUINT32_SWAP_LE_BE_X86 (val))
++#else /* !__i386__ */
++# define GUINT16_SWAP_LE_BE(val) (GUINT16_SWAP_LE_BE_CONSTANT (val))
++# define GUINT32_SWAP_LE_BE(val) (GUINT32_SWAP_LE_BE_CONSTANT (val))
++#endif /* __i386__ */
++
++#ifdef G_HAVE_GINT64
++# define GUINT64_SWAP_LE_BE_CONSTANT(val) ((guint64) ( \
++ (((guint64) (val) & \
++ (guint64) G_GINT64_CONSTANT(0x00000000000000ffU)) << 56) | \
++ (((guint64) (val) & \
++ (guint64) G_GINT64_CONSTANT(0x000000000000ff00U)) << 40) | \
++ (((guint64) (val) & \
++ (guint64) G_GINT64_CONSTANT(0x0000000000ff0000U)) << 24) | \
++ (((guint64) (val) & \
++ (guint64) G_GINT64_CONSTANT(0x00000000ff000000U)) << 8) | \
++ (((guint64) (val) & \
++ (guint64) G_GINT64_CONSTANT(0x000000ff00000000U)) >> 8) | \
++ (((guint64) (val) & \
++ (guint64) G_GINT64_CONSTANT(0x0000ff0000000000U)) >> 24) | \
++ (((guint64) (val) & \
++ (guint64) G_GINT64_CONSTANT(0x00ff000000000000U)) >> 40) | \
++ (((guint64) (val) & \
++ (guint64) G_GINT64_CONSTANT(0xff00000000000000U)) >> 56)))
++# if defined (__i386__) && defined (__GNUC__) && __GNUC__ >= 2
++# define GUINT64_SWAP_LE_BE_X86(val) \
++ (__extension__ \
++ ({ union { guint64 __ll; \
++ guint32 __l[2]; } __r; \
++ if (__builtin_constant_p (val)) \
++ __r.__ll = GUINT64_SWAP_LE_BE_CONSTANT (val); \
++ else \
++ { \
++ union { guint64 __ll; \
++ guint32 __l[2]; } __w; \
++ __w.__ll = ((guint64) val); \
++ __r.__l[0] = GUINT32_SWAP_LE_BE (__w.__l[1]); \
++ __r.__l[1] = GUINT32_SWAP_LE_BE (__w.__l[0]); \
++ } \
++ __r.__ll; }))
++# define GUINT64_SWAP_LE_BE(val) (GUINT64_SWAP_LE_BE_X86 (val))
++# else /* !__i386__ */
++# define GUINT64_SWAP_LE_BE(val) (GUINT64_SWAP_LE_BE_CONSTANT(val))
++# endif
++#endif
++
++#define GUINT16_SWAP_LE_PDP(val) ((guint16) (val))
++#define GUINT16_SWAP_BE_PDP(val) (GUINT16_SWAP_LE_BE (val))
++#define GUINT32_SWAP_LE_PDP(val) ((guint32) ( \
++ (((guint32) (val) & (guint32) 0x0000ffffU) << 16) | \
++ (((guint32) (val) & (guint32) 0xffff0000U) >> 16)))
++#define GUINT32_SWAP_BE_PDP(val) ((guint32) ( \
++ (((guint32) (val) & (guint32) 0x00ff00ffU) << 8) | \
++ (((guint32) (val) & (guint32) 0xff00ff00U) >> 8)))
++
++/* The G*_TO_?E() macros are defined in glibconfig.h.
++ * The transformation is symmetric, so the FROM just maps to the TO.
++ */
++#define GINT16_FROM_LE(val) (GINT16_TO_LE (val))
++#define GUINT16_FROM_LE(val) (GUINT16_TO_LE (val))
++#define GINT16_FROM_BE(val) (GINT16_TO_BE (val))
++#define GUINT16_FROM_BE(val) (GUINT16_TO_BE (val))
++#define GINT32_FROM_LE(val) (GINT32_TO_LE (val))
++#define GUINT32_FROM_LE(val) (GUINT32_TO_LE (val))
++#define GINT32_FROM_BE(val) (GINT32_TO_BE (val))
++#define GUINT32_FROM_BE(val) (GUINT32_TO_BE (val))
++
++#ifdef G_HAVE_GINT64
++#define GINT64_FROM_LE(val) (GINT64_TO_LE (val))
++#define GUINT64_FROM_LE(val) (GUINT64_TO_LE (val))
++#define GINT64_FROM_BE(val) (GINT64_TO_BE (val))
++#define GUINT64_FROM_BE(val) (GUINT64_TO_BE (val))
++#endif
++
++#define GLONG_FROM_LE(val) (GLONG_TO_LE (val))
++#define GULONG_FROM_LE(val) (GULONG_TO_LE (val))
++#define GLONG_FROM_BE(val) (GLONG_TO_BE (val))
++#define GULONG_FROM_BE(val) (GULONG_TO_BE (val))
++
++#define GINT_FROM_LE(val) (GINT_TO_LE (val))
++#define GUINT_FROM_LE(val) (GUINT_TO_LE (val))
++#define GINT_FROM_BE(val) (GINT_TO_BE (val))
++#define GUINT_FROM_BE(val) (GUINT_TO_BE (val))
++
++
++/* Portable versions of host-network order stuff
++ */
++#define g_ntohl(val) (GUINT32_FROM_BE (val))
++#define g_ntohs(val) (GUINT16_FROM_BE (val))
++#define g_htonl(val) (GUINT32_TO_BE (val))
++#define g_htons(val) (GUINT16_TO_BE (val))
++
++
++/* Glib version.
++ * we prefix variable declarations so they can
++ * properly get exported in windows dlls.
++ */
++#define GUTILS_C_VAR extern
++
++
++GUTILS_C_VAR const guint glib_major_version;
++GUTILS_C_VAR const guint glib_minor_version;
++GUTILS_C_VAR const guint glib_micro_version;
++GUTILS_C_VAR const guint glib_interface_age;
++GUTILS_C_VAR const guint glib_binary_age;
++
++#define GLIB_CHECK_VERSION(major,minor,micro) \
++ (GLIB_MAJOR_VERSION > (major) || \
++ (GLIB_MAJOR_VERSION == (major) && GLIB_MINOR_VERSION > (minor)) || \
++ (GLIB_MAJOR_VERSION == (major) && GLIB_MINOR_VERSION == (minor) && \
++ GLIB_MICRO_VERSION >= (micro)))
++
++/* Forward declarations of glib types.
++ */
++typedef struct _GAllocator GAllocator;
++typedef struct _GArray GArray;
++typedef struct _GByteArray GByteArray;
++typedef struct _GDebugKey GDebugKey;
++typedef struct _GHashTable GHashTable;
++typedef struct _GList GList;
++typedef struct _GMemChunk GMemChunk;
++typedef struct _GNode GNode;
++typedef struct _GPtrArray GPtrArray;
++typedef struct _GSList GSList;
++typedef struct _GString GString;
++typedef struct _GStringChunk GStringChunk;
++typedef struct _GTree GTree;
++typedef struct _GTuples GTuples;
++
++/* Tree traverse flags */
++typedef enum
++{
++ G_TRAVERSE_LEAFS = 1 << 0,
++ G_TRAVERSE_NON_LEAFS = 1 << 1,
++ G_TRAVERSE_ALL = G_TRAVERSE_LEAFS | G_TRAVERSE_NON_LEAFS,
++ G_TRAVERSE_MASK = 0x03
++} GTraverseFlags;
++
++/* Tree traverse orders */
++typedef enum
++{
++ G_IN_ORDER,
++ G_PRE_ORDER,
++ G_POST_ORDER,
++ G_LEVEL_ORDER
++} GTraverseType;
++
++/* Log level shift offset for user defined
++ * log levels (0-7 are used by GLib).
++ */
++#define G_LOG_LEVEL_USER_SHIFT (8)
++
++/* Glib log levels and flags.
++ */
++typedef enum
++{
++ /* log flags */
++ G_LOG_FLAG_RECURSION = 1 << 0,
++ G_LOG_FLAG_FATAL = 1 << 1,
++
++ /* GLib log levels */
++ G_LOG_LEVEL_ERROR = 1 << 2, /* always fatal */
++ G_LOG_LEVEL_CRITICAL = 1 << 3,
++ G_LOG_LEVEL_WARNING = 1 << 4,
++ G_LOG_LEVEL_MESSAGE = 1 << 5,
++ G_LOG_LEVEL_INFO = 1 << 6,
++ G_LOG_LEVEL_DEBUG = 1 << 7,
++
++ G_LOG_LEVEL_MASK = ~(G_LOG_FLAG_RECURSION | G_LOG_FLAG_FATAL)
++} GLogLevelFlags;
++
++/* GLib log levels that are considered fatal by default */
++#define G_LOG_FATAL_MASK (G_LOG_FLAG_RECURSION | G_LOG_LEVEL_ERROR)
++
++
++typedef gint (*GCompareFunc) (gconstpointer a,
++ gconstpointer b);
++typedef gchar* (*GCompletionFunc) (gpointer);
++typedef void (*GDestroyNotify) (gpointer data);
++typedef void (*GDataForeachFunc) (GQuark key_id,
++ gpointer data,
++ gpointer user_data);
++typedef void (*GFunc) (gpointer data,
++ gpointer user_data);
++typedef guint (*GHashFunc) (gconstpointer key);
++typedef void (*GFreeFunc) (gpointer data);
++typedef void (*GHFunc) (gpointer key,
++ gpointer value,
++ gpointer user_data);
++typedef gboolean (*GHRFunc) (gpointer key,
++ gpointer value,
++ gpointer user_data);
++typedef void (*GLogFunc) (const gchar *log_domain,
++ GLogLevelFlags log_level,
++ const gchar *message,
++ gpointer user_data);
++typedef gboolean (*GNodeTraverseFunc) (GNode *node,
++ gpointer data);
++typedef void (*GNodeForeachFunc) (GNode *node,
++ gpointer data);
++typedef gint (*GSearchFunc) (gpointer key,
++ gpointer data);
++typedef gint (*GTraverseFunc) (gpointer key,
++ gpointer value,
++ gpointer data);
++typedef void (*GVoidFunc) (void);
++
++
++struct _GList
++{
++ gpointer data;
++ GList *next;
++ GList *prev;
++};
++
++struct _GSList
++{
++ gpointer data;
++ GSList *next;
++};
++
++struct _GString
++{
++ gchar *str;
++ gint len;
++};
++
++struct _GArray
++{
++ gchar *data;
++ guint len;
++};
++
++struct _GByteArray
++{
++ guint8 *data;
++ guint len;
++};
++
++struct _GPtrArray
++{
++ gpointer *pdata;
++ guint len;
++};
++
++struct _GTuples
++{
++ guint len;
++};
++
++struct _GDebugKey
++{
++ gchar *key;
++ guint value;
++};
++
++
++/* Doubly linked lists
++ */
++void g_list_push_allocator (GAllocator *allocator);
++void g_list_pop_allocator (void);
++GList* g_list_alloc (void);
++void g_list_free (GList *list);
++void g_list_free_1 (GList *list);
++GList* g_list_append (GList *list,
++ gpointer data);
++GList* g_list_prepend (GList *list,
++ gpointer data);
++GList* g_list_insert (GList *list,
++ gpointer data,
++ gint position);
++GList* g_list_insert_sorted (GList *list,
++ gpointer data,
++ GCompareFunc func);
++GList* g_list_concat (GList *list1,
++ GList *list2);
++GList* g_list_remove (GList *list,
++ gpointer data);
++GList* g_list_remove_link (GList *list,
++ GList *llink);
++GList* g_list_reverse (GList *list);
++GList* g_list_copy (GList *list);
++GList* g_list_nth (GList *list,
++ guint n);
++GList* g_list_find (GList *list,
++ gpointer data);
++GList* g_list_find_custom (GList *list,
++ gpointer data,
++ GCompareFunc func);
++gint g_list_position (GList *list,
++ GList *llink);
++gint g_list_index (GList *list,
++ gpointer data);
++GList* g_list_last (GList *list);
++GList* g_list_first (GList *list);
++guint g_list_length (GList *list);
++void g_list_foreach (GList *list,
++ GFunc func,
++ gpointer user_data);
++GList* g_list_sort (GList *list,
++ GCompareFunc compare_func);
++gpointer g_list_nth_data (GList *list,
++ guint n);
++#define g_list_previous(list) ((list) ? (((GList *)(list))->prev) : NULL)
++#define g_list_next(list) ((list) ? (((GList *)(list))->next) : NULL)
++
++
++/* Singly linked lists
++ */
++void g_slist_push_allocator (GAllocator *allocator);
++void g_slist_pop_allocator (void);
++GSList* g_slist_alloc (void);
++void g_slist_free (GSList *list);
++void g_slist_free_1 (GSList *list);
++GSList* g_slist_append (GSList *list,
++ gpointer data);
++GSList* g_slist_prepend (GSList *list,
++ gpointer data);
++GSList* g_slist_insert (GSList *list,
++ gpointer data,
++ gint position);
++GSList* g_slist_insert_sorted (GSList *list,
++ gpointer data,
++ GCompareFunc func);
++GSList* g_slist_concat (GSList *list1,
++ GSList *list2);
++GSList* g_slist_remove (GSList *list,
++ gpointer data);
++GSList* g_slist_remove_link (GSList *list,
++ GSList *llink);
++GSList* g_slist_reverse (GSList *list);
++GSList* g_slist_copy (GSList *list);
++GSList* g_slist_nth (GSList *list,
++ guint n);
++GSList* g_slist_find (GSList *list,
++ gpointer data);
++GSList* g_slist_find_custom (GSList *list,
++ gpointer data,
++ GCompareFunc func);
++gint g_slist_position (GSList *list,
++ GSList *llink);
++gint g_slist_index (GSList *list,
++ gpointer data);
++GSList* g_slist_last (GSList *list);
++guint g_slist_length (GSList *list);
++void g_slist_foreach (GSList *list,
++ GFunc func,
++ gpointer user_data);
++GSList* g_slist_sort (GSList *list,
++ GCompareFunc compare_func);
++gpointer g_slist_nth_data (GSList *list,
++ guint n);
++#define g_slist_next(slist) ((slist) ? (((GSList *)(slist))->next) : NULL)
++
++
++/* Hash tables
++ */
++GHashTable* g_hash_table_new (GHashFunc hash_func,
++ GCompareFunc key_compare_func);
++void g_hash_table_destroy (GHashTable *hash_table);
++void g_hash_table_insert (GHashTable *hash_table,
++ gpointer key,
++ gpointer value);
++void g_hash_table_remove (GHashTable *hash_table,
++ gconstpointer key);
++gpointer g_hash_table_lookup (GHashTable *hash_table,
++ gconstpointer key);
++gboolean g_hash_table_lookup_extended(GHashTable *hash_table,
++ gconstpointer lookup_key,
++ gpointer *orig_key,
++ gpointer *value);
++void g_hash_table_freeze (GHashTable *hash_table);
++void g_hash_table_thaw (GHashTable *hash_table);
++void g_hash_table_foreach (GHashTable *hash_table,
++ GHFunc func,
++ gpointer user_data);
++guint g_hash_table_foreach_remove (GHashTable *hash_table,
++ GHRFunc func,
++ gpointer user_data);
++guint g_hash_table_size (GHashTable *hash_table);
++
++
++
++
++/* Balanced binary trees
++ */
++GTree* g_tree_new (GCompareFunc key_compare_func);
++void g_tree_destroy (GTree *tree);
++void g_tree_insert (GTree *tree,
++ gpointer key,
++ gpointer value);
++void g_tree_remove (GTree *tree,
++ gpointer key);
++gpointer g_tree_lookup (GTree *tree,
++ gpointer key);
++void g_tree_traverse (GTree *tree,
++ GTraverseFunc traverse_func,
++ GTraverseType traverse_type,
++ gpointer data);
++gpointer g_tree_search (GTree *tree,
++ GSearchFunc search_func,
++ gpointer data);
++gint g_tree_height (GTree *tree);
++gint g_tree_nnodes (GTree *tree);
++
++
++
++/* N-way tree implementation
++ */
++struct _GNode
++{
++ gpointer data;
++ GNode *next;
++ GNode *prev;
++ GNode *parent;
++ GNode *children;
++};
++
++#define G_NODE_IS_ROOT(node) (((GNode*) (node))->parent == NULL && \
++ ((GNode*) (node))->prev == NULL && \
++ ((GNode*) (node))->next == NULL)
++#define G_NODE_IS_LEAF(node) (((GNode*) (node))->children == NULL)
++
++void g_node_push_allocator (GAllocator *allocator);
++void g_node_pop_allocator (void);
++GNode* g_node_new (gpointer data);
++void g_node_destroy (GNode *root);
++void g_node_unlink (GNode *node);
++GNode* g_node_insert (GNode *parent,
++ gint position,
++ GNode *node);
++GNode* g_node_insert_before (GNode *parent,
++ GNode *sibling,
++ GNode *node);
++GNode* g_node_prepend (GNode *parent,
++ GNode *node);
++guint g_node_n_nodes (GNode *root,
++ GTraverseFlags flags);
++GNode* g_node_get_root (GNode *node);
++gboolean g_node_is_ancestor (GNode *node,
++ GNode *descendant);
++guint g_node_depth (GNode *node);
++GNode* g_node_find (GNode *root,
++ GTraverseType order,
++ GTraverseFlags flags,
++ gpointer data);
++
++/* convenience macros */
++#define g_node_append(parent, node) \
++ g_node_insert_before ((parent), NULL, (node))
++#define g_node_insert_data(parent, position, data) \
++ g_node_insert ((parent), (position), g_node_new (data))
++#define g_node_insert_data_before(parent, sibling, data) \
++ g_node_insert_before ((parent), (sibling), g_node_new (data))
++#define g_node_prepend_data(parent, data) \
++ g_node_prepend ((parent), g_node_new (data))
++#define g_node_append_data(parent, data) \
++ g_node_insert_before ((parent), NULL, g_node_new (data))
++
++/* traversal function, assumes that `node' is root
++ * (only traverses `node' and its subtree).
++ * this function is just a high level interface to
++ * low level traversal functions, optimized for speed.
++ */
++void g_node_traverse (GNode *root,
++ GTraverseType order,
++ GTraverseFlags flags,
++ gint max_depth,
++ GNodeTraverseFunc func,
++ gpointer data);
++
++/* return the maximum tree height starting with `node', this is an expensive
++ * operation, since we need to visit all nodes. this could be shortened by
++ * adding `guint height' to struct _GNode, but then again, this is not very
++ * often needed, and would make g_node_insert() more time consuming.
++ */
++guint g_node_max_height (GNode *root);
++
++void g_node_children_foreach (GNode *node,
++ GTraverseFlags flags,
++ GNodeForeachFunc func,
++ gpointer data);
++void g_node_reverse_children (GNode *node);
++guint g_node_n_children (GNode *node);
++GNode* g_node_nth_child (GNode *node,
++ guint n);
++GNode* g_node_last_child (GNode *node);
++GNode* g_node_find_child (GNode *node,
++ GTraverseFlags flags,
++ gpointer data);
++gint g_node_child_position (GNode *node,
++ GNode *child);
++gint g_node_child_index (GNode *node,
++ gpointer data);
++
++GNode* g_node_first_sibling (GNode *node);
++GNode* g_node_last_sibling (GNode *node);
++
++#define g_node_prev_sibling(node) ((node) ? \
++ ((GNode*) (node))->prev : NULL)
++#define g_node_next_sibling(node) ((node) ? \
++ ((GNode*) (node))->next : NULL)
++#define g_node_first_child(node) ((node) ? \
++ ((GNode*) (node))->children : NULL)
++
++
++
++/* Fatal error handlers.
++ * g_on_error_query() will prompt the user to either
++ * [E]xit, [H]alt, [P]roceed or show [S]tack trace.
++ * g_on_error_stack_trace() invokes gdb, which attaches to the current
++ * process and shows a stack trace.
++ * These function may cause different actions on non-unix platforms.
++ * The prg_name arg is required by gdb to find the executable, if it is
++ * passed as NULL, g_on_error_query() will try g_get_prgname().
++ */
++void g_on_error_query (const gchar *prg_name);
++void g_on_error_stack_trace (const gchar *prg_name);
++
++
++/* Logging mechanism
++ */
++extern const gchar *g_log_domain_glib;
++guint g_log_set_handler (const gchar *log_domain,
++ GLogLevelFlags log_levels,
++ GLogFunc log_func,
++ gpointer user_data);
++void g_log_remove_handler (const gchar *log_domain,
++ guint handler_id);
++void g_log_default_handler (const gchar *log_domain,
++ GLogLevelFlags log_level,
++ const gchar *message,
++ gpointer unused_data);
++#ifdef __KORBIT__
++#define g_log(log_domain, log_level, format, args...) \
++G_STMT_START { printf(format, ##args); printf("\n"); } G_STMT_END
++#define g_logv(log_domain, log_level, format, args...)
++#else /* !__KORBIT__ */
++void g_log (const gchar *log_domain,
++ GLogLevelFlags log_level,
++ const gchar *format,
++ ...) G_GNUC_PRINTF (3, 4);
++void g_logv (const gchar *log_domain,
++ GLogLevelFlags log_level,
++ const gchar *format,
++ va_list args);
++#endif /* !__KORBIT__ */
++GLogLevelFlags g_log_set_fatal_mask (const gchar *log_domain,
++ GLogLevelFlags fatal_mask);
++GLogLevelFlags g_log_set_always_fatal (GLogLevelFlags fatal_mask);
++#ifndef G_LOG_DOMAIN
++#define G_LOG_DOMAIN ((gchar*) 0)
++#endif /* G_LOG_DOMAIN */
++#ifdef __GNUC__
++#define g_error(format, args...) g_log (G_LOG_DOMAIN, \
++ G_LOG_LEVEL_ERROR, \
++ format, ##args)
++#define g_message(format, args...) g_log (G_LOG_DOMAIN, \
++ G_LOG_LEVEL_MESSAGE, \
++ format, ##args)
++#define g_warning(format, args...) g_log (G_LOG_DOMAIN, \
++ G_LOG_LEVEL_WARNING, \
++ format, ##args)
++#else /* !__GNUC__ */
++static void
++g_error (const gchar *format,
++ ...)
++{
++ va_list args;
++ va_start (args, format);
++ g_logv (G_LOG_DOMAIN, G_LOG_LEVEL_ERROR, format, args);
++ va_end (args);
++}
++static void
++g_message (const gchar *format,
++ ...)
++{
++ va_list args;
++ va_start (args, format);
++ g_logv (G_LOG_DOMAIN, G_LOG_LEVEL_MESSAGE, format, args);
++ va_end (args);
++}
++static void
++g_warning (const gchar *format,
++ ...)
++{
++ va_list args;
++ va_start (args, format);
++ g_logv (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING, format, args);
++ va_end (args);
++}
++#endif /* !__GNUC__ */
++
++typedef void (*GPrintFunc) (const gchar *string);
++#ifdef __KORBIT__
++#define g_print(format, args...) printf(format, ##args)
++#else
++void g_print (const gchar *format,
++ ...) G_GNUC_PRINTF (1, 2);
++#endif
++GPrintFunc g_set_print_handler (GPrintFunc func);
++void g_printerr (const gchar *format,
++ ...) G_GNUC_PRINTF (1, 2);
++GPrintFunc g_set_printerr_handler (GPrintFunc func);
++
++/* deprecated compatibility functions, use g_log_set_handler() instead */
++typedef void (*GErrorFunc) (const gchar *str);
++typedef void (*GWarningFunc) (const gchar *str);
++GErrorFunc g_set_error_handler (GErrorFunc func);
++GWarningFunc g_set_warning_handler (GWarningFunc func);
++GPrintFunc g_set_message_handler (GPrintFunc func);
++
++
++gpointer g_malloc (gulong size);
++gpointer g_malloc0 (gulong size);
++gpointer g_realloc (gpointer mem,
++ gulong size);
++void g_free (gpointer mem);
++
++/* Generic allocators
++ */
++GAllocator* g_allocator_new (const gchar *name,
++ guint n_preallocs);
++void g_allocator_free (GAllocator *allocator);
++
++#define G_ALLOCATOR_LIST (1)
++#define G_ALLOCATOR_SLIST (2)
++#define G_ALLOCATOR_NODE (3)
++
++
++/* "g_mem_chunk_new" creates a new memory chunk.
++ * Memory chunks are used to allocate pieces of memory which are
++ * always the same size. Lists are a good example of such a data type.
++ * The memory chunk allocates and frees blocks of memory as needed.
++ * Just be sure to call "g_mem_chunk_free" and not "g_free" on data
++ * allocated in a mem chunk. ("g_free" will most likely cause a seg
++ * fault...somewhere).
++ *
++ * Oh yeah, GMemChunk is an opaque data type. (You don't really
++ * want to know what's going on inside do you?)
++ */
++
++/* ALLOC_ONLY MemChunk's can only allocate memory. The free operation
++ * is interpreted as a no op. ALLOC_ONLY MemChunk's save 4 bytes per
++ * atom. (They are also useful for lists which use MemChunk to allocate
++ * memory but are also part of the MemChunk implementation).
++ * ALLOC_AND_FREE MemChunk's can allocate and free memory.
++ */
++
++#define G_ALLOC_ONLY 1
++#define G_ALLOC_AND_FREE 2
++
++GMemChunk* g_mem_chunk_new (gchar *name,
++ gint atom_size,
++ gulong area_size,
++ gint type);
++void g_mem_chunk_destroy (GMemChunk *mem_chunk);
++gpointer g_mem_chunk_alloc (GMemChunk *mem_chunk);
++gpointer g_mem_chunk_alloc0 (GMemChunk *mem_chunk);
++void g_mem_chunk_free (GMemChunk *mem_chunk,
++ gpointer mem);
++void g_mem_chunk_clean (GMemChunk *mem_chunk);
++void g_mem_chunk_reset (GMemChunk *mem_chunk);
++void g_mem_chunk_print (GMemChunk *mem_chunk);
++void g_mem_chunk_info (void);
++
++/* Ah yes...we have a "g_blow_chunks" function.
++ * "g_blow_chunks" simply compresses all the chunks. This operation
++ * consists of freeing every memory area that should be freed (but
++ * which we haven't gotten around to doing yet). And, no,
++ * "g_blow_chunks" doesn't follow the naming scheme, but it is a
++ * much better name than "g_mem_chunk_clean_all" or something
++ * similar.
++ */
++void g_blow_chunks (void);
++
++
++/* String utility functions that modify a string argument or
++ * return a constant string that must not be freed.
++ */
++#define G_STR_DELIMITERS "_-|> <."
++gchar* g_strdelimit (gchar *string,
++ const gchar *delimiters,
++ gchar new_delimiter);
++#ifndef __KORBIT__
++gdouble g_strtod (const gchar *nptr,
++ gchar **endptr);
++#endif /* !__KORBIT__ */
++gchar* g_strerror (gint errnum);
++gchar* g_strsignal (gint signum);
++gint g_strcasecmp (const gchar *s1,
++ const gchar *s2);
++gint g_strncasecmp (const gchar *s1,
++ const gchar *s2,
++ guint n);
++void g_strdown (gchar *string);
++void g_strup (gchar *string);
++void g_strreverse (gchar *string);
++/* removes leading spaces */
++gchar* g_strchug (gchar *string);
++/* removes trailing spaces */
++gchar* g_strchomp (gchar *string);
++/* removes leading & trailing spaces */
++#define g_strstrip( string ) g_strchomp (g_strchug (string))
++
++/* String utility functions that return a newly allocated string which
++ * ought to be freed from the caller at some point.
++ */
++gchar* g_strdup (const gchar *str);
++gchar* g_strdup_printf (const gchar *format,
++ ...) G_GNUC_PRINTF (1, 2);
++gchar* g_strdup_vprintf (const gchar *format,
++ va_list args);
++gchar* g_strndup (const gchar *str,
++ guint n);
++gchar* g_strnfill (guint length,
++ gchar fill_char);
++gchar* g_strconcat (const gchar *string1,
++ ...); /* NULL terminated */
++gchar* g_strjoin (const gchar *separator,
++ ...); /* NULL terminated */
++gchar* g_strescape (gchar *string);
++gpointer g_memdup (gconstpointer mem,
++ guint byte_size);
++
++/* NULL terminated string arrays.
++ * g_strsplit() splits up string into max_tokens tokens at delim and
++ * returns a newly allocated string array.
++ * g_strjoinv() concatenates all of str_array's strings, sliding in an
++ * optional separator, the returned string is newly allocated.
++ * g_strfreev() frees the array itself and all of its strings.
++ */
++gchar** g_strsplit (const gchar *string,
++ const gchar *delimiter,
++ gint max_tokens);
++gchar* g_strjoinv (const gchar *separator,
++ gchar **str_array);
++void g_strfreev (gchar **str_array);
++
++
++
++/* calculate a string size, guarranteed to fit format + args.
++ */
++guint g_printf_string_upper_bound (const gchar* format,
++ va_list args);
++
++
++/* Retrive static string info
++ */
++gchar* g_get_user_name (void);
++gchar* g_get_real_name (void);
++gchar* g_get_home_dir (void);
++gchar* g_get_tmp_dir (void);
++gchar* g_get_prgname (void);
++void g_set_prgname (const gchar *prgname);
++
++
++/* Miscellaneous utility functions
++ */
++guint g_parse_debug_string (const gchar *string,
++ GDebugKey *keys,
++ guint nkeys);
++gint g_snprintf (gchar *string,
++ gulong n,
++ gchar const *format,
++ ...) G_GNUC_PRINTF (3, 4);
++gint g_vsnprintf (gchar *string,
++ gulong n,
++ gchar const *format,
++ va_list args);
++gchar* g_basename (const gchar *file_name);
++/* Check if a file name is an absolute path */
++gboolean g_path_is_absolute (const gchar *file_name);
++/* In case of absolute paths, skip the root part */
++gchar* g_path_skip_root (gchar *file_name);
++
++/* strings are newly allocated with g_malloc() */
++gchar* g_dirname (const gchar *file_name);
++gchar* g_get_current_dir (void);
++gchar* g_getenv (const gchar *variable);
++
++
++/* we use a GLib function as a replacement for ATEXIT, so
++ * the programmer is not required to check the return value
++ * (if there is any in the implementation) and doesn't encounter
++ * missing include files.
++ */
++void g_atexit (GVoidFunc func);
++
++
++/* Bit tests
++ */
++G_INLINE_FUNC gint g_bit_nth_lsf (guint32 mask,
++ gint nth_bit);
++#ifdef G_CAN_INLINE
++G_INLINE_FUNC gint
++g_bit_nth_lsf (guint32 mask,
++ gint nth_bit)
++{
++ do
++ {
++ nth_bit++;
++ if (mask & (1 << (guint) nth_bit))
++ return nth_bit;
++ }
++ while (nth_bit < 32);
++ return -1;
++}
++#endif /* G_CAN_INLINE */
++
++G_INLINE_FUNC gint g_bit_nth_msf (guint32 mask,
++ gint nth_bit);
++#ifdef G_CAN_INLINE
++G_INLINE_FUNC gint
++g_bit_nth_msf (guint32 mask,
++ gint nth_bit)
++{
++ if (nth_bit < 0)
++ nth_bit = 32;
++ do
++ {
++ nth_bit--;
++ if (mask & (1 << (guint) nth_bit))
++ return nth_bit;
++ }
++ while (nth_bit > 0);
++ return -1;
++}
++#endif /* G_CAN_INLINE */
++
++G_INLINE_FUNC guint g_bit_storage (guint number);
++#ifdef G_CAN_INLINE
++G_INLINE_FUNC guint
++g_bit_storage (guint number)
++{
++ register guint n_bits = 0;
++
++ do
++ {
++ n_bits++;
++ number >>= 1;
++ }
++ while (number);
++ return n_bits;
++}
++#endif /* G_CAN_INLINE */
++
++/* String Chunks
++ */
++GStringChunk* g_string_chunk_new (gint size);
++void g_string_chunk_free (GStringChunk *chunk);
++gchar* g_string_chunk_insert (GStringChunk *chunk,
++ const gchar *string);
++gchar* g_string_chunk_insert_const (GStringChunk *chunk,
++ const gchar *string);
++
++
++/* Strings
++ */
++GString* g_string_new (const gchar *init);
++GString* g_string_sized_new (guint dfl_size);
++void g_string_free (GString *string,
++ gint free_segment);
++GString* g_string_assign (GString *lval,
++ const gchar *rval);
++GString* g_string_truncate (GString *string,
++ gint len);
++GString* g_string_append (GString *string,
++ const gchar *val);
++GString* g_string_append_c (GString *string,
++ gchar c);
++GString* g_string_prepend (GString *string,
++ const gchar *val);
++GString* g_string_prepend_c (GString *string,
++ gchar c);
++GString* g_string_insert (GString *string,
++ gint pos,
++ const gchar *val);
++GString* g_string_insert_c (GString *string,
++ gint pos,
++ gchar c);
++GString* g_string_erase (GString *string,
++ gint pos,
++ gint len);
++GString* g_string_down (GString *string);
++GString* g_string_up (GString *string);
++void g_string_sprintf (GString *string,
++ const gchar *format,
++ ...) G_GNUC_PRINTF (2, 3);
++void g_string_sprintfa (GString *string,
++ const gchar *format,
++ ...) G_GNUC_PRINTF (2, 3);
++
++
++/* Resizable arrays, remove fills any cleared spot and shortens the
++ * array, while preserving the order. remove_fast will distort the
++ * order by moving the last element to the position of the removed
++ */
++
++#define g_array_append_val(a,v) g_array_append_vals (a, &v, 1)
++#define g_array_prepend_val(a,v) g_array_prepend_vals (a, &v, 1)
++#define g_array_insert_val(a,i,v) g_array_insert_vals (a, i, &v, 1)
++#define g_array_index(a,t,i) (((t*) (a)->data) [(i)])
++
++GArray* g_array_new (gboolean zero_terminated,
++ gboolean clear,
++ guint element_size);
++void g_array_free (GArray *array,
++ gboolean free_segment);
++GArray* g_array_append_vals (GArray *array,
++ gconstpointer data,
++ guint len);
++GArray* g_array_prepend_vals (GArray *array,
++ gconstpointer data,
++ guint len);
++GArray* g_array_insert_vals (GArray *array,
++ guint index,
++ gconstpointer data,
++ guint len);
++GArray* g_array_set_size (GArray *array,
++ guint length);
++GArray* g_array_remove_index (GArray *array,
++ guint index);
++GArray* g_array_remove_index_fast (GArray *array,
++ guint index);
++
++/* Resizable pointer array. This interface is much less complicated
++ * than the above. Add appends appends a pointer. Remove fills any
++ * cleared spot and shortens the array. remove_fast will again distort
++ * order.
++ */
++#define g_ptr_array_index(array,index) (array->pdata)[index]
++GPtrArray* g_ptr_array_new (void);
++void g_ptr_array_free (GPtrArray *array,
++ gboolean free_seg);
++void g_ptr_array_set_size (GPtrArray *array,
++ gint length);
++gpointer g_ptr_array_remove_index (GPtrArray *array,
++ guint index);
++gpointer g_ptr_array_remove_index_fast (GPtrArray *array,
++ guint index);
++gboolean g_ptr_array_remove (GPtrArray *array,
++ gpointer data);
++gboolean g_ptr_array_remove_fast (GPtrArray *array,
++ gpointer data);
++void g_ptr_array_add (GPtrArray *array,
++ gpointer data);
++
++/* Hash Functions
++ */
++gint g_str_equal (gconstpointer v,
++ gconstpointer v2);
++guint g_str_hash (gconstpointer v);
++
++gint g_int_equal (gconstpointer v,
++ gconstpointer v2);
++guint g_int_hash (gconstpointer v);
++
++/* This "hash" function will just return the key's adress as an
++ * unsigned integer. Useful for hashing on plain adresses or
++ * simple integer values.
++ * passing NULL into g_hash_table_new() as GHashFunc has the
++ * same effect as passing g_direct_hash().
++ */
++guint g_direct_hash (gconstpointer v);
++gint g_direct_equal (gconstpointer v,
++ gconstpointer v2);
++
++
++
++/* Prime numbers.
++ */
++
++/* This function returns prime numbers spaced by approximately 1.5-2.0
++ * and is for use in resizing data structures which prefer
++ * prime-valued sizes. The closest spaced prime function returns the
++ * next largest prime, or the highest it knows about which is about
++ * MAXINT/4.
++ */
++guint g_spaced_primes_closest (guint num);
++
++
++
++#ifndef __KORBIT__
++/* GLib Thread support
++ */
++typedef struct _GMutex GMutex;
++typedef struct _GCond GCond;
++typedef struct _GPrivate GPrivate;
++typedef struct _GStaticPrivate GStaticPrivate;
++typedef struct _GThreadFunctions GThreadFunctions;
++struct _GThreadFunctions
++{
++ GMutex* (*mutex_new) (void);
++ void (*mutex_lock) (GMutex *mutex);
++ gboolean (*mutex_trylock) (GMutex *mutex);
++ void (*mutex_unlock) (GMutex *mutex);
++ void (*mutex_free) (GMutex *mutex);
++ GCond* (*cond_new) (void);
++ void (*cond_signal) (GCond *cond);
++ void (*cond_broadcast) (GCond *cond);
++ void (*cond_wait) (GCond *cond,
++ GMutex *mutex);
++ gboolean (*cond_timed_wait) (GCond *cond,
++ GMutex *mutex,
++ GTimeVal *end_time);
++ void (*cond_free) (GCond *cond);
++ GPrivate* (*private_new) (GDestroyNotify destructor);
++ gpointer (*private_get) (GPrivate *private_key);
++ void (*private_set) (GPrivate *private_key,
++ gpointer data);
++};
++
++GUTILS_C_VAR GThreadFunctions g_thread_functions_for_glib_use;
++GUTILS_C_VAR gboolean g_thread_use_default_impl;
++GUTILS_C_VAR gboolean g_threads_got_initialized;
++
++/* initializes the mutex/cond/private implementation for glib, might
++ * only be called once, and must not be called directly or indirectly
++ * from another glib-function, e.g. as a callback.
++ */
++void g_thread_init (GThreadFunctions *vtable);
++
++/* internal function for fallback static mutex implementation */
++GMutex* g_static_mutex_get_mutex_impl (GMutex **mutex);
++
++/* shorthands for conditional and unconditional function calls */
++#define G_THREAD_UF(name, arglist) \
++ (*g_thread_functions_for_glib_use . name) arglist
++#define G_THREAD_CF(name, fail, arg) \
++ (g_thread_supported () ? G_THREAD_UF (name, arg) : (fail))
++/* keep in mind, all those mutexes and static mutexes are not
++ * recursive in general, don't rely on that
++ */
++#define g_thread_supported() (g_threads_got_initialized)
++#define g_mutex_new() G_THREAD_UF (mutex_new, ())
++#define g_mutex_lock(mutex) G_THREAD_CF (mutex_lock, (void)0, (mutex))
++#define g_mutex_trylock(mutex) G_THREAD_CF (mutex_trylock, TRUE, (mutex))
++#define g_mutex_unlock(mutex) G_THREAD_CF (mutex_unlock, (void)0, (mutex))
++#define g_mutex_free(mutex) G_THREAD_CF (mutex_free, (void)0, (mutex))
++#define g_cond_new() G_THREAD_UF (cond_new, ())
++#define g_cond_signal(cond) G_THREAD_CF (cond_signal, (void)0, (cond))
++#define g_cond_broadcast(cond) G_THREAD_CF (cond_broadcast, (void)0, (cond))
++#define g_cond_wait(cond, mutex) G_THREAD_CF (cond_wait, (void)0, (cond, \
++ mutex))
++#define g_cond_free(cond) G_THREAD_CF (cond_free, (void)0, (cond))
++#define g_cond_timed_wait(cond, mutex, abs_time) G_THREAD_CF (cond_timed_wait, \
++ TRUE, \
++ (cond, mutex, \
++ abs_time))
++#define g_private_new(destructor) G_THREAD_UF (private_new, (destructor))
++#define g_private_get(private_key) G_THREAD_CF (private_get, \
++ ((gpointer)private_key), \
++ (private_key))
++#define g_private_set(private_key, value) G_THREAD_CF (private_set, \
++ (void) (private_key = \
++ (GPrivate*) (value)), \
++ (private_key, value))
++/* GStaticMutexes can be statically initialized with the value
++ * G_STATIC_MUTEX_INIT, and then they can directly be used, that is
++ * much easier, than having to explicitly allocate the mutex before
++ * use
++ */
++#define g_static_mutex_lock(mutex) \
++ g_mutex_lock (g_static_mutex_get_mutex (mutex))
++#define g_static_mutex_trylock(mutex) \
++ g_mutex_trylock (g_static_mutex_get_mutex (mutex))
++#define g_static_mutex_unlock(mutex) \
++ g_mutex_unlock (g_static_mutex_get_mutex (mutex))
++struct _GStaticPrivate
++{
++ guint index;
++};
++#define G_STATIC_PRIVATE_INIT { 0 }
++gpointer g_static_private_get (GStaticPrivate *private_key);
++void g_static_private_set (GStaticPrivate *private_key,
++ gpointer data,
++ GDestroyNotify notify);
++#endif /* __KORBIT__ */
++
++/* these are some convenience macros that expand to nothing if GLib
++ * was configured with --disable-threads. for using StaticMutexes,
++ * you define them with G_LOCK_DEFINE_STATIC (name) or G_LOCK_DEFINE (name)
++ * if you need to export the mutex. With G_LOCK_EXTERN (name) you can
++ * declare such an globally defined lock. name is a unique identifier
++ * for the protected varibale or code portion. locking, testing and
++ * unlocking of such mutexes can be done with G_LOCK(), G_UNLOCK() and
++ * G_TRYLOCK() respectively.
++ */
++#ifdef __KORBIT__
++#undef G_THREADS_ENABLED
++#endif
++
++extern void glib_dummy_decl (void);
++#define G_LOCK_NAME(name) (g__ ## name ## _lock)
++#ifdef G_THREADS_ENABLED
++# define G_LOCK_DEFINE_STATIC(name) static G_LOCK_DEFINE (name)
++# define G_LOCK_DEFINE(name) \
++ GStaticMutex G_LOCK_NAME (name) = G_STATIC_MUTEX_INIT
++# define G_LOCK_EXTERN(name) extern GStaticMutex G_LOCK_NAME (name)
++
++# define G_LOCK(name) g_static_mutex_lock (&G_LOCK_NAME (name))
++# define G_UNLOCK(name) g_static_mutex_unlock (&G_LOCK_NAME (name))
++# define G_TRYLOCK(name) g_static_mutex_trylock (&G_LOCK_NAME (name))
++#else /* !G_THREADS_ENABLED */
++# define G_LOCK_DEFINE_STATIC(name) extern void glib_dummy_decl (void)
++# define G_LOCK_DEFINE(name) extern void glib_dummy_decl (void)
++# define G_LOCK_EXTERN(name) extern void glib_dummy_decl (void)
++# define G_LOCK(name)
++# define G_UNLOCK(name)
++# define G_TRYLOCK(name) (FALSE)
++#endif /* !G_THREADS_ENABLED */
++
++#ifdef __cplusplus
++}
++#endif /* __cplusplus */
++
++
++#endif /* __G_LIB_H__ */
+diff -urN linux-2.4.1/net/korbit/kglib/glibconfig.h linux-2.4.1-korbit/net/korbit/kglib/glibconfig.h
+--- linux-2.4.1/net/korbit/kglib/glibconfig.h Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/kglib/glibconfig.h Thu Feb 1 11:46:56 2001
+@@ -0,0 +1,131 @@
++/* glibconfig.h
++ *
++ * This is a generated file. Please modify `configure.in'
++ */
++
++#ifndef GLIBCONFIG_H
++#define GLIBCONFIG_H
++
++#ifdef __cplusplus
++extern "C" {
++#endif /* __cplusplus */
++
++#include <limits.h>
++/*#include <float.h>*/
++#define GLIB_HAVE_SYS_POLL_H
++
++#define G_MINFLOAT FLT_MIN
++#define G_MAXFLOAT FLT_MAX
++#define G_MINDOUBLE DBL_MIN
++#define G_MAXDOUBLE DBL_MAX
++#define G_MINSHORT SHRT_MIN
++#define G_MAXSHORT SHRT_MAX
++#define G_MININT INT_MIN
++#define G_MAXINT INT_MAX
++#define G_MINLONG LONG_MIN
++#define G_MAXLONG LONG_MAX
++
++typedef signed char gint8;
++typedef unsigned char guint8;
++typedef signed short gint16;
++typedef unsigned short guint16;
++typedef signed int gint32;
++typedef unsigned int guint32;
++
++#if defined (__GNUC__) && (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 8))
++# define G_GNUC_EXTENSION __extension__
++#else
++# define G_GNUC_EXTENSION
++#endif
++
++#define G_HAVE_GINT64 1
++
++G_GNUC_EXTENSION typedef signed long long gint64;
++G_GNUC_EXTENSION typedef unsigned long long guint64;
++
++#define G_GINT64_CONSTANT(val) (G_GNUC_EXTENSION (val##LL))
++
++#define GPOINTER_TO_INT(p) ((gint) (p))
++#define GPOINTER_TO_UINT(p) ((guint) (p))
++
++#define GINT_TO_POINTER(i) ((gpointer) (i))
++#define GUINT_TO_POINTER(u) ((gpointer) (u))
++
++#ifdef NeXT /* @#%@! NeXTStep */
++# define g_ATEXIT(proc) (!atexit (proc))
++#else
++# define g_ATEXIT(proc) (atexit (proc))
++#endif
++
++#define g_memmove(d,s,n) G_STMT_START { memmove ((d), (s), (n)); } G_STMT_END
++
++#define GLIB_MAJOR_VERSION 1
++#define GLIB_MINOR_VERSION 2
++#define GLIB_MICRO_VERSION 8
++
++
++#define G_VA_COPY __va_copy
++
++#ifdef __cplusplus
++#define G_HAVE_INLINE 1
++#else /* !__cplusplus */
++#define G_HAVE_INLINE 1
++#define G_HAVE___INLINE 1
++#define G_HAVE___INLINE__ 1
++#endif /* !__cplusplus */
++
++#define G_THREADS_ENABLED
++#define G_THREADS_IMPL_POSIX
++typedef struct _GStaticMutex GStaticMutex;
++struct _GStaticMutex
++{
++ struct _GMutex *runtime_mutex;
++ union {
++ char pad[24];
++ double dummy_double;
++ void *dummy_pointer;
++ long dummy_long;
++ } aligned_pad_u;
++};
++#define G_STATIC_MUTEX_INIT { NULL, { { 0,0,0,0,0,0,77,88,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} } }
++#define g_static_mutex_get_mutex(mutex) (g_thread_use_default_impl ? ((GMutex*) &((mutex)->aligned_pad_u)) : g_static_mutex_get_mutex_impl (&((mutex)->runtime_mutex)))
++
++#define GINT16_TO_BE(val) ((gint16) (val))
++#define GUINT16_TO_BE(val) ((guint16) (val))
++#define GINT16_TO_LE(val) ((gint16) GUINT16_SWAP_LE_BE (val))
++#define GUINT16_TO_LE(val) (GUINT16_SWAP_LE_BE (val))
++#define GINT32_TO_BE(val) ((gint32) (val))
++#define GUINT32_TO_BE(val) ((guint32) (val))
++#define GINT32_TO_LE(val) ((gint32) GUINT32_SWAP_LE_BE (val))
++#define GUINT32_TO_LE(val) (GUINT32_SWAP_LE_BE (val))
++#define GINT64_TO_BE(val) ((gint64) (val))
++#define GUINT64_TO_BE(val) ((guint64) (val))
++#define GINT64_TO_LE(val) ((gint64) GUINT64_SWAP_LE_BE (val))
++#define GUINT64_TO_LE(val) (GUINT64_SWAP_LE_BE (val))
++#define GLONG_TO_LE(val) ((glong) GINT32_TO_LE (val))
++#define GULONG_TO_LE(val) ((gulong) GUINT32_TO_LE (val))
++#define GLONG_TO_BE(val) ((glong) GINT32_TO_BE (val))
++#define GULONG_TO_BE(val) ((gulong) GUINT32_TO_BE (val))
++#define GINT_TO_LE(val) ((gint) GINT32_TO_LE (val))
++#define GUINT_TO_LE(val) ((guint) GUINT32_TO_LE (val))
++#define GINT_TO_BE(val) ((gint) GINT32_TO_BE (val))
++#define GUINT_TO_BE(val) ((guint) GUINT32_TO_BE (val))
++#define G_BYTE_ORDER G_LITTLE_ENDIAN
++
++#define GLIB_SYSDEF_POLLIN =1
++#define GLIB_SYSDEF_POLLOUT =4
++#define GLIB_SYSDEF_POLLPRI =2
++#define GLIB_SYSDEF_POLLERR =8
++#define GLIB_SYSDEF_POLLHUP =16
++#define GLIB_SYSDEF_POLLNVAL =32
++
++
++#define G_HAVE_WCHAR_H 1
++#define G_HAVE_WCTYPE_H 1
++
++
++#ifdef __cplusplus
++}
++#endif /* __cplusplus */
++
++#endif /* GLIBCONFIG_H */
+diff -urN linux-2.4.1/net/korbit/kglib/glist.c linux-2.4.1-korbit/net/korbit/kglib/glist.c
+--- linux-2.4.1/net/korbit/kglib/glist.c Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/kglib/glist.c Thu Feb 1 11:46:57 2001
+@@ -0,0 +1,666 @@
++/* GLIB - Library of useful routines for C programming
++ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Library General Public
++ * License as published by the Free Software Foundation; either
++ * version 2 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Library General Public License for more details.
++ *
++ * You should have received a copy of the GNU Library General Public
++ * License along with this library; if not, write to the
++ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
++ * Boston, MA 02111-1307, USA.
++ */
++
++/*
++ * Modified by the GLib Team and others 1997-1999. See the AUTHORS
++ * file for a list of people on the GLib Team. See the ChangeLog
++ * files for a list of changes. These files are distributed with
++ * GLib at ftp://ftp.gtk.org/pub/gtk/.
++ */
++
++#include "glib.h"
++
++
++struct _GAllocator /* from gmem.c */
++{
++ gchar *name;
++ guint16 n_preallocs;
++ guint is_unused : 1;
++ guint type : 4;
++ GAllocator *last;
++ GMemChunk *mem_chunk;
++ GList *free_lists; /* implementation specific */
++};
++
++static GAllocator *current_allocator = NULL;
++G_LOCK_DEFINE_STATIC (current_allocator);
++
++/* HOLDS: current_allocator_lock */
++static void
++g_list_validate_allocator (GAllocator *allocator)
++{
++ g_return_if_fail (allocator != NULL);
++ g_return_if_fail (allocator->is_unused == TRUE);
++
++ if (allocator->type != G_ALLOCATOR_LIST)
++ {
++ allocator->type = G_ALLOCATOR_LIST;
++ if (allocator->mem_chunk)
++ {
++ g_mem_chunk_destroy (allocator->mem_chunk);
++ allocator->mem_chunk = NULL;
++ }
++ }
++
++ if (!allocator->mem_chunk)
++ {
++ allocator->mem_chunk = g_mem_chunk_new (allocator->name,
++ sizeof (GList),
++ sizeof (GList) * allocator->n_preallocs,
++ G_ALLOC_ONLY);
++ allocator->free_lists = NULL;
++ }
++
++ allocator->is_unused = FALSE;
++}
++
++void
++g_list_push_allocator(GAllocator *allocator)
++{
++ G_LOCK (current_allocator);
++ g_list_validate_allocator ( allocator );
++ allocator->last = current_allocator;
++ current_allocator = allocator;
++ G_UNLOCK (current_allocator);
++}
++
++void
++g_list_pop_allocator (void)
++{
++ G_LOCK (current_allocator);
++ if (current_allocator)
++ {
++ GAllocator *allocator;
++
++ allocator = current_allocator;
++ current_allocator = allocator->last;
++ allocator->last = NULL;
++ allocator->is_unused = TRUE;
++ }
++ G_UNLOCK (current_allocator);
++}
++
++GList*
++g_list_alloc (void)
++{
++ GList *list;
++
++ G_LOCK (current_allocator);
++ if (!current_allocator)
++ {
++ GAllocator *allocator = g_allocator_new ("GLib default GList allocator",
++ 128);
++ g_list_validate_allocator (allocator);
++ allocator->last = NULL;
++ current_allocator = allocator;
++ }
++ if (!current_allocator->free_lists)
++ {
++ list = g_chunk_new (GList, current_allocator->mem_chunk);
++ list->data = NULL;
++ }
++ else
++ {
++ if (current_allocator->free_lists->data)
++ {
++ list = current_allocator->free_lists->data;
++ current_allocator->free_lists->data = list->next;
++ list->data = NULL;
++ }
++ else
++ {
++ list = current_allocator->free_lists;
++ current_allocator->free_lists = list->next;
++ }
++ }
++ G_UNLOCK (current_allocator);
++ list->next = NULL;
++ list->prev = NULL;
++
++ return list;
++}
++
++void
++g_list_free (GList *list)
++{
++ if (list)
++ {
++ list->data = list->next;
++ G_LOCK (current_allocator);
++ list->next = current_allocator->free_lists;
++ current_allocator->free_lists = list;
++ G_UNLOCK (current_allocator);
++ }
++}
++
++void
++g_list_free_1 (GList *list)
++{
++ if (list)
++ {
++ list->data = NULL;
++ G_LOCK (current_allocator);
++ list->next = current_allocator->free_lists;
++ current_allocator->free_lists = list;
++ G_UNLOCK (current_allocator);
++ }
++}
++
++GList*
++g_list_append (GList *list,
++ gpointer data)
++{
++ GList *new_list;
++ GList *last;
++
++ new_list = g_list_alloc ();
++ new_list->data = data;
++
++ if (list)
++ {
++ last = g_list_last (list);
++ /* g_assert (last != NULL); */
++ last->next = new_list;
++ new_list->prev = last;
++
++ return list;
++ }
++ else
++ return new_list;
++}
++
++GList*
++g_list_prepend (GList *list,
++ gpointer data)
++{
++ GList *new_list;
++
++ new_list = g_list_alloc ();
++ new_list->data = data;
++
++ if (list)
++ {
++ if (list->prev)
++ {
++ list->prev->next = new_list;
++ new_list->prev = list->prev;
++ }
++ list->prev = new_list;
++ new_list->next = list;
++ }
++
++ return new_list;
++}
++
++GList*
++g_list_insert (GList *list,
++ gpointer data,
++ gint position)
++{
++ GList *new_list;
++ GList *tmp_list;
++
++ if (position < 0)
++ return g_list_append (list, data);
++ else if (position == 0)
++ return g_list_prepend (list, data);
++
++ tmp_list = g_list_nth (list, position);
++ if (!tmp_list)
++ return g_list_append (list, data);
++
++ new_list = g_list_alloc ();
++ new_list->data = data;
++
++ if (tmp_list->prev)
++ {
++ tmp_list->prev->next = new_list;
++ new_list->prev = tmp_list->prev;
++ }
++ new_list->next = tmp_list;
++ tmp_list->prev = new_list;
++
++ if (tmp_list == list)
++ return new_list;
++ else
++ return list;
++}
++
++GList *
++g_list_concat (GList *list1, GList *list2)
++{
++ GList *tmp_list;
++
++ if (list2)
++ {
++ tmp_list = g_list_last (list1);
++ if (tmp_list)
++ tmp_list->next = list2;
++ else
++ list1 = list2;
++ list2->prev = tmp_list;
++ }
++
++ return list1;
++}
++
++GList*
++g_list_remove (GList *list,
++ gpointer data)
++{
++ GList *tmp;
++
++ tmp = list;
++ while (tmp)
++ {
++ if (tmp->data != data)
++ tmp = tmp->next;
++ else
++ {
++ if (tmp->prev)
++ tmp->prev->next = tmp->next;
++ if (tmp->next)
++ tmp->next->prev = tmp->prev;
++
++ if (list == tmp)
++ list = list->next;
++
++ g_list_free_1 (tmp);
++
++ break;
++ }
++ }
++ return list;
++}
++
++GList*
++g_list_remove_link (GList *list,
++ GList *link)
++{
++ if (link)
++ {
++ if (link->prev)
++ link->prev->next = link->next;
++ if (link->next)
++ link->next->prev = link->prev;
++
++ if (link == list)
++ list = list->next;
++
++ link->next = NULL;
++ link->prev = NULL;
++ }
++
++ return list;
++}
++
++GList*
++g_list_copy (GList *list)
++{
++ GList *new_list = NULL;
++
++ if (list)
++ {
++ GList *last;
++
++ new_list = g_list_alloc ();
++ new_list->data = list->data;
++ last = new_list;
++ list = list->next;
++ while (list)
++ {
++ last->next = g_list_alloc ();
++ last->next->prev = last;
++ last = last->next;
++ last->data = list->data;
++ list = list->next;
++ }
++ }
++
++ return new_list;
++}
++
++GList*
++g_list_reverse (GList *list)
++{
++ GList *last;
++
++ last = NULL;
++ while (list)
++ {
++ last = list;
++ list = last->next;
++ last->next = last->prev;
++ last->prev = list;
++ }
++
++ return last;
++}
++
++GList*
++g_list_nth (GList *list,
++ guint n)
++{
++ while ((n-- > 0) && list)
++ list = list->next;
++
++ return list;
++}
++
++gpointer
++g_list_nth_data (GList *list,
++ guint n)
++{
++ while ((n-- > 0) && list)
++ list = list->next;
++
++ return list ? list->data : NULL;
++}
++
++GList*
++g_list_find (GList *list,
++ gpointer data)
++{
++ while (list)
++ {
++ if (list->data == data)
++ break;
++ list = list->next;
++ }
++
++ return list;
++}
++
++GList*
++g_list_find_custom (GList *list,
++ gpointer data,
++ GCompareFunc func)
++{
++ g_return_val_if_fail (func != NULL, list);
++
++ while (list)
++ {
++ if (! func (list->data, data))
++ return list;
++ list = list->next;
++ }
++
++ return NULL;
++}
++
++
++gint
++g_list_position (GList *list,
++ GList *link)
++{
++ gint i;
++
++ i = 0;
++ while (list)
++ {
++ if (list == link)
++ return i;
++ i++;
++ list = list->next;
++ }
++
++ return -1;
++}
++
++gint
++g_list_index (GList *list,
++ gpointer data)
++{
++ gint i;
++
++ i = 0;
++ while (list)
++ {
++ if (list->data == data)
++ return i;
++ i++;
++ list = list->next;
++ }
++
++ return -1;
++}
++
++GList*
++g_list_last (GList *list)
++{
++ if (list)
++ {
++ while (list->next)
++ list = list->next;
++ }
++
++ return list;
++}
++
++GList*
++g_list_first (GList *list)
++{
++ if (list)
++ {
++ while (list->prev)
++ list = list->prev;
++ }
++
++ return list;
++}
++
++guint
++g_list_length (GList *list)
++{
++ guint length;
++
++ length = 0;
++ while (list)
++ {
++ length++;
++ list = list->next;
++ }
++
++ return length;
++}
++
++void
++g_list_foreach (GList *list,
++ GFunc func,
++ gpointer user_data)
++{
++ while (list)
++ {
++ (*func) (list->data, user_data);
++ list = list->next;
++ }
++}
++
++
++GList*
++g_list_insert_sorted (GList *list,
++ gpointer data,
++ GCompareFunc func)
++{
++ GList *tmp_list = list;
++ GList *new_list;
++ gint cmp;
++
++ g_return_val_if_fail (func != NULL, list);
++
++ if (!list)
++ {
++ new_list = g_list_alloc();
++ new_list->data = data;
++ return new_list;
++ }
++
++ cmp = (*func) (data, tmp_list->data);
++
++ while ((tmp_list->next) && (cmp > 0))
++ {
++ tmp_list = tmp_list->next;
++ cmp = (*func) (data, tmp_list->data);
++ }
++
++ new_list = g_list_alloc();
++ new_list->data = data;
++
++ if ((!tmp_list->next) && (cmp > 0))
++ {
++ tmp_list->next = new_list;
++ new_list->prev = tmp_list;
++ return list;
++ }
++
++ if (tmp_list->prev)
++ {
++ tmp_list->prev->next = new_list;
++ new_list->prev = tmp_list->prev;
++ }
++ new_list->next = tmp_list;
++ tmp_list->prev = new_list;
++
++ if (tmp_list == list)
++ return new_list;
++ else
++ return list;
++}
++
++static GList *
++g_list_sort_merge (GList *l1,
++ GList *l2,
++ GCompareFunc compare_func)
++{
++ GList list, *l, *lprev;
++
++ l = &list;
++ lprev = NULL;
++
++ while (l1 && l2)
++ {
++ if (compare_func (l1->data, l2->data) < 0)
++ {
++ l->next = l1;
++ l = l->next;
++ l->prev = lprev;
++ lprev = l;
++ l1 = l1->next;
++ }
++ else
++ {
++ l->next = l2;
++ l = l->next;
++ l->prev = lprev;
++ lprev = l;
++ l2 = l2->next;
++ }
++ }
++ l->next = l1 ? l1 : l2;
++ l->next->prev = l;
++
++ return list.next;
++}
++
++GList*
++g_list_sort (GList *list,
++ GCompareFunc compare_func)
++{
++ GList *l1, *l2;
++
++ if (!list)
++ return NULL;
++ if (!list->next)
++ return list;
++
++ l1 = list;
++ l2 = list->next;
++
++ while ((l2 = l2->next) != NULL)
++ {
++ if ((l2 = l2->next) == NULL)
++ break;
++ l1 = l1->next;
++ }
++ l2 = l1->next;
++ l1->next = NULL;
++
++ return g_list_sort_merge (g_list_sort (list, compare_func),
++ g_list_sort (l2, compare_func),
++ compare_func);
++}
++
++GList*
++g_list_sort2 (GList *list,
++ GCompareFunc compare_func)
++{
++ GSList *runs = NULL;
++ GList *tmp;
++
++ /* Degenerate case. */
++ if (!list) return NULL;
++
++ /* Assume: list = [12,2,4,11,2,4,6,1,1,12]. */
++ for (tmp = list; tmp; )
++ {
++ GList *tmp2;
++ for (tmp2 = tmp;
++ tmp2->next && compare_func (tmp2->data, tmp2->next->data) <= 0;
++ tmp2 = tmp2->next)
++ /* Nothing */;
++ runs = g_slist_append (runs, tmp);
++ tmp = tmp2->next;
++ tmp2->next = NULL;
++ }
++ /* Now: runs = [[12],[2,4,11],[2,4,6],[1,1,12]]. */
++
++ while (runs->next)
++ {
++ /* We have more than one run. Merge pairwise. */
++ GSList *dst, *src, *dstprev = NULL;
++ dst = src = runs;
++ while (src && src->next)
++ {
++ dst->data = g_list_sort_merge (src->data,
++ src->next->data,
++ compare_func);
++ dstprev = dst;
++ dst = dst->next;
++ src = src->next->next;
++ }
++
++ /* If number of runs was odd, just keep the last. */
++ if (src)
++ {
++ dst->data = src->data;
++ dstprev = dst;
++ dst = dst->next;
++ }
++
++ dstprev->next = NULL;
++ g_slist_free (dst);
++ }
++
++ /* After 1st loop: runs = [[2,4,11,12],[1,1,2,4,6,12]]. */
++ /* After 2nd loop: runs = [[1,1,2,2,4,4,6,11,12,12]]. */
++
++ list = runs->data;
++ g_slist_free (runs);
++ return list;
++}
+diff -urN linux-2.4.1/net/korbit/kglib/gmem.c linux-2.4.1-korbit/net/korbit/kglib/gmem.c
+--- linux-2.4.1/net/korbit/kglib/gmem.c Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/kglib/gmem.c Thu Feb 1 11:46:57 2001
+@@ -0,0 +1,767 @@
++/* GLIB - Library of useful routines for C programming
++ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Library General Public
++ * License as published by the Free Software Foundation; either
++ * version 2 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Library General Public License for more details.
++ *
++ * You should have received a copy of the GNU Library General Public
++ * License along with this library; if not, write to the
++ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
++ * Boston, MA 02111-1307, USA.
++ */
++
++/*
++ * Modified by the GLib Team and others 1997-1999. See the AUTHORS
++ * file for a list of people on the GLib Team. See the ChangeLog
++ * files for a list of changes. These files are distributed with
++ * GLib at ftp://ftp.gtk.org/pub/gtk/.
++ *
++ * Mutilated on 10/22/00 by Fredrik and Chris
++ */
++
++#ifdef HAVE_CONFIG_H
++#include <config.h>
++#endif
++
++#include <stdlib.h>
++#include <string.h>
++#include "glib.h"
++
++#define MEM_PROFILE_TABLE_SIZE 8192
++#define ENTER_MEM_CHUNK_ROUTINE()
++#define LEAVE_MEM_CHUNK_ROUTINE()
++
++/*
++ * This library can check for some attempts to do illegal things to
++ * memory (ENABLE_MEM_CHECK), and can do profiling
++ * (ENABLE_MEM_PROFILE). Both features are implemented by storing
++ * words before the start of the memory chunk.
++ *
++ * The first, at offset -2*SIZEOF_LONG, is used only if
++ * ENABLE_MEM_CHECK is set, and stores 0 after the memory has been
++ * allocated and 1 when it has been freed. The second, at offset
++ * -SIZEOF_LONG, is used if either flag is set and stores the size of
++ * the block.
++ *
++ * The MEM_CHECK flag is checked when memory is realloc'd and free'd,
++ * and it can be explicitly checked before using a block by calling
++ * g_mem_check().
++ */
++
++#define MEM_AREA_SIZE 4L
++
++#define MEM_ALIGN sizeof(long)
++
++
++typedef struct _GFreeAtom GFreeAtom;
++typedef struct _GMemArea GMemArea;
++typedef struct _GRealMemChunk GRealMemChunk;
++
++struct _GFreeAtom
++{
++ GFreeAtom *next;
++};
++
++struct _GMemArea
++{
++ GMemArea *next; /* the next mem area */
++ GMemArea *prev; /* the previous mem area */
++ gulong index; /* the current index into the "mem" array */
++ gulong free; /* the number of free bytes in this mem area */
++ gulong allocated; /* the number of atoms allocated from this area */
++ gulong mark; /* is this mem area marked for deletion */
++ gchar mem[MEM_AREA_SIZE]; /* the mem array from which atoms get allocated
++ * the actual size of this array is determined by
++ * the mem chunk "area_size". ANSI says that it
++ * must be declared to be the maximum size it
++ * can possibly be (even though the actual size
++ * may be less).
++ */
++};
++
++struct _GRealMemChunk
++{
++ gchar *name; /* name of this MemChunk...used for debugging output */
++ gint type; /* the type of MemChunk: ALLOC_ONLY or ALLOC_AND_FREE */
++ gint num_mem_areas; /* the number of memory areas */
++ gint num_marked_areas; /* the number of areas marked for deletion */
++ guint atom_size; /* the size of an atom */
++ gulong area_size; /* the size of a memory area */
++ GMemArea *mem_area; /* the current memory area */
++ GMemArea *mem_areas; /* a list of all the mem areas owned by this chunk */
++ GMemArea *free_mem_area; /* the free area...which is about to be destroyed */
++ GFreeAtom *free_atoms; /* the free atoms list */
++ GTree *mem_tree; /* tree of mem areas sorted by memory address */
++ GRealMemChunk *next; /* pointer to the next chunk */
++ GRealMemChunk *prev; /* pointer to the previous chunk */
++};
++
++
++static gulong g_mem_chunk_compute_size (gulong size,
++ gulong min_size);
++static gint g_mem_chunk_area_compare (GMemArea *a,
++ GMemArea *b);
++static gint g_mem_chunk_area_search (GMemArea *a,
++ gchar *addr);
++
++
++/* here we can't use StaticMutexes, as they depend upon a working
++ * g_malloc, the same holds true for StaticPrivate */
++#ifndef __KORBIT__
++static GMutex* mem_chunks_lock = NULL;
++#endif /* !__KORBIT__ */
++static GRealMemChunk *mem_chunks = NULL;
++
++
++gpointer
++g_malloc (gulong size)
++{
++ gpointer p;
++
++ if (size == 0)
++ return NULL;
++
++ p = (gpointer) malloc (size);
++ if (!p)
++ g_error ("could not allocate %ld bytes", size);
++
++ return p;
++}
++
++gpointer
++g_malloc0 (gulong size)
++{
++ gpointer p;
++
++ if (size == 0)
++ return NULL;
++
++ p = (gpointer) calloc (size, 1);
++ if (!p)
++ g_error ("could not allocate %ld bytes", size);
++
++ return p;
++}
++
++gpointer
++g_realloc (gpointer mem,
++ gulong size)
++{
++ gpointer p;
++
++ if (size == 0)
++ {
++ g_free (mem);
++
++ return NULL;
++ }
++
++ if (!mem)
++ {
++#ifdef REALLOC_0_WORKS
++ p = (gpointer) realloc (NULL, size);
++#else /* !REALLOC_0_WORKS */
++ p = (gpointer) malloc (size);
++#endif /* !REALLOC_0_WORKS */
++ }
++ else
++ {
++ p = (gpointer) realloc (mem, size);
++ }
++
++ if (!p)
++ g_error ("could not reallocate %lu bytes", (gulong) size);
++
++ return p;
++}
++
++void
++g_free (gpointer mem)
++{
++ if (mem)
++ {
++ free (mem);
++ }
++}
++
++
++void
++g_mem_profile (void)
++{
++}
++
++void
++g_mem_check (gpointer mem)
++{
++}
++
++GMemChunk*
++g_mem_chunk_new (gchar *name,
++ gint atom_size,
++ gulong area_size,
++ gint type)
++{
++ GRealMemChunk *mem_chunk;
++ gulong rarea_size;
++
++ g_return_val_if_fail (atom_size > 0, NULL);
++ g_return_val_if_fail (area_size >= atom_size, NULL);
++
++ ENTER_MEM_CHUNK_ROUTINE();
++
++ area_size = (area_size + atom_size - 1) / atom_size;
++ area_size *= atom_size;
++
++ mem_chunk = g_new (struct _GRealMemChunk, 1);
++ mem_chunk->name = name;
++ mem_chunk->type = type;
++ mem_chunk->num_mem_areas = 0;
++ mem_chunk->num_marked_areas = 0;
++ mem_chunk->mem_area = NULL;
++ mem_chunk->free_mem_area = NULL;
++ mem_chunk->free_atoms = NULL;
++ mem_chunk->mem_tree = NULL;
++ mem_chunk->mem_areas = NULL;
++ mem_chunk->atom_size = atom_size;
++
++ if (mem_chunk->type == G_ALLOC_AND_FREE)
++ mem_chunk->mem_tree = g_tree_new ((GCompareFunc) g_mem_chunk_area_compare);
++
++ if (mem_chunk->atom_size % MEM_ALIGN)
++ mem_chunk->atom_size += MEM_ALIGN - (mem_chunk->atom_size % MEM_ALIGN);
++
++ rarea_size = area_size + sizeof (GMemArea) - MEM_AREA_SIZE;
++ rarea_size = g_mem_chunk_compute_size (rarea_size, atom_size + sizeof (GMemArea) - MEM_AREA_SIZE);
++ mem_chunk->area_size = rarea_size - (sizeof (GMemArea) - MEM_AREA_SIZE);
++
++#ifndef __KORBIT__
++ g_mutex_lock (mem_chunks_lock);
++#endif /* !__KORBIT__ */
++ mem_chunk->next = mem_chunks;
++ mem_chunk->prev = NULL;
++ if (mem_chunks)
++ mem_chunks->prev = mem_chunk;
++ mem_chunks = mem_chunk;
++#ifndef __KORBIT__
++ g_mutex_unlock (mem_chunks_lock);
++#endif /* !__KORBIT__ */
++
++ LEAVE_MEM_CHUNK_ROUTINE();
++
++ return ((GMemChunk*) mem_chunk);
++}
++
++void
++g_mem_chunk_destroy (GMemChunk *mem_chunk)
++{
++ GRealMemChunk *rmem_chunk;
++ GMemArea *mem_areas;
++ GMemArea *temp_area;
++
++ g_return_if_fail (mem_chunk != NULL);
++
++ ENTER_MEM_CHUNK_ROUTINE();
++
++ rmem_chunk = (GRealMemChunk*) mem_chunk;
++
++ mem_areas = rmem_chunk->mem_areas;
++ while (mem_areas)
++ {
++ temp_area = mem_areas;
++ mem_areas = mem_areas->next;
++ g_free (temp_area);
++ }
++
++ if (rmem_chunk->next)
++ rmem_chunk->next->prev = rmem_chunk->prev;
++ if (rmem_chunk->prev)
++ rmem_chunk->prev->next = rmem_chunk->next;
++
++#ifndef __KORBIT__
++ g_mutex_lock (mem_chunks_lock);
++#endif /* !__KORBIT__ */
++ if (rmem_chunk == mem_chunks)
++ mem_chunks = mem_chunks->next;
++#ifndef __KORBIT__
++ g_mutex_unlock (mem_chunks_lock);
++#endif /* !__KORBIT__ */
++
++ if (rmem_chunk->type == G_ALLOC_AND_FREE)
++ g_tree_destroy (rmem_chunk->mem_tree);
++
++ g_free (rmem_chunk);
++
++ LEAVE_MEM_CHUNK_ROUTINE();
++}
++
++gpointer
++g_mem_chunk_alloc (GMemChunk *mem_chunk)
++{
++ GRealMemChunk *rmem_chunk;
++ GMemArea *temp_area;
++ gpointer mem;
++
++ ENTER_MEM_CHUNK_ROUTINE();
++
++ g_return_val_if_fail (mem_chunk != NULL, NULL);
++
++ rmem_chunk = (GRealMemChunk*) mem_chunk;
++
++ while (rmem_chunk->free_atoms)
++ {
++ /* Get the first piece of memory on the "free_atoms" list.
++ * We can go ahead and destroy the list node we used to keep
++ * track of it with and to update the "free_atoms" list to
++ * point to its next element.
++ */
++ mem = rmem_chunk->free_atoms;
++ rmem_chunk->free_atoms = rmem_chunk->free_atoms->next;
++
++ /* Determine which area this piece of memory is allocated from */
++ temp_area = g_tree_search (rmem_chunk->mem_tree,
++ (GSearchFunc) g_mem_chunk_area_search,
++ mem);
++
++ /* If the area has been marked, then it is being destroyed.
++ * (ie marked to be destroyed).
++ * We check to see if all of the segments on the free list that
++ * reference this area have been removed. This occurs when
++ * the ammount of free memory is less than the allocatable size.
++ * If the chunk should be freed, then we place it in the "free_mem_area".
++ * This is so we make sure not to free the mem area here and then
++ * allocate it again a few lines down.
++ * If we don't allocate a chunk a few lines down then the "free_mem_area"
++ * will be freed.
++ * If there is already a "free_mem_area" then we'll just free this mem area.
++ */
++ if (temp_area->mark)
++ {
++ /* Update the "free" memory available in that area */
++ temp_area->free += rmem_chunk->atom_size;
++
++ if (temp_area->free == rmem_chunk->area_size)
++ {
++ if (temp_area == rmem_chunk->mem_area)
++ rmem_chunk->mem_area = NULL;
++
++ if (rmem_chunk->free_mem_area)
++ {
++ rmem_chunk->num_mem_areas -= 1;
++
++ if (temp_area->next)
++ temp_area->next->prev = temp_area->prev;
++ if (temp_area->prev)
++ temp_area->prev->next = temp_area->next;
++ if (temp_area == rmem_chunk->mem_areas)
++ rmem_chunk->mem_areas = rmem_chunk->mem_areas->next;
++
++ if (rmem_chunk->type == G_ALLOC_AND_FREE)
++ g_tree_remove (rmem_chunk->mem_tree, temp_area);
++ g_free (temp_area);
++ }
++ else
++ rmem_chunk->free_mem_area = temp_area;
++
++ rmem_chunk->num_marked_areas -= 1;
++ }
++ }
++ else
++ {
++ /* Update the number of allocated atoms count.
++ */
++ temp_area->allocated += 1;
++
++ /* The area wasn't marked...return the memory
++ */
++ goto outa_here;
++ }
++ }
++
++ /* If there isn't a current mem area or the current mem area is out of space
++ * then allocate a new mem area. We'll first check and see if we can use
++ * the "free_mem_area". Otherwise we'll just malloc the mem area.
++ */
++ if ((!rmem_chunk->mem_area) ||
++ ((rmem_chunk->mem_area->index + rmem_chunk->atom_size) > rmem_chunk->area_size))
++ {
++ if (rmem_chunk->free_mem_area)
++ {
++ rmem_chunk->mem_area = rmem_chunk->free_mem_area;
++ rmem_chunk->free_mem_area = NULL;
++ }
++ else
++ {
++ rmem_chunk->mem_area = (GMemArea*) g_malloc (sizeof (GMemArea) -
++ MEM_AREA_SIZE +
++ rmem_chunk->area_size);
++
++ rmem_chunk->num_mem_areas += 1;
++ rmem_chunk->mem_area->next = rmem_chunk->mem_areas;
++ rmem_chunk->mem_area->prev = NULL;
++
++ if (rmem_chunk->mem_areas)
++ rmem_chunk->mem_areas->prev = rmem_chunk->mem_area;
++ rmem_chunk->mem_areas = rmem_chunk->mem_area;
++
++ if (rmem_chunk->type == G_ALLOC_AND_FREE)
++ g_tree_insert (rmem_chunk->mem_tree, rmem_chunk->mem_area, rmem_chunk->mem_area);
++ }
++
++ rmem_chunk->mem_area->index = 0;
++ rmem_chunk->mem_area->free = rmem_chunk->area_size;
++ rmem_chunk->mem_area->allocated = 0;
++ rmem_chunk->mem_area->mark = 0;
++ }
++
++ /* Get the memory and modify the state variables appropriately.
++ */
++ mem = (gpointer) &rmem_chunk->mem_area->mem[rmem_chunk->mem_area->index];
++ rmem_chunk->mem_area->index += rmem_chunk->atom_size;
++ rmem_chunk->mem_area->free -= rmem_chunk->atom_size;
++ rmem_chunk->mem_area->allocated += 1;
++
++outa_here:
++
++ LEAVE_MEM_CHUNK_ROUTINE();
++
++ return mem;
++}
++
++gpointer
++g_mem_chunk_alloc0 (GMemChunk *mem_chunk)
++{
++ gpointer mem;
++
++ mem = g_mem_chunk_alloc (mem_chunk);
++ if (mem)
++ {
++ GRealMemChunk *rmem_chunk = (GRealMemChunk*) mem_chunk;
++
++ memset (mem, 0, rmem_chunk->atom_size);
++ }
++
++ return mem;
++}
++
++void
++g_mem_chunk_free (GMemChunk *mem_chunk,
++ gpointer mem)
++{
++ GRealMemChunk *rmem_chunk;
++ GMemArea *temp_area;
++ GFreeAtom *free_atom;
++
++ g_return_if_fail (mem_chunk != NULL);
++ g_return_if_fail (mem != NULL);
++
++ ENTER_MEM_CHUNK_ROUTINE();
++
++ rmem_chunk = (GRealMemChunk*) mem_chunk;
++
++ /* Don't do anything if this is an ALLOC_ONLY chunk
++ */
++ if (rmem_chunk->type == G_ALLOC_AND_FREE)
++ {
++ /* Place the memory on the "free_atoms" list
++ */
++ free_atom = (GFreeAtom*) mem;
++ free_atom->next = rmem_chunk->free_atoms;
++ rmem_chunk->free_atoms = free_atom;
++
++ temp_area = g_tree_search (rmem_chunk->mem_tree,
++ (GSearchFunc) g_mem_chunk_area_search,
++ mem);
++
++ temp_area->allocated -= 1;
++
++ if (temp_area->allocated == 0)
++ {
++ temp_area->mark = 1;
++ rmem_chunk->num_marked_areas += 1;
++ }
++ }
++
++ LEAVE_MEM_CHUNK_ROUTINE();
++}
++
++/* This doesn't free the free_area if there is one */
++void
++g_mem_chunk_clean (GMemChunk *mem_chunk)
++{
++ GRealMemChunk *rmem_chunk;
++ GMemArea *mem_area;
++ GFreeAtom *prev_free_atom;
++ GFreeAtom *temp_free_atom;
++ gpointer mem;
++
++ g_return_if_fail (mem_chunk != NULL);
++
++ rmem_chunk = (GRealMemChunk*) mem_chunk;
++
++ if (rmem_chunk->type == G_ALLOC_AND_FREE)
++ {
++ prev_free_atom = NULL;
++ temp_free_atom = rmem_chunk->free_atoms;
++
++ while (temp_free_atom)
++ {
++ mem = (gpointer) temp_free_atom;
++
++ mem_area = g_tree_search (rmem_chunk->mem_tree,
++ (GSearchFunc) g_mem_chunk_area_search,
++ mem);
++
++ /* If this mem area is marked for destruction then delete the
++ * area and list node and decrement the free mem.
++ */
++ if (mem_area->mark)
++ {
++ if (prev_free_atom)
++ prev_free_atom->next = temp_free_atom->next;
++ else
++ rmem_chunk->free_atoms = temp_free_atom->next;
++ temp_free_atom = temp_free_atom->next;
++
++ mem_area->free += rmem_chunk->atom_size;
++ if (mem_area->free == rmem_chunk->area_size)
++ {
++ rmem_chunk->num_mem_areas -= 1;
++ rmem_chunk->num_marked_areas -= 1;
++
++ if (mem_area->next)
++ mem_area->next->prev = mem_area->prev;
++ if (mem_area->prev)
++ mem_area->prev->next = mem_area->next;
++ if (mem_area == rmem_chunk->mem_areas)
++ rmem_chunk->mem_areas = rmem_chunk->mem_areas->next;
++ if (mem_area == rmem_chunk->mem_area)
++ rmem_chunk->mem_area = NULL;
++
++ if (rmem_chunk->type == G_ALLOC_AND_FREE)
++ g_tree_remove (rmem_chunk->mem_tree, mem_area);
++ g_free (mem_area);
++ }
++ }
++ else
++ {
++ prev_free_atom = temp_free_atom;
++ temp_free_atom = temp_free_atom->next;
++ }
++ }
++ }
++}
++
++void
++g_mem_chunk_reset (GMemChunk *mem_chunk)
++{
++ GRealMemChunk *rmem_chunk;
++ GMemArea *mem_areas;
++ GMemArea *temp_area;
++
++ g_return_if_fail (mem_chunk != NULL);
++
++ rmem_chunk = (GRealMemChunk*) mem_chunk;
++
++ mem_areas = rmem_chunk->mem_areas;
++ rmem_chunk->num_mem_areas = 0;
++ rmem_chunk->mem_areas = NULL;
++ rmem_chunk->mem_area = NULL;
++
++ while (mem_areas)
++ {
++ temp_area = mem_areas;
++ mem_areas = mem_areas->next;
++ g_free (temp_area);
++ }
++
++ rmem_chunk->free_atoms = NULL;
++
++ if (rmem_chunk->mem_tree)
++ g_tree_destroy (rmem_chunk->mem_tree);
++ rmem_chunk->mem_tree = g_tree_new ((GCompareFunc) g_mem_chunk_area_compare);
++}
++
++void
++g_mem_chunk_print (GMemChunk *mem_chunk)
++{
++ GRealMemChunk *rmem_chunk;
++ GMemArea *mem_areas;
++ gulong mem;
++
++ g_return_if_fail (mem_chunk != NULL);
++
++ rmem_chunk = (GRealMemChunk*) mem_chunk;
++ mem_areas = rmem_chunk->mem_areas;
++ mem = 0;
++
++ while (mem_areas)
++ {
++ mem += rmem_chunk->area_size - mem_areas->free;
++ mem_areas = mem_areas->next;
++ }
++
++ g_log (g_log_domain_glib, G_LOG_LEVEL_INFO,
++ "%s: %ld bytes using %d mem areas",
++ rmem_chunk->name, mem, rmem_chunk->num_mem_areas);
++}
++
++void
++g_mem_chunk_info (void)
++{
++ GRealMemChunk *mem_chunk;
++ gint count;
++
++ count = 0;
++#ifndef __KORBIT__
++ g_mutex_lock (mem_chunks_lock);
++#endif /* !__KORBIT__ */
++ mem_chunk = mem_chunks;
++ while (mem_chunk)
++ {
++ count += 1;
++ mem_chunk = mem_chunk->next;
++ }
++#ifndef __KORBIT__
++ g_mutex_unlock (mem_chunks_lock);
++#endif /* !__KORBIT__ */
++ g_log (g_log_domain_glib, G_LOG_LEVEL_INFO, "%d mem chunks", count);
++
++#ifndef __KORBIT__
++ g_mutex_lock (mem_chunks_lock);
++#endif /* !__KORBIT__ */
++ mem_chunk = mem_chunks;
++#ifndef __KORBIT__
++ g_mutex_unlock (mem_chunks_lock);
++#endif /* !__KORBIT__ */
++
++ while (mem_chunk)
++ {
++ g_mem_chunk_print ((GMemChunk*) mem_chunk);
++ mem_chunk = mem_chunk->next;
++ }
++}
++
++void
++g_blow_chunks (void)
++{
++ GRealMemChunk *mem_chunk;
++
++#ifndef __KORBIT__
++ g_mutex_lock (mem_chunks_lock);
++#endif /* !__KORBIT__ */
++ mem_chunk = mem_chunks;
++#ifndef __KORBIT__
++ g_mutex_unlock (mem_chunks_lock);
++#endif /* !__KORBIT__ */
++ while (mem_chunk)
++ {
++ g_mem_chunk_clean ((GMemChunk*) mem_chunk);
++ mem_chunk = mem_chunk->next;
++ }
++}
++
++
++static gulong
++g_mem_chunk_compute_size (gulong size,
++ gulong min_size)
++{
++ gulong power_of_2;
++ gulong lower, upper;
++
++ power_of_2 = 16;
++ while (power_of_2 < size)
++ power_of_2 <<= 1;
++
++ lower = power_of_2 >> 1;
++ upper = power_of_2;
++
++ if (size - lower < upper - size && lower >= min_size)
++ return lower;
++ else
++ return upper;
++}
++
++static gint
++g_mem_chunk_area_compare (GMemArea *a,
++ GMemArea *b)
++{
++ if (a->mem > b->mem)
++ return 1;
++ else if (a->mem < b->mem)
++ return -1;
++ return 0;
++}
++
++static gint
++g_mem_chunk_area_search (GMemArea *a,
++ gchar *addr)
++{
++ if (a->mem <= addr)
++ {
++ if (addr < &a->mem[a->index])
++ return 0;
++ return 1;
++ }
++ return -1;
++}
++
++/* generic allocators
++ */
++struct _GAllocator /* from gmem.c */
++{
++ gchar *name;
++ guint16 n_preallocs;
++ guint is_unused : 1;
++ guint type : 4;
++ GAllocator *last;
++ GMemChunk *mem_chunk;
++ gpointer dummy; /* implementation specific */
++};
++
++GAllocator*
++g_allocator_new (const gchar *name,
++ guint n_preallocs)
++{
++ GAllocator *allocator;
++
++ g_return_val_if_fail (name != NULL, NULL);
++
++ allocator = g_new0 (GAllocator, 1);
++ allocator->name = g_strdup (name);
++ allocator->n_preallocs = CLAMP (n_preallocs, 1, 65535);
++ allocator->is_unused = TRUE;
++ allocator->type = 0;
++ allocator->last = NULL;
++ allocator->mem_chunk = NULL;
++ allocator->dummy = NULL;
++
++ return allocator;
++}
++
++void
++g_allocator_free (GAllocator *allocator)
++{
++ g_return_if_fail (allocator != NULL);
++ g_return_if_fail (allocator->is_unused == TRUE);
++
++ g_free (allocator->name);
++ if (allocator->mem_chunk)
++ g_mem_chunk_destroy (allocator->mem_chunk);
++
++ g_free (allocator);
++}
++
++void
++g_mem_init (void)
++{
++#ifndef __KORBIT__
++ mem_chunks_lock = g_mutex_new();
++#endif /* !__KORBIT__ */
++}
+diff -urN linux-2.4.1/net/korbit/kglib/gprimes.c linux-2.4.1-korbit/net/korbit/kglib/gprimes.c
+--- linux-2.4.1/net/korbit/kglib/gprimes.c Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/kglib/gprimes.c Thu Feb 1 11:46:57 2001
+@@ -0,0 +1,79 @@
++/* GLIB - Library of useful routines for C programming
++ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Library General Public
++ * License as published by the Free Software Foundation; either
++ * version 2 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Library General Public License for more details.
++ *
++ * You should have received a copy of the GNU Library General Public
++ * License along with this library; if not, write to the
++ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
++ * Boston, MA 02111-1307, USA.
++ */
++
++/*
++ * Modified by the GLib Team and others 1997-1999. See the AUTHORS
++ * file for a list of people on the GLib Team. See the ChangeLog
++ * files for a list of changes. These files are distributed with
++ * GLib at ftp://ftp.gtk.org/pub/gtk/.
++ */
++
++#include "glib.h"
++
++static const guint g_primes[] =
++{
++ 11,
++ 19,
++ 37,
++ 73,
++ 109,
++ 163,
++ 251,
++ 367,
++ 557,
++ 823,
++ 1237,
++ 1861,
++ 2777,
++ 4177,
++ 6247,
++ 9371,
++ 14057,
++ 21089,
++ 31627,
++ 47431,
++ 71143,
++ 106721,
++ 160073,
++ 240101,
++ 360163,
++ 540217,
++ 810343,
++ 1215497,
++ 1823231,
++ 2734867,
++ 4102283,
++ 6153409,
++ 9230113,
++ 13845163,
++};
++
++static const guint g_nprimes = sizeof (g_primes) / sizeof (g_primes[0]);
++
++guint
++g_spaced_primes_closest (guint num)
++{
++ gint i;
++
++ for (i = 0; i < g_nprimes; i++)
++ if (g_primes[i] > num)
++ return g_primes[i];
++
++ return g_primes[g_nprimes - 1];
++}
+diff -urN linux-2.4.1/net/korbit/kglib/gslist.c linux-2.4.1-korbit/net/korbit/kglib/gslist.c
+--- linux-2.4.1/net/korbit/kglib/gslist.c Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/kglib/gslist.c Thu Feb 1 11:46:57 2001
+@@ -0,0 +1,591 @@
++/* GLIB - Library of useful routines for C programming
++ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Library General Public
++ * License as published by the Free Software Foundation; either
++ * version 2 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Library General Public License for more details.
++ *
++ * You should have received a copy of the GNU Library General Public
++ * License along with this library; if not, write to the
++ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
++ * Boston, MA 02111-1307, USA.
++ */
++
++/*
++ * Modified by the GLib Team and others 1997-1999. See the AUTHORS
++ * file for a list of people on the GLib Team. See the ChangeLog
++ * files for a list of changes. These files are distributed with
++ * GLib at ftp://ftp.gtk.org/pub/gtk/.
++ */
++
++#include "glib.h"
++
++
++struct _GAllocator /* from gmem.c */
++{
++ gchar *name;
++ guint16 n_preallocs;
++ guint is_unused : 1;
++ guint type : 4;
++ GAllocator *last;
++ GMemChunk *mem_chunk;
++ GSList *free_lists; /* implementation specific */
++};
++
++G_LOCK_DEFINE_STATIC (current_allocator);
++static GAllocator *current_allocator = NULL;
++
++/* HOLDS: current_allocator_lock */
++static void
++g_slist_validate_allocator (GAllocator *allocator)
++{
++ g_return_if_fail (allocator != NULL);
++ g_return_if_fail (allocator->is_unused == TRUE);
++
++ if (allocator->type != G_ALLOCATOR_SLIST)
++ {
++ allocator->type = G_ALLOCATOR_SLIST;
++ if (allocator->mem_chunk)
++ {
++ g_mem_chunk_destroy (allocator->mem_chunk);
++ allocator->mem_chunk = NULL;
++ }
++ }
++
++ if (!allocator->mem_chunk)
++ {
++ allocator->mem_chunk = g_mem_chunk_new (allocator->name,
++ sizeof (GSList),
++ sizeof (GSList) * allocator->n_preallocs,
++ G_ALLOC_ONLY);
++ allocator->free_lists = NULL;
++ }
++
++ allocator->is_unused = FALSE;
++}
++
++void
++g_slist_push_allocator (GAllocator *allocator)
++{
++ G_LOCK (current_allocator);
++ g_slist_validate_allocator (allocator);
++ allocator->last = current_allocator;
++ current_allocator = allocator;
++ G_UNLOCK (current_allocator);
++}
++
++void
++g_slist_pop_allocator (void)
++{
++ G_LOCK (current_allocator);
++ if (current_allocator)
++ {
++ GAllocator *allocator;
++
++ allocator = current_allocator;
++ current_allocator = allocator->last;
++ allocator->last = NULL;
++ allocator->is_unused = TRUE;
++ }
++ G_UNLOCK (current_allocator);
++}
++
++GSList*
++g_slist_alloc (void)
++{
++ GSList *list;
++
++ G_LOCK (current_allocator);
++ if (!current_allocator)
++ {
++ GAllocator *allocator = g_allocator_new ("GLib default GSList allocator",
++ 128);
++ g_slist_validate_allocator (allocator);
++ allocator->last = NULL;
++ current_allocator = allocator;
++ }
++ if (!current_allocator->free_lists)
++ {
++ list = g_chunk_new (GSList, current_allocator->mem_chunk);
++ list->data = NULL;
++ }
++ else
++ {
++ if (current_allocator->free_lists->data)
++ {
++ list = current_allocator->free_lists->data;
++ current_allocator->free_lists->data = list->next;
++ list->data = NULL;
++ }
++ else
++ {
++ list = current_allocator->free_lists;
++ current_allocator->free_lists = list->next;
++ }
++ }
++ G_UNLOCK (current_allocator);
++
++ list->next = NULL;
++
++ return list;
++}
++
++void
++g_slist_free (GSList *list)
++{
++ if (list)
++ {
++ list->data = list->next;
++ G_LOCK (current_allocator);
++ list->next = current_allocator->free_lists;
++ current_allocator->free_lists = list;
++ G_UNLOCK (current_allocator);
++ }
++}
++
++void
++g_slist_free_1 (GSList *list)
++{
++ if (list)
++ {
++ list->data = NULL;
++ G_LOCK (current_allocator);
++ list->next = current_allocator->free_lists;
++ current_allocator->free_lists = list;
++ G_UNLOCK (current_allocator);
++ }
++}
++
++GSList*
++g_slist_append (GSList *list,
++ gpointer data)
++{
++ GSList *new_list;
++ GSList *last;
++
++ new_list = g_slist_alloc ();
++ new_list->data = data;
++
++ if (list)
++ {
++ last = g_slist_last (list);
++ /* g_assert (last != NULL); */
++ last->next = new_list;
++
++ return list;
++ }
++ else
++ return new_list;
++}
++
++GSList*
++g_slist_prepend (GSList *list,
++ gpointer data)
++{
++ GSList *new_list;
++
++ new_list = g_slist_alloc ();
++ new_list->data = data;
++ new_list->next = list;
++
++ return new_list;
++}
++
++GSList*
++g_slist_insert (GSList *list,
++ gpointer data,
++ gint position)
++{
++ GSList *prev_list;
++ GSList *tmp_list;
++ GSList *new_list;
++
++ if (position < 0)
++ return g_slist_append (list, data);
++ else if (position == 0)
++ return g_slist_prepend (list, data);
++
++ new_list = g_slist_alloc ();
++ new_list->data = data;
++
++ if (!list)
++ return new_list;
++
++ prev_list = NULL;
++ tmp_list = list;
++
++ while ((position-- > 0) && tmp_list)
++ {
++ prev_list = tmp_list;
++ tmp_list = tmp_list->next;
++ }
++
++ if (prev_list)
++ {
++ new_list->next = prev_list->next;
++ prev_list->next = new_list;
++ }
++ else
++ {
++ new_list->next = list;
++ list = new_list;
++ }
++
++ return list;
++}
++
++GSList *
++g_slist_concat (GSList *list1, GSList *list2)
++{
++ if (list2)
++ {
++ if (list1)
++ g_slist_last (list1)->next = list2;
++ else
++ list1 = list2;
++ }
++
++ return list1;
++}
++
++GSList*
++g_slist_remove (GSList *list,
++ gpointer data)
++{
++ GSList *tmp;
++ GSList *prev;
++
++ prev = NULL;
++ tmp = list;
++
++ while (tmp)
++ {
++ if (tmp->data == data)
++ {
++ if (prev)
++ prev->next = tmp->next;
++ if (list == tmp)
++ list = list->next;
++
++ tmp->next = NULL;
++ g_slist_free (tmp);
++
++ break;
++ }
++
++ prev = tmp;
++ tmp = tmp->next;
++ }
++
++ return list;
++}
++
++GSList*
++g_slist_remove_link (GSList *list,
++ GSList *link)
++{
++ GSList *tmp;
++ GSList *prev;
++
++ prev = NULL;
++ tmp = list;
++
++ while (tmp)
++ {
++ if (tmp == link)
++ {
++ if (prev)
++ prev->next = tmp->next;
++ if (list == tmp)
++ list = list->next;
++
++ tmp->next = NULL;
++ break;
++ }
++
++ prev = tmp;
++ tmp = tmp->next;
++ }
++
++ return list;
++}
++
++GSList*
++g_slist_copy (GSList *list)
++{
++ GSList *new_list = NULL;
++
++ if (list)
++ {
++ GSList *last;
++
++ new_list = g_slist_alloc ();
++ new_list->data = list->data;
++ last = new_list;
++ list = list->next;
++ while (list)
++ {
++ last->next = g_slist_alloc ();
++ last = last->next;
++ last->data = list->data;
++ list = list->next;
++ }
++ }
++
++ return new_list;
++}
++
++GSList*
++g_slist_reverse (GSList *list)
++{
++ GSList *prev = NULL;
++
++ while (list)
++ {
++ GSList *next = list->next;
++
++ list->next = prev;
++
++ prev = list;
++ list = next;
++ }
++
++ return prev;
++}
++
++GSList*
++g_slist_nth (GSList *list,
++ guint n)
++{
++ while ((n-- > 0) && list)
++ list = list->next;
++
++ return list;
++}
++
++gpointer
++g_slist_nth_data (GSList *list,
++ guint n)
++{
++ while ((n-- > 0) && list)
++ list = list->next;
++
++ return list ? list->data : NULL;
++}
++
++GSList*
++g_slist_find (GSList *list,
++ gpointer data)
++{
++ while (list)
++ {
++ if (list->data == data)
++ break;
++ list = list->next;
++ }
++
++ return list;
++}
++
++GSList*
++g_slist_find_custom (GSList *list,
++ gpointer data,
++ GCompareFunc func)
++{
++ g_return_val_if_fail (func != NULL, list);
++
++ while (list)
++ {
++ if (! func (list->data, data))
++ return list;
++ list = list->next;
++ }
++
++ return NULL;
++}
++
++gint
++g_slist_position (GSList *list,
++ GSList *link)
++{
++ gint i;
++
++ i = 0;
++ while (list)
++ {
++ if (list == link)
++ return i;
++ i++;
++ list = list->next;
++ }
++
++ return -1;
++}
++
++gint
++g_slist_index (GSList *list,
++ gpointer data)
++{
++ gint i;
++
++ i = 0;
++ while (list)
++ {
++ if (list->data == data)
++ return i;
++ i++;
++ list = list->next;
++ }
++
++ return -1;
++}
++
++GSList*
++g_slist_last (GSList *list)
++{
++ if (list)
++ {
++ while (list->next)
++ list = list->next;
++ }
++
++ return list;
++}
++
++guint
++g_slist_length (GSList *list)
++{
++ guint length;
++
++ length = 0;
++ while (list)
++ {
++ length++;
++ list = list->next;
++ }
++
++ return length;
++}
++
++void
++g_slist_foreach (GSList *list,
++ GFunc func,
++ gpointer user_data)
++{
++ while (list)
++ {
++ (*func) (list->data, user_data);
++ list = list->next;
++ }
++}
++
++GSList*
++g_slist_insert_sorted (GSList *list,
++ gpointer data,
++ GCompareFunc func)
++{
++ GSList *tmp_list = list;
++ GSList *prev_list = NULL;
++ GSList *new_list;
++ gint cmp;
++
++ g_return_val_if_fail (func != NULL, list);
++
++ if (!list)
++ {
++ new_list = g_slist_alloc();
++ new_list->data = data;
++ return new_list;
++ }
++
++ cmp = (*func) (data, tmp_list->data);
++
++ while ((tmp_list->next) && (cmp > 0))
++ {
++ prev_list = tmp_list;
++ tmp_list = tmp_list->next;
++ cmp = (*func) (data, tmp_list->data);
++ }
++
++ new_list = g_slist_alloc();
++ new_list->data = data;
++
++ if ((!tmp_list->next) && (cmp > 0))
++ {
++ tmp_list->next = new_list;
++ return list;
++ }
++
++ if (prev_list)
++ {
++ prev_list->next = new_list;
++ new_list->next = tmp_list;
++ return list;
++ }
++ else
++ {
++ new_list->next = list;
++ return new_list;
++ }
++}
++
++static GSList*
++g_slist_sort_merge (GSList *l1,
++ GSList *l2,
++ GCompareFunc compare_func)
++{
++ GSList list, *l;
++
++ l=&list;
++
++ while (l1 && l2)
++ {
++ if (compare_func(l1->data,l2->data) < 0)
++ {
++ l=l->next=l1;
++ l1=l1->next;
++ }
++ else
++ {
++ l=l->next=l2;
++ l2=l2->next;
++ }
++ }
++ l->next= l1 ? l1 : l2;
++
++ return list.next;
++}
++
++GSList*
++g_slist_sort (GSList *list,
++ GCompareFunc compare_func)
++{
++ GSList *l1, *l2;
++
++ if (!list)
++ return NULL;
++ if (!list->next)
++ return list;
++
++ l1 = list;
++ l2 = list->next;
++
++ while ((l2 = l2->next) != NULL)
++ {
++ if ((l2 = l2->next) == NULL)
++ break;
++ l1=l1->next;
++ }
++ l2 = l1->next;
++ l1->next = NULL;
++
++ return g_slist_sort_merge (g_slist_sort (list, compare_func),
++ g_slist_sort (l2, compare_func),
++ compare_func);
++}
+diff -urN linux-2.4.1/net/korbit/kglib/gstrfuncs.c linux-2.4.1-korbit/net/korbit/kglib/gstrfuncs.c
+--- linux-2.4.1/net/korbit/kglib/gstrfuncs.c Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/kglib/gstrfuncs.c Thu Feb 1 11:46:57 2001
+@@ -0,0 +1,1308 @@
++/* GLIB - Library of useful routines for C programming
++ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Library General Public
++ * License as published by the Free Software Foundation; either
++ * version 2 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Library General Public License for more details.
++ *
++ * You should have received a copy of the GNU Library General Public
++ * License along with this library; if not, write to the
++ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
++ * Boston, MA 02111-1307, USA.
++ */
++
++/*
++ * Modified by the GLib Team and others 1997-1999. See the AUTHORS
++ * file for a list of people on the GLib Team. See the ChangeLog
++ * files for a list of changes. These files are distributed with
++ * GLib at ftp://ftp.gtk.org/pub/gtk/.
++ */
++
++#ifdef HAVE_CONFIG_H
++#include <config.h>
++#endif
++
++#include <stdarg.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <locale.h>
++#include <ctype.h> /* For tolower() */
++#if !defined (HAVE_STRSIGNAL) || !defined(NO_SYS_SIGLIST_DECL)
++#include <signal.h>
++#endif
++#include "glib.h"
++/* do not include <unistd.h> in this place since it
++ * inteferes with g_strsignal() on some OSes
++ */
++
++gchar*
++g_strdup (const gchar *str) {
++ gchar *new_str;
++
++ if (str)
++ {
++ new_str = g_new (char, strlen (str) + 1);
++ strcpy (new_str, str);
++ }
++ else
++ new_str = NULL;
++
++ return new_str;
++}
++
++gpointer
++g_memdup (gconstpointer mem,
++ guint byte_size)
++{
++ gpointer new_mem;
++
++ if (mem)
++ {
++ new_mem = g_malloc (byte_size);
++ memcpy (new_mem, mem, byte_size);
++ }
++ else
++ new_mem = NULL;
++
++ return new_mem;
++}
++
++gchar*
++g_strndup (const gchar *str,
++ guint n)
++{
++ gchar *new_str;
++
++ if (str)
++ {
++ new_str = g_new (gchar, n + 1);
++ strncpy (new_str, str, n);
++ new_str[n] = '\0';
++ }
++ else
++ new_str = NULL;
++
++ return new_str;
++}
++
++gchar*
++g_strnfill (guint length,
++ gchar fill_char)
++{
++ register gchar *str, *s, *end;
++
++ str = g_new (gchar, length + 1);
++ s = str;
++ end = str + length;
++ while (s < end)
++ *(s++) = fill_char;
++ *s = 0;
++
++ return str;
++}
++
++gchar*
++g_strdup_vprintf (const gchar *format,
++ va_list args1)
++{
++ gchar *buffer;
++ va_list args2;
++
++ G_VA_COPY (args2, args1);
++
++ buffer = g_new (gchar, g_printf_string_upper_bound (format, args1));
++
++ vsprintf (buffer, format, args2);
++ va_end (args2);
++
++ return buffer;
++}
++
++gchar*
++g_strdup_printf (const gchar *format,
++ ...)
++{
++ gchar *buffer;
++ va_list args;
++
++ va_start (args, format);
++ buffer = g_strdup_vprintf (format, args);
++ va_end (args);
++
++ return buffer;
++}
++
++gchar*
++g_strconcat (const gchar *string1, ...)
++{
++ guint l;
++ va_list args;
++ gchar *s;
++ gchar *concat;
++
++ g_return_val_if_fail (string1 != NULL, NULL);
++
++ l = 1 + strlen (string1);
++ va_start (args, string1);
++ s = va_arg (args, gchar*);
++ while (s)
++ {
++ l += strlen (s);
++ s = va_arg (args, gchar*);
++ }
++ va_end (args);
++
++ concat = g_new (gchar, l);
++ concat[0] = 0;
++
++ strcat (concat, string1);
++ va_start (args, string1);
++ s = va_arg (args, gchar*);
++ while (s)
++ {
++ strcat (concat, s);
++ s = va_arg (args, gchar*);
++ }
++ va_end (args);
++
++ return concat;
++}
++
++#ifndef __KORBIT__
++gdouble
++g_strtod (const gchar *nptr,
++ gchar **endptr)
++{
++ gchar *fail_pos_1;
++ gchar *fail_pos_2;
++ gdouble val_1;
++ gdouble val_2 = 0;
++
++ g_return_val_if_fail (nptr != NULL, 0);
++
++ fail_pos_1 = NULL;
++ fail_pos_2 = NULL;
++
++ val_1 = strtod (nptr, &fail_pos_1);
++
++ if (fail_pos_1 && fail_pos_1[0] != 0)
++ {
++ gchar *old_locale;
++
++ old_locale = g_strdup (setlocale (LC_NUMERIC, NULL));
++ setlocale (LC_NUMERIC, "C");
++ val_2 = strtod (nptr, &fail_pos_2);
++ setlocale (LC_NUMERIC, old_locale);
++ g_free (old_locale);
++ }
++
++ if (!fail_pos_1 || fail_pos_1[0] == 0 || fail_pos_1 >= fail_pos_2)
++ {
++ if (endptr)
++ *endptr = fail_pos_1;
++ return val_1;
++ }
++ else
++ {
++ if (endptr)
++ *endptr = fail_pos_2;
++ return val_2;
++ }
++}
++#endif /* !__KORBIT__ */
++
++gchar*
++g_strerror (gint errnum)
++{
++#ifndef __KORBIT__
++ static GStaticPrivate msg_private = G_STATIC_PRIVATE_INIT;
++ char *msg;
++#endif
++
++#ifdef __KORBIT__
++#undef HAVE_STRERROR
++#define NO_SYS_ERRLIST 1
++#endif
++
++#if defined(HAVE_STRERROR)
++ return strerror (errnum);
++#elif NO_SYS_ERRLIST
++ switch (errnum)
++ {
++#ifdef E2BIG
++ case E2BIG: return "argument list too long";
++#endif
++#ifdef EACCES
++ case EACCES: return "permission denied";
++#endif
++#ifdef EADDRINUSE
++ case EADDRINUSE: return "address already in use";
++#endif
++#ifdef EADDRNOTAVAIL
++ case EADDRNOTAVAIL: return "can't assign requested address";
++#endif
++#ifdef EADV
++ case EADV: return "advertise error";
++#endif
++#ifdef EAFNOSUPPORT
++ case EAFNOSUPPORT: return "address family not supported by protocol family";
++#endif
++#ifdef EAGAIN
++ case EAGAIN: return "try again";
++#endif
++#ifdef EALIGN
++ case EALIGN: return "EALIGN";
++#endif
++#ifdef EALREADY
++ case EALREADY: return "operation already in progress";
++#endif
++#ifdef EBADE
++ case EBADE: return "bad exchange descriptor";
++#endif
++#ifdef EBADF
++ case EBADF: return "bad file number";
++#endif
++#ifdef EBADFD
++ case EBADFD: return "file descriptor in bad state";
++#endif
++#ifdef EBADMSG
++ case EBADMSG: return "not a data message";
++#endif
++#ifdef EBADR
++ case EBADR: return "bad request descriptor";
++#endif
++#ifdef EBADRPC
++ case EBADRPC: return "RPC structure is bad";
++#endif
++#ifdef EBADRQC
++ case EBADRQC: return "bad request code";
++#endif
++#ifdef EBADSLT
++ case EBADSLT: return "invalid slot";
++#endif
++#ifdef EBFONT
++ case EBFONT: return "bad font file format";
++#endif
++#ifdef EBUSY
++ case EBUSY: return "mount device busy";
++#endif
++#ifdef ECHILD
++ case ECHILD: return "no children";
++#endif
++#ifdef ECHRNG
++ case ECHRNG: return "channel number out of range";
++#endif
++#ifdef ECOMM
++ case ECOMM: return "communication error on send";
++#endif
++#ifdef ECONNABORTED
++ case ECONNABORTED: return "software caused connection abort";
++#endif
++#ifdef ECONNREFUSED
++ case ECONNREFUSED: return "connection refused";
++#endif
++#ifdef ECONNRESET
++ case ECONNRESET: return "connection reset by peer";
++#endif
++#if defined(EDEADLK) && (!defined(EWOULDBLOCK) || (EDEADLK != EWOULDBLOCK)) && (!defined(EDEADLOCK) || (EDEADLK != EDEADLOCK))
++ case EDEADLK: return "resource deadlock avoided";
++#endif
++#ifdef EDEADLOCK
++ case EDEADLOCK: return "resource deadlock avoided";
++#endif
++#ifdef EDESTADDRREQ
++ case EDESTADDRREQ: return "destination address required";
++#endif
++#ifdef EDIRTY
++ case EDIRTY: return "mounting a dirty fs w/o force";
++#endif
++#ifdef EDOM
++ case EDOM: return "math argument out of range";
++#endif
++#ifdef EDOTDOT
++ case EDOTDOT: return "cross mount point";
++#endif
++#ifdef EDQUOT
++ case EDQUOT: return "disk quota exceeded";
++#endif
++#ifdef EDUPPKG
++ case EDUPPKG: return "duplicate package name";
++#endif
++#ifdef EEXIST
++ case EEXIST: return "file already exists";
++#endif
++#ifdef EFAULT
++ case EFAULT: return "bad address in system call argument";
++#endif
++#ifdef EFBIG
++ case EFBIG: return "file too large";
++#endif
++#ifdef EHOSTDOWN
++ case EHOSTDOWN: return "host is down";
++#endif
++#ifdef EHOSTUNREACH
++ case EHOSTUNREACH: return "host is unreachable";
++#endif
++#ifdef EIDRM
++ case EIDRM: return "identifier removed";
++#endif
++#ifdef EINIT
++ case EINIT: return "initialization error";
++#endif
++#ifdef EINPROGRESS
++ case EINPROGRESS: return "operation now in progress";
++#endif
++#ifdef EINTR
++ case EINTR: return "interrupted system call";
++#endif
++#ifdef EINVAL
++ case EINVAL: return "invalid argument";
++#endif
++#ifdef EIO
++ case EIO: return "I/O error";
++#endif
++#ifdef EISCONN
++ case EISCONN: return "socket is already connected";
++#endif
++#ifdef EISDIR
++ case EISDIR: return "illegal operation on a directory";
++#endif
++#ifdef EISNAME
++ case EISNAM: return "is a name file";
++#endif
++#ifdef ELBIN
++ case ELBIN: return "ELBIN";
++#endif
++#ifdef EL2HLT
++ case EL2HLT: return "level 2 halted";
++#endif
++#ifdef EL2NSYNC
++ case EL2NSYNC: return "level 2 not synchronized";
++#endif
++#ifdef EL3HLT
++ case EL3HLT: return "level 3 halted";
++#endif
++#ifdef EL3RST
++ case EL3RST: return "level 3 reset";
++#endif
++#ifdef ELIBACC
++ case ELIBACC: return "can not access a needed shared library";
++#endif
++#ifdef ELIBBAD
++ case ELIBBAD: return "accessing a corrupted shared library";
++#endif
++#ifdef ELIBEXEC
++ case ELIBEXEC: return "can not exec a shared library directly";
++#endif
++#ifdef ELIBMAX
++ case ELIBMAX: return "attempting to link in more shared libraries than system limit";
++#endif
++#ifdef ELIBSCN
++ case ELIBSCN: return ".lib section in a.out corrupted";
++#endif
++#ifdef ELNRNG
++ case ELNRNG: return "link number out of range";
++#endif
++#ifdef ELOOP
++ case ELOOP: return "too many levels of symbolic links";
++#endif
++#ifdef EMFILE
++ case EMFILE: return "too many open files";
++#endif
++#ifdef EMLINK
++ case EMLINK: return "too many links";
++#endif
++#ifdef EMSGSIZE
++ case EMSGSIZE: return "message too long";
++#endif
++#ifdef EMULTIHOP
++ case EMULTIHOP: return "multihop attempted";
++#endif
++#ifdef ENAMETOOLONG
++ case ENAMETOOLONG: return "file name too long";
++#endif
++#ifdef ENAVAIL
++ case ENAVAIL: return "not available";
++#endif
++#ifdef ENET
++ case ENET: return "ENET";
++#endif
++#ifdef ENETDOWN
++ case ENETDOWN: return "network is down";
++#endif
++#ifdef ENETRESET
++ case ENETRESET: return "network dropped connection on reset";
++#endif
++#ifdef ENETUNREACH
++ case ENETUNREACH: return "network is unreachable";
++#endif
++#ifdef ENFILE
++ case ENFILE: return "file table overflow";
++#endif
++#ifdef ENOANO
++ case ENOANO: return "anode table overflow";
++#endif
++#if defined(ENOBUFS) && (!defined(ENOSR) || (ENOBUFS != ENOSR))
++ case ENOBUFS: return "no buffer space available";
++#endif
++#ifdef ENOCSI
++ case ENOCSI: return "no CSI structure available";
++#endif
++#ifdef ENODATA
++ case ENODATA: return "no data available";
++#endif
++#ifdef ENODEV
++ case ENODEV: return "no such device";
++#endif
++#ifdef ENOENT
++ case ENOENT: return "no such file or directory";
++#endif
++#ifdef ENOEXEC
++ case ENOEXEC: return "exec format error";
++#endif
++#ifdef ENOLCK
++ case ENOLCK: return "no locks available";
++#endif
++#ifdef ENOLINK
++ case ENOLINK: return "link has be severed";
++#endif
++#ifdef ENOMEM
++ case ENOMEM: return "not enough memory";
++#endif
++#ifdef ENOMSG
++ case ENOMSG: return "no message of desired type";
++#endif
++#ifdef ENONET
++ case ENONET: return "machine is not on the network";
++#endif
++#ifdef ENOPKG
++ case ENOPKG: return "package not installed";
++#endif
++#ifdef ENOPROTOOPT
++ case ENOPROTOOPT: return "bad proocol option";
++#endif
++#ifdef ENOSPC
++ case ENOSPC: return "no space left on device";
++#endif
++#ifdef ENOSR
++ case ENOSR: return "out of stream resources";
++#endif
++#ifdef ENOSTR
++ case ENOSTR: return "not a stream device";
++#endif
++#ifdef ENOSYM
++ case ENOSYM: return "unresolved symbol name";
++#endif
++#ifdef ENOSYS
++ case ENOSYS: return "function not implemented";
++#endif
++#ifdef ENOTBLK
++ case ENOTBLK: return "block device required";
++#endif
++#ifdef ENOTCONN
++ case ENOTCONN: return "socket is not connected";
++#endif
++#ifdef ENOTDIR
++ case ENOTDIR: return "not a directory";
++#endif
++#ifdef ENOTEMPTY
++ case ENOTEMPTY: return "directory not empty";
++#endif
++#ifdef ENOTNAM
++ case ENOTNAM: return "not a name file";
++#endif
++#ifdef ENOTSOCK
++ case ENOTSOCK: return "socket operation on non-socket";
++#endif
++#ifdef ENOTTY
++ case ENOTTY: return "inappropriate device for ioctl";
++#endif
++#ifdef ENOTUNIQ
++ case ENOTUNIQ: return "name not unique on network";
++#endif
++#ifdef ENXIO
++ case ENXIO: return "no such device or address";
++#endif
++#ifdef EOPNOTSUPP
++ case EOPNOTSUPP: return "operation not supported on socket";
++#endif
++#ifdef EPERM
++ case EPERM: return "not owner";
++#endif
++#ifdef EPFNOSUPPORT
++ case EPFNOSUPPORT: return "protocol family not supported";
++#endif
++#ifdef EPIPE
++ case EPIPE: return "broken pipe";
++#endif
++#ifdef EPROCLIM
++ case EPROCLIM: return "too many processes";
++#endif
++#ifdef EPROCUNAVAIL
++ case EPROCUNAVAIL: return "bad procedure for program";
++#endif
++#ifdef EPROGMISMATCH
++ case EPROGMISMATCH: return "program version wrong";
++#endif
++#ifdef EPROGUNAVAIL
++ case EPROGUNAVAIL: return "RPC program not available";
++#endif
++#ifdef EPROTO
++ case EPROTO: return "protocol error";
++#endif
++#ifdef EPROTONOSUPPORT
++ case EPROTONOSUPPORT: return "protocol not suppored";
++#endif
++#ifdef EPROTOTYPE
++ case EPROTOTYPE: return "protocol wrong type for socket";
++#endif
++#ifdef ERANGE
++ case ERANGE: return "math result unrepresentable";
++#endif
++#if defined(EREFUSED) && (!defined(ECONNREFUSED) || (EREFUSED != ECONNREFUSED))
++ case EREFUSED: return "EREFUSED";
++#endif
++#ifdef EREMCHG
++ case EREMCHG: return "remote address changed";
++#endif
++#ifdef EREMDEV
++ case EREMDEV: return "remote device";
++#endif
++#ifdef EREMOTE
++ case EREMOTE: return "pathname hit remote file system";
++#endif
++#ifdef EREMOTEIO
++ case EREMOTEIO: return "remote i/o error";
++#endif
++#ifdef EREMOTERELEASE
++ case EREMOTERELEASE: return "EREMOTERELEASE";
++#endif
++#ifdef EROFS
++ case EROFS: return "read-only file system";
++#endif
++#ifdef ERPCMISMATCH
++ case ERPCMISMATCH: return "RPC version is wrong";
++#endif
++#ifdef ERREMOTE
++ case ERREMOTE: return "object is remote";
++#endif
++#ifdef ESHUTDOWN
++ case ESHUTDOWN: return "can't send afer socket shutdown";
++#endif
++#ifdef ESOCKTNOSUPPORT
++ case ESOCKTNOSUPPORT: return "socket type not supported";
++#endif
++#ifdef ESPIPE
++ case ESPIPE: return "invalid seek";
++#endif
++#ifdef ESRCH
++ case ESRCH: return "no such process";
++#endif
++#ifdef ESRMNT
++ case ESRMNT: return "srmount error";
++#endif
++#ifdef ESTALE
++ case ESTALE: return "stale remote file handle";
++#endif
++#ifdef ESUCCESS
++ case ESUCCESS: return "Error 0";
++#endif
++#ifdef ETIME
++ case ETIME: return "timer expired";
++#endif
++#ifdef ETIMEDOUT
++ case ETIMEDOUT: return "connection timed out";
++#endif
++#ifdef ETOOMANYREFS
++ case ETOOMANYREFS: return "too many references: can't splice";
++#endif
++#ifdef ETXTBSY
++ case ETXTBSY: return "text file or pseudo-device busy";
++#endif
++#ifdef EUCLEAN
++ case EUCLEAN: return "structure needs cleaning";
++#endif
++#ifdef EUNATCH
++ case EUNATCH: return "protocol driver not attached";
++#endif
++#ifdef EUSERS
++ case EUSERS: return "too many users";
++#endif
++#ifdef EVERSION
++ case EVERSION: return "version mismatch";
++#endif
++#if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
++ case EWOULDBLOCK: return "operation would block";
++#endif
++#ifdef EXDEV
++ case EXDEV: return "cross-domain link";
++#endif
++#ifdef EXFULL
++ case EXFULL: return "message tables full";
++#endif
++ }
++#else /* NO_SYS_ERRLIST */
++ extern int sys_nerr;
++ extern char *sys_errlist[];
++
++ if ((errnum > 0) && (errnum <= sys_nerr))
++ return sys_errlist [errnum];
++#endif /* NO_SYS_ERRLIST */
++
++#ifndef __KORBIT__
++ msg = g_static_private_get (&msg_private);
++ if (!msg)
++ {
++ msg = g_new (gchar, 64);
++ g_static_private_set (&msg_private, msg, g_free);
++ }
++
++ sprintf (msg, "unknown error (%d)", errnum);
++
++ return msg;
++#else
++ return "unknown error";
++#endif /* !__KORBIT__ */
++}
++
++gchar*
++g_strsignal (gint signum)
++{
++#ifndef __KORBIT__
++ static GStaticPrivate msg_private = G_STATIC_PRIVATE_INIT;
++ char *msg;
++#endif
++
++#ifdef HAVE_STRSIGNAL
++ extern char *strsignal (int sig);
++ return strsignal (signum);
++#elif NO_SYS_SIGLIST
++ switch (signum)
++ {
++#ifdef SIGHUP
++ case SIGHUP: return "Hangup";
++#endif
++#ifdef SIGINT
++ case SIGINT: return "Interrupt";
++#endif
++#ifdef SIGQUIT
++ case SIGQUIT: return "Quit";
++#endif
++#ifdef SIGILL
++ case SIGILL: return "Illegal instruction";
++#endif
++#ifdef SIGTRAP
++ case SIGTRAP: return "Trace/breakpoint trap";
++#endif
++#ifdef SIGABRT
++ case SIGABRT: return "IOT trap/Abort";
++#endif
++#ifdef SIGBUS
++ case SIGBUS: return "Bus error";
++#endif
++#ifdef SIGFPE
++ case SIGFPE: return "Floating point exception";
++#endif
++#ifdef SIGKILL
++ case SIGKILL: return "Killed";
++#endif
++#ifdef SIGUSR1
++ case SIGUSR1: return "User defined signal 1";
++#endif
++#ifdef SIGSEGV
++ case SIGSEGV: return "Segmentation fault";
++#endif
++#ifdef SIGUSR2
++ case SIGUSR2: return "User defined signal 2";
++#endif
++#ifdef SIGPIPE
++ case SIGPIPE: return "Broken pipe";
++#endif
++#ifdef SIGALRM
++ case SIGALRM: return "Alarm clock";
++#endif
++#ifdef SIGTERM
++ case SIGTERM: return "Terminated";
++#endif
++#ifdef SIGSTKFLT
++ case SIGSTKFLT: return "Stack fault";
++#endif
++#ifdef SIGCHLD
++ case SIGCHLD: return "Child exited";
++#endif
++#ifdef SIGCONT
++ case SIGCONT: return "Continued";
++#endif
++#ifdef SIGSTOP
++ case SIGSTOP: return "Stopped (signal)";
++#endif
++#ifdef SIGTSTP
++ case SIGTSTP: return "Stopped";
++#endif
++#ifdef SIGTTIN
++ case SIGTTIN: return "Stopped (tty input)";
++#endif
++#ifdef SIGTTOU
++ case SIGTTOU: return "Stopped (tty output)";
++#endif
++#ifdef SIGURG
++ case SIGURG: return "Urgent condition";
++#endif
++#ifdef SIGXCPU
++ case SIGXCPU: return "CPU time limit exceeded";
++#endif
++#ifdef SIGXFSZ
++ case SIGXFSZ: return "File size limit exceeded";
++#endif
++#ifdef SIGVTALRM
++ case SIGVTALRM: return "Virtual time alarm";
++#endif
++#ifdef SIGPROF
++ case SIGPROF: return "Profile signal";
++#endif
++#ifdef SIGWINCH
++ case SIGWINCH: return "Window size changed";
++#endif
++#ifdef SIGIO
++ case SIGIO: return "Possible I/O";
++#endif
++#ifdef SIGPWR
++ case SIGPWR: return "Power failure";
++#endif
++#ifdef SIGUNUSED
++ case SIGUNUSED: return "Unused signal";
++#endif
++ }
++#else /* NO_SYS_SIGLIST */
++
++#ifdef NO_SYS_SIGLIST_DECL
++ extern char *sys_siglist[]; /*(see Tue Jan 19 00:44:24 1999 in changelog)*/
++#endif
++
++ return (char*) /* this function should return const --josh */ sys_siglist [signum];
++#endif /* NO_SYS_SIGLIST */
++
++#ifndef __KORBIT__
++ msg = g_static_private_get (&msg_private);
++ if (!msg)
++ {
++ msg = g_new (gchar, 64);
++ g_static_private_set (&msg_private, msg, g_free);
++ }
++
++ sprintf (msg, "unknown signal (%d)", signum);
++
++ return msg;
++#else
++ return "unknown error";
++#endif /* !__KORBIT__ */
++}
++
++guint
++g_printf_string_upper_bound (const gchar* format,
++ va_list args)
++{
++ guint len = 1;
++
++ while (*format)
++ {
++ gboolean long_int = FALSE;
++ gboolean extra_long = FALSE;
++ gchar c;
++
++ c = *format++;
++
++ if (c == '%')
++ {
++ gboolean done = FALSE;
++
++ while (*format && !done)
++ {
++ switch (*format++)
++ {
++ gchar *string_arg;
++
++ case '*':
++ len += va_arg (args, int);
++ break;
++ case '1':
++ case '2':
++ case '3':
++ case '4':
++ case '5':
++ case '6':
++ case '7':
++ case '8':
++ case '9':
++ /* add specified format length, since it might exceed the
++ * size we assume it to have.
++ */
++ format -= 1;
++ len += strtol (format, (char**) &format, 10);
++ break;
++ case 'h':
++ /* ignore short int flag, since all args have at least the
++ * same size as an int
++ */
++ break;
++ case 'l':
++ if (long_int)
++ extra_long = TRUE; /* linux specific */
++ else
++ long_int = TRUE;
++ break;
++ case 'q':
++ case 'L':
++ long_int = TRUE;
++ extra_long = TRUE;
++ break;
++ case 's':
++ string_arg = va_arg (args, char *);
++ if (string_arg)
++ len += strlen (string_arg);
++ else
++ {
++ /* add enough padding to hold "(null)" identifier */
++ len += 16;
++ }
++ done = TRUE;
++ break;
++ case 'd':
++ case 'i':
++ case 'o':
++ case 'u':
++ case 'x':
++ case 'X':
++#ifdef G_HAVE_GINT64
++ if (extra_long)
++ (void) va_arg (args, gint64);
++ else
++#endif /* G_HAVE_GINT64 */
++ {
++ if (long_int)
++ (void) va_arg (args, long);
++ else
++ (void) va_arg (args, int);
++ }
++ len += extra_long ? 64 : 32;
++ done = TRUE;
++ break;
++ case 'D':
++ case 'O':
++ case 'U':
++ (void) va_arg (args, long);
++ len += 32;
++ done = TRUE;
++ break;
++ case 'e':
++ case 'E':
++ case 'f':
++ case 'g':
++#ifdef HAVE_LONG_DOUBLE
++ if (extra_long)
++ (void) va_arg (args, long double);
++ else
++#endif /* HAVE_LONG_DOUBLE */
++ (void) va_arg (args, double);
++ len += extra_long ? 128 : 64;
++ done = TRUE;
++ break;
++ case 'c':
++ (void) va_arg (args, int);
++ len += 1;
++ done = TRUE;
++ break;
++ case 'p':
++ case 'n':
++ (void) va_arg (args, void*);
++ len += 32;
++ done = TRUE;
++ break;
++ case '%':
++ len += 1;
++ done = TRUE;
++ break;
++ default:
++ /* ignore unknow/invalid flags */
++ break;
++ }
++ }
++ }
++ else
++ len += 1;
++ }
++
++ return len;
++}
++
++void
++g_strdown (gchar *string)
++{
++ register guchar *s;
++
++ g_return_if_fail (string != NULL);
++
++ s = string;
++
++ while (*s)
++ {
++ *s = tolower (*s);
++ s++;
++ }
++}
++
++void
++g_strup (gchar *string)
++{
++ register guchar *s;
++
++ g_return_if_fail (string != NULL);
++
++ s = string;
++
++ while (*s)
++ {
++ *s = toupper (*s);
++ s++;
++ }
++}
++
++void
++g_strreverse (gchar *string)
++{
++ g_return_if_fail (string != NULL);
++
++ if (*string)
++ {
++ register gchar *h, *t;
++
++ h = string;
++ t = string + strlen (string) - 1;
++
++ while (h < t)
++ {
++ register gchar c;
++
++ c = *h;
++ *h = *t;
++ h++;
++ *t = c;
++ t--;
++ }
++ }
++}
++
++gint
++g_strcasecmp (const gchar *s1,
++ const gchar *s2)
++{
++#ifdef HAVE_STRCASECMP
++ g_return_val_if_fail (s1 != NULL, 0);
++ g_return_val_if_fail (s2 != NULL, 0);
++
++ return strcasecmp (s1, s2);
++#else
++ gint c1, c2;
++
++ g_return_val_if_fail (s1 != NULL, 0);
++ g_return_val_if_fail (s2 != NULL, 0);
++
++ while (*s1 && *s2)
++ {
++ /* According to A. Cox, some platforms have islower's that
++ * don't work right on non-uppercase
++ */
++ c1 = isupper ((guchar)*s1) ? tolower ((guchar)*s1) : *s1;
++ c2 = isupper ((guchar)*s2) ? tolower ((guchar)*s2) : *s2;
++ if (c1 != c2)
++ return (c1 - c2);
++ s1++; s2++;
++ }
++
++ return (((gint)(guchar) *s1) - ((gint)(guchar) *s2));
++#endif
++}
++
++gint
++g_strncasecmp (const gchar *s1,
++ const gchar *s2,
++ guint n)
++{
++#ifdef HAVE_STRNCASECMP
++ return strncasecmp (s1, s2, n);
++#else
++ gint c1, c2;
++
++ g_return_val_if_fail (s1 != NULL, 0);
++ g_return_val_if_fail (s2 != NULL, 0);
++
++ while (n-- && *s1 && *s2)
++ {
++ /* According to A. Cox, some platforms have islower's that
++ * don't work right on non-uppercase
++ */
++ c1 = isupper ((guchar)*s1) ? tolower ((guchar)*s1) : *s1;
++ c2 = isupper ((guchar)*s2) ? tolower ((guchar)*s2) : *s2;
++ if (c1 != c2)
++ return (c1 - c2);
++ s1++; s2++;
++ }
++
++ if (n)
++ return (((gint)(guchar) *s1) - ((gint)(guchar) *s2));
++ else
++ return 0;
++#endif
++}
++
++gchar*
++g_strdelimit (gchar *string,
++ const gchar *delimiters,
++ gchar new_delim)
++{
++ register gchar *c;
++
++ g_return_val_if_fail (string != NULL, NULL);
++
++ if (!delimiters)
++ delimiters = G_STR_DELIMITERS;
++
++ for (c = string; *c; c++)
++ {
++ if (strchr (delimiters, *c))
++ *c = new_delim;
++ }
++
++ return string;
++}
++
++gchar*
++g_strescape (gchar *string)
++{
++ gchar *q;
++ gchar *escaped;
++ guint backslashes = 0;
++ gchar *p = string;
++
++ g_return_val_if_fail (string != NULL, NULL);
++
++ while (*p != '\000')
++ backslashes += (*p++ == '\\');
++
++ if (!backslashes)
++ return g_strdup (string);
++
++ escaped = g_new (gchar, strlen (string) + backslashes + 1);
++
++ p = string;
++ q = escaped;
++
++ while (*p != '\000')
++ {
++ if (*p == '\\')
++ *q++ = '\\';
++ *q++ = *p++;
++ }
++ *q = '\000';
++
++ return escaped;
++}
++
++/* blame Elliot for these next five routines */
++gchar*
++g_strchug (gchar *string)
++{
++ guchar *start;
++
++ g_return_val_if_fail (string != NULL, NULL);
++
++ for (start = string; *start && isspace (*start); start++)
++ ;
++
++ g_memmove(string, start, strlen(start) + 1);
++
++ return string;
++}
++
++gchar*
++g_strchomp (gchar *string)
++{
++ gchar *s;
++
++ g_return_val_if_fail (string != NULL, NULL);
++
++ if (!*string)
++ return string;
++
++ for (s = string + strlen (string) - 1; s >= string && isspace ((guchar)*s);
++ s--)
++ *s = '\0';
++
++ return string;
++}
++
++gchar**
++g_strsplit (const gchar *string,
++ const gchar *delimiter,
++ gint max_tokens)
++{
++ GSList *string_list = NULL, *slist;
++ gchar **str_array, *s;
++ guint i, n = 1;
++
++ g_return_val_if_fail (string != NULL, NULL);
++ g_return_val_if_fail (delimiter != NULL, NULL);
++
++ if (max_tokens < 1)
++ max_tokens = G_MAXINT;
++
++ s = strstr (string, delimiter);
++ if (s)
++ {
++ guint delimiter_len = strlen (delimiter);
++
++ do
++ {
++ guint len;
++ gchar *new_string;
++
++ len = s - string;
++ new_string = g_new (gchar, len + 1);
++ strncpy (new_string, string, len);
++ new_string[len] = 0;
++ string_list = g_slist_prepend (string_list, new_string);
++ n++;
++ string = s + delimiter_len;
++ s = strstr (string, delimiter);
++ }
++ while (--max_tokens && s);
++ }
++ if (*string)
++ {
++ n++;
++ string_list = g_slist_prepend (string_list, g_strdup (string));
++ }
++
++ str_array = g_new (gchar*, n);
++
++ i = n - 1;
++
++ str_array[i--] = NULL;
++ for (slist = string_list; slist; slist = slist->next)
++ str_array[i--] = slist->data;
++
++ g_slist_free (string_list);
++
++ return str_array;
++}
++
++void
++g_strfreev (gchar **str_array)
++{
++ if (str_array)
++ {
++ int i;
++
++ for(i = 0; str_array[i] != NULL; i++)
++ g_free(str_array[i]);
++
++ g_free (str_array);
++ }
++}
++
++gchar*
++g_strjoinv (const gchar *separator,
++ gchar **str_array)
++{
++ gchar *string;
++
++ g_return_val_if_fail (str_array != NULL, NULL);
++
++ if (separator == NULL)
++ separator = "";
++
++ if (*str_array)
++ {
++ guint i, len;
++ guint separator_len;
++
++ separator_len = strlen (separator);
++ len = 1 + strlen (str_array[0]);
++ for(i = 1; str_array[i] != NULL; i++)
++ len += separator_len + strlen(str_array[i]);
++
++ string = g_new (gchar, len);
++ *string = 0;
++ strcat (string, *str_array);
++ for (i = 1; str_array[i] != NULL; i++)
++ {
++ strcat (string, separator);
++ strcat (string, str_array[i]);
++ }
++ }
++ else
++ string = g_strdup ("");
++
++ return string;
++}
++
++gchar*
++g_strjoin (const gchar *separator,
++ ...)
++{
++ gchar *string, *s;
++ va_list args;
++ guint len;
++ guint separator_len;
++
++ if (separator == NULL)
++ separator = "";
++
++ separator_len = strlen (separator);
++
++ va_start (args, separator);
++
++ s = va_arg (args, gchar*);
++
++ if (s)
++ {
++ len = strlen (s);
++
++ s = va_arg (args, gchar*);
++ while (s)
++ {
++ len += separator_len + strlen (s);
++ s = va_arg (args, gchar*);
++ }
++ va_end (args);
++
++ string = g_new (gchar, len + 1);
++ *string = 0;
++
++ va_start (args, separator);
++
++ s = va_arg (args, gchar*);
++ strcat (string, s);
++
++ s = va_arg (args, gchar*);
++ while (s)
++ {
++ strcat (string, separator);
++ strcat (string, s);
++ s = va_arg (args, gchar*);
++ }
++ }
++ else
++ string = g_strdup ("");
++
++ va_end (args);
++
++ return string;
++}
+diff -urN linux-2.4.1/net/korbit/kglib/gstring.c linux-2.4.1-korbit/net/korbit/kglib/gstring.c
+--- linux-2.4.1/net/korbit/kglib/gstring.c Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/kglib/gstring.c Thu Feb 1 11:46:57 2001
+@@ -0,0 +1,508 @@
++/* GLIB - Library of useful routines for C programming
++ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Library General Public
++ * License as published by the Free Software Foundation; either
++ * version 2 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Library General Public License for more details.
++ *
++ * You should have received a copy of the GNU Library General Public
++ * License along with this library; if not, write to the
++ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
++ * Boston, MA 02111-1307, USA.
++ */
++
++/*
++ * Modified by the GLib Team and others 1997-1999. See the AUTHORS
++ * file for a list of people on the GLib Team. See the ChangeLog
++ * files for a list of changes. These files are distributed with
++ * GLib at ftp://ftp.gtk.org/pub/gtk/.
++ */
++
++#include <stdarg.h>
++#include <stdlib.h>
++#include <stdio.h>
++#include <string.h>
++#include <ctype.h>
++#include "glib.h"
++
++
++typedef struct _GRealStringChunk GRealStringChunk;
++typedef struct _GRealString GRealString;
++
++struct _GRealStringChunk
++{
++ GHashTable *const_table;
++ GSList *storage_list;
++ gint storage_next;
++ gint this_size;
++ gint default_size;
++};
++
++struct _GRealString
++{
++ gchar *str;
++ gint len;
++ gint alloc;
++};
++
++G_LOCK_DEFINE_STATIC (string_mem_chunk);
++static GMemChunk *string_mem_chunk = NULL;
++
++/* Hash Functions.
++ */
++
++gint
++g_str_equal (gconstpointer v, gconstpointer v2)
++{
++ return strcmp ((const gchar*) v, (const gchar*)v2) == 0;
++}
++
++/* 31 bit hash function */
++guint
++g_str_hash (gconstpointer key)
++{
++ const char *p = key;
++ guint h = *p;
++
++ if (h)
++ for (p += 1; *p != '\0'; p++)
++ h = (h << 5) - h + *p;
++
++ return h;
++}
++
++/* String Chunks.
++ */
++
++GStringChunk*
++g_string_chunk_new (gint default_size)
++{
++ GRealStringChunk *new_chunk = g_new (GRealStringChunk, 1);
++ gint size = 1;
++
++ while (size < default_size)
++ size <<= 1;
++
++ new_chunk->const_table = NULL;
++ new_chunk->storage_list = NULL;
++ new_chunk->storage_next = size;
++ new_chunk->default_size = size;
++ new_chunk->this_size = size;
++
++ return (GStringChunk*) new_chunk;
++}
++
++void
++g_string_chunk_free (GStringChunk *fchunk)
++{
++ GRealStringChunk *chunk = (GRealStringChunk*) fchunk;
++ GSList *tmp_list;
++
++ g_return_if_fail (chunk != NULL);
++
++ if (chunk->storage_list)
++ {
++ for (tmp_list = chunk->storage_list; tmp_list; tmp_list = tmp_list->next)
++ g_free (tmp_list->data);
++
++ g_slist_free (chunk->storage_list);
++ }
++
++ if (chunk->const_table)
++ g_hash_table_destroy (chunk->const_table);
++
++ g_free (chunk);
++}
++
++gchar*
++g_string_chunk_insert (GStringChunk *fchunk,
++ const gchar *string)
++{
++ GRealStringChunk *chunk = (GRealStringChunk*) fchunk;
++ gint len = strlen (string);
++ char* pos;
++
++ g_return_val_if_fail (chunk != NULL, NULL);
++
++ if ((chunk->storage_next + len + 1) > chunk->this_size)
++ {
++ gint new_size = chunk->default_size;
++
++ while (new_size < len+1)
++ new_size <<= 1;
++
++ chunk->storage_list = g_slist_prepend (chunk->storage_list,
++ g_new (char, new_size));
++
++ chunk->this_size = new_size;
++ chunk->storage_next = 0;
++ }
++
++ pos = ((char*)chunk->storage_list->data) + chunk->storage_next;
++
++ strcpy (pos, string);
++
++ chunk->storage_next += len + 1;
++
++ return pos;
++}
++
++gchar*
++g_string_chunk_insert_const (GStringChunk *fchunk,
++ const gchar *string)
++{
++ GRealStringChunk *chunk = (GRealStringChunk*) fchunk;
++ char* lookup;
++
++ g_return_val_if_fail (chunk != NULL, NULL);
++
++ if (!chunk->const_table)
++ chunk->const_table = g_hash_table_new (g_str_hash, g_str_equal);
++
++ lookup = (char*) g_hash_table_lookup (chunk->const_table, (gchar *)string);
++
++ if (!lookup)
++ {
++ lookup = g_string_chunk_insert (fchunk, string);
++ g_hash_table_insert (chunk->const_table, lookup, lookup);
++ }
++
++ return lookup;
++}
++
++/* Strings.
++ */
++static gint
++nearest_pow (gint num)
++{
++ gint n = 1;
++
++ while (n < num)
++ n <<= 1;
++
++ return n;
++}
++
++static void
++g_string_maybe_expand (GRealString* string, gint len)
++{
++ if (string->len + len >= string->alloc)
++ {
++ string->alloc = nearest_pow (string->len + len + 1);
++ string->str = g_realloc (string->str, string->alloc);
++ }
++}
++
++GString*
++g_string_sized_new (guint dfl_size)
++{
++ GRealString *string;
++
++ G_LOCK (string_mem_chunk);
++ if (!string_mem_chunk)
++ string_mem_chunk = g_mem_chunk_new ("string mem chunk",
++ sizeof (GRealString),
++ 1024, G_ALLOC_AND_FREE);
++
++ string = g_chunk_new (GRealString, string_mem_chunk);
++ G_UNLOCK (string_mem_chunk);
++
++ string->alloc = 0;
++ string->len = 0;
++ string->str = NULL;
++
++ g_string_maybe_expand (string, MAX (dfl_size, 2));
++ string->str[0] = 0;
++
++ return (GString*) string;
++}
++
++GString*
++g_string_new (const gchar *init)
++{
++ GString *string;
++
++ string = g_string_sized_new (2);
++
++ if (init)
++ g_string_append (string, init);
++
++ return string;
++}
++
++void
++g_string_free (GString *string,
++ gint free_segment)
++{
++ g_return_if_fail (string != NULL);
++
++ if (free_segment)
++ g_free (string->str);
++
++ G_LOCK (string_mem_chunk);
++ g_mem_chunk_free (string_mem_chunk, string);
++ G_UNLOCK (string_mem_chunk);
++}
++
++GString*
++g_string_assign (GString *lval,
++ const gchar *rval)
++{
++ g_return_val_if_fail (lval != NULL, NULL);
++ g_return_val_if_fail (rval != NULL, NULL);
++
++ g_string_truncate (lval, 0);
++ g_string_append (lval, rval);
++
++ return lval;
++}
++
++GString*
++g_string_truncate (GString* fstring,
++ gint len)
++{
++ GRealString *string = (GRealString*)fstring;
++
++ g_return_val_if_fail (string != NULL, NULL);
++ g_return_val_if_fail (len >= 0, NULL);
++
++ string->len = len;
++
++ string->str[len] = 0;
++
++ return fstring;
++}
++
++GString*
++g_string_append (GString *fstring,
++ const gchar *val)
++{
++ GRealString *string = (GRealString*)fstring;
++ int len;
++
++ g_return_val_if_fail (string != NULL, NULL);
++ g_return_val_if_fail (val != NULL, fstring);
++
++ len = strlen (val);
++ g_string_maybe_expand (string, len);
++
++ strcpy (string->str + string->len, val);
++
++ string->len += len;
++
++ return fstring;
++}
++
++GString*
++g_string_append_c (GString *fstring,
++ gchar c)
++{
++ GRealString *string = (GRealString*)fstring;
++
++ g_return_val_if_fail (string != NULL, NULL);
++ g_string_maybe_expand (string, 1);
++
++ string->str[string->len++] = c;
++ string->str[string->len] = 0;
++
++ return fstring;
++}
++
++GString*
++g_string_prepend (GString *fstring,
++ const gchar *val)
++{
++ GRealString *string = (GRealString*)fstring;
++ gint len;
++
++ g_return_val_if_fail (string != NULL, NULL);
++ g_return_val_if_fail (val != NULL, fstring);
++
++ len = strlen (val);
++ g_string_maybe_expand (string, len);
++
++ g_memmove (string->str + len, string->str, string->len);
++
++ strncpy (string->str, val, len);
++
++ string->len += len;
++
++ string->str[string->len] = 0;
++
++ return fstring;
++}
++
++GString*
++g_string_prepend_c (GString *fstring,
++ gchar c)
++{
++ GRealString *string = (GRealString*)fstring;
++
++ g_return_val_if_fail (string != NULL, NULL);
++ g_string_maybe_expand (string, 1);
++
++ g_memmove (string->str + 1, string->str, string->len);
++
++ string->str[0] = c;
++
++ string->len += 1;
++
++ string->str[string->len] = 0;
++
++ return fstring;
++}
++
++GString*
++g_string_insert (GString *fstring,
++ gint pos,
++ const gchar *val)
++{
++ GRealString *string = (GRealString*)fstring;
++ gint len;
++
++ g_return_val_if_fail (string != NULL, NULL);
++ g_return_val_if_fail (val != NULL, fstring);
++ g_return_val_if_fail (pos >= 0, fstring);
++ g_return_val_if_fail (pos <= string->len, fstring);
++
++ len = strlen (val);
++ g_string_maybe_expand (string, len);
++
++ g_memmove (string->str + pos + len, string->str + pos, string->len - pos);
++
++ strncpy (string->str + pos, val, len);
++
++ string->len += len;
++
++ string->str[string->len] = 0;
++
++ return fstring;
++}
++
++GString *
++g_string_insert_c (GString *fstring,
++ gint pos,
++ gchar c)
++{
++ GRealString *string = (GRealString*)fstring;
++
++ g_return_val_if_fail (string != NULL, NULL);
++ g_return_val_if_fail (pos <= string->len, fstring);
++
++ g_string_maybe_expand (string, 1);
++
++ g_memmove (string->str + pos + 1, string->str + pos, string->len - pos);
++
++ string->str[pos] = c;
++
++ string->len += 1;
++
++ string->str[string->len] = 0;
++
++ return fstring;
++}
++
++GString*
++g_string_erase (GString *fstring,
++ gint pos,
++ gint len)
++{
++ GRealString *string = (GRealString*)fstring;
++
++ g_return_val_if_fail (string != NULL, NULL);
++ g_return_val_if_fail (len >= 0, fstring);
++ g_return_val_if_fail (pos >= 0, fstring);
++ g_return_val_if_fail (pos <= string->len, fstring);
++ g_return_val_if_fail (pos + len <= string->len, fstring);
++
++ if (pos + len < string->len)
++ g_memmove (string->str + pos, string->str + pos + len, string->len - (pos + len));
++
++ string->len -= len;
++
++ string->str[string->len] = 0;
++
++ return fstring;
++}
++
++GString*
++g_string_down (GString *fstring)
++{
++ GRealString *string = (GRealString*)fstring;
++ guchar *s;
++
++ g_return_val_if_fail (string != NULL, NULL);
++
++ s = string->str;
++
++ while (*s)
++ {
++ *s = tolower (*s);
++ s++;
++ }
++
++ return fstring;
++}
++
++GString*
++g_string_up (GString *fstring)
++{
++ GRealString *string = (GRealString*)fstring;
++ guchar *s;
++
++ g_return_val_if_fail (string != NULL, NULL);
++
++ s = string->str;
++
++ while (*s)
++ {
++ *s = toupper (*s);
++ s++;
++ }
++
++ return fstring;
++}
++
++static void
++g_string_sprintfa_int (GString *string,
++ const gchar *fmt,
++ va_list args)
++{
++ gchar *buffer;
++
++ buffer = g_strdup_vprintf (fmt, args);
++ g_string_append (string, buffer);
++ g_free (buffer);
++}
++
++void
++g_string_sprintf (GString *string,
++ const gchar *fmt,
++ ...)
++{
++ va_list args;
++
++ g_string_truncate (string, 0);
++
++ va_start (args, fmt);
++ g_string_sprintfa_int (string, fmt, args);
++ va_end (args);
++}
++
++void
++g_string_sprintfa (GString *string,
++ const gchar *fmt,
++ ...)
++{
++ va_list args;
++
++ va_start (args, fmt);
++ g_string_sprintfa_int (string, fmt, args);
++ va_end (args);
++}
+diff -urN linux-2.4.1/net/korbit/kglib/gtree.c linux-2.4.1-korbit/net/korbit/kglib/gtree.c
+--- linux-2.4.1/net/korbit/kglib/gtree.c Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/kglib/gtree.c Thu Feb 1 11:46:57 2001
+@@ -0,0 +1,740 @@
++/* GLIB - Library of useful routines for C programming
++ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Library General Public
++ * License as published by the Free Software Foundation; either
++ * version 2 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Library General Public License for more details.
++ *
++ * You should have received a copy of the GNU Library General Public
++ * License along with this library; if not, write to the
++ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
++ * Boston, MA 02111-1307, USA.
++ */
++
++/*
++ * Modified by the GLib Team and others 1997-1999. See the AUTHORS
++ * file for a list of people on the GLib Team. See the ChangeLog
++ * files for a list of changes. These files are distributed with
++ * GLib at ftp://ftp.gtk.org/pub/gtk/.
++ */
++
++#include "glib.h"
++
++
++typedef struct _GRealTree GRealTree;
++typedef struct _GTreeNode GTreeNode;
++
++struct _GRealTree
++{
++ GTreeNode *root;
++ GCompareFunc key_compare;
++};
++
++struct _GTreeNode
++{
++ gint balance; /* height (left) - height (right) */
++ GTreeNode *left; /* left subtree */
++ GTreeNode *right; /* right subtree */
++ gpointer key; /* key for this node */
++ gpointer value; /* value stored at this node */
++};
++
++
++static GTreeNode* g_tree_node_new (gpointer key,
++ gpointer value);
++static void g_tree_node_destroy (GTreeNode *node);
++static GTreeNode* g_tree_node_insert (GTreeNode *node,
++ GCompareFunc compare,
++ gpointer key,
++ gpointer value,
++ gint *inserted);
++static GTreeNode* g_tree_node_remove (GTreeNode *node,
++ GCompareFunc compare,
++ gpointer key);
++static GTreeNode* g_tree_node_balance (GTreeNode *node);
++static GTreeNode* g_tree_node_remove_leftmost (GTreeNode *node,
++ GTreeNode **leftmost);
++static GTreeNode* g_tree_node_restore_left_balance (GTreeNode *node,
++ gint old_balance);
++static GTreeNode* g_tree_node_restore_right_balance (GTreeNode *node,
++ gint old_balance);
++static gpointer g_tree_node_lookup (GTreeNode *node,
++ GCompareFunc compare,
++ gpointer key);
++static gint g_tree_node_count (GTreeNode *node);
++static gint g_tree_node_pre_order (GTreeNode *node,
++ GTraverseFunc traverse_func,
++ gpointer data);
++static gint g_tree_node_in_order (GTreeNode *node,
++ GTraverseFunc traverse_func,
++ gpointer data);
++static gint g_tree_node_post_order (GTreeNode *node,
++ GTraverseFunc traverse_func,
++ gpointer data);
++static gpointer g_tree_node_search (GTreeNode *node,
++ GSearchFunc search_func,
++ gpointer data);
++static gint g_tree_node_height (GTreeNode *node);
++static GTreeNode* g_tree_node_rotate_left (GTreeNode *node);
++static GTreeNode* g_tree_node_rotate_right (GTreeNode *node);
++static void g_tree_node_check (GTreeNode *node);
++
++
++G_LOCK_DEFINE_STATIC (g_tree_global);
++static GMemChunk *node_mem_chunk = NULL;
++static GTreeNode *node_free_list = NULL;
++
++
++static GTreeNode*
++g_tree_node_new (gpointer key,
++ gpointer value)
++{
++ GTreeNode *node;
++
++ G_LOCK (g_tree_global);
++ if (node_free_list)
++ {
++ node = node_free_list;
++ node_free_list = node->right;
++ }
++ else
++ {
++ if (!node_mem_chunk)
++ node_mem_chunk = g_mem_chunk_new ("GLib GTreeNode mem chunk",
++ sizeof (GTreeNode),
++ 1024,
++ G_ALLOC_ONLY);
++
++ node = g_chunk_new (GTreeNode, node_mem_chunk);
++ }
++ G_UNLOCK (g_tree_global);
++
++ node->balance = 0;
++ node->left = NULL;
++ node->right = NULL;
++ node->key = key;
++ node->value = value;
++
++ return node;
++}
++
++static void
++g_tree_node_destroy (GTreeNode *node)
++{
++ if (node)
++ {
++ g_tree_node_destroy (node->right);
++ g_tree_node_destroy (node->left);
++ G_LOCK (g_tree_global);
++ node->right = node_free_list;
++ node_free_list = node;
++ G_UNLOCK (g_tree_global);
++ }
++}
++
++
++GTree*
++g_tree_new (GCompareFunc key_compare_func)
++{
++ GRealTree *rtree;
++
++ g_return_val_if_fail (key_compare_func != NULL, NULL);
++
++ rtree = g_new (GRealTree, 1);
++ rtree->root = NULL;
++ rtree->key_compare = key_compare_func;
++
++ return (GTree*) rtree;
++}
++
++void
++g_tree_destroy (GTree *tree)
++{
++ GRealTree *rtree;
++
++ g_return_if_fail (tree != NULL);
++
++ rtree = (GRealTree*) tree;
++
++ g_tree_node_destroy (rtree->root);
++ g_free (rtree);
++}
++
++void
++g_tree_insert (GTree *tree,
++ gpointer key,
++ gpointer value)
++{
++ GRealTree *rtree;
++ gint inserted;
++
++ g_return_if_fail (tree != NULL);
++
++ rtree = (GRealTree*) tree;
++
++ inserted = FALSE;
++ rtree->root = g_tree_node_insert (rtree->root, rtree->key_compare,
++ key, value, &inserted);
++}
++
++void
++g_tree_remove (GTree *tree,
++ gpointer key)
++{
++ GRealTree *rtree;
++
++ g_return_if_fail (tree != NULL);
++
++ rtree = (GRealTree*) tree;
++
++ rtree->root = g_tree_node_remove (rtree->root, rtree->key_compare, key);
++}
++
++gpointer
++g_tree_lookup (GTree *tree,
++ gpointer key)
++{
++ GRealTree *rtree;
++
++ g_return_val_if_fail (tree != NULL, NULL);
++
++ rtree = (GRealTree*) tree;
++
++ return g_tree_node_lookup (rtree->root, rtree->key_compare, key);
++}
++
++void
++g_tree_traverse (GTree *tree,
++ GTraverseFunc traverse_func,
++ GTraverseType traverse_type,
++ gpointer data)
++{
++ GRealTree *rtree;
++
++ g_return_if_fail (tree != NULL);
++
++ rtree = (GRealTree*) tree;
++
++ if (!rtree->root)
++ return;
++
++ switch (traverse_type)
++ {
++ case G_PRE_ORDER:
++ g_tree_node_pre_order (rtree->root, traverse_func, data);
++ break;
++
++ case G_IN_ORDER:
++ g_tree_node_in_order (rtree->root, traverse_func, data);
++ break;
++
++ case G_POST_ORDER:
++ g_tree_node_post_order (rtree->root, traverse_func, data);
++ break;
++
++ case G_LEVEL_ORDER:
++ g_warning ("g_tree_traverse(): traverse type G_LEVEL_ORDER isn't implemented.");
++ break;
++ }
++}
++
++gpointer
++g_tree_search (GTree *tree,
++ GSearchFunc search_func,
++ gpointer data)
++{
++ GRealTree *rtree;
++
++ g_return_val_if_fail (tree != NULL, NULL);
++
++ rtree = (GRealTree*) tree;
++
++ if (rtree->root)
++ return g_tree_node_search (rtree->root, search_func, data);
++ else
++ return NULL;
++}
++
++gint
++g_tree_height (GTree *tree)
++{
++ GRealTree *rtree;
++
++ g_return_val_if_fail (tree != NULL, 0);
++
++ rtree = (GRealTree*) tree;
++
++ if (rtree->root)
++ return g_tree_node_height (rtree->root);
++ else
++ return 0;
++}
++
++gint
++g_tree_nnodes (GTree *tree)
++{
++ GRealTree *rtree;
++
++ g_return_val_if_fail (tree != NULL, 0);
++
++ rtree = (GRealTree*) tree;
++
++ if (rtree->root)
++ return g_tree_node_count (rtree->root);
++ else
++ return 0;
++}
++
++static GTreeNode*
++g_tree_node_insert (GTreeNode *node,
++ GCompareFunc compare,
++ gpointer key,
++ gpointer value,
++ gint *inserted)
++{
++ gint old_balance;
++ gint cmp;
++
++ if (!node)
++ {
++ *inserted = TRUE;
++ return g_tree_node_new (key, value);
++ }
++
++ cmp = (* compare) (key, node->key);
++ if (cmp == 0)
++ {
++ *inserted = FALSE;
++ node->value = value;
++ return node;
++ }
++
++ if (cmp < 0)
++ {
++ if (node->left)
++ {
++ old_balance = node->left->balance;
++ node->left = g_tree_node_insert (node->left, compare, key, value, inserted);
++
++ if ((old_balance != node->left->balance) && node->left->balance)
++ node->balance -= 1;
++ }
++ else
++ {
++ *inserted = TRUE;
++ node->left = g_tree_node_new (key, value);
++ node->balance -= 1;
++ }
++ }
++ else if (cmp > 0)
++ {
++ if (node->right)
++ {
++ old_balance = node->right->balance;
++ node->right = g_tree_node_insert (node->right, compare, key, value, inserted);
++
++ if ((old_balance != node->right->balance) && node->right->balance)
++ node->balance += 1;
++ }
++ else
++ {
++ *inserted = TRUE;
++ node->right = g_tree_node_new (key, value);
++ node->balance += 1;
++ }
++ }
++
++ if (*inserted)
++ {
++ if ((node->balance < -1) || (node->balance > 1))
++ node = g_tree_node_balance (node);
++ }
++
++ return node;
++}
++
++static GTreeNode*
++g_tree_node_remove (GTreeNode *node,
++ GCompareFunc compare,
++ gpointer key)
++{
++ GTreeNode *new_root;
++ gint old_balance;
++ gint cmp;
++
++ if (!node)
++ return NULL;
++
++ cmp = (* compare) (key, node->key);
++ if (cmp == 0)
++ {
++ GTreeNode *garbage;
++
++ garbage = node;
++
++ if (!node->right)
++ {
++ node = node->left;
++ }
++ else
++ {
++ old_balance = node->right->balance;
++ node->right = g_tree_node_remove_leftmost (node->right, &new_root);
++ new_root->left = node->left;
++ new_root->right = node->right;
++ new_root->balance = node->balance;
++ node = g_tree_node_restore_right_balance (new_root, old_balance);
++ }
++
++ G_LOCK (g_tree_global);
++ garbage->right = node_free_list;
++ node_free_list = garbage;
++ G_UNLOCK (g_tree_global);
++ }
++ else if (cmp < 0)
++ {
++ if (node->left)
++ {
++ old_balance = node->left->balance;
++ node->left = g_tree_node_remove (node->left, compare, key);
++ node = g_tree_node_restore_left_balance (node, old_balance);
++ }
++ }
++ else if (cmp > 0)
++ {
++ if (node->right)
++ {
++ old_balance = node->right->balance;
++ node->right = g_tree_node_remove (node->right, compare, key);
++ node = g_tree_node_restore_right_balance (node, old_balance);
++ }
++ }
++
++ return node;
++}
++
++static GTreeNode*
++g_tree_node_balance (GTreeNode *node)
++{
++ if (node->balance < -1)
++ {
++ if (node->left->balance > 0)
++ node->left = g_tree_node_rotate_left (node->left);
++ node = g_tree_node_rotate_right (node);
++ }
++ else if (node->balance > 1)
++ {
++ if (node->right->balance < 0)
++ node->right = g_tree_node_rotate_right (node->right);
++ node = g_tree_node_rotate_left (node);
++ }
++
++ return node;
++}
++
++static GTreeNode*
++g_tree_node_remove_leftmost (GTreeNode *node,
++ GTreeNode **leftmost)
++{
++ gint old_balance;
++
++ if (!node->left)
++ {
++ *leftmost = node;
++ return node->right;
++ }
++
++ old_balance = node->left->balance;
++ node->left = g_tree_node_remove_leftmost (node->left, leftmost);
++ return g_tree_node_restore_left_balance (node, old_balance);
++}
++
++static GTreeNode*
++g_tree_node_restore_left_balance (GTreeNode *node,
++ gint old_balance)
++{
++ if (!node->left)
++ node->balance += 1;
++ else if ((node->left->balance != old_balance) &&
++ (node->left->balance == 0))
++ node->balance += 1;
++
++ if (node->balance > 1)
++ return g_tree_node_balance (node);
++ return node;
++}
++
++static GTreeNode*
++g_tree_node_restore_right_balance (GTreeNode *node,
++ gint old_balance)
++{
++ if (!node->right)
++ node->balance -= 1;
++ else if ((node->right->balance != old_balance) &&
++ (node->right->balance == 0))
++ node->balance -= 1;
++
++ if (node->balance < -1)
++ return g_tree_node_balance (node);
++ return node;
++}
++
++static gpointer
++g_tree_node_lookup (GTreeNode *node,
++ GCompareFunc compare,
++ gpointer key)
++{
++ gint cmp;
++
++ if (!node)
++ return NULL;
++
++ cmp = (* compare) (key, node->key);
++ if (cmp == 0)
++ return node->value;
++
++ if (cmp < 0)
++ {
++ if (node->left)
++ return g_tree_node_lookup (node->left, compare, key);
++ }
++ else if (cmp > 0)
++ {
++ if (node->right)
++ return g_tree_node_lookup (node->right, compare, key);
++ }
++
++ return NULL;
++}
++
++static gint
++g_tree_node_count (GTreeNode *node)
++{
++ gint count;
++
++ count = 1;
++ if (node->left)
++ count += g_tree_node_count (node->left);
++ if (node->right)
++ count += g_tree_node_count (node->right);
++
++ return count;
++}
++
++static gint
++g_tree_node_pre_order (GTreeNode *node,
++ GTraverseFunc traverse_func,
++ gpointer data)
++{
++ if ((*traverse_func) (node->key, node->value, data))
++ return TRUE;
++ if (node->left)
++ {
++ if (g_tree_node_pre_order (node->left, traverse_func, data))
++ return TRUE;
++ }
++ if (node->right)
++ {
++ if (g_tree_node_pre_order (node->right, traverse_func, data))
++ return TRUE;
++ }
++
++ return FALSE;
++}
++
++static gint
++g_tree_node_in_order (GTreeNode *node,
++ GTraverseFunc traverse_func,
++ gpointer data)
++{
++ if (node->left)
++ {
++ if (g_tree_node_in_order (node->left, traverse_func, data))
++ return TRUE;
++ }
++ if ((*traverse_func) (node->key, node->value, data))
++ return TRUE;
++ if (node->right)
++ {
++ if (g_tree_node_in_order (node->right, traverse_func, data))
++ return TRUE;
++ }
++
++ return FALSE;
++}
++
++static gint
++g_tree_node_post_order (GTreeNode *node,
++ GTraverseFunc traverse_func,
++ gpointer data)
++{
++ if (node->left)
++ {
++ if (g_tree_node_post_order (node->left, traverse_func, data))
++ return TRUE;
++ }
++ if (node->right)
++ {
++ if (g_tree_node_post_order (node->right, traverse_func, data))
++ return TRUE;
++ }
++ if ((*traverse_func) (node->key, node->value, data))
++ return TRUE;
++
++ return FALSE;
++}
++
++static gpointer
++g_tree_node_search (GTreeNode *node,
++ GSearchFunc search_func,
++ gpointer data)
++{
++ gint dir;
++
++ if (!node)
++ return NULL;
++
++ do {
++ dir = (* search_func) (node->key, data);
++ if (dir == 0)
++ return node->value;
++
++ if (dir < 0)
++ node = node->left;
++ else if (dir > 0)
++ node = node->right;
++ } while (node && (dir != 0));
++
++ return NULL;
++}
++
++static gint
++g_tree_node_height (GTreeNode *node)
++{
++ gint left_height;
++ gint right_height;
++
++ if (node)
++ {
++ left_height = 0;
++ right_height = 0;
++
++ if (node->left)
++ left_height = g_tree_node_height (node->left);
++
++ if (node->right)
++ right_height = g_tree_node_height (node->right);
++
++ return MAX (left_height, right_height) + 1;
++ }
++
++ return 0;
++}
++
++static GTreeNode*
++g_tree_node_rotate_left (GTreeNode *node)
++{
++ GTreeNode *left;
++ GTreeNode *right;
++ gint a_bal;
++ gint b_bal;
++
++ left = node->left;
++ right = node->right;
++
++ node->right = right->left;
++ right->left = node;
++
++ a_bal = node->balance;
++ b_bal = right->balance;
++
++ if (b_bal <= 0)
++ {
++ if (a_bal >= 1)
++ right->balance = b_bal - 1;
++ else
++ right->balance = a_bal + b_bal - 2;
++ node->balance = a_bal - 1;
++ }
++ else
++ {
++ if (a_bal <= b_bal)
++ right->balance = a_bal - 2;
++ else
++ right->balance = b_bal - 1;
++ node->balance = a_bal - b_bal - 1;
++ }
++
++ return right;
++}
++
++static GTreeNode*
++g_tree_node_rotate_right (GTreeNode *node)
++{
++ GTreeNode *left;
++ gint a_bal;
++ gint b_bal;
++
++ left = node->left;
++
++ node->left = left->right;
++ left->right = node;
++
++ a_bal = node->balance;
++ b_bal = left->balance;
++
++ if (b_bal <= 0)
++ {
++ if (b_bal > a_bal)
++ left->balance = b_bal + 1;
++ else
++ left->balance = a_bal + 2;
++ node->balance = a_bal - b_bal + 1;
++ }
++ else
++ {
++ if (a_bal <= -1)
++ left->balance = b_bal + 1;
++ else
++ left->balance = a_bal + b_bal + 2;
++ node->balance = a_bal + 1;
++ }
++
++ return left;
++}
++
++static void
++g_tree_node_check (GTreeNode *node)
++{
++ gint left_height;
++ gint right_height;
++ gint balance;
++
++ if (node)
++ {
++ left_height = 0;
++ right_height = 0;
++
++ if (node->left)
++ left_height = g_tree_node_height (node->left);
++ if (node->right)
++ right_height = g_tree_node_height (node->right);
++
++ balance = right_height - left_height;
++ if (balance != node->balance)
++ g_log (g_log_domain_glib, G_LOG_LEVEL_INFO,
++ "g_tree_node_check: failed: %d ( %d )\n",
++ balance, node->balance);
++
++ if (node->left)
++ g_tree_node_check (node->left);
++ if (node->right)
++ g_tree_node_check (node->right);
++ }
++}
+diff -urN linux-2.4.1/net/korbit/kglib/gutils.c linux-2.4.1-korbit/net/korbit/kglib/gutils.c
+--- linux-2.4.1/net/korbit/kglib/gutils.c Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/kglib/gutils.c Thu Feb 1 11:46:57 2001
+@@ -0,0 +1,915 @@
++/* GLIB - Library of useful routines for C programming
++ * Copyright (C) 1995-1998 Peter Mattis, Spencer Kimball and Josh MacDonald
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Library General Public
++ * License as published by the Free Software Foundation; either
++ * version 2 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Library General Public License for more details.
++ *
++ * You should have received a copy of the GNU Library General Public
++ * License along with this library; if not, write to the
++ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
++ * Boston, MA 02111-1307, USA.
++ */
++
++/*
++ * Modified by the GLib Team and others 1997-1999. See the AUTHORS
++ * file for a list of people on the GLib Team. See the ChangeLog
++ * files for a list of changes. These files are distributed with
++ * GLib at ftp://ftp.gtk.org/pub/gtk/.
++ */
++
++#define G_INLINE_FUNC extern
++#define G_CAN_INLINE 1
++
++#ifdef HAVE_UNISTD_H
++#include <unistd.h>
++#endif
++#include <stdarg.h>
++#include <stdlib.h>
++#include <stdio.h>
++#include <string.h>
++#include <errno.h>
++#ifdef HAVE_PWD_H
++#include <pwd.h>
++#endif
++#include <sys/types.h>
++#ifdef HAVE_SYS_PARAM_H
++#include <sys/param.h>
++#endif
++
++#ifdef NATIVE_WIN32
++# define STRICT /* Strict typing, please */
++# include <windows.h>
++# include <direct.h>
++# include <errno.h>
++# include <ctype.h>
++# ifdef _MSC_VER
++# include <io.h>
++# endif /* _MSC_VER */
++#endif /* NATIVE_WIN32 */
++
++/* implement Glib's inline functions
++ */
++#include "glib.h"
++
++#ifdef MAXPATHLEN
++#define G_PATH_LENGTH (MAXPATHLEN + 1)
++#elif defined (PATH_MAX)
++#define G_PATH_LENGTH (PATH_MAX + 1)
++#else /* !MAXPATHLEN */
++#define G_PATH_LENGTH (2048 + 1)
++#endif /* !MAXPATHLEN && !PATH_MAX */
++
++const guint glib_major_version = 1;
++const guint glib_minor_version = 2;
++const guint glib_micro_version = 8;
++const guint glib_interface_age = 8;
++const guint glib_binary_age = 8;
++
++#if defined (NATIVE_WIN32) && defined (__LCC__)
++int __stdcall
++LibMain (void *hinstDll,
++ unsigned long dwReason,
++ void *reserved)
++{
++ return 1;
++}
++#endif /* NATIVE_WIN32 && __LCC__ */
++
++void
++g_atexit (GVoidFunc func)
++{
++ gint result;
++ gchar *error = NULL;
++
++ /* keep this in sync with glib.h */
++
++#ifdef G_NATIVE_ATEXIT
++ result = ATEXIT (func);
++ if (result)
++ error = g_strerror (errno);
++#elif defined (HAVE_ATEXIT)
++# ifdef NeXT /* @#%@! NeXTStep */
++ result = !atexit ((void (*)(void)) func);
++ if (result)
++ error = g_strerror (errno);
++# else
++ result = atexit ((void (*)(void)) func);
++ if (result)
++ error = g_strerror (errno);
++# endif /* NeXT */
++#elif defined (HAVE_ON_EXIT)
++ result = on_exit ((void (*)(int, void *)) func, NULL);
++ if (result)
++ error = g_strerror (errno);
++#else
++ result = 0;
++ error = "no implementation";
++#endif /* G_NATIVE_ATEXIT */
++
++ if (error)
++ g_error ("Could not register atexit() function: %s", error);
++}
++
++gint
++g_snprintf (gchar *str,
++ gulong n,
++ gchar const *fmt,
++ ...)
++{
++#ifdef HAVE_VSNPRINTF
++ va_list args;
++ gint retval;
++
++ g_return_val_if_fail (str != NULL, 0);
++ g_return_val_if_fail (n > 0, 0);
++ g_return_val_if_fail (fmt != NULL, 0);
++
++ va_start (args, fmt);
++ retval = vsnprintf (str, n, fmt, args);
++ va_end (args);
++
++ if (retval < 0)
++ {
++ str[n-1] = '\0';
++ retval = strlen (str);
++ }
++
++ return retval;
++#else /* !HAVE_VSNPRINTF */
++ gchar *printed;
++ va_list args;
++
++ g_return_val_if_fail (str != NULL, 0);
++ g_return_val_if_fail (n > 0, 0);
++ g_return_val_if_fail (fmt != NULL, 0);
++
++ va_start (args, fmt);
++ printed = g_strdup_vprintf (fmt, args);
++ va_end (args);
++
++ strncpy (str, printed, n);
++ str[n-1] = '\0';
++
++ g_free (printed);
++
++ return strlen (str);
++#endif /* !HAVE_VSNPRINTF */
++}
++
++gint
++g_vsnprintf (gchar *str,
++ gulong n,
++ gchar const *fmt,
++ va_list args)
++{
++#ifdef HAVE_VSNPRINTF
++ gint retval;
++
++ g_return_val_if_fail (str != NULL, 0);
++ g_return_val_if_fail (n > 0, 0);
++ g_return_val_if_fail (fmt != NULL, 0);
++
++ retval = vsnprintf (str, n, fmt, args);
++
++ if (retval < 0)
++ {
++ str[n-1] = '\0';
++ retval = strlen (str);
++ }
++
++ return retval;
++#else /* !HAVE_VSNPRINTF */
++ gchar *printed;
++
++ g_return_val_if_fail (str != NULL, 0);
++ g_return_val_if_fail (n > 0, 0);
++ g_return_val_if_fail (fmt != NULL, 0);
++
++ printed = g_strdup_vprintf (fmt, args);
++ strncpy (str, printed, n);
++ str[n-1] = '\0';
++
++ g_free (printed);
++
++ return strlen (str);
++#endif /* !HAVE_VSNPRINTF */
++}
++
++guint
++g_parse_debug_string (const gchar *string,
++ GDebugKey *keys,
++ guint nkeys)
++{
++ guint i;
++ guint result = 0;
++
++ g_return_val_if_fail (string != NULL, 0);
++
++ if (!g_strcasecmp (string, "all"))
++ {
++ for (i=0; i<nkeys; i++)
++ result |= keys[i].value;
++ }
++ else
++ {
++ gchar *str = g_strdup (string);
++ gchar *p = str;
++ gchar *q;
++ gboolean done = FALSE;
++
++ while (*p && !done)
++ {
++ q = strchr (p, ':');
++ if (!q)
++ {
++ q = p + strlen(p);
++ done = TRUE;
++ }
++
++ *q = 0;
++
++ for (i=0; i<nkeys; i++)
++ if (!g_strcasecmp(keys[i].key, p))
++ result |= keys[i].value;
++
++ p = q+1;
++ }
++
++ g_free (str);
++ }
++
++ return result;
++}
++
++gchar*
++g_basename (const gchar *file_name)
++{
++ register gchar *base;
++
++ g_return_val_if_fail (file_name != NULL, NULL);
++
++ base = strrchr (file_name, G_DIR_SEPARATOR);
++ if (base)
++ return base + 1;
++
++#ifdef NATIVE_WIN32
++ if (isalpha (file_name[0]) && file_name[1] == ':')
++ return (gchar*) file_name + 2;
++#endif /* NATIVE_WIN32 */
++
++ return (gchar*) file_name;
++}
++
++gboolean
++g_path_is_absolute (const gchar *file_name)
++{
++ g_return_val_if_fail (file_name != NULL, FALSE);
++
++ if (file_name[0] == G_DIR_SEPARATOR)
++ return TRUE;
++
++#ifdef NATIVE_WIN32
++ if (isalpha (file_name[0]) && file_name[1] == ':' && file_name[2] == G_DIR_SEPARATOR)
++ return TRUE;
++#endif
++
++ return FALSE;
++}
++
++gchar*
++g_path_skip_root (gchar *file_name)
++{
++ g_return_val_if_fail (file_name != NULL, NULL);
++
++ if (file_name[0] == G_DIR_SEPARATOR)
++ return file_name + 1;
++
++#ifdef NATIVE_WIN32
++ if (isalpha (file_name[0]) && file_name[1] == ':' && file_name[2] == G_DIR_SEPARATOR)
++ return file_name + 3;
++#endif
++
++ return NULL;
++}
++
++gchar*
++g_dirname (const gchar *file_name)
++{
++ register gchar *base;
++ register guint len;
++
++ g_return_val_if_fail (file_name != NULL, NULL);
++
++ base = strrchr (file_name, G_DIR_SEPARATOR);
++ if (!base)
++ return g_strdup (".");
++ while (base > file_name && *base == G_DIR_SEPARATOR)
++ base--;
++ len = (guint) 1 + base - file_name;
++
++ base = g_new (gchar, len + 1);
++ g_memmove (base, file_name, len);
++ base[len] = 0;
++
++ return base;
++}
++
++#ifndef __KORBIT__
++gchar*
++g_get_current_dir (void)
++{
++ gchar *buffer;
++ gchar *dir;
++
++ buffer = g_new (gchar, G_PATH_LENGTH);
++ *buffer = 0;
++
++ /* We don't use getcwd(3) on SUNOS, because, it does a popen("pwd")
++ * and, if that wasn't bad enough, hangs in doing so.
++ */
++#if defined (sun) && !defined (__SVR4)
++ dir = getwd (buffer);
++#else /* !sun */
++ dir = getcwd (buffer, G_PATH_LENGTH - 1);
++#endif /* !sun */
++
++ if (!dir || !*buffer)
++ {
++ /* hm, should we g_error() out here?
++ * this can happen if e.g. "./" has mode \0000
++ */
++ buffer[0] = G_DIR_SEPARATOR;
++ buffer[1] = 0;
++ }
++
++ dir = g_strdup (buffer);
++ g_free (buffer);
++
++ return dir;
++}
++#endif /* !__KORBIT__ */
++
++gchar*
++g_getenv (const gchar *variable)
++{
++#ifndef NATIVE_WIN32
++ g_return_val_if_fail (variable != NULL, NULL);
++
++ return getenv (variable);
++#else
++ gchar *v;
++ guint k;
++ static gchar *p = NULL;
++ static gint l;
++ gchar dummy[2];
++
++ g_return_val_if_fail (variable != NULL, NULL);
++
++ v = getenv (variable);
++ if (!v)
++ return NULL;
++
++ /* On Windows NT, it is relatively typical that environment variables
++ * contain references to other environment variables. Handle that by
++ * calling ExpandEnvironmentStrings.
++ */
++
++ /* First check how much space we need */
++ k = ExpandEnvironmentStrings (v, dummy, 2);
++ /* Then allocate that much, and actualy do the expansion */
++ if (p == NULL)
++ {
++ p = g_malloc (k);
++ l = k;
++ }
++ else if (k > l)
++ {
++ p = g_realloc (p, k);
++ l = k;
++ }
++ ExpandEnvironmentStrings (v, p, k);
++ return p;
++#endif
++}
++
++
++G_LOCK_DEFINE_STATIC (g_utils_global);
++
++static gchar *g_tmp_dir = NULL;
++static gchar *g_user_name = NULL;
++static gchar *g_real_name = NULL;
++static gchar *g_home_dir = NULL;
++
++/* HOLDS: g_utils_global_lock */
++static void
++g_get_any_init (void)
++{
++ if (!g_tmp_dir)
++ {
++ g_tmp_dir = g_strdup (g_getenv ("TMPDIR"));
++ if (!g_tmp_dir)
++ g_tmp_dir = g_strdup (g_getenv ("TMP"));
++ if (!g_tmp_dir)
++ g_tmp_dir = g_strdup (g_getenv ("TEMP"));
++
++#ifdef P_tmpdir
++ if (!g_tmp_dir)
++ {
++ int k;
++ g_tmp_dir = g_strdup (P_tmpdir);
++ k = strlen (g_tmp_dir);
++ if (g_tmp_dir[k-1] == G_DIR_SEPARATOR)
++ g_tmp_dir[k-1] = '\0';
++ }
++#endif
++
++ if (!g_tmp_dir)
++ {
++#ifndef NATIVE_WIN32
++ g_tmp_dir = g_strdup ("/tmp");
++#else /* NATIVE_WIN32 */
++ g_tmp_dir = g_strdup ("C:\\");
++#endif /* NATIVE_WIN32 */
++ }
++
++ if (!g_home_dir)
++ g_home_dir = g_strdup (g_getenv ("HOME"));
++
++#ifdef NATIVE_WIN32
++ if (!g_home_dir)
++ {
++ /* The official way to specify a home directory on NT is
++ * the HOMEDRIVE and HOMEPATH environment variables.
++ *
++ * This is inside #ifdef NATIVE_WIN32 because with the cygwin dll,
++ * HOME should be a POSIX style pathname.
++ */
++
++ if (getenv ("HOMEDRIVE") != NULL && getenv ("HOMEPATH") != NULL)
++ {
++ gchar *homedrive, *homepath;
++
++ homedrive = g_strdup (g_getenv ("HOMEDRIVE"));
++ homepath = g_strdup (g_getenv ("HOMEPATH"));
++
++ g_home_dir = g_strconcat (homedrive, homepath, NULL);
++ g_free (homedrive);
++ g_free (homepath);
++ }
++ }
++#endif /* !NATIVE_WIN32 */
++
++#ifdef HAVE_PWD_H
++ {
++ struct passwd *pw = NULL;
++ gpointer buffer = NULL;
++
++# ifdef HAVE_GETPWUID_R
++ struct passwd pwd;
++ guint bufsize = 64;
++ gint error;
++
++ do
++ {
++ g_free (buffer);
++ buffer = g_malloc (bufsize);
++ errno = 0;
++
++# ifdef HAVE_GETPWUID_R_POSIX
++ error = getpwuid_r (getuid (), &pwd, buffer, bufsize, &pw);
++ error = error < 0 ? errno : error;
++# else /* !HAVE_GETPWUID_R_POSIX */
++# ifdef _AIX
++ error = getpwuid_r (getuid (), &pwd, buffer, bufsize);
++ pw = error == 0 ? &pwd : NULL;
++# else /* !_AIX */
++ pw = getpwuid_r (getuid (), &pwd, buffer, bufsize);
++ error = pw ? 0 : errno;
++# endif /* !_AIX */
++# endif /* !HAVE_GETPWUID_R_POSIX */
++
++ if (!pw)
++ {
++ /* we bail out prematurely if the user id can't be found
++ * (should be pretty rare case actually), or if the buffer
++ * should be sufficiently big and lookups are still not
++ * successfull.
++ */
++ if (error == 0 || error == ENOENT)
++ {
++ g_warning ("getpwuid_r(): failed due to: No such user %d.",
++ getuid ());
++ break;
++ }
++ if (bufsize > 32 * 1024)
++ {
++ g_warning ("getpwuid_r(): failed due to: %s.",
++ g_strerror (error));
++ break;
++ }
++
++ bufsize *= 2;
++ }
++ }
++ while (!pw);
++# endif /* !HAVE_GETPWUID_R */
++
++ if (!pw)
++ {
++ setpwent ();
++ pw = getpwuid (getuid ());
++ endpwent ();
++ }
++ if (pw)
++ {
++ g_user_name = g_strdup (pw->pw_name);
++ g_real_name = g_strdup (pw->pw_gecos);
++ if (!g_home_dir)
++ g_home_dir = g_strdup (pw->pw_dir);
++ }
++ g_free (buffer);
++ }
++
++#else /* !HAVE_PWD_H */
++
++# ifdef NATIVE_WIN32
++ {
++ guint len = 17;
++ gchar buffer[17];
++
++ if (GetUserName (buffer, &len))
++ {
++ g_user_name = g_strdup (buffer);
++ g_real_name = g_strdup (buffer);
++ }
++ }
++# endif /* NATIVE_WIN32 */
++
++#endif /* !HAVE_PWD_H */
++
++ if (!g_user_name)
++ g_user_name = g_strdup ("somebody");
++ if (!g_real_name)
++ g_real_name = g_strdup ("Unknown");
++ else
++ {
++ gchar *p;
++
++ for (p = g_real_name; *p; p++)
++ if (*p == ',')
++ {
++ *p = 0;
++ p = g_strdup (g_real_name);
++ g_free (g_real_name);
++ g_real_name = p;
++ break;
++ }
++ }
++ }
++}
++
++gchar*
++g_get_user_name (void)
++{
++ G_LOCK (g_utils_global);
++ if (!g_tmp_dir)
++ g_get_any_init ();
++ G_UNLOCK (g_utils_global);
++
++ return g_user_name;
++}
++
++gchar*
++g_get_real_name (void)
++{
++ G_LOCK (g_utils_global);
++ if (!g_tmp_dir)
++ g_get_any_init ();
++ G_UNLOCK (g_utils_global);
++
++ return g_real_name;
++}
++
++/* Return the home directory of the user. If there is a HOME
++ * environment variable, its value is returned, otherwise use some
++ * system-dependent way of finding it out. If no home directory can be
++ * deduced, return NULL.
++ */
++
++gchar*
++g_get_home_dir (void)
++{
++ G_LOCK (g_utils_global);
++ if (!g_tmp_dir)
++ g_get_any_init ();
++ G_UNLOCK (g_utils_global);
++
++ return g_home_dir;
++}
++
++/* Return a directory to be used to store temporary files. This is the
++ * value of the TMPDIR, TMP or TEMP environment variables (they are
++ * checked in that order). If none of those exist, use P_tmpdir from
++ * stdio.h. If that isn't defined, return "/tmp" on POSIXly systems,
++ * and C:\ on Windows.
++ */
++
++gchar*
++g_get_tmp_dir (void)
++{
++ G_LOCK (g_utils_global);
++ if (!g_tmp_dir)
++ g_get_any_init ();
++ G_UNLOCK (g_utils_global);
++
++ return g_tmp_dir;
++}
++
++static gchar *g_prgname = NULL;
++
++gchar*
++g_get_prgname (void)
++{
++ gchar* retval;
++
++ G_LOCK (g_utils_global);
++ retval = g_prgname;
++ G_UNLOCK (g_utils_global);
++
++ return retval;
++}
++
++void
++g_set_prgname (const gchar *prgname)
++{
++ gchar *c;
++
++ G_LOCK (g_utils_global);
++ c = g_prgname;
++ g_prgname = g_strdup (prgname);
++ g_free (c);
++ G_UNLOCK (g_utils_global);
++}
++
++guint
++g_direct_hash (gconstpointer v)
++{
++ return GPOINTER_TO_UINT (v);
++}
++
++gint
++g_direct_equal (gconstpointer v1,
++ gconstpointer v2)
++{
++ return v1 == v2;
++}
++
++gint
++g_int_equal (gconstpointer v1,
++ gconstpointer v2)
++{
++ return *((const gint*) v1) == *((const gint*) v2);
++}
++
++guint
++g_int_hash (gconstpointer v)
++{
++ return *(const gint*) v;
++}
++
++#if 0 /* Old IO Channels */
++
++GIOChannel*
++g_iochannel_new (gint fd)
++{
++ GIOChannel *channel = g_new (GIOChannel, 1);
++
++ channel->fd = fd;
++
++#ifdef NATIVE_WIN32
++ channel->peer = 0;
++ channel->peer_fd = 0;
++ channel->offset = 0;
++ channel->need_wakeups = 0;
++#endif /* NATIVE_WIN32 */
++
++ return channel;
++}
++
++void
++g_iochannel_free (GIOChannel *channel)
++{
++ g_return_if_fail (channel != NULL);
++
++ g_free (channel);
++}
++
++void
++g_iochannel_close_and_free (GIOChannel *channel)
++{
++ g_return_if_fail (channel != NULL);
++
++ close (channel->fd);
++
++ g_iochannel_free (channel);
++}
++
++#undef g_iochannel_wakeup_peer
++
++void
++g_iochannel_wakeup_peer (GIOChannel *channel)
++{
++#ifdef NATIVE_WIN32
++ static guint message = 0;
++#endif
++
++ g_return_if_fail (channel != NULL);
++
++#ifdef NATIVE_WIN32
++ if (message == 0)
++ message = RegisterWindowMessage ("gdk-pipe-readable");
++
++# if 0
++ g_print ("g_iochannel_wakeup_peer: calling PostThreadMessage (%#x, %d, %d, %d)\n",
++ channel->peer, message, channel->peer_fd, channel->offset);
++# endif
++ PostThreadMessage (channel->peer, message,
++ channel->peer_fd, channel->offset);
++#endif /* NATIVE_WIN32 */
++}
++
++#endif /* Old IO Channels */
++
++#ifdef NATIVE_WIN32
++#ifdef _MSC_VER
++
++int
++gwin_ftruncate (gint fd,
++ guint size)
++{
++ HANDLE hfile;
++ guint curpos;
++
++ g_return_val_if_fail (fd >= 0, -1);
++
++ hfile = (HANDLE) _get_osfhandle (fd);
++ curpos = SetFilePointer (hfile, 0, NULL, FILE_CURRENT);
++ if (curpos == 0xFFFFFFFF
++ || SetFilePointer (hfile, size, NULL, FILE_BEGIN) == 0xFFFFFFFF
++ || !SetEndOfFile (hfile))
++ {
++ gint error = GetLastError ();
++
++ switch (error)
++ {
++ case ERROR_INVALID_HANDLE:
++ errno = EBADF;
++ break;
++ default:
++ errno = EIO;
++ break;
++ }
++
++ return -1;
++ }
++
++ return 0;
++}
++
++DIR*
++gwin_opendir (const char *dirname)
++{
++ DIR *result;
++ gchar *mask;
++ guint k;
++
++ g_return_val_if_fail (dirname != NULL, NULL);
++
++ result = g_new0 (DIR, 1);
++ result->find_file_data = g_new0 (WIN32_FIND_DATA, 1);
++ result->dir_name = g_strdup (dirname);
++
++ k = strlen (result->dir_name);
++ if (k && result->dir_name[k - 1] == '\\')
++ {
++ result->dir_name[k - 1] = '\0';
++ k--;
++ }
++ mask = g_strdup_printf ("%s\\*", result->dir_name);
++
++ result->find_file_handle = (guint) FindFirstFile (mask,
++ (LPWIN32_FIND_DATA) result->find_file_data);
++ g_free (mask);
++
++ if (result->find_file_handle == (guint) INVALID_HANDLE_VALUE)
++ {
++ int error = GetLastError ();
++
++ g_free (result->dir_name);
++ g_free (result->find_file_data);
++ g_free (result);
++ switch (error)
++ {
++ default:
++ errno = EIO;
++ return NULL;
++ }
++ }
++ result->just_opened = TRUE;
++
++ return result;
++}
++
++struct dirent*
++gwin_readdir (DIR *dir)
++{
++ static struct dirent result;
++
++ g_return_val_if_fail (dir != NULL, NULL);
++
++ if (dir->just_opened)
++ dir->just_opened = FALSE;
++ else
++ {
++ if (!FindNextFile ((HANDLE) dir->find_file_handle,
++ (LPWIN32_FIND_DATA) dir->find_file_data))
++ {
++ int error = GetLastError ();
++
++ switch (error)
++ {
++ case ERROR_NO_MORE_FILES:
++ return NULL;
++ default:
++ errno = EIO;
++ return NULL;
++ }
++ }
++ }
++ strcpy (result.d_name, g_basename (((LPWIN32_FIND_DATA) dir->find_file_data)->cFileName));
++
++ return &result;
++}
++
++void
++gwin_rewinddir (DIR *dir)
++{
++ gchar *mask;
++
++ g_return_if_fail (dir != NULL);
++
++ if (!FindClose ((HANDLE) dir->find_file_handle))
++ g_warning ("gwin_rewinddir(): FindClose() failed\n");
++
++ mask = g_strdup_printf ("%s\\*", dir->dir_name);
++ dir->find_file_handle = (guint) FindFirstFile (mask,
++ (LPWIN32_FIND_DATA) dir->find_file_data);
++ g_free (mask);
++
++ if (dir->find_file_handle == (guint) INVALID_HANDLE_VALUE)
++ {
++ int error = GetLastError ();
++
++ switch (error)
++ {
++ default:
++ errno = EIO;
++ return;
++ }
++ }
++ dir->just_opened = TRUE;
++}
++
++gint
++gwin_closedir (DIR *dir)
++{
++ g_return_val_if_fail (dir != NULL, -1);
++
++ if (!FindClose ((HANDLE) dir->find_file_handle))
++ {
++ int error = GetLastError ();
++
++ switch (error)
++ {
++ default:
++ errno = EIO; return -1;
++ }
++ }
++
++ g_free (dir->dir_name);
++ g_free (dir->find_file_data);
++ g_free (dir);
++
++ return 0;
++}
++
++#endif /* _MSC_VER */
++
++#endif /* NATIVE_WIN32 */
+diff -urN linux-2.4.1/net/korbit/kglib/korbit_errno.c linux-2.4.1-korbit/net/korbit/kglib/korbit_errno.c
+--- linux-2.4.1/net/korbit/kglib/korbit_errno.c Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/kglib/korbit_errno.c Thu Feb 1 11:46:57 2001
+@@ -0,0 +1 @@
++int korbit_errno;
+diff -urN linux-2.4.1/net/korbit/korbit.h linux-2.4.1-korbit/net/korbit/korbit.h
+--- linux-2.4.1/net/korbit/korbit.h Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/korbit.h Thu Feb 1 11:46:49 2001
+@@ -0,0 +1,53 @@
++
++#ifndef KORBIT_H
++#define KORBIT_H
++
++#ifdef __KERNEL__
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/proc_fs.h>
++#endif
++
++#include "stdlib.h"
++
++#ifdef __KERNEL__
++static int korbit_get_ior_func(char *buffer, char **start, off_t offset,
++ int length, int *eof, void *data) {
++ int Len = strlen((char*)data);
++ memcpy(buffer, data, Len); // Data is the ior...
++ buffer[Len++] = '\n'; // Add a newline to make fredrik happy
++ buffer[Len] = 0; // Null terminate the buffer...
++ *start = buffer + offset;
++ *eof = 1;
++
++ Len -= offset;
++ if (Len > length)
++ Len = length;
++ if (Len < 0)
++ Len = 0;
++
++ return Len;
++}
++
++#endif
++
++
++static inline void korbit_register_ior(const char *name, CORBA_Object obj,
++ CORBA_ORB orb, CORBA_Environment *ev) {
++ char *retval = CORBA_ORB_object_to_string(orb, obj, ev);
++#if defined(__KERNEL__) && defined(CONFIG_PROC_FS)
++ char *procdirname = malloc(strlen(name)+7); // 7 = len("corba/\0")
++ strcpy(procdirname, "corba/");
++ strcpy(procdirname+6, name);
++
++ create_proc_read_entry(procdirname, 0, 0, korbit_get_ior_func, retval);
++
++ free(procdirname);
++ // Don't free the ior in the /proc handling case...
++#else
++ // No procfs support, just print to console... :(
++ g_print("%s IOR:\n%s\n", name, retval);
++ CORBA_free(retval);
++#endif
++}
++#endif
+diff -urN linux-2.4.1/net/korbit/modules/CVS/Entries linux-2.4.1-korbit/net/korbit/modules/CVS/Entries
+--- linux-2.4.1/net/korbit/modules/CVS/Entries Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/CVS/Entries Thu Feb 1 11:46:58 2001
+@@ -0,0 +1,5 @@
++/Config.in/1.8/Thu Feb 1 09:46:58 2001//
++/Makefile/1.8/Thu Feb 1 09:46:58 2001//
++/Makefile.module/1.2/Thu Feb 1 09:46:58 2001//
++/README/1.1/Thu Feb 1 09:46:58 2001//
++D
+diff -urN linux-2.4.1/net/korbit/modules/CVS/Entries.Log linux-2.4.1-korbit/net/korbit/modules/CVS/Entries.Log
+--- linux-2.4.1/net/korbit/modules/CVS/Entries.Log Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/CVS/Entries.Log Thu Feb 1 11:47:09 2001
+@@ -0,0 +1,6 @@
++A D/CharDev////
++A D/Console////
++A D/CorbaFS////
++A D/Echo////
++A D/FileServer////
++A D/UserFS////
+diff -urN linux-2.4.1/net/korbit/modules/CVS/Repository linux-2.4.1-korbit/net/korbit/modules/CVS/Repository
+--- linux-2.4.1/net/korbit/modules/CVS/Repository Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/CVS/Repository Thu Feb 1 11:46:57 2001
+@@ -0,0 +1 @@
++/cvsroot/korbit/linux/net/korbit/modules
+diff -urN linux-2.4.1/net/korbit/modules/CVS/Root linux-2.4.1-korbit/net/korbit/modules/CVS/Root
+--- linux-2.4.1/net/korbit/modules/CVS/Root Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/CVS/Root Thu Feb 1 11:46:57 2001
+@@ -0,0 +1 @@
++vraalsen@cvs.korbit.sourceforge.net:/cvsroot/korbit
+diff -urN linux-2.4.1/net/korbit/modules/CharDev/CVS/Entries linux-2.4.1-korbit/net/korbit/modules/CharDev/CVS/Entries
+--- linux-2.4.1/net/korbit/modules/CharDev/CVS/Entries Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/CharDev/CVS/Entries Thu Feb 1 11:46:58 2001
+@@ -0,0 +1,4 @@
++/Makefile/1.3/Thu Feb 1 09:46:58 2001//
++/README/1.1/Thu Feb 1 09:46:58 2001//
++/chardev.idl/1.1/Thu Feb 1 09:46:58 2001//
++D
+diff -urN linux-2.4.1/net/korbit/modules/CharDev/CVS/Entries.Log linux-2.4.1-korbit/net/korbit/modules/CharDev/CVS/Entries.Log
+--- linux-2.4.1/net/korbit/modules/CharDev/CVS/Entries.Log Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/CharDev/CVS/Entries.Log Thu Feb 1 11:47:00 2001
+@@ -0,0 +1,3 @@
++A D/kernel////
++A D/kernel-perl////
++A D/userspace////
+diff -urN linux-2.4.1/net/korbit/modules/CharDev/CVS/Repository linux-2.4.1-korbit/net/korbit/modules/CharDev/CVS/Repository
+--- linux-2.4.1/net/korbit/modules/CharDev/CVS/Repository Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/CharDev/CVS/Repository Thu Feb 1 11:46:58 2001
+@@ -0,0 +1 @@
++/cvsroot/korbit/linux/net/korbit/modules/CharDev
+diff -urN linux-2.4.1/net/korbit/modules/CharDev/CVS/Root linux-2.4.1-korbit/net/korbit/modules/CharDev/CVS/Root
+--- linux-2.4.1/net/korbit/modules/CharDev/CVS/Root Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/CharDev/CVS/Root Thu Feb 1 11:46:58 2001
+@@ -0,0 +1 @@
++vraalsen@cvs.korbit.sourceforge.net:/cvsroot/korbit
+diff -urN linux-2.4.1/net/korbit/modules/CharDev/Makefile linux-2.4.1-korbit/net/korbit/modules/CharDev/Makefile
+--- linux-2.4.1/net/korbit/modules/CharDev/Makefile Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/CharDev/Makefile Thu Feb 1 11:46:58 2001
+@@ -0,0 +1,11 @@
++#
++# Makefile for KORBit - CharDev
++#
++# Note! Dependencies are done automagically by 'make dep', which also
++# removes any old dependencies. DON'T put your own dependencies here
++# unless it's something special (ie not a .c file).
++
++subdir-$(CONFIG_CORBA_CHARDEV) := kernel
++
++include $(TOPDIR)/Rules.make
++
+diff -urN linux-2.4.1/net/korbit/modules/CharDev/README linux-2.4.1-korbit/net/korbit/modules/CharDev/README
+--- linux-2.4.1/net/korbit/modules/CharDev/README Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/CharDev/README Thu Feb 1 11:46:58 2001
+@@ -0,0 +1 @@
++This module is used to implement a character device with kORBit.
+diff -urN linux-2.4.1/net/korbit/modules/CharDev/chardev.idl linux-2.4.1-korbit/net/korbit/modules/CharDev/chardev.idl
+--- linux-2.4.1/net/korbit/modules/CharDev/chardev.idl Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/CharDev/chardev.idl Thu Feb 1 11:46:58 2001
+@@ -0,0 +1,5 @@
++typedef sequence<octet> Buffer;
++
++interface CharDev {
++ long read(out Buffer buffer, in long size);
++};
+diff -urN linux-2.4.1/net/korbit/modules/CharDev/kernel/CVS/Entries linux-2.4.1-korbit/net/korbit/modules/CharDev/kernel/CVS/Entries
+--- linux-2.4.1/net/korbit/modules/CharDev/kernel/CVS/Entries Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/CharDev/kernel/CVS/Entries Thu Feb 1 11:46:59 2001
+@@ -0,0 +1,4 @@
++/Makefile/1.2/Thu Feb 1 09:46:59 2001//
++/README/1.2/Thu Feb 1 09:46:59 2001//
++/chardev-kernel.c/1.9/Thu Feb 1 09:46:59 2001//
++D
+diff -urN linux-2.4.1/net/korbit/modules/CharDev/kernel/CVS/Repository linux-2.4.1-korbit/net/korbit/modules/CharDev/kernel/CVS/Repository
+--- linux-2.4.1/net/korbit/modules/CharDev/kernel/CVS/Repository Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/CharDev/kernel/CVS/Repository Thu Feb 1 11:46:59 2001
+@@ -0,0 +1 @@
++/cvsroot/korbit/linux/net/korbit/modules/CharDev/kernel
+diff -urN linux-2.4.1/net/korbit/modules/CharDev/kernel/CVS/Root linux-2.4.1-korbit/net/korbit/modules/CharDev/kernel/CVS/Root
+--- linux-2.4.1/net/korbit/modules/CharDev/kernel/CVS/Root Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/CharDev/kernel/CVS/Root Thu Feb 1 11:46:59 2001
+@@ -0,0 +1 @@
++vraalsen@cvs.korbit.sourceforge.net:/cvsroot/korbit
+diff -urN linux-2.4.1/net/korbit/modules/CharDev/kernel/Makefile linux-2.4.1-korbit/net/korbit/modules/CharDev/kernel/Makefile
+--- linux-2.4.1/net/korbit/modules/CharDev/kernel/Makefile Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/CharDev/kernel/Makefile Thu Feb 1 11:46:59 2001
+@@ -0,0 +1,20 @@
++#
++# Makefile for KORBit / chardev
++#
++# Note! Dependencies are done automagically by 'make dep', which also
++# removes any old dependencies. DON'T put your own dependencies here
++# unless it's something special (ie not a .c file).
++#
++# Note 2! The CFLAGS definition is now in the main makefile...
++
++O_TARGET := corba-chardev-kernel.o
++
++obj-y := chardev-common.o chardev-stubs.o chardev-kernel.o
++obj-m := $(O_TARGET)
++
++include ../../Makefile.module
++
++chardev-kernel.c: chardev.h
++
++chardev.h chardev-stubs.c chardev-common.c: ../chardev.idl
++ $(ORBIT_IDL) ../chardev.idl
+diff -urN linux-2.4.1/net/korbit/modules/CharDev/kernel/README linux-2.4.1-korbit/net/korbit/modules/CharDev/kernel/README
+--- linux-2.4.1/net/korbit/modules/CharDev/kernel/README Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/CharDev/kernel/README Thu Feb 1 11:46:59 2001
+@@ -0,0 +1,5 @@
++This module is used to implement the kernel side of the CORBA Character
++device.
++
++ORB: kORBit
++Status: Working!!!
+diff -urN linux-2.4.1/net/korbit/modules/CharDev/kernel/chardev-kernel.c linux-2.4.1-korbit/net/korbit/modules/CharDev/kernel/chardev-kernel.c
+--- linux-2.4.1/net/korbit/modules/CharDev/kernel/chardev-kernel.c Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/CharDev/kernel/chardev-kernel.c Thu Feb 1 11:46:59 2001
+@@ -0,0 +1,140 @@
++//-----------------------------------------------------------------------------
++//
++// chardev-kernel - Kernel miscdevice to CORBA glue.
++//
++// This file implements a standard Linux Kernel "miscdevice". This device
++// operates by forwarding all calls across to a remote CORBA server. This
++// server is located by reading the file /tmp/chardev-ior at the time the
++// device is opened. The device exported is major #10, minor #42. Create this
++// device with 'mknod' like all the others.
++//
++// No implementations of CORBA functions should block, although I think it
++// might be just fine, I'm not sure. Let's just make this a TODO. :) -CAL
++//
++// TODO: Locking, finish exporting all "miscdevice" functions, send position
++// on READ request.
++//
++// History:
++// Keith Wessel - Initial hack, initial idea
++// Andy Reitz - Get it to compile
++// Chris Lattner - Make it work. :)
++//
++//-----------------------------------------------------------------------------
++
++
++#include "chardev.h"
++#include <stdio.h>
++#include "orb/orbit.h"
++#include "korbit.h"
++#include <linux/miscdevice.h>
++
++#define DEV_MINOR 42
++
++CORBA_ORB orb;
++CORBA_Environment *ev;
++
++static int open_dev(struct inode *inode, struct file *file) {
++ char *iorstr = (char *)malloc(10240);
++ int error = -EINVAL;
++ int fd, len;
++
++ if (iorstr == 0) return -ENOMEM;
++
++ if ((fd = open ("/tmp/chardev-ior", O_RDONLY, 0)) == -1) {
++ printk("kORBit: chararacter driver couldn't open /tmp/chardev-ior!\n");
++ goto outfree;
++ }
++
++ len = read(fd, iorstr, 10240);
++ close(fd);
++ if (len == -1)
++ goto outfree;
++
++ iorstr[len] = 0; // Null terminate string!
++
++ printk("CharDEV IOR String = %s\n", iorstr);
++ file->private_data = (void*)CORBA_ORB_string_to_object(orb, iorstr, ev);
++ if (!file->private_data)
++ goto outfree;
++
++ // TODO: Send create_dev message out over CORBA
++
++ error = 0;
++ outfree:
++ free(iorstr);
++ return error;
++}
++
++static int release_dev(struct inode *inode, struct file *file) {
++ // TODO: Send release_dev message out over CORBA...
++ if (file->private_data)
++ CORBA_free(file->private_data);
++ return 0;
++}
++
++
++static ssize_t read_dev(struct file * file, char * buf, size_t count,
++ loff_t *ppos) {
++ Buffer *octet_buffer = NULL;
++ if (!file->private_data) return -EINVAL;
++ if (!count) return 0;
++
++ if (!access_ok(VERIFY_WRITE, buf, count))
++ return -EFAULT;
++
++ CharDev_read(file->private_data, &octet_buffer, count, ev);
++
++ if (!octet_buffer)
++ return -EPERM;
++
++ if (copy_to_user(buf, octet_buffer->_buffer, octet_buffer->_length))
++ return -EFAULT;
++
++ // TODO: Should free octet_buffer here!?!?!?
++
++ return octet_buffer->_length;
++}
++
++
++//-----------------------------------------------------------------------------
++// Kernel Callbacks for miscdevice
++//-----------------------------------------------------------------------------
++
++
++static struct file_operations dev_fops = {
++ owner: THIS_MODULE,
++ open: open_dev,
++ read: read_dev,
++ release: release_dev,
++ // mmap: mmap_dev,
++ // llseek: llseek_dev,
++ // write: write_dev,
++};
++
++static struct miscdevice cdev = {
++ DEV_MINOR,
++ "CORBA Character device",
++ &dev_fops
++};
++
++
++//-----------------------------------------------------------------------------
++// Module Initializion/Finalization
++//-----------------------------------------------------------------------------
++
++static int __init CharDev_init(void) {
++ int argc = 1;
++ char *argv[] = { "CharDev-kernel", 0 };
++ ev = g_new0(CORBA_Environment,1);
++ orb = CORBA_ORB_init(&argc, argv, "orbit-local-orb", ev);
++
++ // Register the device
++ return misc_register(&cdev);
++}
++
++static void __exit CharDev_exit(void) {
++ misc_deregister(&cdev);
++}
++
++module_init(CharDev_init)
++module_exit(CharDev_exit)
+diff -urN linux-2.4.1/net/korbit/modules/CharDev/kernel-perl/CVS/Entries linux-2.4.1-korbit/net/korbit/modules/CharDev/kernel-perl/CVS/Entries
+--- linux-2.4.1/net/korbit/modules/CharDev/kernel-perl/CVS/Entries Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/CharDev/kernel-perl/CVS/Entries Thu Feb 1 11:46:59 2001
+@@ -0,0 +1,3 @@
++/PerlTest/1.1/Thu Feb 1 09:46:59 2001//
++/README/1.1/Thu Feb 1 09:46:59 2001//
++D
+diff -urN linux-2.4.1/net/korbit/modules/CharDev/kernel-perl/CVS/Repository linux-2.4.1-korbit/net/korbit/modules/CharDev/kernel-perl/CVS/Repository
+--- linux-2.4.1/net/korbit/modules/CharDev/kernel-perl/CVS/Repository Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/CharDev/kernel-perl/CVS/Repository Thu Feb 1 11:46:59 2001
+@@ -0,0 +1 @@
++/cvsroot/korbit/linux/net/korbit/modules/CharDev/kernel-perl
+diff -urN linux-2.4.1/net/korbit/modules/CharDev/kernel-perl/CVS/Root linux-2.4.1-korbit/net/korbit/modules/CharDev/kernel-perl/CVS/Root
+--- linux-2.4.1/net/korbit/modules/CharDev/kernel-perl/CVS/Root Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/CharDev/kernel-perl/CVS/Root Thu Feb 1 11:46:59 2001
+@@ -0,0 +1 @@
++vraalsen@cvs.korbit.sourceforge.net:/cvsroot/korbit
+diff -urN linux-2.4.1/net/korbit/modules/CharDev/kernel-perl/PerlTest linux-2.4.1-korbit/net/korbit/modules/CharDev/kernel-perl/PerlTest
+--- linux-2.4.1/net/korbit/modules/CharDev/kernel-perl/PerlTest Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/CharDev/kernel-perl/PerlTest Thu Feb 1 11:46:59 2001
+@@ -0,0 +1,17 @@
++#!/usr/bin/perl -w
++
++use CORBA::ORBit idl => [ qw(../chardev.idl) ];
++use Error qw(:try);
++use strict;
++
++my $orb = CORBA::ORB_init("orbit-local-orb");
++open IOR, "/tmp/chardev-ior" or die "no chardev server found!";
++my $ior = <IOR>;
++close IOR;
++#chomp($ior); # Kill fredrik's newline...
++
++my $chardev = $orb->string_to_object($ior);
++# Echo echoString(in string astring, out long anum);
++my ($ressize, $buf) = $chardev->read(10);
++
++print "Return size = $ressize\nresult = $buf\n";
+diff -urN linux-2.4.1/net/korbit/modules/CharDev/kernel-perl/README linux-2.4.1-korbit/net/korbit/modules/CharDev/kernel-perl/README
+--- linux-2.4.1/net/korbit/modules/CharDev/kernel-perl/README Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/CharDev/kernel-perl/README Thu Feb 1 11:46:59 2001
+@@ -0,0 +1,6 @@
++This module is used to test the user side of the CORBA Character
++device. It doesn't do anything really complex, just implements a quick
++sanity test for the server.
++
++ORB: ORBit - Perl
++Status: Working!
+diff -urN linux-2.4.1/net/korbit/modules/CharDev/userspace/CVS/Entries linux-2.4.1-korbit/net/korbit/modules/CharDev/userspace/CVS/Entries
+--- linux-2.4.1/net/korbit/modules/CharDev/userspace/CVS/Entries Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/CharDev/userspace/CVS/Entries Thu Feb 1 11:47:00 2001
+@@ -0,0 +1,6 @@
++/Makefile/1.5/Thu Feb 1 09:47:00 2001//
++/README/1.1/Thu Feb 1 09:47:00 2001//
++/RunServer.sh/1.1/Thu Feb 1 09:47:00 2001//
++/chardev-server.c/1.5/Thu Feb 1 09:47:00 2001//
++/chardev-skelimpl.c/1.5/Thu Feb 1 09:47:00 2001//
++D
+diff -urN linux-2.4.1/net/korbit/modules/CharDev/userspace/CVS/Repository linux-2.4.1-korbit/net/korbit/modules/CharDev/userspace/CVS/Repository
+--- linux-2.4.1/net/korbit/modules/CharDev/userspace/CVS/Repository Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/CharDev/userspace/CVS/Repository Thu Feb 1 11:47:00 2001
+@@ -0,0 +1 @@
++/cvsroot/korbit/linux/net/korbit/modules/CharDev/userspace
+diff -urN linux-2.4.1/net/korbit/modules/CharDev/userspace/CVS/Root linux-2.4.1-korbit/net/korbit/modules/CharDev/userspace/CVS/Root
+--- linux-2.4.1/net/korbit/modules/CharDev/userspace/CVS/Root Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/CharDev/userspace/CVS/Root Thu Feb 1 11:47:00 2001
+@@ -0,0 +1 @@
++vraalsen@cvs.korbit.sourceforge.net:/cvsroot/korbit
+diff -urN linux-2.4.1/net/korbit/modules/CharDev/userspace/Makefile linux-2.4.1-korbit/net/korbit/modules/CharDev/userspace/Makefile
+--- linux-2.4.1/net/korbit/modules/CharDev/userspace/Makefile Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/CharDev/userspace/Makefile Thu Feb 1 11:47:00 2001
+@@ -0,0 +1,30 @@
++#
++# Makefile for KORBit / CharDev
++#
++# Note! Dependencies are done automagically by 'make dep', which also
++# removes any old dependencies. DON'T put your own dependencies here
++# unless it's something special (ie not a .c file).
++#
++# Note 2! The CFLAGS definition is now in the main makefile...
++
++CFLAGS = -Wall -I/usr/lib/glib/include
++LDFLAGS = -lORBit -lIIOP -lORBitutil
++OBJS = chardev-common.o chardev-skels.o chardev-server.o
++ORBIT-IDL = /usr/bin/orbit-idl
++
++chardev-server: $(OBJS)
++ gcc -o chardev-server $(OBJS) $(LDFLAGS)
++
++chardev-server.o: chardev.h chardev-skelimpl.c
++
++chardev.h chardev-skels.c chardev-common.c: ../chardev.idl
++ $(ORBIT-IDL) ../chardev.idl
++
++chardev-skelimpl.c:
++
++%.o: %.c
++ gcc -c $< $(CFLAGS)
++clean:
++ rm -f $(OBJS) chardev-server chardev-common.c chardev-skels.c \
++ chardev-stubs.c chardev.h
++
+diff -urN linux-2.4.1/net/korbit/modules/CharDev/userspace/README linux-2.4.1-korbit/net/korbit/modules/CharDev/userspace/README
+--- linux-2.4.1/net/korbit/modules/CharDev/userspace/README Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/CharDev/userspace/README Thu Feb 1 11:47:00 2001
+@@ -0,0 +1,4 @@
++This is an example character driver.
++
++ORB: ORBit
++Status: not yet working
+diff -urN linux-2.4.1/net/korbit/modules/CharDev/userspace/RunServer.sh linux-2.4.1-korbit/net/korbit/modules/CharDev/userspace/RunServer.sh
+--- linux-2.4.1/net/korbit/modules/CharDev/userspace/RunServer.sh Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/CharDev/userspace/RunServer.sh Thu Feb 1 11:47:00 2001
+@@ -0,0 +1 @@
++./chardev-server -ORBIIOPUSock=0 -ORBIIOPIPv4=1
+diff -urN linux-2.4.1/net/korbit/modules/CharDev/userspace/chardev-server.c linux-2.4.1-korbit/net/korbit/modules/CharDev/userspace/chardev-server.c
+--- linux-2.4.1/net/korbit/modules/CharDev/userspace/chardev-server.c Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/CharDev/userspace/chardev-server.c Thu Feb 1 11:47:00 2001
+@@ -0,0 +1,77 @@
++//-----------------------------------------------------------------------------
++//
++// chardev-server.c - TEST Kernel miscdevice implementation
++//
++// This file implements the standard server code for a userspace server. This
++// is basically cut and paste boilerplate code adapted from the CorbaFS server
++// by Fredrik Vraalsen.
++//
++// TODO: Locking, finish exporting all "miscdevice" functions, send position
++// on READ request.
++//
++// History:
++// Keith Wessel - Initial hack, initial idea
++// Andy Reitz - Get it to compile
++// Chris Lattner - Hack'n'slash, make it work, comment it, kill warnings.
++//
++//-----------------------------------------------------------------------------
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <signal.h>
++#include <orb/orbit.h>
++
++// #include the C file because all the functions are static. Bizarre.
++#include "chardev-skelimpl.c"
++
++int main(int argc, char *argv[]) {
++ PortableServer_POA poa;
++ PortableServer_POAManager pm;
++
++ CharDev chardev = CORBA_OBJECT_NIL;
++ impl_POA_CharDev *chardev_impl;
++ PortableServer_ObjectId *objid;
++
++ CORBA_Environment ev;
++ char *retval;
++ CORBA_ORB orb;
++ FILE *IORFILE;
++
++ orb = CORBA_ORB_init(&argc, argv, "orbit-local-orb", &ev);
++ poa = (PortableServer_POA)CORBA_ORB_resolve_initial_references(orb, "RootPOA", &ev);
++
++ chardev = impl_CharDev__create(poa, &ev);
++ pm = PortableServer_POA__get_the_POAManager(poa, &ev);
++ PortableServer_POAManager_activate(pm, &ev);
++
++ if (!chardev) {
++ printf("Cannot get objref\n");
++ return 1;
++ }
++
++ chardev_impl = PortableServer_POA_reference_to_servant(poa, chardev, &ev);
++ objid = PortableServer_POA_servant_to_id(poa, chardev_impl, &ev);
++
++ retval = CORBA_ORB_object_to_string(orb, chardev, &ev);
++
++ g_print("FYI, this also goes into /tmp/chardev-ior for you.\n");
++ g_print("%s\n", retval); fflush(stdout);
++
++ IORFILE = fopen ("/tmp/chardev-ior", "w");
++ if (IORFILE == NULL) {
++ perror("ERROR: IOR_WRITE_TO_DISK");
++ exit(1);
++ }
++
++ fprintf(IORFILE, "%s", retval);
++ fclose(IORFILE);
++
++ CORBA_free(retval); // Free the corba string like a good little CORBear
++
++
++ // La dee dah... I will never return for you mister.
++ CORBA_ORB_run(orb, &ev);
++ return 0;
++}
++
+diff -urN linux-2.4.1/net/korbit/modules/CharDev/userspace/chardev-skelimpl.c linux-2.4.1-korbit/net/korbit/modules/CharDev/userspace/chardev-skelimpl.c
+--- linux-2.4.1/net/korbit/modules/CharDev/userspace/chardev-skelimpl.c Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/CharDev/userspace/chardev-skelimpl.c Thu Feb 1 11:47:00 2001
+@@ -0,0 +1,119 @@
++//-----------------------------------------------------------------------------
++//
++// chardev-skelimpl.c - TEST Kernel miscdevice implementation
++//
++// This file implements a CORBA "miscdevice" (character device node).
++// This device simply outputs a fixed string (set by "message", below) when
++// cat'd. Pretty simple stuff, but you can obviously do much more creative
++// things with it.
++//
++// TODO: Locking, finish exporting all "miscdevice" functions, send position
++// on READ request.
++//
++// Right now we have ONE server object with global state, so that when you
++// read the string from that object, it is finished. This should be reset
++// whenever an open request is had or when the file position is reset (duh).
++//
++// History:
++// Keith Wessel - Initial hack, initial idea
++// Andy Reitz - Get it to compile
++// Chris Lattner - Make it work, comment it, no warnings.
++//
++//-----------------------------------------------------------------------------
++
++#include "chardev.h"
++
++// The message to spit out.
++const char *message = "Hello world!\nI love kORBit\n";
++
++
++/*** App-specific servant structures ***/
++
++typedef struct
++{
++ POA_CharDev servant;
++ PortableServer_POA poa;
++ int AmountRead;
++
++}
++impl_POA_CharDev;
++
++/*** Implementation stub prototypes ***/
++
++static inline void impl_CharDev__destroy(impl_POA_CharDev * servant,
++ CORBA_Environment * ev);
++static CORBA_long
++impl_CharDev_read(impl_POA_CharDev * servant,
++ Buffer ** buffer, CORBA_long size, CORBA_Environment * ev);
++
++/*** epv structures ***/
++
++static PortableServer_ServantBase__epv impl_CharDev_base_epv = {
++ NULL, /* _private data */
++ NULL, /* finalize routine */
++ NULL, /* default_POA routine */
++};
++static POA_CharDev__epv impl_CharDev_epv = {
++ NULL, /* _private */
++ (gpointer) & impl_CharDev_read,
++
++};
++
++/*** vepv structures ***/
++
++static POA_CharDev__vepv impl_CharDev_vepv = {
++ &impl_CharDev_base_epv,
++ &impl_CharDev_epv,
++};
++
++/*** Stub implementations ***/
++
++static CharDev
++impl_CharDev__create(PortableServer_POA poa, CORBA_Environment * ev)
++{
++ CharDev retval;
++ impl_POA_CharDev *newservant;
++ PortableServer_ObjectId *objid;
++
++ newservant = g_new0(impl_POA_CharDev, 1);
++ newservant->servant.vepv = &impl_CharDev_vepv;
++ newservant->poa = poa;
++ newservant->AmountRead = 0; // Initialize chardev stuff...
++
++ POA_CharDev__init((PortableServer_Servant) newservant, ev);
++ objid = PortableServer_POA_activate_object(poa, newservant, ev);
++ CORBA_free(objid);
++ retval = PortableServer_POA_servant_to_reference(poa, newservant, ev);
++
++ return retval;
++}
++
++static inline void
++impl_CharDev__destroy(impl_POA_CharDev * servant, CORBA_Environment * ev)
++{
++ PortableServer_ObjectId *objid;
++
++ objid = PortableServer_POA_servant_to_id(servant->poa, servant, ev);
++ PortableServer_POA_deactivate_object(servant->poa, objid, ev);
++ CORBA_free(objid);
++
++ POA_CharDev__fini((PortableServer_Servant) servant, ev);
++ g_free(servant);
++}
++
++static CORBA_long
++impl_CharDev_read(impl_POA_CharDev * servant,
++ Buffer ** buffer, CORBA_long ReqSize, CORBA_Environment * ev)
++{
++ int AvailSize = strlen(message)-servant->AmountRead;
++ CORBA_long retval = (ReqSize > AvailSize) ? AvailSize : ReqSize;
++
++ *buffer = Buffer__alloc();
++ (*buffer)->_buffer = CORBA_octet_allocbuf(retval);
++ (*buffer)->_length = retval;
++
++ strncpy((*buffer)->_buffer, message + servant->AmountRead, retval);
++ servant->AmountRead += retval;
++ return retval;
++}
++
+diff -urN linux-2.4.1/net/korbit/modules/Config.in linux-2.4.1-korbit/net/korbit/modules/Config.in
+--- linux-2.4.1/net/korbit/modules/Config.in Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/Config.in Thu Feb 1 11:46:58 2001
+@@ -0,0 +1,11 @@
++# Console server
++#
++dep_tristate ' CORBA Console Server (EXPERIMENTAL)' CONFIG_CORBA_CONSOLE $CONFIG_KORBIT
++
++dep_tristate ' CORBA Echo Server (EXPERIMENTAL)' CONFIG_CORBA_ECHO $CONFIG_KORBIT
++
++dep_tristate ' CORBA FileSystem Access (EXPERIMENTAL)' CONFIG_CORBA_FILESERVER $CONFIG_KORBIT
++
++dep_tristate ' CORBA User-space FileSystem (EXPERIMENTAL)' CONFIG_CORBA_CORBAFS $CONFIG_KORBIT
++
++dep_tristate ' CORBA Character Device Interface (EXPERIMENTAL)' CONFIG_CORBA_CHARDEV $CONFIG_KORBIT
+diff -urN linux-2.4.1/net/korbit/modules/Console/CVS/Entries linux-2.4.1-korbit/net/korbit/modules/Console/CVS/Entries
+--- linux-2.4.1/net/korbit/modules/Console/CVS/Entries Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/Console/CVS/Entries Thu Feb 1 11:47:01 2001
+@@ -0,0 +1,4 @@
++/Makefile/1.2/Thu Feb 1 09:47:00 2001//
++/README/1.1/Thu Feb 1 09:47:00 2001//
++/console.idl/1.1/Thu Feb 1 09:47:00 2001//
++D
+diff -urN linux-2.4.1/net/korbit/modules/Console/CVS/Entries.Log linux-2.4.1-korbit/net/korbit/modules/Console/CVS/Entries.Log
+--- linux-2.4.1/net/korbit/modules/Console/CVS/Entries.Log Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/Console/CVS/Entries.Log Thu Feb 1 11:47:02 2001
+@@ -0,0 +1,3 @@
++A D/PerlClient////
++A D/client////
++A D/server////
+diff -urN linux-2.4.1/net/korbit/modules/Console/CVS/Repository linux-2.4.1-korbit/net/korbit/modules/Console/CVS/Repository
+--- linux-2.4.1/net/korbit/modules/Console/CVS/Repository Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/Console/CVS/Repository Thu Feb 1 11:47:00 2001
+@@ -0,0 +1 @@
++/cvsroot/korbit/linux/net/korbit/modules/Console
+diff -urN linux-2.4.1/net/korbit/modules/Console/CVS/Root linux-2.4.1-korbit/net/korbit/modules/Console/CVS/Root
+--- linux-2.4.1/net/korbit/modules/Console/CVS/Root Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/Console/CVS/Root Thu Feb 1 11:47:00 2001
+@@ -0,0 +1 @@
++vraalsen@cvs.korbit.sourceforge.net:/cvsroot/korbit
+diff -urN linux-2.4.1/net/korbit/modules/Console/Makefile linux-2.4.1-korbit/net/korbit/modules/Console/Makefile
+--- linux-2.4.1/net/korbit/modules/Console/Makefile Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/Console/Makefile Thu Feb 1 11:47:00 2001
+@@ -0,0 +1,11 @@
++#
++# Makefile for KORBit/modules/Console
++#
++# Note! Dependencies are done automagically by 'make dep', which also
++# removes any old dependencies. DON'T put your own dependencies here
++# unless it's something special (ie not a .c file).
++
++subdir-$(CONFIG_CORBA_CONSOLE) := server
++
++include $(TOPDIR)/Rules.make
++
+diff -urN linux-2.4.1/net/korbit/modules/Console/PerlClient/CVS/Entries linux-2.4.1-korbit/net/korbit/modules/Console/PerlClient/CVS/Entries
+--- linux-2.4.1/net/korbit/modules/Console/PerlClient/CVS/Entries Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/Console/PerlClient/CVS/Entries Thu Feb 1 11:47:01 2001
+@@ -0,0 +1,3 @@
++/Client/1.1/Thu Feb 1 09:47:01 2001//
++/README/1.1/Thu Feb 1 09:47:01 2001//
++D
+diff -urN linux-2.4.1/net/korbit/modules/Console/PerlClient/CVS/Repository linux-2.4.1-korbit/net/korbit/modules/Console/PerlClient/CVS/Repository
+--- linux-2.4.1/net/korbit/modules/Console/PerlClient/CVS/Repository Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/Console/PerlClient/CVS/Repository Thu Feb 1 11:47:01 2001
+@@ -0,0 +1 @@
++/cvsroot/korbit/linux/net/korbit/modules/Console/PerlClient
+diff -urN linux-2.4.1/net/korbit/modules/Console/PerlClient/CVS/Root linux-2.4.1-korbit/net/korbit/modules/Console/PerlClient/CVS/Root
+--- linux-2.4.1/net/korbit/modules/Console/PerlClient/CVS/Root Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/Console/PerlClient/CVS/Root Thu Feb 1 11:47:01 2001
+@@ -0,0 +1 @@
++vraalsen@cvs.korbit.sourceforge.net:/cvsroot/korbit
+diff -urN linux-2.4.1/net/korbit/modules/Console/PerlClient/Client linux-2.4.1-korbit/net/korbit/modules/Console/PerlClient/Client
+--- linux-2.4.1/net/korbit/modules/Console/PerlClient/Client Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/Console/PerlClient/Client Thu Feb 1 11:47:01 2001
+@@ -0,0 +1,14 @@
++#!/usr/bin/perl -w
++
++use CORBA::ORBit idl => [ qw(../console.idl) ];
++use Error qw(:try);
++use strict;
++
++my $orb = CORBA::ORB_init("orbit-local-orb");
++open IOR, "/proc/corba/console-server" or die "no console server found!";
++my $ior = <IOR>;
++close IOR;
++chomp($ior); # Kill fredrik's newline...
++
++my $console = $orb->string_to_object($ior);
++$console->print("Hello Strange World");
+diff -urN linux-2.4.1/net/korbit/modules/Console/PerlClient/README linux-2.4.1-korbit/net/korbit/modules/Console/PerlClient/README
+--- linux-2.4.1/net/korbit/modules/Console/PerlClient/README Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/Console/PerlClient/README Thu Feb 1 11:47:01 2001
+@@ -0,0 +1,3 @@
++This is a perl client for the Console server.
++
++ORB: ORBit
+diff -urN linux-2.4.1/net/korbit/modules/Console/README linux-2.4.1-korbit/net/korbit/modules/Console/README
+--- linux-2.4.1/net/korbit/modules/Console/README Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/Console/README Thu Feb 1 11:47:00 2001
+@@ -0,0 +1 @@
++The "hello world" testcase. This is used to write a string to the linux console.
+diff -urN linux-2.4.1/net/korbit/modules/Console/client/CVS/Entries linux-2.4.1-korbit/net/korbit/modules/Console/client/CVS/Entries
+--- linux-2.4.1/net/korbit/modules/Console/client/CVS/Entries Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/Console/client/CVS/Entries Thu Feb 1 11:47:01 2001
+@@ -0,0 +1,4 @@
++/Makefile/1.2/Thu Feb 1 09:47:01 2001//
++/README/1.1/Thu Feb 1 09:47:01 2001//
++/console-client.c/1.1/Thu Feb 1 09:47:01 2001//
++D
+diff -urN linux-2.4.1/net/korbit/modules/Console/client/CVS/Repository linux-2.4.1-korbit/net/korbit/modules/Console/client/CVS/Repository
+--- linux-2.4.1/net/korbit/modules/Console/client/CVS/Repository Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/Console/client/CVS/Repository Thu Feb 1 11:47:01 2001
+@@ -0,0 +1 @@
++/cvsroot/korbit/linux/net/korbit/modules/Console/client
+diff -urN linux-2.4.1/net/korbit/modules/Console/client/CVS/Root linux-2.4.1-korbit/net/korbit/modules/Console/client/CVS/Root
+--- linux-2.4.1/net/korbit/modules/Console/client/CVS/Root Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/Console/client/CVS/Root Thu Feb 1 11:47:01 2001
+@@ -0,0 +1 @@
++vraalsen@cvs.korbit.sourceforge.net:/cvsroot/korbit
+diff -urN linux-2.4.1/net/korbit/modules/Console/client/Makefile linux-2.4.1-korbit/net/korbit/modules/Console/client/Makefile
+--- linux-2.4.1/net/korbit/modules/Console/client/Makefile Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/Console/client/Makefile Thu Feb 1 11:47:01 2001
+@@ -0,0 +1,32 @@
++#
++# Makefile for KORBit
++#
++# Note! Dependencies are done automagically by 'make dep', which also
++# removes any old dependencies. DON'T put your own dependencies here
++# unless it's something special (ie not a .c file).
++#
++# Note 2! The CFLAGS definition is now in the main makefile...
++
++PROJECT = console
++
++CFLAGS = -Wall `orbit-config --cflags client` -I../../..
++LDFLAGS = `orbit-config --libs client`
++OBJS = $(PROJECT)-common.o $(PROJECT)-stubs.o $(PROJECT)-client.o
++ORBIT-IDL = orbit-idl
++
++$(PROJECT)-client: $(OBJS)
++ gcc -o $(PROJECT)-client $(OBJS) $(LDFLAGS)
++
++$(PROJECT)-client.c: $(PROJECT).h
++
++$(PROJECT).h $(PROJECT)-common.c $(PROJECT)-stubs.c: ../$(PROJECT).idl
++ $(ORBIT-IDL) --noskels ../$(PROJECT).idl
++
++clean:
++ rm -f $(OBJS) $(PROJECT)-client
++
++realclean: clean
++ rm -f $(PROJECT).h
++ rm -f $(PROJECT)-common.c
++ rm -f $(PROJECT)-stubs.c
++ rm -f *~
+diff -urN linux-2.4.1/net/korbit/modules/Console/client/README linux-2.4.1-korbit/net/korbit/modules/Console/client/README
+--- linux-2.4.1/net/korbit/modules/Console/client/README Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/Console/client/README Thu Feb 1 11:47:01 2001
+@@ -0,0 +1,3 @@
++C Client to access console server.
++
++ORB: ORBit
+diff -urN linux-2.4.1/net/korbit/modules/Console/client/console-client.c linux-2.4.1-korbit/net/korbit/modules/Console/client/console-client.c
+--- linux-2.4.1/net/korbit/modules/Console/client/console-client.c Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/Console/client/console-client.c Thu Feb 1 11:47:01 2001
+@@ -0,0 +1,63 @@
++#include <stdio.h>
++#include <stdlib.h>
++#include <orb/orbit.h>
++
++#include "console.h"
++
++Console console_client;
++
++int
++main (int argc, char *argv[])
++{
++ CORBA_Environment ev;
++ CORBA_ORB orb;
++ char *Message = "Hey dood, nice hair";
++ int i;
++
++ int niters = 10;
++
++ CORBA_exception_init(&ev);
++ orb = CORBA_ORB_init(&argc, argv, "orbit-local-orb", &ev);
++
++#if 0
++ for(i = 0; i < (sizeof(theblah) - 1); i++)
++ theblah[i] = 'a';
++ theblah[sizeof(theblah) - 1] = '\0';
++#endif
++
++ if(argc < 2)
++ {
++ printf("Need a binding ID thing as argv[1]\n");
++ return 1;
++ }
++
++ if(argc >= 3)
++ niters = atoi(argv[2]);
++
++ if (argc >= 4)
++ Message = argv[3];
++
++ console_client = CORBA_ORB_string_to_object(orb, argv[1], &ev);
++ if (!console_client) {
++ printf("Cannot bind to %s\n", argv[1]);
++ return 1;
++ }
++
++ printf("corba = %d, console = %d, foobar = %d\n",
++ CORBA_Object_is_a(console_client, "IDL:CORBA/Object:1.0", &ev),
++ CORBA_Object_is_a(console_client, "IDL:Empty:1.0", &ev),
++ CORBA_Object_is_a(console_client, "IDL:Foo/Bar:1.0", &ev));
++
++ for(i = 0; i < niters; i++) {
++ Console_print(console_client, Message, &ev);
++ if(ev._major != CORBA_NO_EXCEPTION) {
++ printf("we got exception %d from doNothing!\n", ev._major);
++ return 1;
++ }
++ }
++
++ CORBA_Object_release(console_client, &ev);
++ CORBA_Object_release((CORBA_Object)orb, &ev);
++
++ return 0;
++}
+diff -urN linux-2.4.1/net/korbit/modules/Console/console.idl linux-2.4.1-korbit/net/korbit/modules/Console/console.idl
+--- linux-2.4.1/net/korbit/modules/Console/console.idl Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/Console/console.idl Thu Feb 1 11:47:00 2001
+@@ -0,0 +1,3 @@
++interface Console {
++ void print(in string TheString);
++};
+diff -urN linux-2.4.1/net/korbit/modules/Console/server/CVS/Entries linux-2.4.1-korbit/net/korbit/modules/Console/server/CVS/Entries
+--- linux-2.4.1/net/korbit/modules/Console/server/CVS/Entries Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/Console/server/CVS/Entries Thu Feb 1 11:47:02 2001
+@@ -0,0 +1,5 @@
++/Makefile/1.7/Thu Feb 1 09:47:02 2001//
++/Makefile.user/1.1/Thu Feb 1 09:47:02 2001//
++/README/1.1/Thu Feb 1 09:47:02 2001//
++/console-server.c/1.7/Thu Feb 1 09:47:02 2001//
++D
+diff -urN linux-2.4.1/net/korbit/modules/Console/server/CVS/Repository linux-2.4.1-korbit/net/korbit/modules/Console/server/CVS/Repository
+--- linux-2.4.1/net/korbit/modules/Console/server/CVS/Repository Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/Console/server/CVS/Repository Thu Feb 1 11:47:02 2001
+@@ -0,0 +1 @@
++/cvsroot/korbit/linux/net/korbit/modules/Console/server
+diff -urN linux-2.4.1/net/korbit/modules/Console/server/CVS/Root linux-2.4.1-korbit/net/korbit/modules/Console/server/CVS/Root
+--- linux-2.4.1/net/korbit/modules/Console/server/CVS/Root Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/Console/server/CVS/Root Thu Feb 1 11:47:02 2001
+@@ -0,0 +1 @@
++vraalsen@cvs.korbit.sourceforge.net:/cvsroot/korbit
+diff -urN linux-2.4.1/net/korbit/modules/Console/server/Makefile linux-2.4.1-korbit/net/korbit/modules/Console/server/Makefile
+--- linux-2.4.1/net/korbit/modules/Console/server/Makefile Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/Console/server/Makefile Thu Feb 1 11:47:02 2001
+@@ -0,0 +1,21 @@
++#
++# Makefile for KORBit
++#
++# Note! Dependencies are done automagically by 'make dep', which also
++# removes any old dependencies. DON'T put your own dependencies here
++# unless it's something special (ie not a .c file).
++#
++# Note 2! The CFLAGS definition is now in the main makefile...
++
++O_TARGET := corba-cons-server.o
++
++obj-y := console-server.o console-skels.o console-common.o
++obj-m := $(O_TARGET)
++
++include ../../Makefile.module
++
++console-server.c: console.h console-common.c console-skels.c
++
++
++console.h console-skels.c: ../console.idl
++ $(ORBIT_IDL) ../console.idl
+diff -urN linux-2.4.1/net/korbit/modules/Console/server/Makefile.user linux-2.4.1-korbit/net/korbit/modules/Console/server/Makefile.user
+--- linux-2.4.1/net/korbit/modules/Console/server/Makefile.user Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/Console/server/Makefile.user Thu Feb 1 11:47:02 2001
+@@ -0,0 +1,32 @@
++#
++# Makefile for KORBit
++#
++# Note! Dependencies are done automagically by 'make dep', which also
++# removes any old dependencies. DON'T put your own dependencies here
++# unless it's something special (ie not a .c file).
++#
++# Note 2! The CFLAGS definition is now in the main makefile...
++
++PROJECT = console
++
++CFLAGS = -Wall `orbit-config --cflags server` -I../../..
++LDFLAGS = `orbit-config --libs server`
++OBJS = $(PROJECT)-common.o $(PROJECT)-skels.o $(PROJECT)-server.o
++ORBIT-IDL = orbit-idl
++
++$(PROJECT)-server: $(OBJS)
++ gcc -o $(PROJECT)-server $(OBJS) $(LDFLAGS)
++
++$(PROJECT)-server.c: $(PROJECT).h
++
++$(PROJECT).h $(PROJECT)-common.c $(PROJECT)-skels.c: ../$(PROJECT).idl
++ $(ORBIT-IDL) --nostubs ../$(PROJECT).idl
++
++clean:
++ rm -f $(OBJS) $(PROJECT)-server
++
++realclean: clean
++ rm -f $(PROJECT).h
++ rm -f $(PROJECT)-common.c
++ rm -f $(PROJECT)-skels.c
++ rm -f *~
+diff -urN linux-2.4.1/net/korbit/modules/Console/server/README linux-2.4.1-korbit/net/korbit/modules/Console/server/README
+--- linux-2.4.1/net/korbit/modules/Console/server/README Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/Console/server/README Thu Feb 1 11:47:02 2001
+@@ -0,0 +1 @@
++Kernel module to implement Console server.
+diff -urN linux-2.4.1/net/korbit/modules/Console/server/console-server.c linux-2.4.1-korbit/net/korbit/modules/Console/server/console-server.c
+--- linux-2.4.1/net/korbit/modules/Console/server/console-server.c Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/Console/server/console-server.c Thu Feb 1 11:47:02 2001
+@@ -0,0 +1,85 @@
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <signal.h>
++#include <orb/orbit.h>
++
++#include <linux/init.h>
++#include <linux/module.h>
++#include "console.h"
++#include "glib.h"
++#include "korbit.h"
++
++Console console_client = CORBA_OBJECT_NIL;
++
++static void corba_console_print(PortableServer_Servant _servant,
++ CORBA_char *TheString,
++ CORBA_Environment *ev);
++
++PortableServer_ServantBase__epv base_epv = {
++ NULL,
++ NULL,
++ NULL
++};
++POA_Console__epv console_epv = { NULL, corba_console_print };
++POA_Console__vepv poa_console_vepv = { &base_epv, &console_epv };
++POA_Console poa_console_servant = { NULL, &poa_console_vepv };
++
++// MAke this global so that I can unregister the module...
++PortableServer_ObjectId objid = {0, sizeof("myFoo"), "myFoo"};
++CORBA_Environment *ev;
++PortableServer_POA poa;
++
++#ifdef __KERNEL__
++int __init corba_console_init(void)
++#else
++int main(int argc, char *argv[])
++#endif
++{
++#ifdef __KERNEL__
++ int argc = 1; char *argv[] = { "server", 0 };
++#endif
++ CORBA_ORB orb;
++
++ ev = g_new0(CORBA_Environment, 1);
++ CORBA_exception_init(ev);
++ orb = CORBA_ORB_init(&argc, argv, "orbit-local-orb", ev);
++
++ poa = (PortableServer_POA)CORBA_ORB_resolve_initial_references(orb, "RootPOA", ev);
++ PortableServer_POAManager_activate(PortableServer_POA__get_the_POAManager(poa, ev), ev);
++
++ POA_Console__init(&poa_console_servant, ev);
++
++ PortableServer_POA_activate_object_with_id(poa,
++ &objid, &poa_console_servant, ev);
++
++ console_client =
++ PortableServer_POA_servant_to_reference(poa, &poa_console_servant, ev);
++ if (!console_client) {
++ printf("Cannot get objref\n");
++ return 1;
++ }
++
++ korbit_register_ior("console-server", console_client, orb, ev);
++
++ CORBA_ORB_run(orb, ev);
++
++ return 0;
++}
++
++#ifdef __KERNEL__
++void corba_console_exit(void) {
++ PortableServer_POA_deactivate_object(poa, &objid, ev);
++ remove_proc_entry("corba/console-server", 0);
++}
++
++module_init(corba_console_init)
++module_exit(corba_console_exit)
++#endif
++
++static void corba_console_print(PortableServer_Servant _servant,
++ CORBA_char *TheString,
++ CORBA_Environment *ev) {
++ printf("Yo. Dood. You said: '%s'!\n", TheString);
++}
++
+diff -urN linux-2.4.1/net/korbit/modules/CorbaFS/CVS/Entries linux-2.4.1-korbit/net/korbit/modules/CorbaFS/CVS/Entries
+--- linux-2.4.1/net/korbit/modules/CorbaFS/CVS/Entries Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/CorbaFS/CVS/Entries Thu Feb 1 11:47:02 2001
+@@ -0,0 +1,4 @@
++/CorbaFS.idl/1.7/Thu Feb 1 09:47:02 2001//
++/Makefile/1.4/Thu Feb 1 09:47:02 2001//
++/README/1.2/Thu Feb 1 09:47:02 2001//
++D
+diff -urN linux-2.4.1/net/korbit/modules/CorbaFS/CVS/Entries.Log linux-2.4.1-korbit/net/korbit/modules/CorbaFS/CVS/Entries.Log
+--- linux-2.4.1/net/korbit/modules/CorbaFS/CVS/Entries.Log Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/CorbaFS/CVS/Entries.Log Thu Feb 1 11:47:04 2001
+@@ -0,0 +1,3 @@
++A D/client////
++A D/server////
++A D/server-perl////
+diff -urN linux-2.4.1/net/korbit/modules/CorbaFS/CVS/Repository linux-2.4.1-korbit/net/korbit/modules/CorbaFS/CVS/Repository
+--- linux-2.4.1/net/korbit/modules/CorbaFS/CVS/Repository Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/CorbaFS/CVS/Repository Thu Feb 1 11:47:02 2001
+@@ -0,0 +1 @@
++/cvsroot/korbit/linux/net/korbit/modules/CorbaFS
+diff -urN linux-2.4.1/net/korbit/modules/CorbaFS/CVS/Root linux-2.4.1-korbit/net/korbit/modules/CorbaFS/CVS/Root
+--- linux-2.4.1/net/korbit/modules/CorbaFS/CVS/Root Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/CorbaFS/CVS/Root Thu Feb 1 11:47:02 2001
+@@ -0,0 +1 @@
++vraalsen@cvs.korbit.sourceforge.net:/cvsroot/korbit
+diff -urN linux-2.4.1/net/korbit/modules/CorbaFS/CorbaFS.idl linux-2.4.1-korbit/net/korbit/modules/CorbaFS/CorbaFS.idl
+--- linux-2.4.1/net/korbit/modules/CorbaFS/CorbaFS.idl Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/CorbaFS/CorbaFS.idl Thu Feb 1 11:47:02 2001
+@@ -0,0 +1,38 @@
++// -----------------------------------------------------------------------------
++// CorbaDS Module - Implement Kernel functionality in Korba
++// -----------------------------------------------------------------------------
++//
++// Main source of information:
++// http://www.cse.unsw.edu.au/~neilb/oss/linux-commentary/vfs.html
++//
++module CorbaFS {
++
++ struct dirent
++ {
++ long inode; // inode number
++ string name; // file name (null-terminated)
++ };
++
++ typedef sequence<dirent> DirEntSeq;
++ typedef sequence<octet> Buffer;
++
++ interface Inode {
++ void getStatus(out unsigned short mode, out unsigned long uid, out unsigned long gid,
++ out unsigned long size, out unsigned long inodeNum, out unsigned short numLinks,
++ out long atime, out long mtime, out long ctime);
++ void readpage(out Buffer buffer, in long size, in long offset);
++ void release();
++ };
++
++ interface FileSystem {
++ Inode getInode(in string path);
++
++ // DirectoryInode getStatus implementation must have S_IFDIR in the S_IFMT
++ // field of the mode value.
++ DirEntSeq readdir(in string path);
++
++ // SymlinkInode getStatus implementation must have S_IFLNK in the S_IFMT
++ // field of the mode value.
++ string readlink(in string filename);
++ };
++};
+diff -urN linux-2.4.1/net/korbit/modules/CorbaFS/Makefile linux-2.4.1-korbit/net/korbit/modules/CorbaFS/Makefile
+--- linux-2.4.1/net/korbit/modules/CorbaFS/Makefile Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/CorbaFS/Makefile Thu Feb 1 11:47:02 2001
+@@ -0,0 +1,11 @@
++#
++# Makefile for KORBit - CorbaFS
++#
++# Note! Dependencies are done automagically by 'make dep', which also
++# removes any old dependencies. DON'T put your own dependencies here
++# unless it's something special (ie not a .c file).
++
++subdir-$(CONFIG_CORBA_CORBAFS) := client
++
++include $(TOPDIR)/Rules.make
++
+diff -urN linux-2.4.1/net/korbit/modules/CorbaFS/README linux-2.4.1-korbit/net/korbit/modules/CorbaFS/README
+--- linux-2.4.1/net/korbit/modules/CorbaFS/README Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/CorbaFS/README Thu Feb 1 11:47:02 2001
+@@ -0,0 +1,14 @@
++This interface is used to implement linux FileSystems in CORBA.
++
++Status: Working for readonly filesystems. Write capability is a todo.
++
++This lets you do all kinds of interesting things (just like the user level
++filesystem proposals would let you do):
++ server/ implements NFS like capability of just exporting an existing FS
++ TODO: webfs, ftpfs, cvsfs, mysqlfs...
++
++Usage:
++ insmod corba-corbafs.o
++ mount -t corbafs -o IOR:... none /mnt/corbafs
++
++Where the IOR comes from a filesystem server that you run somewhere...
+diff -urN linux-2.4.1/net/korbit/modules/CorbaFS/client/CVS/Entries linux-2.4.1-korbit/net/korbit/modules/CorbaFS/client/CVS/Entries
+--- linux-2.4.1/net/korbit/modules/CorbaFS/client/CVS/Entries Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/CorbaFS/client/CVS/Entries Thu Feb 1 11:47:03 2001
+@@ -0,0 +1,6 @@
++/CorbaFS-client.c/1.9/Thu Feb 1 09:47:03 2001//
++/CorbaFS-user-client.c/1.3/Thu Feb 1 09:47:03 2001//
++/Makefile/1.4/Thu Feb 1 09:47:03 2001//
++/Makefile.user/1.1/Thu Feb 1 09:47:03 2001//
++/README/1.1/Thu Feb 1 09:47:03 2001//
++D
+diff -urN linux-2.4.1/net/korbit/modules/CorbaFS/client/CVS/Repository linux-2.4.1-korbit/net/korbit/modules/CorbaFS/client/CVS/Repository
+--- linux-2.4.1/net/korbit/modules/CorbaFS/client/CVS/Repository Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/CorbaFS/client/CVS/Repository Thu Feb 1 11:47:03 2001
+@@ -0,0 +1 @@
++/cvsroot/korbit/linux/net/korbit/modules/CorbaFS/client
+diff -urN linux-2.4.1/net/korbit/modules/CorbaFS/client/CVS/Root linux-2.4.1-korbit/net/korbit/modules/CorbaFS/client/CVS/Root
+--- linux-2.4.1/net/korbit/modules/CorbaFS/client/CVS/Root Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/CorbaFS/client/CVS/Root Thu Feb 1 11:47:03 2001
+@@ -0,0 +1 @@
++vraalsen@cvs.korbit.sourceforge.net:/cvsroot/korbit
+diff -urN linux-2.4.1/net/korbit/modules/CorbaFS/client/CorbaFS-client.c linux-2.4.1-korbit/net/korbit/modules/CorbaFS/client/CorbaFS-client.c
+--- linux-2.4.1/net/korbit/modules/CorbaFS/client/CorbaFS-client.c Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/CorbaFS/client/CorbaFS-client.c Fri Feb 2 02:20:21 2001
+@@ -0,0 +1,469 @@
++/*
++ * corbafs - Interface glue between native linux VFS layer and CORBA
++ */
++
++#include <linux/module.h>
++#include <linux/fs.h>
++#include <linux/pagemap.h>
++#include <linux/init.h>
++#include <linux/string.h>
++#include <linux/locks.h>
++#include <linux/dirent.h>
++#include <linux/module.h>
++
++#include <asm/uaccess.h>
++#include "CorbaFS.h"
++
++/* some random number */
++#define CORBAFS_MAGIC 0xC02BAF5
++
++// CORBA Stuff...
++CORBA_ORB orb;
++CORBA_Environment *ev;
++
++
++/*
++ * FILE OPERATIONS FILE OPERATIONS FILE OPERATIONS FILE OPERATIONS
++ */
++
++/* Declarations for the file_operations structure for normal files...
++ */
++static struct file_operations corbafs_file_operations = {
++ read: generic_file_read,
++};
++
++
++/* Declarations for the file_operations structure for directories...
++ */
++static int corbafs_readdir(struct file *file, void *data, filldir_t filldir);
++
++static struct file_operations corbafs_dir_operations = {
++ read: generic_read_dir,
++ readdir: corbafs_readdir,
++};
++
++
++/*
++ * INODE OPERATIONS INODE OPERATIONS INODE OPERATIONS INODE OPERATIONS
++ */
++
++/* Declarations for the inode_operations structure for symlinks...
++ */
++static int corbafs_readlink(struct dentry *dentry, char *buffer, int buflen);
++static int corbafs_followlink(struct dentry *link, struct nameidata *nd);
++
++static struct inode_operations corbafs_symlink_inode_operations = {
++ readlink: corbafs_readlink,
++ follow_link: corbafs_followlink,
++};
++
++
++/* Declarations for the inode_operations structure for directories...
++ */
++static struct dentry *corbafs_lookup(struct inode *dir, struct dentry *dentry);
++
++static struct inode_operations corbafs_dir_inode_operations = {
++ lookup: corbafs_lookup,
++};
++
++
++/*
++ * OTHER OPERATIONS OTHER OPERATIONS OTHER OPERATIONS OTHER OPERATIONS
++ */
++
++/* Declarations for the corba FS's address space ops...
++ */
++static int corbafs_readpage(struct file *file, struct page * page);
++
++static struct address_space_operations corbafs_aops = {
++ readpage: corbafs_readpage,
++};
++
++
++/* Declarations for the super_operations structure...
++ */
++static int corbafs_statfs(struct super_block *sb, struct statfs *buf);
++static void corbafs_delete_inode(struct inode *);
++
++static struct super_operations corbafs_ops = {
++ statfs: corbafs_statfs,
++ delete_inode: corbafs_delete_inode,
++};
++
++
++
++
++/* do_local_path - Modified version of d_path that is used to get the remote
++ * filename that a dentry represents...
++ */
++static char *d_local_path(struct dentry *dentry, char *buffer, int buflen) {
++ char * end = buffer+buflen;
++ char * retval;
++ int namelen;
++
++ *--end = '\0';
++ buflen--;
++
++ /* Get '/' right */
++ retval = end-1;
++ *retval = '/';
++ for (;;) {
++ if (IS_ROOT(dentry)) {
++ if (dentry->d_name.len > 1 ||
++ dentry->d_name.name[0] != '/' ||
++ retval != end) { /* Only for root directory */
++ namelen = dentry->d_name.len;
++ buflen -= namelen;
++ if (buflen >= 0) {
++ end -= namelen;
++ memcpy(end, dentry->d_name.name, namelen);
++ }
++ }
++ return end;
++ }
++ namelen = dentry->d_name.len;
++ buflen -= namelen + 1;
++ if (buflen < 0)
++ break;
++ end -= namelen;
++ memcpy(end, dentry->d_name.name, namelen);
++ *--end = '/';
++ retval = end;
++ if (dentry == dentry->d_parent) break;
++ dentry = dentry->d_parent;
++ }
++ return retval;
++}
++
++
++/* corbafs_readpage - This request should be between a file_open and a
++ * file_release, so file_fd(f) should be valid. Just read the buffer...
++ */
++static int corbafs_readpage(struct file *f, struct page * page)
++{
++ struct inode *d_inode = f->f_dentry->d_inode;
++ CorbaFS_Inode inode;
++ CorbaFS_Buffer *buffer = NULL;
++
++ int offset = page->index*PAGE_CACHE_SIZE;
++ int bytesRead;
++
++#if 0
++ printk("*** READPAGE 0x%p: 0x%lX->0x%lX to 0x%p\n",
++ f,
++ page->index,
++ page->index*PAGE_CACHE_SIZE,
++ page_address(page));
++#endif
++
++ inode = d_inode->u.generic_ip;
++ if (!inode) return -EPERM;
++
++ CorbaFS_Inode_readpage(inode, &buffer, PAGE_CACHE_SIZE, offset, ev);
++ if (!buffer) return -EPERM; /* ??? */
++
++ bytesRead = buffer->_length;
++ memcpy(page_address(page), buffer->_buffer, bytesRead);
++
++ if (bytesRead != PAGE_CACHE_SIZE) { /* EOF? */
++ /* Zero out rest of page for security. */
++ memset((void*)(page_address(page)+bytesRead), 0,
++ PAGE_CACHE_SIZE-bytesRead);
++ }
++
++ SetPageUptodate(page);
++ UnlockPage(page);
++ return 0;
++}
++
++
++
++struct inode *corbafs_get_inode(struct super_block *sb, const char *path)
++{
++ struct inode * inode = get_empty_inode();
++ CorbaFS_FileSystem fs_client;
++ CorbaFS_Inode newInode;
++
++ if (!inode) return 0;
++
++ inode->i_sb = sb;
++ inode->i_dev = sb->s_dev;
++
++ fs_client = sb->u.generic_sbp;
++//printk("\n \n \nCorbaFS_FileSystem_getInode(0x%X, %s)\n", fs_client, path);
++ newInode = CorbaFS_FileSystem_getInode(fs_client, path, ev);
++//printk("NewInode = 0x%X\n \n \n \n", newInode);
++ if (!newInode) {
++ iput(inode);
++ return NULL;
++ }
++
++//printk("CorbaFS_Inode_getStatus\n");
++ CorbaFS_Inode_getStatus(newInode,
++ &inode->i_mode, &inode->i_uid, &inode->i_gid,
++ (CORBA_unsigned_long *)&inode->i_size,
++ (CORBA_unsigned_long *)&inode->i_ino,
++ &inode->i_nlink,
++ (CORBA_long *)&inode->i_atime,
++ (CORBA_long *)&inode->i_mtime,
++ (CORBA_long *)&inode->i_ctime,
++ ev);
++//printk("Back from CorbaFS_Inode_getStatus\n \n \n \n");
++
++ inode->u.generic_ip = (void*)newInode;
++
++ /* TODO: Map things back correctly??? */
++ inode->i_uid = 0 /*current->fsuid */;
++ inode->i_gid = 0 /*current->fsgid */;
++
++ inode->i_blksize = PAGE_CACHE_SIZE;
++ inode->i_blocks = 0;
++ inode->i_rdev = 0;
++ inode->i_op = NULL;
++ inode->i_fop = NULL;
++ inode->i_mapping->a_ops = &corbafs_aops;
++ inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
++
++ switch (inode->i_mode & S_IFMT) {
++ default:
++ /* Do I really want to expose device inodes? */
++ init_special_inode(inode, inode->i_mode, sb->s_dev);
++ break;
++ case S_IFREG:
++ inode->i_fop = &corbafs_file_operations;
++ break;
++ case S_IFDIR:
++ inode->i_op = &corbafs_dir_inode_operations;
++ inode->i_fop = &corbafs_dir_operations;
++ break;
++ case S_IFLNK:
++ inode->i_op = &corbafs_symlink_inode_operations;
++ break;
++ }
++ insert_inode_hash(inode);
++
++ return inode;
++}
++
++static int corbafs_readdir(struct file *file, void *data, filldir_t filldir)
++{
++ struct inode *inode = file->f_dentry->d_inode;
++ struct super_block *sb = file->f_dentry->d_sb;
++ unsigned offset = file->f_pos;
++ char *path, *page = (char *)__get_free_page(GFP_KERNEL);
++ int i;
++ unsigned char d_type = DT_UNKNOWN;
++ CorbaFS_FileSystem fs_client;
++ CorbaFS_DirEntSeq *dirEntSeq;
++ CorbaFS_dirent *dirEnts;
++
++ if (offset >= inode->i_size) return 0;
++
++ path = d_local_path(file->f_dentry, page, PAGE_SIZE);
++
++ fs_client = sb->u.generic_sbp;
++ if (!fs_client)
++ return -EPERM; /* ??? */
++
++// printk("\n \n \nCorbaFS_FileSystem_readdir(%s)\n", path);
++
++ dirEntSeq = CorbaFS_FileSystem_readdir(fs_client, path, ev);
++
++// printk("CorbaFS_FileSystem_readdir = %d\n \n \n \n", dirEntSeq->_length);
++
++ if (dirEntSeq->_length == 0) goto full;
++
++ dirEnts = dirEntSeq->_buffer;
++ i = 0;
++ if (offset) { // We have read PART of the directory
++ int idxadj = offset; // Start reading now from where we left
++ while (idxadj > 0) { // off...
++ idxadj -= sizeof(struct dirent)+
++ strlen(dirEnts[i].name);
++ i++;
++ }
++
++ if (idxadj < 0) { // We should end up with exactly 0.
++ printf("Alert! Readdir can't resume in the middle "
++ "of a directory! stopage.\n");
++ goto full;
++ }
++ }
++
++ for (; i < dirEntSeq->_length; i++) {
++ int myinode = dirEnts[i].inode;
++ char *myname = dirEnts[i].name;
++ int namelen = strlen(myname);
++
++ if (filldir(data, myname, namelen, offset, myinode, d_type))
++ goto full;
++ offset += sizeof(struct dirent)+namelen;
++ }
++
++ full:
++ file->f_pos = offset;
++ return 0;
++}
++
++static int corbafs_statfs(struct super_block *sb, struct statfs *buf) {
++ buf->f_type = CORBAFS_MAGIC;
++ buf->f_bsize = PAGE_CACHE_SIZE;
++ buf->f_namelen = 255;
++ return 0;
++}
++
++/*
++ * Lookup the data. Most of the grunt work is done by corbafs_get_inode.
++ */
++static struct dentry *corbafs_lookup(struct inode *dir, struct dentry *dentry)
++{
++ struct inode *New;
++ char *Path, *Page = (char *)__get_free_page(GFP_KERNEL);
++ if (Page == 0) goto out; /* nomem? */
++
++ Path = d_local_path(dentry, Page, PAGE_SIZE);
++
++ New = corbafs_get_inode(dir->i_sb, Path);
++ free_page((unsigned long)Page);
++
++ if (New) {
++ d_add(dentry, New);
++ return 0;
++ }
++
++out:
++ d_add(dentry, NULL);
++ return 0;
++}
++
++
++static char *corbafs_read_a_link(struct dentry *dentry) {
++ char *path, *page, *s = 0;
++ struct super_block *sb = dentry->d_sb;
++ CorbaFS_FileSystem fs_client;
++
++ page = (char *)__get_free_page(GFP_KERNEL);
++ if (page == 0) goto out; /* nomem? */
++
++ path = d_local_path(dentry, page, PAGE_SIZE);
++
++ fs_client = sb->u.generic_sbp;
++// printk("\n \n \nCorbaFS_FileSystem_readlink(%s)\n", path);
++ s = CorbaFS_FileSystem_readlink(fs_client, path, ev);
++// printk("CorbaFS_FileSystem_readlink = %s\n \n \n \n", s);
++
++ if (ev->_major != CORBA_NO_EXCEPTION) {
++ if (s) {
++ // CORBA_string_free(s,..);
++ s = 0;
++ }
++ goto outfree;
++ }
++ outfree:
++ free_page((unsigned long)page);
++ out:
++ return s;
++}
++
++
++static int corbafs_readlink(struct dentry *dentry, char *buffer, int buflen) {
++ char *str = corbafs_read_a_link(dentry);
++ int error = -EINVAL;
++
++ if (str) {
++ error = vfs_readlink(dentry, buffer, buflen, str);
++ // TODO: CORBA_string__free the string str.
++ }
++ return error;
++}
++
++/* Fill in nd->dentry
++ */
++static int corbafs_followlink(struct dentry *link, struct nameidata *nd) {
++ int Error = -ENOMEM;
++ char *Path = corbafs_read_a_link(link);
++ if (!Path) goto out;
++
++#if 1
++ printk("Followlink: %s\n", Path);
++#endif
++ Error = vfs_follow_link(nd, Path);
++ // TODO: CORBA_string__free the string str.
++
++ out:
++ return Error;
++}
++
++static void corbafs_delete_inode(struct inode *inode) {
++ CorbaFS_Inode Inode = inode->u.generic_ip;
++// printk("\n \n \nCorbaFS_Inode_Release\n");
++ CorbaFS_Inode_release(Inode, ev);
++// printk("CorbaFS_Inode_Release done\n \n \n \n");
++}
++
++static void corbafs_put_super(struct super_block *sb) {
++// MOD_DEC_USE_COUNT;
++}
++
++static struct super_block *corbafs_read_super(struct super_block * sb, void * data, int silent) {
++ struct dentry *root = 0;
++ struct inode *root_inode = 0;
++
++ CorbaFS_FileSystem fs_client;
++
++ sb->s_blocksize = PAGE_CACHE_SIZE;
++ sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
++ sb->s_magic = CORBAFS_MAGIC;
++ sb->s_op = &corbafs_ops;
++
++//printk("corbafs_read_super: '%s'\n", (char*)data);
++
++ // Note that the CORBA IOR is now in *data
++ fs_client = CORBA_ORB_string_to_object(orb, data, ev);
++
++//printk("fs_client: 0x%X\n", fs_client);
++ if (!fs_client)
++ return NULL;
++
++ sb->u.generic_sbp = fs_client;
++
++ root_inode = corbafs_get_inode(sb, "/");
++//printk("root_inode = 0x%X\n", root_inode);
++ root = d_alloc_root(root_inode);
++ if (!root) {
++ iput(root_inode);
++ return NULL;
++ }
++ sb->s_root = root;
++
++// MOD_INC_USE_COUNT;
++ return sb;
++}
++
++static DECLARE_FSTYPE(corbafs_fs_type, "corbafs", corbafs_read_super, 0);
++
++static int __init init_corbafs_fs(void) {
++ int argc = 1;
++ char *argv[] = { "client", 0 };
++ ev = g_new0(CORBA_Environment,1);
++ orb = CORBA_ORB_init(&argc, argv, "orbit-local-orb", ev);
++
++ return register_filesystem(&corbafs_fs_type);
++}
++
++static void __exit exit_corbafs_fs(void)
++{
++ // remove object from orb.
++ printf("\n \n \nCorbaFS_exit()\n");
++ unregister_filesystem(&corbafs_fs_type);
++ CORBA_Object_release((CORBA_Object)orb, ev);
++}
++
++module_init(init_corbafs_fs)
++module_exit(exit_corbafs_fs)
++
++/*
++ * Local variables:
++ * c-file-style: "linux"
++ * End:
++ */
+diff -urN linux-2.4.1/net/korbit/modules/CorbaFS/client/CorbaFS-common.c linux-2.4.1-korbit/net/korbit/modules/CorbaFS/client/CorbaFS-common.c
+--- linux-2.4.1/net/korbit/modules/CorbaFS/client/CorbaFS-common.c Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/CorbaFS/client/CorbaFS-common.c Thu Feb 1 16:36:08 2001
+@@ -0,0 +1,370 @@
++/*
++ * This file was generated by orbit-idl - DO NOT EDIT!
++ */
++
++#include <string.h>
++#include "CorbaFS.h"
++
++#if ( (TC_IMPL_TC_CorbaFS_dirent_0 == 'C') \
++&& (TC_IMPL_TC_CorbaFS_dirent_1 == 'o') \
++&& (TC_IMPL_TC_CorbaFS_dirent_2 == 'r') \
++&& (TC_IMPL_TC_CorbaFS_dirent_3 == 'b') \
++&& (TC_IMPL_TC_CorbaFS_dirent_4 == 'a') \
++&& (TC_IMPL_TC_CorbaFS_dirent_5 == 'F') \
++&& (TC_IMPL_TC_CorbaFS_dirent_6 == 'S') \
++) && !defined(TC_DEF_TC_CorbaFS_dirent)
++#define TC_DEF_TC_CorbaFS_dirent 1
++static const char *anon_subnames_array1[] = { "inode", "name" };
++static const CORBA_TypeCode anon_subtypes_array2[] =
++ { (CORBA_TypeCode) & TC_CORBA_long_struct,
++ (CORBA_TypeCode) & TC_CORBA_string_struct };
++const struct CORBA_TypeCode_struct TC_CorbaFS_dirent_struct = {
++
++ {{(ORBit_RootObject_Interface *) & ORBit_TypeCode_epv, TRUE, -1},
++ ORBIT_PSEUDO_TYPECODE},
++
++ CORBA_tk_struct, "dirent", "IDL:CorbaFS/dirent:1.0",
++ 0, 2,
++ (const char **) anon_subnames_array1,
++ (CORBA_TypeCode *) anon_subtypes_array2,
++ NULL,
++ CORBA_OBJECT_NIL, 0, -1, 0, 0
++};
++#endif
++#if ( (TC_IMPL_TC_CORBA_sequence_CorbaFS_dirent_0 == 'C') \
++&& (TC_IMPL_TC_CORBA_sequence_CorbaFS_dirent_1 == 'o') \
++&& (TC_IMPL_TC_CORBA_sequence_CorbaFS_dirent_2 == 'r') \
++&& (TC_IMPL_TC_CORBA_sequence_CorbaFS_dirent_3 == 'b') \
++&& (TC_IMPL_TC_CORBA_sequence_CorbaFS_dirent_4 == 'a') \
++&& (TC_IMPL_TC_CORBA_sequence_CorbaFS_dirent_5 == 'F') \
++&& (TC_IMPL_TC_CORBA_sequence_CorbaFS_dirent_6 == 'S') \
++) && !defined(TC_DEF_TC_CORBA_sequence_CorbaFS_dirent)
++#define TC_DEF_TC_CORBA_sequence_CorbaFS_dirent 1
++static const CORBA_TypeCode anon_subtypes_array6[] =
++ { (CORBA_TypeCode) & TC_CorbaFS_dirent_struct };
++const struct CORBA_TypeCode_struct TC_CORBA_sequence_CorbaFS_dirent_struct = {
++
++ {{(ORBit_RootObject_Interface *) & ORBit_TypeCode_epv, TRUE, -1},
++ ORBIT_PSEUDO_TYPECODE},
++
++ CORBA_tk_sequence, NULL, NULL,
++ 0, 1,
++ NULL,
++ (CORBA_TypeCode *) anon_subtypes_array6,
++ NULL,
++ CORBA_OBJECT_NIL, 0, -1, 0, 0
++};
++#endif
++#if ( (TC_IMPL_TC_CORBA_sequence_CorbaFS_dirent_0 == 'C') \
++&& (TC_IMPL_TC_CORBA_sequence_CorbaFS_dirent_1 == 'o') \
++&& (TC_IMPL_TC_CORBA_sequence_CorbaFS_dirent_2 == 'r') \
++&& (TC_IMPL_TC_CORBA_sequence_CorbaFS_dirent_3 == 'b') \
++&& (TC_IMPL_TC_CORBA_sequence_CorbaFS_dirent_4 == 'a') \
++&& (TC_IMPL_TC_CORBA_sequence_CorbaFS_dirent_5 == 'F') \
++&& (TC_IMPL_TC_CORBA_sequence_CorbaFS_dirent_6 == 'S') \
++) && !defined(TC_DEF_TC_CORBA_sequence_CorbaFS_dirent)
++#define TC_DEF_TC_CORBA_sequence_CorbaFS_dirent 1
++static const CORBA_TypeCode anon_subtypes_array15[] =
++ { (CORBA_TypeCode) & TC_CorbaFS_dirent_struct };
++const struct CORBA_TypeCode_struct TC_CORBA_sequence_CorbaFS_dirent_struct = {
++
++ {{(ORBit_RootObject_Interface *) & ORBit_TypeCode_epv, TRUE, -1},
++ ORBIT_PSEUDO_TYPECODE},
++
++ CORBA_tk_sequence, NULL, NULL,
++ 0, 1,
++ NULL,
++ (CORBA_TypeCode *) anon_subtypes_array15,
++ NULL,
++ CORBA_OBJECT_NIL, 0, -1, 0, 0
++};
++#endif
++#if ( (TC_IMPL_TC_CorbaFS_DirEntSeq_0 == 'C') \
++&& (TC_IMPL_TC_CorbaFS_DirEntSeq_1 == 'o') \
++&& (TC_IMPL_TC_CorbaFS_DirEntSeq_2 == 'r') \
++&& (TC_IMPL_TC_CorbaFS_DirEntSeq_3 == 'b') \
++&& (TC_IMPL_TC_CorbaFS_DirEntSeq_4 == 'a') \
++&& (TC_IMPL_TC_CorbaFS_DirEntSeq_5 == 'F') \
++&& (TC_IMPL_TC_CorbaFS_DirEntSeq_6 == 'S') \
++) && !defined(TC_DEF_TC_CorbaFS_DirEntSeq)
++#define TC_DEF_TC_CorbaFS_DirEntSeq 1
++static const CORBA_TypeCode anon_subtypes_array19[] =
++ { (CORBA_TypeCode) & TC_CORBA_sequence_CorbaFS_dirent_struct };
++const struct CORBA_TypeCode_struct TC_CorbaFS_DirEntSeq_struct = {
++
++ {{(ORBit_RootObject_Interface *) & ORBit_TypeCode_epv, TRUE, -1},
++ ORBIT_PSEUDO_TYPECODE},
++
++ CORBA_tk_alias, "DirEntSeq", "IDL:CorbaFS/DirEntSeq:1.0",
++ 0, 1,
++ NULL,
++ (CORBA_TypeCode *) anon_subtypes_array19,
++ NULL,
++ CORBA_OBJECT_NIL, 0, -1, 0, 0
++};
++#endif
++#if ( (TC_IMPL_TC_CORBA_sequence_CORBA_octet_0 == 'C') \
++&& (TC_IMPL_TC_CORBA_sequence_CORBA_octet_1 == 'o') \
++&& (TC_IMPL_TC_CORBA_sequence_CORBA_octet_2 == 'r') \
++&& (TC_IMPL_TC_CORBA_sequence_CORBA_octet_3 == 'b') \
++&& (TC_IMPL_TC_CORBA_sequence_CORBA_octet_4 == 'a') \
++&& (TC_IMPL_TC_CORBA_sequence_CORBA_octet_5 == 'F') \
++&& (TC_IMPL_TC_CORBA_sequence_CORBA_octet_6 == 'S') \
++) && !defined(TC_DEF_TC_CORBA_sequence_CORBA_octet)
++#define TC_DEF_TC_CORBA_sequence_CORBA_octet 1
++static const CORBA_TypeCode anon_subtypes_array23[] =
++ { (CORBA_TypeCode) & TC_CORBA_octet_struct };
++const struct CORBA_TypeCode_struct TC_CORBA_sequence_CORBA_octet_struct = {
++
++ {{(ORBit_RootObject_Interface *) & ORBit_TypeCode_epv, TRUE, -1},
++ ORBIT_PSEUDO_TYPECODE},
++
++ CORBA_tk_sequence, NULL, NULL,
++ 0, 1,
++ NULL,
++ (CORBA_TypeCode *) anon_subtypes_array23,
++ NULL,
++ CORBA_OBJECT_NIL, 0, -1, 0, 0
++};
++#endif
++#if ( (TC_IMPL_TC_CORBA_sequence_CORBA_octet_0 == 'C') \
++&& (TC_IMPL_TC_CORBA_sequence_CORBA_octet_1 == 'o') \
++&& (TC_IMPL_TC_CORBA_sequence_CORBA_octet_2 == 'r') \
++&& (TC_IMPL_TC_CORBA_sequence_CORBA_octet_3 == 'b') \
++&& (TC_IMPL_TC_CORBA_sequence_CORBA_octet_4 == 'a') \
++&& (TC_IMPL_TC_CORBA_sequence_CORBA_octet_5 == 'F') \
++&& (TC_IMPL_TC_CORBA_sequence_CORBA_octet_6 == 'S') \
++) && !defined(TC_DEF_TC_CORBA_sequence_CORBA_octet)
++#define TC_DEF_TC_CORBA_sequence_CORBA_octet 1
++static const CORBA_TypeCode anon_subtypes_array32[] =
++ { (CORBA_TypeCode) & TC_CORBA_octet_struct };
++const struct CORBA_TypeCode_struct TC_CORBA_sequence_CORBA_octet_struct = {
++
++ {{(ORBit_RootObject_Interface *) & ORBit_TypeCode_epv, TRUE, -1},
++ ORBIT_PSEUDO_TYPECODE},
++
++ CORBA_tk_sequence, NULL, NULL,
++ 0, 1,
++ NULL,
++ (CORBA_TypeCode *) anon_subtypes_array32,
++ NULL,
++ CORBA_OBJECT_NIL, 0, -1, 0, 0
++};
++#endif
++#if ( (TC_IMPL_TC_CorbaFS_Buffer_0 == 'C') \
++&& (TC_IMPL_TC_CorbaFS_Buffer_1 == 'o') \
++&& (TC_IMPL_TC_CorbaFS_Buffer_2 == 'r') \
++&& (TC_IMPL_TC_CorbaFS_Buffer_3 == 'b') \
++&& (TC_IMPL_TC_CorbaFS_Buffer_4 == 'a') \
++&& (TC_IMPL_TC_CorbaFS_Buffer_5 == 'F') \
++&& (TC_IMPL_TC_CorbaFS_Buffer_6 == 'S') \
++) && !defined(TC_DEF_TC_CorbaFS_Buffer)
++#define TC_DEF_TC_CorbaFS_Buffer 1
++static const CORBA_TypeCode anon_subtypes_array36[] =
++ { (CORBA_TypeCode) & TC_CORBA_sequence_CORBA_octet_struct };
++const struct CORBA_TypeCode_struct TC_CorbaFS_Buffer_struct = {
++
++ {{(ORBit_RootObject_Interface *) & ORBit_TypeCode_epv, TRUE, -1},
++ ORBIT_PSEUDO_TYPECODE},
++
++ CORBA_tk_alias, "Buffer", "IDL:CorbaFS/Buffer:1.0",
++ 0, 1,
++ NULL,
++ (CORBA_TypeCode *) anon_subtypes_array36,
++ NULL,
++ CORBA_OBJECT_NIL, 0, -1, 0, 0
++};
++#endif
++#if ( (TC_IMPL_TC_CorbaFS_Inode_0 == 'C') \
++&& (TC_IMPL_TC_CorbaFS_Inode_1 == 'o') \
++&& (TC_IMPL_TC_CorbaFS_Inode_2 == 'r') \
++&& (TC_IMPL_TC_CorbaFS_Inode_3 == 'b') \
++&& (TC_IMPL_TC_CorbaFS_Inode_4 == 'a') \
++&& (TC_IMPL_TC_CorbaFS_Inode_5 == 'F') \
++&& (TC_IMPL_TC_CorbaFS_Inode_6 == 'S') \
++) && !defined(TC_DEF_TC_CorbaFS_Inode)
++#define TC_DEF_TC_CorbaFS_Inode 1
++const struct CORBA_TypeCode_struct TC_CorbaFS_Inode_struct = {
++
++ {{(ORBit_RootObject_Interface *) & ORBit_TypeCode_epv, TRUE, -1},
++ ORBIT_PSEUDO_TYPECODE},
++
++ CORBA_tk_objref, "Inode", "IDL:CorbaFS/Inode:1.0",
++ 0, 0,
++ NULL,
++ NULL,
++ NULL,
++ CORBA_OBJECT_NIL, 0, -1, 0, 0
++};
++#endif
++#if ( (TC_IMPL_TC_CorbaFS_FileSystem_0 == 'C') \
++&& (TC_IMPL_TC_CorbaFS_FileSystem_1 == 'o') \
++&& (TC_IMPL_TC_CorbaFS_FileSystem_2 == 'r') \
++&& (TC_IMPL_TC_CorbaFS_FileSystem_3 == 'b') \
++&& (TC_IMPL_TC_CorbaFS_FileSystem_4 == 'a') \
++&& (TC_IMPL_TC_CorbaFS_FileSystem_5 == 'F') \
++&& (TC_IMPL_TC_CorbaFS_FileSystem_6 == 'S') \
++) && !defined(TC_DEF_TC_CorbaFS_FileSystem)
++#define TC_DEF_TC_CorbaFS_FileSystem 1
++const struct CORBA_TypeCode_struct TC_CorbaFS_FileSystem_struct = {
++
++ {{(ORBit_RootObject_Interface *) & ORBit_TypeCode_epv, TRUE, -1},
++ ORBIT_PSEUDO_TYPECODE},
++
++ CORBA_tk_objref, "FileSystem", "IDL:CorbaFS/FileSystem:1.0",
++ 0, 0,
++ NULL,
++ NULL,
++ NULL,
++ CORBA_OBJECT_NIL, 0, -1, 0, 0
++};
++#endif
++gpointer
++CorbaFS_dirent__free(gpointer mem, gpointer dat, CORBA_boolean free_strings)
++{
++ CorbaFS_dirent *var = mem;
++
++ if (free_strings) {
++ CORBA_string__free(&(var->name), NULL, free_strings);
++ }
++ return (gpointer) (var + 1);
++}
++
++CorbaFS_dirent *
++CorbaFS_dirent__alloc(void)
++{
++ CorbaFS_dirent *retval;
++
++ retval =
++ ORBit_alloc(sizeof(CorbaFS_dirent),
++ (ORBit_free_childvals) CorbaFS_dirent__free,
++ GUINT_TO_POINTER(1));
++ memset(&(retval->name), '\0', sizeof(retval->name));
++ return retval;
++}
++
++#if ( (ORBIT_IMPL_CORBA_sequence_CorbaFS_dirent_0 == 'C') \
++&& (ORBIT_IMPL_CORBA_sequence_CorbaFS_dirent_1 == 'o') \
++&& (ORBIT_IMPL_CORBA_sequence_CorbaFS_dirent_2 == 'r') \
++&& (ORBIT_IMPL_CORBA_sequence_CorbaFS_dirent_3 == 'b') \
++&& (ORBIT_IMPL_CORBA_sequence_CorbaFS_dirent_4 == 'a') \
++&& (ORBIT_IMPL_CORBA_sequence_CorbaFS_dirent_5 == 'F') \
++&& (ORBIT_IMPL_CORBA_sequence_CorbaFS_dirent_6 == 'S') \
++) && !defined(ORBIT_DEF_CORBA_sequence_CorbaFS_dirent)
++#define ORBIT_DEF_CORBA_sequence_CorbaFS_dirent 1
++
++gpointer
++CORBA_sequence_CorbaFS_dirent__free(gpointer mem, gpointer dat,
++ CORBA_boolean free_strings)
++{
++ CORBA_sequence_CorbaFS_dirent *val = mem;
++
++ if (val->_release)
++ ORBit_free(val->_buffer, free_strings);
++ return (gpointer) (val + 1);
++}
++
++CORBA_sequence_CorbaFS_dirent *
++CORBA_sequence_CorbaFS_dirent__alloc(void)
++{
++ CORBA_sequence_CorbaFS_dirent *retval;
++
++ retval =
++ ORBit_alloc(sizeof(CORBA_sequence_CorbaFS_dirent),
++ (ORBit_free_childvals) CORBA_sequence_CorbaFS_dirent__free,
++ GUINT_TO_POINTER(1));
++ retval->_maximum = 0;
++ retval->_length = 0;
++ retval->_buffer = NULL;
++ retval->_release = CORBA_FALSE;
++ return retval;
++}
++
++CorbaFS_dirent *
++CORBA_sequence_CorbaFS_dirent_allocbuf(CORBA_unsigned_long len)
++{
++ CorbaFS_dirent *retval =
++ ORBit_alloc(sizeof(CorbaFS_dirent) * len,
++ (ORBit_free_childvals) CorbaFS_dirent__free,
++ GUINT_TO_POINTER(len));
++
++ memset(retval, '\0', sizeof(CorbaFS_dirent) * len);
++ return retval;
++}
++#endif
++
++gpointer
++CorbaFS_DirEntSeq__free(gpointer mem, gpointer dat,
++ CORBA_boolean free_strings)
++{
++ return CORBA_sequence_CorbaFS_dirent__free(mem, dat, free_strings);
++}
++
++CorbaFS_DirEntSeq *
++CorbaFS_DirEntSeq__alloc(void)
++{
++ return CORBA_sequence_CorbaFS_dirent__alloc();
++}
++
++#if ( (ORBIT_IMPL_CORBA_sequence_CORBA_octet_0 == 'C') \
++&& (ORBIT_IMPL_CORBA_sequence_CORBA_octet_1 == 'o') \
++&& (ORBIT_IMPL_CORBA_sequence_CORBA_octet_2 == 'r') \
++&& (ORBIT_IMPL_CORBA_sequence_CORBA_octet_3 == 'b') \
++&& (ORBIT_IMPL_CORBA_sequence_CORBA_octet_4 == 'a') \
++&& (ORBIT_IMPL_CORBA_sequence_CORBA_octet_5 == 'F') \
++&& (ORBIT_IMPL_CORBA_sequence_CORBA_octet_6 == 'S') \
++) && !defined(ORBIT_DEF_CORBA_sequence_CORBA_octet)
++#define ORBIT_DEF_CORBA_sequence_CORBA_octet 1
++
++gpointer
++CORBA_sequence_CORBA_octet__free(gpointer mem, gpointer dat,
++ CORBA_boolean free_strings)
++{
++ CORBA_sequence_CORBA_octet *val = mem;
++
++ if (val->_release)
++ ORBit_free(val->_buffer, free_strings);
++ return (gpointer) (val + 1);
++}
++
++CORBA_sequence_CORBA_octet *
++CORBA_sequence_CORBA_octet__alloc(void)
++{
++ CORBA_sequence_CORBA_octet *retval;
++
++ retval =
++ ORBit_alloc(sizeof(CORBA_sequence_CORBA_octet),
++ (ORBit_free_childvals) CORBA_sequence_CORBA_octet__free,
++ GUINT_TO_POINTER(1));
++ retval->_maximum = 0;
++ retval->_length = 0;
++ retval->_buffer = NULL;
++ retval->_release = CORBA_FALSE;
++ return retval;
++}
++
++CORBA_octet *
++CORBA_sequence_CORBA_octet_allocbuf(CORBA_unsigned_long len)
++{
++ CORBA_octet *retval =
++ ORBit_alloc(sizeof(CORBA_octet) * len, (ORBit_free_childvals) NULL,
++ GUINT_TO_POINTER(len));
++
++ return retval;
++}
++#endif
++
++gpointer
++CorbaFS_Buffer__free(gpointer mem, gpointer dat, CORBA_boolean free_strings)
++{
++ return CORBA_sequence_CORBA_octet__free(mem, dat, free_strings);
++}
++
++CorbaFS_Buffer *
++CorbaFS_Buffer__alloc(void)
++{
++ return CORBA_sequence_CORBA_octet__alloc();
++}
++
++CORBA_unsigned_long CorbaFS_Inode__classid = 0;
++CORBA_unsigned_long CorbaFS_FileSystem__classid = 0;
+diff -urN linux-2.4.1/net/korbit/modules/CorbaFS/client/CorbaFS-stubs.c linux-2.4.1-korbit/net/korbit/modules/CorbaFS/client/CorbaFS-stubs.c
+--- linux-2.4.1/net/korbit/modules/CorbaFS/client/CorbaFS-stubs.c Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/CorbaFS/client/CorbaFS-stubs.c Thu Feb 1 16:36:08 2001
+@@ -0,0 +1,791 @@
++/*
++ * This file was generated by orbit-idl - DO NOT EDIT!
++ */
++
++#include <string.h>
++#include "CorbaFS.h"
++
++void
++CorbaFS_Inode_getStatus(CorbaFS_Inode _obj, CORBA_unsigned_short * mode,
++ CORBA_unsigned_long * uid, CORBA_unsigned_long * gid,
++ CORBA_unsigned_long * size,
++ CORBA_unsigned_long * inodeNum,
++ CORBA_unsigned_short * numLinks, CORBA_long * atime,
++ CORBA_long * mtime, CORBA_long * ctime,
++ CORBA_Environment * ev)
++{
++ register GIOP_unsigned_long _ORBIT_request_id,
++ _ORBIT_system_exception_minor;
++ register CORBA_completion_status _ORBIT_completion_status;
++ register GIOPSendBuffer *_ORBIT_send_buffer;
++ register GIOPRecvBuffer *_ORBIT_recv_buffer;
++ register GIOPConnection *_cnx;
++
++ if (_obj->servant && _obj->vepv && CorbaFS_Inode__classid) {
++
++ ((POA_CorbaFS_Inode__epv *) _obj->vepv[CorbaFS_Inode__classid])->
++ getStatus(_obj->servant, mode, uid, gid, size, inodeNum, numLinks,
++ atime, mtime, ctime, ev);
++ return;
++ }
++ _cnx = ORBit_object_get_connection(_obj);
++ _ORBIT_retry_request:
++ _ORBIT_send_buffer = NULL;
++ _ORBIT_recv_buffer = NULL;
++ _ORBIT_completion_status = CORBA_COMPLETED_NO;
++ _ORBIT_request_id = GPOINTER_TO_UINT(alloca(0));
++ { /* marshalling */
++ static const struct
++ {
++ CORBA_unsigned_long len;
++ char opname[10];
++ }
++ _ORBIT_operation_name_data =
++ {
++ 10, "getStatus"};
++ static const struct iovec _ORBIT_operation_vec =
++ { (gpointer) & _ORBIT_operation_name_data, 14 };
++
++ _ORBIT_send_buffer =
++ giop_send_request_buffer_use(_cnx, NULL, _ORBIT_request_id,
++ CORBA_TRUE,
++ &(_obj->active_profile->object_key_vec),
++ &_ORBIT_operation_vec,
++ &ORBit_default_principal_iovec);
++
++ _ORBIT_system_exception_minor = ex_CORBA_COMM_FAILURE;
++ if (!_ORBIT_send_buffer)
++ goto _ORBIT_system_exception;
++ giop_send_buffer_write(_ORBIT_send_buffer);
++ _ORBIT_completion_status = CORBA_COMPLETED_MAYBE;
++ giop_send_buffer_unuse(_ORBIT_send_buffer);
++ _ORBIT_send_buffer = NULL;
++ }
++ { /* demarshalling */
++ register guchar *_ORBIT_curptr;
++
++ _ORBIT_recv_buffer =
++ giop_recv_reply_buffer_use_2(_cnx, _ORBIT_request_id, TRUE);
++ if (!_ORBIT_recv_buffer)
++ goto _ORBIT_system_exception;
++ _ORBIT_completion_status = CORBA_COMPLETED_YES;
++ if (_ORBIT_recv_buffer->message.u.reply.reply_status !=
++ GIOP_NO_EXCEPTION) goto _ORBIT_msg_exception;
++ _ORBIT_curptr = GIOP_RECV_BUFFER(_ORBIT_recv_buffer)->cur;
++ if (giop_msg_conversion_needed(GIOP_MESSAGE_BUFFER(_ORBIT_recv_buffer))) {
++ _ORBIT_curptr = ALIGN_ADDRESS(_ORBIT_curptr, 2);
++
++ (*((guint16 *) & ((*mode)))) =
++ GUINT16_SWAP_LE_BE(*((guint16 *) _ORBIT_curptr));
++ _ORBIT_curptr += 2;
++ _ORBIT_curptr = ALIGN_ADDRESS(_ORBIT_curptr, 4);
++
++ (*((guint32 *) & ((*uid)))) =
++ GUINT32_SWAP_LE_BE(*((guint32 *) _ORBIT_curptr));
++ _ORBIT_curptr += 4;
++ (*((guint32 *) & ((*gid)))) =
++ GUINT32_SWAP_LE_BE(*((guint32 *) _ORBIT_curptr));
++ _ORBIT_curptr += 4;
++ (*((guint32 *) & ((*size)))) =
++ GUINT32_SWAP_LE_BE(*((guint32 *) _ORBIT_curptr));
++ _ORBIT_curptr += 4;
++ (*((guint32 *) & ((*inodeNum)))) =
++ GUINT32_SWAP_LE_BE(*((guint32 *) _ORBIT_curptr));
++ _ORBIT_curptr += 4;
++ (*((guint16 *) & ((*numLinks)))) =
++ GUINT16_SWAP_LE_BE(*((guint16 *) _ORBIT_curptr));
++ _ORBIT_curptr += 2;
++ _ORBIT_curptr = ALIGN_ADDRESS(_ORBIT_curptr, 4);
++
++ (*((guint32 *) & ((*atime)))) =
++ GUINT32_SWAP_LE_BE(*((guint32 *) _ORBIT_curptr));
++ _ORBIT_curptr += 4;
++ (*((guint32 *) & ((*mtime)))) =
++ GUINT32_SWAP_LE_BE(*((guint32 *) _ORBIT_curptr));
++ _ORBIT_curptr += 4;
++ (*((guint32 *) & ((*ctime)))) =
++ GUINT32_SWAP_LE_BE(*((guint32 *) _ORBIT_curptr));} else {
++ _ORBIT_curptr = ALIGN_ADDRESS(_ORBIT_curptr, 2);
++ (*mode) = *((CORBA_unsigned_short *) _ORBIT_curptr);
++ _ORBIT_curptr += 2;
++ _ORBIT_curptr = ALIGN_ADDRESS(_ORBIT_curptr, 4);
++ (*uid) = *((CORBA_unsigned_long *) _ORBIT_curptr);
++ _ORBIT_curptr += 4;
++ (*gid) = *((CORBA_unsigned_long *) _ORBIT_curptr);
++ _ORBIT_curptr += 4;
++ (*size) = *((CORBA_unsigned_long *) _ORBIT_curptr);
++ _ORBIT_curptr += 4;
++ (*inodeNum) = *((CORBA_unsigned_long *) _ORBIT_curptr);
++ _ORBIT_curptr += 4;
++ (*numLinks) = *((CORBA_unsigned_short *) _ORBIT_curptr);
++ _ORBIT_curptr += 2;
++ _ORBIT_curptr = ALIGN_ADDRESS(_ORBIT_curptr, 4);
++ (*atime) = *((CORBA_long *) _ORBIT_curptr);
++ _ORBIT_curptr += 4;
++ (*mtime) = *((CORBA_long *) _ORBIT_curptr);
++ _ORBIT_curptr += 4;
++ (*ctime) = *((CORBA_long *) _ORBIT_curptr);
++ }
++ giop_recv_buffer_unuse(_ORBIT_recv_buffer);
++ return;
++ _ORBIT_system_exception:
++ CORBA_exception_set_system(ev, _ORBIT_system_exception_minor,
++ _ORBIT_completion_status);
++ giop_recv_buffer_unuse(_ORBIT_recv_buffer);
++ giop_send_buffer_unuse(_ORBIT_send_buffer);
++ return;
++ _ORBIT_msg_exception:
++ if (_ORBIT_recv_buffer->message.u.reply.reply_status ==
++ GIOP_LOCATION_FORWARD) {
++ if (_obj->forward_locations != NULL)
++ ORBit_delete_profiles(_obj->forward_locations);
++ _obj->forward_locations = ORBit_demarshal_IOR(_ORBIT_recv_buffer);
++ _cnx = ORBit_object_get_forwarded_connection(_obj);
++ giop_recv_buffer_unuse(_ORBIT_recv_buffer);
++
++ goto _ORBIT_retry_request;
++ } else {
++ ORBit_handle_exception(_ORBIT_recv_buffer, ev, NULL, _obj->orb);
++ giop_recv_buffer_unuse(_ORBIT_recv_buffer);
++ return;
++ }
++ }
++}
++void
++CorbaFS_Inode_readpage(CorbaFS_Inode _obj, CorbaFS_Buffer ** buffer,
++ const CORBA_long size, const CORBA_long offset,
++ CORBA_Environment * ev)
++{
++ register GIOP_unsigned_long _ORBIT_request_id,
++ _ORBIT_system_exception_minor;
++ register CORBA_completion_status _ORBIT_completion_status;
++ register GIOPSendBuffer *_ORBIT_send_buffer;
++ register GIOPRecvBuffer *_ORBIT_recv_buffer;
++ register GIOPConnection *_cnx;
++ register CORBA_unsigned_long _ORBIT_tmpvar_1;
++
++ if (_obj->servant && _obj->vepv && CorbaFS_Inode__classid) {
++
++ ((POA_CorbaFS_Inode__epv *) _obj->vepv[CorbaFS_Inode__classid])->
++ readpage(_obj->servant, buffer, size, offset, ev);
++ return;
++ }
++ _cnx = ORBit_object_get_connection(_obj);
++ _ORBIT_retry_request:
++ _ORBIT_send_buffer = NULL;
++ _ORBIT_recv_buffer = NULL;
++ _ORBIT_completion_status = CORBA_COMPLETED_NO;
++ _ORBIT_request_id = GPOINTER_TO_UINT(alloca(0));
++ { /* marshalling */
++ static const struct
++ {
++ CORBA_unsigned_long len;
++ char opname[9];
++ }
++ _ORBIT_operation_name_data =
++ {
++ 9, "readpage"};
++ static const struct iovec _ORBIT_operation_vec =
++ { (gpointer) & _ORBIT_operation_name_data, 13 };
++
++ _ORBIT_send_buffer =
++ giop_send_request_buffer_use(_cnx, NULL, _ORBIT_request_id,
++ CORBA_TRUE,
++ &(_obj->active_profile->object_key_vec),
++ &_ORBIT_operation_vec,
++ &ORBit_default_principal_iovec);
++
++ _ORBIT_system_exception_minor = ex_CORBA_COMM_FAILURE;
++ if (!_ORBIT_send_buffer)
++ goto _ORBIT_system_exception;
++ giop_message_buffer_do_alignment(GIOP_MESSAGE_BUFFER
++ (_ORBIT_send_buffer), 4);
++ giop_message_buffer_append_mem(GIOP_MESSAGE_BUFFER(_ORBIT_send_buffer),
++ &(size), sizeof(size));
++ giop_message_buffer_append_mem(GIOP_MESSAGE_BUFFER(_ORBIT_send_buffer),
++ &(offset), sizeof(offset));
++ giop_send_buffer_write(_ORBIT_send_buffer);
++ _ORBIT_completion_status = CORBA_COMPLETED_MAYBE;
++ giop_send_buffer_unuse(_ORBIT_send_buffer);
++ _ORBIT_send_buffer = NULL;
++ }
++ { /* demarshalling */
++ register guchar *_ORBIT_curptr;
++
++ _ORBIT_recv_buffer =
++ giop_recv_reply_buffer_use_2(_cnx, _ORBIT_request_id, TRUE);
++ if (!_ORBIT_recv_buffer)
++ goto _ORBIT_system_exception;
++ _ORBIT_completion_status = CORBA_COMPLETED_YES;
++ if (_ORBIT_recv_buffer->message.u.reply.reply_status !=
++ GIOP_NO_EXCEPTION) goto _ORBIT_msg_exception;
++ *buffer = CorbaFS_Buffer__alloc();
++ _ORBIT_curptr = GIOP_RECV_BUFFER(_ORBIT_recv_buffer)->cur;
++ if (giop_msg_conversion_needed(GIOP_MESSAGE_BUFFER(_ORBIT_recv_buffer))) {
++ _ORBIT_curptr = ALIGN_ADDRESS(_ORBIT_curptr, 4);
++
++ (*((guint32 *) & (((**buffer))._length))) =
++ GUINT32_SWAP_LE_BE(*((guint32 *) _ORBIT_curptr));
++ _ORBIT_curptr += 4;
++
++ ((**buffer))._buffer =
++ CORBA_sequence_CORBA_octet_allocbuf(((**buffer))._length);
++ ((**buffer))._release = CORBA_TRUE;
++ memcpy(((**buffer))._buffer, _ORBIT_curptr,
++ sizeof(((**buffer))._buffer[_ORBIT_tmpvar_1]) *
++ ((**buffer))._length);
++ _ORBIT_curptr +=
++ sizeof(((**buffer))._buffer[_ORBIT_tmpvar_1]) *
++ ((**buffer))._length;
++ } else {
++ _ORBIT_curptr = ALIGN_ADDRESS(_ORBIT_curptr, 4);
++ ((**buffer))._length = *((CORBA_unsigned_long *) _ORBIT_curptr);
++ _ORBIT_curptr += 4;
++
++ ((**buffer))._buffer =
++ CORBA_sequence_CORBA_octet_allocbuf(((**buffer))._length);
++ ((**buffer))._release = CORBA_TRUE;
++ memcpy(((**buffer))._buffer, _ORBIT_curptr,
++ sizeof(((**buffer))._buffer[_ORBIT_tmpvar_1]) *
++ ((**buffer))._length);
++ _ORBIT_curptr +=
++ sizeof(((**buffer))._buffer[_ORBIT_tmpvar_1]) *
++ ((**buffer))._length;
++ }
++ giop_recv_buffer_unuse(_ORBIT_recv_buffer);
++ return;
++ _ORBIT_system_exception:
++ CORBA_exception_set_system(ev, _ORBIT_system_exception_minor,
++ _ORBIT_completion_status);
++ giop_recv_buffer_unuse(_ORBIT_recv_buffer);
++ giop_send_buffer_unuse(_ORBIT_send_buffer);
++ return;
++ _ORBIT_msg_exception:
++ if (_ORBIT_recv_buffer->message.u.reply.reply_status ==
++ GIOP_LOCATION_FORWARD) {
++ if (_obj->forward_locations != NULL)
++ ORBit_delete_profiles(_obj->forward_locations);
++ _obj->forward_locations = ORBit_demarshal_IOR(_ORBIT_recv_buffer);
++ _cnx = ORBit_object_get_forwarded_connection(_obj);
++ giop_recv_buffer_unuse(_ORBIT_recv_buffer);
++
++ goto _ORBIT_retry_request;
++ } else {
++ ORBit_handle_exception(_ORBIT_recv_buffer, ev, NULL, _obj->orb);
++ giop_recv_buffer_unuse(_ORBIT_recv_buffer);
++ return;
++ }
++ }
++}
++void
++CorbaFS_Inode_release(CorbaFS_Inode _obj, CORBA_Environment * ev)
++{
++ register GIOP_unsigned_long _ORBIT_request_id,
++ _ORBIT_system_exception_minor;
++ register CORBA_completion_status _ORBIT_completion_status;
++ register GIOPSendBuffer *_ORBIT_send_buffer;
++ register GIOPRecvBuffer *_ORBIT_recv_buffer;
++ register GIOPConnection *_cnx;
++
++ if (_obj->servant && _obj->vepv && CorbaFS_Inode__classid) {
++
++ ((POA_CorbaFS_Inode__epv *) _obj->vepv[CorbaFS_Inode__classid])->
++ release(_obj->servant, ev);
++ return;
++ }
++ _cnx = ORBit_object_get_connection(_obj);
++ _ORBIT_retry_request:
++ _ORBIT_send_buffer = NULL;
++ _ORBIT_recv_buffer = NULL;
++ _ORBIT_completion_status = CORBA_COMPLETED_NO;
++ _ORBIT_request_id = GPOINTER_TO_UINT(alloca(0));
++ { /* marshalling */
++ static const struct
++ {
++ CORBA_unsigned_long len;
++ char opname[8];
++ }
++ _ORBIT_operation_name_data =
++ {
++ 8, "release"};
++ static const struct iovec _ORBIT_operation_vec =
++ { (gpointer) & _ORBIT_operation_name_data, 12 };
++
++ _ORBIT_send_buffer =
++ giop_send_request_buffer_use(_cnx, NULL, _ORBIT_request_id,
++ CORBA_TRUE,
++ &(_obj->active_profile->object_key_vec),
++ &_ORBIT_operation_vec,
++ &ORBit_default_principal_iovec);
++
++ _ORBIT_system_exception_minor = ex_CORBA_COMM_FAILURE;
++ if (!_ORBIT_send_buffer)
++ goto _ORBIT_system_exception;
++ giop_send_buffer_write(_ORBIT_send_buffer);
++ _ORBIT_completion_status = CORBA_COMPLETED_MAYBE;
++ giop_send_buffer_unuse(_ORBIT_send_buffer);
++ _ORBIT_send_buffer = NULL;
++ }
++ { /* demarshalling */
++ register guchar *_ORBIT_curptr;
++
++ _ORBIT_recv_buffer =
++ giop_recv_reply_buffer_use_2(_cnx, _ORBIT_request_id, TRUE);
++ if (!_ORBIT_recv_buffer)
++ goto _ORBIT_system_exception;
++ _ORBIT_completion_status = CORBA_COMPLETED_YES;
++ if (_ORBIT_recv_buffer->message.u.reply.reply_status !=
++ GIOP_NO_EXCEPTION) goto _ORBIT_msg_exception;
++ _ORBIT_curptr = GIOP_RECV_BUFFER(_ORBIT_recv_buffer)->cur;
++ if (giop_msg_conversion_needed(GIOP_MESSAGE_BUFFER(_ORBIT_recv_buffer))) {
++ } else {
++ }
++ giop_recv_buffer_unuse(_ORBIT_recv_buffer);
++ return;
++ _ORBIT_system_exception:
++ CORBA_exception_set_system(ev, _ORBIT_system_exception_minor,
++ _ORBIT_completion_status);
++ giop_recv_buffer_unuse(_ORBIT_recv_buffer);
++ giop_send_buffer_unuse(_ORBIT_send_buffer);
++ return;
++ _ORBIT_msg_exception:
++ if (_ORBIT_recv_buffer->message.u.reply.reply_status ==
++ GIOP_LOCATION_FORWARD) {
++ if (_obj->forward_locations != NULL)
++ ORBit_delete_profiles(_obj->forward_locations);
++ _obj->forward_locations = ORBit_demarshal_IOR(_ORBIT_recv_buffer);
++ _cnx = ORBit_object_get_forwarded_connection(_obj);
++ giop_recv_buffer_unuse(_ORBIT_recv_buffer);
++
++ goto _ORBIT_retry_request;
++ } else {
++ ORBit_handle_exception(_ORBIT_recv_buffer, ev, NULL, _obj->orb);
++ giop_recv_buffer_unuse(_ORBIT_recv_buffer);
++ return;
++ }
++ }
++}
++CorbaFS_Inode
++CorbaFS_FileSystem_getInode(CorbaFS_FileSystem _obj, const CORBA_char * path,
++ CORBA_Environment * ev)
++{
++ register GIOP_unsigned_long _ORBIT_request_id,
++ _ORBIT_system_exception_minor;
++ register CORBA_completion_status _ORBIT_completion_status;
++ register GIOPSendBuffer *_ORBIT_send_buffer;
++ register GIOPRecvBuffer *_ORBIT_recv_buffer;
++ register GIOPConnection *_cnx;
++ CorbaFS_Inode _ORBIT_retval;
++
++ if (_obj->servant && _obj->vepv && CorbaFS_FileSystem__classid) {
++ _ORBIT_retval =
++ ((POA_CorbaFS_FileSystem__epv *) _obj->
++ vepv[CorbaFS_FileSystem__classid])->getInode(_obj->servant, path,
++ ev);
++ return _ORBIT_retval;
++ }
++ _cnx = ORBit_object_get_connection(_obj);
++ _ORBIT_retry_request:
++ _ORBIT_send_buffer = NULL;
++ _ORBIT_recv_buffer = NULL;
++ _ORBIT_completion_status = CORBA_COMPLETED_NO;
++ _ORBIT_request_id = GPOINTER_TO_UINT(alloca(0));
++ { /* marshalling */
++ static const struct
++ {
++ CORBA_unsigned_long len;
++ char opname[9];
++ }
++ _ORBIT_operation_name_data =
++ {
++ 9, "getInode"};
++ static const struct iovec _ORBIT_operation_vec =
++ { (gpointer) & _ORBIT_operation_name_data, 13 };
++ register CORBA_unsigned_long _ORBIT_tmpvar_0;
++ CORBA_unsigned_long _ORBIT_tmpvar_1;
++
++ _ORBIT_send_buffer =
++ giop_send_request_buffer_use(_cnx, NULL, _ORBIT_request_id,
++ CORBA_TRUE,
++ &(_obj->active_profile->object_key_vec),
++ &_ORBIT_operation_vec,
++ &ORBit_default_principal_iovec);
++
++ _ORBIT_system_exception_minor = ex_CORBA_COMM_FAILURE;
++ if (!_ORBIT_send_buffer)
++ goto _ORBIT_system_exception;
++ _ORBIT_tmpvar_1 = strlen(path) + 1;
++ giop_message_buffer_do_alignment(GIOP_MESSAGE_BUFFER
++ (_ORBIT_send_buffer), 4);
++ {
++ guchar *_ORBIT_t;
++
++ _ORBIT_t = alloca(sizeof(_ORBIT_tmpvar_1));
++ memcpy(_ORBIT_t, &(_ORBIT_tmpvar_1), sizeof(_ORBIT_tmpvar_1));
++ giop_message_buffer_append_mem(GIOP_MESSAGE_BUFFER
++ (_ORBIT_send_buffer), (_ORBIT_t),
++ sizeof(_ORBIT_tmpvar_1));
++ }
++ giop_message_buffer_append_mem(GIOP_MESSAGE_BUFFER(_ORBIT_send_buffer),
++ (path),
++ sizeof(path[_ORBIT_tmpvar_0]) *
++ _ORBIT_tmpvar_1);
++ giop_send_buffer_write(_ORBIT_send_buffer);
++ _ORBIT_completion_status = CORBA_COMPLETED_MAYBE;
++ giop_send_buffer_unuse(_ORBIT_send_buffer);
++ _ORBIT_send_buffer = NULL;
++ }
++ { /* demarshalling */
++ register guchar *_ORBIT_curptr;
++
++ _ORBIT_recv_buffer =
++ giop_recv_reply_buffer_use_2(_cnx, _ORBIT_request_id, TRUE);
++ if (!_ORBIT_recv_buffer)
++ goto _ORBIT_system_exception;
++ _ORBIT_completion_status = CORBA_COMPLETED_YES;
++ if (_ORBIT_recv_buffer->message.u.reply.reply_status !=
++ GIOP_NO_EXCEPTION) goto _ORBIT_msg_exception;
++ _ORBIT_curptr = GIOP_RECV_BUFFER(_ORBIT_recv_buffer)->cur;
++ if (giop_msg_conversion_needed(GIOP_MESSAGE_BUFFER(_ORBIT_recv_buffer))) {
++ GIOP_RECV_BUFFER(_ORBIT_recv_buffer)->cur = _ORBIT_curptr;
++ _ORBIT_retval =
++ ORBit_demarshal_object(_ORBIT_recv_buffer,
++ GIOP_MESSAGE_BUFFER(_ORBIT_recv_buffer)->
++ connection->orb_data);
++ _ORBIT_curptr = GIOP_RECV_BUFFER(_ORBIT_recv_buffer)->cur;
++ } else {
++ GIOP_RECV_BUFFER(_ORBIT_recv_buffer)->cur = _ORBIT_curptr;
++ _ORBIT_retval =
++ ORBit_demarshal_object(_ORBIT_recv_buffer,
++ GIOP_MESSAGE_BUFFER(_ORBIT_recv_buffer)->
++ connection->orb_data);
++ _ORBIT_curptr = GIOP_RECV_BUFFER(_ORBIT_recv_buffer)->cur;
++ }
++ giop_recv_buffer_unuse(_ORBIT_recv_buffer);
++ return _ORBIT_retval;
++ _ORBIT_system_exception:
++ CORBA_exception_set_system(ev, _ORBIT_system_exception_minor,
++ _ORBIT_completion_status);
++ giop_recv_buffer_unuse(_ORBIT_recv_buffer);
++ giop_send_buffer_unuse(_ORBIT_send_buffer);
++ return _ORBIT_retval;
++ _ORBIT_msg_exception:
++ if (_ORBIT_recv_buffer->message.u.reply.reply_status ==
++ GIOP_LOCATION_FORWARD) {
++ if (_obj->forward_locations != NULL)
++ ORBit_delete_profiles(_obj->forward_locations);
++ _obj->forward_locations = ORBit_demarshal_IOR(_ORBIT_recv_buffer);
++ _cnx = ORBit_object_get_forwarded_connection(_obj);
++ giop_recv_buffer_unuse(_ORBIT_recv_buffer);
++
++ goto _ORBIT_retry_request;
++ } else {
++ ORBit_handle_exception(_ORBIT_recv_buffer, ev, NULL, _obj->orb);
++ giop_recv_buffer_unuse(_ORBIT_recv_buffer);
++ return _ORBIT_retval;
++ }
++ }
++}
++CorbaFS_DirEntSeq *
++CorbaFS_FileSystem_readdir(CorbaFS_FileSystem _obj, const CORBA_char * path,
++ CORBA_Environment * ev)
++{
++ register GIOP_unsigned_long _ORBIT_request_id,
++ _ORBIT_system_exception_minor;
++ register CORBA_completion_status _ORBIT_completion_status;
++ register GIOPSendBuffer *_ORBIT_send_buffer;
++ register GIOPRecvBuffer *_ORBIT_recv_buffer;
++ register GIOPConnection *_cnx;
++ CorbaFS_DirEntSeq *_ORBIT_retval;
++ register CORBA_unsigned_long _ORBIT_tmpvar_5;
++ register CORBA_unsigned_long _ORBIT_tmpvar_6;
++ CORBA_unsigned_long _ORBIT_tmpvar_7;
++
++ if (_obj->servant && _obj->vepv && CorbaFS_FileSystem__classid) {
++ _ORBIT_retval =
++ ((POA_CorbaFS_FileSystem__epv *) _obj->
++ vepv[CorbaFS_FileSystem__classid])->readdir(_obj->servant, path,
++ ev);
++ return _ORBIT_retval;
++ }
++ _cnx = ORBit_object_get_connection(_obj);
++ _ORBIT_retry_request:
++ _ORBIT_send_buffer = NULL;
++ _ORBIT_recv_buffer = NULL;
++ _ORBIT_completion_status = CORBA_COMPLETED_NO;
++ _ORBIT_request_id = GPOINTER_TO_UINT(alloca(0));
++ { /* marshalling */
++ static const struct
++ {
++ CORBA_unsigned_long len;
++ char opname[8];
++ }
++ _ORBIT_operation_name_data =
++ {
++ 8, "readdir"};
++ static const struct iovec _ORBIT_operation_vec =
++ { (gpointer) & _ORBIT_operation_name_data, 12 };
++ register CORBA_unsigned_long _ORBIT_tmpvar_0;
++ CORBA_unsigned_long _ORBIT_tmpvar_1;
++
++ _ORBIT_send_buffer =
++ giop_send_request_buffer_use(_cnx, NULL, _ORBIT_request_id,
++ CORBA_TRUE,
++ &(_obj->active_profile->object_key_vec),
++ &_ORBIT_operation_vec,
++ &ORBit_default_principal_iovec);
++
++ _ORBIT_system_exception_minor = ex_CORBA_COMM_FAILURE;
++ if (!_ORBIT_send_buffer)
++ goto _ORBIT_system_exception;
++ _ORBIT_tmpvar_1 = strlen(path) + 1;
++ giop_message_buffer_do_alignment(GIOP_MESSAGE_BUFFER
++ (_ORBIT_send_buffer), 4);
++ {
++ guchar *_ORBIT_t;
++
++ _ORBIT_t = alloca(sizeof(_ORBIT_tmpvar_1));
++ memcpy(_ORBIT_t, &(_ORBIT_tmpvar_1), sizeof(_ORBIT_tmpvar_1));
++ giop_message_buffer_append_mem(GIOP_MESSAGE_BUFFER
++ (_ORBIT_send_buffer), (_ORBIT_t),
++ sizeof(_ORBIT_tmpvar_1));
++ }
++ giop_message_buffer_append_mem(GIOP_MESSAGE_BUFFER(_ORBIT_send_buffer),
++ (path),
++ sizeof(path[_ORBIT_tmpvar_0]) *
++ _ORBIT_tmpvar_1);
++ giop_send_buffer_write(_ORBIT_send_buffer);
++ _ORBIT_completion_status = CORBA_COMPLETED_MAYBE;
++ giop_send_buffer_unuse(_ORBIT_send_buffer);
++ _ORBIT_send_buffer = NULL;
++ }
++ { /* demarshalling */
++ register guchar *_ORBIT_curptr;
++
++ _ORBIT_recv_buffer =
++ giop_recv_reply_buffer_use_2(_cnx, _ORBIT_request_id, TRUE);
++ if (!_ORBIT_recv_buffer)
++ goto _ORBIT_system_exception;
++ _ORBIT_completion_status = CORBA_COMPLETED_YES;
++ if (_ORBIT_recv_buffer->message.u.reply.reply_status !=
++ GIOP_NO_EXCEPTION) goto _ORBIT_msg_exception;
++ _ORBIT_retval = CorbaFS_DirEntSeq__alloc();
++ _ORBIT_curptr = GIOP_RECV_BUFFER(_ORBIT_recv_buffer)->cur;
++ if (giop_msg_conversion_needed(GIOP_MESSAGE_BUFFER(_ORBIT_recv_buffer))) {
++ _ORBIT_curptr = ALIGN_ADDRESS(_ORBIT_curptr, 4);
++
++ (*((guint32 *) & ((*_ORBIT_retval)._length))) =
++ GUINT32_SWAP_LE_BE(*((guint32 *) _ORBIT_curptr));
++ _ORBIT_curptr += 4;
++
++ (*_ORBIT_retval)._buffer =
++ CORBA_sequence_CorbaFS_dirent_allocbuf((*_ORBIT_retval)._length);
++ (*_ORBIT_retval)._release = CORBA_TRUE;
++ for (_ORBIT_tmpvar_5 = 0; _ORBIT_tmpvar_5 < (*_ORBIT_retval)._length;
++ _ORBIT_tmpvar_5++) {
++ _ORBIT_curptr = ALIGN_ADDRESS(_ORBIT_curptr, 4);
++
++ (*
++ ((guint32 *) &
++ ((*_ORBIT_retval)._buffer[_ORBIT_tmpvar_5].inode))) =
++GUINT32_SWAP_LE_BE(*((guint32 *) _ORBIT_curptr));
++ _ORBIT_curptr += 4;
++
++ (*((guint32 *) & (_ORBIT_tmpvar_7))) =
++ GUINT32_SWAP_LE_BE(*((guint32 *) _ORBIT_curptr));
++ _ORBIT_curptr += 4;
++
++ (*_ORBIT_retval)._buffer[_ORBIT_tmpvar_5].name =
++ CORBA_string_alloc(_ORBIT_tmpvar_7);
++ memcpy((*_ORBIT_retval)._buffer[_ORBIT_tmpvar_5].name,
++ _ORBIT_curptr,
++ sizeof((*_ORBIT_retval)._buffer[_ORBIT_tmpvar_5].
++ name[_ORBIT_tmpvar_6]) * _ORBIT_tmpvar_7);
++ _ORBIT_curptr +=
++ sizeof((*_ORBIT_retval)._buffer[_ORBIT_tmpvar_5].
++ name[_ORBIT_tmpvar_6]) * _ORBIT_tmpvar_7;
++ }
++
++ } else {
++ _ORBIT_curptr = ALIGN_ADDRESS(_ORBIT_curptr, 4);
++ (*_ORBIT_retval)._length = *((CORBA_unsigned_long *) _ORBIT_curptr);
++ _ORBIT_curptr += 4;
++
++ (*_ORBIT_retval)._buffer =
++ CORBA_sequence_CorbaFS_dirent_allocbuf((*_ORBIT_retval)._length);
++ (*_ORBIT_retval)._release = CORBA_TRUE;
++ for (_ORBIT_tmpvar_5 = 0; _ORBIT_tmpvar_5 < (*_ORBIT_retval)._length;
++ _ORBIT_tmpvar_5++) {
++ _ORBIT_curptr = ALIGN_ADDRESS(_ORBIT_curptr, 4);
++ (*_ORBIT_retval)._buffer[_ORBIT_tmpvar_5].inode = *((CORBA_long *) _ORBIT_curptr);
++ _ORBIT_curptr += 4;
++ _ORBIT_tmpvar_7 = *((CORBA_unsigned_long *) _ORBIT_curptr);
++ _ORBIT_curptr += 4;
++
++ (*_ORBIT_retval)._buffer[_ORBIT_tmpvar_5].name =
++ CORBA_string_alloc(_ORBIT_tmpvar_7);
++ memcpy((*_ORBIT_retval)._buffer[_ORBIT_tmpvar_5].name,
++ _ORBIT_curptr,
++ sizeof((*_ORBIT_retval)._buffer[_ORBIT_tmpvar_5].
++ name[_ORBIT_tmpvar_6]) * _ORBIT_tmpvar_7);
++ _ORBIT_curptr +=
++ sizeof((*_ORBIT_retval)._buffer[_ORBIT_tmpvar_5].
++ name[_ORBIT_tmpvar_6]) * _ORBIT_tmpvar_7;
++ }
++
++ }
++ giop_recv_buffer_unuse(_ORBIT_recv_buffer);
++ return _ORBIT_retval;
++ _ORBIT_system_exception:
++ CORBA_exception_set_system(ev, _ORBIT_system_exception_minor,
++ _ORBIT_completion_status);
++ giop_recv_buffer_unuse(_ORBIT_recv_buffer);
++ giop_send_buffer_unuse(_ORBIT_send_buffer);
++ return _ORBIT_retval;
++ _ORBIT_msg_exception:
++ if (_ORBIT_recv_buffer->message.u.reply.reply_status ==
++ GIOP_LOCATION_FORWARD) {
++ if (_obj->forward_locations != NULL)
++ ORBit_delete_profiles(_obj->forward_locations);
++ _obj->forward_locations = ORBit_demarshal_IOR(_ORBIT_recv_buffer);
++ _cnx = ORBit_object_get_forwarded_connection(_obj);
++ giop_recv_buffer_unuse(_ORBIT_recv_buffer);
++
++ goto _ORBIT_retry_request;
++ } else {
++ ORBit_handle_exception(_ORBIT_recv_buffer, ev, NULL, _obj->orb);
++ giop_recv_buffer_unuse(_ORBIT_recv_buffer);
++ return _ORBIT_retval;
++ }
++ }
++}
++CORBA_char *
++CorbaFS_FileSystem_readlink(CorbaFS_FileSystem _obj,
++ const CORBA_char * filename,
++ CORBA_Environment * ev)
++{
++ register GIOP_unsigned_long _ORBIT_request_id,
++ _ORBIT_system_exception_minor;
++ register CORBA_completion_status _ORBIT_completion_status;
++ register GIOPSendBuffer *_ORBIT_send_buffer;
++ register GIOPRecvBuffer *_ORBIT_recv_buffer;
++ register GIOPConnection *_cnx;
++ CORBA_char *_ORBIT_retval;
++ register CORBA_unsigned_long _ORBIT_tmpvar_4;
++ CORBA_unsigned_long _ORBIT_tmpvar_5;
++
++ if (_obj->servant && _obj->vepv && CorbaFS_FileSystem__classid) {
++ _ORBIT_retval =
++ ((POA_CorbaFS_FileSystem__epv *) _obj->
++ vepv[CorbaFS_FileSystem__classid])->readlink(_obj->servant,
++ filename, ev);
++ return _ORBIT_retval;
++ }
++ _cnx = ORBit_object_get_connection(_obj);
++ _ORBIT_retry_request:
++ _ORBIT_send_buffer = NULL;
++ _ORBIT_recv_buffer = NULL;
++ _ORBIT_completion_status = CORBA_COMPLETED_NO;
++ _ORBIT_request_id = GPOINTER_TO_UINT(alloca(0));
++ { /* marshalling */
++ static const struct
++ {
++ CORBA_unsigned_long len;
++ char opname[9];
++ }
++ _ORBIT_operation_name_data =
++ {
++ 9, "readlink"};
++ static const struct iovec _ORBIT_operation_vec =
++ { (gpointer) & _ORBIT_operation_name_data, 13 };
++ register CORBA_unsigned_long _ORBIT_tmpvar_0;
++ CORBA_unsigned_long _ORBIT_tmpvar_1;
++
++ _ORBIT_send_buffer =
++ giop_send_request_buffer_use(_cnx, NULL, _ORBIT_request_id,
++ CORBA_TRUE,
++ &(_obj->active_profile->object_key_vec),
++ &_ORBIT_operation_vec,
++ &ORBit_default_principal_iovec);
++
++ _ORBIT_system_exception_minor = ex_CORBA_COMM_FAILURE;
++ if (!_ORBIT_send_buffer)
++ goto _ORBIT_system_exception;
++ _ORBIT_tmpvar_1 = strlen(filename) + 1;
++ giop_message_buffer_do_alignment(GIOP_MESSAGE_BUFFER
++ (_ORBIT_send_buffer), 4);
++ {
++ guchar *_ORBIT_t;
++
++ _ORBIT_t = alloca(sizeof(_ORBIT_tmpvar_1));
++ memcpy(_ORBIT_t, &(_ORBIT_tmpvar_1), sizeof(_ORBIT_tmpvar_1));
++ giop_message_buffer_append_mem(GIOP_MESSAGE_BUFFER
++ (_ORBIT_send_buffer), (_ORBIT_t),
++ sizeof(_ORBIT_tmpvar_1));
++ }
++ giop_message_buffer_append_mem(GIOP_MESSAGE_BUFFER(_ORBIT_send_buffer),
++ (filename),
++ sizeof(filename[_ORBIT_tmpvar_0]) *
++ _ORBIT_tmpvar_1);
++ giop_send_buffer_write(_ORBIT_send_buffer);
++ _ORBIT_completion_status = CORBA_COMPLETED_MAYBE;
++ giop_send_buffer_unuse(_ORBIT_send_buffer);
++ _ORBIT_send_buffer = NULL;
++ }
++ { /* demarshalling */
++ register guchar *_ORBIT_curptr;
++
++ _ORBIT_recv_buffer =
++ giop_recv_reply_buffer_use_2(_cnx, _ORBIT_request_id, TRUE);
++ if (!_ORBIT_recv_buffer)
++ goto _ORBIT_system_exception;
++ _ORBIT_completion_status = CORBA_COMPLETED_YES;
++ if (_ORBIT_recv_buffer->message.u.reply.reply_status !=
++ GIOP_NO_EXCEPTION) goto _ORBIT_msg_exception;
++ _ORBIT_curptr = GIOP_RECV_BUFFER(_ORBIT_recv_buffer)->cur;
++ if (giop_msg_conversion_needed(GIOP_MESSAGE_BUFFER(_ORBIT_recv_buffer))) {
++ _ORBIT_curptr = ALIGN_ADDRESS(_ORBIT_curptr, 4);
++
++ (*((guint32 *) & (_ORBIT_tmpvar_5))) =
++ GUINT32_SWAP_LE_BE(*((guint32 *) _ORBIT_curptr));
++ _ORBIT_curptr += 4;
++ _ORBIT_retval = CORBA_string_alloc(_ORBIT_tmpvar_5);
++ memcpy(_ORBIT_retval, _ORBIT_curptr,
++ sizeof(_ORBIT_retval[_ORBIT_tmpvar_4]) * _ORBIT_tmpvar_5);
++ _ORBIT_curptr +=
++ sizeof(_ORBIT_retval[_ORBIT_tmpvar_4]) * _ORBIT_tmpvar_5;
++ } else {
++ _ORBIT_curptr = ALIGN_ADDRESS(_ORBIT_curptr, 4);
++ _ORBIT_tmpvar_5 = *((CORBA_unsigned_long *) _ORBIT_curptr);
++ _ORBIT_curptr += 4;
++ _ORBIT_retval = CORBA_string_alloc(_ORBIT_tmpvar_5);
++ memcpy(_ORBIT_retval, _ORBIT_curptr,
++ sizeof(_ORBIT_retval[_ORBIT_tmpvar_4]) * _ORBIT_tmpvar_5);
++ _ORBIT_curptr +=
++ sizeof(_ORBIT_retval[_ORBIT_tmpvar_4]) * _ORBIT_tmpvar_5;
++ }
++ giop_recv_buffer_unuse(_ORBIT_recv_buffer);
++ return _ORBIT_retval;
++ _ORBIT_system_exception:
++ CORBA_exception_set_system(ev, _ORBIT_system_exception_minor,
++ _ORBIT_completion_status);
++ giop_recv_buffer_unuse(_ORBIT_recv_buffer);
++ giop_send_buffer_unuse(_ORBIT_send_buffer);
++ return _ORBIT_retval;
++ _ORBIT_msg_exception:
++ if (_ORBIT_recv_buffer->message.u.reply.reply_status ==
++ GIOP_LOCATION_FORWARD) {
++ if (_obj->forward_locations != NULL)
++ ORBit_delete_profiles(_obj->forward_locations);
++ _obj->forward_locations = ORBit_demarshal_IOR(_ORBIT_recv_buffer);
++ _cnx = ORBit_object_get_forwarded_connection(_obj);
++ giop_recv_buffer_unuse(_ORBIT_recv_buffer);
++
++ goto _ORBIT_retry_request;
++ } else {
++ ORBit_handle_exception(_ORBIT_recv_buffer, ev, NULL, _obj->orb);
++ giop_recv_buffer_unuse(_ORBIT_recv_buffer);
++ return _ORBIT_retval;
++ }
++ }
++}
+diff -urN linux-2.4.1/net/korbit/modules/CorbaFS/client/CorbaFS-user-client.c linux-2.4.1-korbit/net/korbit/modules/CorbaFS/client/CorbaFS-user-client.c
+--- linux-2.4.1/net/korbit/modules/CorbaFS/client/CorbaFS-user-client.c Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/CorbaFS/client/CorbaFS-user-client.c Thu Feb 1 11:47:03 2001
+@@ -0,0 +1,92 @@
++#include <stdio.h>
++#include <stdlib.h>
++#include <orb/orbit.h>
++
++#include "CorbaFS.h"
++
++CorbaFS_FileSystem fs;
++
++int
++main (int argc, char *argv[])
++{
++ CORBA_Environment ev;
++ CORBA_ORB orb;
++ CorbaFS_Inode inode;
++ CorbaFS_Buffer *buffer;
++ CorbaFS_DirEntSeq *dirents;
++ CorbaFS_dirent *dirent;
++
++ CORBA_unsigned_short mode;
++ CORBA_unsigned_long uid;
++ CORBA_unsigned_long gid;
++ CORBA_unsigned_long size;
++ CORBA_unsigned_long inodeNum;
++ CORBA_unsigned_short numLinks;
++ CORBA_long atime;
++ CORBA_long mtime;
++ CORBA_long ctime;
++
++ int i;
++
++ int niters = 10;
++
++ CORBA_exception_init(&ev);
++ orb = CORBA_ORB_init(&argc, argv, "orbit-local-orb", &ev);
++
++ if(argc < 2)
++ {
++ printf("Need a binding ID thing as argv[1]\n");
++ return 1;
++ }
++
++
++ fs = CORBA_ORB_string_to_object(orb, argv[1], &ev);
++ if (!fs) {
++ printf("Cannot bind to %s\n", argv[1]);
++ return 1;
++ }
++
++ if (argc >= 3)
++ inode = CorbaFS_FileSystem_getInode(fs, argv[2], &ev);
++ else
++ inode = CorbaFS_FileSystem_getInode(fs, "/proc/cpuinfo", &ev);
++
++ if (!inode)
++ {
++ printf("Cannot get inode\n");
++ }
++
++ CorbaFS_Inode_getStatus(inode,
++ &mode,
++ &uid,
++ &gid,
++ &size,
++ &inodeNum,
++ &numLinks,
++ &atime,
++ &mtime,
++ &ctime,
++ &ev);
++
++ printf("inode = %x\n", inode);
++ CorbaFS_Inode_readpage(inode, &buffer, 1000, 100, &ev);
++ printf("readpage got %d bytes\n", buffer->_length);
++ printf("readpage returned : %s\n", buffer->_buffer);
++
++ if (argc >= 3)
++ dirents = CorbaFS_FileSystem_readdir(fs, argv[2], &ev);
++ else
++ dirents = CorbaFS_FileSystem_readdir(fs, "/", &ev);
++
++ dirent = dirents->_buffer;
++ for (i = 0; i < dirents->_length; i++)
++ {
++ printf("%d = %s\n", dirent->inode, dirent->name);
++ dirent++;
++ }
++
++ CORBA_Object_release(fs, &ev);
++ CORBA_Object_release((CORBA_Object)orb, &ev);
++
++ return 0;
++}
+diff -urN linux-2.4.1/net/korbit/modules/CorbaFS/client/CorbaFS.h linux-2.4.1-korbit/net/korbit/modules/CorbaFS/client/CorbaFS.h
+--- linux-2.4.1/net/korbit/modules/CorbaFS/client/CorbaFS.h Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/CorbaFS/client/CorbaFS.h Thu Feb 1 16:36:08 2001
+@@ -0,0 +1,349 @@
++/*
++ * This file was generated by orbit-idl - DO NOT EDIT!
++ */
++
++#include <glib.h>
++#define ORBIT_IDL_SERIAL 9
++#include <orb/orbit.h>
++
++#ifndef CorbaFS_H
++#define CorbaFS_H 1
++#ifdef __cplusplus
++extern "C"
++{
++#endif /* __cplusplus */
++
++/** typedefs **/
++#if !defined(_CorbaFS_dirent_defined)
++#define _CorbaFS_dirent_defined 1
++ typedef struct
++ {
++ CORBA_long inode;
++ CORBA_char *name;
++ }
++ CorbaFS_dirent;
++
++#if !defined(TC_IMPL_TC_CorbaFS_dirent_0)
++#define TC_IMPL_TC_CorbaFS_dirent_0 'C'
++#define TC_IMPL_TC_CorbaFS_dirent_1 'o'
++#define TC_IMPL_TC_CorbaFS_dirent_2 'r'
++#define TC_IMPL_TC_CorbaFS_dirent_3 'b'
++#define TC_IMPL_TC_CorbaFS_dirent_4 'a'
++#define TC_IMPL_TC_CorbaFS_dirent_5 'F'
++#define TC_IMPL_TC_CorbaFS_dirent_6 'S'
++ extern const struct CORBA_TypeCode_struct TC_CorbaFS_dirent_struct;
++#define TC_CorbaFS_dirent ((CORBA_TypeCode)&TC_CorbaFS_dirent_struct)
++#endif
++ extern CorbaFS_dirent *CorbaFS_dirent__alloc(void);
++ extern gpointer CorbaFS_dirent__free(gpointer mem, gpointer dat,
++ CORBA_boolean free_strings); /* ORBit internal use */
++#endif
++#if !defined(ORBIT_DECL_CORBA_sequence_CorbaFS_dirent) && !defined(_CORBA_sequence_CorbaFS_dirent_defined)
++#define ORBIT_DECL_CORBA_sequence_CorbaFS_dirent 1
++#define _CORBA_sequence_CorbaFS_dirent_defined 1
++#define ORBIT_IMPL_CORBA_sequence_CorbaFS_dirent_0 'C'
++#define ORBIT_IMPL_CORBA_sequence_CorbaFS_dirent_1 'o'
++#define ORBIT_IMPL_CORBA_sequence_CorbaFS_dirent_2 'r'
++#define ORBIT_IMPL_CORBA_sequence_CorbaFS_dirent_3 'b'
++#define ORBIT_IMPL_CORBA_sequence_CorbaFS_dirent_4 'a'
++#define ORBIT_IMPL_CORBA_sequence_CorbaFS_dirent_5 'F'
++#define ORBIT_IMPL_CORBA_sequence_CorbaFS_dirent_6 'S'
++ typedef struct
++ {
++ CORBA_unsigned_long _maximum,
++ _length;
++ CorbaFS_dirent *_buffer;
++ CORBA_boolean _release;
++ }
++ CORBA_sequence_CorbaFS_dirent;
++#if !defined(TC_IMPL_TC_CORBA_sequence_CorbaFS_dirent_0)
++#define TC_IMPL_TC_CORBA_sequence_CorbaFS_dirent_0 'C'
++#define TC_IMPL_TC_CORBA_sequence_CorbaFS_dirent_1 'o'
++#define TC_IMPL_TC_CORBA_sequence_CorbaFS_dirent_2 'r'
++#define TC_IMPL_TC_CORBA_sequence_CorbaFS_dirent_3 'b'
++#define TC_IMPL_TC_CORBA_sequence_CorbaFS_dirent_4 'a'
++#define TC_IMPL_TC_CORBA_sequence_CorbaFS_dirent_5 'F'
++#define TC_IMPL_TC_CORBA_sequence_CorbaFS_dirent_6 'S'
++ extern const struct CORBA_TypeCode_struct
++ TC_CORBA_sequence_CorbaFS_dirent_struct;
++#define TC_CORBA_sequence_CorbaFS_dirent ((CORBA_TypeCode)&TC_CORBA_sequence_CorbaFS_dirent_struct)
++#endif
++ extern CORBA_sequence_CorbaFS_dirent
++ *CORBA_sequence_CorbaFS_dirent__alloc(void);
++ extern gpointer CORBA_sequence_CorbaFS_dirent__free(gpointer mem,
++ gpointer dat,
++ CORBA_boolean free_strings); /* ORBit internal use */
++ CorbaFS_dirent *CORBA_sequence_CorbaFS_dirent_allocbuf(CORBA_unsigned_long
++ len);
++#endif
++#if !defined(_CorbaFS_DirEntSeq_defined)
++#define _CorbaFS_DirEntSeq_defined 1
++ typedef CORBA_sequence_CorbaFS_dirent CorbaFS_DirEntSeq;
++#if !defined(TC_IMPL_TC_CorbaFS_DirEntSeq_0)
++#define TC_IMPL_TC_CorbaFS_DirEntSeq_0 'C'
++#define TC_IMPL_TC_CorbaFS_DirEntSeq_1 'o'
++#define TC_IMPL_TC_CorbaFS_DirEntSeq_2 'r'
++#define TC_IMPL_TC_CorbaFS_DirEntSeq_3 'b'
++#define TC_IMPL_TC_CorbaFS_DirEntSeq_4 'a'
++#define TC_IMPL_TC_CorbaFS_DirEntSeq_5 'F'
++#define TC_IMPL_TC_CorbaFS_DirEntSeq_6 'S'
++ extern const struct CORBA_TypeCode_struct TC_CorbaFS_DirEntSeq_struct;
++#define TC_CorbaFS_DirEntSeq ((CORBA_TypeCode)&TC_CorbaFS_DirEntSeq_struct)
++#endif
++ extern CorbaFS_DirEntSeq *CorbaFS_DirEntSeq__alloc(void);
++ extern gpointer CorbaFS_DirEntSeq__free(gpointer mem, gpointer dat,
++ CORBA_boolean free_strings); /* ORBit internal use */
++#endif
++#if !defined(ORBIT_DECL_CORBA_sequence_CORBA_octet) && !defined(_CORBA_sequence_CORBA_octet_defined)
++#define ORBIT_DECL_CORBA_sequence_CORBA_octet 1
++#define _CORBA_sequence_CORBA_octet_defined 1
++#define ORBIT_IMPL_CORBA_sequence_CORBA_octet_0 'C'
++#define ORBIT_IMPL_CORBA_sequence_CORBA_octet_1 'o'
++#define ORBIT_IMPL_CORBA_sequence_CORBA_octet_2 'r'
++#define ORBIT_IMPL_CORBA_sequence_CORBA_octet_3 'b'
++#define ORBIT_IMPL_CORBA_sequence_CORBA_octet_4 'a'
++#define ORBIT_IMPL_CORBA_sequence_CORBA_octet_5 'F'
++#define ORBIT_IMPL_CORBA_sequence_CORBA_octet_6 'S'
++ typedef struct
++ {
++ CORBA_unsigned_long _maximum,
++ _length;
++ CORBA_octet *_buffer;
++ CORBA_boolean _release;
++ }
++ CORBA_sequence_CORBA_octet;
++#if !defined(TC_IMPL_TC_CORBA_sequence_CORBA_octet_0)
++#define TC_IMPL_TC_CORBA_sequence_CORBA_octet_0 'C'
++#define TC_IMPL_TC_CORBA_sequence_CORBA_octet_1 'o'
++#define TC_IMPL_TC_CORBA_sequence_CORBA_octet_2 'r'
++#define TC_IMPL_TC_CORBA_sequence_CORBA_octet_3 'b'
++#define TC_IMPL_TC_CORBA_sequence_CORBA_octet_4 'a'
++#define TC_IMPL_TC_CORBA_sequence_CORBA_octet_5 'F'
++#define TC_IMPL_TC_CORBA_sequence_CORBA_octet_6 'S'
++ extern const struct CORBA_TypeCode_struct
++ TC_CORBA_sequence_CORBA_octet_struct;
++#define TC_CORBA_sequence_CORBA_octet ((CORBA_TypeCode)&TC_CORBA_sequence_CORBA_octet_struct)
++#endif
++ extern CORBA_sequence_CORBA_octet *CORBA_sequence_CORBA_octet__alloc(void);
++ extern gpointer CORBA_sequence_CORBA_octet__free(gpointer mem,
++ gpointer dat,
++ CORBA_boolean free_strings); /* ORBit internal use */
++ CORBA_octet *CORBA_sequence_CORBA_octet_allocbuf(CORBA_unsigned_long len);
++#endif
++#if !defined(_CorbaFS_Buffer_defined)
++#define _CorbaFS_Buffer_defined 1
++ typedef CORBA_sequence_CORBA_octet CorbaFS_Buffer;
++#if !defined(TC_IMPL_TC_CorbaFS_Buffer_0)
++#define TC_IMPL_TC_CorbaFS_Buffer_0 'C'
++#define TC_IMPL_TC_CorbaFS_Buffer_1 'o'
++#define TC_IMPL_TC_CorbaFS_Buffer_2 'r'
++#define TC_IMPL_TC_CorbaFS_Buffer_3 'b'
++#define TC_IMPL_TC_CorbaFS_Buffer_4 'a'
++#define TC_IMPL_TC_CorbaFS_Buffer_5 'F'
++#define TC_IMPL_TC_CorbaFS_Buffer_6 'S'
++ extern const struct CORBA_TypeCode_struct TC_CorbaFS_Buffer_struct;
++#define TC_CorbaFS_Buffer ((CORBA_TypeCode)&TC_CorbaFS_Buffer_struct)
++#endif
++ extern CorbaFS_Buffer *CorbaFS_Buffer__alloc(void);
++ extern gpointer CorbaFS_Buffer__free(gpointer mem, gpointer dat,
++ CORBA_boolean free_strings); /* ORBit internal use */
++#endif
++#if !defined(ORBIT_DECL_CorbaFS_Inode) && !defined(_CorbaFS_Inode_defined)
++#define ORBIT_DECL_CorbaFS_Inode 1
++#define _CorbaFS_Inode_defined 1
++#define CorbaFS_Inode__free CORBA_Object__free
++ typedef CORBA_Object CorbaFS_Inode;
++ extern CORBA_unsigned_long CorbaFS_Inode__classid;
++#if !defined(TC_IMPL_TC_CorbaFS_Inode_0)
++#define TC_IMPL_TC_CorbaFS_Inode_0 'C'
++#define TC_IMPL_TC_CorbaFS_Inode_1 'o'
++#define TC_IMPL_TC_CorbaFS_Inode_2 'r'
++#define TC_IMPL_TC_CorbaFS_Inode_3 'b'
++#define TC_IMPL_TC_CorbaFS_Inode_4 'a'
++#define TC_IMPL_TC_CorbaFS_Inode_5 'F'
++#define TC_IMPL_TC_CorbaFS_Inode_6 'S'
++ extern const struct CORBA_TypeCode_struct TC_CorbaFS_Inode_struct;
++#define TC_CorbaFS_Inode ((CORBA_TypeCode)&TC_CorbaFS_Inode_struct)
++#endif
++#endif
++#if !defined(ORBIT_DECL_CorbaFS_FileSystem) && !defined(_CorbaFS_FileSystem_defined)
++#define ORBIT_DECL_CorbaFS_FileSystem 1
++#define _CorbaFS_FileSystem_defined 1
++#define CorbaFS_FileSystem__free CORBA_Object__free
++ typedef CORBA_Object CorbaFS_FileSystem;
++ extern CORBA_unsigned_long CorbaFS_FileSystem__classid;
++#if !defined(TC_IMPL_TC_CorbaFS_FileSystem_0)
++#define TC_IMPL_TC_CorbaFS_FileSystem_0 'C'
++#define TC_IMPL_TC_CorbaFS_FileSystem_1 'o'
++#define TC_IMPL_TC_CorbaFS_FileSystem_2 'r'
++#define TC_IMPL_TC_CorbaFS_FileSystem_3 'b'
++#define TC_IMPL_TC_CorbaFS_FileSystem_4 'a'
++#define TC_IMPL_TC_CorbaFS_FileSystem_5 'F'
++#define TC_IMPL_TC_CorbaFS_FileSystem_6 'S'
++ extern const struct CORBA_TypeCode_struct TC_CorbaFS_FileSystem_struct;
++#define TC_CorbaFS_FileSystem ((CORBA_TypeCode)&TC_CorbaFS_FileSystem_struct)
++#endif
++#endif
++
++/** POA structures **/
++ typedef struct
++ {
++ void *_private;
++ void (*getStatus) (PortableServer_Servant _servant,
++ CORBA_unsigned_short * mode,
++ CORBA_unsigned_long * uid, CORBA_unsigned_long * gid,
++ CORBA_unsigned_long * size,
++ CORBA_unsigned_long * inodeNum,
++ CORBA_unsigned_short * numLinks, CORBA_long * atime,
++ CORBA_long * mtime, CORBA_long * ctime,
++ CORBA_Environment * ev);
++ void (*readpage) (PortableServer_Servant _servant,
++ CorbaFS_Buffer ** buffer, const CORBA_long size,
++ const CORBA_long offset, CORBA_Environment * ev);
++ void (*release) (PortableServer_Servant _servant,
++ CORBA_Environment * ev);
++ }
++ POA_CorbaFS_Inode__epv;
++ typedef struct
++ {
++ PortableServer_ServantBase__epv *_base_epv;
++ POA_CorbaFS_Inode__epv *CorbaFS_Inode_epv;
++ }
++ POA_CorbaFS_Inode__vepv;
++ typedef struct
++ {
++ void *_private;
++ POA_CorbaFS_Inode__vepv *vepv;
++ }
++ POA_CorbaFS_Inode;
++ extern void POA_CorbaFS_Inode__init(PortableServer_Servant servant,
++ CORBA_Environment * ev);
++ extern void POA_CorbaFS_Inode__fini(PortableServer_Servant servant,
++ CORBA_Environment * ev);
++ typedef struct
++ {
++ void *_private;
++
++ CorbaFS_Inode(*getInode) (PortableServer_Servant _servant,
++ const CORBA_char * path,
++ CORBA_Environment * ev);
++ CorbaFS_DirEntSeq *(*readdir) (PortableServer_Servant _servant,
++ const CORBA_char * path,
++ CORBA_Environment * ev);
++ CORBA_char *(*readlink) (PortableServer_Servant _servant,
++ const CORBA_char * filename,
++ CORBA_Environment * ev);
++ }
++ POA_CorbaFS_FileSystem__epv;
++ typedef struct
++ {
++ PortableServer_ServantBase__epv *_base_epv;
++ POA_CorbaFS_FileSystem__epv *CorbaFS_FileSystem_epv;
++ }
++ POA_CorbaFS_FileSystem__vepv;
++ typedef struct
++ {
++ void *_private;
++ POA_CorbaFS_FileSystem__vepv *vepv;
++ }
++ POA_CorbaFS_FileSystem;
++ extern void POA_CorbaFS_FileSystem__init(PortableServer_Servant servant,
++ CORBA_Environment * ev);
++ extern void POA_CorbaFS_FileSystem__fini(PortableServer_Servant servant,
++ CORBA_Environment * ev);
++
++/** prototypes **/
++ void CorbaFS_Inode_getStatus(CorbaFS_Inode _obj,
++ CORBA_unsigned_short * mode,
++ CORBA_unsigned_long * uid,
++ CORBA_unsigned_long * gid,
++ CORBA_unsigned_long * size,
++ CORBA_unsigned_long * inodeNum,
++ CORBA_unsigned_short * numLinks,
++ CORBA_long * atime, CORBA_long * mtime,
++ CORBA_long * ctime, CORBA_Environment * ev);
++ void CorbaFS_Inode_readpage(CorbaFS_Inode _obj, CorbaFS_Buffer ** buffer,
++ const CORBA_long size, const CORBA_long offset,
++ CORBA_Environment * ev);
++ void CorbaFS_Inode_release(CorbaFS_Inode _obj, CORBA_Environment * ev);
++ CorbaFS_Inode CorbaFS_FileSystem_getInode(CorbaFS_FileSystem _obj,
++ const CORBA_char * path,
++ CORBA_Environment * ev);
++ CorbaFS_DirEntSeq *CorbaFS_FileSystem_readdir(CorbaFS_FileSystem _obj,
++ const CORBA_char * path,
++ CORBA_Environment * ev);
++ CORBA_char *CorbaFS_FileSystem_readlink(CorbaFS_FileSystem _obj,
++ const CORBA_char * filename,
++ CORBA_Environment * ev);
++
++ void _ORBIT_skel_CorbaFS_Inode_getStatus(POA_CorbaFS_Inode *
++ _ORBIT_servant,
++ GIOPRecvBuffer *
++ _ORBIT_recv_buffer,
++ CORBA_Environment * ev,
++ void (*_impl_getStatus)
++ (PortableServer_Servant _servant,
++ CORBA_unsigned_short * mode,
++ CORBA_unsigned_long * uid,
++ CORBA_unsigned_long * gid,
++ CORBA_unsigned_long * size,
++ CORBA_unsigned_long * inodeNum,
++ CORBA_unsigned_short * numLinks,
++ CORBA_long * atime,
++ CORBA_long * mtime,
++ CORBA_long * ctime,
++ CORBA_Environment * ev));
++ void _ORBIT_skel_CorbaFS_Inode_readpage(POA_CorbaFS_Inode * _ORBIT_servant,
++ GIOPRecvBuffer *
++ _ORBIT_recv_buffer,
++ CORBA_Environment * ev,
++ void (*_impl_readpage)
++ (PortableServer_Servant _servant,
++ CorbaFS_Buffer ** buffer,
++ const CORBA_long size,
++ const CORBA_long offset,
++ CORBA_Environment * ev));
++ void _ORBIT_skel_CorbaFS_Inode_release(POA_CorbaFS_Inode * _ORBIT_servant,
++ GIOPRecvBuffer * _ORBIT_recv_buffer,
++ CORBA_Environment * ev,
++ void (*_impl_release)
++ (PortableServer_Servant _servant,
++ CORBA_Environment * ev));
++ void _ORBIT_skel_CorbaFS_FileSystem_getInode(POA_CorbaFS_FileSystem *
++ _ORBIT_servant,
++ GIOPRecvBuffer *
++ _ORBIT_recv_buffer,
++ CORBA_Environment * ev,
++ CorbaFS_Inode(*_impl_getInode)
++ (PortableServer_Servant
++ _servant,
++ const CORBA_char * path,
++ CORBA_Environment * ev));
++ void _ORBIT_skel_CorbaFS_FileSystem_readdir(POA_CorbaFS_FileSystem *
++ _ORBIT_servant,
++ GIOPRecvBuffer *
++ _ORBIT_recv_buffer,
++ CORBA_Environment * ev,
++ CorbaFS_DirEntSeq *
++ (*_impl_readdir)
++ (PortableServer_Servant
++ _servant,
++ const CORBA_char * path,
++ CORBA_Environment * ev));
++ void _ORBIT_skel_CorbaFS_FileSystem_readlink(POA_CorbaFS_FileSystem *
++ _ORBIT_servant,
++ GIOPRecvBuffer *
++ _ORBIT_recv_buffer,
++ CORBA_Environment * ev,
++ CORBA_char *
++ (*_impl_readlink)
++ (PortableServer_Servant
++ _servant,
++ const CORBA_char * filename,
++ CORBA_Environment * ev));
++#ifdef __cplusplus
++}
++#endif /* __cplusplus */
++
++#endif
++#undef ORBIT_IDL_SERIAL
+diff -urN linux-2.4.1/net/korbit/modules/CorbaFS/client/Makefile linux-2.4.1-korbit/net/korbit/modules/CorbaFS/client/Makefile
+--- linux-2.4.1/net/korbit/modules/CorbaFS/client/Makefile Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/CorbaFS/client/Makefile Thu Feb 1 11:47:03 2001
+@@ -0,0 +1,20 @@
++#
++# Makefile for KORBit CorbaFS client
++#
++# Note! Dependencies are done automagically by 'make dep', which also
++# removes any old dependencies. DON'T put your own dependencies here
++# unless it's something special (ie not a .c file).
++#
++# Note 2! The CFLAGS definition is now in the main makefile...
++
++O_TARGET := corba-corbafs-client.o
++
++obj-y := CorbaFS-common.o CorbaFS-stubs.o CorbaFS-client.o
++obj-m := $(O_TARGET)
++
++include ../../Makefile.module
++
++CorbaFS-client.c: CorbaFS.h
++
++CorbaFS.h CorbaFS-common.c CorbaFS-stubs.c: ../CorbaFS.idl
++ $(ORBIT_IDL) --noskels ../CorbaFS.idl
+diff -urN linux-2.4.1/net/korbit/modules/CorbaFS/client/Makefile.user linux-2.4.1-korbit/net/korbit/modules/CorbaFS/client/Makefile.user
+--- linux-2.4.1/net/korbit/modules/CorbaFS/client/Makefile.user Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/CorbaFS/client/Makefile.user Thu Feb 1 11:47:03 2001
+@@ -0,0 +1,32 @@
++#
++# Makefile for KORBit
++#
++# Note! Dependencies are done automagically by 'make dep', which also
++# removes any old dependencies. DON'T put your own dependencies here
++# unless it's something special (ie not a .c file).
++#
++# Note 2! The CFLAGS definition is now in the main makefile...
++
++PROJECT = CorbaFS
++
++CFLAGS = -Wall `orbit-config --cflags client` -I../../..
++LDFLAGS = `orbit-config --libs client`
++OBJS = $(PROJECT)-common.o $(PROJECT)-stubs.o $(PROJECT)-user-client.o
++ORBIT-IDL = orbit-idl
++
++$(PROJECT)-user-client: $(OBJS)
++ gcc -o $(PROJECT)-user-client $(OBJS) $(LDFLAGS)
++
++$(PROJECT)-user-client.o: $(PROJECT).h
++
++$(PROJECT).h $(PROJECT)-common.c $(PROJECT)-stubs.c: ../$(PROJECT).idl
++ $(ORBIT-IDL) --noskels ../$(PROJECT).idl
++
++clean:
++ rm -f $(OBJS) $(PROJECT)-user-client
++
++realclean: clean
++ rm -f $(PROJECT).h
++ rm -f $(PROJECT)-common.c
++ rm -f $(PROJECT)-skels.c
++ rm -f *~
+diff -urN linux-2.4.1/net/korbit/modules/CorbaFS/client/README linux-2.4.1-korbit/net/korbit/modules/CorbaFS/client/README
+--- linux-2.4.1/net/korbit/modules/CorbaFS/client/README Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/CorbaFS/client/README Thu Feb 1 11:47:03 2001
+@@ -0,0 +1,4 @@
++This module implements the kernel VFS->kORBit interface. This is called a 'client'
++because it actually USES a CORBA object that is exported from someplace else.
++
++ORB: kORBit
+diff -urN linux-2.4.1/net/korbit/modules/CorbaFS/server/CVS/Entries linux-2.4.1-korbit/net/korbit/modules/CorbaFS/server/CVS/Entries
+--- linux-2.4.1/net/korbit/modules/CorbaFS/server/CVS/Entries Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/CorbaFS/server/CVS/Entries Thu Feb 1 11:47:04 2001
+@@ -0,0 +1,6 @@
++/CorbaFS-server.c/1.8/Thu Feb 1 09:47:03 2001//
++/CorbaFS-skelimpl.c/1.10/Thu Feb 1 09:47:04 2001//
++/Makefile/1.5/Thu Feb 1 09:47:04 2001//
++/README/1.2/Thu Feb 1 09:47:04 2001//
++/RunServer.sh/1.1/Thu Feb 1 09:47:04 2001//
++D
+diff -urN linux-2.4.1/net/korbit/modules/CorbaFS/server/CVS/Repository linux-2.4.1-korbit/net/korbit/modules/CorbaFS/server/CVS/Repository
+--- linux-2.4.1/net/korbit/modules/CorbaFS/server/CVS/Repository Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/CorbaFS/server/CVS/Repository Thu Feb 1 11:47:03 2001
+@@ -0,0 +1 @@
++/cvsroot/korbit/linux/net/korbit/modules/CorbaFS/server
+diff -urN linux-2.4.1/net/korbit/modules/CorbaFS/server/CVS/Root linux-2.4.1-korbit/net/korbit/modules/CorbaFS/server/CVS/Root
+--- linux-2.4.1/net/korbit/modules/CorbaFS/server/CVS/Root Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/CorbaFS/server/CVS/Root Thu Feb 1 11:47:03 2001
+@@ -0,0 +1 @@
++vraalsen@cvs.korbit.sourceforge.net:/cvsroot/korbit
+diff -urN linux-2.4.1/net/korbit/modules/CorbaFS/server/CorbaFS-server.c linux-2.4.1-korbit/net/korbit/modules/CorbaFS/server/CorbaFS-server.c
+--- linux-2.4.1/net/korbit/modules/CorbaFS/server/CorbaFS-server.c Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/CorbaFS/server/CorbaFS-server.c Thu Feb 1 11:47:03 2001
+@@ -0,0 +1,37 @@
++#include <stdio.h>
++#include "CorbaFS-skelimpl.c"
++
++CORBA_ORB orb;
++PortableServer_POA poa;
++CORBA_Environment *ev;
++PortableServer_ObjectId *objid;
++
++int main(int argc, char *argv[]) {
++ CorbaFS_FileSystem fs;
++ impl_POA_CorbaFS_FileSystem *fs_impl;
++
++ PortableServer_POAManager pm;
++ ev = g_new0(CORBA_Environment,1);
++
++ CORBA_exception_init(ev);
++ printf("Make sure you use TCP/IP and not Unix sockets!\n");
++
++ orb = CORBA_ORB_init(&argc, argv, "orbit-local-orb", ev);
++ poa = (PortableServer_POA)
++ CORBA_ORB_resolve_initial_references(orb,
++ "RootPOA",
++ ev);
++ fs = impl_CorbaFS_FileSystem__create(poa, ev);
++
++ pm = PortableServer_POA__get_the_POAManager(poa, ev);
++ PortableServer_POAManager_activate(pm, ev);
++
++ fs_impl = PortableServer_POA_reference_to_servant( poa, fs, ev );
++ objid = PortableServer_POA_servant_to_id( poa, fs_impl, ev );
++
++ printf("CorbaFS-server:\n%s\n", CORBA_ORB_object_to_string(orb, fs, ev));
++
++ CORBA_ORB_run(orb, ev);
++
++ return 0;
++}
+diff -urN linux-2.4.1/net/korbit/modules/CorbaFS/server/CorbaFS-skelimpl.c linux-2.4.1-korbit/net/korbit/modules/CorbaFS/server/CorbaFS-skelimpl.c
+--- linux-2.4.1/net/korbit/modules/CorbaFS/server/CorbaFS-skelimpl.c Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/CorbaFS/server/CorbaFS-skelimpl.c Thu Feb 1 11:47:04 2001
+@@ -0,0 +1,353 @@
++#include <sys/param.h>
++#include <sys/types.h>
++#include <sys/stat.h>
++#include <unistd.h>
++#include <fcntl.h>
++#include <dirent.h>
++
++#include "CorbaFS.h"
++
++/*** App-specific servant structures ***/
++
++#define printf(fmt, args...) fprintf(stderr, fmt, ##args);
++
++typedef struct
++{
++ POA_CorbaFS_Inode servant;
++ PortableServer_POA poa;
++
++ CORBA_char *path;
++#if 0
++ CORBA_unsigned_short mode;
++ CORBA_unsigned_long uid;
++ CORBA_unsigned_long gid;
++ CORBA_unsigned_long size;
++ CORBA_unsigned_long inodeNum;
++ CORBA_unsigned_short numLinks;
++ CORBA_long atime;
++ CORBA_long mtime;
++ CORBA_long ctime;
++#endif
++}
++impl_POA_CorbaFS_Inode;
++
++typedef struct
++{
++ POA_CorbaFS_FileSystem servant;
++ PortableServer_POA poa;
++
++}
++impl_POA_CorbaFS_FileSystem;
++
++/*** Implementation stub prototypes ***/
++
++static void impl_CorbaFS_Inode__destroy(impl_POA_CorbaFS_Inode * servant,
++ CORBA_Environment * ev);
++static void
++impl_CorbaFS_Inode_getStatus(impl_POA_CorbaFS_Inode * servant,
++ CORBA_unsigned_short * mode,
++ CORBA_unsigned_long * uid,
++ CORBA_unsigned_long * gid,
++ CORBA_unsigned_long * size,
++ CORBA_unsigned_long * inodeNum,
++ CORBA_unsigned_short * numLinks,
++ CORBA_long * atime,
++ CORBA_long * mtime,
++ CORBA_long * ctime, CORBA_Environment * ev);
++
++static void
++impl_CorbaFS_Inode_readpage(impl_POA_CorbaFS_Inode * servant,
++ CorbaFS_Buffer ** buffer,
++ CORBA_long size,
++ CORBA_long offset, CORBA_Environment * ev);
++
++static void
++impl_CorbaFS_Inode_release(impl_POA_CorbaFS_Inode * servant,
++ CORBA_Environment * ev);
++
++static void impl_CorbaFS_FileSystem__destroy(impl_POA_CorbaFS_FileSystem *
++ servant, CORBA_Environment * ev);
++static CorbaFS_Inode
++impl_CorbaFS_FileSystem_getInode(impl_POA_CorbaFS_FileSystem * servant,
++ CORBA_char * path, CORBA_Environment * ev);
++
++static CorbaFS_DirEntSeq
++ *impl_CorbaFS_FileSystem_readdir(impl_POA_CorbaFS_FileSystem * servant,
++ CORBA_char * path,
++
++ CORBA_Environment * ev);
++
++static CORBA_char
++ *impl_CorbaFS_FileSystem_readlink(impl_POA_CorbaFS_FileSystem * servant,
++ CORBA_char * filename,
++ CORBA_Environment * ev);
++
++/*** epv structures ***/
++
++static PortableServer_ServantBase__epv impl_CorbaFS_Inode_base_epv = {
++ NULL, /* _private data */
++ NULL, /* finalize routine */
++ NULL, /* default_POA routine */
++};
++static POA_CorbaFS_Inode__epv impl_CorbaFS_Inode_epv = {
++ NULL, /* _private */
++ (gpointer) & impl_CorbaFS_Inode_getStatus,
++
++ (gpointer) & impl_CorbaFS_Inode_readpage,
++
++ (gpointer) & impl_CorbaFS_Inode_release,
++
++};
++static PortableServer_ServantBase__epv impl_CorbaFS_FileSystem_base_epv = {
++ NULL, /* _private data */
++ NULL, /* finalize routine */
++ NULL, /* default_POA routine */
++};
++static POA_CorbaFS_FileSystem__epv impl_CorbaFS_FileSystem_epv = {
++ NULL, /* _private */
++ (gpointer) & impl_CorbaFS_FileSystem_getInode,
++
++ (gpointer) & impl_CorbaFS_FileSystem_readdir,
++
++ (gpointer) & impl_CorbaFS_FileSystem_readlink,
++
++};
++
++/*** vepv structures ***/
++
++static POA_CorbaFS_Inode__vepv impl_CorbaFS_Inode_vepv = {
++ &impl_CorbaFS_Inode_base_epv,
++ &impl_CorbaFS_Inode_epv,
++};
++static POA_CorbaFS_FileSystem__vepv impl_CorbaFS_FileSystem_vepv = {
++ &impl_CorbaFS_FileSystem_base_epv,
++ &impl_CorbaFS_FileSystem_epv,
++};
++
++/*** Stub implementations ***/
++
++static CorbaFS_Inode
++impl_CorbaFS_Inode__create(PortableServer_POA poa, CORBA_Environment * ev)
++{
++ CorbaFS_Inode retval;
++ impl_POA_CorbaFS_Inode *newservant;
++ PortableServer_ObjectId *objid;
++
++ newservant = g_new0(impl_POA_CorbaFS_Inode, 1);
++ newservant->servant.vepv = &impl_CorbaFS_Inode_vepv;
++ newservant->poa = poa;
++ POA_CorbaFS_Inode__init((PortableServer_Servant) newservant, ev);
++ objid = PortableServer_POA_activate_object(poa, newservant, ev);
++ CORBA_free(objid);
++ retval = PortableServer_POA_servant_to_reference(poa, newservant, ev);
++
++ return retval;
++}
++
++static void
++impl_CorbaFS_Inode__destroy(impl_POA_CorbaFS_Inode * servant,
++ CORBA_Environment * ev)
++{
++ PortableServer_ObjectId *objid;
++
++ objid = PortableServer_POA_servant_to_id(servant->poa, servant, ev);
++ PortableServer_POA_deactivate_object(servant->poa, objid, ev);
++ CORBA_free(objid);
++
++ POA_CorbaFS_Inode__fini((PortableServer_Servant) servant, ev);
++ g_free(servant);
++}
++
++static void
++impl_CorbaFS_Inode_getStatus(impl_POA_CorbaFS_Inode * servant,
++ CORBA_unsigned_short * mode,
++ CORBA_unsigned_long * uid,
++ CORBA_unsigned_long * gid,
++ CORBA_unsigned_long * size,
++ CORBA_unsigned_long * inodeNum,
++ CORBA_unsigned_short * numLinks,
++ CORBA_long * atime,
++ CORBA_long * mtime,
++ CORBA_long * ctime, CORBA_Environment * ev)
++{
++ struct stat buf;
++
++ printf("Inode_getStatus()\n");
++ printf("Inode path = %s\n", servant->path);
++ lstat(servant->path, &buf);
++
++ *mode = buf.st_mode;
++ *uid = buf.st_uid;
++ *gid = buf.st_gid;
++ *size = buf.st_size;
++ *inodeNum = buf.st_ino;
++ *numLinks = buf.st_nlink;
++ *atime = buf.st_atime;
++ *mtime = buf.st_mtime;
++ *ctime = buf.st_ctime;
++}
++
++static void
++impl_CorbaFS_Inode_readpage(impl_POA_CorbaFS_Inode * servant,
++ CorbaFS_Buffer ** buffer,
++ CORBA_long size,
++ CORBA_long offset, CORBA_Environment * ev)
++{
++ int fd = -1, c = 0;
++
++ printf("Inode_readpage(buffer, %d, %d)\n", size, offset);
++ printf("Inode_readpage : path = %s\n", servant->path);
++
++ *buffer = CorbaFS_Buffer__alloc();
++ (*buffer)->_maximum = size;
++ (*buffer)->_buffer = CORBA_octet_allocbuf(size);
++
++ memset((*buffer)->_buffer, size, 0);
++
++ fd = open(servant->path, O_RDONLY);
++ printf("Inode_readpage : fd = %d\n", fd);
++ lseek(fd, offset, SEEK_SET);
++ c = read(fd, (*buffer)->_buffer, size);
++ printf("Inode_readpage : read %d bytes\n", c);
++ (*buffer)->_length = c;
++ close(fd);
++}
++
++static void
++impl_CorbaFS_Inode_release(impl_POA_CorbaFS_Inode * servant,
++ CORBA_Environment * ev)
++{
++ printf("Inode_release()\n");
++}
++
++static CorbaFS_FileSystem
++impl_CorbaFS_FileSystem__create(PortableServer_POA poa,
++ CORBA_Environment * ev)
++{
++ CorbaFS_FileSystem retval;
++ impl_POA_CorbaFS_FileSystem *newservant;
++ PortableServer_ObjectId *objid;
++
++ newservant = g_new0(impl_POA_CorbaFS_FileSystem, 1);
++ newservant->servant.vepv = &impl_CorbaFS_FileSystem_vepv;
++ newservant->poa = poa;
++ POA_CorbaFS_FileSystem__init((PortableServer_Servant) newservant, ev);
++ objid = PortableServer_POA_activate_object(poa, newservant, ev);
++ CORBA_free(objid);
++ retval = PortableServer_POA_servant_to_reference(poa, newservant, ev);
++
++ return retval;
++}
++
++static void
++impl_CorbaFS_FileSystem__destroy(impl_POA_CorbaFS_FileSystem * servant,
++ CORBA_Environment * ev)
++{
++ PortableServer_ObjectId *objid;
++
++ objid = PortableServer_POA_servant_to_id(servant->poa, servant, ev);
++ PortableServer_POA_deactivate_object(servant->poa, objid, ev);
++ CORBA_free(objid);
++
++ POA_CorbaFS_FileSystem__fini((PortableServer_Servant) servant, ev);
++ g_free(servant);
++}
++
++static CorbaFS_Inode
++impl_CorbaFS_FileSystem_getInode(impl_POA_CorbaFS_FileSystem * servant,
++ CORBA_char * path, CORBA_Environment * ev)
++{
++ CorbaFS_Inode retval;
++ impl_POA_CorbaFS_Inode *inode;
++
++ printf("FileSystem_getInode(%s)\n", path);
++
++ retval = impl_CorbaFS_Inode__create(servant->poa, ev);
++
++ inode = PortableServer_POA_reference_to_servant( servant->poa, retval, ev );
++ inode->path = CORBA_string_dup(path);
++#if 0
++ inode->mode = 0040777; /* world-readable directory */
++ inode->uid = 0;
++ inode->gid = 0;
++ inode->size = 4096;
++ inode->inodeNum = inodeNum++;
++ inode->numLinks = 1;
++ inode->atime = 0;
++ inode->mtime = 100;
++ inode->ctime = 10000;
++#endif
++
++ return retval;
++}
++
++static CorbaFS_DirEntSeq *
++impl_CorbaFS_FileSystem_readdir(impl_POA_CorbaFS_FileSystem * servant,
++ CORBA_char * path, CORBA_Environment * ev)
++{
++ CorbaFS_DirEntSeq *retval;
++ CorbaFS_dirent *dirent;
++
++ DIR *dir;
++ struct dirent *dirp;
++ int c;
++
++ printf("FileSystem_readdir(%s)\n", path);
++
++ retval = CorbaFS_DirEntSeq__alloc();
++ retval->_maximum = 0;
++ retval->_length = 0;
++
++ dir = opendir(path);
++ if (dir == NULL)
++ return retval;
++
++ c = 0;
++ while ((dirp = readdir(dir)))
++ c++;
++
++ rewinddir(dir);
++
++ printf("%d directories\n", c);
++
++ retval->_buffer = CORBA_sequence_CorbaFS_dirent_allocbuf(c);
++ retval->_maximum = c;
++ dirent = retval->_buffer;
++
++ c = 0;
++ while ((dirp = readdir(dir)) && (c < retval->_maximum))
++ {
++ printf("Adding directory %d : %s (%d)\n", c, dirp->d_name, dirp->d_ino);
++
++ dirent[c].inode = dirp->d_ino;
++ dirent[c].name = CORBA_string_dup(dirp->d_name);
++ c++;
++ }
++ retval->_length = c;
++
++ closedir(dir);
++
++ return retval;
++}
++
++static CORBA_char *
++impl_CorbaFS_FileSystem_readlink(impl_POA_CorbaFS_FileSystem * servant,
++ CORBA_char * filename,
++ CORBA_Environment * ev)
++{
++ CORBA_char *retval = CORBA_OBJECT_NIL;
++ char tmp[MAXPATHLEN + 1];
++ int len;
++
++ printf("FileSystem_readlink(%s) = ", filename);
++ len = readlink(filename, tmp, MAXPATHLEN);
++ if (len != -1)
++ {
++ tmp[len] = '\0';
++ retval = CORBA_string_dup(tmp);
++ }
++
++ printf("%s\n", retval);
++
++ return retval;
++}
+diff -urN linux-2.4.1/net/korbit/modules/CorbaFS/server/Makefile linux-2.4.1-korbit/net/korbit/modules/CorbaFS/server/Makefile
+--- linux-2.4.1/net/korbit/modules/CorbaFS/server/Makefile Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/CorbaFS/server/Makefile Thu Feb 1 11:47:04 2001
+@@ -0,0 +1,32 @@
++#
++# Makefile for KORBit
++#
++# Note! Dependencies are done automagically by 'make dep', which also
++# removes any old dependencies. DON'T put your own dependencies here
++# unless it's something special (ie not a .c file).
++#
++# Note 2! The CFLAGS definition is now in the main makefile...
++
++PROJECT = CorbaFS
++
++CFLAGS = -Wall `orbit-config --cflags server` -I../../..
++LDFLAGS = `orbit-config --libs server`
++OBJS = $(PROJECT)-common.o $(PROJECT)-skels.o $(PROJECT)-server.o
++ORBIT-IDL = orbit-idl
++
++$(PROJECT)-server: $(OBJS)
++ gcc -o $(PROJECT)-server $(OBJS) $(LDFLAGS)
++
++$(PROJECT)-server.o: $(PROJECT).h $(PROJECT)-skelimpl.c
++
++$(PROJECT).h $(PROJECT)-common.c $(PROJECT)-skels.c: ../$(PROJECT).idl
++ $(ORBIT-IDL) --nostubs ../$(PROJECT).idl
++
++clean:
++ rm -f $(OBJS) $(PROJECT)-server
++
++realclean: clean
++ rm -f $(PROJECT).h
++ rm -f $(PROJECT)-common.c
++ rm -f $(PROJECT)-skels.c
++ rm -f *~
+diff -urN linux-2.4.1/net/korbit/modules/CorbaFS/server/README linux-2.4.1-korbit/net/korbit/modules/CorbaFS/server/README
+--- linux-2.4.1/net/korbit/modules/CorbaFS/server/README Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/CorbaFS/server/README Thu Feb 1 11:47:04 2001
+@@ -0,0 +1,8 @@
++This server provides an NFS like capability of exporting an existing filesystem.
++
++ORB: ORBit
++Status: Working! (for readonly fs's)
++
++NOTE!!!!: When starting this server make sure you pass ORBit the options to
++ have it use ipv4 sockets and not unix domain sockets, or else bad
++ things will happen. You can use the included RunServer script.
+diff -urN linux-2.4.1/net/korbit/modules/CorbaFS/server/RunServer.sh linux-2.4.1-korbit/net/korbit/modules/CorbaFS/server/RunServer.sh
+--- linux-2.4.1/net/korbit/modules/CorbaFS/server/RunServer.sh Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/CorbaFS/server/RunServer.sh Thu Feb 1 11:47:04 2001
+@@ -0,0 +1 @@
++./CorbaFS-server -ORBIIOPUSock=0 -ORBIIOPIPv4=1
+diff -urN linux-2.4.1/net/korbit/modules/CorbaFS/server-perl/CVS/Entries linux-2.4.1-korbit/net/korbit/modules/CorbaFS/server-perl/CVS/Entries
+--- linux-2.4.1/net/korbit/modules/CorbaFS/server-perl/CVS/Entries Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/CorbaFS/server-perl/CVS/Entries Thu Feb 1 11:47:04 2001
+@@ -0,0 +1,3 @@
++/PerlServer/1.2/Thu Feb 1 09:47:04 2001//
++/README/1.1/Thu Feb 1 09:47:04 2001//
++D
+diff -urN linux-2.4.1/net/korbit/modules/CorbaFS/server-perl/CVS/Repository linux-2.4.1-korbit/net/korbit/modules/CorbaFS/server-perl/CVS/Repository
+--- linux-2.4.1/net/korbit/modules/CorbaFS/server-perl/CVS/Repository Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/CorbaFS/server-perl/CVS/Repository Thu Feb 1 11:47:04 2001
+@@ -0,0 +1 @@
++/cvsroot/korbit/linux/net/korbit/modules/CorbaFS/server-perl
+diff -urN linux-2.4.1/net/korbit/modules/CorbaFS/server-perl/CVS/Root linux-2.4.1-korbit/net/korbit/modules/CorbaFS/server-perl/CVS/Root
+--- linux-2.4.1/net/korbit/modules/CorbaFS/server-perl/CVS/Root Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/CorbaFS/server-perl/CVS/Root Thu Feb 1 11:47:04 2001
+@@ -0,0 +1 @@
++vraalsen@cvs.korbit.sourceforge.net:/cvsroot/korbit
+diff -urN linux-2.4.1/net/korbit/modules/CorbaFS/server-perl/PerlServer linux-2.4.1-korbit/net/korbit/modules/CorbaFS/server-perl/PerlServer
+--- linux-2.4.1/net/korbit/modules/CorbaFS/server-perl/PerlServer Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/CorbaFS/server-perl/PerlServer Thu Feb 1 11:47:04 2001
+@@ -0,0 +1,67 @@
++#!/usr/bin/perl -w
++use CORBA::ORBit idl => [ qw(../CorbaFS.idl) ];
++use Error qw(:try);
++use strict;
++
++
++package MyFSInode;
++@MyFSInode::ISA = qw(POA_CorbaFS::Inode);
++
++sub new {
++ my $self = bless { name => shift };
++ print "INODE CREATED: $self->{name}!\n";
++}
++
++sub getStatus {
++ my ($self) = @_;
++ print "$self->getStatus()\n";
++}
++
++sub readpage {
++ return "";
++}
++
++sub release {
++}
++
++
++package MyFileSystem;
++@MyFileSystem::ISA = qw(POA_CorbaFS::FileSystem);
++
++sub new {
++ my $self = bless { root => '/home' };
++}
++
++sub getInode {
++ my $path = shift;
++ print "getInode($path)\n";
++ return new MyFSInode($path);
++}
++
++sub readdir {
++ my $path = shift;
++ print "readdir($path)\n";
++ return [ { inode => 1, name => '...' } ];
++}
++
++sub readlink {
++ my $path = shift;
++ print "readlink($path)\n";
++ return "fredrik";
++}
++
++
++package Main;
++
++my $orb = CORBA::ORB_init("orbit-local-orb");
++my $poa = $orb->resolve_initial_references("RootPOA");
++
++my $Server = new MyFileSystem();
++my $id = $poa->activate_object($Server);
++my $ref = $orb->object_to_string($poa->id_to_reference($id));
++
++print "$ref\n";
++
++print "Running orb:\n";
++$orb->run();
++exit(0);
+diff -urN linux-2.4.1/net/korbit/modules/CorbaFS/server-perl/README linux-2.4.1-korbit/net/korbit/modules/CorbaFS/server-perl/README
+--- linux-2.4.1/net/korbit/modules/CorbaFS/server-perl/README Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/CorbaFS/server-perl/README Thu Feb 1 11:47:04 2001
+@@ -0,0 +1,4 @@
++Test filesystem implementation in Perl.
++
++ORB: ORBit/Perl
++Status: horribly broken
+diff -urN linux-2.4.1/net/korbit/modules/Echo/CVS/Entries linux-2.4.1-korbit/net/korbit/modules/Echo/CVS/Entries
+--- linux-2.4.1/net/korbit/modules/Echo/CVS/Entries Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/Echo/CVS/Entries Thu Feb 1 11:47:05 2001
+@@ -0,0 +1,4 @@
++/Makefile/1.3/Thu Feb 1 09:47:04 2001//
++/README/1.1/Thu Feb 1 09:47:05 2001//
++/echo.idl/1.1/Thu Feb 1 09:47:05 2001//
++D
+diff -urN linux-2.4.1/net/korbit/modules/Echo/CVS/Entries.Log linux-2.4.1-korbit/net/korbit/modules/Echo/CVS/Entries.Log
+--- linux-2.4.1/net/korbit/modules/Echo/CVS/Entries.Log Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/Echo/CVS/Entries.Log Thu Feb 1 11:47:06 2001
+@@ -0,0 +1,3 @@
++A D/client////
++A D/client-perl////
++A D/server////
+diff -urN linux-2.4.1/net/korbit/modules/Echo/CVS/Repository linux-2.4.1-korbit/net/korbit/modules/Echo/CVS/Repository
+--- linux-2.4.1/net/korbit/modules/Echo/CVS/Repository Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/Echo/CVS/Repository Thu Feb 1 11:47:04 2001
+@@ -0,0 +1 @@
++/cvsroot/korbit/linux/net/korbit/modules/Echo
+diff -urN linux-2.4.1/net/korbit/modules/Echo/CVS/Root linux-2.4.1-korbit/net/korbit/modules/Echo/CVS/Root
+--- linux-2.4.1/net/korbit/modules/Echo/CVS/Root Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/Echo/CVS/Root Thu Feb 1 11:47:04 2001
+@@ -0,0 +1 @@
++vraalsen@cvs.korbit.sourceforge.net:/cvsroot/korbit
+diff -urN linux-2.4.1/net/korbit/modules/Echo/Makefile linux-2.4.1-korbit/net/korbit/modules/Echo/Makefile
+--- linux-2.4.1/net/korbit/modules/Echo/Makefile Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/Echo/Makefile Thu Feb 1 11:47:04 2001
+@@ -0,0 +1,11 @@
++#
++# Makefile for KORBit/modules/Console
++#
++# Note! Dependencies are done automagically by 'make dep', which also
++# removes any old dependencies. DON'T put your own dependencies here
++# unless it's something special (ie not a .c file).
++
++subdir-$(CONFIG_CORBA_ECHO) := client server
++
++include $(TOPDIR)/Rules.make
++
+diff -urN linux-2.4.1/net/korbit/modules/Echo/README linux-2.4.1-korbit/net/korbit/modules/Echo/README
+--- linux-2.4.1/net/korbit/modules/Echo/README Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/Echo/README Thu Feb 1 11:47:05 2001
+@@ -0,0 +1,2 @@
++The Echo test is very similar to the console test, but it also "returns" a
++"random" number. The random number, in our case, is simply a constant.
+diff -urN linux-2.4.1/net/korbit/modules/Echo/client/CVS/Entries linux-2.4.1-korbit/net/korbit/modules/Echo/client/CVS/Entries
+--- linux-2.4.1/net/korbit/modules/Echo/client/CVS/Entries Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/Echo/client/CVS/Entries Thu Feb 1 11:47:05 2001
+@@ -0,0 +1,6 @@
++/Makefile/1.4/Thu Feb 1 09:47:05 2001//
++/Makefile.user/1.1/Thu Feb 1 09:47:05 2001//
++/README/1.1/Thu Feb 1 09:47:05 2001//
++/RunClient.sh/1.1/Thu Feb 1 09:47:05 2001//
++/echo-client.c/1.6/Thu Feb 1 09:47:05 2001//
++D
+diff -urN linux-2.4.1/net/korbit/modules/Echo/client/CVS/Repository linux-2.4.1-korbit/net/korbit/modules/Echo/client/CVS/Repository
+--- linux-2.4.1/net/korbit/modules/Echo/client/CVS/Repository Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/Echo/client/CVS/Repository Thu Feb 1 11:47:05 2001
+@@ -0,0 +1 @@
++/cvsroot/korbit/linux/net/korbit/modules/Echo/client
+diff -urN linux-2.4.1/net/korbit/modules/Echo/client/CVS/Root linux-2.4.1-korbit/net/korbit/modules/Echo/client/CVS/Root
+--- linux-2.4.1/net/korbit/modules/Echo/client/CVS/Root Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/Echo/client/CVS/Root Thu Feb 1 11:47:05 2001
+@@ -0,0 +1 @@
++vraalsen@cvs.korbit.sourceforge.net:/cvsroot/korbit
+diff -urN linux-2.4.1/net/korbit/modules/Echo/client/Makefile linux-2.4.1-korbit/net/korbit/modules/Echo/client/Makefile
+--- linux-2.4.1/net/korbit/modules/Echo/client/Makefile Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/Echo/client/Makefile Thu Feb 1 11:47:05 2001
+@@ -0,0 +1,20 @@
++#
++# Makefile for KORBit
++#
++# Note! Dependencies are done automagically by 'make dep', which also
++# removes any old dependencies. DON'T put your own dependencies here
++# unless it's something special (ie not a .c file).
++#
++# Note 2! The CFLAGS definition is now in the main makefile...
++
++O_TARGET := corba-echo-client.o
++
++obj-y := echo-common.o echo-stubs.o echo-client.o
++obj-m := $(O_TARGET)
++
++include ../../Makefile.module
++
++echo-client.c: echo.h
++
++echo.h echo-common.c echo-stubs.c: ../echo.idl
++ $(ORBIT_IDL) --noskels ../echo.idl
+diff -urN linux-2.4.1/net/korbit/modules/Echo/client/Makefile.user linux-2.4.1-korbit/net/korbit/modules/Echo/client/Makefile.user
+--- linux-2.4.1/net/korbit/modules/Echo/client/Makefile.user Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/Echo/client/Makefile.user Thu Feb 1 11:47:05 2001
+@@ -0,0 +1,32 @@
++#
++# Makefile for KORBit
++#
++# Note! Dependencies are done automagically by 'make dep', which also
++# removes any old dependencies. DON'T put your own dependencies here
++# unless it's something special (ie not a .c file).
++#
++# Note 2! The CFLAGS definition is now in the main makefile...
++
++PROJECT = echo
++
++CFLAGS = -Wall `orbit-config --cflags client` -I../../..
++LDFLAGS = `orbit-config --libs client`
++OBJS = $(PROJECT)-common.o $(PROJECT)-stubs.o $(PROJECT)-client.o
++ORBIT-IDL = orbit-idl
++
++$(PROJECT)-client: $(OBJS)
++ gcc -o $(PROJECT)-client $(OBJS) $(LDFLAGS)
++
++$(PROJECT)-client.c: $(PROJECT).h
++
++$(PROJECT).h $(PROJECT)-common.c $(PROJECT)-stubs.c: ../$(PROJECT).idl
++ $(ORBIT-IDL) --noskels ../$(PROJECT).idl
++
++clean:
++ rm -f $(OBJS) $(PROJECT)-client
++
++realclean: clean
++ rm -f $(PROJECT).h
++ rm -f $(PROJECT)-common.c
++ rm -f $(PROJECT)-stubs.c
++ rm -f *~
+diff -urN linux-2.4.1/net/korbit/modules/Echo/client/README linux-2.4.1-korbit/net/korbit/modules/Echo/client/README
+--- linux-2.4.1/net/korbit/modules/Echo/client/README Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/Echo/client/README Thu Feb 1 11:47:05 2001
+@@ -0,0 +1,4 @@
++This simply tests the Echo service.
++
++ORB: ORBit
++Status: working
+diff -urN linux-2.4.1/net/korbit/modules/Echo/client/RunClient.sh linux-2.4.1-korbit/net/korbit/modules/Echo/client/RunClient.sh
+--- linux-2.4.1/net/korbit/modules/Echo/client/RunClient.sh Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/Echo/client/RunClient.sh Thu Feb 1 11:47:05 2001
+@@ -0,0 +1,3 @@
++#!/bin/sh
++date
++./echo-client `cat /proc/corba/echo-server` 5
+diff -urN linux-2.4.1/net/korbit/modules/Echo/client/echo-client.c linux-2.4.1-korbit/net/korbit/modules/Echo/client/echo-client.c
+--- linux-2.4.1/net/korbit/modules/Echo/client/echo-client.c Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/Echo/client/echo-client.c Thu Feb 1 11:47:05 2001
+@@ -0,0 +1,119 @@
++#include <stdio.h>
++#include <stdlib.h>
++#include <sys/time.h>
++#include <unistd.h>
++#include <orb/orbit.h>
++
++#ifdef __KERNEL__
++#include <linux/init.h>
++#include <linux/module.h>
++#include "korbit.h"
++#endif
++#include "echo.h"
++
++Echo echo_client, bec;
++
++#define BATCH_SIZE 1
++
++
++#ifndef __KERNEL__
++int main (int argc, char *argv[]) {
++#else
++int __init corba_echo_init(void) {
++ int argc = 1; char *argv[] = { "echo-client", 0, 0 };
++#endif
++ CORBA_Environment ev;
++ CORBA_ORB orb;
++ CORBA_long rv;
++ char buf[30];
++ int i, j;
++
++ int niters = 5;
++
++#ifndef __KERNEL__
++ struct timeval start, end;
++ long diff, diffsum = 0;
++#endif
++
++ CORBA_exception_init(&ev);
++ orb = CORBA_ORB_init(&argc, argv, "orbit-local-orb", &ev);
++
++#ifdef __KERNEL__
++ {
++ int c, fd = open("/tmp/echo-ior", O_RDONLY, 0);
++ if (fd == -1)
++ return -1;
++ printf("Reading IOR from /tmp/echo-ior\n");
++ argv[1] = malloc(501);
++ c = read(fd, argv[1], 500);
++ argv[1][c] = '\0';
++ printf("Reading %d bytes: %s\n", c, argv[1]);
++ }
++#else
++ if(argc < 2)
++ {
++ printf("Need an IOR as argv[1]\n");
++ return 1;
++ }
++
++ if(argc == 3)
++ niters = atoi(argv[2]);
++#endif
++
++ echo_client = CORBA_ORB_string_to_object(orb, argv[1], &ev);
++ if (!echo_client) {
++ printf("Cannot bind to %s\n", argv[1]);
++ return 1;
++ }
++
++ for(i = 0; i < niters; i++) {
++ g_snprintf(buf, sizeof(buf), "Hello, world [%d]", i);
++#ifdef __KERNEL__
++ bec = Echo_echoString(echo_client, buf, &rv, &ev);
++#else
++ gettimeofday(&start, NULL);
++ for (j = BATCH_SIZE; j > 0; j--) {
++ bec = Echo_echoString(echo_client, buf, &rv, &ev);
++ if (j != 1) CORBA_Object_release(bec, &ev);
++ }
++ gettimeofday(&end, NULL);
++ diff = (end.tv_sec - start.tv_sec) * 1000000 + (end.tv_usec - start.tv_usec);
++ diff /= BATCH_SIZE;
++ diffsum += diff;
++
++ printf("duration = %d usec\t", diff);
++#endif
++
++ if(ev._major != CORBA_NO_EXCEPTION) {
++ printf("\nWe got exception %d from echoString!\n", ev._major);
++ return 1;
++ }
++
++ CORBA_Object_release(echo_client, &ev);
++ if(ev._major != CORBA_NO_EXCEPTION) {
++ printf("we got exception %d from release!\n", ev._major);
++ return 1;
++ }
++
++ printf("[client] %d\n", rv);
++
++ echo_client = bec; bec = CORBA_OBJECT_NIL;
++ }
++
++#ifndef __KERNEL__
++ printf("duration average = %d usec\n", diffsum / niters);
++ CORBA_Object_release(echo_client, &ev);
++ CORBA_Object_release((CORBA_Object)orb, &ev);
++#endif
++
++ return 0;
++}
++
++
++#ifdef __KERNEL__
++void corba_echo_exit(void) {
++}
++
++module_init(corba_echo_init)
++module_exit(corba_echo_exit)
++#endif
+diff -urN linux-2.4.1/net/korbit/modules/Echo/client/echo-common.c linux-2.4.1-korbit/net/korbit/modules/Echo/client/echo-common.c
+--- linux-2.4.1/net/korbit/modules/Echo/client/echo-common.c Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/Echo/client/echo-common.c Thu Feb 1 16:36:36 2001
+@@ -0,0 +1,27 @@
++/*
++ * This file was generated by orbit-idl - DO NOT EDIT!
++ */
++
++#include <string.h>
++#include "echo.h"
++
++#if ( (TC_IMPL_TC_Echo_0 == 'e') \
++&& (TC_IMPL_TC_Echo_1 == 'c') \
++&& (TC_IMPL_TC_Echo_2 == 'h') \
++&& (TC_IMPL_TC_Echo_3 == 'o') \
++) && !defined(TC_DEF_TC_Echo)
++#define TC_DEF_TC_Echo 1
++const struct CORBA_TypeCode_struct TC_Echo_struct = {
++
++ {{(ORBit_RootObject_Interface *) & ORBit_TypeCode_epv, TRUE, -1},
++ ORBIT_PSEUDO_TYPECODE},
++
++ CORBA_tk_objref, "Echo", "IDL:Echo:1.0",
++ 0, 0,
++ NULL,
++ NULL,
++ NULL,
++ CORBA_OBJECT_NIL, 0, -1, 0, 0
++};
++#endif
++CORBA_unsigned_long Echo__classid = 0;
+diff -urN linux-2.4.1/net/korbit/modules/Echo/client/echo-stubs.c linux-2.4.1-korbit/net/korbit/modules/Echo/client/echo-stubs.c
+--- linux-2.4.1/net/korbit/modules/Echo/client/echo-stubs.c Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/Echo/client/echo-stubs.c Thu Feb 1 16:36:36 2001
+@@ -0,0 +1,134 @@
++/*
++ * This file was generated by orbit-idl - DO NOT EDIT!
++ */
++
++#include <string.h>
++#include "echo.h"
++
++Echo
++Echo_echoString(Echo _obj, const CORBA_char * astring, CORBA_long * anum,
++ CORBA_Environment * ev)
++{
++ register GIOP_unsigned_long _ORBIT_request_id,
++ _ORBIT_system_exception_minor;
++ register CORBA_completion_status _ORBIT_completion_status;
++ register GIOPSendBuffer *_ORBIT_send_buffer;
++ register GIOPRecvBuffer *_ORBIT_recv_buffer;
++ register GIOPConnection *_cnx;
++ Echo _ORBIT_retval;
++
++ if (_obj->servant && _obj->vepv && Echo__classid) {
++ _ORBIT_retval =
++ ((POA_Echo__epv *) _obj->vepv[Echo__classid])->echoString(_obj->
++ servant,
++ astring,
++ anum, ev);
++ return _ORBIT_retval;
++ }
++ _cnx = ORBit_object_get_connection(_obj);
++ _ORBIT_retry_request:
++ _ORBIT_send_buffer = NULL;
++ _ORBIT_recv_buffer = NULL;
++ _ORBIT_completion_status = CORBA_COMPLETED_NO;
++ _ORBIT_request_id = GPOINTER_TO_UINT(alloca(0));
++ { /* marshalling */
++ static const struct
++ {
++ CORBA_unsigned_long len;
++ char opname[11];
++ }
++ _ORBIT_operation_name_data =
++ {
++ 11, "echoString"};
++ static const struct iovec _ORBIT_operation_vec =
++ { (gpointer) & _ORBIT_operation_name_data, 15 };
++ register CORBA_unsigned_long _ORBIT_tmpvar_0;
++ CORBA_unsigned_long _ORBIT_tmpvar_1;
++
++ _ORBIT_send_buffer =
++ giop_send_request_buffer_use(_cnx, NULL, _ORBIT_request_id,
++ CORBA_TRUE,
++ &(_obj->active_profile->object_key_vec),
++ &_ORBIT_operation_vec,
++ &ORBit_default_principal_iovec);
++
++ _ORBIT_system_exception_minor = ex_CORBA_COMM_FAILURE;
++ if (!_ORBIT_send_buffer)
++ goto _ORBIT_system_exception;
++ _ORBIT_tmpvar_1 = strlen(astring) + 1;
++ giop_message_buffer_do_alignment(GIOP_MESSAGE_BUFFER
++ (_ORBIT_send_buffer), 4);
++ {
++ guchar *_ORBIT_t;
++
++ _ORBIT_t = alloca(sizeof(_ORBIT_tmpvar_1));
++ memcpy(_ORBIT_t, &(_ORBIT_tmpvar_1), sizeof(_ORBIT_tmpvar_1));
++ giop_message_buffer_append_mem(GIOP_MESSAGE_BUFFER
++ (_ORBIT_send_buffer), (_ORBIT_t),
++ sizeof(_ORBIT_tmpvar_1));
++ }
++ giop_message_buffer_append_mem(GIOP_MESSAGE_BUFFER(_ORBIT_send_buffer),
++ (astring),
++ sizeof(astring[_ORBIT_tmpvar_0]) *
++ _ORBIT_tmpvar_1);
++ giop_send_buffer_write(_ORBIT_send_buffer);
++ _ORBIT_completion_status = CORBA_COMPLETED_MAYBE;
++ giop_send_buffer_unuse(_ORBIT_send_buffer);
++ _ORBIT_send_buffer = NULL;
++ }
++ { /* demarshalling */
++ register guchar *_ORBIT_curptr;
++
++ _ORBIT_recv_buffer =
++ giop_recv_reply_buffer_use_2(_cnx, _ORBIT_request_id, TRUE);
++ if (!_ORBIT_recv_buffer)
++ goto _ORBIT_system_exception;
++ _ORBIT_completion_status = CORBA_COMPLETED_YES;
++ if (_ORBIT_recv_buffer->message.u.reply.reply_status !=
++ GIOP_NO_EXCEPTION) goto _ORBIT_msg_exception;
++ _ORBIT_curptr = GIOP_RECV_BUFFER(_ORBIT_recv_buffer)->cur;
++ if (giop_msg_conversion_needed(GIOP_MESSAGE_BUFFER(_ORBIT_recv_buffer))) {
++ GIOP_RECV_BUFFER(_ORBIT_recv_buffer)->cur = _ORBIT_curptr;
++ _ORBIT_retval =
++ ORBit_demarshal_object(_ORBIT_recv_buffer,
++ GIOP_MESSAGE_BUFFER(_ORBIT_recv_buffer)->
++ connection->orb_data);
++ _ORBIT_curptr = GIOP_RECV_BUFFER(_ORBIT_recv_buffer)->cur;
++ _ORBIT_curptr = ALIGN_ADDRESS(_ORBIT_curptr, 4);
++
++ (*((guint32 *) & ((*anum)))) =
++ GUINT32_SWAP_LE_BE(*((guint32 *) _ORBIT_curptr));} else {
++ GIOP_RECV_BUFFER(_ORBIT_recv_buffer)->cur = _ORBIT_curptr;
++ _ORBIT_retval =
++ ORBit_demarshal_object(_ORBIT_recv_buffer,
++ GIOP_MESSAGE_BUFFER(_ORBIT_recv_buffer)->
++ connection->orb_data);
++ _ORBIT_curptr = GIOP_RECV_BUFFER(_ORBIT_recv_buffer)->cur;
++ _ORBIT_curptr = ALIGN_ADDRESS(_ORBIT_curptr, 4);
++ (*anum) = *((CORBA_long *) _ORBIT_curptr);
++ }
++ giop_recv_buffer_unuse(_ORBIT_recv_buffer);
++ return _ORBIT_retval;
++ _ORBIT_system_exception:
++ CORBA_exception_set_system(ev, _ORBIT_system_exception_minor,
++ _ORBIT_completion_status);
++ giop_recv_buffer_unuse(_ORBIT_recv_buffer);
++ giop_send_buffer_unuse(_ORBIT_send_buffer);
++ return _ORBIT_retval;
++ _ORBIT_msg_exception:
++ if (_ORBIT_recv_buffer->message.u.reply.reply_status ==
++ GIOP_LOCATION_FORWARD) {
++ if (_obj->forward_locations != NULL)
++ ORBit_delete_profiles(_obj->forward_locations);
++ _obj->forward_locations = ORBit_demarshal_IOR(_ORBIT_recv_buffer);
++ _cnx = ORBit_object_get_forwarded_connection(_obj);
++ giop_recv_buffer_unuse(_ORBIT_recv_buffer);
++
++ goto _ORBIT_retry_request;
++ } else {
++ ORBit_handle_exception(_ORBIT_recv_buffer, ev, NULL, _obj->orb);
++ giop_recv_buffer_unuse(_ORBIT_recv_buffer);
++ return _ORBIT_retval;
++ }
++ }
++}
+diff -urN linux-2.4.1/net/korbit/modules/Echo/client/echo.h linux-2.4.1-korbit/net/korbit/modules/Echo/client/echo.h
+--- linux-2.4.1/net/korbit/modules/Echo/client/echo.h Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/Echo/client/echo.h Thu Feb 1 16:36:36 2001
+@@ -0,0 +1,77 @@
++/*
++ * This file was generated by orbit-idl - DO NOT EDIT!
++ */
++
++#include <glib.h>
++#define ORBIT_IDL_SERIAL 9
++#include <orb/orbit.h>
++
++#ifndef echo_H
++#define echo_H 1
++#ifdef __cplusplus
++extern "C"
++{
++#endif /* __cplusplus */
++
++/** typedefs **/
++#if !defined(ORBIT_DECL_Echo) && !defined(_Echo_defined)
++#define ORBIT_DECL_Echo 1
++#define _Echo_defined 1
++#define Echo__free CORBA_Object__free
++ typedef CORBA_Object Echo;
++ extern CORBA_unsigned_long Echo__classid;
++#if !defined(TC_IMPL_TC_Echo_0)
++#define TC_IMPL_TC_Echo_0 'e'
++#define TC_IMPL_TC_Echo_1 'c'
++#define TC_IMPL_TC_Echo_2 'h'
++#define TC_IMPL_TC_Echo_3 'o'
++ extern const struct CORBA_TypeCode_struct TC_Echo_struct;
++#define TC_Echo ((CORBA_TypeCode)&TC_Echo_struct)
++#endif
++#endif
++
++/** POA structures **/
++ typedef struct
++ {
++ void *_private;
++
++ Echo(*echoString) (PortableServer_Servant _servant,
++ const CORBA_char * astring, CORBA_long * anum,
++ CORBA_Environment * ev);
++ }
++ POA_Echo__epv;
++ typedef struct
++ {
++ PortableServer_ServantBase__epv *_base_epv;
++ POA_Echo__epv *Echo_epv;
++ }
++ POA_Echo__vepv;
++ typedef struct
++ {
++ void *_private;
++ POA_Echo__vepv *vepv;
++ }
++ POA_Echo;
++ extern void POA_Echo__init(PortableServer_Servant servant,
++ CORBA_Environment * ev);
++ extern void POA_Echo__fini(PortableServer_Servant servant,
++ CORBA_Environment * ev);
++
++/** prototypes **/
++ Echo Echo_echoString(Echo _obj, const CORBA_char * astring,
++ CORBA_long * anum, CORBA_Environment * ev);
++
++ void _ORBIT_skel_Echo_echoString(POA_Echo * _ORBIT_servant,
++ GIOPRecvBuffer * _ORBIT_recv_buffer,
++ CORBA_Environment * ev,
++ Echo(*_impl_echoString)
++ (PortableServer_Servant _servant,
++ const CORBA_char * astring,
++ CORBA_long * anum,
++ CORBA_Environment * ev));
++#ifdef __cplusplus
++}
++#endif /* __cplusplus */
++
++#endif
++#undef ORBIT_IDL_SERIAL
+diff -urN linux-2.4.1/net/korbit/modules/Echo/client-perl/CVS/Entries linux-2.4.1-korbit/net/korbit/modules/Echo/client-perl/CVS/Entries
+--- linux-2.4.1/net/korbit/modules/Echo/client-perl/CVS/Entries Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/Echo/client-perl/CVS/Entries Thu Feb 1 11:47:06 2001
+@@ -0,0 +1,3 @@
++/PerlTest/1.2/Thu Feb 1 09:47:06 2001//
++/README/1.1/Thu Feb 1 09:47:06 2001//
++D
+diff -urN linux-2.4.1/net/korbit/modules/Echo/client-perl/CVS/Repository linux-2.4.1-korbit/net/korbit/modules/Echo/client-perl/CVS/Repository
+--- linux-2.4.1/net/korbit/modules/Echo/client-perl/CVS/Repository Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/Echo/client-perl/CVS/Repository Thu Feb 1 11:47:06 2001
+@@ -0,0 +1 @@
++/cvsroot/korbit/linux/net/korbit/modules/Echo/client-perl
+diff -urN linux-2.4.1/net/korbit/modules/Echo/client-perl/CVS/Root linux-2.4.1-korbit/net/korbit/modules/Echo/client-perl/CVS/Root
+--- linux-2.4.1/net/korbit/modules/Echo/client-perl/CVS/Root Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/Echo/client-perl/CVS/Root Thu Feb 1 11:47:06 2001
+@@ -0,0 +1 @@
++vraalsen@cvs.korbit.sourceforge.net:/cvsroot/korbit
+diff -urN linux-2.4.1/net/korbit/modules/Echo/client-perl/PerlTest linux-2.4.1-korbit/net/korbit/modules/Echo/client-perl/PerlTest
+--- linux-2.4.1/net/korbit/modules/Echo/client-perl/PerlTest Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/Echo/client-perl/PerlTest Thu Feb 1 11:47:06 2001
+@@ -0,0 +1,17 @@
++#!/usr/bin/perl -w
++
++use CORBA::ORBit idl => [ qw(../echo.idl) ];
++use Error qw(:try);
++use strict;
++
++my $orb = CORBA::ORB_init("orbit-local-orb");
++open IOR, "/proc/corba/echo-server" or die "no console server found!";
++my $ior = <IOR>;
++close IOR;
++chomp($ior); # Kill fredrik's newline...
++
++my $echo = $orb->string_to_object($ior);
++# Echo echoString(in string astring, out long anum);
++my ($echo2, $num) = $echo->echoString("Echo Strange World");
++
++print "Return Echo = $echo2\nnum = $num\n";
+diff -urN linux-2.4.1/net/korbit/modules/Echo/client-perl/README linux-2.4.1-korbit/net/korbit/modules/Echo/client-perl/README
+--- linux-2.4.1/net/korbit/modules/Echo/client-perl/README Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/Echo/client-perl/README Thu Feb 1 11:47:06 2001
+@@ -0,0 +1,4 @@
++Another test of the echo server.
++
++ORB: ORBit/Perl
++Status: Working fine
+diff -urN linux-2.4.1/net/korbit/modules/Echo/echo.idl linux-2.4.1-korbit/net/korbit/modules/Echo/echo.idl
+--- linux-2.4.1/net/korbit/modules/Echo/echo.idl Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/Echo/echo.idl Thu Feb 1 11:47:05 2001
+@@ -0,0 +1,3 @@
++interface Echo {
++ Echo echoString(in string astring, out long anum);
++};
+diff -urN linux-2.4.1/net/korbit/modules/Echo/server/CVS/Entries linux-2.4.1-korbit/net/korbit/modules/Echo/server/CVS/Entries
+--- linux-2.4.1/net/korbit/modules/Echo/server/CVS/Entries Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/Echo/server/CVS/Entries Thu Feb 1 11:47:06 2001
+@@ -0,0 +1,6 @@
++/Makefile/1.2/Thu Feb 1 09:47:06 2001//
++/Makefile.user/1.3/Thu Feb 1 09:47:06 2001//
++/README/1.1/Thu Feb 1 09:47:06 2001//
++/RunServer.sh/1.1/Thu Feb 1 09:47:06 2001//
++/echo-server.c/1.8/Thu Feb 1 09:47:06 2001//
++D
+diff -urN linux-2.4.1/net/korbit/modules/Echo/server/CVS/Repository linux-2.4.1-korbit/net/korbit/modules/Echo/server/CVS/Repository
+--- linux-2.4.1/net/korbit/modules/Echo/server/CVS/Repository Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/Echo/server/CVS/Repository Thu Feb 1 11:47:06 2001
+@@ -0,0 +1 @@
++/cvsroot/korbit/linux/net/korbit/modules/Echo/server
+diff -urN linux-2.4.1/net/korbit/modules/Echo/server/CVS/Root linux-2.4.1-korbit/net/korbit/modules/Echo/server/CVS/Root
+--- linux-2.4.1/net/korbit/modules/Echo/server/CVS/Root Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/Echo/server/CVS/Root Thu Feb 1 11:47:06 2001
+@@ -0,0 +1 @@
++vraalsen@cvs.korbit.sourceforge.net:/cvsroot/korbit
+diff -urN linux-2.4.1/net/korbit/modules/Echo/server/Makefile linux-2.4.1-korbit/net/korbit/modules/Echo/server/Makefile
+--- linux-2.4.1/net/korbit/modules/Echo/server/Makefile Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/Echo/server/Makefile Thu Feb 1 11:47:06 2001
+@@ -0,0 +1,21 @@
++#
++# Makefile for KORBit
++#
++# Note! Dependencies are done automagically by 'make dep', which also
++# removes any old dependencies. DON'T put your own dependencies here
++# unless it's something special (ie not a .c file).
++#
++# Note 2! The CFLAGS definition is now in the main makefile...
++
++O_TARGET := corba-echo-server.o
++
++obj-y := echo-server.o echo-skels.o echo-common.o
++obj-m := $(O_TARGET)
++
++include ../../Makefile.module
++
++echo-server.c: echo.h echo-skels.c
++
++
++echo.h echo-common.c echo-skels.c: ../echo.idl
++ $(ORBIT_IDL) ../echo.idl
+diff -urN linux-2.4.1/net/korbit/modules/Echo/server/Makefile.user linux-2.4.1-korbit/net/korbit/modules/Echo/server/Makefile.user
+--- linux-2.4.1/net/korbit/modules/Echo/server/Makefile.user Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/Echo/server/Makefile.user Thu Feb 1 11:47:06 2001
+@@ -0,0 +1,27 @@
++#
++# Makefile for user level server
++#
++
++PROJECT = echo
++
++CFLAGS = -Wall `orbit-config --cflags server` -I../../..
++LDFLAGS = `orbit-config --libs server`
++OBJS = $(PROJECT)-common.o $(PROJECT)-skels.o $(PROJECT)-server.o
++ORBIT-IDL = orbit-idl
++
++$(PROJECT)-server: $(OBJS)
++ gcc -o $(PROJECT)-server $(OBJS) $(LDFLAGS)
++
++$(PROJECT)-server.c: $(PROJECT).h
++
++$(PROJECT).h $(PROJECT)-common.c $(PROJECT)-skels.c: ../$(PROJECT).idl
++ $(ORBIT-IDL) --nostubs ../$(PROJECT).idl
++
++clean:
++ rm -f $(OBJS) $(PROJECT)-server
++
++realclean: clean
++ rm -f $(PROJECT).h
++ rm -f $(PROJECT)-common.c
++ rm -f $(PROJECT)-skels.c
++ rm -f *~
+diff -urN linux-2.4.1/net/korbit/modules/Echo/server/README linux-2.4.1-korbit/net/korbit/modules/Echo/server/README
+--- linux-2.4.1/net/korbit/modules/Echo/server/README Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/Echo/server/README Thu Feb 1 11:47:06 2001
+@@ -0,0 +1,5 @@
++This server implements the kernel side interface in terms of printk.
++
++This server also builds in user space with ORBit. Build with
++ make -f Makefile.user
++
+diff -urN linux-2.4.1/net/korbit/modules/Echo/server/RunServer.sh linux-2.4.1-korbit/net/korbit/modules/Echo/server/RunServer.sh
+--- linux-2.4.1/net/korbit/modules/Echo/server/RunServer.sh Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/Echo/server/RunServer.sh Thu Feb 1 11:47:06 2001
+@@ -0,0 +1 @@
++./echo-server -ORBIIOPUSock=0 -ORBIIOPIPv4=1
+diff -urN linux-2.4.1/net/korbit/modules/Echo/server/echo-common.c linux-2.4.1-korbit/net/korbit/modules/Echo/server/echo-common.c
+--- linux-2.4.1/net/korbit/modules/Echo/server/echo-common.c Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/Echo/server/echo-common.c Thu Feb 1 16:36:57 2001
+@@ -0,0 +1,27 @@
++/*
++ * This file was generated by orbit-idl - DO NOT EDIT!
++ */
++
++#include <string.h>
++#include "echo.h"
++
++#if ( (TC_IMPL_TC_Echo_0 == 'e') \
++&& (TC_IMPL_TC_Echo_1 == 'c') \
++&& (TC_IMPL_TC_Echo_2 == 'h') \
++&& (TC_IMPL_TC_Echo_3 == 'o') \
++) && !defined(TC_DEF_TC_Echo)
++#define TC_DEF_TC_Echo 1
++const struct CORBA_TypeCode_struct TC_Echo_struct = {
++
++ {{(ORBit_RootObject_Interface *) & ORBit_TypeCode_epv, TRUE, -1},
++ ORBIT_PSEUDO_TYPECODE},
++
++ CORBA_tk_objref, "Echo", "IDL:Echo:1.0",
++ 0, 0,
++ NULL,
++ NULL,
++ NULL,
++ CORBA_OBJECT_NIL, 0, -1, 0, 0
++};
++#endif
++CORBA_unsigned_long Echo__classid = 0;
+diff -urN linux-2.4.1/net/korbit/modules/Echo/server/echo-server.c linux-2.4.1-korbit/net/korbit/modules/Echo/server/echo-server.c
+--- linux-2.4.1/net/korbit/modules/Echo/server/echo-server.c Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/Echo/server/echo-server.c Thu Feb 1 11:47:06 2001
+@@ -0,0 +1,103 @@
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <signal.h>
++#include <orb/orbit.h>
++
++#include <linux/init.h>
++#include <linux/module.h>
++#include "echo.h"
++#include "glib.h"
++#include "korbit.h"
++
++Echo echo_client = CORBA_OBJECT_NIL;
++
++static CORBA_Object
++do_echoString(PortableServer_Servant servant,
++ CORBA_char *astring,
++ CORBA_long *outnum,
++ CORBA_Environment *ev);
++
++PortableServer_ServantBase__epv base_epv = {
++ NULL,
++ NULL,
++ NULL
++};
++POA_Echo__epv echo_epv = { NULL, do_echoString };
++POA_Echo__vepv poa_echo_vepv = { &base_epv, &echo_epv };
++POA_Echo poa_echo_servant = { NULL, &poa_echo_vepv };
++
++PortableServer_ObjectId objid = {0, sizeof("myEchoString"), "myEchoString"};
++PortableServer_POA poa;
++CORBA_Environment *ev;
++
++#ifdef __KERNEL__
++int __init corba_echo_init(void)
++#else
++int main(int argc, char *argv[])
++#endif
++{
++#ifdef __KERNEL__
++ int argc = 1; char *argv[] = { "server", 0 };
++#endif
++ CORBA_ORB orb;
++ ev = g_new0(CORBA_Environment, 1);
++ orb = CORBA_ORB_init(&argc, argv, "orbit-local-orb", ev);
++ if (!orb) {
++ printf("Error getting ORB!\n");
++ return 1;
++ }
++
++ poa = (PortableServer_POA)
++ CORBA_ORB_resolve_initial_references(orb, "RootPOA", ev);
++ if (!poa) {
++ printf("Error getting POA!\n");
++ return 1;
++ }
++
++ PortableServer_POAManager_activate(
++ PortableServer_POA__get_the_POAManager(poa, ev), ev);
++
++
++ POA_Echo__init(&poa_echo_servant, ev);
++ PortableServer_POA_activate_object_with_id(poa,
++ &objid, &poa_echo_servant, ev);
++
++ echo_client = PortableServer_POA_servant_to_reference(poa,
++ &poa_echo_servant,
++ ev);
++ if (!echo_client) {
++ printf("Cannot get objref\n");
++ return 1;
++ }
++
++ korbit_register_ior("echo-server", echo_client, orb, ev);
++
++ CORBA_ORB_run(orb, ev);
++ return 0;
++}
++
++#ifdef __KERNEL__
++void corba_echo_exit(void) {
++ PortableServer_POA_deactivate_object(poa, &objid, ev);
++ remove_proc_entry("corba/echo-server", 0);
++}
++
++module_init(corba_echo_init)
++module_exit(corba_echo_exit)
++#endif
++
++static CORBA_Object
++do_echoString(PortableServer_Servant servant,
++ CORBA_char *astring,
++ CORBA_long *outnum,
++ CORBA_Environment *ev)
++{
++ *outnum = 12345678;
++
++#if 1
++ g_message("[server] %s -> %d", astring, *outnum);
++#endif
++
++ return CORBA_Object_duplicate(echo_client, ev);
++}
+diff -urN linux-2.4.1/net/korbit/modules/Echo/server/echo-skels.c linux-2.4.1-korbit/net/korbit/modules/Echo/server/echo-skels.c
+--- linux-2.4.1/net/korbit/modules/Echo/server/echo-skels.c Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/Echo/server/echo-skels.c Thu Feb 1 16:36:57 2001
+@@ -0,0 +1,115 @@
++/*
++ * This file was generated by orbit-idl - DO NOT EDIT!
++ */
++
++#include <string.h>
++#include "echo.h"
++
++void
++_ORBIT_skel_Echo_echoString(POA_Echo * _ORBIT_servant,
++ GIOPRecvBuffer * _ORBIT_recv_buffer,
++ CORBA_Environment * ev,
++ Echo(*_impl_echoString) (PortableServer_Servant
++ _servant,
++ const CORBA_char *
++ astring,
++ CORBA_long * anum,
++ CORBA_Environment * ev))
++{
++ Echo _ORBIT_retval;
++ CORBA_char *astring;
++ CORBA_long anum;
++
++ { /* demarshalling */
++ guchar *_ORBIT_curptr;
++ register CORBA_unsigned_long _ORBIT_tmpvar_2;
++ CORBA_unsigned_long _ORBIT_tmpvar_3;
++
++ _ORBIT_curptr = GIOP_RECV_BUFFER(_ORBIT_recv_buffer)->cur;
++ if (giop_msg_conversion_needed(GIOP_MESSAGE_BUFFER(_ORBIT_recv_buffer))) {
++ _ORBIT_curptr = ALIGN_ADDRESS(_ORBIT_curptr, 4);
++
++ (*((guint32 *) & (_ORBIT_tmpvar_3))) =
++ GUINT32_SWAP_LE_BE(*((guint32 *) _ORBIT_curptr));
++ _ORBIT_curptr += 4;
++ astring = (void *) _ORBIT_curptr;
++ _ORBIT_curptr += sizeof(astring[_ORBIT_tmpvar_2]) * _ORBIT_tmpvar_3;
++ } else {
++ _ORBIT_curptr = ALIGN_ADDRESS(_ORBIT_curptr, 4);
++ _ORBIT_tmpvar_3 = *((CORBA_unsigned_long *) _ORBIT_curptr);
++ _ORBIT_curptr += 4;
++ astring = (void *) _ORBIT_curptr;
++ _ORBIT_curptr += sizeof(astring[_ORBIT_tmpvar_2]) * _ORBIT_tmpvar_3;
++ }
++ }
++ _ORBIT_retval = _impl_echoString(_ORBIT_servant, astring, &(anum), ev);
++ { /* marshalling */
++ register GIOPSendBuffer *_ORBIT_send_buffer;
++
++ _ORBIT_send_buffer =
++ giop_send_reply_buffer_use(GIOP_MESSAGE_BUFFER(_ORBIT_recv_buffer)->
++ connection, NULL,
++ _ORBIT_recv_buffer->message.u.request.
++ request_id, ev->_major);
++ if (_ORBIT_send_buffer) {
++ if (ev->_major == CORBA_NO_EXCEPTION) {
++ ORBit_marshal_object(_ORBIT_send_buffer, _ORBIT_retval);
++ giop_message_buffer_do_alignment(GIOP_MESSAGE_BUFFER
++ (_ORBIT_send_buffer), 4);
++ giop_message_buffer_append_mem(GIOP_MESSAGE_BUFFER
++ (_ORBIT_send_buffer), &(anum),
++ sizeof(anum));
++ } else
++ ORBit_send_system_exception(_ORBIT_send_buffer, ev);
++ giop_send_buffer_write(_ORBIT_send_buffer);
++ giop_send_buffer_unuse(_ORBIT_send_buffer);
++ }
++ if (ev->_major == CORBA_NO_EXCEPTION)
++ CORBA_Object_release(_ORBIT_retval, ev);
++ }
++}
++static ORBitSkeleton
++get_skel_Echo(POA_Echo * servant,
++ GIOPRecvBuffer * _ORBIT_recv_buffer, gpointer * impl)
++{
++ gchar *opname = _ORBIT_recv_buffer->message.u.request.operation;
++
++ switch (opname[0]) {
++ case 'e':
++ if (strcmp((opname + 1), "choString"))
++ break;
++ *impl = (gpointer) servant->vepv->Echo_epv->echoString;
++ return (ORBitSkeleton) _ORBIT_skel_Echo_echoString;
++ break;
++ default:
++ break;
++ }
++ return NULL;
++}
++
++static void
++init_local_objref_Echo(CORBA_Object obj, POA_Echo * servant)
++{
++ obj->vepv[Echo__classid] = servant->vepv->Echo_epv;
++}
++
++void
++POA_Echo__init(PortableServer_Servant servant, CORBA_Environment * env)
++{
++ static const PortableServer_ClassInfo class_info =
++ { (ORBit_impl_finder) & get_skel_Echo, "IDL:Echo:1.0",
++ (ORBit_local_objref_init) & init_local_objref_Echo };
++
++ PortableServer_ServantBase__init(((PortableServer_ServantBase *) servant),
++ env);
++ ORBIT_OBJECT_KEY(((PortableServer_ServantBase *) servant)->_private)->
++ class_info = (PortableServer_ClassInfo *) & class_info;
++ if (!Echo__classid)
++ Echo__classid = ORBit_register_class(&class_info);
++}
++
++void
++POA_Echo__fini(PortableServer_Servant servant, CORBA_Environment * env)
++{
++ PortableServer_ServantBase__fini(servant, env);
++}
+diff -urN linux-2.4.1/net/korbit/modules/Echo/server/echo-stubs.c linux-2.4.1-korbit/net/korbit/modules/Echo/server/echo-stubs.c
+--- linux-2.4.1/net/korbit/modules/Echo/server/echo-stubs.c Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/Echo/server/echo-stubs.c Thu Feb 1 16:36:57 2001
+@@ -0,0 +1,134 @@
++/*
++ * This file was generated by orbit-idl - DO NOT EDIT!
++ */
++
++#include <string.h>
++#include "echo.h"
++
++Echo
++Echo_echoString(Echo _obj, const CORBA_char * astring, CORBA_long * anum,
++ CORBA_Environment * ev)
++{
++ register GIOP_unsigned_long _ORBIT_request_id,
++ _ORBIT_system_exception_minor;
++ register CORBA_completion_status _ORBIT_completion_status;
++ register GIOPSendBuffer *_ORBIT_send_buffer;
++ register GIOPRecvBuffer *_ORBIT_recv_buffer;
++ register GIOPConnection *_cnx;
++ Echo _ORBIT_retval;
++
++ if (_obj->servant && _obj->vepv && Echo__classid) {
++ _ORBIT_retval =
++ ((POA_Echo__epv *) _obj->vepv[Echo__classid])->echoString(_obj->
++ servant,
++ astring,
++ anum, ev);
++ return _ORBIT_retval;
++ }
++ _cnx = ORBit_object_get_connection(_obj);
++ _ORBIT_retry_request:
++ _ORBIT_send_buffer = NULL;
++ _ORBIT_recv_buffer = NULL;
++ _ORBIT_completion_status = CORBA_COMPLETED_NO;
++ _ORBIT_request_id = GPOINTER_TO_UINT(alloca(0));
++ { /* marshalling */
++ static const struct
++ {
++ CORBA_unsigned_long len;
++ char opname[11];
++ }
++ _ORBIT_operation_name_data =
++ {
++ 11, "echoString"};
++ static const struct iovec _ORBIT_operation_vec =
++ { (gpointer) & _ORBIT_operation_name_data, 15 };
++ register CORBA_unsigned_long _ORBIT_tmpvar_0;
++ CORBA_unsigned_long _ORBIT_tmpvar_1;
++
++ _ORBIT_send_buffer =
++ giop_send_request_buffer_use(_cnx, NULL, _ORBIT_request_id,
++ CORBA_TRUE,
++ &(_obj->active_profile->object_key_vec),
++ &_ORBIT_operation_vec,
++ &ORBit_default_principal_iovec);
++
++ _ORBIT_system_exception_minor = ex_CORBA_COMM_FAILURE;
++ if (!_ORBIT_send_buffer)
++ goto _ORBIT_system_exception;
++ _ORBIT_tmpvar_1 = strlen(astring) + 1;
++ giop_message_buffer_do_alignment(GIOP_MESSAGE_BUFFER
++ (_ORBIT_send_buffer), 4);
++ {
++ guchar *_ORBIT_t;
++
++ _ORBIT_t = alloca(sizeof(_ORBIT_tmpvar_1));
++ memcpy(_ORBIT_t, &(_ORBIT_tmpvar_1), sizeof(_ORBIT_tmpvar_1));
++ giop_message_buffer_append_mem(GIOP_MESSAGE_BUFFER
++ (_ORBIT_send_buffer), (_ORBIT_t),
++ sizeof(_ORBIT_tmpvar_1));
++ }
++ giop_message_buffer_append_mem(GIOP_MESSAGE_BUFFER(_ORBIT_send_buffer),
++ (astring),
++ sizeof(astring[_ORBIT_tmpvar_0]) *
++ _ORBIT_tmpvar_1);
++ giop_send_buffer_write(_ORBIT_send_buffer);
++ _ORBIT_completion_status = CORBA_COMPLETED_MAYBE;
++ giop_send_buffer_unuse(_ORBIT_send_buffer);
++ _ORBIT_send_buffer = NULL;
++ }
++ { /* demarshalling */
++ register guchar *_ORBIT_curptr;
++
++ _ORBIT_recv_buffer =
++ giop_recv_reply_buffer_use_2(_cnx, _ORBIT_request_id, TRUE);
++ if (!_ORBIT_recv_buffer)
++ goto _ORBIT_system_exception;
++ _ORBIT_completion_status = CORBA_COMPLETED_YES;
++ if (_ORBIT_recv_buffer->message.u.reply.reply_status !=
++ GIOP_NO_EXCEPTION) goto _ORBIT_msg_exception;
++ _ORBIT_curptr = GIOP_RECV_BUFFER(_ORBIT_recv_buffer)->cur;
++ if (giop_msg_conversion_needed(GIOP_MESSAGE_BUFFER(_ORBIT_recv_buffer))) {
++ GIOP_RECV_BUFFER(_ORBIT_recv_buffer)->cur = _ORBIT_curptr;
++ _ORBIT_retval =
++ ORBit_demarshal_object(_ORBIT_recv_buffer,
++ GIOP_MESSAGE_BUFFER(_ORBIT_recv_buffer)->
++ connection->orb_data);
++ _ORBIT_curptr = GIOP_RECV_BUFFER(_ORBIT_recv_buffer)->cur;
++ _ORBIT_curptr = ALIGN_ADDRESS(_ORBIT_curptr, 4);
++
++ (*((guint32 *) & ((*anum)))) =
++ GUINT32_SWAP_LE_BE(*((guint32 *) _ORBIT_curptr));} else {
++ GIOP_RECV_BUFFER(_ORBIT_recv_buffer)->cur = _ORBIT_curptr;
++ _ORBIT_retval =
++ ORBit_demarshal_object(_ORBIT_recv_buffer,
++ GIOP_MESSAGE_BUFFER(_ORBIT_recv_buffer)->
++ connection->orb_data);
++ _ORBIT_curptr = GIOP_RECV_BUFFER(_ORBIT_recv_buffer)->cur;
++ _ORBIT_curptr = ALIGN_ADDRESS(_ORBIT_curptr, 4);
++ (*anum) = *((CORBA_long *) _ORBIT_curptr);
++ }
++ giop_recv_buffer_unuse(_ORBIT_recv_buffer);
++ return _ORBIT_retval;
++ _ORBIT_system_exception:
++ CORBA_exception_set_system(ev, _ORBIT_system_exception_minor,
++ _ORBIT_completion_status);
++ giop_recv_buffer_unuse(_ORBIT_recv_buffer);
++ giop_send_buffer_unuse(_ORBIT_send_buffer);
++ return _ORBIT_retval;
++ _ORBIT_msg_exception:
++ if (_ORBIT_recv_buffer->message.u.reply.reply_status ==
++ GIOP_LOCATION_FORWARD) {
++ if (_obj->forward_locations != NULL)
++ ORBit_delete_profiles(_obj->forward_locations);
++ _obj->forward_locations = ORBit_demarshal_IOR(_ORBIT_recv_buffer);
++ _cnx = ORBit_object_get_forwarded_connection(_obj);
++ giop_recv_buffer_unuse(_ORBIT_recv_buffer);
++
++ goto _ORBIT_retry_request;
++ } else {
++ ORBit_handle_exception(_ORBIT_recv_buffer, ev, NULL, _obj->orb);
++ giop_recv_buffer_unuse(_ORBIT_recv_buffer);
++ return _ORBIT_retval;
++ }
++ }
++}
+diff -urN linux-2.4.1/net/korbit/modules/Echo/server/echo.h linux-2.4.1-korbit/net/korbit/modules/Echo/server/echo.h
+--- linux-2.4.1/net/korbit/modules/Echo/server/echo.h Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/Echo/server/echo.h Thu Feb 1 16:36:57 2001
+@@ -0,0 +1,77 @@
++/*
++ * This file was generated by orbit-idl - DO NOT EDIT!
++ */
++
++#include <glib.h>
++#define ORBIT_IDL_SERIAL 9
++#include <orb/orbit.h>
++
++#ifndef echo_H
++#define echo_H 1
++#ifdef __cplusplus
++extern "C"
++{
++#endif /* __cplusplus */
++
++/** typedefs **/
++#if !defined(ORBIT_DECL_Echo) && !defined(_Echo_defined)
++#define ORBIT_DECL_Echo 1
++#define _Echo_defined 1
++#define Echo__free CORBA_Object__free
++ typedef CORBA_Object Echo;
++ extern CORBA_unsigned_long Echo__classid;
++#if !defined(TC_IMPL_TC_Echo_0)
++#define TC_IMPL_TC_Echo_0 'e'
++#define TC_IMPL_TC_Echo_1 'c'
++#define TC_IMPL_TC_Echo_2 'h'
++#define TC_IMPL_TC_Echo_3 'o'
++ extern const struct CORBA_TypeCode_struct TC_Echo_struct;
++#define TC_Echo ((CORBA_TypeCode)&TC_Echo_struct)
++#endif
++#endif
++
++/** POA structures **/
++ typedef struct
++ {
++ void *_private;
++
++ Echo(*echoString) (PortableServer_Servant _servant,
++ const CORBA_char * astring, CORBA_long * anum,
++ CORBA_Environment * ev);
++ }
++ POA_Echo__epv;
++ typedef struct
++ {
++ PortableServer_ServantBase__epv *_base_epv;
++ POA_Echo__epv *Echo_epv;
++ }
++ POA_Echo__vepv;
++ typedef struct
++ {
++ void *_private;
++ POA_Echo__vepv *vepv;
++ }
++ POA_Echo;
++ extern void POA_Echo__init(PortableServer_Servant servant,
++ CORBA_Environment * ev);
++ extern void POA_Echo__fini(PortableServer_Servant servant,
++ CORBA_Environment * ev);
++
++/** prototypes **/
++ Echo Echo_echoString(Echo _obj, const CORBA_char * astring,
++ CORBA_long * anum, CORBA_Environment * ev);
++
++ void _ORBIT_skel_Echo_echoString(POA_Echo * _ORBIT_servant,
++ GIOPRecvBuffer * _ORBIT_recv_buffer,
++ CORBA_Environment * ev,
++ Echo(*_impl_echoString)
++ (PortableServer_Servant _servant,
++ const CORBA_char * astring,
++ CORBA_long * anum,
++ CORBA_Environment * ev));
++#ifdef __cplusplus
++}
++#endif /* __cplusplus */
++
++#endif
++#undef ORBIT_IDL_SERIAL
+diff -urN linux-2.4.1/net/korbit/modules/FileServer/CVS/Entries linux-2.4.1-korbit/net/korbit/modules/FileServer/CVS/Entries
+--- linux-2.4.1/net/korbit/modules/FileServer/CVS/Entries Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/FileServer/CVS/Entries Thu Feb 1 11:47:07 2001
+@@ -0,0 +1,4 @@
++/FileServer.idl/1.3/Thu Feb 1 09:47:07 2001//
++/Makefile/1.2/Thu Feb 1 09:47:07 2001//
++/README/1.1/Thu Feb 1 09:47:07 2001//
++D
+diff -urN linux-2.4.1/net/korbit/modules/FileServer/CVS/Entries.Log linux-2.4.1-korbit/net/korbit/modules/FileServer/CVS/Entries.Log
+--- linux-2.4.1/net/korbit/modules/FileServer/CVS/Entries.Log Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/FileServer/CVS/Entries.Log Thu Feb 1 11:47:09 2001
+@@ -0,0 +1,4 @@
++A D/client////
++A D/server////
++A D/server-user////
++A D/wrapper////
+diff -urN linux-2.4.1/net/korbit/modules/FileServer/CVS/Repository linux-2.4.1-korbit/net/korbit/modules/FileServer/CVS/Repository
+--- linux-2.4.1/net/korbit/modules/FileServer/CVS/Repository Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/FileServer/CVS/Repository Thu Feb 1 11:47:07 2001
+@@ -0,0 +1 @@
++/cvsroot/korbit/linux/net/korbit/modules/FileServer
+diff -urN linux-2.4.1/net/korbit/modules/FileServer/CVS/Root linux-2.4.1-korbit/net/korbit/modules/FileServer/CVS/Root
+--- linux-2.4.1/net/korbit/modules/FileServer/CVS/Root Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/FileServer/CVS/Root Thu Feb 1 11:47:07 2001
+@@ -0,0 +1 @@
++vraalsen@cvs.korbit.sourceforge.net:/cvsroot/korbit
+diff -urN linux-2.4.1/net/korbit/modules/FileServer/FileServer.idl linux-2.4.1-korbit/net/korbit/modules/FileServer/FileServer.idl
+--- linux-2.4.1/net/korbit/modules/FileServer/FileServer.idl Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/FileServer/FileServer.idl Thu Feb 1 11:47:07 2001
+@@ -0,0 +1,158 @@
++// -----------------------------------------------------------------------------
++// FileServer.idl
++// -----------------------------------------------------------------------------
++//
++// This file is used to define the Kernel CORBA API for accessing the filesystem
++// on a machine. This defines mappings both to access the files in the kernel
++// and to implement a filesystem for the kernel. This should probably be split
++// into two files eventually.
++//
++// Currently unimplemented: KernelAccessAPI::FileSystem::ReadDirectory
++// KernelAccessAPI::FileSystem::Select
++// KernelImplementationAPI::SuperBlock::getDiskQuotaOps
++//
++// -----------------------------------------------------------------------------
++
++
++// These are the exceptions that may be thrown and what they map to in the
++// Linux kernel. This interface is extended by other interfaces so that the
++// names don't have to be typedef'd into each interface that wants to use these
++// errors.
++//
++interface Errors {
++ exception IsDirectory {}; // EISDIR
++ exception PermissionDenied {}; // EACCES
++ exception FileExists {}; // EEXIST
++ exception FileNotFound {}; // ENOENT
++ exception IsNotDirectory {}; // ENOTDIR
++ exception ReadOnlyFile {}; // EROFS, ETXTBSY
++ exception RecursiveSymlink {}; // ELOOP
++ exception IsBusy {}; // EBUSY
++ exception OtherError{}; // Misc other ones...
++};
++
++
++// -----------------------------------------------------------------------------
++// KernelAccessAPI Module - Allow user level programs to call into the kernel
++// -----------------------------------------------------------------------------
++
++module FileServer {
++ struct FileStatus { // Corba equilivant of struct stat
++ long DeviceNum; // st_dev
++ long InodeNum; // st_ino
++ short Mode; // st_mode
++ short NumLinks; // st_nlink
++ long UserID; // st_uid
++ long GroupID; // st_gid
++ long DeviceType; // st_rdev
++ unsigned long Size; // st_size
++ unsigned long BlockSize; // st_blksize
++ unsigned long NumBlocks; // st_blocks;
++ unsigned long AccessTime; // st_blocks;
++ unsigned long ModifiedTime; // st_blocks;
++ unsigned long ChangeTime; // st_blocks;
++ };
++
++ typedef sequence<octet> buffer;
++
++ // ---------------------------------------------------------------------------
++ // FileSystem Interface - Access to filesystem and File object factory
++ // ---------------------------------------------------------------------------
++
++ interface File : Errors {
++ void Read(in long count, out buffer buf)
++ raises (IsDirectory, OtherError);
++ void Write(in buffer buf)
++ raises (OtherError);
++ void Close();
++
++ long FileControl(in long command) raises (OtherError);
++
++ FileStatus GetStatus() raises (OtherError);
++
++ void ChangeDirectoryTo() // This implements fchdir...
++ raises (IsNotDirectory, PermissionDenied, OtherError);
++
++ enum SeekDirection { FromStart, FromCurrent, FromEnd };
++ long Seek(in long Offset, in SeekDirection Direction) raises (OtherError);
++
++ File Duplicate() raises (OtherError);
++ };
++
++
++
++ // ---------------------------------------------------------------------------
++ // FileSystem Interface - Access to filesystem and File object factory
++ // ---------------------------------------------------------------------------
++
++ interface FileSystem : Errors {
++
++ // -------------------------------------------------------------------------
++ // File Manipulation Routines
++ // -------------------------------------------------------------------------
++
++ File Open(in string Filename, in long openFlags, in short mode)
++ raises (FileExists, IsDirectory, PermissionDenied, FileNotFound,
++ IsNotDirectory, ReadOnlyFile, RecursiveSymlink, OtherError);
++
++ File Create(in string Filename, in short mode)
++ raises (FileExists, IsDirectory, PermissionDenied, FileNotFound,
++ IsNotDirectory, ReadOnlyFile, RecursiveSymlink, OtherError);
++
++ void Link(in string FromPath, in string ToPath)
++ raises (PermissionDenied, IsNotDirectory, RecursiveSymlink, FileExists);
++
++ void Unlink(in string Filename)
++ raises (PermissionDenied, FileNotFound, IsNotDirectory, IsDirectory);
++
++ void Rename(in string OldName, in string NewName)
++ raises (IsDirectory, FileExists, IsBusy, IsNotDirectory, PermissionDenied,
++ RecursiveSymlink);
++
++ void ReadLink(in string Linkname, out string LinkValue)
++ raises (FileNotFound, PermissionDenied, RecursiveSymlink, OtherError);
++
++
++ FileStatus GetStatus(in string Filename)
++ raises (FileNotFound, PermissionDenied, RecursiveSymlink, IsNotDirectory,
++ OtherError);
++
++ FileStatus GetLinkStatus(in string Filename)
++ raises (FileNotFound, PermissionDenied, RecursiveSymlink, IsNotDirectory,
++ OtherError);
++
++
++ // -------------------------------------------------------------------------
++ // Directory Manipulation Routines
++ // -------------------------------------------------------------------------
++
++ void MakeDirectory(in string PathName, in short mode)
++ raises (FileExists, PermissionDenied, FileNotFound, IsNotDirectory,
++ ReadOnlyFile, RecursiveSymlink, OtherError);
++
++ void RemoveDirectory(in string PathName)
++ raises (PermissionDenied, FileNotFound, IsNotDirectory);
++
++ // ChangeDirectory returns CWD so that you can implement getcwd as
++ // { return ChangeDirectory("."); }
++ string ChangeDirectory(in string PathName)
++ raises (IsNotDirectory, PermissionDenied, FileNotFound, RecursiveSymlink);
++
++
++ // -------------------------------------------------------------------------
++ // Special Purpose Routines...
++ // -------------------------------------------------------------------------
++
++ void MakeNode(in string FileName, in short Mode, in long DeviceNum)
++ raises (PermissionDenied, FileExists, FileNotFound, IsNotDirectory,
++ RecursiveSymlink);
++
++ void Mount(in string DeviceFile, in string Location, in string FSType,
++ in long Flags)
++ raises (PermissionDenied, FileNotFound, IsBusy, IsNotDirectory);
++
++ void Unmount(in string Filename)
++ raises (PermissionDenied, FileNotFound, IsBusy);
++ };
++
++};
+diff -urN linux-2.4.1/net/korbit/modules/FileServer/Makefile linux-2.4.1-korbit/net/korbit/modules/FileServer/Makefile
+--- linux-2.4.1/net/korbit/modules/FileServer/Makefile Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/FileServer/Makefile Thu Feb 1 11:47:07 2001
+@@ -0,0 +1,11 @@
++#
++# Makefile for KORBit/modules/CorbaFS
++#
++# Note! Dependencies are done automagically by 'make dep', which also
++# removes any old dependencies. DON'T put your own dependencies here
++# unless it's something special (ie not a .c file).
++
++subdir-$(CONFIG_CORBA_FILESERVER) := server
++
++include $(TOPDIR)/Rules.make
++
+diff -urN linux-2.4.1/net/korbit/modules/FileServer/README linux-2.4.1-korbit/net/korbit/modules/FileServer/README
+--- linux-2.4.1/net/korbit/modules/FileServer/README Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/FileServer/README Thu Feb 1 11:47:07 2001
+@@ -0,0 +1,8 @@
++This interface lets you export file related syscalls through CORBA. This is
++genuinely useful, however, when you use the 'wrapper' library, that can be
++LD_PRELOADED before you run your application. This allows you to forward
++filesystem calls through CORBA without having to modify your application.
++
++Being able to forward filesystem calls though CORBA, of course, means that
++you can attach to any remote machine you want. :)
++
+diff -urN linux-2.4.1/net/korbit/modules/FileServer/client/CVS/Entries linux-2.4.1-korbit/net/korbit/modules/FileServer/client/CVS/Entries
+--- linux-2.4.1/net/korbit/modules/FileServer/client/CVS/Entries Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/FileServer/client/CVS/Entries Thu Feb 1 11:47:07 2001
+@@ -0,0 +1,4 @@
++/FileServer-client.cpp/1.1/Thu Feb 1 09:47:07 2001//
++/Makefile/1.1/Thu Feb 1 09:47:07 2001//
++/README/1.1/Thu Feb 1 09:47:07 2001//
++D
+diff -urN linux-2.4.1/net/korbit/modules/FileServer/client/CVS/Repository linux-2.4.1-korbit/net/korbit/modules/FileServer/client/CVS/Repository
+--- linux-2.4.1/net/korbit/modules/FileServer/client/CVS/Repository Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/FileServer/client/CVS/Repository Thu Feb 1 11:47:07 2001
+@@ -0,0 +1 @@
++/cvsroot/korbit/linux/net/korbit/modules/FileServer/client
+diff -urN linux-2.4.1/net/korbit/modules/FileServer/client/CVS/Root linux-2.4.1-korbit/net/korbit/modules/FileServer/client/CVS/Root
+--- linux-2.4.1/net/korbit/modules/FileServer/client/CVS/Root Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/FileServer/client/CVS/Root Thu Feb 1 11:47:07 2001
+@@ -0,0 +1 @@
++vraalsen@cvs.korbit.sourceforge.net:/cvsroot/korbit
+diff -urN linux-2.4.1/net/korbit/modules/FileServer/client/FileServer-client.cpp linux-2.4.1-korbit/net/korbit/modules/FileServer/client/FileServer-client.cpp
+--- linux-2.4.1/net/korbit/modules/FileServer/client/FileServer-client.cpp Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/FileServer/client/FileServer-client.cpp Thu Feb 1 11:47:07 2001
+@@ -0,0 +1,78 @@
++#include <OB/CORBA.h>
++#include <OB/Util.h>
++#include <OB/CosNaming.h>
++#include <stdlib.h>
++#include <sys/types.h>
++#include <sys/stat.h>
++#include <fcntl.h>
++
++#include "FileServer.h"
++
++int main(int argc, char* argv[])
++{
++ if (argc < 3)
++ {
++ cout << "Usage : " << argv[0] << " ior filename" << endl;
++ exit(1);
++ }
++
++ cout << "FileServer client initializing" << endl;
++
++ CORBA_ORB_var orb = CORBA_ORB_init(argc, argv);
++ cout << "ORB initialized" << endl;
++
++ try
++ {
++ CORBA_Object_var obj = orb->string_to_object( argv[1] );
++ assert(!CORBA_is_nil(obj));
++ cout << "got object... " << orb->object_to_string(obj) << endl;
++
++ FileServer_FileSystem_var fs = FileServer_FileSystem::_narrow(obj);
++ assert(!CORBA_is_nil(fs));
++ cout << "it's a FileServer!" << endl;
++
++ obj = fs->Open(argv[2], O_RDONLY, 0);
++ assert(!CORBA_is_nil(obj));
++ cout << "got object... " << orb->object_to_string(obj) << endl;
++
++ FileServer_File_var file = FileServer_File::_narrow(obj);
++ assert(!CORBA_is_nil(file));
++ cout << "it's a FileServer_File!" << endl;
++
++ FileServer_buffer *buf = new FileServer_buffer;
++ cout << "reading 1000 bytes" << endl;
++ file->Read(1000, buf);
++
++ cout << "got " << buf->length() << " bytes" << endl;
++ cout << buf->data() << endl;
++
++ file->Close();
++
++ delete buf;
++ }
++ catch (const CORBA_SystemException& ex) {
++ OBPrintException(ex);
++ return 1;
++ }
++ catch (const Errors::FileNotFound& ex) {
++ cout << "ERROR : File not found" << endl;
++ return 1;
++ }
++ catch (const Errors::PermissionDenied& ex) {
++ cout << "ERROR : Permission denied" << endl;
++ return 1;
++ }
++ catch (const Errors::IsDirectory& ex) {
++ cout << "ERROR : Is directory" << endl;
++ return 1;
++ }
++ catch (const Errors::OtherError& ex) {
++ cout << "ERROR : Other error" << endl;
++ return 1;
++ }
++ catch (const CORBA_UserException& ex)
++ {
++ cout << "ERROR : Uncaught exception" << endl;
++ return 1;
++ }
++}
+diff -urN linux-2.4.1/net/korbit/modules/FileServer/client/Makefile linux-2.4.1-korbit/net/korbit/modules/FileServer/client/Makefile
+--- linux-2.4.1/net/korbit/modules/FileServer/client/Makefile Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/FileServer/client/Makefile Thu Feb 1 11:47:07 2001
+@@ -0,0 +1,32 @@
++CC = CC -mt -pta
++OBDIR = /home/class/cs423/local
++IDL = $(OBDIR)/bin/idl
++CPPFLAGS = -I. -I$(OBDIR)/include
++LDFLAGS = -L$(OBDIR)/lib
++LIBS = -lCosNaming -lOB -lJTC -lsocket -lnsl -lposix4
++
++all: FileServer-client
++
++FileServer-client: FileServer.o FileServer-client.o
++ $(CC) $(LDFLAGS) -o FileServer-client FileServer-client.o FileServer.o $(LIBS)
++
++nameserv:
++ nameserv -i -OAport 10000
++
++FileServer.h FileServer.cpp: ../FileServer.idl
++ rm -f FileServer.cpp FileServer.h
++ rm -f FileServer_skel.h FileServer_skel.cpp
++ $(IDL) ../FileServer.idl
++
++FileServer_skel.cpp FileServer_skel.h: FileServer.cpp
++
++%.o: %.cpp
++ $(CC) $(CPPFLAGS) -c $<
++
++clean:
++ rm -f FileServer-client *.o *~
++
++realclean: clean
++ rm -f FileServer.h FileServer.cpp
++ rm -f FileServer_skel.h FileServer_skel.cpp
++ rm -rf SunWS_cache
+diff -urN linux-2.4.1/net/korbit/modules/FileServer/client/README linux-2.4.1-korbit/net/korbit/modules/FileServer/client/README
+--- linux-2.4.1/net/korbit/modules/FileServer/client/README Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/FileServer/client/README Thu Feb 1 11:47:07 2001
+@@ -0,0 +1,4 @@
++Very minimal test of the FileServer capability.
++
++ORB: Orbacus
++
+diff -urN linux-2.4.1/net/korbit/modules/FileServer/server/CVS/Entries linux-2.4.1-korbit/net/korbit/modules/FileServer/server/CVS/Entries
+--- linux-2.4.1/net/korbit/modules/FileServer/server/CVS/Entries Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/FileServer/server/CVS/Entries Thu Feb 1 11:47:08 2001
+@@ -0,0 +1,6 @@
++/FileServer-server.c/1.2/Thu Feb 1 09:47:08 2001//
++/FileServer-skelimpl.c/1.8/Thu Feb 1 09:47:08 2001//
++/Makefile/1.3/Thu Feb 1 09:47:08 2001//
++/Makefile.user/1.4/Thu Feb 1 09:47:08 2001//
++/README/1.1/Thu Feb 1 09:47:08 2001//
++D
+diff -urN linux-2.4.1/net/korbit/modules/FileServer/server/CVS/Repository linux-2.4.1-korbit/net/korbit/modules/FileServer/server/CVS/Repository
+--- linux-2.4.1/net/korbit/modules/FileServer/server/CVS/Repository Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/FileServer/server/CVS/Repository Thu Feb 1 11:47:08 2001
+@@ -0,0 +1 @@
++/cvsroot/korbit/linux/net/korbit/modules/FileServer/server
+diff -urN linux-2.4.1/net/korbit/modules/FileServer/server/CVS/Root linux-2.4.1-korbit/net/korbit/modules/FileServer/server/CVS/Root
+--- linux-2.4.1/net/korbit/modules/FileServer/server/CVS/Root Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/FileServer/server/CVS/Root Thu Feb 1 11:47:08 2001
+@@ -0,0 +1 @@
++vraalsen@cvs.korbit.sourceforge.net:/cvsroot/korbit
+diff -urN linux-2.4.1/net/korbit/modules/FileServer/server/FileServer-server.c linux-2.4.1-korbit/net/korbit/modules/FileServer/server/FileServer-server.c
+--- linux-2.4.1/net/korbit/modules/FileServer/server/FileServer-server.c Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/FileServer/server/FileServer-server.c Thu Feb 1 11:47:08 2001
+@@ -0,0 +1,57 @@
++#include <stdio.h>
++#include "FileServer-skelimpl.c"
++#include "korbit.h"
++
++CORBA_ORB orb;
++PortableServer_POA poa;
++CORBA_Environment *ev;
++PortableServer_ObjectId *objid;
++
++#ifdef __KERNEL__
++int __init FileServer_init(void) {
++#else
++int main(int argc, char *argv[]) {
++#endif
++ FileServer_FileSystem fs;
++ impl_POA_FileServer_FileSystem *fs_impl;
++
++ PortableServer_POAManager pm;
++#ifdef __KERNEL__
++ int argc = 1;
++ char *argv[] = { "server", 0 };
++#endif
++ ev = g_new0(CORBA_Environment,1);
++
++ CORBA_exception_init(ev);
++
++ orb = CORBA_ORB_init(&argc, argv, "orbit-local-orb", ev);
++ poa = (PortableServer_POA)
++ CORBA_ORB_resolve_initial_references(orb,
++ "RootPOA",
++ ev);
++ fs = impl_FileServer_FileSystem__create(poa, ev);
++
++ pm = PortableServer_POA__get_the_POAManager(poa, ev);
++ PortableServer_POAManager_activate(pm, ev);
++
++ fs_impl = PortableServer_POA_reference_to_servant( poa, fs, ev );
++ objid = PortableServer_POA_servant_to_id( poa, fs_impl, ev );
++
++ korbit_register_ior("FileServer-server", fs, orb, ev);
++
++ CORBA_ORB_run(orb, ev);
++
++ return 0;
++}
++
++#ifdef __KERNEL__
++void FileServer_exit(void)
++{
++ PortableServer_POA_deactivate_object(poa, objid, ev);
++ remove_proc_entry("corba/FileServer-server", 0);
++ printf("FileServer_exit()\n");
++}
++
++module_init(FileServer_init)
++module_exit(FileServer_exit)
++#endif
+diff -urN linux-2.4.1/net/korbit/modules/FileServer/server/FileServer-skelimpl.c linux-2.4.1-korbit/net/korbit/modules/FileServer/server/FileServer-skelimpl.c
+--- linux-2.4.1/net/korbit/modules/FileServer/server/FileServer-skelimpl.c Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/FileServer/server/FileServer-skelimpl.c Thu Feb 1 11:47:08 2001
+@@ -0,0 +1,804 @@
++#include <stdio.h>
++#include <stdlib.h>
++#include <unistd.h>
++#include <sys/types.h>
++#include <sys/stat.h>
++#include <fcntl.h>
++#include <errno.h>
++
++#include "FileServer.h"
++
++static void set_exception(int errno, CORBA_Environment *ev)
++{
++ switch (errno)
++ {
++ case ENOENT:
++ CORBA_exception_set(ev, CORBA_USER_EXCEPTION,
++ ex_Errors_FileNotFound,
++ Errors_FileNotFound__alloc());
++ break;
++ case EEXIST:
++ CORBA_exception_set(ev, CORBA_USER_EXCEPTION,
++ ex_Errors_FileExists,
++ Errors_FileExists__alloc());
++ break;
++ case EACCES:
++ CORBA_exception_set(ev, CORBA_USER_EXCEPTION,
++ ex_Errors_PermissionDenied,
++ Errors_PermissionDenied__alloc());
++ break;
++ case EISDIR:
++ CORBA_exception_set(ev, CORBA_USER_EXCEPTION,
++ ex_Errors_IsDirectory,
++ Errors_IsDirectory__alloc());
++ break;
++ case ENOTDIR:
++ CORBA_exception_set(ev, CORBA_USER_EXCEPTION,
++ ex_Errors_IsNotDirectory,
++ Errors_IsNotDirectory__alloc());
++ break;
++ case EROFS:
++ case ETXTBSY:
++ CORBA_exception_set(ev, CORBA_USER_EXCEPTION,
++ ex_Errors_ReadOnlyFile,
++ Errors_ReadOnlyFile__alloc());
++ break;
++ case ELOOP:
++ CORBA_exception_set(ev, CORBA_USER_EXCEPTION,
++ ex_Errors_RecursiveSymlink,
++ Errors_RecursiveSymlink__alloc());
++ break;
++ case EBUSY:
++ CORBA_exception_set(ev, CORBA_USER_EXCEPTION,
++ ex_Errors_IsBusy,
++ Errors_IsBusy__alloc());
++ break;
++ default:
++ CORBA_exception_set(ev, CORBA_USER_EXCEPTION,
++ ex_Errors_OtherError,
++ Errors_OtherError__alloc());
++ break;
++ }
++}
++
++
++/*** App-specific servant structures ***/
++typedef struct
++{
++ POA_Errors servant;
++ PortableServer_POA poa;
++
++}
++impl_POA_Errors;
++
++typedef struct
++{
++ POA_FileServer_File servant;
++ PortableServer_POA poa;
++
++ int fd;
++}
++impl_POA_FileServer_File;
++
++typedef struct
++{
++ POA_FileServer_FileSystem servant;
++ PortableServer_POA poa;
++
++}
++impl_POA_FileServer_FileSystem;
++
++/*** Implementation stub prototypes ***/
++static void impl_Errors__destroy(impl_POA_Errors * servant,
++ CORBA_Environment * ev);
++
++static void impl_FileServer_File__destroy(impl_POA_FileServer_File * servant,
++ CORBA_Environment * ev);
++static void
++impl_FileServer_File_Read(impl_POA_FileServer_File * servant,
++ CORBA_long count,
++ FileServer_buffer ** buf, CORBA_Environment * ev);
++
++static void
++impl_FileServer_File_Write(impl_POA_FileServer_File * servant,
++ FileServer_buffer * buf, CORBA_Environment * ev);
++
++static void
++impl_FileServer_File_Close(impl_POA_FileServer_File * servant,
++ CORBA_Environment * ev);
++
++static CORBA_long
++impl_FileServer_File_FileControl(impl_POA_FileServer_File * servant,
++ CORBA_long command, CORBA_Environment * ev);
++
++static FileServer_FileStatus
++impl_FileServer_File_GetStatus(impl_POA_FileServer_File * servant,
++ CORBA_Environment * ev);
++
++static void
++impl_FileServer_File_ChangeDirectoryTo(impl_POA_FileServer_File * servant,
++ CORBA_Environment * ev);
++
++static CORBA_long
++impl_FileServer_File_Seek(impl_POA_FileServer_File * servant,
++ CORBA_long Offset,
++ FileServer_File_SeekDirection Direction,
++ CORBA_Environment * ev);
++
++static FileServer_File
++impl_FileServer_File_Duplicate(impl_POA_FileServer_File * servant,
++ CORBA_Environment * ev);
++
++static void impl_FileServer_FileSystem__destroy(impl_POA_FileServer_FileSystem
++ * servant,
++
++ CORBA_Environment * ev);
++static FileServer_File
++impl_FileServer_FileSystem_Open(impl_POA_FileServer_FileSystem * servant,
++ CORBA_char * Filename, CORBA_long openFlags,
++ CORBA_short mode, CORBA_Environment * ev);
++
++static FileServer_File
++impl_FileServer_FileSystem_Create(impl_POA_FileServer_FileSystem * servant,
++ CORBA_char * Filename,
++ CORBA_short mode, CORBA_Environment * ev);
++
++static void
++impl_FileServer_FileSystem_Link(impl_POA_FileServer_FileSystem * servant,
++ CORBA_char * FromPath,
++ CORBA_char * ToPath, CORBA_Environment * ev);
++
++static void
++impl_FileServer_FileSystem_Unlink(impl_POA_FileServer_FileSystem * servant,
++ CORBA_char * Filename,
++
++ CORBA_Environment * ev);
++
++static void
++impl_FileServer_FileSystem_Rename(impl_POA_FileServer_FileSystem * servant,
++ CORBA_char * OldName,
++ CORBA_char * NewName,
++
++ CORBA_Environment * ev);
++
++static void
++impl_FileServer_FileSystem_ReadLink(impl_POA_FileServer_FileSystem * servant,
++ CORBA_char * Linkname,
++ CORBA_char ** LinkValue,
++ CORBA_Environment * ev);
++
++static FileServer_FileStatus
++impl_FileServer_FileSystem_GetStatus(impl_POA_FileServer_FileSystem * servant,
++ CORBA_char * Filename,
++ CORBA_Environment * ev);
++
++static FileServer_FileStatus
++impl_FileServer_FileSystem_GetLinkStatus(impl_POA_FileServer_FileSystem *
++ servant, CORBA_char * Filename,
++ CORBA_Environment * ev);
++
++static void
++impl_FileServer_FileSystem_MakeDirectory(impl_POA_FileServer_FileSystem *
++ servant, CORBA_char * PathName,
++ CORBA_short mode,
++ CORBA_Environment * ev);
++
++static void
++impl_FileServer_FileSystem_RemoveDirectory(impl_POA_FileServer_FileSystem *
++ servant, CORBA_char * PathName,
++ CORBA_Environment * ev);
++
++static CORBA_char
++ *impl_FileServer_FileSystem_ChangeDirectory(impl_POA_FileServer_FileSystem
++ * servant,
++ CORBA_char * PathName,
++ CORBA_Environment * ev);
++
++static void
++impl_FileServer_FileSystem_MakeNode(impl_POA_FileServer_FileSystem * servant,
++ CORBA_char * FileName,
++ CORBA_short Mode,
++ CORBA_long DeviceNum,
++
++ CORBA_Environment * ev);
++
++static void
++impl_FileServer_FileSystem_Mount(impl_POA_FileServer_FileSystem * servant,
++ CORBA_char * DeviceFile,
++ CORBA_char * Location,
++ CORBA_char * FSType,
++ CORBA_long Flags, CORBA_Environment * ev);
++
++static void
++impl_FileServer_FileSystem_Unmount(impl_POA_FileServer_FileSystem * servant,
++ CORBA_char * Filename,
++
++ CORBA_Environment * ev);
++
++/*** epv structures ***/
++static PortableServer_ServantBase__epv impl_Errors_base_epv = {
++ NULL, /* _private data */
++ NULL, /* finalize routine */
++ NULL, /* default_POA routine */
++};
++static POA_Errors__epv impl_Errors_epv = {
++ NULL, /* _private */
++
++};
++
++static PortableServer_ServantBase__epv impl_FileServer_File_base_epv = {
++ NULL, /* _private data */
++ NULL, /* finalize routine */
++ NULL, /* default_POA routine */
++};
++static POA_FileServer_File__epv impl_FileServer_File_epv = {
++ NULL, /* _private */
++ (gpointer) & impl_FileServer_File_Read,
++
++ (gpointer) & impl_FileServer_File_Write,
++
++ (gpointer) & impl_FileServer_File_Close,
++
++ (gpointer) & impl_FileServer_File_FileControl,
++
++ (gpointer) & impl_FileServer_File_GetStatus,
++
++ (gpointer) & impl_FileServer_File_ChangeDirectoryTo,
++
++ (gpointer) & impl_FileServer_File_Seek,
++
++ (gpointer) & impl_FileServer_File_Duplicate,
++
++};
++static POA_Errors__epv impl_FileServer_File_Errors_epv = {
++ NULL, /* _private */
++};
++static PortableServer_ServantBase__epv impl_FileServer_FileSystem_base_epv = {
++ NULL, /* _private data */
++ NULL, /* finalize routine */
++ NULL, /* default_POA routine */
++};
++static POA_FileServer_FileSystem__epv impl_FileServer_FileSystem_epv = {
++ NULL, /* _private */
++ (gpointer) & impl_FileServer_FileSystem_Open,
++
++ (gpointer) & impl_FileServer_FileSystem_Create,
++
++ (gpointer) & impl_FileServer_FileSystem_Link,
++
++ (gpointer) & impl_FileServer_FileSystem_Unlink,
++
++ (gpointer) & impl_FileServer_FileSystem_Rename,
++
++ (gpointer) & impl_FileServer_FileSystem_ReadLink,
++
++ (gpointer) & impl_FileServer_FileSystem_GetStatus,
++
++ (gpointer) & impl_FileServer_FileSystem_GetLinkStatus,
++
++ (gpointer) & impl_FileServer_FileSystem_MakeDirectory,
++
++ (gpointer) & impl_FileServer_FileSystem_RemoveDirectory,
++
++ (gpointer) & impl_FileServer_FileSystem_ChangeDirectory,
++
++ (gpointer) & impl_FileServer_FileSystem_MakeNode,
++
++ (gpointer) & impl_FileServer_FileSystem_Mount,
++
++ (gpointer) & impl_FileServer_FileSystem_Unmount,
++
++};
++static POA_Errors__epv impl_FileServer_FileSystem_Errors_epv = {
++ NULL, /* _private */
++};
++
++/*** vepv structures ***/
++static POA_Errors__vepv impl_Errors_vepv = {
++ &impl_Errors_base_epv,
++ &impl_Errors_epv,
++};
++
++static POA_FileServer_File__vepv impl_FileServer_File_vepv = {
++ &impl_FileServer_File_base_epv,
++ &impl_FileServer_File_Errors_epv,
++ &impl_FileServer_File_epv,
++};
++static POA_FileServer_FileSystem__vepv impl_FileServer_FileSystem_vepv = {
++ &impl_FileServer_FileSystem_base_epv,
++ &impl_FileServer_FileSystem_Errors_epv,
++ &impl_FileServer_FileSystem_epv,
++};
++
++/*** Stub implementations ***/
++static Errors
++impl_Errors__create(PortableServer_POA poa, CORBA_Environment * ev)
++{
++ Errors retval;
++ impl_POA_Errors *newservant;
++ PortableServer_ObjectId *objid;
++
++ newservant = g_new0(impl_POA_Errors, 1);
++ newservant->servant.vepv = &impl_Errors_vepv;
++ newservant->poa = poa;
++ POA_Errors__init((PortableServer_Servant) newservant, ev);
++ objid = PortableServer_POA_activate_object(poa, newservant, ev);
++ CORBA_free(objid);
++ retval = PortableServer_POA_servant_to_reference(poa, newservant, ev);
++
++ return retval;
++}
++
++static void
++impl_Errors__destroy(impl_POA_Errors * servant, CORBA_Environment * ev)
++{
++ PortableServer_ObjectId *objid;
++
++ objid = PortableServer_POA_servant_to_id(servant->poa, servant, ev);
++ PortableServer_POA_deactivate_object(servant->poa, objid, ev);
++ CORBA_free(objid);
++
++ POA_Errors__fini((PortableServer_Servant) servant, ev);
++ g_free(servant);
++}
++
++static FileServer_File
++impl_FileServer_File__create(PortableServer_POA poa, CORBA_Environment * ev)
++{
++ FileServer_File retval;
++ impl_POA_FileServer_File *newservant;
++ PortableServer_ObjectId *objid;
++
++ newservant = g_new0(impl_POA_FileServer_File, 1);
++ newservant->servant.vepv = &impl_FileServer_File_vepv;
++ newservant->poa = poa;
++ newservant->fd = -1;
++
++ POA_FileServer_File__init((PortableServer_Servant) newservant, ev);
++ objid = PortableServer_POA_activate_object(poa, newservant, ev);
++ CORBA_free(objid);
++ retval = PortableServer_POA_servant_to_reference(poa, newservant, ev);
++
++ return retval;
++}
++
++static void
++impl_FileServer_File__destroy(impl_POA_FileServer_File * servant,
++ CORBA_Environment * ev)
++{
++ PortableServer_ObjectId *objid;
++
++ objid = PortableServer_POA_servant_to_id(servant->poa, servant, ev);
++ PortableServer_POA_deactivate_object(servant->poa, objid, ev);
++ CORBA_free(objid);
++
++ POA_FileServer_File__fini((PortableServer_Servant) servant, ev);
++ g_free(servant);
++}
++
++static void
++impl_FileServer_File_Read(impl_POA_FileServer_File * servant,
++ CORBA_long count,
++ FileServer_buffer ** buf, CORBA_Environment * ev)
++{
++ size_t num_read;
++
++ *buf = FileServer_buffer__alloc();
++ (*buf)->_maximum = count;
++ (*buf)->_buffer = CORBA_octet_allocbuf(count);
++ (*buf)->_length = 0;
++
++ printf("File->Read(%d, char *buf)\n", count);
++
++ if (servant->fd == -1) /* Trying to read from a closed file */
++ {
++ printf("File->Read ERROR : fd == -1\n");
++ set_exception(EBADF, ev);
++ return;
++ }
++
++ num_read = read(servant->fd, (*buf)->_buffer, count);
++ if (num_read == -1)
++ {
++ printf("File->Read ERROR : %d\n", errno);
++ set_exception(errno, ev);
++ return;
++ }
++
++ (*buf)->_length = num_read;
++}
++
++static void
++impl_FileServer_File_Write(impl_POA_FileServer_File * servant,
++ FileServer_buffer * buf, CORBA_Environment * ev)
++{
++ printf("UNIMP: FileServer::File::Write called and unimplemented\n");
++}
++
++static void
++impl_FileServer_File_Close(impl_POA_FileServer_File * servant,
++ CORBA_Environment * ev)
++{
++ printf("File->Close()\n");
++
++ if (servant->fd == -1) /* This should never happen !?! */
++ {
++ printf("File->Close ERROR : fd == -1\n");
++ set_exception(EBADF, ev);
++ return;
++ }
++
++ close(servant->fd);
++ servant->fd = 0;
++ impl_FileServer_File__destroy(servant, ev);
++}
++
++static CORBA_long
++impl_FileServer_File_FileControl(impl_POA_FileServer_File * servant,
++ CORBA_long command, CORBA_Environment * ev)
++{
++ CORBA_long retval;
++
++ if (servant->fd == -1)
++ {
++ printf("File->FileControl ERROR : fd == -1\n");
++ set_exception(EBADF, ev);
++ return -1;
++ }
++
++ retval = fcntl(servant->fd, command, 0); /* FIXME arg? */
++ if (retval == -1)
++ {
++ printf("File->FileControl ERROR : %d\n", errno);
++ set_exception(errno, ev);
++ }
++
++ return retval;
++}
++
++
++FileServer_FileStatus
++stat2FileStatus(struct stat buf)
++{
++ FileServer_FileStatus retval;
++
++ retval.DeviceNum = buf.st_dev;
++ retval.InodeNum = buf.st_ino;
++ retval.Mode = buf.st_mode;
++ retval.NumLinks = buf.st_nlink;
++ retval.UserID = buf.st_uid;
++ retval.GroupID = buf.st_gid;
++ retval.DeviceType = buf.st_rdev;
++ retval.Size = buf.st_size;
++ retval.BlockSize = buf.st_blksize;
++ retval.NumBlocks = buf.st_blocks;
++ retval.AccessTime = buf.st_atime;
++ retval.ModifiedTime = buf.st_mtime;
++ retval.ChangeTime = buf.st_ctime;
++
++ return retval;
++}
++
++
++static FileServer_FileStatus
++impl_FileServer_File_GetStatus(impl_POA_FileServer_File * servant,
++ CORBA_Environment * ev)
++{
++ FileServer_FileStatus retval;
++
++ struct stat buf;
++ int res;
++
++ if (servant->fd == -1)
++ {
++ printf("File->GetStatus ERROR : fd == -1\n");
++ set_exception(EBADF, ev);
++ return retval;
++ }
++
++ res = fstat(servant->fd, &buf);
++ if (res == -1)
++ {
++ printf("File->GetStatus ERROR : %d\n", errno);
++ set_exception(errno, ev);
++ return retval;
++ }
++
++ retval = stat2FileStatus(buf);
++
++ return retval;
++}
++
++static void
++impl_FileServer_File_ChangeDirectoryTo(impl_POA_FileServer_File * servant,
++ CORBA_Environment * ev)
++{
++ printf("UNIMP: impl_FileServer_File_ChangeDirectoryTo\n");
++}
++
++static CORBA_long
++impl_FileServer_File_Seek(impl_POA_FileServer_File * servant,
++ CORBA_long Offset,
++ FileServer_File_SeekDirection Direction,
++ CORBA_Environment * ev)
++{
++ CORBA_long retval = -1;
++ int whence;
++
++ if (servant->fd == -1)
++ {
++ printf("File->Seek ERROR : fd == -1\n");
++ set_exception(EBADF, ev);
++ return retval;
++ }
++
++ switch (Direction)
++ {
++ case FileServer_File_FromStart :
++ whence = SEEK_SET;
++ break;
++ case FileServer_File_FromCurrent :
++ whence = SEEK_CUR;
++ break;
++ case FileServer_File_FromEnd :
++ whence = SEEK_END;
++ break;
++ default :
++ set_exception(EINVAL, ev);
++ return retval;
++ }
++
++ retval = lseek(servant->fd, Offset, whence);
++ if (retval == -1)
++ {
++ printf("File->Seek ERROR : %d\n", errno);
++ set_exception(errno, ev);
++ }
++
++ return retval;
++}
++
++static FileServer_File
++impl_FileServer_File_Duplicate(impl_POA_FileServer_File * servant,
++ CORBA_Environment * ev)
++{
++ FileServer_File retval;
++ printf("UNIMP: impl_FileServer_File_Duplicate\n");
++ return retval;
++}
++
++static FileServer_FileSystem
++impl_FileServer_FileSystem__create(PortableServer_POA poa,
++ CORBA_Environment * ev)
++{
++ FileServer_FileSystem retval;
++ impl_POA_FileServer_FileSystem *newservant;
++ PortableServer_ObjectId *objid;
++
++ newservant = g_new0(impl_POA_FileServer_FileSystem, 1);
++ newservant->servant.vepv = &impl_FileServer_FileSystem_vepv;
++ newservant->poa = poa;
++ POA_FileServer_FileSystem__init((PortableServer_Servant) newservant, ev);
++ objid = PortableServer_POA_activate_object(poa, newservant, ev);
++ CORBA_free(objid);
++ retval = PortableServer_POA_servant_to_reference(poa, newservant, ev);
++
++ return retval;
++}
++
++static void
++impl_FileServer_FileSystem__destroy(impl_POA_FileServer_FileSystem * servant,
++ CORBA_Environment * ev)
++{
++ PortableServer_ObjectId *objid;
++
++ objid = PortableServer_POA_servant_to_id(servant->poa, servant, ev);
++ PortableServer_POA_deactivate_object(servant->poa, objid, ev);
++ CORBA_free(objid);
++
++ POA_FileServer_FileSystem__fini((PortableServer_Servant) servant, ev);
++ g_free(servant);
++}
++
++static FileServer_File
++impl_FileServer_FileSystem_Open(impl_POA_FileServer_FileSystem * servant,
++ CORBA_char * Filename,
++ CORBA_long openFlags,
++ CORBA_short mode, CORBA_Environment * ev)
++{
++ FileServer_File retval = CORBA_OBJECT_NIL;
++
++ impl_POA_FileServer_File *file;
++
++ printf("FileSystem->Open(%s,%x)\n", Filename, openFlags);
++
++ retval = impl_FileServer_File__create(servant->poa, ev);
++
++ file = PortableServer_POA_reference_to_servant( servant->poa, retval, ev );
++ file->fd = open(Filename, openFlags, mode);
++
++ if (file->fd == -1) {
++ printf("FileSystem->Open ERROR : %d\n", errno);
++ set_exception(errno, ev);
++ }
++
++ return retval;
++}
++
++static FileServer_File
++impl_FileServer_FileSystem_Create(impl_POA_FileServer_FileSystem * servant,
++ CORBA_char * Filename,
++ CORBA_short mode, CORBA_Environment * ev)
++{
++ FileServer_File retval = CORBA_OBJECT_NIL;
++
++ impl_POA_FileServer_File *file;
++
++ printf("FileSystem->Create(%s,%x)\n", Filename, mode);
++
++ retval = impl_FileServer_File__create(servant->poa, ev);
++
++ file = PortableServer_POA_reference_to_servant( servant->poa, retval, ev );
++ file->fd = creat(Filename, mode);
++
++ if (file->fd == -1) {
++ printf("FileSystem->Create ERROR : %d\n", errno);
++ set_exception(errno, ev);
++ }
++
++ return retval;
++}
++
++static void
++impl_FileServer_FileSystem_Link(impl_POA_FileServer_FileSystem * servant,
++ CORBA_char * FromPath,
++ CORBA_char * ToPath, CORBA_Environment * ev)
++{
++ printf("UNIMP: impl_FileServer_FileSystem_Link\n");
++}
++
++static void
++impl_FileServer_FileSystem_Unlink(impl_POA_FileServer_FileSystem * servant,
++ CORBA_char * Filename,
++ CORBA_Environment * ev)
++{
++ printf("UNIMP: impl_FileServer_FileSystem_Unlink\n");
++}
++
++static void
++impl_FileServer_FileSystem_Rename(impl_POA_FileServer_FileSystem * servant,
++ CORBA_char * OldName,
++ CORBA_char * NewName,
++ CORBA_Environment * ev)
++{
++ printf("UNIMP: impl_FileServer_FileSystem_Rename\n");
++}
++
++static void
++impl_FileServer_FileSystem_ReadLink(impl_POA_FileServer_FileSystem * servant,
++ CORBA_char * Linkname,
++ CORBA_char ** LinkValue,
++ CORBA_Environment * ev)
++{
++ char tmp[PATH_MAX + 1];
++ int res, len;
++
++ printf("FileSystem->ReadLink(%s, value)\n", Linkname);
++
++ res = readlink(Linkname, tmp, PATH_MAX);
++ if (res == -1)
++ {
++ set_exception(errno, ev);
++ return;
++ }
++
++ len = strlen(tmp);
++ *LinkValue = (char *)malloc(len * sizeof(char));
++ memcpy(*LinkValue, tmp, len);
++ (*LinkValue)[len] = '\0';
++}
++
++static FileServer_FileStatus
++impl_FileServer_FileSystem_GetStatus(impl_POA_FileServer_FileSystem * servant,
++ CORBA_char * Filename,
++ CORBA_Environment * ev)
++{
++ FileServer_FileStatus retval;
++ struct stat buf;
++ int res;
++
++ printf("FileSystem->GetStatus(%s)\n", Filename);
++
++ res = stat(Filename, &buf);
++
++ if (res == -1)
++ {
++ printf("FileSystem->GetStatus(%s)\n", Filename);
++ set_exception(errno, ev);
++ return retval;
++ }
++
++ retval = stat2FileStatus(buf);
++
++ return retval;
++}
++
++static FileServer_FileStatus
++impl_FileServer_FileSystem_GetLinkStatus(impl_POA_FileServer_FileSystem *
++ servant, CORBA_char * Filename,
++ CORBA_Environment * ev)
++{
++ FileServer_FileStatus retval;
++ struct stat buf;
++ int res;
++
++ printf("FileSystem->GetLinkStatus(%s)\n", Filename);
++
++ res = lstat(Filename, &buf);
++
++ if (res == -1)
++ {
++ printf("FileSystem->GetLinkStatus(%s)\n", Filename);
++ set_exception(errno, ev);
++ return retval;
++ }
++
++ retval = stat2FileStatus(buf);
++
++ return retval;
++}
++
++static void
++impl_FileServer_FileSystem_MakeDirectory(impl_POA_FileServer_FileSystem *
++ servant, CORBA_char * PathName,
++ CORBA_short mode,
++ CORBA_Environment * ev)
++{
++ printf("UNIMP: impl_FileServer_FileSystem_MakeDirectory\n");
++}
++
++static void
++impl_FileServer_FileSystem_RemoveDirectory(impl_POA_FileServer_FileSystem *
++ servant, CORBA_char * PathName,
++ CORBA_Environment * ev)
++{
++ printf("UNIMP: impl_FileServer_FileSystem_RemoveDirectory\n");
++}
++
++static CORBA_char *
++impl_FileServer_FileSystem_ChangeDirectory(impl_POA_FileServer_FileSystem *
++ servant, CORBA_char * PathName,
++ CORBA_Environment * ev)
++{
++ CORBA_char *retval;
++ printf("UNIMP: impl_FileServer_FileSystem_ChangeDirectory\n");
++ return retval;
++}
++
++static void
++impl_FileServer_FileSystem_MakeNode(impl_POA_FileServer_FileSystem * servant,
++ CORBA_char * FileName,
++ CORBA_short Mode,
++ CORBA_long DeviceNum,
++ CORBA_Environment * ev)
++{
++ printf("UNIMP: impl_FileServer_FileSystem_MakeNode\n");
++}
++
++static void
++impl_FileServer_FileSystem_Mount(impl_POA_FileServer_FileSystem * servant,
++ CORBA_char * DeviceFile,
++ CORBA_char * Location,
++ CORBA_char * FSType,
++ CORBA_long Flags, CORBA_Environment * ev)
++{
++ printf("UNIMP: impl_FileServer_FileSystem_Mount: ARE YOU CRAZY!?!?\n");
++}
++
++static void
++impl_FileServer_FileSystem_Unmount(impl_POA_FileServer_FileSystem * servant,
++ CORBA_char * Filename,
++ CORBA_Environment * ev)
++{
++ printf("UNIMP: impl_FileServer_FileSystem_Unmount: Ha ha ha funny guy!\n");
++}
+diff -urN linux-2.4.1/net/korbit/modules/FileServer/server/Makefile linux-2.4.1-korbit/net/korbit/modules/FileServer/server/Makefile
+--- linux-2.4.1/net/korbit/modules/FileServer/server/Makefile Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/FileServer/server/Makefile Thu Feb 1 11:47:08 2001
+@@ -0,0 +1,20 @@
++#
++# Makefile for KORBit / FileServer
++#
++# Note! Dependencies are done automagically by 'make dep', which also
++# removes any old dependencies. DON'T put your own dependencies here
++# unless it's something special (ie not a .c file).
++#
++# Note 2! The CFLAGS definition is now in the main makefile...
++
++O_TARGET := corba-fileserver-server.o
++
++obj-y := FileServer-common.o FileServer-skels.o FileServer-server.o
++obj-m := $(O_TARGET)
++
++include ../../Makefile.module
++
++FileServer-server.c: FileServer.h FileServer-common.c FileServer-skels.c FileServer-skelimpl.c
++
++FileServer.h FileServer-skels.c FileServer-common.c: ../FileServer.idl
++ $(ORBIT_IDL) ../FileServer.idl
+diff -urN linux-2.4.1/net/korbit/modules/FileServer/server/Makefile.user linux-2.4.1-korbit/net/korbit/modules/FileServer/server/Makefile.user
+--- linux-2.4.1/net/korbit/modules/FileServer/server/Makefile.user Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/FileServer/server/Makefile.user Thu Feb 1 11:47:08 2001
+@@ -0,0 +1,32 @@
++#
++# Makefile for KORBit
++#
++# Note! Dependencies are done automagically by 'make dep', which also
++# removes any old dependencies. DON'T put your own dependencies here
++# unless it's something special (ie not a .c file).
++#
++# Note 2! The CFLAGS definition is now in the main makefile...
++
++PROJECT = FileServer
++
++CFLAGS = -Wall `orbit-config --cflags server` -I../../..
++LDFLAGS = `orbit-config --libs server`
++OBJS = $(PROJECT)-common.o $(PROJECT)-skels.o $(PROJECT)-server.o
++ORBIT-IDL = orbit-idl
++
++$(PROJECT)-server: $(OBJS)
++ gcc -o $(PROJECT)-server $(OBJS) $(LDFLAGS)
++
++$(PROJECT)-server.c: $(PROJECT).h $(PROJECT)-skelimpl.c
++
++$(PROJECT).h $(PROJECT)-common.c $(PROJECT)-skels.c $(PROJECT)-skelimpl.c: ../$(PROJECT).idl
++ $(ORBIT-IDL) --nostubs ../$(PROJECT).idl
++
++clean:
++ rm -f $(OBJS) $(PROJECT)-server
++
++realclean: clean
++ rm -f $(PROJECT).h
++ rm -f $(PROJECT)-common.c
++ rm -f $(PROJECT)-skels.c
++ rm -f *~
+diff -urN linux-2.4.1/net/korbit/modules/FileServer/server/README linux-2.4.1-korbit/net/korbit/modules/FileServer/server/README
+--- linux-2.4.1/net/korbit/modules/FileServer/server/README Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/FileServer/server/README Thu Feb 1 11:47:08 2001
+@@ -0,0 +1,4 @@
++Kernel side implementation of the file server functionality.
++
++ORB: kORBit
++Status: Mostly unimplemented.
+diff -urN linux-2.4.1/net/korbit/modules/FileServer/server-user/CVS/Entries linux-2.4.1-korbit/net/korbit/modules/FileServer/server-user/CVS/Entries
+--- linux-2.4.1/net/korbit/modules/FileServer/server-user/CVS/Entries Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/FileServer/server-user/CVS/Entries Thu Feb 1 11:47:08 2001
+@@ -0,0 +1,4 @@
++/FileServer-server.c/1.1/Thu Feb 1 09:47:08 2001//
++/Makefile/1.1/Thu Feb 1 09:47:08 2001//
++/README/1.1/Thu Feb 1 09:47:08 2001//
++D
+diff -urN linux-2.4.1/net/korbit/modules/FileServer/server-user/CVS/Repository linux-2.4.1-korbit/net/korbit/modules/FileServer/server-user/CVS/Repository
+--- linux-2.4.1/net/korbit/modules/FileServer/server-user/CVS/Repository Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/FileServer/server-user/CVS/Repository Thu Feb 1 11:47:08 2001
+@@ -0,0 +1 @@
++/cvsroot/korbit/linux/net/korbit/modules/FileServer/server-user
+diff -urN linux-2.4.1/net/korbit/modules/FileServer/server-user/CVS/Root linux-2.4.1-korbit/net/korbit/modules/FileServer/server-user/CVS/Root
+--- linux-2.4.1/net/korbit/modules/FileServer/server-user/CVS/Root Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/FileServer/server-user/CVS/Root Thu Feb 1 11:47:08 2001
+@@ -0,0 +1 @@
++vraalsen@cvs.korbit.sourceforge.net:/cvsroot/korbit
+diff -urN linux-2.4.1/net/korbit/modules/FileServer/server-user/FileServer-server.c linux-2.4.1-korbit/net/korbit/modules/FileServer/server-user/FileServer-server.c
+--- linux-2.4.1/net/korbit/modules/FileServer/server-user/FileServer-server.c Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/FileServer/server-user/FileServer-server.c Thu Feb 1 11:47:08 2001
+@@ -0,0 +1,234 @@
++#include <OB/CORBA.h>
++#include <OB/Util.h>
++#include <OB/CosNaming.h>
++#include <stdlib.h>
++#include <sys/types.h>
++#include <sys/stat.h>
++#include <fcntl.h>
++#include <errno.h>
++
++#include "FileServer_skel.h"
++
++static void ThrowErr() {
++ switch (errno) {
++ case 0: return;
++ case EISDIR:
++ throw Errors::IsDirectory();
++ case EPERM:
++ throw Errors::PermissionDenied();
++ case EEXIST:
++ throw Errors::FileExists();
++ case ENOENT:
++ throw Errors::FileNotFound();
++ case ENOTDIR:
++ throw Errors::IsNotDirectory();
++ case EROFS:
++ case ETXTBSY:
++ throw Errors::ReadOnlyFile();
++ case ELOOP:
++ throw Errors::RecursiveSymlink();
++ case EBUSY:
++ throw Errors::IsBusy();
++ default:
++ throw Errors::OtherError();
++ }
++}
++
++
++class FileServer_File_impl : public FileServer_File_skel {
++ int FD;
++ public:
++ FileServer_File_impl(int fd) { FD = fd; }
++
++ virtual void Read(CORBA_Long count, FileServer_buffer*& buf) {
++ errno = 0;
++ cout << "Read\n";
++ buf = new FileServer_buffer();
++ ThrowErr();
++ }
++
++ virtual void Write(const FileServer_buffer& buf) {
++ errno = 0;
++ cout << "Write\n";
++ ThrowErr();
++ }
++
++ virtual void Close() {
++ errno = 0;
++ close(FD);
++ cout << "Close()\n";
++ ThrowErr();
++ }
++
++ virtual CORBA_Long FileControl(CORBA_Long command) {
++ errno = 0;
++ cout << "filecontrol\n";
++ ThrowErr();
++ return 0;
++ }
++
++ virtual FileServer_FileStatus GetStatus() {
++ errno = 0;
++ cout << "stat\n";
++ FileServer_FileStatus Stat;
++ ThrowErr();
++ return Stat;
++ }
++
++ virtual void ChangeDirectoryTo() {
++ errno = 0;
++ cout << "ChangeDirectoryTo()\n";
++ ThrowErr();
++ }
++
++ virtual CORBA_Long Seek(CORBA_Long Offset, SeekDirection Direction) {
++ errno = 0;
++ cout << "Seek(" << Offset << ")\n";
++ ThrowErr();
++ return -1;
++ }
++
++ virtual FileServer_File_ptr Duplicate() {
++ errno = 0;
++ cout << "Duplicate!\n";
++ ThrowErr();
++ return 0;
++ }
++};
++
++
++class FileServer_impl : public FileServer_FileSystem_skel {
++ public :
++ virtual FileServer_File_ptr Open(const char* Filename,
++ CORBA_Long openFlags,
++ CORBA_Short mode) {
++ errno = 0;
++ int fd = open(Filename, openFlags, mode);
++ if (fd != -1) return new FileServer_File_impl(fd);
++ cout << "open\n";
++ ThrowErr();
++ return 0;
++ }
++
++ virtual FileServer_File_ptr Create(const char* Filename,
++ CORBA_Short mode) {
++ errno = 0;
++ cout << "create\n";
++ ThrowErr();
++ return 0;
++ }
++
++
++ virtual void Link(const char* FromPath,
++ const char* ToPath) {
++ errno = 0;
++ cout << "link\n";
++ ThrowErr();
++ }
++
++ virtual void Unlink(const char* Filename) {
++ errno = 0;
++ cout << "unlink\n";
++ ThrowErr();
++ }
++
++ virtual void Rename(const char* OldName,
++ const char* NewName) {
++ errno = 0;
++ cout << "rename\n";
++ ThrowErr();
++ }
++
++
++ virtual void ReadLink(const char* Linkname,
++ char*& LinkValue) {
++ errno = 0;
++ cout << "readlink\n";
++ ThrowErr();
++ }
++
++ virtual FileServer_FileStatus GetStatus(const char* Filename) {
++ errno = 0;
++ cout << "stat\n";
++ FileServer_FileStatus Stat;
++ ThrowErr();
++ return Stat;
++ }
++
++
++ virtual FileServer_FileStatus GetLinkStatus(const char* Filename) {
++ errno = 0;
++ cout << "lstat\n";
++ FileServer_FileStatus Stat;
++ ThrowErr();
++ return Stat;
++ }
++
++
++ virtual void MakeDirectory(const char* PathName,
++ CORBA_Short mode) {
++ errno = 0;
++ cout << "mkdir\n";
++ ThrowErr();
++ }
++
++ virtual void RemoveDirectory(const char* PathName) {
++ errno = 0;
++ cout << "rmdir\n";
++ ThrowErr();
++ }
++
++
++ virtual char* ChangeDirectory(const char* PathName) {
++ errno = 0;
++ cout << "chdir\n";
++ ThrowErr();
++ return CORBA_string_dup("hello");
++ }
++
++ virtual void MakeNode(const char* FileName,
++ CORBA_Short Mode,
++ CORBA_Long DeviceNum) {
++ errno = 0;
++ cout << "mknod\n";
++ ThrowErr();
++ }
++
++
++ virtual void Mount(const char* DeviceFile,
++ const char* Location,
++ const char* FSType,
++ CORBA_Long Flags) {
++ errno = 0;
++ cout << "Mount\n";
++ ThrowErr();
++ }
++
++ virtual void Unmount(const char* Filename) {
++ errno = 0;
++ cout << "Unmount\n";
++ ThrowErr();
++ }
++};
++
++
++int main(int argc, char* argv[]) {
++ cout << "FileServer UserSpace Server initializing" << endl;
++
++ try {
++ CORBA_ORB_var orb = CORBA_ORB_init(argc, argv);
++ CORBA_BOA_var boa = orb->BOA_init(argc, argv);
++
++ FileServer_FileSystem_var FS = new FileServer_impl();
++
++ cout << orb->object_to_string(FS) << endl;
++
++ //
++ // Run implementation
++ //
++ boa -> impl_is_ready(CORBA_ImplementationDef::_nil());
++ } catch(CORBA_SystemException& ex) {
++ OBPrintException(ex);
++ return 1;
++ }
++}
+diff -urN linux-2.4.1/net/korbit/modules/FileServer/server-user/Makefile linux-2.4.1-korbit/net/korbit/modules/FileServer/server-user/Makefile
+--- linux-2.4.1/net/korbit/modules/FileServer/server-user/Makefile Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/FileServer/server-user/Makefile Thu Feb 1 11:47:08 2001
+@@ -0,0 +1,29 @@
++CC = CC -mt -pta
++OBDIR = /home/class/cs423/local
++IDL = $(OBDIR)/bin/idl
++CPPFLAGS = -I. -I$(OBDIR)/include
++LDFLAGS = -L$(OBDIR)/lib
++LIBS = -lCosNaming -lOB -lJTC -lsocket -lnsl -lposix4
++
++all: FileServer
++
++FileServer: FileServer.o FileServer-server.o FileServer_skel.o
++ $(CC) $(LDFLAGS) -o FileServer FileServer-server.o FileServer.o FileServer_skel.o $(LIBS)
++
++FileServer.h FileServer.cpp: ../FileServer.idl
++ rm -f FileServer.cpp FileServer.h
++ rm -f FileServer_skel.h FileServer_skel.cpp
++ $(IDL) ../FileServer.idl
++
++FileServer_skel.cpp FileServer_skel.h: FileServer.cpp
++
++%.o: %.cpp
++ $(CC) $(CPPFLAGS) -c $<
++
++clean:
++ rm -f FileServer *.o *~
++
++realclean: clean
++ rm -f FileServer.h FileServer.cpp
++ rm -f FileServer_skel.h FileServer_skel.cpp
++ rm -rf SunWS_cache
+diff -urN linux-2.4.1/net/korbit/modules/FileServer/server-user/README linux-2.4.1-korbit/net/korbit/modules/FileServer/server-user/README
+--- linux-2.4.1/net/korbit/modules/FileServer/server-user/README Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/FileServer/server-user/README Thu Feb 1 11:47:08 2001
+@@ -0,0 +1 @@
++This is a user space implementation of the FileServer interface.
+diff -urN linux-2.4.1/net/korbit/modules/FileServer/wrapper/CVS/Entries linux-2.4.1-korbit/net/korbit/modules/FileServer/wrapper/CVS/Entries
+--- linux-2.4.1/net/korbit/modules/FileServer/wrapper/CVS/Entries Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/FileServer/wrapper/CVS/Entries Thu Feb 1 11:47:09 2001
+@@ -0,0 +1,6 @@
++/FileServer_wrapper.cpp/1.2/Thu Feb 1 09:47:09 2001//
++/FileServer_wrapper.h/1.2/Thu Feb 1 09:47:09 2001//
++/Makefile/1.1/Thu Feb 1 09:47:09 2001//
++/README/1.1/Thu Feb 1 09:47:09 2001//
++/test.c/1.2/Thu Feb 1 09:47:09 2001//
++D
+diff -urN linux-2.4.1/net/korbit/modules/FileServer/wrapper/CVS/Repository linux-2.4.1-korbit/net/korbit/modules/FileServer/wrapper/CVS/Repository
+--- linux-2.4.1/net/korbit/modules/FileServer/wrapper/CVS/Repository Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/FileServer/wrapper/CVS/Repository Thu Feb 1 11:47:09 2001
+@@ -0,0 +1 @@
++/cvsroot/korbit/linux/net/korbit/modules/FileServer/wrapper
+diff -urN linux-2.4.1/net/korbit/modules/FileServer/wrapper/CVS/Root linux-2.4.1-korbit/net/korbit/modules/FileServer/wrapper/CVS/Root
+--- linux-2.4.1/net/korbit/modules/FileServer/wrapper/CVS/Root Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/FileServer/wrapper/CVS/Root Thu Feb 1 11:47:09 2001
+@@ -0,0 +1 @@
++vraalsen@cvs.korbit.sourceforge.net:/cvsroot/korbit
+diff -urN linux-2.4.1/net/korbit/modules/FileServer/wrapper/FileServer_wrapper.cpp linux-2.4.1-korbit/net/korbit/modules/FileServer/wrapper/FileServer_wrapper.cpp
+--- linux-2.4.1/net/korbit/modules/FileServer/wrapper/FileServer_wrapper.cpp Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/FileServer/wrapper/FileServer_wrapper.cpp Thu Feb 1 11:47:09 2001
+@@ -0,0 +1,135 @@
++/*
++ * FileServer_wrapper.cpp
++ *
++ * We want to intercept *all* file I/O, so that once the LD_PRELOAD
++ * variable is set, everything you see is on the remote side.
++ *
++ * Needed environment variables:
++ * LD_PRELOAD - duh (what's the lib name?)
++ * KORBIT_IOR - IOR of the file servin' ORB to connect to.
++ *
++ */
++
++#include <stdio.h>
++#include <dlfcn.h>
++#include <stdarg.h>
++#include <stdlib.h>
++#include <string.h>
++#include <dirent.h>
++#include <errno.h>
++
++#include "OB/CORBA.h"
++//#include "OB/Util.h"
++//#include "OB/CosNaming.h"
++
++#include "FileServer.h"
++#include "FileServer_wrapper.h"
++
++#define DEBUG
++
++#ifdef DEBUG
++#define debugOut(X) cerr << X << flush;
++#else
++#define debugOut(X)
++#endif
++
++
++FileSystemState::FileSystemState() {
++ char *argv[] = { (char*)"/usr/bin/mkdir", 0 };
++ int argc = 1;
++
++ debugOut ("FS_wrapper: InitializeOrb(): start.\n");
++
++ /* Set 'PerformingInitialization = true'? */
++
++ orb = CORBA_ORB_init(argc, argv);
++ if (CORBA_is_nil(orb)) {
++ cerr << "Error initializing ORB!\n";
++ exit(1);
++ }
++ debugOut ("\tORB initialized successfully.\n");
++
++ const char *env = getenv("KORBIT_IOR");
++ if (!env) {
++ // This should check /proc/corba/FileServer-server also!
++ cerr << "InitializeOrb Error: KORBIT_IOR not found in environment!\n";
++ exit(1);
++ }
++
++ cout << "IOR = " << env << endl;
++
++ // WHY DO I HANG IN string_to_object??
++ CORBA_Object_var obj = orb->string_to_object(env);
++ debugOut("\tORB initialized successfully.\n");
++
++ if (CORBA_is_nil(obj)) {
++ cerr << "InitializeOrb Error: IOR is invalid: " << env << endl;
++ exit (1);
++ }
++
++ debugOut ("\tORB initialized successfully.\n");
++ try {
++ FS = FileServer_FileSystem::_narrow(obj);
++ } catch (...) {
++ cerr << "InitializeOrb Error: Got an exception from _narrow().\n";
++ exit (1);
++ }
++
++ /* Initialize my data structure 'o file descriptors. */
++
++ // Set up mapping for stdin, stdout, stderr. Set up a new fd, #4 for
++ // console/debug output
++
++ // stderr can go to console for now.
++
++ debugOut ("FS_wrapper: InitializeOrb(): finished successfully.\n");
++} /* End InitializeOrb(). */
++
++
++FileSystemState::~FileSystemState() (void) {
++} /* End CleanupOrb(). */
++
++
++void HandleException(CORBA_UserException &Exception) {
++ try {
++ throw Exception; // get the type back...
++ } catch (Errors::FileExists &) {
++ errno = EEXIST;
++ } catch (Errors::PermissionDenied &) {
++ errno = EACCES;
++ } catch (Errors::FileNotFound &) {
++ errno = ENOENT;
++ } catch (Errors::IsNotDirectory &) {
++ errno = ENOTDIR;
++ } catch (Errors::ReadOnlyFile &) {
++ errno = EROFS;
++ } catch (Errors::RecursiveSymlink &) {
++ errno = ELOOP;
++ } catch (Errors::OtherError &) {
++ errno = EIO; /* I/O error */
++ } catch (CORBA_UserException &Exception) {
++ cerr << "unknown exception occurred! \n";
++ }
++}
++
++//int open(const char *path, int oflag, mode_t mode) {
++
++
++// return -1;
++//}
++
++int mkdir(const char *pathname, mode_t mode) {
++ debugOut("FS_wrapper: mkdir(" << pathname << "): start.\n");
++
++ try {
++ FileSystemState::get().getFS()->MakeDirectory(pathname, mode);
++ } catch (CORBA_UserException &ex) {
++ HandleException(ex);
++ return -1;
++ }
++
++ // Success!
++ debugOut("FS wrapper: mkdir(): finish successfully.\n");
++ return 0;
++} // End mkdir()
++
+diff -urN linux-2.4.1/net/korbit/modules/FileServer/wrapper/FileServer_wrapper.h linux-2.4.1-korbit/net/korbit/modules/FileServer/wrapper/FileServer_wrapper.h
+--- linux-2.4.1/net/korbit/modules/FileServer/wrapper/FileServer_wrapper.h Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/FileServer/wrapper/FileServer_wrapper.h Thu Feb 1 11:47:09 2001
+@@ -0,0 +1,81 @@
++// The KORBit FileServer wrapper, which is a shared library that gets
++// hit with the LD_PRELOAD action, so as to redirect all FS calls
++// out the CORBA hole.
++//
++// Note that most of these functions have the side effect of modifying errno.
++//
++#ifndef FILESERVER_WRAPPER_H
++#define FILESERVER_WRAPPER_H
++
++#include <sys/types.h>
++#include <sys/stat.h>
++#include <fcntl.h>
++
++// This class contains all the global variables for this file. It is very
++// important that we use this mechanism so that our library is initialized as
++// early as possible, but no earlier. In particular this means that we cannot
++// be initialized before iostreams are, which we use for debugging. This scheme
++// the only way to that we are constructed and descructed on demand.
++//
++class FileSystemState {
++private:
++ FileSystemState(); // private ctor/dtor. The only way to get one of these is
++ ~FileSystemState(); // to call FileSystemState::get()
++
++ FileSystemState(const FileSystemState &); // do not implement
++ FileSystemState &operator=(const FileSystemState &); // do not implement
++
++
++ CORBA_ORB_var orb; // Global reference to the orb.
++ FileServer_FileSystem_var FS; // Global reference to FS object...
++public:
++ static FileSystemState &get() {
++ // Static objects like this are intialized the first time they are used, and
++ // destroyed when the project shuts down. This is exactly the semantics we
++ // want.
++ static FileSystemState FSS;
++ return FSS;
++ }
++
++ CORBA_ORB_var getORB() { return orb; }
++ FileServer_FileSystem_var getFS() { return FS; }
++};
++
++extern "C" {
++
++ //
++ // interface File
++ //
++ // pread, readv, pwrite, writev
++ int read(int FD, void *Buffer, size_t NumBytes);
++ int write(int FD, void *Buffer, size_t NumBytes);
++ int close(int FD);
++ // fcntl
++ // fstat
++ // fchdir
++ // seek
++ int dup(int FD);
++ int dup2(int FDFrom, int FDTo);
++
++ //
++ // interface FileSystem
++ //
++ // int open(const char *path, int oflag, mode_t mode);
++ int creat(const char *path, mode_t mode);
++
++// link
++// unlink
++// rename
++// readlink
++// stat
++// lstat
++ int mkdir(const char *Path, mode_t Mode);
++// rmdir
++ int chdir(const char *Path);
++}
++
++//
++// Local function prototypes.
++//
++
++#endif
+diff -urN linux-2.4.1/net/korbit/modules/FileServer/wrapper/Makefile linux-2.4.1-korbit/net/korbit/modules/FileServer/wrapper/Makefile
+--- linux-2.4.1/net/korbit/modules/FileServer/wrapper/Makefile Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/FileServer/wrapper/Makefile Thu Feb 1 11:47:09 2001
+@@ -0,0 +1,29 @@
++CC = CC -mt -pta -g
++OBDIR = /home/class/cs423/local
++IDL = $(OBDIR)/bin/idl
++CPPFLAGS = -I. -I$(OBDIR)/include
++LDFLAGS = -L$(OBDIR)/lib -G -fPIC
++LIBS = -lCosNaming -lOB -lJTC -lsocket -lnsl -lposix4 -lCstd -lCrun
++
++all: libfswrapper.so
++
++libfswrapper.so: FileServer.o FileServer_wrapper.o
++ CC $(LDFLAGS) -o $@ FileServer_wrapper.o FileServer.o $(LIBS)
++
++FileServer.h FileServer.cpp: ../FileServer.idl
++ rm -f FileServer.cpp FileServer.h
++ rm -f FileServer_skel.h FileServer_skel.cpp
++ $(IDL) ../FileServer.idl
++
++FileServer_skel.cpp FileServer_skel.h: FileServer.cpp
++
++%.o: %.cpp
++ $(CC) $(CPPFLAGS) -c $<
++
++clean:
++ rm -f libfswrapper.so *.o *~
++
++realclean: clean
++ rm -f FileServer.h FileServer.cpp
++ rm -f FileServer_skel.h FileServer_skel.cpp
++ rm -rf SunWS_cache
+diff -urN linux-2.4.1/net/korbit/modules/FileServer/wrapper/README linux-2.4.1-korbit/net/korbit/modules/FileServer/wrapper/README
+--- linux-2.4.1/net/korbit/modules/FileServer/wrapper/README Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/FileServer/wrapper/README Thu Feb 1 11:47:09 2001
+@@ -0,0 +1,5 @@
++This is a library that may be LD_PRELOAD'd to forward filesystem related calls
++through the FileServer interface.
++
++ORB: ORBacus
++Status: Mostly not working
+diff -urN linux-2.4.1/net/korbit/modules/FileServer/wrapper/test.c linux-2.4.1-korbit/net/korbit/modules/FileServer/wrapper/test.c
+--- linux-2.4.1/net/korbit/modules/FileServer/wrapper/test.c Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/FileServer/wrapper/test.c Thu Feb 1 11:47:09 2001
+@@ -0,0 +1,15 @@
++#include <stdlib.h>
++#include <stdio.h>
++#include <sys/types.h>
++#include <sys/stat.h>
++
++int main(void)
++{
++ if (mkdir("test", 0666) == -1)
++ {
++ perror ("mkdir failed because: ");
++ return (1);
++ }
++
++ return (0);
++}
+diff -urN linux-2.4.1/net/korbit/modules/Makefile linux-2.4.1-korbit/net/korbit/modules/Makefile
+--- linux-2.4.1/net/korbit/modules/Makefile Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/Makefile Thu Feb 1 11:46:58 2001
+@@ -0,0 +1,15 @@
++#
++# Makefile for KORBit/modules
++#
++# Note! Dependencies are done automagically by 'make dep', which also
++# removes any old dependencies. DON'T put your own dependencies here
++# unless it's something special (ie not a .c file).
++
++subdir-$(CONFIG_CORBA_CONSOLE) += Console
++subdir-$(CONFIG_CORBA_ECHO) += Echo
++subdir-$(CONFIG_CORBA_FILESERVER) += FileServer
++subdir-$(CONFIG_CORBA_CORBAFS) += CorbaFS
++subdir-$(CONFIG_CORBA_CHARDEV) += CharDev
++
++include $(TOPDIR)/Rules.make
++
+diff -urN linux-2.4.1/net/korbit/modules/Makefile.module linux-2.4.1-korbit/net/korbit/modules/Makefile.module
+--- linux-2.4.1/net/korbit/modules/Makefile.module Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/Makefile.module Thu Feb 1 11:46:58 2001
+@@ -0,0 +1,9 @@
++M_OBJS := $(O_TARGET)
++
++EXTRA_CFLAGS = -D__KORBIT__ -DHAVE_CONFIG_H -I. -I../../.. -I../../../include -I../../../kglib -nostdinc
++
++
++ORBIT_IDL = orbit-idl
++
++include $(TOPDIR)/Rules.make
++
+diff -urN linux-2.4.1/net/korbit/modules/README linux-2.4.1-korbit/net/korbit/modules/README
+--- linux-2.4.1/net/korbit/modules/README Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/README Thu Feb 1 11:46:58 2001
+@@ -0,0 +1,7 @@
++Modules included so far:
++
++CharDev : Implement Linux character device drivers
++Console : Print strings to the Linux console
++CorbaFS : Implement Linux filesystems through the VFS layer
++Echo : Testcase to test orb two-way communication
++FileServer: Access a filesystem through CORBA
+diff -urN linux-2.4.1/net/korbit/modules/UserFS/CVS/Entries linux-2.4.1-korbit/net/korbit/modules/UserFS/CVS/Entries
+--- linux-2.4.1/net/korbit/modules/UserFS/CVS/Entries Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/UserFS/CVS/Entries Thu Feb 1 11:47:09 2001
+@@ -0,0 +1 @@
++D
+diff -urN linux-2.4.1/net/korbit/modules/UserFS/CVS/Entries.Log linux-2.4.1-korbit/net/korbit/modules/UserFS/CVS/Entries.Log
+--- linux-2.4.1/net/korbit/modules/UserFS/CVS/Entries.Log Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/UserFS/CVS/Entries.Log Thu Feb 1 11:47:10 2001
+@@ -0,0 +1 @@
++A D/client////
+diff -urN linux-2.4.1/net/korbit/modules/UserFS/CVS/Repository linux-2.4.1-korbit/net/korbit/modules/UserFS/CVS/Repository
+--- linux-2.4.1/net/korbit/modules/UserFS/CVS/Repository Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/UserFS/CVS/Repository Thu Feb 1 11:47:09 2001
+@@ -0,0 +1 @@
++/cvsroot/korbit/linux/net/korbit/modules/UserFS
+diff -urN linux-2.4.1/net/korbit/modules/UserFS/CVS/Root linux-2.4.1-korbit/net/korbit/modules/UserFS/CVS/Root
+--- linux-2.4.1/net/korbit/modules/UserFS/CVS/Root Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/UserFS/CVS/Root Thu Feb 1 11:47:09 2001
+@@ -0,0 +1 @@
++vraalsen@cvs.korbit.sourceforge.net:/cvsroot/korbit
+diff -urN linux-2.4.1/net/korbit/modules/UserFS/client/CVS/Entries linux-2.4.1-korbit/net/korbit/modules/UserFS/client/CVS/Entries
+--- linux-2.4.1/net/korbit/modules/UserFS/client/CVS/Entries Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/UserFS/client/CVS/Entries Thu Feb 1 11:47:10 2001
+@@ -0,0 +1 @@
++D
+diff -urN linux-2.4.1/net/korbit/modules/UserFS/client/CVS/Repository linux-2.4.1-korbit/net/korbit/modules/UserFS/client/CVS/Repository
+--- linux-2.4.1/net/korbit/modules/UserFS/client/CVS/Repository Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/UserFS/client/CVS/Repository Thu Feb 1 11:47:10 2001
+@@ -0,0 +1 @@
++/cvsroot/korbit/linux/net/korbit/modules/UserFS/client
+diff -urN linux-2.4.1/net/korbit/modules/UserFS/client/CVS/Root linux-2.4.1-korbit/net/korbit/modules/UserFS/client/CVS/Root
+--- linux-2.4.1/net/korbit/modules/UserFS/client/CVS/Root Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/modules/UserFS/client/CVS/Root Thu Feb 1 11:47:10 2001
+@@ -0,0 +1 @@
++vraalsen@cvs.korbit.sourceforge.net:/cvsroot/korbit
+diff -urN linux-2.4.1/net/korbit/orb/CVS/Entries linux-2.4.1-korbit/net/korbit/orb/CVS/Entries
+--- linux-2.4.1/net/korbit/orb/CVS/Entries Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/orb/CVS/Entries Thu Feb 1 11:47:14 2001
+@@ -0,0 +1,60 @@
++/Makefile/1.6/Thu Feb 1 09:47:10 2001//
++/allocator-defs.h/1.1.1.1/Thu Feb 1 09:47:10 2001//
++/allocators.c/1.2/Thu Feb 1 09:47:10 2001//
++/allocators.h/1.1.1.1/Thu Feb 1 09:47:10 2001//
++/cdr.c/1.1.1.1/Thu Feb 1 09:47:10 2001//
++/cdr.h/1.1.1.1/Thu Feb 1 09:47:10 2001//
++/corba_any.c/1.3/Thu Feb 1 09:47:10 2001//
++/corba_any.h/1.1.1.1/Thu Feb 1 09:47:10 2001//
++/corba_any_proto.h/1.1.1.1/Thu Feb 1 09:47:11 2001//
++/corba_any_type.h/1.1.1.1/Thu Feb 1 09:47:11 2001//
++/corba_basic_sequences_type.h/1.1.1.1/Thu Feb 1 09:47:11 2001//
++/corba_context.c/1.1.1.1/Thu Feb 1 09:47:11 2001//
++/corba_context.h/1.1.1.1/Thu Feb 1 09:47:11 2001//
++/corba_env.h/1.1.1.1/Thu Feb 1 09:47:11 2001//
++/corba_env_type.h/1.1.1.1/Thu Feb 1 09:47:11 2001//
++/corba_object.c/1.7/Thu Feb 1 09:47:11 2001//
++/corba_object.h/1.1.1.1/Thu Feb 1 09:47:11 2001//
++/corba_object_type.h/1.1.1.1/Thu Feb 1 09:47:11 2001//
++/corba_orb.h/1.1.1.1/Thu Feb 1 09:47:11 2001//
++/corba_orb_type.h/1.1.1.1/Thu Feb 1 09:47:11 2001//
++/corba_portableserver.h/1.1.1.1/Thu Feb 1 09:47:11 2001//
++/corba_portableserver_type.h/1.1.1.1/Thu Feb 1 09:47:11 2001//
++/corba_sequences.h/1.1.1.1/Thu Feb 1 09:47:12 2001//
++/corba_sequences_type.h/1.1.1.1/Thu Feb 1 09:47:12 2001//
++/corba_typecode.h/1.1.1.1/Thu Feb 1 09:47:12 2001//
++/corba_typecode_type.h/1.3/Thu Feb 1 09:47:12 2001//
++/dii.c/1.2/Thu Feb 1 09:47:12 2001//
++/dii.h/1.2/Thu Feb 1 09:47:12 2001//
++/env.c/1.2/Thu Feb 1 09:47:12 2001//
++/env.h/1.2/Thu Feb 1 09:47:12 2001//
++/genrand.c/1.4/Thu Feb 1 09:47:12 2001//
++/genrand.h/1.1.1.1/Thu Feb 1 09:47:12 2001//
++/iop.h/1.1.1.1/Thu Feb 1 09:47:12 2001//
++/ir.c/1.1.1.1/Thu Feb 1 09:47:12 2001//
++/ir.h/1.1.1.1/Thu Feb 1 09:47:12 2001//
++/options.c/1.2/Thu Feb 1 09:47:12 2001//
++/options.h/1.2/Thu Feb 1 09:47:13 2001//
++/orb.c/1.13/Thu Feb 1 09:47:13 2001//
++/orb.h/1.2/Thu Feb 1 09:47:13 2001//
++/orbit.c/1.1.1.1/Thu Feb 1 09:47:13 2001//
++/orbit.h/1.2/Thu Feb 1 09:47:13 2001//
++/orbit.h.in/1.1.1.1/Thu Feb 1 09:47:13 2001//
++/orbit_config.h/1.1.1.1/Thu Feb 1 09:47:13 2001//
++/orbit_object.c/1.1.1.1/Thu Feb 1 09:47:13 2001//
++/orbit_object.h/1.1.1.1/Thu Feb 1 09:47:13 2001//
++/orbit_object_type.h/1.1.1.1/Thu Feb 1 09:47:13 2001//
++/orbit_poa.c/1.1.1.1/Thu Feb 1 09:47:13 2001//
++/orbit_poa.h/1.3/Thu Feb 1 09:47:13 2001//
++/orbit_poa_type.h/1.1.1.1/Thu Feb 1 09:47:13 2001//
++/orbit_typecode.c/1.1.1.1/Thu Feb 1 09:47:14 2001//
++/orbit_typecode.h/1.1.1.1/Thu Feb 1 09:47:14 2001//
++/orbit_types.h/1.1.1.1/Thu Feb 1 09:47:14 2001//
++/poa.c/1.1.1.1/Thu Feb 1 09:47:14 2001//
++/poa.h/1.1.1.1/Thu Feb 1 09:47:14 2001//
++/sequences.c/1.1.1.1/Thu Feb 1 09:47:14 2001//
++/sequences.h/1.1.1.1/Thu Feb 1 09:47:14 2001//
++/server.c/1.5/Thu Feb 1 09:47:14 2001//
++/typecode.c/1.1.1.1/Thu Feb 1 09:47:14 2001//
++/typecode.h/1.1.1.1/Thu Feb 1 09:47:14 2001//
++D
+diff -urN linux-2.4.1/net/korbit/orb/CVS/Repository linux-2.4.1-korbit/net/korbit/orb/CVS/Repository
+--- linux-2.4.1/net/korbit/orb/CVS/Repository Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/orb/CVS/Repository Thu Feb 1 11:47:10 2001
+@@ -0,0 +1 @@
++/cvsroot/korbit/linux/net/korbit/orb
+diff -urN linux-2.4.1/net/korbit/orb/CVS/Root linux-2.4.1-korbit/net/korbit/orb/CVS/Root
+--- linux-2.4.1/net/korbit/orb/CVS/Root Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/orb/CVS/Root Thu Feb 1 11:47:10 2001
+@@ -0,0 +1 @@
++vraalsen@cvs.korbit.sourceforge.net:/cvsroot/korbit
+diff -urN linux-2.4.1/net/korbit/orb/Makefile linux-2.4.1-korbit/net/korbit/orb/Makefile
+--- linux-2.4.1/net/korbit/orb/Makefile Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/orb/Makefile Thu Feb 1 11:47:10 2001
+@@ -0,0 +1,25 @@
++#
++# Makefile for KORBit/orb
++#
++# Note! Dependencies are done automagically by 'make dep', which also
++# removes any old dependencies. DON'T put your own dependencies here
++# unless it's something special (ie not a .o file).
++#
++# Note 2! The CFLAGS definition is now in the main makefile...
++
++O_TARGET := orblib.o
++
++#obj-m := $(O_TARGET)
++obj-y := allocators.o options.o poa.o \
++ cdr.o env.o orb.o sequences.o \
++ corba_any.o genrand.o orbit.o server.o \
++ corba_context.o orbit_object.o typecode.o \
++ corba_object.o orbit_poa.o \
++ dii.o ir.o orbit_typecode.o
++
++EXTRA_CFLAGS = -D__KORBIT__ -DHAVE_CONFIG_H -I. -I.. -I../include -I../kglib -I../ORBitutil -nostdinc \
++ -DORBit_SYSRC=\"/etc/orbitrc\" \
++ -DORBIT_MAJOR_VERSION="0" -DORBIT_MINOR_VERSION="5" -DORBIT_MICRO_VERSION="3" -DORBIT_VERSION=\"0.5.3\"
++
++include $(TOPDIR)/Rules.make
++
+diff -urN linux-2.4.1/net/korbit/orb/allocator-defs.h linux-2.4.1-korbit/net/korbit/orb/allocator-defs.h
+--- linux-2.4.1/net/korbit/orb/allocator-defs.h Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/orb/allocator-defs.h Thu Feb 1 11:47:10 2001
+@@ -0,0 +1,40 @@
++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
++
++/* By Elliot Lee. Copyright (c) 1998 Red Hat Software */
++
++
++/********************************************************
++ * Never include this header file directly. Only allocators.[ch]
++ * should do this
++ ********************************************************/
++
++/* Macro crap */
++
++#ifdef ALLOCATOR_DEFINITION
++
++#define ORBIT_DEFINE_CHUNK(x, xsize) \
++DEFINE_LOCK(x##_allocator); \
++GMemChunk *x##_allocator = NULL
++
++#elif defined(ALLOCATOR_INITIALIZATION)
++
++#define ORBIT_DEFINE_CHUNK(x, xsize) INIT_LOCK(x##_allocator); \
++x##_allocator = g_mem_chunk_new(#x, (xsize), \
++(xsize) * ORBIT_CHUNKS_PREALLOC, G_ALLOC_AND_FREE)
++
++#else
++
++#define ORBIT_DEFINE_CHUNK(x, xsize) \
++EXTERN_LOCK(x##_allocator); \
++extern GMemChunk *x##_allocator
++
++#endif
++
++/*****************************************************
++ * Here's where we define the actual chunks that are used
++ *****************************************************/
++ORBIT_DEFINE_CHUNK(CORBA_TypeCode, sizeof(struct CORBA_TypeCode_struct));
++ORBIT_DEFINE_CHUNK(CORBA_Object, sizeof(struct CORBA_Object_struct));
++ORBIT_DEFINE_CHUNK(CORBA_NVList, sizeof(struct CORBA_NVList_type));
++
++#undef ORBIT_DEFINE_CHUNK
+diff -urN linux-2.4.1/net/korbit/orb/allocators.c linux-2.4.1-korbit/net/korbit/orb/allocators.c
+--- linux-2.4.1/net/korbit/orb/allocators.c Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/orb/allocators.c Thu Feb 1 11:47:10 2001
+@@ -0,0 +1,241 @@
++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
++
++/* By Elliot Lee. Copyright (c) 1998 Red Hat Software */
++
++#include "orbit.h"
++
++#if 0
++#define CORBA_Object_release(x, y) ({ g_message(__FILE__ ":%d Releasing object %#x from %d", __LINE__, \
++x, ORBIT_ROOT_OBJECT(x)->refs); CORBA_Object_release(x, y); })
++#define CORBA_Object_duplicate(x, y) ({ g_message(__FILE__ ":%d Duping object %#x from %d", __LINE__, \
++x, ORBIT_ROOT_OBJECT(x)->refs); CORBA_Object_duplicate(x, y); })
++#endif
++
++/* The memory chunk stuff */
++
++#define ALLOCATOR_DEFINITION
++#include "allocator-defs.h"
++#undef ALLOCATOR_DEFINITION
++
++void
++ORBit_chunks_init(void)
++{
++#define ALLOCATOR_INITIALIZATION
++#include "allocator-defs.h"
++#undef ALLOCATOR_INTIALIZATION
++}
++
++gpointer
++ORBit_chunk_alloc(GMemChunk *chunk,
++ PARAM_LOCK(chunk))
++{
++ gpointer retval;
++
++ GET_LOCK(chunk);
++ retval = g_mem_chunk_alloc(chunk);
++ RELEASE_LOCK(chunk);
++
++ return retval;
++}
++
++void
++ORBit_chunk_free(GMemChunk *chunk,
++ PARAM_LOCK(chunk),
++ gpointer mem)
++{
++ GET_LOCK(chunk);
++ g_mem_chunk_free(chunk, mem);
++ RELEASE_LOCK(chunk);
++}
++
++/* end memory chunk routines */
++
++/****************************************************************/
++
++/************* begin funky memory alloc/free system */
++
++/****** functions */
++
++gpointer ORBit_alloc(size_t block_size,
++ ORBit_free_childvals freefunc,
++ gpointer func_data)
++{
++ return ORBit_alloc_2(block_size, freefunc, func_data, 0);
++}
++
++gpointer
++ORBit_alloc_2(size_t block_size,
++ ORBit_free_childvals freefunc,
++ gpointer func_data,
++ size_t before_size)
++{
++ ORBit_mem_info *block;
++
++ if(block_size == 0) return NULL;
++
++ block = (ORBit_mem_info *)((char *)
++ g_malloc(block_size + sizeof(ORBit_mem_info) + before_size)
++ + before_size);
++
++#ifdef ORBIT_DEBUG
++ block->magic = 0xdeadbeef;
++#endif
++ block->free = freefunc;
++ block->func_data = func_data;
++
++ return MEMINFO_TO_PTR(block);
++}
++
++/*
++ ORBit_free
++ ----------
++
++ Frees a corba primitive type.
++
++ mem = pointer to the memory block. (must have a preceeding pointer to a meminfo block)
++
++ 1)obtains a pointer to the preceeding meminfo structure
++ 2)Uses the meminfo structure to find the number of elements in the memory block
++ 3)iterates through the memory block, calling the free function for each item.
++
++ */
++
++void
++ORBit_free(gpointer mem, CORBA_boolean free_strings)
++{
++ ORBit_mem_info *block;
++
++ if(!mem)
++ return;
++
++ block = PTR_TO_MEMINFO(mem);
++
++#ifdef ORBIT_DEBUG
++ g_assert(block->magic == 0xdeadbeef);
++#endif
++
++ if(block->free) {
++ int i;
++ gpointer x;
++ gpointer my_data;
++
++ if((gpointer)block->free == (gpointer)ORBit_free_via_TypeCode)
++ my_data = ((guchar *)block) - sizeof(CORBA_TypeCode);
++ else
++ my_data = NULL;
++
++#ifdef ORBIT_DEBUG
++ if(block->func_data == NULL)
++ g_warning("block with freefunc %p has no items", block->free);
++#endif
++
++ for(i = 0, x = mem; i < (gulong)block->func_data; i++)
++ x = block->free(x, my_data, free_strings);
++
++ if((gpointer)block->free == (gpointer)ORBit_free_via_TypeCode)
++ /* ((guchar *)block) -= sizeof(CORBA_TypeCode); */
++ block = (ORBit_mem_info *)
++ (((guchar *)block) - sizeof(CORBA_TypeCode));
++ g_free(block);
++ } else
++ g_free(block);
++}
++
++/******************************************************************/
++/* These aren't currently used... */
++
++gpointer
++ORBit_free_via_TypeCode(gpointer mem, gpointer tcp, gboolean free_strings)
++{
++ CORBA_TypeCode tc = *(CORBA_TypeCode *)tcp, subtc;
++ int i;
++ guchar *retval = NULL;
++
++ switch(tc->kind) {
++ case CORBA_tk_any:
++ {
++ CORBA_any *anyval = mem;
++ if(anyval->_release)
++ CORBA_free(anyval->_value);
++ retval = (guchar *)(anyval + 1);
++ }
++ break;
++ case CORBA_tk_TypeCode:
++ case CORBA_tk_objref:
++ {
++ CORBA_Object_release(*(CORBA_Object *)mem, NULL);
++
++ retval = (guchar *)mem + sizeof(CORBA_Object);
++ }
++ break;
++ case CORBA_tk_Principal:
++ {
++ CORBA_Principal *pval = mem;
++ if(pval->_release)
++ CORBA_free(pval->_buffer);
++ retval = (guchar *)(pval + 1);
++ }
++ break;
++ case CORBA_tk_except:
++ case CORBA_tk_struct:
++ mem = ALIGN_ADDRESS(mem, ORBit_find_alignment(tc));
++ for(i = 0; i < tc->sub_parts; i++) {
++ subtc = (CORBA_TypeCode)CORBA_Object_duplicate((CORBA_Object)tc->subtypes[i], NULL);
++ mem = ORBit_free_via_TypeCode(mem, &subtc,
++ free_strings);
++ }
++ retval = mem;
++ break;
++ case CORBA_tk_union:
++ subtc = (CORBA_TypeCode)CORBA_Object_duplicate(
++ (CORBA_Object)ORBit_get_union_tag(tc, &mem, TRUE), NULL);
++ {
++ int sz = 0;
++ int al = 1;
++ for(i = 0; i < tc->sub_parts; i++) {
++ al = MAX(al, ORBit_find_alignment(tc->subtypes[i]));
++ sz = MAX(sz, ORBit_gather_alloc_info(tc->subtypes[i]));
++ }
++ mem = ALIGN_ADDRESS(mem, al);
++ ORBit_free_via_TypeCode(mem, &subtc, free_strings);
++ /* the end of the body (subtc) may not be the
++ * same as the end of the union */
++ retval = mem + sz;
++ }
++ break;
++ case CORBA_tk_wstring:
++ case CORBA_tk_string:
++ if(free_strings)
++ CORBA_free(*(char **)mem);
++ retval = (guchar *)mem + sizeof(char *);
++ break;
++ case CORBA_tk_sequence:
++ {
++ CORBA_sequence_octet *pval = mem;
++ if(pval->_release)
++ CORBA_free(pval->_buffer);
++
++ retval = (guchar *)mem + sizeof(CORBA_sequence_octet);
++ }
++ break;
++ case CORBA_tk_array:
++ for(i = 0; i < tc->length; i++) {
++ subtc = (CORBA_TypeCode)CORBA_Object_duplicate((CORBA_Object)tc->subtypes[0], NULL);
++ mem = ORBit_free_via_TypeCode(mem, &subtc,
++ free_strings);
++ }
++ retval = mem;
++ break;
++ case CORBA_tk_alias:
++ subtc = (CORBA_TypeCode)CORBA_Object_duplicate((CORBA_Object)tc->subtypes[0], NULL);
++ retval = ORBit_free_via_TypeCode(mem, &subtc, free_strings);
++ break;
++ default:
++ retval = ((guchar *)mem) + ORBit_gather_alloc_info(tc);
++ break;
++ }
++
++ CORBA_Object_release((CORBA_Object)tc, NULL);
++
++ return (gpointer)retval;
++}
+diff -urN linux-2.4.1/net/korbit/orb/allocators.h linux-2.4.1-korbit/net/korbit/orb/allocators.h
+--- linux-2.4.1/net/korbit/orb/allocators.h Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/orb/allocators.h Thu Feb 1 11:47:10 2001
+@@ -0,0 +1,61 @@
++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
++
++/* By Elliot Lee. Copyright (c) 1998 Red Hat Software */
++
++#ifndef ALLOCATORS_H
++#define ALLOCATORS_H 1
++
++#include <orb/orbit.h>
++
++#include <orb/allocator-defs.h>
++
++#define ORBIT_CHUNK_ALLOC(typename) \
++ORBit_chunk_alloc(typename##_allocator, LOCK_NAME(typename##_allocator))
++
++#define ORBIT_CHUNK_FREE(typename, mem) \
++ORBit_chunk_free(typename##_allocator, LOCK_NAME(typename##_allocator), (mem))
++
++void ORBit_chunks_init(void);
++
++gpointer ORBit_chunk_alloc(GMemChunk *chunk,
++ PARAM_LOCK(chunk_lock));
++
++void ORBit_chunk_free(GMemChunk *chunk,
++ PARAM_LOCK(chunk_lock),
++ gpointer mem);
++
++/* General memory allocation routines */
++
++#define PTR_TO_MEMINFO(x) (((ORBit_mem_info *)(x)) - 1)
++#define MEMINFO_TO_PTR(x) ((gpointer)((x) + 1))
++
++typedef gpointer (*ORBit_free_childvals)(gpointer mem,
++ gpointer func_data,
++ CORBA_boolean free_strings);
++
++typedef struct {
++#ifdef ORBIT_DEBUG
++ gulong magic;
++#endif
++ /* If this routine returns FALSE, it indicates that it already free'd
++ the memory block itself */
++ ORBit_free_childvals free; /* function pointer to free function */
++ gpointer func_data;
++} ORBit_mem_info;
++
++gpointer ORBit_alloc(size_t block_size,
++ ORBit_free_childvals freefunc,
++ gpointer func_data);
++gpointer ORBit_alloc_2(size_t block_size,
++ ORBit_free_childvals freefunc,
++ gpointer func_data,
++ size_t before_size);
++
++void ORBit_free(gpointer mem, CORBA_boolean free_strings);
++
++/* internal stuff */
++gpointer ORBit_free_via_TypeCode(gpointer mem,
++ gpointer tcp,
++ gboolean free_strings);
++
++#endif /* ALLOCATORS_H */
+diff -urN linux-2.4.1/net/korbit/orb/cdr.c linux-2.4.1-korbit/net/korbit/orb/cdr.c
+--- linux-2.4.1/net/korbit/orb/cdr.c Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/orb/cdr.c Thu Feb 1 11:47:10 2001
+@@ -0,0 +1,643 @@
++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
++
++/*
++ * ORBit: A CORBA v2.2 ORB
++ *
++ * Copyright (C) 1998 Richard H. Porter
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Library General Public
++ * License as published by the Free Software Foundation; either
++ * version 2 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Library General Public License for more details.
++ *
++ * You should have received a copy of the GNU Library General Public
++ * License along with this library; if not, write to the Free
++ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Author: Dick Porter <dick@cymru.net>
++ *
++ */
++
++#include "config.h"
++#include "../IIOP/iiop-endianP.h"
++#include <stdlib.h>
++#include <string.h>
++#include <ctype.h>
++#include <assert.h>
++
++#include "orbit.h"
++
++#define CDR_GROW_AMOUNT 128
++
++static CORBA_boolean CDR_buffer_grow(CDR_Codec *codec, const unsigned int growth)
++{
++ unsigned int real_growth;
++ div_t divvy;
++
++ if(codec->release_buffer) {
++ divvy=div(growth, CDR_GROW_AMOUNT);
++ real_growth=CDR_GROW_AMOUNT * (divvy.quot+1);
++
++ codec->buffer=(CORBA_octet *)g_realloc(codec->buffer,
++ codec->buf_len
++ +real_growth);
++ }
++
++ return CORBA_TRUE;
++}
++
++static void CDR_buffer_puts(CDR_Codec *codec, const void *data, const unsigned int len)
++{
++ if(codec->wptr+len > codec->buf_len) {
++ CORBA_boolean res=CDR_buffer_grow(codec, len);
++
++ if(res==CORBA_FALSE) {
++ /* just bail out for now */
++ g_assert(!"Malloc error");
++ }
++ }
++
++ memcpy(&codec->buffer[codec->wptr], data, len);
++ codec->wptr+=len;
++}
++
++CORBA_boolean CDR_buffer_gets(CDR_Codec *codec, void *dest, const unsigned int len)
++{
++ if(codec->rptr+len > codec->buf_len) {
++ ORBit_Trace(TraceMod_CDR, TraceLevel_Debug, "CDR_buffer_gets: attempt to read past end of buffer\n");
++ return(CORBA_FALSE);
++ }
++
++ memcpy(dest, &codec->buffer[codec->rptr], len);
++ codec->rptr+=len;
++
++ return(CORBA_TRUE);
++}
++
++static void CDR_buffer_put(CDR_Codec *codec, void *datum)
++{
++ if(codec->wptr+1 > codec->buf_len) {
++ CORBA_boolean res=CDR_buffer_grow(codec, 1);
++
++ if(res==CORBA_FALSE) {
++ /* just bail out for now */
++ g_assert(!"Malloc error");
++ }
++ }
++
++ codec->buffer[codec->wptr++]=*(unsigned char *)datum;
++}
++
++static CORBA_boolean CDR_buffer_get(CDR_Codec *codec, void *dest)
++{
++ if(codec->rptr+1 > codec->buf_len) {
++ ORBit_Trace(TraceMod_CDR, TraceLevel_Debug, "CDR_buffer_get: attempt to read past end of buffer\n");
++ return(CORBA_FALSE);
++ }
++
++ *(CORBA_octet *)dest=codec->buffer[codec->rptr++];
++ return(CORBA_TRUE);
++}
++
++#ifdef lame_slow_code
++static void CDR_buffer_put2(CDR_Codec *codec, void *datum)
++{
++ unsigned long align;
++
++ g_assert(codec!=NULL);
++ g_assert(codec->readonly!=CORBA_TRUE);
++ g_assert(codec->wptr<=codec->buf_len);
++
++ align=((codec->wptr+1)&~1L);
++
++ if(align+2 > codec->buf_len) {
++ CORBA_boolean res=CDR_buffer_grow(codec, align+2-codec->wptr);
++
++ if(res==CORBA_FALSE) {
++ /* just bail out for now */
++ g_assert(!"Malloc error");
++ }
++ }
++
++ while(codec->wptr < align) {
++ codec->buffer[codec->wptr++]='\0';
++ }
++
++ codec->buffer[codec->wptr++]=((CORBA_octet *)datum)[0];
++ codec->buffer[codec->wptr++]=((CORBA_octet *)datum)[1];
++}
++
++static CORBA_boolean CDR_buffer_get2(CDR_Codec *codec, void *dest)
++{
++ unsigned long align;
++
++ g_assert(codec!=NULL);
++ g_assert(dest!=NULL);
++ g_assert(codec->rptr<=codec->buf_len);
++
++ align=((codec->rptr+1)&~1L);
++
++ if(align+2 > codec->buf_len) {
++ ORBit_Trace(TraceMod_CDR, TraceLevel_Debug, "CDR_buffer_get2: attempt to read past end of buffer\n");
++ return(CORBA_FALSE);
++ }
++
++ codec->rptr=align;
++
++ ((CORBA_octet *)dest)[0]=codec->buffer[codec->rptr++];
++ ((CORBA_octet *)dest)[1]=codec->buffer[codec->rptr++];
++
++ return(CORBA_TRUE);
++}
++
++static void CDR_buffer_put4(CDR_Codec *codec, void *datum)
++{
++ unsigned long align;
++
++ g_assert(codec!=NULL);
++ g_assert(codec->readonly!=CORBA_TRUE);
++ g_assert(codec->wptr<=codec->buf_len);
++
++ align=((codec->wptr+3)&~3L);
++
++ if(align+4 > codec->buf_len) {
++ CORBA_boolean res=CDR_buffer_grow(codec, align+4-codec->wptr);
++
++ if(res==CORBA_FALSE) {
++ /* just bail out for now */
++ g_assert(!"Malloc error");
++ }
++ }
++
++ while(codec->wptr < align) {
++ codec->buffer[codec->wptr++]='\0';
++ }
++
++ codec->buffer[codec->wptr++]=((CORBA_octet *)datum)[0];
++ codec->buffer[codec->wptr++]=((CORBA_octet *)datum)[1];
++ codec->buffer[codec->wptr++]=((CORBA_octet *)datum)[2];
++ codec->buffer[codec->wptr++]=((CORBA_octet *)datum)[3];
++}
++
++static CORBA_boolean CDR_buffer_get4(CDR_Codec *codec, void *dest)
++{
++ unsigned long align;
++
++ g_assert(codec!=NULL);
++ g_assert(dest!=NULL);
++ g_assert(codec->rptr<=codec->buf_len);
++
++ align=((codec->rptr+3)&~3L);
++
++ if(align+4 > codec->buf_len) {
++ ORBit_Trace(TraceMod_CDR, TraceLevel_Debug, "CDR_buffer_get4: attempt to read past end of buffer\n");
++ return(CORBA_FALSE);
++ }
++
++ codec->rptr=align;
++
++ ((CORBA_octet *)dest)[0]=codec->buffer[codec->rptr++];
++ ((CORBA_octet *)dest)[1]=codec->buffer[codec->rptr++];
++ ((CORBA_octet *)dest)[2]=codec->buffer[codec->rptr++];
++ ((CORBA_octet *)dest)[3]=codec->buffer[codec->rptr++];
++
++ return(CORBA_TRUE);
++}
++
++static void CDR_buffer_put8(CDR_Codec *codec, void *datum)
++{
++ unsigned long align;
++
++ g_assert(codec!=NULL);
++ g_assert(codec->readonly!=CORBA_TRUE);
++ g_assert(codec->wptr<=codec->buf_len);
++
++ align=((codec->wptr+7)&~7L);
++
++ if(align+8 > codec->buf_len) {
++ CORBA_boolean res=CDR_buffer_grow(codec, align+8-codec->wptr);
++
++ if(res==CORBA_FALSE) {
++ /* just bail out for now */
++ g_assert(!"Malloc error");
++ }
++ }
++
++ while(codec->wptr < align) {
++ codec->buffer[codec->wptr++]='\0';
++ }
++
++ codec->buffer[codec->wptr++]=((CORBA_octet *)datum)[0];
++ codec->buffer[codec->wptr++]=((CORBA_octet *)datum)[1];
++ codec->buffer[codec->wptr++]=((CORBA_octet *)datum)[2];
++ codec->buffer[codec->wptr++]=((CORBA_octet *)datum)[3];
++ codec->buffer[codec->wptr++]=((CORBA_octet *)datum)[4];
++ codec->buffer[codec->wptr++]=((CORBA_octet *)datum)[5];
++ codec->buffer[codec->wptr++]=((CORBA_octet *)datum)[6];
++ codec->buffer[codec->wptr++]=((CORBA_octet *)datum)[7];
++}
++
++#if 0
++static CORBA_boolean CDR_buffer_get8(CDR_Codec *codec, void *dest)
++{
++ unsigned long align;
++
++ g_assert(codec!=NULL);
++ g_assert(dest!=NULL);
++ g_assert(codec->rptr<=codec->buf_len);
++
++ align=((codec->rptr+7)&~7L);
++
++ if(align+8 > codec->buf_len) {
++ ORBit_Trace(TraceMod_CDR, TraceLevel_Debug, "CDR_buffer_get8: attempt to read past end of buffer\n");
++ return(CORBA_FALSE);
++ }
++
++ codec->rptr=align;
++
++ ((CORBA_octet *)dest)[0]=codec->buffer[codec->rptr++];
++ ((CORBA_octet *)dest)[1]=codec->buffer[codec->rptr++];
++ ((CORBA_octet *)dest)[2]=codec->buffer[codec->rptr++];
++ ((CORBA_octet *)dest)[3]=codec->buffer[codec->rptr++];
++ ((CORBA_octet *)dest)[4]=codec->buffer[codec->rptr++];
++ ((CORBA_octet *)dest)[5]=codec->buffer[codec->rptr++];
++ ((CORBA_octet *)dest)[6]=codec->buffer[codec->rptr++];
++ ((CORBA_octet *)dest)[7]=codec->buffer[codec->rptr++];
++
++ return(CORBA_TRUE);
++}
++#endif
++
++static void CDR_buffer_put16(CDR_Codec *codec, void *datum)
++{
++ unsigned long align;
++
++ g_assert(codec!=NULL);
++ g_assert(codec->readonly!=CORBA_TRUE);
++ g_assert(codec->wptr<=codec->buf_len);
++
++ align=((codec->wptr+15)&~15L);
++
++ if(align+16 > codec->buf_len) {
++ CORBA_boolean res=CDR_buffer_grow(codec, align+16-codec->wptr);
++
++ if(res==CORBA_FALSE) {
++ /* just bail out for now */
++ g_assert(!"Malloc error");
++ }
++ }
++
++ while(codec->wptr < align) {
++ codec->buffer[codec->wptr++]='\0';
++ }
++
++ codec->buffer[codec->wptr++]=((CORBA_octet *)datum)[0];
++ codec->buffer[codec->wptr++]=((CORBA_octet *)datum)[1];
++ codec->buffer[codec->wptr++]=((CORBA_octet *)datum)[2];
++ codec->buffer[codec->wptr++]=((CORBA_octet *)datum)[3];
++ codec->buffer[codec->wptr++]=((CORBA_octet *)datum)[4];
++ codec->buffer[codec->wptr++]=((CORBA_octet *)datum)[5];
++ codec->buffer[codec->wptr++]=((CORBA_octet *)datum)[6];
++ codec->buffer[codec->wptr++]=((CORBA_octet *)datum)[7];
++ codec->buffer[codec->wptr++]=((CORBA_octet *)datum)[8];
++ codec->buffer[codec->wptr++]=((CORBA_octet *)datum)[9];
++ codec->buffer[codec->wptr++]=((CORBA_octet *)datum)[10];
++ codec->buffer[codec->wptr++]=((CORBA_octet *)datum)[11];
++ codec->buffer[codec->wptr++]=((CORBA_octet *)datum)[12];
++ codec->buffer[codec->wptr++]=((CORBA_octet *)datum)[13];
++ codec->buffer[codec->wptr++]=((CORBA_octet *)datum)[14];
++ codec->buffer[codec->wptr++]=((CORBA_octet *)datum)[15];
++}
++
++#if 0
++static CORBA_boolean CDR_buffer_get16(CDR_Codec *codec, void *dest)
++{
++ unsigned long align;
++
++ g_assert(codec!=NULL);
++ g_assert(dest!=NULL);
++ g_assert(codec->rptr<=codec->buf_len);
++
++ align=((codec->rptr+15)&~15L);
++
++ if(align+16 > codec->buf_len) {
++ ORBit_Trace(TraceMod_CDR, TraceLevel_Debug, "CDR_buffer_get16: attempt to read past end of buffer\n");
++ return(CORBA_FALSE);
++ }
++
++ codec->rptr=align;
++
++ ((CORBA_octet *)dest)[0]=codec->buffer[codec->rptr++];
++ ((CORBA_octet *)dest)[1]=codec->buffer[codec->rptr++];
++ ((CORBA_octet *)dest)[2]=codec->buffer[codec->rptr++];
++ ((CORBA_octet *)dest)[3]=codec->buffer[codec->rptr++];
++ ((CORBA_octet *)dest)[4]=codec->buffer[codec->rptr++];
++ ((CORBA_octet *)dest)[5]=codec->buffer[codec->rptr++];
++ ((CORBA_octet *)dest)[6]=codec->buffer[codec->rptr++];
++ ((CORBA_octet *)dest)[7]=codec->buffer[codec->rptr++];
++ ((CORBA_octet *)dest)[8]=codec->buffer[codec->rptr++];
++ ((CORBA_octet *)dest)[9]=codec->buffer[codec->rptr++];
++ ((CORBA_octet *)dest)[10]=codec->buffer[codec->rptr++];
++ ((CORBA_octet *)dest)[11]=codec->buffer[codec->rptr++];
++ ((CORBA_octet *)dest)[12]=codec->buffer[codec->rptr++];
++ ((CORBA_octet *)dest)[13]=codec->buffer[codec->rptr++];
++ ((CORBA_octet *)dest)[14]=codec->buffer[codec->rptr++];
++ ((CORBA_octet *)dest)[15]=codec->buffer[codec->rptr++];
++
++ return(CORBA_TRUE);
++}
++#endif
++#endif /* lame_slow_code */
++
++#define CDR_buffer_put2(codec, datum) CDR_buffer_putn(codec, datum, 2)
++#define CDR_buffer_put4(codec, datum) CDR_buffer_putn(codec, datum, 4)
++#define CDR_buffer_put8(codec, datum) CDR_buffer_putn(codec, datum, 8)
++#define CDR_buffer_put16(codec, datum) CDR_buffer_putn(codec, datum, 16)
++#define CDR_buffer_get2(codec, dest) CDR_buffer_getn(codec, dest, 2)
++#define CDR_buffer_get4(codec, dest) CDR_buffer_getn(codec, dest, 4)
++#define CDR_buffer_get8(codec, dest) CDR_buffer_getn(codec, dest, 8)
++#define CDR_buffer_get16(codec, dest) CDR_buffer_getn(codec, dest, 16)
++
++static CORBA_boolean
++CDR_buffer_getn(CDR_Codec *codec, void *dest, int bsize)
++{
++ codec->rptr = (unsigned long)ALIGN_ADDRESS(codec->rptr, bsize);
++ if(codec->host_endian==codec->data_endian)
++ memcpy(dest, codec->buffer + codec->rptr, bsize);
++ else
++ iiop_byteswap(dest, codec->buffer + codec->rptr, bsize);
++ codec->rptr += bsize;
++
++ return CORBA_TRUE;
++}
++
++static CORBA_boolean
++CDR_buffer_putn(CDR_Codec *codec, void *datum, int bsize)
++{
++ codec->wptr = (unsigned long)ALIGN_ADDRESS(codec->wptr, bsize);
++ if(codec->host_endian==codec->data_endian)
++ memcpy(codec->buffer + codec->wptr, datum, bsize);
++ else
++ iiop_byteswap(codec->buffer + codec->wptr, datum, bsize);
++ codec->wptr += bsize;
++
++ return CORBA_TRUE;
++}
++
++#define CDR_swap2(d,s) iiop_byteswap((d), (s), 2)
++#define CDR_swap4(d,s) iiop_byteswap((d), (s), 4)
++#define CDR_swap8(d,s) iiop_byteswap((d), (s), 8)
++#define CDR_swap16(d,s) iiop_byteswap((d), (s), 16)
++
++#ifdef lame_slow_code
++static void CDR_swap2(void *d, void *s)
++{
++ ((CORBA_octet *)d)[0]=((CORBA_octet *)s)[1];
++ ((CORBA_octet *)d)[1]=((CORBA_octet *)s)[0];
++}
++
++static void CDR_swap4(void *d, void *s)
++{
++ ((CORBA_octet *)d)[0]=((CORBA_octet *)s)[3];
++ ((CORBA_octet *)d)[1]=((CORBA_octet *)s)[2];
++ ((CORBA_octet *)d)[2]=((CORBA_octet *)s)[1];
++ ((CORBA_octet *)d)[3]=((CORBA_octet *)s)[0];
++}
++
++static void CDR_swap8(void *d, void *s)
++{
++ ((CORBA_octet *)d)[0]=((CORBA_octet *)s)[7];
++ ((CORBA_octet *)d)[1]=((CORBA_octet *)s)[6];
++ ((CORBA_octet *)d)[2]=((CORBA_octet *)s)[5];
++ ((CORBA_octet *)d)[3]=((CORBA_octet *)s)[4];
++ ((CORBA_octet *)d)[4]=((CORBA_octet *)s)[3];
++ ((CORBA_octet *)d)[5]=((CORBA_octet *)s)[2];
++ ((CORBA_octet *)d)[6]=((CORBA_octet *)s)[1];
++ ((CORBA_octet *)d)[7]=((CORBA_octet *)s)[0];
++}
++
++static void CDR_swap16(void *d, void *s)
++{
++ ((CORBA_octet *)d)[0]=((CORBA_octet *)s)[15];
++ ((CORBA_octet *)d)[1]=((CORBA_octet *)s)[14];
++ ((CORBA_octet *)d)[2]=((CORBA_octet *)s)[13];
++ ((CORBA_octet *)d)[3]=((CORBA_octet *)s)[12];
++ ((CORBA_octet *)d)[4]=((CORBA_octet *)s)[11];
++ ((CORBA_octet *)d)[5]=((CORBA_octet *)s)[10];
++ ((CORBA_octet *)d)[6]=((CORBA_octet *)s)[9];
++ ((CORBA_octet *)d)[7]=((CORBA_octet *)s)[8];
++ ((CORBA_octet *)d)[8]=((CORBA_octet *)s)[7];
++ ((CORBA_octet *)d)[9]=((CORBA_octet *)s)[6];
++ ((CORBA_octet *)d)[10]=((CORBA_octet *)s)[5];
++ ((CORBA_octet *)d)[11]=((CORBA_octet *)s)[4];
++ ((CORBA_octet *)d)[12]=((CORBA_octet *)s)[3];
++ ((CORBA_octet *)d)[13]=((CORBA_octet *)s)[2];
++ ((CORBA_octet *)d)[14]=((CORBA_octet *)s)[1];
++ ((CORBA_octet *)d)[15]=((CORBA_octet *)s)[0];
++}
++#endif
++
++
++void CDR_put_short(CDR_Codec *codec, CORBA_short s)
++{
++ CDR_buffer_put2(codec, &s);
++}
++
++CORBA_boolean CDR_get_short(CDR_Codec *codec, CORBA_short *s)
++{
++ return CDR_buffer_get2(codec, s);
++}
++
++void CDR_put_ushort(CDR_Codec *codec, CORBA_unsigned_short us)
++{
++ CDR_buffer_put2(codec, &us);
++}
++
++CORBA_boolean CDR_get_ushort(CDR_Codec *codec, CORBA_unsigned_short *us)
++{
++ return CDR_buffer_get2(codec, us);
++}
++
++void CDR_put_long(CDR_Codec *codec, CORBA_long l)
++{
++ CDR_buffer_put4(codec, &l);
++}
++
++CORBA_boolean CDR_get_long(CDR_Codec *codec, CORBA_long *l)
++{
++ return CDR_buffer_get4(codec, l);
++}
++
++void CDR_put_ulong(CDR_Codec *codec, CORBA_unsigned_long ul)
++{
++ CDR_buffer_put4(codec, &ul);
++}
++
++CORBA_boolean CDR_get_ulong(CDR_Codec *codec, CORBA_unsigned_long *ul)
++{
++ return CDR_buffer_get4(codec, ul);
++}
++
++#ifdef HAVE_CORBA_LONG_LONG
++CORBA_boolean CDR_get_long_long(CDR_Codec *codec, CORBA_long_long *ul)
++{
++ return CDR_buffer_get8(codec, ul);
++}
++
++void CDR_put_long_long(CDR_Codec *codec, CORBA_long_long ll)
++{
++ CDR_buffer_put8(codec, &ll);
++}
++
++void CDR_put_ulong_long(CDR_Codec *codec, CORBA_unsigned_long_long ll)
++{
++ CDR_buffer_put8(codec, &ll);
++}
++
++CORBA_boolean CDR_get_ulong_long(CDR_Codec *codec, CORBA_unsigned_long_long *ull)
++{
++ return CDR_buffer_get8(codec, ull);
++}
++#endif
++
++void CDR_put_float(CDR_Codec *codec, CORBA_float f)
++{
++ CDR_buffer_put4(codec, &f);
++}
++
++void CDR_put_double(CDR_Codec *codec, CORBA_double d)
++{
++ CDR_buffer_put8(codec, &d);
++}
++
++void CDR_put_long_double(CDR_Codec *codec, CORBA_long_double ld)
++{
++ CDR_buffer_put16(codec, &ld);
++}
++
++void CDR_put_octet(CDR_Codec *codec, CORBA_octet datum)
++{
++ CDR_buffer_put(codec, &datum);
++}
++
++CORBA_boolean CDR_get_octet(CDR_Codec *codec, CORBA_octet *datum)
++{
++ return(CDR_buffer_get(codec, datum));
++}
++
++void CDR_put_octets(CDR_Codec *codec, void *data, unsigned long len)
++{
++ CDR_buffer_puts(codec, data, len);
++}
++
++void CDR_put_char(CDR_Codec *codec, CORBA_char c)
++{
++ CDR_buffer_put(codec, &c);
++}
++
++CORBA_boolean CDR_get_char(CDR_Codec *codec, CORBA_char *c)
++{
++ return CDR_buffer_get(codec, c);
++}
++
++void CDR_put_boolean(CDR_Codec *codec, CORBA_boolean datum)
++{
++ datum = datum&&1;
++ CDR_buffer_put(codec, &datum);
++}
++
++CORBA_boolean CDR_get_boolean(CDR_Codec *codec, CORBA_boolean *b)
++{
++ return CDR_buffer_get(codec, b);
++}
++
++void CDR_put_string(CDR_Codec *codec, const char *str)
++{
++ unsigned int len;
++
++ len=strlen(str)+1;
++
++ CDR_put_ulong(codec, len);
++ CDR_buffer_puts(codec, str, len);
++}
++
++CORBA_boolean CDR_get_string_static(CDR_Codec *codec,
++ CORBA_char **str)
++{
++ CORBA_unsigned_long len;
++
++ if(CDR_get_ulong(codec, &len)==CORBA_FALSE)
++ return CORBA_FALSE;
++
++ if((codec->rptr + len) > codec->buf_len)
++ return CORBA_FALSE;
++
++ *str = ((CORBA_char *)codec->buffer) + codec->rptr;
++
++ codec->rptr += len;
++
++ return CORBA_TRUE;
++}
++
++CORBA_boolean CDR_get_string(CDR_Codec *codec, CORBA_char **str)
++{
++ CORBA_unsigned_long len;
++
++ if(CDR_get_ulong(codec, &len)==CORBA_FALSE)
++ return(CORBA_FALSE);
++
++ if(len==0)
++ return(CORBA_FALSE);
++
++ *str=g_new(CORBA_char, len);
++
++ if(CDR_buffer_gets(codec, *str, len)==CORBA_FALSE) {
++ g_free(*str);
++ return(CORBA_FALSE);
++ }
++
++ if((*str)[len-1]!='\0') {
++ ORBit_Trace(TraceMod_CDR, TraceLevel_Notice, "CDR_get_string: string was not NULL-terminated, terminating it now\n");
++ (*str)[len-1]='\0';
++ }
++
++ return(CORBA_TRUE);
++}
++
++CORBA_boolean CDR_get_seq_begin(CDR_Codec *codec, CORBA_unsigned_long *ul)
++{
++ return(CDR_get_ulong(codec, ul));
++}
++
++CDR_Codec *CDR_codec_init_static(CDR_Codec *codec)
++{
++ memset(codec, 0, sizeof(CDR_Codec));
++
++ codec->host_endian = FLAG_ENDIANNESS;
++
++ return codec;
++}
++
++CDR_Codec *CDR_codec_init(void)
++{
++ CDR_Codec *new;
++
++ new=g_new0(CDR_Codec, 1);
++ CDR_codec_init_static(new);
++ new->release_buffer = CORBA_TRUE;
++
++ return(new);
++}
++
++void CDR_codec_free(CDR_Codec *codec)
++{
++ if(codec->release_buffer)
++ g_free(codec->buffer);
++
++ g_free(codec);
++}
+diff -urN linux-2.4.1/net/korbit/orb/cdr.h linux-2.4.1-korbit/net/korbit/orb/cdr.h
+--- linux-2.4.1/net/korbit/orb/cdr.h Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/orb/cdr.h Thu Feb 1 16:22:12 2001
+@@ -0,0 +1,83 @@
++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
++
++/*
++ * ORBit: A CORBA v2.2 ORB
++ *
++ * Copyright (C) 1998 Richard H. Porter
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Library General Public
++ * License as published by the Free Software Foundation; either
++ * version 2 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Library General Public License for more details.
++ *
++ * You should have received a copy of the GNU Library General Public
++ * License along with this library; if not, write to the Free
++ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Author: Dick Porter <dick@cymru.net>
++ *
++ */
++
++#ifndef _ORBIT_CDR_H_
++#define _ORBIT_CDR_H_
++
++#include "orbit_types.h"
++
++typedef enum {
++ BigEndian=0,
++ LittleEndian=1
++} CDR_Endianness;
++
++typedef struct {
++ CDR_Endianness host_endian;
++ CDR_Endianness data_endian;
++ CORBA_octet *buffer;
++ unsigned int buf_len;
++ unsigned int wptr, rptr;
++ CORBA_boolean readonly;
++ CORBA_boolean release_buffer;
++} CDR_Codec;
++
++#define HEXDIGIT(c) (isdigit((guchar)(c))?(c)-'0':tolower((guchar)(c))-'a'+10)
++#define HEXOCTET(a,b) ((HEXDIGIT((a)) << 4) | HEXDIGIT((b)))
++
++extern CDR_Codec *CDR_codec_init(void);
++extern CDR_Codec *CDR_codec_init_static(CDR_Codec *codec);
++extern void CDR_codec_free(CDR_Codec *);
++
++extern void CDR_put_short(CDR_Codec *codec, CORBA_short s);
++extern void CDR_put_ushort(CDR_Codec *codec, CORBA_unsigned_short us);
++extern void CDR_put_long(CDR_Codec *codec, CORBA_long l);
++extern void CDR_put_ulong(CDR_Codec *codec, CORBA_unsigned_long ul);
++#ifdef HAVE_CORBA_LONG_LONG
++extern void CDR_put_long_long(CDR_Codec *codec, CORBA_long_long ll);
++extern void CDR_put_ulong_long(CDR_Codec *codec, CORBA_unsigned_long_long ull);
++extern CORBA_boolean CDR_get_ulong_long(CDR_Codec *codec, CORBA_unsigned_long_long *ul);
++extern CORBA_boolean CDR_get_long_long(CDR_Codec *codec, CORBA_long_long *ul);
++#endif
++extern void CDR_put_float(CDR_Codec *codec, CORBA_float f);
++extern void CDR_put_double(CDR_Codec *codec, CORBA_double d);
++extern void CDR_put_long_double(CDR_Codec *codec, CORBA_long_double ld);
++extern void CDR_put_octet(CDR_Codec *codec, CORBA_octet datum);
++extern void CDR_put_octets(CDR_Codec *codec, void *data, unsigned long len);
++extern void CDR_put_char(CDR_Codec *codec, CORBA_char c);
++extern void CDR_put_boolean(CDR_Codec *codec, CORBA_boolean datum);
++extern void CDR_put_string(CDR_Codec *codec, const char *str);
++extern CORBA_boolean CDR_buffer_gets(CDR_Codec *codec, void *dest, const unsigned int len);
++extern CORBA_boolean CDR_get_short(CDR_Codec *codec, CORBA_short *us);
++extern CORBA_boolean CDR_get_ushort(CDR_Codec *codec, CORBA_unsigned_short *us);
++extern CORBA_boolean CDR_get_long(CDR_Codec *codec, CORBA_long *l);
++extern CORBA_boolean CDR_get_ulong(CDR_Codec *codec, CORBA_unsigned_long *ul);
++extern CORBA_boolean CDR_get_octet(CDR_Codec *codec, CORBA_octet *datum);
++extern CORBA_boolean CDR_get_boolean(CDR_Codec *codec, CORBA_boolean *b);
++extern CORBA_boolean CDR_get_char(CDR_Codec *codec, CORBA_char *c);
++extern CORBA_boolean CDR_get_string(CDR_Codec *codec, CORBA_char **str);
++extern CORBA_boolean CDR_get_string_static(CDR_Codec *codec, CORBA_char **str);
++extern CORBA_boolean CDR_get_seq_begin(CDR_Codec *codec, CORBA_unsigned_long *ul);
++
++#endif /* !_ORBIT_CDR_H_ */
+diff -urN linux-2.4.1/net/korbit/orb/corba_any.c linux-2.4.1-korbit/net/korbit/orb/corba_any.c
+--- linux-2.4.1/net/korbit/orb/corba_any.c Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/orb/corba_any.c Thu Feb 1 11:47:10 2001
+@@ -0,0 +1,914 @@
++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
++
++/*
++ * ORBit: A CORBA v2.2 ORB
++ *
++ * Copyright (C) 1998 Red Hat Software
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Library General Public
++ * License as published by the Free Software Foundation; either
++ * version 2 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Library General Public License for more details.
++ *
++ * You should have received a copy of the GNU Library General Public
++ * License along with this library; if not, write to the Free
++ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Author: Elliot Lee <sopwith@redhat.com>
++ *
++ */
++
++#include <config.h>
++#include <IIOP/IIOP.h>
++#include "orbit.h"
++
++#if 0
++#define CORBA_Object_release(x, y) ({ g_message(__FILE__ ":%d Releasing object %#x from %d", __LINE__, \
++x, ORBIT_ROOT_OBJECT(x)->refs); CORBA_Object_release(x, y); })
++#define CORBA_Object_duplicate(x, y) ({ g_message(__FILE__ ":%d Duping object %#x from %d", __LINE__, \
++x, ORBIT_ROOT_OBJECT(x)->refs); CORBA_Object_duplicate(x, y); })
++#endif
++
++gint
++ORBit_find_alignment(CORBA_TypeCode tc)
++{
++ gint retval = 1;
++ int i;
++
++ switch(tc->kind) {
++ case CORBA_tk_union:
++ retval = MAX(retval, ORBit_find_alignment(tc->discriminator));
++ case CORBA_tk_except:
++ case CORBA_tk_struct:
++#if ALIGNOF_CORBA_STRUCT > 1
++ retval = MAX(retval, ALIGNOF_CORBA_STRUCT);
++#endif
++ for(i = 0; i < tc->sub_parts; i++)
++ retval = MAX(retval, ORBit_find_alignment(tc->subtypes[i]));
++ return retval;
++ case CORBA_tk_ulong:
++ case CORBA_tk_long:
++ case CORBA_tk_enum:
++ return ALIGNOF_CORBA_LONG;
++ case CORBA_tk_ushort:
++ case CORBA_tk_short:
++ case CORBA_tk_wchar:
++ return ALIGNOF_CORBA_SHORT;
++ case CORBA_tk_longlong:
++ case CORBA_tk_ulonglong:
++ return ALIGNOF_CORBA_LONG_LONG;
++ case CORBA_tk_longdouble:
++ return ALIGNOF_CORBA_LONG_DOUBLE;
++ case CORBA_tk_float:
++ return ALIGNOF_CORBA_FLOAT;
++ case CORBA_tk_double:
++ return ALIGNOF_CORBA_DOUBLE;
++ case CORBA_tk_boolean:
++ case CORBA_tk_char:
++ case CORBA_tk_octet:
++ return ALIGNOF_CORBA_CHAR;
++ case CORBA_tk_string:
++ case CORBA_tk_wstring:
++ case CORBA_tk_TypeCode:
++ case CORBA_tk_objref:
++ return ALIGNOF_CORBA_POINTER;
++ case CORBA_tk_sequence:
++ case CORBA_tk_any:
++ return MAX(MAX(ALIGNOF_CORBA_LONG, ALIGNOF_CORBA_STRUCT), ALIGNOF_CORBA_POINTER);
++ case CORBA_tk_array:
++ case CORBA_tk_alias:
++ return ORBit_find_alignment(tc->subtypes[0]);
++ case CORBA_tk_fixed:
++ return MAX(ALIGNOF_CORBA_SHORT, ALIGNOF_CORBA_STRUCT);
++ default:
++ return 1;
++ }
++}
++
++static void
++ORBit_marshal_value(GIOPSendBuffer *buf,
++ gpointer *val,
++ CORBA_TypeCode tc,
++ ORBit_marshal_value_info *mi)
++{
++ CORBA_unsigned_long i, ulval;
++ gpointer subval;
++ ORBit_marshal_value_info submi;
++
++#if 0
++ g_message("Marshalling a %d value from %#x to offset %d",
++ tc->kind, (gulong)*val,
++ GIOP_MESSAGE_BUFFER(buf)->message_header.message_size);
++#endif
++
++ switch(tc->kind) {
++ case CORBA_tk_wchar:
++ case CORBA_tk_ushort:
++ case CORBA_tk_short:
++ *val = ALIGN_ADDRESS(*val, ALIGNOF_CORBA_SHORT);
++ giop_message_buffer_append_mem_a(GIOP_MESSAGE_BUFFER(buf), *val, sizeof(CORBA_short));
++ *val = ((guchar *)*val) + sizeof(CORBA_short);
++ break;
++ case CORBA_tk_enum:
++ case CORBA_tk_long:
++ case CORBA_tk_ulong:
++ *val = ALIGN_ADDRESS(*val, ALIGNOF_CORBA_LONG);
++ giop_message_buffer_append_mem_a(GIOP_MESSAGE_BUFFER(buf), *val, sizeof(CORBA_long));
++ *val = ((guchar *)*val) + sizeof(CORBA_long);
++ break;
++ case CORBA_tk_float:
++ *val = ALIGN_ADDRESS(*val, ALIGNOF_CORBA_FLOAT);
++ giop_message_buffer_append_mem_a(GIOP_MESSAGE_BUFFER(buf), *val, sizeof(CORBA_float));
++ *val = ((guchar *)*val) + sizeof(CORBA_float);
++ break;
++ case CORBA_tk_double:
++ *val = ALIGN_ADDRESS(*val, ALIGNOF_CORBA_DOUBLE);
++ giop_message_buffer_append_mem_a(GIOP_MESSAGE_BUFFER(buf), *val, sizeof(CORBA_double));
++ *val = ((guchar *)*val) + sizeof(CORBA_double);
++ break;
++ case CORBA_tk_boolean:
++ case CORBA_tk_char:
++ case CORBA_tk_octet:
++ giop_message_buffer_append_mem(GIOP_MESSAGE_BUFFER(buf), *val, sizeof(CORBA_octet));
++ *val = ((guchar *)*val) + sizeof(CORBA_octet);
++ break;
++ case CORBA_tk_any:
++ *val = ALIGN_ADDRESS(*val, MAX(ALIGNOF_CORBA_STRUCT, ALIGNOF_CORBA_POINTER));
++ ORBit_marshal_any(buf, *val);
++ *val = ((guchar *)*val) + sizeof(CORBA_any);
++ break;
++ case CORBA_tk_TypeCode:
++ *val = ALIGN_ADDRESS(*val, ALIGNOF_CORBA_POINTER);
++ ORBit_encode_CORBA_TypeCode(*val, buf);
++ *val = ((guchar *)*val) + sizeof(CORBA_TypeCode);
++ break;
++ case CORBA_tk_Principal:
++ *val = ALIGN_ADDRESS(*val,
++ MAX(MAX(ALIGNOF_CORBA_LONG, ALIGNOF_CORBA_STRUCT),
++ ALIGNOF_CORBA_POINTER));
++
++ ulval = *(CORBA_unsigned_long *)(*val);
++ giop_message_buffer_append_mem_a(GIOP_MESSAGE_BUFFER(buf), *val, sizeof(CORBA_unsigned_long));
++
++ giop_message_buffer_append_mem(GIOP_MESSAGE_BUFFER(buf),
++ *(char**)((char *)*val+sizeof(CORBA_unsigned_long)),
++ ulval);
++ *val = ((guchar *)*val) + sizeof(CORBA_Principal);
++ break;
++ case CORBA_tk_objref:
++ *val = ALIGN_ADDRESS(*val, ALIGNOF_CORBA_POINTER);
++ ORBit_marshal_object(buf, *val);
++ *val = ((guchar *)*val) + sizeof(CORBA_Object);
++ break;
++ case CORBA_tk_except:
++ case CORBA_tk_struct:
++ *val = ALIGN_ADDRESS(*val, ORBit_find_alignment(tc));
++ for(i = 0; i < tc->sub_parts; i++) {
++ ORBit_marshal_value(buf, val, tc->subtypes[i], mi);
++ }
++ break;
++ case CORBA_tk_union:
++ /* Basic algorithm:
++ marshal the discriminator
++ find out which value we want to use */
++ {
++ CORBA_TypeCode utc;
++
++ *val = ALIGN_ADDRESS(*val, ALIGNOF_CORBA_STRUCT);
++
++ utc = ORBit_get_union_tag(tc, val, TRUE);
++
++ *val = ALIGN_ADDRESS(*val, ALIGNOF_CORBA_STRUCT);
++
++ ORBit_marshal_value(buf, val, tc->discriminator, mi);
++ *val = ALIGN_ADDRESS(*val, ORBit_find_alignment(tc));
++ ORBit_marshal_value(buf, val, utc, mi);
++ }
++ break;
++ case CORBA_tk_wstring:
++ ulval = strlen(*(char **)*val) + 1;
++
++ *val = ALIGN_ADDRESS(*val, ALIGNOF_CORBA_POINTER);
++ giop_send_buffer_append_mem_indirect_a(buf,
++ &ulval,
++ sizeof(CORBA_unsigned_long));
++ giop_message_buffer_append_mem(GIOP_MESSAGE_BUFFER(buf), *(char **)*val, ulval);
++
++ *val = ((guchar *)*val) + sizeof(char *);
++ break;
++ case CORBA_tk_string:
++ ulval = strlen(*(char **)*val) + 1;
++
++ *val = ALIGN_ADDRESS(*val, ALIGNOF_CORBA_POINTER);
++
++ giop_send_buffer_append_mem_indirect_a(buf,
++ &ulval,
++ sizeof(CORBA_unsigned_long));
++ giop_message_buffer_append_mem(GIOP_MESSAGE_BUFFER(buf), *(char **)*val, ulval);
++
++ *val = ((guchar *)*val) + sizeof(char *);
++ break;
++ case CORBA_tk_sequence:
++ {
++ CORBA_sequence_octet *sval = *val;
++
++ *val = ALIGN_ADDRESS(*val,
++ MAX(MAX(ALIGNOF_CORBA_LONG, ALIGNOF_CORBA_STRUCT), ALIGNOF_CORBA_POINTER));
++
++ giop_message_buffer_append_mem_a(GIOP_MESSAGE_BUFFER(buf),
++ &sval->_length,
++ sizeof(sval->_length));
++
++ subval = sval->_buffer;
++
++ for(i = 0; i < sval->_length; i++)
++ ORBit_marshal_value(buf, &subval, tc->subtypes[0], mi);
++
++ *val = ((guchar *)*val) + sizeof(CORBA_sequence_octet);
++ }
++ break;
++ case CORBA_tk_array:
++ submi.alias_element_type = tc->subtypes[0];
++ for(i = 0; i < tc->length; i++) {
++ ORBit_marshal_value(buf, val, submi.alias_element_type, &submi);
++ *val = ALIGN_ADDRESS(*val, ORBit_find_alignment(tc->subtypes[0]));
++ }
++ break;
++ case CORBA_tk_alias:
++ submi.alias_element_type = tc->subtypes[0];
++ ORBit_marshal_value(buf, val, submi.alias_element_type, &submi);
++ break;
++ case CORBA_tk_longlong:
++ case CORBA_tk_ulonglong:
++ *val = ALIGN_ADDRESS(*val, ALIGNOF_CORBA_LONG_LONG);
++ giop_message_buffer_append_mem_a(GIOP_MESSAGE_BUFFER(buf), *val, sizeof(CORBA_long_long));
++ return /* *val + sizeof(CORBA_long_long)*/;
++ break;
++ case CORBA_tk_longdouble:
++ *val = ALIGN_ADDRESS(*val, ALIGNOF_CORBA_LONG_DOUBLE);
++ giop_message_buffer_append_mem_a(GIOP_MESSAGE_BUFFER(buf), *val, sizeof(CORBA_long_double));
++ return /* *val + sizeof(CORBA_long_double)*/;
++ break;
++ case CORBA_tk_fixed:
++ /* XXX todo */
++ g_error("CORBA_fixed NYI");
++
++ break;
++ case CORBA_tk_null:
++ case CORBA_tk_void:
++ break;
++ default:
++ g_error("Can't encode unknown type %d", tc->kind);
++ }
++}
++
++static glong ORBit_get_union_switch(CORBA_TypeCode tc, gpointer *val, gboolean update)
++{
++#ifdef __KORBIT__
++ glong retval = 0;
++#else
++ glong retval;
++#endif
++
++ switch(tc->kind) {
++ case CORBA_tk_ulong:
++ case CORBA_tk_long:
++ case CORBA_tk_enum:
++ retval = *(CORBA_long *)*val;
++ if(update) *val += sizeof(CORBA_long);
++ break;
++ case CORBA_tk_ushort:
++ case CORBA_tk_short:
++ retval = *(CORBA_short *)*val;
++ if(update) *val += sizeof(CORBA_short);
++ break;
++ case CORBA_tk_char:
++ case CORBA_tk_boolean:
++ case CORBA_tk_octet:
++ retval = *(CORBA_octet *)*val;
++ if(update) *val += sizeof(CORBA_char);
++ break;
++ case CORBA_tk_alias:
++ return ORBit_get_union_switch(tc->subtypes[0], val, update);
++ break;
++ default:
++ g_error("Wow, some nut has passed us a weird type[%d] as a union discriminator!", tc->kind);
++ }
++
++ return retval;
++}
++
++/* This function (and the one above it) exist for the
++ sole purpose of finding out which CORBA_TypeCode a union discriminator value
++ indicates.
++
++ If {update} is TRUE, {*val} will be advanced by the native size
++ of the descriminator type.
++
++ Hairy stuff.
++*/
++CORBA_TypeCode
++ORBit_get_union_tag(CORBA_TypeCode union_tc, gpointer *val, gboolean update)
++{
++ glong discrim_val, case_val;
++ int i;
++ CORBA_TypeCode retval = CORBA_OBJECT_NIL;
++
++ discrim_val = ORBit_get_union_switch(union_tc->discriminator, val, update);
++
++ for(i = 0; i < union_tc->sub_parts; i++) {
++ if(i == union_tc->default_index)
++ continue;
++
++ case_val = ORBit_get_union_switch(union_tc->sublabels[i]._type,
++ &union_tc->sublabels[i]._value, FALSE);
++ if(case_val == discrim_val) {
++ retval = union_tc->subtypes[i];
++ break;
++ }
++ }
++
++ if(retval)
++ return retval;
++ else if(union_tc->default_index >= 0)
++ return union_tc->subtypes[union_tc->default_index];
++ else {
++ return TC_null;
++ }
++}
++
++void
++ORBit_marshal_arg(GIOPSendBuffer *buf,
++ gpointer val,
++ CORBA_TypeCode tc)
++{
++ ORBit_marshal_value_info mi;
++
++ ORBit_marshal_value(buf, &val, tc, &mi);
++}
++
++
++void
++ORBit_marshal_any(GIOPSendBuffer *buf, const CORBA_any *val)
++{
++ ORBit_marshal_value_info mi;
++
++ gpointer mval = val->_value;
++
++ ORBit_encode_CORBA_TypeCode(val->_type, buf);
++
++ ORBit_marshal_value(buf, &mval, val->_type, &mi);
++}
++
++size_t
++ORBit_gather_alloc_info(CORBA_TypeCode tc)
++{
++ int i, n, align=1, prevalign, sum, prev;
++ size_t block_size;
++
++ switch(tc->kind) {
++ case CORBA_tk_long:
++ case CORBA_tk_ulong:
++ case CORBA_tk_enum:
++ return sizeof(CORBA_long);
++ break;
++ case CORBA_tk_short:
++ case CORBA_tk_ushort:
++ return sizeof(CORBA_short);
++ break;
++ case CORBA_tk_float:
++ return sizeof(CORBA_float);
++ break;
++ case CORBA_tk_double:
++ return sizeof(CORBA_double);
++ break;
++ case CORBA_tk_boolean:
++ case CORBA_tk_char:
++ case CORBA_tk_octet:
++ return sizeof(CORBA_octet);
++ break;
++ case CORBA_tk_any:
++ return sizeof(CORBA_any);
++ break;
++ case CORBA_tk_TypeCode:
++ return sizeof(CORBA_TypeCode);
++ break;
++ case CORBA_tk_Principal:
++ return sizeof(CORBA_Principal);
++ break;
++ case CORBA_tk_objref:
++ return sizeof(CORBA_Object);
++ break;
++ case CORBA_tk_except:
++ case CORBA_tk_struct:
++ sum = 0;
++ for(i = 0; i < tc->sub_parts; i++) {
++ sum = GPOINTER_TO_INT(ALIGN_ADDRESS(sum, ORBit_find_alignment(tc->subtypes[i])));
++ sum += ORBit_gather_alloc_info(tc->subtypes[i]);
++ }
++ sum = GPOINTER_TO_INT(ALIGN_ADDRESS(sum, ORBit_find_alignment(tc)));
++ return sum;
++ break;
++ case CORBA_tk_union:
++ sum = ORBit_gather_alloc_info(tc->discriminator);
++ n = -1;
++ align = 1;
++ for(prev = prevalign = i = 0; i < tc->sub_parts; i++) {
++ prevalign = align;
++ align = ORBit_find_alignment(tc->subtypes[i]);
++ if(align > prevalign)
++ n = i;
++
++ prev = MAX(prev, ORBit_gather_alloc_info(tc->subtypes[i]));
++ }
++ if(n >= 0)
++ sum = GPOINTER_TO_INT(ALIGN_ADDRESS(sum, ORBit_find_alignment(tc->subtypes[n])));
++ sum += prev;
++ sum = GPOINTER_TO_INT(ALIGN_ADDRESS(sum, ORBit_find_alignment(tc)));
++ return sum;
++ break;
++ case CORBA_tk_wstring:
++ case CORBA_tk_string:
++ return sizeof(char *);
++ break;
++ case CORBA_tk_sequence:
++ return sizeof(CORBA_sequence_octet);
++ break;
++ case CORBA_tk_array:
++ block_size = ORBit_gather_alloc_info(tc->subtypes[0]);
++ return block_size * tc->length;
++ break;
++ case CORBA_tk_alias:
++ return ORBit_gather_alloc_info(tc->subtypes[0]);
++ case CORBA_tk_longlong:
++ case CORBA_tk_ulonglong:
++ return sizeof(CORBA_long_long);
++ case CORBA_tk_longdouble:
++ return sizeof(CORBA_long_double);
++ case CORBA_tk_wchar:
++ return sizeof(CORBA_wchar);
++ case CORBA_tk_fixed:
++ return sizeof(CORBA_fixed_d_s);
++ default:
++ return 0;
++ }
++}
++
++/* to allocate a block, we need to know of any important data
++ contained in it.
++*/
++static gpointer
++ORBit_demarshal_allocate_mem(CORBA_TypeCode tc, gint nelements)
++{
++ size_t block_size;
++ gpointer retval = NULL;
++
++ if(!nelements) return retval;
++
++ block_size = ORBit_gather_alloc_info(tc);
++
++ if(block_size) {
++ retval = ORBit_alloc_2(block_size * nelements,
++ (ORBit_free_childvals)ORBit_free_via_TypeCode,
++ GINT_TO_POINTER(nelements),
++ sizeof(CORBA_TypeCode));
++
++ *(CORBA_TypeCode *)((char *)retval-sizeof(ORBit_mem_info)-sizeof(CORBA_TypeCode)) = (CORBA_TypeCode)CORBA_Object_duplicate((CORBA_Object)tc, NULL);
++ }
++
++ return retval;
++}
++
++#define DM_GET_ATOM(x, n) G_STMT_START{ GIOP_RECV_BUFFER(buf)->decoder(x, (GIOP_RECV_BUFFER(buf)->cur), n); GIOP_RECV_BUFFER(buf)->cur = ((guchar *)GIOP_RECV_BUFFER(buf)->cur) + n; }G_STMT_END
++
++static void
++ORBit_demarshal_value(GIOPRecvBuffer *buf,
++ gpointer *val,
++ CORBA_TypeCode tc,
++ gboolean dup_strings,
++ CORBA_ORB orb)
++{
++ CORBA_long i, n;
++
++#if 0
++ g_message("Demarshalling a %d value from offset %d into %#x",
++ tc->kind, buf->cur - buf->message_body, (gulong)*val);
++#endif
++
++ switch(tc->kind) {
++ case CORBA_tk_short:
++ case CORBA_tk_ushort:
++ case CORBA_tk_wchar:
++ *val = ALIGN_ADDRESS(*val, ALIGNOF_CORBA_SHORT);
++ buf->cur = ALIGN_ADDRESS(buf->cur, sizeof(CORBA_short));
++ DM_GET_ATOM(*val, sizeof(CORBA_short));
++ *val = ((guchar *)*val) + sizeof(CORBA_short);
++ break;
++ case CORBA_tk_long:
++ case CORBA_tk_ulong:
++ case CORBA_tk_enum:
++ *val = ALIGN_ADDRESS(*val, ALIGNOF_CORBA_LONG);
++ buf->cur = ALIGN_ADDRESS(buf->cur, sizeof(CORBA_long));
++ DM_GET_ATOM(*val, sizeof(CORBA_long));
++ *val = ((guchar *)*val) + sizeof(CORBA_long);
++ break;
++ case CORBA_tk_longlong:
++ case CORBA_tk_ulonglong:
++ *val = ALIGN_ADDRESS(*val, ALIGNOF_CORBA_LONG_LONG);
++ buf->cur = ALIGN_ADDRESS(buf->cur, sizeof(CORBA_long_long));
++ DM_GET_ATOM(*val, sizeof(CORBA_long_long));
++ *val = ((guchar *)*val) + sizeof(CORBA_long_long);
++ break;
++ case CORBA_tk_longdouble:
++ *val = ALIGN_ADDRESS(*val, ALIGNOF_CORBA_LONG_DOUBLE);
++ buf->cur = ALIGN_ADDRESS(buf->cur, sizeof(CORBA_long_double));
++ DM_GET_ATOM(*val, sizeof(CORBA_long_double));
++ *val = ((guchar *)*val) + sizeof(CORBA_long_double);
++ break;
++ case CORBA_tk_float:
++ *val = ALIGN_ADDRESS(*val, ALIGNOF_CORBA_FLOAT);
++ buf->cur = ALIGN_ADDRESS(buf->cur, sizeof(CORBA_float));
++ DM_GET_ATOM(*val, sizeof(CORBA_float));
++ *val = ((guchar *)*val) + sizeof(CORBA_float);
++ break;
++ case CORBA_tk_double:
++ *val = ALIGN_ADDRESS(*val, ALIGNOF_CORBA_DOUBLE);
++ buf->cur = ALIGN_ADDRESS(buf->cur, sizeof(CORBA_double));
++ DM_GET_ATOM(*val, sizeof(CORBA_double));
++ *val = ((guchar *)*val) + sizeof(CORBA_double);
++ break;
++ case CORBA_tk_boolean:
++ case CORBA_tk_char:
++ case CORBA_tk_octet:
++ DM_GET_ATOM(*val, sizeof(CORBA_octet));
++ *val = ((guchar *)*val) + sizeof(CORBA_octet);
++ break;
++ case CORBA_tk_any:
++ {
++ CORBA_any *decoded;
++
++ *val = ALIGN_ADDRESS(*val,
++ MAX(ALIGNOF_CORBA_LONG,
++ MAX(ALIGNOF_CORBA_POINTER, ALIGNOF_CORBA_STRUCT)));
++ decoded = *val;
++ decoded->_release = CORBA_FALSE;
++ ORBit_demarshal_any(buf, decoded, dup_strings, orb);
++ *val = ((guchar *)*val) + sizeof(CORBA_any);
++ }
++ break;
++ case CORBA_tk_TypeCode:
++ *val = ALIGN_ADDRESS(*val, ALIGNOF_CORBA_POINTER);
++ ORBit_decode_CORBA_TypeCode(*val, buf);
++ CORBA_Object_duplicate(*(CORBA_Object *)*val, NULL);
++ *val = ((guchar *)*val) + sizeof(CORBA_TypeCode);
++ break;
++ case CORBA_tk_Principal:
++ {
++ CORBA_Principal *p;
++
++ *val = ALIGN_ADDRESS(*val, MAX(ALIGNOF_CORBA_STRUCT,
++ MAX(ALIGNOF_CORBA_LONG, ALIGNOF_CORBA_POINTER)));
++
++ p = *val;
++ buf->cur = ALIGN_ADDRESS(buf->cur, sizeof(CORBA_long));
++ CORBA_sequence_set_release(p, dup_strings);
++ DM_GET_ATOM(&p->_length, sizeof(CORBA_long));
++ p->_buffer = ORBit_alloc(p->_length, NULL, GINT_TO_POINTER(1));
++ memcpy(p->_buffer, buf->cur, p->_length);
++ buf->cur = ((guchar *)buf->cur) + p->_length;
++ *val = ((guchar *)*val) + sizeof(CORBA_sequence_octet);
++ }
++ break;
++ case CORBA_tk_objref:
++ *val = ALIGN_ADDRESS(*val, ALIGNOF_CORBA_POINTER);
++ *(CORBA_Object *)*val = ORBit_demarshal_object(buf, orb);
++ *val = ((guchar *)*val) + sizeof(CORBA_Object);
++ break;
++ case CORBA_tk_except:
++ case CORBA_tk_struct:
++ *val = ALIGN_ADDRESS(*val, ORBit_find_alignment(tc));
++ for(i = 0; i < tc->sub_parts; i++) {
++ ORBit_demarshal_value(buf, val, tc->subtypes[i], dup_strings, orb);
++ }
++ break;
++ case CORBA_tk_union:
++ {
++ gpointer discrimptr;
++
++ discrimptr = *val = ALIGN_ADDRESS(*val, ORBit_find_alignment(tc));
++ ORBit_demarshal_value(buf, val, tc->discriminator, dup_strings, orb);
++ n = 1;
++ for(i = 0; i < tc->sub_parts; i++) {
++ n = MAX(n, ORBit_find_alignment(tc->subtypes[i]));
++ }
++ *val = ALIGN_ADDRESS(*val, n);
++ ORBit_demarshal_value(buf, val,
++ ORBit_get_union_tag(tc, &discrimptr, FALSE),
++ dup_strings, orb);
++ }
++ break;
++ case CORBA_tk_string:
++ case CORBA_tk_wstring:
++ *val = ALIGN_ADDRESS(*val, ALIGNOF_CORBA_POINTER);
++ buf->cur = ALIGN_ADDRESS(buf->cur, sizeof(CORBA_long));
++ DM_GET_ATOM(&i, sizeof(CORBA_long));
++ if(dup_strings)
++ *(char **)*val = CORBA_string_dup(buf->cur);
++ else
++ *(char **)*val = buf->cur;
++ *val = ((guchar *)*val) + sizeof(CORBA_char *);
++ buf->cur = (gpointer)((char *)buf->cur + i);
++ break;
++ case CORBA_tk_sequence:
++ {
++ CORBA_sequence_octet *p;
++ gpointer subval;
++
++ *val = ALIGN_ADDRESS(*val, MAX(ALIGNOF_CORBA_STRUCT,
++ MAX(ALIGNOF_CORBA_LONG, ALIGNOF_CORBA_POINTER)));
++ p = *val;
++ buf->cur = ALIGN_ADDRESS(buf->cur, sizeof(CORBA_long));
++ DM_GET_ATOM(&p->_length, sizeof(CORBA_long));
++ if(tc->subtypes[0]->kind == CORBA_tk_octet
++ || tc->subtypes[0]->kind == CORBA_tk_boolean
++ || tc->subtypes[0]->kind == CORBA_tk_char) {
++ /* This special-casing could be taken further to apply to
++ all atoms... */
++ p->_buffer = ORBit_alloc(p->_length, NULL, GINT_TO_POINTER(1));
++ memcpy(p->_buffer, buf->cur, p->_length);
++ buf->cur = ((guchar *)buf->cur) + p->_length;
++ } else {
++ p->_buffer = ORBit_demarshal_allocate_mem(tc->subtypes[0],
++ p->_length);
++ subval = p->_buffer;
++
++ for(i = 0; i < p->_length; i++)
++ ORBit_demarshal_value(buf, &subval,
++ tc->subtypes[0],
++ dup_strings,
++ orb);
++ }
++
++ *val = ((guchar *)*val) + sizeof(CORBA_sequence_octet);
++ }
++ break;
++ case CORBA_tk_array:
++ for(i = 0; i < tc->length; i++)
++ ORBit_demarshal_value(buf, val, tc->subtypes[0], dup_strings, orb);
++ break;
++ case CORBA_tk_alias:
++ ORBit_demarshal_value(buf, val, tc->subtypes[0], dup_strings, orb);
++ break;
++ case CORBA_tk_fixed:
++ g_error("CORBA_fixed NYI");
++ break;
++ default:
++ break;
++ }
++}
++
++gpointer
++ORBit_demarshal_arg(GIOPRecvBuffer *buf,
++ CORBA_TypeCode tc,
++ gboolean dup_strings,
++ CORBA_ORB orb)
++{
++ gpointer retval, val;
++
++ retval = val = ORBit_demarshal_allocate_mem(tc, 1);
++
++ ORBit_demarshal_value(buf, &val, tc, dup_strings, orb);
++
++ return retval;
++}
++
++void
++ORBit_demarshal_any(GIOPRecvBuffer *buf, CORBA_any *retval,
++ gboolean dup_strings,
++ CORBA_ORB orb)
++{
++ gpointer val;
++
++#if 0
++ /* I wish I knew whether this was correct or not. It breaks things like 'any anop();' for sure,
++ since we can't always initialize every single possible 'any' underneath _ORBIT_retval */
++ if(retval->_release)
++ CORBA_free(retval->_value);
++#endif
++
++ CORBA_any_set_release(retval, CORBA_TRUE);
++
++ ORBit_decode_CORBA_TypeCode(&retval->_type, buf);
++ CORBA_Object_duplicate((CORBA_Object)retval->_type, NULL);
++
++ val = retval->_value = ORBit_demarshal_allocate_mem(retval->_type, 1);
++ ORBit_demarshal_value(buf, &val, retval->_type, dup_strings, orb);
++}
++
++void
++_ORBit_copy_value(gpointer *val, gpointer *newval, CORBA_TypeCode tc)
++{
++ CORBA_long i;
++ gpointer pval1, pval2;
++
++ switch(tc->kind) {
++ case CORBA_tk_wchar:
++ case CORBA_tk_short:
++ case CORBA_tk_ushort:
++ *val = ALIGN_ADDRESS(*val, ALIGNOF_CORBA_SHORT);
++ *newval = ALIGN_ADDRESS(*newval, ALIGNOF_CORBA_SHORT);
++ *(CORBA_short *)*newval = *(CORBA_short *)*val;
++ *val = ((guchar *)*val) + sizeof(CORBA_short);
++ *newval = ((guchar *)*newval) + sizeof(CORBA_short);
++ break;
++ case CORBA_tk_enum:
++ case CORBA_tk_long:
++ case CORBA_tk_ulong:
++ *val = ALIGN_ADDRESS(*val, ALIGNOF_CORBA_LONG);
++ *newval = ALIGN_ADDRESS(*newval, ALIGNOF_CORBA_LONG);
++ *(CORBA_long *)*newval = *(CORBA_long *)*val;
++ *val = ((guchar *)*val) + sizeof(CORBA_long);
++ *newval = ((guchar *)*newval) + sizeof(CORBA_long);
++ break;
++ case CORBA_tk_longlong:
++ case CORBA_tk_ulonglong:
++ *val = ALIGN_ADDRESS(*val, ALIGNOF_CORBA_LONG_LONG);
++ *newval = ALIGN_ADDRESS(*newval, ALIGNOF_CORBA_LONG_LONG);
++ *(CORBA_long_long *)*newval = *(CORBA_long_long *)*val;
++ *val = ((guchar *)*val) + sizeof(CORBA_long_long);
++ *newval = ((guchar *)*newval) + sizeof(CORBA_long_long);
++ break;
++ case CORBA_tk_longdouble:
++ *val = ALIGN_ADDRESS(*val, ALIGNOF_CORBA_LONG_DOUBLE);
++ *newval = ALIGN_ADDRESS(*newval, ALIGNOF_CORBA_LONG_DOUBLE);
++ *(CORBA_long_double *)*newval = *(CORBA_long_double *)*val;
++ *val = ((guchar *)*val) + sizeof(CORBA_long_double);
++ *newval = ((guchar *)*newval) + sizeof(CORBA_long_double);
++ break;
++ case CORBA_tk_float:
++ *val = ALIGN_ADDRESS(*val, ALIGNOF_CORBA_FLOAT);
++ *newval = ALIGN_ADDRESS(*newval, ALIGNOF_CORBA_FLOAT);
++ *(CORBA_long *)*newval = *(CORBA_long *)*val;
++ *val = ((guchar *)*val) + sizeof(CORBA_float);
++ *newval = ((guchar *)*newval) + sizeof(CORBA_float);
++ break;
++ case CORBA_tk_double:
++ *val = ALIGN_ADDRESS(*val, ALIGNOF_CORBA_DOUBLE);
++ *newval = ALIGN_ADDRESS(*newval, ALIGNOF_CORBA_DOUBLE);
++ *(CORBA_double *)*newval = *(CORBA_double *)*val;
++ *val = ((guchar *)*val) + sizeof(CORBA_double);
++ *newval = ((guchar *)*newval) + sizeof(CORBA_double);
++ break;
++ case CORBA_tk_boolean:
++ case CORBA_tk_char:
++ case CORBA_tk_octet:
++ *(CORBA_octet *)*newval = *(CORBA_octet *)*val;
++ *val = ((guchar *)*val) + sizeof(CORBA_octet);
++ *newval = ((guchar *)*newval) + sizeof(CORBA_octet);
++ break;
++ case CORBA_tk_any:
++ {
++ CORBA_any *oldany, *newany;
++ *val = ALIGN_ADDRESS(*val, MAX(ALIGNOF_CORBA_STRUCT, ALIGNOF_CORBA_POINTER));
++ *newval = ALIGN_ADDRESS(*newval, MAX(ALIGNOF_CORBA_STRUCT, ALIGNOF_CORBA_POINTER));
++ oldany = *val;
++ newany = *newval;
++ newany->_type = (CORBA_TypeCode)CORBA_Object_duplicate((CORBA_Object)oldany->_type, NULL);
++ /* XXX are we supposed to do this even if oldany->_release
++ == FALSE? */
++ newany->_value = ORBit_copy_value(oldany->_value, oldany->_type);
++ newany->_release = CORBA_TRUE;
++ *val = ((guchar *)*val) + sizeof(CORBA_any);
++ *newval = ((guchar *)*newval) + sizeof(CORBA_any);
++ }
++ break;
++ case CORBA_tk_Principal:
++ *val = ALIGN_ADDRESS(*val,
++ MAX(MAX(ALIGNOF_CORBA_LONG,
++ ALIGNOF_CORBA_STRUCT),
++ ALIGNOF_CORBA_POINTER));
++ *newval = ALIGN_ADDRESS(*newval,
++ MAX(MAX(ALIGNOF_CORBA_LONG,
++ ALIGNOF_CORBA_STRUCT),
++ ALIGNOF_CORBA_POINTER));
++ *(CORBA_Principal *)*newval = *(CORBA_Principal *)*val;
++ ((CORBA_Principal *)*newval)->_buffer =
++ CORBA_octet_allocbuf(((CORBA_Principal *)*newval)->_length);
++ memcpy(((CORBA_Principal *)*newval)->_buffer,
++ ((CORBA_Principal *)*val)->_buffer,
++ ((CORBA_Principal *)*val)->_length);
++ *val = ((guchar *)*val) + sizeof(CORBA_Principal);
++ *newval = ((guchar *)*newval) + sizeof(CORBA_Principal);
++ break;
++ case CORBA_tk_TypeCode:
++ case CORBA_tk_objref:
++ *val = ALIGN_ADDRESS(*val, ALIGNOF_CORBA_POINTER);
++ *newval = ALIGN_ADDRESS(*newval, ALIGNOF_CORBA_POINTER);
++ *(CORBA_Object *)*newval = CORBA_Object_duplicate(*(CORBA_Object *)*val,
++ NULL);
++ *val = ((guchar *)*val) + sizeof(CORBA_Object);
++ *newval = ((guchar *)*newval) + sizeof(CORBA_Object);
++ break;
++ case CORBA_tk_struct:
++ case CORBA_tk_except:
++ *val = ALIGN_ADDRESS(*val, ORBit_find_alignment(tc));
++ *newval = ALIGN_ADDRESS(*newval, ORBit_find_alignment(tc));
++ for(i = 0; i < tc->sub_parts; i++) {
++ _ORBit_copy_value(val, newval, tc->subtypes[i]);
++ }
++ break;
++ case CORBA_tk_union:
++ {
++ CORBA_TypeCode utc = ORBit_get_union_tag(tc, val, FALSE);
++ gint union_align = ORBit_find_alignment(tc);
++ size_t union_size = ORBit_gather_alloc_info(tc);
++
++ /* need to advance val,newval by size of union, not just
++ * current tagged field within it */
++ pval1 = *val = ALIGN_ADDRESS(*val, ALIGNOF_CORBA_STRUCT);
++ pval2 = *newval = ALIGN_ADDRESS(*newval, ALIGNOF_CORBA_STRUCT);
++ _ORBit_copy_value(&pval1, &pval2, tc->discriminator);
++ pval1 = ALIGN_ADDRESS(pval1, union_align);
++ pval2 = ALIGN_ADDRESS(pval2, union_align);
++ _ORBit_copy_value(&pval1, &pval2, utc);
++ *val = ((guchar *)*val) + union_size;
++ *newval = ((guchar *)*newval) + union_size;
++ }
++ break;
++ case CORBA_tk_wstring:
++ case CORBA_tk_string:
++ *val = ALIGN_ADDRESS(*val, ALIGNOF_CORBA_POINTER);
++ *newval = ALIGN_ADDRESS(*newval, ALIGNOF_CORBA_POINTER);
++
++ *(CORBA_char **)*newval = CORBA_string_dup(*(CORBA_char **)*val);
++ *val = ((guchar *)*val) + sizeof(CORBA_char *);
++ *newval = ((guchar *)*newval) + sizeof(CORBA_char *);
++ break;
++ case CORBA_tk_sequence:
++ *val = ALIGN_ADDRESS(*val,
++ MAX(MAX(ALIGNOF_CORBA_LONG,
++ ALIGNOF_CORBA_STRUCT),
++ ALIGNOF_CORBA_POINTER));
++ *newval = ALIGN_ADDRESS(*newval,
++ MAX(MAX(ALIGNOF_CORBA_LONG,
++ ALIGNOF_CORBA_STRUCT),
++ ALIGNOF_CORBA_POINTER));
++ ((CORBA_Principal *)*newval)->_release = CORBA_TRUE;
++ ((CORBA_Principal *)*newval)->_length =
++ ((CORBA_Principal *)*newval)->_maximum =
++ ((CORBA_Principal *)*val)->_length;
++ ((CORBA_Principal *)*newval)->_buffer = pval2 =
++ ORBit_demarshal_allocate_mem(tc->subtypes[0],
++ ((CORBA_Principal *)*val)->_length);
++ pval1 = ((CORBA_Principal *)*val)->_buffer;
++
++ for(i = 0; i < ((CORBA_Principal *)*newval)->_length; i++) {
++ _ORBit_copy_value(&pval1, &pval2, tc->subtypes[0]);
++ }
++ *val = ((guchar *)*val) + sizeof(CORBA_sequence_octet);
++ *newval = ((guchar *)*newval) + sizeof(CORBA_sequence_octet);
++ break;
++ case CORBA_tk_array:
++ for(i = 0; i < tc->length; i++) {
++ _ORBit_copy_value(val, newval, tc->subtypes[0]);
++ }
++ break;
++ case CORBA_tk_alias:
++ _ORBit_copy_value(val, newval, tc->subtypes[0]);
++ break;
++ case CORBA_tk_fixed:
++ g_error("CORBA_fixed NYI!");
++ break;
++ case CORBA_tk_void:
++ case CORBA_tk_null:
++ *val = NULL;
++ break;
++ default:
++ g_error("Can't handle copy of value kind %d", tc->kind);
++ }
++}
++
++gpointer
++ORBit_copy_value(gpointer value, CORBA_TypeCode tc)
++{
++ gpointer retval, newval;
++
++ retval = newval = ORBit_demarshal_allocate_mem(tc, 1);
++ _ORBit_copy_value(&value, &newval, tc);
++
++ return retval;
++}
++
++void
++CORBA_any__copy(CORBA_any *out, CORBA_any *in)
++{
++ out->_type = (CORBA_TypeCode)CORBA_Object_duplicate((CORBA_Object)in->_type,
++ NULL);
++ out->_value = ORBit_copy_value(in->_value, in->_type);
++ out->_release = CORBA_TRUE;
++}
+diff -urN linux-2.4.1/net/korbit/orb/corba_any.h linux-2.4.1-korbit/net/korbit/orb/corba_any.h
+--- linux-2.4.1/net/korbit/orb/corba_any.h Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/orb/corba_any.h Thu Feb 1 16:20:50 2001
+@@ -0,0 +1,45 @@
++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
++
++/*
++ * ORBit: A CORBA v2.2 ORB
++ *
++ * Copyright (C) 1998 Richard H. Porter
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Library General Public
++ * License as published by the Free Software Foundation; either
++ * version 2 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Library General Public License for more details.
++ *
++ * You should have received a copy of the GNU Library General Public
++ * License along with this library; if not, write to the Free
++ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Author: Dick Porter <dick@cymru.net>
++ *
++ */
++
++#ifndef _ORBIT_CORBA_ANY_H_
++#define _ORBIT_CORBA_ANY_H_
++
++#include "orbit_types.h"
++#include "corba_typecode.h"
++
++#include <unistd.h>
++
++typedef struct CORBA_any_type CORBA_any;
++
++size_t ORBit_gather_alloc_info(CORBA_TypeCode tc);
++gint ORBit_find_alignment(CORBA_TypeCode tc);
++CORBA_TypeCode ORBit_get_union_tag(CORBA_TypeCode union_tc,
++ gpointer *val, gboolean update);
++gpointer ORBit_copy_value(gpointer value, CORBA_TypeCode tc);
++void _ORBit_copy_value(gpointer *val, gpointer *newval, CORBA_TypeCode tc);
++
++void CORBA_any__copy(CORBA_any *out, CORBA_any *in);
++
++#endif /* !_ORBIT_CORBA_ANY_H_ */
+diff -urN linux-2.4.1/net/korbit/orb/corba_any_proto.h linux-2.4.1-korbit/net/korbit/orb/corba_any_proto.h
+--- linux-2.4.1/net/korbit/orb/corba_any_proto.h Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/orb/corba_any_proto.h Thu Feb 1 11:47:11 2001
+@@ -0,0 +1,16 @@
++#ifndef _ORBIT_CORBA_ANY_PROTO_H_
++#define _ORBIT_CORBA_ANY_PROTO_H_
++
++void ORBit_marshal_arg(GIOPSendBuffer *buf,
++ gpointer val,
++ CORBA_TypeCode tc);
++void ORBit_marshal_any(GIOPSendBuffer *buf, const CORBA_any *val);
++gpointer ORBit_demarshal_arg(GIOPRecvBuffer *buf,
++ CORBA_TypeCode tc,
++ gboolean dup_strings,
++ CORBA_ORB orb);
++void ORBit_demarshal_any(GIOPRecvBuffer *buf, CORBA_any *retval,
++ gboolean dup_strings,
++ CORBA_ORB orb);
++
++#endif /* !_ORBIT_CORBA_ANY_PROTO_H_ */
+diff -urN linux-2.4.1/net/korbit/orb/corba_any_type.h linux-2.4.1-korbit/net/korbit/orb/corba_any_type.h
+--- linux-2.4.1/net/korbit/orb/corba_any_type.h Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/orb/corba_any_type.h Thu Feb 1 16:20:50 2001
+@@ -0,0 +1,48 @@
++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
++
++/*
++ * ORBit: A CORBA v2.2 ORB
++ *
++ * Copyright (C) 1998 Richard H. Porter
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Library General Public
++ * License as published by the Free Software Foundation; either
++ * version 2 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Library General Public License for more details.
++ *
++ * You should have received a copy of the GNU Library General Public
++ * License along with this library; if not, write to the Free
++ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Author: Dick Porter <dick@acm.org>
++ *
++ */
++
++#ifndef _ORBIT_CORBA_ANY_TYPE_H_
++#define _ORBIT_CORBA_ANY_TYPE_H_
++
++#include "corba_any.h"
++#include "corba_typecode.h"
++
++struct CORBA_any_type {
++ CORBA_TypeCode _type;
++ gpointer _value;
++ CORBA_boolean _release;
++};
++
++typedef struct ORBit_marshal_value_info_struct {
++ CORBA_TypeCode alias_element_type;
++} ORBit_marshal_value_info;
++
++#define CORBA_ANYFLAGS_RELEASE 1
++
++
++#endif /* !_ORBIT_CORBA_ANY_TYPE_H_ */
++
++
++
+diff -urN linux-2.4.1/net/korbit/orb/corba_basic_sequences_type.h linux-2.4.1-korbit/net/korbit/orb/corba_basic_sequences_type.h
+--- linux-2.4.1/net/korbit/orb/corba_basic_sequences_type.h Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/orb/corba_basic_sequences_type.h Thu Feb 1 11:47:11 2001
+@@ -0,0 +1,43 @@
++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
++
++/*
++ * ORBit: A CORBA v2.2 ORB
++ *
++ * Copyright (C) 1998 Richard H. Porter
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Library General Public
++ * License as published by the Free Software Foundation; either
++ * version 2 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Library General Public License for more details.
++ *
++ * You should have received a copy of the GNU Library General Public
++ * License along with this library; if not, write to the Free
++ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Author: Dick Porter <dick@cymru.net>
++ *
++ */
++
++#ifndef _ORBIT_CORBA_BASIC_SEQUENCES_TYPE_H_
++#define _ORBIT_CORBA_BASIC_SEQUENCES_TYPE_H_
++
++#include <ORBitutil/basic_types.h>
++
++#ifndef _CORBA_sequence_octet_defined
++#define _CORBA_sequence_octet_defined 1
++
++typedef struct CORBA_sequence_octet_struct {
++ CORBA_unsigned_long _maximum;
++ CORBA_unsigned_long _length;
++ CORBA_octet *_buffer;
++ CORBA_boolean _release;
++} CORBA_sequence_octet;
++#endif /* !_CORBA_sequence_octet_defined */
++
++#include <orb/corba_sequences.h>
++#endif /* !_ORBIT_CORBA_BASIC_SEQUENCES_TYPE_H_ */
+diff -urN linux-2.4.1/net/korbit/orb/corba_context.c linux-2.4.1-korbit/net/korbit/orb/corba_context.c
+--- linux-2.4.1/net/korbit/orb/corba_context.c Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/orb/corba_context.c Thu Feb 1 11:47:11 2001
+@@ -0,0 +1,390 @@
++#include "orb/orbit.h"
++
++#define o_return_val_if_fail(expr, val) if(!(expr)) { CORBA_exception_set_system(ev, ex_CORBA_BAD_PARAM, CORBA_COMPLETED_NO); return (val); }
++#define o_return_if_fail(expr) if(!(expr)) { CORBA_exception_set_system(ev, ex_CORBA_BAD_PARAM, CORBA_COMPLETED_NO); return; }
++
++static gboolean
++free_entry(gpointer key, gpointer value, gpointer user_data)
++{
++ g_free(key);
++ g_free(value);
++
++ return TRUE;
++}
++
++static void
++ORBit_Context_release(CORBA_Context ctx, CORBA_Environment *ev);
++
++static gboolean
++free_child(gpointer value, gpointer user_data)
++{
++ CORBA_Context ctx = value;
++
++ ORBIT_ROOT_OBJECT(ctx)->refs = 1;
++ ctx->parent_ctx = CORBA_OBJECT_NIL;
++ ORBit_Context_release(ctx, NULL);
++
++ return TRUE;
++}
++
++static void
++ORBit_Context_release(CORBA_Context ctx,
++ CORBA_Environment *ev)
++{
++ ORBIT_ROOT_OBJECT_UNREF(ctx);
++
++ if(ORBIT_ROOT_OBJECT(ctx)->refs <= 0) {
++ if(ctx->children) {
++ g_slist_foreach(ctx->children, (GFunc)free_child, ctx);
++ g_slist_free(ctx->children);
++ }
++
++ if(ctx->mappings) {
++ g_hash_table_foreach_remove(ctx->mappings, free_entry, ctx);
++ g_hash_table_destroy(ctx->mappings);
++ }
++
++ if(ctx->parent_ctx != CORBA_OBJECT_NIL)
++ ctx->parent_ctx->children = g_slist_remove(ctx->parent_ctx->children, ctx->the_name);
++
++ g_free(ctx->the_name);
++
++ g_free(ctx);
++ }
++}
++
++static const ORBit_RootObject_Interface CORBA_Context_epv =
++{
++ (void (*)(gpointer, CORBA_Environment *))ORBit_Context_release,
++};
++
++static CORBA_Context
++CORBA_Context_new(CORBA_Context parent, const char *name, CORBA_Environment *ev)
++{
++ CORBA_Context retval;
++
++ retval = g_new0(struct CORBA_Context_type, 1);
++
++ ORBit_pseudo_object_init(ORBIT_PSEUDO_OBJECT(retval), ORBIT_PSEUDO_CONTEXT, ev);
++
++ ORBIT_ROOT_OBJECT(retval)->refs = 0;
++ ORBit_RootObject_set_interface(ORBIT_ROOT_OBJECT(retval), (gpointer)&CORBA_Context_epv, ev);
++
++ if(name)
++ retval->the_name = g_strdup(name);
++
++ retval->parent_ctx = parent;
++ if(parent)
++ parent->children = g_slist_prepend(parent->children, retval);
++
++ return retval;
++}
++
++/* Section 5.6.1 */
++CORBA_Status CORBA_ORB_get_default_context(CORBA_ORB orb, CORBA_Context *ctx, CORBA_Environment *ev)
++{
++ g_return_if_fail(ev != NULL);
++ o_return_if_fail(orb && ctx);
++
++ if(!orb->default_ctx)
++ orb->default_ctx = CORBA_Context_new(CORBA_OBJECT_NIL, NULL, ev);
++
++ *ctx = (CORBA_Context)CORBA_Object_duplicate((CORBA_Object)orb->default_ctx, ev);
++}
++
++/********* XXX todo - CORBA_Context support */
++CORBA_Status CORBA_Context_set_one_value(CORBA_Context ctx, CORBA_Identifier prop_name, char *value, CORBA_Environment *ev)
++{
++ gpointer old_nom, old_value;
++ g_return_if_fail(ev != NULL);
++ o_return_if_fail(ctx && prop_name && value);
++
++ if(!ctx->mappings)
++ ctx->mappings = g_hash_table_new(g_str_hash, g_str_equal);
++
++ if(g_hash_table_lookup_extended(ctx->mappings, prop_name, &old_nom, &old_value)) {
++ g_free(old_nom);
++ g_free(old_value);
++ }
++
++ g_hash_table_insert(ctx->mappings, g_strdup(prop_name), g_strdup(value));
++}
++
++/* Section 5.6.3 */
++CORBA_Status CORBA_Context_set_values(CORBA_Context ctx, CORBA_NVList *values, CORBA_Environment *ev)
++{
++ int i;
++
++ for(i = 0; i < values->list->len; i++) {
++ CORBA_NamedValue *nvp;
++
++ nvp = ((CORBA_NamedValue *)values->list->data) + i;
++
++ g_assert(nvp->argument._type == TC_string);
++
++ CORBA_Context_set_one_value(ctx, nvp->name, nvp->argument._value, ev);
++ }
++}
++
++/* Section 5.6.4 */
++
++typedef struct {
++ CORBA_Context ctx;
++ CORBA_Identifier prop_name;
++ CORBA_NVList *values;
++ CORBA_Environment *ev;
++ int len;
++} CTXSearchInfo;
++
++static gboolean
++list_has_key(CORBA_NVList *list, const char *key)
++{
++ int i;
++
++ for(i = 0; i < list->list->len; i++) {
++ CORBA_NamedValue *nvp;
++
++ nvp = ((CORBA_NamedValue *)list->list->data) + i;
++
++ if(!strcmp(nvp->name, key))
++ return TRUE;
++ }
++
++ return FALSE;
++}
++
++static void
++search_props(gpointer key, gpointer value, CTXSearchInfo *csi)
++{
++ if(strncmp(key, csi->prop_name, csi->len))
++ return;
++
++ if(list_has_key(csi->values, key))
++ return;
++
++ CORBA_NVList_add_item(csi->values, key, TC_string, &value, strlen(value) + 1, CORBA_IN_COPY_VALUE, NULL);
++}
++
++static void
++ctx_get_values(CORBA_Context ctx, CORBA_Flags op_flags,
++ CORBA_Identifier prop_name, CORBA_NVList **values,
++ gint is_wc,
++ CORBA_Environment *ev)
++{
++ gboolean go_up = FALSE;
++
++ if(is_wc >= 0) {
++ CTXSearchInfo csi;
++
++ csi.ctx = ctx;
++ csi.prop_name = prop_name;
++ csi.values = *values;
++ csi.ev = ev;
++ csi.len = is_wc;
++
++ if(ctx->mappings)
++ g_hash_table_foreach(ctx->mappings, (GHFunc)search_props, &csi);
++
++ go_up = TRUE;
++
++ } else {
++ char *val = NULL;
++
++ if(ctx->mappings)
++ val = g_hash_table_lookup(ctx->mappings, prop_name);
++
++ if(val)
++ CORBA_NVList_add_item(*values, prop_name, TC_string, &val, strlen(val) + 1, CORBA_IN_COPY_VALUE, ev);
++ else
++ go_up = TRUE;
++ }
++
++ if(go_up
++ && ctx->parent_ctx
++ && !(op_flags & CORBA_CTX_RESTRICT_SCOPE))
++ ctx_get_values(ctx->parent_ctx, op_flags, prop_name, values, is_wc, ev);
++}
++
++CORBA_Status CORBA_Context_get_values(CORBA_Context ctx,
++ CORBA_Identifier start_scope,
++ CORBA_Flags op_flags,
++ CORBA_Identifier prop_name,
++ CORBA_NVList **values,
++ CORBA_Environment *ev)
++{
++ char *ctmp;
++ int wc_pos;
++
++ CORBA_ORB_create_list(CORBA_OBJECT_NIL, 0, values, ev);
++
++ if(start_scope && *start_scope) {
++ while(ctx && (!ctx->the_name || strcmp(ctx->the_name, start_scope)))
++ ctx = ctx->parent_ctx;
++
++ if(!ctx) {
++ CORBA_exception_set_system(ev, ex_CORBA_INV_IDENT, CORBA_COMPLETED_NO);
++ return;
++ }
++ }
++
++ ctmp = strchr(prop_name, '*');
++ if(ctmp)
++ wc_pos = ctmp - prop_name;
++ else
++ wc_pos = -1;
++
++ CORBA_ORB_create_list(CORBA_OBJECT_NIL, 0, values, ev);
++
++ ctx_get_values(ctx, op_flags, prop_name, values, (prop_name[strlen(prop_name) - 1] == '*'), ev);
++
++ if((*values)->list->len == 0)
++ {
++ CORBA_NVList_free(*values, ev);
++ *values = NULL;
++ CORBA_exception_set_system(ev, ex_CORBA_UNKNOWN, CORBA_COMPLETED_NO);
++ }
++}
++
++/* Section 5.6.5 */
++static void
++delete_props(gpointer key, gpointer value, CTXSearchInfo *csi)
++{
++ if(strncmp(key, csi->prop_name, csi->len))
++ return;
++
++ g_hash_table_remove(csi->ctx->mappings, key);
++ g_free(key);
++ g_free(value);
++}
++
++CORBA_Status CORBA_Context_delete_values(CORBA_Context ctx, CORBA_Identifier prop_name, CORBA_Environment *ev)
++{
++ char *ctmp;
++ int wc_pos;
++
++ if(!ctx->mappings)
++ return;
++
++ ctmp = strchr(prop_name, '*');
++ if(ctmp)
++ wc_pos = ctmp - prop_name;
++ else
++ wc_pos = -1;
++
++ if(wc_pos >= 0) {
++ CTXSearchInfo csi;
++
++ memset(&csi, 0, sizeof(csi));
++ csi.ctx = ctx;
++ csi.prop_name = prop_name;
++ csi.ev = ev;
++ csi.len = wc_pos;
++
++ g_hash_table_foreach(ctx->mappings, (GHFunc)delete_props, &csi);
++ } else {
++ gpointer old_nom, old_value;
++
++ if(g_hash_table_lookup_extended(ctx->mappings, prop_name, &old_nom, &old_value)) {
++ g_free(old_nom);
++ g_free(old_value);
++ }
++ }
++}
++
++/* Section 5.6.6 */
++CORBA_Status CORBA_Context_create_child(CORBA_Context ctx, CORBA_Identifier ctx_name, CORBA_Context *child_ctx, CORBA_Environment *ev)
++{
++ *child_ctx = CORBA_Context_new(ctx, ctx_name, ev);
++}
++
++/* Section 5.6.7 */
++CORBA_Status CORBA_Context_delete(CORBA_Context ctx, CORBA_Flags del_flags, CORBA_Environment *ev)
++{
++ if((del_flags & CORBA_CTX_DELETE_DESCENDENTS)
++ || !ctx->children)
++ free_child(ctx, NULL);
++}
++
++void
++ORBit_Context_marshal(CORBA_Context ctx, const ORBit_ContextMarshalItem *mlist, CORBA_unsigned_long nitems, GIOPSendBuffer *buf)
++{
++ int i;
++ CORBA_unsigned_long *real_nitems, ltmp;
++
++ real_nitems = giop_send_buffer_append_mem_indirect_a(buf, &nitems, sizeof(nitems));
++ if(!ctx->mappings) {
++ *real_nitems = 0;
++ return;
++ }
++
++ for(*real_nitems = i = 0; i < nitems; i++) {
++ char *value;
++
++ value = g_hash_table_lookup(ctx->mappings, mlist[i].str);
++ if(!value)
++ continue;
++
++ /* Key */
++ giop_message_buffer_append_mem_a(GIOP_MESSAGE_BUFFER(buf), &(mlist[i].len), sizeof(mlist[i].len));
++ giop_message_buffer_append_mem(GIOP_MESSAGE_BUFFER(buf), mlist[i].str, mlist[i].len);
++ (*real_nitems)++;
++
++ /* Value */
++ ltmp = strlen(value) + 1;
++ giop_send_buffer_append_mem_indirect_a(buf, &ltmp, sizeof(ltmp));
++ giop_message_buffer_append_mem(GIOP_MESSAGE_BUFFER(buf), value, ltmp);
++ (*real_nitems)++;
++ }
++}
++
++#define GET_ATOM(x) G_STMT_START{ GIOP_RECV_BUFFER(recv_buffer)->decoder(&x, (GIOP_RECV_BUFFER(recv_buffer)->cur), sizeof(x)); \
++GIOP_RECV_BUFFER(recv_buffer)->cur = ((guchar *)GIOP_RECV_BUFFER(recv_buffer)->cur) + sizeof(x); \
++}G_STMT_END
++#define ALIGNFOR(x) recv_buffer->cur = ALIGN_ADDRESS(recv_buffer->cur, sizeof(x))
++
++void
++ORBit_Context_demarshal(CORBA_Context parent, CORBA_Context initme, GIOPRecvBuffer *recv_buffer)
++{
++ CORBA_unsigned_long nstrings, keylen, vallen, i;
++ char *key, *value;
++
++ memset(initme, 0, sizeof(struct CORBA_Context_type));
++ ORBIT_ROOT_OBJECT(initme)->refs = -1;
++
++ initme->parent_ctx = parent;
++
++ ALIGNFOR(nstrings);
++ GET_ATOM(nstrings);
++
++ if(nstrings)
++ initme->mappings = g_hash_table_new(g_str_hash, g_str_equal);
++ else
++ return;
++
++ g_hash_table_freeze(initme->mappings);
++ for(i = 0; i < nstrings; ) {
++ ALIGNFOR(keylen);
++ GET_ATOM(keylen);
++ key = recv_buffer->cur;
++ recv_buffer->cur = ((char *)recv_buffer->cur) + keylen;
++ i++;
++
++ if(i >= nstrings)
++ break;
++
++ ALIGNFOR(vallen);
++ GET_ATOM(vallen);
++ value = recv_buffer->cur;
++ recv_buffer->cur = ((char *)recv_buffer->cur) + vallen;
++ i++;
++
++ g_hash_table_insert(initme->mappings, key, value);
++ }
++ g_hash_table_thaw(initme->mappings);
++}
++
++void
++ORBit_Context_server_free(CORBA_Context ctx)
++{
++ g_hash_table_destroy(ctx->mappings);
++}
+diff -urN linux-2.4.1/net/korbit/orb/corba_context.h linux-2.4.1-korbit/net/korbit/orb/corba_context.h
+--- linux-2.4.1/net/korbit/orb/corba_context.h Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/orb/corba_context.h Thu Feb 1 16:20:50 2001
+@@ -0,0 +1,65 @@
++#ifndef CORBA_CONTEXT_H
++#define CORBA_CONTEXT_H 1
++
++#include "orbit_object_type.h"
++#include "orbit_object.h"
++
++typedef struct {
++ CORBA_unsigned_long len;
++ const CORBA_char *str;
++} ORBit_ContextMarshalItem;
++
++typedef struct CORBA_Context_type *CORBA_Context;
++
++struct CORBA_Context_type {
++ struct ORBit_PseudoObject_struct parent;
++ GHashTable *mappings;
++ GSList *children;
++
++ char *the_name;
++
++ CORBA_Context parent_ctx;
++};
++
++
++extern CORBA_Status CORBA_Context_set_one_value(
++ CORBA_Context ctx,
++ CORBA_Identifier prop_name,
++ char *value,
++ CORBA_Environment *ev);
++
++extern CORBA_Status CORBA_Context_set_values(
++ CORBA_Context ctx,
++ CORBA_NVList *values,
++ CORBA_Environment *ev);
++
++extern CORBA_Status CORBA_Context_get_values(
++ CORBA_Context ctx,
++ CORBA_Identifier start_scope,
++ CORBA_Flags op_flags,
++ CORBA_Identifier prop_name,
++ CORBA_NVList **values,
++ CORBA_Environment *ev);
++
++extern CORBA_Status CORBA_Context_delete_values(
++ CORBA_Context ctx,
++ CORBA_Identifier prop_name,
++ CORBA_Environment *ev);
++
++extern CORBA_Status CORBA_Context_create_child(
++ CORBA_Context ctx,
++ CORBA_Identifier ctx_name,
++ CORBA_Context *child_ctx,
++ CORBA_Environment *ev);
++
++extern CORBA_Status CORBA_Context_delete(
++ CORBA_Context ctx,
++ CORBA_Flags del_flags,
++ CORBA_Environment *ev);
++
++void ORBit_Context_marshal(CORBA_Context ctx, const ORBit_ContextMarshalItem *mlist,
++ CORBA_unsigned_long nitems, GIOPSendBuffer *buf);
++void ORBit_Context_demarshal(CORBA_Context parent, CORBA_Context initme, GIOPRecvBuffer *recv_buffer);
++void ORBit_Context_server_free(CORBA_Context ctx);
++
++#endif
+diff -urN linux-2.4.1/net/korbit/orb/corba_env.h linux-2.4.1-korbit/net/korbit/orb/corba_env.h
+--- linux-2.4.1/net/korbit/orb/corba_env.h Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/orb/corba_env.h Thu Feb 1 11:47:11 2001
+@@ -0,0 +1,79 @@
++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
++
++/*
++ * ORBit: A CORBA v2.2 ORB
++ *
++ * Copyright (C) 1998 Richard H. Porter
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Library General Public
++ * License as published by the Free Software Foundation; either
++ * version 2 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Library General Public License for more details.
++ *
++ * You should have received a copy of the GNU Library General Public
++ * License along with this library; if not, write to the Free
++ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Author: Dick Porter <dick@cymru.net>
++ *
++ */
++
++#ifndef _ORBIT_CORBA_ENV_H_
++#define _ORBIT_CORBA_ENV_H_
++
++typedef struct CORBA_Environment_type CORBA_Environment;
++
++/* 3.15 */
++typedef enum {
++ CORBA_COMPLETED_YES=0,
++ CORBA_COMPLETED_NO,
++ CORBA_COMPLETED_MAYBE
++} CORBA_completion_status;
++
++typedef enum {
++ CORBA_NO_EXCEPTION=0,
++ CORBA_USER_EXCEPTION,
++ CORBA_SYSTEM_EXCEPTION
++} CORBA_exception_type;
++
++
++#define ex_CORBA_UNKNOWN 1
++#define ex_CORBA_BAD_PARAM 2
++#define ex_CORBA_NO_MEMORY 3
++#define ex_CORBA_IMP_LIMIT 4
++#define ex_CORBA_COMM_FAILURE 5
++#define ex_CORBA_INV_OBJREF 6
++#define ex_CORBA_NO_PERMISSION 7
++#define ex_CORBA_INTERNAL 8
++#define ex_CORBA_MARSHAL 9
++#define ex_CORBA_INITIALIZE 10
++#define ex_CORBA_NO_IMPLEMENT 11
++#define ex_CORBA_BAD_TYPECODE 12
++#define ex_CORBA_BAD_OPERATION 13
++#define ex_CORBA_NO_RESOURCES 14
++#define ex_CORBA_NO_RESPONSE 15
++#define ex_CORBA_PERSIST_STORE 16
++#define ex_CORBA_BAD_INV_ORDER 17
++#define ex_CORBA_TRANSIENT 18
++#define ex_CORBA_FREE_MEM 19
++#define ex_CORBA_INV_IDENT 20
++#define ex_CORBA_INV_FLAG 21
++#define ex_CORBA_INTF_REPOS 22
++#define ex_CORBA_BAD_CONTEXT 23
++#define ex_CORBA_OBJ_ADAPTER 24
++#define ex_CORBA_DATA_CONVERSION 25
++#define ex_CORBA_OBJECT_NOT_EXIST 26
++#define ex_CORBA_TRANSACTION_REQUIRED 27
++#define ex_CORBA_TRANSACTION_ROLLEDBACK 28
++#define ex_CORBA_INVALID_TRANSACTION 29
++
++
++#endif /* !_ORBIT_CORBA_ENV_H_ */
++
++
++
+diff -urN linux-2.4.1/net/korbit/orb/corba_env_type.h linux-2.4.1-korbit/net/korbit/orb/corba_env_type.h
+--- linux-2.4.1/net/korbit/orb/corba_env_type.h Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/orb/corba_env_type.h Thu Feb 1 16:20:50 2001
+@@ -0,0 +1,79 @@
++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
++
++/*
++ * ORBit: A CORBA v2.2 ORB
++ *
++ * Copyright (C) 1998 Richard H. Porter
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Library General Public
++ * License as published by the Free Software Foundation; either
++ * version 2 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Library General Public License for more details.
++ *
++ * You should have received a copy of the GNU Library General Public
++ * License along with this library; if not, write to the Free
++ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Author: Dick Porter <dick@cymru.net>
++ *
++ */
++
++#ifndef _ORBIT_CORBA_ENV_TYPE_H_
++#define _ORBIT_CORBA_ENV_TYPE_H_
++
++#include "corba_env.h"
++#include "corba_any.h"
++
++typedef struct CORBA_system_exception {
++ CORBA_unsigned_long minor;
++ CORBA_completion_status completed;
++} CORBA_SystemException;
++
++#define SYSEXC(name) typedef CORBA_SystemException name;
++
++SYSEXC(CORBA_UNKNOWN)
++SYSEXC(CORBA_BAD_PARAM)
++SYSEXC(CORBA_NO_MEMORY)
++SYSEXC(CORBA_IMP_LIMIT)
++SYSEXC(CORBA_COMM_FAILURE)
++SYSEXC(CORBA_INV_OBJREF)
++SYSEXC(CORBA_NO_PERMISSION)
++SYSEXC(CORBA_INTERNAL)
++SYSEXC(CORBA_MARSHAL)
++SYSEXC(CORBA_INITIALIZE)
++SYSEXC(CORBA_NO_IMPLEMENT)
++SYSEXC(CORBA_BAD_TYPECODE)
++SYSEXC(CORBA_BAD_OPERATION)
++SYSEXC(CORBA_NO_RESOURCES)
++SYSEXC(CORBA_NO_RESPONSE)
++SYSEXC(CORBA_PERSIST_STORE)
++SYSEXC(CORBA_BAD_INV_ORDER)
++SYSEXC(CORBA_TRANSIENT)
++SYSEXC(CORBA_FREE_MEM)
++SYSEXC(CORBA_INV_IDENT)
++SYSEXC(CORBA_INV_FLAG)
++SYSEXC(CORBA_INTF_REPOS)
++SYSEXC(CORBA_BAD_CONTEXT)
++SYSEXC(CORBA_OBJ_ADAPTER)
++SYSEXC(CORBA_DATA_CONVERSION)
++SYSEXC(CORBA_OBJECT_NOT_EXIST)
++SYSEXC(CORBA_TRANSACTION_REQUIRED)
++SYSEXC(CORBA_TRANSACTION_ROLLEDBACK)
++SYSEXC(CORBA_INVALID_TRANSACTION)
++
++
++/* 19.22 */
++struct CORBA_Environment_type {
++ CORBA_exception_type _major;
++ CORBA_char *_repo_id;
++ void *_params;
++ CORBA_any *_any;
++};
++
++
++#endif /* !_ORBIT_CORBA_ENV_TYPE_H_ */
+diff -urN linux-2.4.1/net/korbit/orb/corba_object.c linux-2.4.1-korbit/net/korbit/orb/corba_object.c
+--- linux-2.4.1/net/korbit/orb/corba_object.c Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/orb/corba_object.c Thu Feb 1 11:47:11 2001
+@@ -0,0 +1,467 @@
++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
++
++/*
++ * ORBit: A CORBA v2.2 ORB
++ *
++ * Copyright (C) 1998 Richard H. Porter
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Library General Public
++ * License as published by the Free Software Foundation; either
++ * version 2 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Library General Public License for more details.
++ *
++ * You should have received a copy of the GNU Library General Public
++ * License along with this library; if not, write to the Free
++ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Author: Dick Porter <dick@cymru.net>
++ * Elliot Lee <sopwith@redhat.com>
++ *
++ */
++
++#include "config.h"
++#include <IIOP/IIOP.h>
++#include "orbit_types.h"
++#include "corba_object.h"
++#include "corba_object_type.h"
++#include "env.h"
++#include "orb.h"
++#ifdef __KORBIT__
++#include "orbit.h"
++#else /* !__KORBIT__ */
++#include "interface_repository.h"
++#endif /* !__KORBIT__ */
++#include <signal.h>
++#include <sys/types.h>
++#include <sys/wait.h>
++#include <alloca.h>
++
++#ifndef __KERNEL__
++#define freeca(ptr)
++#endif
++
++#ifndef __KORBIT__
++/* Section 4.2.1 */
++CORBA_InterfaceDef CORBA_Object_get_interface(CORBA_Object obj, CORBA_Environment *ev)
++{
++ CORBA_Repository repo;
++ CORBA_InterfaceDef interface;
++
++ if(obj==CORBA_OBJECT_NIL)
++ return(CORBA_OBJECT_NIL); /* no exception defined in spec */
++
++ repo=CORBA_ORB_resolve_initial_references(obj->orb, "InterfaceRepository", ev);
++ if(repo==CORBA_OBJECT_NIL)
++ return(CORBA_OBJECT_NIL);
++
++ interface=CORBA_Repository_lookup_id(repo, obj->object_id, ev);
++ CORBA_Object_release(repo, ev);
++
++ return(interface);
++}
++#endif /* !__KORBIT__ */
++
++/* Section 4.2.3 */
++CORBA_boolean CORBA_Object_is_nil(CORBA_Object obj, CORBA_Environment *ev)
++{
++ if(obj==CORBA_OBJECT_NIL) {
++ return(CORBA_TRUE);
++ } else {
++ return(CORBA_FALSE);
++ }
++}
++
++/* Section 4.2.2 */
++/* XXXX Big warning: lots of places inside ORBit expect this to
++ always return 'obj'. Do not change this, upon pain
++ of death... */
++CORBA_Object CORBA_Object_duplicate(CORBA_Object obj, CORBA_Environment *ev)
++{
++ if(obj == CORBA_OBJECT_NIL)
++ return CORBA_OBJECT_NIL;
++
++ if(ORBIT_ROOT_OBJECT(obj)->refs >= 0)
++ ORBIT_ROOT_OBJECT_REF(obj);
++
++ return(obj);
++}
++
++
++/* Section 4.2.2 */
++void CORBA_Object_release(CORBA_Object obj, CORBA_Environment *ev)
++{
++ if(obj != CORBA_OBJECT_NIL)
++ ORBIT_ROOT_OBJECT_release(obj,ev);
++}
++
++extern GHashTable *ORBit_class_assignments;
++
++void ORBit_impl_CORBA_Object_is_a(gpointer servant,
++ GIOPRecvBuffer * _ORBIT_recv_buffer,
++ CORBA_Environment *ev,
++ gpointer dummy)
++{
++ GIOPSendBuffer *_ORBIT_send_buffer;
++ struct CORBA_Object_struct objdummy; /* XXX badhack to save backwards compat */
++ CORBA_boolean retval;
++ char *repo_id;
++ CORBA_unsigned_long slen;
++ guchar *curptr;
++ ORBit_ObjectKey *objkey;
++ gpointer *tmp_vepv;
++ guint sz;
++ CORBA_unsigned_long clsid;
++ PortableServer_ServantBase *_ORBIT_servant;
++
++ _ORBIT_servant = servant;
++
++ /* XXX security implications */
++ curptr = _ORBIT_recv_buffer->cur;
++ curptr = ALIGN_ADDRESS(curptr, 4);
++ if(giop_msg_conversion_needed(GIOP_MESSAGE_BUFFER(_ORBIT_recv_buffer)))
++ iiop_byteswap((guchar *)&slen, curptr, sizeof(CORBA_unsigned_long));
++ else
++ slen = *((CORBA_unsigned_long *)curptr);
++ curptr += 4;
++ repo_id = curptr;
++
++ repo_id[slen] = '\0';
++
++ objkey = ORBIT_OBJECT_KEY(_ORBIT_servant->_private);
++
++ sz = sizeof(gpointer) * (ORBit_class_assignment_counter + 1);
++ tmp_vepv = alloca(sz);
++ memset(tmp_vepv, '\0', sz);
++
++ objdummy.vepv = tmp_vepv;
++ objkey->class_info->init_local_objref(&objdummy, servant);
++
++ clsid = GPOINTER_TO_UINT(g_hash_table_lookup(ORBit_class_assignments, repo_id));
++ retval = (clsid && tmp_vepv[clsid]);
++
++ _ORBIT_send_buffer = giop_send_reply_buffer_use(GIOP_MESSAGE_BUFFER(_ORBIT_recv_buffer)->connection, NULL,
++ _ORBIT_recv_buffer->message.u.request.request_id, ev->_major);
++ giop_message_buffer_append_mem(GIOP_MESSAGE_BUFFER(_ORBIT_send_buffer), &retval, sizeof(retval));
++ giop_send_buffer_write(_ORBIT_send_buffer);
++ giop_send_buffer_unuse(_ORBIT_send_buffer);
++ freeca(tmp_vepv);
++}
++
++/* Section 4.2.4 */
++CORBA_boolean CORBA_Object_is_a(CORBA_Object obj, CORBA_char *logical_type_id, CORBA_Environment *ev)
++{
++ if(obj == CORBA_OBJECT_NIL)
++ return CORBA_FALSE;
++
++ if (obj->servant && obj->vepv) {
++ CORBA_unsigned_long clsid;
++
++ clsid = GPOINTER_TO_UINT(g_hash_table_lookup(ORBit_class_assignments, logical_type_id));
++
++ return (clsid && (clsid < obj->vepv_size) && obj->vepv[clsid]);
++ } else if(!strcmp(obj->object_id, logical_type_id)
++ || !strcmp("IDL:CORBA/Object:1.0", logical_type_id)) {
++ return CORBA_TRUE;
++ } else {
++ /* Cut and paste from orbit-idl output */
++ /* XXX security implications */
++ GIOP_unsigned_long _ORBIT_request_id;
++ register GIOP_unsigned_long _ORBIT_system_exception_minor;
++ register CORBA_completion_status _ORBIT_completion_status;
++ register GIOPSendBuffer *_ORBIT_send_buffer;
++ register GIOPRecvBuffer *_ORBIT_recv_buffer;
++ register GIOPConnection *_cnx;
++
++ _cnx = ORBit_object_get_connection(obj);
++
++ _ORBIT_retry_request:
++ _ORBIT_send_buffer = NULL;
++ _ORBIT_recv_buffer = NULL;
++ _ORBIT_completion_status = CORBA_COMPLETED_NO;
++ /* A unique uint pointer is anything on the stack,
++ so set this variable to point to its own address on the
++ stack. :) */
++ _ORBIT_request_id = GPOINTER_TO_UINT(&_ORBIT_request_id);
++ { /* marshalling */
++ static const struct {
++ CORBA_unsigned_long len;
++ char opname[6];
++ } _ORBIT_operation_name_data = {
++ 6, "_is_a"
++ };
++ static const struct iovec _ORBIT_operation_vec =
++ {(gpointer) & _ORBIT_operation_name_data, 10};
++ register CORBA_unsigned_long _ORBIT_tmpvar_0;
++ CORBA_unsigned_long _ORBIT_tmpvar_1;
++
++ _ORBIT_send_buffer =
++ giop_send_request_buffer_use(_cnx, NULL, _ORBIT_request_id, CORBA_TRUE,
++ &(obj->active_profile->object_key_vec), &_ORBIT_operation_vec, &ORBit_default_principal_iovec);
++
++ _ORBIT_system_exception_minor = ex_CORBA_COMM_FAILURE;
++ if (!_ORBIT_send_buffer)
++ goto _ORBIT_system_exception;
++ _ORBIT_tmpvar_1 = strlen(logical_type_id) + 1;
++ giop_message_buffer_do_alignment(GIOP_MESSAGE_BUFFER(_ORBIT_send_buffer), 4);
++ giop_message_buffer_append_mem(GIOP_MESSAGE_BUFFER(_ORBIT_send_buffer), &(_ORBIT_tmpvar_1), sizeof(_ORBIT_tmpvar_1));
++ giop_message_buffer_append_mem(GIOP_MESSAGE_BUFFER(_ORBIT_send_buffer), (logical_type_id), sizeof(logical_type_id[_ORBIT_tmpvar_0]) * _ORBIT_tmpvar_1);
++ giop_send_buffer_write(_ORBIT_send_buffer);
++ _ORBIT_completion_status = CORBA_COMPLETED_MAYBE;
++ giop_send_buffer_unuse(_ORBIT_send_buffer);
++ _ORBIT_send_buffer = NULL;
++ }
++ { /* demarshalling */
++ register guchar *_ORBIT_curptr;
++ CORBA_boolean _ORBIT_retval;
++
++ _ORBIT_recv_buffer = giop_recv_reply_buffer_use_2(_cnx, _ORBIT_request_id, TRUE);
++ if (!_ORBIT_recv_buffer)
++ goto _ORBIT_system_exception;
++ _ORBIT_completion_status = CORBA_COMPLETED_YES;
++ if (_ORBIT_recv_buffer->message.u.reply.reply_status != GIOP_NO_EXCEPTION)
++ goto _ORBIT_msg_exception;
++ if (giop_msg_conversion_needed(GIOP_MESSAGE_BUFFER(_ORBIT_recv_buffer))) {
++ _ORBIT_curptr = GIOP_RECV_BUFFER(_ORBIT_recv_buffer)->cur;
++ _ORBIT_retval = *((CORBA_boolean *) _ORBIT_curptr);
++ } else {
++ _ORBIT_curptr = GIOP_RECV_BUFFER(_ORBIT_recv_buffer)->cur;
++ _ORBIT_retval = *((CORBA_boolean *) _ORBIT_curptr);
++ }
++ giop_recv_buffer_unuse(_ORBIT_recv_buffer);
++ return _ORBIT_retval;
++ _ORBIT_system_exception:
++ CORBA_exception_set_system(ev, _ORBIT_system_exception_minor, _ORBIT_completion_status);
++ giop_recv_buffer_unuse(_ORBIT_recv_buffer);
++ giop_send_buffer_unuse(_ORBIT_send_buffer);
++ return _ORBIT_retval;
++ _ORBIT_msg_exception:
++ if (_ORBIT_recv_buffer->message.u.reply.reply_status == GIOP_LOCATION_FORWARD) {
++ if (obj->forward_locations != NULL)
++ ORBit_delete_profiles(obj->forward_locations);
++ obj->forward_locations = ORBit_demarshal_IOR(_ORBIT_recv_buffer);
++ _cnx = ORBit_object_get_forwarded_connection(obj);
++ giop_recv_buffer_unuse(_ORBIT_recv_buffer);
++
++ goto _ORBIT_retry_request;
++ } else {
++ ORBit_handle_exception(_ORBIT_recv_buffer, ev, NULL, obj->orb);
++ giop_recv_buffer_unuse(_ORBIT_recv_buffer);
++ return _ORBIT_retval;
++ }
++ }
++
++ }
++}
++
++/* Section 4.2.5 */
++#ifndef __KORBIT__
++static void do_exit(int signum) {
++ _exit(5);
++#warning "This should be removed... use BUG instead..."
++}
++#endif
++
++/* Lovely hack to try and figure out without hanging whether an object exists or not. */
++CORBA_boolean CORBA_Object_non_existent(CORBA_Object obj, CORBA_Environment *ev)
++{
++#ifndef __KORBIT__
++ int childpid, exitstatus, itmp;
++#endif
++
++ ev->_major = CORBA_NO_EXCEPTION;
++
++ if(obj == CORBA_OBJECT_NIL)
++ return TRUE;
++
++ if(obj->servant)
++ return FALSE;
++
++ if(obj->connection && obj->connection->is_valid)
++ return FALSE;
++
++#ifndef __KORBIT__
++ childpid = fork();
++
++ if(!childpid) {
++ GIOPConnection* cnx = NULL;
++ struct sigaction sa;
++
++ memset(&sa, 0, sizeof(sa));
++ sa.sa_handler = do_exit;
++ sigaction(SIGALRM, &sa, NULL);
++ alarm(2);
++ cnx = _ORBit_object_get_connection(obj);
++
++ /* XXX todo - try invoking a strange operation on the object, and see what type of exception we get. */
++
++ _exit((cnx == NULL)?1:0);
++ }
++
++ itmp = waitpid(childpid, &exitstatus, 0);
++
++ if(itmp < 0) return TRUE;
++ return WEXITSTATUS(exitstatus) && TRUE;
++#else /* __KORBIT__ */
++ return FALSE;
++#endif /* __KORBIT__ */
++}
++
++gboolean
++g_CORBA_Object_equal(CORBA_Object obj1, CORBA_Object obj2)
++{
++ gboolean retval;
++ CORBA_Environment ev;
++
++ CORBA_exception_init(&ev);
++
++ retval = (gboolean)CORBA_Object_is_equivalent(obj1, obj2, &ev);
++
++ CORBA_exception_free(&ev);
++
++ return retval;
++}
++
++/* Section 4.2.6 */
++CORBA_boolean CORBA_Object_is_equivalent(CORBA_Object obj, CORBA_Object other_object, CORBA_Environment *ev)
++{
++ ORBit_Object_info *obj_profile, *other_object_profile;
++ int i,j, obj_profile_count, other_object_profile_count;
++
++ if(obj == CORBA_OBJECT_NIL
++ && other_object == CORBA_OBJECT_NIL)
++ return CORBA_TRUE;
++
++ if(obj == CORBA_OBJECT_NIL
++ || other_object == CORBA_OBJECT_NIL)
++ goto ret_false;
++
++ /*
++ * If one profile in "obj" matches one in "other_object", then these
++ * objects are equivalent.
++ *
++ * This is O(n*m) at worst case :-( Hopefully though most objects will
++ * only have 1 or 2 profiles.
++ *
++ * The profile list could be indexed as a hash table (the linked list
++ * is still needed, as the profile order is significant)
++ */
++
++ obj_profile_count = g_slist_length(obj->profile_list);
++ other_object_profile_count = g_slist_length(other_object->profile_list);
++
++ for(i=0;i<obj_profile_count;i++) {
++ obj_profile=(ORBit_Object_info *)g_slist_nth_data(obj->profile_list, i);
++
++ for(j=0;j<other_object_profile_count;j++) {
++ other_object_profile=(ORBit_Object_info *)g_slist_nth_data(other_object->profile_list, j);
++
++ if(obj_profile->profile_type != other_object_profile->profile_type)
++ continue;
++
++ if(obj_profile->object_key._length != other_object_profile->object_key._length)
++ continue;
++
++ if(memcmp(obj_profile->object_key._buffer, other_object_profile->object_key._buffer, obj_profile->object_key._length))
++ continue;
++
++ if(obj_profile->profile_type == IOP_TAG_INTERNET_IOP) {
++ TAG_INTERNET_IOP_info *ii1, *ii2;
++
++ ii1 = &obj_profile->tag.iopinfo;
++ ii2 = &other_object_profile->tag.iopinfo;
++
++ if(ii1->port != ii2->port)
++ continue;
++ if(strcmp(ii1->host, ii2->host))
++ continue;
++
++ return(CORBA_TRUE);
++ } else if(obj_profile->profile_type == IOP_TAG_ORBIT_SPECIFIC) {
++ TAG_ORBIT_SPECIFIC_info *oi1, *oi2;
++
++ oi1 = &obj_profile->tag.orbitinfo;
++ oi2 = &other_object_profile->tag.orbitinfo;
++
++ if(strcmp(oi1->unix_sock_path, oi2->unix_sock_path))
++ continue;
++ if(oi1->ipv6_port != oi2->ipv6_port)
++ continue;
++
++ return(CORBA_TRUE);
++ }
++ }
++ }
++
++ ret_false:
++ return CORBA_FALSE;
++}
++
++guint
++g_CORBA_Object_hash(CORBA_Object obj)
++{
++ guint retval;
++ CORBA_Environment ev;
++
++ CORBA_exception_init(&ev);
++
++ retval = (guint)CORBA_Object_hash(obj, UINT_MAX, &ev);
++
++ CORBA_exception_free(&ev);
++
++ return retval;
++}
++
++static void profile_hash(gpointer item, gpointer data)
++{
++ ORBit_Object_info *info = (ORBit_Object_info *)item;
++ CORBA_unsigned_long *retval = (CORBA_unsigned_long *)data;
++
++ g_assert(info);
++ g_assert(retval);
++
++ *retval ^= info->object_key._length;
++
++ if(info->profile_type == IOP_TAG_INTERNET_IOP) {
++ *retval ^= !info->tag.iopinfo.port;
++ } else if(info->profile_type == IOP_TAG_ORBIT_SPECIFIC) {
++ *retval ^= g_str_hash(info->tag.orbitinfo.unix_sock_path);
++ *retval ^= !info->tag.orbitinfo.ipv6_port;
++ }
++}
++
++/* Section 4.2.6 */
++CORBA_unsigned_long CORBA_Object_hash(CORBA_Object obj,
++ CORBA_unsigned_long maximum,
++ CORBA_Environment *ev)
++{
++ CORBA_unsigned_long retval = 0;
++ char *tptr;
++
++ g_assert(obj);
++
++ tptr = obj->object_id;
++ while(*tptr) {
++ retval = (retval << 8) ^ *tptr;
++ tptr++;
++ }
++
++ if(g_slist_length(obj->profile_list)>0) {
++ g_slist_foreach(obj->profile_list, profile_hash, &retval);
++ } else {
++ g_warning("Object of type %s doesn't seem to have any connection info!", obj->object_id);
++ }
++
++ return (retval % maximum);
++}
++
++/* Section 4.2.7 */
++CORBA_Policy CORBA_Object_get_policy(CORBA_Object obj, CORBA_PolicyType policy_type, CORBA_Environment *ev)
++{
++ g_assert(!"Not yet implemented");
++ return(NULL);
++}
+diff -urN linux-2.4.1/net/korbit/orb/corba_object.h linux-2.4.1-korbit/net/korbit/orb/corba_object.h
+--- linux-2.4.1/net/korbit/orb/corba_object.h Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/orb/corba_object.h Thu Feb 1 16:20:50 2001
+@@ -0,0 +1,59 @@
++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
++
++/*
++ * ORBit: A CORBA v2.2 ORB
++ *
++ * Copyright (C) 1998 Richard H. Porter
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Library General Public
++ * License as published by the Free Software Foundation; either
++ * version 2 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Library General Public License for more details.
++ *
++ * You should have received a copy of the GNU Library General Public
++ * License along with this library; if not, write to the Free
++ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Author: Dick Porter <dick@cymru.net>
++ *
++ */
++
++#ifndef _ORBIT_CORBA_OBJECT_H_
++#define _ORBIT_CORBA_OBJECT_H_
++
++#include <ORBitutil/basic_types.h>
++
++#include "corba_env.h"
++#include "corba_orb.h"
++#include "corba_sequences.h"
++
++#define CORBA_OBJECT_NIL NULL
++
++typedef struct CORBA_Object_struct *CORBA_Object;
++
++#define CORBA_OBJECT(x) ((CORBA_Object)(x))
++
++/* Used for internal stuff mostly, but also good if you want to store
++ a hash of objects */
++gboolean g_CORBA_Object_equal(CORBA_Object obj1, CORBA_Object obj2);
++guint g_CORBA_Object_hash(CORBA_Object obj);
++
++void ORBit_impl_CORBA_Object_is_a(gpointer servant,
++ GIOPRecvBuffer * _ORBIT_recv_buffer,
++ CORBA_Environment *ev, gpointer dummy);
++#define ORBIT_IMPLEMENTS_IS_A
++
++extern CORBA_boolean CORBA_Object_is_a(
++ CORBA_Object obj,
++ CORBA_char *logical_type_id,
++ CORBA_Environment *ev);
++
++#endif /* !_ORBIT_CORBA_OBJECT_H_ */
++
++
++
+diff -urN linux-2.4.1/net/korbit/orb/corba_object_type.h linux-2.4.1-korbit/net/korbit/orb/corba_object_type.h
+--- linux-2.4.1/net/korbit/orb/corba_object_type.h Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/orb/corba_object_type.h Thu Feb 1 16:20:50 2001
+@@ -0,0 +1,54 @@
++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
++
++/*
++ * ORBit: A CORBA v2.2 ORB
++ *
++ * Copyright (C) 1998 Richard H. Porter
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Library General Public
++ * License as published by the Free Software Foundation; either
++ * version 2 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Library General Public License for more details.
++ *
++ * You should have received a copy of the GNU Library General Public
++ * License along with this library; if not, write to the Free
++ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Author: Dick Porter <dick@cymru.net>
++ *
++ */
++
++#ifndef _ORBIT_CORBA_OBJECT_TYPE_H_
++#define _ORBIT_CORBA_OBJECT_TYPE_H_
++
++#include <sys/uio.h> /* for struct iovec */
++
++#include <IIOP/IIOP.h> /* for giop_connection */
++
++#include "corba_object.h"
++#include "corba_basic_sequences_type.h"
++
++#include "orbit_object_type.h"
++
++struct CORBA_Object_struct {
++ struct ORBit_RootObject_struct parent;
++ CORBA_ORB orb;
++ GIOPConnection *connection;
++ CORBA_char *object_id;
++ GSList *profile_list;
++ GSList *forward_locations;
++ ORBit_Object_info *active_profile; /* points at a member of profile_list or forward_locations */
++
++ /* Used for direct calls */
++ gpointer *vepv;
++ /* PortableServer_Servant - looping includes :( */ gpointer servant;
++ guint vepv_size;
++};
++
++
++#endif /* !_ORBIT_CORBA_OBJECT_TYPE_H_ */
+diff -urN linux-2.4.1/net/korbit/orb/corba_orb.h linux-2.4.1-korbit/net/korbit/orb/corba_orb.h
+--- linux-2.4.1/net/korbit/orb/corba_orb.h Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/orb/corba_orb.h Thu Feb 1 11:47:11 2001
+@@ -0,0 +1,48 @@
++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
++
++/*
++ * ORBit: A CORBA v2.2 ORB
++ *
++ * Copyright (C) 1998 Richard H. Porter
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Library General Public
++ * License as published by the Free Software Foundation; either
++ * version 2 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Library General Public License for more details.
++ *
++ * You should have received a copy of the GNU Library General Public
++ * License along with this library; if not, write to the Free
++ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Author: Dick Porter <dick@cymru.net>
++ *
++ */
++
++#ifndef _ORBIT_CORBA_ORB_H_
++#define _ORBIT_CORBA_ORB_H_
++
++typedef char *CORBA_ORB_ObjectId;
++
++#ifndef CORBA_POLICY_TYPE
++#define CORBA_POLICY_TYPE 1
++/* We need to define this in corba_orb_type.h as well, sometimes... */
++typedef struct CORBA_Policy_type *CORBA_Policy;
++#endif
++
++typedef CORBA_unsigned_long CORBA_PolicyType;
++
++typedef struct CORBA_ORB_type *CORBA_ORB;
++
++typedef struct CORBA_DomainManager_type *CORBA_DomainManager;
++
++typedef struct CORBA_ConstructionPolicy_type *CORBA_ConstructionPolicy;
++
++#define ex_CORBA_ORB_InvalidName "IDL:CORBA/ORB/InvalidName:1.0"
++
++#endif /* !_ORBIT_CORBA_ORB_H_ */
++
+diff -urN linux-2.4.1/net/korbit/orb/corba_orb_type.h linux-2.4.1-korbit/net/korbit/orb/corba_orb_type.h
+--- linux-2.4.1/net/korbit/orb/corba_orb_type.h Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/orb/corba_orb_type.h Thu Feb 1 16:20:50 2001
+@@ -0,0 +1,77 @@
++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
++
++/*
++ * ORBit: A CORBA v2.2 ORB
++ *
++ * Copyright (C) 1998 Richard H. Porter
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Library General Public
++ * License as published by the Free Software Foundation; either
++ * version 2 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Library General Public License for more details.
++ *
++ * You should have received a copy of the GNU Library General Public
++ * License along with this library; if not, write to the Free
++ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Author: Dick Porter <dick@cymru.net>
++ *
++ */
++
++#ifndef _ORBIT_CORBA_ORB_TYPE_H_
++#define _ORBIT_CORBA_ORB_TYPE_H_
++
++#include "corba_object.h"
++
++struct CORBA_ORB_type {
++ struct ORBit_PseudoObject_struct parent;
++ CORBA_ORBid orb_identifier;
++ CORBA_RepositoryId repoid;
++ CORBA_boolean use_poa;
++
++ CORBA_Object imr, ir, naming, root_poa;
++ struct {
++ GIOPConnection *ipv4;
++ GIOPConnection *ipv6;
++ GIOPConnection *usock;
++ } cnx;
++
++ GHashTable *objrefs;
++
++ GPtrArray *poas;
++
++ CORBA_Context default_ctx;
++};
++
++#define CORBA_ORB_CAST(orb) ((CORBA_ORB)orb)
++
++typedef struct CORBA_ORB_InvalidName {
++ int dummy;
++} CORBA_ORB_InvalidName;
++
++struct CORBA_Policy_type {
++ struct ORBit_PseudoObject_struct parent;
++ CORBA_PolicyType policy_type;
++};
++#ifndef CORBA_POLICY_TYPE
++#define CORBA_POLICY_TYPE 1
++typedef struct CORBA_Policy_type *CORBA_Policy;
++#endif
++
++struct CORBA_DomainManager_type {
++ struct ORBit_PseudoObject_struct parent;
++};
++
++#define CORBA_SecConstruction (11)
++
++struct CORBA_ConstructionPolicy_type {
++ int fill_me_in;
++};
++
++
++#endif /* !_ORBIT_CORBA_ORB_TYPE_H_ */
+diff -urN linux-2.4.1/net/korbit/orb/corba_portableserver.h linux-2.4.1-korbit/net/korbit/orb/corba_portableserver.h
+--- linux-2.4.1/net/korbit/orb/corba_portableserver.h Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/orb/corba_portableserver.h Thu Feb 1 11:47:11 2001
+@@ -0,0 +1,80 @@
++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
++
++/*
++ * ORBit: A CORBA v2.2 ORB
++ *
++ * Copyright (C) 1998 Richard H. Porter
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Library General Public
++ * License as published by the Free Software Foundation; either
++ * version 2 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Library General Public License for more details.
++ *
++ * You should have received a copy of the GNU Library General Public
++ * License along with this library; if not, write to the Free
++ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Author: Dick Porter <dick@cymru.net>
++ *
++ */
++
++#ifndef _ORBIT_CORBA_PORTABLESERVER_H_
++#define _ORBIT_CORBA_PORTABLESERVER_H_
++
++typedef struct PortableServer_ThreadPolicy_type *PortableServer_ThreadPolicy;
++typedef struct PortableServer_LifespanPolicy_type *PortableServer_LifespanPolicy;
++typedef struct PortableServer_IdUniquenessPolicy_type *PortableServer_IdUniquenessPolicy;
++typedef struct PortableServer_IdAssignmentPolicy_type *PortableServer_IdAssignmentPolicy;
++typedef struct PortableServer_ImplicitActivationPolicy_type *PortableServer_ImplicitActivationPolicy;
++typedef struct PortableServer_ServantRetentionPolicy_type *PortableServer_ServantRetentionPolicy;
++typedef struct PortableServer_RequestProcessingPolicy_type *PortableServer_RequestProcessingPolicy;
++typedef struct PortableServer_POAManager_type* PortableServer_POAManager;
++typedef struct PortableServer_AdapterActivator_type *PortableServer_AdapterActivator;
++typedef struct PortableServer_ServantManager_type *PortableServer_ServantManager;
++typedef struct PortableServer_ServantActivator_type *PortableServer_ServantActivator;
++typedef struct PortableServer_ServantLocator_type *PortableServer_ServantLocator;
++typedef struct PortableServer_POA_type *PortableServer_POA;
++typedef struct PortableServer_Current_type *PortableServer_Current;
++
++typedef enum {
++ PortableServer_ORB_CTRL_MODEL=0,
++ PortableServer_SINGLE_THREAD_MODEL
++} PortableServer_ThreadPolicyValue;
++
++typedef enum {
++ PortableServer_TRANSIENT=0,
++ PortableServer_PERSISTENT
++} PortableServer_LifespanPolicyValue;
++
++typedef enum {
++ PortableServer_UNIQUE_ID=0,
++ PortableServer_MULTIPLE_ID
++} PortableServer_IdUniquenessPolicyValue;
++
++typedef enum {
++ PortableServer_USER_ID=0,
++ PortableServer_SYSTEM_ID
++} PortableServer_IdAssignmentPolicyValue;
++
++typedef enum {
++ PortableServer_IMPLICIT_ACTIVATION=0,
++ PortableServer_NO_IMPLICIT_ACTIVATION
++} PortableServer_ImplicitActivationPolicyValue;
++
++typedef enum {
++ PortableServer_RETAIN=0,
++ PortableServer_NON_RETAIN
++} PortableServer_ServantRetentionPolicyValue;
++
++typedef enum {
++ PortableServer_USE_ACTIVE_OBJECT_MAP_ONLY=0,
++ PortableServer_USE_DEFAULT_SERVANT,
++ PortableServer_USE_SERVANT_MANAGER
++} PortableServer_RequestProcessingPolicyValue;
++
++#endif /* !_ORBIT_CORBA_PORTABLESERVER_H_ */
+diff -urN linux-2.4.1/net/korbit/orb/corba_portableserver_type.h linux-2.4.1-korbit/net/korbit/orb/corba_portableserver_type.h
+--- linux-2.4.1/net/korbit/orb/corba_portableserver_type.h Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/orb/corba_portableserver_type.h Thu Feb 1 11:47:11 2001
+@@ -0,0 +1,361 @@
++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
++
++/*
++ * ORBit: A CORBA v2.2 ORB
++ *
++ * Copyright (C) 1998 Richard H. Porter
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Library General Public
++ * License as published by the Free Software Foundation; either
++ * version 2 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Library General Public License for more details.
++ *
++ * You should have received a copy of the GNU Library General Public
++ * License along with this library; if not, write to the Free
++ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Author: Dick Porter <dick@cymru.net>
++ *
++ */
++
++#ifndef _ORBIT_CORBA_PORTABLESERVER_TYPE_H_
++#define _ORBIT_CORBA_PORTABLESERVER_TYPE_H_
++
++/* 19.26 */
++
++typedef void *PortableServer_ServantLocator_Cookie;
++typedef void *PortableServer_Servant;
++
++#ifndef _PortableServer_ForwardRequest_defined
++#define _PortableServer_ForwardRequest_defined
++
++typedef struct PortableServer_ForwardRequest {
++ CORBA_Object forward_reference;
++} PortableServer_ForwardRequest;
++
++#define ex_PortableServer_ForwardRequest "IDL:PortableServer/ForwardRequest:1.0"
++#endif /* !_PortableServer_ForwardRequest_defined */
++
++#define PortableServer_THREAD_POLICY_ID 16
++struct PortableServer_ThreadPolicy_type {
++ struct CORBA_Policy_type corba_policy;
++ PortableServer_ThreadPolicyValue value;
++};
++
++#define PortableServer_LIFESPAN_POLICY_ID 17
++extern const CORBA_PolicyType PortableServer_LifespanPolicy_PolicyType;
++struct PortableServer_LifespanPolicy_type {
++ struct CORBA_Policy_type corba_policy;
++ PortableServer_LifespanPolicyValue value;
++};
++
++#define PortableServer_ID_UNIQUENESS_POLICY_ID 18
++struct PortableServer_IdUniquenessPolicy_type {
++ struct CORBA_Policy_type corba_policy;
++ PortableServer_IdUniquenessPolicyValue value;
++};
++
++#define PortableServer_ID_ASSIGNMENT_POLICY_ID 19
++struct PortableServer_IdAssignmentPolicy_type {
++ struct CORBA_Policy_type corba_policy;
++ PortableServer_IdAssignmentPolicyValue value;
++};
++
++#define PortableServer_IMPLICIT_ACTIVATION_POLICY_ID 20
++struct PortableServer_ImplicitActivationPolicy_type {
++ struct CORBA_Policy_type corba_policy;
++ PortableServer_ImplicitActivationPolicyValue value;
++};
++
++#define PortableServer_SERVANT_RETENTION_POLICY_ID 21
++struct PortableServer_ServantRetentionPolicy_type {
++ struct CORBA_Policy_type corba_policy;
++ PortableServer_ServantRetentionPolicyValue value;
++};
++
++#define PortableServer_REQUEST_PROCESSING_POLICY_ID 22
++struct PortableServer_RequestProcessingPolicy_type {
++ struct CORBA_Policy_type corba_policy;
++ PortableServer_RequestProcessingPolicyValue value;
++};
++
++#ifndef _PortableServer_POAManager_AdapterInactive_defined
++#define _PortableServer_POAManager_AdapterInactive_defined
++
++typedef struct PortableServer_POAManager_AdapterInactive {
++ int fill_me_in;
++} PortableServer_POAManager_AdapterInactive;
++
++#define ex_PortableServer_POAManager_AdapterInactive "IDL:PortableServer/POAManager/AdapterInactive:1.0"
++#endif /* !_PortableServer_POAManager_AdapterInactive_defined */
++
++typedef enum { PortableServer_POAManager_HOLDING,
++ PortableServer_POAManager_ACTIVE,
++ PortableServer_POAManager_DISCARDING,
++ PortableServer_POAManager_INACTIVE
++} PortableServer_POAManager_State;
++
++struct PortableServer_POAManager_type {
++ struct ORBit_PseudoObject_struct parent;
++ GSList* poa_collection;
++ CORBA_ORB orb;
++ PortableServer_POAManager_State state;
++};
++
++struct PortableServer_AdapterActivator_type {
++ int fill_me_in;
++};
++
++struct PortableServer_ServantManager_type {
++ int fill_me_in;
++};
++
++#ifndef _PortableServer_POA_AdapterAlreadyExists_defined
++#define _PortableServer_POA_AdapterAlreadyExists_defined
++
++typedef struct PortableServer_POA_AdapterAlreadyExists {
++ int fill_me_in;
++} PortableServer_POA_AdapterAlreadyExists;
++
++#define ex_PortableServer_POA_AdapterAlreadyExists "IDL:PortableServer/POA/AdapterAlreadyExists:1.0"
++#endif /* !_PortableServer_POA_AdapterAlreadyExists_defined */
++
++#ifndef _PortableServer_POAManager_AdapterInactive_defined
++#define _PortableServer_POAManager_AdapterInactive_defined
++
++typedef struct PortableServer_POAManager_AdapterInactive {
++ int fill_me_in;
++} PortableServer_POAManager_AdapterInactive;
++
++#define ex_PortableServer_POAManager_AdapterInactive "IDL:PortableServer/POAManager/AdapterInactive:1.0"
++#endif /* !_PortableServer_POAManager_AdapterInactive_defined */
++
++#ifndef _PortableServer_POA_AdapterNonExistent_defined
++#define _PortableServer_POA_AdapterNonExistent_defined
++
++typedef struct PortableServer_POA_AdapterNonExistent {
++ int fill_me_in;
++} PortableServer_POA_AdapterNonExistent;
++
++#define ex_PortableServer_POA_AdapterNonExistent "IDL:PortableServer/POA/AdapterNonExistent:1.0"
++#endif /* !_PortableServer_POA_AdapterNonExistent_defined */
++
++#ifndef _PortableServer_POA_InvalidPolicy_defined
++#define _PortableServer_POA_InvalidPolicy_defined
++
++typedef struct PortableServer_POA_InvalidPolicy {
++ CORBA_unsigned_short index;
++} PortableServer_POA_InvalidPolicy;
++
++#define ex_PortableServer_POA_InvalidPolicy "IDL:PortableServer/POA/InvalidPolicy:1.0"
++#endif /* !_PortableServer_POA_InvalidPolicy_defined */
++
++#ifndef _PortableServer_POA_NoServant_defined
++#define _PortableServer_POA_NoServant_defined
++
++typedef struct PortableServer_POA_NoServant {
++ int fill_me_in;
++} PortableServer_POA_NoServant;
++
++#define ex_PortableServer_POA_NoServant "IDL:PortableServer/POA/NoServant:1.0"
++#endif /* !_PortableServer_POA_NoServant_defined */
++
++#ifndef _PortableServer_POA_ObjectAlreadyActive_defined
++#define _PortableServer_POA_ObjectAlreadyActive_defined
++
++typedef struct PortableServer_POA_ObjectAlreadyActive {
++ int fill_me_in;
++} PortableServer_POA_ObjectAlreadyActive;
++
++#define ex_PortableServer_POA_ObjectAlreadyActive "IDL:PortableServer/POA/ObjectAlreadyActive:1.0"
++#endif /* !_PortableServer_POA_ObjectAlreadyActive_defined */
++
++#ifndef _PortableServer_POA_ObjectNotActive_defined
++#define _PortableServer_POA_ObjectNotActive_defined
++
++typedef struct PortableServer_POA_ObjectNotActive {
++ int fill_me_in;
++} PortableServer_POA_ObjectNotActive;
++
++#define ex_PortableServer_POA_ObjectNotActive "IDL:PortableServer/POA/ObjectNotActive:1.0"
++#endif /* !_PortableServer_POA_ObjectNotActive_defined */
++
++#ifndef _PortableServer_POA_ServantAlreadyActive_defined
++#define _PortableServer_POA_ServantAlreadyActive_defined
++
++typedef struct PortableServer_POA_ServantAlreadyActive {
++ int fill_me_in;
++} PortableServer_POA_ServantAlreadyActive;
++
++#define ex_PortableServer_POA_ServantAlreadyActive "IDL:PortableServer/POA/ServantAlreadyActive:1.0"
++#endif /* !_PortableServer_POA_ServantAlreadyActive_defined */
++
++#ifndef _PortableServer_POA_ServantNotActive_defined
++#define _PortableServer_POA_ServantNotActive_defined
++
++typedef struct PortableServer_POA_ServantNotActive {
++ int fill_me_in;
++} PortableServer_POA_ServantNotActive;
++
++#define ex_PortableServer_POA_ServantNotActive "IDL:PortableServer/POA/ServantNotActive:1.0"
++#endif /* !_PortableServer_POA_ServantNotActive_defined */
++
++#ifndef _PortableServer_POA_WrongAdapter_defined
++#define _PortableServer_POA_WrongAdapter_defined
++
++typedef struct PortableServer_POA_WrongAdapter {
++ int fill_me_in;
++} PortableServer_POA_WrongAdapter;
++
++#define ex_PortableServer_POA_WrongAdapter "IDL:PortableServer/POA/WrongAdapter:1.0"
++#endif /* !_PortableServer_POA_WrongAdapter_defined */
++
++#ifndef _PortableServer_POA_WrongPolicy_defined
++#define _PortableServer_POA_WrongPolicy_defined
++
++typedef struct PortableServer_POA_WrongPolicy {
++ int fill_me_in;
++} PortableServer_POA_WrongPolicy;
++
++#define ex_PortableServer_POA_WrongPolicy "IDL:PortableServer/POA/WrongPolicy:1.0"
++#endif /* !_PortableServer_POA_WrongPolicy_defined */
++
++#ifndef _PortableServer_Current_NoContext_defined
++#define _PortableServer_Current_NoContext_defined
++
++typedef struct PortableServer_Current_NoContext {
++ int fill_me_in;
++} PortableServer_Current_NoContext;
++
++#define ex_PortableServer_Current_NoContext "IDL:PortableServer/Current/NoContext:1.0"
++#endif /* !_PortableServer_Current_NoContext_defined */
++
++struct PortableServer_Current_type {
++ int fill_me_in;
++};
++
++typedef struct PortableServer_ServantBase__epv {
++ void *_private;
++ void (*finalize)(PortableServer_Servant, CORBA_Environment *);
++ PortableServer_POA (*default_POA)(PortableServer_Servant, CORBA_Environment *);
++} PortableServer_ServantBase__epv;
++
++typedef PortableServer_ServantBase__epv *PortableServer_ServantBase__vepv;
++
++typedef struct PortableServer_ServantBase {
++ void *_private;
++ PortableServer_ServantBase__vepv *vepv;
++} PortableServer_ServantBase;
++
++/* 19.27 */
++
++typedef void (*PortableServer_DynamicImplRoutine) (PortableServer_Servant servant, CORBA_ServerRequest request);
++
++typedef struct PortableServer_DynamicImpl__epv {
++ void *_private;
++ PortableServer_DynamicImplRoutine invoke;
++ CORBA_RepositoryId (*primary_interface) (PortableServer_Servant svt, PortableServer_ObjectId id, PortableServer_POA poa, CORBA_Environment *env);
++} PortableServer_DynamicImpl__epv;
++
++typedef struct PortableServer_DynamicImpl__vepv {
++ PortableServer_ServantBase__epv *_base_epv;
++ PortableServer_DynamicImpl__epv *PortableServer_DynamicImpl_epv;
++} PortableServer_DynamicImpl__vepv;
++
++typedef struct PortableServer_DynamicImpl {
++ void *_private;
++ PortableServer_DynamicImpl__vepv *vepv;
++} PortableServer_DynamicImpl;
++
++typedef struct {
++ void *_private;
++} POA_PortableServer_ServantManager__epv;
++
++typedef struct {
++ void *_private;
++
++ PortableServer_Servant (*incarnate) (PortableServer_Servant servant,
++ PortableServer_ObjectId * oid,
++ PortableServer_POA adapter,
++ CORBA_Environment * ev);
++
++ void (*etherealize) (PortableServer_Servant servant,
++ PortableServer_ObjectId* oid,
++ PortableServer_POA adapter,
++ PortableServer_Servant serv,
++ CORBA_boolean cleanup_in_progress,
++ CORBA_boolean remaining_activations,
++ CORBA_Environment * ev);
++
++} POA_PortableServer_ServantActivator__epv;
++
++typedef struct {
++ PortableServer_ServantBase__epv *_base_epv;
++ POA_PortableServer_ServantManager__epv *PortableServer_ServantManager_epv;
++ POA_PortableServer_ServantActivator__epv *PortableServer_ServantActivator_epv;
++} POA_PortableServer_ServantActivator__vepv;
++
++typedef struct {
++ void *_private;
++ POA_PortableServer_ServantActivator__vepv *vepv;
++} POA_PortableServer_ServantActivator;
++
++extern void
++POA_PortableServer_ServantActivator__init(PortableServer_Servant servant,
++ CORBA_Environment * ev);
++extern void
++POA_PortableServer_ServantActivator__fini(PortableServer_Servant servant,
++ CORBA_Environment * ev);
++
++typedef struct {
++ void *_private;
++
++ PortableServer_Servant (*preinvoke) (PortableServer_Servant servant,
++ PortableServer_ObjectId * oid,
++ PortableServer_POA adapter,
++ CORBA_Identifier operation,
++ PortableServer_ServantLocator_Cookie *the_cookie,
++ CORBA_Environment * ev);
++
++ void (*postinvoke) (PortableServer_Servant servant,
++ PortableServer_ObjectId * oid,
++ PortableServer_POA adapter,
++ CORBA_Identifier operation,
++ PortableServer_ServantLocator_Cookie the_cookie,
++ PortableServer_Servant the_servant,
++ CORBA_Environment * ev);
++} POA_PortableServer_ServantLocator__epv;
++
++typedef struct {
++ PortableServer_ServantBase__epv *_base_epv;
++ POA_PortableServer_ServantManager__epv *PortableServer_ServantManager_epv;
++ POA_PortableServer_ServantLocator__epv *PortableServer_ServantLocator_epv;
++} POA_PortableServer_ServantLocator__vepv;
++
++typedef struct {
++ void *_private;
++ POA_PortableServer_ServantLocator__vepv *vepv;
++} POA_PortableServer_ServantLocator;
++
++extern void
++POA_PortableServer_ServantLocator__init(PortableServer_Servant servant,
++ CORBA_Environment * ev);
++extern void
++POA_PortableServer_ServantLocator__fini(PortableServer_Servant servant,
++ CORBA_Environment * ev);
++
++struct CORBA_ServerRequest_type {
++ struct ORBit_PseudoObject_struct parent;
++ GIOPRecvBuffer *rbuf;
++ GIOPSendBuffer *sbuf;
++ CORBA_NVList *params;
++ CORBA_ORB orb;
++ guchar did_ctx, did_exc;
++};
++
++#endif /* !_ORBIT_CORBA_PORTABLESERVER_TYPE_H_ */
+diff -urN linux-2.4.1/net/korbit/orb/corba_sequences.h linux-2.4.1-korbit/net/korbit/orb/corba_sequences.h
+--- linux-2.4.1/net/korbit/orb/corba_sequences.h Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/orb/corba_sequences.h Thu Feb 1 11:47:12 2001
+@@ -0,0 +1,74 @@
++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
++
++/*
++ * ORBit: A CORBA v2.2 ORB
++ *
++ * Copyright (C) 1998 Richard H. Porter
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Library General Public
++ * License as published by the Free Software Foundation; either
++ * version 2 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Library General Public License for more details.
++ *
++ * You should have received a copy of the GNU Library General Public
++ * License along with this library; if not, write to the Free
++ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Author: Dick Porter <dick@cymru.net>
++ *
++ */
++
++#ifndef _ORBIT_CORBA_SEQUENCES_H_
++#define _ORBIT_CORBA_SEQUENCES_H_
++
++
++/* moved from sequences.h */
++#include "corba_basic_sequences_type.h"
++
++typedef CORBA_sequence_octet CORBA_ReferenceData;
++
++#define _CORBA_sequence_ServiceOption_defined
++typedef struct CORBA_sequence_ServiceOption CORBA_sequence_ServiceOption;
++
++#define _CORBA_sequence_ServiceDetail_defined
++typedef struct CORBA_sequence_ServiceDetail CORBA_sequence_ServiceDetail;
++
++#define _CORBA_sequence_ORB_ObjectId_defined
++typedef struct CORBA_sequence_ORB_ObjectId CORBA_ORB_ObjectIdList;
++
++#define _CORBA_sequence_NameValuePair_defined
++typedef struct CORBA_sequence_NameValuePair CORBA_NameValuePairSeq;
++
++#define _CORBA_sequence_CORBA_any_defined
++typedef struct CORBA_sequence_CORBA_any_struct CORBA_AnySeq;
++typedef struct CORBA_sequence_CORBA_any_struct CORBA_sequence_CORBA_any;
++
++#define _CORBA_sequence_Policy_defined
++typedef struct CORBA_sequence_Policy CORBA_PolicyList;
++
++#define _CORBA_sequence_DomainManager_defined
++typedef struct CORBA_sequence_DomainManager CORBA_DomainManagerList;
++
++#define _PortableServer_sequence_octet_defined
++typedef struct PortableServer_sequence_octet PortableServer_ObjectId;
++
++
++/* Moved from orbit_types.h */
++#ifndef HAVE_CORBA_PRINCIPAL
++#define HAVE_CORBA_PRINCIPAL 1
++typedef CORBA_sequence_octet CORBA_Principal;
++#endif
++typedef CORBA_sequence_octet CORBA_DynAny_OctetSeq;
++typedef CORBA_sequence_octet CORBA_DynFixed_OctetSeq;
++typedef CORBA_sequence_octet CORBA_DynEnum_OctetSeq;
++typedef CORBA_sequence_octet CORBA_DynStruct_OctetSeq;
++typedef CORBA_sequence_octet CORBA_DynUnion_OctetSeq;
++typedef CORBA_sequence_octet CORBA_DynSequence_OctetSeq;
++typedef CORBA_sequence_octet CORBA_DynArray_OctetSeq;
++
++#endif /* !_ORBIT_CORBA_SEQUENCES_H_ */
+diff -urN linux-2.4.1/net/korbit/orb/corba_sequences_type.h linux-2.4.1-korbit/net/korbit/orb/corba_sequences_type.h
+--- linux-2.4.1/net/korbit/orb/corba_sequences_type.h Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/orb/corba_sequences_type.h Thu Feb 1 11:47:12 2001
+@@ -0,0 +1,98 @@
++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
++
++/*
++ * ORBit: A CORBA v2.2 ORB
++ *
++ * Copyright (C) 1998 Richard H. Porter
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Library General Public
++ * License as published by the Free Software Foundation; either
++ * version 2 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Library General Public License for more details.
++ *
++ * You should have received a copy of the GNU Library General Public
++ * License along with this library; if not, write to the Free
++ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Author: Dick Porter <dick@cymru.net>
++ *
++ */
++
++#ifndef _ORBIT_CORBA_SEQUENCES_TYPE_H_
++#define _ORBIT_CORBA_SEQUENCES_TYPE_H_
++
++#include "corba_sequences.h"
++
++struct CORBA_sequence_ServiceOption {
++ CORBA_unsigned_long _maximum;
++ CORBA_unsigned_long _length;
++ CORBA_ServiceOption *_buffer;
++ CORBA_boolean _release;
++};
++
++struct CORBA_sequence_ServiceDetail {
++ CORBA_unsigned_long _maximum;
++ CORBA_unsigned_long _length;
++ CORBA_ServiceDetail *_buffer;
++ CORBA_boolean _release;
++};
++
++struct CORBA_sequence_ORB_ObjectId {
++ CORBA_unsigned_long _maximum;
++ CORBA_unsigned_long _length;
++ CORBA_ORB_ObjectId *_buffer;
++ CORBA_boolean _release;
++};
++
++struct CORBA_sequence_NameValuePair {
++ CORBA_unsigned_long _maximum;
++ CORBA_unsigned_long _length;
++ struct CORBA_NameValuePair *_buffer;
++ CORBA_boolean _release;
++};
++
++struct CORBA_sequence_CORBA_any_struct {
++ CORBA_unsigned_long _maximum;
++ CORBA_unsigned_long _length;
++ CORBA_any *_buffer;
++ CORBA_boolean _release;
++};
++
++struct CORBA_sequence_Policy {
++ CORBA_unsigned_long _maximum;
++ CORBA_unsigned_long _length;
++ CORBA_Policy *_buffer;
++ CORBA_boolean _release;
++};
++
++struct CORBA_sequence_DomainManager {
++ CORBA_unsigned_long _maximum;
++ CORBA_unsigned_long _length;
++ CORBA_DomainManager *_buffer;
++ CORBA_boolean _release;
++};
++
++struct PortableServer_sequence_octet {
++ CORBA_unsigned_long _maximum;
++ CORBA_unsigned_long _length;
++ CORBA_octet *_buffer;
++ CORBA_boolean _release;
++};
++
++/* Generic sequence */
++struct CORBA_Sequence_type {
++ CORBA_unsigned_long _maximum;
++ CORBA_unsigned_long _length;
++ void *_buffer;
++ CORBA_boolean _release;
++};
++
++#define CORBA_SEQFLAGS_RELEASE 1
++
++
++#endif /* !_ORBIT_CORBA_SEQUENCES_TYPE_H_ */
+diff -urN linux-2.4.1/net/korbit/orb/corba_typecode.h linux-2.4.1-korbit/net/korbit/orb/corba_typecode.h
+--- linux-2.4.1/net/korbit/orb/corba_typecode.h Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/orb/corba_typecode.h Thu Feb 1 11:47:12 2001
+@@ -0,0 +1,167 @@
++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
++
++/*
++ * ORBit: A CORBA v2.2 ORB
++ *
++ * Copyright (C) 1998 Richard H. Porter
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Library General Public
++ * License as published by the Free Software Foundation; either
++ * version 2 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Library General Public License for more details.
++ *
++ * You should have received a copy of the GNU Library General Public
++ * License along with this library; if not, write to the Free
++ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Author: Dick Porter <dick@cymru.net>
++ *
++ */
++
++#ifndef _ORBIT_CORBA_TYPECODE_H_
++#define _ORBIT_CORBA_TYPECODE_H_
++
++/* moved from orbit_types.h */
++typedef struct CORBA_TypeCode_struct *CORBA_TypeCode;
++
++typedef enum {
++ CORBA_tk_null=0,
++ CORBA_tk_void=1,
++ CORBA_tk_short=2,
++ CORBA_tk_long=3,
++ CORBA_tk_ushort=4,
++ CORBA_tk_ulong=5,
++ CORBA_tk_float=6,
++ CORBA_tk_double=7,
++ CORBA_tk_boolean=8,
++ CORBA_tk_char=9,
++ CORBA_tk_octet=10,
++ CORBA_tk_any=11,
++ CORBA_tk_TypeCode=12,
++ CORBA_tk_Principal=13,
++ CORBA_tk_objref=14,
++ CORBA_tk_struct=15,
++ CORBA_tk_union=16,
++ CORBA_tk_enum=17,
++ CORBA_tk_string=18,
++ CORBA_tk_sequence=19,
++ CORBA_tk_array=20,
++ CORBA_tk_alias=21,
++ CORBA_tk_except=22,
++ CORBA_tk_longlong=23,
++ CORBA_tk_ulonglong=24,
++ CORBA_tk_longdouble=25,
++ CORBA_tk_wchar=26,
++ CORBA_tk_wstring=27,
++ CORBA_tk_fixed=28,
++ CORBA_tk_recursive=0xffffffff,
++ CORBA_tk_last=29 /* hack for GIOP */
++} CORBA_TCKind;
++
++#define TC_CORBA_short TC_short
++#define TC_CORBA_long TC_long
++#define TC_CORBA_longlong TC_longlong
++#define TC_CORBA_long_long TC_longlong
++#define TC_CORBA_ushort TC_ushort
++#define TC_CORBA_unsigned_short TC_ushort
++#define TC_CORBA_ulong TC_ulong
++#define TC_CORBA_unsigned_long TC_ulong
++#define TC_CORBA_ulonglong TC_ulonglong
++#define TC_CORBA_unsigned_long_long TC_ulonglong
++#define TC_CORBA_float TC_float
++#define TC_CORBA_double TC_double
++#define TC_CORBA_longdouble TC_longdouble
++#define TC_CORBA_long_double TC_longdouble
++#define TC_CORBA_boolean TC_boolean
++#define TC_CORBA_char TC_char
++#define TC_CORBA_wchar TC_wchar
++#define TC_CORBA_octet TC_octet
++#define TC_CORBA_any TC_any
++#define TC_CORBA_TypeCode TC_TypeCode
++#define TC_CORBA_Principal TC_Principal
++#define TC_CORBA_Object TC_Object
++#define TC_CORBA_string TC_string
++#define TC_CORBA_wstring TC_wstring
++
++#define TC_null ((CORBA_TypeCode)&TC_null_struct)
++#define TC_void ((CORBA_TypeCode)&TC_void_struct)
++#define TC_short ((CORBA_TypeCode)&TC_short_struct)
++#define TC_long ((CORBA_TypeCode)&TC_long_struct)
++#define TC_longlong ((CORBA_TypeCode)&TC_longlong_struct)
++#define TC_ushort ((CORBA_TypeCode)&TC_ushort_struct)
++#define TC_ulong ((CORBA_TypeCode)&TC_ulong_struct)
++#define TC_ulonglong ((CORBA_TypeCode)&TC_ulonglong_struct)
++#define TC_float ((CORBA_TypeCode)&TC_float_struct)
++#define TC_double ((CORBA_TypeCode)&TC_double_struct)
++#define TC_longdouble ((CORBA_TypeCode)&TC_longdouble_struct)
++#define TC_boolean ((CORBA_TypeCode)&TC_boolean_struct)
++#define TC_char ((CORBA_TypeCode)&TC_char_struct)
++#define TC_wchar ((CORBA_TypeCode)&TC_wchar_struct)
++#define TC_octet ((CORBA_TypeCode)&TC_octet_struct)
++#define TC_any ((CORBA_TypeCode)&TC_any_struct)
++#define TC_TypeCode ((CORBA_TypeCode)&TC_TypeCode_struct)
++#define TC_Principal ((CORBA_TypeCode)&TC_Principal_struct)
++#define TC_Object ((CORBA_TypeCode)&TC_Object_struct)
++#define TC_string ((CORBA_TypeCode)&TC_string_struct)
++#define TC_wstring ((CORBA_TypeCode)&TC_wstring_struct)
++#define TC_CORBA_NamedValue ((CORBA_TypeCode)&TC_CORBA_NamedValue_struct)
++
++#define TC_CORBA_short_struct TC_short_struct
++#define TC_CORBA_long_struct TC_long_struct
++#define TC_CORBA_longlong_struct TC_longlong_struct
++#define TC_CORBA_long_long_struct TC_longlong_struct
++#define TC_CORBA_ushort_struct TC_ushort_struct
++#define TC_CORBA_unsigned_short_struct TC_ushort_struct
++#define TC_CORBA_ulong_struct TC_ulong_struct
++#define TC_CORBA_unsigned_long_struct TC_ulong_struct
++#define TC_CORBA_ulonglong_struct TC_ulonglong_struct
++#define TC_CORBA_unsigned_long_long_struct TC_ulonglong_struct
++#define TC_CORBA_float_struct TC_float_struct
++#define TC_CORBA_double_struct TC_double_struct
++#define TC_CORBA_longdouble_struct TC_longdouble_struct
++#define TC_CORBA_long_double_struct TC_longdouble_struct
++#define TC_CORBA_boolean_struct TC_boolean_struct
++#define TC_CORBA_char_struct TC_char_struct
++#define TC_CORBA_wchar_struct TC_wchar_struct
++#define TC_CORBA_octet_struct TC_octet_struct
++#define TC_CORBA_any_struct TC_any_struct
++#define TC_CORBA_TypeCode_struct TC_TypeCode_struct
++#define TC_CORBA_Principal_struct TC_Principal_struct
++#define TC_CORBA_Object_struct TC_Object_struct
++#define TC_CORBA_string_struct TC_string_struct
++#define TC_CORBA_wstring_struct TC_wstring_struct
++
++extern const struct CORBA_TypeCode_struct TC_null_struct;
++extern const struct CORBA_TypeCode_struct TC_void_struct;
++extern const struct CORBA_TypeCode_struct TC_short_struct;
++extern const struct CORBA_TypeCode_struct TC_long_struct;
++extern const struct CORBA_TypeCode_struct TC_longlong_struct;
++extern const struct CORBA_TypeCode_struct TC_ushort_struct;
++extern const struct CORBA_TypeCode_struct TC_ulong_struct;
++extern const struct CORBA_TypeCode_struct TC_ulonglong_struct;
++extern const struct CORBA_TypeCode_struct TC_float_struct;
++extern const struct CORBA_TypeCode_struct TC_double_struct;
++extern const struct CORBA_TypeCode_struct TC_longdouble_struct;
++extern const struct CORBA_TypeCode_struct TC_boolean_struct;
++extern const struct CORBA_TypeCode_struct TC_char_struct;
++extern const struct CORBA_TypeCode_struct TC_wchar_struct;
++extern const struct CORBA_TypeCode_struct TC_octet_struct;
++extern const struct CORBA_TypeCode_struct TC_any_struct;
++extern const struct CORBA_TypeCode_struct TC_TypeCode_struct;
++extern const struct CORBA_TypeCode_struct TC_Principal_struct;
++extern const struct CORBA_TypeCode_struct TC_Object_struct;
++extern const struct CORBA_TypeCode_struct TC_string_struct;
++extern const struct CORBA_TypeCode_struct TC_wstring_struct;
++extern const struct CORBA_TypeCode_struct TC_CORBA_NamedValue_struct;
++
++
++#endif /* !_ORBIT_CORBA_TYPECODE_H_ */
++
++
++
++
+diff -urN linux-2.4.1/net/korbit/orb/corba_typecode_type.h linux-2.4.1-korbit/net/korbit/orb/corba_typecode_type.h
+--- linux-2.4.1/net/korbit/orb/corba_typecode_type.h Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/orb/corba_typecode_type.h Thu Feb 1 16:20:50 2001
+@@ -0,0 +1,66 @@
++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
++
++/*
++ * ORBit: A CORBA v2.2 ORB
++ *
++ * Copyright (C) 1998 Richard H. Porter
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Library General Public
++ * License as published by the Free Software Foundation; either
++ * version 2 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Library General Public License for more details.
++ *
++ * You should have received a copy of the GNU Library General Public
++ * License along with this library; if not, write to the Free
++ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Author: Dick Porter <dick@cymru.net>
++ *
++ */
++
++#ifndef _ORBIT_CORBA_TYPECODE_TYPE_H_
++#define _ORBIT_CORBA_TYPECODE_TYPE_H_
++
++#include <ORBitutil/basic_types.h>
++#include "corba_typecode.h"
++#include "corba_any.h"
++
++typedef struct CORBA_TypeCode_Bounds {
++ int dummy;
++} CORBA_TypeCode_Bounds;
++
++typedef struct CORBA_TypeCode_BadKind {
++ int dummy;
++} CORBA_TypeCode_BadKind;
++
++struct CORBA_TypeCode_struct {
++ struct ORBit_PseudoObject_struct parent;
++ CORBA_TCKind kind;
++#ifndef __KORBIT__
++ const
++#endif
++ char *name;
++#ifndef __KORBIT__
++ const
++#endif
++ char *repo_id;
++ CORBA_unsigned_long length;
++ CORBA_unsigned_long sub_parts;
++ const char **subnames; /* for struct, exception, union, enum */
++ CORBA_TypeCode *subtypes; /* for struct, exception, union, alias, array, sequence */
++ CORBA_any *sublabels; /* for union */
++ CORBA_TypeCode discriminator; /* for union */
++ CORBA_unsigned_long recurse_depth; /* for recursive sequence */
++ CORBA_long default_index; /* for union */
++ CORBA_unsigned_short digits; /* for fixed */
++ CORBA_short scale; /* for fixed */
++};
++
++
++#endif /* !_ORBIT_CORBA_TYPECODE_TYPE_H_ */
++
+diff -urN linux-2.4.1/net/korbit/orb/dii.c linux-2.4.1-korbit/net/korbit/orb/dii.c
+--- linux-2.4.1/net/korbit/orb/dii.c Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/orb/dii.c Thu Feb 1 11:47:12 2001
+@@ -0,0 +1,454 @@
++/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
++
++/*
++ * ORBit: A CORBA v2.2 ORB
++ *
++ * Copyright (C) 1998 Red Hat Software, Richard H. Porter
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Library General Public
++ * License as published by the Free Software Foundation; either
++ * version 2 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Library General Public License for more details.
++ *
++ * You should have received a copy of the GNU Library General Public
++ * License along with this library; if not, write to the Free
++ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Author: Elliot Lee <sopwith@redhat.com>
++ * Dick Porter <dick@cymru.net>
++ *
++ */
++
++#include <stdlib.h>
++#include <string.h>
++#include <assert.h>
++
++#include "orbit.h"
++#ifndef __KORBIT__
++#include "interface_repository.h"
++#endif /* !__KORBIT__ */
++
++struct CORBA_Request_type {
++ struct ORBit_PseudoObject_struct parent;
++
++ CORBA_Object obj;
++ CORBA_Context ctx;
++
++ CORBA_Flags req_flags;
++ CORBA_Identifier operation;
++
++ CORBA_NamedValue *result;
++ CORBA_NVList *arg_list;
++
++ CORBA_unsigned_long request_id;
++ GIOPSendBuffer *request_buffer;
++ GIOPRecvBuffer *reply_buffer;
++};
++
++static const ORBit_RootObject_Interface interface_CORBA_Request = {
++ (void (*)(gpointer,CORBA_Environment *))CORBA_Request_delete
++};
++
++/* Section 5.2.1 */
++CORBA_Status
++CORBA_Object_create_request(CORBA_Object obj,
++ CORBA_Context ctx,
++ CORBA_Identifier operation,
++ CORBA_NVList *arg_list,
++ CORBA_NamedValue *result,
++ CORBA_Request *request,
++ CORBA_Flags req_flags,
++ CORBA_Environment *ev)
++{
++ CORBA_Request new;
++
++ new=g_new0(struct CORBA_Request_type, 1);
++ ORBit_pseudo_object_init((ORBit_PseudoObject)new, ORBIT_PSEUDO_REQUEST, ev);
++ ORBit_RootObject_set_interface((ORBit_RootObject)new,
++ (ORBit_RootObject_Interface *)&interface_CORBA_Request, ev);
++
++ if(new==NULL) {
++ CORBA_exception_set_system(ev,
++ ex_CORBA_NO_MEMORY,
++ CORBA_COMPLETED_NO);
++ return;
++ }
++
++ new->obj=CORBA_Object_duplicate(obj, ev);
++ new->ctx=(CORBA_Context)CORBA_Object_duplicate((CORBA_Object)ctx, ev);
++ new->operation=CORBA_string_dup(operation);
++
++ new->result=result;
++
++ new->req_flags=req_flags;
++ new->request_id = giop_get_request_id();
++ new->arg_list = arg_list;
++
++ *request=(CORBA_Request)CORBA_Object_duplicate((CORBA_Object)new, ev);
++}
++
++/* Section 5.2, 5.2.2 */
++CORBA_Status
++CORBA_Request_add_arg(CORBA_Request req,
++ CORBA_Identifier name,
++ CORBA_TypeCode arg_type,
++ void *value,
++ CORBA_long len,
++ CORBA_Flags arg_flags,
++ CORBA_Environment *ev)
++{
++ gpointer new_value;
++
++ g_assert(req!=NULL);
++
++ if((arg_flags & CORBA_IN_COPY_VALUE) && (arg_flags & CORBA_ARG_IN)) {
++ new_value = ORBit_copy_value(value, arg_type);
++ if(new_value==NULL) {
++ CORBA_exception_set_system(ev, ex_CORBA_NO_MEMORY,
++ CORBA_COMPLETED_NO);
++ return;
++ }
++ } else
++ new_value=value;
++
++ CORBA_NVList_add_item(req->arg_list, name, arg_type,
++ new_value, len, arg_flags | req->req_flags, ev);
++}
++
++/* Section 5.2, 5.2.3 */
++CORBA_Status
++CORBA_Request_invoke(CORBA_Request req,
++ CORBA_Flags invoke_flags,
++ CORBA_Environment *ev)
++{
++ CORBA_Request_send(req, invoke_flags, ev);
++ if(ev->_major == CORBA_NO_EXCEPTION)
++ CORBA_Request_get_response(req, invoke_flags, ev);
++}
++
++/* Section 5.2, 5.2.4 */
++CORBA_Status CORBA_Request_delete(CORBA_Request req, CORBA_Environment *ev)
++{
++ CORBA_Object_release(req->obj, ev);
++ CORBA_Object_release((CORBA_Object)req->ctx, ev);
++
++ if(req->operation != NULL)
++ CORBA_free(req->operation);
++
++ if(req->arg_list != NULL) {
++ if(req->req_flags & CORBA_OUT_LIST_MEMORY)
++ CORBA_NVList_free(req->arg_list, ev);
++ else {
++ int i;
++ for(i = 0; i < req->arg_list->list->len; i++)
++ ORBit_NamedValue_free(&g_array_index(req->arg_list->list,
++ CORBA_NamedValue, i));
++ g_array_free(req->arg_list->list, TRUE);
++
++ g_free(req->arg_list);
++ }
++ }
++
++ if(req->result!=NULL)
++ ORBit_NamedValue_free(req->result);
++
++ if(req->request_buffer)
++ giop_send_buffer_unuse(req->request_buffer);
++
++ if(req->reply_buffer)
++ giop_recv_buffer_unuse(req->reply_buffer);
++
++ g_free(req);
++}
++
++/* Section 5.2, 5.3.1 */
++CORBA_Status
++CORBA_Request_send(CORBA_Request req,
++ CORBA_Flags invoke_flags,
++ CORBA_Environment *ev)
++{
++ int i;
++ GIOPConnection *cnx;
++
++ struct { CORBA_unsigned_long opstrlen; char opname[1]; } *opnameinfo;
++ struct iovec opvec = { NULL, 0 };
++
++ opvec.iov_len = strlen(req->operation)+1+sizeof(CORBA_unsigned_long);
++
++ opnameinfo = g_malloc(strlen(req->operation)+1+sizeof(CORBA_unsigned_long));
++ opvec.iov_base = (gpointer)opnameinfo;
++ opnameinfo->opstrlen = strlen(req->operation) + 1;
++ strcpy(opnameinfo->opname, req->operation);
++
++ cnx = ORBit_object_get_connection(req->obj);
++
++ g_assert(req->obj->active_profile);
++ req->request_buffer =
++ giop_send_request_buffer_use(req->obj->connection,
++ NULL,
++ req->request_id,
++ req->result?TRUE:FALSE,
++ &(req->obj->active_profile->object_key_vec),
++ &opvec,
++ &ORBit_default_principal_iovec
++ );
++
++ if(!req->request_buffer) {
++ CORBA_exception_set_system(ev,
++ ex_CORBA_COMM_FAILURE,
++ CORBA_COMPLETED_NO);
++ return;
++ }
++
++ for(i = 0; i < req->arg_list->list->len; i++) {
++ CORBA_NamedValue *nv;
++
++ nv = &g_array_index(req->arg_list->list, CORBA_NamedValue, i);
++
++ if((nv->arg_modes & CORBA_ARG_IN)
++ || (nv->arg_modes & CORBA_ARG_INOUT))
++ ORBit_marshal_arg(req->request_buffer,
++ nv->argument._value,
++ nv->argument._type);
++ }
++
++ giop_send_buffer_write(req->request_buffer);
++
++ giop_send_buffer_unuse(req->request_buffer);
++ req->request_buffer = 0;
++
++ g_free(opnameinfo);
++}
++
++/* Section 5.3.2 */
++CORBA_Status
++CORBA_send_multiple_requests(CORBA_Request *reqs,
++ CORBA_Environment *env,
++ CORBA_long count,
++ CORBA_Flags invoke_flags)
++{
++ int i;
++
++ for(i = 0; i < count; i++)
++ CORBA_Request_send(reqs[i], invoke_flags, env);
++}
++
++void
++ORBit_handle_dii_reply(CORBA_Request req, CORBA_Environment *ev)
++{
++ int i;
++
++ /* XXX TODO - handle exceptions, location forwards(?), all that */
++ req->result->argument._value =
++ ORBit_demarshal_arg(req->reply_buffer, req->result->argument._type,
++ TRUE, req->obj->orb);
++ req->result->argument._release = CORBA_TRUE;
++
++ for(i = 0; i < req->arg_list->list->len; i++) {
++ CORBA_NamedValue *nv;
++
++ nv = &g_array_index(req->arg_list->list, CORBA_NamedValue, i);
++
++ if(nv->arg_modes & CORBA_ARG_INOUT) {
++ CORBA_Object_duplicate((CORBA_Object)nv->argument._type, NULL);
++ CORBA_any__free(&nv->argument, NULL, TRUE);
++ }
++
++ if((nv->arg_modes & CORBA_ARG_OUT)
++ || (nv->arg_modes & CORBA_ARG_INOUT))
++ nv->argument._value = ORBit_demarshal_arg(req->reply_buffer,
++ nv->argument._type,
++ TRUE, req->obj->orb);
++ }
++
++ giop_recv_buffer_unuse(req->reply_buffer);
++ req->reply_buffer = 0;
++}
++
++/* Section 5.2, 5.3.3
++ *
++ * Raises: WrongTransaction
++ */
++CORBA_Status
++CORBA_Request_get_response(CORBA_Request req,
++ CORBA_Flags response_flags,
++ CORBA_Environment *ev)
++{
++ req->reply_buffer = giop_recv_reply_buffer_use(req->request_id,
++ !(response_flags & CORBA_RESP_NO_WAIT));
++
++ if(!req->reply_buffer) {
++ CORBA_exception_set_system(ev,
++ ex_CORBA_COMM_FAILURE,
++ CORBA_COMPLETED_NO);
++ return;
++ }
++
++ ORBit_handle_dii_reply(req, ev);
++}
++
++/* Section 5.3.4
++ *
++ * Raises: WrongTransaction
++ */
++CORBA_Status
++CORBA_Request_get_next_response(CORBA_Environment *env,
++ CORBA_Flags response_flags,
++ CORBA_Request *req)
++{
++ int i;
++ GIOPRecvBuffer *rb;
++ GArray *reqids = g_array_new(FALSE, FALSE,
++ sizeof(CORBA_unsigned_long));
++
++ for(i = 0; req[i]; i++) {
++ g_array_append_val(reqids, req[i]->request_id);
++ }
++
++ rb = giop_recv_reply_buffer_use_multiple(reqids,
++ !(response_flags & CORBA_RESP_NO_WAIT));
++
++ if(rb) {
++ for(i = 0; i < reqids->len; i++) {
++ if(g_array_index(reqids, CORBA_unsigned_long, i)
++ == rb->message.u.reply.request_id) {
++ req[i]->reply_buffer = rb;
++ break;
++ }
++ }
++
++ if(i < reqids->len)
++ ORBit_handle_dii_reply(req[i], env);
++ }
++
++ g_array_free(reqids, TRUE);
++}
++
++
++/* Section 5.4.1 */
++CORBA_Status
++CORBA_ORB_create_list(CORBA_ORB orb,
++ CORBA_long count,
++ CORBA_NVList **new_list,
++ CORBA_Environment *ev)
++{
++ CORBA_NVList *new;
++
++ new = g_new0(CORBA_NVList, 1);
++ if(new==NULL) goto new_alloc_failed;
++
++ new->list = g_array_new(FALSE, TRUE, sizeof(CORBA_NamedValue));
++
++ *new_list = new;
++
++ return;
++
++ new_alloc_failed:
++ CORBA_exception_set_system(ev, ex_CORBA_NO_MEMORY, CORBA_COMPLETED_NO);
++}
++
++#ifndef __KORBIT__
++/* Section 5.4.6 */
++CORBA_Status
++CORBA_ORB_create_operation_list(CORBA_ORB orb,
++ CORBA_OperationDef oper,
++ CORBA_NVList **new_list,
++ CORBA_Environment *ev)
++{
++ if(!new_list) {
++ CORBA_exception_set_system(ev,
++ ex_CORBA_BAD_PARAM,
++ CORBA_COMPLETED_NO);
++ return;
++ }
++
++ g_warning("CORBA_ORB_create_operation_list NYI");
++
++ CORBA_exception_set_system(ev,
++ ex_CORBA_IMP_LIMIT,
++ CORBA_COMPLETED_NO);
++}
++#endif /* !__KORBIT__ */
++
++/* Section 5.4.2 */
++CORBA_Status
++CORBA_NVList_add_item(CORBA_NVList *list,
++ CORBA_Identifier item_name,
++ CORBA_TypeCode item_type,
++ void *value,
++ CORBA_long value_len,
++ CORBA_Flags item_flags,
++ CORBA_Environment *ev)
++{
++ CORBA_NamedValue newval;
++
++ g_assert(list!=NULL);
++
++ newval.name = CORBA_string_dup(item_name);
++ newval.argument._type = (CORBA_TypeCode)CORBA_Object_duplicate((CORBA_Object)item_type, ev);
++ if(item_flags & CORBA_IN_COPY_VALUE) {
++ newval.argument._value = ORBit_copy_value(value, item_type);
++ newval.argument._release = CORBA_TRUE;
++ } else {
++ newval.argument._value = value;
++ newval.argument._release = CORBA_FALSE;
++ }
++
++ newval.len = value_len; /* Is this even useful? *sigh* */
++ newval.arg_modes = item_flags;
++
++ g_array_append_val(list->list, newval);
++}
++
++void ORBit_NamedValue_free(CORBA_NamedValue *nv)
++{
++ CORBA_free(nv->name);
++}
++
++/* Section 5.4.3 */
++CORBA_Status
++CORBA_NVList_free(CORBA_NVList *list,
++ CORBA_Environment *ev)
++{
++ int i;
++
++ CORBA_NVList_free_memory(list, ev);
++
++ for(i = 0; i < list->list->len; i++)
++ ORBit_NamedValue_free(&g_array_index(list->list, CORBA_NamedValue, i));
++
++ g_array_free(list->list, TRUE);
++
++ g_free(list);
++}
++
++/* Section 5.4.4 */
++CORBA_Status
++CORBA_NVList_free_memory(CORBA_NVList *list,
++ CORBA_Environment *ev)
++{
++ int i;
++
++ for(i = 0; i < list->list->len; i++) {
++ CORBA_free(g_array_index(list->list, CORBA_NamedValue, i).argument._value);
++ g_array_index(list->list, CORBA_NamedValue, i).argument._value = NULL;
++ CORBA_Object_release((CORBA_Object)g_array_index(list->list, CORBA_NamedValue, i).argument._type, ev);
++ g_array_index(list->list, CORBA_NamedValue, i).argument._release = CORBA_FALSE;
++ }
++}
++
++
++/* Section 5.4.5 */
++CORBA_Status
++CORBA_NVList_get_count(CORBA_NVList *list,
++ CORBA_long *count,
++ CORBA_Environment *ev)
++{
++ *count = list->list->len;
++}
++
+diff -urN linux-2.4.1/net/korbit/orb/dii.h linux-2.4.1-korbit/net/korbit/orb/dii.h
+--- linux-2.4.1/net/korbit/orb/dii.h Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/orb/dii.h Thu Feb 1 11:47:12 2001
+@@ -0,0 +1,124 @@
++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
++
++/*
++ * ORBit: A CORBA v2.2 ORB
++ *
++ * Copyright (C) 1998 Richard H. Porter
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Library General Public
++ * License as published by the Free Software Foundation; either
++ * version 2 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Library General Public License for more details.
++ *
++ * You should have received a copy of the GNU Library General Public
++ * License along with this library; if not, write to the Free
++ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Author: Dick Porter <dick@cymru.net>
++ *
++ */
++
++#ifndef _ORBIT_DII_H_
++#define _ORBIT_DII_H_
++
++#include "orb/orbit_types.h"
++#ifndef __KORBIT__
++#include "orb/interface_repository.h"
++#endif /* !__KORBIT__ */
++
++extern CORBA_Status CORBA_Object_create_request(
++ CORBA_Object obj,
++ CORBA_Context ctx,
++ CORBA_Identifier operation,
++ CORBA_NVList *arg_list,
++ CORBA_NamedValue *result,
++ CORBA_Request *request,
++ CORBA_Flags req_flags,
++ CORBA_Environment *ev);
++
++extern CORBA_Status CORBA_Request_add_arg(
++ CORBA_Request req,
++ CORBA_Identifier name,
++ CORBA_TypeCode arg_type,
++ void *value,
++ CORBA_long len,
++ CORBA_Flags arg_flags,
++ CORBA_Environment *ev);
++
++extern CORBA_Status CORBA_Request_invoke(
++ CORBA_Request req,
++ CORBA_Flags invoke_flags,
++ CORBA_Environment *ev);
++
++extern CORBA_Status CORBA_Request_delete(
++ CORBA_Request req,
++ CORBA_Environment *ev);
++
++extern CORBA_Status CORBA_Request_send(
++ CORBA_Request req,
++ CORBA_Flags invoke_flags,
++ CORBA_Environment *ev);
++
++extern CORBA_Status CORBA_send_multiple_requests(
++ CORBA_Request reqs[],
++ CORBA_Environment *env,
++ CORBA_long count,
++ CORBA_Flags invoke_flags);
++
++extern CORBA_Status CORBA_Request_get_response(
++ CORBA_Request req,
++ CORBA_Flags response_flags,
++ CORBA_Environment *ev);
++
++extern CORBA_Status CORBA_get_next_response(
++ CORBA_Environment *env,
++ CORBA_Flags response_flags,
++ CORBA_Request *req);
++
++extern CORBA_Status CORBA_NVList_add_item(
++ CORBA_NVList *list,
++ CORBA_Identifier item_name,
++ CORBA_TypeCode item_type,
++ void *value,
++ CORBA_long value_len,
++ CORBA_Flags item_flags,
++ CORBA_Environment *ev);
++
++extern void ORBit_NamedValue_free(
++ CORBA_NamedValue *nv);
++
++
++extern CORBA_Status CORBA_ORB_create_list(
++ CORBA_ORB orb,
++ CORBA_long count,
++ CORBA_NVList **new_list,
++ CORBA_Environment *ev);
++
++#ifndef __KORBIT__
++extern CORBA_Status CORBA_ORB_create_operation_list(
++ CORBA_ORB orb,
++ CORBA_OperationDef oper,
++ CORBA_NVList **new_list,
++ CORBA_Environment *ev);
++#endif /* !__KORBIT__ */
++
++extern CORBA_Status CORBA_NVList_free(CORBA_NVList *list,
++ CORBA_Environment *ev);
++
++extern CORBA_Status CORBA_NVList_free_memory(
++ CORBA_NVList *list,
++ CORBA_Environment *ev);
++
++extern CORBA_Status CORBA_NVList_get_count(
++ CORBA_NVList *list,
++ CORBA_long *count,
++ CORBA_Environment *ev);
++
++extern const int sizeofs[], container_sizeofs[];
++
++#endif /* _ORBIT_DII_H_ */
+diff -urN linux-2.4.1/net/korbit/orb/env.c linux-2.4.1-korbit/net/korbit/orb/env.c
+--- linux-2.4.1/net/korbit/orb/env.c Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/orb/env.c Thu Feb 1 11:47:12 2001
+@@ -0,0 +1,345 @@
++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
++
++/*
++ * ORBit: A CORBA v2.2 ORB
++ *
++ * Copyright (C) 1998 Richard H. Porter
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Library General Public
++ * License as published by the Free Software Foundation; either
++ * version 2 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Library General Public License for more details.
++ *
++ * You should have received a copy of the GNU Library General Public
++ * License along with this library; if not, write to the Free
++ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Author: Dick Porter <dick@cymru.net>
++ *
++ */
++
++/*
++ * CORBA_Environment handling functions
++ */
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <assert.h>
++
++#include "orbit.h"
++#ifndef __KORBIT__
++#include "interface_repository.h"
++#endif /* !__KORBIT__ */
++
++struct SysExInfo {
++ const char *repo_id;
++ const int exnum;
++};
++
++static const struct SysExInfo exception_table[] = {
++ {NULL, 0},
++ {"IDL:CORBA/UNKNOWN:1.0", 1},
++ {"IDL:CORBA/BAD_PARAM:1.0", 2},
++ {"IDL:CORBA/NO_MEMORY:1.0", 3},
++ {"IDL:CORBA/IMP_LIMIT:1.0", 4},
++ {"IDL:CORBA/COMM_FAILURE:1.0", 5},
++ {"IDL:CORBA/INV_OBJREF:1.0", 6},
++ {"IDL:CORBA/NO_PERMISSION:1.0", 7},
++ {"IDL:CORBA/INTERNAL:1.0", 8},
++ {"IDL:CORBA/MARSHAL:1.0", 9},
++ {"IDL:CORBA/INITIALIZE:1.0", 10},
++ {"IDL:CORBA/NO_IMPLEMENT:1.0", 11},
++ {"IDL:CORBA/BAD_TYPECODE:1.0", 12},
++ {"IDL:CORBA/BAD_OPERATION:1.0", 13},
++ {"IDL:CORBA/NO_RESOURCES:1.0", 14},
++ {"IDL:CORBA/NO_RESPONSE:1.0", 15},
++ {"IDL:CORBA/PERSIST_STORE:1.0", 16},
++ {"IDL:CORBA/BAD_INV_ORDER:1.0", 17},
++ {"IDL:CORBA/TRANSIENT:1.0", 18},
++ {"IDL:CORBA/FREE_MEM:1.0", 19},
++ {"IDL:CORBA/INV_IDENT:1.0", 20},
++ {"IDL:CORBA/INV_FLAG:1.0", 21},
++ {"IDL:CORBA/INTF_REPOS:1.0", 22},
++ {"IDL:CORBA/BAD_CONTEXT:1.0", 23},
++ {"IDL:CORBA/OBJ_ADAPTER:1.0", 24},
++ {"IDL:CORBA/DATA_CONVERSION:1.0", 25},
++ {"IDL:CORBA/OBJECT_NOT_EXIST:1.0", 26},
++ {"IDL:CORBA/TRANSACTION_REQUIRED:1.0", 27},
++ {"IDL:CORBA/TRANSACTION_ROLLEDBACK:1.0", 28},
++ {"IDL:CORBA/INVALID_TRANSACTION:1.0", 29},
++ {NULL,0}
++};
++
++void CORBA_exception_free(CORBA_Environment *ev)
++{
++ g_assert(ev!=NULL);
++
++ ev->_major=CORBA_NO_EXCEPTION;
++
++ if(ev->_repo_id) {
++ CORBA_free(ev->_repo_id);
++ ev->_repo_id=NULL;
++ }
++
++ if(ev->_params) {
++ CORBA_free(ev->_params);
++ ev->_params=NULL;
++ }
++
++ if(ev->_any) {
++ CORBA_free(ev->_any);
++ ev->_any=NULL;
++ }
++}
++
++void CORBA_exception_set(CORBA_Environment *ev, CORBA_exception_type major,
++ const CORBA_char *except_repos_id, void *param)
++{
++ g_assert(ev!=NULL);
++
++ if(ev->_major != CORBA_NO_EXCEPTION)
++ CORBA_exception_free(ev);
++
++ ev->_major=major;
++
++ if(except_repos_id==NULL) {
++ ev->_repo_id=NULL;
++ } else {
++ ev->_repo_id=CORBA_string_dup(except_repos_id);
++ }
++
++ ev->_params=param;
++}
++
++void CORBA_exception_set_system(CORBA_Environment *ev, CORBA_unsigned_long ex_value,
++ CORBA_completion_status completed)
++{
++ CORBA_SystemException *new;
++
++ new=ORBit_alloc(sizeof(CORBA_SystemException), NULL, NULL);
++ if(new!=NULL) {
++ new->minor=0;
++ new->completed=completed;
++
++ /* XXX what should the repo ID be? */
++ CORBA_exception_set(ev, CORBA_SYSTEM_EXCEPTION,
++ exception_table[ex_value].repo_id,
++ new);
++ }
++}
++
++void CORBA_exception_init(CORBA_Environment *ev)
++{
++ g_assert(ev!=NULL);
++
++ ev->_major=CORBA_NO_EXCEPTION;
++ ev->_repo_id=NULL;
++ ev->_params=NULL;
++ ev->_any=NULL;
++}
++
++CORBA_char *CORBA_exception_id(CORBA_Environment *ev)
++{
++ g_assert(ev!=NULL);
++
++ if(ev->_major==CORBA_NO_EXCEPTION) {
++ return(NULL);
++ } else {
++ return(ev->_repo_id);
++ }
++}
++
++void *CORBA_exception_value(CORBA_Environment *ev)
++{
++ g_assert(ev!=NULL);
++
++ if(ev->_major==CORBA_NO_EXCEPTION) {
++ return(NULL);
++ } else {
++ return(ev->_params);
++ }
++}
++
++#ifndef __KORBIT__
++CORBA_any *CORBA_exception_as_any(CORBA_Environment *ev)
++{
++ g_assert(ev!=NULL);
++
++ if(ev->_major==CORBA_NO_EXCEPTION) {
++ return(NULL);
++ }
++
++ if(ev->_any!=NULL) {
++ return(ev->_any);
++ }
++
++ ev->_any=g_new(CORBA_any, 1);
++ if(ev->_any!=NULL) {
++ /* XXX is this the correct type? */
++ ev->_any->_type = (CORBA_TypeCode)TC_CORBA_ExceptionDescription;
++ ev->_any->_value = ev->_params;
++ ev->_any->_release = 0;
++ }
++
++ return(ev->_any);
++}
++#endif /* !__KORBIT__ */
++
++/**** ORBit_handle_exception
++ Inputs: 'rb' - a receive buffer for which an exception condition has
++ been determined
++ 'ev' - memory in which to store the exception information
++
++ 'user_exceptions' - list of user exceptions raisable
++ for this particular operation.
++ Side-effects: reinitializes '*ev'
++
++ Description:
++ During demarshalling a reply, if reply_status != CORBA_NO_EXCEPTION,
++ we must find out what exception was raised and place that information
++ in '*ev'. */
++
++void ORBit_handle_exception(GIOPRecvBuffer *rb, CORBA_Environment *ev,
++ const ORBit_exception_demarshal_info *user_exceptions,
++ CORBA_ORB orb)
++{
++ CORBA_SystemException *new;
++ CORBA_unsigned_long len, completion_status;
++ CORBA_char *my_repoid;
++
++ g_return_if_fail(GIOP_MESSAGE_BUFFER(rb)->message_header.message_type == GIOP_REPLY);
++
++ CORBA_exception_free(ev);
++
++ rb->cur = ALIGN_ADDRESS(rb->cur, sizeof(len));
++ rb->decoder(&len, rb->cur, sizeof(len));
++ /* (guchar *)rb->cur += sizeof(len); */
++ rb->cur = ((guchar *)rb->cur) + sizeof(len);
++
++ if(len) {
++ my_repoid = rb->cur;
++ rb->cur = ((guchar *)rb->cur) + len;
++ } else
++ my_repoid = NULL;
++
++ if(rb->message.u.reply.reply_status == CORBA_SYSTEM_EXCEPTION) {
++ CORBA_unsigned_long minor;
++
++ ev->_major = CORBA_SYSTEM_EXCEPTION;
++
++ rb->cur = ALIGN_ADDRESS(rb->cur, sizeof(minor));
++ rb->decoder(&minor, rb->cur, sizeof(minor));
++ rb->cur = ((guchar *)rb->cur) + sizeof(minor);
++
++ rb->cur = ALIGN_ADDRESS(rb->cur, sizeof(completion_status));
++ rb->decoder(&completion_status, rb->cur, sizeof(completion_status));
++ rb->cur = ((guchar *)rb->cur) + sizeof(completion_status);
++
++ new=ORBit_alloc(sizeof(CORBA_SystemException), NULL, NULL);
++
++ if(new!=NULL) {
++ new->minor=minor;
++ new->completed=completion_status;
++
++ /* XXX what should the repo ID be? */
++ CORBA_exception_set(ev, CORBA_SYSTEM_EXCEPTION,
++ my_repoid,
++ new);
++ }
++ } else if(rb->message.u.reply.reply_status == CORBA_USER_EXCEPTION) {
++ int i;
++
++ if(!user_exceptions) {
++ /* weirdness; they raised an exception that we don't
++ know about */
++ CORBA_exception_set_system(ev, ex_CORBA_MARSHAL,
++ CORBA_COMPLETED_MAYBE);
++ } else {
++ for(i = 0; user_exceptions[i].tc != CORBA_OBJECT_NIL;
++ i++) {
++ if(!strcmp(user_exceptions[i].tc->repo_id,
++ my_repoid))
++ break;
++ }
++
++ if(user_exceptions[i].tc == CORBA_OBJECT_NIL) {
++ /* weirdness; they raised an exception
++ that we don't know about */
++ CORBA_exception_set_system(ev, ex_CORBA_MARSHAL,
++ CORBA_COMPLETED_MAYBE);
++ } else {
++ user_exceptions[i].demarshal(rb, ev);
++ }
++ }
++ };
++
++ /* ignore LOCATION_FORWARD here, that gets handled in the stub */
++}
++
++void
++ORBit_send_system_exception(GIOPSendBuffer *send_buffer,
++ CORBA_Environment *ev)
++{
++ CORBA_unsigned_long minor;
++ CORBA_unsigned_long completion_status;
++ CORBA_SystemException *se = ev->_params;
++
++ minor = se->minor;
++ completion_status = se->completed;
++
++ ENCODER_CALL(CORBA_char, ev->_repo_id);
++ giop_send_buffer_append_mem_indirect_a(send_buffer, &minor,
++ sizeof(minor));
++ giop_send_buffer_append_mem_indirect_a(send_buffer,
++ &completion_status,
++ sizeof(completion_status));
++}
++
++void
++ORBit_send_user_exception(GIOPSendBuffer *send_buffer,
++ CORBA_Environment *ev,
++ const ORBit_exception_marshal_info *user_exceptions)
++{
++ int i;
++
++ for(i = 0; user_exceptions[i].tc != CORBA_OBJECT_NIL; i++) {
++ if(!strcmp(user_exceptions[i].tc->repo_id, ev->_repo_id))
++ break;
++ }
++
++ if(user_exceptions[i].tc == CORBA_OBJECT_NIL) {
++ CORBA_Environment fakeev;
++ CORBA_exception_init(&fakeev);
++ CORBA_exception_set_system(&fakeev, ex_CORBA_UNKNOWN,
++ CORBA_COMPLETED_MAYBE);
++ ORBit_send_system_exception(send_buffer, &fakeev);
++ CORBA_exception_free(&fakeev);
++ } else {
++ ENCODER_CALL(CORBA_char, ev->_repo_id);
++
++ if(user_exceptions[i].marshal && ev->_params)
++ user_exceptions[i].marshal(send_buffer, ev);
++ }
++}
++
++void
++ORBit_handle_system_exception(CORBA_Environment *ev,
++ CORBA_unsigned_long system_exception_minor,
++ CORBA_unsigned_long completion_status,
++ GIOPRecvBuffer *recv_buffer,
++ GIOPSendBuffer *send_buffer)
++{
++ CORBA_exception_set_system(ev, system_exception_minor, completion_status);
++
++ if(send_buffer)
++ giop_send_buffer_unuse(send_buffer);
++
++ if(recv_buffer)
++ giop_recv_buffer_unuse(recv_buffer);
++}
+diff -urN linux-2.4.1/net/korbit/orb/env.h linux-2.4.1-korbit/net/korbit/orb/env.h
+--- linux-2.4.1/net/korbit/orb/env.h Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/orb/env.h Thu Feb 1 16:21:56 2001
+@@ -0,0 +1,79 @@
++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
++
++/*
++ * ORBit: A CORBA v2.2 ORB
++ *
++ * Copyright (C) 1998, 1999 Richard H. Porter, Red Hat Software
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Library General Public
++ * License as published by the Free Software Foundation; either
++ * version 2 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Library General Public License for more details.
++ *
++ * You should have received a copy of the GNU Library General Public
++ * License along with this library; if not, write to the Free
++ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Author: Dick Porter <dick@cymru.net>
++ *
++ */
++
++#ifndef _ORBIT_ENV_H_
++#define _ORBIT_ENV_H_
++
++#include "orbit_types.h"
++
++extern void CORBA_exception_set(CORBA_Environment *ev,
++ CORBA_exception_type major,
++ const CORBA_char *except_repos_id,
++ void *param);
++
++extern void CORBA_exception_set_system(CORBA_Environment *ev,
++ CORBA_unsigned_long ex_value,
++ CORBA_completion_status completed);
++
++extern void CORBA_exception_init(CORBA_Environment *ev);
++
++extern CORBA_char *CORBA_exception_id(CORBA_Environment *e);
++
++extern void *CORBA_exception_value(CORBA_Environment *ev);
++
++extern void CORBA_exception_free(CORBA_Environment *ev);
++
++#ifndef __KORBIT__
++extern CORBA_any *CORBA_exception_as_any(CORBA_Environment *ev);
++#endif /* !__KORBIT__ */
++
++typedef struct {
++ const CORBA_TypeCode tc;
++ void (*demarshal)(GIOPRecvBuffer *_ORBIT_recv_buffer, CORBA_Environment *ev);
++} ORBit_exception_demarshal_info;
++
++typedef struct {
++ const CORBA_TypeCode tc;
++ void (*marshal)(GIOPSendBuffer *_ORBIT_send_buffer, CORBA_Environment *ev);
++} ORBit_exception_marshal_info;
++
++/* ORBit-specific */
++void ORBit_handle_exception(GIOPRecvBuffer *rb, CORBA_Environment *ev,
++ const ORBit_exception_demarshal_info *user_exceptions,
++ CORBA_ORB orb);
++void ORBit_send_system_exception(GIOPSendBuffer *send_buffer,
++ CORBA_Environment *ev);
++void ORBit_send_user_exception(GIOPSendBuffer *send_buffer,
++ CORBA_Environment *ev,
++ const ORBit_exception_marshal_info *user_exceptions);
++
++/* Used by stubs */
++void ORBit_handle_system_exception(CORBA_Environment *ev,
++ CORBA_unsigned_long system_exception_minor,
++ CORBA_unsigned_long completion_status,
++ GIOPRecvBuffer *recv_buffer,
++ GIOPSendBuffer *send_buffer);
++
++#endif /* !_ORBIT_ENV_H_ */
+diff -urN linux-2.4.1/net/korbit/orb/genrand.c linux-2.4.1-korbit/net/korbit/orb/genrand.c
+--- linux-2.4.1/net/korbit/orb/genrand.c Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/orb/genrand.c Thu Feb 1 11:47:12 2001
+@@ -0,0 +1,131 @@
++#include "genrand.h"
++#include "ORBitutil/util.h"
++#include <unistd.h>
++#include <sys/types.h>
++#include <fcntl.h>
++#include <glib.h>
++#include <signal.h>
++#include <sys/time.h>
++#include <limits.h>
++#include <stdio.h>
++#ifdef __KERNEL__
++#include <linux/random.h>
++#endif
++
++static gboolean
++genrand_dev(guchar *buffer, int buf_len)
++{
++#ifdef __KERNEL__
++ get_random_bytes(buffer, buf_len);
++#else /*! __KERNEL__*/
++ int fd;
++
++ fd = open("/dev/urandom", O_RDONLY);
++ if(fd < 0)
++ return FALSE;
++
++ if(read(fd, buffer, buf_len) < buf_len)
++ {
++ close(fd);
++ return FALSE;
++ }
++
++ close(fd);
++#endif /*! __KERNEL__*/
++
++ return TRUE;
++}
++
++#ifndef __KORBIT__
++static volatile int received_alarm = 0;
++
++static void
++handle_alarm(int signum)
++{
++ received_alarm = 1;
++}
++
++static inline guchar
++hashlong(long val)
++{
++ guchar retval, *ptr;
++ int i;
++
++ for(ptr = (guchar *)&val, i = 0; i < sizeof(val); i++)
++ retval ^= ptr[i];
++
++ return retval;
++}
++
++static gboolean
++genrand_unix(guchar *buffer, int buf_len)
++{
++ struct sigaction sa, oldsa;
++ struct itimerval it, oldit;
++ int i;
++ long min, max;
++ long *counts;
++ double diff;
++ long *uninit;
++
++ counts = alloca(buf_len * sizeof(long));
++
++ memset(&sa, 0, sizeof(sa));
++ sa.sa_handler = handle_alarm;
++ sigaction(SIGALRM, &sa, &oldsa);
++ memset(&it, 0, sizeof(it));
++ it.it_value.tv_usec = 1;
++ getitimer(ITIMER_REAL, &oldit);
++
++ for(i = 0, min = LONG_MAX, max = 0; i < buf_len; i++)
++ {
++ received_alarm = 0;
++ setitimer(ITIMER_REAL, &it, NULL);
++ for(counts[i] = 0; !received_alarm; counts[i]++);
++
++ max = MAX(counts[i], max);
++ min = MIN(counts[i], min);
++ }
++
++ if(!(max - min))
++ {
++ freeca(counts);
++ return FALSE;
++ }
++
++ diff = max - min;
++
++ uninit = alloca(buf_len * sizeof(long)); /* Purposely not initialized */
++ for(i = 0; i < buf_len; i++)
++ {
++ long diffval;
++ diffval = counts[i] - min;
++
++ buffer[i] ^= (guchar)( ((double) (diffval*256) / diff )) ^ hashlong(uninit[i]);
++ }
++
++ setitimer(ITIMER_REAL, &oldit, NULL);
++ sigaction(SIGALRM, &oldsa, NULL);
++
++ freeca(counts);
++ freeca(uninit);
++
++ return TRUE;
++}
++#endif /* !__KORBIT__ */
++
++void
++orbit_genrand(guchar *buffer, int buf_len)
++{
++ g_return_if_fail(buf_len);
++
++ if(genrand_dev(buffer, buf_len))
++ return;
++#ifndef __KORBIT__
++ else if(genrand_unix(buffer, buf_len))
++ return;
++#endif
++ else
++ g_error("Couldn't generate random data!");
++}
++
+diff -urN linux-2.4.1/net/korbit/orb/genrand.h linux-2.4.1-korbit/net/korbit/orb/genrand.h
+--- linux-2.4.1/net/korbit/orb/genrand.h Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/orb/genrand.h Thu Feb 1 11:47:12 2001
+@@ -0,0 +1,8 @@
++#ifndef ORBIT_GENRAND_H
++#define ORBIT_GENRAND_H 1
++
++#include <glib.h>
++
++void orbit_genrand(guchar *buffer, int buf_len);
++
++#endif /* ORBIT_GENRAND_H */
+diff -urN linux-2.4.1/net/korbit/orb/iop.h linux-2.4.1-korbit/net/korbit/orb/iop.h
+--- linux-2.4.1/net/korbit/orb/iop.h Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/orb/iop.h Thu Feb 1 11:47:12 2001
+@@ -0,0 +1,207 @@
++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
++
++/*
++ * ORBit: A CORBA v2.2 ORB
++ *
++ * Copyright (C) 1998 Richard H. Porter
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Library General Public
++ * License as published by the Free Software Foundation; either
++ * version 2 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Library General Public License for more details.
++ *
++ * You should have received a copy of the GNU Library General Public
++ * License along with this library; if not, write to the Free
++ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Author: Dick Porter <dick@cymru.net>
++ *
++ */
++
++#ifndef _ORBIT_IOP_H_
++#define _ORBIT_IOP_H_
++
++#include <ORBitutil/basic_types.h>
++
++#include <orb/corba_basic_sequences_type.h>
++
++#ifndef HAVE_CORBA_PRINCIPAL
++#define HAVE_CORBA_PRINCIPAL 1
++typedef CORBA_sequence_octet CORBA_Principal;
++#endif
++
++typedef CORBA_unsigned_long IOP_ProfileId;
++
++#define IOP_TAG_INTERNET_IOP 0
++#define IOP_TAG_MULTIPLE_COMPONENTS 1
++#define IOP_TAG_ORBIT_SPECIFIC 0xbadfaecal
++
++typedef struct IOP_TaggedProfile {
++ IOP_ProfileId tag;
++ CORBA_sequence_octet profile_data;
++} IOP_TaggedProfile;
++
++typedef struct CORBA_sequence_TaggedProfile {
++ CORBA_unsigned_long _maximum;
++ CORBA_unsigned_long _length;
++ IOP_TaggedProfile *_buffer;
++} CORBA_sequence_TaggedProfile;
++
++typedef struct IOP_IOR {
++ CORBA_char *type_id;
++ CORBA_sequence_TaggedProfile profiles;
++} IOP_IOR;
++
++typedef CORBA_unsigned_long IOP_ComponentId;
++
++typedef struct IOP_TaggedComponent {
++ IOP_ComponentId tag;
++ CORBA_sequence_octet component_data;
++} IOP_TaggedComponent;
++
++typedef struct CORBA_sequence_TaggedComponent {
++ CORBA_unsigned_long _maximum;
++ CORBA_unsigned_long _length;
++ IOP_TaggedComponent *_buffer;
++} CORBA_sequence_TaggedComponent;
++
++typedef struct CORBA_sequence_TaggedComponent IOP_MultipleComponentProfile;
++
++#define IOP_TAG_ORB_TYPE 0
++#define IOP_TAG_CODE_SETS 1
++#define IOP_TAG_SEC_NAME 14
++#define IOP_TAG_ASSOCIATION_OPTIONS 13
++#define IOP_TAG_GENERIC_SEC_MECH 12
++
++typedef CORBA_unsigned_long IOP_ServiceId;
++
++typedef struct IOP_ServiceContext {
++ IOP_ServiceId context_id;
++ CORBA_sequence_octet context_data;
++} IOP_ServiceContext;
++
++typedef struct CORBA_sequence_ServiceContext {
++ CORBA_unsigned_long _maximum;
++ CORBA_unsigned_long _length;
++ IOP_ServiceContext *_buffer;
++} CORBA_sequence_ServiceContext;
++
++typedef struct CORBA_sequence_ServiceContext IOP_ServiceContextList;
++
++#define IOP_TransactionService 0
++#define IOP_CodeSets 1
++
++typedef CORBA_unsigned_long CONV_FRAME_CodeSetId;
++
++typedef struct CORBA_sequence_CodeSetId {
++ CORBA_unsigned_long _maximum;
++ CORBA_unsigned_long _length;
++ CONV_FRAME_CodeSetId *_buffer;
++} CORBA_sequence_CodeSetId;
++
++typedef struct CONV_FRAME_CodeSetComponent {
++ CONV_FRAME_CodeSetId native_code_set;
++ CORBA_sequence_CodeSetId conversion_code_sets;
++} CONV_FRAME_CodeSetComponent;
++
++typedef struct CONV_FRAME_CodeSetComponentInfo {
++ CONV_FRAME_CodeSetComponent ForCharData;
++ CONV_FRAME_CodeSetComponent ForWcharData;
++} CONV_FRAME_CodeSetComponentInfo;
++
++typedef struct CONV_FRAME_CodeSetContext {
++ CONV_FRAME_CodeSetId char_data;
++ CONV_FRAME_CodeSetId wchar_data;
++} CONV_FRAME_CodeSetContext;
++
++typedef struct GIOP_Version {
++ CORBA_octet major;
++ CORBA_octet minor;
++} GIOP_Version;
++
++typedef enum {
++ GIOP_Request=0,
++ GIOP_Reply,
++ GIOP_CancelRequest,
++ GIOP_LocateRequest,
++ GIOP_LocateReply,
++ GIOP_CloseConnection,
++ GIOP_MessageError
++} GIOP_MsgType_1_0;
++
++typedef struct GIOP_MessageHeader_1_0 {
++ CORBA_char magic[4];
++ GIOP_Version GIOP_version;
++ CORBA_boolean byte_order;
++ CORBA_octet message_type;
++ CORBA_unsigned_long message_size;
++} GIOP_MessageHeader_1_0;
++
++typedef struct GIOP_MessageHeader_1_1 {
++ CORBA_char magic[4];
++ GIOP_Version GIOP_version;
++ CORBA_octet flags;
++ CORBA_octet message_type;
++ CORBA_unsigned_long message_size;
++} GIOP_MessageHeader_1_1;
++
++typedef struct GIOP_RequestHeader_1_0 {
++ IOP_ServiceContextList service_context;
++ CORBA_unsigned_long request_id;
++ CORBA_boolean response_expected;
++ CORBA_sequence_octet object_key;
++ CORBA_char *operation;
++ CORBA_Principal requesting_principal;
++} GIOP_RequestHeader_1_0;
++
++typedef struct GIOP_RequestHeader_1_1 {
++ IOP_ServiceContextList service_context;
++ CORBA_unsigned_long request_id;
++ CORBA_boolean response_expected;
++ CORBA_octet reserved[3];
++ CORBA_sequence_octet object_key;
++ CORBA_char *operation;
++ CORBA_Principal requesting_principal;
++} GIOP_RequestHeader_1_1;
++
++typedef struct GIOP_SystemExceptionReplyBody {
++ CORBA_char *exception_id;
++ CORBA_unsigned_long minor_code_value;
++ CORBA_unsigned_long completion_status;
++} GIOP_SystemExceptionReplyBody;
++
++typedef struct GIOP_CancelRequestHeader {
++ CORBA_unsigned_long request_id;
++} GIOP_CancelRequestHeader;
++
++typedef struct GIOP_LocateRequestHeader {
++ CORBA_unsigned_long request_id;
++ CORBA_sequence_octet object_key;
++} GIOP_LocateRequestHeader;
++
++typedef struct IIOP_Version {
++ CORBA_octet major;
++ CORBA_octet minor;
++} IIOP_Version;
++
++typedef struct IIOP_ProfileBody_1_0 {
++ IIOP_Version iiop_version;
++ CORBA_char *host;
++ CORBA_unsigned_short port;
++ CORBA_sequence_octet object_key;
++} IIOP_ProfileBody_1_0;
++
++typedef struct IIOP_ProfileBody_1_1 {
++ IIOP_Version iiop_version;
++ CORBA_char *host;
++ CORBA_unsigned_short port;
++ CORBA_sequence_octet object_key;
++ CORBA_sequence_TaggedComponent components;
++} IIOP_ProfileBody_1_1;
++
++#endif /* !_ORBIT_IOP_H_ */
+diff -urN linux-2.4.1/net/korbit/orb/ir.c linux-2.4.1-korbit/net/korbit/orb/ir.c
+--- linux-2.4.1/net/korbit/orb/ir.c Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/orb/ir.c Thu Feb 1 11:47:12 2001
+@@ -0,0 +1,293 @@
++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
++
++/*
++ * ORBit: A CORBA v2.2 ORB
++ *
++ * Copyright (C) 1998 Richard H. Porter
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Library General Public
++ * License as published by the Free Software Foundation; either
++ * version 2 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Library General Public License for more details.
++ *
++ * You should have received a copy of the GNU Library General Public
++ * License along with this library; if not, write to the Free
++ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Author: Dick Porter <dick@cymru.net>
++ *
++ */
++
++#include <stdlib.h>
++#include <assert.h>
++
++#include "orbit.h"
++
++/* FIXME: Right now this function doesn't record whether or not it has
++ already visited a given TypeCode. I'm not sure if every recursive
++ type will have a tk_recursive node in it; if not, then this will
++ need to be reworked a bit. */
++CORBA_boolean CORBA_TypeCode_equal(CORBA_TypeCode obj, CORBA_TypeCode tc, CORBA_Environment *ev)
++{
++ int i;
++
++ g_return_val_if_fail(obj!=NULL, CORBA_FALSE);
++ g_return_val_if_fail(tc!=NULL, CORBA_FALSE);
++
++ if (obj->kind != tc->kind) {
++ return CORBA_FALSE;
++ }
++
++ switch (obj->kind) {
++ case CORBA_tk_wstring:
++ case CORBA_tk_string:
++ return obj->length == tc->length;
++ case CORBA_tk_objref:
++ return ! strcmp (obj->repo_id, tc->repo_id);
++ case CORBA_tk_except:
++ case CORBA_tk_struct:
++ if (strcmp (obj->repo_id, tc->repo_id)
++ || obj->sub_parts != tc->sub_parts)
++ return CORBA_FALSE;
++ for (i = 0; i < obj->sub_parts; ++i)
++ if (! CORBA_TypeCode_equal (obj->subtypes[i],
++ tc->subtypes[i], ev))
++ return CORBA_FALSE;
++ break;
++ case CORBA_tk_union:
++ if (strcmp (obj->repo_id, tc->repo_id)
++ || obj->sub_parts != tc->sub_parts
++ || ! CORBA_TypeCode_equal (obj->discriminator,
++ tc->discriminator, ev)
++ || obj->default_index != tc->default_index)
++ return CORBA_FALSE;
++ for (i = 0; i < obj->sub_parts; ++i)
++
++ if (! CORBA_TypeCode_equal (obj->subtypes[i],
++ tc->subtypes[i], ev)
++ || ! ORBit_any_equivalent (obj->sublabels[i],
++ tc->sublabels[i], ev))
++ return CORBA_FALSE;
++
++ break;
++ case CORBA_tk_enum:
++ if (obj->sub_parts != tc->sub_parts
++ || strcmp (obj->repo_id, tc->repo_id))
++ return CORBA_FALSE;
++ for (i = 0; i < obj->sub_parts; ++i)
++ if (strcmp (obj->subnames[i], tc->subnames[i]))
++ return CORBA_FALSE;
++ break;
++ case CORBA_tk_sequence:
++ case CORBA_tk_array:
++ if (obj->length != tc->length)
++ return CORBA_FALSE;
++ g_assert (obj->sub_parts == 1);
++ g_assert (tc->sub_parts == 1);
++ return CORBA_TypeCode_equal (obj->subtypes[0], tc->subtypes[0],
++ ev);
++ case CORBA_tk_alias:
++ if (strcmp (obj->repo_id, tc->repo_id))
++ return CORBA_FALSE;
++
++ g_assert (obj->sub_parts == 1);
++ g_assert (tc->sub_parts == 1);
++
++ return CORBA_TypeCode_equal (obj->subtypes[0], tc->subtypes[0],
++ ev);
++ break;
++ case CORBA_tk_recursive:
++ return obj->recurse_depth == tc->recurse_depth;
++ case CORBA_tk_fixed:
++ return obj->digits == tc->digits && obj->scale == tc->scale;
++
++ default:
++ /* Everything else is primitive. */
++ break;
++ }
++
++ return CORBA_TRUE;
++}
++
++CORBA_TCKind CORBA_TypeCode_kind(CORBA_TypeCode obj, CORBA_Environment *ev)
++{
++ return obj->kind;
++}
++
++static void bad_kind (CORBA_Environment *ev)
++{
++ CORBA_TypeCode_BadKind *err;
++ err = g_new (CORBA_TypeCode_BadKind, 1);
++ if (err == NULL) {
++ CORBA_exception_set_system (ev, ex_CORBA_NO_MEMORY,
++ CORBA_COMPLETED_NO);
++ } else {
++ err->dummy = 23;
++ CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
++ "IDL:omg.org/CORBA/TypeCode/BadKind/1.0",
++ err);
++ }
++}
++
++CORBA_RepositoryId CORBA_TypeCode_id(CORBA_TypeCode obj, CORBA_Environment *ev)
++{
++ if (! (obj->kind == CORBA_tk_objref || obj->kind == CORBA_tk_struct
++ || obj->kind == CORBA_tk_enum || obj->kind == CORBA_tk_alias
++ || obj->kind == CORBA_tk_except)) {
++ bad_kind (ev);
++ return NULL;
++ }
++ return obj->repo_id;
++}
++
++CORBA_Identifier CORBA_TypeCode_name(CORBA_TypeCode obj, CORBA_Environment *ev)
++{
++ if (! (obj->kind == CORBA_tk_objref || obj->kind == CORBA_tk_struct
++ || obj->kind == CORBA_tk_enum || obj->kind == CORBA_tk_alias
++ || obj->kind == CORBA_tk_except)) {
++ bad_kind (ev);
++ return NULL;
++ }
++
++ return obj->name;
++}
++
++CORBA_unsigned_long CORBA_TypeCode_member_count(CORBA_TypeCode obj, CORBA_Environment *ev)
++{
++ if (! (obj->kind == CORBA_tk_struct || obj->kind == CORBA_tk_union
++ || obj->kind == CORBA_tk_enum)) {
++ bad_kind (ev);
++ return 0;
++ }
++ return obj->sub_parts;
++}
++
++static void bounds_error (CORBA_Environment *ev)
++{
++ CORBA_TypeCode_Bounds *err;
++ err = g_new (CORBA_TypeCode_Bounds, 1);
++ if (err == NULL) {
++ CORBA_exception_set_system (ev, ex_CORBA_NO_MEMORY,
++ CORBA_COMPLETED_NO);
++ } else {
++ err->dummy = 23;
++ CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
++ "IDL:omg.org/CORBA/TypeCode/Bounds/1.0",
++ err);
++ }
++}
++
++CORBA_Identifier CORBA_TypeCode_member_name(CORBA_TypeCode obj, CORBA_unsigned_long index, CORBA_Environment *ev)
++{
++ if (! (obj->kind == CORBA_tk_struct || obj->kind == CORBA_tk_union
++ || obj->kind == CORBA_tk_enum)) {
++ bad_kind (ev);
++ return NULL;
++ }
++ if (index > obj->sub_parts) {
++ bounds_error (ev);
++ return NULL;
++ }
++ return obj->subnames[index];
++}
++
++CORBA_TypeCode CORBA_TypeCode_member_type(CORBA_TypeCode obj, CORBA_unsigned_long index, CORBA_Environment *ev)
++{
++ if (! (obj->kind == CORBA_tk_struct || obj->kind == CORBA_tk_union
++ || obj->kind == CORBA_tk_enum)) {
++ bad_kind (ev);
++ return NULL;
++ }
++ if (index > obj->sub_parts) {
++ bounds_error (ev);
++ return NULL;
++ }
++ return obj->subtypes[index];
++}
++
++CORBA_any *CORBA_TypeCode_member_label(CORBA_TypeCode obj, CORBA_unsigned_long index, CORBA_Environment *ev)
++{
++ if (obj->kind != CORBA_tk_union) {
++ bad_kind (ev);
++ return NULL;
++ }
++ if (index > obj->sub_parts) {
++ bounds_error (ev);
++ return NULL;
++ }
++ return &obj->sublabels[index];
++}
++
++CORBA_TypeCode CORBA_TypeCode_discriminator_type(CORBA_TypeCode obj, CORBA_Environment *ev)
++{
++ if (obj->kind != CORBA_tk_union) {
++ bad_kind (ev);
++ return NULL;
++ }
++ return obj->discriminator;
++}
++
++CORBA_long CORBA_TypeCode_default_index(CORBA_TypeCode obj, CORBA_Environment *ev)
++{
++ if (obj->kind != CORBA_tk_union) {
++ bad_kind (ev);
++ return 0;
++ }
++ return obj->default_index;
++}
++
++CORBA_unsigned_long CORBA_TypeCode_length(CORBA_TypeCode obj, CORBA_Environment *ev)
++{
++ if (! (obj->kind == CORBA_tk_string || obj->kind == CORBA_tk_wstring
++ || obj->kind == CORBA_tk_array)) {
++ bad_kind (ev);
++ return 0;
++ }
++ return obj->length;
++}
++
++CORBA_TypeCode CORBA_TypeCode_content_type(CORBA_TypeCode obj, CORBA_Environment *ev)
++{
++ if (! (obj->kind == CORBA_tk_sequence || obj->kind == CORBA_tk_array
++ || obj->kind == CORBA_tk_alias)) {
++ bad_kind (ev);
++ return NULL;
++ }
++ g_assert (obj->sub_parts == 1);
++ return obj->subtypes[0];
++}
++
++CORBA_unsigned_short CORBA_TypeCode_fixed_digits(CORBA_TypeCode obj, CORBA_Environment *ev)
++{
++ if (obj->kind != CORBA_tk_fixed) {
++ bad_kind (ev);
++ return 0;
++ }
++ return obj->digits;
++}
++
++CORBA_short CORBA_TypeCode_fixed_scale(CORBA_TypeCode obj, CORBA_Environment *ev)
++{
++ if (obj->kind != CORBA_tk_fixed) {
++ bad_kind (ev);
++ return 0;
++ }
++ return obj->scale;
++}
++
++CORBA_long CORBA_TypeCode_param_count(CORBA_TypeCode obj, CORBA_Environment *ev)
++{
++ g_assert(!"Deprecated");
++ return(0);
++}
++
++CORBA_any *CORBA_TypeCode_parameter(CORBA_TypeCode obj, CORBA_long index, CORBA_Environment *ev)
++{
++ g_assert(!"Deprecated");
++ return(NULL);
++}
+diff -urN linux-2.4.1/net/korbit/orb/ir.h linux-2.4.1-korbit/net/korbit/orb/ir.h
+--- linux-2.4.1/net/korbit/orb/ir.h Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/orb/ir.h Thu Feb 1 11:47:12 2001
+@@ -0,0 +1,100 @@
++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
++
++/*
++ * ORBit: A CORBA v2.2 ORB
++ *
++ * Copyright (C) 1998 Richard H. Porter
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Library General Public
++ * License as published by the Free Software Foundation; either
++ * version 2 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Library General Public License for more details.
++ *
++ * You should have received a copy of the GNU Library General Public
++ * License along with this library; if not, write to the Free
++ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Author: Dick Porter <dick@cymru.net>
++ *
++ */
++
++#ifndef _ORBIT_IR_H_
++#define _ORBIT_IR_H_
++
++#include "orbit_types.h"
++
++extern CORBA_boolean CORBA_TypeCode_equal(
++ CORBA_TypeCode obj,
++ CORBA_TypeCode tc,
++ CORBA_Environment *ev);
++
++extern CORBA_TCKind CORBA_TypeCode_kind(
++ CORBA_TypeCode obj,
++ CORBA_Environment *ev);
++
++extern CORBA_RepositoryId CORBA_TypeCode_id(
++ CORBA_TypeCode obj,
++ CORBA_Environment *ev);
++
++extern CORBA_Identifier CORBA_TypeCode_name(
++ CORBA_TypeCode obj,
++ CORBA_Environment *ev);
++
++extern CORBA_unsigned_long CORBA_TypeCode_member_count(
++ CORBA_TypeCode obj,
++ CORBA_Environment *ev);
++
++extern CORBA_Identifier CORBA_TypeCode_member_name(
++ CORBA_TypeCode obj,
++ CORBA_unsigned_long index,
++ CORBA_Environment *ev);
++
++extern CORBA_TypeCode CORBA_TypeCode_member_type(
++ CORBA_TypeCode obj,
++ CORBA_unsigned_long index,
++ CORBA_Environment *ev);
++
++extern CORBA_any *CORBA_TypeCode_member_label(
++ CORBA_TypeCode obj,
++ CORBA_unsigned_long index,
++ CORBA_Environment *ev);
++
++extern CORBA_TypeCode CORBA_TypeCode_discriminator_type(
++ CORBA_TypeCode obj,
++ CORBA_Environment *ev);
++
++extern CORBA_long CORBA_TypeCode_default_index(
++ CORBA_TypeCode obj,
++ CORBA_Environment *ev);
++
++extern CORBA_unsigned_long CORBA_TypeCode_length(
++ CORBA_TypeCode obj,
++ CORBA_Environment *ev);
++
++extern CORBA_TypeCode CORBA_TypeCode_content_type(
++ CORBA_TypeCode obj,
++ CORBA_Environment *ev);
++
++extern CORBA_unsigned_short CORBA_TypeCode_fixed_digits(
++ CORBA_TypeCode obj,
++ CORBA_Environment *ev);
++
++extern CORBA_short CORBA_TypeCode_fixed_scale(
++ CORBA_TypeCode obj,
++ CORBA_Environment *ev);
++
++extern CORBA_long CORBA_TypeCode_param_count(
++ CORBA_TypeCode obj,
++ CORBA_Environment *ev);
++
++extern CORBA_any *CORBA_TypeCode_parameter(
++ CORBA_TypeCode obj,
++ CORBA_long index,
++ CORBA_Environment *ev);
++
++#endif /* !_ORBIT_IR_H_ */
+diff -urN linux-2.4.1/net/korbit/orb/options.c linux-2.4.1-korbit/net/korbit/orb/options.c
+--- linux-2.4.1/net/korbit/orb/options.c Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/orb/options.c Thu Feb 1 11:47:12 2001
+@@ -0,0 +1,160 @@
++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
++
++/*
++ * ORBit: A CORBA v2.2 ORB
++ *
++ * Copyright (C) 1998 Richard H. Porter
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Library General Public
++ * License as published by the Free Software Foundation; either
++ * version 2 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Library General Public License for more details.
++ *
++ * You should have received a copy of the GNU Library General Public
++ * License along with this library; if not, write to the Free
++ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Author: Dick Porter <dick@cymru.net>
++ *
++ */
++
++/*
++ * Option parsing
++ *
++ * All ORB options are stripped from the application's argv, and argc is
++ * adjusted accordingly
++ */
++
++#include <stdlib.h>
++#include <stdio.h>
++#include <string.h>
++#include <glib.h>
++
++#include "options.h"
++
++#ifndef __KORBIT__
++void ORBit_option_set(ORBit_orb_options *option, const char *val)
++{
++ g_assert(option!=NULL);
++
++ if(option->type==no_arg && option->arg!=NULL) {
++ /* Treat as an int arg with val=1
++ */
++ int *int_arg=(int *)option->arg;
++
++ *int_arg=1;
++ } else {
++ if(option->type==string_arg && option->arg!=NULL) {
++ char **str_arg=(char **)option->arg;
++
++ /* free any existing value */
++ if(*str_arg!=NULL) {
++ g_free(*str_arg);
++ }
++ *str_arg=g_strdup(val);
++ } else if(option->type==int_arg && option->arg!=NULL) {
++ int *int_arg=(int *)option->arg;
++
++ *int_arg=atoi(val);
++ }
++
++ }
++}
++
++void ORBit_option_parse(int *argc, char **argv, ORBit_orb_options *options)
++{
++ int i,j,numargs;
++ char name[1024], *val;
++ ORBit_orb_options *search=NULL;
++ int *erase;
++
++ numargs=*argc;
++
++ erase=g_new0(int, *argc);
++
++ for(i=1; i< *argc; i++) {
++ if(argv[i][0]!='-') {
++ if(search==NULL) {
++ /* Skip non-option */
++ continue;
++ } else {
++ /* an required option value has been found */
++ erase[i]=1;
++ numargs-=1;
++
++ if(search->arg==NULL) {
++ /* dont store any values, just strip
++ * the argv
++ */
++ search=NULL;
++ continue;
++ }
++
++ ORBit_option_set(search, argv[i]);
++
++ search=NULL;
++ continue;
++ }
++ } else {
++ if(search!=NULL &&
++ (search->type==string_arg || search->type==int_arg)) {
++ fprintf(stderr, "Option %s requires an argument\n", search->name);
++ }
++ }
++
++ val=argv[i];
++ while(*val && *val=='-')
++ val++;
++
++ strncpy(name,val,1023);
++ name[1023]='\0';
++
++ val=strchr(name, '=');
++ if(val!=NULL) {
++ *val++='\0';
++ }
++
++ for(search=options;search->name!=NULL;search++) {
++ if(!strcmp(name, search->name)) {
++ break;
++ }
++ }
++
++ if(search->name==NULL) {
++ /* Didn't find it in our list of interesting options */
++ search=NULL;
++ } else {
++ /* Found it */
++ erase[i]=1;
++ numargs-=1;
++
++ if(search->type==no_arg || val!=NULL) {
++ ORBit_option_set(search, val);
++ search=NULL;
++ }
++ }
++ }
++
++ j=1;
++ for(i=1; i< *argc; i++) {
++ if(erase[i]==1) {
++ continue;
++ } else {
++ if(j<numargs) {
++ argv[j++]=argv[i];
++ } else {
++ argv[j++]='\0';
++ }
++ }
++ }
++
++ *argc=numargs;
++
++ g_free(erase);
++}
++#endif /* !__KORBIT__ */
+diff -urN linux-2.4.1/net/korbit/orb/options.h linux-2.4.1-korbit/net/korbit/orb/options.h
+--- linux-2.4.1/net/korbit/orb/options.h Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/orb/options.h Thu Feb 1 11:47:13 2001
+@@ -0,0 +1,46 @@
++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
++
++/*
++ * ORBit: A CORBA v2.2 ORB
++ *
++ * Copyright (C) 1998 Richard H. Porter
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Library General Public
++ * License as published by the Free Software Foundation; either
++ * version 2 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Library General Public License for more details.
++ *
++ * You should have received a copy of the GNU Library General Public
++ * License along with this library; if not, write to the Free
++ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Author: Dick Porter <dick@cymru.net>
++ *
++ */
++
++#ifndef _ORBIT_OPTIONS_H_
++#define _ORBIT_OPTIONS_H_
++
++typedef enum {
++ no_arg=0,
++ string_arg,
++ int_arg
++} ORBit_opt_type;
++
++typedef struct {
++ char *name;
++ ORBit_opt_type type;
++ void *arg;
++} ORBit_orb_options;
++
++#ifndef __KORBIT__
++extern void ORBit_option_set(ORBit_orb_options *found, const char *val);
++extern void ORBit_option_parse(int *argc, char **argv, ORBit_orb_options *options);
++#endif
++
++#endif /* !_ORBIT_OPTIONS_H_ */
+diff -urN linux-2.4.1/net/korbit/orb/orb.c linux-2.4.1-korbit/net/korbit/orb/orb.c
+--- linux-2.4.1/net/korbit/orb/orb.c Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/orb/orb.c Thu Feb 1 11:47:13 2001
+@@ -0,0 +1,1700 @@
++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
++
++/*
++ * ORBit: A CORBA v2.2 ORB
++ *
++ * Copyright (C) 1998 Richard H. Porter and Red Hat Software
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Library General Public
++ * License as published by the Free Software Foundation; either
++ * version 2 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Library General Public License for more details.
++ *
++ * You should have received a copy of the GNU Library General Public
++ * License along with this library; if not, write to the Free
++ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Author: Dick Porter <dick@acm.org>
++ * Elliot Lee <sopwith@redhat.com>
++ *
++ */
++
++#define o_return_val_if_fail(expr, val) if(!(expr)) { CORBA_exception_set_system(ev, ex_CORBA_BAD_PARAM, CORBA_COMPLETED_NO); return (val); }
++#define o_return_if_fail(expr) if(!(expr)) { CORBA_exception_set_system(ev, ex_CORBA_BAD_PARAM, CORBA_COMPLETED_NO); return; }
++
++#include "config.h"
++
++#include <unistd.h>
++#include <errno.h>
++#include <sys/stat.h>
++#include <stdlib.h>
++#include <stdio.h>
++#include <string.h>
++#include <ctype.h>
++#include <assert.h>
++#include <pwd.h>
++#include <time.h>
++#include <sys/types.h>
++#include <dirent.h>
++#include <sys/types.h>
++#include <sys/socket.h>
++#include <sys/un.h>
++#include <utime.h>
++
++#include "../IIOP/iiop-endianP.h"
++#include "orbit.h"
++
++#include "orbit_poa.h"
++#include "orbit_object.h"
++#include "orbit_object_type.h"
++
++#ifndef __KERNEL__
++#define freeca(ptr)
++#endif
++
++#ifndef SUN_LEN
++/* This system is not POSIX.1g. */
++#define SUN_LEN(ptr) ((size_t) (((struct sockaddr_un *) 0)->sun_path) \
++ + strlen ((ptr)->sun_path))
++#endif
++
++static void ORBit_ORB_release(CORBA_ORB orb, CORBA_Environment *ev);
++
++static const ORBit_RootObject_Interface CORBA_ORB_epv =
++{
++ (void (*)(gpointer, CORBA_Environment *))ORBit_ORB_release
++};
++
++
++static int ORBit_ORBid_setup(CORBA_ORB orb, CORBA_ORBid id)
++{
++ g_assert(orb!=NULL);
++ g_assert(id!=NULL);
++
++ if(strcmp(id, "orbit-local-orb")) {
++#ifdef __KORBIT__
++ printf("ORBit_ORBid_setup: Unknown ORB id: %s\n", id);
++#else
++ fprintf(stderr, "ORBit_ORBid_setup: Unknown ORB id: %s\n", id);
++#endif
++ return(0);
++ }
++
++ orb->orb_identifier=g_strdup(id);
++
++ return(1);
++}
++
++#ifndef __KORBIT__
++static gboolean
++free_key_and_data(gpointer key, gpointer data, gpointer user_data)
++{
++ g_free(key); g_free(data);
++
++ return TRUE;
++}
++
++static void ORBit_rc_load(const char *rcfile, ORBit_orb_options *options)
++{
++ FILE *fp;
++ GHashTable *read_options;
++ ORBit_orb_options *search;
++
++ fp=fopen(rcfile, "r");
++
++ if(fp==NULL)
++ return;
++
++ read_options=g_hash_table_new(g_str_hash, g_str_equal);
++
++ while(!feof(fp)) {
++ char buf[1024];
++
++ if(fgets(buf, 1024, fp)!=NULL) {
++ guchar *bptr, *tmp, *key, *data;
++ size_t start, len;
++
++ if(buf[0]=='#')
++ continue;
++
++ bptr=buf;
++ tmp=strpbrk(bptr, " \t\n=");
++ if(tmp==NULL) continue;
++ *tmp++='\0';
++ key=g_strdup(bptr);
++ bptr=tmp;
++
++ start=0;
++ while(bptr+start != '\0' &&
++ (isspace(bptr[start]) || bptr[start]=='='))
++ start++;
++ len=strcspn(bptr+start, " \t\n");
++ bptr[start+len]='\0';
++ if(len>0) {
++ data=g_strdup(bptr+start);
++ } else {
++ data=g_strdup("TRUE");
++ }
++
++ g_hash_table_insert(read_options, key, data);
++ }
++ }
++ fclose(fp);
++
++ for(search=options;search->name!=NULL;search++) {
++ char *read_val;
++
++ read_val=g_hash_table_lookup(read_options, search->name);
++ if(read_val!=NULL) {
++ ORBit_option_set(search, read_val);
++ }
++ }
++
++ g_hash_table_foreach_remove(read_options, free_key_and_data, NULL);
++ g_hash_table_destroy(read_options);
++}
++#endif /* !__KORBIT__ */
++
++static void ORBit_ORB_release(CORBA_ORB orb, CORBA_Environment *ev)
++{
++ g_assert(orb!=NULL);
++
++ if(--(ORBIT_ROOT_OBJECT(orb)->refs))
++ return;
++
++ if(orb->orb_identifier!=NULL) {
++ g_free(orb->orb_identifier);
++ }
++ if(!CORBA_Object_is_nil(orb->imr, ev)) {
++ CORBA_Object_release(orb->imr, ev);
++ }
++ if(!CORBA_Object_is_nil(orb->ir, ev)) {
++ CORBA_Object_release(orb->ir, ev);
++ }
++ if(!CORBA_Object_is_nil(orb->naming, ev)) {
++ CORBA_Object_release(orb->naming, ev);
++ }
++ if(!CORBA_Object_is_nil(orb->root_poa, ev)) {
++ CORBA_Object_release(orb->root_poa, ev);
++ }
++ if(orb->cnx.ipv4)
++ giop_connection_unref(orb->cnx.ipv4);
++ if(orb->cnx.ipv6)
++ giop_connection_unref(orb->cnx.ipv6);
++#ifndef __KORBIT__
++ if(orb->cnx.usock)
++ giop_connection_unref(orb->cnx.usock);
++#endif
++
++ g_free(orb);
++}
++
++#ifndef __KORBIT__
++static GIOPConnection*
++ORBit_ORB_make_usock_connection(void)
++{
++ GIOPConnection *retval = NULL;
++ GString *tmpstr;
++ struct stat statbuf;
++
++ tmpstr = g_string_new(NULL);
++
++ g_string_sprintf(tmpstr, "/tmp/orbit-%s", g_get_user_name());
++
++ if(mkdir(tmpstr->str, 0700) != 0) {
++ int e = errno;
++
++ switch (e) {
++ case 0:
++ case EEXIST:
++ if (stat(tmpstr->str, &statbuf) != 0)
++ g_error ("Can not stat %s\n", tmpstr->str);
++
++ if (statbuf.st_uid != getuid ())
++ g_error ("Owner of %s is not the current user\n",
++ tmpstr->str);
++
++ if((statbuf.st_mode & (S_IRWXG|S_IRWXO))
++ || !S_ISDIR(statbuf.st_mode))
++ g_error ("Wrong permissions for %s\n",
++ tmpstr->str);
++ break;
++
++ default:
++ g_error("Unknown error on directory creation of %s (%s)\n",
++ tmpstr->str, g_strerror (e));
++ }
++ }
++
++ {
++ struct utimbuf utb;
++ memset(&utb, 0, sizeof(utb));
++ utime(tmpstr->str, &utb);
++ }
++
++
++#ifdef WE_DONT_CARE_ABOUT_STUPID_2DOT0DOTX_KERNELS
++ g_string_sprintf(tmpstr, "/tmp/orbit-%s",
++ g_get_user_name());
++ dirh = opendir(tmpstr->str);
++ while(!retval && (dent = readdir(dirh))) {
++ int usfd, ret;
++ struct sockaddr_un saddr;
++
++ saddr.sun_family = AF_UNIX;
++
++ if(strncmp(dent->d_name, "orb-", 4))
++ continue;
++
++ g_snprintf(saddr.sun_path, sizeof(saddr.sun_path),
++ "/tmp/orbit-%s/%s",
++ g_get_user_name(), dent->d_name);
++
++ usfd = socket(AF_UNIX, SOCK_STREAM, 0);
++ g_assert(usfd >= 0);
++
++ ret = connect(usfd, &saddr, SUN_LEN(&saddr));
++ close(usfd);
++
++ if(ret >= 0)
++ continue;
++
++ unlink(saddr.sun_path);
++ }
++ closedir(dirh);
++#endif /* WE_DONT_CARE_ABOUT_STUPID_2DOT0DOTX_KERNELS */
++
++ srand(time(NULL));
++ while(!retval) {
++ g_string_sprintf(tmpstr, "/tmp/orbit-%s/orb-%d%d",
++ g_get_user_name(), rand(), rand());
++ retval =
++ GIOP_CONNECTION(iiop_connection_server_unix(tmpstr->str));
++ }
++
++ g_string_free(tmpstr, TRUE);
++
++ return retval;
++}
++#endif /* !__KORBIT__ */
++
++
++// Synchronize between the user process starting up the orb and the ORB thread
++// this mutex gets released when the orb is all fired up and ready to go.
++static DECLARE_MUTEX(StartupSem);
++static CORBA_ORB TheOneTrueOrb = 0;
++
++struct CORBA_ORB_init_args { // A pointer to this struct is passed to
++ int *argc; // __CORBA_ORB_init
++ char **argv;
++ CORBA_ORBid orb_identifier;
++ CORBA_Environment *ev;
++};
++
++
++CORBA_ORB __CORBA_ORB_init(struct CORBA_ORB_init_args *Args) {
++ int *argc = Args->argc;
++ char **argv = Args->argv;
++ CORBA_ORBid orb_identifier = Args->orb_identifier;
++ CORBA_Environment *ev = Args->ev;
++
++ int no_iiop_server=0;
++ int no_iiop_proxy=0;
++#ifdef __KORBIT__
++ int use_ipv4=1;
++#else
++ int use_ipv4=0;
++#endif
++ int use_ipv6=0;
++ int use_usock=1;
++ int debug_level=0;
++ int debug_modules=0;
++ int nosysrc=0;
++ int nouserrc=0;
++ char *imr_ior=NULL, *imr_addr=NULL;
++ char *ir_ior=NULL, *ir_addr=NULL;
++ char *naming_ior=NULL, *naming_addr=NULL;
++ char *root_poa_ior=NULL, *root_poa_addr=NULL;
++ char *orb_id_opt=NULL;
++#ifndef __KORBIT__
++ char *ctmp;
++#endif
++ CORBA_ORB orb = 0;
++
++ /* The variable addresses in these structs need to be assigned at
++ * run-time if you want to compile with -pedantic
++ *
++ * (You will also get scads of warnings about "long long" too)
++ */
++
++ ORBit_orb_options pre_rc_options[]={
++ {"ORBNoSystemRC", no_arg, NULL},
++ {"ORBNoUserRC", no_arg, NULL},
++ {NULL, 0, NULL},
++ };
++
++ /* These options are compatible with MICO */
++ ORBit_orb_options options[]={
++ {"ORBNoIIOPServer", no_arg, NULL},
++ {"ORBNoIIOPProxy", no_arg, NULL},
++ {"ORBid", string_arg, NULL},
++ {"ORBImplRepoIOR", string_arg, NULL},
++ {"ORBImplRepoAddr", string_arg, NULL},
++ {"ORBIfaceRepoIOR", string_arg, NULL},
++ {"ORBIfaceRepoAddr", string_arg, NULL},
++ {"ORBNamingIOR", string_arg, NULL},
++ {"ORBNamingAddr", string_arg, NULL},
++ {"ORBDebugLevel", int_arg, NULL},
++ {"ORBBindAddr", string_arg, NULL}, /* XXX need to make
++ libIIOP support this */
++ {"ORBIIOPAddr", string_arg, NULL},
++
++ /* These options aren't */
++ {"ORBDebugModules", int_arg, NULL},
++ {"ORBRootPOAIOR", string_arg, NULL},
++ {"ORBRootPOAAddr", string_arg, NULL},
++ {"ORBIIOPUSock", int_arg, NULL},
++ {"ORBIIOPIPv4", int_arg, NULL},
++ {"ORBIIOPIPv6", int_arg, NULL},
++ {NULL,0,NULL},
++ };
++
++ if (ev == NULL || !argc || !argv || !orb_identifier) {
++ if (ev) {
++ CORBA_exception_set_system(ev, ex_CORBA_BAD_PARAM,
++ CORBA_COMPLETED_NO);
++ }
++ up(&StartupSem); // Okay, let the insmod thread continue...
++ return 0;
++ }
++
++ pre_rc_options[0].arg = (void *) &nosysrc;
++ pre_rc_options[1].arg = (void *) &nouserrc;
++ options[0].arg = (void *) &no_iiop_server;
++ options[1].arg = (void *) &no_iiop_proxy;
++ options[2].arg = (void *) &orb_id_opt;
++ options[3].arg = (void *) &imr_ior;
++ options[4].arg = (void *) &imr_addr;
++ options[5].arg = (void *) &ir_ior;
++ options[6].arg = (void *) &ir_addr;
++ options[7].arg = (void *) &naming_ior;
++ options[8].arg = (void *) &naming_addr;
++ options[9].arg = (void *) &debug_level;
++ options[12].arg = (void *) &debug_modules;
++ options[13].arg = (void *) &root_poa_ior;
++ options[14].arg = (void *) &root_poa_addr;
++ options[15].arg = (void *) &use_usock;
++ options[16].arg = (void *) &use_ipv4;
++ options[17].arg = (void *) &use_ipv6;
++
++#ifndef __KORBIT__
++ ORBit_option_parse(argc, argv, pre_rc_options);
++
++ if(!nosysrc) {
++ ORBit_rc_load(ORBit_SYSRC, options);
++ }
++
++ if(!nouserrc) {
++ char *buf;
++
++ ctmp = g_get_home_dir();
++
++ buf = alloca(strlen(ctmp) + sizeof("/.orbitrc"));
++ sprintf(buf, "%s/.orbitrc", ctmp);
++ ORBit_rc_load(buf, options);
++ freeca(buf);
++ }
++
++ ORBit_option_parse(argc, argv, options);
++#endif /* !__KORBIT__ */
++
++ ORBit_Trace_setLevel(debug_level);
++ ORBit_Trace_setModules(debug_modules);
++
++ CORBA_exception_init(ev);
++
++ ORBit_chunks_init();
++
++ giop_init(argv[0]);
++
++ orb=g_new0(struct CORBA_ORB_type, 1);
++
++ if(orb==NULL) {
++ CORBA_exception_set_system(ev, ex_CORBA_NO_MEMORY, CORBA_COMPLETED_NO);
++ goto error;
++ }
++
++ ORBit_pseudo_object_init(ORBIT_PSEUDO_OBJECT(orb), ORBIT_PSEUDO_ORB, ev);
++
++ ORBit_RootObject_set_interface(ORBIT_ROOT_OBJECT(orb),
++ (gpointer)&CORBA_ORB_epv, ev);
++
++ ORBIT_ROOT_OBJECT(orb)->refs = 1;
++
++ if(orb_id_opt!=NULL) {
++ if(!ORBit_ORBid_setup(orb, orb_id_opt))
++ goto error;
++ g_free(orb_id_opt);
++ } else if(orb_identifier!=NULL) {
++ if(!ORBit_ORBid_setup(orb, orb_identifier))
++ goto error;
++ } else {
++ orb->orb_identifier=g_strdup("orbit-local-orb");
++ }
++
++ if(orb->orb_identifier==NULL) {
++ CORBA_exception_set_system(ev, ex_CORBA_NO_MEMORY, CORBA_COMPLETED_NO);
++ goto error;
++ }
++
++ if(use_ipv4) {
++ orb->cnx.ipv4 = GIOP_CONNECTION(iiop_connection_server());
++
++ giop_connection_ref(orb->cnx.ipv4);
++ GIOP_CONNECTION(orb->cnx.ipv4)->orb_data = orb;
++ }
++
++ if(use_ipv6) {
++ orb->cnx.ipv6 = GIOP_CONNECTION(iiop_connection_server_ipv6());
++ giop_connection_ref(orb->cnx.ipv6);
++ GIOP_CONNECTION(orb->cnx.ipv6)->orb_data = orb;
++ }
++
++#ifndef __KORBIT__
++ if(use_usock) {
++ orb->cnx.usock = ORBit_ORB_make_usock_connection();
++
++ giop_connection_ref(orb->cnx.usock);
++ GIOP_CONNECTION(orb->cnx.usock)->orb_data = orb;
++ }
++#endif
++
++ orb->objrefs = g_hash_table_new((GHashFunc)g_CORBA_Object_hash,
++ (GCompareFunc)g_CORBA_Object_equal);
++ orb->poas = g_ptr_array_new();
++
++ /* when I figure out what MICO is doing with the iiop_proxy and
++ * iiop_server stuff, it'll get handled here.
++ */
++
++ /*
++ * Connect to / create implementation repository
++ */
++
++ {
++ CORBA_Object imr=NULL;
++
++ if(imr_ior!=NULL) {
++ imr=CORBA_ORB_string_to_object(orb, imr_ior, ev);
++ g_free(imr_ior);
++ } else if(imr_addr!=NULL) {
++ /*imr=CORBA_ORB_bind(orb, "IDL:omg.org/CORBA/ImplRepository:1.0", imr_addr, ev);*/
++ g_free(imr_addr);
++ }
++
++ if(!CORBA_Object_is_nil(imr, ev)) {
++ CORBA_ORB_set_initial_reference(orb, "ImplementationRepository", imr, ev);
++ }
++ }
++
++ /*
++ * Connect to / create interface repository
++ */
++
++ {
++ CORBA_Object ir=NULL;
++
++ if(ir_ior!=NULL) {
++ ir=CORBA_ORB_string_to_object(orb, ir_ior, ev);
++ g_free(ir_ior);
++ } else if(ir_addr!=NULL) {
++ /*ir=CORBA_ORB_bind(orb, "IDL:omg.org/CORBA/Repository:1.0", ir_addr, ev);*/
++ g_free(ir_addr);
++ }
++
++ if(!CORBA_Object_is_nil(ir, ev)) {
++ CORBA_ORB_set_initial_reference(orb, "InterfaceRepository", ir, ev);
++ }
++ }
++
++ /*
++ * Connect to naming service
++ */
++
++ {
++ CORBA_Object naming=NULL;
++
++ if(naming_ior!=NULL) {
++ naming=CORBA_ORB_string_to_object(orb, naming_ior, ev);
++ g_free(naming_ior);
++ } else if(naming_addr!=NULL) {
++ /*CORBA_ORB_ObjectTag tag=CORBA_ORB_string_to_tag(orb, "root", ev);*/
++
++ /*naming=CORBA_ORB_bind_tag(orb, "IDL:omg.org/CosNaming/NamingContext:1.0", tag, naming_addr, ev);*/
++ g_free(naming_addr);
++ }
++
++ if(!CORBA_Object_is_nil(naming, ev)) {
++ CORBA_ORB_set_initial_reference(orb, "NameService", naming, ev);
++ }
++ }
++
++ /*
++ * Connect to / create RootPOA
++ */
++
++ {
++ PortableServer_POA root_poa=CORBA_OBJECT_NIL;
++
++ if(root_poa_ior!=NULL) {
++ root_poa=(PortableServer_POA)
++ CORBA_ORB_string_to_object(orb,
++ root_poa_ior, ev);
++ g_free(root_poa_ior);
++ }
++
++ /* And attatch it to the orb */
++
++ if(!CORBA_Object_is_nil((CORBA_Object)root_poa, ev)) {
++ CORBA_ORB_set_initial_reference((CORBA_ORB)orb,
++ "RootPOA",
++ (CORBA_Object)root_poa,
++ ev);
++ }
++ }
++
++ ORBit_custom_run_setup(orb, ev);
++
++ if (!strcmp("server", argv[0])) // Only do this for servers.
++ TheOneTrueOrb = orb;
++ up(&StartupSem); // Okay, let the insmod thread continue...
++ return orb;
++
++error:
++ if(orb!=NULL) {
++ ORBit_ORB_release(orb, ev);
++ orb = NULL;
++ }
++ g_free(imr_ior);
++ g_free(imr_addr);
++ g_free(ir_ior);
++ g_free(ir_addr);
++ g_free(naming_ior);
++ g_free(naming_addr);
++ g_free(root_poa_ior);
++ g_free(root_poa_addr);
++ g_free(orb_id_opt);
++
++ TheOneTrueOrb = 0;
++ up(&StartupSem); // Okay, let the insmod thread continue...
++ return 0;
++}
++
++
++#if __KERNEL__
++#include <linux/smp_lock.h>
++#include <linux/proc_fs.h>
++
++// This is the main corba thread function...
++//
++void __CORBA_ORB_run(CORBA_ORB orb, CORBA_Environment *ev);
++int MainCORBAThread(void *Args) {
++ // Make a directory in /proc... yaay...
++ proc_mkdir("corba", 0);
++
++ __CORBA_ORB_init((struct CORBA_ORB_init_args*)Args);
++ if (TheOneTrueOrb == 0) return 0;
++
++ strcpy(current->comm, "korbit"); // Set the thread name...
++
++ lock_kernel(); /* This seems to be required for exit_mm */
++ exit_mm(current);
++
++ __CORBA_ORB_run(TheOneTrueOrb,
++ ((struct CORBA_ORB_init_args*)Args)->ev);
++ return 0;
++}
++#endif
++
++
++/* Section 4.4
++ *
++ * Adjusts argc and argv appropriately
++ */
++
++CORBA_ORB CORBA_ORB_init(int *argc, char **argv, CORBA_ORBid orb_identifier,
++ CORBA_Environment *ev) {
++
++ struct CORBA_ORB_init_args Args;
++ Args.argc = argc;
++ Args.argv = argv;
++ Args.orb_identifier = orb_identifier;
++ Args.ev = ev;
++
++#ifdef __KERNEL__
++ if (!strcmp(argv[0], "server")) { // Are we a server?
++ down(&StartupSem); // Grab the semaphore...
++ if (TheOneTrueOrb) {
++ CORBA_exception_init(ev);
++ goto out_success;
++ }
++
++ // This releases the semaphore when it is done initializing.
++ (void)kernel_thread(MainCORBAThread, &Args,
++ CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
++
++ // This will block until the semaphore is released by the
++ // ORB thread.
++ down(&StartupSem);
++ } else { // If we are a corba client, like CorbaFS...
++ return __CORBA_ORB_init(&Args);
++ }
++
++ out_success:
++ up(&StartupSem); // Okay, we're now here.
++#else
++ __CORBA_ORB_init(&Args);
++#endif
++ if (TheOneTrueOrb)
++ return (CORBA_ORB)CORBA_Object_duplicate((CORBA_Object)TheOneTrueOrb, ev);
++ return 0;
++}
++
++
++
++
++typedef struct {
++ CORBA_Object obj;
++ CDR_Codec *codec;
++ gboolean emit_active;
++} profile_user_data;
++
++static void ORBit_emit_profile(gpointer item, gpointer userdata)
++{
++ ORBit_Object_info *profile=(ORBit_Object_info *)item;
++ profile_user_data *data=(profile_user_data *)userdata;
++ CORBA_Object obj=data->obj;
++ CDR_Codec encaps_codec_d;
++ CDR_Codec *codec=data->codec, *encaps = &encaps_codec_d;
++ gboolean emit_active=data->emit_active;
++ static const CORBA_octet iiopversion[] = {1,0};
++ CORBA_octet codecbuf[2048];
++
++ g_assert(obj!=NULL);
++ g_assert(codec!=NULL);
++ g_assert(profile!=NULL);
++
++ if((profile == obj->active_profile) && (emit_active == FALSE))
++ return; /* we already did this one */
++
++ switch(profile->profile_type) {
++ case IOP_TAG_INTERNET_IOP:
++ CDR_codec_init_static(encaps);
++ encaps->buffer = codecbuf;
++ encaps->release_buffer = CORBA_FALSE;
++ encaps->buf_len = 2048;
++ encaps->readonly = CORBA_FALSE;
++ encaps->host_endian = encaps->data_endian = FLAG_ENDIANNESS;
++
++ CDR_put_ulong(codec, IOP_TAG_INTERNET_IOP);
++ CDR_put_octet(encaps, FLAG_ENDIANNESS);
++ CDR_put_octets(encaps, (gpointer)iiopversion, sizeof(iiopversion));
++ CDR_put_string(encaps, profile->tag.iopinfo.host);
++ CDR_put_ushort(encaps, profile->tag.iopinfo.port);
++ CDR_put_ulong(encaps, profile->object_key._length);
++ CDR_put_octets(encaps, profile->object_key._buffer,
++ profile->object_key._length);
++ CDR_put_ulong(codec, encaps->wptr);
++ CDR_put_octets(codec, encaps->buffer, encaps->wptr);
++ break;
++
++ case IOP_TAG_ORBIT_SPECIFIC:
++ CDR_codec_init_static(encaps);
++ encaps->buffer = codecbuf;
++ encaps->release_buffer = CORBA_FALSE;
++ encaps->buf_len = 2048;
++ encaps->readonly = CORBA_FALSE;
++ encaps->host_endian = encaps->data_endian = FLAG_ENDIANNESS;
++
++ CDR_put_ulong(codec, IOP_TAG_ORBIT_SPECIFIC);
++ CDR_put_octet(encaps, FLAG_ENDIANNESS);
++ CDR_put_octets(encaps, (gpointer)iiopversion, sizeof(iiopversion));
++ CDR_put_string(encaps, profile->tag.orbitinfo.unix_sock_path);
++ CDR_put_ushort(encaps, profile->tag.orbitinfo.ipv6_port);
++ CDR_put_ulong(encaps, profile->object_key._length);
++ CDR_put_octets(encaps, profile->object_key._buffer,
++ profile->object_key._length);
++ CDR_put_ulong(codec, encaps->wptr);
++ CDR_put_octets(codec, encaps->buffer, encaps->wptr);
++ break;
++
++ default:
++ g_warning("Skipping tag %d", profile->profile_type);
++ break;
++ }
++}
++
++CORBA_char *CORBA_ORB_object_to_string(CORBA_ORB orb,
++ CORBA_Object obj,
++ CORBA_Environment *ev)
++{
++ int i;
++ CDR_Codec codec_d;
++ CDR_Codec *codec = &codec_d;
++ CORBA_char *rc = NULL;
++ CORBA_unsigned_long ntags;
++ profile_user_data data;
++ CORBA_octet codecbuf[2048];
++ char *ctmp;
++
++ g_return_val_if_fail(ev, NULL);
++ o_return_val_if_fail(orb && obj, NULL);
++
++ if(!obj || !orb) {
++ CORBA_exception_set_system(ev,
++ ex_CORBA_BAD_PARAM,
++ CORBA_COMPLETED_NO);
++ return NULL;
++ }
++
++ if(ORBIT_ROOT_OBJECT(obj)->is_pseudo_object) {
++ CORBA_exception_set_system(ev,
++ ex_CORBA_MARSHAL,
++ CORBA_COMPLETED_NO);
++ return NULL;
++ }
++
++ CDR_codec_init_static(codec);
++
++ codec->buffer = codecbuf;
++ codec->release_buffer = CORBA_FALSE;
++ codec->buf_len = 2048;
++ codec->readonly = CORBA_FALSE;
++ codec->host_endian = codec->data_endian = FLAG_ENDIANNESS;
++
++ CDR_put_octet(codec, FLAG_ENDIANNESS);
++
++ CDR_put_string(codec, obj->object_id);
++ ntags = g_slist_length(obj->profile_list);
++ CDR_put_ulong(codec, ntags);
++
++ data.obj=obj;
++ data.codec=codec;
++ data.emit_active=TRUE;
++ if(obj->active_profile != NULL)
++ ORBit_emit_profile(obj->active_profile, &data); /* do this one first */
++
++ data.emit_active=FALSE;
++ g_slist_foreach(obj->profile_list, ORBit_emit_profile, &data);
++
++ rc = CORBA_string_alloc(4 + (codec->wptr * 2) + 1);
++ strcpy(rc, "IOR:");
++
++#define hexdigit(n) (((n)>9)?(n+'a'-10):(n+'0'))
++
++ for(i = 0, ctmp = rc + strlen("IOR:"); i < codec->wptr; i++) {
++ *(ctmp++) = hexdigit((((codec->buffer[i]) & 0xF0) >> 4));
++ *(ctmp++) = hexdigit(((codec->buffer[i]) & 0xF));
++ }
++ *ctmp = '\0';
++
++ {
++ /* Debug check */
++ CORBA_Object obj;
++ CORBA_Environment myev;
++
++ CORBA_exception_init(&myev);
++
++ obj = CORBA_ORB_string_to_object(orb, rc, &myev);
++
++ if (CORBA_Object_is_nil(obj, &myev)) {
++ g_warning("Bug in %s, created bad IOR `%s'\n",
++ __FUNCTION__, rc);
++ CORBA_free(rc);
++ return NULL;
++ }
++
++ CORBA_Object_release(obj, &myev);
++ }
++
++ return rc;
++}
++
++/* Quote from the GNU libc manual:
++
++ "If you try to allocate more storage than the machine can provide,
++ you don't get a clean error message. Instead you get a fatal
++ signal like the one you would get from an infinite recursion;
++ probably a segmentation violation (see section Program Error
++ Signals)."
++
++ The man page claims alloca() returns NULL on failure; this appears
++ to be a load of shit on Linux where you just get flaming death, but
++ we check anyway in case other systems work that way.
++
++ On Linux we check that the size is less than MAX_STACK_ALLOC
++
++ Note that the CORBA_alloc() calls in here can still cause
++ program abort, and really that should be fixed in a similar
++ way since our lengths are coming in from unpredictable sources
++ like files or the network.
++*/
++
++#define MAX_STACK_ALLOC 8192
++
++CORBA_Object CORBA_ORB_string_to_object(CORBA_ORB orb, CORBA_char *str,
++ CORBA_Environment *ev)
++{
++ GSList *profiles=NULL;
++ CORBA_Object retval = NULL;
++ CORBA_char *type_id;
++ ORBit_Object_info *object_info;
++ CDR_Codec codec_d, encaps_codec_d;
++ CDR_Codec *codec = &codec_d, *encaps_codec = &encaps_codec_d;
++ CORBA_octet *buffer, endian;
++ int i, j;
++ CORBA_unsigned_long len, seq_len, misclen;
++
++ g_return_val_if_fail(ev, CORBA_OBJECT_NIL);
++ o_return_val_if_fail(orb && str, CORBA_OBJECT_NIL);
++
++ if(strncmp(str, "IOR:", 4)) {
++ CORBA_exception_set_system(ev, ex_CORBA_MARSHAL,
++ CORBA_COMPLETED_NO);
++ return(CORBA_OBJECT_NIL);
++ }
++
++ CDR_codec_init_static(codec);
++ len = strlen(str);
++
++ if((len % 2) || len <= 4) {
++ CORBA_exception_set_system(ev, ex_CORBA_MARSHAL,
++ CORBA_COMPLETED_NO);
++ return(CORBA_OBJECT_NIL);
++ }
++
++ codec->buf_len = (len-4)/2;
++ buffer = alloca(codec->buf_len);
++
++ codec->buffer=buffer;
++ codec->release_buffer = CORBA_FALSE;
++ codec->readonly = TRUE;
++
++ for(j = 0, i = 4; i < len; i+=2) {
++ buffer[j++] = HEXOCTET(str[i], str[i+1]);
++ };
++
++ CDR_get_octet(codec, &endian);
++
++ codec->data_endian = endian;
++ codec->host_endian = FLAG_ENDIANNESS;
++
++ CDR_get_string_static(codec, &type_id);
++
++ CDR_get_seq_begin(codec, &seq_len);
++
++ for(i = 0; i < seq_len; i++) {
++ IOP_ProfileId tag;
++
++ object_info=g_new0(ORBit_Object_info, 1);
++
++ if (!CDR_get_ulong(codec, &tag))
++ goto error_out;
++
++ switch(tag) {
++ case IOP_TAG_INTERNET_IOP:
++ if (!CDR_get_ulong(codec, &misclen))
++ goto error_out;
++
++ CDR_codec_init_static(encaps_codec);
++
++ if (misclen > MAX_STACK_ALLOC)
++ goto error_out;
++
++ encaps_codec->buffer = alloca(misclen);
++ if (encaps_codec->buffer == NULL)
++ /* misclen was probably junk */
++ goto error_out;
++
++ encaps_codec->release_buffer = FALSE;
++ if(!CDR_buffer_gets(codec, encaps_codec->buffer, misclen))
++ goto error_out;
++
++ encaps_codec->buf_len = misclen;
++ encaps_codec->readonly = CORBA_TRUE;
++ if(!CDR_get_octet(encaps_codec, &endian))
++ goto error_out;
++ encaps_codec->data_endian = endian;
++ encaps_codec->host_endian = FLAG_ENDIANNESS;
++
++ if (encaps_codec->data_endian > 1)
++ goto error_out;
++
++ object_info->profile_type = IOP_TAG_INTERNET_IOP;
++ if(!CDR_get_octet(encaps_codec, &object_info->iiop_major))
++ goto error_out;
++ if(object_info->iiop_major != 1)
++ goto error_out;
++ if(!CDR_get_octet(encaps_codec, &object_info->iiop_minor))
++ goto error_out;
++ if(!CDR_get_string(encaps_codec, &object_info->tag.iopinfo.host))
++ goto error_out;
++ if(!CDR_get_ushort(encaps_codec, &object_info->tag.iopinfo.port))
++ goto error_out;
++ if(!CDR_get_seq_begin(encaps_codec, &object_info->object_key._length))
++ goto error_out;
++
++ object_info->object_key._maximum = 0;
++
++ /* The POA gives out ORBit_alloc()d profiles, so we have to too */
++ object_info->object_key._buffer = ORBit_alloc(object_info->object_key._length, NULL, NULL);
++ if(!CDR_buffer_gets(encaps_codec, object_info->object_key._buffer,
++ object_info->object_key._length))
++ goto error_out;
++
++ ORBit_set_object_key(object_info);
++ profiles=g_slist_append(profiles, object_info);
++ break;
++
++ case IOP_TAG_MULTIPLE_COMPONENTS:
++ /* Just skip any multiple_components data, for now */
++ if(!CDR_get_ulong(codec, &misclen))
++ goto error_out;
++
++ CDR_codec_init_static(encaps_codec);
++
++ if (misclen > MAX_STACK_ALLOC)
++ goto error_out;
++
++ encaps_codec->buf_len = misclen;
++ encaps_codec->buffer = alloca(misclen);
++ if (encaps_codec->buffer == NULL)
++ /* misclen was probably junk */
++ goto error_out;
++
++ encaps_codec->release_buffer = FALSE;
++ encaps_codec->readonly = CORBA_TRUE;
++ if(!CDR_buffer_gets(codec, encaps_codec->buffer, misclen))
++ goto error_out;
++ break;
++
++ case IOP_TAG_ORBIT_SPECIFIC:
++ if(!CDR_get_ulong(codec, &misclen))
++ goto error_out;
++
++ CDR_codec_init_static(encaps_codec);
++
++ if (misclen > MAX_STACK_ALLOC)
++ goto error_out;
++
++ encaps_codec->buffer = alloca(misclen);
++ if (encaps_codec->buffer == NULL)
++ /* misclen was probably junk */
++ goto error_out;
++
++ encaps_codec->release_buffer = FALSE;
++ if(!CDR_buffer_gets(codec, encaps_codec->buffer, misclen))
++ goto error_out;
++
++ encaps_codec->buf_len = misclen;
++ encaps_codec->readonly = CORBA_TRUE;
++
++ if(!CDR_get_octet(encaps_codec, &endian))
++ goto error_out;
++
++ encaps_codec->data_endian = endian;
++ encaps_codec->host_endian = FLAG_ENDIANNESS;
++
++ if (encaps_codec->data_endian > 1)
++ goto error_out;
++
++ object_info->profile_type=IOP_TAG_ORBIT_SPECIFIC;
++ if(!CDR_get_octet(encaps_codec, &object_info->iiop_major))
++ goto error_out;
++
++ if(object_info->iiop_major != 1)
++ goto error_out;
++ if(!CDR_get_octet(encaps_codec, &object_info->iiop_minor))
++ goto error_out;
++
++ if(!CDR_get_string(encaps_codec, &object_info->tag.orbitinfo.unix_sock_path))
++ goto error_out;
++
++ if(!CDR_get_ushort(encaps_codec, &object_info->tag.orbitinfo.ipv6_port))
++ goto error_out;
++ if(!CDR_get_seq_begin(encaps_codec, &object_info->object_key._length))
++ goto error_out;
++ object_info->object_key._maximum = 0;
++
++ /* The POA gives out ORBit_alloc()d profiles, so we have to too */
++ object_info->object_key._buffer = ORBit_alloc(object_info->object_key._length, NULL, NULL);
++ if(!CDR_buffer_gets(encaps_codec, object_info->object_key._buffer,
++ object_info->object_key._length))
++ goto error_out;
++
++ ORBit_set_object_key(object_info);
++ profiles=g_slist_append(profiles, object_info);
++ break;
++ default:
++ g_warning("Unknown tag 0x%x", tag);
++
++ /* Skip it */
++ if(!CDR_get_ulong(codec, &misclen))
++ goto error_out;
++
++ CDR_codec_init_static(encaps_codec);
++
++ if (misclen > MAX_STACK_ALLOC)
++ goto error_out;
++
++ encaps_codec->buf_len = misclen;
++ encaps_codec->buffer = alloca(misclen);
++ if (encaps_codec->buffer == NULL)
++ /* misclen was probably junk */
++ goto error_out;
++
++ encaps_codec->release_buffer = FALSE;
++ encaps_codec->readonly = CORBA_TRUE;
++ if(!CDR_buffer_gets(codec, encaps_codec->buffer, misclen))
++ goto error_out;
++
++ break;
++ }
++ }
++
++ freeca(buffer); /* Same as codec->buffer */
++ freeca(encaps_codec->buffer);
++
++ return ORBit_create_object_with_info(profiles, type_id, orb, ev);
++
++ error_out:
++
++ if(object_info) {
++ CORBA_free(object_info->object_key._buffer);
++ g_free(object_info);
++ ORBit_delete_profiles(profiles);
++ }
++
++ freeca(buffer); /* Same as codec->buffer */
++ freeca(encaps_codec->buffer);
++
++ return retval;
++}
++
++/* Section 4.1.2 */
++CORBA_boolean CORBA_ORB_get_service_information(CORBA_ORB orb, CORBA_ServiceType service_type, CORBA_ServiceInformation *service_information, CORBA_Environment *ev)
++{
++ g_assert(!"Not yet implemented");
++ return(CORBA_FALSE);
++}
++
++CORBA_Current *CORBA_ORB_get_current(CORBA_ORB orb, CORBA_Environment *ev)
++{
++ g_return_val_if_fail(ev, NULL);
++ o_return_val_if_fail(orb, NULL);
++
++ /* XXX check this over */
++ return (CORBA_Current *)GET_THREAD_DATA();
++}
++
++/* Section 4.5 */
++CORBA_ORB_ObjectIdList *CORBA_ORB_list_initial_services(CORBA_ORB orb, CORBA_Environment *ev)
++{
++ static const char *services[] = {"RootPOA"};
++ CORBA_ORB_ObjectIdList *list;
++
++ g_return_val_if_fail(ev, NULL);
++ o_return_val_if_fail(orb, NULL);
++
++ list = (CORBA_ORB_ObjectIdList *)CORBA_sequence_octet__alloc();
++ list->_maximum=list->_length= 1;
++ list->_buffer = (CORBA_ORB_ObjectId *)services;
++ CORBA_sequence_set_release((void *)list, CORBA_FALSE);
++
++ /* defined reserved references are:
++ * RootPOA
++ * POACurrent
++ * InterfaceRepository
++ * NameService
++ * TradingService
++ * SecurityCurrent
++ * TransactionCurrent
++ */
++
++ return list;
++}
++
++/* Section 4.5
++ *
++ * raises InvalidName
++ */
++CORBA_Object CORBA_ORB_resolve_initial_references(CORBA_ORB orb, CORBA_ORB_ObjectId identifier, CORBA_Environment *ev)
++{
++ g_return_val_if_fail(ev, CORBA_OBJECT_NIL);
++ o_return_val_if_fail(orb, CORBA_OBJECT_NIL);
++
++ if(!strcmp(identifier, "ImplementationRepository"))
++ return CORBA_Object_duplicate(orb->imr, ev);
++ else if(!strcmp(identifier, "InterfaceRepository"))
++ return CORBA_Object_duplicate(orb->ir, ev);
++ else if(!strcmp(identifier, "NameService"))
++ return CORBA_Object_duplicate(orb->naming, ev);
++ else if(!strcmp(identifier, "RootPOA")) {
++ if(CORBA_Object_is_nil(orb->root_poa, ev)) {
++ CORBA_PolicyList policies = {0,0,NULL,CORBA_FALSE};
++ PortableServer_POAManager poa_mgr;
++ /* Create a poa manager */
++ poa_mgr = ORBit_POAManager_new(ev);
++ poa_mgr->orb = orb;
++
++ /* Create the root poa */
++ orb->root_poa = (CORBA_Object)
++ ORBit_POA_new(orb,
++ "RootPOA",
++ poa_mgr,
++ &policies,
++ ev);
++ CORBA_Object_duplicate(orb->root_poa, ev);
++ }
++
++ return CORBA_Object_duplicate(orb->root_poa, ev);
++ }
++
++ /* throw user exception: InvalidName */
++ CORBA_exception_set(ev,CORBA_USER_EXCEPTION,
++ ex_CORBA_ORB_InvalidName,
++ NULL);
++
++ goto error;
++error:
++ return(NULL);
++}
++
++/* This is a MICO extension
++ *
++ * raises InvalidName
++ */
++void CORBA_ORB_set_initial_reference(CORBA_ORB orb, CORBA_ORB_ObjectId identifier, CORBA_Object obj, CORBA_Environment *ev)
++{
++ g_return_if_fail(ev);
++ o_return_if_fail(orb && identifier && obj);
++
++ if(!strcmp(identifier, "ImplementationRepository")) {
++ if(!CORBA_Object_is_nil(orb->imr, ev)) {
++ CORBA_Object_release(orb->imr, ev);
++ }
++ orb->imr=CORBA_Object_duplicate(obj, ev);
++ } else if(!strcmp(identifier, "InterfaceRepository")) {
++ if(!CORBA_Object_is_nil(orb->ir, ev)) {
++ CORBA_Object_release(orb->ir, ev);
++ }
++ orb->ir=CORBA_Object_duplicate(obj, ev);
++ } else if(!strcmp(identifier, "NameService")) {
++ if(!CORBA_Object_is_nil(orb->naming, ev)) {
++ CORBA_Object_release(orb->naming, ev);
++ }
++ orb->naming=CORBA_Object_duplicate(obj, ev);
++ } else if(!strcmp(identifier, "RootPOA")) {
++ if(!CORBA_Object_is_nil(orb->root_poa, ev)) {
++ CORBA_Object_release(orb->root_poa, ev);
++ }
++ orb->root_poa=CORBA_Object_duplicate(obj, ev);
++ } else {
++ /* throw user exception: InvalidName */
++ CORBA_exception_set(ev,CORBA_USER_EXCEPTION,ex_CORBA_ORB_InvalidName,NULL);
++ goto error;
++ }
++
++ return;
++error:
++ return;
++}
++
++/* Section 4.9.1 */
++CORBA_boolean CORBA_ORB_work_pending(CORBA_ORB orb, CORBA_Environment *ev)
++{
++ g_assert(!"Not yet implemented");
++ return(CORBA_FALSE);
++}
++
++/* Section 4.9.2 */
++void CORBA_ORB_perform_work(CORBA_ORB orb, CORBA_Environment *ev)
++{
++ g_assert(!"Not yet implemented");
++ return;
++}
++
++/* Section 4.9.4 */
++void
++CORBA_ORB_shutdown(CORBA_ORB orb,
++ CORBA_boolean wait_for_completion,
++ CORBA_Environment *ev)
++{
++ g_return_if_fail(ev);
++ o_return_if_fail(orb);
++
++ /* XXX implement on a per-ORB basis, and also
++ handle whatever wait_for_completion means */
++
++ if(orb->cnx.ipv4)
++ giop_connection_unref(orb->cnx.ipv4);
++ if(orb->cnx.ipv6)
++ giop_connection_unref(orb->cnx.ipv6);
++#ifndef __KORBIT__
++ if(orb->cnx.usock)
++ giop_connection_unref(orb->cnx.usock);
++#endif
++
++ giop_main_quit();
++}
++
++/* Section 4.9.3 */
++/* CORBA_ORB_run is in server.c */
++
++/* Section 4.7 */
++CORBA_PolicyType
++CORBA_Policy__get_policy_type(CORBA_Policy obj, CORBA_Environment *ev)
++{
++ g_return_val_if_fail(ev, 0);
++ o_return_val_if_fail(obj, 0);
++
++ return obj->policy_type;
++}
++
++/* Section 4.7 */
++CORBA_Policy CORBA_Policy_copy(CORBA_Policy obj, CORBA_Environment *ev)
++{
++ g_return_val_if_fail(ev, CORBA_OBJECT_NIL);
++ o_return_val_if_fail(obj, CORBA_OBJECT_NIL);
++
++ ORBIT_ROOT_OBJECT_REF(obj);
++
++ return obj;
++}
++
++/* Section 4.7
++ *
++ * raises CORBA_NO_PERMISSION
++ */
++void CORBA_Policy_destroy(CORBA_Policy obj, CORBA_Environment *ev)
++{
++ g_return_if_fail(ev);
++ o_return_if_fail(obj);
++
++ ORBIT_ROOT_OBJECT_UNREF(obj);
++ if(ORBIT_ROOT_OBJECT(obj)->refs <= 0)
++ ORBIT_ROOT_OBJECT_release(obj, ev);
++}
++
++#ifndef __KORBIT__
++/* Section 4.8.2 */
++CORBA_Policy CORBA_DomainManager_get_domain_policy(CORBA_DomainManager obj, CORBA_PolicyType policy_type, CORBA_Environment *ev)
++{
++ g_return_val_if_fail(ev, CORBA_OBJECT_NIL);
++ o_return_val_if_fail(obj, CORBA_OBJECT_NIL);
++
++ g_assert(!"Not yet implemented");
++ return(NULL);
++}
++
++/* Section 4.8.2 */
++void CORBA_ConstructionPolicy_make_domain_manager(CORBA_ConstructionPolicy obj, CORBA_InterfaceDef object_type, CORBA_boolean constr_policy, CORBA_Environment *
++ev)
++{
++ g_return_if_fail(ev);
++ o_return_if_fail(obj && object_type);
++
++ g_assert(!"Not yet implemented");
++ return;
++}
++
++/* Section 4.2.8 */
++CORBA_DomainManagerList *CORBA_Object_get_domain_managers(CORBA_Object obj, CORBA_Environment *ev)
++{
++ g_return_val_if_fail(ev, NULL);
++ o_return_val_if_fail(obj, NULL);
++
++ g_assert(!"Not yet implemented");
++ return(NULL);
++}
++
++CORBA_TypeCode CORBA_ORB_create_struct_tc(CORBA_ORB obj, CORBA_RepositoryId id, CORBA_Identifier name, CORBA_StructMemberSeq members, CORBA_Environment *ev)
++{
++ CORBA_TypeCode tc;
++ int i;
++
++ tc=ORBIT_CHUNK_ALLOC(CORBA_TypeCode);
++ if(tc == NULL)
++ goto tc_alloc_failed;
++
++ tc->subtypes=g_new0(CORBA_TypeCode, members._length);
++ if(tc->subtypes == NULL)
++ goto subtypes_alloc_failed;
++
++ tc->subnames=g_new0(char *, members._length);
++ if(tc->subnames == NULL)
++ goto subnames_alloc_failed;
++
++ tc->kind=CORBA_tk_struct;
++ tc->name=g_strdup(name);
++ tc->repo_id=g_strdup(id);
++ tc->sub_parts=members._length;
++ tc->length=members._length;
++
++ for(i=0;i<members._length;i++) {
++ CORBA_StructMember *mem=(CORBA_StructMember *)&(members._buffer[i]);
++
++ g_assert(&(mem->type)!=NULL);
++
++ tc->subtypes[i] = ORBIT_CHUNK_ALLOC(CORBA_TypeCode);
++ memcpy(tc->subtypes[i], mem->type, (size_t)sizeof(struct CORBA_TypeCode_struct));
++ tc->subnames[i]=g_strdup(mem->name);
++ }
++
++ return(tc);
++
++ subnames_alloc_failed:
++ g_free(tc->subtypes);
++ subtypes_alloc_failed:
++ ORBIT_CHUNK_FREE(CORBA_TypeCode, tc);
++ tc_alloc_failed:
++ CORBA_exception_set_system(ev, ex_CORBA_NO_MEMORY, CORBA_COMPLETED_NO);
++ return NULL;
++}
++
++CORBA_TypeCode
++CORBA_ORB_create_union_tc(CORBA_ORB obj, CORBA_RepositoryId id,
++ CORBA_Identifier name,
++ CORBA_TypeCode discriminator_type,
++ CORBA_UnionMemberSeq members,
++ CORBA_Environment *ev)
++{
++ CORBA_TypeCode tc;
++ int i;
++
++ tc=ORBIT_CHUNK_ALLOC(CORBA_TypeCode);
++
++ if(tc == NULL)
++ goto tc_alloc_failed;
++
++ tc->discriminator = ORBIT_CHUNK_ALLOC(CORBA_TypeCode);
++
++ if(tc->discriminator == NULL)
++ goto discriminator_alloc_failed;
++
++ memcpy(tc->discriminator, discriminator_type, (size_t)sizeof(CORBA_TypeCode));
++
++ tc->subtypes=g_new0(CORBA_TypeCode, members._length);
++ if(tc->subtypes==NULL)
++ goto subtypes_alloc_failed;
++
++ tc->subnames=g_new0(char *, members._length);
++ if(tc->subnames==NULL)
++ goto subnames_alloc_failed;
++
++ tc->sublabels=g_new0(CORBA_any, members._length);
++ if(tc->sublabels == NULL)
++ goto sublabels_alloc_failed;
++
++ tc->kind=CORBA_tk_union;
++ tc->name=g_strdup(name);
++ tc->repo_id=g_strdup(id);
++ tc->sub_parts=members._length;
++ tc->length=members._length;
++ tc->default_index=-1;
++
++ for(i=0;i<members._length;i++) {
++ CORBA_UnionMember *mem=(CORBA_UnionMember *)&(members._buffer[i]);
++
++ g_assert(&(mem->label)!=NULL);
++ memcpy(&(tc->sublabels[i]), &(mem->label), (size_t)sizeof(CORBA_any));
++ g_assert(&(mem->type)!=NULL);
++ tc->subtypes[i] = ORBIT_CHUNK_ALLOC(CORBA_TypeCode);
++ memcpy(tc->subtypes[i], mem->type, (size_t)sizeof(struct CORBA_TypeCode_struct));
++ tc->subnames[i]=g_strdup(mem->name);
++
++ if(mem->label._type->kind==CORBA_tk_octet) {
++ tc->default_index=i;
++ }
++ }
++
++ return(tc);
++
++sublabels_alloc_failed:
++ g_free(tc->sublabels);
++subnames_alloc_failed:
++ g_free(tc->subtypes);
++subtypes_alloc_failed:
++ ORBIT_CHUNK_FREE(CORBA_TypeCode, tc->discriminator);
++discriminator_alloc_failed:
++ ORBIT_CHUNK_FREE(CORBA_TypeCode, tc);
++ tc_alloc_failed:
++ CORBA_exception_set_system(ev, ex_CORBA_NO_MEMORY, CORBA_COMPLETED_NO);
++ return NULL;
++}
++
++CORBA_TypeCode CORBA_ORB_create_enum_tc(CORBA_ORB obj, CORBA_RepositoryId id, CORBA_Identifier name, CORBA_EnumMemberSeq members, CORBA_Environment *ev)
++{
++ CORBA_TypeCode tc;
++ int i;
++
++ tc = ORBIT_CHUNK_ALLOC(CORBA_TypeCode);
++ if(tc == NULL)
++ goto tc_alloc_failed;
++
++ tc->subnames=g_new0(char *, members._length);
++ if(tc->subnames==NULL)
++ goto subnames_alloc_failed;
++
++ tc->kind = CORBA_tk_enum;
++ tc->name = g_strdup(name);
++ tc->repo_id = g_strdup(id);
++ tc->sub_parts = members._length;
++ tc->length = members._length;
++
++ for(i=0;i<members._length;i++) {
++ tc->subnames[i]=g_strdup(members._buffer[i]);
++ }
++
++ return(tc);
++
++ subnames_alloc_failed:
++ ORBIT_CHUNK_FREE(CORBA_TypeCode, tc);
++ tc_alloc_failed:
++ CORBA_exception_set_system(ev, ex_CORBA_NO_MEMORY, CORBA_COMPLETED_NO);
++ return(NULL);
++}
++
++CORBA_TypeCode CORBA_ORB_create_alias_tc(CORBA_ORB obj, CORBA_RepositoryId id, CORBA_Identifier name, CORBA_TypeCode original_type, CORBA_Environment *ev)
++{
++ CORBA_TypeCode tc;
++
++ tc = ORBIT_CHUNK_ALLOC(CORBA_TypeCode);
++ if(tc==NULL)
++ goto tc_alloc_failed;
++
++ /* Can't use chunks here, because it's sometimes an array. Doh! */
++ tc->subtypes=g_new0(CORBA_TypeCode, 1);
++ if(tc->subtypes==NULL)
++ goto subtypes_alloc_failed;
++
++ tc->kind=CORBA_tk_alias;
++ tc->name=g_strdup(name);
++ tc->repo_id=g_strdup(id);
++ tc->sub_parts=1;
++ tc->length=1;
++
++ tc->subtypes[0] = ORBIT_CHUNK_ALLOC(CORBA_TypeCode);
++ memcpy(tc->subtypes[0], original_type, (size_t)sizeof(struct CORBA_TypeCode_struct));
++
++ return(tc);
++ subtypes_alloc_failed:
++ ORBIT_CHUNK_FREE(CORBA_TypeCode, tc);
++tc_alloc_failed:
++ CORBA_exception_set_system(ev, ex_CORBA_NO_MEMORY, CORBA_COMPLETED_NO);
++ return NULL;
++}
++
++CORBA_TypeCode CORBA_ORB_create_exception_tc(CORBA_ORB obj, CORBA_RepositoryId id, CORBA_Identifier name, CORBA_StructMemberSeq members, CORBA_Environment *ev)
++{
++ CORBA_TypeCode tc;
++ int i;
++
++ tc=ORBIT_CHUNK_ALLOC(CORBA_TypeCode);
++ if(tc==NULL)
++ goto tc_alloc_failed;
++
++ tc->subtypes=g_new0(CORBA_TypeCode, members._length);
++ if(tc->subtypes==NULL)
++ goto subtypes_alloc_failed;
++
++ tc->subnames=g_new0(char *, members._length);
++ if(tc->subnames==NULL)
++ goto subnames_alloc_failed;
++
++ tc->kind=CORBA_tk_except;
++ tc->name=g_strdup(name);
++ tc->repo_id=g_strdup(id);
++ tc->sub_parts=members._length;
++ tc->length=members._length;
++
++ for(i=0;i<members._length;i++) {
++ CORBA_StructMember *mem=(CORBA_StructMember *)&(members._buffer[i]);
++
++ g_assert(mem->type != NULL);
++ tc->subtypes[i] = ORBIT_CHUNK_ALLOC(CORBA_TypeCode);
++ memcpy(tc->subtypes[i], mem->type, (size_t)sizeof(struct CORBA_TypeCode_struct));
++ tc->subnames[i]=g_strdup(mem->name);
++ }
++
++ return(tc);
++
++ subnames_alloc_failed:
++ g_free(tc->subtypes);
++ subtypes_alloc_failed:
++ ORBIT_CHUNK_FREE(CORBA_TypeCode, tc);
++ tc_alloc_failed:
++ CORBA_exception_set_system(ev, ex_CORBA_NO_MEMORY, CORBA_COMPLETED_NO);
++ return(NULL);
++}
++
++CORBA_TypeCode CORBA_ORB_create_interface_tc(CORBA_ORB obj, CORBA_RepositoryId id, CORBA_Identifier name, CORBA_Environment *ev)
++{
++ CORBA_TypeCode tc;
++
++ tc=ORBIT_CHUNK_ALLOC(CORBA_TypeCode);
++ if(tc==NULL) {
++ CORBA_exception_set_system(ev, ex_CORBA_NO_MEMORY,
++ CORBA_COMPLETED_NO);
++ return(NULL);
++ }
++
++ tc->kind=CORBA_tk_objref;
++ tc->name=g_strdup(name);
++ tc->repo_id=g_strdup(id);
++
++ return(tc);
++}
++
++CORBA_TypeCode CORBA_ORB_create_string_tc(CORBA_ORB obj, CORBA_unsigned_long bound, CORBA_Environment *ev)
++{
++ CORBA_TypeCode tc;
++
++ tc=ORBIT_CHUNK_ALLOC(CORBA_TypeCode);
++ if(tc==NULL) {
++ CORBA_exception_set_system(ev, ex_CORBA_NO_MEMORY, CORBA_COMPLETED_NO);
++ return(NULL);
++ }
++
++ tc->kind=CORBA_tk_string;
++ tc->length=bound;
++
++ return(tc);
++}
++
++CORBA_TypeCode CORBA_ORB_create_wstring_tc(CORBA_ORB obj, CORBA_unsigned_long bound, CORBA_Environment *ev)
++{
++ CORBA_TypeCode tc;
++
++ tc=ORBIT_CHUNK_ALLOC(CORBA_TypeCode);
++ if(tc==NULL) {
++ CORBA_exception_set_system(ev, ex_CORBA_NO_MEMORY, CORBA_COMPLETED_NO);
++ return(NULL);
++ }
++
++ tc->kind=CORBA_tk_wstring;
++ tc->length=bound;
++
++ return(tc);
++}
++
++CORBA_TypeCode CORBA_ORB_create_fixed_tc(CORBA_ORB obj, CORBA_unsigned_short digits, CORBA_short scale, CORBA_Environment *ev)
++{
++ CORBA_TypeCode tc;
++
++ tc=ORBIT_CHUNK_ALLOC(CORBA_TypeCode);
++ if(tc==NULL) {
++ CORBA_exception_set_system(ev, ex_CORBA_NO_MEMORY, CORBA_COMPLETED_NO);
++ return(NULL);
++ }
++
++ tc->kind=CORBA_tk_fixed;
++ tc->digits=digits;
++ tc->scale=scale;
++
++ return(tc);
++}
++
++CORBA_TypeCode CORBA_ORB_create_sequence_tc(CORBA_ORB obj, CORBA_unsigned_long bound, CORBA_TypeCode element_type, CORBA_Environment *ev)
++{
++ CORBA_TypeCode tc;
++
++ tc=ORBIT_CHUNK_ALLOC(CORBA_TypeCode);
++ if(tc==NULL)
++ goto tc_alloc_failed;
++
++ /* Can't use chunks here because we can only be sure of getting
++ one consecutive chunk from glib */
++ tc->subtypes=g_new0(CORBA_TypeCode, 1);
++ if(tc->subtypes==NULL)
++ goto subtypes_alloc_failed;
++
++ tc->kind=CORBA_tk_sequence;
++ tc->sub_parts=1;
++ tc->length=bound;
++
++ tc->subtypes[0] = ORBIT_CHUNK_ALLOC(CORBA_TypeCode);
++ memcpy(tc->subtypes[0], element_type,
++ (size_t)sizeof(struct CORBA_TypeCode_struct));
++
++ return(tc);
++
++ subtypes_alloc_failed:
++ ORBIT_CHUNK_FREE(CORBA_TypeCode, tc);
++ tc_alloc_failed:
++ CORBA_exception_set_system(ev, ex_CORBA_NO_MEMORY, CORBA_COMPLETED_NO);
++ return(NULL);
++}
++
++CORBA_TypeCode CORBA_ORB_create_recursive_sequence_tc(CORBA_ORB obj, CORBA_unsigned_long bound, CORBA_unsigned_long offset, CORBA_Environment *ev)
++{
++ CORBA_TypeCode tc;
++
++ tc=ORBIT_CHUNK_ALLOC(CORBA_TypeCode);
++ if(tc==NULL)
++ goto tc_alloc_failed;
++
++ tc->subtypes=g_new0(CORBA_TypeCode, 1);
++ if(tc->subtypes==NULL)
++ goto subtypes_alloc_failed;
++
++ tc->kind=CORBA_tk_sequence;
++ tc->sub_parts=1;
++ tc->length=bound;
++
++ tc->subtypes[0] = ORBIT_CHUNK_ALLOC(CORBA_TypeCode);
++ tc->subtypes[0]->kind=CORBA_tk_recursive;
++ tc->subtypes[0]->recurse_depth=offset;
++
++ return(tc);
++
++ subtypes_alloc_failed:
++ ORBIT_CHUNK_FREE(CORBA_TypeCode, tc);
++ tc_alloc_failed:
++ CORBA_exception_set_system(ev, ex_CORBA_NO_MEMORY, CORBA_COMPLETED_NO);
++ return(NULL);
++}
++
++CORBA_TypeCode CORBA_ORB_create_array_tc(CORBA_ORB obj, CORBA_unsigned_long length, CORBA_TypeCode element_type, CORBA_Environment *ev)
++{
++ CORBA_TypeCode tc;
++
++ tc=ORBIT_CHUNK_ALLOC(CORBA_TypeCode);
++ if(tc==NULL)
++ goto tc_alloc_failed;
++
++ tc->subtypes=g_new0(CORBA_TypeCode, 1);
++ if(tc->subtypes==NULL)
++ goto subtypes_alloc_failed;
++
++ tc->kind=CORBA_tk_array;
++ tc->sub_parts=1;
++ tc->length=length;
++
++ tc->subtypes[0] = ORBIT_CHUNK_ALLOC(CORBA_TypeCode);
++ memcpy(tc->subtypes[0], element_type, (size_t)sizeof(CORBA_TypeCode));
++
++ return(tc);
++
++ subtypes_alloc_failed:
++ ORBIT_CHUNK_FREE(CORBA_TypeCode, tc);
++ tc_alloc_failed:
++ CORBA_exception_set_system(ev, ex_CORBA_NO_MEMORY, CORBA_COMPLETED_NO);
++ return(NULL);
++}
++#endif /* !__KORBIT__ */
+diff -urN linux-2.4.1/net/korbit/orb/orb.h linux-2.4.1-korbit/net/korbit/orb/orb.h
+--- linux-2.4.1/net/korbit/orb/orb.h Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/orb/orb.h Thu Feb 1 11:47:13 2001
+@@ -0,0 +1,231 @@
++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
++
++/*
++ * ORBit: A CORBA v2.2 ORB
++ *
++ * Copyright (C) 1998 Richard H. Porter
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Library General Public
++ * License as published by the Free Software Foundation; either
++ * version 2 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Library General Public License for more details.
++ *
++ * You should have received a copy of the GNU Library General Public
++ * License along with this library; if not, write to the Free
++ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Author: Dick Porter <dick@cymru.net>
++ *
++ */
++
++#ifndef _ORBIT_ORB_H_
++#define _ORBIT_ORB_H_
++
++#include "orb/orbit_types.h"
++#ifndef __KORBIT__
++#include "orb/interface_repository.h"
++#endif /* !__KORBIT__ */
++
++extern CORBA_ORB CORBA_ORB_init(
++ int *argc,
++ char **argv,
++ CORBA_ORBid orb_identifier,
++ CORBA_Environment *ev);
++
++extern CORBA_char *CORBA_ORB_object_to_string(
++ CORBA_ORB orb,
++ CORBA_Object obj,
++ CORBA_Environment *ev);
++
++extern CORBA_Object CORBA_ORB_string_to_object(
++ CORBA_ORB orb,
++ CORBA_char *str,
++ CORBA_Environment *ev);
++
++extern CORBA_Status CORBA_ORB_get_default_context(
++ CORBA_ORB orb,
++ CORBA_Context *ctx,
++ CORBA_Environment *ev);
++
++extern CORBA_boolean CORBA_ORB_get_service_information(
++ CORBA_ORB orb,
++ CORBA_ServiceType service_type,
++ CORBA_ServiceInformation *service_information,
++ CORBA_Environment *ev);
++
++extern CORBA_Current *CORBA_ORB_get_current(
++ CORBA_ORB orb,
++ CORBA_Environment *ev);
++
++extern CORBA_ORB_ObjectIdList* CORBA_ORB_list_initial_services(
++ CORBA_ORB orb,
++ CORBA_Environment *ev);
++
++extern CORBA_Object CORBA_ORB_resolve_initial_references(
++ CORBA_ORB orb,
++ CORBA_ORB_ObjectId identifier,
++ CORBA_Environment *ev);
++
++extern void CORBA_ORB_set_initial_reference(
++ CORBA_ORB orb,
++ CORBA_ORB_ObjectId identifier,
++ CORBA_Object obj,
++ CORBA_Environment *ev);
++
++extern CORBA_boolean CORBA_ORB_work_pending(
++ CORBA_ORB orb,
++ CORBA_Environment *ev);
++
++extern void CORBA_ORB_perform_work(
++ CORBA_ORB orb,
++ CORBA_Environment *ev);
++
++extern void CORBA_ORB_shutdown(
++ CORBA_ORB orb,
++ CORBA_boolean wait_for_completion,
++ CORBA_Environment *ev);
++
++extern void CORBA_ORB_run(
++ CORBA_ORB orb,
++ CORBA_Environment *ev);
++
++extern CORBA_PolicyType CORBA_Policy__get_policy_type(
++ CORBA_Policy obj,
++ CORBA_Environment *ev);
++
++extern CORBA_Policy CORBA_Policy_copy(
++ CORBA_Policy obj,
++ CORBA_Environment *ev);
++
++extern void CORBA_Policy_destroy(
++ CORBA_Policy obj,
++ CORBA_Environment *ev);
++
++#ifndef __KORBIT__
++extern CORBA_InterfaceDef CORBA_Object_get_interface(
++ CORBA_Object obj,
++ CORBA_Environment *ev);
++#endif /* !__KORBIT__ */
++
++extern CORBA_boolean CORBA_Object_is_nil(
++ CORBA_Object obj,
++ CORBA_Environment *ev);
++
++extern CORBA_Object CORBA_Object_duplicate(
++ CORBA_Object obj,
++ CORBA_Environment *ev);
++
++extern void CORBA_Object_release(
++ CORBA_Object obj,
++ CORBA_Environment *ev);
++
++extern CORBA_boolean CORBA_Object_non_existent(
++ CORBA_Object obj,
++ CORBA_Environment *ev);
++
++extern CORBA_boolean CORBA_Object_is_equivalent(
++ CORBA_Object obj,
++ CORBA_Object other_object,
++ CORBA_Environment *ev);
++
++extern CORBA_unsigned_long CORBA_Object_hash(
++ CORBA_Object obj,
++ CORBA_unsigned_long maximum,
++ CORBA_Environment *ev);
++
++extern CORBA_Policy CORBA_Object_get_policy(
++ CORBA_Object obj,
++ CORBA_PolicyType policy_type,
++ CORBA_Environment *ev);
++
++#ifndef __KORBIT__
++extern CORBA_DomainManagerList *CORBA_Object_get_domain_managers(
++ CORBA_Object obj,
++ CORBA_Environment *ev);
++
++extern CORBA_Policy CORBA_DomainManager_get_domain_policy(
++ CORBA_DomainManager obj,
++ CORBA_PolicyType policy_type,
++ CORBA_Environment *ev);
++
++extern void CORBA_ConstructionPolicy_make_domain_manager(
++ CORBA_ConstructionPolicy obj,
++ CORBA_Object /*CORBA_InterfaceDef*/ object_type,
++ CORBA_boolean constr_policy,
++ CORBA_Environment *ev);
++
++CORBA_TypeCode CORBA_ORB_create_struct_tc(CORBA_ORB obj,
++ CORBA_RepositoryId id,
++ CORBA_Identifier name,
++ CORBA_StructMemberSeq members,
++ CORBA_Environment *ev);
++
++CORBA_TypeCode CORBA_ORB_create_union_tc(CORBA_ORB obj,
++ CORBA_RepositoryId id,
++ CORBA_Identifier name,
++ CORBA_TypeCode discriminator_type,
++ CORBA_UnionMemberSeq members,
++ CORBA_Environment *ev);
++
++CORBA_TypeCode CORBA_ORB_create_enum_tc(CORBA_ORB obj,
++ CORBA_RepositoryId id,
++ CORBA_Identifier name,
++ CORBA_EnumMemberSeq members,
++ CORBA_Environment *ev);
++
++CORBA_TypeCode CORBA_ORB_create_alias_tc(CORBA_ORB obj,
++ CORBA_RepositoryId id,
++ CORBA_Identifier name,
++ CORBA_TypeCode original_type,
++ CORBA_Environment *ev);
++
++CORBA_TypeCode CORBA_ORB_create_exception_tc(CORBA_ORB obj,
++ CORBA_RepositoryId id,
++ CORBA_Identifier name,
++ CORBA_StructMemberSeq members,
++ CORBA_Environment *ev);
++
++CORBA_TypeCode CORBA_ORB_create_interface_tc(CORBA_ORB obj,
++ CORBA_RepositoryId id,
++ CORBA_Identifier name,
++ CORBA_Environment *ev);
++
++CORBA_TypeCode CORBA_ORB_create_string_tc(CORBA_ORB obj,
++ CORBA_unsigned_long bound,
++ CORBA_Environment *ev);
++
++CORBA_TypeCode CORBA_ORB_create_wstring_tc(CORBA_ORB obj,
++ CORBA_unsigned_long bound,
++ CORBA_Environment *ev);
++
++CORBA_TypeCode CORBA_ORB_create_fixed_tc(CORBA_ORB obj,
++ CORBA_unsigned_short digits,
++ CORBA_short scale,
++ CORBA_Environment *ev);
++
++extern CORBA_TypeCode CORBA_ORB_create_sequence_tc(
++ CORBA_ORB obj,
++ CORBA_unsigned_long bound,
++ CORBA_TypeCode element_type,
++ CORBA_Environment *ev);
++
++extern CORBA_TypeCode CORBA_ORB_create_recursive_sequence_tc(
++ CORBA_ORB obj,
++ CORBA_unsigned_long bound,
++ CORBA_unsigned_long offset,
++ CORBA_Environment *ev);
++
++extern CORBA_TypeCode CORBA_ORB_create_array_tc(
++ CORBA_ORB obj,
++ CORBA_unsigned_long length,
++ CORBA_TypeCode element_type,
++ CORBA_Environment *ev);
++
++#endif /* !__KORBIT__ */
++
++#endif /* !_ORBIT_ORB_H_ */
+diff -urN linux-2.4.1/net/korbit/orb/orbit.c linux-2.4.1-korbit/net/korbit/orb/orbit.c
+--- linux-2.4.1/net/korbit/orb/orbit.c Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/orb/orbit.c Thu Feb 1 11:47:13 2001
+@@ -0,0 +1,387 @@
++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
++
++/*
++ * ORBit: A CORBA v2.2 ORB
++ *
++ * Copyright (C) 1998 Richard H. Porter and Red Hat Software
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Library General Public
++ * License as published by the Free Software Foundation; either
++ * version 2 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Library General Public License for more details.
++ *
++ * You should have received a copy of the GNU Library General Public
++ * License along with this library; if not, write to the Free
++ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Author: Dick Porter <dick@cymru.net>
++ *
++ */
++
++/*
++ * This file is a repository for random functions that don't fit anywhere
++ * else, and for ORBit-specific stuff.
++ */
++
++#include <stdlib.h>
++#include <string.h>
++#include <sys/types.h>
++#include <netdb.h>
++#include <netinet/in.h>
++#include <arpa/inet.h>
++#include <assert.h>
++#include <math.h>
++
++#include "orbit.h"
++
++const guint orbit_major_version = ORBIT_MAJOR_VERSION,
++ orbit_minor_version = ORBIT_MINOR_VERSION,
++ orbit_micro_version = ORBIT_MICRO_VERSION;
++const char orbit_version[] = ORBIT_VERSION;
++
++typedef struct ORBitClassInfo ORBitClassInfo;
++
++typedef void (*ORBitObjectInitFunc)(CORBA_Object _handle_to_be, gpointer class_data);
++
++struct ORBitClassInfo {
++ char *name;
++ gulong id;
++ gpointer method_stubs, method_skels;
++ ORBitObjectInitFunc class_vtable_init_func;
++ ORBitClassInfo **parent_classes;
++};
++
++GHashTable *orbit_class_list = NULL, *orbit_class_byid;
++glong class_id_counter = -1;
++
++void CORBA_any_set_release(CORBA_any *any, CORBA_boolean flag)
++{
++ g_assert(any!=NULL);
++
++ if(flag==CORBA_TRUE) {
++ any->_release |= CORBA_ANYFLAGS_RELEASE;
++ } else {
++ any->_release &= ~CORBA_ANYFLAGS_RELEASE;
++ }
++
++}
++
++CORBA_boolean CORBA_any_get_release(CORBA_any *any)
++{
++ g_assert(any!=NULL);
++
++ if(any->_release & CORBA_ANYFLAGS_RELEASE)
++ return(CORBA_TRUE);
++ else
++ return(CORBA_FALSE);
++}
++
++void CORBA_sequence_set_release(void *seq, CORBA_boolean flag)
++{
++ struct CORBA_Sequence_type *sequence;
++
++ g_assert(seq!=NULL);
++
++ sequence=(struct CORBA_Sequence_type *)seq;
++
++ if(flag==CORBA_TRUE) {
++ sequence->_release |= CORBA_ANYFLAGS_RELEASE;
++ } else {
++ sequence->_release &= ~CORBA_ANYFLAGS_RELEASE;
++ }
++}
++
++CORBA_boolean CORBA_sequence_get_release(void *seq)
++{
++ struct CORBA_Sequence_type *sequence;
++
++ g_assert(seq!=NULL);
++
++ sequence=(struct CORBA_Sequence_type *)seq;
++
++ if(sequence->_release & CORBA_ANYFLAGS_RELEASE)
++ return(CORBA_TRUE);
++ else
++ return(CORBA_FALSE);
++}
++
++/*
++ * As far as I understand, values returned by CORBA_*_alloc() are supposed to be
++ * freeable by CORBA_free(), so we can't use memory chunks here in any reasonable
++ * fashion.
++ */
++gpointer
++CORBA_any__free(gpointer mem, gpointer func_data, CORBA_boolean free_strings)
++{
++ CORBA_any *aval = mem;
++
++ if(aval->_release)
++ ORBit_free(aval->_value, free_strings);
++ CORBA_Object_release((CORBA_Object)aval->_type, NULL);
++
++ return aval + 1;
++}
++
++CORBA_any *CORBA_any_alloc(void)
++{
++ CORBA_any *retval = ORBit_alloc(sizeof(CORBA_any), &CORBA_any__free,
++ GINT_TO_POINTER(1));
++
++ memset(retval, 0, sizeof(CORBA_any)); /* Make things easier on stubs */
++
++ return retval;
++}
++
++/*
++ * Compares the typecodes of each any
++ */
++CORBA_boolean ORBit_any_equivalent(CORBA_any obj, CORBA_any any, CORBA_Environment *ev)
++{
++ return(CORBA_FALSE);
++}
++
++/* This is needed by skels, that generate a __free function when they see
++ the TypeCode interface */
++gpointer
++CORBA_TypeCode__free(gpointer mem, gpointer func_data, CORBA_boolean free_strings)
++{
++ CORBA_Object_release(*(CORBA_Object *)mem, NULL);
++ return ((guchar *)mem) + sizeof(CORBA_TypeCode);
++}
++
++CORBA_char *CORBA_string_dup(const CORBA_char *string)
++{
++ if(!string)
++ return NULL;
++
++ return strcpy(ORBit_alloc(strlen(string)+1, NULL, NULL), string);
++}
++
++CORBA_char *CORBA_string_alloc(CORBA_unsigned_long len)
++{
++ return ORBit_alloc(len + 1, NULL, NULL);
++}
++
++CORBA_wchar *CORBA_wstring_alloc(CORBA_unsigned_long len)
++{
++ return ORBit_alloc(len + 1, NULL, NULL);
++}
++
++gpointer
++CORBA_string__free(gpointer str, gpointer dat, CORBA_boolean free_strings)
++{
++ if(free_strings)
++ CORBA_free(*((gpointer *)str));
++ return (gpointer)((guchar *)str + sizeof(CORBA_char *));
++}
++
++gpointer CORBA_Object__free(gpointer str, gpointer dat, CORBA_boolean free_strings)
++{
++ CORBA_Environment ev;
++ CORBA_exception_init(&ev);
++ CORBA_Object_release(*((gpointer *)str), &ev);
++ CORBA_exception_free(&ev);
++ return (gpointer)((guchar *)str + sizeof(CORBA_Object));
++}
++
++/* 19.14 */
++
++/* The big picture for fixeds.
++ We have to represent a number in memory.
++
++ 1 2 3 . 4 5 6 7
++
++ There are three pieces of information in a fixed:
++
++ - Number of significant digits. (_digits)
++
++ - The scale. The number of places the decimal point is to the right
++ of the first significant digit. (_scale)
++
++ - The digits themselves (_value)
++
++ */
++CORBA_long CORBA_fixed_integer_part(const void *fp)
++{
++ CORBA_long retval = 0;
++ int i, power_of_ten, digit;
++ const CORBA_fixed_d_s *val = fp;
++
++ g_return_val_if_fail(fp != NULL, INT_MIN);
++
++ for(i = 0; i < (val->_digits - val->_scale); i++) {
++ power_of_ten = val->_digits - i - val->_scale - 1;
++ digit = val->_value[i];
++ retval += digit * ((int)pow(10, power_of_ten));
++ }
++
++ return retval;
++}
++
++CORBA_long CORBA_fixed_fraction_part(const void *fp)
++{
++ CORBA_long retval = 0;
++ int i, power_of_ten, digit;
++ const CORBA_fixed_d_s *val = fp;
++
++ g_return_val_if_fail(fp != NULL, INT_MIN);
++
++ for(i = val->_digits - val->_scale; i < val->_digits; i++){
++ power_of_ten = val->_digits - i - 1;
++ digit = val->_value[i];
++ retval += digit * ((int)pow(10, power_of_ten));
++ }
++
++ return retval;
++}
++
++static inline
++CORBA_long do_div (CORBA_long *n)
++{
++ int __res;
++
++ __res = (*n) % (unsigned) 10;
++ *n = (*n) / (unsigned) 10;
++
++ return __res;
++}
++
++void CORBA_fixed_set(void *rp, CORBA_long i, CORBA_long f)
++{
++ CORBA_fixed_d_s *val = rp;
++ CORBA_long left_to_eat, cur;
++ signed char sign = 1;
++
++ g_return_if_fail(rp != NULL);
++
++ memset(val->_value, 0, val->_digits);
++
++ if(i) sign = i/abs(i);
++ val->_sign = sign;
++ i = abs(i);
++ f = abs(f);
++
++ for(cur = 0, left_to_eat = i;
++ left_to_eat != 0 && cur < val->_digits; cur++) {
++ val->_value[cur] = do_div(&left_to_eat) * sign;
++ sign = 1;
++ }
++
++ val->_scale = cur - 1;
++
++ for(left_to_eat = f;
++ left_to_eat != 0 && cur < val->_digits; cur++) {
++ val->_value[cur] = do_div(&left_to_eat);
++ }
++}
++
++void CORBA_fixed_add(void *rp, const void *f1p, const void *f2p)
++{
++ g_assert(!"Not yet implemented");
++}
++
++void CORBA_fixed_sub(void *rp, const void *f1p, const void *f2p)
++{
++ g_assert(!"Not yet implemented");
++}
++
++void CORBA_fixed_mul(void *rp, const void *f1p, const void *f2p)
++{
++ g_assert(!"Not yet implemented");
++}
++
++void CORBA_fixed_div(void *rp, const void *f1p, const void *f2p)
++{
++ g_assert(!"Not yet implemented");
++}
++
++CORBA_fixed_d_s *CORBA_fixed_alloc(CORBA_unsigned_short d)
++{
++ return (CORBA_fixed_d_s *)
++ g_malloc(sizeof(CORBA_fixed_d_s) + d + 1);
++}
++
++void CORBA_free(void *storage)
++{
++ ORBit_free(storage, CORBA_TRUE);
++}
++
++int ORBit_parse_unixsock(CORBA_Object obj,
++ char *sockpath,
++ gboolean existing_only)
++{
++ if(!sockpath || !*sockpath)
++ return -1;
++
++ obj->connection =
++ GIOP_CONNECTION(iiop_connection_unix_get(sockpath,
++ existing_only));
++
++ if(!obj->connection)
++ return -1;
++
++ giop_connection_ref(obj->connection);
++ return 0;
++}
++
++int ORBit_parse_inet(CORBA_Object obj, char *hostname, unsigned short port,
++ gboolean existing_only)
++{
++ obj->connection = GIOP_CONNECTION(iiop_connection_get(hostname, port, existing_only));
++
++ if(!obj->connection)
++ return -1;
++ giop_connection_ref(obj->connection);
++ return 0;
++}
++
++static const CORBA_unsigned_long zero_int = 0;
++struct iovec ORBit_default_principal_iovec = {(gpointer)&zero_int, sizeof(zero_int)};
++
++void ORBit_set_default_principal(CORBA_Principal *principal)
++{
++ gpointer t;
++
++ if((gpointer)ORBit_default_principal_iovec.iov_base != (gpointer)&zero_int)
++ g_free(ORBit_default_principal_iovec.iov_base);
++
++ ORBit_default_principal_iovec.iov_len = principal->_length
++ + sizeof(CORBA_unsigned_long);
++
++ t = ORBit_default_principal_iovec.iov_base =
++ g_malloc(ORBit_default_principal_iovec.iov_len);
++
++ memcpy(t, &principal->_length, sizeof(principal->_length));
++
++ t = ((guchar *)t) + sizeof(principal->_length);
++ memcpy(t, principal->_buffer, principal->_length);
++}
++
++CORBA_unsigned_long ORBit_class_assignment_counter = 0;
++GHashTable *ORBit_class_assignments = NULL;
++
++/* XXX not thread-safe */
++CORBA_unsigned_long
++ORBit_register_class(const PortableServer_ClassInfo *class_info)
++{
++ CORBA_unsigned_long retval;
++
++ if(!ORBit_class_assignments)
++ ORBit_class_assignments = g_hash_table_new(g_str_hash, g_str_equal);
++
++ /* This needs to be pre-increment - we don't want to give out
++ classid 0, because (a) that is reserved for the base Object class
++ (b) all the routines allocate a new id if the variable
++ storing their ID == 0 */
++ retval = ++ORBit_class_assignment_counter;
++
++ g_hash_table_insert(ORBit_class_assignments, (gpointer)class_info->class_name,
++ GINT_TO_POINTER(retval));
++
++ return retval;
++}
+diff -urN linux-2.4.1/net/korbit/orb/orbit.h linux-2.4.1-korbit/net/korbit/orb/orbit.h
+--- linux-2.4.1/net/korbit/orb/orbit.h Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/orb/orbit.h Thu Feb 1 11:47:13 2001
+@@ -0,0 +1,207 @@
++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
++
++/*
++ * ORBit: A CORBA v2.2 ORB
++ *
++ * Copyright (C) 1998 Richard H. Porter
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Library General Public
++ * License as published by the Free Software Foundation; either
++ * version 2 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Library General Public License for more details.
++ *
++ * You should have received a copy of the GNU Library General Public
++ * License along with this library; if not, write to the Free
++ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Author: Dick Porter <dick@acm.org>
++ * Elliot Lee <sopwith@redhat.com>
++ *
++ */
++
++/* these two blocks are outside of the main header for good reason...
++ People may include headers from many different stubs, and we want to
++ have the version checked on all of them.
++ */
++#ifndef ORBIT_SERIAL
++#define ORBIT_SERIAL 9
++#endif
++
++#ifdef ORBIT_IDL_SERIAL
++#if ORBIT_IDL_SERIAL < 9
++#error "You need to rerun 'orbit-idl' on the .idl file whose stubs you are using. These stubs were generated with an older version of ORBit, and need to be regenerated."
++#endif
++#endif
++
++#ifndef _ORBIT_H_
++#define _ORBIT_H_
++
++#ifdef __cplusplus
++extern "C" {
++#endif /* __cplusplus */
++
++#include <glib.h>
++
++#define BACKWARDS_COMPAT_0_4
++#undef NOT_BACKWARDS_COMPAT_0_4
++
++#include <sys/types.h>
++#include <sys/uio.h>
++#include <IIOP/IIOP.h>
++#include <ORBitutil/util.h>
++#include <orb/orbit_config.h>
++#include <orb/orbit_types.h>
++#include <orb/allocators.h>
++#include <orb/cdr.h>
++#include <orb/dii.h>
++#ifndef __KORBIT__
++#include <orb/dynany.h>
++#endif
++#include <orb/env.h>
++#include <orb/iop.h>
++#include <orb/ir.h>
++#include <orb/options.h>
++#include <orb/orb.h>
++#include <orb/poa.h>
++#include <orb/sequences.h>
++#include <orb/orbit_typecode.h>
++#include <orb/typecode.h>
++
++#ifndef ORBIT_MAJOR_VERSION
++#define ORBIT_MAJOR_VERSION (0)
++#define ORBIT_MINOR_VERSION (5)
++#define ORBIT_MICRO_VERSION (3)
++#endif
++
++extern const guint orbit_major_version,
++ orbit_minor_version,
++ orbit_micro_version;
++extern const char orbit_version[];
++
++extern void CORBA_any_set_release(
++ CORBA_any *,
++ CORBA_boolean);
++
++extern CORBA_boolean CORBA_any_get_release(
++ CORBA_any *);
++
++extern void CORBA_sequence_set_release(
++ void *,
++ CORBA_boolean);
++
++extern CORBA_boolean CORBA_sequence_get_release(
++ void *);
++
++#define CORBA_any__alloc CORBA_any_alloc
++extern CORBA_any *CORBA_any_alloc(
++ void);
++
++extern gpointer CORBA_any__free(gpointer mem, gpointer func_data,
++ CORBA_boolean free_strings);
++extern gpointer CORBA_TypeCode__free(gpointer mem, gpointer func_data,
++ CORBA_boolean free_strings);
++
++extern CORBA_boolean ORBit_any_equivalent(
++ CORBA_any obj,
++ CORBA_any any,
++ CORBA_Environment *ev);
++
++extern CORBA_char *CORBA_string_dup(const CORBA_char *string);
++extern CORBA_char *CORBA_string_alloc(CORBA_unsigned_long len);
++extern gpointer CORBA_string__free(gpointer str, gpointer dat, CORBA_boolean free_strings);
++
++gpointer CORBA_Object__free(gpointer str, gpointer dat, CORBA_boolean free_strings);
++
++extern CORBA_wchar *CORBA_wstring_alloc(CORBA_unsigned_long len);
++#define CORBA_wstring_free CORBA_string_free
++
++/* 19.14 */
++extern CORBA_long CORBA_fixed_integer_part(
++ const void *fp);
++
++extern CORBA_long CORBA_fixed_fraction_part(
++ const void *fp);
++
++extern void CORBA_fixed_set(
++ void *rp,
++ CORBA_long i,
++ CORBA_long f);
++
++extern void CORBA_fixed_add(
++ void *rp,
++ const void *f1p,
++ const void *f2p);
++
++extern void CORBA_fixed_sub(
++ void *rp,
++ const void *f1p,
++ const void *f2p);
++
++extern void CORBA_fixed_mul(
++ void *rp,
++ const void *f1p,
++ const void *f2p);
++
++extern void CORBA_fixed_div(
++ void *rp,
++ const void *f1p,
++ const void *f2p);
++
++extern CORBA_fixed_d_s *CORBA_fixed_alloc(
++ CORBA_unsigned_short d);
++
++extern void CORBA_free(
++ void *storage);
++
++extern int ORBit_parse_inet(
++ CORBA_Object obj,
++ char *hostname,
++ unsigned short port,
++ gboolean existing_only);
++
++extern int ORBit_parse_unixsock(CORBA_Object obj,
++ char *sockpath,
++ gboolean existing_only);
++
++/****
++ This function lets you use your own event loop, if you so wish.
++ Also see IIOP.h's IIOP{Add,Remove}ConnectionHandler function pointers,
++ which are app-settable (you should set them before CORBA_ORB_init,
++ if you want them to be useful)
++ ****/
++
++ /* needs to be called by your event loop when data comes in on one of the
++ GIOPConnection fd's */
++void ORBit_custom_run_setup(CORBA_ORB orb, CORBA_Environment *ev);
++ void ORBit_handle_incoming(GIOPConnection *connection);
++
++/* Returns CORBA_TRUE if the request is OK to proceed. */
++typedef enum {
++ ORBIT_MESSAGE_BAD,
++ ORBIT_MESSAGE_ALLOW,
++ ORBIT_MESSAGE_ALLOW_ALL /* Allow all subsequent messages on
++ this connection with no checking */
++} ORBit_MessageValidationResult;
++typedef ORBit_MessageValidationResult (*ORBit_request_validate)
++ (CORBA_unsigned_long request_id,
++ CORBA_Principal *principal,
++ CORBA_char *operation);
++void ORBit_set_request_validation_handler(ORBit_request_validate validator);
++
++extern struct iovec ORBit_default_principal_iovec;
++void ORBit_set_default_principal(CORBA_Principal *principal);
++
++extern CORBA_unsigned_long ORBit_class_assignment_counter;
++
++CORBA_unsigned_long ORBit_register_class(const PortableServer_ClassInfo *class_info);
++
++#ifdef __cplusplus
++}
++#endif /* __cplusplus */
++
++#endif /* !_ORBIT_H_ */
+diff -urN linux-2.4.1/net/korbit/orb/orbit.h.in linux-2.4.1-korbit/net/korbit/orb/orbit.h.in
+--- linux-2.4.1/net/korbit/orb/orbit.h.in Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/orb/orbit.h.in Thu Feb 1 11:47:13 2001
+@@ -0,0 +1,205 @@
++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
++
++/*
++ * ORBit: A CORBA v2.2 ORB
++ *
++ * Copyright (C) 1998 Richard H. Porter
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Library General Public
++ * License as published by the Free Software Foundation; either
++ * version 2 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Library General Public License for more details.
++ *
++ * You should have received a copy of the GNU Library General Public
++ * License along with this library; if not, write to the Free
++ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Author: Dick Porter <dick@acm.org>
++ * Elliot Lee <sopwith@redhat.com>
++ *
++ */
++
++/* these two blocks are outside of the main header for good reason...
++ People may include headers from many different stubs, and we want to
++ have the version checked on all of them.
++ */
++#ifndef ORBIT_SERIAL
++#define ORBIT_SERIAL @ORBIT_SERIAL@
++#endif
++
++#ifdef ORBIT_IDL_SERIAL
++#if ORBIT_IDL_SERIAL < @ORBIT_SERIAL@
++#error "You need to rerun 'orbit-idl' on the .idl file whose stubs you are using. These stubs were generated with an older version of ORBit, and need to be regenerated."
++#endif
++#endif
++
++#ifndef _ORBIT_H_
++#define _ORBIT_H_
++
++#ifdef __cplusplus
++extern "C" {
++#endif /* __cplusplus */
++
++#include <glib.h>
++
++#define BACKWARDS_COMPAT_0_4
++#undef NOT_BACKWARDS_COMPAT_0_4
++
++#include <sys/types.h>
++#include <sys/uio.h>
++#include <IIOP/IIOP.h>
++#include <ORBitutil/util.h>
++#include <orb/orbit_config.h>
++#include <orb/orbit_types.h>
++#include <orb/allocators.h>
++#include <orb/cdr.h>
++#include <orb/dii.h>
++#include <orb/dynany.h>
++#include <orb/env.h>
++#include <orb/iop.h>
++#include <orb/ir.h>
++#include <orb/options.h>
++#include <orb/orb.h>
++#include <orb/poa.h>
++#include <orb/sequences.h>
++#include <orb/orbit_typecode.h>
++#include <orb/typecode.h>
++
++#ifndef ORBIT_MAJOR_VERSION
++#define ORBIT_MAJOR_VERSION (@ORBIT_MAJOR_VERSION@)
++#define ORBIT_MINOR_VERSION (@ORBIT_MINOR_VERSION@)
++#define ORBIT_MICRO_VERSION (@ORBIT_MICRO_VERSION@)
++#endif
++
++extern const guint orbit_major_version,
++ orbit_minor_version,
++ orbit_micro_version;
++extern const char orbit_version[];
++
++extern void CORBA_any_set_release(
++ CORBA_any *,
++ CORBA_boolean);
++
++extern CORBA_boolean CORBA_any_get_release(
++ CORBA_any *);
++
++extern void CORBA_sequence_set_release(
++ void *,
++ CORBA_boolean);
++
++extern CORBA_boolean CORBA_sequence_get_release(
++ void *);
++
++#define CORBA_any__alloc CORBA_any_alloc
++extern CORBA_any *CORBA_any_alloc(
++ void);
++
++extern gpointer CORBA_any__free(gpointer mem, gpointer func_data,
++ CORBA_boolean free_strings);
++extern gpointer CORBA_TypeCode__free(gpointer mem, gpointer func_data,
++ CORBA_boolean free_strings);
++
++extern CORBA_boolean ORBit_any_equivalent(
++ CORBA_any obj,
++ CORBA_any any,
++ CORBA_Environment *ev);
++
++extern CORBA_char *CORBA_string_dup(const CORBA_char *string);
++extern CORBA_char *CORBA_string_alloc(CORBA_unsigned_long len);
++extern gpointer CORBA_string__free(gpointer str, gpointer dat, CORBA_boolean free_strings);
++
++gpointer CORBA_Object__free(gpointer str, gpointer dat, CORBA_boolean free_strings);
++
++extern CORBA_wchar *CORBA_wstring_alloc(CORBA_unsigned_long len);
++#define CORBA_wstring_free CORBA_string_free
++
++/* 19.14 */
++extern CORBA_long CORBA_fixed_integer_part(
++ const void *fp);
++
++extern CORBA_long CORBA_fixed_fraction_part(
++ const void *fp);
++
++extern void CORBA_fixed_set(
++ void *rp,
++ CORBA_long i,
++ CORBA_long f);
++
++extern void CORBA_fixed_add(
++ void *rp,
++ const void *f1p,
++ const void *f2p);
++
++extern void CORBA_fixed_sub(
++ void *rp,
++ const void *f1p,
++ const void *f2p);
++
++extern void CORBA_fixed_mul(
++ void *rp,
++ const void *f1p,
++ const void *f2p);
++
++extern void CORBA_fixed_div(
++ void *rp,
++ const void *f1p,
++ const void *f2p);
++
++extern CORBA_fixed_d_s *CORBA_fixed_alloc(
++ CORBA_unsigned_short d);
++
++extern void CORBA_free(
++ void *storage);
++
++extern int ORBit_parse_inet(
++ CORBA_Object obj,
++ char *hostname,
++ unsigned short port,
++ gboolean existing_only);
++
++extern int ORBit_parse_unixsock(CORBA_Object obj,
++ char *sockpath,
++ gboolean existing_only);
++
++/****
++ This function lets you use your own event loop, if you so wish.
++ Also see IIOP.h's IIOP{Add,Remove}ConnectionHandler function pointers,
++ which are app-settable (you should set them before CORBA_ORB_init,
++ if you want them to be useful)
++ ****/
++
++ /* needs to be called by your event loop when data comes in on one of the
++ GIOPConnection fd's */
++void ORBit_custom_run_setup(CORBA_ORB orb, CORBA_Environment *ev);
++ void ORBit_handle_incoming(GIOPConnection *connection);
++
++/* Returns CORBA_TRUE if the request is OK to proceed. */
++typedef enum {
++ ORBIT_MESSAGE_BAD,
++ ORBIT_MESSAGE_ALLOW,
++ ORBIT_MESSAGE_ALLOW_ALL /* Allow all subsequent messages on
++ this connection with no checking */
++} ORBit_MessageValidationResult;
++typedef ORBit_MessageValidationResult (*ORBit_request_validate)
++ (CORBA_unsigned_long request_id,
++ CORBA_Principal *principal,
++ CORBA_char *operation);
++void ORBit_set_request_validation_handler(ORBit_request_validate validator);
++
++extern struct iovec ORBit_default_principal_iovec;
++void ORBit_set_default_principal(CORBA_Principal *principal);
++
++extern CORBA_unsigned_long ORBit_class_assignment_counter;
++
++CORBA_unsigned_long ORBit_register_class(const PortableServer_ClassInfo *class_info);
++
++#ifdef __cplusplus
++}
++#endif /* __cplusplus */
++
++#endif /* !_ORBIT_H_ */
+diff -urN linux-2.4.1/net/korbit/orb/orbit_config.h linux-2.4.1-korbit/net/korbit/orb/orbit_config.h
+--- linux-2.4.1/net/korbit/orb/orbit_config.h Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/orb/orbit_config.h Thu Feb 1 11:47:13 2001
+@@ -0,0 +1,9 @@
++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
++#ifndef ORB_CONFIG_H
++#define ORB_CONFIG_H 1
++
++/* When creating a memory pool for a particular type, how many chunks
++ do we want to pre-allocated? */
++#define ORBIT_CHUNKS_PREALLOC 2
++
++#endif /* ORB_CONFIG_H */
+diff -urN linux-2.4.1/net/korbit/orb/orbit_object.c linux-2.4.1-korbit/net/korbit/orb/orbit_object.c
+--- linux-2.4.1/net/korbit/orb/orbit_object.c Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/orb/orbit_object.c Thu Feb 1 11:47:13 2001
+@@ -0,0 +1,699 @@
++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
++
++/*
++ * ORBit: A CORBA v2.2 ORB
++ *
++ * Copyright (C) 1998 Richard H. Porter and Red Hat Software
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Library General Public
++ * License as published by the Free Software Foundation; either
++ * version 2 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Library General Public License for more details.
++ *
++ * You should have received a copy of the GNU Library General Public
++ * License along with this library; if not, write to the Free
++ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Author: Phil Dawes <philipd@parallax.co.uk>
++ * Elliot Lee <sopwith@redhat.com>
++ *
++ */
++
++/*
++ * ORBit specific CORBA_Object functions.
++ *
++ */
++
++#include <string.h>
++#include "config.h"
++#include "../IIOP/iiop-endianP.h"
++#include "orbit_object_type.h"
++#include "corba_object_type.h"
++#include "allocators.h"
++#include "iop.h"
++#include <IIOP/IIOP.h>
++
++static void ORBit_object_try_existing_connections(CORBA_Object obj);
++static void CORBA_Object_release_fn(CORBA_Object obj, CORBA_Environment *ev);
++
++static ORBit_RootObject_Interface CORBA_Object_epv =
++{
++ (void (*)(gpointer, CORBA_Environment *))CORBA_Object_release_fn,
++};
++
++void ORBit_pseudo_object_init(ORBit_PseudoObject obj,
++ ORBit_PseudoObject_type obj_type,
++ CORBA_Environment *ev)
++{
++ ORBIT_ROOT_OBJECT(obj)->is_pseudo_object = TRUE;
++ ORBIT_ROOT_OBJECT(obj)->refs = 0;
++ ORBIT_PSEUDO_OBJECT(obj)->pseudo_object_type = obj_type;
++}
++
++static const ORBit_RootObject_Interface CORBA_Policy__epv =
++{
++ (void (*)(gpointer, CORBA_Environment *))CORBA_Policy_destroy
++};
++
++void ORBit_policy_object_init(CORBA_Policy obj,
++ CORBA_PolicyType obj_type,
++ CORBA_Environment *ev)
++{
++ ORBit_pseudo_object_init(ORBIT_PSEUDO_OBJECT(obj),
++ ORBIT_PSEUDO_POLICY, ev);
++
++ obj->policy_type = obj_type;
++
++ ORBit_RootObject_set_interface(ORBIT_ROOT_OBJECT(obj),
++ (gpointer)&CORBA_Policy__epv,
++ ev);
++}
++
++void ORBit_object_reference_init(CORBA_Object obj, CORBA_Environment *ev)
++{
++ /* set the interface up */
++ ORBit_RootObject_set_interface(ORBIT_ROOT_OBJECT(obj),&CORBA_Object_epv,ev);
++ /* initialise the reference count */
++ ORBIT_ROOT_OBJECT(obj)->refs = 0;
++ ORBIT_ROOT_OBJECT(obj)->is_pseudo_object = FALSE;
++}
++
++CORBA_Object
++ORBit_CORBA_Object_new(CORBA_Environment *ev)
++{
++ CORBA_Object obj;
++ /* Create the object */
++ obj = ORBIT_CHUNK_ALLOC(CORBA_Object);
++ memset(obj, '\0', sizeof(struct CORBA_Object_struct));
++
++ ORBit_object_reference_init(obj, ev);
++
++ return obj;
++
++}
++
++void
++ORBit_set_object_key(ORBit_Object_info *info)
++{
++ g_assert(info);
++
++ g_assert(info->object_key._length);
++
++ info->object_key_data = g_malloc(sizeof(CORBA_unsigned_long) + info->object_key._length);
++ info->object_key_data->_length = info->object_key._length;
++ memcpy(info->object_key_data->_buffer, info->object_key._buffer, info->object_key._length);
++
++ info->object_key_vec.iov_base =
++ (gpointer)info->object_key_data;
++ info->object_key_vec.iov_len = sizeof(CORBA_unsigned_long) + info->object_key._length;
++}
++
++static void ORBit_free_profile(gpointer item, gpointer data)
++{
++ ORBit_Object_info *info=(ORBit_Object_info *)item;
++
++ g_assert(info);
++
++ g_free(info->object_key_data);
++ CORBA_free(info->object_key._buffer);
++
++ if(info->profile_type == IOP_TAG_INTERNET_IOP) {
++ g_free(info->tag.iopinfo.host);
++ } else if(info->profile_type == IOP_TAG_ORBIT_SPECIFIC) {
++ g_free(info->tag.orbitinfo.unix_sock_path);
++ } else {
++ g_warning("ORBit_free_profile asked to free type %d", info->profile_type);
++ }
++
++ g_free(info); /* Check its safe to free the item within a foreach func */
++}
++
++void ORBit_delete_profiles(GSList *profile_list)
++{
++ g_slist_foreach(profile_list, ORBit_free_profile, NULL);
++ g_slist_free(profile_list);
++}
++
++/* this function is wired up to the RootObject interface */
++void
++CORBA_Object_release_fn(CORBA_Object obj, CORBA_Environment *ev)
++{
++
++ g_assert(obj!=NULL);
++
++ ORBIT_ROOT_OBJECT_UNREF(obj);
++
++ if(ORBIT_ROOT_OBJECT(obj)->refs <= 0) {
++ g_hash_table_remove(obj->orb->objrefs, obj);
++
++ if(obj->connection)
++ giop_connection_unref(obj->connection);
++
++ g_free(obj->object_id);
++ ORBit_delete_profiles(obj->profile_list);
++ ORBit_delete_profiles(obj->forward_locations);
++
++ ORBIT_CHUNK_FREE(CORBA_Object, obj);
++ }
++}
++
++
++/* Sets the interface member in the RootObject to the epv specified*/
++void
++ORBit_RootObject_set_interface(ORBit_RootObject obj,
++ ORBit_RootObject_Interface* epv,
++ CORBA_Environment *ev)
++{
++ g_assert(obj!=NULL);
++ g_assert(epv!=NULL);
++
++ obj->interface = epv;
++}
++
++#define GET_ATOM(x) G_STMT_START{ GIOP_RECV_BUFFER(recv_buffer)->decoder(&x, (GIOP_RECV_BUFFER(recv_buffer)->cur), sizeof(x)); \
++GIOP_RECV_BUFFER(recv_buffer)->cur = ((guchar *)GIOP_RECV_BUFFER(recv_buffer)->cur) + sizeof(x); \
++}G_STMT_END
++#define ALIGNFOR(x) recv_buffer->cur = ALIGN_ADDRESS(recv_buffer->cur, sizeof(x))
++
++CORBA_Object
++ORBit_create_object_with_info(GSList *profiles,
++ const CORBA_char *type_id,
++ CORBA_ORB orb,
++ CORBA_Environment *ev)
++{
++ CORBA_Object new;
++ struct CORBA_Object_struct refcheck;
++
++ if(!type_id || !*type_id) {
++ g_warning("Failing object creation because object has no type");
++ CORBA_exception_set_system(ev, ex_CORBA_MARSHAL,
++ CORBA_COMPLETED_MAYBE);
++ return CORBA_OBJECT_NIL;
++ }
++
++ if(g_slist_length(profiles) < 1) {
++ g_warning("Failing object creation because object has no profiles");
++ CORBA_exception_set_system(ev, ex_CORBA_MARSHAL,
++ CORBA_COMPLETED_MAYBE);
++ return CORBA_OBJECT_NIL;
++ }
++
++ /* XXX badhack :) */
++ refcheck.object_id = type_id;
++ refcheck.profile_list = profiles;
++
++ new = g_hash_table_lookup(orb->objrefs, &refcheck);
++ if(new) {
++ ORBit_delete_profiles(profiles);
++ return CORBA_Object_duplicate(new, ev);
++ }
++
++ new = ORBit_CORBA_Object_new(ev);
++ new->connection = NULL;
++ new->object_id = g_strdup(type_id);
++ new->orb = (CORBA_ORB)CORBA_Object_duplicate((CORBA_Object)orb, ev);
++ new->profile_list = profiles;
++ new->active_profile = NULL;
++
++ ORBit_object_try_existing_connections(new);
++
++ g_hash_table_insert(orb->objrefs, new, new);
++
++ return CORBA_Object_duplicate(new, ev);
++}
++
++static ORBit_Object_info *
++ORBit_demarshal_profile(GIOPRecvBuffer *recv_buffer, IOP_ProfileId profile_id)
++{
++ ORBit_Object_info *object_info;
++ CORBA_unsigned_long subpart_len;
++ CORBA_octet o;
++ CDR_Codec codec_d;
++ CDR_Codec *codec=&codec_d;
++
++ object_info = g_new0(ORBit_Object_info, 1);
++
++ switch(profile_id) {
++ case IOP_TAG_INTERNET_IOP:
++ GET_ATOM(subpart_len); /* The length of the embedded sequence */
++ CDR_codec_init_static(codec);
++ codec->buffer = recv_buffer->cur;
++ codec->release_buffer = CORBA_FALSE;
++ recv_buffer->cur = ((guchar *)recv_buffer->cur) + subpart_len;
++
++ codec->readonly = CORBA_TRUE;
++ codec->host_endian = codec->data_endian = FLAG_ENDIANNESS;
++ codec->buf_len = subpart_len;
++
++ CDR_get_octet(codec, &o);
++ codec->data_endian = o;
++
++ object_info->profile_type = IOP_TAG_INTERNET_IOP;
++ CDR_get_octet(codec, &object_info->iiop_major);
++
++ if(object_info->iiop_major != 1)
++ goto error_exit;
++ /* XXX should we check for a specific minor version? */
++ CDR_get_octet(codec, &object_info->iiop_minor);
++
++ CDR_get_string(codec, &object_info->tag.iopinfo.host);
++
++ CDR_get_ushort(codec, &object_info->tag.iopinfo.port);
++
++ CDR_get_seq_begin(codec, &object_info->object_key._length);
++ object_info->object_key._buffer =
++ ORBit_alloc(object_info->object_key._length, NULL, NULL);
++ CDR_buffer_gets(codec, object_info->object_key._buffer,
++ object_info->object_key._length);
++ object_info->object_key._maximum = object_info->object_key._release = 0;
++
++ ORBit_set_object_key(object_info);
++
++ return(object_info);
++ break;
++
++ case IOP_TAG_MULTIPLE_COMPONENTS:
++ default:
++ GET_ATOM(subpart_len);
++ g_warning("IOP_TAG_MULTIPLE_COMPONENTS decoding needs finishing");
++ object_info->profile_type = IOP_TAG_MULTIPLE_COMPONENTS;
++ recv_buffer->cur = ((guchar *)recv_buffer->cur) + subpart_len;
++ return(object_info);
++ break;
++
++ case IOP_TAG_ORBIT_SPECIFIC:
++ GET_ATOM(subpart_len);
++ CDR_codec_init_static(codec);
++ codec->buffer = recv_buffer->cur;
++ codec->release_buffer = CORBA_FALSE;
++ recv_buffer->cur = ((guchar *)recv_buffer->cur) + subpart_len;
++
++ codec->readonly = CORBA_TRUE;
++ codec->host_endian = codec->data_endian = FLAG_ENDIANNESS;
++ codec->buf_len = subpart_len;
++
++ CDR_get_octet(codec, &o);
++ codec->data_endian = o;
++
++ object_info->profile_type = IOP_TAG_ORBIT_SPECIFIC;
++ CDR_get_octet(codec, &object_info->iiop_major);
++
++ if(object_info->iiop_major != 1)
++ goto error_exit;
++ /* XXX should we check for a specific minor version? */
++ CDR_get_octet(codec, &object_info->iiop_minor);
++
++ CDR_get_string(codec, &object_info->tag.orbitinfo.unix_sock_path);
++ CDR_get_ushort(codec, &object_info->tag.orbitinfo.ipv6_port);
++
++ CDR_get_seq_begin(codec, &object_info->object_key._length);
++ object_info->object_key._buffer =
++ ORBit_alloc(object_info->object_key._length, NULL, NULL);
++ CDR_buffer_gets(codec, object_info->object_key._buffer,
++ object_info->object_key._length);
++ object_info->object_key._maximum = object_info->object_key._release = 0;
++
++ ORBit_set_object_key(object_info);
++
++ return(object_info);
++ break;
++ }
++
++error_exit:
++ g_message("demarshal_profile(): IIOP major is %d",
++ object_info->iiop_major);
++ g_free(object_info);
++
++ return(NULL);
++}
++
++GSList *ORBit_demarshal_IOR(GIOPRecvBuffer *recv_buffer)
++{
++ GSList *profiles=NULL;
++ ORBit_Object_info *object_info;
++ CORBA_unsigned_long len, seq_len;
++ IOP_ProfileId profile_id;
++ int i;
++
++ /* Get type_id */
++ ALIGNFOR(CORBA_unsigned_long);
++ GET_ATOM(len);
++
++ if(len == 0)
++ return(NULL);
++
++ recv_buffer->cur = ((guchar *)recv_buffer->cur) + len;
++
++ /* Decode the sequence<TaggedProfile> */
++ ALIGNFOR(CORBA_unsigned_long);
++ GET_ATOM(seq_len);
++ for(i = 0; i < seq_len; i++) {
++ ALIGNFOR(CORBA_unsigned_long);
++ GET_ATOM(profile_id);
++ object_info=ORBit_demarshal_profile(recv_buffer, profile_id);
++ if(object_info==NULL) {
++ goto error_exit;
++ } else {
++ profiles=g_slist_append(profiles, object_info);
++ }
++ }
++
++ return(profiles);
++
++error_exit:
++ ORBit_delete_profiles(profiles);
++ return(NULL);
++}
++
++CORBA_Object
++ORBit_demarshal_object(GIOPRecvBuffer *recv_buffer, CORBA_ORB orb)
++{
++ GSList *profiles=NULL;
++ ORBit_Object_info *object_info;
++ CORBA_char *type_id;
++ CORBA_unsigned_long len, seq_len;
++ IOP_ProfileId profile_id;
++ int i;
++ CORBA_Environment ev;
++ CORBA_Object retval;
++
++ CORBA_exception_init(&ev);
++
++ /* Get type_id */
++ ALIGNFOR(CORBA_unsigned_long);
++ GET_ATOM(len);
++
++ type_id = recv_buffer->cur;
++ recv_buffer->cur = ((guchar *)recv_buffer->cur) + len;
++
++ /* Decode the sequence<TaggedProfile> */
++ ALIGNFOR(CORBA_unsigned_long);
++ GET_ATOM(seq_len);
++
++ if(!seq_len)
++ return CORBA_OBJECT_NIL;
++
++ for(i = 0; i < seq_len; i++) {
++ ALIGNFOR(CORBA_unsigned_long);
++ GET_ATOM(profile_id);
++ object_info=ORBit_demarshal_profile(recv_buffer, profile_id);
++ if(object_info)
++ profiles=g_slist_append(profiles, object_info);
++ }
++
++ if(!profiles)
++ goto error_exit;
++
++ retval = ORBit_create_object_with_info(profiles, type_id, orb, &ev);
++
++ return retval;
++
++ error_exit:
++ ORBit_delete_profiles(profiles);
++
++ CORBA_exception_set_system(&ev, ex_CORBA_MARSHAL,
++ CORBA_COMPLETED_MAYBE);
++ return CORBA_OBJECT_NIL;
++}
++
++static void ORBit_marshal_profile(gpointer item, gpointer data)
++{
++ ORBit_Object_info *info = (ORBit_Object_info *)item;
++ GIOPSendBuffer *send_buffer = (GIOPSendBuffer *)data;
++ static const CORBA_unsigned_long ioptag = IOP_TAG_INTERNET_IOP,
++ orbittag = IOP_TAG_ORBIT_SPECIFIC;
++ CDR_Codec codec_d;
++ CDR_Codec *codec = &codec_d;
++ CORBA_unsigned_long len;
++ CORBA_octet codecbuf[2048];
++ static const CORBA_octet oc_endian = FLAG_ENDIANNESS;
++ static const CORBA_octet iiopversion[] = {1,0};
++
++ g_assert(info);
++ g_assert(send_buffer);
++
++ if(info->profile_type == IOP_TAG_INTERNET_IOP) {
++ giop_message_buffer_append_mem(GIOP_MESSAGE_BUFFER(send_buffer),
++ &ioptag, sizeof(ioptag));
++
++ CDR_codec_init_static(codec);
++ codec->buffer = codecbuf;
++ codec->buf_len = 2048;
++ codec->release_buffer = CORBA_FALSE;
++ codec->readonly = CORBA_FALSE;
++ codec->data_endian = codec->host_endian = FLAG_ENDIANNESS;
++ CDR_put_octet(codec, oc_endian);
++ CDR_put_octet(codec, iiopversion[0]);
++ CDR_put_octet(codec, iiopversion[1]);
++ CDR_put_string(codec, info->tag.iopinfo.host);
++ CDR_put_ushort(codec, info->tag.iopinfo.port);
++ CDR_put_ulong(codec, info->object_key._length);
++ CDR_put_octets(codec, info->object_key._buffer,
++ info->object_key._length);
++ len = codec->wptr;
++ giop_send_buffer_append_mem_indirect_a(send_buffer,
++ &len, sizeof(len));
++ giop_send_buffer_append_mem_indirect(send_buffer,
++ codec->buffer, codec->wptr);
++ } else if(info->profile_type==IOP_TAG_ORBIT_SPECIFIC) {
++ giop_message_buffer_append_mem_a(GIOP_MESSAGE_BUFFER(send_buffer),
++ &orbittag, sizeof(orbittag));
++ CDR_codec_init_static(codec);
++ codec->buffer = codecbuf;
++ codec->release_buffer = CORBA_FALSE;
++ codec->buf_len = 2048;
++ codec->readonly = CORBA_FALSE;
++ codec->data_endian = codec->host_endian = FLAG_ENDIANNESS;
++ CDR_put_octet(codec, oc_endian);
++ CDR_put_octets(codec, (gpointer)iiopversion, sizeof(iiopversion));
++ CDR_put_string(codec, info->tag.orbitinfo.unix_sock_path);
++ CDR_put_ushort(codec, info->tag.orbitinfo.ipv6_port);
++ CDR_put_ulong(codec, info->object_key._length);
++ CDR_put_octets(codec, info->object_key._buffer,
++ info->object_key._length);
++ len = codec->wptr;
++ giop_send_buffer_append_mem_indirect_a(send_buffer,
++ &len, sizeof(len));
++ giop_send_buffer_append_mem_indirect(send_buffer,
++ codec->buffer, codec->wptr);
++ } else {
++ g_warning("ORBit_marshal_profile ask to marshal type %d\n", info->profile_type);
++ }
++}
++
++void
++ORBit_marshal_object(GIOPSendBuffer *send_buffer, CORBA_Object obj)
++{
++ CORBA_unsigned_long len;
++
++
++ if(!obj) {
++ static const CORBA_unsigned_long zero = 0, one = 1;
++ /* zero-length typename */
++ giop_message_buffer_append_mem_a(GIOP_MESSAGE_BUFFER(send_buffer),
++ &one, sizeof(one));
++ giop_message_buffer_append_mem(GIOP_MESSAGE_BUFFER(send_buffer),
++ &zero, 1);
++
++ /* zero profiles */
++ giop_message_buffer_append_mem_a(GIOP_MESSAGE_BUFFER(send_buffer),
++ &zero, sizeof(zero));
++ return;
++ }
++ g_return_if_fail(ORBIT_ROOT_OBJECT(obj)->refs > 0);
++
++ len = strlen(obj->object_id) + 1;
++ giop_send_buffer_append_mem_indirect_a(send_buffer, &len,
++ sizeof(len));
++ giop_message_buffer_append_mem(GIOP_MESSAGE_BUFFER(send_buffer),
++ obj->object_id, len);
++
++ len = g_slist_length(obj->profile_list);
++ giop_send_buffer_append_mem_indirect_a(GIOP_SEND_BUFFER(send_buffer),
++ &len, sizeof(len));
++
++ /* Marshal active first? */
++ g_slist_foreach(obj->profile_list, ORBit_marshal_profile, send_buffer);
++}
++
++static void ORBit_test_profile(gpointer item, gpointer data)
++{
++ ORBit_Object_info *info = (ORBit_Object_info *)item;
++ CORBA_Object obj = (CORBA_Object)data;
++
++ if(obj->active_profile != NULL)
++ return; /* we already have a good profile */
++
++ if(info->profile_type == IOP_TAG_ORBIT_SPECIFIC) {
++ if(!ORBit_parse_unixsock(obj, info->tag.orbitinfo.unix_sock_path, TRUE)) {
++ /* success */
++ obj->active_profile=info;
++ }
++ } else if(info->profile_type == IOP_TAG_INTERNET_IOP) {
++ if(!ORBit_parse_inet(obj, info->tag.iopinfo.host, info->tag.iopinfo.port, TRUE)) {
++ /* success */
++ obj->active_profile=info;
++ }
++ }
++}
++
++static void
++ORBit_object_try_existing_connections(CORBA_Object obj)
++{
++ g_slist_foreach(obj->profile_list, ORBit_test_profile, obj);
++}
++
++static void ORBit_activate_profile(gpointer item, gpointer data)
++{
++ ORBit_Object_info *info = (ORBit_Object_info *)item;
++ CORBA_Object obj = (CORBA_Object)data;
++
++ if(obj->active_profile != NULL)
++ return; /* we already have a good profile */
++
++ if(info->profile_type == IOP_TAG_ORBIT_SPECIFIC) {
++ if(!ORBit_parse_unixsock(obj, info->tag.orbitinfo.unix_sock_path, FALSE)) {
++ /* success */
++ obj->active_profile=info;
++ }
++ } else if(info->profile_type == IOP_TAG_INTERNET_IOP) {
++ if(!ORBit_parse_inet(obj, info->tag.iopinfo.host, info->tag.iopinfo.port, FALSE)) {
++ /* success */
++ obj->active_profile=info;
++ }
++ }
++}
++
++GIOPConnection *
++_ORBit_object_get_connection(CORBA_Object obj)
++{
++ g_return_val_if_fail(obj, NULL);
++
++ if (obj->connection) {
++ giop_connection_unref(obj->connection);
++ obj->connection = NULL;
++ obj->active_profile = NULL;
++ }
++
++ g_slist_foreach(obj->profile_list, ORBit_activate_profile, obj);
++
++ if(obj->active_profile == NULL || !obj->connection)
++ return NULL;
++
++ obj->connection->orb_data = obj->orb;
++
++ return obj->connection;
++}
++
++GIOPConnection *
++ORBit_object_get_forwarded_connection(CORBA_Object obj)
++{
++ g_return_val_if_fail(obj, NULL);
++
++ if (obj->connection) {
++ giop_connection_unref(obj->connection);
++ obj->connection = NULL;
++ obj->active_profile = NULL;
++ }
++
++ g_slist_foreach(obj->forward_locations, ORBit_activate_profile, obj);
++
++ if(obj->active_profile == NULL || !obj->connection)
++ return NULL;
++
++ obj->connection->orb_data = obj->orb;
++
++ return obj->connection;
++}
++
++/* This function is heavily based on the idl stubs output. Any changes there
++ will probably have to be reflected here also. */
++
++void ORBit_object_locate(CORBA_Object obj, CORBA_Environment *ev)
++{
++ GIOPConnection *cnx;
++ GIOPSendBuffer *send_buffer;
++ GIOPRecvBuffer *recv_buffer;
++ GIOP_unsigned_long request_id;
++
++ g_return_if_fail(obj!=NULL);
++ g_return_if_fail(ev!=NULL);
++
++ /* Send a LOCATE_REQUEST, wait for a LOCATE_REPLY. The reply will
++ either say "Object here", or will carry a new location. We set
++ obj->active_profile appropriately */
++
++ cnx=ORBit_object_get_connection(obj);
++ if((cnx==NULL) || (obj->active_profile==NULL)) {
++ CORBA_exception_set_system(ev, ex_CORBA_COMM_FAILURE, CORBA_COMPLETED_NO);
++ return;
++ }
++ request_id=giop_get_request_id();
++ send_buffer=giop_send_locate_request_buffer_use(cnx, request_id, &(obj->active_profile->object_key_vec));
++ if(!send_buffer) {
++ CORBA_exception_set_system(ev, ex_CORBA_COMM_FAILURE, CORBA_COMPLETED_NO);
++ return;
++ }
++
++ giop_send_buffer_write(send_buffer);
++ giop_send_buffer_unuse(send_buffer);
++
++ recv_buffer=giop_recv_locate_reply_buffer_use(request_id, TRUE);
++ if(recv_buffer==NULL || recv_buffer->message_buffer.message_header.message_type!=GIOP_LOCATEREPLY) {
++ CORBA_exception_set_system(ev, ex_CORBA_COMM_FAILURE, CORBA_COMPLETED_MAYBE);
++ if(recv_buffer)
++ giop_recv_buffer_unuse(recv_buffer);
++
++ return;
++ }
++
++ ev->_major=CORBA_NO_EXCEPTION;
++ switch(recv_buffer->message.u.locate_reply.locate_status) {
++ case GIOP_UNKNOWN_OBJECT:
++ CORBA_exception_set_system(ev, ex_CORBA_OBJECT_NOT_EXIST, CORBA_COMPLETED_NO);
++ break;
++
++ case GIOP_OBJECT_HERE:
++ /* No further processing necessary */
++ break;
++
++ case GIOP_OBJECT_FORWARD:
++ /* We've been forwarded onto somewhere else. The message body
++ contains the new IOR */
++ if(obj->forward_locations != NULL) {
++ ORBit_delete_profiles(obj->forward_locations);
++ }
++ obj->forward_locations=ORBit_demarshal_IOR(recv_buffer);
++
++ /* This will adjust obj->active_profile */
++ cnx=ORBit_object_get_forwarded_connection(obj);
++ break;
++
++ default:
++ g_message("Bad Reply in ORBit_locate_object()\n");
++ break;
++
++ }
++
++ giop_recv_buffer_unuse(recv_buffer);
++}
++
++GIOPConnection *
++ORBit_handle_location_forward(GIOPRecvBuffer *rb, CORBA_Object obj)
++{
++ GIOPConnection *retval;
++
++ if(obj->forward_locations)
++ ORBit_delete_profiles(obj->forward_locations);
++ obj->forward_locations = ORBit_demarshal_IOR(rb);
++
++ retval = ORBit_object_get_forwarded_connection(obj);
++ giop_recv_buffer_unuse(rb);
++
++ return retval;
++}
+diff -urN linux-2.4.1/net/korbit/orb/orbit_object.h linux-2.4.1-korbit/net/korbit/orb/orbit_object.h
+--- linux-2.4.1/net/korbit/orb/orbit_object.h Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/orb/orbit_object.h Thu Feb 1 16:20:50 2001
+@@ -0,0 +1,114 @@
++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
++
++/*
++ * ORBit: A CORBA v2.2 ORB
++ *
++ * Copyright (C) 1998 Richard H. Porter and Red Hat Software
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Library General Public
++ * License as published by the Free Software Foundation; either
++ * version 2 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Library General Public License for more details.
++ *
++ * You should have received a copy of the GNU Library General Public
++ * License along with this library; if not, write to the Free
++ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Author: Phil Dawes <philipd@parallax.co.uk>
++ *
++ */
++
++/*
++ * ORBit specific CORBA_Object funcitons.
++ *
++ */
++#ifndef _ORBIT_ORBIT_OBJECT_H_
++#define _ORBIT_ORBIT_OBJECT_H_
++
++#include <IIOP/IIOP.h>
++#include "corba_object.h"
++
++extern CORBA_Object ORBit_CORBA_Object_new(CORBA_Environment *ev);
++extern void ORBit_CORBA_Object_free(CORBA_Object obj, CORBA_Environment *ev);
++
++
++typedef enum {
++ ORBIT_PSEUDO_ORB,
++ ORBIT_PSEUDO_POA,
++ ORBIT_PSEUDO_POAMANAGER,
++ ORBIT_PSEUDO_POLICY,
++ ORBIT_PSEUDO_TYPECODE,
++ ORBIT_PSEUDO_REQUEST,
++ ORBIT_PSEUDO_SERVERREQUEST,
++ ORBIT_PSEUDO_CONTEXT
++} ORBit_PseudoObject_type;
++typedef struct ORBit_PseudoObject_struct *ORBit_PseudoObject;
++
++void ORBit_pseudo_object_init(ORBit_PseudoObject obj,
++ ORBit_PseudoObject_type obj_type,
++ CORBA_Environment *ev);
++void ORBit_policy_object_init(CORBA_Policy obj,
++ CORBA_PolicyType obj_type,
++ CORBA_Environment *ev);
++
++/* Use ORBit_CORBA_Object_new() */
++void ORBit_object_reference_init(CORBA_Object obj, CORBA_Environment *ev);
++
++typedef struct {
++ CORBA_char *host;
++ CORBA_unsigned_short port;
++} TAG_INTERNET_IOP_info;
++
++typedef struct {
++ CORBA_char *unix_sock_path;
++ CORBA_unsigned_short ipv6_port;
++} TAG_ORBIT_SPECIFIC_info;
++
++typedef struct {
++ int fill_me_in;
++} TAG_MULTIPLE_COMPONENTS_info;
++
++typedef struct {
++ CORBA_octet iiop_major, iiop_minor;
++ IOP_ProfileId profile_type;
++ union {
++ TAG_INTERNET_IOP_info iopinfo;
++ TAG_ORBIT_SPECIFIC_info orbitinfo;
++ TAG_MULTIPLE_COMPONENTS_info mcinfo;
++ } tag;
++
++ /* If the object key is invariant wrt to the various profiles, then
++ this should probably go in CORBA_Object_struct
++ */
++ CORBA_sequence_octet object_key;
++ struct { CORBA_unsigned_long _length; char _buffer[1]; } *object_key_data;
++ struct iovec object_key_vec;
++} ORBit_Object_info;
++
++void ORBit_set_object_key(ORBit_Object_info *info);
++
++CORBA_Object ORBit_create_object_with_info(GSList *profiles,
++ const CORBA_char *type_id,
++ CORBA_ORB orb,
++ CORBA_Environment *ev);
++
++#define ORBit_object_get_connection(obj) \
++ ((obj)->connection && (obj)->connection->is_valid)?((obj)->connection):_ORBit_object_get_connection(obj)
++GIOPConnection *_ORBit_object_get_connection(CORBA_Object obj);
++GIOPConnection *ORBit_object_get_forwarded_connection(CORBA_Object obj);
++void ORBit_object_locate(CORBA_Object obj, CORBA_Environment *ev);
++
++void ORBit_marshal_object(GIOPSendBuffer *send_buffer, CORBA_Object obj);
++CORBA_Object ORBit_demarshal_object(GIOPRecvBuffer *recv_buffer,
++ CORBA_ORB orb);
++GSList *ORBit_demarshal_IOR(GIOPRecvBuffer *recv_buffer);
++
++extern void ORBit_delete_profiles(GSList *profile_list);
++GIOPConnection *ORBit_handle_location_forward(GIOPRecvBuffer *rb, CORBA_Object obj);
++
++#endif /* _ORBIT_ORBIT_OBJECT_H_ */
+diff -urN linux-2.4.1/net/korbit/orb/orbit_object_type.h linux-2.4.1-korbit/net/korbit/orb/orbit_object_type.h
+--- linux-2.4.1/net/korbit/orb/orbit_object_type.h Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/orb/orbit_object_type.h Thu Feb 1 16:20:50 2001
+@@ -0,0 +1,87 @@
++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
++
++/*
++ * ORBit: A CORBA v2.2 ORB
++ *
++ * Copyright (C) 1998 Richard H. Porter
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Library General Public
++ * License as published by the Free Software Foundation; either
++ * version 2 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Library General Public License for more details.
++ *
++ * You should have received a copy of the GNU Library General Public
++ * License along with this library; if not, write to the Free
++ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Author: Dick Porter <dick@cymru.net>
++ * Philip Dawes
++ * Elliot Lee <sopwith@redhat.com>
++ *
++ */
++
++#ifndef _ORBIT_ORBIT_OBJECT_TYPE_H_
++#define _ORBIT_ORBIT_OBJECT_TYPE_H_
++
++#include "orbit_object.h"
++
++
++/****** Root object **********/
++/*****************************/
++
++typedef struct ORBit_RootObject_Interface_struct ORBit_RootObject_Interface;
++struct ORBit_RootObject_Interface_struct
++{
++ void (*release)(gpointer obj, CORBA_Environment *ev);
++};
++
++
++
++#define ORBIT_ROOT_OBJECT(x) ((ORBit_RootObject)(x))
++
++
++typedef struct ORBit_RootObject_struct *ORBit_RootObject;
++struct ORBit_RootObject_struct {
++ ORBit_RootObject_Interface* interface; /* the interface */
++
++ guchar is_pseudo_object;
++ gint refs;
++};
++
++
++/* Reference counting interface */
++
++#define ORBIT_ROOT_OBJECT_REF(obj) (ORBIT_ROOT_OBJECT(obj)->refs++)
++#define ORBIT_ROOT_OBJECT_UNREF(obj) (ORBIT_ROOT_OBJECT(obj)->refs--)
++
++
++ /* Virtual function interface*/
++
++#define ORBIT_ROOT_OBJECT_release(obj,ev) \
++(ORBIT_ROOT_OBJECT(obj)->interface->release(obj,ev))
++
++
++
++extern void ORBit_RootObject_set_interface(ORBit_RootObject obj,
++ ORBit_RootObject_Interface* epv,
++ CORBA_Environment *ev);
++
++
++
++/****** Pseudo object --> RootObject ********/
++/*********************************************/
++
++#define ORBIT_PSEUDO_OBJECT(x) ((ORBit_PseudoObject)(x))
++
++struct ORBit_PseudoObject_struct {
++ struct ORBit_RootObject_struct parent;
++ ORBit_PseudoObject_type pseudo_object_type;
++};
++
++
++#endif /* !_ORBIT_CORBA_OBJECT_TYPE_H_ */
+diff -urN linux-2.4.1/net/korbit/orb/orbit_poa.c linux-2.4.1-korbit/net/korbit/orb/orbit_poa.c
+--- linux-2.4.1/net/korbit/orb/orbit_poa.c Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/orb/orbit_poa.c Thu Feb 1 11:47:13 2001
+@@ -0,0 +1,809 @@
++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
++
++/*
++ * ORBit: A CORBA v2.2 ORB
++ *
++ * Copyright (C) 1998 Richard H. Porter and Red Hat Software
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Library General Public
++ * License as published by the Free Software Foundation; either
++ * version 2 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Library General Public License for more details.
++ *
++ * You should have received a copy of the GNU Library General Public
++ * License along with this library; if not, write to the Free
++ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Author: Phil Dawes <philipd@parallax.co.uk>
++ * Elliot Lee <sopwith@redhat.com>
++ *
++ */
++
++/*
++ * ORBit specific POA funcitons.
++ *
++ */
++
++#include <string.h>
++#include "orbit.h"
++#include "orbit_poa_type.h"
++#include "orbit_poa.h"
++#include "genrand.h"
++
++#define POA_KEY_LEN (sizeof(CORBA_unsigned_long) + ORBIT_RAND_KEY_LEN)
++#define OBJ_KEY_LEN (sizeof(CORBA_unsigned_long) + ORBIT_RAND_KEY_LEN)
++
++static void ORBit_POAManager_release(PortableServer_POAManager poa_mgr,
++ CORBA_Environment *ev);
++
++static void ORBit_POA_release(PortableServer_POA poa,
++ CORBA_Environment *ev);
++
++static PortableServer_Servant
++ORBit_POA_ServantManager_use_servant(PortableServer_POA poa,
++ GIOPRecvBuffer *recv_buffer,
++ PortableServer_ServantLocator_Cookie *the_cookie,
++ PortableServer_ObjectId *oid,
++ ORBit_POAObject *fake_obj_impl,
++ CORBA_Environment *ev);
++static void
++ORBit_POA_ServantManager_unuse_servant(PortableServer_Servant servant,
++ PortableServer_POA poa,
++ GIOPRecvBuffer *recv_buffer,
++ PortableServer_ServantLocator_Cookie cookie,
++ PortableServer_ObjectId *oid,
++ ORBit_POAObject *fake_obj_impl,
++ CORBA_Environment *ev);
++
++static const ORBit_RootObject_Interface CORBA_POAManager_epv =
++{
++ (void (*)(gpointer, CORBA_Environment *))ORBit_POAManager_release,
++};
++
++static const ORBit_RootObject_Interface CORBA_POA_epv =
++{
++ (void (*)(gpointer, CORBA_Environment *))ORBit_POA_release,
++};
++
++guint
++g_sequence_octet_hash(CORBA_sequence_octet *so)
++{
++ const char *s = (char*)so->_buffer;
++ const char *p, *e = ((char *)so->_buffer) + so->_length;
++ guint h=0, g;
++
++ for(p = s; p < e; p ++) {
++ h = ( h << 4 ) + *p;
++ if ( ( g = h & 0xf0000000 ) ) {
++ h = h ^ (g >> 24);
++ h = h ^ g;
++ }
++ }
++
++ return h;
++}
++
++gint
++g_sequence_octet_compare(CORBA_sequence_octet *s1, CORBA_sequence_octet *s2)
++{
++ if(s2->_length != s1->_length)
++ return FALSE;
++
++ return !memcmp(s1->_buffer, s2->_buffer, s1->_length);
++}
++
++PortableServer_POAManager
++ORBit_POAManager_new(CORBA_Environment *ev)
++{
++ PortableServer_POAManager poa_mgr;
++
++ poa_mgr = g_new0(struct PortableServer_POAManager_type, 1);
++
++ if(poa_mgr == NULL) {
++ CORBA_exception_set_system(ev, ex_CORBA_NO_MEMORY, CORBA_COMPLETED_NO);
++ goto error;
++ }
++
++ /* Initialise poa manager */
++
++ ORBit_pseudo_object_init(ORBIT_PSEUDO_OBJECT(poa_mgr),
++ ORBIT_PSEUDO_POAMANAGER, ev);
++ ORBIT_ROOT_OBJECT(poa_mgr)->refs = 0;
++ ORBit_RootObject_set_interface(ORBIT_ROOT_OBJECT(poa_mgr),
++ (gpointer)&CORBA_POAManager_epv, ev);
++
++ poa_mgr->poa_collection = NULL;
++ poa_mgr->state = PortableServer_POAManager_HOLDING;
++
++ return poa_mgr;
++
++error:
++ if(poa_mgr != NULL){
++ ORBit_POAManager_release(poa_mgr, ev);
++ }
++ return NULL;
++}
++
++static void
++ORBit_POAManager_release(PortableServer_POAManager poa_mgr,
++ CORBA_Environment *ev)
++{
++
++ if(--(ORBIT_ROOT_OBJECT(poa_mgr)->refs) > 0)
++ return;
++
++ if(poa_mgr != NULL) {
++ if(poa_mgr->poa_collection != NULL) {
++ g_slist_free(poa_mgr->poa_collection);
++ poa_mgr->poa_collection = NULL;
++ }
++ g_free(poa_mgr);
++ poa_mgr = NULL;
++ }
++}
++
++static void
++ORBit_POAManager_register_poa(PortableServer_POAManager poa_mgr,
++ PortableServer_POA poa,
++ CORBA_Environment *ev)
++{
++ poa_mgr->poa_collection = g_slist_remove(poa_mgr->poa_collection, poa);
++ poa_mgr->poa_collection =
++ g_slist_append(poa_mgr->poa_collection, poa);
++}
++
++static void
++ORBit_POAManager_unregister_poa(PortableServer_POAManager poa_mgr,
++ PortableServer_POA poa,
++ CORBA_Environment *ev)
++{
++ poa_mgr->poa_collection = g_slist_remove(poa_mgr->poa_collection, poa);
++}
++
++static void
++ORBit_POA_set_policy(PortableServer_POA poa,
++ CORBA_Policy policy,
++ CORBA_Environment *ev)
++{
++ switch(policy->policy_type) {
++ case PortableServer_THREAD_POLICY_ID:
++ poa->thread = ((PortableServer_ThreadPolicy)policy)->value;
++ break;
++ case PortableServer_LIFESPAN_POLICY_ID:
++ poa->lifespan = ((PortableServer_LifespanPolicy)policy)->value;
++ break;
++ case PortableServer_ID_UNIQUENESS_POLICY_ID:
++ poa->id_uniqueness = ((PortableServer_IdUniquenessPolicy)policy)->value;
++ break;
++ case PortableServer_ID_ASSIGNMENT_POLICY_ID:
++ poa->id_assignment = ((PortableServer_IdAssignmentPolicy)policy)->value;
++ break;
++ case PortableServer_IMPLICIT_ACTIVATION_POLICY_ID:
++ poa->implicit_activation = ((PortableServer_ImplicitActivationPolicy)policy)->value;
++ break;
++ case PortableServer_SERVANT_RETENTION_POLICY_ID:
++ poa->servant_retention = ((PortableServer_ServantRetentionPolicy)policy)->value;
++ break;
++ case PortableServer_REQUEST_PROCESSING_POLICY_ID:
++ poa->request_processing = ((PortableServer_ServantRetentionPolicy)policy)->value;
++ break;
++ default:
++ g_warning("Unknown policy type, cannot set it on this POA");
++ }
++}
++
++
++static void
++ORBit_POA_check_policy_conflicts(PortableServer_POA poa,
++ CORBA_Environment *ev)
++{
++
++ /* Check for those policy combinations that aren't allowed */
++ if ((poa->servant_retention == PortableServer_NON_RETAIN &&
++ poa->request_processing == PortableServer_USE_ACTIVE_OBJECT_MAP_ONLY) ||
++
++ (poa->request_processing == PortableServer_USE_DEFAULT_SERVANT &&
++ poa->id_uniqueness == PortableServer_UNIQUE_ID) ||
++
++ (poa->implicit_activation == PortableServer_IMPLICIT_ACTIVATION &&
++ (poa->id_assignment == PortableServer_USER_ID ||
++ poa->servant_retention == PortableServer_NON_RETAIN))
++ )
++ {
++ CORBA_exception_set(ev, CORBA_USER_EXCEPTION,
++ ex_PortableServer_POA_InvalidPolicy,
++ NULL);
++ }
++}
++
++
++static void
++ORBit_POA_set_policylist(PortableServer_POA poa,
++ CORBA_PolicyList *policies,
++ CORBA_Environment *ev)
++{
++ CORBA_unsigned_long i;
++
++ for(i = 0; i < policies->_length; i++) {
++ if(ev->_major != CORBA_NO_EXCEPTION)
++ break;
++ ORBit_POA_set_policy(poa, policies->_buffer[i], ev);
++ }
++}
++
++PortableServer_POA
++ORBit_POA_new(CORBA_ORB orb,
++ CORBA_char *adapter_name,
++ PortableServer_POAManager the_POAManager,
++ CORBA_PolicyList *policies,
++ CORBA_Environment *ev)
++{
++ PortableServer_POA poa;
++
++ /* Create the object */
++ poa = (PortableServer_POA) g_new0(struct PortableServer_POA_type, 1);
++ if(poa == NULL) {
++ CORBA_exception_set_system(ev, ex_CORBA_NO_MEMORY, CORBA_COMPLETED_NO);
++ goto error;
++ }
++
++ ORBit_pseudo_object_init(ORBIT_PSEUDO_OBJECT(poa), ORBIT_PSEUDO_POA, ev);
++
++ ORBIT_ROOT_OBJECT(poa)->refs = 0;
++ ORBit_RootObject_set_interface(ORBIT_ROOT_OBJECT(poa),
++ (gpointer)&CORBA_POA_epv, ev);
++
++ if(ev->_major != CORBA_NO_EXCEPTION) goto error;
++
++ /* If no POAManager was specified, create one */
++ if(the_POAManager == NULL) {
++ the_POAManager = ORBit_POAManager_new(ev);
++ }
++
++ /* Register this poa with the poa manager */
++ if(the_POAManager != NULL)
++ ORBit_POAManager_register_poa(the_POAManager,poa,ev);
++ if(ev->_major != CORBA_NO_EXCEPTION) goto error;
++
++ /* Wire up the poa_manager */
++ poa->the_POAManager = the_POAManager;
++
++ /* Initialise the child poas table */
++ poa->child_POAs = NULL; /* initialise the slist */
++
++ poa->held_requests = NULL;
++
++ poa->poaID = orb->poas->len;
++ g_ptr_array_set_size(orb->poas, orb->poas->len + 1);
++ g_ptr_array_index(orb->poas, poa->poaID) = poa;
++
++ poa->orb = orb;
++
++ g_return_val_if_fail(ev->_major == CORBA_NO_EXCEPTION, NULL);
++
++ /* Need to initialise poa policies etc.. here */
++ poa->thread = PortableServer_ORB_CTRL_MODEL;
++ poa->lifespan = PortableServer_TRANSIENT;
++ poa->id_uniqueness = PortableServer_UNIQUE_ID;
++ poa->id_assignment = PortableServer_SYSTEM_ID;
++ poa->servant_retention = PortableServer_RETAIN;
++ poa->request_processing = PortableServer_USE_ACTIVE_OBJECT_MAP_ONLY;
++ poa->implicit_activation = PortableServer_NO_IMPLICIT_ACTIVATION;
++ if (policies) {
++ ORBit_POA_set_policylist(poa, policies, ev);
++ ORBit_POA_check_policy_conflicts(poa, ev);
++ if(ev->_major != CORBA_NO_EXCEPTION) goto error;
++ }
++
++ /* copy the name */
++ poa->the_name = CORBA_string_dup(adapter_name);
++
++ poa->active_object_map = g_hash_table_new((GHashFunc)g_sequence_octet_hash,
++ (GCompareFunc)g_sequence_octet_compare);
++ poa->objnum_to_obj = g_ptr_array_new();
++ g_ptr_array_set_size(poa->objnum_to_obj, 1);
++ g_ptr_array_index(poa->objnum_to_obj, 0) = NULL;
++
++ orbit_genrand(poa->rand_data, ORBIT_RAND_KEY_LEN);
++
++ return poa;
++
++error:
++ if(poa && poa->the_name){
++ CORBA_free(poa->the_name);
++ }
++
++ if(poa != NULL){
++ ORBit_POA_release(poa, NULL);
++ }
++ return NULL;
++}
++
++static void
++ORBit_POA_release(PortableServer_POA poa,
++ CORBA_Environment *ev)
++{
++ ORBIT_ROOT_OBJECT_UNREF(poa);
++
++ if(ORBIT_ROOT_OBJECT(poa)->refs <= 0) {
++ CORBA_free(poa->the_name);
++
++ g_slist_foreach(poa->child_POAs, (GFunc)CORBA_Object_release,
++ ev);
++
++ if(poa->parent_poa)
++ ORBit_POA_remove_child(poa->parent_poa, poa, ev);
++
++ ORBit_POAManager_unregister_poa(poa->the_POAManager,
++ poa, ev);
++
++ g_ptr_array_index(poa->orb->poas, poa->poaID) = NULL;
++
++ g_free(poa);
++ }
++}
++
++void
++ORBit_POA_add_child(PortableServer_POA poa,
++ PortableServer_POA child_poa,
++ CORBA_Environment *ev)
++
++{
++ g_return_if_fail(poa != NULL);
++ g_return_if_fail(child_poa != NULL);
++
++ poa->child_POAs = g_slist_prepend(poa->child_POAs, child_poa);
++}
++
++void
++ORBit_POA_remove_child(PortableServer_POA poa,
++ PortableServer_POA child_poa,
++ CORBA_Environment *ev)
++{
++ g_return_if_fail(poa != NULL);
++ g_return_if_fail(child_poa != NULL);
++
++ poa->child_POAs = g_slist_remove(poa->child_POAs, child_poa);
++}
++
++extern ORBit_request_validate ORBIT_request_validator;
++
++gboolean
++ORBit_POA_handle_request(GIOPRecvBuffer *recv_buffer,
++ PortableServer_POA poa)
++{
++ PortableServer_ServantBase *servant;
++ PortableServer_ServantLocator_Cookie cookie;
++ ORBit_POAObject *obj_impl = NULL, tmp_obj_impl;
++ ORBitSkeleton skel;
++ gpointer imp = NULL;
++ CORBA_Environment ev;
++ GIOPSendBuffer *send_buffer;
++ guchar *opname;
++ PortableServer_ObjectId *oid = NULL;
++
++ CORBA_exception_init(&ev);
++
++ switch(poa->the_POAManager->state) {
++ case PortableServer_POAManager_HOLDING:
++ poa->held_requests = g_slist_prepend(poa->held_requests,
++ recv_buffer);
++ return FALSE;
++ break;
++ case PortableServer_POAManager_DISCARDING:
++ send_buffer = giop_send_reply_buffer_use(GIOP_MESSAGE_BUFFER(recv_buffer)->connection,
++ NULL,
++ recv_buffer->message.u.request.request_id,
++ CORBA_SYSTEM_EXCEPTION);
++ CORBA_exception_set_system(&ev,
++ ex_CORBA_TRANSIENT,
++ CORBA_COMPLETED_NO);
++ ORBit_send_system_exception(send_buffer, &ev);
++ giop_send_buffer_write(send_buffer);
++ giop_recv_buffer_unuse(recv_buffer);
++ giop_send_buffer_unuse(send_buffer);
++ CORBA_exception_free(&ev);
++ return TRUE;
++ break;
++ case PortableServer_POAManager_INACTIVE:
++ send_buffer = giop_send_reply_buffer_use(GIOP_MESSAGE_BUFFER(recv_buffer)->connection,
++ NULL,
++ recv_buffer->message.u.request.request_id,
++ CORBA_SYSTEM_EXCEPTION);
++ CORBA_exception_set_system(&ev,
++ ex_CORBA_OBJ_ADAPTER,
++ CORBA_COMPLETED_NO);
++ ORBit_send_system_exception(send_buffer, &ev);
++ giop_send_buffer_write(send_buffer);
++ giop_recv_buffer_unuse(recv_buffer);
++ giop_send_buffer_unuse(send_buffer);
++ CORBA_exception_free(&ev);
++ return TRUE;
++ break;
++ case PortableServer_POAManager_ACTIVE:
++ default:
++ break;
++ }
++
++ servant = NULL;
++
++ if(recv_buffer->message.u.request.object_key._length
++ < (POA_KEY_LEN + sizeof(CORBA_unsigned_long))) {
++ CORBA_exception_set_system(&ev,
++ ex_CORBA_OBJECT_NOT_EXIST,
++ CORBA_COMPLETED_NO);
++ goto errout;
++ }
++
++ obj_impl = ORBit_POA_find_oid_for_object_key(poa, &(recv_buffer->message.u.request.object_key), &oid);
++
++ if(poa->servant_retention == PortableServer_RETAIN
++ && obj_impl) {
++ servant = obj_impl->servant;
++ oid = obj_impl->object_id;
++ }
++
++ if(!servant) {
++ switch(poa->request_processing) {
++ case PortableServer_USE_SERVANT_MANAGER:
++ servant = ORBit_POA_ServantManager_use_servant(poa,
++ recv_buffer,
++ &cookie,
++ oid,
++ &tmp_obj_impl,
++ &ev);
++ break;
++ case PortableServer_USE_DEFAULT_SERVANT:
++ servant = poa->default_servant;
++ if(servant == NULL) {
++ CORBA_exception_set_system(&ev,
++ ex_CORBA_OBJ_ADAPTER,
++ CORBA_COMPLETED_NO);
++ goto errout;
++ }
++ break;
++ default:
++ break;
++ }
++ }
++
++ if(!poa || !servant || !servant->_private) {
++ CORBA_exception_set_system(&ev,
++ ex_CORBA_OBJECT_NOT_EXIST,
++ CORBA_COMPLETED_NO);
++ goto errout;
++ }
++
++ opname = recv_buffer->message.u.request.operation;
++
++ skel = ORBIT_OBJECT_KEY(servant->_private)->class_info->relay_call(servant, recv_buffer, &imp);
++
++ if(!skel) {
++ if (opname[0] == '_' && strcmp(opname + 1, "is_a") == 0) {
++ skel = (gpointer)&ORBit_impl_CORBA_Object_is_a;
++ }
++ else {
++ CORBA_exception_set_system(&ev, ex_CORBA_BAD_OPERATION,
++ CORBA_COMPLETED_NO);
++ goto errout;
++ }
++ }
++ else if (!imp) {
++ CORBA_exception_set_system(&ev, ex_CORBA_NO_IMPLEMENT,
++ CORBA_COMPLETED_NO);
++ goto errout;
++ }
++
++ /* If it got through the random keys, and nobody else had the opportunity to say otherwise, it must be auth'd */
++
++ if(!ORBIT_request_validator)
++ GIOP_MESSAGE_BUFFER(recv_buffer)->connection->is_auth = TRUE;
++
++ skel(servant, recv_buffer, &ev, imp);
++
++ if(poa->request_processing == PortableServer_USE_SERVANT_MANAGER) {
++ ORBit_POA_ServantManager_unuse_servant(servant,
++ poa,
++ recv_buffer,
++ cookie, oid,
++ &tmp_obj_impl,
++ &ev);
++ }
++
++ if(!obj_impl)
++ CORBA_free(oid);
++
++ CORBA_exception_free(&ev);
++
++ return TRUE;
++
++ errout:
++ if(ev._major == CORBA_SYSTEM_EXCEPTION) {
++ GIOPSendBuffer *reply_buf;
++
++ reply_buf =
++ giop_send_reply_buffer_use(GIOP_MESSAGE_BUFFER(recv_buffer)->connection,
++ NULL,
++ recv_buffer->message.u.request.request_id,
++ CORBA_SYSTEM_EXCEPTION);
++
++ ORBit_send_system_exception(reply_buf, &ev);
++
++ giop_send_buffer_write(reply_buf);
++ giop_send_buffer_unuse(reply_buf);
++ } else /* User exceptions are handled in the skels! */
++ g_assert(ev._major == CORBA_NO_EXCEPTION);
++
++ if(!obj_impl)
++ CORBA_free(oid);
++
++ CORBA_exception_free(&ev);
++
++ return TRUE;
++}
++
++PortableServer_POA
++ORBit_POA_find_POA_for_object_key(PortableServer_POA root_poa,
++ CORBA_sequence_octet *key)
++{
++ CORBA_unsigned_long pid;
++
++ if(key->_length < (sizeof(CORBA_unsigned_long) + ORBIT_RAND_KEY_LEN))
++ return NULL;
++
++ pid = *((CORBA_unsigned_long *)key->_buffer);
++
++ if(pid < root_poa->orb->poas->len) {
++ PortableServer_POA poa;
++ poa = g_ptr_array_index(root_poa->orb->poas, pid);
++ if(!poa)
++ return NULL;
++ if(memcmp(poa->rand_data, key->_buffer + sizeof(CORBA_unsigned_long), ORBIT_RAND_KEY_LEN))
++ return NULL;
++ return poa;
++ } else
++ return NULL;
++}
++
++void
++ORBit_POA_find_object_key_for_oid(PortableServer_POA poa,
++ ORBit_POAObject *obj,
++ PortableServer_ObjectId *oid,
++ CORBA_sequence_octet *retval)
++{
++ CORBA_long *vptr;
++
++ g_return_if_fail(poa && (obj || oid));
++ g_return_if_fail(retval);
++
++ if(oid)
++ g_assert(!oid->_buffer[oid->_length - 1]);
++
++ if(obj)
++ retval->_length = POA_KEY_LEN + OBJ_KEY_LEN;
++ else
++ retval->_length = POA_KEY_LEN + sizeof(CORBA_long) + oid->_length;
++ retval->_buffer = CORBA_octet_allocbuf(retval->_length);
++ CORBA_sequence_set_release(retval, CORBA_TRUE);
++
++ vptr = (CORBA_long *)retval->_buffer;
++ *vptr = poa->poaID;
++ memcpy(retval->_buffer + sizeof(CORBA_unsigned_long), poa->rand_data, ORBIT_RAND_KEY_LEN);
++
++ vptr = (CORBA_long *)(retval->_buffer + POA_KEY_LEN);
++ if(obj) {
++ *vptr = obj->objnum;
++ memcpy(retval->_buffer + POA_KEY_LEN + sizeof(CORBA_unsigned_long), obj->rand_data, ORBIT_RAND_KEY_LEN);
++ } else {
++ *vptr = -((CORBA_long)oid->_length);
++ memcpy(retval->_buffer + POA_KEY_LEN + sizeof(CORBA_unsigned_long), oid->_buffer, oid->_length);
++ }
++}
++
++ORBit_POAObject *
++ORBit_POA_find_oid_for_object_key(PortableServer_POA poa,
++ CORBA_sequence_octet *object_key,
++ PortableServer_ObjectId **oid)
++{
++ CORBA_long onum;
++ guchar *nptr;
++ ORBit_POAObject *objinfo;
++
++ *oid = NULL;
++ nptr = object_key->_buffer + POA_KEY_LEN;
++
++ if(object_key->_length < (POA_KEY_LEN + sizeof(CORBA_long))) {
++ return NULL;
++ }
++
++ onum = *((CORBA_long *)nptr);
++
++ if(onum < 0) {
++ /* onum will be the -strlen(ObjectId) */
++ if(object_key->_length < (POA_KEY_LEN + sizeof(CORBA_long) - onum))
++ return NULL;
++
++ *oid = (PortableServer_ObjectId *)CORBA_sequence_octet__alloc();
++ (*oid)->_length = -onum;
++ (*oid)->_buffer = CORBA_octet_allocbuf((*oid)->_length);
++ memcpy((*oid)->_buffer, object_key->_buffer + POA_KEY_LEN + sizeof(CORBA_long), (*oid)->_length);
++
++ return NULL;
++ }
++
++ if(onum >= poa->objnum_to_obj->len)
++ return NULL;
++
++ objinfo = g_ptr_array_index(poa->objnum_to_obj, onum);
++
++ if(GPOINTER_TO_UINT(objinfo) <= poa->objnum_to_obj->len)
++ return NULL;
++
++ if(object_key->_length < (POA_KEY_LEN + OBJ_KEY_LEN))
++ return NULL;
++
++ if(memcmp(object_key->_buffer + POA_KEY_LEN + sizeof(CORBA_long), objinfo->rand_data, ORBIT_RAND_KEY_LEN))
++ return NULL;
++
++ return objinfo;
++}
++
++DEFINE_LOCK(id_assignment_counter);
++static int id_assignment_counter = 0;
++
++PortableServer_ObjectId *
++ORBit_POA_allocate_oid(PortableServer_POA poa,
++ const char *basis)
++{
++ PortableServer_ObjectId *new_objid;
++ char buf[512];
++ int len;
++
++ new_objid = (PortableServer_ObjectId *)CORBA_sequence_octet__alloc();
++
++ GET_LOCK(id_assignment_counter);
++ g_snprintf(buf, sizeof(buf), "%s%d", basis?basis:"Object",
++ id_assignment_counter);
++ id_assignment_counter++;
++ RELEASE_LOCK(id_assignment_counter);
++
++ len = strlen(buf)+1;
++ new_objid->_buffer = CORBA_octet_allocbuf(len);
++ new_objid->_length = len;
++ new_objid->_maximum = len;
++ new_objid->_release = CORBA_TRUE;
++
++ strcpy((CORBA_char *)new_objid->_buffer, buf);
++
++ return new_objid;
++}
++
++static PortableServer_Servant
++ORBit_POA_ServantManager_use_servant(PortableServer_POA poa,
++ GIOPRecvBuffer *recv_buffer,
++ PortableServer_ServantLocator_Cookie *the_cookie,
++ PortableServer_ObjectId *oid,
++ ORBit_POAObject *fake_obj_impl,
++ CORBA_Environment *ev)
++{
++ if(poa->servant_retention == PortableServer_RETAIN) {
++ POA_PortableServer_ServantActivator *sm;
++ POA_PortableServer_ServantActivator__epv *epv;
++
++ sm = (POA_PortableServer_ServantActivator *)poa->servant_manager;
++ epv = sm->vepv->PortableServer_ServantActivator_epv;
++ return epv->incarnate(sm, oid, poa, ev);
++ } else {
++ POA_PortableServer_ServantLocator *sm;
++ POA_PortableServer_ServantLocator__epv *epv;
++ PortableServer_ServantBase *retval;
++
++ sm = (POA_PortableServer_ServantLocator *)poa->servant_manager;
++ epv = sm->vepv->PortableServer_ServantLocator_epv;
++ retval = epv->preinvoke(sm, oid,
++ poa, recv_buffer->message.u.request.operation,
++ the_cookie,
++ ev);
++
++ ((ORBit_ObjectKey *)retval->_private)->object = fake_obj_impl;
++ fake_obj_impl->object_id = oid;
++ fake_obj_impl->poa = poa;
++ fake_obj_impl->orb = poa->orb;
++ fake_obj_impl->objnum = -1;
++#ifdef NOT_BACKWARDS_COMPAT_0_4
++ fake_obj_impl->use_count = NULL;
++ fake_obj_impl->death_callback = NULL;
++#endif
++
++ return retval;
++ }
++}
++
++static void
++ORBit_POA_ServantManager_unuse_servant(PortableServer_Servant servant,
++ PortableServer_POA poa,
++ GIOPRecvBuffer *recv_buffer,
++ PortableServer_ServantLocator_Cookie cookie,
++ PortableServer_ObjectId *oid,
++ ORBit_POAObject *fake_obj_impl,
++ CORBA_Environment *ev)
++{
++ POA_PortableServer_ServantLocator *sm;
++ POA_PortableServer_ServantLocator__epv *epv;
++
++ if(poa->servant_retention != PortableServer_NON_RETAIN)
++ return;
++
++ sm = (POA_PortableServer_ServantLocator *)poa->servant_manager;
++ epv = sm->vepv->PortableServer_ServantLocator_epv;
++
++ ((ORBit_ObjectKey *)((PortableServer_ServantBase *)servant)->_private)->object = NULL;
++ epv->postinvoke(sm, oid,
++ poa, recv_buffer->message.u.request.operation,
++ cookie, servant, ev);
++
++}
++
++typedef struct {
++ PortableServer_POA poa;
++ CORBA_Environment *ev;
++} EtherealizeInfo;
++
++void
++ORBit_POA_etherealize_object(PortableServer_ObjectId *oid,
++ ORBit_POAObject *obj_impl,
++ EtherealizeInfo *ei)
++{
++ POA_PortableServer_ServantActivator__epv *epv;
++ POA_PortableServer_ServantActivator *sm;
++
++ g_assert(ei->poa->servant_manager);
++
++ g_hash_table_remove(ei->poa->active_object_map,
++ obj_impl->object_id);
++
++ sm = (POA_PortableServer_ServantActivator *)ei->poa->servant_manager;
++ epv = sm->vepv->PortableServer_ServantActivator_epv;
++ epv->etherealize(sm, obj_impl->object_id, ei->poa,
++ obj_impl->servant,
++ CORBA_TRUE, CORBA_FALSE, ei->ev);
++}
++
++void
++ORBit_POA_etherealize_objects(PortableServer_POA poa,
++ CORBA_Environment *ev)
++{
++ EtherealizeInfo ei;
++
++ ei.poa = poa;
++ ei.ev = ev;
++
++ if(poa->servant_retention == PortableServer_RETAIN
++ && poa->request_processing == PortableServer_USE_SERVANT_MANAGER) {
++
++ g_hash_table_foreach(poa->active_object_map,
++ (GHFunc)ORBit_POA_etherealize_object,
++ &ei);
++ }
++}
++
++#ifdef NOT_BACKWARDS_COMPAT_0_4
++void ORBit_servant_set_deathwatch(PortableServer_ServantBase *servant,
++ int *use_count,
++ GFunc death_func,
++ gpointer user_data)
++{
++ ORBit_POAObject *pobj;
++
++ pobj = ORBIT_OBJECT_KEY(servant->_private)->object;
++
++ pobj->use_count = use_count;
++ pobj->death_callback = death_func;
++ pobj->user_data = user_data;
++}
++#endif
+diff -urN linux-2.4.1/net/korbit/orb/orbit_poa.h linux-2.4.1-korbit/net/korbit/orb/orbit_poa.h
+--- linux-2.4.1/net/korbit/orb/orbit_poa.h Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/orb/orbit_poa.h Thu Feb 1 16:20:50 2001
+@@ -0,0 +1,89 @@
++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
++
++/*
++ * ORBit: A CORBA v2.2 ORB
++ *
++ * Copyright (C) 1998 Richard H. Porter and Red Hat Software
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Library General Public
++ * License as published by the Free Software Foundation; either
++ * version 2 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Library General Public License for more details.
++ *
++ * You should have received a copy of the GNU Library General Public
++ * License along with this library; if not, write to the Free
++ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Author: Phil Dawes <philipd@parallax.co.uk>
++ *
++ */
++
++/*
++ * ORBit specific POA funcitons.
++ *
++ */
++
++#ifndef _ORBIT_ORBIT_POA_H_
++#define _ORBIT_ORBIT_POA_H_
++
++#include "orbit_types.h"
++#include "orbit_poa_type.h"
++
++/*
++ * Creates a new POAManager
++ */
++
++extern PortableServer_POAManager ORBit_POAManager_new(CORBA_Environment *ev);
++
++extern void ORBit_POAManager_free(PortableServer_POAManager poa_mgr,
++ CORBA_Environment *ev);
++
++extern PortableServer_POA ORBit_POA_new(CORBA_ORB orb,
++ CORBA_char *adapter_name,
++ PortableServer_POAManager the_POAManager,
++ CORBA_PolicyList *policies,
++ CORBA_Environment *ev);
++
++extern void ORBit_POA_free(PortableServer_POA poa, CORBA_Environment *ev);
++
++extern void ORBit_POA_add_child(PortableServer_POA poa,
++ PortableServer_POA child_poa,
++ CORBA_Environment *ev);
++void ORBit_POA_remove_child(PortableServer_POA poa,
++ PortableServer_POA child_poa,
++ CORBA_Environment *ev);
++
++gboolean ORBit_POA_handle_request(GIOPRecvBuffer *recv_buffer,
++ PortableServer_POA poa);
++PortableServer_POA
++ORBit_POA_find_POA_for_object_key(PortableServer_POA root_poa,
++ CORBA_sequence_octet *key);
++void
++ORBit_POA_find_object_key_for_oid(PortableServer_POA poa,
++ ORBit_POAObject *obj,
++ PortableServer_ObjectId *oid,
++ CORBA_sequence_octet *retval);
++ORBit_POAObject *
++ORBit_POA_find_oid_for_object_key(PortableServer_POA poa,
++ CORBA_sequence_octet *object_key,
++ PortableServer_ObjectId **oid);
++
++PortableServer_ObjectId *ORBit_POA_allocate_oid(PortableServer_POA poa,
++ const char *basis);
++
++void ORBit_POA_etherealize_objects(PortableServer_POA poa, CORBA_Environment *ev);
++
++#ifdef NOT_BACKWARDS_COMPAT_0_4
++/* Bad hack for shared libraries */
++void ORBit_servant_set_deathwatch(PortableServer_ServantBase *servant,
++ int *use_count,
++ GFunc death_func,
++ gpointer user_data);
++#endif
++
++#endif /* !_ORBIT_ORBIT_POA_H_ */
+diff -urN linux-2.4.1/net/korbit/orb/orbit_poa_type.h linux-2.4.1-korbit/net/korbit/orb/orbit_poa_type.h
+--- linux-2.4.1/net/korbit/orb/orbit_poa_type.h Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/orb/orbit_poa_type.h Thu Feb 1 11:47:13 2001
+@@ -0,0 +1,112 @@
++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
++
++/*
++ * ORBit: A CORBA v2.2 ORB
++ *
++ * Copyright (C) 1998 Richard H. Porter and Red Hat Software
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Library General Public
++ * License as published by the Free Software Foundation; either
++ * version 2 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Library General Public License for more details.
++ *
++ * You should have received a copy of the GNU Library General Public
++ * License along with this library; if not, write to the Free
++ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Author: Phil Dawes <philipd@parallax.co.uk>
++ *
++ */
++
++/*
++ * ORBit specific POA funcitons.
++ *
++ */
++
++#ifndef _ORBIT_ORBIT_POA_TYPE_H_
++#define _ORBIT_ORBIT_POA_TYPE_H_
++
++typedef void (*ORBitSkeleton)(PortableServer_ServantBase *_ORBIT_servant,
++ gpointer _ORBIT_recv_buffer,
++ CORBA_Environment *ev,
++ gpointer implementation);
++typedef ORBitSkeleton (*ORBit_impl_finder)(PortableServer_ServantBase *servant,
++ gpointer _ORBIT_recv_buffer,
++ gpointer *implementation);
++typedef void (*ORBit_local_objref_init)(CORBA_Object obj,
++ PortableServer_ServantBase *servant);
++typedef struct {
++ ORBit_impl_finder relay_call;
++ const gchar *class_name;
++ ORBit_local_objref_init init_local_objref;
++} PortableServer_ClassInfo;
++
++#define ORBIT_RAND_KEY_LEN 8
++
++typedef struct {
++ PortableServer_ObjectId *object_id;
++ PortableServer_Servant servant;
++ PortableServer_POA poa;
++ CORBA_ORB orb;
++ CORBA_unsigned_long objnum;
++
++ /* Stuff for doing shared libraries nicely */
++ guchar rand_data[ORBIT_RAND_KEY_LEN];
++
++#ifdef NOT_BACKWARDS_COMPAT_0_4
++ int *use_count;
++ GFunc death_callback;
++ gpointer user_data;
++#endif
++} ORBit_POAObject;
++
++typedef struct {
++ PortableServer_ClassInfo *class_info;
++ ORBit_POAObject *object;
++} ORBit_ObjectKey;
++
++#define ORBIT_OBJECT_KEY(x) ((ORBit_ObjectKey *)(x))
++
++struct PortableServer_POA_type {
++ struct ORBit_PseudoObject_struct parent;
++
++ PortableServer_POA parent_poa;
++ CORBA_ORB orb;
++ CORBA_unsigned_long poaID;
++
++ GHashTable *active_object_map;
++ GPtrArray *objnum_to_obj; /* maps objnums to ORBit_POAObject's */
++ CORBA_long first_free_id;
++
++ /* Requests received while in a HOLDING state */
++ GSList *held_requests;
++
++ /* this'll be a hash table when I can be arsed to look up
++ how to implement efficient hash tables - Phil.*/
++ GSList *child_POAs;
++
++ CORBA_char *the_name;
++ PortableServer_POAManager the_POAManager;
++
++ PortableServer_AdapterActivator the_activator;
++
++ PortableServer_ServantManager servant_manager;
++ PortableServer_Servant default_servant;
++
++ PortableServer_ThreadPolicyValue thread;
++ PortableServer_LifespanPolicyValue lifespan;
++ PortableServer_IdUniquenessPolicyValue id_uniqueness;
++ PortableServer_IdAssignmentPolicyValue id_assignment;
++ PortableServer_ImplicitActivationPolicyValue implicit_activation;
++ PortableServer_ServantRetentionPolicyValue servant_retention;
++ PortableServer_RequestProcessingPolicyValue request_processing;
++
++ guchar rand_data[ORBIT_RAND_KEY_LEN];
++};
++
++#endif /* !_ORBIT_ORBIT_POA_TYPE_H_ */
+diff -urN linux-2.4.1/net/korbit/orb/orbit_typecode.c linux-2.4.1-korbit/net/korbit/orb/orbit_typecode.c
+--- linux-2.4.1/net/korbit/orb/orbit_typecode.c Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/orb/orbit_typecode.c Thu Feb 1 11:47:14 2001
+@@ -0,0 +1,593 @@
++#include "orbit.h"
++#include "orbit_typecode.h"
++#include "cdr.h"
++#include "corba_typecode_type.h"
++#include <IIOP/giop-msg-buffer.h>
++#include "../IIOP/iiop-endianP.h"
++
++#if 0
++#define CORBA_Object_release(x, y) ({ g_message(__FILE__ ":%d Releasing object %#x from %d", __LINE__, \
++x, ORBIT_ROOT_OBJECT(x)->refs); CORBA_Object_release(x, y); })
++#define CORBA_Object_duplicate(x, y) ({ g_message(__FILE__ ":%d Duping object %#x from %d", __LINE__, \
++x, ORBIT_ROOT_OBJECT(x)->refs); CORBA_Object_duplicate(x, y); })
++#endif
++
++typedef struct{
++ CORBA_TypeCode tc;
++ guint index;
++}TCRecursionNode;
++
++typedef struct{
++ GSList* prior_tcs; /* Could be a hash table by typecode */
++ guint current_idx; /* The "top-level" index of the start of the current codec */
++}TCEncodeContext;
++
++typedef struct{
++ GSList* prior_tcs; /* Could be a hash table by offset */
++ guint current_idx;
++}TCDecodeContext;
++
++
++
++static void tc_enc(CORBA_TypeCode t, CDR_Codec* c, TCEncodeContext* ctx);
++static void tc_dec(CORBA_TypeCode* t, CDR_Codec* c, TCDecodeContext* ctx);
++static void tc_enc_tk_objref(CORBA_TypeCode t, CDR_Codec* c, TCEncodeContext* ctx);
++static void tc_dec_tk_objref(CORBA_TypeCode t, CDR_Codec* c, TCDecodeContext* ctx);
++static void tc_enc_tk_sequence(CORBA_TypeCode t, CDR_Codec* c, TCEncodeContext* ctx);
++static void tc_dec_tk_sequence(CORBA_TypeCode t, CDR_Codec* c, TCDecodeContext* ctx);
++static void tc_enc_tk_string(CORBA_TypeCode t, CDR_Codec* c, TCEncodeContext* ctx);
++static void tc_dec_tk_string(CORBA_TypeCode t, CDR_Codec* c, TCDecodeContext* ctx);
++static void tc_enc_tk_struct(CORBA_TypeCode t, CDR_Codec* c, TCEncodeContext* ctx);
++static void tc_dec_tk_struct(CORBA_TypeCode t, CDR_Codec* c, TCDecodeContext* ctx);
++static void tc_enc_tk_union(CORBA_TypeCode t, CDR_Codec* c, TCEncodeContext* ctx);
++static void tc_dec_tk_union(CORBA_TypeCode t, CDR_Codec* c, TCDecodeContext* ctx);
++static void tc_enc_tk_enum(CORBA_TypeCode t, CDR_Codec* c, TCEncodeContext* ctx);
++static void tc_dec_tk_enum(CORBA_TypeCode t, CDR_Codec* c, TCDecodeContext* ctx);
++static void tc_enc_tk_alias(CORBA_TypeCode t, CDR_Codec* c, TCEncodeContext* ctx);
++static void tc_dec_tk_alias(CORBA_TypeCode t, CDR_Codec* c, TCDecodeContext* ctx);
++static void tc_enc_tk_except(CORBA_TypeCode t, CDR_Codec* c, TCEncodeContext* ctx);
++static void tc_dec_tk_except(CORBA_TypeCode t, CDR_Codec* c, TCDecodeContext* ctx);
++static void tc_enc_tk_array(CORBA_TypeCode t, CDR_Codec* c, TCEncodeContext* ctx);
++static void tc_dec_tk_array(CORBA_TypeCode t, CDR_Codec* c, TCDecodeContext* ctx);
++static void tc_enc_tk_fixed(CORBA_TypeCode t, CDR_Codec* c, TCEncodeContext* ctx);
++static void tc_dec_tk_fixed(CORBA_TypeCode t, CDR_Codec* c, TCDecodeContext* ctx);
++static void tc_enc_tk_wstring(CORBA_TypeCode t, CDR_Codec* c, TCEncodeContext* ctx);
++static void tc_dec_tk_wstring(CORBA_TypeCode t, CDR_Codec* c, TCDecodeContext* ctx);
++
++
++
++typedef void
++(*CORBA_TypeCodeEncoder)(CORBA_TypeCode t,
++ CDR_Codec* c,
++ TCEncodeContext* ctx);
++
++typedef void
++(*CORBA_TypeCodeDecoder)(CORBA_TypeCode t,
++ CDR_Codec* c,
++ TCDecodeContext* ctx);
++
++
++typedef enum{
++ TK_EMPTY,
++ TK_SIMPLE,
++ TK_COMPLEX
++} TkType;
++
++typedef struct{
++ TkType type;
++ CORBA_TypeCodeEncoder encoder;
++ CORBA_TypeCodeDecoder decoder;
++} TkInfo;
++
++static const TkInfo tk_info[CORBA_tk_last]={
++ {TK_EMPTY, NULL, NULL}, /* tk_null */
++ {TK_EMPTY, NULL, NULL}, /* tk_void */
++ {TK_EMPTY, NULL, NULL}, /* tk_short */
++ {TK_EMPTY, NULL, NULL}, /* tk_long */
++ {TK_EMPTY, NULL, NULL}, /* tk_ushort */
++ {TK_EMPTY, NULL, NULL}, /* tk_ulong */
++ {TK_EMPTY, NULL, NULL}, /* tk_float */
++ {TK_EMPTY, NULL, NULL}, /* tk_double */
++ {TK_EMPTY, NULL, NULL}, /* tk_boolean */
++ {TK_EMPTY, NULL, NULL}, /* tk_char */
++ {TK_EMPTY, NULL, NULL}, /* tk_octet */
++ {TK_EMPTY, NULL, NULL}, /* tk_any */
++ {TK_EMPTY, NULL, NULL}, /* tk_TypeCode */
++ {TK_EMPTY, NULL, NULL}, /* tk_Principal */
++ {TK_COMPLEX, tc_enc_tk_objref, tc_dec_tk_objref}, /* tk_objref */
++ {TK_COMPLEX, tc_enc_tk_struct, tc_dec_tk_struct}, /* tk_struct */
++ {TK_COMPLEX, tc_enc_tk_union, tc_dec_tk_union}, /* tk_union */
++ {TK_COMPLEX, tc_enc_tk_enum, tc_dec_tk_enum}, /* tk_enum */
++ {TK_SIMPLE, tc_enc_tk_string, tc_dec_tk_string}, /* tk_string */
++ {TK_COMPLEX, tc_enc_tk_sequence, tc_dec_tk_sequence}, /* tk_sequence */
++ {TK_COMPLEX, tc_enc_tk_array, tc_dec_tk_array}, /* tk_array */
++ {TK_COMPLEX, tc_enc_tk_alias, tc_dec_tk_alias}, /* tk_alias */
++ {TK_COMPLEX, tc_enc_tk_except, tc_dec_tk_except}, /* tk_except */
++ {TK_EMPTY, NULL, NULL}, /* tk_longlong */
++ {TK_EMPTY, NULL, NULL}, /* tk_ulonglong */
++ {TK_EMPTY, NULL, NULL}, /* tk_longdouble */
++ {TK_EMPTY, NULL, NULL}, /* tk_wchar */
++ {TK_SIMPLE, tc_enc_tk_wstring, tc_dec_tk_wstring}, /* tk_wstring */
++ {TK_SIMPLE, tc_enc_tk_fixed, tc_dec_tk_fixed} /* tk_fixed */
++};
++
++void ORBit_encode_CORBA_TypeCode(CORBA_TypeCode t, GIOPSendBuffer* buf)
++{
++ CDR_Codec codec_d;
++ CDR_Codec* codec = &codec_d;
++ TCEncodeContext ctx;
++ GSList* l;
++ CORBA_octet codecbuf[2048];
++
++ CDR_codec_init_static(codec);
++
++ codec->wptr = 0;
++ codec->buffer = codecbuf;
++ codec->release_buffer = FALSE;
++ codec->buf_len = 2048;
++ codec->data_endian=FLAG_ENDIANNESS;
++
++ ctx.current_idx=0;
++ ctx.prior_tcs=NULL;
++ tc_enc(t, codec, &ctx);
++ for(l=ctx.prior_tcs;l;l=l->next)
++ g_free(l->data);
++ g_slist_free(ctx.prior_tcs);
++ giop_send_buffer_append_mem_indirect(buf,
++ codec->buffer,
++ codec->wptr);
++}
++
++void ORBit_decode_CORBA_TypeCode(CORBA_TypeCode* t, GIOPRecvBuffer* buf)
++{
++ CDR_Codec codec_d;
++ CDR_Codec* codec = &codec_d;
++ TCDecodeContext ctx;
++ GSList* l;
++
++ CDR_codec_init_static(codec);
++ codec->buffer=buf->cur;
++ codec->release_buffer=CORBA_FALSE;
++ codec->readonly=CORBA_TRUE;
++ codec->buf_len = /* hope this is correct */
++ ((guchar *)buf->message_body) +
++ GIOP_MESSAGE_BUFFER(buf)->message_header.message_size
++ - ((guchar *)buf->cur);
++
++ codec->data_endian=GIOP_MESSAGE_BUFFER(buf)->message_header.flags & 1;
++
++ ctx.current_idx=0;
++ ctx.prior_tcs=NULL;
++ tc_dec(t, codec, &ctx);
++ for(l=ctx.prior_tcs;l;l=l->next)
++ g_free(l->data);
++ g_slist_free(ctx.prior_tcs);
++ buf->cur = ((guchar *)buf->cur) + codec->rptr;
++}
++
++
++/* Encode a typecode to a codec, possibly recursively */
++
++static void tc_enc(CORBA_TypeCode tc,
++ CDR_Codec* codec,
++ TCEncodeContext* ctx)
++{
++ TCRecursionNode* node;
++ const TkInfo* info;
++ GSList* l;
++ CORBA_octet codecbuf[2048];
++ CDR_Codec encaps_d;
++ CDR_Codec* encaps = &encaps_d;
++
++ g_assert(CLAMP(0, tc->kind, CORBA_tk_last) == tc->kind);
++
++ for(l=ctx->prior_tcs;l;l=l->next){
++ TCRecursionNode* node=l->data;
++ /* CORBA_CORBA_TypeCode_equal might save space, but is slow.. */
++ if(node->tc==tc){
++ CDR_put_ulong(codec, CORBA_tk_recursive);
++ CDR_put_long(codec,
++ node->index
++ -ctx->current_idx
++ -codec->wptr);
++ return;
++ }
++ }
++
++ /* All right, this isn't a previously met type. So record it. */
++ /* NOTE: put kind before recording index so alignment is dealt with! */
++ CDR_put_ulong(codec, tc->kind);
++
++ node=g_new(TCRecursionNode, 1);
++ node->tc=tc;
++ node->index=ctx->current_idx+codec->wptr - 4; /* -4 for kind */
++ ctx->prior_tcs=g_slist_prepend(ctx->prior_tcs, node);
++
++ info=&tk_info[tc->kind];
++ switch(info->type){
++ guint tmp_index;
++ case TK_EMPTY:
++ break;
++ case TK_COMPLEX:
++ tmp_index=ctx->current_idx;
++ ctx->current_idx+=codec->wptr+4; /* +4 for the length */
++ CDR_codec_init_static(encaps);
++ encaps->wptr = 0;
++ encaps->buffer = codecbuf;
++ encaps->release_buffer = FALSE;
++ encaps->buf_len = 2048;
++ encaps->data_endian=FLAG_ENDIANNESS;
++ CDR_put_octet(encaps, FLAG_ENDIANNESS);
++ (info->encoder)(tc, encaps, ctx);
++ CDR_put_ulong(codec, encaps->wptr);
++ /* Now this is a time hog */
++ CDR_put_octets(codec, encaps->buffer, encaps->wptr);
++ ctx->current_idx=tmp_index;
++ break;
++ case TK_SIMPLE:
++ (info->encoder)(tc, codec, ctx);
++ }
++}
++
++static void
++ORBit_TypeCode_release(gpointer obj, CORBA_Environment *ev)
++{
++ /* we will initialize the TC_ constants with a negative refcount */
++ if(ORBIT_ROOT_OBJECT(obj)->refs >= 0) {
++ ORBIT_ROOT_OBJECT_UNREF(obj);
++
++ if(ORBIT_ROOT_OBJECT(obj)->refs <= 0) {
++ CORBA_TypeCode tc = obj;
++ int i;
++
++ g_free(tc->name);
++ g_free(tc->repo_id);
++
++ for(i = 0; i < tc->sub_parts; i++) {
++ if(tc->subnames)
++ g_free(tc->subnames[i]);
++
++ if(tc->subtypes)
++ CORBA_Object_release((CORBA_Object)tc->subtypes[i], ev);
++
++ if(tc->sublabels)
++ CORBA_any__free(&tc->sublabels[i], NULL, TRUE);
++ }
++
++ g_free(tc->subnames);
++ g_free(tc->subtypes);
++ g_free(tc->sublabels);
++
++ if(tc->discriminator)
++ CORBA_Object_release((CORBA_Object)tc->discriminator, ev);
++
++ g_free(obj);
++ }
++
++ }
++}
++
++const ORBit_RootObject_Interface ORBit_TypeCode_epv = {
++ &ORBit_TypeCode_release
++};
++
++static void tc_dec(CORBA_TypeCode* t, CDR_Codec* c, TCDecodeContext* ctx)
++{
++ CORBA_TCKind kind;
++ CORBA_TypeCode tc;
++ const TkInfo* info;
++ TCRecursionNode* node;
++ CDR_Codec encaps_d;
++ CDR_Codec* encaps = &encaps_d;
++
++ CDR_get_ulong(c, &kind);
++
++ g_assert(CLAMP(0, kind, CORBA_tk_last) == kind);
++
++ if(kind==CORBA_tk_recursive){
++ CORBA_long offset;
++ GSList* l;
++ CDR_get_ulong(c, &offset);
++ for(l=ctx->prior_tcs;l;l=l->next){
++ node=l->data;
++ /* NOTE: below, -4 is b/c we already read offset */
++ if(node->index==ctx->current_idx+c->rptr+offset-4){
++ *t=node->tc;
++ return;
++ }
++ }
++ ORBit_Trace(TraceMod_ORB, TraceLevel_Error,
++ "tc_dec: Invalid CORBA_TypeCode recursion offset "
++ "in input buffer\n");
++ g_assert_not_reached();
++ }
++
++ ORBit_Trace(TraceMod_TC, TraceLevel_Debug, "codec->host_endian: %d, codec->data_endian: %d\n", c->host_endian, c->data_endian);
++ ORBit_Trace(TraceMod_TC, TraceLevel_Debug, "kind: %d, CORBA_tk_last: %d\n", kind, CORBA_tk_last);
++ g_assert(kind<CORBA_tk_last);
++
++ node=g_new(TCRecursionNode, 1);
++ node->index=ctx->current_idx+c->rptr-4; /* -4 for the TCKind */
++ info=&tk_info[kind];
++
++ tc=g_new0(struct CORBA_TypeCode_struct, 1);
++
++ /* Passing in NULL for CORBA_Environment is patently dangerous. */
++ ORBit_pseudo_object_init((ORBit_PseudoObject)tc,
++ ORBIT_PSEUDO_TYPECODE, NULL);
++ ORBit_RootObject_set_interface((ORBit_RootObject)tc,
++ (ORBit_RootObject_Interface *)&ORBit_TypeCode_epv,
++ NULL);
++
++ tc->kind=kind;
++ switch(info->type){
++ guint tmp_index;
++ CORBA_octet o;
++
++ case TK_EMPTY:
++ break;
++
++ case TK_COMPLEX:
++ tmp_index=ctx->current_idx;
++ CDR_codec_init_static(encaps);
++ CDR_get_ulong(c, &encaps->buf_len);
++ ctx->current_idx+=c->rptr;
++ encaps->buffer=&c->buffer[c->rptr];
++ encaps->release_buffer=CORBA_FALSE;
++ CDR_get_octet(encaps, &o);
++ encaps->data_endian=o;
++ (info->decoder)(tc, encaps, ctx);
++ c->rptr += encaps->buf_len;
++ ctx->current_idx=tmp_index;
++ break;
++ case TK_SIMPLE:
++ (info->decoder)(tc, c, ctx);
++ break;
++ }
++ node->tc=tc;
++ ctx->prior_tcs=g_slist_prepend(ctx->prior_tcs, node);
++ *t=tc;
++}
++
++
++
++static void tc_enc_tk_objref(CORBA_TypeCode t, CDR_Codec* c, TCEncodeContext* ctx)
++{
++ CDR_put_string(c, t->repo_id);
++ CDR_put_string(c, t->name);
++}
++
++static void tc_dec_tk_objref(CORBA_TypeCode t, CDR_Codec* c, TCDecodeContext* ctx)
++{
++ CDR_get_string(c, &t->repo_id);
++ CDR_get_string(c, &t->name);
++}
++
++static void tc_enc_tk_sequence(CORBA_TypeCode t, CDR_Codec* c, TCEncodeContext* ctx)
++{
++ tc_enc(*t->subtypes, c, ctx);
++ CDR_put_ulong(c, t->length);
++}
++
++static void tc_dec_tk_sequence(CORBA_TypeCode t, CDR_Codec* c, TCDecodeContext* ctx)
++{
++ t->subtypes=g_new(CORBA_TypeCode, 1);
++ tc_dec(&t->subtypes[0], c, ctx);
++ CORBA_Object_duplicate((CORBA_Object)t->subtypes[0], NULL);
++ CDR_get_ulong(c, &t->length);
++}
++
++static void tc_enc_tk_string(CORBA_TypeCode t, CDR_Codec* c, TCEncodeContext* ctx)
++{
++ CDR_put_ulong(c, t->length);
++}
++
++static void tc_dec_tk_string(CORBA_TypeCode t, CDR_Codec* c, TCDecodeContext* ctx)
++{
++ CDR_get_ulong(c, &t->length);
++}
++
++static void tc_enc_tk_struct(CORBA_TypeCode t, CDR_Codec* c, TCEncodeContext* ctx)
++{
++ CORBA_unsigned_long i;
++ CDR_put_string(c, t->repo_id);
++ CDR_put_string(c, t->name);
++ CDR_put_ulong(c, t->sub_parts);
++ for(i=0;i<t->sub_parts;i++){
++ CDR_put_string(c, t->subnames[i]);
++ tc_enc(t->subtypes[i], c, ctx);
++ }
++}
++
++static void tc_dec_tk_struct(CORBA_TypeCode t, CDR_Codec* c, TCDecodeContext* ctx)
++{
++ CORBA_unsigned_long i;
++ CDR_get_string(c, &t->repo_id);
++ CDR_get_string(c, &t->name);
++ CDR_get_ulong(c, &t->sub_parts);
++ t->subnames=g_new(gchar*, t->sub_parts);
++ t->subtypes=g_new(CORBA_TypeCode, t->sub_parts);
++ for(i=0;i<t->sub_parts;i++){
++ CDR_get_string(c, &t->subnames[i]);
++ tc_dec(&t->subtypes[i], c, ctx);
++ CORBA_Object_duplicate((CORBA_Object)t->subtypes[i], NULL);
++ }
++}
++
++#define UNION_MEMBERS(dir) \
++ MEMBER_LOOPER_##dir(ulong, long, long); \
++ case CORBA_tk_enum: /* fall through */ \
++ MEMBER_LOOPER_##dir(ulong, unsigned_long, ulong); \
++ MEMBER_LOOPER_##dir(octet, boolean, boolean); \
++ MEMBER_LOOPER_##dir(octet, char, char); \
++ MEMBER_LOOPER_##dir(ushort, short, short); \
++ MEMBER_LOOPER_##dir(ushort, unsigned_short, ushort); \
++ MEMBER_LOOPER_##dir(ulong_long, long_long, longlong); \
++ MEMBER_LOOPER_##dir(ulong_long, unsigned_long_long, ulonglong); \
++ /* MEMBER_LOOPER_##dir(wchar, wchar, wchar); */
++
++
++static void tc_enc_tk_union(CORBA_TypeCode t, CDR_Codec* c, TCEncodeContext* ctx)
++{
++ CORBA_unsigned_long i;
++ CDR_put_string(c, t->repo_id);
++ CDR_put_string(c, t->name);
++ tc_enc(t->discriminator, c, ctx);
++ CDR_put_long(c, t->default_index);
++ CDR_put_ulong(c, t->sub_parts);
++ i=t->sub_parts;
++ /* Thank goodness the discriminator types are rather limited,
++ we can do the marshalling inline.. */
++#define MEMBER_LOOPER_ENC(putname, typename, tkname) \
++ case CORBA_tk_##tkname: \
++ for(i=0;i<t->sub_parts;i++){ \
++ CDR_put_##putname(c, *(CORBA_##typename*) \
++ (t->sublabels[i]._value)); \
++ CDR_put_string(c, t->subnames[i]); \
++ tc_enc(t->subtypes[i], c, ctx); \
++ } \
++ break
++
++ switch(t->discriminator->kind){
++ UNION_MEMBERS(ENC);
++ default:
++ ORBit_Trace(TraceMod_ORB, TraceLevel_Error,
++ "tc_enc_tk_union: Illegal union discriminator "
++ "type %s\n", t->discriminator->name);
++ }
++}
++
++static void tc_dec_tk_union(CORBA_TypeCode t, CDR_Codec* c, TCDecodeContext* ctx)
++{
++ CORBA_unsigned_long i;
++ CDR_get_string(c, &t->repo_id);
++ CDR_get_string(c, &t->name);
++ tc_dec(&t->discriminator, c, ctx);
++ CORBA_Object_duplicate((CORBA_Object)t->discriminator, NULL);
++ CDR_get_ulong(c, &t->default_index);
++ CDR_get_ulong(c, &t->sub_parts);
++
++ t->sublabels=g_new(CORBA_any, t->sub_parts);
++ t->subnames=g_new(gchar*, t->sub_parts);
++ t->subtypes=g_new(CORBA_TypeCode, t->sub_parts);
++
++#define MEMBER_LOOPER_DEC(getname, typename, tkname) \
++ case CORBA_tk_##tkname: \
++ for(i=0;i<t->sub_parts;i++){ \
++ t->sublabels[i]._type = \
++ CORBA_Object_duplicate((CORBA_Object)t->discriminator, NULL); \
++ t->sublabels[i]._value = g_new(CORBA_##typename,1); \
++ t->sublabels[i]._release = CORBA_TRUE; \
++ CDR_get_##getname(c, t->sublabels[i]._value); \
++ CDR_get_string(c, &t->subnames[i]); \
++ tc_dec(&t->subtypes[i], c, ctx); \
++ CORBA_Object_duplicate((CORBA_Object)t->subtypes[i], NULL); \
++ } \
++ break
++
++ switch(t->discriminator->kind){
++ UNION_MEMBERS(DEC);
++ default:
++ /* XXX: what is correct error handling */
++ g_assert(!"Not yet implemented.");
++ }
++}
++
++static void tc_enc_tk_enum(CORBA_TypeCode t, CDR_Codec* c, TCEncodeContext* ctx)
++{
++ CORBA_unsigned_long i;
++ CDR_put_string(c, t->repo_id);
++ CDR_put_string(c, t->name);
++ CDR_put_ulong(c, t->sub_parts);
++ for(i=0;i<t->sub_parts;i++)
++ CDR_put_string(c, t->subnames[i]);
++}
++
++static void tc_dec_tk_enum(CORBA_TypeCode t, CDR_Codec* c, TCDecodeContext* ctx)
++{
++ CORBA_unsigned_long i;
++ CDR_get_string(c, &t->repo_id);
++ CDR_get_string(c, &t->name);
++ CDR_get_ulong(c, &t->sub_parts);
++ t->subnames=g_new(gchar*, t->sub_parts);
++ for(i=0;i<t->sub_parts;i++)
++ CDR_get_string(c, &t->subnames[i]);
++}
++
++static void tc_enc_tk_alias(CORBA_TypeCode t, CDR_Codec* c, TCEncodeContext* ctx)
++{
++ CDR_put_string(c, t->repo_id);
++ CDR_put_string(c, t->name);
++ tc_enc(*t->subtypes, c, ctx);
++}
++
++static void tc_dec_tk_alias(CORBA_TypeCode t, CDR_Codec* c, TCDecodeContext* ctx)
++{
++ CDR_get_string(c, &t->repo_id);
++ CDR_get_string(c, &t->name);
++ t->subtypes=g_new(CORBA_TypeCode, 1);
++ tc_dec(t->subtypes, c, ctx);
++ CORBA_Object_duplicate((CORBA_Object)t->subtypes[0], NULL);
++}
++
++
++static void tc_enc_tk_except(CORBA_TypeCode t, CDR_Codec* c, TCEncodeContext* ctx)
++{
++ gulong i;
++ CDR_put_string(c, t->repo_id);
++ CDR_put_string(c, t->name);
++ CDR_put_ulong(c, t->sub_parts);
++ for(i=0;i<t->length;i++){
++ CDR_put_string(c, t->subnames[i]);
++ tc_enc(t->subtypes[i], c, ctx);
++ }
++}
++
++static void tc_dec_tk_except(CORBA_TypeCode t, CDR_Codec* c, TCDecodeContext* ctx)
++{
++ gulong i;
++ CDR_get_string(c, &t->repo_id);
++ CDR_get_string(c, &t->name);
++ CDR_get_ulong(c, &t->sub_parts);
++ t->subtypes=g_new(CORBA_TypeCode, t->sub_parts);
++ t->subnames=g_new(gchar*, t->sub_parts);
++ for(i=0;i<t->length;i++){
++ CDR_get_string(c, &t->subnames[i]);
++ tc_dec(&t->subtypes[i], c, ctx);
++ CORBA_Object_duplicate((CORBA_Object)t->subtypes[i], NULL);
++ }
++}
++
++static void tc_enc_tk_array(CORBA_TypeCode t, CDR_Codec* c, TCEncodeContext* ctx)
++{
++ tc_enc(*t->subtypes, c, ctx);
++ CDR_put_ulong(c, t->length);
++}
++
++static void tc_dec_tk_array(CORBA_TypeCode t, CDR_Codec* c, TCDecodeContext* ctx)
++{
++ t->subtypes=g_new(CORBA_TypeCode, 1);
++ tc_dec(t->subtypes, c, ctx);
++ CORBA_Object_duplicate((CORBA_Object)t->subtypes[0], NULL);
++ CDR_get_ulong(c, &t->length);
++}
++
++static void tc_enc_tk_wstring(CORBA_TypeCode t, CDR_Codec* c, TCEncodeContext* ctx)
++{
++ g_assert(!"Not yet implemented.");
++}
++
++static void tc_dec_tk_wstring(CORBA_TypeCode t, CDR_Codec* c, TCDecodeContext* ctx)
++{
++ g_assert(!"Not yet implemented.");
++}
++
++static void tc_enc_tk_fixed(CORBA_TypeCode t, CDR_Codec* c, TCEncodeContext* ctx)
++{
++ g_assert(!"Not yet implemented.");
++}
++
++static void tc_dec_tk_fixed(CORBA_TypeCode t, CDR_Codec* c, TCDecodeContext* ctx)
++{
++ g_assert(!"Not yet implemented.");
++}
+diff -urN linux-2.4.1/net/korbit/orb/orbit_typecode.h linux-2.4.1-korbit/net/korbit/orb/orbit_typecode.h
+--- linux-2.4.1/net/korbit/orb/orbit_typecode.h Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/orb/orbit_typecode.h Thu Feb 1 16:21:53 2001
+@@ -0,0 +1,10 @@
++#ifndef _ORBIT_ORBIT_TYPECODE_H_
++#define _ORBIT_ORBIT_TYPECODE_H_
++
++#include "orbit_types.h"
++
++extern const ORBit_RootObject_Interface ORBit_TypeCode_epv;
++void ORBit_encode_CORBA_TypeCode(CORBA_TypeCode tc, GIOPSendBuffer* buf);
++void ORBit_decode_CORBA_TypeCode(CORBA_TypeCode* tc, GIOPRecvBuffer* buf);
++
++#endif
+diff -urN linux-2.4.1/net/korbit/orb/orbit_types.h linux-2.4.1-korbit/net/korbit/orb/orbit_types.h
+--- linux-2.4.1/net/korbit/orb/orbit_types.h Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/orb/orbit_types.h Thu Feb 1 16:20:50 2001
+@@ -0,0 +1,176 @@
++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
++
++/*
++ * ORBit: A CORBA v2.2 ORB
++ *
++ * Copyright (C) 1998 Richard H. Porter and Red Hat Software
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Library General Public
++ * License as published by the Free Software Foundation; either
++ * version 2 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Library General Public License for more details.
++ *
++ * You should have received a copy of the GNU Library General Public
++ * License along with this library; if not, write to the Free
++ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Author: Dick Porter <dick@cymru.net>
++ *
++ */
++
++#ifndef _ORBIT_TYPES_H_
++#define _ORBIT_TYPES_H_
++
++#include <stddef.h> /* for wchar_t */
++#include <sys/types.h> /* for sysdep types */
++#include <netinet/in.h> /* for sockaddr_in */
++#include <sys/uio.h> /* for struct iovec */
++
++#include <ORBitutil/basic_types.h>
++
++#define CORBA_TRUE 1
++#define CORBA_FALSE 0
++
++typedef CORBA_char *CORBA_ORBid;
++
++typedef CORBA_unsigned_long CORBA_ServiceOption;
++typedef CORBA_unsigned_long CORBA_ServiceDetailType;
++
++#include "corba_orb.h"
++
++/*
++ * CORBA_RepositoryId and CORBA_Identifier are defined in the Interface
++ * Repository, but are needed in other interfaces in the ORB itself.
++ */
++#if !defined(_CORBA_Identifier_defined)
++#define _CORBA_Identifier_defined 1
++typedef CORBA_char *CORBA_Identifier;
++#define CORBA_Identifier__free CORBA_string__free
++#endif
++
++#if !defined(_CORBA_RepositoryId_defined)
++#define _CORBA_RepositoryId_defined 1
++typedef CORBA_char *CORBA_RepositoryId;
++#define CORBA_RepositoryId__free CORBA_string__free
++#endif
++
++#include "corba_any.h"
++
++typedef struct CORBA_ServiceDetail_type CORBA_ServiceDetail;
++typedef struct CORBA_Request_type *CORBA_Request;
++typedef struct CORBA_ServerRequest_type *CORBA_ServerRequest;
++typedef struct CORBA_DynFixed_type *CORBA_DynFixed;
++typedef struct CORBA_Current_type *CORBA_Current;
++typedef void CORBA_Status;
++typedef CORBA_unsigned_long CORBA_enum;
++typedef CORBA_unsigned_long CORBA_Flags;
++
++typedef struct CORBA_NVList_type {
++ CORBA_Flags flags;
++ GArray *list;
++} CORBA_NVList;
++
++#include "corba_context.h"
++
++#include "corba_portableserver.h"
++
++#include "corba_env.h"
++
++#include "corba_sequences_type.h"
++
++#include "corba_basic_sequences_type.h"
++
++#include "corba_object.h"
++
++#include "orbit_object_type.h"
++
++#include "corba_object_type.h"
++
++#include "corba_orb_type.h"
++
++#include "corba_typecode.h"
++#include "corba_typecode_type.h"
++#include "corba_any_type.h"
++#include "corba_any_proto.h"
++
++#if !defined(TC_IMPL_TC_CORBA_Identifier_0)
++#define TC_IMPL_TC_CORBA_Identifier_0 '/'
++#define TC_CORBA_Identifier ((CORBA_TypeCode)&TC_CORBA_Identifier_struct)
++extern const struct CORBA_TypeCode_struct TC_CORBA_Identifier_struct;
++#endif
++
++#if !defined(TC_IMPL_TC_CORBA_RepositoryId_0)
++#define TC_IMPL_TC_CORBA_RepositoryId_0 '/'
++extern const struct CORBA_TypeCode_struct TC_CORBA_RepositoryId_struct;
++#define TC_CORBA_RepositoryId ((CORBA_TypeCode)&TC_CORBA_RepositoryId_struct)
++#endif
++
++/* 19.14 */
++
++/* XXX */
++typedef struct CORBA_fixed_d_s {
++ CORBA_unsigned_short _digits;
++ CORBA_short _scale;
++ signed char _sign;
++ signed char _value[1];
++} CORBA_fixed_d_s;
++
++#include "corba_env_type.h"
++
++
++typedef struct CORBA_WrongTransaction {
++ int dummy;
++} CORBA_WrongTransaction;
++
++#define CORBA_ARG_IN (1<<0)
++#define CORBA_ARG_OUT (1<<1)
++#define CORBA_ARG_INOUT (1<<2)
++#define CORBA_CTX_RESTRICT_SCOPE (1<<3)
++#define CORBA_CTX_DELETE_DESCENDENTS (1<<4)
++#define CORBA_OUT_LIST_MEMORY (1<<5)
++#define CORBA_IN_COPY_VALUE (1<<6)
++#define CORBA_DEPENDENT_LIST (1<<7)
++#define CORBA_INV_NO_RESPONSE (1<<8)
++#define CORBA_INV_TERM_ON_ERROR (1<<9)
++#define CORBA_RESP_NO_WAIT (1<<10)
++
++typedef struct CORBA_NamedValue {
++ CORBA_Identifier name; /* argument name */
++ CORBA_any argument; /* argument */
++ CORBA_long len; /* length/count of argument value */
++ CORBA_Flags arg_modes; /* argument mode flags */
++} CORBA_NamedValue;
++
++typedef CORBA_char *CORBA_FieldName;
++
++typedef struct CORBA_NameValuePair {
++ CORBA_FieldName id;
++ CORBA_any value;
++} CORBA_NameValuePair;
++
++struct CORBA_Current_type {
++ int fill_me_in;
++};
++
++#include "corba_portableserver_type.h"
++
++typedef CORBA_unsigned_short CORBA_ServiceType;
++
++#define CORBA_Security (1)
++
++struct CORBA_ServiceDetail_type {
++ CORBA_ServiceDetailType service_detail_type;
++ CORBA_sequence_octet service_detail;
++};
++
++typedef struct CORBA_ServiceInformation_struct {
++ CORBA_sequence_ServiceOption service_options;
++ CORBA_sequence_ServiceDetail service_details;
++} CORBA_ServiceInformation;
++
++#endif /* !_ORBIT_TYPES_H_ */
+diff -urN linux-2.4.1/net/korbit/orb/poa.c linux-2.4.1-korbit/net/korbit/orb/poa.c
+--- linux-2.4.1/net/korbit/orb/poa.c Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/orb/poa.c Thu Feb 1 11:47:14 2001
+@@ -0,0 +1,1387 @@
++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
++
++/*
++ * ORBit: A CORBA v2.2 ORB
++ *
++ * Copyright (C) 1998 Richard H. Porter, and Red Hat Software
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Library General Public
++ * License as published by the Free Software Foundation; either
++ * version 2 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Library General Public License for more details.
++ *
++ * You should have received a copy of the GNU Library General Public
++ * License along with this library; if not, write to the Free
++ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Author: Dick Porter <dick@cymru.net>
++ * Elliot Lee <sopwith@redhat.com>
++ *
++ */
++
++#include <string.h>
++#include <stdio.h>
++#include <assert.h>
++
++#include "orbit.h"
++#include "orbit_poa.h"
++#include "genrand.h"
++
++PortableServer_ThreadPolicyValue
++PortableServer_ThreadPolicy__get_value(PortableServer_ThreadPolicy obj, CORBA_Environment *ev)
++{
++ if(!obj) {
++ ev->_major = 2 ;
++ goto error_exit;
++ }
++ ev->_major = CORBA_NO_EXCEPTION;
++
++ return obj->value;
++
++error_exit:
++ CORBA_exception_set_system(ev, 0, CORBA_COMPLETED_NO);
++ return 0;
++}
++
++PortableServer_LifespanPolicyValue
++PortableServer_LifespanPolicy__get_value(PortableServer_LifespanPolicy obj, CORBA_Environment *ev)
++{
++ if(!obj) {
++ ev->_major = 2 ;
++ goto error_exit;
++ }
++
++ ev->_major = CORBA_NO_EXCEPTION;
++ return obj->value;
++
++error_exit:
++ CORBA_exception_set_system(ev, 0, CORBA_COMPLETED_NO);
++ return 0;
++}
++
++PortableServer_IdUniquenessPolicyValue
++PortableServer_IdUniquenessPolicy__get_value(PortableServer_IdUniquenessPolicy obj, CORBA_Environment *ev)
++{
++ if(!obj) {
++ ev->_major = 2 ;
++ goto error_exit;
++ }
++
++ ev->_major = CORBA_NO_EXCEPTION;
++ return obj->value;
++
++error_exit:
++ CORBA_exception_set_system(ev, 0, CORBA_COMPLETED_NO);
++ return 0;
++}
++
++PortableServer_IdAssignmentPolicyValue
++PortableServer_IdAssignmentPolicy__get_value(PortableServer_IdAssignmentPolicy obj, CORBA_Environment *ev)
++{
++ if(!obj) {
++ ev->_major = 2 ;
++ goto error_exit;
++ }
++
++ ev->_major = CORBA_NO_EXCEPTION;
++ return obj->value;
++
++error_exit:
++ CORBA_exception_set_system(ev, 0, CORBA_COMPLETED_NO);
++ return 0;
++}
++
++PortableServer_ImplicitActivationPolicyValue
++PortableServer_ImplicitActivationPolicy__get_value(PortableServer_ImplicitActivationPolicy obj, CORBA_Environment *ev)
++{
++ if(!obj) {
++ ev->_major = 2 ;
++ goto error_exit;
++ }
++
++ ev->_major = CORBA_NO_EXCEPTION;
++ return obj->value;
++
++error_exit:
++ CORBA_exception_set_system(ev, 0, CORBA_COMPLETED_NO);
++ return 0;
++}
++
++PortableServer_ServantRetentionPolicyValue
++PortableServer_ServantRetentionPolicy__get_value(PortableServer_ServantRetentionPolicy obj, CORBA_Environment *ev)
++{
++ if(!obj) {
++ ev->_major = 2 ;
++ goto error_exit;
++ }
++
++ ev->_major = CORBA_NO_EXCEPTION;
++ return obj->value;
++
++error_exit:
++ CORBA_exception_set_system(ev, 0, CORBA_COMPLETED_NO);
++ return 0;
++}
++
++PortableServer_RequestProcessingPolicyValue
++PortableServer_RequestProcessingPolicy__get_value(PortableServer_RequestProcessingPolicy obj, CORBA_Environment *ev)
++{
++ if(!obj) {
++ ev->_major = 2 ;
++ goto error_exit;
++ }
++
++ ev->_major = CORBA_NO_EXCEPTION;
++ return obj->value;
++
++error_exit:
++ CORBA_exception_set_system(ev, 0, CORBA_COMPLETED_NO);
++ return 0;
++}
++
++/* make emacs happy; */
++
++PortableServer_POAManager_State
++PortableServer_POAManager_get_state(PortableServer_POAManager obj,
++ CORBA_Environment *ev)
++{
++ if(!obj) {
++ CORBA_exception_set_system(ev,
++ ex_CORBA_BAD_PARAM,
++ CORBA_COMPLETED_NO);
++ return -1;
++ }
++
++ ev->_major = CORBA_NO_EXCEPTION;
++ return obj->state;
++}
++
++/**** PortableServer_POAManager_activate
++ Inputs: 'obj' - a POAManager to activate
++ Outputs: '*ev' - result of the activate operation
++
++ Side effect: Clears the 'held_requests' lists for all POA's
++ associated with the 'obj' POAManager.
++
++ Description: Sets the POAManager state to 'ACTIVE', then
++ goes through all the POA's associated with this
++ POAManager, and makes them re-process their
++ 'held_requests'
++ */
++void
++PortableServer_POAManager_activate(PortableServer_POAManager obj,
++ CORBA_Environment *ev)
++{
++ GSList *todo;
++ GSList *curitem;
++ PortableServer_POA curpoa;
++
++ if(!obj) {
++ CORBA_exception_set_system(ev,
++ ex_CORBA_BAD_PARAM,
++ CORBA_COMPLETED_NO);
++ return;
++ }
++
++ if(obj->state == PortableServer_POAManager_INACTIVE) {
++ CORBA_exception_set(ev, CORBA_USER_EXCEPTION,
++ ex_PortableServer_POAManager_AdapterInactive,
++ NULL);
++ return;
++ }
++
++ obj->state = PortableServer_POAManager_ACTIVE;
++
++ for(curitem = obj->poa_collection; curitem;
++ curitem = g_slist_next(curitem)) {
++ curpoa = (PortableServer_POA)curitem->data;
++
++ todo = curpoa->held_requests;
++ curpoa->held_requests = NULL;
++
++ g_slist_foreach(todo, (GFunc)ORBit_POA_handle_request,
++ curpoa);
++ g_slist_foreach(todo, (GFunc)giop_recv_buffer_unuse,
++ NULL);
++
++ g_slist_free(todo);
++ }
++ ev->_major = CORBA_NO_EXCEPTION;
++}
++
++void
++PortableServer_POAManager_hold_requests(PortableServer_POAManager obj,
++ CORBA_boolean wait_for_completion,
++ CORBA_Environment *ev)
++{
++ if(!obj) {
++ CORBA_exception_set_system(ev,
++ ex_CORBA_BAD_PARAM,
++ CORBA_COMPLETED_NO);
++ return;
++ }
++
++ if(obj->state == PortableServer_POAManager_INACTIVE) {
++ CORBA_exception_set(ev, CORBA_USER_EXCEPTION,
++ ex_PortableServer_POAManager_AdapterInactive,
++ NULL);
++ return;
++ }
++
++ obj->state = PortableServer_POAManager_HOLDING;
++ if(!wait_for_completion)
++ g_warning("hold_requests not finished - don't know how to kill outstanding request fulfillments");
++
++ ev->_major = CORBA_NO_EXCEPTION;
++}
++
++void
++PortableServer_POAManager_discard_requests(PortableServer_POAManager obj,
++ CORBA_boolean wait_for_completion,
++ CORBA_Environment *ev)
++{
++ if(!obj) {
++ CORBA_exception_set_system(ev,
++ ex_CORBA_BAD_PARAM,
++ CORBA_COMPLETED_NO);
++ return;
++ }
++
++ if(obj->state == PortableServer_POAManager_INACTIVE) {
++ CORBA_exception_set(ev, CORBA_USER_EXCEPTION,
++ ex_PortableServer_POAManager_AdapterInactive,
++ NULL);
++ return;
++ }
++
++ obj->state = PortableServer_POAManager_DISCARDING;
++ if(!wait_for_completion)
++ g_warning("discard_requests not finished - don't know how to kill outstanding request fulfillments");
++ ev->_major = CORBA_NO_EXCEPTION;
++}
++
++void
++PortableServer_POAManager_deactivate(PortableServer_POAManager obj,
++ CORBA_boolean etherealize_objects,
++ CORBA_boolean wait_for_completion,
++ CORBA_Environment *ev)
++{
++ if(!obj) {
++ CORBA_exception_set_system(ev,
++ ex_CORBA_BAD_PARAM,
++ CORBA_COMPLETED_NO);
++ return;
++ }
++
++ if(obj->state == PortableServer_POAManager_INACTIVE) {
++ CORBA_exception_set(ev, CORBA_USER_EXCEPTION,
++ ex_PortableServer_POAManager_AdapterInactive,
++ NULL);
++ return;
++ }
++
++ obj->state = PortableServer_POAManager_INACTIVE;
++
++ if(etherealize_objects)
++ g_slist_foreach(obj->poa_collection, (GFunc)ORBit_POA_etherealize_objects, ev);
++ ev->_major = CORBA_NO_EXCEPTION;
++}
++
++
++CORBA_boolean
++PortableServer_AdapterActivator_unknown_adapter(PortableServer_AdapterActivator obj,
++ PortableServer_POA parent,
++ CORBA_char *name,
++ CORBA_Environment *ev)
++{
++ g_assert(!"Not yet implemented");
++ return(CORBA_FALSE);
++}
++
++
++/**** PortableServer_ServantActivator_incarnate
++ */
++PortableServer_Servant
++
++PortableServer_ServantActivator_incarnate
++(PortableServer_ServantActivator obj,
++ PortableServer_ObjectId *oid,
++ PortableServer_POA adapter,
++ CORBA_Environment *ev)
++{
++ g_assert(!"Not yet implemented");
++ return(NULL);
++}
++
++void
++PortableServer_ServantActivator_etherealize
++(PortableServer_ServantActivator obj,
++ PortableServer_ObjectId *oid, PortableServer_POA adapter,
++ PortableServer_Servant serv,
++ CORBA_boolean cleanup_in_progress,
++ CORBA_boolean remaining_activations,
++ CORBA_Environment *ev)
++{
++ g_assert(!"Not yet implemented");
++ return;
++}
++
++PortableServer_POA
++PortableServer_POA_create_POA
++ (PortableServer_POA poa,
++ CORBA_char *adapter_name,
++ PortableServer_POAManager a_POAManager,
++ CORBA_PolicyList* policies,
++ CORBA_Environment *ev)
++{
++ PortableServer_POA new_poa = NULL;
++ PortableServer_POA check_poa = NULL;
++
++ /* Check for a child POA by the same name in parent */
++ check_poa = PortableServer_POA_find_POA(poa,adapter_name,
++ FALSE, ev);
++ CORBA_exception_free (ev);
++
++ if (!check_poa) {
++ new_poa = ORBit_POA_new(poa->orb,
++ adapter_name, a_POAManager, policies, ev);
++ } else {
++ CORBA_exception_set(ev, CORBA_USER_EXCEPTION,
++ ex_PortableServer_POA_AdapterAlreadyExists,
++ NULL);
++ new_poa = NULL;
++ }
++
++ if(ev->_major == CORBA_NO_EXCEPTION) {
++ new_poa->parent_poa = poa;
++ ORBit_POA_add_child(poa, new_poa, ev);
++ }
++
++ return new_poa;
++}
++
++/**** PortableServer_POA_find_POA
++ Inputs: 'obj' - a POA
++ 'activate_it' - whether to activate unknown POA's
++
++ Outputs: 'child_poa'
++
++ Description: Finds (and optionally activates) a child POA of 'obj'
++ with the specified names.
++
++ TODO: Activate non-existent adapters if asked.
++
++ */
++PortableServer_POA
++PortableServer_POA_find_POA(PortableServer_POA obj,
++ CORBA_char *adapter_name,
++ CORBA_boolean activate_it,
++ CORBA_Environment *ev)
++{
++ GSList *curitem;
++ PortableServer_POA child_poa;
++
++ for(curitem = obj->child_POAs; curitem;
++ curitem = g_slist_next(curitem)) {
++ child_poa = (PortableServer_POA)curitem->data;
++ if(!strcmp(child_poa->the_name, adapter_name)) {
++ ev->_major = CORBA_NO_EXCEPTION;
++ return child_poa;
++ }
++ }
++
++ if(activate_it)
++ g_warning("Don't yet know how to activate POA named \"%s\"",
++ adapter_name);
++
++ CORBA_exception_set(ev, CORBA_USER_EXCEPTION,
++ ex_PortableServer_POA_AdapterNonExistent,
++ NULL);
++
++ return NULL;
++}
++
++/**** PortableServer_POA_destroy
++ Inputs: 'obj' - the POA to be destroyed
++ 'etherealize_objects' - flag indicating whether any servant
++ manager should be asked to etherealize
++ objects in the active object map
++ 'wait_for_completion' - flag indicating whether to wait for
++ requests currently being handled
++ */
++void
++PortableServer_POA_destroy(PortableServer_POA obj,
++ CORBA_boolean etherealize_objects,
++ CORBA_boolean wait_for_completion,
++ CORBA_Environment *ev)
++{
++ if(etherealize_objects || !wait_for_completion)
++ g_warning("PortableServer_POA_destroy not yet fully implemented; ignoring flags");
++
++ if(ORBIT_ROOT_OBJECT(obj)->refs > 1)
++ g_warning("POA has multiple refs [%d]",
++ ORBIT_ROOT_OBJECT(obj)->refs);
++
++ CORBA_Object_release((CORBA_Object)obj, ev);
++ ev->_major = CORBA_NO_EXCEPTION;
++}
++
++PortableServer_ThreadPolicy PortableServer_POA_create_thread_policy(PortableServer_POA obj, PortableServer_ThreadPolicyValue value, CORBA_Environment *ev)
++{
++ PortableServer_ThreadPolicy retval;
++
++ retval = g_new(struct PortableServer_ThreadPolicy_type, 1);
++ ORBit_policy_object_init((CORBA_Policy)retval,
++ PortableServer_THREAD_POLICY_ID, ev);
++
++ retval->value = value;
++
++ return (PortableServer_ThreadPolicy)CORBA_Object_duplicate((CORBA_Object)retval, ev);
++}
++
++PortableServer_LifespanPolicy PortableServer_POA_create_lifespan_policy(PortableServer_POA obj, PortableServer_LifespanPolicyValue value, CORBA_Environment *ev)
++{
++ PortableServer_LifespanPolicy retval;
++
++ retval = g_new(struct PortableServer_LifespanPolicy_type, 1);
++ ORBit_policy_object_init((CORBA_Policy)retval,
++ PortableServer_LIFESPAN_POLICY_ID, ev);
++
++ retval->value = value;
++
++ return (PortableServer_LifespanPolicy)CORBA_Object_duplicate((CORBA_Object)retval, ev);
++}
++
++PortableServer_IdUniquenessPolicy PortableServer_POA_create_id_uniqueness_policy(PortableServer_POA obj, PortableServer_IdUniquenessPolicyValue value, CORBA_Environment *ev)
++{
++ PortableServer_IdUniquenessPolicy retval;
++
++ retval = g_new(struct PortableServer_IdUniquenessPolicy_type, 1);
++ ORBit_policy_object_init((CORBA_Policy)retval,
++ PortableServer_ID_UNIQUENESS_POLICY_ID,
++ ev);
++
++ retval->value = value;
++
++ return (PortableServer_IdUniquenessPolicy)CORBA_Object_duplicate((CORBA_Object)retval, ev);
++}
++
++PortableServer_IdAssignmentPolicy PortableServer_POA_create_id_assignment_policy(PortableServer_POA obj, PortableServer_IdAssignmentPolicyValue value, CORBA_Environment *ev)
++{
++ PortableServer_IdAssignmentPolicy retval;
++
++ retval = g_new(struct PortableServer_IdAssignmentPolicy_type, 1);
++ ORBit_policy_object_init((CORBA_Policy)retval,
++ PortableServer_ID_ASSIGNMENT_POLICY_ID, ev);
++
++ retval->value = value;
++
++ return (PortableServer_IdAssignmentPolicy)CORBA_Object_duplicate((CORBA_Object)retval, ev);
++}
++
++PortableServer_ImplicitActivationPolicy PortableServer_POA_create_implicit_activation_policy(PortableServer_POA obj, PortableServer_ImplicitActivationPolicyValue value, CORBA_Environment *ev)
++{
++ PortableServer_ImplicitActivationPolicy retval;
++
++ retval = g_new(struct PortableServer_ImplicitActivationPolicy_type, 1);
++ ORBit_policy_object_init((CORBA_Policy)retval,
++ PortableServer_IMPLICIT_ACTIVATION_POLICY_ID, ev);
++
++ retval->value = value;
++
++ return (PortableServer_ImplicitActivationPolicy)CORBA_Object_duplicate((CORBA_Object)retval, ev);
++}
++
++PortableServer_ServantRetentionPolicy PortableServer_POA_create_servant_retention_policy(PortableServer_POA obj, PortableServer_ServantRetentionPolicyValue value, CORBA_Environment *ev)
++{
++ PortableServer_ServantRetentionPolicy retval;
++
++ retval = g_new(struct PortableServer_ServantRetentionPolicy_type, 1);
++ ORBit_policy_object_init((CORBA_Policy)retval,
++ PortableServer_SERVANT_RETENTION_POLICY_ID, ev);
++
++ retval->value = value;
++
++ return (PortableServer_ServantRetentionPolicy)CORBA_Object_duplicate((CORBA_Object)retval, ev);
++}
++
++PortableServer_RequestProcessingPolicy PortableServer_POA_create_request_processing_policy(PortableServer_POA obj, PortableServer_RequestProcessingPolicyValue value, CORBA_Environment *ev)
++{
++ PortableServer_RequestProcessingPolicy retval;
++
++ retval = g_new(struct PortableServer_RequestProcessingPolicy_type, 1);
++ ORBit_policy_object_init((CORBA_Policy)retval,
++ PortableServer_REQUEST_PROCESSING_POLICY_ID, ev);
++
++ retval->value = value;
++
++ return (PortableServer_RequestProcessingPolicy)CORBA_Object_duplicate((CORBA_Object)retval, ev);
++}
++
++CORBA_char *PortableServer_POA__get_the_name(PortableServer_POA obj, CORBA_Environment *ev)
++{
++ g_assert(obj);
++ g_assert(obj->the_name);
++ return obj->the_name;
++}
++
++PortableServer_POA
++PortableServer_POA__get_the_parent(PortableServer_POA obj,
++ CORBA_Environment *ev)
++{
++ if(!obj) {
++ CORBA_exception_set_system(ev,
++ ex_CORBA_BAD_PARAM,
++ CORBA_COMPLETED_NO);
++ return NULL;
++ }
++
++ return obj->parent_poa;
++}
++
++PortableServer_POAManager
++PortableServer_POA__get_the_POAManager(PortableServer_POA obj,
++ CORBA_Environment *ev)
++{
++ if(!obj) {
++ CORBA_exception_set_system(ev,
++ ex_CORBA_BAD_PARAM,
++ CORBA_COMPLETED_NO);
++ return NULL;
++ }
++
++ return obj->the_POAManager;
++}
++
++PortableServer_AdapterActivator PortableServer_POA__get_the_activator(PortableServer_POA obj, CORBA_Environment *ev)
++{
++ if(!obj) {
++ CORBA_exception_set_system(ev,
++ ex_CORBA_BAD_PARAM,
++ CORBA_COMPLETED_NO);
++ return NULL;
++ }
++
++ return obj->the_activator;
++}
++
++void PortableServer_POA__set_the_activator(PortableServer_POA obj, PortableServer_AdapterActivator the_activator, CORBA_Environment *ev)
++{
++ if(!obj) {
++ CORBA_exception_set_system(ev,
++ ex_CORBA_BAD_PARAM,
++ CORBA_COMPLETED_NO);
++ return;
++ }
++
++ obj->the_activator = the_activator;
++}
++
++PortableServer_ServantManager PortableServer_POA_get_servant_manager(PortableServer_POA obj, CORBA_Environment *ev)
++{
++ if(!obj) {
++ CORBA_exception_set_system(ev, ex_CORBA_BAD_PARAM,
++ CORBA_COMPLETED_NO);
++ return NULL;
++ }
++
++ if(obj->request_processing != PortableServer_USE_SERVANT_MANAGER) {
++ CORBA_exception_set(ev, CORBA_USER_EXCEPTION,
++ ex_PortableServer_POA_WrongPolicy,
++ NULL);
++ return NULL;
++ }
++
++ return obj->servant_manager;
++}
++
++void PortableServer_POA_set_servant_manager(PortableServer_POA obj, PortableServer_ServantManager imgr, CORBA_Environment *ev)
++{
++ if(!obj) {
++ CORBA_exception_set_system(ev, ex_CORBA_BAD_PARAM,
++ CORBA_COMPLETED_NO);
++ return;
++ }
++
++ if(obj->request_processing != PortableServer_USE_SERVANT_MANAGER) {
++ CORBA_exception_set(ev, CORBA_USER_EXCEPTION,
++ ex_PortableServer_POA_WrongPolicy,
++ NULL);
++ return;
++ }
++
++ obj->servant_manager = imgr;
++}
++
++PortableServer_Servant PortableServer_POA_get_servant(PortableServer_POA obj, CORBA_Environment *ev)
++{
++ if(!obj) {
++ CORBA_exception_set_system(ev, ex_CORBA_BAD_PARAM,
++ CORBA_COMPLETED_NO);
++ return NULL;
++ }
++
++ if(obj->request_processing != PortableServer_USE_DEFAULT_SERVANT) {
++ CORBA_exception_set(ev, CORBA_USER_EXCEPTION,
++ ex_PortableServer_POA_WrongPolicy,
++ NULL);
++ return NULL;
++ }
++
++ return obj->default_servant;
++}
++
++void PortableServer_POA_set_servant(PortableServer_POA obj, PortableServer_Servant p_servant, CORBA_Environment *ev)
++{
++ if(!obj) {
++ CORBA_exception_set_system(ev, ex_CORBA_BAD_PARAM,
++ CORBA_COMPLETED_NO);
++ return;
++ }
++
++ if(obj->request_processing != PortableServer_USE_DEFAULT_SERVANT) {
++ CORBA_exception_set(ev, CORBA_USER_EXCEPTION,
++ ex_PortableServer_POA_WrongPolicy,
++ NULL);
++ return;
++ }
++
++ obj->default_servant = p_servant;
++}
++
++static CORBA_unsigned_long
++get_objnum_for_obj(PortableServer_POA poa, ORBit_POAObject *obj)
++{
++ CORBA_unsigned_long retval;
++
++ if(poa->first_free_id) {
++ retval = poa->first_free_id;
++ poa->first_free_id = GPOINTER_TO_UINT(g_ptr_array_index(poa->objnum_to_obj,
++ retval));
++ g_ptr_array_index(poa->objnum_to_obj, retval) = obj;
++ } else {
++ retval = poa->objnum_to_obj->len;
++ g_ptr_array_add(poa->objnum_to_obj,
++ obj);
++ }
++
++ return retval;
++}
++
++static CORBA_ORB
++get_orb_for_poa(PortableServer_POA poa)
++{
++ if(poa->orb)
++ return poa->orb;
++ if(poa->parent_poa)
++ return get_orb_for_poa(poa->parent_poa);
++
++ return CORBA_OBJECT_NIL;
++}
++
++PortableServer_ObjectId *
++PortableServer_POA_activate_object(PortableServer_POA obj,
++ PortableServer_Servant p_servant,
++ CORBA_Environment *ev)
++{
++ PortableServer_ServantBase *servant;
++ PortableServer_ObjectId *new_objid;
++ ORBit_POAObject *new_obj;
++
++ servant = p_servant;
++
++ if(obj->servant_retention != PortableServer_RETAIN
++ || obj->id_assignment != PortableServer_SYSTEM_ID) {
++ CORBA_exception_set(ev, CORBA_USER_EXCEPTION,
++ ex_PortableServer_POA_WrongPolicy,
++ NULL);
++ return NULL;
++ }
++
++ /* Servant Already Active */
++ if((obj->id_uniqueness==PortableServer_UNIQUE_ID) &&
++ (ORBIT_OBJECT_KEY(servant->_private)->object != 0)) {
++ CORBA_exception_set(ev, CORBA_USER_EXCEPTION,
++ ex_PortableServer_POA_ServantAlreadyActive,
++ NULL);
++ return NULL;
++ }
++
++
++ new_obj = g_new0(ORBit_POAObject, 1);
++ new_obj->object_id = (PortableServer_ObjectId*)CORBA_sequence_octet__alloc();
++
++ new_objid =
++ ORBit_POA_allocate_oid(obj,
++ ORBIT_OBJECT_KEY(servant->_private)->class_info->class_name);
++
++ new_obj->object_id->_buffer = CORBA_octet_allocbuf(new_objid->_length);
++ new_obj->object_id->_length = new_objid->_length;
++ memcpy(new_obj->object_id->_buffer, new_objid->_buffer,
++ new_objid->_length);
++ CORBA_sequence_set_release(new_obj->object_id, CORBA_TRUE);
++
++ new_obj->servant = p_servant;
++ ORBIT_OBJECT_KEY(servant->_private)->object = new_obj;
++ new_obj->orb = get_orb_for_poa(obj);
++ new_obj->poa = obj;
++ new_obj->objnum = get_objnum_for_obj(obj, new_obj);
++ orbit_genrand(new_obj->rand_data, ORBIT_RAND_KEY_LEN);
++
++ g_hash_table_insert(obj->active_object_map,
++ new_obj->object_id,
++ new_obj);
++
++ ev->_major = CORBA_NO_EXCEPTION;
++
++ return new_objid;
++}
++
++void
++PortableServer_POA_activate_object_with_id(PortableServer_POA obj,
++ PortableServer_ObjectId *id,
++ PortableServer_Servant p_servant,
++ CORBA_Environment *ev)
++{
++ PortableServer_ServantBase *servant = p_servant;
++ ORBit_POAObject *newobj;
++
++ if(!obj || !id || !p_servant) {
++ CORBA_exception_set_system(ev, ex_CORBA_BAD_PARAM,
++ CORBA_COMPLETED_NO);
++ return;
++ }
++
++ newobj = g_hash_table_lookup(obj->active_object_map,
++ id);
++
++ if(newobj) {
++ CORBA_exception_set(ev, CORBA_USER_EXCEPTION,
++ ex_PortableServer_POA_ObjectAlreadyActive, NULL);
++ return;
++ }
++
++ newobj = g_new0(ORBit_POAObject, 1);
++ newobj->object_id = (PortableServer_ObjectId *)CORBA_sequence_octet__alloc();
++ newobj->object_id->_length = id->_length;
++ newobj->object_id->_buffer = CORBA_octet_allocbuf(id->_length);
++ newobj->object_id->_release = CORBA_TRUE;
++ memcpy(newobj->object_id->_buffer, id->_buffer, id->_length);
++ newobj->poa = obj;
++ newobj->orb = get_orb_for_poa(obj);
++ newobj->objnum = get_objnum_for_obj(obj, newobj);
++ orbit_genrand(newobj->rand_data, ORBIT_RAND_KEY_LEN);
++
++ newobj->servant = p_servant;
++
++ g_hash_table_insert(obj->active_object_map,
++ newobj->object_id,
++ newobj);
++
++ ORBIT_OBJECT_KEY(servant->_private)->object = newobj;
++
++ ev->_major = CORBA_NO_EXCEPTION;
++}
++
++void
++PortableServer_POA_deactivate_object(PortableServer_POA obj,
++ PortableServer_ObjectId *oid,
++ CORBA_Environment *ev)
++{
++ ORBit_POAObject *oldobj;
++
++ if(!obj || !oid) {
++ CORBA_exception_set_system(ev, ex_CORBA_BAD_PARAM,
++ CORBA_COMPLETED_NO);
++ return;
++ }
++
++ oldobj = g_hash_table_lookup(obj->active_object_map,
++ oid);
++
++ if(!oldobj) {
++ CORBA_exception_set(ev, CORBA_USER_EXCEPTION,
++ ex_PortableServer_POA_ObjectNotActive,
++ NULL);
++ return;
++ }
++
++ g_ptr_array_index(obj->objnum_to_obj, oldobj->objnum) = GUINT_TO_POINTER(obj->first_free_id);
++ obj->first_free_id = oldobj->objnum;
++
++ g_hash_table_remove(obj->active_object_map, oid);
++
++ if(obj->request_processing == PortableServer_USE_SERVANT_MANAGER) {
++ POA_PortableServer_ServantActivator__epv *epv;
++ POA_PortableServer_ServantActivator *sm;
++
++ sm = (POA_PortableServer_ServantActivator *)obj->servant_manager;
++ epv = sm->vepv->PortableServer_ServantActivator_epv;
++ epv->etherealize(sm, oldobj->object_id, obj,
++ oldobj->servant,
++ CORBA_FALSE,
++ CORBA_FALSE,
++ ev);
++ }
++
++ CORBA_free(oldobj->object_id);
++
++ g_free(oldobj);
++ ev->_major = CORBA_NO_EXCEPTION;
++}
++
++CORBA_Object
++PortableServer_POA_create_reference(PortableServer_POA obj,
++ CORBA_RepositoryId intf,
++ CORBA_Environment *ev)
++{
++ g_assert(!"Not yet implemented");
++ return(NULL);
++}
++
++PortableServer_ObjectId *PortableServer_POA_servant_to_id(PortableServer_POA obj, PortableServer_Servant p_servant, CORBA_Environment *ev)
++{
++ PortableServer_ObjectId *retval, *orig;
++ PortableServer_ServantBase *serv = p_servant;
++ g_return_val_if_fail(p_servant != NULL, NULL);
++
++ orig = ORBIT_OBJECT_KEY(serv->_private)->object->object_id;
++ retval = (PortableServer_ObjectId *)CORBA_sequence_octet__alloc();
++ retval->_length = retval->_maximum = orig->_length;
++ retval->_buffer = CORBA_octet_allocbuf(retval->_length);
++ memcpy(retval->_buffer, orig->_buffer, retval->_length);
++ CORBA_sequence_set_release(retval, CORBA_TRUE);
++
++ return retval;
++}
++
++CORBA_Object
++PortableServer_POA_servant_to_reference(PortableServer_POA obj, PortableServer_Servant p_servant, CORBA_Environment *ev)
++{
++ CORBA_Object retval;
++ PortableServer_ObjectId *orig_id;
++ PortableServer_ServantBase *servant = p_servant;
++ ORBit_ObjectKey *obj_key = ORBIT_OBJECT_KEY(servant->_private);
++
++ int implicit = (obj->implicit_activation == PortableServer_IMPLICIT_ACTIVATION);
++ int activate_able = (obj_key->object == 0) ||
++ (obj->id_uniqueness==PortableServer_MULTIPLE_ID);
++ /* ImplicitActivationPolicy */
++ if( implicit && activate_able) {
++ orig_id = PortableServer_POA_activate_object(obj, p_servant, ev);
++ } else {
++ orig_id = obj_key->object->object_id;
++ }
++ retval = PortableServer_POA_id_to_reference(obj,orig_id,ev);
++
++ return retval;
++}
++
++PortableServer_Servant
++PortableServer_POA_reference_to_servant(PortableServer_POA obj, CORBA_Object reference, CORBA_Environment *ev)
++{
++ GSList *cur;
++
++ g_assert(reference);
++
++ if(obj->request_processing != PortableServer_USE_DEFAULT_SERVANT
++ && obj->servant_retention != PortableServer_RETAIN) {
++ CORBA_exception_set(ev, CORBA_USER_EXCEPTION,
++ ex_PortableServer_POA_WrongPolicy,
++ NULL);
++ return NULL;
++ }
++
++ if(reference->servant)
++ return reference->servant;
++
++ for(cur = reference->profile_list; cur; cur = cur->next) {
++ PortableServer_ObjectId *oid;
++ ORBit_Object_info *curprof = cur->data;
++ ORBit_POAObject *objinfo;
++
++ objinfo = ORBit_POA_find_oid_for_object_key(obj, &(curprof->object_key), &oid);
++ CORBA_free(oid);
++ if(objinfo)
++ return objinfo->servant;
++ }
++
++ CORBA_exception_set(ev, CORBA_USER_EXCEPTION,
++ ex_PortableServer_POA_ObjectNotActive,
++ NULL);
++ return NULL;
++}
++
++PortableServer_ObjectId *PortableServer_POA_reference_to_id(PortableServer_POA obj, CORBA_Object reference, CORBA_Environment *ev)
++{
++ PortableServer_ObjectId *retval;
++ ORBit_POAObject *objinfo;
++
++ g_assert(reference);
++ g_assert(reference->active_profile);
++
++ if(obj->request_processing != PortableServer_USE_DEFAULT_SERVANT
++ && obj->servant_retention != PortableServer_RETAIN) {
++ CORBA_exception_set(ev, CORBA_USER_EXCEPTION,
++ ex_PortableServer_POA_WrongPolicy,
++ NULL);
++ return NULL;
++ }
++
++ objinfo = ORBit_POA_find_oid_for_object_key(obj, &(reference->active_profile->object_key), &retval);
++ if(objinfo) {
++ CORBA_free(retval);
++ retval = (PortableServer_ObjectId *)CORBA_sequence_octet__alloc();
++ retval->_length = retval->_maximum = objinfo->object_id->_length;
++ retval->_buffer = CORBA_octet_allocbuf(retval->_length);
++ memcpy(retval->_buffer, objinfo->object_id->_buffer, retval->_length);
++ CORBA_sequence_set_release(retval, CORBA_TRUE);
++ return retval;
++ } else if(retval)
++ return retval;
++
++ CORBA_exception_set(ev, CORBA_USER_EXCEPTION,
++ ex_PortableServer_POA_ObjectNotActive,
++ NULL);
++ return NULL;
++}
++
++PortableServer_Servant PortableServer_POA_id_to_servant(PortableServer_POA obj, PortableServer_ObjectId *oid, CORBA_Environment *ev)
++{
++ ORBit_POAObject *objinfo;
++
++ if(obj->servant_retention != PortableServer_RETAIN) {
++ CORBA_exception_set(ev, CORBA_USER_EXCEPTION,
++ ex_PortableServer_POA_WrongPolicy,
++ NULL);
++ return NULL;
++ }
++
++ objinfo = g_hash_table_lookup(obj->active_object_map,
++ oid);
++
++ if(!objinfo) {
++ CORBA_exception_set(ev, CORBA_USER_EXCEPTION,
++ ex_PortableServer_POA_WrongPolicy,
++ NULL);
++ return NULL;
++ }
++
++ return objinfo->servant;
++}
++
++static CORBA_Object
++my_PortableServer_POA_id_to_reference(PortableServer_POA obj,
++ PortableServer_ObjectId *oid,
++ const char *type_id,
++ CORBA_Environment *ev)
++{
++ GSList *profiles=NULL;
++ ORBit_Object_info *object_info;
++ CORBA_Object retval;
++ CORBA_ORB orb;
++ ORBit_POAObject *pobj;
++ ORBit_ObjectKey *objkey = NULL;
++
++ orb = obj->the_POAManager->orb;
++
++ g_assert(!oid->_buffer[oid->_length - 1]);
++
++ pobj = g_hash_table_lookup(obj->active_object_map, oid);
++
++ if(pobj) {
++ objkey = ORBIT_OBJECT_KEY(((PortableServer_ServantBase *)pobj->servant)->_private);
++ type_id= objkey->class_info->class_name;
++ }
++
++ /* Do the local connection first, so it will be attempted first by
++ the client parsing the IOR string
++ */
++ if(orb->cnx.ipv6 || orb->cnx.usock) {
++ object_info = g_new0(ORBit_Object_info, 1);
++
++ object_info->profile_type=IOP_TAG_ORBIT_SPECIFIC;
++ object_info->iiop_major = 1;
++ object_info->iiop_minor = 0;
++
++ ORBit_POA_find_object_key_for_oid(obj, pobj, oid, &object_info->object_key);
++
++#ifdef HAVE_IPV6
++ if(orb->cnx.ipv6) {
++ object_info->tag.orbitinfo.ipv6_port =
++ ntohs(IIOP_CONNECTION(orb->cnx.ipv6)->u.ipv6.location.sin_port);
++ }
++#endif
++ if(orb->cnx.usock) {
++ object_info->tag.orbitinfo.unix_sock_path =
++ g_strdup(IIOP_CONNECTION(orb->cnx.usock)->u.usock.sun_path);
++ }
++ ORBit_set_object_key(object_info);
++ profiles=g_slist_append(profiles, object_info);
++ }
++
++ if(orb->cnx.ipv4) {
++ object_info=g_new0(ORBit_Object_info, 1);
++
++ object_info->profile_type = IOP_TAG_INTERNET_IOP;
++ object_info->iiop_major = 1;
++ object_info->iiop_minor = 0;
++ ORBit_POA_find_object_key_for_oid(obj, pobj, oid, &object_info->object_key);
++
++ object_info->tag.iopinfo.host = g_strdup(IIOP_CONNECTION(orb->cnx.ipv4)->u.ipv4.hostname);
++ object_info->tag.iopinfo.port = ntohs(IIOP_CONNECTION(orb->cnx.ipv4)->u.ipv4.location.sin_port);
++
++ ORBit_set_object_key(object_info);
++ profiles=g_slist_append(profiles, object_info);
++ }
++
++ retval = ORBit_create_object_with_info(profiles, type_id, orb, ev);
++
++ if(retval != CORBA_OBJECT_NIL
++ && ev->_major == CORBA_NO_EXCEPTION
++ && objkey && objkey->class_info && objkey->class_info->init_local_objref) {
++ /* XXX potential memleak if we get an already-valid objref */
++ retval->vepv = g_new0(gpointer, ORBit_class_assignment_counter + 1);
++ retval->vepv_size = ORBit_class_assignment_counter + 1;
++ objkey->class_info->init_local_objref(retval, pobj->servant);
++ retval->servant = pobj->servant;
++ } else
++ retval->vepv = retval->servant = NULL;
++
++ return retval;
++}
++
++CORBA_Object PortableServer_POA_id_to_reference(PortableServer_POA obj,
++ PortableServer_ObjectId *oid,
++ CORBA_Environment *ev)
++{
++ return my_PortableServer_POA_id_to_reference(obj, oid, NULL, ev);
++}
++
++CORBA_Object
++PortableServer_POA_create_reference_with_id(PortableServer_POA obj,
++ PortableServer_ObjectId *oid,
++ CORBA_RepositoryId intf,
++ CORBA_Environment *ev)
++{
++ return my_PortableServer_POA_id_to_reference(obj, oid, intf, ev);
++}
++
++PortableServer_POA PortableServer_Current_get_POA(PortableServer_Current obj, CORBA_Environment *ev)
++{
++ g_assert(!"Not yet implemented");
++ return(NULL);
++}
++
++PortableServer_ObjectId *PortableServer_Current_get_object_id(PortableServer_Current obj, CORBA_Environment *ev)
++{
++ g_assert(!"Not yet implemented");
++ return(NULL);
++}
++
++
++CORBA_char *PortableServer_ObjectId_to_string(PortableServer_ObjectId *id, CORBA_Environment *env)
++{
++ return CORBA_string_dup((CORBA_char *)id->_buffer);
++}
++
++CORBA_wchar *PortableServer_ObjectId_to_wstring(PortableServer_ObjectId *id, CORBA_Environment *env)
++{
++ g_assert(!"Not yet implemented");
++ return(NULL);
++}
++
++PortableServer_ObjectId *PortableServer_string_to_ObjectId(CORBA_char *str, CORBA_Environment *env)
++{
++ PortableServer_ObjectId *retval;
++
++ retval = (PortableServer_ObjectId *)CORBA_sequence_octet__alloc();
++
++ retval->_length = strlen(str) + 1;
++ retval->_buffer = CORBA_octet_allocbuf(retval->_length);
++
++ memcpy(retval->_buffer, str, retval->_length);
++
++ return retval;
++}
++
++PortableServer_ObjectId *PortableServer_wstring_to_ObjectId(CORBA_wchar *str, CORBA_Environment *env)
++{
++ g_assert(!"Not yet implemented");
++ return(NULL);
++}
++
++
++PortableServer_POA PortableServer_ServantBase__default_POA(PortableServer_Servant servant, CORBA_Environment *ev)
++{
++ g_return_val_if_fail(servant, NULL);
++
++ return ORBIT_OBJECT_KEY(((PortableServer_ServantBase *)servant)->_private)->object->poa;
++}
++
++void PortableServer_ServantLocator_preinvoke(PortableServer_ObjectId *oid, PortableServer_POA adapter, CORBA_Identifier op_name, PortableServer_ServantLocator_Cookie *cookie)
++{
++ g_assert(!"Not yet implemented");
++ return;
++}
++
++void PortableServer_ServantLocator_postinvoke(PortableServer_ObjectId *oid, PortableServer_POA adapter, CORBA_Identifier op_name, PortableServer_ServantLocator_Cookie cookie, PortableServer_Servant servant)
++{
++ g_assert(!"Not yet implemented");
++ return;
++}
++
++void PortableServer_ServantBase__init(PortableServer_Servant servant,
++ CORBA_Environment *ev)
++{
++ PortableServer_ServantBase *serv = servant;
++
++ if(!serv->_private) /* If not already initialized, create the place to
++ stick our info */
++ serv->_private = g_new0(ORBit_ObjectKey, 1);
++}
++
++void PortableServer_ServantBase__fini(PortableServer_Servant servant,
++ CORBA_Environment *ev)
++{
++ PortableServer_ServantBase *serv = servant;
++
++ g_free(serv->_private);
++ serv->_private = NULL;
++}
++
++
++/************************ ServerRequest stuff ********************/
++
++CORBA_Identifier CORBA_ServerRequest_operation(CORBA_ServerRequest req, CORBA_Environment *env)
++{
++ return CORBA_string_dup(req->rbuf->message.u.request.operation);
++}
++
++CORBA_Context
++CORBA_ServerRequest_ctx(CORBA_ServerRequest req, CORBA_Environment *env)
++{
++ if(!req->params || req->did_ctx) {
++ CORBA_exception_set_system(env, ex_CORBA_BAD_INV_ORDER,
++ CORBA_COMPLETED_NO);
++ return NULL;
++ }
++
++ return NULL;
++}
++
++void
++CORBA_ServerRequest_arguments(CORBA_ServerRequest req,
++ CORBA_NVList *parameters,
++ CORBA_Environment *env)
++{
++ int i;
++
++ if(req->params) {
++ CORBA_exception_set_system(env, ex_CORBA_BAD_INV_ORDER,
++ CORBA_COMPLETED_NO);
++ return;
++ }
++
++ req->params = parameters;
++
++ for(i = 0; i < parameters->list->len; i++) {
++ CORBA_NamedValue *cur;
++
++ cur = &g_array_index(parameters->list, CORBA_NamedValue, i);
++
++ if(cur->arg_modes & CORBA_ARG_OUT) continue;
++ cur->argument._value = ORBit_demarshal_arg(req->rbuf,
++ cur->argument._type,
++ TRUE,
++ (CORBA_ORB)req->orb);
++ CORBA_any_set_release(&cur->argument, TRUE);
++ }
++}
++
++void
++CORBA_ServerRequest_set_result(CORBA_ServerRequest req,
++ CORBA_any *value,
++ CORBA_Environment *env)
++{
++ if(req->sbuf) {
++ CORBA_exception_set_system(env, ex_CORBA_BAD_INV_ORDER,
++ CORBA_COMPLETED_NO);
++ return;
++ }
++
++ req->sbuf = giop_send_reply_buffer_use(GIOP_MESSAGE_BUFFER(req->rbuf)->connection,
++ NULL,
++ req->rbuf->message.u.request.request_id,
++ CORBA_NO_EXCEPTION);
++ if(!req->sbuf) {
++ CORBA_exception_set_system(env, ex_CORBA_COMM_FAILURE,
++ CORBA_COMPLETED_NO);
++ return;
++ }
++
++ ORBit_marshal_arg(req->sbuf, value->_value, value->_type);
++}
++
++void
++CORBA_ServerRequest_set_exception(CORBA_ServerRequest req,
++ CORBA_exception_type major,
++ CORBA_any *value,
++ CORBA_Environment *env)
++{
++ if(req->sbuf) {
++ CORBA_exception_set_system(env, ex_CORBA_BAD_INV_ORDER,
++ CORBA_COMPLETED_NO);
++ return;
++ }
++
++ req->sbuf = giop_send_reply_buffer_use(GIOP_MESSAGE_BUFFER(req->rbuf)->connection,
++ NULL,
++ req->rbuf->message.u.request.request_id,
++ major);
++ if(!req->sbuf) {
++ CORBA_exception_set_system(env, ex_CORBA_COMM_FAILURE,
++ CORBA_COMPLETED_NO);
++ return;
++ }
++
++ req->did_exc = TRUE;
++
++ /* XXX do we really need to copy the repo_id into the
++ send buffer? Or is there a way to assume that the CORBA_TypeCode
++ value->_type will be around until after we send the message? */
++ {
++ CORBA_unsigned_long slen;
++ slen = strlen(value->_type->repo_id) + 1;
++ giop_send_buffer_append_mem_indirect_a(req->sbuf, &slen,
++ sizeof(slen));
++ giop_send_buffer_append_mem_indirect(req->sbuf,
++ value->_type->repo_id,
++ slen);
++ }
++
++ ORBit_marshal_arg(req->sbuf, value->_value, value->_type);
++}
++
++void
++POA_PortableServer_ServantActivator__init(PortableServer_Servant servant,
++ CORBA_Environment * ev)
++{
++ static const PortableServer_ClassInfo class_info =
++ {NULL,
++ "IDL:omg.org/PortableServer/ServantActivator:1.0",
++ NULL};
++
++ PortableServer_ServantBase__init(((PortableServer_ServantBase *) servant), ev);
++
++ ORBIT_OBJECT_KEY(((PortableServer_ServantBase *)servant)->_private)->class_info = (gpointer)&class_info;
++}
++
++void
++POA_PortableServer_ServantActivator__fini(PortableServer_Servant servant,
++ CORBA_Environment * ev)
++{
++ PortableServer_ServantBase__fini(servant, ev);
++}
++
++void
++POA_PortableServer_ServantLocator__init(PortableServer_Servant servant,
++ CORBA_Environment * ev)
++{
++ static const PortableServer_ClassInfo class_info =
++ {NULL,
++ "IDL:omg.org/PortableServer/ServantLocator:1.0",
++ NULL};
++
++ PortableServer_ServantBase__init(((PortableServer_ServantBase *)servant), ev);
++
++ ORBIT_OBJECT_KEY(((PortableServer_ServantBase *)servant)->_private)->class_info = (gpointer)&class_info;
++}
++
++void
++POA_PortableServer_ServantLocator__fini(PortableServer_Servant servant,
++ CORBA_Environment * ev)
++{
++ PortableServer_ServantBase__fini(servant, ev);
++}
++
++/* POA-related DSI stuff */
++static void
++dynamic_impl_skel(PortableServer_DynamicImpl *_ORBIT_servant,
++ GIOPRecvBuffer *_ORBIT_recv_buffer,
++ CORBA_Environment *ev,
++ PortableServer_DynamicImplRoutine invoke)
++{
++ /* here the magic occurs... */
++ struct CORBA_ServerRequest_type sr;
++
++ ORBit_pseudo_object_init(ORBIT_PSEUDO_OBJECT(&sr),
++ ORBIT_PSEUDO_SERVERREQUEST, ev);
++
++ CORBA_Object_duplicate((CORBA_Object)&sr, ev); /* just to make
++ sure it doesn't die
++ elsewhere */
++
++ sr.rbuf = _ORBIT_recv_buffer;
++ sr.orb = GIOP_MESSAGE_BUFFER(_ORBIT_recv_buffer)->connection->orb_data;
++
++ _ORBIT_servant->vepv->PortableServer_DynamicImpl_epv->invoke(_ORBIT_servant,
++ &sr);
++
++ if(sr.sbuf) {
++ int i;
++ for(i = 0; i < sr.params->list->len; i++) {
++ CORBA_NamedValue *cur;
++
++ cur = &g_array_index(sr.params->list, CORBA_NamedValue, i);
++
++ if(cur->arg_modes & CORBA_ARG_IN) continue;
++
++ ORBit_marshal_arg(sr.sbuf, cur->argument._value,
++ cur->argument._type);
++ }
++
++ giop_send_buffer_write(sr.sbuf);
++ giop_send_buffer_unuse(sr.sbuf);
++ } else
++ g_warning("Yo, your DSI code is messed up! You forgot to set_result|set_exception");
++
++ CORBA_NVList_free(sr.params, ev);
++}
++
++static ORBitSkeleton
++dynamic_impl_get_skel(PortableServer_DynamicImpl * servant,
++ GIOPRecvBuffer * _ORBIT_recv_buffer,
++ gpointer * impl)
++{
++ *impl = (gpointer)servant->vepv->PortableServer_DynamicImpl_epv->invoke;
++
++ return (ORBitSkeleton)dynamic_impl_skel;
++}
++
++void
++PortableServer_DynamicImpl__init(PortableServer_Servant servant,
++ CORBA_Environment *ev)
++{
++ static const PortableServer_ClassInfo class_info =
++ {(ORBitSkeleton (*)(PortableServer_ServantBase *, gpointer, gpointer *))
++ &dynamic_impl_get_skel, "IDL:CORBA/Object:1.0", NULL};
++
++ PortableServer_ServantBase__init(servant, ev);
++
++ ORBIT_OBJECT_KEY(((PortableServer_ServantBase *)servant)->_private)->class_info =
++ (PortableServer_ClassInfo *) & class_info;
++
++}
++
++void PortableServer_DynamicImpl__fini(PortableServer_Servant servant,
++ CORBA_Environment *ev)
++{
++ PortableServer_ServantBase__fini(servant, ev);
++}
++
+diff -urN linux-2.4.1/net/korbit/orb/poa.h linux-2.4.1-korbit/net/korbit/orb/poa.h
+--- linux-2.4.1/net/korbit/orb/poa.h Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/orb/poa.h Thu Feb 1 11:47:14 2001
+@@ -0,0 +1,337 @@
++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
++
++/*
++ * ORBit: A CORBA v2.2 ORB
++ *
++ * Copyright (C) 1998 Richard H. Porter
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Library General Public
++ * License as published by the Free Software Foundation; either
++ * version 2 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Library General Public License for more details.
++ *
++ * You should have received a copy of the GNU Library General Public
++ * License along with this library; if not, write to the Free
++ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Author: Dick Porter <dick@cymru.net>
++ *
++ */
++
++#ifndef _ORBIT_POA_H_
++#define _ORBIT_POA_H_
++
++#include "orbit_types.h"
++
++extern PortableServer_ThreadPolicyValue PortableServer_ThreadPolicy__get_value(
++ PortableServer_ThreadPolicy obj,
++ CORBA_Environment *ev);
++
++extern PortableServer_LifespanPolicyValue PortableServer_LifespanPolicy__get_value(
++ PortableServer_LifespanPolicy obj,
++ CORBA_Environment *ev);
++
++extern PortableServer_IdUniquenessPolicyValue PortableServer_IdUniquenessPolicy__get_value(
++ PortableServer_IdUniquenessPolicy obj,
++ CORBA_Environment *ev);
++
++extern PortableServer_IdAssignmentPolicyValue PortableServer_IdAssignmentPolicy__get_value(
++ PortableServer_IdAssignmentPolicy obj,
++ CORBA_Environment *ev);
++
++extern PortableServer_ImplicitActivationPolicyValue PortableServer_ImplicitActivationPolicy__get_value(
++ PortableServer_ImplicitActivationPolicy obj,
++ CORBA_Environment *ev);
++
++extern PortableServer_ServantRetentionPolicyValue PortableServer_ServantRetentionPolicy__get_value(
++ PortableServer_ServantRetentionPolicy obj,
++ CORBA_Environment *ev);
++
++extern PortableServer_RequestProcessingPolicyValue PortableServer_RequestProcessingPolicy__get_value(
++ PortableServer_RequestProcessingPolicy obj,
++ CORBA_Environment *ev);
++
++PortableServer_POAManager_State
++PortableServer_POAManager_get_state(PortableServer_POAManager obj,
++ CORBA_Environment *ev);
++
++extern void PortableServer_POAManager_activate(
++ PortableServer_POAManager obj,
++ CORBA_Environment *ev);
++
++extern void PortableServer_POAManager_hold_requests(
++ PortableServer_POAManager obj,
++ CORBA_boolean wait_for_completion,
++ CORBA_Environment *ev);
++
++extern void PortableServer_POAManager_discard_requests(
++ PortableServer_POAManager obj,
++ CORBA_boolean wait_for_completion,
++ CORBA_Environment *ev);
++
++extern void PortableServer_POAManager_deactivate(
++ PortableServer_POAManager obj,
++ CORBA_boolean etherealize_objects,
++ CORBA_boolean wait_for_completion,
++ CORBA_Environment *ev);
++
++extern CORBA_boolean PortableServer_AdapterActivator_unknown_adapter(
++ PortableServer_AdapterActivator obj,
++ PortableServer_POA parent,
++ CORBA_char *name,
++ CORBA_Environment *ev);
++
++extern PortableServer_Servant PortableServer_ServantActivator_incarnate(
++ PortableServer_ServantActivator obj,
++ PortableServer_ObjectId *oid,
++ PortableServer_POA adapter,
++ CORBA_Environment *ev);
++
++extern void PortableServer_ServantActivator_etherealize(
++ PortableServer_ServantActivator obj,
++ PortableServer_ObjectId *oid,
++ PortableServer_POA adapter,
++ PortableServer_Servant serv,
++ CORBA_boolean cleanup_in_progress,
++ CORBA_boolean remaining_activations,
++ CORBA_Environment *ev);
++
++extern PortableServer_POA PortableServer_POA_create_POA(
++ PortableServer_POA obj,
++ CORBA_char *adapter_name,
++ PortableServer_POAManager a_POAManager,
++ CORBA_PolicyList *policies,
++ CORBA_Environment *ev);
++
++extern PortableServer_POA PortableServer_POA_find_POA(
++ PortableServer_POA obj,
++ CORBA_char *adapter_name,
++ CORBA_boolean activate_it,
++ CORBA_Environment *ev);
++
++extern void PortableServer_POA_destroy(
++ PortableServer_POA obj,
++ CORBA_boolean etherealize_objects,
++ CORBA_boolean wait_for_completion,
++ CORBA_Environment *ev);
++
++extern PortableServer_ThreadPolicy PortableServer_POA_create_thread_policy(
++ PortableServer_POA obj,
++ PortableServer_ThreadPolicyValue value,
++ CORBA_Environment *ev);
++
++extern PortableServer_LifespanPolicy PortableServer_POA_create_lifespan_policy(
++ PortableServer_POA obj,
++ PortableServer_LifespanPolicyValue value,
++ CORBA_Environment *ev);
++
++extern PortableServer_IdUniquenessPolicy PortableServer_POA_create_id_uniqueness_policy(
++ PortableServer_POA obj,
++ PortableServer_IdUniquenessPolicyValue value,
++ CORBA_Environment *ev);
++
++extern PortableServer_IdAssignmentPolicy PortableServer_POA_create_id_assignment_policy(
++ PortableServer_POA obj,
++ PortableServer_IdAssignmentPolicyValue value,
++ CORBA_Environment *ev);
++
++extern PortableServer_ImplicitActivationPolicy PortableServer_POA_create_implicit_activation_policy(
++ PortableServer_POA obj,
++ PortableServer_ImplicitActivationPolicyValue value,
++ CORBA_Environment *ev);
++
++extern PortableServer_ServantRetentionPolicy PortableServer_POA_create_servant_retention_policy(
++ PortableServer_POA obj,
++ PortableServer_ServantRetentionPolicyValue value,
++ CORBA_Environment *ev);
++
++extern PortableServer_RequestProcessingPolicy PortableServer_POA_create_request_processing_policy(
++ PortableServer_POA obj,
++ PortableServer_RequestProcessingPolicyValue value,
++ CORBA_Environment *ev);
++
++extern CORBA_char *PortableServer_POA__get_the_name(
++ PortableServer_POA obj,
++ CORBA_Environment *ev);
++
++extern PortableServer_POA PortableServer_POA__get_the_parent(
++ PortableServer_POA obj,
++ CORBA_Environment *ev);
++
++extern PortableServer_POAManager PortableServer_POA__get_the_POAManager(
++ PortableServer_POA obj,
++ CORBA_Environment *ev);
++
++extern PortableServer_AdapterActivator PortableServer_POA__get_the_activator(
++ PortableServer_POA obj,
++ CORBA_Environment *ev);
++
++extern void PortableServer_POA__set_the_activator(
++ PortableServer_POA obj,
++ PortableServer_AdapterActivator the_activator,
++ CORBA_Environment *ev);
++
++extern PortableServer_ServantManager PortableServer_POA_get_servant_manager(
++ PortableServer_POA obj,
++ CORBA_Environment *ev);
++
++extern void PortableServer_POA_set_servant_manager(
++ PortableServer_POA obj,
++ PortableServer_ServantManager imgr,
++ CORBA_Environment *ev);
++
++extern PortableServer_Servant PortableServer_POA_get_servant(
++ PortableServer_POA obj,
++ CORBA_Environment *ev);
++
++extern void PortableServer_POA_set_servant(
++ PortableServer_POA obj,
++ PortableServer_Servant p_servant,
++ CORBA_Environment *ev);
++
++extern PortableServer_ObjectId *PortableServer_POA_activate_object(
++ PortableServer_POA obj,
++ PortableServer_Servant p_servant,
++ CORBA_Environment *ev);
++
++extern void PortableServer_POA_activate_object_with_id(
++ PortableServer_POA obj,
++ PortableServer_ObjectId *id,
++ PortableServer_Servant p_servant,
++ CORBA_Environment *ev);
++
++extern void PortableServer_POA_deactivate_object(
++ PortableServer_POA obj,
++ PortableServer_ObjectId *oid,
++ CORBA_Environment *ev);
++
++extern CORBA_Object PortableServer_POA_create_reference(
++ PortableServer_POA obj,
++ CORBA_RepositoryId intf,
++ CORBA_Environment *ev);
++
++extern CORBA_Object PortableServer_POA_create_reference_with_id(
++ PortableServer_POA obj,
++ PortableServer_ObjectId *oid,
++ CORBA_RepositoryId intf,
++ CORBA_Environment *ev);
++
++extern PortableServer_ObjectId *PortableServer_POA_servant_to_id(
++ PortableServer_POA obj,
++ PortableServer_Servant p_servant,
++ CORBA_Environment *ev);
++
++extern CORBA_Object PortableServer_POA_servant_to_reference(
++ PortableServer_POA obj,
++ PortableServer_Servant p_servant,
++ CORBA_Environment *ev);
++
++extern PortableServer_Servant PortableServer_POA_reference_to_servant(
++ PortableServer_POA obj,
++ CORBA_Object reference,
++ CORBA_Environment *ev);
++
++extern PortableServer_ObjectId *PortableServer_POA_reference_to_id(
++ PortableServer_POA obj,
++ CORBA_Object reference,
++ CORBA_Environment *ev);
++
++extern PortableServer_Servant PortableServer_POA_id_to_servant(
++ PortableServer_POA obj,
++ PortableServer_ObjectId *oid,
++ CORBA_Environment *ev);
++
++extern CORBA_Object PortableServer_POA_id_to_reference(
++ PortableServer_POA obj,
++ PortableServer_ObjectId *oid,
++ CORBA_Environment *ev);
++
++extern PortableServer_POA PortableServer_Current_get_POA(
++ PortableServer_Current obj,
++ CORBA_Environment *ev);
++
++extern PortableServer_ObjectId *PortableServer_Current_get_object_id(
++ PortableServer_Current obj,
++ CORBA_Environment *ev);
++
++extern CORBA_char *PortableServer_ObjectId_to_string(
++ PortableServer_ObjectId *id,
++ CORBA_Environment *env);
++
++extern CORBA_wchar *PortableServer_ObjectId_to_wstring(
++ PortableServer_ObjectId *id,
++ CORBA_Environment *env);
++
++extern PortableServer_ObjectId *PortableServer_string_to_ObjectId(
++ CORBA_char *str,
++ CORBA_Environment *env);
++
++extern PortableServer_ObjectId *PortableServer_wstring_to_ObjectId(
++ CORBA_wchar *str,
++ CORBA_Environment *env);
++
++extern PortableServer_POA PortableServer_ServantBase__default_POA(
++ PortableServer_Servant,
++ CORBA_Environment *);
++
++extern void PortableServer_ServantLocator_preinvoke(
++ PortableServer_ObjectId *oid,
++ PortableServer_POA adapter,
++ CORBA_Identifier op_name,
++ PortableServer_ServantLocator_Cookie *cookie);
++
++extern void PortableServer_ServantLocator_postinvoke(
++ PortableServer_ObjectId *oid,
++ PortableServer_POA adapter,
++ CORBA_Identifier op_name,
++ PortableServer_ServantLocator_Cookie cookie,
++ PortableServer_Servant servant);
++
++extern void PortableServer_ServantBase__init(
++ PortableServer_Servant,
++ CORBA_Environment *);
++
++extern void PortableServer_ServantBase__fini(
++ PortableServer_Servant,
++ CORBA_Environment *);
++
++/* 19.27 */
++extern CORBA_Identifier CORBA_ServerRequest_operation(
++ CORBA_ServerRequest req,
++ CORBA_Environment *env);
++
++extern CORBA_Context CORBA_ServerRequest_ctx(
++ CORBA_ServerRequest req,
++ CORBA_Environment *env);
++
++extern void CORBA_ServerRequest_arguments(
++ CORBA_ServerRequest req,
++ CORBA_NVList *parameters,
++ CORBA_Environment *env);
++
++extern void CORBA_ServerRequest_set_result(
++ CORBA_ServerRequest req,
++ CORBA_any *value,
++ CORBA_Environment *env);
++
++extern void CORBA_ServerRequest_set_exception(
++ CORBA_ServerRequest req,
++ CORBA_exception_type major,
++ CORBA_any *value,
++ CORBA_Environment *env);
++
++extern void PortableServer_DynamicImpl__init(PortableServer_Servant,
++ CORBA_Environment *ev);
++
++extern void PortableServer_DynamicImpl__fini(PortableServer_Servant,
++ CORBA_Environment *ev);
++
++
++#include "orbit_poa_type.h"
++
++#endif /* !_ORBIT_POA_H_ */
+diff -urN linux-2.4.1/net/korbit/orb/sequences.c linux-2.4.1-korbit/net/korbit/orb/sequences.c
+--- linux-2.4.1/net/korbit/orb/sequences.c Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/orb/sequences.c Thu Feb 1 11:47:14 2001
+@@ -0,0 +1,35 @@
++#include "orbit.h"
++#include "sequences.h"
++
++gpointer CORBA_sequence_octet_free(gpointer mem,
++ gpointer func_data)
++{
++ CORBA_sequence_octet *seqo = mem;
++
++ if(seqo->_release)
++ CORBA_free(seqo->_buffer);
++
++ return (gpointer)((guchar *)mem + sizeof(CORBA_sequence_octet));
++}
++
++CORBA_octet *
++CORBA_octet_allocbuf(CORBA_unsigned_long len)
++{
++ return (CORBA_octet *)ORBit_alloc(len, NULL, NULL);
++}
++
++CORBA_sequence_octet *CORBA_sequence_octet__alloc(void)
++{
++ CORBA_sequence_octet *seqo;
++
++ seqo = ORBit_alloc(sizeof(CORBA_sequence_octet),
++ (ORBit_free_childvals)CORBA_sequence_octet_free,
++ GUINT_TO_POINTER(1));
++
++ seqo->_length = seqo->_maximum = 0;
++ seqo->_buffer = NULL;
++ seqo->_release = CORBA_TRUE;
++
++ return seqo;
++}
++
+diff -urN linux-2.4.1/net/korbit/orb/sequences.h linux-2.4.1-korbit/net/korbit/orb/sequences.h
+--- linux-2.4.1/net/korbit/orb/sequences.h Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/orb/sequences.h Thu Feb 1 16:21:19 2001
+@@ -0,0 +1,35 @@
++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
++
++/*
++ * ORBit: A CORBA v2.2 ORB
++ *
++ * Copyright (C) 1998 Richard H. Porter
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Library General Public
++ * License as published by the Free Software Foundation; either
++ * version 2 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Library General Public License for more details.
++ *
++ * You should have received a copy of the GNU Library General Public
++ * License along with this library; if not, write to the Free
++ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Author: Dick Porter <dick@cymru.net>
++ *
++ */
++
++#ifndef _ORBIT_SEQUENCES_H_
++#define _ORBIT_SEQUENCES_H_
++
++/* #include "corba_sequences_type.h" */
++#include "orbit_types.h"
++
++CORBA_octet *CORBA_octet_allocbuf(CORBA_unsigned_long len);
++CORBA_sequence_octet *CORBA_sequence_octet__alloc(void);
++
++#endif /* !_ORBIT_SEQUENCES_H_ */
+diff -urN linux-2.4.1/net/korbit/orb/server.c linux-2.4.1-korbit/net/korbit/orb/server.c
+--- linux-2.4.1/net/korbit/orb/server.c Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/orb/server.c Thu Feb 1 11:47:14 2001
+@@ -0,0 +1,217 @@
++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
++
++/* Elliot's stuff */
++/* This is somewhat a mess, because I tried to make it easy to add
++ select() support, and as a result #ifdef's litter the land. */
++
++#include "orbit.h"
++#include "orbit_poa.h"
++#include "orbit_poa_type.h"
++#include <IIOP/IIOP-private.h>
++#ifdef HAVE_SYS_POLL_H
++#include <sys/poll.h>
++#endif
++#include <sys/types.h>
++#include <sys/socket.h>
++
++/* We need:
++ a way to find out what FD's need to be selected on
++ a dummy main loop to implement the CORBA_ORB_run() routine;
++*/
++
++gboolean orb_server_keep_running = FALSE;
++
++ORBit_request_validate ORBIT_request_validator = NULL;
++
++/* function protos */
++static PortableServer_POA ORBit_find_POA_for_request(PortableServer_POA poa,
++ GIOPRecvBuffer *recv_buffer);
++static PortableServer_POA ORBit_find_POA_for_locate_request(PortableServer_POA poa,
++ GIOPRecvBuffer *recv_buffer);
++
++static void ORBit_handle_incoming_message(GIOPRecvBuffer *recv_buffer);
++
++void
++ORBit_custom_run_setup(CORBA_ORB orb, CORBA_Environment *ev)
++{
++ IIOPIncomingMessageHandler = ORBit_handle_incoming_message;
++}
++
++
++#if __KERNEL__
++// Modules don't do anything when they call this...
++void CORBA_ORB_run(CORBA_ORB orb, CORBA_Environment *ev) {
++ // This should probably free the ORB pointer, because it is a
++ // duplicated pointer from the one true orb.
++
++}
++
++// The ORB thread calls __CORBA_ORB_run by itself.
++#define CORBA_ORB_run __CORBA_ORB_run
++
++#endif
++
++void
++CORBA_ORB_run(CORBA_ORB orb, CORBA_Environment *ev)
++{
++ ORBit_custom_run_setup(orb, ev);
++
++ orb_server_keep_running = TRUE;
++
++ giop_main();
++}
++
++static void
++ORBit_handle_incoming_request(GIOPRecvBuffer *recv_buffer)
++{
++ CORBA_ORB orb;
++ PortableServer_POA poa;
++ GIOPConnection *connection;
++ ORBit_MessageValidationResult mvr;
++ gboolean do_unuse = TRUE;
++
++ g_assert(recv_buffer);
++
++ connection = GIOP_MESSAGE_BUFFER(recv_buffer)->connection;
++ g_return_if_fail(connection != NULL);
++
++ orb = connection->orb_data;
++
++ g_return_if_fail(orb != NULL);
++
++ ORBit_Trace(TraceMod_ORB, TraceLevel_Debug,
++ "Received request %s, id %d, on %s",
++ recv_buffer->message.u.request.operation,
++ recv_buffer->message.u.request.request_id,
++ recv_buffer->message.u.request.object_key._buffer);
++
++ if(ORBIT_request_validator)
++ mvr = ORBIT_request_validator(recv_buffer->message.u.request.request_id,
++ &recv_buffer->message.u.request.requesting_principal,
++ recv_buffer->message.u.request.operation);
++ else
++ mvr = ORBIT_MESSAGE_ALLOW;
++
++ if(mvr == ORBIT_MESSAGE_ALLOW_ALL)
++ connection->is_auth = TRUE;
++
++ if(mvr != ORBIT_MESSAGE_BAD) {
++ /* Find the POA for this incoming request */
++ poa = ORBit_find_POA_for_request((PortableServer_POA)orb->root_poa,
++ recv_buffer);
++
++ if(poa)
++ do_unuse = ORBit_POA_handle_request(recv_buffer, poa);
++ else
++ g_warning("No POA found for operation %s [%d]",
++ recv_buffer->message.u.request.operation,
++ recv_buffer->message.u.request.request_id);
++ } else {
++ g_warning("Request %s, ID %d was rejected by the authentication mechanism!",
++ recv_buffer->message.u.request.operation,
++ recv_buffer->message.u.request.request_id);
++ }
++
++ if(do_unuse)
++ giop_recv_buffer_unuse(recv_buffer);
++}
++
++static void
++ORBit_handle_incoming_locate_request(GIOPRecvBuffer *recv_buffer)
++{
++ CORBA_ORB orb;
++ PortableServer_POA poa;
++ GIOPConnection *connection;
++ GIOPSendBuffer *send_buffer;
++
++ g_assert(recv_buffer!=NULL);
++
++ connection = GIOP_MESSAGE_BUFFER(recv_buffer)->connection;
++ g_return_if_fail(connection != NULL);
++
++ orb = connection->orb_data;
++
++ g_return_if_fail(orb != NULL);
++
++ ORBit_Trace(TraceMod_ORB, TraceLevel_Debug,
++ "Received locate request id %d, on %s",
++ recv_buffer->message.u.locate_request.request_id,
++ recv_buffer->message.u.locate_request.object_key._buffer);
++ /* Find the POA for this incoming request */
++ poa = ORBit_find_POA_for_locate_request((PortableServer_POA)orb->root_poa, recv_buffer);
++
++ if(poa) {
++ /* Object found, reply with "Object Here" */
++ send_buffer = giop_send_locate_reply_buffer_use(connection,
++ recv_buffer->message.u.locate_request.request_id,
++ GIOP_OBJECT_HERE);
++ giop_send_buffer_write(send_buffer);
++ giop_send_buffer_unuse(send_buffer);
++ } else {
++ /* Object not found, reply with "Unknown Object" */
++ send_buffer = giop_send_locate_reply_buffer_use(connection,
++ recv_buffer->message.u.locate_request.request_id,
++ GIOP_UNKNOWN_OBJECT);
++ giop_send_buffer_write(send_buffer);
++ giop_send_buffer_unuse(send_buffer);
++ }
++
++ giop_recv_buffer_unuse(recv_buffer);
++}
++
++static void
++ORBit_handle_incoming_message(GIOPRecvBuffer *recv_buffer)
++{
++ GIOPConnection *connection;
++
++ g_assert(recv_buffer);
++
++ connection = GIOP_MESSAGE_BUFFER(recv_buffer)->connection;
++ g_return_if_fail(connection != NULL);
++
++ switch(GIOP_MESSAGE_BUFFER(recv_buffer)->message_header.message_type) {
++ case GIOP_REQUEST:
++ ORBit_handle_incoming_request(recv_buffer);
++ break;
++ case GIOP_LOCATEREQUEST:
++ ORBit_handle_incoming_locate_request(recv_buffer);
++ break;
++ case GIOP_CLOSECONNECTION:
++ /* Lame hack - need to do this in a manner that isn't
++ IIOP-specific */
++ giop_recv_buffer_unuse(recv_buffer);
++ giop_main_handle_connection_exception(connection);
++ break;
++ case GIOP_REPLY:
++ /* the above comment probably applies here also... */
++ giop_received_list_push(recv_buffer);
++ break;
++ default:
++ g_warning("discarding message type %d (id possibly %d)",
++ GIOP_MESSAGE_BUFFER(recv_buffer)->message_header.message_type,
++ GIOP_MESSAGE_BUFFER(recv_buffer)->message_header.message_type?recv_buffer->message.u.reply.request_id:recv_buffer->message.u.request.request_id);
++ break;
++ }
++}
++
++static PortableServer_POA
++ORBit_find_POA_for_request(PortableServer_POA poa,
++ GIOPRecvBuffer *recv_buffer)
++{
++ return ORBit_POA_find_POA_for_object_key(poa,
++ &recv_buffer->message.u.request.object_key);
++}
++
++static PortableServer_POA
++ORBit_find_POA_for_locate_request(PortableServer_POA poa,
++ GIOPRecvBuffer *recv_buffer)
++{
++ return ORBit_POA_find_POA_for_object_key(poa,
++ &recv_buffer->message.u.locate_request.object_key);
++}
++
++void
++ORBit_set_request_validation_handler(ORBit_request_validate validator)
++{
++ ORBIT_request_validator = validator;
++}
+diff -urN linux-2.4.1/net/korbit/orb/typecode.c linux-2.4.1-korbit/net/korbit/orb/typecode.c
+--- linux-2.4.1/net/korbit/orb/typecode.c Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/orb/typecode.c Thu Feb 1 11:47:14 2001
+@@ -0,0 +1,104 @@
++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
++
++/*
++ * ORBit: A CORBA v2.2 ORB
++ *
++ * Copyright (C) 1998 Richard H. Porter, Red Hat Software
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Library General Public
++ * License as published by the Free Software Foundation; either
++ * version 2 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Library General Public License for more details.
++ *
++ * You should have received a copy of the GNU Library General Public
++ * License along with this library; if not, write to the Free
++ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Author: Dick Porter <dick@cymru.net>
++ * Elliot Lee <sopwith@cuc.edu>
++ *
++ */
++
++#include "orbit.h"
++#include "orbit_typecode.h"
++
++const struct CORBA_TypeCode_struct TC_null_struct=
++ {{{(ORBit_RootObject_Interface *)&ORBit_TypeCode_epv, CORBA_FALSE, -1}, ORBIT_PSEUDO_TYPECODE}, CORBA_tk_null, "null", "", 0, 0, NULL, NULL, NULL, NULL, -1, 0, 0, 0};
++const struct CORBA_TypeCode_struct TC_void_struct=
++ {{{(ORBit_RootObject_Interface *)&ORBit_TypeCode_epv, CORBA_FALSE, -1}, ORBIT_PSEUDO_TYPECODE}, CORBA_tk_void, "void", "", 0, 0, NULL, NULL, NULL, NULL, -1, 0, 0, 0};
++const struct CORBA_TypeCode_struct TC_short_struct=
++ {{{(ORBit_RootObject_Interface *)&ORBit_TypeCode_epv, CORBA_FALSE, -1}, ORBIT_PSEUDO_TYPECODE}, CORBA_tk_short, "short", "", 0, 0, NULL, NULL, NULL, NULL, -1, 0, 0, 0};
++const struct CORBA_TypeCode_struct TC_long_struct=
++ {{{(ORBit_RootObject_Interface *)&ORBit_TypeCode_epv, CORBA_FALSE, -1}, ORBIT_PSEUDO_TYPECODE}, CORBA_tk_long, "long", "", 0, 0, NULL, NULL, NULL, NULL, -1, 0, 0, 0};
++const struct CORBA_TypeCode_struct TC_longlong_struct=
++ {{{(ORBit_RootObject_Interface *)&ORBit_TypeCode_epv, CORBA_FALSE, -1}, ORBIT_PSEUDO_TYPECODE}, CORBA_tk_longlong, "long long", "", 0, 0, NULL, NULL, NULL, NULL, -1, 0, 0, 0};
++const struct CORBA_TypeCode_struct TC_ushort_struct=
++ {{{(ORBit_RootObject_Interface *)&ORBit_TypeCode_epv, CORBA_FALSE, -1}, ORBIT_PSEUDO_TYPECODE}, CORBA_tk_ushort, "unsigned short", "", 0, 0, NULL, NULL, NULL, NULL, -1, 0, 0, 0};
++const struct CORBA_TypeCode_struct TC_ulong_struct=
++ {{{(ORBit_RootObject_Interface *)&ORBit_TypeCode_epv, CORBA_FALSE, -1}, ORBIT_PSEUDO_TYPECODE}, CORBA_tk_ulong, "unsigned long", "", 0, 0, NULL, NULL, NULL, NULL, -1, 0, 0, 0};
++const struct CORBA_TypeCode_struct TC_ulonglong_struct=
++ {{{(ORBit_RootObject_Interface *)&ORBit_TypeCode_epv, CORBA_FALSE, -1}, ORBIT_PSEUDO_TYPECODE}, CORBA_tk_ulonglong, "unsigned long long", "", 0, 0, NULL, NULL, NULL, NULL, -1, 0, 0, 0};
++const struct CORBA_TypeCode_struct TC_float_struct=
++ {{{(ORBit_RootObject_Interface *)&ORBit_TypeCode_epv, CORBA_FALSE, -1}, ORBIT_PSEUDO_TYPECODE}, CORBA_tk_float, "float", "", 0, 0, NULL, NULL, NULL, NULL, -1, 0, 0, 0};
++const struct CORBA_TypeCode_struct TC_double_struct=
++ {{{(ORBit_RootObject_Interface *)&ORBit_TypeCode_epv, CORBA_FALSE, -1}, ORBIT_PSEUDO_TYPECODE}, CORBA_tk_double, "double", "", 0, 0, NULL, NULL, NULL, NULL, -1, 0, 0, 0};
++const struct CORBA_TypeCode_struct TC_longdouble_struct=
++ {{{(ORBit_RootObject_Interface *)&ORBit_TypeCode_epv, CORBA_FALSE, -1}, ORBIT_PSEUDO_TYPECODE}, CORBA_tk_longdouble, "long double", "", 0, 0, NULL, NULL, NULL, NULL, -1, 0, 0, 0};
++const struct CORBA_TypeCode_struct TC_boolean_struct=
++ {{{(ORBit_RootObject_Interface *)&ORBit_TypeCode_epv, CORBA_FALSE, -1}, ORBIT_PSEUDO_TYPECODE}, CORBA_tk_boolean, "boolean", "", 0, 0, NULL, NULL, NULL, NULL, -1, 0, 0, 0};
++const struct CORBA_TypeCode_struct TC_char_struct=
++ {{{(ORBit_RootObject_Interface *)&ORBit_TypeCode_epv, CORBA_FALSE, -1}, ORBIT_PSEUDO_TYPECODE}, CORBA_tk_char, "char", "", 0, 0, NULL, NULL, NULL, NULL, -1, 0, 0, 0};
++const struct CORBA_TypeCode_struct TC_wchar_struct=
++ {{{(ORBit_RootObject_Interface *)&ORBit_TypeCode_epv, CORBA_FALSE, -1}, ORBIT_PSEUDO_TYPECODE}, CORBA_tk_wchar, "wide char", "", 0, 0, NULL, NULL, NULL, NULL, -1, 0, 0, 0};
++const struct CORBA_TypeCode_struct TC_octet_struct=
++ {{{(ORBit_RootObject_Interface *)&ORBit_TypeCode_epv, CORBA_FALSE, -1}, ORBIT_PSEUDO_TYPECODE}, CORBA_tk_octet, "octet", "", 0, 0, NULL, NULL, NULL, NULL, -1, 0, 0, 0};
++const struct CORBA_TypeCode_struct TC_any_struct=
++ {{{(ORBit_RootObject_Interface *)&ORBit_TypeCode_epv, CORBA_FALSE, -1}, ORBIT_PSEUDO_TYPECODE}, CORBA_tk_any, "any", "", 0, 0, NULL, NULL, NULL, NULL, -1, 0, 0, 0};
++const struct CORBA_TypeCode_struct TC_TypeCode_struct=
++ {{{(ORBit_RootObject_Interface *)&ORBit_TypeCode_epv, CORBA_FALSE, -1}, ORBIT_PSEUDO_TYPECODE}, CORBA_tk_TypeCode, "TypeCode", "", 0, 0, NULL, NULL, NULL, NULL, -1, 0, 0, 0};
++const struct CORBA_TypeCode_struct TC_Principal_struct=
++ {{{(ORBit_RootObject_Interface *)&ORBit_TypeCode_epv, CORBA_FALSE, -1}, ORBIT_PSEUDO_TYPECODE}, CORBA_tk_Principal, "Principal", "", 0, 0, NULL, NULL, NULL, NULL, -1, 0, 0, 0};
++const struct CORBA_TypeCode_struct TC_Object_struct=
++ {{{(ORBit_RootObject_Interface *)&ORBit_TypeCode_epv, CORBA_FALSE, -1}, ORBIT_PSEUDO_TYPECODE}, CORBA_tk_objref, "Object Reference", "", 0, 0, NULL, NULL, NULL, NULL, -1, 0, 0, 0};
++const struct CORBA_TypeCode_struct TC_string_struct=
++ {{{(ORBit_RootObject_Interface *)&ORBit_TypeCode_epv, CORBA_FALSE, -1}, ORBIT_PSEUDO_TYPECODE}, CORBA_tk_string, "string", "", 0, 0, NULL, NULL, NULL, NULL, -1, 0, 0, 0};
++const struct CORBA_TypeCode_struct TC_wstring_struct=
++ {{{(ORBit_RootObject_Interface *)&ORBit_TypeCode_epv, CORBA_FALSE, -1}, ORBIT_PSEUDO_TYPECODE}, CORBA_tk_wstring, "wide string", "", 0, 0, NULL, NULL, NULL, NULL, -1, 0, 0, 0};
++const struct CORBA_TypeCode_struct TC_CORBA_NamedValue_struct=
++ {{{(ORBit_RootObject_Interface *)&ORBit_TypeCode_epv, CORBA_FALSE, -1}, ORBIT_PSEUDO_TYPECODE}, CORBA_tk_struct, "CORBA NamedValue", "", 0, 0, NULL, NULL, NULL, NULL, -1, 0, 0, 0};
++
++static const CORBA_TypeCode anon_subtypes_array7[] =
++{(CORBA_TypeCode) & TC_CORBA_string_struct};
++
++#if (TC_IMPL_TC_CORBA_Identifier_0 == '/')
++const struct CORBA_TypeCode_struct TC_CORBA_Identifier_struct =
++{
++ {
++ {(ORBit_RootObject_Interface *) & ORBit_TypeCode_epv, TRUE, -1}, ORBIT_PSEUDO_TYPECODE},
++ CORBA_tk_alias, "Identifier", "IDL:omg.org/CORBA/Identifier:1.0",
++ 0, 1,
++ NULL,
++ (CORBA_TypeCode *) anon_subtypes_array7,
++ NULL,
++ CORBA_OBJECT_NIL, 0, -1, 0, 0
++};
++#endif
++
++#if (TC_IMPL_TC_CORBA_RepositoryId_0 == '/')
++const struct CORBA_TypeCode_struct TC_CORBA_RepositoryId_struct =
++{
++ {
++ {(ORBit_RootObject_Interface *) & ORBit_TypeCode_epv, TRUE, -1}, ORBIT_PSEUDO_TYPECODE},
++ CORBA_tk_alias, "RepositoryId", "IDL:omg.org/CORBA/RepositoryId:1.0",
++ 0, 1,
++ NULL,
++ (CORBA_TypeCode *) anon_subtypes_array7,
++ NULL,
++ CORBA_OBJECT_NIL, 0, -1, 0, 0
++};
++#endif
+diff -urN linux-2.4.1/net/korbit/orb/typecode.h linux-2.4.1-korbit/net/korbit/orb/typecode.h
+--- linux-2.4.1/net/korbit/orb/typecode.h Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/orb/typecode.h Thu Feb 1 11:47:14 2001
+@@ -0,0 +1,31 @@
++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
++
++/*
++ * ORBit: A CORBA v2.2 ORB
++ *
++ * Copyright (C) 1998 Richard H. Porter
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Library General Public
++ * License as published by the Free Software Foundation; either
++ * version 2 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Library General Public License for more details.
++ *
++ * You should have received a copy of the GNU Library General Public
++ * License along with this library; if not, write to the Free
++ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Author: Dick Porter <dick@cymru.net>
++ *
++ */
++
++#ifndef _ORBIT_TYPECODE_H_
++#define _ORBIT_TYPECODE_H_
++
++#include "orbit_types.h"
++
++#endif /* !_ORBIT_TYPECODE_H_ */
+diff -urN linux-2.4.1/net/korbit/sup/CVS/Entries linux-2.4.1-korbit/net/korbit/sup/CVS/Entries
+--- linux-2.4.1/net/korbit/sup/CVS/Entries Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/sup/CVS/Entries Thu Feb 1 11:47:15 2001
+@@ -0,0 +1 @@
++D
+diff -urN linux-2.4.1/net/korbit/sup/CVS/Repository linux-2.4.1-korbit/net/korbit/sup/CVS/Repository
+--- linux-2.4.1/net/korbit/sup/CVS/Repository Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/sup/CVS/Repository Thu Feb 1 11:47:15 2001
+@@ -0,0 +1 @@
++/cvsroot/korbit/linux/net/korbit/sup
+diff -urN linux-2.4.1/net/korbit/sup/CVS/Root linux-2.4.1-korbit/net/korbit/sup/CVS/Root
+--- linux-2.4.1/net/korbit/sup/CVS/Root Thu Jan 1 03:00:00 1970
++++ linux-2.4.1-korbit/net/korbit/sup/CVS/Root Thu Feb 1 11:47:15 2001
+@@ -0,0 +1 @@
++vraalsen@cvs.korbit.sourceforge.net:/cvsroot/korbit
diff --git a/fs/libmysqlfs.c b/fs/libmysqlfs.c
new file mode 100644
index 00000000000..fde325c3c42
--- /dev/null
+++ b/fs/libmysqlfs.c
@@ -0,0 +1,151 @@
+/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include "libmysqlfs.h"
+
+int search_and_replace(char *search, char* replace, char* string)
+{
+ char buff[1024];
+ int found=0;
+ char *ptr1;
+ const char *ptr2=buff;
+ char *strptr=string;
+
+ DBUG_ENTER("search_and_replace");
+ DBUG_PRINT("enter",("search: '%s' replace:'%s' string:'%s'",search,replace,string));
+ strcpy(buff,string);
+ while(ptr1=strstr(ptr2,search))
+ {
+ strncpy(strptr,ptr2,ptr1-buff);
+ strptr+=ptr1-buff;
+ ptr2+=ptr1-buff+strlen(search);
+ strcpy(strptr,replace);
+ strptr+=strlen(replace);
+ found++;
+ }
+ DBUG_RETURN(found);
+}
+
+int show_functions(char *b, function_type type)
+{
+ int i=0,j=0;
+ struct func_st func;
+ DBUG_ENTER("show_functions");
+ get_dynamic(&functions_array,(gptr)&func,i);
+ while(func.length) {
+ if (func.type == type)
+ strcpy(&b[j++*BUFLEN],func.filename);
+ get_dynamic(&functions_array,(gptr)&func,++i);
+ }
+ DBUG_RETURN(j);
+}
+
+struct func_st * check_if_function(char *name, function_type type)
+{
+ int pathlen;
+ int j,i=0, len;
+ static struct func_st function;
+ char buffer[BUFLEN];
+
+ DBUG_ENTER("check_if_function");
+ DBUG_PRINT("enter",("name: '%s' type: '%d'", name, type));
+ pathlen=strlen(name);
+
+ /* We try to compare last element in path to function names */
+ get_dynamic(&functions_array,(gptr)&function,i);
+ while(function.length) {
+ function.continuous ?
+ (j=!strncasecmp(function.filename, name, function.length))
+ : (j=!strcasecmp(function.filename,name));
+ if(j) { /* This happens when function was matched */
+ DBUG_PRINT("info",("Function %s detected!",function.filename));
+ break;
+ }
+ get_dynamic(&functions_array,(gptr)&function,++i);
+ }
+
+ /* Copy path to buffer and trip function name (if found) from it */
+ if(function.length != 0)
+ {
+ DBUG_RETURN(&function);
+ } else {
+ DBUG_RETURN(0);
+ }
+}
+
+/*
+ * parse - splits "path" into different variables
+ * in way "/server/database/table/(field|key)/(value|function)". If path is shorter,
+ * then other fields will be NULL. If path is longer than four levels or
+ * shorter than one level, FS_NOTEXIST is returned.
+ */
+int parse(const char * path, char *server, char * database, char *table,
+ char* field, char* value, struct func_st **funce)
+{
+ char buffer[BUFLEN];
+ char *p=buffer;
+ char *x;
+ int len;
+
+ DBUG_ENTER("parse");
+ DBUG_PRINT("enter",("path: '%s'", path));
+
+ *server=*database=*table=*field=*value='\0';
+
+ /* Search for first slash and drop it */
+ strcpy(buffer,path);
+ x=strtok_r(p,"/",&p);
+ if(x)
+ {
+ strcpy(server,x); /* First argument is server name */
+ if(*p)
+ strcpy(database,strtok_r(p,"/",&p)); /* Second is database */
+ if(p && *p)
+ strcpy(table ,strtok_r(p,"/",&p)); /* Third is table name */
+ if(p && *p)
+ strcpy(field ,strtok_r(p,"/",&p)); /* Fourth is field or key name */
+ if(p && *p)
+ strcpy(value ,strtok_r(p,"/",&p)); /* Fifth is field/key value or function */
+ }
+
+ /* We have to find if last argument is function,
+ * In which case we clear it
+ */
+ if(*value) {
+ *funce=check_if_function(value,VALUE_FUNCTION);
+ if(*funce) *value='\0';
+ } else if (*field) {
+ *funce=check_if_function(field,FIELD_FUNCTION);
+ if(*funce) *field='\0';
+ } else if (*table) {
+ *funce=check_if_function(table,TABLE_FUNCTION);
+ if(*funce) *table='\0';
+ } else if (*database) {
+ *funce=check_if_function(database,DATABASE_FUNCTION);
+ if(*funce) *database='\0';
+ } else if (*server) {
+ *funce=check_if_function(server,SERVER_FUNCTION);
+ if(*funce) *server='\0';
+ } else
+ *funce=NULL;
+
+ DBUG_PRINT("info",("path: '%s', server: '%s', db: '%s', table: '%s', field: '%s', value: '%s', function: '%x'",
+ buffer, server, database, table, field, value, funce ));
+ if(p && *p) /* Something is in buffer - too deep in levels */
+ DBUG_RETURN(-1)
+ else
+ DBUG_RETURN(0)
+}
diff --git a/fs/libmysqlfs.h b/fs/libmysqlfs.h
new file mode 100644
index 00000000000..0e95daaa791
--- /dev/null
+++ b/fs/libmysqlfs.h
@@ -0,0 +1,81 @@
+/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include "CorbaFS.h"
+
+#include <my_global.h>
+#include <my_sys.h>
+#include <m_string.h>
+#include <m_ctype.h>
+#include "mysql.h"
+
+#define BUFLEN 1024
+#define MAXDIRS 1024
+
+typedef enum {
+ FUNC_NONE,
+ FUNC_SERVER_UPTIME,
+ FUNC_SERVER_THREADS,
+ FUNC_SERVER_VERSION,
+ FUNC_DATABASE_CREATED,
+ FUNC_TABLE_COUNT,
+ FUNC_TABLE_CREATED,
+ FUNC_FIELD_LENGTH,
+ FUNC_KEY_AVG,
+ FUNC_KEY_SUM,
+ FUNC_KEY_MAX,
+ FUNC_KEY_MIN
+} func_enum;
+
+
+typedef enum {
+ NONE_FUNCTION,
+ ROOT_FUNCTION,
+ SERVER_FUNCTION,
+ DATABASE_FUNCTION,
+ TABLE_FUNCTION,
+ KEY_FUNCTION,
+ FIELD_FUNCTION,
+ VALUE_FUNCTION
+} function_type;
+
+struct func_st {
+ char type_s[20];
+ char filename[20];
+ char function[80];
+ function_type type;
+ int length;
+ my_bool continuous;
+} ;
+
+
+int parse(const char* path,
+ char* root,
+ char* database,
+ char* table,
+ char* key,
+ char* field,
+ struct func_st **func
+);
+
+gptr db_load_functions();
+int db_function(char *b,const char *server, const char *database,const char *table,const char *field,
+ const char *value, const char *path, struct func_st *function);
+int fix_filenames(char *buf);
+
+DYNAMIC_ARRAY functions_array;
+
+
diff --git a/fs/my.cnf b/fs/my.cnf
new file mode 100644
index 00000000000..e70f2c30cbf
--- /dev/null
+++ b/fs/my.cnf
@@ -0,0 +1,5 @@
+[mysqlcorbafs]
+socket=/var/lib/mysql/mysql.sock
+host=127.0.0.1
+user=root
+#password=xxxxxx
diff --git a/fs/mysqlcorbafs.c b/fs/mysqlcorbafs.c
new file mode 100644
index 00000000000..8943c00ed25
--- /dev/null
+++ b/fs/mysqlcorbafs.c
@@ -0,0 +1,991 @@
+/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+/*
+ *
+ * fsck.mysql
+ */
+
+#include "libmysqlfs.h"
+#include "mysqlcorbafs.h"
+#include <getopt.h>
+#define MAXPATHLEN 256
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <dirent.h>
+
+#include <my_sys.h>
+static long inodeNum;
+
+extern DYNAMIC_ARRAY functions_array;
+enum options {OPT_FTB=256, OPT_LTB, OPT_ENC, OPT_O_ENC, OPT_ESC, OPT_KEYWORDS,
+ OPT_LOCKS, OPT_DROP, OPT_OPTIMIZE, OPT_DELAYED, OPT_TABLES,
+ OPT_CHARSETS_DIR, OPT_DEFAULT_CHARSET};
+
+CHANGEABLE_VAR changeable_vars[] = {
+ { "max_allowed_packet", (long*) &max_allowed_packet,24*1024*1024,4096,
+ 24*1024L*1024L,MALLOC_OVERHEAD,1024},
+ { "net_buffer_length", (long*) &net_buffer_length,1024*1024L-1025,4096,
+ 24*1024L*1024L,MALLOC_OVERHEAD,1024},
+ { 0, 0, 0, 0, 0, 0, 0}
+};
+
+CORBA_ORB orb;
+PortableServer_POA poa;
+CORBA_Environment *ev;
+PortableServer_ObjectId *objid;
+static my_bool verbose=0,opt_compress=0,extended_insert=0, lock_tables=0,
+ opt_quoted=0, opt_lock=0, opt_delayed=0, ignore_errors=0;
+
+gptr fptr;
+
+static const char *load_default_groups[]= { "mysqlcorbafs","client",0 };
+static char *default_charset, *current_host, *current_user, *opt_password,
+ *path,*fields_terminated=0, *lines_terminated=0, *enclosed=0,
+ *opt_enclosed=0, *escaped=0;
+
+static struct option long_options[] =
+{
+ {"add-locks", no_argument, 0,OPT_LOCKS},
+ {"character-sets-dir",required_argument,0, OPT_CHARSETS_DIR},
+ {"compress", no_argument, 0, 'C'},
+ {"database",required_argument, 0, 'D'},
+ {"debug",optional_argument, 0, '#'},
+ {"default-character-set", required_argument, 0, OPT_DEFAULT_CHARSET},
+ {"delayed-insert",no_argument, 0, OPT_DELAYED},
+ {"fields-terminated-by", required_argument, 0, (int) OPT_FTB},
+ {"fields-enclosed-by", required_argument,0, (int) OPT_ENC},
+ {"fields-optionally-enclosed-by", required_argument, 0, (int) OPT_O_ENC},
+ {"fields-escaped-by", required_argument,0, (int) OPT_ESC},
+ {"functions",required_argument, 0, 'f'},
+ {"help", no_argument, 0,'?'},
+ {"host", required_argument,0, 'h'},
+ {"lines-terminated-by", required_argument, 0, (int) OPT_LTB},
+ {"lock-tables", no_argument, 0, 'l'},
+ {"no-data", no_argument, 0, 'd'},
+ {"password", optional_argument, 0, 'p'},
+#ifdef __WIN__
+ {"pipe",no_argument,0, 'W'},
+#endif
+ {"port", required_argument,0, 'P'},
+// {"quick", no_argument,0, 'q'},
+ {"quote-names",no_argument,0, 'Q'},
+ {"set-variable",required_argument,0, 'O'},
+ {"socket", required_argument,0, 'S'},
+#include "sslopt-longopts.h"
+#ifndef DONT_ALLOW_USER_CHANGE
+ {"user", required_argument,0, 'u'},
+#endif
+ {"verbose", no_argument,0, 'v'},
+ {"version", no_argument,0, 'V'},
+ {0, 0, 0, 0}
+};
+
+
+/*
+void
+print_table_data(MYSQL_RES *result)
+{
+ String separator(256);
+ MYSQL_ROW cur;
+ MYSQL_FIELD *field;
+ bool *num_flag;
+
+ num_flag=(bool*) my_alloca(sizeof(bool)*mysql_num_fields(result));
+ if (info_flag)
+ {
+ print_field_types(result);
+ mysql_field_seek(result,0);
+ }
+ separator.copy("+",1);
+ while ((field = mysql_fetch_field(result)))
+ {
+ uint length=skip_column_names ? 0 : (uint) strlen(field->name);
+ if (quick)
+ length=max(length,field->length);
+ else
+ length=max(length,field->max_length);
+ if (length < 4 && !IS_NOT_NULL(field->flags))
+ length=4; // Room for "NULL"
+ field->max_length=length+1;
+ separator.fill(separator.length()+length+2,'-');
+ separator.append('+');
+ }
+ tee_puts(separator.c_ptr(), PAGER);
+ if (!skip_column_names)
+ {
+ mysql_field_seek(result,0);
+ (void) tee_fputs("|", PAGER);
+ for (uint off=0; (field = mysql_fetch_field(result)) ; off++)
+ {
+ tee_fprintf(PAGER, " %-*s|",min(field->max_length,MAX_COLUMN_LENGTH),
+ field->name);
+ num_flag[off]= IS_NUM(field->type);
+ }
+ (void) tee_fputs("\n", PAGER);
+ tee_puts(separator.c_ptr(), PAGER);
+ }
+
+ while ((cur = mysql_fetch_row(result)))
+ {
+ (void) tee_fputs("|", PAGER);
+ mysql_field_seek(result,0);
+ for (uint off=0 ; off < mysql_num_fields(result); off++)
+ {
+ const char *str=cur[off] ? cur[off] : "NULL";
+ field = mysql_fetch_field(result);
+ uint length=field->max_length;
+ if (length > MAX_COLUMN_LENGTH)
+ {
+ tee_fputs(str,PAGER); tee_fputs(" |",PAGER);
+ }
+ else
+ tee_fprintf(PAGER, num_flag[off] ? "%*s |" : " %-*s|",
+ length, str);
+ }
+ (void) tee_fputs("\n", PAGER);
+ }
+ tee_puts(separator.c_ptr(), PAGER);
+ my_afree((gptr) num_flag);
+}
+
+void
+print_table_data_html(MYSQL_RES *result)
+{
+ MYSQL_ROW cur;
+ MYSQL_FIELD *field;
+
+ mysql_field_seek(result,0);
+ (void) tee_fputs("<TABLE BORDER=1><TR>", PAGER);
+ if (!skip_column_names)
+ {
+ while((field = mysql_fetch_field(result)))
+ {
+ tee_fprintf(PAGER, "<TH>%s</TH>", (field->name ?
+ (field->name[0] ? field->name :
+ " &nbsp; ") : "NULL"));
+ }
+ (void) tee_fputs("</TR>", PAGER);
+ }
+ while ((cur = mysql_fetch_row(result)))
+ {
+ (void) tee_fputs("<TR>", PAGER);
+ for (uint i=0; i < mysql_num_fields(result); i++)
+ {
+ ulong *lengths=mysql_fetch_lengths(result);
+ (void) tee_fputs("<TD>", PAGER);
+ safe_put_field(cur[i],lengths[i]);
+ (void) tee_fputs("</TD>", PAGER);
+ }
+ (void) tee_fputs("</TR>", PAGER);
+ }
+ (void) tee_fputs("</TABLE>", PAGER);
+}
+
+
+void
+print_table_data_xml(MYSQL_RES *result)
+{
+ MYSQL_ROW cur;
+ MYSQL_FIELD *fields;
+
+ mysql_field_seek(result,0);
+
+ char *statement;
+ statement=(char*) my_malloc(strlen(glob_buffer.ptr())*5+1, MYF(MY_WME));
+ xmlencode(statement, (char*) glob_buffer.ptr());
+
+ (void) my_chomp(strend(statement));
+
+ tee_fprintf(PAGER,"<?xml version=\"1.0\"?>\n\n<resultset statement=\"%s\">", statement);
+
+ my_free(statement,MYF(MY_ALLOW_ZERO_PTR));
+
+ fields = mysql_fetch_fields(result);
+
+ while ((cur = mysql_fetch_row(result)))
+ {
+ (void) tee_fputs("\n <row>\n", PAGER);
+ for (uint i=0; i < mysql_num_fields(result); i++)
+ {
+ char *data;
+ ulong *lengths=mysql_fetch_lengths(result);
+ data=(char*) my_malloc(lengths[i]*5+1, MYF(MY_WME));
+ tee_fprintf(PAGER, "\t<%s>", (fields[i].name ?
+ (fields[i].name[0] ? fields[i].name :
+ " &nbsp; ") : "NULL"));
+ xmlencode(data, cur[i]);
+ safe_put_field(data, strlen(data));
+ tee_fprintf(PAGER, "</%s>\n", (fields[i].name ?
+ (fields[i].name[0] ? fields[i].name :
+ " &nbsp; ") : "NULL"));
+ my_free(data,MYF(MY_ALLOW_ZERO_PTR));
+ }
+ (void) tee_fputs(" </row>\n", PAGER);
+ }
+ (void) tee_fputs("</resultset>\n", PAGER);
+}
+
+
+void
+print_table_data_vertically(MYSQL_RES *result)
+{
+ MYSQL_ROW cur;
+ uint max_length=0;
+ MYSQL_FIELD *field;
+
+ while ((field = mysql_fetch_field(result)))
+ {
+ uint length=(uint) strlen(field->name);
+ if (length > max_length)
+ max_length= length;
+ field->max_length=length;
+ }
+
+ mysql_field_seek(result,0);
+ for (uint row_count=1; (cur= mysql_fetch_row(result)); row_count++)
+ {
+ mysql_field_seek(result,0);
+ tee_fprintf(PAGER,
+ "*************************** %d. row ***************************\n", row_count);
+ for (uint off=0; off < mysql_num_fields(result); off++)
+ {
+ field= mysql_fetch_field(result);
+ tee_fprintf(PAGER, "%*s: ",(int) max_length,field->name);
+ tee_fprintf(PAGER, "%s\n",cur[off] ? (char*) cur[off] : "NULL");
+ }
+ }
+}
+
+
+
+*/
+
+
+
+static my_bool test_if_special_chars(const char *str)
+{
+ for ( ; *str ; str++)
+ if (!isvar(*str) && *str != '$')
+ return 1;
+ return 0;
+} /* test_if_special_chars */
+
+char *quote_name(char *name, char *buff)
+{
+ char *end;
+ DBUG_ENTER("quote_name");
+ if (!opt_quoted && !test_if_special_chars(name))
+ return name;
+ buff[0]=QUOTE_CHAR;
+ *end=strmov(buff+1,name);
+ end[0]=QUOTE_CHAR;
+ end[1]=0;
+ DBUG_RETURN(buff);
+} /* quote_name */
+
+/*
+ * Allow the user to specify field terminator strings like:
+ * "'", "\", "\\" (escaped backslash), "\t" (tab), "\n" (newline)
+ * This is done by doubleing ' and add a end -\ if needed to avoid
+ * syntax errors from the SQL parser.
+ */
+
+char *field_escape(char *to,const char *from,uint length)
+{
+ const char *end;
+ uint end_backslashes=0;
+ DBUG_ENTER("field_escape");
+
+ {
+ *to++= *from;
+ if (*from == '\\')
+ end_backslashes^=1; /* find odd number of backslashes */
+ else {
+ if (*from == '\'' && !end_backslashes)
+ *to++= *from; /* We want a duplicate of "'" for MySQL */
+ end_backslashes=0;
+ }
+ }
+ /* Add missing backslashes if user has specified odd number of backs.*/
+ if (end_backslashes)
+ *to++= '\\';
+ DBUG_RETURN(to);
+} /* field_escape */
+
+void safe_exit(int error)
+{
+ if (!first_error)
+ first_error= error;
+ if (ignore_errors)
+ return;
+ if (sock)
+ mysql_close(sock);
+ exit(error);
+}
+/* safe_exit */
+
+
+/*
+ * ** DBerror -- prints mysql error message and exits the program.
+ */
+void DBerror(MYSQL *mysql, const char *when)
+{
+ DBUG_ENTER("DBerror");
+ my_printf_error(0,"Got error: %d: %s %s", MYF(0),
+ mysql_errno(mysql), mysql_error(mysql), when);
+ safe_exit(EX_MYSQLERR);
+ DBUG_VOID_RETURN;
+} /* DBerror */
+
+void print_version(void)
+{
+ printf("%s Ver %s Distrib %s, for %s (%s)\n",my_progname,CORBAFS_VERSION,
+ MYSQL_SERVER_VERSION,SYSTEM_TYPE,MACHINE_TYPE);
+} /* print_version */
+
+void usage(void)
+{
+ uint i;
+ print_version();
+ puts("By Tõnu Samuel. Some code is partially from other geeks around the world");
+ puts("This software comes with ABSOLUTELY NO WARRANTY. This is free software,\nand you are welcome to modify and redistribute it under the GPL license\n");
+ puts("Dumping definition and data mysql database or table");
+ printf("Usage: %s [OPTIONS]\n", my_progname);
+ printf("\n\
+ -#, --debug=... Output debug log. Often this is 'd:t:o,filename`.\n\
+ --character-sets-dir=...\n\
+ Directory where character sets are\n\
+ -?, --help Display this help message and exit.\n\
+ -c, --complete-insert Use complete insert statements.\n\
+ -C, --compress Use compression in server/client protocol.\n\
+ --default-character-set=...\n\
+ Set the default character set\n\
+ -e, --extended-insert Allows utilization of the new, much faster\n\
+ INSERT syntax.\n\
+ --add-locks Add locks around insert statements.\n\
+ --allow-keywords Allow creation of column names that are keywords.\n\
+ --delayed-insert Insert rows with INSERT DELAYED.\n\
+ -f, --force Continue even if we get an sql-error.\n\
+ -h, --host=... Connect to host.\n");
+puts("\
+ -l, --lock-tables Lock all tables for read.\n\
+ -t, --no-create-info Don't write table creation info.\n\
+ -d, --no-data No row information.\n\
+ -O, --set-variable var=option\n\
+ give a variable a value. --help lists variables\n\
+ -p, --password[=...] Password to use when connecting to server.\n\
+ If password is not given it's solicited on the tty.\n");
+#ifdef __WIN__
+ puts("-W, --pipe Use named pipes to connect to server");
+#endif
+ printf("\
+ -P, --port=... Port number to use for connection.\n\
+ -q, --quick Don't buffer query, dump directly to stdout.\n\
+ -S, --socket=... Socket file to use for connection.\n\
+ --tables Overrides option --databases (-B).\n");
+#include "sslopt-usage.h"
+#ifndef DONT_ALLOW_USER_CHANGE
+ printf("\
+ -u, --user=# User for login if not current user.\n");
+#endif
+ printf("\
+ -v, --verbose Print info about the various stages.\n\
+ -V, --version Output version information and exit.\n\
+");
+ print_defaults("my",load_default_groups);
+
+ printf("\nPossible variables for option --set-variable (-O) are:\n");
+ for (i=0 ; changeable_vars[i].name ; i++)
+ printf("%-20s current value: %lu\n",
+ changeable_vars[i].name,
+ (ulong) *changeable_vars[i].varptr);
+} /* usage */
+
+
+
+static int get_options(int *argc,char ***argv)
+{
+ int c,option_index;
+ my_bool tty_password=0;
+ DBUG_ENTER("get_options");
+ load_defaults("my",load_default_groups,argc,argv);
+ set_all_changeable_vars(changeable_vars);
+ while ((c=getopt_long(*argc,*argv,"#::p::h:u:O:P:S:T:EBaAcCdefFlnqtvVw:?Ix",
+ long_options, &option_index)) != EOF)
+ {
+ switch(c) {
+ case 'e':
+ extended_insert=1;
+ break;
+ case OPT_DEFAULT_CHARSET:
+ default_charset= optarg;
+ break;
+ case OPT_CHARSETS_DIR:
+ charsets_dir= optarg;
+ break;
+
+ ignore_errors=1;
+ break;
+ case 'h':
+ my_free(current_host,MYF(MY_ALLOW_ZERO_PTR));
+ current_host=my_strdup(optarg,MYF(MY_WME));
+ break;
+#ifndef DONT_ALLOW_USER_CHANGE
+ case 'u':
+ current_user=optarg;
+ break;
+#endif
+ case 'O':
+ if (set_changeable_var(optarg, changeable_vars))
+ {
+ usage();
+ return(1);
+ }
+ break;
+ case 'p':
+ if (optarg)
+ {
+ char *start=optarg;
+ my_free(opt_password,MYF(MY_ALLOW_ZERO_PTR));
+ opt_password=my_strdup(optarg,MYF(MY_FAE));
+ while (*optarg) *optarg++= 'x'; /* Destroy argument */
+ if (*start)
+ start[1]=0; /* Cut length of argument */
+ } else
+ tty_password=1;
+ break;
+ case 'P':
+ opt_mysql_port= (unsigned int) atoi(optarg);
+ break;
+ case 'S':
+ opt_mysql_unix_port= optarg;
+ break;
+ case 'W':
+#ifdef __WIN__
+ opt_mysql_unix_port=MYSQL_NAMEDPIPE;
+#endif
+ break;
+ case 'T':
+ path= optarg;
+ break;
+ case '#':
+ DBUG_PUSH(optarg ? optarg : "d:t:o");
+ break;
+ case 'C':
+ opt_compress=1;
+ break;
+ case 'l': lock_tables=1; break;
+ case 'Q': opt_quoted=1; break;
+ case 'v': verbose=1; break;
+ case 'V': print_version(); exit(0);
+ default:
+ fprintf(stderr,"%s: Illegal option character '%c'\n",my_progname,opterr);
+ /* Fall throught */
+ case 'I':
+ case '?':
+ usage();
+ exit(0);
+ case (int) OPT_FTB:
+ fields_terminated= optarg;
+ break;
+ case (int) OPT_LTB:
+ lines_terminated= optarg;
+ break;
+ case (int) OPT_ENC:
+ enclosed= optarg;
+ break;
+ case (int) OPT_O_ENC:
+ opt_enclosed= optarg;
+ break;
+ case (int) OPT_ESC:
+ escaped= optarg;
+ break;
+ case (int) OPT_LOCKS:
+ opt_lock=1;
+ break;
+ case (int) OPT_OPTIMIZE:
+ extended_insert=opt_lock=lock_tables=1;
+ break;
+ case (int) OPT_DELAYED:
+ opt_delayed=1;
+ break;
+#include "sslopt-case.h"
+ }
+ }
+ if (opt_delayed)
+ opt_lock=0; /* Can't have lock with delayed */
+ if (!path && (enclosed || opt_enclosed || escaped || lines_terminated ||
+ fields_terminated))
+ {
+ fprintf(stderr, "%s: You must use option --tab with --fields-...\n", my_progname);
+ return(1);
+ }
+
+ if (enclosed && opt_enclosed)
+ {
+ fprintf(stderr, "%s: You can't use ..enclosed.. and ..optionally-enclosed.. at the same time.\n", my_progname);
+ return(1);
+ }
+ if (default_charset)
+ {
+ if (set_default_charset_by_name(default_charset, MYF(MY_WME)))
+ exit(1);
+ }
+ (*argc)-=optind;
+ (*argv)+=optind;
+ if (tty_password)
+ opt_password=get_tty_password(NullS);
+ DBUG_RETURN(0);
+} /* get_options */
+
+
+/*** epv structures ***/
+
+static PortableServer_ServantBase__epv impl_Inode_base_epv = {
+ NULL, /* _private data */
+ NULL, /* finalize routine */
+ NULL, /* default_POA routine */
+};
+static POA_CorbaFS_Inode__epv impl_Inode_epv = {
+ NULL, /* _private */
+ (gpointer) & impl_Inode_getStatus,
+ (gpointer) & impl_Inode_readpage,
+ (gpointer) & impl_Inode_release,
+
+};
+static PortableServer_ServantBase__epv impl_FileSystem_base_epv = {
+ NULL, /* _private data */
+ NULL, /* finalize routine */
+ NULL, /* default_POA routine */
+};
+static POA_CorbaFS_FileSystem__epv impl_FileSystem_epv = {
+ NULL, /* _private */
+ (gpointer) & impl_FileSystem_getInode,
+ (gpointer) & impl_FileSystem_readdir,
+ (gpointer) & impl_FileSystem_readlink,
+};
+
+/*** vepv structures ***/
+
+static POA_CorbaFS_Inode__vepv impl_Inode_vepv = {
+ &impl_Inode_base_epv,
+ &impl_Inode_epv,
+};
+static POA_CorbaFS_FileSystem__vepv impl_FileSystem_vepv = {
+ &impl_FileSystem_base_epv,
+ &impl_FileSystem_epv,
+};
+
+/*** Stub implementations ***/
+
+static CorbaFS_Inode
+impl_Inode__create(PortableServer_POA poa, CORBA_Environment * ev)
+{
+ CorbaFS_Inode retval;
+ impl_POA_CorbaFS_Inode *newservant;
+ PortableServer_ObjectId *objid;
+
+ DBUG_ENTER("impl_Inode__create");
+ newservant = g_new0(impl_POA_CorbaFS_Inode, 1);
+ newservant->servant.vepv = &impl_Inode_vepv;
+ newservant->poa = poa;
+ POA_CorbaFS_Inode__init((PortableServer_Servant) newservant, ev);
+ objid = PortableServer_POA_activate_object(poa, newservant, ev);
+ CORBA_free(objid);
+ retval = PortableServer_POA_servant_to_reference(poa, newservant, ev);
+
+ DBUG_RETURN(retval);
+}
+
+static void
+impl_Inode__destroy(impl_POA_CorbaFS_Inode * servant,
+ CORBA_Environment * ev)
+{
+ PortableServer_ObjectId *objid;
+
+ DBUG_ENTER("impl_Inode__destroy");
+ objid = PortableServer_POA_servant_to_id(servant->poa, servant, ev);
+ PortableServer_POA_deactivate_object(servant->poa, objid, ev);
+ CORBA_free(objid);
+
+ POA_CorbaFS_Inode__fini((PortableServer_Servant) servant, ev);
+ g_free(servant);
+ DBUG_VOID_RETURN;
+}
+
+static void
+impl_Inode_getStatus(impl_POA_CorbaFS_Inode * servant,
+ CORBA_unsigned_short * mode,
+ CORBA_unsigned_long * uid,
+ CORBA_unsigned_long * gid,
+ CORBA_unsigned_long * size,
+ CORBA_unsigned_long * inodeNum,
+ CORBA_unsigned_short * numLinks,
+ CORBA_long * atime,
+ CORBA_long * mtime,
+ CORBA_long * ctime, CORBA_Environment * ev)
+{
+ struct stat buf;
+ char
+ server[BUFLEN],
+ database[BUFLEN],
+ table[BUFLEN],
+ key[BUFLEN],
+ field[BUFLEN],
+ value[BUFLEN];
+
+ struct func_st *func;
+
+ DBUG_ENTER("impl_Inode_getStatus");
+ DBUG_PRINT("enter",("path: '%s', mode: '%o', uid: '%d', gid: '%d', size: '%d',
+ inodeNum: '%d', numLinks: '%d', atime: '%d',mtime: '%d', ctime: '%d'",
+ servant->path, mode, uid, gid, size, inodeNum, numLinks, atime, mtime, ctime));
+ DBUG_PRINT("info",("func: %x",&func));
+ if(parse(servant->path, server, database, table, field, value, &func)>0)
+ {
+ DBUG_PRINT("info",("ENOENT"));
+ *mode=0;
+ } else if (func != NULL){
+ DBUG_PRINT("info",("func: %x",&func));
+ DBUG_PRINT("info",("Argument is function at %x, returning S_IFREG",func));
+ *mode = S_IFREG; // File
+ } else if (*field){
+ DBUG_PRINT("info",("Argument is file, returning S_IFREG"));
+ *mode = S_IFREG; // File
+ } else {
+ DBUG_PRINT("info",("Argument is directory, returning S_IFDIR"));
+ *mode = S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH ; // Dir
+ }
+
+ *mode |= S_IRUSR | S_IRGRP | S_IROTH;
+ *uid = 0;
+ *gid = 0;
+ *size = 4096;
+ *inodeNum = servant->inodeNum;
+ *numLinks = 1;
+ *atime = 3;
+ *mtime = 2;
+ *ctime = 1;
+
+// lstat(servant->path, &buf);
+// *mode = buf.st_mode;
+/* *uid = buf.st_uid;
+ *gid = buf.st_gid;
+ *size = buf.st_size;
+ *inodeNum = buf.st_ino;
+ *numLinks = buf.st_nlink;
+ *atime = buf.st_atime;
+ *mtime = buf.st_mtime;
+ *ctime = buf.st_ctime;*/
+ DBUG_VOID_RETURN;
+}
+
+static void
+impl_Inode_readpage(impl_POA_CorbaFS_Inode * servant,
+ CorbaFS_Buffer ** buffer,
+ CORBA_long size,
+ CORBA_long offset, CORBA_Environment * ev)
+{
+ int type;
+ int fd = -1, c = 0;
+ int res;
+ char
+ server[BUFLEN],
+ database[BUFLEN],
+ table[BUFLEN],
+ key[BUFLEN],
+ field[BUFLEN],
+ value[BUFLEN];
+ struct func_st *func;
+
+ DBUG_ENTER("impl_Inode_readpage");
+ DBUG_PRINT("enter",("path: '%s'", servant->path));
+ *buffer = CorbaFS_Buffer__alloc();
+ (*buffer)->_maximum = size;
+ (*buffer)->_buffer = CORBA_octet_allocbuf(size);
+ printf("requested to read %d bytes\n",size);
+ memset((*buffer)->_buffer, size, 0);
+ type = parse(servant->path, server, database, table, field, value, &func);
+ if (func != NULL)
+ res=db_function((*buffer)->_buffer, server, database, table, field, value, servant->path, func);
+ else
+ res=db_show_field((*buffer)->_buffer, database, table, field, path, value);
+ if(res>0)
+ (*buffer)->_length = strlen((*buffer)->_buffer);
+ else
+ (*buffer)->_length = 0;
+/*
+ fd = open(servant->path, O_RDONLY);
+ printf("Inode_readpage : fd = %d\n", fd);
+ lseek(fd, offset, SEEK_SET);
+ c = read(fd, (*buffer)->_buffer, size);
+ printf("Inode_readpage : read %d bytes\n", c);
+ (*buffer)->_length = c;
+ close(fd);
+*/
+ DBUG_VOID_RETURN;
+}
+
+static void
+impl_Inode_release(impl_POA_CorbaFS_Inode * servant,
+ CORBA_Environment * ev)
+{
+ DBUG_ENTER("impl_Inode_readpage");
+ DBUG_PRINT("enter",("path: '%s'", servant->path));
+ DBUG_VOID_RETURN;
+}
+
+/*
+ * This function is called when we get mounted
+ */
+CorbaFS_FileSystem
+impl_FileSystem__create(PortableServer_POA poa,
+ CORBA_Environment * ev)
+{
+ CorbaFS_FileSystem retval;
+ impl_POA_CorbaFS_FileSystem *newservant;
+ PortableServer_ObjectId *objid;
+
+ DBUG_ENTER("impl_FileSystem__create");
+ newservant = g_new0(impl_POA_CorbaFS_FileSystem, 1);
+ newservant->servant.vepv = &impl_FileSystem_vepv;
+ newservant->poa = poa;
+ POA_CorbaFS_FileSystem__init((PortableServer_Servant) newservant, ev);
+ objid = PortableServer_POA_activate_object(poa, newservant, ev);
+ CORBA_free(objid);
+ retval = PortableServer_POA_servant_to_reference(poa, newservant, ev);
+
+ DBUG_RETURN(retval);
+}
+
+/*
+ * This function is called when we get unmounted
+ */
+static void
+impl_FileSystem__destroy(impl_POA_CorbaFS_FileSystem * servant,
+ CORBA_Environment * ev)
+{
+ PortableServer_ObjectId *objid;
+ DBUG_ENTER("impl_FileSystem__destroy");
+
+ objid = PortableServer_POA_servant_to_id(servant->poa, servant, ev);
+ PortableServer_POA_deactivate_object(servant->poa, objid, ev);
+ CORBA_free(objid);
+
+ POA_CorbaFS_FileSystem__fini((PortableServer_Servant) servant, ev);
+ g_free(servant);
+ DBUG_VOID_RETURN;
+}
+
+static CorbaFS_Inode
+impl_FileSystem_getInode(impl_POA_CorbaFS_FileSystem * servant,
+ CORBA_char * path, CORBA_Environment * ev)
+{
+ CorbaFS_Inode retval;
+ impl_POA_CorbaFS_Inode *inode;
+ char
+ database[BUFLEN],
+ table[BUFLEN],
+ key[BUFLEN],
+ field[BUFLEN];
+ char buffer[MAXDIRS][BUFLEN];
+ int c;
+
+ DBUG_ENTER("impl_FileSystem_getInode");
+ DBUG_PRINT("enter",("path: '%s'", path));
+
+ //FIXME: We should verify the existense of file/dir here
+ //
+ retval = impl_Inode__create(servant->poa, ev);
+ inode = PortableServer_POA_reference_to_servant( servant->poa, retval, ev );
+ inode->path = CORBA_string_dup(path);
+ //FIXME: inodeNum Generation goes here
+ //
+ inode->inodeNum= inodeNum++;
+#if 0
+ inode->mode = 0040777; /* world-readable directory */
+ inode->uid = 0;
+ inode->gid = 0;
+ inode->size = 4096;
+ inode->inodeNum = inodeNum++;
+ inode->numLinks = 1;
+ inode->atime = 0;
+ inode->mtime = 100;
+ inode->ctime = 10000;
+#endif
+ DBUG_RETURN(retval);
+}
+
+
+static CorbaFS_DirEntSeq *
+impl_FileSystem_readdir(impl_POA_CorbaFS_FileSystem * servant,
+ CORBA_char * path, CORBA_Environment * ev)
+{
+ CorbaFS_DirEntSeq *retval;
+ CorbaFS_dirent *dirent;
+
+ struct func_st *func;
+ int c, c2,i;
+ char
+ server[BUFLEN],
+ table[BUFLEN],
+ field[BUFLEN],
+ value[BUFLEN],
+ buffer[MAXDIRS][BUFLEN],
+ buffer2[MAXDIRS][BUFLEN],
+ database[BUFLEN];
+
+ DBUG_ENTER("impl_FileSystem_readdir");
+ DBUG_PRINT("enter",("path: '%s'", path));
+ retval = CorbaFS_DirEntSeq__alloc();
+ retval->_maximum = 0;
+ retval->_length = 0;
+
+ parse(path, server, database, table, field, value, &func);
+ if (func != NULL) {
+ c2 = db_function((char *)buffer, server, database, table, field, value, path, func);
+ } else if(!*server) {
+ c2 = db_show_servers(buffer2,MAXDIRS);
+ c = show_functions((char *)buffer, ROOT_FUNCTION);
+ } else if(!*database) {
+ c2 = db_show_databases(buffer2,MAXDIRS);
+ c = show_functions((char *)buffer, SERVER_FUNCTION);
+ } else if(!*table){
+ c2 = db_show_tables(buffer2, database);
+ c = show_functions((char *)buffer, DATABASE_FUNCTION);
+ } else if(!*field){
+ c2 = db_show_primary_keys(buffer2, database,table);
+ if(c2>=0) {
+ c = show_functions((char *)buffer, TABLE_FUNCTION);
+ }
+ } else {
+ c2 = db_show_fields(buffer2, database, table, field);
+ c = show_functions((char *)buffer, FIELD_FUNCTION);
+ c = show_functions((char *)buffer, KEY_FUNCTION);
+ }
+ if(c2 < 0)
+ c=c2=0; // Error occured in database routines
+
+ /* Allocate space to hold all found entries plus "." and ".." */
+ retval->_maximum = c + c2 + 2;
+ retval->_buffer = CORBA_sequence_CorbaFS_dirent_allocbuf(retval->_maximum) ;
+ dirent = retval->_buffer;
+
+ i = 0;
+ while (i < c) {
+ long inode = 123L;
+ dirent[i].inode = inode;
+ dirent[i].name = CORBA_string_dup(buffer[i]);
+ i++;
+ }
+ i = 0;
+ while (i < c2) {
+ long inode = 123L;
+ dirent[c+i].inode = inode;
+ dirent[c+i].name = CORBA_string_dup(buffer2[i]);
+ i++;
+ }
+ dirent[c+i].inode = 123L;
+ dirent[c+i].name = CORBA_string_dup(".");
+ i++;
+ dirent[c+i].inode = 123L;
+ dirent[c+i].name = CORBA_string_dup("..");
+
+ retval->_length = retval->_maximum;
+ DBUG_RETURN(retval);
+}
+
+static CORBA_char *
+impl_FileSystem_readlink(impl_POA_CorbaFS_FileSystem * servant,
+ CORBA_char * filename,
+ CORBA_Environment * ev)
+{
+ CORBA_char *retval = CORBA_OBJECT_NIL;
+ char tmp[MAXPATHLEN + 1];
+ int len;
+
+ DBUG_ENTER("impl_FileSystem_readlink");
+ DBUG_PRINT("enter",("path: '%s'", filename));
+
+/* len = readlink(filename, tmp, MAXPATHLEN);
+ if (len != -1)
+ {
+ tmp[len] = '\0';
+ retval = CORBA_string_dup(tmp);
+ }
+
+ printf("%s\n", retval);
+ */
+ DBUG_RETURN(retval);
+}
+
+int fix_filenames(char *buf)
+{
+ int i;
+ for(i=0; i<strlen(buf);i++)
+ if(buf[i]=='/')
+ buf[i]='_';
+}
+
+int main(int argc, char *argv[]) {
+ CorbaFS_FileSystem fs;
+ impl_POA_CorbaFS_FileSystem *fs_impl;
+ FILE *f;
+ PortableServer_POAManager pm;
+
+ DBUG_ENTER("main");
+ DBUG_PROCESS(argv[0]);
+ ev = g_new0(CORBA_Environment,1);
+ CORBA_exception_init(ev);
+ orb = CORBA_ORB_init(&argc, argv, "orbit-local-orb", ev);
+ MY_INIT(argv[0]);
+
+ /*
+ ** Check out the args
+ */
+ if (get_options(&argc, &argv))
+ {
+ my_end(0);
+ exit(EX_USAGE);
+ }
+ if (db_connect(current_host, current_user, opt_password))
+ exit(EX_MYSQLERR);
+ fptr = db_load_functions();
+ db_load_formats();
+ poa = (PortableServer_POA)
+ CORBA_ORB_resolve_initial_references(orb, "RootPOA", ev);
+ fs = impl_FileSystem__create(poa, ev);
+
+ pm = PortableServer_POA__get_the_POAManager(poa, ev);
+ PortableServer_POAManager_activate(pm, ev);
+
+ fs_impl = PortableServer_POA_reference_to_servant( poa, fs, ev );
+ objid = PortableServer_POA_servant_to_id( poa, fs_impl, ev );
+ printf("CorbaFS-server:\n%s\n", CORBA_ORB_object_to_string(orb, fs, ev));
+ f=fopen("/tmp/mysqlcorbafs.ior","w");
+ fputs(CORBA_ORB_object_to_string(orb, fs, ev),f);
+ fclose(f);
+ CORBA_ORB_run(orb, ev);
+ db_disconnect(current_host);
+
+ return 0;
+}
diff --git a/fs/mysqlcorbafs.h b/fs/mysqlcorbafs.h
new file mode 100644
index 00000000000..f805a1fb584
--- /dev/null
+++ b/fs/mysqlcorbafs.h
@@ -0,0 +1,157 @@
+/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include "CorbaFS.h"
+
+#include <my_global.h>
+#include <my_sys.h>
+#include <m_string.h>
+#include <m_ctype.h>
+#include "mysql.h"
+
+#define QUOTE_CHAR '`'
+/* Exit codes */
+
+#define EX_USAGE 1
+#define EX_MYSQLERR 2
+#define EX_CONSCHECK 3
+#define EX_EOM 4
+
+#define CORBAFS_VERSION "0.01"
+
+typedef struct
+{
+ POA_CorbaFS_Inode servant;
+ PortableServer_POA poa;
+
+ CORBA_char *path;
+ CORBA_unsigned_long inodeNum;
+#if 0
+ CORBA_unsigned_short mode;
+ CORBA_unsigned_long uid;
+ CORBA_unsigned_long gid;
+ CORBA_unsigned_long size;
+ CORBA_unsigned_short numLinks;
+ CORBA_long atime;
+ CORBA_long mtime;
+ CORBA_long ctime;
+#endif
+}
+impl_POA_CorbaFS_Inode;
+
+typedef struct
+{
+ POA_CorbaFS_FileSystem servant;
+ PortableServer_POA poa;
+
+}
+impl_POA_CorbaFS_FileSystem;
+
+/*** Implementation stub prototypes ***/
+CorbaFS_FileSystem
+impl_FileSystem__create(PortableServer_POA poa, CORBA_Environment * ev);
+
+static void
+impl_Inode__destroy(impl_POA_CorbaFS_Inode * servant,
+ CORBA_Environment * ev);
+static void
+impl_Inode_getStatus(impl_POA_CorbaFS_Inode * servant,
+ CORBA_unsigned_short * mode,
+ CORBA_unsigned_long * uid,
+ CORBA_unsigned_long * gid,
+ CORBA_unsigned_long * size,
+ CORBA_unsigned_long * inodeNum,
+ CORBA_unsigned_short * numLinks,
+ CORBA_long * atime,
+ CORBA_long * mtime,
+ CORBA_long * ctime, CORBA_Environment * ev);
+
+static void
+impl_Inode_readpage(impl_POA_CorbaFS_Inode * servant,
+ CorbaFS_Buffer ** buffer,
+ CORBA_long size,
+ CORBA_long offset, CORBA_Environment * ev);
+
+static void
+impl_Inode_release(impl_POA_CorbaFS_Inode * servant,
+ CORBA_Environment * ev);
+
+static void impl_FileSystem__destroy(impl_POA_CorbaFS_FileSystem *
+ servant, CORBA_Environment * ev);
+
+static CorbaFS_Inode
+impl_FileSystem_getInode(impl_POA_CorbaFS_FileSystem * servant,
+ CORBA_char * path, CORBA_Environment * ev);
+
+static CorbaFS_DirEntSeq *
+impl_FileSystem_readdir(impl_POA_CorbaFS_FileSystem * servant,
+ CORBA_char * path,
+ CORBA_Environment * ev);
+
+static CORBA_char *
+impl_FileSystem_readlink(impl_POA_CorbaFS_FileSystem * servant,
+ CORBA_char * filename,
+ CORBA_Environment * ev);
+
+static my_bool verbose,opt_compress;
+static uint opt_mysql_port=0;
+static my_string opt_mysql_unix_port=0;
+static int first_error=0;
+static MYSQL connection, *sock=0;
+
+extern uint opt_mysql_port;
+extern my_string opt_mysql_unix_port,host,user,password;
+
+
+
+static struct format {
+ char *tablestart;
+
+ char *headerrowstart;
+ char *headercellstart;
+ char *headercellseparator;
+ char *headercellend;
+ char *headerrowend;
+ int headerformat; /* 0 - simple, 1 - left padded, 2 - right padded */
+
+ char *contentrowstart;
+ char *contentcellstart;
+ char *contentcellseparator;
+ char *contentcellend;
+ char *contentrowend;
+ int contentformat;
+
+ char *footerrowstart;
+ char *footercellstart;
+ char *footercellseparator;
+ char *footercellend;
+ char *footerrowend;
+ int footerformat;
+
+ char *tableend;
+
+ char *leftuppercorner;
+ char *rightuppercorner;
+ char *leftdowncorner;
+ char *rightdowncorner;
+ char *leftcross;
+ char *rightcross;
+ char *topcross;
+ char *middlecross;
+ char *bottomcross;
+
+
+} Human, HTML, CSF, XML;
diff --git a/fs/mysqlcorbafs_test.c b/fs/mysqlcorbafs_test.c
new file mode 100644
index 00000000000..bd7d9381744
--- /dev/null
+++ b/fs/mysqlcorbafs_test.c
@@ -0,0 +1,92 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <orb/orbit.h>
+
+#include "CorbaFS.h"
+
+CorbaFS_FileSystem fs;
+
+int
+main (int argc, char *argv[])
+{
+ CORBA_Environment ev;
+ CORBA_ORB orb;
+ CorbaFS_Inode inode;
+ CorbaFS_Buffer *buffer;
+ CorbaFS_DirEntSeq *dirents;
+ CorbaFS_dirent *dirent;
+
+ CORBA_unsigned_short mode;
+ CORBA_unsigned_long uid;
+ CORBA_unsigned_long gid;
+ CORBA_unsigned_long size;
+ CORBA_unsigned_long inodeNum;
+ CORBA_unsigned_short numLinks;
+ CORBA_long atime;
+ CORBA_long mtime;
+ CORBA_long ctime;
+
+ int i;
+
+ int niters = 10;
+
+ CORBA_exception_init(&ev);
+ orb = CORBA_ORB_init(&argc, argv, "orbit-local-orb", &ev);
+
+ if(argc < 2)
+ {
+ printf("Need a binding ID thing as argv[1]\n");
+ return 1;
+ }
+
+
+ fs = CORBA_ORB_string_to_object(orb, argv[1], &ev);
+ if (!fs) {
+ printf("Cannot bind to %s\n", argv[1]);
+ return 1;
+ }
+
+ if (argc >= 3)
+ inode = CorbaFS_FileSystem_getInode(fs, argv[2], &ev);
+ else
+ inode = CorbaFS_FileSystem_getInode(fs, "/proc/cpuinfo", &ev);
+
+ if (!inode)
+ {
+ printf("Cannot get inode\n");
+ }
+
+ CorbaFS_Inode_getStatus(inode,
+ &mode,
+ &uid,
+ &gid,
+ &size,
+ &inodeNum,
+ &numLinks,
+ &atime,
+ &mtime,
+ &ctime,
+ &ev);
+
+ printf("inode = %x\n", inode);
+ CorbaFS_Inode_readpage(inode, &buffer, 100000, 100, &ev);
+ printf("readpage got %d bytes\n", buffer->_length);
+ printf("readpage returned : %s\n", buffer->_buffer);
+
+ if (argc >= 3)
+ dirents = CorbaFS_FileSystem_readdir(fs, argv[2], &ev);
+ else
+ dirents = CorbaFS_FileSystem_readdir(fs, "/", &ev);
+
+ dirent = dirents->_buffer;
+ for (i = 0; i < dirents->_length; i++)
+ {
+ printf("%d = %s\n", dirent->inode, dirent->name);
+ dirent++;
+ }
+
+ CORBA_Object_release(fs, &ev);
+ CORBA_Object_release((CORBA_Object)orb, &ev);
+
+ return 0;
+}
diff --git a/fs/mysqlfsck b/fs/mysqlfsck
new file mode 100755
index 00000000000..7b4e049b1e3
--- /dev/null
+++ b/fs/mysqlfsck
@@ -0,0 +1,11 @@
+#!/bin/sh
+
+mountpoint=$*
+
+if [#($mountpoint) -eq "0"];
+then
+ exit;
+fi
+
+
+
diff --git a/heap/_check.c b/heap/_check.c
index e22eb5e7e4a..03fb664cba9 100644
--- a/heap/_check.c
+++ b/heap/_check.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -79,9 +79,11 @@ static int check_one_key(HP_KEYDEF *keydef, uint keynr, ulong records,
}
DBUG_PRINT("info",
("records: %ld seeks: %d max links: %d hitrate: %.2f",
- records,seek,max_links,(float) seek / (float) (records ? records : 1)));
+ records,seek,max_links,
+ (float) seek / (float) (records ? records : 1)));
if (print_status)
printf("Key: %d records: %ld seeks: %d max links: %d hitrate: %.2f\n",
- keynr, records, seek, max_links, (float) seek / (float) records);
+ keynr, records, seek, max_links,
+ (float) seek / (float) (records ? records : 1));
return error;
}
diff --git a/heap/_rectest.c b/heap/_rectest.c
index 3368fbeeffa..522940286fd 100644
--- a/heap/_rectest.c
+++ b/heap/_rectest.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
diff --git a/heap/heapdef.h b/heap/heapdef.h
index 938cb55c0eb..bdd7de45370 100644
--- a/heap/heapdef.h
+++ b/heap/heapdef.h
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -70,6 +70,7 @@ extern int _hp_rec_key_cmp(HP_KEYDEF *keydef,const byte *rec1,
extern int _hp_key_cmp(HP_KEYDEF *keydef,const byte *rec,
const byte *key);
extern void _hp_make_key(HP_KEYDEF *keydef,byte *key,const byte *rec);
+extern my_bool hp_if_null_in_key(HP_KEYDEF *keyinfo, const byte *record);
extern int _hp_close(register HP_INFO *info);
extern void _hp_clear(HP_SHARE *info);
diff --git a/heap/hp_block.c b/heap/hp_block.c
index 510d89d6d1e..5c052218e58 100644
--- a/heap/hp_block.c
+++ b/heap/hp_block.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
diff --git a/heap/hp_clear.c b/heap/hp_clear.c
index 702c2e09d29..2dcf91c03d7 100644
--- a/heap/hp_clear.c
+++ b/heap/hp_clear.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -44,7 +44,7 @@ void _hp_clear(HP_SHARE *info)
block->levels=0;
block->last_allocated=0;
}
- info->records=info->deleted=info->data_length=info->index_length=0;;
+ info->records=info->deleted=info->data_length=info->index_length=0;
info->blength=1;
info->changed=0;
info->del_link=0;
diff --git a/heap/hp_close.c b/heap/hp_close.c
index 583602e98cb..9e7d9ab31d1 100644
--- a/heap/hp_close.c
+++ b/heap/hp_close.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -19,7 +19,7 @@
#include "heapdef.h"
/* Close a database open by hp_open() */
- /* Data is not deallocated */
+ /* Data is normally not deallocated */
int heap_close(HP_INFO *info)
{
@@ -43,9 +43,9 @@ int _hp_close(register HP_INFO *info)
}
#endif
info->s->changed=0;
- info->s->open_count--;
heap_open_list=list_delete(heap_open_list,&info->open_list);
+ if (!--info->s->open_count && info->s->delete_on_close)
+ _hp_free(info->s); /* Table was deleted */
my_free((gptr) info,MYF(0));
DBUG_RETURN(error);
}
-
diff --git a/heap/hp_create.c b/heap/hp_create.c
index 01c5f43adfd..1307fab1d12 100644
--- a/heap/hp_create.c
+++ b/heap/hp_create.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -21,33 +21,49 @@
#include "heapdef.h"
+
int heap_create(const char *name)
{
+ reg1 HP_SHARE *share;
DBUG_ENTER("heap_create");
- (void) heap_delete_all(name);
+ pthread_mutex_lock(&THR_LOCK_heap);
+ if ((share=_hp_find_named_heap(name)))
+ {
+ if (share->open_count == 0)
+ _hp_free(share);
+ }
+ else
+ {
+ my_errno=ENOENT;
+ }
+ pthread_mutex_unlock(&THR_LOCK_heap);
DBUG_RETURN(0);
}
-int heap_delete_all(const char *name)
+int heap_delete_table(const char *name)
{
- reg1 HP_SHARE *info;
- int found;
- DBUG_ENTER("heap_delete_all");
+ int result;
+ reg1 HP_SHARE *share;
+ DBUG_ENTER("heap_delete_table");
+
pthread_mutex_lock(&THR_LOCK_heap);
- if ((info=_hp_find_named_heap(name)))
+ if ((share=_hp_find_named_heap(name)))
{
- if (info->open_count == 0)
- _hp_free(info);
- found=0;
+ if (share->open_count == 0)
+ _hp_free(share);
+ else
+ share->delete_on_close=1;
+ result=0;
}
else
{
- found=my_errno=ENOENT;
+ result=my_errno=ENOENT;
}
pthread_mutex_unlock(&THR_LOCK_heap);
- DBUG_RETURN(found);
+ DBUG_RETURN(result);
}
+
void _hp_free(HP_SHARE *share)
{
heap_share_list=list_delete(heap_share_list,&share->open_list);
diff --git a/heap/hp_delete.c b/heap/hp_delete.c
index a6e77fe5f27..3ac321d5fa2 100644
--- a/heap/hp_delete.c
+++ b/heap/hp_delete.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -50,7 +50,8 @@ int heap_delete(HP_INFO *info, const byte *record)
info->current_hash_ptr=0;
DBUG_RETURN(0);
err:
- if( ++(share->records) == share->blength) share->blength+= share->blength;
+ if (++(share->records) == share->blength)
+ share->blength+= share->blength;
DBUG_RETURN(my_errno);
}
@@ -66,7 +67,8 @@ int _hp_delete_key(HP_INFO *info, register HP_KEYDEF *keyinfo,
DBUG_ENTER("_hp_delete_key");
blength=share->blength;
- if (share->records+1 == blength) blength+= blength;
+ if (share->records+1 == blength)
+ blength+= blength;
lastpos=hp_find_hash(&keyinfo->block,share->records);
last_ptr=0;
diff --git a/heap/hp_extra.c b/heap/hp_extra.c
index 133be01c676..46e3f529f34 100644
--- a/heap/hp_extra.c
+++ b/heap/hp_extra.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
diff --git a/heap/hp_hash.c b/heap/hp_hash.c
index eb35b947871..e29e51d2b75 100644
--- a/heap/hp_hash.c
+++ b/heap/hp_hash.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -158,11 +158,22 @@ ulong _hp_hashnr(register HP_KEYDEF *keydef, register const byte *key)
{
uchar *pos=(uchar*) key;
key+=seg->length;
+ if (seg->null_bit)
+ {
+ key++; /* Skipp null byte */
+ if (*pos) /* Found null */
+ {
+ nr^= (nr << 1) | 1;
+ continue;
+ }
+ pos++;
+ }
if (seg->type == HA_KEYTYPE_TEXT)
{
for (; pos < (uchar*) key ; pos++)
{
- nr^=(ulong) ((((uint) nr & 63)+nr2)*((uint) my_sort_order[(uint) *pos]))+ (nr << 8);
+ nr^=(ulong) ((((uint) nr & 63)+nr2) *
+ ((uint) my_sort_order[(uint) *pos])) + (nr << 8);
nr2+=3;
}
}
@@ -170,7 +181,7 @@ ulong _hp_hashnr(register HP_KEYDEF *keydef, register const byte *key)
{
for (; pos < (uchar*) key ; pos++)
{
- nr^=(ulong) ((((uint) nr & 63)+nr2)*((uint) *pos))+ (nr << 8);
+ nr^=(ulong) ((((uint) nr & 63)+nr2)*((uint) *pos)) + (nr << 8);
nr2+=3;
}
}
@@ -188,11 +199,20 @@ ulong _hp_rec_hashnr(register HP_KEYDEF *keydef, register const byte *rec)
for (seg=keydef->seg,endseg=seg+keydef->keysegs ; seg < endseg ; seg++)
{
uchar *pos=(uchar*) rec+seg->start,*end=pos+seg->length;
+ if (seg->null_bit)
+ {
+ if (rec[seg->null_pos] & seg->null_bit)
+ {
+ nr^= (nr << 1) | 1;
+ continue;
+ }
+ }
if (seg->type == HA_KEYTYPE_TEXT)
{
for (; pos < end ; pos++)
{
- nr^=(ulong) ((((uint) nr & 63)+nr2)*((uint) my_sort_order[(uint) *pos]))+ (nr << 8);
+ nr^=(ulong) ((((uint) nr & 63)+nr2)*
+ ((uint) my_sort_order[(uint) *pos]))+ (nr << 8);
nr2+=3;
}
}
@@ -234,6 +254,16 @@ ulong _hp_hashnr(register HP_KEYDEF *keydef, register const byte *key)
{
uchar *pos=(uchar*) key;
key+=seg->length;
+ if (seg->null_bit)
+ {
+ key++;
+ if (*pos)
+ {
+ nr^= (nr << 1) | 1;
+ continue;
+ }
+ pos++;
+ }
if (seg->type == HA_KEYTYPE_TEXT)
{
for (; pos < (uchar*) key ; pos++)
@@ -264,6 +294,14 @@ ulong _hp_rec_hashnr(register HP_KEYDEF *keydef, register const byte *rec)
for (seg=keydef->seg,endseg=seg+keydef->keysegs ; seg < endseg ; seg++)
{
uchar *pos=(uchar*) rec+seg->start,*end=pos+seg->length;
+ if (seg->null_bit)
+ {
+ if (rec[seg->null_pos] & seg->null_bit)
+ {
+ nr^= (nr << 1) | 1;
+ continue;
+ }
+ }
if (seg->type == HA_KEYTYPE_TEXT)
{
for ( ; pos < end ; pos++)
@@ -295,6 +333,14 @@ int _hp_rec_key_cmp(HP_KEYDEF *keydef, const byte *rec1, const byte *rec2)
for (seg=keydef->seg,endseg=seg+keydef->keysegs ; seg < endseg ; seg++)
{
+ if (seg->null_bit)
+ {
+ if ((rec1[seg->null_pos] & seg->null_bit) !=
+ (rec2[seg->null_pos] & seg->null_bit))
+ return 1;
+ if (rec1[seg->null_pos] & seg->null_bit)
+ continue;
+ }
if (seg->type == HA_KEYTYPE_TEXT)
{
if (my_sortcmp(rec1+seg->start,rec2+seg->start,seg->length))
@@ -309,14 +355,24 @@ int _hp_rec_key_cmp(HP_KEYDEF *keydef, const byte *rec1, const byte *rec2)
return 0;
}
- /* Compare a key in a record to a hole key */
+ /* Compare a key in a record to a whole key */
int _hp_key_cmp(HP_KEYDEF *keydef, const byte *rec, const byte *key)
{
HP_KEYSEG *seg,*endseg;
- for (seg=keydef->seg,endseg=seg+keydef->keysegs ; seg < endseg ; seg++)
+ for (seg=keydef->seg,endseg=seg+keydef->keysegs ;
+ seg < endseg ;
+ key+= (seg++)->length)
{
+ if (seg->null_bit)
+ {
+ int found_null=test(rec[seg->null_pos] & seg->null_bit);
+ if (found_null != (int) *key++)
+ return 1;
+ if (found_null)
+ continue;
+ }
if (seg->type == HA_KEYTYPE_TEXT)
{
if (my_sortcmp(rec+seg->start,key,seg->length))
@@ -327,7 +383,6 @@ int _hp_key_cmp(HP_KEYDEF *keydef, const byte *rec, const byte *key)
if (bcmp(rec+seg->start,key,seg->length))
return 1;
}
- key+=seg->length;
}
return 0;
}
@@ -341,7 +396,28 @@ void _hp_make_key(HP_KEYDEF *keydef, byte *key, const byte *rec)
for (seg=keydef->seg,endseg=seg+keydef->keysegs ; seg < endseg ; seg++)
{
+ if (seg->null_bit)
+ *key++= test(rec[seg->null_pos] & seg->null_bit);
memcpy(key,rec+seg->start,(size_t) seg->length);
key+=seg->length;
}
}
+
+
+/*
+ Test if any of the key parts are NULL.
+ Return:
+ 1 if any of the key parts was NULL
+ 0 otherwise
+*/
+
+my_bool hp_if_null_in_key(HP_KEYDEF *keydef, const byte *record)
+{
+ HP_KEYSEG *seg,*endseg;
+ for (seg=keydef->seg,endseg=seg+keydef->keysegs ; seg < endseg ; seg++)
+ {
+ if (seg->null_bit && (record[seg->null_pos] & seg->null_bit))
+ return 1;
+ }
+ return 0;
+}
diff --git a/heap/hp_info.c b/heap/hp_info.c
index 379f4d9ec0f..3e9d6b6a90b 100644
--- a/heap/hp_info.c
+++ b/heap/hp_info.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
diff --git a/heap/hp_open.c b/heap/hp_open.c
index 692142de14a..938ab8c4f78 100644
--- a/heap/hp_open.c
+++ b/heap/hp_open.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -44,7 +44,12 @@ HP_INFO *heap_open(const char *name, int mode, uint keys, HP_KEYDEF *keydef,
key_segs+= keydef[i].keysegs;
bzero((char*) &keydef[i].block,sizeof(keydef[i].block));
for (j=length=0 ; j < keydef[i].keysegs; j++)
+ {
length+=keydef[i].seg[j].length;
+ if (keydef[i].seg[j].null_bit &&
+ !(keydef[i].flag & HA_NULL_ARE_EQUAL))
+ keydef[i].flag |= HA_NULL_PART_KEY;
+ }
keydef[i].length=length;
if (length > max_length)
max_length=length;
diff --git a/heap/hp_panic.c b/heap/hp_panic.c
index cfd370a56d0..4b93190b7e1 100644
--- a/heap/hp_panic.c
+++ b/heap/hp_panic.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
diff --git a/heap/hp_rename.c b/heap/hp_rename.c
index 267c16b589d..118c5931f43 100644
--- a/heap/hp_rename.c
+++ b/heap/hp_rename.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
diff --git a/heap/hp_rfirst.c b/heap/hp_rfirst.c
index e3b9654061d..9a1f09244a0 100644
--- a/heap/hp_rfirst.c
+++ b/heap/hp_rfirst.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
diff --git a/heap/hp_rkey.c b/heap/hp_rkey.c
index 157267f7149..e7a1d81fba6 100644
--- a/heap/hp_rkey.c
+++ b/heap/hp_rkey.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -20,7 +20,7 @@ int heap_rkey(HP_INFO *info, byte *record, int inx, const byte *key)
{
byte *pos;
HP_SHARE *share=info->s;
- DBUG_ENTER("hp_rkey");
+ DBUG_ENTER("heap_rkey");
DBUG_PRINT("enter",("base: %lx inx: %d",info,inx));
if ((uint) inx >= share->keys)
diff --git a/heap/hp_rlast.c b/heap/hp_rlast.c
index 38e07fde2bb..463b6dc9aac 100644
--- a/heap/hp_rlast.c
+++ b/heap/hp_rlast.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
diff --git a/heap/hp_rnext.c b/heap/hp_rnext.c
index 6aa3cf06d97..4e5cb7e37c2 100644
--- a/heap/hp_rnext.c
+++ b/heap/hp_rnext.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
diff --git a/heap/hp_rprev.c b/heap/hp_rprev.c
index 28a821c143e..c7c649e6b9f 100644
--- a/heap/hp_rprev.c
+++ b/heap/hp_rprev.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
diff --git a/heap/hp_rrnd.c b/heap/hp_rrnd.c
index 63181967a29..78abebcaf47 100644
--- a/heap/hp_rrnd.c
+++ b/heap/hp_rrnd.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
diff --git a/heap/hp_rsame.c b/heap/hp_rsame.c
index 888fb349f5a..a346707641b 100644
--- a/heap/hp_rsame.c
+++ b/heap/hp_rsame.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
diff --git a/heap/hp_scan.c b/heap/hp_scan.c
index b7684cd2673..e74f8b43ba7 100644
--- a/heap/hp_scan.c
+++ b/heap/hp_scan.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
diff --git a/heap/hp_static.c b/heap/hp_static.c
index 5e5326ca76b..a458b742b9c 100644
--- a/heap/hp_static.c
+++ b/heap/hp_static.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
diff --git a/heap/hp_test1.c b/heap/hp_test1.c
index f44752af3bc..e07af2761f0 100644
--- a/heap/hp_test1.c
+++ b/heap/hp_test1.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -20,7 +20,7 @@
raderas.
*/
-#include <global.h>
+#include <my_global.h>
#include <my_sys.h>
#include <m_string.h>
#include "heap.h"
diff --git a/heap/hp_test2.c b/heap/hp_test2.c
index a76aa19e082..e2570893519 100644
--- a/heap/hp_test2.c
+++ b/heap/hp_test2.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -30,7 +30,7 @@
#include <signal.h>
#define MAX_RECORDS 100000
-#define MAX_KEYS 3
+#define MAX_KEYS 4
static int get_options(int argc, char *argv[]);
static int rnd(int max_value);
@@ -40,16 +40,20 @@ static uint flag=0,verbose=0,testflag=0,recant=10000,silent=0;
static uint keys=MAX_KEYS;
static uint16 key1[1001];
static my_bool key3[MAX_RECORDS];
+static int reclength=39;
+
static int calc_check(byte *buf,uint length);
+static void make_record(char *record, uint n1, uint n2, uint n3,
+ const char *mark, uint count);
- /* Huvudprogrammet */
+/* Main program */
int main(int argc, char *argv[])
{
register uint i,j;
uint ant,n1,n2,n3;
- uint reclength,write_count,update,opt_delete,check2,dupp_keys,found_key;
+ uint write_count,update,opt_delete,check2,dupp_keys,found_key;
int error;
ulong pos;
unsigned long key_check;
@@ -66,7 +70,6 @@ int main(int argc, char *argv[])
filename2= "test2_2";
file=file2=0;
get_options(argc,argv);
- reclength=37;
write_count=update=opt_delete=0;
key_check=0;
@@ -77,21 +80,33 @@ int main(int argc, char *argv[])
keyinfo[0].seg[0].type=HA_KEYTYPE_BINARY;
keyinfo[0].seg[0].start=0;
keyinfo[0].seg[0].length=6;
+ keyinfo[0].seg[0].null_bit=0;
keyinfo[1].seg=keyseg+1;
keyinfo[1].keysegs=2;
keyinfo[1].flag=0;
keyinfo[1].seg[0].type=HA_KEYTYPE_BINARY;
keyinfo[1].seg[0].start=7;
keyinfo[1].seg[0].length=6;
+ keyinfo[1].seg[0].null_bit=0;
keyinfo[1].seg[1].type=HA_KEYTYPE_TEXT;
- keyinfo[1].seg[1].start=0; /* Tv}delad nyckel */
+ keyinfo[1].seg[1].start=0; /* key in two parts */
keyinfo[1].seg[1].length=6;
+ keyinfo[1].seg[1].null_bit=0;
keyinfo[2].seg=keyseg+3;
keyinfo[2].keysegs=1;
keyinfo[2].flag=HA_NOSAME;
keyinfo[2].seg[0].type=HA_KEYTYPE_BINARY;
keyinfo[2].seg[0].start=12;
keyinfo[2].seg[0].length=8;
+ keyinfo[2].seg[0].null_bit=0;
+ keyinfo[3].keysegs=1;
+ keyinfo[3].flag=HA_NOSAME;
+ keyinfo[3].seg=keyseg+4;
+ keyinfo[3].seg[0].type=HA_KEYTYPE_BINARY;
+ keyinfo[3].seg[0].start=37;
+ keyinfo[3].seg[0].length=1;
+ keyinfo[3].seg[0].null_bit=1;
+ keyinfo[3].seg[0].null_pos=38;
bzero((char*) key1,sizeof(key1));
bzero((char*) key3,sizeof(key3));
@@ -110,7 +125,7 @@ int main(int argc, char *argv[])
for (i=0 ; i < recant ; i++)
{
n1=rnd(1000); n2=rnd(100); n3=rnd(min(recant*5,MAX_RECORDS));
- sprintf(record,"%6d:%4d:%8d:Pos: %4d ",n1,n2,n3,write_count);
+ make_record(record,n1,n2,n3,"Pos",write_count);
if (heap_write(file,record))
{
@@ -191,7 +206,7 @@ int main(int argc, char *argv[])
for (i=0 ; i < write_count/10 ; i++)
{
n1=rnd(1000); n2=rnd(100); n3=rnd(min(recant*2,MAX_RECORDS));
- sprintf(record2,"%6d:%4d:%8d:XXX: %4d ",n1,n2,n3,update);
+ make_record(record2, n1, n2, n3, "XXX", update);
if (rnd(2) == 1)
{
if (heap_scan_init(file))
@@ -572,7 +587,7 @@ end:
heap_clear(file);
if (heap_close(file) || (file2 && heap_close(file2)))
goto err;
- heap_delete_all(filename2);
+ heap_delete_table(filename2);
heap_panic(HA_PANIC_CLOSE);
my_end(MY_GIVE_INFO);
return(0);
@@ -654,3 +669,13 @@ static int calc_check(byte *buf, uint length)
check+= (int) (uchar) *(buf++);
return check;
}
+
+static void make_record(char *record, uint n1, uint n2, uint n3,
+ const char *mark, uint count)
+{
+ bfill(record,reclength,' ');
+ sprintf(record,"%6d:%4d:%8d:%3.3s: %4d",
+ n1,n2,n3,mark,count);
+ record[37]='A'; /* Store A in null key */
+ record[38]=1; /* set as null */
+}
diff --git a/heap/hp_update.c b/heap/hp_update.c
index a1d9c51e9dd..8cf3e4d4b8d 100644
--- a/heap/hp_update.c
+++ b/heap/hp_update.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
diff --git a/heap/hp_write.c b/heap/hp_write.c
index 12b5c638f78..806f40e5be5 100644
--- a/heap/hp_write.c
+++ b/heap/hp_write.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -62,6 +62,7 @@ int heap_write(HP_INFO *info, const byte *record)
info->update|=HA_STATE_AKTIV;
DBUG_RETURN(0);
err:
+ DBUG_PRINT("info",("Duplicate key: %d",key));
info->errkey= key;
do
{
@@ -237,8 +238,10 @@ int _hp_write_key(register HP_SHARE *info, HP_KEYDEF *keyinfo,
_hp_movelink(pos,gpos,empty);
}
- /* Check if dupplicated keys */
- if ((keyinfo->flag & HA_NOSAME) && pos == gpos)
+ /* Check if duplicated keys */
+ if ((keyinfo->flag & HA_NOSAME) && pos == gpos &&
+ (!(keyinfo->flag & HA_NULL_PART_KEY) ||
+ !hp_if_null_in_key(keyinfo, record)))
{
pos=empty;
do
diff --git a/include/Makefile.am b/include/Makefile.am
index f3685b51cd3..b943e8d76e6 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -16,28 +16,28 @@
# MA 02111-1307, USA
BUILT_SOURCES = mysql_version.h m_ctype.h my_config.h
-pkginclude_HEADERS = dbug.h m_string.h my_sys.h mysql.h mysql_com.h \
- mysqld_error.h my_list.h \
+pkginclude_HEADERS = dbug.h m_string.h my_sys.h my_list.h \
+ mysql.h mysql_com.h mysqld_error.h mysql_embed.h \
my_pthread.h my_no_pthread.h raid.h errmsg.h \
my_global.h my_net.h \
sslopt-case.h sslopt-longopts.h sslopt-usage.h \
sslopt-vars.h $(BUILT_SOURCES)
-noinst_HEADERS = global.h config-win.h \
+noinst_HEADERS = config-win.h \
nisam.h heap.h merge.h my_bitmap.h\
myisam.h myisampack.h myisammrg.h ft_global.h\
my_dir.h mysys_err.h my_base.h \
my_nosys.h my_alarm.h queues.h \
my_tree.h hash.h thr_alarm.h thr_lock.h \
- getopt.h t_ctype.h violite.h \
+ getopt.h my_getopt.h t_ctype.h violite.h md5.h \
mysql_version.h.in
# mysql_version.h are generated
-SUPERCLEANFILES = mysql_version.h my_global.h my_config.h
+SUPERCLEANFILES = mysql_version.h my_config.h
# Some include files that may be moved and patched by configure
DISTCLEANFILES = sched.h
-all-local: my_global.h my_config.h
+all-local: my_config.h
# Since we include my_config.h it better exist from the beginning
link_sources:
@@ -48,11 +48,6 @@ link_sources:
my_config.h: ../config.h
$(CP) ../config.h my_config.h
-# This should be changed in the source and removed.
-my_global.h: global.h
- $(RM) -f my_global.h
- $(CP) global.h my_global.h
-
# These files should not be included in distributions since they are
# generated by configure from the .h.in files
dist-hook:
diff --git a/include/config-win.h b/include/config-win.h
index 4e4088f07dd..a3770cd68ad 100644
--- a/include/config-win.h
+++ b/include/config-win.h
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/* Defines for Win32 to make it compatible for MySQL */
@@ -138,7 +137,7 @@ typedef uint rf_SetTimer;
#define USE_MB 1
#define USE_MB_IDENT 1
#define USE_STRCOLL 1
-
+
/* Convert some simple functions to Posix */
#define sigset(A,B) signal((A),(B))
@@ -254,6 +253,9 @@ inline double ulonglong2double(ulonglong value)
#define HAVE_STRPBRK
#define HAVE_STRSTR
#define HAVE_COMPRESS
+#define HAVE_CREATESEMAPHORE
+
+#define HAVE_ISAM /* We want to have support for ISAM in 4.0 */
#ifdef NOT_USED
#define HAVE_SNPRINTF /* Gave link error */
diff --git a/include/dbug.h b/include/dbug.h
index 3c86cbb8ac2..5c88e2e42db 100644
--- a/include/dbug.h
+++ b/include/dbug.h
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#ifndef _dbug_h
#define _dbug_h
diff --git a/include/errmsg.h b/include/errmsg.h
index 8087c526937..76a57f47611 100644
--- a/include/errmsg.h
+++ b/include/errmsg.h
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/* Error messages for mysql clients */
/* error messages for the demon is in share/language/errmsg.sys */
@@ -57,3 +56,8 @@ extern const char *client_errors[]; /* Error messages */
#define CR_NAMEDPIPESETSTATE_ERROR 2018
#define CR_CANT_READ_CHARSET 2019
#define CR_NET_PACKET_TOO_LARGE 2020
+#define CR_EMBEDDED_CONNECTION 2021
+#define CR_PROBE_SLAVE_STATUS 2022
+#define CR_PROBE_SLAVE_HOSTS 2023
+#define CR_PROBE_SLAVE_CONNECT 2024
+#define CR_PROBE_MASTER_CONNECT 2025
diff --git a/include/ft_global.h b/include/ft_global.h
index 3937bd87c7f..4218eb75aa7 100644
--- a/include/ft_global.h
+++ b/include/ft_global.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+/* Copyright (C) 2000 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -27,29 +27,36 @@ extern "C" {
#endif
#define FT_QUERY_MAXLEN 1024
+#define HA_FT_MAXLEN 254
-typedef struct ft_doc_rec {
- my_off_t dpos;
- double weight;
-} FT_DOC;
+typedef struct st_ft_info FT_INFO;
+struct _ft_vft {
+ int (*read_next)(FT_INFO *, char *);
+ float (*find_relevance)(FT_INFO *, byte *, uint);
+ void (*close_search)(FT_INFO *);
+ float (*get_relevance)(FT_INFO *);
+ void (*reinit_search)(FT_INFO *);
+};
-typedef struct st_ft_doclist {
- int ndocs;
- int curdoc;
- void *info; /* actually (MI_INFO *) but don't want to include myisam.h */
- FT_DOC doc[1];
-} FT_DOCLIST;
+#ifndef FT_CORE
+struct st_ft_info {
+ struct _ft_vft *please; /* INTERCAL style :-) */
+};
+#endif
extern const char *ft_precompiled_stopwords[];
+extern ulong ft_min_word_len;
+extern ulong ft_max_word_len;
+extern ulong ft_max_word_len_for_sort;
+extern const char *ft_boolean_syntax;
+
int ft_init_stopwords(const char **);
void ft_free_stopwords(void);
-FT_DOCLIST * ft_init_search(void *, uint, byte *, uint, my_bool);
-int ft_read_next(FT_DOCLIST *, char *);
-#define ft_close_search(handler) my_free(((gptr)(handler)),MYF(0))
-#define ft_get_relevance(handler) ((handler)->doc[(handler)->curdoc].weight)
-#define ft_reinit_search(handler) (((FT_DOCLIST *)(handler))->curdoc=-1)
+#define FT_NL 0
+#define FT_BOOL 1
+FT_INFO *ft_init_search(uint,void *, uint, byte *, uint, my_bool);
#ifdef __cplusplus
}
diff --git a/include/getopt.h b/include/getopt.h
index 790915b97df..94e73c03ff3 100644
--- a/include/getopt.h
+++ b/include/getopt.h
@@ -1,3 +1,19 @@
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
/* Declarations for getopt.
Copyright (C) 1989, 90, 91, 92, 93, 94 Free Software Foundation, Inc.
diff --git a/include/hash.h b/include/hash.h
index c98b0851645..8ca8d9fde02 100644
--- a/include/hash.h
+++ b/include/hash.h
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/* Dynamic hashing of record with different key-length */
@@ -54,6 +53,7 @@ gptr hash_next(HASH *info,const byte *key,uint length);
my_bool hash_insert(HASH *info,const byte *data);
my_bool hash_delete(HASH *hash,byte *record);
my_bool hash_update(HASH *hash,byte *record,byte *old_key,uint old_key_length);
+void hash_replace(HASH *hash, uint idx, byte *new_row);
my_bool hash_check(HASH *hash); /* Only in debug library */
#define hash_clear(H) bzero((char*) (H),sizeof(*(H)))
diff --git a/include/heap.h b/include/heap.h
index 14698810297..02b04e2b3ec 100644
--- a/include/heap.h
+++ b/include/heap.h
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 should be included when using heap_database_funktions */
/* Author: Michael Widenius */
@@ -79,11 +78,13 @@ typedef struct st_hp_keyseg /* Key-portion */
uint start; /* Start of key in record (from 0) */
uint length; /* Keylength */
uint type;
+ uint null_bit; /* bit set in row+null_pos */
+ uint null_pos;
} HP_KEYSEG;
typedef struct st_hp_keydef /* Key definition with open */
{
- uint flag; /* NOSAME */
+ uint flag; /* HA_NOSAME | HA_NULL_PART_KEY */
uint keysegs; /* Number of key-segment */
uint length; /* Length of key (automatic) */
HP_KEYSEG *seg;
@@ -109,6 +110,7 @@ typedef struct st_heap_share
THR_LOCK lock;
pthread_mutex_t intern_lock; /* Locking for use with _locking */
#endif
+ my_bool delete_on_close;
LIST open_list;
} HP_SHARE;
@@ -144,7 +146,7 @@ extern int heap_scan(register HP_INFO *info, byte *record);
extern int heap_delete(HP_INFO *info,const byte *buff);
extern int heap_info(HP_INFO *info,HEAPINFO *x,int flag);
extern int heap_create(const char *name);
-extern int heap_delete_all(const char *name);
+extern int heap_delete_table(const char *name);
extern int heap_extra(HP_INFO *info,enum ha_extra_function function);
extern int heap_rename(const char *old_name,const char *new_name);
extern int heap_panic(enum ha_panic_function flag);
diff --git a/include/m_ctype.h b/include/m_ctype.h
index 645c07b79ae..61afcb7245e 100644
--- a/include/m_ctype.h
+++ b/include/m_ctype.h
@@ -1,23 +1,22 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/*
A better inplementation of the UNIX ctype(3) library.
- Notes: global.h should be included before ctype.h
+ Notes: my_global.h should be included before ctype.h
*/
#ifndef _m_ctype_h
@@ -57,13 +56,12 @@ extern CHARSET_INFO *default_charset_info;
extern CHARSET_INFO *find_compiled_charset(uint cs_number);
extern CHARSET_INFO *find_compiled_charset_by_name(const char *name);
extern CHARSET_INFO compiled_charsets[];
+extern uint compiled_charset_number(const char *name);
+extern const char *compiled_charset_name(uint charset_number);
#define MY_CHARSET_UNDEFINED 0
#define MY_CHARSET_CURRENT (default_charset_info->number)
-#ifdef __WIN__
-#include <ctype.h>
-#endif
/* Don't include std ctype.h when this is included */
#define _CTYPE_H
#define _CTYPE_H_
@@ -71,6 +69,26 @@ extern CHARSET_INFO compiled_charsets[];
#define __CTYPE_INCLUDED
#define _CTYPE_USING /* Don't put names in global namespace. */
+/* Fix things, if ctype.h would have been included before */
+#undef toupper
+#undef _toupper
+#undef _tolower
+#undef toupper
+#undef tolower
+#undef isalpha
+#undef isupper
+#undef islower
+#undef isdigit
+#undef isxdigit
+#undef isalnum
+#undef isspace
+#undef ispunct
+#undef isprint
+#undef isgraph
+#undef iscntrl
+#undef isascii
+#undef toascii
+
#define _U 01 /* Upper case */
#define _L 02 /* Lower case */
#define _N 04 /* Numeral (digit) */
@@ -85,7 +103,6 @@ extern CHARSET_INFO compiled_charsets[];
#define my_to_lower (default_charset_info->to_lower)
#define my_sort_order (default_charset_info->sort_order)
-#ifndef __WIN__
#define _toupper(c) (char) my_to_upper[(uchar) (c)]
#define _tolower(c) (char) my_to_lower[(uchar) (c)]
#define toupper(c) (char) my_to_upper[(uchar) (c)]
@@ -109,8 +126,6 @@ extern CHARSET_INFO compiled_charsets[];
#undef ctype
#endif /* ctype */
-#endif /* __WIN__ */
-
#define my_isalpha(s, c) (((s)->ctype+1)[(uchar) (c)] & (_U | _L))
#define my_isupper(s, c) (((s)->ctype+1)[(uchar) (c)] & _U)
#define my_islower(s, c) (((s)->ctype+1)[(uchar) (c)] & _L)
diff --git a/include/m_string.h b/include/m_string.h
index 7eb2f1fe690..c6943613b1a 100644
--- a/include/m_string.h
+++ b/include/m_string.h
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/* There may be prolems include all of theese. Try to test in
configure with ones are needed? */
@@ -132,11 +131,12 @@ extern void bzero(gptr dst,uint len);
#if !defined(bcmp) && !defined(HAVE_BCMP)
extern int bcmp(const char *s1,const char *s2,uint len);
+#endif
#ifdef HAVE_purify
extern int my_bcmp(const char *s1,const char *s2,uint len);
+#undef bcmp
#define bcmp(A,B,C) my_bcmp((A),(B),(C))
#endif
-#endif
#ifndef bmove512
extern void bmove512(gptr dst,const gptr src,uint len);
diff --git a/sql/md5.h b/include/md5.h
index 862129391f1..aa4116ff17f 100644
--- a/sql/md5.h
+++ b/include/md5.h
@@ -1,3 +1,19 @@
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
/* MD5.H - header file for MD5C.C
*/
@@ -57,24 +73,21 @@ If using PROTOTYPES, then PROTO_LIST returns the list, otherwise it
#else
#define PROTO_LIST(list) ()
#endif
-
-
/* MD5 context. */
typedef struct {
UINT4 state[4]; /* state (ABCD) */
UINT4 count[2]; /* number of bits, modulo 2^64 (lsb first) */
unsigned char buffer[64]; /* input buffer */
-} MD5_CTX;
+} my_MD5_CTX;
#ifdef __cplusplus
extern "C" {
#endif
- void MD5Init PROTO_LIST ((MD5_CTX *));
- void MD5Update PROTO_LIST
- ((MD5_CTX *, unsigned char *, unsigned int));
- void MD5Final PROTO_LIST ((unsigned char [16], MD5_CTX *));
+ void my_MD5Init PROTO_LIST ((my_MD5_CTX *));
+ void my_MD5Update PROTO_LIST
+ ((my_MD5_CTX *, unsigned char *, unsigned int));
+ void my_MD5Final PROTO_LIST ((unsigned char [16], my_MD5_CTX *));
#ifdef __cplusplus
}
#endif
-
diff --git a/include/merge.h b/include/merge.h
index c661e03a0c7..97cea5fabb1 100644
--- a/include/merge.h
+++ b/include/merge.h
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 should be included when using merge_isam_funktions */
/* Author: Michael Widenius */
diff --git a/include/my_alarm.h b/include/my_alarm.h
index b6c5ca6a3f4..fdfce9c65c9 100644
--- a/include/my_alarm.h
+++ b/include/my_alarm.h
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/*
File to include when we want to use alarm or a loop_counter to display
diff --git a/include/my_base.h b/include/my_base.h
index 6275adab124..68f33147145 100644
--- a/include/my_base.h
+++ b/include/my_base.h
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 includes constants used with all databases */
/* Author: Michael Widenius */
@@ -24,7 +23,7 @@
#ifndef stdin /* Included first in handler */
#define USES_TYPES /* my_dir with sys/types is included */
#define CHSIZE_USED
-#include <global.h>
+#include <my_global.h>
#include <my_dir.h> /* This includes types */
#include <my_sys.h>
#include <m_string.h>
@@ -57,7 +56,20 @@ enum ha_rkey_function {
HA_READ_AFTER_KEY, /* Find next rec. after key-record */
HA_READ_BEFORE_KEY, /* Find next rec. before key-record */
HA_READ_PREFIX, /* Key which as same prefix */
- HA_READ_PREFIX_LAST /* Last key with the same prefix */
+ HA_READ_PREFIX_LAST, /* Last key with the same prefix */
+ HA_READ_MBR_CONTAIN,
+ HA_READ_MBR_INTERSECT,
+ HA_READ_MBR_WITHIN,
+ HA_READ_MBR_DISJOINT,
+ HA_READ_MBR_EQUAL
+};
+
+ /* Key algorithm types */
+
+enum ha_key_alg {
+ HA_KEY_ALG_BTREE=0, /* B-tree, default one */
+ HA_KEY_ALG_RTREE=1, /* R-tree, for spatial searches */
+ HA_KEY_ALG_HASH=2 /* HASH keys (HEAP tables) */
};
/* The following is parameter to ha_extra() */
@@ -91,7 +103,10 @@ enum ha_extra_function {
HA_EXTRA_RESET_STATE, /* Reset positions */
HA_EXTRA_IGNORE_DUP_KEY, /* Dup keys don't rollback everything*/
HA_EXTRA_NO_IGNORE_DUP_KEY,
- HA_EXTRA_DONT_USE_CURSOR_TO_UPDATE /* Cursor will not be used for update */
+ HA_EXTRA_DONT_USE_CURSOR_TO_UPDATE, /* Cursor will not be used for update */
+ HA_EXTRA_BULK_INSERT_BEGIN,
+ HA_EXTRA_BULK_INSERT_END,
+ HA_EXTRA_PREPARE_FOR_DELETE
};
/* The following is parameter to ha_panic() */
@@ -134,6 +149,9 @@ enum ha_base_keytype {
#define HA_BINARY_PACK_KEY 32 /* Packing of all keys to prev key */
#define HA_FULLTEXT 128 /* SerG: for full-text search */
#define HA_UNIQUE_CHECK 256 /* Check the key for uniqueness */
+#define HA_SPATIAL 1024 /* Alex Barkov: for spatial search */
+#define HA_NULL_ARE_EQUAL 2048 /* NULL in key are cmp as equal */
+
/* Automatic bits in key-flag */
@@ -156,6 +174,7 @@ enum ha_base_keytype {
#define HA_BLOB_PART 32
#define HA_SWAP_KEY 64
#define HA_REVERSE_SORT 128 /* Sort key in reverse order */
+#define HA_NO_SORT 256 /* do not bother sorting on this keyseg */
/* optionbits for database */
#define HA_OPTION_PACK_RECORD 1
@@ -222,6 +241,7 @@ enum ha_base_keytype {
/* Other constants */
#define HA_NAMELEN 64 /* Max length of saved filename */
+#define NO_SUCH_KEY ((uint)~0) /* used as a key no. */
/* Intern constants in databases */
@@ -235,6 +255,13 @@ enum ha_base_keytype {
#define SEARCH_UPDATE 64
#define SEARCH_PREFIX 128
#define SEARCH_LAST 256
+#define MBR_CONTAIN 512
+#define MBR_INTERSECT 1024
+#define MBR_WITHIN 2048
+#define MBR_DISJOINT 4096
+#define MBR_EQUAL 8192
+#define MBR_DATA 16384
+#define SEARCH_NULL_ARE_EQUAL 32768 /* NULL in keys are equal */
/* bits in opt_flag */
#define QUICK_USED 1
@@ -259,8 +286,8 @@ enum ha_base_keytype {
#define HA_STATE_EXTEND_BLOCK 2048
enum en_fieldtype {
- FIELD_LAST=-1,FIELD_NORMAL,FIELD_SKIPP_ENDSPACE,FIELD_SKIPP_PRESPACE,
- FIELD_SKIPP_ZERO,FIELD_BLOB,FIELD_CONSTANT,FIELD_INTERVALL,FIELD_ZERO,
+ FIELD_LAST=-1,FIELD_NORMAL,FIELD_SKIP_ENDSPACE,FIELD_SKIP_PRESPACE,
+ FIELD_SKIP_ZERO,FIELD_BLOB,FIELD_CONSTANT,FIELD_INTERVALL,FIELD_ZERO,
FIELD_VARCHAR,FIELD_CHECK
};
diff --git a/include/my_bitmap.h b/include/my_bitmap.h
index 3243e5f0b24..ca0037addfb 100644
--- a/include/my_bitmap.h
+++ b/include/my_bitmap.h
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#ifndef _my_bitmap_h_
#define _my_bitmap_h_
diff --git a/include/my_dir.h b/include/my_dir.h
index 1961ca79549..4ccda050914 100644
--- a/include/my_dir.h
+++ b/include/my_dir.h
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#ifndef _my_dir_h
#define _my_dir_h
diff --git a/include/my_getopt.h b/include/my_getopt.h
new file mode 100644
index 00000000000..2e40fb8ffaa
--- /dev/null
+++ b/include/my_getopt.h
@@ -0,0 +1,53 @@
+/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+struct my_optarg
+{
+ char *arg; /* option argument */
+ int pos; /* next element in ARGV */
+ int verbose; /* 0 = inhibit warnings of unrecognized options */
+ int unrecognized; /* position of the unrecognized option */
+};
+
+
+enum get_opt_var_type { GET_NO_ARG, GET_LONG, GET_LL, GET_STR };
+enum get_opt_arg_type { NO_ARG, OPT_ARG, REQUIRED_ARG };
+
+struct my_option
+{
+ const char *name; /* Name of the option */
+ const char *comment; /* option comment, for autom. --help */
+ gptr *value; /* The variable value */
+ gptr *u_max_value; /* The user def. max variable value */
+ const char **str_values; /* Pointer to possible values */
+ enum get_opt_var_type var_type;
+ enum get_opt_arg_type arg_type;
+ int id; /* unique id or short option */
+ longlong def_value; /* Default value */
+ longlong min_value; /* Min allowed value */
+ longlong max_value; /* Max allowed value */
+ longlong sub_size; /* Subtract this from given value */
+ long block_size; /* Value should be a mult. of this */
+ int app_type; /* To be used by an application */
+};
+
+extern int handle_options (int *argc, char ***argv,
+ const struct my_option *longopts,
+ my_bool (*get_one_option)(int,
+ const struct my_option *,
+ char *));
+extern void my_print_help(const struct my_option *options);
+extern void my_print_variables(const struct my_option *options);
diff --git a/include/global.h b/include/my_global.h
index b8b118cd855..6a7385e18a2 100644
--- a/include/global.h
+++ b/include/my_global.h
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 is the main include file that should included 'first' in every
C file. */
@@ -52,6 +51,33 @@
#endif
#endif /* _WIN32... */
+/* sometimes we want to make sure that the variable is not put into
+ a register in debugging mode so we can see its value in the core
+*/
+
+#ifndef DBUG_OFF
+#define dbug_volatile volatile
+#else
+#define dbug_volatile
+#endif
+
+/*
+ The macros below are borrowed from include/linux/compiler.h in the
+ Linux kernel. Use them to indicate the likelyhood of the truthfulness
+ of a condition. This serves two purposes - newer versions of gcc will be
+ able to optimize for branch predication, which could yield siginficant
+ performance gains in frequently executed sections of the code, and the
+ other reason to use them is for documentation
+*/
+
+#if !defined(__GNUC__) || (__GNUC__ == 2 && __GNUC_MINOR__ < 96)
+#define __builtin_expect(x, expected_value) (x)
+#endif
+
+#define likely(x) __builtin_expect((x),1)
+#define unlikely(x) __builtin_expect((x),0)
+
+
/* Fix problem with S_ISLNK() on Linux */
#if defined(HAVE_LINUXTHREADS)
#undef _GNU_SOURCE
@@ -103,7 +129,7 @@
#ifdef _AIX /* By soren@t.dk */
#define _H_STRINGS
#define _SYS_STREAM_H
-#define _AIX32_CURSES
+/* #define _AIX32_CURSES */ /* XXX: this breaks AIX 4.3.3 (others?). */
#endif
#ifdef HAVE_BROKEN_SNPRINTF /* HPUX 10.20 don't have this defined */
@@ -189,7 +215,13 @@
# endif
#endif /* TIME_WITH_SYS_TIME */
#ifdef HAVE_UNISTD_H
+#if defined(HAVE_OPENSSL) && !defined(__FreeBSD__) && !defined(NeXT)
+#define crypt unistd_crypt
+#endif
#include <unistd.h>
+#ifdef HAVE_OPENSSL
+#undef crypt
+#endif
#endif
#if defined(__cplusplus) && defined(NO_CPLUSPLUS_ALLOCA)
#undef HAVE_ALLOCA
@@ -217,7 +249,7 @@
#define setrlimit cma_setrlimit64
#endif
-/* We can not live without these */
+/* We can not live without the following defines */
#define USE_MYFUNC 1 /* Must use syscall indirection */
#define MASTER 1 /* Compile without unireg */
@@ -226,7 +258,7 @@
#define USE_REGEX 1 /* We want the use the regex library */
/* Do not define for ultra sparcs */
#ifndef OS2
-#define USE_BMOVE512 1 /* Use this unless the system bmove is faster */
+#define USE_BMOVE512 1 /* Use this unless system bmove is faster */
#endif
/* Paranoid settings. Define I_AM_PARANOID if you are paranoid */
@@ -261,7 +293,7 @@ int __void__;
#define LINT_INIT(var)
#endif
-/* Define som useful general macros */
+/* Define some useful general macros */
#if defined(__cplusplus) && defined(__GNUC__)
#define max(a, b) ((a) >? (b))
#define min(a, b) ((a) <? (b))
@@ -275,6 +307,7 @@ typedef unsigned int uint;
typedef unsigned short ushort;
#endif
+#define CMP_NUM(a,b) (((a) < (b)) ? -1 : ((a) == (b)) ? 0 : 1)
#define sgn(a) (((a) < 0) ? -1 : ((a) > 0) ? 1 : 0)
#define swap(t,a,b) { register t dummy; dummy = a; a = b; b = dummy; }
#define test(a) ((a) ? 1 : 0)
@@ -322,11 +355,6 @@ typedef unsigned short ushort;
#endif
#include <dbug.h>
-#ifndef DBUG_OFF
-#define dbug_assert(A) assert(A)
-#else
-#define dbug_assert(A)
-#endif
#define MIN_ARRAY_SIZE 0 /* Zero or One. Gcc allows zero*/
#define ASCII_BITS_USED 8 /* Bit char used */
@@ -356,6 +384,7 @@ typedef int pshort; /* Mixed prototypes can't take short int */
typedef double pfloat; /* Mixed prototypes can't take float */
#endif
typedef int (*qsort_cmp)(const void *,const void *);
+typedef int (*qsort_cmp2)(void*, const void *,const void *);
#ifdef HAVE_mit_thread
#define qsort_t void
#undef QSORT_TYPE_IS_VOID
@@ -451,8 +480,6 @@ typedef SOCKET_SIZE_TYPE size_socket;
/* Some things that this system doesn't have */
#define ONLY_OWN_DATABASES /* We are using only databases by monty */
-#define NO_PISAM /* Not needed anymore */
-#define NO_MISAM /* Not needed anymore */
#define NO_HASH /* Not needed anymore */
#ifdef __WIN__
#define NO_DIR_LIBRARY /* Not standar dir-library */
@@ -617,7 +644,7 @@ typedef unsigned long ulong; /* Short for unsigned long */
#ifndef longlong_defined
#if defined(HAVE_LONG_LONG) && SIZEOF_LONG != 8
typedef unsigned long long int ulonglong; /* ulong or unsigned long long */
-typedef long long int longlong;
+typedef long long int longlong;
#else
typedef unsigned long ulonglong; /* ulong or unsigned long long */
typedef long longlong;
@@ -650,13 +677,14 @@ typedef off_t os_off_t;
#if defined(__WIN__)
#define socket_errno WSAGetLastError()
-#define SOCKET_EINTR WSAEINTR
+#define SOCKET_EINTR WSAEINTR
#define SOCKET_EAGAIN WSAEINPROGRESS
+#define SOCKET_EWOULDBLOCK WSAEINPROGRESS
#define SOCKET_ENFILE ENFILE
#define SOCKET_EMFILE EMFILE
#elif defined(OS2)
#define socket_errno sock_errno()
-#define SOCKET_EINTR SOCEINTR
+#define SOCKET_EINTR SOCEINTR
#define SOCKET_EAGAIN SOCEINPROGRESS
#define SOCKET_EWOULDBLOCK SOCEWOULDBLOCK
#define SOCKET_ENFILE SOCENFILE
@@ -717,6 +745,20 @@ typedef char bool; /* Ordinary boolean values 0 1 */
#define MY_HOW_OFTEN_TO_ALARM 2 /* How often we want info on screen */
#define MY_HOW_OFTEN_TO_WRITE 1000 /* How often we want info on screen */
+#ifdef HAVE_TIMESPEC_TS_SEC
+#define set_timespec(ABSTIME,SEC) { (ABSTIME).ts_sec=time(0) + (time_t) (SEC); (ABSTIME).ts_nsec=0; }
+#elif defined(__WIN__)
+#define set_timespec(ABSTIME,SEC) { (ABSTIME).tv_sec=time((time_t*)0) + (time_t) (SEC); (ABSTIME).tv_nsec=0; }
+#else
+#define set_timespec(ABSTIME,SEC) \
+{\
+ struct timeval tv;\
+ gettimeofday(&tv,0);\
+ (ABSTIME).tv_sec=tv.tv_sec+(time_t) (SEC);\
+ (ABSTIME).tv_nsec=tv.tv_usec*1000;\
+}
+#endif
+
/*
** Define-funktions for reading and storing in machine independent format
** (low byte first)
@@ -768,7 +810,7 @@ typedef union {
#define float8get(V,M) doubleget((V),(M))
#define float4store(V,M) memcpy((byte*) V,(byte*) (&M),sizeof(float))
#define float8store(V,M) doublestore((V),(M))
-#endif /* __i386__ */
+#endif /* __i386__ */
#ifndef sint2korr
#define sint2korr(A) (int16) (((int16) ((uchar) (A)[0])) +\
@@ -813,9 +855,9 @@ typedef union {
*((uchar*) (T))= (uchar)(def_temp); \
*((uchar*) (T+1))=(uchar)((def_temp >> 8)); }
#define int3store(T,A) { /*lint -save -e734 */\
- *((T))=(char) ((A));\
- *((T)+1)=(char) (((A) >> 8));\
- *((T)+2)=(char) (((A) >> 16)); \
+ *((uchar*)(T))=(uchar) ((A));\
+ *((uchar*) (T)+1)=(uchar) (((A) >> 8));\
+ *((uchar*)(T)+2)=(uchar) (((A) >> 16)); \
/*lint -restore */}
#define int4store(T,A) { *(T)=(char) ((A));\
*((T)+1)=(char) (((A) >> 8));\
@@ -963,4 +1005,13 @@ typedef union {
#define statistic_add(V,C,L) (V)+=(C)
#endif
+/* Macros to make switching between C and C++ mode easier */
+#ifdef __cplusplus
+#define C_MODE_START extern "C" {
+#define C_MODE_END }
+#else
+#define C_MODE_START
+#define C_MODE_END
+#endif
+
#endif /* _global_h */
diff --git a/include/my_list.h b/include/my_list.h
index 7391db70e27..0f56d4c532b 100644
--- a/include/my_list.h
+++ b/include/my_list.h
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#ifndef _list_h_
#define _list_h_
diff --git a/include/my_net.h b/include/my_net.h
index 6a8e98d685c..c2ebe80a343 100644
--- a/include/my_net.h
+++ b/include/my_net.h
@@ -1,28 +1,33 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
-
-/* thread safe version of some common functions */
-
-/* for thread safe my_inet_ntoa */
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-#if !defined(MSDOS) && !defined(__WIN__) && !defined(__BEOS__)
+ 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 */
+
+/*
+ thread safe version of some common functions:
+ my_inet_ntoa
+
+ This file is also used to make handling of sockets and ioctl()
+ portable accross systems.
+
+*/
+
+#ifndef _my_net_h
+#define _my_net_h
+C_MODE_START
+
+#include <errno.h>
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
@@ -32,10 +37,35 @@ extern "C" {
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
-#endif /* !defined(MSDOS) && !defined(__WIN__) */
+#ifdef HAVE_POLL
+#include <sys/poll.h>
+#endif
+#ifdef HAVE_SYS_IOCTL_H
+#include <sys/ioctl.h>
+#endif
+
+#if !defined(MSDOS) && !defined(__WIN__) && !defined(HAVE_BROKEN_NETINET_INCLUDES) && !defined(__BEOS__)
+#include <netinet/in_systm.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#if !defined(alpha_linux_port)
+#include <netinet/tcp.h>
+#endif
+#endif
+
+#if defined(__EMX__)
+#include <sys/ioctl.h>
+#define ioctlsocket(A,B,C) ioctl((A),(B),(void *)(C),sizeof(*(C)))
+#undef HAVE_FCNTL
+#endif /* defined(__EMX__) */
+
+#if defined(MSDOS) || defined(__WIN__)
+#define O_NONBLOCK 1 /* For emulation of fcntl() */
+#endif
+
+/* Thread safe or portable version of some functions */
void my_inet_ntoa(struct in_addr in, char *buf);
-#ifdef __cplusplus
-}
+C_MODE_END
#endif
diff --git a/include/my_no_pthread.h b/include/my_no_pthread.h
index 2ff8896fa74..81c0de580db 100644
--- a/include/my_no_pthread.h
+++ b/include/my_no_pthread.h
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 undefs some pthread mutex locks when one isn't using threads
diff --git a/include/my_nosys.h b/include/my_nosys.h
index 5991904f260..605906f0e07 100644
--- a/include/my_nosys.h
+++ b/include/my_nosys.h
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/*
Header to remove use of my_functions in functions where we need speed and
diff --git a/include/my_pthread.h b/include/my_pthread.h
index cd72bcced83..4ca42339897 100644
--- a/include/my_pthread.h
+++ b/include/my_pthread.h
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/* Defines to make different thread packages compatible */
@@ -133,16 +132,17 @@ void pthread_exit(void *a); /* was #define pthread_exit(A) ExitThread(A)*/
#define pthread_equal(A,B) ((A) == (B))
#ifdef OS2
-int pthread_mutex_init (pthread_mutex_t *, const pthread_mutexattr_t *);
-int pthread_mutex_lock (pthread_mutex_t *);
-int pthread_mutex_unlock (pthread_mutex_t *);
-int pthread_mutex_destroy (pthread_mutex_t *);
+extern int pthread_mutex_init (pthread_mutex_t *, const pthread_mutexattr_t *);
+extern int pthread_mutex_lock (pthread_mutex_t *);
+extern int pthread_mutex_unlock (pthread_mutex_t *);
+extern int pthread_mutex_destroy (pthread_mutex_t *);
#define my_pthread_setprio(A,B) DosSetPriority(PRTYS_THREAD,PRTYC_NOCHANGE, B, A)
#define pthread_kill(A,B) raise(B)
#define pthread_exit(A) pthread_dummy()
#else
#define pthread_mutex_init(A,B) InitializeCriticalSection(A)
#define pthread_mutex_lock(A) (EnterCriticalSection(A),0)
+#define pthread_mutex_trylock(A) (WaitForSingleObject((A), 0) == WAIT_TIMEOUT)
#define pthread_mutex_unlock(A) LeaveCriticalSection(A)
#define pthread_mutex_destroy(A) DeleteCriticalSection(A)
#define my_pthread_setprio(A,B) SetThreadPriority(GetCurrentThread(), (B))
@@ -446,6 +446,14 @@ struct hostent *my_gethostbyname_r(const char *name,
#endif /* defined(__WIN__) */
+#if defined(HPUX) && !defined(DONT_REMAP_PTHREAD_FUNCTIONS)
+#define pthread_cond_timedwait(a,b,c) my_pthread_cond_timedwait((a),(b),(c))
+#define pthread_mutex_trylock(a) my_pthread_mutex_trylock((a))
+int my_pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex,
+ struct timespec *abstime);
+int my_pthread_mutex_trylock(pthread_mutex_t *mutex);
+#endif
+
/* safe_mutex adds checking to mutex for easier debugging */
typedef struct st_safe_mutex_t
@@ -476,6 +484,7 @@ int safe_cond_timedwait(pthread_cond_t *cond, safe_mutex_t *mp,
#undef pthread_mutex_t
#undef pthread_cond_wait
#undef pthread_cond_timedwait
+#undef pthread_mutex_trylock
#define pthread_mutex_init(A,B) safe_mutex_init((A),(B))
#define pthread_mutex_lock(A) safe_mutex_lock((A),__FILE__,__LINE__)
#define pthread_mutex_unlock(A) safe_mutex_unlock((A),__FILE__,__LINE__)
@@ -623,5 +632,4 @@ extern struct st_my_thread_var *_my_thread_var(void) __attribute__ ((const));
#ifdef __cplusplus
}
#endif
-
#endif /* _my_ptread_h */
diff --git a/include/my_semaphore.h b/include/my_semaphore.h
new file mode 100644
index 00000000000..484423150f7
--- /dev/null
+++ b/include/my_semaphore.h
@@ -0,0 +1,51 @@
+/*
+ * Module: semaphore.h
+ *
+ * Purpose:
+ * Semaphores aren't actually part of the PThreads standard.
+ * They are defined by the POSIX Standard:
+ *
+ * POSIX 1003.1b-1993 (POSIX.1b)
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright (C) 1998
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA
+ */
+
+/* This is hacked by Monty to be included in mysys library */
+
+#ifndef _my_semaphore_h_
+#define _my_semaphore_h_
+
+#ifndef __WIN__
+#include <semaphore.h>
+#else
+
+C_MODE_START
+
+typedef HANDLE sem_t;
+int sem_init (sem_t * sem, int pshared, unsigned int value);
+int sem_destroy (sem_t * sem);
+int sem_trywait (sem_t * sem);
+int sem_wait (sem_t * sem);
+int sem_post (sem_t * sem);
+int sem_post_multiple (sem_t * sem,int count);
+int sem_getvalue (sem_t * sem, int * sval);
+
+C_MODE_END
+#endif /* __WIN__ */
+#endif /* !_my_semaphore_h_ */
diff --git a/include/my_sys.h b/include/my_sys.h
index 5b45f6a91e5..61f93d665cd 100644
--- a/include/my_sys.h
+++ b/include/my_sys.h
@@ -1,25 +1,22 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#ifndef _my_sys_h
#define _my_sys_h
-#ifdef __cplusplus
-extern "C" {
-#endif
+C_MODE_START
#ifdef HAVE_AIOWAIT
#include <sys/asynch.h> /* Used by record-cache */
@@ -59,6 +56,9 @@ extern int NEAR my_errno; /* Last error in mysys */
#define MY_WME 16 /* Write message on error */
#define MY_WAIT_IF_FULL 32 /* Wait and try again if disk full error */
#define MY_RAID 64 /* Support for RAID (not the "Johnson&Johnson"-s one ;) */
+#define MY_FULL_IO 512 /* For my_read - loop intil I/O
+ is complete
+ */
#define MY_DONT_CHECK_FILESIZE 128 /* Option to init_io_cache() */
#define MY_LINK_WARNING 32 /* my_redel() gives warning if links */
#define MY_COPYTIME 64 /* my_redel() copys time */
@@ -90,6 +90,16 @@ extern int NEAR my_errno; /* Last error in mysys */
#define ME_COLOUR2 ((2 << ME_HIGHBYTE))
#define ME_COLOUR3 ((3 << ME_HIGHBYTE))
+ /* Bits in last argument to fn_format */
+#define MY_REPLACE_DIR 1 /* replace dir in name with 'dir' */
+#define MY_REPLACE_EXT 2 /* replace extension with 'ext' */
+#define MY_UNPACK_FILENAME 4 /* Unpack name (~ -> home) */
+#define MY_PACK_FILENAME 8 /* Pack name (home -> ~) */
+#define MY_RESOLVE_SYMLINKS 16 /* Resolve all symbolic links */
+#define MY_RETURN_REAL_PATH 32 /* return full path for file */
+#define MY_SAFE_PATH 64 /* Return NULL if too long path */
+#define MY_RELATIVE_PATH 128 /* name is relative to 'dir' */
+
/* My seek flags */
#define MY_SEEK_SET 0
#define MY_SEEK_CUR 1
@@ -106,10 +116,12 @@ extern int NEAR my_errno; /* Last error in mysys */
#define MY_WAIT_FOR_USER_TO_FIX_PANIC 60 /* in seconds */
#define MY_WAIT_GIVE_USER_A_MESSAGE 10 /* Every 10 times of prev */
#define MIN_COMPRESS_LENGTH 50 /* Don't compress small bl. */
-#define KEYCACHE_BLOCK_SIZE 1024
+#define DEFAULT_KEYCACHE_BLOCK_SIZE 1024
+#define MAX_KEYCACHE_BLOCK_SIZE 16384
/* root_alloc flags */
#define MY_KEEP_PREALLOC 1
+#define MY_MARK_BLOCKS_FREE 2 /* move used to free list and reuse them */
/* defines when allocating data */
@@ -189,9 +201,10 @@ extern char *get_charsets_dir(char *buf);
/* statistics */
extern ulong _my_cache_w_requests,_my_cache_write,_my_cache_r_requests,
_my_cache_read;
-extern ulong _my_blocks_used,_my_blocks_changed;
+extern ulong _my_blocks_used,_my_blocks_changed;
+extern uint key_cache_block_size;
extern ulong my_file_opened,my_stream_opened, my_tmp_file_created;
-extern my_bool key_cache_inited;
+extern my_bool key_cache_inited, my_init_done;
/* Point to current my_message() */
extern void (*my_sigtstp_cleanup)(void),
@@ -227,7 +240,10 @@ typedef struct st_typelib { /* Different types saved here */
const char **type_names;
} TYPELIB;
-enum cache_type {READ_CACHE,WRITE_CACHE,READ_FIFO,READ_NET,WRITE_NET};
+enum cache_type {READ_CACHE,WRITE_CACHE,
+ SEQ_READ_APPEND /* sequential read or append */,
+ READ_FIFO,
+ READ_NET,WRITE_NET};
enum flush_type { FLUSH_KEEP, FLUSH_RELEASE, FLUSH_IGNORE_CHANGED,
FLUSH_FORCE_WRITE};
@@ -246,7 +262,8 @@ typedef struct st_record_cache /* Used when cacheing records */
} RECORD_CACHE;
enum file_type { UNOPEN = 0, FILE_BY_OPEN, FILE_BY_CREATE,
- STREAM_BY_FOPEN, STREAM_BY_FDOPEN, FILE_BY_MKSTEMP };
+ STREAM_BY_FOPEN, STREAM_BY_FDOPEN, FILE_BY_MKSTEMP,
+ FILE_BY_DUP };
extern struct my_file_info
{
@@ -270,20 +287,111 @@ typedef struct st_dynamic_string {
uint length,max_length,alloc_increment;
} DYNAMIC_STRING;
+struct st_io_cache;
+typedef int (*IO_CACHE_CALLBACK)(struct st_io_cache*);
+
typedef struct st_io_cache /* Used when cacheing files */
{
+ /* pos_in_file is offset in file corresponding to the first byte of
+ byte* buffer. end_of_file is the offset of end of file for READ_CACHE
+ and WRITE_CACHE. For SEQ_READ_APPEND it the maximum of the actual
+ end of file and the position represented by read_end.
+ */
my_off_t pos_in_file,end_of_file;
- byte *rc_pos,*rc_end,*buffer,*rc_request_pos;
+ /* read_pos points to current read position in the buffer
+ read_end is the non-inclusive boundary in the buffer for the currently
+ valid read area
+ buffer is the read buffer
+ not sure about request_pos except that it is used in async_io
+ */
+ byte *read_pos,*read_end,*buffer,*request_pos;
+ /* write_buffer is used only in WRITE caches and in SEQ_READ_APPEND to
+ buffer writes
+ append_read_pos is only used in SEQ_READ_APPEND, and points to the
+ current read position in the write buffer. Note that reads in
+ SEQ_READ_APPEND caches can happen from both read buffer (byte* buffer),
+ and write buffer (byte* write_buffer).
+ write_pos points to current write position in the write buffer and
+ write_end is the non-inclusive boundary of the valid write area
+ */
+ byte *write_buffer, *append_read_pos, *write_pos, *write_end;
+ /* current_pos and current_end are convenience variables used by
+ my_b_tell() and other routines that need to know the current offset
+ current_pos points to &write_pos, and current_end to &write_end in a
+ WRITE_CACHE, and &read_pos and &read_end respectively otherwise
+ */
+ byte **current_pos, **current_end;
+/* The lock is for append buffer used in SEQ_READ_APPEND cache */
+#ifdef THREAD
+ pthread_mutex_t append_buffer_lock;
+ /* need mutex copying from append buffer to read buffer */
+#endif
+ /* a caller will use my_b_read() macro to read from the cache
+ if the data is already in cache, it will be simply copied with
+ memcpy() and internal variables will be accordinging updated with
+ no functions invoked. However, if the data is not fully in the cache,
+ my_b_read() will call read_function to fetch the data. read_function
+ must never be invoked directly
+ */
int (*read_function)(struct st_io_cache *,byte *,uint);
+ /* same idea as in the case of read_function, except my_b_write() needs to
+ be replaced with my_b_append() for a SEQ_READ_APPEND cache
+ */
+ int (*write_function)(struct st_io_cache *,const byte *,uint);
+ /* specifies the type of the cache. Depending on the type of the cache
+ certain operations might not be available and yield unpredicatable
+ results. Details to be documented later
+ */
+ enum cache_type type;
+ /* callbacks when the actual read I/O happens. These were added and
+ are currently used for binary logging of LOAD DATA INFILE - when a
+ block is read from the file, we create a block create/append event, and
+ when IO_CACHE is closed, we create an end event. These functions could,
+ of course be used for other things
+ */
+ IO_CACHE_CALLBACK pre_read;
+ IO_CACHE_CALLBACK post_read;
+ IO_CACHE_CALLBACK pre_close;
+ void* arg; /* for use by pre/post_read */
char *file_name; /* if used with 'open_cached_file' */
char *dir,*prefix;
- File file;
+ File file; /* file descriptor */
+ /* seek_not_done is set by my_b_seek() to inform the upcoming read/write
+ operation that a seek needs to be preformed prior to the actual I/O
+ error is 0 if the cache operation was successful, -1 if there was a
+ "hard" error, and the actual number of I/O-ed bytes if the read/write was
+ partial
+ */
int seek_not_done,error;
+ /* buffer_length is the size of memory allocated for buffer or write_buffer
+ read_length is the same as buffer_length except when we use async io
+ not sure why we need it
+ */
uint buffer_length,read_length;
myf myflags; /* Flags used to my_read/my_write */
- enum cache_type type;
+ /*
+ alloced_buffer is 1 if the buffer was allocated by init_io_cache() and
+ 0 if it was supplied by the user
+ Currently READ_NET is the only one that will use a buffer allocated
+ somewhere else
+ */
+ my_bool alloced_buffer;
+ /* init_count is incremented every time we call init_io_cache()
+ It is not reset in end_io_cache(). This variable
+ was introduced for slave relay logs - RELAY_LOG_INFO stores a pointer
+ to IO_CACHE that could in some cases refer to the IO_CACHE of the
+ currently active relay log. The IO_CACHE then could be closed,
+ re-opened and start pointing to a different log file. In that case,
+ we could not know reliably if this happened without init_count
+ one must be careful with bzero() prior to the subsequent init_io_cache()
+ call
+ */
+ int init_count;
#ifdef HAVE_AIOWAIT
+ /* as inidicated by ifdef, this is for async I/O, we will have
+ Sinisa comment this some time
+ */
uint inited;
my_off_t aio_read_pos;
my_aio_result aio_result;
@@ -300,35 +408,41 @@ typedef int (*qsort2_cmp)(const void *, const void *, const void *);
#define my_b_EOF INT_MIN
#define my_b_read(info,Buffer,Count) \
- ((info)->rc_pos + (Count) <= (info)->rc_end ?\
- (memcpy(Buffer,(info)->rc_pos,(size_t) (Count)), \
- ((info)->rc_pos+=(Count)),0) :\
+ ((info)->read_pos + (Count) <= (info)->read_end ?\
+ (memcpy(Buffer,(info)->read_pos,(size_t) (Count)), \
+ ((info)->read_pos+=(Count)),0) :\
(*(info)->read_function)((info),Buffer,Count))
+#define my_b_write(info,Buffer,Count) \
+ ((info)->write_pos + (Count) <=(info)->write_end ?\
+ (memcpy((info)->write_pos, (Buffer), (size_t)(Count)),\
+ ((info)->write_pos+=(Count)),0) : \
+ (*(info)->write_function)((info),(Buffer),(Count)))
+
+
#define my_b_get(info) \
- ((info)->rc_pos != (info)->rc_end ?\
- ((info)->rc_pos++, (int) (uchar) (info)->rc_pos[-1]) :\
+ ((info)->read_pos != (info)->read_end ?\
+ ((info)->read_pos++, (int) (uchar) (info)->read_pos[-1]) :\
_my_b_get(info))
-#define my_b_write(info,Buffer,Count) \
- ((info)->rc_pos + (Count) <= (info)->rc_end ?\
- (memcpy((info)->rc_pos,Buffer,(size_t) (Count)), \
- ((info)->rc_pos+=(Count)),0) :\
- _my_b_write(info,Buffer,Count))
-
/* my_b_write_byte dosn't have any err-check */
#define my_b_write_byte(info,chr) \
- (((info)->rc_pos < (info)->rc_end) ?\
- ((*(info)->rc_pos++)=(chr)) :\
- (_my_b_write(info,0,0) , ((*(info)->rc_pos++)=(chr))))
+ (((info)->write_pos < (info)->write_end) ?\
+ ((*(info)->write_pos++)=(chr)) :\
+ (_my_b_write(info,0,0) , ((*(info)->write_pos++)=(chr))))
#define my_b_fill_cache(info) \
- (((info)->rc_end=(info)->rc_pos),(*(info)->read_function)(info,0,0))
+ (((info)->read_end=(info)->read_pos),(*(info)->read_function)(info,0,0))
#define my_b_tell(info) ((info)->pos_in_file + \
- ((info)->rc_pos - (info)->rc_request_pos))
+ (uint) (*(info)->current_pos - (info)->request_pos))
+
+/* tell write offset in the SEQ_APPEND cache */
+my_off_t my_b_append_tell(IO_CACHE* info);
+
+#define my_b_bytes_in_cache(info) (uint) (*(info)->current_end - \
+ *(info)->current_pos)
-#define my_b_bytes_in_cache(info) ((uint) ((info)->rc_end - (info)->rc_pos))
typedef struct st_changeable_var {
const char *name; /* Name of variable */
@@ -380,6 +494,7 @@ extern File my_register_filename(File fd, const char *FileName,
extern File my_create(const char *FileName,int CreateFlags,
int AccsesFlags, myf MyFlags);
extern int my_close(File Filedes,myf MyFlags);
+extern File my_dup(File file, myf MyFlags);
extern int my_mkdir(const char *dir, int Flags, myf MyFlags);
extern int my_readlink(char *to, const char *filename, myf MyFlags);
extern int my_realpath(char *to, const char *filename, myf MyFlags);
@@ -457,12 +572,12 @@ extern uint dirname_part(my_string to,const char *name);
extern uint dirname_length(const char *name);
#define base_name(A) (A+dirname_length(A))
extern int test_if_hard_path(const char *dir_name);
-extern char *convert_dirname(my_string name);
+extern char *convert_dirname(char *to, const char *from, const char *from_end);
extern void to_unix_path(my_string name);
extern my_string fn_ext(const char *name);
extern my_string fn_same(my_string toname,const char *name,int flag);
-extern my_string fn_format(my_string to,const char *name,const char *dsk,
- const char *form,int flag);
+extern my_string fn_format(my_string to,const char *name,const char *dir,
+ const char *form, uint flag);
extern size_s strlength(const char *str);
extern void pack_dirname(my_string to,const char *from);
extern uint unpack_dirname(my_string to,const char *from);
@@ -521,13 +636,18 @@ extern my_bool reinit_io_cache(IO_CACHE *info,enum cache_type type,
my_off_t seek_offset,pbool use_async_io,
pbool clear_cache);
extern int _my_b_read(IO_CACHE *info,byte *Buffer,uint Count);
+extern int _my_b_seq_read(IO_CACHE *info,byte *Buffer,uint Count);
extern int _my_b_net_read(IO_CACHE *info,byte *Buffer,uint Count);
extern int _my_b_get(IO_CACHE *info);
extern int _my_b_async_read(IO_CACHE *info,byte *Buffer,uint Count);
extern int _my_b_write(IO_CACHE *info,const byte *Buffer,uint Count);
+extern int my_b_append(IO_CACHE *info,const byte *Buffer,uint Count);
extern int my_block_write(IO_CACHE *info, const byte *Buffer,
uint Count, my_off_t pos);
-extern int flush_io_cache(IO_CACHE *info);
+extern int _flush_io_cache(IO_CACHE *info, int need_append_buffer_lock);
+
+#define flush_io_cache(info) _flush_io_cache((info),1)
+
extern int end_io_cache(IO_CACHE *info);
extern uint my_b_fill(IO_CACHE *info);
extern void my_b_seek(IO_CACHE *info,my_off_t pos);
@@ -581,7 +701,9 @@ extern void my_free_lock(byte *ptr,myf flags);
void init_alloc_root(MEM_ROOT *mem_root, uint block_size, uint pre_alloc_size);
gptr alloc_root(MEM_ROOT *mem_root,unsigned int Size);
void free_root(MEM_ROOT *root, myf MyFLAGS);
+void set_prealloc_root(MEM_ROOT *root, char *ptr);
char *strdup_root(MEM_ROOT *root,const char *str);
+char *strmake_root(MEM_ROOT *root,const char *str,uint len);
char *memdup_root(MEM_ROOT *root,const char *str,uint len);
void load_defaults(const char *conf_file, const char **groups,
int *argc, char ***argv);
@@ -591,6 +713,8 @@ my_bool my_compress(byte *, ulong *, ulong *);
my_bool my_uncompress(byte *, ulong *, ulong *);
byte *my_compress_alloc(const byte *packet, ulong *len, ulong *complen);
ulong checksum(const byte *mem, uint count);
+uint my_bit_log2(ulong value);
+
#if defined(_MSC_VER) && !defined(__WIN__)
extern void sleep(int sec);
@@ -599,8 +723,6 @@ extern void sleep(int sec);
extern my_bool have_tcpip; /* Is set if tcpip is used */
#endif
-#ifdef __cplusplus
-}
-#endif
+C_MODE_END
#include "raid.h"
#endif /* _my_sys_h */
diff --git a/include/my_tree.h b/include/my_tree.h
index 0a227ea3944..8b326a19518 100644
--- a/include/my_tree.h
+++ b/include/my_tree.h
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#ifndef _tree_h
#define _tree_h
@@ -32,6 +31,9 @@ typedef enum { left_root_right, right_root_left } TREE_WALK;
typedef uint32 element_count;
typedef int (*tree_walk_action)(void *,element_count,void *);
+typedef enum { free_init, free_free, free_end } TREE_FREE;
+typedef void (*tree_element_free)(void*, TREE_FREE, void *);
+
#ifdef MSDOS
typedef struct st_tree_element {
struct st_tree_element *left,*right;
@@ -49,18 +51,22 @@ typedef struct st_tree_element {
typedef struct st_tree {
TREE_ELEMENT *root,null_element;
TREE_ELEMENT **parents[MAX_TREE_HIGHT];
- uint offset_to_key,elements_in_tree,size_of_element;
- qsort_cmp compare;
+ uint offset_to_key,elements_in_tree,size_of_element,memory_limit,allocated;
+ qsort_cmp2 compare;
+ void* custom_arg;
MEM_ROOT mem_root;
my_bool with_delete;
- void (*free)(void *);
+ tree_element_free free;
} TREE;
- /* Functions on hole tree */
-void init_tree(TREE *tree,uint default_alloc_size, int element_size,
- qsort_cmp compare, my_bool with_delete,
- void (*free_element)(void*));
+ /* Functions on whole tree */
+void init_tree(TREE *tree, uint default_alloc_size, uint memory_limit,
+ int size, qsort_cmp2 compare, my_bool with_delete,
+ tree_element_free free_element, void *custom_arg);
void delete_tree(TREE*);
+void reset_tree(TREE*);
+ /* similar to delete tree, except we do not my_free() blocks in mem_root
+ */
#define is_tree_inited(tree) ((tree)->root != 0)
/* Functions on leafs */
diff --git a/include/myisam.h b/include/myisam.h
index 9ecb5ef4294..35953496a47 100644
--- a/include/myisam.h
+++ b/include/myisam.h
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 should be included when using myisam_funktions */
@@ -46,6 +45,11 @@ extern "C" {
/* Max extra space to use when sorting keys */
#define MI_MAX_TEMP_LENGTH 256*1024L*1024L
+/* Possible values for myisam_block_size (must be power of 2) */
+#define MI_KEY_BLOCK_LENGTH 1024 /* default key block length */
+#define MI_MIN_KEY_BLOCK_LENGTH 1024 /* Min key block length */
+#define MI_MAX_KEY_BLOCK_LENGTH 16384
+
#define mi_portable_sizeof_char_ptr 8
typedef uint32 ha_checksum;
@@ -68,6 +72,7 @@ typedef struct st_mi_isaminfo /* Struct from h_info */
ulong mean_reclength; /* Mean recordlength (if packed) */
ulonglong auto_increment;
ulonglong key_map; /* Which keys are used */
+ char *data_file_name, *index_file_name;
uint keys; /* Number of keys in use */
uint options; /* HA_OPTION_... used */
int errkey, /* With key was dupplicated on err */
@@ -86,6 +91,7 @@ typedef struct st_mi_isaminfo /* Struct from h_info */
typedef struct st_mi_create_info
{
+ char *index_file_name, *data_file_name; /* If using symlinks */
ha_rows max_rows;
ha_rows reloc_rows;
ulonglong auto_increment;
@@ -120,6 +126,7 @@ typedef struct st_mi_keydef /* Key definition with open & info */
uint16 keysegs; /* Number of key-segment */
uint16 flag; /* NOSAME, PACK_USED */
+ uint8 key_alg; /* BTREE, RTREE */
uint16 block_length; /* Length of keyblock (auto) */
uint16 underflow_block_length; /* When to execute underflow */
uint16 keylength; /* Tot length of keyparts (auto) */
@@ -184,12 +191,15 @@ typedef struct st_columndef /* column information */
#endif
} MI_COLUMNDEF;
+/* invalidator function reference for Query Cache */
+typedef void (* invalidator_by_filename)(const char * filename);
extern my_string myisam_log_filename; /* Name of logfile */
extern uint myisam_block_size;
-extern my_bool myisam_flush,myisam_delay_key_write;
+extern my_bool myisam_flush,myisam_delay_key_write,myisam_single_user;
extern my_bool myisam_concurrent_insert;
extern my_off_t myisam_max_temp_length,myisam_max_extra_temp_length;
+extern ulong myisam_bulk_insert_tree_size;
/* Prototypes for myisam-functions */
@@ -219,7 +229,7 @@ extern my_off_t mi_position(struct st_myisam_info *file);
extern int mi_status(struct st_myisam_info *info, MI_ISAMINFO *x, uint flag);
extern int mi_lock_database(struct st_myisam_info *file,int lock_type);
extern int mi_create(const char *name,uint keys,MI_KEYDEF *keydef,
- uint columns, MI_COLUMNDEF *columndef,
+ uint columns, MI_COLUMNDEF *columndef,
uint uniques, MI_UNIQUEDEF *uniquedef,
MI_CREATE_INFO *create_info, uint flags);
extern int mi_delete_table(const char *name);
@@ -296,17 +306,17 @@ typedef struct st_sort_info {
struct st_mi_check_param *param;
enum data_file_type new_data_file_type;
SORT_KEY_BLOCKS *key_block,*key_block_end;
- uint key,find_length;
+ uint key,find_length,real_key_length;
my_off_t pos,max_pos,filepos,start_recpos,filelength,dupp,buff_length;
ha_rows max_records;
ulonglong unique[MI_MAX_KEY_SEG+1];
my_bool fix_datafile;
char *record,*buff;
+ void *wordlist, *wordptr;
MI_KEYDEF *keyinfo;
MI_KEYSEG *keyseg;
} SORT_INFO;
-
typedef struct st_mi_check_param
{
ulonglong auto_increment_value;
diff --git a/include/myisammrg.h b/include/myisammrg.h
index a797c954614..acf80ee2adf 100644
--- a/include/myisammrg.h
+++ b/include/myisammrg.h
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+/* Copyright (C) 2000 MySQL AB
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
- This library is distributed in the hope that it will be useful,
+ 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
- Library General Public License for more details.
+ 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 Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 should be included when using merge_isam_funktions */
@@ -34,6 +33,13 @@ extern "C" {
#define MYRG_NAME_EXT ".MRG"
+/* In which table to INSERT rows */
+#define MERGE_INSERT_DISABLED 0
+#define MERGE_INSERT_TO_FIRST 1
+#define MERGE_INSERT_TO_LAST 2
+
+extern TYPELIB merge_insert_method;
+
/* Param to/from myrg_info */
typedef struct st_mymerge_info /* Struct from h_info */
@@ -44,7 +50,7 @@ typedef struct st_mymerge_info /* Struct from h_info */
ulonglong data_file_length;
uint reclength; /* Recordlength */
int errkey; /* With key was dupplicated on err */
- uint options; /* HA_OPTIONS_... used */
+ uint options; /* HA_OPTION_... used */
} MYMERGE_INFO;
typedef struct st_myrg_table_info
@@ -56,6 +62,7 @@ typedef struct st_myrg_table_info
typedef struct st_myrg_info
{
MYRG_TABLE *open_tables,*current_table,*end_table,*last_used_table;
+ uint merge_insert_method;
ulonglong records; /* records in tables */
ulonglong del; /* Removed records */
ulonglong data_file_length;
@@ -81,11 +88,13 @@ extern int myrg_rkey(MYRG_INFO *file,byte *buf,int inx,const byte *key,
extern int myrg_rrnd(MYRG_INFO *file,byte *buf,ulonglong pos);
extern int myrg_rsame(MYRG_INFO *file,byte *record,int inx);
extern int myrg_update(MYRG_INFO *file,const byte *old,byte *new_rec);
+extern int myrg_write(MYRG_INFO *info,byte *rec);
extern int myrg_status(MYRG_INFO *file,MYMERGE_INFO *x,int flag);
extern int myrg_lock_database(MYRG_INFO *file,int lock_type);
-extern int myrg_create(const char *name,const char **table_names,
- my_bool fix_names);
+extern int myrg_create(const char *name, const char **table_names,
+ uint insert_method, my_bool fix_names);
extern int myrg_extra(MYRG_INFO *file,enum ha_extra_function function);
+extern void myrg_extrafunc(MYRG_INFO *info,invalidator_by_filename inv);
extern ha_rows myrg_records_in_range(MYRG_INFO *info,int inx,
const byte *start_key,uint start_key_len,
enum ha_rkey_function start_search_flag,
diff --git a/include/myisampack.h b/include/myisampack.h
index a51cdc7e6eb..31666bb184c 100644
--- a/include/myisampack.h
+++ b/include/myisampack.h
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/*
Storing of values in high byte first order.
diff --git a/include/mysql.h b/include/mysql.h
index 0bd5b7092b8..074ea0a1876 100644
--- a/include/mysql.h
+++ b/include/mysql.h
@@ -1,21 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
-/* defines for the libmysql library */
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#ifndef _mysql_h
#define _mysql_h
@@ -28,12 +25,10 @@
#undef __WIN__
#endif
-#ifndef MYSQL_SERVER
#ifdef __cplusplus
extern "C" {
#endif
-#endif
-
+
#ifndef _global_h /* If not standard header */
#include <sys/types.h>
#ifdef __LCC__
@@ -50,32 +45,15 @@ typedef char my_bool;
#endif
typedef char * gptr;
-#ifndef ST_USED_MEM_DEFINED
-#define ST_USED_MEM_DEFINED
-typedef struct st_used_mem { /* struct for once_alloc */
- struct st_used_mem *next; /* Next block in use */
- unsigned int left; /* memory left in block */
- unsigned int size; /* size of block */
-} USED_MEM;
-typedef struct st_mem_root {
- USED_MEM *free;
- USED_MEM *used;
- USED_MEM *pre_alloc;
- unsigned int min_malloc;
- unsigned int block_size;
-
- void (*error_handler)(void);
-} MEM_ROOT;
-#endif
-
#ifndef my_socket_defined
#ifdef __WIN__
#define my_socket SOCKET
#else
typedef int my_socket;
-#endif
-#endif
-#endif
+#endif /* __WIN__ */
+#endif /* my_socket_defined */
+#endif /* _global_h */
+
#include "mysql_com.h"
#include "mysql_version.h"
@@ -92,12 +70,14 @@ extern char *mysql_unix_port;
typedef struct st_mysql_field {
char *name; /* Name of column */
char *table; /* Table of column if column was a field */
+ char *org_table; /* Org table name if table was an alias */
+ char *db; /* Database for table */
char *def; /* Default value (set by mysql_list_fields) */
- enum enum_field_types type; /* Type of field. Se mysql_com.h for types */
- unsigned int length; /* Width of column */
- unsigned int max_length; /* Max width of selected set */
+ unsigned long length; /* Width of column */
+ unsigned long max_length; /* Max width of selected set */
unsigned int flags; /* Div flags */
unsigned int decimals; /* Number of decimals in field */
+ enum enum_field_types type; /* Type of field. Se mysql_com.h for types */
} MYSQL_FIELD;
typedef char **MYSQL_ROW; /* return data as array of strings */
@@ -120,6 +100,24 @@ typedef struct st_mysql_rows {
typedef MYSQL_ROWS *MYSQL_ROW_OFFSET; /* offset to current row */
+#ifndef ST_USED_MEM_DEFINED
+#define ST_USED_MEM_DEFINED
+typedef struct st_used_mem { /* struct for once_alloc */
+ struct st_used_mem *next; /* Next block in use */
+ unsigned int left; /* memory left in block */
+ unsigned int size; /* size of block */
+} USED_MEM;
+typedef struct st_mem_root {
+ USED_MEM *free;
+ USED_MEM *used;
+ USED_MEM *pre_alloc;
+ unsigned int min_malloc;
+ unsigned int block_size;
+
+ void (*error_handler)(void);
+} MEM_ROOT;
+#endif
+
typedef struct st_mysql_data {
my_ulonglong rows;
unsigned int fields;
@@ -129,15 +127,31 @@ typedef struct st_mysql_data {
struct st_mysql_options {
unsigned int connect_timeout,client_flag;
- my_bool compress,named_pipe;
unsigned int port;
char *host,*init_command,*user,*password,*unix_socket,*db;
char *my_cnf_file,*my_cnf_group, *charset_dir, *charset_name;
- my_bool use_ssl; /* if to use SSL or not */
char *ssl_key; /* PEM key file */
char *ssl_cert; /* PEM cert file */
char *ssl_ca; /* PEM CA file */
char *ssl_capath; /* PEM directory of CA-s? */
+ char *ssl_cipher; /* cipher to use */
+ my_bool use_ssl; /* if to use SSL or not */
+ my_bool compress,named_pipe;
+ /*
+ on connect, find out the replication role of the server, and
+ establish connections to all the peers
+ */
+ my_bool rpl_probe;
+ /*
+ each call to mysql_real_query() will parse it to tell if it is a read
+ or a write, and direct it to the slave or the master
+ */
+ my_bool rpl_parse;
+ /*
+ if set, never read from a master,only from slave, when doing
+ a read that is replication-aware
+ */
+ my_bool no_master_reads;
};
enum mysql_option { MYSQL_OPT_CONNECT_TIMEOUT, MYSQL_OPT_COMPRESS,
@@ -149,46 +163,106 @@ enum mysql_option { MYSQL_OPT_CONNECT_TIMEOUT, MYSQL_OPT_COMPRESS,
enum mysql_status { MYSQL_STATUS_READY,MYSQL_STATUS_GET_RESULT,
MYSQL_STATUS_USE_RESULT};
+/*
+ There are three types of queries - the ones that have to go to
+ the master, the ones that go to a slave, and the adminstrative
+ type which must happen on the pivot connectioin
+*/
+enum mysql_rpl_type { MYSQL_RPL_MASTER, MYSQL_RPL_SLAVE,
+ MYSQL_RPL_ADMIN };
+
+
typedef struct st_mysql {
NET net; /* Communication parameters */
gptr connector_fd; /* ConnectorFd for SSL */
char *host,*user,*passwd,*unix_socket,*server_version,*host_info,
*info,*db;
- unsigned int port,client_flag,server_capabilities;
- unsigned int protocol_version;
- unsigned int field_count;
- unsigned int server_status;
- unsigned long thread_id; /* Id for connection in server */
+ struct charset_info_st *charset;
+ MYSQL_FIELD *fields;
+ MEM_ROOT field_alloc;
my_ulonglong affected_rows;
my_ulonglong insert_id; /* id if insert on table with NEXTNR */
my_ulonglong extra_info; /* Used by mysqlshow */
+ unsigned long thread_id; /* Id for connection in server */
unsigned long packet_length;
+ unsigned int port,client_flag,server_capabilities;
+ unsigned int protocol_version;
+ unsigned int field_count;
+ unsigned int server_status;
+ unsigned int server_language;
+ struct st_mysql_options options;
enum mysql_status status;
- MYSQL_FIELD *fields;
- MEM_ROOT field_alloc;
my_bool free_me; /* If free in mysql_close */
my_bool reconnect; /* set to 1 if automatic reconnect */
- struct st_mysql_options options;
char scramble_buff[9];
- struct charset_info_st *charset;
- unsigned int server_language;
+
+ /*
+ Set if this is the original connection, not a master or a slave we have
+ added though mysql_rpl_probe() or mysql_set_master()/ mysql_add_slave()
+ */
+ my_bool rpl_pivot;
+ /* pointers to the master, and the next slave
+ connections, points to itself if lone connection */
+ struct st_mysql* master, *next_slave;
+
+ struct st_mysql* last_used_slave; /* needed for round-robin slave pick */
+ /* needed for send/read/store/use result to work correctly with replication */
+ struct st_mysql* last_used_con;
} MYSQL;
typedef struct st_mysql_res {
my_ulonglong row_count;
- unsigned int field_count, current_field;
MYSQL_FIELD *fields;
MYSQL_DATA *data;
MYSQL_ROWS *data_cursor;
+ unsigned long *lengths; /* column lengths of current row */
+ MYSQL *handle; /* for unbuffered reads */
MEM_ROOT field_alloc;
+ unsigned int field_count, current_field;
MYSQL_ROW row; /* If unbuffered read */
MYSQL_ROW current_row; /* buffer to current row */
- unsigned long *lengths; /* column lengths of current row */
- MYSQL *handle; /* for unbuffered reads */
- my_bool eof; /* Used my mysql_fetch_row */
+ my_bool eof; /* Used by mysql_fetch_row */
} MYSQL_RES;
+#define MAX_MYSQL_MANAGER_ERR 256
+#define MAX_MYSQL_MANAGER_MSG 256
+
+#define MANAGER_OK 200
+#define MANAGER_INFO 250
+#define MANAGER_ACCESS 401
+#define MANAGER_CLIENT_ERR 450
+#define MANAGER_INTERNAL_ERR 500
+
+
+
+typedef struct st_mysql_manager
+{
+ NET net;
+ char *host,*user,*passwd;
+ unsigned int port;
+ my_bool free_me;
+ my_bool eof;
+ int cmd_status;
+ int last_errno;
+ char* net_buf,*net_buf_pos,*net_data_end;
+ int net_buf_size;
+ char last_error[MAX_MYSQL_MANAGER_ERR];
+} MYSQL_MANAGER;
+
+/* Set up and bring down the server; to ensure that applications will
+ * work when linked against either the standard client library or the
+ * embedded server library, these functions should be called. */
+int STDCALL mysql_server_init(int argc, char **argv, char **groups);
+void STDCALL mysql_server_end(void);
+
+/* Set up and bring down a thread; these function should be called
+ * for each thread in an application which opens at least one MySQL
+ * connection. All uses of the connection(s) should be between these
+ * function calls. */
+my_bool STDCALL mysql_thread_init(void);
+void STDCALL mysql_thread_end(void);
+
/* Functions to get information from the MYSQL and MYSQL_RES structures */
/* Should definitely be used if one uses shared libraries */
@@ -211,18 +285,12 @@ unsigned long STDCALL mysql_thread_id(MYSQL *mysql);
const char * STDCALL mysql_character_set_name(MYSQL *mysql);
MYSQL * STDCALL mysql_init(MYSQL *mysql);
-#ifdef HAVE_OPENSSL
int STDCALL mysql_ssl_set(MYSQL *mysql, const char *key,
const char *cert, const char *ca,
- const char *capath);
-char * STDCALL mysql_ssl_cipher(MYSQL *mysql);
+ const char *capath, const char *cipher);
int STDCALL mysql_ssl_clear(MYSQL *mysql);
-#endif /* HAVE_OPENSSL */
-MYSQL * STDCALL mysql_connect(MYSQL *mysql, const char *host,
- const char *user, const char *passwd);
my_bool STDCALL mysql_change_user(MYSQL *mysql, const char *user,
const char *passwd, const char *db);
-#if MYSQL_VERSION_ID >= 32200
MYSQL * STDCALL mysql_real_connect(MYSQL *mysql, const char *host,
const char *user,
const char *passwd,
@@ -230,24 +298,55 @@ MYSQL * STDCALL mysql_real_connect(MYSQL *mysql, const char *host,
unsigned int port,
const char *unix_socket,
unsigned int clientflag);
-#else
-MYSQL * STDCALL mysql_real_connect(MYSQL *mysql, const char *host,
- const char *user,
- const char *passwd,
- unsigned int port,
- const char *unix_socket,
- unsigned int clientflag);
-#endif
void STDCALL mysql_close(MYSQL *sock);
int STDCALL mysql_select_db(MYSQL *mysql, const char *db);
int STDCALL mysql_query(MYSQL *mysql, const char *q);
int STDCALL mysql_send_query(MYSQL *mysql, const char *q,
- unsigned int length);
+ unsigned long length);
int STDCALL mysql_read_query_result(MYSQL *mysql);
int STDCALL mysql_real_query(MYSQL *mysql, const char *q,
- unsigned int length);
-int STDCALL mysql_create_db(MYSQL *mysql, const char *DB);
-int STDCALL mysql_drop_db(MYSQL *mysql, const char *DB);
+ unsigned long length);
+/* perform query on master */
+int STDCALL mysql_master_query(MYSQL *mysql, const char *q,
+ unsigned long length);
+int STDCALL mysql_master_send_query(MYSQL *mysql, const char *q,
+ unsigned long length);
+/* perform query on slave */
+int STDCALL mysql_slave_query(MYSQL *mysql, const char *q,
+ unsigned long length);
+int STDCALL mysql_slave_send_query(MYSQL *mysql, const char *q,
+ unsigned long length);
+
+/*
+ enable/disable parsing of all queries to decide if they go on master or
+ slave
+*/
+void STDCALL mysql_enable_rpl_parse(MYSQL* mysql);
+void STDCALL mysql_disable_rpl_parse(MYSQL* mysql);
+/* get the value of the parse flag */
+int STDCALL mysql_rpl_parse_enabled(MYSQL* mysql);
+
+/* enable/disable reads from master */
+void STDCALL mysql_enable_reads_from_master(MYSQL* mysql);
+void STDCALL mysql_disable_reads_from_master(MYSQL* mysql);
+/* get the value of the master read flag */
+int STDCALL mysql_reads_from_master_enabled(MYSQL* mysql);
+
+enum mysql_rpl_type STDCALL mysql_rpl_query_type(const char* q, int len);
+
+/* discover the master and its slaves */
+int STDCALL mysql_rpl_probe(MYSQL* mysql);
+
+/* set the master, close/free the old one, if it is not a pivot */
+int STDCALL mysql_set_master(MYSQL* mysql, const char* host,
+ unsigned int port,
+ const char* user,
+ const char* passwd);
+int STDCALL mysql_add_slave(MYSQL* mysql, const char* host,
+ unsigned int port,
+ const char* user,
+ const char* passwd);
+
int STDCALL mysql_shutdown(MYSQL *mysql);
int STDCALL mysql_dump_debug_info(MYSQL *mysql);
int STDCALL mysql_refresh(MYSQL *mysql,
@@ -295,18 +394,40 @@ char * STDCALL mysql_odbc_escape_string(MYSQL *mysql,
unsigned long *length));
void STDCALL myodbc_remove_escape(MYSQL *mysql,char *name);
unsigned int STDCALL mysql_thread_safe(void);
-
-
+MYSQL_MANAGER* STDCALL mysql_manager_init(MYSQL_MANAGER* con);
+MYSQL_MANAGER* STDCALL mysql_manager_connect(MYSQL_MANAGER* con,
+ const char* host,
+ const char* user,
+ const char* passwd,
+ unsigned int port);
+void STDCALL mysql_manager_close(MYSQL_MANAGER* con);
+int STDCALL mysql_manager_command(MYSQL_MANAGER* con,
+ const char* cmd, int cmd_len);
+int STDCALL mysql_manager_fetch_line(MYSQL_MANAGER* con,
+ char* res_buf,
+ int res_buf_size);
#define mysql_reload(mysql) mysql_refresh((mysql),REFRESH_GRANT)
-/* new api functions */
-
+#ifdef USE_OLD_FUNCTIONS
+MYSQL * STDCALL mysql_connect(MYSQL *mysql, const char *host,
+ const char *user, const char *passwd);
+int STDCALL mysql_create_db(MYSQL *mysql, const char *DB);
+int STDCALL mysql_drop_db(MYSQL *mysql, const char *DB);
+#define mysql_reload(mysql) mysql_refresh((mysql),REFRESH_GRANT)
+#endif
#define HAVE_MYSQL_REAL_CONNECT
-#ifndef MYSQL_SERVER
+/*
+ The following functions are mainly exported because of mysqlbinlog;
+ They are not for general usage
+*/
+
+int simple_command(MYSQL *mysql,enum enum_server_command command,
+ const char *arg, unsigned long length, my_bool skipp_check);
+unsigned long net_safe_read(MYSQL* mysql);
+
#ifdef __cplusplus
}
#endif
-#endif
-#endif
+#endif /* _mysql_h */
diff --git a/include/mysql_com.h b/include/mysql_com.h
index 2e455c456fa..cc887cc7c83 100644
--- a/include/mysql_com.h
+++ b/include/mysql_com.h
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/*
** Common definition between mysql server & client
@@ -42,7 +41,8 @@ enum enum_server_command {COM_SLEEP,COM_QUIT,COM_INIT_DB,COM_QUERY,
COM_PROCESS_INFO,COM_CONNECT,COM_PROCESS_KILL,
COM_DEBUG,COM_PING,COM_TIME,COM_DELAYED_INSERT,
COM_CHANGE_USER, COM_BINLOG_DUMP,
- COM_TABLE_DUMP, COM_CONNECT_OUT};
+ COM_TABLE_DUMP, COM_CONNECT_OUT,
+ COM_REGISTER_SLAVE};
#define NOT_NULL_FLAG 1 /* Field can't be NULL */
#define PRI_KEY_FLAG 2 /* Field is part of a primary key */
@@ -77,6 +77,11 @@ enum enum_server_command {COM_SLEEP,COM_QUIT,COM_INIT_DB,COM_QUERY,
#define REFRESH_READ_LOCK 16384 /* Lock tables for read */
#define REFRESH_FAST 32768 /* Intern flag */
+/* RESET (remove all queries) from query cache */
+#define REFRESH_QUERY_CACHE 65536
+#define REFRESH_QUERY_CACHE_FREE 0x20000L /* pack query cache */
+#define REFRESH_DES_KEY_FILE 0x40000L
+
#define CLIENT_LONG_PASSWORD 1 /* new more secure passwords */
#define CLIENT_FOUND_ROWS 2 /* Found instead of affected rows */
#define CLIENT_LONG_FLAG 4 /* Get all column flags */
@@ -100,36 +105,36 @@ enum enum_server_command {COM_SLEEP,COM_QUIT,COM_INIT_DB,COM_QUERY,
#define NET_WRITE_TIMEOUT 60 /* Timeout on write */
#define NET_WAIT_TIMEOUT 8*60*60 /* Wait for new query */
-#ifndef Vio_defined
-#define Vio_defined
-#ifdef HAVE_VIO
-class Vio; /* Fill Vio class in C++ */
-#else
struct st_vio; /* Only C */
typedef struct st_vio Vio;
-#endif
-#endif
+
+#define MAX_CHAR_WIDTH 255 // Max length for a CHAR colum
+#define MAX_BLOB_WIDTH 8192 // Default width for blob
typedef struct st_net {
Vio* vio;
+ unsigned char *buff,*buff_end,*write_pos,*read_pos;
my_socket fd; /* For Perl DBI/dbd */
+ unsigned long max_packet;
int fcntl;
- unsigned char *buff,*buff_end,*write_pos,*read_pos;
+ unsigned int last_errno,timeout,pkt_nr,compress_pkt_nr;
char last_error[MYSQL_ERRMSG_SIZE];
- unsigned int last_errno,max_packet,timeout,pkt_nr;
unsigned char error;
my_bool return_errno,compress;
- my_bool no_send_ok; /* needed if we are doing several
- queries in one command ( as in LOAD TABLE ... FROM MASTER ),
- and do not want to confuse the client with OK at the wrong time
- */
+ /*
+ The following variable is set if we are doing several queries in one
+ command ( as in LOAD TABLE ... FROM MASTER ),
+ and do not want to confuse the client with OK at the wrong time
+ */
unsigned long remain_in_buf,length, buf_length, where_b;
unsigned int *return_status;
unsigned char reading_or_writing;
char save_char;
+ my_bool no_send_ok;
+ gptr query_cache_query;
} NET;
-#define packet_error ((unsigned int) -1)
+#define packet_error (~(unsigned long) 0)
enum enum_field_types { FIELD_TYPE_DECIMAL, FIELD_TYPE_TINY,
FIELD_TYPE_SHORT, FIELD_TYPE_LONG,
@@ -146,17 +151,22 @@ enum enum_field_types { FIELD_TYPE_DECIMAL, FIELD_TYPE_TINY,
FIELD_TYPE_LONG_BLOB=251,
FIELD_TYPE_BLOB=252,
FIELD_TYPE_VAR_STRING=253,
- FIELD_TYPE_STRING=254
+ FIELD_TYPE_STRING=254,
+ FIELD_TYPE_GEOMETRY=255
};
#define FIELD_TYPE_CHAR FIELD_TYPE_TINY /* For compability */
#define FIELD_TYPE_INTERVAL FIELD_TYPE_ENUM /* For compability */
+#define net_new_transaction(net) ((net)->pkt_nr=0)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
extern unsigned long max_allowed_packet;
extern unsigned long net_buffer_length;
-#define net_new_transaction(net) ((net)->pkt_nr=0)
-
int my_net_init(NET *net, Vio* vio);
void net_end(NET *net);
void net_clear(NET *net);
@@ -165,13 +175,22 @@ int my_net_write(NET *net,const char *packet,unsigned long len);
int net_write_command(NET *net,unsigned char command,const char *packet,
unsigned long len);
int net_real_write(NET *net,const char *packet,unsigned long len);
-unsigned int my_net_read(NET *net);
+unsigned long my_net_read(NET *net);
+
+/* The following function is not meant for normal usage */
+struct sockaddr;
+int my_connect(my_socket s, const struct sockaddr *name, unsigned int namelen,
+ unsigned int timeout);
struct rand_struct {
unsigned long seed1,seed2,max_value;
double max_value_dbl;
};
+#ifdef __cplusplus
+}
+#endif
+
/* The following is for user defined functions */
enum Item_result {STRING_RESULT,REAL_RESULT,INT_RESULT};
@@ -191,7 +210,7 @@ typedef struct st_udf_init
{
my_bool maybe_null; /* 1 if function can return NULL */
unsigned int decimals; /* for real functions */
- unsigned int max_length; /* For string functions */
+ unsigned long max_length; /* For string functions */
char *ptr; /* free pointer for function data */
my_bool const_item; /* 0 if result is independent of arguments */
} UDF_INIT;
@@ -205,7 +224,7 @@ typedef struct st_udf_init
#ifdef __cplusplus
extern "C" {
#endif
-
+
void randominit(struct rand_struct *,unsigned long seed1,
unsigned long seed2);
double rnd(struct rand_struct *);
diff --git a/include/mysql_embed.h b/include/mysql_embed.h
new file mode 100644
index 00000000000..58a743771fa
--- /dev/null
+++ b/include/mysql_embed.h
@@ -0,0 +1,30 @@
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+/* Defines that are unique to the embedded version of MySQL */
+
+#ifdef EMBEDDED_LIBRARY
+
+/* Things we don't need in the embedded version of MySQL */
+
+#undef HAVE_PSTACK /* No stacktrace */
+#undef HAVE_DLOPEN /* No udf functions */
+#undef HAVE_OPENSSL
+#undef HAVE_VIO
+#undef HAVE_ISAM
+
+#define DONT_USE_RAID
+#endif /* EMBEDDED_LIBRARY */
diff --git a/include/mysqld_error.h b/include/mysqld_error.h
index 81e0dd1d06d..c910078331e 100644
--- a/include/mysqld_error.h
+++ b/include/mysqld_error.h
@@ -1,3 +1,19 @@
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
/* Definefile for errormessagenumbers */
#define ER_HASHCHK 1000
@@ -218,4 +234,13 @@
#define ER_CANNOT_ADD_FOREIGN 1215
#define ER_NO_REFERENCED_ROW 1216
#define ER_ROW_IS_REFERENCED 1217
-#define ER_ERROR_MESSAGES 218
+#define ER_CONNECT_TO_MASTER 1218
+#define ER_QUERY_ON_MASTER 1219
+#define ER_ERROR_WHEN_EXECUTING_COMMAND 1220
+#define ER_WRONG_USAGE 1221
+#define ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT 1222
+#define ER_CANT_UPDATE_WITH_READLOCK 1223
+#define ER_MIXING_NOT_ALLOWED 1224
+#define ER_DUP_ARGUMENT 1225
+#define ER_USER_LIMIT_REACHED 1226
+#define ER_ERROR_MESSAGES 227
diff --git a/include/mysys_err.h b/include/mysys_err.h
index 2d23ead36b6..b3d058aff3e 100644
--- a/include/mysys_err.h
+++ b/include/mysys_err.h
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#ifndef _mysys_err_h
#define _mysys_err_h
diff --git a/include/nisam.h b/include/nisam.h
index 7ce2b44ee79..e8f29991a4e 100644
--- a/include/nisam.h
+++ b/include/nisam.h
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 should be included when using nisam_funktions */
/* Author: Michael Widenius */
diff --git a/include/queues.h b/include/queues.h
index 66125e650ca..70cb99a1513 100644
--- a/include/queues.h
+++ b/include/queues.h
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/*
Code for generell handling of priority Queues.
@@ -53,6 +52,7 @@ void delete_queue(QUEUE *queue);
void queue_insert(QUEUE *queue,byte *element);
byte *queue_remove(QUEUE *queue,uint idx);
void _downheap(QUEUE *queue,uint idx);
+void queue_fix(QUEUE *queue);
#define is_queue_inited(queue) ((queue)->root != 0)
#ifdef __cplusplus
diff --git a/include/raid.h b/include/raid.h
index 8cbd0f1a442..4a988760157 100644
--- a/include/raid.h
+++ b/include/raid.h
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+/* Copyright (C) 2000 MySQL AB
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
- This library is distributed in the hope that it will be useful,
+ 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
- Library General Public License for more details.
+ 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 Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/* Parser needs these defines always, even if USE_RAID is not defined */
#define RAID_TYPE_0 1 /* Striping */
@@ -23,15 +22,10 @@
#define RAID_DEFAULT_CHUNKS 4
#define RAID_DEFAULT_CHUNKSIZE 256*1024 /* 256kB */
+C_MODE_START
+#define my_raid_type(raid_type) raid_type_string[(int)(raid_type)]
extern const char *raid_type_string[];
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-const char *my_raid_type(int raid_type);
-#ifdef __cplusplus
-}
-#endif
+C_MODE_END
#if defined(USE_RAID) && !defined(DONT_USE_RAID)
diff --git a/include/sslopt-case.h b/include/sslopt-case.h
index d995e31044e..ae6026f9136 100644
--- a/include/sslopt-case.h
+++ b/include/sslopt-case.h
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#ifdef HAVE_OPENSSL
case OPT_SSL_SSL:
@@ -36,7 +35,12 @@
break;
case OPT_SSL_CAPATH:
opt_use_ssl = 1; /* true */
- my_free(opt_ssl_ca, MYF(MY_ALLOW_ZERO_PTR));
- opt_ssl_ca = my_strdup(optarg, MYF(0));
+ my_free(opt_ssl_capath, MYF(MY_ALLOW_ZERO_PTR));
+ opt_ssl_capath = my_strdup(optarg, MYF(0));
+ break;
+ case OPT_SSL_CIPHER:
+ opt_use_ssl = 1; /* true */
+ my_free(opt_ssl_cipher, MYF(MY_ALLOW_ZERO_PTR));
+ opt_ssl_cipher = my_strdup(optarg, MYF(0));
break;
#endif
diff --git a/include/sslopt-longopts.h b/include/sslopt-longopts.h
index 2f58f0e9265..2a0f27f3235 100644
--- a/include/sslopt-longopts.h
+++ b/include/sslopt-longopts.h
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#ifdef HAVE_OPENSSL
@@ -22,10 +21,12 @@
#define OPT_SSL_CERT 202
#define OPT_SSL_CA 203
#define OPT_SSL_CAPATH 204
+#define OPT_SSL_CIPHER 205
{"ssl", no_argument, 0, OPT_SSL_SSL},
{"ssl-key", required_argument, 0, OPT_SSL_KEY},
{"ssl-cert", required_argument, 0, OPT_SSL_CERT},
{"ssl-ca", required_argument, 0, OPT_SSL_CA},
{"ssl-capath", required_argument, 0, OPT_SSL_CAPATH},
+ {"ssl-cipher", required_argument, 0, OPT_SSL_CIPHER},
#endif /* HAVE_OPENSSL */
diff --git a/include/sslopt-usage.h b/include/sslopt-usage.h
index 5b2b4a88709..e5e374dea44 100644
--- a/include/sslopt-usage.h
+++ b/include/sslopt-usage.h
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#ifdef OPEN_SSL
puts("\
@@ -21,5 +20,6 @@
--ssl-key X509 key in PEM format (implies --ssl)\n\
--ssl-cert X509 cert in PEM format (implies --ssl)\n\
--ssl-ca CA file in PEM format (check OpenSSL docs, implies --ssl)\n\
- --ssl-capath CA directory (check OpenSSL docs, implies --ssl)");
+ --ssl-capath CA directory (check OpenSSL docs, implies --ssl)\n\
+ --ssl-cipher SSL cipher to use (implies --ssl)");
#endif
diff --git a/include/sslopt-vars.h b/include/sslopt-vars.h
index 597ab4d9fa6..164cf541381 100644
--- a/include/sslopt-vars.h
+++ b/include/sslopt-vars.h
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#ifdef HAVE_OPENSSL
static my_bool opt_use_ssl = 0;
@@ -21,4 +20,5 @@ static char *opt_ssl_key = 0;
static char *opt_ssl_cert = 0;
static char *opt_ssl_ca = 0;
static char *opt_ssl_capath = 0;
+static char *opt_ssl_cipher = 0;
#endif
diff --git a/include/t_ctype.h b/include/t_ctype.h
index f6e799828e6..3e190977e6c 100644
--- a/include/t_ctype.h
+++ b/include/t_ctype.h
@@ -1,3 +1,19 @@
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
/*
Copyright (C) 1998, 1999 by Pruet Boonma, all rights reserved.
Copyright (C) 1998 by Theppitak Karoonboonyanan, all rights reserved.
@@ -121,7 +137,7 @@ enum l1_symbols {
L1_SARA_AI_MAIMUAN,
L1_SARA_AI_MAIMALAI
};
-
+
/* level 2 symbols & order */
enum l2_symbols {
L2_BLANK = TOT_LEVELS,
@@ -135,7 +151,7 @@ enum l2_symbols {
L2_TONE3,
L2_TONE4
};
-
+
/* level 3 symbols & order */
enum l3_symbols {
L3_BLANK = TOT_LEVELS,
diff --git a/include/thr_alarm.h b/include/thr_alarm.h
index 1f3fed1d29b..5caf552718c 100644
--- a/include/thr_alarm.h
+++ b/include/thr_alarm.h
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/* Prototypes when using thr_alarm library functions */
@@ -39,24 +38,23 @@ extern "C" {
#define THR_SERVER_ALARM SIGALRM
#endif
-#if defined(DONT_USE_THR_ALARM)
+#if defined(DONT_USE_THR_ALARM) || !defined(THREAD)
#define USE_ALARM_THREAD
#undef USE_ONE_SIGNAL_HAND
-typedef struct st_thr_alarm_entry
-{
- uint crono;
-} thr_alarm_entry;
+typedef my_bool thr_alarm_t;
+typedef my_bool ALARM;
-#define thr_alarm_init(A) (A)->crono=0
-#define thr_alarm_in_use(A) (A)->crono
+#define thr_alarm_init(A) (*(A))=0
+#define thr_alarm_in_use(A) (*(A) != 0)
+#define thr_end_alarm(A)
+#define thr_alarm(A,B,C) ((*(A)=1)-1)
+/* The following should maybe be (*(A)) */
+#define thr_got_alarm(A) 0
#define init_thr_alarm(A)
#define thr_alarm_kill(A)
#define end_thr_alarm()
-#define thr_alarm(A,B) (((A)->crono=1)-1)
-#define thr_got_alarm(A) (A)->crono
-#define thr_end_alarm(A)
#else
#if defined(__WIN__)
@@ -109,4 +107,3 @@ bool thr_got_alarm(thr_alarm_t *alrm);
}
#endif /* __cplusplus */
#endif /* _thr_alarm_h */
-
diff --git a/include/thr_lock.h b/include/thr_lock.h
index 6dd59f80e64..7459849cb04 100644
--- a/include/thr_lock.h
+++ b/include/thr_lock.h
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/* For use with thr_lock:s */
@@ -28,7 +27,7 @@ extern "C" {
struct st_thr_lock;
extern ulong locks_immediate,locks_waited ;
-
+
enum thr_lock_type { TL_IGNORE=-1,
TL_UNLOCK, /* UNLOCK ANY LOCK */
TL_READ, /* Read lock */
diff --git a/include/violite.h b/include/violite.h
index 49df6994d53..0f36e493b57 100644
--- a/include/violite.h
+++ b/include/violite.h
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/*
* Vio Lite.
@@ -25,9 +24,6 @@
#include "my_net.h" /* needed because of struct in_addr */
-#ifdef HAVE_VIO
-#include <Vio.h> /* Full VIO interface */
-#else
/* Simple vio interface in C; The functions are implemented in violite.c */
@@ -35,83 +31,202 @@
extern "C" {
#endif /* __cplusplus */
-#ifndef Vio_defined
-#define Vio_defined
-struct st_vio; /* Only C */
-typedef struct st_vio Vio;
-#endif
-
enum enum_vio_type { VIO_CLOSED, VIO_TYPE_TCPIP, VIO_TYPE_SOCKET,
VIO_TYPE_NAMEDPIPE, VIO_TYPE_SSL};
-Vio* vio_new(my_socket sd,
- enum enum_vio_type type,
- my_bool localhost);
+#ifndef __WIN__
+#define HANDLE void *
+#endif
+
+Vio* vio_new(my_socket sd, enum enum_vio_type type, my_bool localhost);
#ifdef __WIN__
-Vio* vio_new_win32pipe(HANDLE hPipe);
+Vio* vio_new_win32pipe(HANDLE hPipe);
+#endif
+void vio_delete(Vio* vio);
+
+#ifdef EMBEDDED_LIBRARY
+void vio_reset(Vio *vio);
+#else
+void vio_reset(Vio* vio, enum enum_vio_type type,
+ my_socket sd, HANDLE hPipe, my_bool localhost);
#endif
-void vio_delete(Vio* vio);
/*
* vio_read and vio_write should have the same semantics
* as read(2) and write(2).
*/
-int vio_read( Vio* vio,
- gptr buf, int size);
-int vio_write( Vio* vio,
- const gptr buf,
- int size);
+int vio_read(Vio *vio, gptr buf, int size);
+int vio_write(Vio *vio, const gptr buf, int size);
/*
* Whenever the socket is set to blocking mode or not.
*/
-int vio_blocking( Vio* vio,
- my_bool onoff);
-my_bool vio_is_blocking( Vio* vio);
+int vio_blocking(Vio *vio, my_bool onoff);
+my_bool vio_is_blocking(Vio *vio);
/*
* setsockopt TCP_NODELAY at IPPROTO_TCP level, when possible.
*/
- int vio_fastsend( Vio* vio);
+int vio_fastsend(Vio *vio);
/*
* setsockopt SO_KEEPALIVE at SOL_SOCKET level, when possible.
*/
-int vio_keepalive( Vio* vio,
- my_bool onoff);
+int vio_keepalive(Vio *vio, my_bool onoff);
/*
* Whenever we should retry the last read/write operation.
*/
-my_bool vio_should_retry( Vio* vio);
+my_bool vio_should_retry(Vio *vio);
/*
* When the workday is over...
*/
-int vio_close( Vio* vio);
+int vio_close(Vio* vio);
/*
* Short text description of the socket for those, who are curious..
*/
-const char* vio_description( Vio* vio);
+const char* vio_description(Vio *vio);
/* Return the type of the connection */
- enum enum_vio_type vio_type(Vio* vio);
+enum enum_vio_type vio_type(Vio* vio);
/* Return last error number */
-int vio_errno(Vio *vio);
+int vio_errno(Vio*vio);
/* Get socket number */
-my_socket vio_fd(Vio *vio);
+my_socket vio_fd(Vio*vio);
/*
* Remote peer's address and name in text form.
*/
-my_bool vio_peer_addr(Vio * vio, char *buf);
+my_bool vio_peer_addr(Vio* vio, char *buf);
/* Remotes in_addr */
void vio_in_addr(Vio *vio, struct in_addr *in);
- /* Return 1 if there is data to be read */
my_bool vio_poll_read(Vio *vio,uint timeout);
#ifdef __cplusplus
}
#endif
+
+#if defined(HAVE_VIO) && !defined(DONT_MAP_VIO)
+#define vio_delete(vio) (vio)->viodelete(vio)
+#define vio_errno(vio) (vio)->vioerrno(vio)
+#define vio_read(vio, buf, size) (vio)->read(vio,buf,size)
+#define vio_write(vio, buf, size) (vio)->write(vio, buf, size)
+#define vio_blocking(vio, set_blocking_mode) (vio)->vioblocking(vio, set_blocking_mode)
+#define vio_is_blocking(vio) (vio)->is_blocking(vio)
+#define vio_fastsend(vio) (vio)->fastsend(vio)
+#define vio_keepalive(vio, set_keep_alive) (vio)->viokeepalive(vio, set_keep_alive)
+#define vio_should_retry(vio) (vio)->should_retry(vio)
+#define vio_close(vio) ((vio)->vioclose)(vio)
+#define vio_peer_addr(vio, buf) (vio)->peer_addr(vio, buf)
+#define vio_in_addr(vio, in) (vio)->in_addr(vio, in)
+#endif /* defined(HAVE_VIO) && !defined(DONT_MAP_VIO) */
+
+#ifdef HAVE_OPENSSL
+#define HEADER_DES_LOCL_H dummy_something
+#include <openssl/ssl.h>
+#include <openssl/err.h>
+#include "my_net.h" /* needed because of struct in_addr */
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+void vio_ssl_delete(Vio* vio);
+
+int vio_ssl_read(Vio* vio,gptr buf, int size);
+int vio_ssl_write(Vio* vio,const gptr buf,int size);
+int vio_ssl_blocking(Vio* vio,my_bool onoff);
+my_bool vio_ssl_is_blocking(Vio* vio);
+
+/* setsockopt TCP_NODELAY at IPPROTO_TCP level, when possible. */
+ int vio_ssl_fastsend(Vio* vio);
+/* setsockopt SO_KEEPALIVE at SOL_SOCKET level, when possible. */
+int vio_ssl_keepalive(Vio* vio, my_bool onoff);
+/* Whenever we should retry the last read/write operation. */
+my_bool vio_ssl_should_retry(Vio* vio);
+/* When the workday is over... */
+int vio_ssl_close(Vio* vio);
+/* Return last error number */
+int vio_ssl_errno(Vio *vio);
+my_bool vio_ssl_peer_addr(Vio* vio, char *buf);
+void vio_ssl_in_addr(Vio *vio, struct in_addr *in);
+
+/* Single copy for server */
+struct st_VioSSLAcceptorFd
+{
+ SSL_CTX* ssl_context_;
+ SSL_METHOD* ssl_method_;
+ struct st_VioSSLAcceptorFd* session_id_context_;
+ enum {
+ state_connect = 1,
+ state_accept = 2
+ };
+
+ /* function pointers which are only once for SSL server
+ Vio*(*sslaccept)(struct st_VioSSLAcceptorFd*,Vio*); */
+};
+
+/* One copy for client */
+struct st_VioSSLConnectorFd
+{
+ SSL_CTX* ssl_context_;
+ SSL_METHOD* ssl_method_;
+ /* function pointers which are only once for SSL client */
+};
+void sslaccept(struct st_VioSSLAcceptorFd*, Vio*, long timeout);
+void sslconnect(struct st_VioSSLConnectorFd*, Vio*, long timeout);
+
+struct st_VioSSLConnectorFd
+*new_VioSSLConnectorFd(const char* key_file, const char* cert_file,
+ const char* ca_file, const char* ca_path,
+ const char* cipher);
+struct st_VioSSLAcceptorFd
+*new_VioSSLAcceptorFd(const char* key_file, const char* cert_file,
+ const char* ca_file,const char* ca_path,
+ const char* cipher);
+Vio* new_VioSSL(struct st_VioSSLAcceptorFd* fd, Vio* sd,int state);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* HAVE_OPENSSL */
+
+/* This enumerator is used in parser - should be always visible */
+enum SSL_type {SSL_TYPE_NONE, SSL_TYPE_ANY, SSL_TYPE_X509, SSL_TYPE_SPECIFIED};
+
+#ifndef EMBEDDED_LIBRARY
+/* This structure is for every connection on both sides */
+struct st_vio
+{
+ my_socket sd; /* my_socket - real or imaginary */
+ HANDLE hPipe;
+ my_bool localhost; /* Are we from localhost? */
+ int fcntl_mode; /* Buffered fcntl(sd,F_GETFL) */
+ struct sockaddr_in local; /* Local internet address */
+ struct sockaddr_in remote; /* Remote internet address */
+ enum enum_vio_type type; /* Type of connection */
+ char desc[30]; /* String description */
+#ifdef HAVE_VIO
+ /* function pointers. They are similar for socket/SSL/whatever */
+ void (*viodelete)(Vio*);
+ int (*vioerrno)(Vio*);
+ int (*read)(Vio*, gptr, int);
+ int (*write)(Vio*, gptr, int);
+ int (*vioblocking)(Vio*, my_bool);
+ my_bool (*is_blocking)(Vio*);
+ int (*viokeepalive)(Vio*, my_bool);
+ int (*fastsend)(Vio*);
+ my_bool (*peer_addr)(Vio*, gptr);
+ void (*in_addr)(Vio*, struct in_addr*);
+ my_bool (*should_retry)(Vio*);
+ int (*vioclose)(Vio*);
+
+#ifdef HAVE_OPENSSL
+ SSL* ssl_;
+ my_bool open_;
+#endif /* HAVE_OPENSSL */
#endif /* HAVE_VIO */
+};
+#endif /* EMBEDDED_LIBRARY */
#endif /* vio_violite_h_ */
diff --git a/innobase/btr/btr0btr.c b/innobase/btr/btr0btr.c
index a96830c24ff..c71ef017aa8 100644
--- a/innobase/btr/btr0btr.c
+++ b/innobase/btr/btr0btr.c
@@ -838,7 +838,7 @@ btr_parse_page_reorganize(
/*======================*/
/* out: end of log record or NULL */
byte* ptr, /* in: buffer */
- byte* end_ptr,/* in: buffer end */
+ byte* end_ptr __attribute__((unused)), /* in: buffer end */
page_t* page, /* in: page or NULL */
mtr_t* mtr) /* in: mtr or NULL */
{
@@ -1439,7 +1439,7 @@ btr_page_split_and_insert(
page_t* insert_page;
page_cur_t* page_cursor;
rec_t* first_rec;
- byte* buf;
+ byte* buf = 0; /* remove warning */
rec_t* move_limit;
ibool insert_will_fit;
ulint n_iterations = 0;
@@ -1617,7 +1617,7 @@ static
void
btr_level_list_remove(
/*==================*/
- dict_tree_t* tree, /* in: index tree */
+ dict_tree_t* tree __attribute__((unused)), /* in: index tree */
page_t* page, /* in: page to remove */
mtr_t* mtr) /* in: mtr */
{
@@ -2339,7 +2339,7 @@ btr_validate_level(
{
ulint space;
page_t* page;
- page_t* right_page;
+ page_t* right_page = 0; /* remove warning */
page_t* father_page;
page_t* right_father_page;
rec_t* node_ptr;
diff --git a/innobase/btr/btr0cur.c b/innobase/btr/btr0cur.c
index a078c843159..d6944ecadc8 100644
--- a/innobase/btr/btr0cur.c
+++ b/innobase/btr/btr0cur.c
@@ -103,7 +103,7 @@ static
void
btr_cur_latch_leaves(
/*=================*/
- dict_tree_t* tree, /* in: index tree */
+ dict_tree_t* tree __attribute__((unused)), /* in: index tree */
page_t* page, /* in: leaf page where the search
converged */
ulint space, /* in: space id */
@@ -228,7 +228,7 @@ btr_cur_search_to_nth_level(
ulint insert_planned;
ulint buf_mode;
ulint estimate;
- ulint root_height;
+ ulint root_height = 0; /* remove warning */
#ifdef BTR_CUR_ADAPT
btr_search_t* info;
#endif
@@ -497,7 +497,7 @@ btr_cur_open_at_index_side(
ulint page_no;
ulint space;
ulint height;
- ulint root_height;
+ ulint root_height = 0; /* remove warning */
rec_t* node_ptr;
ulint estimate;
@@ -2988,8 +2988,9 @@ btr_store_big_rec_extern_fields(
rec_t* rec, /* in: record */
big_rec_t* big_rec_vec, /* in: vector containing fields
to be stored externally */
- mtr_t* local_mtr) /* in: mtr containing the latch to
- rec and to the tree */
+ mtr_t* local_mtr __attribute__((unused))) /* in: mtr
+ containing the latch to rec and to the
+ tree */
{
byte* data;
ulint local_len;
@@ -3150,9 +3151,9 @@ btr_free_externally_stored_field(
ibool do_not_free_inherited,/* in: TRUE if called in a
rollback and we do not want to free
inherited fields */
- mtr_t* local_mtr) /* in: mtr containing the latch to
- data an an X-latch to the index
- tree */
+ mtr_t* local_mtr __attribute__((unused))) /* in: mtr
+ containing the latch to data an an
+ X-latch to the index tree */
{
page_t* page;
page_t* rec_page;
diff --git a/innobase/btr/btr0sea.c b/innobase/btr/btr0sea.c
index ca8589813ca..21b4c12ab56 100644
--- a/innobase/btr/btr0sea.c
+++ b/innobase/btr/btr0sea.c
@@ -1245,7 +1245,7 @@ btr_search_update_hash_on_insert(
dulint tree_id;
ulint fold;
ulint ins_fold;
- ulint next_fold;
+ ulint next_fold = 0; /* remove warning (??? bug ???) */
ulint n_fields;
ulint n_bytes;
ulint side;
diff --git a/innobase/buf/buf0buf.c b/innobase/buf/buf0buf.c
index 055d76e6d81..adb61bfbb56 100644
--- a/innobase/buf/buf0buf.c
+++ b/innobase/buf/buf0buf.c
@@ -280,7 +280,7 @@ buf_page_print(
ut_sprintf_buf(buf, read_buf, UNIV_PAGE_SIZE);
fprintf(stderr,
- "InnoDB: Page dump in ascii and hex (%lu bytes):\n%s",
+ "InnoDB: Page dump in ascii and hex (%u bytes):\n%s",
UNIV_PAGE_SIZE, buf);
fprintf(stderr, "InnoDB: End of page dump\n");
diff --git a/innobase/buf/buf0lru.c b/innobase/buf/buf0lru.c
index a2996eefca9..5ab045212c2 100644
--- a/innobase/buf/buf0lru.c
+++ b/innobase/buf/buf0lru.c
@@ -103,9 +103,10 @@ ibool
buf_LRU_search_and_free_block(
/*==========================*/
/* out: TRUE if freed */
- ulint n_iterations) /* in: how many times this has been called
- repeatedly without result: a high value
- means that we should search farther */
+ ulint n_iterations __attribute__((unused))) /* in: how many times
+ this has been called repeatedly without
+ result: a high value means that we should
+ search farther */
{
buf_block_t* block;
ibool freed;
@@ -199,7 +200,7 @@ buf_LRU_get_free_block(void)
buf_block_t* block = NULL;
ibool freed;
ulint n_iterations = 0;
- ibool mon_value_was;
+ ibool mon_value_was = 0; /* remove bug */
ibool started_monitor = FALSE;
loop:
mutex_enter(&(buf_pool->mutex));
diff --git a/innobase/data/data0data.c b/innobase/data/data0data.c
index 2254dcb6ae6..03abcb9b6e0 100644
--- a/innobase/data/data0data.c
+++ b/innobase/data/data0data.c
@@ -572,7 +572,7 @@ from entry with dtuple_convert_big_rec. */
void
dtuple_convert_back_big_rec(
/*========================*/
- dict_index_t* index, /* in: index */
+ dict_index_t* index __attribute__((unused)), /* in: index */
dtuple_t* entry, /* in: entry whose data was put to vector */
big_rec_t* vector) /* in, own: big rec vector; it is
freed in this function */
diff --git a/innobase/dict/dict0boot.c b/innobase/dict/dict0boot.c
index 206fbe32940..374c567c3ca 100644
--- a/innobase/dict/dict0boot.c
+++ b/innobase/dict/dict0boot.c
@@ -254,27 +254,29 @@ dict_boot(void)
/* Insert into the dictionary cache the descriptions of the basic
system tables */
/*-------------------------*/
- table = dict_mem_table_create("SYS_TABLES", DICT_HDR_SPACE, 8);
-
- dict_mem_table_add_col(table, "NAME", DATA_BINARY, 0, 0, 0);
- dict_mem_table_add_col(table, "ID", DATA_BINARY, 0, 0, 0);
- dict_mem_table_add_col(table, "N_COLS", DATA_INT, 0, 4, 0);
- dict_mem_table_add_col(table, "TYPE", DATA_INT, 0, 4, 0);
- dict_mem_table_add_col(table, "MIX_ID", DATA_BINARY, 0, 0, 0);
- dict_mem_table_add_col(table, "MIX_LEN", DATA_INT, 0, 4, 0);
- dict_mem_table_add_col(table, "CLUSTER_NAME", DATA_BINARY, 0, 0, 0);
- dict_mem_table_add_col(table, "SPACE", DATA_INT, 0, 4, 0);
+ table = dict_mem_table_create((char *) "SYS_TABLES", DICT_HDR_SPACE,8);
+
+ dict_mem_table_add_col(table, (char *) "NAME", DATA_BINARY, 0, 0, 0);
+ dict_mem_table_add_col(table, (char *) "ID", DATA_BINARY, 0, 0, 0);
+ dict_mem_table_add_col(table, (char *) "N_COLS", DATA_INT, 0, 4, 0);
+ dict_mem_table_add_col(table, (char *) "TYPE", DATA_INT, 0, 4, 0);
+ dict_mem_table_add_col(table, (char *) "MIX_ID", DATA_BINARY, 0, 0, 0);
+ dict_mem_table_add_col(table, (char *) "MIX_LEN", DATA_INT, 0, 4, 0);
+ dict_mem_table_add_col(table, (char *) "CLUSTER_NAME", DATA_BINARY,
+ 0, 0, 0);
+ dict_mem_table_add_col(table, (char *) "SPACE", DATA_INT, 0, 4, 0);
table->id = DICT_TABLES_ID;
dict_table_add_to_cache(table);
dict_sys->sys_tables = table;
- index = dict_mem_index_create("SYS_TABLES", "CLUST_IND",
- DICT_HDR_SPACE,
- DICT_UNIQUE | DICT_CLUSTERED, 1);
+ index = dict_mem_index_create((char *) "SYS_TABLES", (char *)
+ "CLUST_IND",
+ DICT_HDR_SPACE,
+ DICT_UNIQUE | DICT_CLUSTERED, 1);
- dict_mem_index_add_field(index, "NAME", 0);
+ dict_mem_index_add_field(index, (char *) "NAME", 0);
index->page_no = mtr_read_ulint(dict_hdr + DICT_HDR_TABLES,
MLOG_4BYTES, &mtr);
@@ -282,51 +284,52 @@ dict_boot(void)
ut_a(dict_index_add_to_cache(table, index));
/*-------------------------*/
- index = dict_mem_index_create("SYS_TABLES", "ID_IND", DICT_HDR_SPACE,
- DICT_UNIQUE, 1);
- dict_mem_index_add_field(index, "ID", 0);
+ index = dict_mem_index_create((char *) "SYS_TABLES",
+ (char *) "ID_IND", DICT_HDR_SPACE,
+ DICT_UNIQUE, 1);
+ dict_mem_index_add_field(index, (char *) "ID", 0);
index->page_no = mtr_read_ulint(dict_hdr + DICT_HDR_TABLE_IDS,
MLOG_4BYTES, &mtr);
index->id = DICT_TABLE_IDS_ID;
ut_a(dict_index_add_to_cache(table, index));
/*-------------------------*/
- table = dict_mem_table_create("SYS_COLUMNS", DICT_HDR_SPACE, 7);
-
- dict_mem_table_add_col(table, "TABLE_ID", DATA_BINARY, 0, 0, 0);
- dict_mem_table_add_col(table, "POS", DATA_INT, 0, 4, 0);
- dict_mem_table_add_col(table, "NAME", DATA_BINARY, 0, 0, 0);
- dict_mem_table_add_col(table, "MTYPE", DATA_INT, 0, 4, 0);
- dict_mem_table_add_col(table, "PRTYPE", DATA_INT, 0, 4, 0);
- dict_mem_table_add_col(table, "LEN", DATA_INT, 0, 4, 0);
- dict_mem_table_add_col(table, "PREC", DATA_INT, 0, 4, 0);
+ table = dict_mem_table_create((char *) "SYS_COLUMNS",DICT_HDR_SPACE,7);
+
+ dict_mem_table_add_col(table, (char *) "TABLE_ID", DATA_BINARY,0,0,0);
+ dict_mem_table_add_col(table, (char *) "POS", DATA_INT, 0, 4, 0);
+ dict_mem_table_add_col(table, (char *) "NAME", DATA_BINARY, 0, 0, 0);
+ dict_mem_table_add_col(table, (char *) "MTYPE", DATA_INT, 0, 4, 0);
+ dict_mem_table_add_col(table, (char *) "PRTYPE", DATA_INT, 0, 4, 0);
+ dict_mem_table_add_col(table, (char *) "LEN", DATA_INT, 0, 4, 0);
+ dict_mem_table_add_col(table, (char *) "PREC", DATA_INT, 0, 4, 0);
table->id = DICT_COLUMNS_ID;
dict_table_add_to_cache(table);
dict_sys->sys_columns = table;
- index = dict_mem_index_create("SYS_COLUMNS", "CLUST_IND",
- DICT_HDR_SPACE,
- DICT_UNIQUE | DICT_CLUSTERED, 2);
+ index = dict_mem_index_create((char *) "SYS_COLUMNS",
+ (char *) "CLUST_IND", DICT_HDR_SPACE,
+ DICT_UNIQUE | DICT_CLUSTERED, 2);
- dict_mem_index_add_field(index, "TABLE_ID", 0);
- dict_mem_index_add_field(index, "POS", 0);
+ dict_mem_index_add_field(index, (char *) "TABLE_ID", 0);
+ dict_mem_index_add_field(index, (char *) "POS", 0);
index->page_no = mtr_read_ulint(dict_hdr + DICT_HDR_COLUMNS,
MLOG_4BYTES, &mtr);
index->id = DICT_COLUMNS_ID;
ut_a(dict_index_add_to_cache(table, index));
/*-------------------------*/
- table = dict_mem_table_create("SYS_INDEXES", DICT_HDR_SPACE, 7);
+ table = dict_mem_table_create((char *) "SYS_INDEXES",DICT_HDR_SPACE,7);
- dict_mem_table_add_col(table, "TABLE_ID", DATA_BINARY, 0, 0, 0);
- dict_mem_table_add_col(table, "ID", DATA_BINARY, 0, 0, 0);
- dict_mem_table_add_col(table, "NAME", DATA_BINARY, 0, 0, 0);
- dict_mem_table_add_col(table, "N_FIELDS", DATA_INT, 0, 4, 0);
- dict_mem_table_add_col(table, "TYPE", DATA_INT, 0, 4, 0);
- dict_mem_table_add_col(table, "SPACE", DATA_INT, 0, 4, 0);
- dict_mem_table_add_col(table, "PAGE_NO", DATA_INT, 0, 4, 0);
+ dict_mem_table_add_col(table, (char *) "TABLE_ID", DATA_BINARY, 0,0,0);
+ dict_mem_table_add_col(table, (char *) "ID", DATA_BINARY, 0, 0, 0);
+ dict_mem_table_add_col(table, (char *) "NAME", DATA_BINARY, 0, 0, 0);
+ dict_mem_table_add_col(table, (char *) "N_FIELDS", DATA_INT, 0, 4, 0);
+ dict_mem_table_add_col(table, (char *) "TYPE", DATA_INT, 0, 4, 0);
+ dict_mem_table_add_col(table, (char *) "SPACE", DATA_INT, 0, 4, 0);
+ dict_mem_table_add_col(table, (char *) "PAGE_NO", DATA_INT, 0, 4, 0);
/* The '+ 2' below comes from the 2 system fields */
ut_ad(DICT_SYS_INDEXES_PAGE_NO_FIELD == 6 + 2);
@@ -336,34 +339,34 @@ dict_boot(void)
dict_table_add_to_cache(table);
dict_sys->sys_indexes = table;
- index = dict_mem_index_create("SYS_INDEXES", "CLUST_IND",
- DICT_HDR_SPACE,
- DICT_UNIQUE | DICT_CLUSTERED, 2);
+ index = dict_mem_index_create((char *) "SYS_INDEXES",
+ (char *) "CLUST_IND", DICT_HDR_SPACE,
+ DICT_UNIQUE | DICT_CLUSTERED, 2);
- dict_mem_index_add_field(index, "TABLE_ID", 0);
- dict_mem_index_add_field(index, "ID", 0);
+ dict_mem_index_add_field(index, (char *) "TABLE_ID", 0);
+ dict_mem_index_add_field(index, (char *) "ID", 0);
index->page_no = mtr_read_ulint(dict_hdr + DICT_HDR_INDEXES,
MLOG_4BYTES, &mtr);
index->id = DICT_INDEXES_ID;
ut_a(dict_index_add_to_cache(table, index));
/*-------------------------*/
- table = dict_mem_table_create("SYS_FIELDS", DICT_HDR_SPACE, 3);
+ table = dict_mem_table_create((char *) "SYS_FIELDS", DICT_HDR_SPACE,3);
- dict_mem_table_add_col(table, "INDEX_ID", DATA_BINARY, 0, 0, 0);
- dict_mem_table_add_col(table, "POS", DATA_INT, 0, 4, 0);
- dict_mem_table_add_col(table, "COL_NAME", DATA_BINARY, 0, 0, 0);
+ dict_mem_table_add_col(table, (char *) "INDEX_ID", DATA_BINARY, 0,0,0);
+ dict_mem_table_add_col(table, (char *) "POS", DATA_INT, 0, 4, 0);
+ dict_mem_table_add_col(table, (char *) "COL_NAME", DATA_BINARY, 0,0,0);
table->id = DICT_FIELDS_ID;
dict_table_add_to_cache(table);
dict_sys->sys_fields = table;
- index = dict_mem_index_create("SYS_FIELDS", "CLUST_IND",
- DICT_HDR_SPACE,
- DICT_UNIQUE | DICT_CLUSTERED, 2);
+ index = dict_mem_index_create((char *) "SYS_FIELDS",
+ (char *) "CLUST_IND", DICT_HDR_SPACE,
+ DICT_UNIQUE | DICT_CLUSTERED, 2);
- dict_mem_index_add_field(index, "INDEX_ID", 0);
- dict_mem_index_add_field(index, "POS", 0);
+ dict_mem_index_add_field(index, (char *) "INDEX_ID", 0);
+ dict_mem_index_add_field(index, (char *) "POS", 0);
index->page_no = mtr_read_ulint(dict_hdr + DICT_HDR_FIELDS,
MLOG_4BYTES, &mtr);
diff --git a/innobase/dict/dict0crea.c b/innobase/dict/dict0crea.c
index f15d36251e4..69b1e7c61fd 100644
--- a/innobase/dict/dict0crea.c
+++ b/innobase/dict/dict0crea.c
@@ -1044,8 +1044,8 @@ dict_create_or_check_foreign_constraint_tables(void)
mutex_enter(&(dict_sys->mutex));
- table1 = dict_table_get_low("SYS_FOREIGN");
- table2 = dict_table_get_low("SYS_FOREIGN_COLS");
+ table1 = dict_table_get_low((char *) "SYS_FOREIGN");
+ table2 = dict_table_get_low((char *) "SYS_FOREIGN_COLS");
if (table1 && table2
&& UT_LIST_GET_LEN(table1->indexes) == 3
@@ -1061,18 +1061,18 @@ dict_create_or_check_foreign_constraint_tables(void)
trx = trx_allocate_for_mysql();
- trx->op_info = "creating foreign key sys tables";
+ trx->op_info = (char *) "creating foreign key sys tables";
if (table1) {
fprintf(stderr,
"InnoDB: dropping incompletely created SYS_FOREIGN table\n");
- row_drop_table_for_mysql("SYS_FOREIGN", trx, TRUE);
+ row_drop_table_for_mysql((char *) "SYS_FOREIGN", trx, TRUE);
}
if (table2) {
fprintf(stderr,
"InnoDB: dropping incompletely created SYS_FOREIGN_COLS table\n");
- row_drop_table_for_mysql("SYS_FOREIGN_COLS", trx, TRUE);
+ row_drop_table_for_mysql((char *) "SYS_FOREIGN_COLS",trx,TRUE);
}
fprintf(stderr,
@@ -1082,7 +1082,7 @@ dict_create_or_check_foreign_constraint_tables(void)
there are 2 secondary indexes on SYS_FOREIGN, and they
are defined just like below */
- str =
+ str = (char *)
"PROCEDURE CREATE_FOREIGN_SYS_TABLES_PROC () IS\n"
"BEGIN\n"
"CREATE TABLE\n"
@@ -1121,15 +1121,15 @@ dict_create_or_check_foreign_constraint_tables(void)
fprintf(stderr,
"InnoDB: dropping incompletely created SYS_FOREIGN tables\n");
- row_drop_table_for_mysql("SYS_FOREIGN", trx, TRUE);
- row_drop_table_for_mysql("SYS_FOREIGN_COLS", trx, TRUE);
+ row_drop_table_for_mysql((char *) "SYS_FOREIGN", trx, TRUE);
+ row_drop_table_for_mysql((char *) "SYS_FOREIGN_COLS",trx,TRUE);
error = DB_MUST_GET_MORE_FILE_SPACE;
}
que_graph_free(graph);
- trx->op_info = "";
+ trx->op_info = (char *) "";
trx_free_for_mysql(trx);
@@ -1165,7 +1165,7 @@ dict_create_add_foreigns_to_dictionary(
ut_ad(mutex_own(&(dict_sys->mutex)));
- if (NULL == dict_table_get_low("SYS_FOREIGN")) {
+ if (NULL == dict_table_get_low((char *) "SYS_FOREIGN")) {
fprintf(stderr,
"InnoDB: table SYS_FOREIGN not found from internal data dictionary\n");
return(DB_ERROR);
diff --git a/innobase/dict/dict0dict.c b/innobase/dict/dict0dict.c
index 56bdf83aa4d..efdac031423 100644
--- a/innobase/dict/dict0dict.c
+++ b/innobase/dict/dict0dict.c
@@ -544,15 +544,19 @@ dict_table_add_to_cache(
The clustered index will not always physically contain all
system columns. */
- dict_mem_table_add_col(table, "DB_ROW_ID", DATA_SYS, DATA_ROW_ID, 0, 0);
+ dict_mem_table_add_col(table, (char *) "DB_ROW_ID", DATA_SYS,
+ DATA_ROW_ID, 0, 0);
ut_ad(DATA_ROW_ID == 0);
- dict_mem_table_add_col(table, "DB_TRX_ID", DATA_SYS, DATA_TRX_ID, 0, 0);
+ dict_mem_table_add_col(table, (char *) "DB_TRX_ID", DATA_SYS,
+ DATA_TRX_ID, 0, 0);
ut_ad(DATA_TRX_ID == 1);
- dict_mem_table_add_col(table, "DB_ROLL_PTR", DATA_SYS, DATA_ROLL_PTR,
+ dict_mem_table_add_col(table, (char *) "DB_ROLL_PTR", DATA_SYS,
+ DATA_ROLL_PTR,
0, 0);
ut_ad(DATA_ROLL_PTR == 2);
- dict_mem_table_add_col(table, "DB_MIX_ID", DATA_SYS, DATA_MIX_ID, 0, 0);
+ dict_mem_table_add_col(table, (char *) "DB_MIX_ID", DATA_SYS,
+ DATA_MIX_ID, 0, 0);
ut_ad(DATA_MIX_ID == 3);
ut_ad(DATA_N_SYS_COLS == 4); /* This assert reminds that if a new
system column is added to the program,
@@ -1968,7 +1972,7 @@ dict_create_foreign_constraints(
return(DB_ERROR);
}
loop:
- ptr = dict_scan_to(ptr, "FOREIGN");
+ ptr = dict_scan_to(ptr, (char *) "FOREIGN");
if (*ptr == '\0' || dict_bracket_count(sql_string, ptr) != 1) {
@@ -1980,19 +1984,19 @@ loop:
return(error);
}
- ptr = dict_accept(ptr, "FOREIGN", &success);
+ ptr = dict_accept(ptr, (char *) "FOREIGN", &success);
if (!isspace(*ptr)) {
return(DB_CANNOT_ADD_CONSTRAINT);
}
- ptr = dict_accept(ptr, "KEY", &success);
+ ptr = dict_accept(ptr, (char *) "KEY", &success);
if (!success) {
goto loop;
}
- ptr = dict_accept(ptr, "(", &success);
+ ptr = dict_accept(ptr, (char *) "(", &success);
if (!success) {
goto loop;
@@ -2010,13 +2014,13 @@ col_loop1:
i++;
- ptr = dict_accept(ptr, ",", &success);
+ ptr = dict_accept(ptr, (char *) ",", &success);
if (success) {
goto col_loop1;
}
- ptr = dict_accept(ptr, ")", &success);
+ ptr = dict_accept(ptr, (char *) ")", &success);
if (!success) {
return(DB_CANNOT_ADD_CONSTRAINT);
@@ -2031,7 +2035,7 @@ col_loop1:
return(DB_CANNOT_ADD_CONSTRAINT);
}
- ptr = dict_accept(ptr, "REFERENCES", &success);
+ ptr = dict_accept(ptr, (char *) "REFERENCES", &success);
if (!success || !isspace(*ptr)) {
return(DB_CANNOT_ADD_CONSTRAINT);
@@ -2062,7 +2066,7 @@ col_loop1:
return(DB_CANNOT_ADD_CONSTRAINT);
}
- ptr = dict_accept(ptr, "(", &success);
+ ptr = dict_accept(ptr, (char *) "(", &success);
if (!success) {
dict_foreign_free(foreign);
@@ -2082,13 +2086,13 @@ col_loop2:
return(DB_CANNOT_ADD_CONSTRAINT);
}
- ptr = dict_accept(ptr, ",", &success);
+ ptr = dict_accept(ptr, (char *) ",", &success);
if (success) {
goto col_loop2;
}
- ptr = dict_accept(ptr, ")", &success);
+ ptr = dict_accept(ptr, (char *) ")", &success);
if (!success || foreign->n_fields != i) {
dict_foreign_free(foreign);
@@ -2623,7 +2627,8 @@ void
dict_update_statistics_low(
/*=======================*/
dict_table_t* table, /* in: table */
- ibool has_dict_mutex) /* in: TRUE if the caller has the
+ ibool has_dict_mutex __attribute__((unused)))
+ /* in: TRUE if the caller has the
dictionary mutex */
{
dict_index_t* index;
diff --git a/innobase/dict/dict0load.c b/innobase/dict/dict0load.c
index dcdc9ee01cd..d803d28963d 100644
--- a/innobase/dict/dict0load.c
+++ b/innobase/dict/dict0load.c
@@ -75,7 +75,7 @@ dict_get_first_table_name_in_db(
mtr_start(&mtr);
- sys_tables = dict_table_get_low("SYS_TABLES");
+ sys_tables = dict_table_get_low((char *) "SYS_TABLES");
sys_index = UT_LIST_GET_FIRST(sys_tables->indexes);
tuple = dtuple_create(heap, 1);
@@ -154,7 +154,7 @@ dict_print(void)
mtr_start(&mtr);
- sys_tables = dict_table_get_low("SYS_TABLES");
+ sys_tables = dict_table_get_low((char *) "SYS_TABLES");
sys_index = UT_LIST_GET_FIRST(sys_tables->indexes);
btr_pcur_open_at_index_side(TRUE, sys_index, BTR_SEARCH_LEAF, &pcur,
@@ -241,7 +241,7 @@ dict_load_table(
mtr_start(&mtr);
- sys_tables = dict_table_get_low("SYS_TABLES");
+ sys_tables = dict_table_get_low((char *) "SYS_TABLES");
sys_index = UT_LIST_GET_FIRST(sys_tables->indexes);
tuple = dtuple_create(heap, 1);
@@ -277,7 +277,7 @@ dict_load_table(
return(NULL);
}
- ut_a(0 == ut_strcmp("SPACE",
+ ut_a(0 == ut_strcmp((char *) "SPACE",
dict_field_get_col(
dict_index_get_nth_field(
dict_table_get_first_index(sys_tables), 9))->name));
@@ -285,7 +285,7 @@ dict_load_table(
field = rec_get_nth_field(rec, 9, &len);
space = mach_read_from_4(field);
- ut_a(0 == ut_strcmp("N_COLS",
+ ut_a(0 == ut_strcmp((char *) "N_COLS",
dict_field_get_col(
dict_index_get_nth_field(
dict_table_get_first_index(sys_tables), 4))->name));
@@ -295,7 +295,7 @@ dict_load_table(
table = dict_mem_table_create(name, space, n_cols);
- ut_a(0 == ut_strcmp("ID",
+ ut_a(0 == ut_strcmp((char *) "ID",
dict_field_get_col(
dict_index_get_nth_field(
dict_table_get_first_index(sys_tables), 3))->name));
@@ -498,7 +498,7 @@ dict_load_columns(
mtr_start(&mtr);
- sys_columns = dict_table_get_low("SYS_COLUMNS");
+ sys_columns = dict_table_get_low((char *) "SYS_COLUMNS");
sys_index = UT_LIST_GET_FIRST(sys_columns->indexes);
tuple = dtuple_create(heap, 1);
@@ -528,7 +528,7 @@ dict_load_columns(
ut_ad(len == 4);
ut_a(i == mach_read_from_4(field));
- ut_a(0 == ut_strcmp("NAME",
+ ut_a(0 == ut_strcmp((char *) "NAME",
dict_field_get_col(
dict_index_get_nth_field(
dict_table_get_first_index(sys_columns), 4))->name));
@@ -550,7 +550,7 @@ dict_load_columns(
field = rec_get_nth_field(rec, 7, &len);
col_len = mach_read_from_4(field);
- ut_a(0 == ut_strcmp("PREC",
+ ut_a(0 == ut_strcmp((char *) "PREC",
dict_field_get_col(
dict_index_get_nth_field(
dict_table_get_first_index(sys_columns), 8))->name));
@@ -608,7 +608,7 @@ dict_load_indexes(
mtr_start(&mtr);
- sys_indexes = dict_table_get_low("SYS_INDEXES");
+ sys_indexes = dict_table_get_low((char *) "SYS_INDEXES");
sys_index = UT_LIST_GET_FIRST(sys_indexes->indexes);
tuple = dtuple_create(heap, 1);
@@ -643,7 +643,7 @@ dict_load_indexes(
ut_ad(len == 8);
id = mach_read_from_8(field);
- ut_a(0 == ut_strcmp("NAME",
+ ut_a(0 == ut_strcmp((char *) "NAME",
dict_field_get_col(
dict_index_get_nth_field(
dict_table_get_first_index(sys_indexes), 4))->name));
@@ -663,7 +663,7 @@ dict_load_indexes(
field = rec_get_nth_field(rec, 7, &len);
space = mach_read_from_4(field);
- ut_a(0 == ut_strcmp("PAGE_NO",
+ ut_a(0 == ut_strcmp((char *) "PAGE_NO",
dict_field_get_col(
dict_index_get_nth_field(
dict_table_get_first_index(sys_indexes), 8))->name));
@@ -674,8 +674,8 @@ dict_load_indexes(
if (is_sys_table
&& ((type & DICT_CLUSTERED)
|| ((table == dict_sys->sys_tables)
- && (name_len == ut_strlen("ID_IND"))
- && (0 == ut_memcmp(name_buf, "ID_IND",
+ && (name_len == ut_strlen((char *) "ID_IND"))
+ && (0 == ut_memcmp(name_buf, (char *) "ID_IND",
name_len))))) {
/* The index was created in memory already in
@@ -727,7 +727,7 @@ dict_load_fields(
mtr_start(&mtr);
- sys_fields = dict_table_get_low("SYS_FIELDS");
+ sys_fields = dict_table_get_low((char *) "SYS_FIELDS");
sys_index = UT_LIST_GET_FIRST(sys_fields->indexes);
tuple = dtuple_create(heap, 1);
@@ -756,7 +756,7 @@ dict_load_fields(
ut_ad(len == 4);
ut_a(i == mach_read_from_4(field));
- ut_a(0 == ut_strcmp("COL_NAME",
+ ut_a(0 == ut_strcmp((char *) "COL_NAME",
dict_field_get_col(
dict_index_get_nth_field(
dict_table_get_first_index(sys_fields), 4))->name));
@@ -807,7 +807,7 @@ dict_load_foreign_cols(
foreign->n_fields * sizeof(void*));
mtr_start(&mtr);
- sys_foreign_cols = dict_table_get_low("SYS_FOREIGN_COLS");
+ sys_foreign_cols = dict_table_get_low((char *) "SYS_FOREIGN_COLS");
sys_index = UT_LIST_GET_FIRST(sys_foreign_cols->indexes);
tuple = dtuple_create(foreign->heap, 1);
@@ -885,7 +885,7 @@ dict_load_foreign(
mtr_start(&mtr);
- sys_foreign = dict_table_get_low("SYS_FOREIGN");
+ sys_foreign = dict_table_get_low((char *) "SYS_FOREIGN");
sys_index = UT_LIST_GET_FIRST(sys_foreign->indexes);
tuple = dtuple_create(heap2, 1);
@@ -999,7 +999,7 @@ dict_load_foreigns(
ut_ad(mutex_own(&(dict_sys->mutex)));
- sys_foreign = dict_table_get_low("SYS_FOREIGN");
+ sys_foreign = dict_table_get_low((char *) "SYS_FOREIGN");
if (sys_foreign == NULL) {
/* No foreign keys defined yet in this database */
diff --git a/innobase/eval/eval0eval.c b/innobase/eval/eval0eval.c
index 110387d8373..157d4e4f98d 100644
--- a/innobase/eval/eval0eval.c
+++ b/innobase/eval/eval0eval.c
@@ -164,8 +164,8 @@ eval_logical(
que_node_t* arg1;
que_node_t* arg2;
ibool val1;
- ibool val2;
- ibool val;
+ ibool val2 = 0; /* remove warning */
+ ibool val = 0; /* remove warning */
int func;
ut_ad(que_node_get_type(logical_node) == QUE_NODE_FUNC);
@@ -205,7 +205,7 @@ eval_arith(
que_node_t* arg1;
que_node_t* arg2;
lint val1;
- lint val2;
+ lint val2 = 0; /* remove warning */
lint val;
int func;
@@ -283,7 +283,7 @@ eval_predefined_2(
{
que_node_t* arg;
que_node_t* arg1;
- que_node_t* arg2;
+ que_node_t* arg2 = 0; /* remove warning (??? bug ???) */
lint int_val;
byte* data;
ulint len1;
diff --git a/innobase/fil/fil0fil.c b/innobase/fil/fil0fil.c
index 138f1a78985..727e52707e8 100644
--- a/innobase/fil/fil0fil.c
+++ b/innobase/fil/fil0fil.c
@@ -1217,7 +1217,7 @@ fil_aio_wait(
ut_ad(fil_validate());
if (os_aio_use_native_aio) {
- srv_io_thread_op_info[segment] = "native aio handle";
+ srv_io_thread_op_info[segment] = (char *) "native aio handle";
#ifdef WIN_ASYNC_IO
ret = os_aio_windows_handle(segment, 0, &fil_node, &message,
&type);
@@ -1228,7 +1228,7 @@ fil_aio_wait(
ut_a(0);
#endif
} else {
- srv_io_thread_op_info[segment] = "simulated aio handle";
+ srv_io_thread_op_info[segment] =(char *)"simulated aio handle";
ret = os_aio_simulated_handle(segment, (void**) &fil_node,
&message, &type);
@@ -1236,7 +1236,7 @@ fil_aio_wait(
ut_a(ret);
- srv_io_thread_op_info[segment] = "complete io for fil node";
+ srv_io_thread_op_info[segment] = (char *) "complete io for fil node";
mutex_enter(&(system->mutex));
@@ -1249,10 +1249,11 @@ fil_aio_wait(
/* Do the i/o handling */
if (buf_pool_is_block(message)) {
- srv_io_thread_op_info[segment] = "complete io for buf page";
+ srv_io_thread_op_info[segment] =
+ (char *) "complete io for buf page";
buf_page_io_complete(message);
} else {
- srv_io_thread_op_info[segment] = "complete io for log";
+ srv_io_thread_op_info[segment] =(char *) "complete io for log";
log_io_complete(message);
}
}
diff --git a/innobase/fsp/fsp0fsp.c b/innobase/fsp/fsp0fsp.c
index ccc13f15fde..25fc2891e76 100644
--- a/innobase/fsp/fsp0fsp.c
+++ b/innobase/fsp/fsp0fsp.c
@@ -803,7 +803,7 @@ fsp_parse_init_file_page(
/*=====================*/
/* out: end of log record or NULL */
byte* ptr, /* in: buffer */
- byte* end_ptr,/* in: buffer end */
+ byte* end_ptr __attribute__((unused)), /* in: buffer end */
page_t* page) /* in: page or NULL */
{
ut_ad(ptr && end_ptr);
@@ -1252,7 +1252,7 @@ fsp_seg_inode_page_get_nth_inode(
/* out: segment inode */
page_t* page, /* in: segment inode page */
ulint i, /* in: inode index on page */
- mtr_t* mtr) /* in: mini-transaction handle */
+ mtr_t* mtr __attribute__((unused))) /* in: mini-transaction handle */
{
ut_ad(i < FSP_SEG_INODES_PER_PAGE);
ut_ad(mtr_memo_contains(mtr, buf_block_align(page),
@@ -1494,7 +1494,7 @@ fseg_get_nth_frag_page_no(
/* out: page number, FIL_NULL if not in use */
fseg_inode_t* inode, /* in: segment inode */
ulint n, /* in: slot index */
- mtr_t* mtr) /* in: mtr handle */
+ mtr_t* mtr __attribute__((unused))) /* in: mtr handle */
{
ut_ad(inode && mtr);
ut_ad(n < FSEG_FRAG_ARR_N_SLOTS);
@@ -1632,7 +1632,7 @@ fseg_create_general(
fsp_header_t* space_header;
fseg_inode_t* inode;
dulint seg_id;
- fseg_header_t* header;
+ fseg_header_t* header = 0; /* remove warning */
rw_lock_t* latch;
ibool success;
page_t* ret = NULL;
diff --git a/innobase/ibuf/ibuf0ibuf.c b/innobase/ibuf/ibuf0ibuf.c
index bd1f0e6e1d8..a6355ce7ca5 100644
--- a/innobase/ibuf/ibuf0ibuf.c
+++ b/innobase/ibuf/ibuf0ibuf.c
@@ -292,6 +292,7 @@ ibuf_count_get(
/**********************************************************************
Sets the ibuf count for a given page. */
+#ifdef UNIV_IBUF_DEBUG
static
void
ibuf_count_set(
@@ -306,6 +307,7 @@ ibuf_count_set(
*(ibuf_counts[space] + page_no) = val;
}
+#endif
/**********************************************************************
Creates the insert buffer data structure at a database startup and
@@ -472,19 +474,18 @@ ibuf_data_init_for_space(
table = dict_mem_table_create(buf, space, 2);
- dict_mem_table_add_col(table, "PAGE_NO", DATA_BINARY, 0, 0, 0);
- dict_mem_table_add_col(table, "TYPES", DATA_BINARY, 0, 0, 0);
+ dict_mem_table_add_col(table,(char *) "PAGE_NO", DATA_BINARY, 0, 0, 0);
+ dict_mem_table_add_col(table,(char *) "TYPES", DATA_BINARY, 0, 0, 0);
table->id = ut_dulint_add(DICT_IBUF_ID_MIN, space);
dict_table_add_to_cache(table);
- index = dict_mem_index_create(buf, "CLUST_IND", space,
- DICT_CLUSTERED | DICT_UNIVERSAL | DICT_IBUF,
- 2);
+ index = dict_mem_index_create(buf, (char *) "CLUST_IND", space,
+ DICT_CLUSTERED | DICT_UNIVERSAL | DICT_IBUF,2);
- dict_mem_index_add_field(index, "PAGE_NO", 0);
- dict_mem_index_add_field(index, "TYPES", 0);
+ dict_mem_index_add_field(index, (char *) "PAGE_NO", 0);
+ dict_mem_index_add_field(index, (char *) "TYPES", 0);
index->page_no = FSP_IBUF_TREE_ROOT_PAGE_NO;
@@ -538,7 +539,7 @@ ibuf_parse_bitmap_init(
/*===================*/
/* out: end of log record or NULL */
byte* ptr, /* in: buffer */
- byte* end_ptr,/* in: buffer end */
+ byte* end_ptr __attribute__((unused)), /* in: buffer end */
page_t* page, /* in: page or NULL */
mtr_t* mtr) /* in: mtr or NULL */
{
@@ -561,7 +562,8 @@ ibuf_bitmap_page_get_bits(
page_t* page, /* in: bitmap page */
ulint page_no,/* in: page whose bits to get */
ulint bit, /* in: IBUF_BITMAP_FREE, IBUF_BITMAP_BUFFERED, ... */
- mtr_t* mtr) /* in: mtr containing an x-latch to the bitmap page */
+ mtr_t* mtr __attribute__((unused))) /* in: mtr containing an x-latch
+ to the bitmap page */
{
ulint byte_offset;
ulint bit_offset;
diff --git a/innobase/include/Makefile.am b/innobase/include/Makefile.am
index fd5cc8b1a80..8664f6dfc17 100644
--- a/innobase/include/Makefile.am
+++ b/innobase/include/Makefile.am
@@ -55,5 +55,7 @@ noinst_HEADERS = btr0btr.h btr0btr.ic btr0cur.h btr0cur.ic \
ut0dbg.h ut0lst.h ut0mem.h ut0mem.ic ut0rnd.h ut0rnd.ic \
ut0sort.h ut0ut.h ut0ut.ic
+EXTRA_DIST = Makefile.i
+
# Don't update the files from bitkeeper
%::SCCS/s.%
diff --git a/innobase/include/Makefile.i b/innobase/include/Makefile.i
index 8c7e9910f26..985ec525950 100644
--- a/innobase/include/Makefile.i
+++ b/innobase/include/Makefile.i
@@ -2,7 +2,7 @@
libsdir = ../libs
-INCLUDES = -I../../include -I../include
+INCLUDES = -I$(srcdir)/../include -I$(srcdir)/../../include -I../../include
# Don't update the files from bitkeeper
%::SCCS/s.%
diff --git a/innobase/include/btr0btr.ic b/innobase/include/btr0btr.ic
index 5c1c89e9840..09006828cc9 100644
--- a/innobase/include/btr0btr.ic
+++ b/innobase/include/btr0btr.ic
@@ -89,7 +89,7 @@ btr_page_get_level(
/*===============*/
/* out: level, leaf level == 0 */
page_t* page, /* in: index page */
- mtr_t* mtr) /* in: mini-transaction handle */
+ mtr_t* mtr __attribute__((unused))) /* in: mini-transaction handle */
{
ut_ad(page && mtr);
@@ -121,7 +121,7 @@ btr_page_get_next(
/*==============*/
/* out: next page number */
page_t* page, /* in: index page */
- mtr_t* mtr) /* in: mini-transaction handle */
+ mtr_t* mtr __attribute__((unused))) /* in: mini-transaction handle */
{
ut_ad(page && mtr);
ut_ad(mtr_memo_contains(mtr, buf_block_align(page),
@@ -155,7 +155,7 @@ btr_page_get_prev(
/*==============*/
/* out: prev page number */
page_t* page, /* in: index page */
- mtr_t* mtr) /* in: mini-transaction handle */
+ mtr_t* mtr __attribute__((unused))) /* in: mini-transaction handle */
{
ut_ad(page && mtr);
diff --git a/innobase/include/buf0buf.ic b/innobase/include/buf0buf.ic
index 8f5443ad150..52bee0eb282 100644
--- a/innobase/include/buf0buf.ic
+++ b/innobase/include/buf0buf.ic
@@ -631,9 +631,10 @@ UNIV_INLINE
void
buf_page_dbg_add_level(
/*===================*/
- buf_frame_t* frame, /* in: buffer page where we have acquired
- a latch */
- ulint level) /* in: latching order level */
+ buf_frame_t* frame __attribute__((unused)), /* in: buffer page
+ where we have acquired latch */
+ ulint level __attribute__((unused))) /* in: latching order
+ level */
{
#ifdef UNIV_SYNC_DEBUG
sync_thread_add_level(&(buf_block_align(frame)->lock), level);
diff --git a/innobase/include/dict0dict.ic b/innobase/include/dict0dict.ic
index 821465f96a8..71ea67117a7 100644
--- a/innobase/include/dict0dict.ic
+++ b/innobase/include/dict0dict.ic
@@ -106,7 +106,7 @@ dict_table_get_n_sys_cols(
/*======================*/
/* out: number of system (e.g.,
ROW_ID) columns of a table */
- dict_table_t* table) /* in: table */
+ dict_table_t* table __attribute__((unused))) /* in: table */
{
ut_ad(table);
ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
diff --git a/innobase/include/dyn0dyn.h b/innobase/include/dyn0dyn.h
index 0952a8b4647..332622b6d4c 100644
--- a/innobase/include/dyn0dyn.h
+++ b/innobase/include/dyn0dyn.h
@@ -18,7 +18,12 @@ typedef dyn_block_t dyn_array_t;
/* Initial 'payload' size in bytes in a dynamic array block */
-#define DYN_ARRAY_DATA_SIZE 512
+#ifndef _AIX
+#define DYN_ARRAY_DATA_SIZE 1024
+#else
+/* AIX has a quite small stack / thread */
+#define DYN_ARRAY_DATA_SIZE 128
+#endif
/*************************************************************************
Initializes a dynamic array. */
diff --git a/innobase/include/ha0ha.ic b/innobase/include/ha0ha.ic
index 7b4c624c653..9d344bca04c 100644
--- a/innobase/include/ha0ha.ic
+++ b/innobase/include/ha0ha.ic
@@ -59,7 +59,7 @@ ha_node_t*
ha_chain_get_next(
/*==============*/
/* out: next node, NULL if none */
- hash_table_t* table, /* in: hash table */
+ hash_table_t* table __attribute__((unused)), /* in: hash table */
ha_node_t* node) /* in: hash chain node */
{
ut_ad(table);
diff --git a/innobase/include/row0mysql.ic b/innobase/include/row0mysql.ic
index 6096e5771f7..e9d493da8b5 100644
--- a/innobase/include/row0mysql.ic
+++ b/innobase/include/row0mysql.ic
@@ -15,7 +15,8 @@ row_mysql_store_var_len(
/*====================*/
/* out: dest + 2 */
byte* dest, /* in: where to store */
- ulint len) /* in: length, must fit in two bytes */
+ ulint len __attribute__((unused))) /* in: length, must fit in two
+ bytes */
{
ut_ad(len < 256 * 256);
/*
diff --git a/innobase/include/row0vers.ic b/innobase/include/row0vers.ic
index aa7a7aa2299..5ece47c35d1 100644
--- a/innobase/include/row0vers.ic
+++ b/innobase/include/row0vers.ic
@@ -60,7 +60,7 @@ row_vers_sec_rec_may_see_older(
/*===========================*/
/* out: FALSE if can be read immediately */
rec_t* rec, /* in: record which should be read or passed */
- dict_index_t* index, /* in: secondary index */
+ dict_index_t* index __attribute__((unused)),/* in: secondary index */
read_view_t* view) /* in: read view */
{
page_t* page;
diff --git a/innobase/include/srv0srv.h b/innobase/include/srv0srv.h
index 01986c759d7..2b40852fe67 100644
--- a/innobase/include/srv0srv.h
+++ b/innobase/include/srv0srv.h
@@ -88,6 +88,7 @@ extern ulint srv_n_rows_read;
extern ibool srv_print_innodb_monitor;
extern ibool srv_print_innodb_lock_monitor;
extern ibool srv_print_innodb_tablespace_monitor;
+extern ibool srv_print_verbose_log;
extern ibool srv_print_innodb_table_monitor;
extern ibool srv_lock_timeout_and_monitor_active;
diff --git a/innobase/include/sync0rw.ic b/innobase/include/sync0rw.ic
index 2a02cfb6a53..09580cfc497 100644
--- a/innobase/include/sync0rw.ic
+++ b/innobase/include/sync0rw.ic
@@ -126,7 +126,8 @@ rw_lock_s_lock_low(
/*===============*/
/* out: TRUE if success */
rw_lock_t* lock, /* in: pointer to rw-lock */
- ulint pass, /* in: pass value; != 0, if the lock will be
+ ulint pass __attribute__((unused)),
+ /* in: pass value; != 0, if the lock will be
passed to another thread to unlock */
char* file_name, /* in: file name where lock requested */
ulint line) /* in: line where requested */
diff --git a/innobase/include/univ.i b/innobase/include/univ.i
index a4345babbbe..8870d80f611 100644
--- a/innobase/include/univ.i
+++ b/innobase/include/univ.i
@@ -30,13 +30,14 @@ be defined:
/* Most C compilers other than gcc do not know 'extern inline' */
#if !defined(__GNUC__) && !defined(__WIN__)
+#undef UNIV_MUST_NOT_INLINE
#define UNIV_MUST_NOT_INLINE
#endif
/* Include two header files from MySQL to make the Unix flavor used
in compiling more Posix-compatible. We assume that 'innobase' is a
subdirectory of 'mysql'. */
-#include <global.h>
+#include <my_global.h>
#include <my_pthread.h>
/* Include <sys/stat.h> to get S_I... macros defined for os0file.c */
diff --git a/innobase/lock/lock0lock.c b/innobase/lock/lock0lock.c
index 0b2b85d0337..f2309a5c562 100644
--- a/innobase/lock/lock0lock.c
+++ b/innobase/lock/lock0lock.c
@@ -539,7 +539,8 @@ lock_sec_rec_cons_read_sees(
index record */
rec_t* rec, /* in: user record which should be read or
passed over by a read cursor */
- dict_index_t* index, /* in: non-clustered index */
+ dict_index_t* index __attribute__((unused)),
+ /* in: non-clustered index */
read_view_t* view) /* in: consistent read view */
{
dulint max_trx_id;
@@ -2292,7 +2293,7 @@ list start is moved to another page. */
void
lock_move_rec_list_start(
/*=====================*/
- page_t* new_page, /* in: index page to move to */
+ page_t* new_page __attribute__((unused)),/*in: index page to move to */
page_t* page, /* in: index page */
rec_t* rec, /* in: record on page: this is the
first record NOT copied */
@@ -2736,7 +2737,7 @@ lock_deadlock_recursive(
we return TRUE */
{
lock_t* lock;
- ulint bit_no;
+ ulint bit_no = 0; /* remove warning */
trx_t* lock_trx;
ut_a(trx && start && wait_lock);
diff --git a/innobase/log/log0log.c b/innobase/log/log0log.c
index 4fcf625242b..e787176bb21 100644
--- a/innobase/log/log0log.c
+++ b/innobase/log/log0log.c
@@ -1858,7 +1858,7 @@ log_group_archive(
os_file_t file_handle;
dulint start_lsn;
dulint end_lsn;
- char name[100];
+ char name[1024];
byte* buf;
ulint len;
ibool ret;
@@ -2650,9 +2650,11 @@ logs_empty_and_mark_files_at_shutdown(void)
dulint lsn;
ulint arch_log_no;
- ut_print_timestamp(stderr);
- fprintf(stderr, " InnoDB: Starting shutdown...\n");
-
+ if (srv_print_verbose_log)
+ {
+ ut_print_timestamp(stderr);
+ fprintf(stderr, " InnoDB: Starting shutdown...\n");
+ }
/* Wait until the master thread and all other operations are idle: our
algorithm only works if the server is idle at shutdown */
@@ -2757,8 +2759,11 @@ loop:
fil_flush_file_spaces(FIL_TABLESPACE);
- ut_print_timestamp(stderr);
- fprintf(stderr, " InnoDB: Shutdown completed\n");
+ if (srv_print_verbose_log)
+ {
+ ut_print_timestamp(stderr);
+ fprintf(stderr, " InnoDB: Shutdown completed\n");
+ }
}
/**********************************************************
diff --git a/innobase/mem/mem0dbg.c b/innobase/mem/mem0dbg.c
index f8f62dffa8b..f94119b7f38 100644
--- a/innobase/mem/mem0dbg.c
+++ b/innobase/mem/mem0dbg.c
@@ -372,7 +372,8 @@ void
mem_heap_validate_or_print(
/*=======================*/
mem_heap_t* heap, /* in: memory heap */
- byte* top, /* in: calculate and validate only until
+ byte* top __attribute__((unused)),
+ /* in: calculate and validate only until
this top pointer in the heap is reached,
if this pointer is NULL, ignored */
ibool print, /* in: if TRUE, prints the contents
@@ -578,7 +579,8 @@ static
void
mem_print_info_low(
/*===============*/
- ibool print_all) /* in: if TRUE, all heaps are printed,
+ ibool print_all __attribute__((unused)))
+ /* in: if TRUE, all heaps are printed,
else only the heaps allocated after the
previous call of this function */
{
diff --git a/innobase/mtr/mtr0mtr.c b/innobase/mtr/mtr0mtr.c
index f38aa6793b9..6aa1f3509d4 100644
--- a/innobase/mtr/mtr0mtr.c
+++ b/innobase/mtr/mtr0mtr.c
@@ -469,7 +469,8 @@ mtr_read_ulint(
/* out: value read */
byte* ptr, /* in: pointer from where to read */
ulint type, /* in: MLOG_1BYTE, MLOG_2BYTES, MLOG_4BYTES */
- mtr_t* mtr) /* in: mini-transaction handle */
+ mtr_t* mtr __attribute__((unused)))
+ /* in: mini-transaction handle */
{
ut_ad(mtr->state == MTR_ACTIVE);
ut_ad(mtr_memo_contains(mtr, buf_block_align(ptr),
@@ -494,8 +495,9 @@ mtr_read_dulint(
/*===========*/
/* out: value read */
byte* ptr, /* in: pointer from where to read */
- ulint type, /* in: MLOG_8BYTES */
- mtr_t* mtr) /* in: mini-transaction handle */
+ ulint type __attribute__((unused)), /* in: MLOG_8BYTES */
+ mtr_t* mtr __attribute__((unused)))
+ /* in: mini-transaction handle */
{
ut_ad(mtr->state == MTR_ACTIVE);
ut_ad(ptr && mtr);
diff --git a/innobase/odbc/odbc0odbc.c b/innobase/odbc/odbc0odbc.c
index 640a88a2503..0deb17c6714 100644
--- a/innobase/odbc/odbc0odbc.c
+++ b/innobase/odbc/odbc0odbc.c
@@ -421,7 +421,7 @@ SQLError(
}
*pfNativeError = 0;
- ut_memcpy(szSqlState, "S1000", 6);
+ ut_memcpy(szSqlState, (char *) "S1000", 6);
len = (ulint)cbErrorMsgMax - 1;
diff --git a/innobase/os/os0file.c b/innobase/os/os0file.c
index 2ae59e26f35..010716d8d17 100644
--- a/innobase/os/os0file.c
+++ b/innobase/os/os0file.c
@@ -494,14 +494,13 @@ os_file_get_size(
offs = lseek(file, 0, SEEK_END);
- if (sizeof(off_t) > 4) {
- *size = (ulint)(offs & 0xFFFFFFFF);
- *size_high = (ulint)(offs >> 32);
- } else {
- *size = (ulint) offs;
- *size_high = 0;
- }
-
+#if SIZEOF_OFF_T > 4
+ *size = (ulint)(offs & 0xFFFFFFFF);
+ *size_high = (ulint)(offs >> 32);
+#else
+ *size = (ulint) offs;
+ *size_high = 0;
+#endif
return(TRUE);
#endif
}
@@ -658,18 +657,16 @@ os_file_pread(
/* If off_t is > 4 bytes in size, then we assume we can pass a
64-bit address */
- if (sizeof(off_t) > 4) {
- offs = (off_t)offset + (((off_t)offset_high) << 32);
-
- } else {
- offs = (off_t)offset;
+#if SIZEOF_OFF_T > 4
+ offs = (off_t)offset + (((off_t)offset_high) << 32);
+#else
+ offs = (off_t)offset;
- if (offset_high > 0) {
- fprintf(stderr,
- "InnoDB: Error: file read at offset > 4 GB\n");
- }
+ if (offset_high > 0) {
+ fprintf(stderr,
+ "InnoDB: Error: file read at offset > 4 GB\n");
}
-
+#endif
os_n_file_reads++;
#ifdef HAVE_PREAD
diff --git a/innobase/os/os0thread.c b/innobase/os/os0thread.c
index 11bff73608a..49d4c8518fb 100644
--- a/innobase/os/os0thread.c
+++ b/innobase/os/os0thread.c
@@ -58,7 +58,8 @@ os_thread_create(
#endif
void* arg, /* in: argument to start
function */
- os_thread_id_t* thread_id) /* out: id of created
+ os_thread_id_t* thread_id __attribute__((unused)))
+ /* out: id of created
thread */
{
#ifdef __WIN__
@@ -204,7 +205,8 @@ ulint
os_thread_get_priority(
/*===================*/
/* out: priority */
- os_thread_t handle) /* in: OS handle to the thread */
+ os_thread_t handle __attribute__((unused)))
+ /* in: OS handle to the thread */
{
#ifdef __WIN__
int os_pri;
diff --git a/innobase/page/page0cur.c b/innobase/page/page0cur.c
index 0b233b4dd72..85beffbcc94 100644
--- a/innobase/page/page0cur.c
+++ b/innobase/page/page0cur.c
@@ -510,14 +510,14 @@ page_cur_parse_insert_rec(
mtr_t* mtr) /* in: mtr or NULL */
{
ulint extra_info_yes;
- ulint offset;
+ ulint offset = 0; /* remove warning */
ulint origin_offset;
ulint end_seg_len;
ulint mismatch_index;
rec_t* cursor_rec;
byte buf1[1024];
byte* buf;
- ulint info_bits;
+ ulint info_bits = 0; /* remove warning */
page_cur_t cursor;
if (!is_short) {
@@ -835,9 +835,9 @@ page_copy_rec_list_end_to_created_page(
rec_t* rec, /* in: first record to copy */
mtr_t* mtr) /* in: mtr */
{
- page_dir_slot_t* slot;
+ page_dir_slot_t* slot = 0; /* remove warning */
byte* heap_top;
- rec_t* insert_rec;
+ rec_t* insert_rec = 0; /* remove warning */
rec_t* prev_rec;
ulint count;
ulint n_recs;
@@ -882,6 +882,7 @@ page_copy_rec_list_end_to_created_page(
slot_index = 0;
n_recs = 0;
+ /* should be do ... until, comment by Jani */
while (rec != page_get_supremum_rec(page)) {
insert_rec = rec_copy(heap_top, rec);
diff --git a/innobase/page/page0page.c b/innobase/page/page0page.c
index a75a7279fb5..bf8af45a00a 100644
--- a/innobase/page/page0page.c
+++ b/innobase/page/page0page.c
@@ -210,7 +210,7 @@ page_parse_create(
/*==============*/
/* out: end of log record or NULL */
byte* ptr, /* in: buffer */
- byte* end_ptr,/* in: buffer end */
+ byte* end_ptr __attribute__((unused)), /* in: buffer end */
page_t* page, /* in: page or NULL */
mtr_t* mtr) /* in: mtr or NULL */
{
@@ -283,7 +283,7 @@ page_create(
tuple = dtuple_create(heap, 1);
field = dtuple_get_nth_field(tuple, 0);
- dfield_set_data(field, "infimum", strlen("infimum") + 1);
+ dfield_set_data(field,(char *) "infimum", strlen("infimum") + 1);
dtype_set(dfield_get_type(field), DATA_VARCHAR, DATA_ENGLISH, 20, 0);
/* Set the corresponding physical record to its place in the page
@@ -305,7 +305,7 @@ page_create(
tuple = dtuple_create(heap, 1);
field = dtuple_get_nth_field(tuple, 0);
- dfield_set_data(field, "supremum", strlen("supremum") + 1);
+ dfield_set_data(field, (char *) "supremum", strlen("supremum") + 1);
dtype_set(dfield_get_type(field), DATA_VARCHAR, DATA_ENGLISH, 20, 0);
supremum_rec = rec_convert_dtuple_to_rec(heap_top, tuple);
diff --git a/innobase/pars/pars0opt.c b/innobase/pars/pars0opt.c
index 6f4957f96ee..35d39caad00 100644
--- a/innobase/pars/pars0opt.c
+++ b/innobase/pars/pars0opt.c
@@ -528,7 +528,7 @@ opt_search_plan_for_table(
ulint goodness;
ulint last_op;
ulint best_goodness;
- ulint best_last_op;
+ ulint best_last_op = 0; /* remove warning */
ulint mix_id_pos;
que_node_t* index_plan[128];
que_node_t* best_index_plan[128];
@@ -546,6 +546,7 @@ opt_search_plan_for_table(
best_index = index; /* Eliminate compiler warning */
best_goodness = 0;
+ /* should be do ... until ? comment by Jani */
while (index) {
goodness = opt_calc_index_goodness(index, sel_node, i,
index_plan, &last_op);
diff --git a/innobase/pars/pars0pars.c b/innobase/pars/pars0pars.c
index 8ffbca579b8..664f498ef3e 100644
--- a/innobase/pars/pars0pars.c
+++ b/innobase/pars/pars0pars.c
@@ -1942,7 +1942,7 @@ Called by yyparse on error. */
void
yyerror(
/*====*/
- char* s) /* in: error message string */
+ char* s __attribute__((unused))) /* in: error message string */
{
ut_ad(s);
diff --git a/innobase/que/que0que.c b/innobase/que/que0que.c
index 97843311d21..1cee316f32c 100644
--- a/innobase/que/que0que.c
+++ b/innobase/que/que0que.c
@@ -103,7 +103,7 @@ que_thr_add_update_info(
mach_write_to_8(thr->msg_buf + SESS_SRV_MSG_N_DELETES,
graph->n_deletes);
}
-#endif
+#endif
/***************************************************************************
Adds a query graph to the session's list of graphs. */
@@ -395,7 +395,7 @@ graph so that the graph can communicate an error message to the client.) */
void
que_fork_error_handle(
/*==================*/
- trx_t* trx, /* in: trx */
+ trx_t* trx __attribute__((unused)), /* in: trx */
que_t* fork) /* in: query graph which was run before signal
handling started, NULL not allowed */
{
@@ -1164,47 +1164,47 @@ que_node_print_info(
addr = (ulint)node;
if (type == QUE_NODE_SELECT) {
- str = "SELECT";
+ str = (char *) "SELECT";
} else if (type == QUE_NODE_INSERT) {
- str = "INSERT";
+ str = (char *) "INSERT";
} else if (type == QUE_NODE_UPDATE) {
- str = "UPDATE";
+ str = (char *) "UPDATE";
} else if (type == QUE_NODE_WHILE) {
- str = "WHILE";
+ str = (char *) "WHILE";
} else if (type == QUE_NODE_ASSIGNMENT) {
- str = "ASSIGNMENT";
+ str = (char *) "ASSIGNMENT";
} else if (type == QUE_NODE_IF) {
- str = "IF";
+ str = (char *) "IF";
} else if (type == QUE_NODE_FETCH) {
- str = "FETCH";
+ str = (char *) "FETCH";
} else if (type == QUE_NODE_OPEN) {
- str = "OPEN";
+ str = (char *) "OPEN";
} else if (type == QUE_NODE_PROC) {
- str = "STORED PROCEDURE";
+ str = (char *) "STORED PROCEDURE";
} else if (type == QUE_NODE_FUNC) {
- str = "FUNCTION";
+ str = (char *) "FUNCTION";
} else if (type == QUE_NODE_LOCK) {
- str = "LOCK";
+ str = (char *) "LOCK";
} else if (type == QUE_NODE_THR) {
- str = "QUERY THREAD";
+ str = (char *) "QUERY THREAD";
} else if (type == QUE_NODE_COMMIT) {
- str = "COMMIT";
+ str = (char *) "COMMIT";
} else if (type == QUE_NODE_UNDO) {
- str = "UNDO ROW";
+ str = (char *) "UNDO ROW";
} else if (type == QUE_NODE_PURGE) {
- str = "PURGE ROW";
+ str = (char *) "PURGE ROW";
} else if (type == QUE_NODE_ROLLBACK) {
- str = "ROLLBACK";
+ str = (char *) "ROLLBACK";
} else if (type == QUE_NODE_CREATE_TABLE) {
- str = "CREATE TABLE";
+ str = (char *) "CREATE TABLE";
} else if (type == QUE_NODE_CREATE_INDEX) {
- str = "CREATE INDEX";
+ str = (char *) "CREATE INDEX";
} else if (type == QUE_NODE_FOR) {
- str = "FOR LOOP";
+ str = (char *) "FOR LOOP";
} else if (type == QUE_NODE_RETURN) {
- str = "RETURN";
+ str = (char *) "RETURN";
} else {
- str = "UNKNOWN NODE TYPE";
+ str = (char *) "UNKNOWN NODE TYPE";
}
printf("Node type %lu: %s, address %lx\n", type, str, addr);
diff --git a/innobase/rem/rem0cmp.c b/innobase/rem/rem0cmp.c
index 60828b122ba..9a5a0eb6e8e 100644
--- a/innobase/rem/rem0cmp.c
+++ b/innobase/rem/rem0cmp.c
@@ -79,7 +79,7 @@ ulint
cmp_collate(
/*========*/
/* out: collation order position */
- dtype_t* type, /* in: type */
+ dtype_t* type __attribute__((unused)) , /* in: type */
ulint code) /* in: code of a character stored in database
record */
{
diff --git a/innobase/rem/rem0rec.c b/innobase/rem/rem0rec.c
index 3889f62afa2..a151389798d 100644
--- a/innobase/rem/rem0rec.c
+++ b/innobase/rem/rem0rec.c
@@ -528,9 +528,9 @@ rec_print(
ut_ad(rec);
if (rec_get_1byte_offs_flag(rec)) {
- offs = "TRUE";
+ offs = (char *) "TRUE";
} else {
- offs = "FALSE";
+ offs = (char *) "FALSE";
}
n = rec_get_n_fields(rec);
diff --git a/innobase/row/row0ins.c b/innobase/row/row0ins.c
index 3321c288e39..c3f912d5f61 100644
--- a/innobase/row/row0ins.c
+++ b/innobase/row/row0ins.c
@@ -399,7 +399,7 @@ row_ins_check_foreign_constraint(
dictionary cache if they exist at all */
dict_table_t* table, /* in: if check_ref is TRUE, then the foreign
table, else the referenced table */
- dict_index_t* index, /* in: index in table */
+ dict_index_t* index __attribute__((unused)),/* in: index in table */
dtuple_t* entry, /* in: index entry for index */
que_thr_t* thr) /* in: query thread */
{
@@ -840,7 +840,7 @@ row_ins_index_entry_low(
que_thr_t* thr) /* in: query thread */
{
btr_cur_t cursor;
- ulint modify;
+ ulint modify = 0; /* remove warning */
rec_t* insert_rec;
rec_t* rec;
ulint err;
diff --git a/innobase/row/row0mysql.c b/innobase/row/row0mysql.c
index c4a844b3fa9..f5ed0ef65af 100644
--- a/innobase/row/row0mysql.c
+++ b/innobase/row/row0mysql.c
@@ -564,7 +564,7 @@ row_lock_table_autoinc_for_mysql(
ut_ad(trx);
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
- trx->op_info = "setting auto-inc lock";
+ trx->op_info = (char *) "setting auto-inc lock";
if (node == NULL) {
row_get_prebuilt_insert_row(prebuilt);
@@ -600,14 +600,14 @@ run_again:
goto run_again;
}
- trx->op_info = "";
+ trx->op_info = (char *) "";
return(err);
}
que_thr_stop_for_mysql_no_error(thr, trx);
- trx->op_info = "";
+ trx->op_info = (char *) "";
return((int) err);
}
@@ -655,7 +655,7 @@ row_insert_for_mysql(
return(DB_ERROR);
}
- trx->op_info = "inserting";
+ trx->op_info = (char *) "inserting";
trx_start_if_not_started(trx);
@@ -696,7 +696,7 @@ run_again:
goto run_again;
}
- trx->op_info = "";
+ trx->op_info = (char *) "";
return(err);
}
@@ -713,7 +713,7 @@ run_again:
}
row_update_statistics_if_needed(prebuilt);
- trx->op_info = "";
+ trx->op_info = (char *) "";
return((int) err);
}
@@ -851,7 +851,7 @@ row_update_for_mysql(
return(DB_ERROR);
}
- trx->op_info = "updating or deleting";
+ trx->op_info = (char *) "updating or deleting";
trx_start_if_not_started(trx);
@@ -896,7 +896,7 @@ run_again:
if (err == DB_RECORD_NOT_FOUND) {
trx->error_state = DB_SUCCESS;
- trx->op_info = "";
+ trx->op_info = (char *) "";
return((int) err);
}
@@ -907,7 +907,7 @@ run_again:
goto run_again;
}
- trx->op_info = "";
+ trx->op_info = (char *) "";
return(err);
}
@@ -926,7 +926,7 @@ run_again:
row_update_statistics_if_needed(prebuilt);
- trx->op_info = "";
+ trx->op_info = (char *) "";
return((int) err);
}
@@ -1060,7 +1060,7 @@ row_create_table_for_mysql(
return(DB_ERROR);
}
- trx->op_info = "creating table";
+ trx->op_info = (char *) "creating table";
if (0 == ut_strcmp(table->name, "mysql/host")
|| 0 == ut_strcmp(table->name, "mysql/user")
@@ -1098,11 +1098,11 @@ row_create_table_for_mysql(
namelen = ut_strlen(table->name);
- keywordlen = ut_strlen("innodb_monitor");
+ keywordlen = ut_strlen((char *) "innodb_monitor");
if (namelen >= keywordlen
&& 0 == ut_memcmp(table->name + namelen - keywordlen,
- "innodb_monitor", keywordlen)) {
+ (char *) "innodb_monitor", keywordlen)) {
/* Table name ends to characters innodb_monitor:
start monitor prints */
@@ -1115,32 +1115,34 @@ row_create_table_for_mysql(
os_event_set(srv_lock_timeout_thread_event);
}
- keywordlen = ut_strlen("innodb_lock_monitor");
+ keywordlen = ut_strlen((char *) "innodb_lock_monitor");
if (namelen >= keywordlen
&& 0 == ut_memcmp(table->name + namelen - keywordlen,
- "innodb_lock_monitor", keywordlen)) {
+ (char *) "innodb_lock_monitor", keywordlen)) {
srv_print_innodb_monitor = TRUE;
srv_print_innodb_lock_monitor = TRUE;
os_event_set(srv_lock_timeout_thread_event);
}
- keywordlen = ut_strlen("innodb_tablespace_monitor");
+ keywordlen = ut_strlen((char *) "innodb_tablespace_monitor");
if (namelen >= keywordlen
&& 0 == ut_memcmp(table->name + namelen - keywordlen,
- "innodb_tablespace_monitor", keywordlen)) {
+ (char *) "innodb_tablespace_monitor",
+ keywordlen)) {
srv_print_innodb_tablespace_monitor = TRUE;
os_event_set(srv_lock_timeout_thread_event);
}
- keywordlen = ut_strlen("innodb_table_monitor");
+ keywordlen = ut_strlen((char *) "innodb_table_monitor");
if (namelen >= keywordlen
&& 0 == ut_memcmp(table->name + namelen - keywordlen,
- "innodb_table_monitor", keywordlen)) {
+ (char *) "innodb_table_monitor",
+ keywordlen)) {
srv_print_innodb_table_monitor = TRUE;
os_event_set(srv_lock_timeout_thread_event);
@@ -1223,7 +1225,7 @@ row_create_table_for_mysql(
mutex_exit(&(dict_sys->mutex));
que_graph_free((que_t*) que_node_get_parent(thr));
- trx->op_info = "";
+ trx->op_info = (char *) "";
return((int) err);
}
@@ -1249,7 +1251,7 @@ row_create_index_for_mysql(
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
- trx->op_info = "creating index";
+ trx->op_info = (char *) "creating index";
trx_start_if_not_started(trx);
@@ -1301,7 +1303,7 @@ row_create_index_for_mysql(
que_graph_free((que_t*) que_node_get_parent(thr));
- trx->op_info = "";
+ trx->op_info = (char *) "";
return((int) err);
}
@@ -1334,7 +1336,7 @@ row_table_add_foreign_constraints(
ut_a(sql_string);
- trx->op_info = "adding foreign keys";
+ trx->op_info = (char *) "adding foreign keys";
trx_start_if_not_started(trx);
@@ -1592,16 +1594,16 @@ row_drop_table_for_mysql(
return(DB_ERROR);
}
- trx->op_info = "dropping table";
+ trx->op_info = (char *) "dropping table";
trx_start_if_not_started(trx);
namelen = ut_strlen(name);
- keywordlen = ut_strlen("innodb_monitor");
+ keywordlen = ut_strlen((char *) "innodb_monitor");
if (namelen >= keywordlen
&& 0 == ut_memcmp(name + namelen - keywordlen,
- "innodb_monitor", keywordlen)) {
+ (char *) "innodb_monitor", keywordlen)) {
/* Table name ends to characters innodb_monitor:
stop monitor prints */
@@ -1610,30 +1612,33 @@ row_drop_table_for_mysql(
srv_print_innodb_lock_monitor = FALSE;
}
- keywordlen = ut_strlen("innodb_lock_monitor");
+ keywordlen = ut_strlen((char *) "innodb_lock_monitor");
if (namelen >= keywordlen
&& 0 == ut_memcmp(name + namelen - keywordlen,
- "innodb_lock_monitor", keywordlen)) {
+ (char *) "innodb_lock_monitor",
+ keywordlen)) {
srv_print_innodb_monitor = FALSE;
srv_print_innodb_lock_monitor = FALSE;
}
- keywordlen = ut_strlen("innodb_tablespace_monitor");
+ keywordlen = ut_strlen((char *) "innodb_tablespace_monitor");
if (namelen >= keywordlen
&& 0 == ut_memcmp(name + namelen - keywordlen,
- "innodb_tablespace_monitor", keywordlen)) {
+ (char *) "innodb_tablespace_monitor",
+ keywordlen)) {
srv_print_innodb_tablespace_monitor = FALSE;
}
- keywordlen = ut_strlen("innodb_table_monitor");
+ keywordlen = ut_strlen((char *) "innodb_table_monitor");
if (namelen >= keywordlen
&& 0 == ut_memcmp(name + namelen - keywordlen,
- "innodb_table_monitor", keywordlen)) {
+ (char *) "innodb_table_monitor",
+ keywordlen)) {
srv_print_innodb_table_monitor = FALSE;
}
@@ -1643,7 +1648,7 @@ row_drop_table_for_mysql(
tables in Innobase. Deleting a row from SYS_INDEXES table also
frees the file segments of the B-tree associated with the index. */
- str1 =
+ str1 = (char *)
"PROCEDURE DROP_TABLE_PROC () IS\n"
"table_name CHAR;\n"
"sys_foreign_id CHAR;\n"
@@ -1654,7 +1659,7 @@ row_drop_table_for_mysql(
"BEGIN\n"
"table_name := '";
- str2 =
+ str2 = (char *)
"';\n"
"SELECT ID INTO table_id\n"
"FROM SYS_TABLES\n"
@@ -1803,7 +1808,7 @@ funct_exit:
trx_commit_for_mysql(trx);
- trx->op_info = "";
+ trx->op_info = (char *) "";
srv_wake_master_thread();
@@ -1828,13 +1833,13 @@ row_drop_database_for_mysql(
ut_a(name != NULL);
ut_a(name[strlen(name) - 1] == '/');
- trx->op_info = "dropping database";
+ trx->op_info = (char *) "dropping database";
trx_start_if_not_started(trx);
loop:
mutex_enter(&(dict_sys->mutex));
- while (table_name = dict_get_first_table_name_in_db(name)) {
+ while ((table_name = dict_get_first_table_name_in_db(name))) {
ut_a(memcmp(table_name, name, strlen(name)) == 0);
table = dict_table_get_low(table_name);
@@ -1876,7 +1881,7 @@ loop:
trx_commit_for_mysql(trx);
- trx->op_info = "";
+ trx->op_info = (char *) "";
return(err);
}
@@ -1931,20 +1936,20 @@ row_rename_table_for_mysql(
return(DB_ERROR);
}
- trx->op_info = "renaming table";
+ trx->op_info = (char *) "renaming table";
trx_start_if_not_started(trx);
- str1 =
+ str1 = (char *)
"PROCEDURE RENAME_TABLE_PROC () IS\n"
"new_table_name CHAR;\n"
"old_table_name CHAR;\n"
"BEGIN\n"
"new_table_name :='";
- str2 =
+ str2 = (char *)
"';\nold_table_name := '";
- str3 =
+ str3 = (char *)
"';\n"
"UPDATE SYS_TABLES SET NAME = new_table_name\n"
"WHERE NAME = old_table_name;\n"
@@ -2037,7 +2042,7 @@ funct_exit:
trx_commit_for_mysql(trx);
- trx->op_info = "";
+ trx->op_info = (char *) "";
return((int) err);
}
@@ -2182,7 +2187,7 @@ row_check_table_for_mysql(
ulint n_rows_in_table = ULINT_UNDEFINED;
ulint ret = DB_SUCCESS;
- prebuilt->trx->op_info = "checking table";
+ prebuilt->trx->op_info = (char *) "checking table";
index = dict_table_get_first_index(table);
@@ -2215,7 +2220,7 @@ row_check_table_for_mysql(
index = dict_table_get_next_index(index);
}
- prebuilt->trx->op_info = "";
+ prebuilt->trx->op_info = (char *) "";
return(ret);
}
diff --git a/innobase/row/row0purge.c b/innobase/row/row0purge.c
index 390f1b59a4d..1dca017c349 100644
--- a/innobase/row/row0purge.c
+++ b/innobase/row/row0purge.c
@@ -204,7 +204,7 @@ row_purge_remove_sec_if_poss_low(
btr_pcur_t pcur;
btr_cur_t* btr_cur;
ibool success;
- ibool old_has;
+ ibool old_has = 0; /* remove warning */
ibool found;
ulint err;
mtr_t mtr;
diff --git a/innobase/row/row0sel.c b/innobase/row/row0sel.c
index 663a544faac..abae7f373bf 100644
--- a/innobase/row/row0sel.c
+++ b/innobase/row/row0sel.c
@@ -64,7 +64,8 @@ row_sel_sec_rec_is_for_clust_rec(
rec_t* sec_rec, /* in: secondary index record */
dict_index_t* sec_index, /* in: secondary index */
rec_t* clust_rec, /* in: clustered index record */
- dict_index_t* clust_index) /* in: clustered index */
+ dict_index_t* clust_index __attribute__((unused)))
+ /* in: clustered index */
{
dict_col_t* col;
byte* sec_field;
@@ -2509,7 +2510,7 @@ row_search_for_mysql(
printf("N tables locked %lu\n", trx->mysql_n_tables_locked);
*/
if (direction == 0) {
- trx->op_info = "starting index read";
+ trx->op_info = (char *) "starting index read";
prebuilt->n_rows_fetched = 0;
prebuilt->n_fetch_cached = 0;
@@ -2520,7 +2521,7 @@ row_search_for_mysql(
row_prebuild_sel_graph(prebuilt);
}
} else {
- trx->op_info = "fetching rows";
+ trx->op_info = (char *) "fetching rows";
if (prebuilt->n_rows_fetched == 0) {
prebuilt->fetch_direction = direction;
@@ -2545,7 +2546,7 @@ row_search_for_mysql(
prebuilt->n_rows_fetched++;
srv_n_rows_read++;
- trx->op_info = "";
+ trx->op_info = (char *) "";
return(DB_SUCCESS);
}
@@ -2557,7 +2558,7 @@ row_search_for_mysql(
cache, but the cache was not full at the time of the
popping: no more rows can exist in the result set */
- trx->op_info = "";
+ trx->op_info = (char *) "";
return(DB_RECORD_NOT_FOUND);
}
@@ -2589,7 +2590,7 @@ row_search_for_mysql(
/* printf("%s record not found 1\n", index->name); */
- trx->op_info = "";
+ trx->op_info = (char *) "";
return(DB_RECORD_NOT_FOUND);
}
@@ -2649,7 +2650,7 @@ row_search_for_mysql(
trx->has_search_latch = FALSE;
}
- trx->op_info = "";
+ trx->op_info = (char *) "";
return(DB_SUCCESS);
} else if (shortcut == SEL_EXHAUSTED) {
@@ -2668,7 +2669,7 @@ row_search_for_mysql(
trx->has_search_latch = FALSE;
}
- trx->op_info = "";
+ trx->op_info = (char *) "";
return(DB_RECORD_NOT_FOUND);
}
@@ -3040,7 +3041,7 @@ lock_wait_or_error:
/* printf("Using index %s cnt %lu ret value %lu err\n", index->name,
cnt, err); */
- trx->op_info = "";
+ trx->op_info = (char *) "";
return(err);
@@ -3061,7 +3062,7 @@ normal_return:
srv_n_rows_read++;
}
- trx->op_info = "";
+ trx->op_info = (char *) "";
return(ret);
}
diff --git a/innobase/row/row0uins.c b/innobase/row/row0uins.c
index 27d1fbcb9ba..9990f893432 100644
--- a/innobase/row/row0uins.c
+++ b/innobase/row/row0uins.c
@@ -234,7 +234,7 @@ void
row_undo_ins_parse_undo_rec(
/*========================*/
undo_node_t* node, /* in: row undo node */
- que_thr_t* thr) /* in: query thread */
+ que_thr_t* thr __attribute__((unused))) /* in: query thread */
{
dict_index_t* clust_index;
byte* ptr;
diff --git a/innobase/row/row0umod.c b/innobase/row/row0umod.c
index 9e8ba87fc2f..631f238a72d 100644
--- a/innobase/row/row0umod.c
+++ b/innobase/row/row0umod.c
@@ -139,7 +139,7 @@ row_undo_mod_remove_clust_low(
/* out: DB_SUCCESS, DB_FAIL, or error code:
we may run out of file space */
undo_node_t* node, /* in: row undo node */
- que_thr_t* thr, /* in: query thread */
+ que_thr_t* thr __attribute__((unused)), /* in: query thread */
mtr_t* mtr, /* in: mtr */
ulint mode) /* in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE */
{
diff --git a/innobase/row/row0upd.c b/innobase/row/row0upd.c
index 435cfa3485e..31d58dd04a2 100644
--- a/innobase/row/row0upd.c
+++ b/innobase/row/row0upd.c
@@ -388,7 +388,7 @@ row_upd_write_sys_vals_to_log(
dulint roll_ptr,/* in: roll ptr of the undo log record */
byte* log_ptr,/* pointer to a buffer of size > 20 opened
in mlog */
- mtr_t* mtr) /* in: mtr */
+ mtr_t* mtr __attribute__((unused))) /* in: mtr */
{
ut_ad(index->type & DICT_CLUSTERED);
ut_ad(mtr);
diff --git a/innobase/srv/srv0srv.c b/innobase/srv/srv0srv.c
index 553c012bf85..c3d3ed53058 100644
--- a/innobase/srv/srv0srv.c
+++ b/innobase/srv/srv0srv.c
@@ -61,7 +61,7 @@ ulint srv_activity_count = 0;
ibool srv_lock_timeout_and_monitor_active = FALSE;
ibool srv_error_monitor_active = FALSE;
-char* srv_main_thread_op_info = "";
+char* srv_main_thread_op_info = (char *) "";
/* Server parameters which are read from the initfile */
@@ -235,6 +235,12 @@ ulint srv_n_rows_read_old = 0;
ibool srv_print_innodb_monitor = FALSE;
ibool srv_print_innodb_lock_monitor = FALSE;
ibool srv_print_innodb_tablespace_monitor = FALSE;
+
+/*
+ Set the following to 0 if you want InnoDB to write messages on
+ stderr on startup/shutdown
+*/
+ibool srv_print_verbose_log = TRUE;
ibool srv_print_innodb_table_monitor = FALSE;
/* The parameters below are obsolete: */
@@ -975,6 +981,7 @@ srv_communication_init(
/*************************************************************************
Implements the recovery utility. */
+#ifdef NOT_USED
static
ulint
srv_recovery_thread(
@@ -1012,7 +1019,7 @@ srv_recovery_thread(
return(0);
}
-
+#endif
/*************************************************************************
Implements the purge utility. */
@@ -1064,6 +1071,7 @@ srv_create_utility_threads(void)
/*************************************************************************
Implements the communication threads. */
+#ifdef NOT_USED
static
ulint
srv_com_thread(
@@ -1111,7 +1119,7 @@ srv_com_thread(
return(0);
}
-
+#endif
/*************************************************************************
Creates the communication threads. */
@@ -1133,6 +1141,7 @@ srv_create_com_threads(void)
/*************************************************************************
Implements the worker threads. */
+#ifdef NOT_USED
static
ulint
srv_worker_thread(
@@ -1175,7 +1184,7 @@ srv_worker_thread(
return(0);
}
-
+#endif
/*************************************************************************
Creates the worker threads. */
@@ -2442,7 +2451,7 @@ srv_master_thread(
os_event_set(srv_sys->operational);
loop:
- srv_main_thread_op_info = "reserving kernel mutex";
+ srv_main_thread_op_info = (char *) "reserving kernel mutex";
n_ios_very_old = log_sys->n_log_ios + buf_pool->n_pages_read
+ buf_pool->n_pages_written;
@@ -2458,7 +2467,7 @@ loop:
for (i = 0; i < 10; i++) {
n_ios_old = log_sys->n_log_ios + buf_pool->n_pages_read
+ buf_pool->n_pages_written;
- srv_main_thread_op_info = "sleeping";
+ srv_main_thread_op_info = (char *) "sleeping";
os_thread_sleep(1000000);
/* ALTER TABLE in MySQL requires on Unix that the table handler
@@ -2480,7 +2489,7 @@ loop:
is issued or the we have specified in my.cnf no flush
at transaction commit */
- srv_main_thread_op_info = "flushing log";
+ srv_main_thread_op_info = (char *) "flushing log";
log_flush_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP);
/* If there were less than 10 i/os during the
@@ -2493,10 +2502,11 @@ loop:
n_ios = log_sys->n_log_ios + buf_pool->n_pages_read
+ buf_pool->n_pages_written;
if (n_pend_ios < 3 && (n_ios - n_ios_old < 10)) {
- srv_main_thread_op_info = "doing insert buffer merge";
+ srv_main_thread_op_info =
+ (char *) "doing insert buffer merge";
ibuf_contract_for_n_pages(TRUE, 5);
- srv_main_thread_op_info = "flushing log";
+ srv_main_thread_op_info = (char *) "flushing log";
log_flush_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP);
}
@@ -2533,20 +2543,20 @@ loop:
+ buf_pool->n_pages_written;
if (n_pend_ios < 3 && (n_ios - n_ios_very_old < 200)) {
- srv_main_thread_op_info = "flushing buffer pool pages";
+ srv_main_thread_op_info =(char *) "flushing buffer pool pages";
buf_flush_batch(BUF_FLUSH_LIST, 50, ut_dulint_max);
- srv_main_thread_op_info = "flushing log";
+ srv_main_thread_op_info = (char *) "flushing log";
log_flush_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP);
}
/* We run a batch of insert buffer merge every 10 seconds,
even if the server were active */
- srv_main_thread_op_info = "doing insert buffer merge";
+ srv_main_thread_op_info = (char *) "doing insert buffer merge";
ibuf_contract_for_n_pages(TRUE, 5);
- srv_main_thread_op_info = "flushing log";
+ srv_main_thread_op_info = (char *) "flushing log";
log_flush_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP);
/* We run a full purge every 10 seconds, even if the server
@@ -2563,13 +2573,13 @@ loop:
goto background_loop;
}
- srv_main_thread_op_info = "purging";
+ srv_main_thread_op_info = (char *) "purging";
n_pages_purged = trx_purge();
current_time = time(NULL);
if (difftime(current_time, last_flush_time) > 1) {
- srv_main_thread_op_info = "flushing log";
+ srv_main_thread_op_info = (char *) "flushing log";
log_flush_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP);
last_flush_time = current_time;
@@ -2598,7 +2608,7 @@ background_loop:
log_checkpoint(TRUE, FALSE);
- srv_main_thread_op_info = "reserving kernel mutex";
+ srv_main_thread_op_info = (char *) "reserving kernel mutex";
mutex_enter(&kernel_mutex);
if (srv_activity_count != old_activity_count) {
@@ -2611,11 +2621,11 @@ background_loop:
/* The server has been quiet for a while: start running background
operations */
- srv_main_thread_op_info = "purging";
+ srv_main_thread_op_info = (char *) "purging";
n_pages_purged = trx_purge();
- srv_main_thread_op_info = "reserving kernel mutex";
+ srv_main_thread_op_info = (char *) "reserving kernel mutex";
mutex_enter(&kernel_mutex);
if (srv_activity_count != old_activity_count) {
@@ -2624,10 +2634,10 @@ background_loop:
}
mutex_exit(&kernel_mutex);
- srv_main_thread_op_info = "doing insert buffer merge";
+ srv_main_thread_op_info = (char *) "doing insert buffer merge";
n_bytes_merged = ibuf_contract_for_n_pages(TRUE, 20);
- srv_main_thread_op_info = "reserving kernel mutex";
+ srv_main_thread_op_info = (char *) "reserving kernel mutex";
mutex_enter(&kernel_mutex);
if (srv_activity_count != old_activity_count) {
@@ -2636,10 +2646,10 @@ background_loop:
}
mutex_exit(&kernel_mutex);
- srv_main_thread_op_info = "flushing buffer pool pages";
+ srv_main_thread_op_info = (char *) "flushing buffer pool pages";
n_pages_flushed = buf_flush_batch(BUF_FLUSH_LIST, 100, ut_dulint_max);
- srv_main_thread_op_info = "reserving kernel mutex";
+ srv_main_thread_op_info = (char *) "reserving kernel mutex";
mutex_enter(&kernel_mutex);
if (srv_activity_count != old_activity_count) {
@@ -2648,14 +2658,15 @@ background_loop:
}
mutex_exit(&kernel_mutex);
- srv_main_thread_op_info = "waiting for buffer pool flush to end";
+ srv_main_thread_op_info =
+ (char *) "waiting for buffer pool flush to end";
buf_flush_wait_batch_end(BUF_FLUSH_LIST);
- srv_main_thread_op_info = "making checkpoint";
+ srv_main_thread_op_info = (char *) "making checkpoint";
log_checkpoint(TRUE, FALSE);
- srv_main_thread_op_info = "reserving kernel mutex";
+ srv_main_thread_op_info = (char *) "reserving kernel mutex";
mutex_enter(&kernel_mutex);
if (srv_activity_count != old_activity_count) {
@@ -2664,7 +2675,8 @@ background_loop:
}
mutex_exit(&kernel_mutex);
- srv_main_thread_op_info = "archiving log (if log archive is on)";
+ srv_main_thread_op_info =
+ (char *) "archiving log (if log archive is on)";
log_archive_do(FALSE, &n_bytes_archived);
@@ -2690,7 +2702,7 @@ background_loop:
master thread to wait for more server activity */
suspend_thread:
- srv_main_thread_op_info = "suspending";
+ srv_main_thread_op_info = (char *) "suspending";
mutex_enter(&kernel_mutex);
@@ -2704,7 +2716,7 @@ suspend_thread:
mutex_exit(&kernel_mutex);
- srv_main_thread_op_info = "waiting for server activity";
+ srv_main_thread_op_info = (char *) "waiting for server activity";
os_event_wait(event);
diff --git a/innobase/srv/srv0start.c b/innobase/srv/srv0start.c
index f9a13944bb5..bbb48331811 100644
--- a/innobase/srv/srv0start.c
+++ b/innobase/srv/srv0start.c
@@ -131,7 +131,8 @@ static
void
srv_normalize_path_for_win(
/*=======================*/
- char* str) /* in/out: null-terminated character string */
+ char* str __attribute__((unused)))
+ /* in/out: null-terminated character string */
{
#ifdef __WIN__
ulint i;
@@ -316,7 +317,8 @@ open_or_create_log_file(
if (k == 0 && i == 0) {
arch_space_id = 2 * k + 1 + SRV_LOG_SPACE_FIRST_ID;
- fil_space_create("arch_log_space", arch_space_id, FIL_LOG);
+ fil_space_create((char *) "arch_log_space", arch_space_id,
+ FIL_LOG);
} else {
arch_space_id = ULINT_UNDEFINED;
}
@@ -516,6 +518,7 @@ open_or_create_data_files(
/*********************************************************************
This thread is used to measure contention of latches. */
+#ifdef NOT_USED
static
ulint
test_measure_cont(
@@ -585,7 +588,7 @@ test_measure_cont(
return(0);
}
-
+#endif
/********************************************************************
Starts InnoDB and creates a new database if database files
are not found and the user wants. Server parameters are
@@ -617,18 +620,21 @@ innobase_start_or_create_for_mysql(void)
srv_is_being_started = TRUE;
srv_startup_is_before_trx_rollback_phase = TRUE;
- if (0 == ut_strcmp(srv_unix_file_flush_method_str, "fdatasync")) {
- srv_unix_file_flush_method = SRV_UNIX_FDATASYNC;
+ if (0 == ut_strcmp(srv_unix_file_flush_method_str,
+ (char *) "fdatasync")) {
+ srv_unix_file_flush_method = SRV_UNIX_FDATASYNC;
- } else if (0 == ut_strcmp(srv_unix_file_flush_method_str, "O_DSYNC")) {
- srv_unix_file_flush_method = SRV_UNIX_O_DSYNC;
+ } else if (0 == ut_strcmp(srv_unix_file_flush_method_str,
+ (char *) "O_DSYNC")) {
+ srv_unix_file_flush_method = SRV_UNIX_O_DSYNC;
} else if (0 == ut_strcmp(srv_unix_file_flush_method_str,
- "littlesync")) {
- srv_unix_file_flush_method = SRV_UNIX_LITTLESYNC;
+ (char *) "littlesync")) {
+ srv_unix_file_flush_method = SRV_UNIX_LITTLESYNC;
- } else if (0 == ut_strcmp(srv_unix_file_flush_method_str, "nosync")) {
- srv_unix_file_flush_method = SRV_UNIX_NOSYNC;
+ } else if (0 == ut_strcmp(srv_unix_file_flush_method_str,
+ (char *) "nosync")) {
+ srv_unix_file_flush_method = SRV_UNIX_NOSYNC;
} else {
fprintf(stderr,
"InnoDB: Unrecognized value %s for innodb_flush_method\n",
@@ -977,9 +983,11 @@ innobase_start_or_create_for_mysql(void)
SRV_MAX_N_IO_THREADS);
/* buf_debug_prints = TRUE; */
- ut_print_timestamp(stderr);
- fprintf(stderr, " InnoDB: Started\n");
-
+ if (srv_print_verbose_log)
+ {
+ ut_print_timestamp(stderr);
+ fprintf(stderr, " InnoDB: Started\n");
+ }
return((int) DB_SUCCESS);
}
diff --git a/innobase/sync/sync0arr.c b/innobase/sync/sync0arr.c
index 7788b104120..4487fa72995 100644
--- a/innobase/sync/sync0arr.c
+++ b/innobase/sync/sync0arr.c
@@ -446,7 +446,7 @@ sync_array_cell_print(
{
mutex_t* mutex;
rw_lock_t* rwlock;
- char* str = NULL;
+ char* str __attribute__((unused)) = NULL;
ulint type;
type = cell->request_type;
diff --git a/innobase/sync/sync0rw.c b/innobase/sync/sync0rw.c
index 1ef2920618f..86ffed7ca95 100644
--- a/innobase/sync/sync0rw.c
+++ b/innobase/sync/sync0rw.c
@@ -115,8 +115,8 @@ rw_lock_create_func(
lock->cfile_name = cfile_name;
lock->cline = cline;
- lock->last_s_file_name = "not yet reserved";
- lock->last_x_file_name = "not yet reserved";
+ lock->last_s_file_name = (char *) "not yet reserved";
+ lock->last_x_file_name = (char *) "not yet reserved";
lock->last_s_line = 0;
lock->last_x_line = 0;
@@ -789,7 +789,7 @@ Prints debug info of an rw-lock. */
void
rw_lock_print(
/*==========*/
- rw_lock_t* lock) /* in: rw-lock */
+ rw_lock_t* lock __attribute__((unused))) /* in: rw-lock */
{
#ifndef UNIV_SYNC_DEBUG
printf(
diff --git a/innobase/sync/sync0sync.c b/innobase/sync/sync0sync.c
index 8b2a39e15eb..3f40aa166ee 100644
--- a/innobase/sync/sync0sync.c
+++ b/innobase/sync/sync0sync.c
@@ -229,7 +229,7 @@ mutex_create_func(
mutex_set_waiters(mutex, 0);
mutex->magic_n = MUTEX_MAGIC_N;
mutex->line = 0;
- mutex->file_name = "not yet reserved";
+ mutex->file_name = (char *) "not yet reserved";
mutex->thread_id = ULINT_UNDEFINED;
mutex->level = SYNC_LEVEL_NONE;
mutex->cfile_name = cfile_name;
diff --git a/innobase/trx/trx0purge.c b/innobase/trx/trx0purge.c
index b73629c9fa4..97362d00b4b 100644
--- a/innobase/trx/trx0purge.c
+++ b/innobase/trx/trx0purge.c
@@ -674,9 +674,9 @@ trx_purge_choose_next_log(void)
trx_rseg_t* rseg;
trx_rseg_t* min_rseg;
dulint min_trx_no;
- ulint space;
- ulint page_no;
- ulint offset;
+ ulint space = 0; /* remove warning (??? bug ???) */
+ ulint page_no = 0; /* remove warning (??? bug ???) */
+ ulint offset = 0; /* remove warning (??? bug ???) */
mtr_t mtr;
ut_ad(mutex_own(&(purge_sys->mutex)));
diff --git a/innobase/trx/trx0rec.c b/innobase/trx/trx0rec.c
index abce470bd1c..05e179e06a5 100644
--- a/innobase/trx/trx0rec.c
+++ b/innobase/trx/trx0rec.c
@@ -989,7 +989,7 @@ trx_undo_parse_erase_page_end(
/*==========================*/
/* out: end of log record or NULL */
byte* ptr, /* in: buffer */
- byte* end_ptr,/* in: buffer end */
+ byte* end_ptr __attribute__((unused)), /* in: buffer end */
page_t* page, /* in: page or NULL */
mtr_t* mtr) /* in: mtr or NULL */
{
@@ -1263,7 +1263,8 @@ trx_undo_prev_version_build(
DB_ERROR if corrupted record */
rec_t* index_rec,/* in: clustered index record in the
index tree */
- mtr_t* index_mtr,/* in: mtr which contains the latch to
+ mtr_t* index_mtr __attribute__((unused)),
+ /* in: mtr which contains the latch to
index_rec page and purge_view */
rec_t* rec, /* in: version of a clustered index record */
dict_index_t* index, /* in: clustered index */
diff --git a/innobase/trx/trx0roll.c b/innobase/trx/trx0roll.c
index 47fffea5e40..97cc2dbff1a 100644
--- a/innobase/trx/trx0roll.c
+++ b/innobase/trx/trx0roll.c
@@ -101,7 +101,7 @@ trx_rollback_for_mysql(
return(DB_SUCCESS);
}
- trx->op_info = "rollback";
+ trx->op_info = (char *) "rollback";
/* Tell Innobase server that there might be work for
utility threads: */
@@ -117,7 +117,7 @@ trx_rollback_for_mysql(
srv_active_wake_master_thread();
- trx->op_info = "";
+ trx->op_info = (char *) "";
return(err);
}
@@ -138,7 +138,7 @@ trx_rollback_last_sql_stat_for_mysql(
return(DB_SUCCESS);
}
- trx->op_info = "rollback of SQL statement";
+ trx->op_info = (char *) "rollback of SQL statement";
/* Tell Innobase server that there might be work for
utility threads: */
@@ -154,7 +154,7 @@ trx_rollback_last_sql_stat_for_mysql(
srv_active_wake_master_thread();
- trx->op_info = "";
+ trx->op_info = (char *) "";
return(err);
}
@@ -180,7 +180,7 @@ trx_rollback_all_without_sess(void)
if (!trx_dummy_sess) {
trx_dummy_sess = sess_open(NULL, (byte*)"Dummy sess",
- ut_strlen("Dummy sess"));
+ ut_strlen((char *) "Dummy sess"));
}
mutex_exit(&kernel_mutex);
diff --git a/innobase/trx/trx0trx.c b/innobase/trx/trx0trx.c
index 6cbf97104b3..607c80edd09 100644
--- a/innobase/trx/trx0trx.c
+++ b/innobase/trx/trx0trx.c
@@ -66,7 +66,7 @@ trx_create(
trx->magic_n = TRX_MAGIC_N;
- trx->op_info = "";
+ trx->op_info = (char *) "";
trx->type = TRX_USER;
trx->conc_state = TRX_NOT_STARTED;
@@ -143,7 +143,7 @@ trx_allocate_for_mysql(void)
if (!trx_dummy_sess) {
trx_dummy_sess = sess_open(NULL, (byte*)"Dummy sess",
- ut_strlen("Dummy sess"));
+ ut_strlen((char *) "Dummy sess"));
}
trx = trx_create(trx_dummy_sess);
@@ -1052,7 +1052,7 @@ trx_sig_send(
ut_a(0);
sess_raise_error_low(trx, 0, 0, NULL, NULL, NULL, NULL,
- "Signal from another session, or a break execution signal");
+ (char *) "Signal from another session, or a break execution signal");
}
/* If there were no other signals ahead in the queue, try to start
@@ -1353,7 +1353,7 @@ trx_commit_for_mysql(
ut_a(trx);
- trx->op_info = "committing";
+ trx->op_info = (char *) "committing";
trx_start_if_not_started(trx);
@@ -1363,7 +1363,7 @@ trx_commit_for_mysql(
mutex_exit(&kernel_mutex);
- trx->op_info = "";
+ trx->op_info = (char *) "";
return(0);
}
diff --git a/innobase/trx/trx0undo.c b/innobase/trx/trx0undo.c
index b5341871228..aae31f3726b 100644
--- a/innobase/trx/trx0undo.c
+++ b/innobase/trx/trx0undo.c
@@ -374,7 +374,7 @@ trx_undo_seg_create(
/*================*/
/* out: segment header page x-latched, NULL
if no space left */
- trx_rseg_t* rseg, /* in: rollback segment */
+ trx_rseg_t* rseg __attribute__((unused)),/* in: rollback segment */
trx_rsegf_t* rseg_hdr,/* in: rollback segment header, page
x-latched */
ulint type, /* in: type of the segment: TRX_UNDO_INSERT or
@@ -657,7 +657,7 @@ trx_undo_parse_discard_latest(
/*==========================*/
/* out: end of log record or NULL */
byte* ptr, /* in: buffer */
- byte* end_ptr,/* in: buffer end */
+ byte* end_ptr __attribute__((unused)), /* in: buffer end */
page_t* page, /* in: page or NULL */
mtr_t* mtr) /* in: mtr or NULL */
{
@@ -844,7 +844,7 @@ static
void
trx_undo_free_page_in_rollback(
/*===========================*/
- trx_t* trx, /* in: transaction */
+ trx_t* trx __attribute__((unused)), /* in: transaction */
trx_undo_t* undo, /* in: undo log memory copy */
ulint page_no,/* in: page number to free: must not be the
header page */
@@ -1567,7 +1567,7 @@ trx_undo_set_state_at_finish(
/*=========================*/
/* out: undo log segment header page,
x-latched */
- trx_t* trx, /* in: transaction */
+ trx_t* trx __attribute__((unused)), /* in: transaction */
trx_undo_t* undo, /* in: undo log memory copy */
mtr_t* mtr) /* in: mtr */
{
diff --git a/isam/_cache.c b/isam/_cache.c
index 53619126660..bca9a699a85 100644
--- a/isam/_cache.c
+++ b/isam/_cache.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -46,11 +46,11 @@ int _nisam_read_cache(IO_CACHE *info, byte *buff, ulong pos, uint length,
buff+=read_length;
}
if ((offset=pos - (ulong) info->pos_in_file) <
- (ulong) (info->rc_end - info->rc_request_pos))
+ (ulong) (info->read_end - info->request_pos))
{
- in_buff_pos=info->rc_request_pos+(uint) offset;
- in_buff_length= min(length,(uint) (info->rc_end-in_buff_pos));
- memcpy(buff,info->rc_request_pos+(uint) offset,(size_t) in_buff_length);
+ in_buff_pos=info->request_pos+(uint) offset;
+ in_buff_length= min(length,(uint) (info->read_end-in_buff_pos));
+ memcpy(buff,info->request_pos+(uint) offset,(size_t) in_buff_length);
if (!(length-=in_buff_length))
return 0;
pos+=in_buff_length;
@@ -61,14 +61,14 @@ int _nisam_read_cache(IO_CACHE *info, byte *buff, ulong pos, uint length,
if (flag & READING_NEXT)
{
if (pos != ((info)->pos_in_file +
- (uint) ((info)->rc_end - (info)->rc_request_pos)))
+ (uint) ((info)->read_end - (info)->request_pos)))
{
info->pos_in_file=pos; /* Force start here */
- info->rc_pos=info->rc_end=info->rc_request_pos; /* Everything used */
+ info->read_pos=info->read_end=info->request_pos; /* Everything used */
info->seek_not_done=1;
}
else
- info->rc_pos=info->rc_end; /* All block used */
+ info->read_pos=info->read_end; /* All block used */
if (!(*info->read_function)(info,buff,length))
return 0;
if (!(flag & READING_HEADER) || info->error == -1 ||
diff --git a/isam/_dbug.c b/isam/_dbug.c
index 18e671793ed..0a52dbbc916 100644
--- a/isam/_dbug.c
+++ b/isam/_dbug.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
diff --git a/isam/_dynrec.c b/isam/_dynrec.c
index 2a908f5b42c..d17d34e6778 100644
--- a/isam/_dynrec.c
+++ b/isam/_dynrec.c
@@ -432,7 +432,7 @@ uint _nisam_rec_pack(N_INFO *info, register byte *to, register const byte *from)
blob++;
from+=sizeof(char*); /* Skipp blob-pointer */
}
- else if (type == FIELD_SKIPP_ZERO)
+ else if (type == FIELD_SKIP_ZERO)
{
if (memcmp((byte*) from,zero_string,length) == 0)
flag|=bit;
@@ -441,11 +441,11 @@ uint _nisam_rec_pack(N_INFO *info, register byte *to, register const byte *from)
memcpy((byte*) to,from,(size_t) length); to+=length;
}
}
- else if (type == FIELD_SKIPP_ENDSPACE ||
- type == FIELD_SKIPP_PRESPACE)
+ else if (type == FIELD_SKIP_ENDSPACE ||
+ type == FIELD_SKIP_PRESPACE)
{
pos= (byte*) from; end= (byte*) from + length;
- if (type == FIELD_SKIPP_ENDSPACE)
+ if (type == FIELD_SKIP_ENDSPACE)
{ /* Pack trailing spaces */
while (end > from && *(end-1) == ' ')
end--;
@@ -532,7 +532,7 @@ my_bool _nisam_rec_check(N_INFO *info,const char *from)
to+=length+ blob_length;
from+=sizeof(char*);
}
- else if (type == FIELD_SKIPP_ZERO)
+ else if (type == FIELD_SKIP_ZERO)
{
if (memcmp((byte*) from,zero_string,length) == 0)
{
@@ -542,11 +542,11 @@ my_bool _nisam_rec_check(N_INFO *info,const char *from)
else
to+=length;
}
- else if (type == FIELD_SKIPP_ENDSPACE ||
- type == FIELD_SKIPP_PRESPACE)
+ else if (type == FIELD_SKIP_ENDSPACE ||
+ type == FIELD_SKIP_PRESPACE)
{
pos= (byte*) from; end= (byte*) from + length;
- if (type == FIELD_SKIPP_ENDSPACE)
+ if (type == FIELD_SKIP_ENDSPACE)
{ /* Pack trailing spaces */
while (end > from && *(end-1) == ' ')
end--;
@@ -641,10 +641,10 @@ uint _nisam_rec_unpack(register N_INFO *info, register byte *to, byte *from,
bzero((byte*) to,rec_length+sizeof(char*));
to+=sizeof(char*);
}
- else if (type == FIELD_SKIPP_ZERO)
+ else if (type == FIELD_SKIP_ZERO)
bzero((byte*) to,rec_length);
- else if (type == FIELD_SKIPP_ENDSPACE ||
- type == FIELD_SKIPP_PRESPACE)
+ else if (type == FIELD_SKIP_ENDSPACE ||
+ type == FIELD_SKIP_PRESPACE)
{
if (rec->base.length > 255 && *from & 128)
{
@@ -662,7 +662,7 @@ uint _nisam_rec_unpack(register N_INFO *info, register byte *to, byte *from,
if (length >= rec_length ||
min_pack_length + length > (uint) (from_end - from))
goto err;
- if (type == FIELD_SKIPP_ENDSPACE)
+ if (type == FIELD_SKIP_ENDSPACE)
{
memcpy(to,(byte*) from,(size_t) length);
bfill((byte*) to+length,rec_length-length,' ');
@@ -690,7 +690,7 @@ uint _nisam_rec_unpack(register N_INFO *info, register byte *to, byte *from,
}
else
{
- if (type == FIELD_SKIPP_ENDSPACE || type == FIELD_SKIPP_PRESPACE)
+ if (type == FIELD_SKIP_ENDSPACE || type == FIELD_SKIP_PRESPACE)
min_pack_length--;
if (min_pack_length + rec_length > (uint) (from_end - from))
goto err;
diff --git a/isam/_key.c b/isam/_key.c
index 62f080af172..c0d667cb32d 100644
--- a/isam/_key.c
+++ b/isam/_key.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
diff --git a/isam/_locking.c b/isam/_locking.c
index ca38c611812..cccedbd16c8 100644
--- a/isam/_locking.c
+++ b/isam/_locking.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
diff --git a/isam/_packrec.c b/isam/_packrec.c
index 5c387f011ad..74a45852e63 100644
--- a/isam/_packrec.c
+++ b/isam/_packrec.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -456,7 +456,7 @@ int _nisam_pack_rec_unpack(register N_INFO *info, register byte *to,
static void (*get_unpack_function(N_RECINFO *rec))(N_RECINFO *, BIT_BUFF *, uchar *, uchar *)
{
switch (rec->base_type) {
- case FIELD_SKIPP_ZERO:
+ case FIELD_SKIP_ZERO:
if (rec->pack_type & PACK_TYPE_ZERO_FILL)
return &uf_zerofill_skipp_zero;
return &uf_skipp_zero;
@@ -466,7 +466,7 @@ static void (*get_unpack_function(N_RECINFO *rec))(N_RECINFO *, BIT_BUFF *, ucha
if (rec->pack_type & PACK_TYPE_ZERO_FILL)
return &uf_zerofill_normal;
return &decode_bytes;
- case FIELD_SKIPP_ENDSPACE:
+ case FIELD_SKIP_ENDSPACE:
if (rec->pack_type & PACK_TYPE_SPACE_FIELDS)
{
if (rec->pack_type & PACK_TYPE_SELECTED)
@@ -476,7 +476,7 @@ static void (*get_unpack_function(N_RECINFO *rec))(N_RECINFO *, BIT_BUFF *, ucha
if (rec->pack_type & PACK_TYPE_SELECTED)
return &uf_endspace_selected;
return &uf_endspace;
- case FIELD_SKIPP_PRESPACE:
+ case FIELD_SKIP_PRESPACE:
if (rec->pack_type & PACK_TYPE_SPACE_FIELDS)
{
if (rec->pack_type & PACK_TYPE_SELECTED)
diff --git a/isam/_page.c b/isam/_page.c
index 6f6d632e85d..65733d66b77 100644
--- a/isam/_page.c
+++ b/isam/_page.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
diff --git a/isam/_search.c b/isam/_search.c
index 93a08ea2b0d..57787d61818 100644
--- a/isam/_search.c
+++ b/isam/_search.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
diff --git a/isam/_statrec.c b/isam/_statrec.c
index d93f4fe27f5..9dbc948440f 100644
--- a/isam/_statrec.c
+++ b/isam/_statrec.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -187,7 +187,7 @@ int _nisam_read_rnd_static_record(N_INFO *info, byte *buf,
(skipp_deleted_blocks || !filepos))
{
cache_read=1; /* Read record using cache */
- cache_length=(uint) (info->rec_cache.rc_end - info->rec_cache.rc_pos);
+ cache_length=(uint) (info->rec_cache.read_end - info->rec_cache.read_pos);
}
else
info->rec_cache.seek_not_done=1; /* Filepos is changed */
diff --git a/isam/changed.c b/isam/changed.c
index 4f87a45aa2d..b8132538b86 100644
--- a/isam/changed.c
+++ b/isam/changed.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
diff --git a/isam/close.c b/isam/close.c
index 6741e7b23f0..f1465990100 100644
--- a/isam/close.c
+++ b/isam/close.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
diff --git a/isam/create.c b/isam/create.c
index fcf54ddc731..1fc2f3b97be 100644
--- a/isam/create.c
+++ b/isam/create.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -96,8 +96,8 @@ int nisam_create(const char *name,uint keys,N_KEYDEF *keyinfo,
pack_reclength+=sizeof(char*)+(1 << (rec->base.length*8));
}
}
- else if (type == FIELD_SKIPP_PRESPACE ||
- type == FIELD_SKIPP_ENDSPACE)
+ else if (type == FIELD_SKIP_PRESPACE ||
+ type == FIELD_SKIP_ENDSPACE)
{
if (pack_reclength != NI_POS_ERROR)
pack_reclength+= rec->base.length > 255 ? 2 : 1;
@@ -105,7 +105,7 @@ int nisam_create(const char *name,uint keys,N_KEYDEF *keyinfo,
}
else if (type == FIELD_ZERO)
packed--;
- else if (type != FIELD_SKIPP_ZERO)
+ else if (type != FIELD_SKIP_ZERO)
{
min_pack_length+=rec->base.length;
packed--; /* Not a pack record type */
@@ -119,7 +119,7 @@ int nisam_create(const char *name,uint keys,N_KEYDEF *keyinfo,
while (rec != recinfo)
{
rec--;
- if (rec->base.type == (int) FIELD_SKIPP_ZERO && rec->base.length == 1)
+ if (rec->base.type == (int) FIELD_SKIP_ZERO && rec->base.length == 1)
{
rec->base.type=(int) FIELD_NORMAL;
packed--;
diff --git a/isam/delete.c b/isam/delete.c
index e50ad72c767..5aa542561c1 100644
--- a/isam/delete.c
+++ b/isam/delete.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -613,5 +613,3 @@ static uint remove_key(N_KEYDEF *keyinfo, uint nod_flag,
(uint) (page_end-start-s_length));
DBUG_RETURN((uint) s_length);
} /* remove_key */
-
-
diff --git a/isam/extra.c b/isam/extra.c
index 1d333fa372f..570c396955f 100644
--- a/isam/extra.c
+++ b/isam/extra.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -204,6 +204,7 @@ int nisam_extra(N_INFO *info, enum ha_extra_function function)
info->s->changed=1; /* Update on close */
break;
case HA_EXTRA_FORCE_REOPEN:
+ case HA_EXTRA_PREPARE_FOR_DELETE:
pthread_mutex_lock(&THR_LOCK_isam);
info->s->last_version= 0L; /* Impossible version */
#ifdef __WIN__
diff --git a/isam/info.c b/isam/info.c
index 43c15af908d..a23494e4876 100644
--- a/isam/info.c
+++ b/isam/info.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
diff --git a/isam/isamchk.c b/isam/isamchk.c
index 3aa1cf4e3c2..c09b1cd3324 100644
--- a/isam/isamchk.c
+++ b/isam/isamchk.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -62,7 +62,7 @@ SET_STACK_SIZE(9000) /* Minimum stack size for program */
#define MIN_SORT_BUFFER (4096-MALLOC_OVERHEAD)
#endif
-#define NEAD_MEM ((uint) 10*4*(IO_SIZE+32)+32) /* Nead for recursion */
+#define NEED_MEM ((uint) 10*4*(IO_SIZE+32)+32) /* Nead for recursion */
#define MAXERR 20
#define BUFFERS_WHEN_SORTING 16 /* Alloc for sort-key-tree */
#define WRITE_COUNT MY_HOW_OFTEN_TO_WRITE
@@ -512,7 +512,7 @@ static int nisamchk(my_string filename)
if (!rep_quick)
{
if (testflag & T_EXTEND)
- VOID(init_key_cache(use_buffers,(uint) NEAD_MEM));
+ VOID(init_key_cache(use_buffers,(uint) NEED_MEM));
VOID(init_io_cache(&read_cache,datafile,(uint) read_buffer_length,
READ_CACHE,share->pack.header_length,1,
MYF(MY_WME)));
@@ -1473,7 +1473,7 @@ my_string name;
printf("Data records: %lu\n",(ulong) share->state.records);
}
- VOID(init_key_cache(use_buffers,NEAD_MEM));
+ VOID(init_key_cache(use_buffers,NEED_MEM));
if (init_io_cache(&read_cache,info->dfile,(uint) read_buffer_length,
READ_CACHE,share->pack.header_length,1,MYF(MY_WME)))
goto err;
@@ -1950,7 +1950,7 @@ int write_info;
if (share->state.key_root[sort_key] == NI_POS_ERROR)
DBUG_RETURN(0); /* Nothing to do */
- init_key_cache(use_buffers,NEAD_MEM);
+ init_key_cache(use_buffers,NEED_MEM);
if (init_io_cache(&info->rec_cache,-1,(uint) write_buffer_length,
WRITE_CACHE,share->pack.header_length,1,
MYF(MY_WME | MY_WAIT_IF_FULL)))
diff --git a/isam/isamdef.h b/isam/isamdef.h
index da08b5f6a14..0884b18e997 100644
--- a/isam/isamdef.h
+++ b/isam/isamdef.h
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
diff --git a/isam/isamlog.c b/isam/isamlog.c
index 5763b697d07..6d2bde42bf7 100644
--- a/isam/isamlog.c
+++ b/isam/isamlog.c
@@ -327,8 +327,8 @@ static int examine_log(my_string file_name, char **table_names)
init_io_cache(&cache,file,0,READ_CACHE,start_offset,0,MYF(0));
bzero((gptr) com_count,sizeof(com_count));
- init_tree(&tree,0,sizeof(file_info),(qsort_cmp) file_info_compare,1,
- (void(*)(void*)) file_info_free);
+ init_tree(&tree,0,0,sizeof(file_info),(qsort_cmp2) file_info_compare,1,
+ (tree_element_free) file_info_free, NULL);
VOID(init_key_cache(KEY_CACHE_SIZE,(uint) (10*4*(IO_SIZE+MALLOC_OVERHEAD))));
files_open=0; access_time=0;
@@ -400,11 +400,7 @@ static int examine_log(my_string file_name, char **table_names)
}
to=isam_file_name;
if (filepath)
- {
- strmov(isam_file_name,filepath);
- convert_dirname(isam_file_name);
- to=strend(isam_file_name);
- }
+ to=convert_dirname(isam_file_name, filepath, NullS);
strmov(to,pos);
fn_ext(isam_file_name)[0]=0; /* Remove extension */
}
diff --git a/isam/log.c b/isam/log.c
index a95b53b5110..78b56690401 100644
--- a/isam/log.c
+++ b/isam/log.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
diff --git a/isam/open.c b/isam/open.c
index a3ede4512b9..48fab27cac1 100644
--- a/isam/open.c
+++ b/isam/open.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
diff --git a/isam/pack_isam.c b/isam/pack_isam.c
index 3d8512847ae..4a3a787ff5c 100644
--- a/isam/pack_isam.c
+++ b/isam/pack_isam.c
@@ -682,9 +682,9 @@ static HUFF_COUNTS *init_huff_count(N_INFO *info,my_off_t records)
type = FIELD_NORMAL;
if (count[i].field_length <= 8 &&
(type == FIELD_NORMAL ||
- type == FIELD_SKIPP_ZERO))
+ type == FIELD_SKIP_ZERO))
count[i].max_zero_fill= count[i].field_length;
- init_tree(&count[i].int_tree,0,-1,(qsort_cmp) compare_tree,0,NULL);
+ init_tree(&count[i].int_tree,0,0,-1,(qsort_cmp2) compare_tree,0,NULL,NULL);
if (records)
count[i].tree_pos=count[i].tree_buff =
my_malloc(count[i].field_length > 1 ? tree_buff_length : 2,
@@ -786,7 +786,7 @@ static int get_statistic(MRG_INFO *mrg,HUFF_COUNTS *huff_counts)
/* Save character counters and space-counts and zero-field-counts */
if (count->field_type == FIELD_NORMAL ||
- count->field_type == FIELD_SKIPP_ENDSPACE)
+ count->field_type == FIELD_SKIP_ENDSPACE)
{
for ( ; end_pos > pos ; end_pos--)
if (end_pos[-1] != ' ')
@@ -805,7 +805,7 @@ static int get_statistic(MRG_INFO *mrg,HUFF_COUNTS *huff_counts)
count->max_end_space = length;
}
if (count->field_type == FIELD_NORMAL ||
- count->field_type == FIELD_SKIPP_PRESPACE)
+ count->field_type == FIELD_SKIP_PRESPACE)
{
for (pos=start_pos; pos < end_pos ; pos++)
if (pos[0] != ' ')
@@ -825,7 +825,7 @@ static int get_statistic(MRG_INFO *mrg,HUFF_COUNTS *huff_counts)
}
if (count->field_length <= 8 &&
(count->field_type == FIELD_NORMAL ||
- count->field_type == FIELD_SKIPP_ZERO))
+ count->field_type == FIELD_SKIP_ZERO))
{
uint i;
if (!memcmp((byte*) start_pos,zero_string,count->field_length))
@@ -906,7 +906,7 @@ static void check_counts(HUFF_COUNTS *huff_counts, uint trees, my_off_t records)
new_length=calc_packed_length(huff_counts,0);
if (old_length < new_length && huff_counts->field_length > 1)
{
- huff_counts->field_type=FIELD_SKIPP_ZERO;
+ huff_counts->field_type=FIELD_SKIP_ZERO;
huff_counts->counts[0]-=length;
huff_counts->bytes_packed=old_length- records/8;
goto found_pack;
@@ -950,7 +950,7 @@ static void check_counts(HUFF_COUNTS *huff_counts, uint trees, my_off_t records)
huff_counts->counts[' ']+=huff_counts->tot_pre_space;
if (test_space_compress(huff_counts,records,huff_counts->max_end_space,
huff_counts->end_space,
- huff_counts->tot_end_space,FIELD_SKIPP_ENDSPACE))
+ huff_counts->tot_end_space,FIELD_SKIP_ENDSPACE))
goto found_pack;
huff_counts->counts[' ']-=huff_counts->tot_pre_space;
}
@@ -958,7 +958,7 @@ static void check_counts(HUFF_COUNTS *huff_counts, uint trees, my_off_t records)
{
if (test_space_compress(huff_counts,records,huff_counts->max_pre_space,
huff_counts->pre_space,
- huff_counts->tot_pre_space,FIELD_SKIPP_PRESPACE))
+ huff_counts->tot_pre_space,FIELD_SKIP_PRESPACE))
goto found_pack;
}
@@ -968,10 +968,10 @@ static void check_counts(HUFF_COUNTS *huff_counts, uint trees, my_off_t records)
if (huff_counts->max_zero_fill &&
(huff_counts->field_type == FIELD_NORMAL ||
- huff_counts->field_type == FIELD_SKIPP_ZERO))
+ huff_counts->field_type == FIELD_SKIP_ZERO))
{
huff_counts->counts[0]-=huff_counts->max_zero_fill*
- (huff_counts->field_type == FIELD_SKIPP_ZERO ?
+ (huff_counts->field_type == FIELD_SKIP_ZERO ?
records - huff_counts->zero_fields : records);
huff_counts->pack_type|=PACK_TYPE_ZERO_FILL;
huff_counts->bytes_packed=calc_packed_length(huff_counts,0);
@@ -1011,9 +1011,9 @@ static void check_counts(HUFF_COUNTS *huff_counts, uint trees, my_off_t records)
if (verbose)
printf("\nnormal: %3d empty-space: %3d empty-zero: %3d empty-fill: %3d\npre-space: %3d end-space: %3d table-lookup: %3d zero: %3d\n",
field_count[FIELD_NORMAL],space_fields,
- field_count[FIELD_SKIPP_ZERO],fill_zero_fields,
- field_count[FIELD_SKIPP_PRESPACE],
- field_count[FIELD_SKIPP_ENDSPACE],
+ field_count[FIELD_SKIP_ZERO],fill_zero_fields,
+ field_count[FIELD_SKIP_PRESPACE],
+ field_count[FIELD_SKIP_ENDSPACE],
field_count[FIELD_INTERVALL],
field_count[FIELD_ZERO]);
DBUG_VOID_RETURN;
@@ -1668,7 +1668,7 @@ static int compress_isam_file(MRG_INFO *mrg, HUFF_COUNTS *huff_counts)
field_length-=count->max_zero_fill;
switch(count->field_type) {
- case FIELD_SKIPP_ZERO:
+ case FIELD_SKIP_ZERO:
if (!memcmp((byte*) start_pos,zero_string,field_length))
{
write_bits(1,1);
@@ -1682,7 +1682,7 @@ static int compress_isam_file(MRG_INFO *mrg, HUFF_COUNTS *huff_counts)
write_bits(tree->code[(uchar) *start_pos],
(uint) tree->code_len[(uchar) *start_pos]);
break;
- case FIELD_SKIPP_ENDSPACE:
+ case FIELD_SKIP_ENDSPACE:
for (pos=end_pos ; pos > start_pos && pos[-1] == ' ' ; pos--) ;
length=(uint) (end_pos-pos);
if (count->pack_type & PACK_TYPE_SELECTED)
@@ -1705,7 +1705,7 @@ static int compress_isam_file(MRG_INFO *mrg, HUFF_COUNTS *huff_counts)
(uint) tree->code_len[(uchar) *start_pos]);
start_pos=end_pos;
break;
- case FIELD_SKIPP_PRESPACE:
+ case FIELD_SKIP_PRESPACE:
for (pos=start_pos ; pos < end_pos && pos[0] == ' ' ; pos++) ;
length=(uint) (pos-start_pos);
if (count->pack_type & PACK_TYPE_SELECTED)
diff --git a/isam/panic.c b/isam/panic.c
index 52a5d1eb3b6..e51e83671df 100644
--- a/isam/panic.c
+++ b/isam/panic.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
diff --git a/isam/range.c b/isam/range.c
index 5594991cfc3..3b79b6d93a9 100644
--- a/isam/range.c
+++ b/isam/range.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
diff --git a/isam/rfirst.c b/isam/rfirst.c
index 82fd3994bdf..cc1cbee92bf 100644
--- a/isam/rfirst.c
+++ b/isam/rfirst.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
diff --git a/isam/rkey.c b/isam/rkey.c
index 8f1f2f11ab5..bbe4576418b 100644
--- a/isam/rkey.c
+++ b/isam/rkey.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
diff --git a/isam/rlast.c b/isam/rlast.c
index df2b1bc39af..a91f1f1011b 100644
--- a/isam/rlast.c
+++ b/isam/rlast.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
diff --git a/isam/rnext.c b/isam/rnext.c
index 451624bb42b..be26098c901 100644
--- a/isam/rnext.c
+++ b/isam/rnext.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
diff --git a/isam/rprev.c b/isam/rprev.c
index 50f22c838fd..0997a04fbbe 100644
--- a/isam/rprev.c
+++ b/isam/rprev.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
diff --git a/isam/rrnd.c b/isam/rrnd.c
index 7fd197a6d58..16b3ab1b859 100644
--- a/isam/rrnd.c
+++ b/isam/rrnd.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
diff --git a/isam/rsame.c b/isam/rsame.c
index fe617cf258c..9a2a03da054 100644
--- a/isam/rsame.c
+++ b/isam/rsame.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
diff --git a/isam/rsamepos.c b/isam/rsamepos.c
index 500dfc60e38..c64ac492d1a 100644
--- a/isam/rsamepos.c
+++ b/isam/rsamepos.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
diff --git a/isam/sort.c b/isam/sort.c
index 72c4c7564f8..d22b0e648a0 100644
--- a/isam/sort.c
+++ b/isam/sort.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
diff --git a/isam/static.c b/isam/static.c
index 941c4defea2..9c68a0cfdba 100644
--- a/isam/static.c
+++ b/isam/static.c
@@ -1,21 +1,21 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/*
- Static variables for pisam library. All definied here for easy making of
+ Static variables for ISAM library. All definied here for easy making of
a shared library
*/
diff --git a/isam/test1.c b/isam/test1.c
index 33c61a53d4a..9ebc7af041d 100644
--- a/isam/test1.c
+++ b/isam/test1.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -19,7 +19,7 @@
static void get_options(int argc, char *argv[]);
static int rec_pointer_size=0,verbose=0,remove_ant=0,pack_keys=1,flags[50],
- packed_field=FIELD_SKIPP_PRESPACE;
+ packed_field=FIELD_SKIP_PRESPACE;
int main(int argc, char *argv[])
{
diff --git a/isam/test2.c b/isam/test2.c
index def6a4d3d5c..176346e74fa 100644
--- a/isam/test2.c
+++ b/isam/test2.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -115,17 +115,17 @@ int main(int argc, char *argv[])
keyinfo[5].seg[1].base.type=0;
keyinfo[5].base.flag = (uint8) (pack_type ? HA_PACK_KEY : 0);
- recinfo[0].base.type=pack_fields ? FIELD_SKIPP_PRESPACE : 0;
+ recinfo[0].base.type=pack_fields ? FIELD_SKIP_PRESPACE : 0;
recinfo[0].base.length=7;
- recinfo[1].base.type=pack_fields ? FIELD_SKIPP_PRESPACE : 0;
+ recinfo[1].base.type=pack_fields ? FIELD_SKIP_PRESPACE : 0;
recinfo[1].base.length=5;
- recinfo[2].base.type=pack_fields ? FIELD_SKIPP_PRESPACE : 0;
+ recinfo[2].base.type=pack_fields ? FIELD_SKIP_PRESPACE : 0;
recinfo[2].base.length=9;
recinfo[3].base.type=FIELD_NORMAL;
recinfo[3].base.length=STANDAR_LENGTH-7-5-9-4;
- recinfo[4].base.type=pack_fields ? FIELD_SKIPP_ZERO : 0;
+ recinfo[4].base.type=pack_fields ? FIELD_SKIP_ZERO : 0;
recinfo[4].base.length=4;
- recinfo[5].base.type=pack_fields ? FIELD_SKIPP_ENDSPACE : 0;
+ recinfo[5].base.type=pack_fields ? FIELD_SKIP_ENDSPACE : 0;
recinfo[5].base.length=60;
if (use_blob)
{
diff --git a/isam/test3.c b/isam/test3.c
index 935c194106d..6c3390a2720 100644
--- a/isam/test3.c
+++ b/isam/test3.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -172,7 +172,7 @@ void start_test(int id)
}
if (key_cacheing && rnd(2) == 0)
init_key_cache(65536L,(uint) IO_SIZE*4*10);
- printf("Process %d, pid: %d\n",id,getpid()); fflush(stdout);
+ printf("Process %d, pid: %d\n",id,(int) getpid()); fflush(stdout);
for (error=i=0 ; i < tests && !error; i++)
{
@@ -356,7 +356,7 @@ int test_write(N_INFO *file,int id,int lock_type)
nisam_extra(file,HA_EXTRA_WRITE_CACHE);
}
- sprintf(record.id,"%7d",getpid());
+ sprintf(record.id,"%7d",(int) getpid());
strmov(record.text,"Testing...");
tries=(uint) rnd(100)+10;
diff --git a/isam/update.c b/isam/update.c
index 82dab4140e3..b3b676f967d 100644
--- a/isam/update.c
+++ b/isam/update.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
diff --git a/isam/write.c b/isam/write.c
index 49b0916afc4..f2c0d8dbc45 100644
--- a/isam/write.c
+++ b/isam/write.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -262,7 +262,7 @@ int _nisam_insert(register N_INFO *info, register N_KEYDEF *keyinfo,
/* This may happen if a key was deleted and the next key could be
compressed better than before */
DBUG_DUMP("anc_buff",(byte*) anc_buff,a_length);
-
+
bmove(key_pos,key_pos - (int) t_length,(uint)key_offset);
}
_nisam_store_key(keyinfo,key_pos,&s_temp);
diff --git a/libmysql/Makefile.am b/libmysql/Makefile.am
index 68c2022223e..2eaf9709a36 100644
--- a/libmysql/Makefile.am
+++ b/libmysql/Makefile.am
@@ -18,10 +18,10 @@
# This file is public domain and comes with NO WARRANTY of any kind
target = libmysqlclient.la
-target_defs = -DUNDEF_THREADS_HACK -DDONT_USE_RAID @LIB_EXTRA_CCFLAGS@
+target_defs = -DUNDEF_THREADS_HACK -DDONT_USE_RAID @LIB_EXTRA_CCFLAGS@ -DMYSQL_CLIENT
LIBS = @CLIENT_LIBS@
INCLUDES = -I$(srcdir)/../include -I../include \
- -I$(srcdir)/.. -I$(top_srcdir) -I..
+ -I$(srcdir)/.. -I$(top_srcdir) -I.. $(openssl_includes)
include $(srcdir)/Makefile.shared
@@ -36,14 +36,23 @@ link_sources:
ss=`echo $(mystringsobjects) | sed "s;\.lo;.c;g"`; \
ds=`echo $(dbugobjects) | sed "s;\.lo;.c;g"`; \
ms=`echo $(mysysobjects) | sed "s;\.lo;.c;g"`; \
+ vs=`echo $(vio_objects) | sed "s;\.lo;.c;g"`; \
for f in $$ss; do \
rm -f $(srcdir)/$$f; \
@LN_CP_F@ $(srcdir)/../strings/$$f $(srcdir)/$$f; \
done; \
+ for f in $$vs; do \
+ rm -f $(srcdir)/$$f; \
+ @LN_CP_F@ $(srcdir)/../vio/$$f $(srcdir)/$$f; \
+ done; \
for f in $(mystringsextra); do \
rm -f $(srcdir)/$$f; \
@LN_CP_F@ $(srcdir)/../strings/$$f $(srcdir)/$$f; \
done; \
+ for f in $$qs; do \
+ rm -f $(srcdir)/$$f; \
+ @LN_CP_F@ $(srcdir)/../sql/$$f $(srcdir)/$$f; \
+ done; \
for f in $$ds; do \
rm -f $(srcdir)/$$f; \
@LN_CP_F@ $(srcdir)/../dbug/$$f $(srcdir)/$$f; \
@@ -62,11 +71,11 @@ link_sources:
# keep only the stubs for safemalloc.c and debug.c
#
# A list of needed headers collected from the deps information 000213
-nh = global.h config-win32.h dbug.h errmsg.h global.h \
+nh = my_global.h config-win32.h dbug.h errmsg.h \
m_ctype.h m_string.h \
my_alarm.h my_config.h my_dir.h my_list.h my_net.h my_sys.h \
- mysql.h mysql_com.h mysql_version.h mysqld_error.h mysys_err.h \
- my_pthread.h thr_alarm.h violite.h hash.h
+ mysql.h mysql_com.h mysql_version.h mysqld_error.h \
+ mysys_err.h my_pthread.h thr_alarm.h violite.h hash.h
# Get a list of the needed objects
lobjs = $(mysysobjects1) $(dbugobjects) $(mystringsobjects)
diff --git a/libmysql/Makefile.shared b/libmysql/Makefile.shared
index e9e100e38b1..0d3aa79b9ce 100644
--- a/libmysql/Makefile.shared
+++ b/libmysql/Makefile.shared
@@ -31,13 +31,14 @@ noinst_PROGRAMS = conf_to_src
CHARSET_OBJS=@CHARSET_OBJS@
LTCHARSET_OBJS= ${CHARSET_OBJS:.o=.lo}
-target_sources = libmysql.c net.c violite.c password.c \
+target_sources = libmysql.c net.c password.c manager.c \
get_password.c errmsg.c
-mystringsobjects = strmov.lo strxmov.lo strnmov.lo strmake.lo strend.lo \
+mystringsobjects = strmov.lo strxmov.lo strxnmov.lo strnmov.lo \
+ strmake.lo strend.lo \
strnlen.lo strfill.lo is_prefix.lo \
int2str.lo str2int.lo strinstr.lo strcont.lo \
- strcend.lo \
+ strcend.lo bcmp.lo \
bchange.lo bmove.lo bmove_upp.lo longlong2str.lo \
strtoull.lo strtoll.lo llstr.lo \
ctype.lo $(LTCHARSET_OBJS)
@@ -55,13 +56,17 @@ mysysobjects1 = my_init.lo my_static.lo my_malloc.lo my_realloc.lo \
mf_loadpath.lo my_pthread.lo my_thr_init.lo \
thr_mutex.lo mulalloc.lo string.lo default.lo \
my_compress.lo array.lo my_once.lo list.lo my_net.lo \
- charset.lo hash.lo mf_iocache.lo my_seek.lo \
- my_pread.lo mf_cache.lo
+ charset.lo hash.lo mf_iocache.lo \
+ mf_iocache2.lo my_seek.lo \
+ my_pread.lo mf_cache.lo my_vsnprintf.lo md5.lo
+
# Not needed in the minimum library
mysysobjects2 = getopt.lo getopt1.lo getvar.lo my_lib.lo
mysysobjects = $(mysysobjects1) $(mysysobjects2)
-target_libadd = $(mysysobjects) $(mystringsobjects) $(dbugobjects)
+target_libadd = $(mysysobjects) $(mystringsobjects) $(dbugobjects) \
+ $(vio_objects)
target_ldflags = -version-info @SHARED_LIB_VERSION@
+vio_objects= vio.lo viosocket.lo viossl.lo viosslfactories.lo
CLEANFILES = $(target_libadd) $(SHLIBOBJS) \
$(target)
DEFS = -DDEFAULT_CHARSET_HOME="\"$(MYSQLBASEdir)\"" \
@@ -76,6 +81,7 @@ clean-local:
rm -f `echo $(mystringsobjects) | sed "s;\.lo;.c;g"` \
`echo $(dbugobjects) | sed "s;\.lo;.c;g"` \
`echo $(mysysobjects) | sed "s;\.lo;.c;g"` \
+ `echo $(vio_objects) | sed "s;\.lo;.c;g"` \
$(mystringsextra) $(mysysheaders) ctype_extra_sources.c \
../linked_client_sources
diff --git a/libmysql/conf_to_src.c b/libmysql/conf_to_src.c
index 76316638153..95ffcf1cb2b 100644
--- a/libmysql/conf_to_src.c
+++ b/libmysql/conf_to_src.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/* can't use -lmysys because this prog is used to create -lstrings */
diff --git a/libmysql/dll.c b/libmysql/dll.c
index d1a23794025..f0a67d8f091 100644
--- a/libmysql/dll.c
+++ b/libmysql/dll.c
@@ -1,25 +1,24 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/*
** Handling initialization of the dll library
*/
-#include <global.h>
+#include <my_global.h>
#include <my_sys.h>
#include <my_pthread.h>
diff --git a/libmysql/errmsg.c b/libmysql/errmsg.c
index 67cfe874f77..3fdb9c0ddc6 100644
--- a/libmysql/errmsg.c
+++ b/libmysql/errmsg.c
@@ -1,24 +1,23 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/* Error messages for MySQL clients */
-/* error messages for the demon is in share/language/errmsg.sys */
+/* error messages for the daemon is in share/language/errmsg.sys */
-#include <global.h>
+#include <my_global.h>
#include <my_sys.h>
#include "errmsg.h"
@@ -45,7 +44,12 @@ const char *client_errors[]=
"Kann Named Pipe nicht oeffnen. Host: %-.64s pipe: %-.32s (%lu)",
"Kann den Status der Named Pipe nicht setzen. Host: %-.64s pipe: %-.32s (%lu)",
"Can't initialize character set %-.64s (path: %-.64s)",
- "Got packet bigger than 'max_allowed_packet'"
+ "Got packet bigger than 'max_allowed_packet'",
+ "Embedded server",
+ "Error on SHOW SLAVE STATUS:",
+ "Error on SHOW SLAVE HOSTS:",
+ "Error connecting to slave:",
+ "Error connecting to master:"
};
/* Start of code added by Roberto M. Serqueira - martinsc@uol.com.br - 05.24.2001 */
@@ -73,7 +77,12 @@ const char *client_errors[]=
"Não pode abrir 'named pipe' para o 'host' %-.64s - 'pipe' %-.32s (%lu)",
"Não pode estabelecer o estado do 'named pipe' para o 'host' %-.64s - 'pipe' %-.32s (%lu)",
"Não pode inicializar conjunto de caracteres %-.64s (caminho %-.64s)",
- "Obteve pacote maior do que 'max_allowed_packet'"
+ "Obteve pacote maior do que 'max_allowed_packet'",
+ "Embedded server"
+ "Error on SHOW SLAVE STATUS:",
+ "Error on SHOW SLAVE HOSTS:",
+ "Error connecting to slave:",
+ "Error connecting to master:"
};
#else /* ENGLISH */
@@ -99,7 +108,12 @@ const char *client_errors[]=
"Can't open named pipe to host: %-.64s pipe: %-.32s (%lu)",
"Can't set state of named pipe to host: %-.64s pipe: %-.32s (%lu)",
"Can't initialize character set %-.64s (path: %-.64s)",
- "Got packet bigger than 'max_allowed_packet'"
+ "Got packet bigger than 'max_allowed_packet'",
+ "Embedded server",
+ "Error on SHOW SLAVE STATUS:",
+ "Error on SHOW SLAVE HOSTS:",
+ "Error connecting to slave:",
+ "Error connecting to master:"
};
#endif
diff --git a/libmysql/get_password.c b/libmysql/get_password.c
index 989de9dd11a..124c315a821 100644
--- a/libmysql/get_password.c
+++ b/libmysql/get_password.c
@@ -1,25 +1,24 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/*
** Ask for a password from tty
** This is an own file to avoid conflicts with curses
*/
-#include <global.h>
+#include <my_global.h>
#include <my_sys.h>
#include "mysql.h"
#include <m_string.h>
diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c
index c75bb0ad462..32aa8e59888 100644
--- a/libmysql/libmysql.c
+++ b/libmysql/libmysql.c
@@ -1,21 +1,20 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
-
-#include <global.h>
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <my_global.h>
#if defined(__WIN__) || defined(_WIN32) || defined(_WIN64)
#include <winsock.h>
#include <odbcinst.h>
@@ -70,7 +69,7 @@ my_string mysql_unix_port=0;
#endif
#if defined(MSDOS) || defined(__WIN__)
-// socket_errno is defined in global.h for all platforms
+// socket_errno is defined in my_global.h for all platforms
#define perror(A)
#else
#include <errno.h>
@@ -91,6 +90,32 @@ static sig_handler pipe_sig_handler(int sig);
static ulong mysql_sub_escape_string(CHARSET_INFO *charset_info, char *to,
const char *from, ulong length);
+int STDCALL mysql_server_init(int argc __attribute__((unused)),
+ char **argv __attribute__((unused)),
+ char **groups __attribute__((unused)))
+{
+ return 0;
+}
+
+void STDCALL mysql_server_end()
+{}
+
+my_bool STDCALL mysql_thread_init()
+{
+#ifdef THREAD
+ return my_thread_init();
+#else
+ return 0;
+#endif
+}
+
+void STDCALL mysql_thread_end()
+{
+#ifdef THREAD
+ my_thread_end();
+#endif
+}
+
/*
Let the user specify that we don't want SIGPIPE; This doesn't however work
with threaded applications as we can have multiple read in progress.
@@ -106,17 +131,23 @@ static ulong mysql_sub_escape_string(CHARSET_INFO *charset_info, char *to,
#define reset_sigpipe(mysql)
#endif
+static MYSQL* spawn_init(MYSQL* parent, const char* host,
+ unsigned int port,
+ const char* user,
+ const char* passwd);
+
+
/****************************************************************************
* A modified version of connect(). connect2() allows you to specify
* a timeout value, in seconds, that we should wait until we
* derermine we can't connect to a particular host. If timeout is 0,
-* connect2() will behave exactly like connect().
+* my_connect() will behave exactly like connect().
*
* Base version coded by Steve Bernacki, Jr. <steve@navinet.net>
*****************************************************************************/
-static int connect2(my_socket s, const struct sockaddr *name, uint namelen,
- uint timeout)
+int my_connect(my_socket s, const struct sockaddr *name, uint namelen,
+ uint timeout)
{
#if defined(__WIN__) || defined(OS2)
return connect(s, (struct sockaddr*) name, namelen);
@@ -284,11 +315,11 @@ HANDLE create_named_pipe(NET *net, uint connect_timeout, char **arg_host,
** or packet is an error message
*****************************************************************************/
-uint
+ulong
net_safe_read(MYSQL *mysql)
{
NET *net= &mysql->net;
- uint len=0;
+ ulong len=0;
init_sigpipe_variables
/* Don't give sigpipe errors if the client doesn't want them */
@@ -306,26 +337,18 @@ net_safe_read(MYSQL *mysql)
CR_NET_PACKET_TOO_LARGE:
CR_SERVER_LOST);
strmov(net->last_error,ER(net->last_errno));
- return(packet_error);
+ return (packet_error);
}
if (net->read_pos[0] == 255)
{
if (len > 3)
{
char *pos=(char*) net->read_pos+1;
- if (mysql->protocol_version > 9)
- { /* New client protocol */
- net->last_errno=uint2korr(pos);
- pos+=2;
- len-=2;
- }
- else
- {
- net->last_errno=CR_UNKNOWN_ERROR;
- len--;
- }
+ net->last_errno=uint2korr(pos);
+ pos+=2;
+ len-=2;
(void) strmake(net->last_error,(char*) pos,
- min(len,sizeof(net->last_error)-1));
+ min((uint) len,(uint) sizeof(net->last_error)-1));
}
else
{
@@ -416,7 +439,7 @@ static void free_rows(MYSQL_DATA *cur)
int
simple_command(MYSQL *mysql,enum enum_server_command command, const char *arg,
- uint length, my_bool skipp_check)
+ ulong length, my_bool skipp_check)
{
NET *net= &mysql->net;
int result= -1;
@@ -647,8 +670,8 @@ mysql_free_result(MYSQL_RES *result)
DBUG_PRINT("warning",("Not all rows in set were read; Ignoring rows"));
for (;;)
{
- uint pkt_len;
- if ((pkt_len=(uint) net_safe_read(result->handle)) == packet_error)
+ ulong pkt_len;
+ if ((pkt_len=net_safe_read(result->handle)) == packet_error)
break;
if (pkt_len == 1 && result->handle->net.read_pos[0] == 254)
break; /* End of data */
@@ -677,6 +700,8 @@ static const char *default_options[]=
"ssl-key" ,"ssl-cert" ,"ssl-ca" ,"ssl-capath",
"character-set-dir", "default-character-set", "interactive-timeout",
"connect-timeout", "local-infile", "disable-local-infile",
+ "replication-probe", "enable-reads-from-master", "repl-parse-query",
+ "ssl-chiper",
NullS
};
@@ -821,6 +846,15 @@ static void mysql_read_default_options(struct st_mysql_options *options,
break;
case 22:
options->client_flag&= CLIENT_LOCAL_FILES;
+ break;
+ case 23: /* replication probe */
+ options->rpl_probe = 1;
+ break;
+ case 24: /* enable-reads-from-master */
+ options->rpl_parse = 1;
+ break;
+ case 25: /* repl-parse-query */
+ options->no_master_reads = 0;
break;
default:
DBUG_PRINT("warning",("unknown option: %s",option[0]));
@@ -845,13 +879,14 @@ unpack_fields(MYSQL_DATA *data,MEM_ROOT *alloc,uint fields,
MYSQL_FIELD *field,*result;
DBUG_ENTER("unpack_fields");
- field=result=(MYSQL_FIELD*) alloc_root(alloc,sizeof(MYSQL_FIELD)*fields);
+ field=result=(MYSQL_FIELD*) alloc_root(alloc,
+ (uint) sizeof(MYSQL_FIELD)*fields);
if (!result)
DBUG_RETURN(0);
for (row=data->data; row ; row = row->next,field++)
{
- field->table= strdup_root(alloc,(char*) row->data[0]);
+ field->org_table= field->table= strdup_root(alloc,(char*) row->data[0]);
field->name= strdup_root(alloc,(char*) row->data[1]);
field->length= (uint) uint3korr(row->data[2]);
field->type= (enum enum_field_types) (uchar) row->data[3][0];
@@ -883,7 +918,8 @@ unpack_fields(MYSQL_DATA *data,MEM_ROOT *alloc,uint fields,
static MYSQL_DATA *read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields,
uint fields)
{
- uint field,pkt_len;
+ uint field;
+ ulong pkt_len;
ulong len;
uchar *cp;
char *to;
@@ -892,7 +928,7 @@ static MYSQL_DATA *read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields,
NET *net = &mysql->net;
DBUG_ENTER("read_rows");
- if ((pkt_len=(uint) net_safe_read(mysql)) == packet_error)
+ if ((pkt_len= net_safe_read(mysql)) == packet_error)
DBUG_RETURN(0);
if (!(result=(MYSQL_DATA*) my_malloc(sizeof(MYSQL_DATA),
MYF(MY_WME | MY_ZEROFILL))))
@@ -969,7 +1005,7 @@ read_one_row(MYSQL *mysql,uint fields,MYSQL_ROW row, ulong *lengths)
ulong pkt_len,len;
uchar *pos,*prev_pos;
- if ((pkt_len=(uint) net_safe_read(mysql)) == packet_error)
+ if ((pkt_len=net_safe_read(mysql)) == packet_error)
return -1;
if (pkt_len == 1 && mysql->net.read_pos[0] == 254)
return 1; /* End of data */
@@ -997,6 +1033,280 @@ read_one_row(MYSQL *mysql,uint fields,MYSQL_ROW row, ulong *lengths)
return 0;
}
+/* perform query on master */
+int STDCALL mysql_master_query(MYSQL *mysql, const char *q,
+ unsigned long length)
+{
+ if (mysql_master_send_query(mysql, q, length))
+ return 1;
+ return mysql_read_query_result(mysql);
+}
+
+int STDCALL mysql_master_send_query(MYSQL *mysql, const char *q,
+ unsigned long length)
+{
+ MYSQL*master = mysql->master;
+ if (!length)
+ length = strlen(q);
+ if (!master->net.vio && !mysql_real_connect(master,0,0,0,0,0,0,0))
+ return 1;
+ mysql->last_used_con = master;
+ return simple_command(master, COM_QUERY, q, length, 1);
+}
+
+
+/* perform query on slave */
+int STDCALL mysql_slave_query(MYSQL *mysql, const char *q,
+ unsigned long length)
+{
+ if (mysql_slave_send_query(mysql, q, length))
+ return 1;
+ return mysql_read_query_result(mysql);
+}
+
+int STDCALL mysql_slave_send_query(MYSQL *mysql, const char *q,
+ unsigned long length)
+{
+ MYSQL* last_used_slave, *slave_to_use = 0;
+
+ if ((last_used_slave = mysql->last_used_slave))
+ slave_to_use = last_used_slave->next_slave;
+ else
+ slave_to_use = mysql->next_slave;
+ /* next_slave is always safe to use - we have a circular list of slaves
+ if there are no slaves, mysql->next_slave == mysql
+ */
+ mysql->last_used_con = mysql->last_used_slave = slave_to_use;
+ if (!length)
+ length = strlen(q);
+ if (!slave_to_use->net.vio && !mysql_real_connect(slave_to_use, 0,0,0,
+ 0,0,0,0))
+ return 1;
+ return simple_command(slave_to_use, COM_QUERY, q, length, 1);
+}
+
+
+/* enable/disable parsing of all queries to decide
+ if they go on master or slave */
+void STDCALL mysql_enable_rpl_parse(MYSQL* mysql)
+{
+ mysql->options.rpl_parse = 1;
+}
+
+void STDCALL mysql_disable_rpl_parse(MYSQL* mysql)
+{
+ mysql->options.rpl_parse = 0;
+}
+
+/* get the value of the parse flag */
+int STDCALL mysql_rpl_parse_enabled(MYSQL* mysql)
+{
+ return mysql->options.rpl_parse;
+}
+
+/* enable/disable reads from master */
+void STDCALL mysql_enable_reads_from_master(MYSQL* mysql)
+{
+ mysql->options.no_master_reads = 0;
+}
+
+void STDCALL mysql_disable_reads_from_master(MYSQL* mysql)
+{
+ mysql->options.no_master_reads = 1;
+}
+
+/* get the value of the master read flag */
+int STDCALL mysql_reads_from_master_enabled(MYSQL* mysql)
+{
+ return !(mysql->options.no_master_reads);
+}
+
+/* We may get an error while doing replication internals.
+ In this case, we add a special explanation to the original
+ error
+*/
+static inline void expand_error(MYSQL* mysql, int error)
+{
+ char tmp[MYSQL_ERRMSG_SIZE];
+ char* p, *tmp_end;
+ tmp_end = strnmov(tmp, mysql->net.last_error, MYSQL_ERRMSG_SIZE);
+ p = strnmov(mysql->net.last_error, ER(error), MYSQL_ERRMSG_SIZE);
+ memcpy(p, tmp, tmp_end - tmp);
+ mysql->net.last_errno = error;
+}
+
+/* This function assumes we have just called SHOW SLAVE STATUS and have
+ read the given result and row
+*/
+static inline int get_master(MYSQL* mysql, MYSQL_RES* res, MYSQL_ROW row)
+{
+ MYSQL* master;
+ if (mysql_num_fields(res) < 3)
+ return 1; /* safety */
+
+ /* use the same username and password as the original connection */
+ if (!(master = spawn_init(mysql, row[0], atoi(row[2]), 0, 0)))
+ return 1;
+ mysql->master = master;
+ return 0;
+}
+
+/* assuming we already know that mysql points to a master connection,
+ retrieve all the slaves
+*/
+static inline int get_slaves_from_master(MYSQL* mysql)
+{
+ MYSQL_RES* res = 0;
+ MYSQL_ROW row;
+ int error = 1;
+ int has_auth_info;
+ int port_ind;
+
+ if (!mysql->net.vio && !mysql_real_connect(mysql,0,0,0,0,0,0,0))
+ {
+ expand_error(mysql, CR_PROBE_MASTER_CONNECT);
+ return 1;
+ }
+
+ if (mysql_query(mysql, "SHOW SLAVE HOSTS") ||
+ !(res = mysql_store_result(mysql)))
+ {
+ expand_error(mysql, CR_PROBE_SLAVE_HOSTS);
+ return 1;
+ }
+
+ switch (mysql_num_fields(res))
+ {
+ case 5:
+ has_auth_info = 0;
+ port_ind=2;
+ break;
+ case 7:
+ has_auth_info = 1;
+ port_ind=4;
+ break;
+ default:
+ goto err;
+ }
+
+ while ((row = mysql_fetch_row(res)))
+ {
+ MYSQL* slave;
+ const char* tmp_user, *tmp_pass;
+
+ if (has_auth_info)
+ {
+ tmp_user = row[2];
+ tmp_pass = row[3];
+ }
+ else
+ {
+ tmp_user = mysql->user;
+ tmp_pass = mysql->passwd;
+ }
+
+ if (!(slave = spawn_init(mysql, row[1], atoi(row[port_ind]),
+ tmp_user, tmp_pass)))
+ goto err;
+
+ /* Now add slave into the circular linked list */
+ slave->next_slave = mysql->next_slave;
+ mysql->next_slave = slave;
+ }
+ error = 0;
+err:
+ if (res)
+ mysql_free_result(res);
+ return error;
+}
+
+int STDCALL mysql_rpl_probe(MYSQL* mysql)
+{
+ MYSQL_RES* res = 0;
+ MYSQL_ROW row;
+ int error = 1;
+ /* first determine the replication role of the server we connected to
+ the most reliable way to do this is to run SHOW SLAVE STATUS and see
+ if we have a non-empty master host. This is still not fool-proof -
+ it is not a sin to have a master that has a dormant slave thread with
+ a non-empty master host. However, it is more reliable to check
+ for empty master than whether the slave thread is actually running
+ */
+ if (mysql_query(mysql, "SHOW SLAVE STATUS") ||
+ !(res = mysql_store_result(mysql)))
+ {
+ expand_error(mysql, CR_PROBE_SLAVE_STATUS);
+ return 1;
+ }
+
+ if (!(row = mysql_fetch_row(res)))
+ goto err;
+
+ /* check master host for emptiness/NULL */
+ if (row[0] && *(row[0]))
+ {
+ /* this is a slave, ask it for the master */
+ if (get_master(mysql, res, row) || get_slaves_from_master(mysql))
+ goto err;
+ }
+ else
+ {
+ mysql->master = mysql;
+ if (get_slaves_from_master(mysql))
+ goto err;
+ }
+
+ error = 0;
+err:
+ if (res)
+ mysql_free_result(res);
+ return error;
+}
+
+
+/* make a not so fool-proof decision on where the query should go, to
+ the master or the slave. Ideally the user should always make this
+ decision himself with mysql_master_query() or mysql_slave_query().
+ However, to be able to more easily port the old code, we support the
+ option of an educated guess - this should work for most applications,
+ however, it may make the wrong decision in some particular cases. If
+ that happens, the user would have to change the code to call
+ mysql_master_query() or mysql_slave_query() explicitly in the place
+ where we have made the wrong decision
+*/
+enum mysql_rpl_type
+STDCALL mysql_rpl_query_type(const char* q, int len)
+{
+ const char* q_end;
+ q_end = (len) ? q + len : strend(q);
+ for(; q < q_end; ++q)
+ {
+ char c;
+ if (isalpha(c=*q))
+ switch(tolower(c))
+ {
+ case 'i': /* insert */
+ case 'u': /* update or unlock tables */
+ case 'l': /* lock tables or load data infile */
+ case 'd': /* drop or delete */
+ case 'a': /* alter */
+ return MYSQL_RPL_MASTER;
+ case 'c': /* create or check */
+ return tolower(q[1]) == 'h' ? MYSQL_RPL_ADMIN : MYSQL_RPL_MASTER ;
+ case 's': /* select or show */
+ return tolower(q[1]) == 'h' ? MYSQL_RPL_ADMIN : MYSQL_RPL_SLAVE;
+ case 'f': /* flush */
+ case 'r': /* repair */
+ case 'g': /* grant */
+ return MYSQL_RPL_ADMIN;
+ default:
+ return MYSQL_RPL_SLAVE;
+ }
+ }
+ return MYSQL_RPL_MASTER; /* By default, send to master */
+}
+
+
/****************************************************************************
** Init MySQL structure or allocate one
****************************************************************************/
@@ -1015,6 +1325,12 @@ mysql_init(MYSQL *mysql)
else
bzero((char*) (mysql),sizeof(*(mysql)));
mysql->options.connect_timeout=CONNECT_TIMEOUT;
+ mysql->last_used_con = mysql->next_slave = mysql->master = mysql;
+ mysql->last_used_slave = 0;
+ /* By default, we are a replication pivot. The caller must reset it
+ after we return if this is not the case.
+ */
+ mysql->rpl_pivot = 1;
#if defined(SIGPIPE) && defined(THREAD) && !defined(__WIN__)
if (!((mysql)->client_flag & CLIENT_IGNORE_SIGPIPE))
(void) signal(SIGPIPE,pipe_sig_handler);
@@ -1074,63 +1390,65 @@ static void mysql_once_init()
#endif
}
-#ifdef HAVE_OPENSSL
/**************************************************************************
** Fill in SSL part of MYSQL structure and set 'use_ssl' flag.
** NB! Errors are not reported until you do mysql_real_connect.
**************************************************************************/
int STDCALL
-mysql_ssl_set(MYSQL *mysql, const char *key, const char *cert,
- const char *ca, const char *capath)
+mysql_ssl_set(MYSQL *mysql __attribute__((unused)) ,
+ const char *key __attribute__((unused)),
+ const char *cert __attribute__((unused)),
+ const char *ca __attribute__((unused)),
+ const char *capath __attribute__((unused)),
+ const char *cipher __attribute__((unused)))
{
+#ifdef HAVE_OPENSSL
mysql->options.ssl_key = key==0 ? 0 : my_strdup(key,MYF(0));
mysql->options.ssl_cert = cert==0 ? 0 : my_strdup(cert,MYF(0));
mysql->options.ssl_ca = ca==0 ? 0 : my_strdup(ca,MYF(0));
mysql->options.ssl_capath = capath==0 ? 0 : my_strdup(capath,MYF(0));
- mysql->options.use_ssl = true;
- mysql->connector_fd = new_VioSSLConnectorFd(key, cert, ca, capath);
+ mysql->options.ssl_cipher = cipher==0 ? 0 : my_strdup(cipher,MYF(0));
+ mysql->options.use_ssl = TRUE;
+ mysql->connector_fd = (gptr)new_VioSSLConnectorFd(key, cert, ca, capath, cipher);
+ DBUG_PRINT("info",("mysql_ssl_set, context: %p",((struct st_VioSSLConnectorFd *)(mysql->connector_fd))->ssl_context_));
+#endif
return 0;
}
-/**************************************************************************
-**************************************************************************/
-
-char * STDCALL
-mysql_ssl_cipher(MYSQL *mysql)
-{
- return (char *)mysql->net.vio->cipher_description();
-}
-
-
-/**************************************************************************
+/*
+***************************************************************************
** Free strings in the SSL structure and clear 'use_ssl' flag.
** NB! Errors are not reported until you do mysql_real_connect.
-**************************************************************************/
-
+**************************************************************************
+*/
int STDCALL
-mysql_ssl_clear(MYSQL *mysql)
+mysql_ssl_clear(MYSQL *mysql __attribute__((unused)))
{
+#ifdef HAVE_OPENSSL
my_free(mysql->options.ssl_key, MYF(MY_ALLOW_ZERO_PTR));
my_free(mysql->options.ssl_cert, MYF(MY_ALLOW_ZERO_PTR));
my_free(mysql->options.ssl_ca, MYF(MY_ALLOW_ZERO_PTR));
my_free(mysql->options.ssl_capath, MYF(MY_ALLOW_ZERO_PTR));
+ my_free(mysql->options.ssl_cipher, MYF(MY_ALLOW_ZERO_PTR));
mysql->options.ssl_key = 0;
mysql->options.ssl_cert = 0;
mysql->options.ssl_ca = 0;
mysql->options.ssl_capath = 0;
- mysql->options.use_ssl = false;
- mysql->connector_fd->delete();
+ mysql->options.ssl_cipher= 0;
+ mysql->options.use_ssl = FALSE;
+ my_free(mysql->connector_fd,MYF(MY_ALLOW_ZERO_PTR));
mysql->connector_fd = 0;
+#endif /* HAVE_OPENSSL */
return 0;
}
-#endif /* HAVE_OPENSSL */
/**************************************************************************
** Connect to sql server
** If host == 0 then use localhost
**************************************************************************/
+#ifdef USE_OLD_FUNCTIONS
MYSQL * STDCALL
mysql_connect(MYSQL *mysql,const char *host,
const char *user, const char *passwd)
@@ -1147,6 +1465,7 @@ mysql_connect(MYSQL *mysql,const char *host,
DBUG_RETURN(res);
}
}
+#endif
/*
@@ -1164,7 +1483,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
my_socket sock;
uint32 ip_addr;
struct sockaddr_in sock_addr;
- uint pkt_length;
+ ulong pkt_length;
NET *net= &mysql->net;
#ifdef __WIN__
HANDLE hPipe=INVALID_HANDLE_VALUE;
@@ -1240,7 +1559,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
bzero((char*) &UNIXaddr,sizeof(UNIXaddr));
UNIXaddr.sun_family = AF_UNIX;
strmov(UNIXaddr.sun_path, unix_socket);
- if (connect2(sock,(struct sockaddr *) &UNIXaddr, sizeof(UNIXaddr),
+ if (my_connect(sock,(struct sockaddr *) &UNIXaddr, sizeof(UNIXaddr),
mysql->options.connect_timeout) <0)
{
DBUG_PRINT("error",("Got error %d on connect to local server",socket_errno));
@@ -1340,7 +1659,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
}
#endif
sock_addr.sin_port = (ushort) htons((ushort) port);
- if (connect2(sock,(struct sockaddr *) &sock_addr, sizeof(sock_addr),
+ if (my_connect(sock,(struct sockaddr *) &sock_addr, sizeof(sock_addr),
mysql->options.connect_timeout) <0)
{
DBUG_PRINT("error",("Got error %d on connect to '%s'",socket_errno,host));
@@ -1378,8 +1697,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
DBUG_DUMP("packet",(char*) net->read_pos,10);
DBUG_PRINT("info",("mysql protocol version %d, server=%d",
PROTOCOL_VERSION, mysql->protocol_version));
- if (mysql->protocol_version != PROTOCOL_VERSION &&
- mysql->protocol_version != PROTOCOL_VERSION-1)
+ if (mysql->protocol_version != PROTOCOL_VERSION)
{
net->last_errno= CR_VERSION_ERROR;
sprintf(net->last_error, ER(CR_VERSION_ERROR), mysql->protocol_version,
@@ -1415,7 +1733,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
charset_name=charset_name_buff;
sprintf(charset_name,"%d",mysql->server_language); /* In case of errors */
if (!(mysql->charset =
- get_charset((uint8) mysql->server_language, MYF(MY_WME))))
+ get_charset((uint8) mysql->server_language, MYF(0))))
mysql->charset = default_charset_info; /* shouldn't be fatal */
}
@@ -1513,11 +1831,9 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
goto error;
/* Do the SSL layering. */
DBUG_PRINT("info", ("IO layer change in progress..."));
- VioSSLConnectorFd* connector_fd = (VioSSLConnectorFd*)
- (mysql->connector_fd);
- VioSocket* vio_socket = (VioSocket*)(mysql->net.vio);
- VioSSL* vio_ssl = connector_fd->connect(vio_socket);
- mysql->net.vio = (NetVio*)(vio_ssl);
+ DBUG_PRINT("info", ("IO context %p",((struct st_VioSSLConnectorFd*)mysql->connector_fd)->ssl_context_));
+ sslconnect((struct st_VioSSLConnectorFd*)(mysql->connector_fd),mysql->net.vio, (long)(mysql->options.connect_timeout));
+ DBUG_PRINT("info", ("IO layer change done!"));
}
#endif /* HAVE_OPENSSL */
@@ -1542,7 +1858,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
mysql->db=my_strdup(db,MYF(MY_WME));
db=0;
}
- if (my_net_write(net,buff,(uint) (end-buff)) || net_flush(net) ||
+ if (my_net_write(net,buff,(ulong) (end-buff)) || net_flush(net) ||
net_safe_read(mysql) == packet_error)
goto error;
if (client_flag & CLIENT_COMPRESS) /* We will use compression */
@@ -1559,6 +1875,9 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
mysql->reconnect=reconnect;
}
+ if (mysql->options.rpl_probe && mysql_rpl_probe(mysql))
+ goto error;
+
DBUG_PRINT("exit",("Mysql handler: %lx",mysql));
reset_sigpipe(mysql);
DBUG_RETURN(mysql);
@@ -1577,6 +1896,23 @@ error:
DBUG_RETURN(0);
}
+/* needed when we move MYSQL structure to a different address */
+static void mysql_fix_pointers(MYSQL* mysql, MYSQL* old_mysql)
+{
+ MYSQL *tmp, *tmp_prev;
+ if (mysql->master == old_mysql)
+ mysql->master = mysql;
+ if (mysql->last_used_con == old_mysql)
+ mysql->last_used_con = mysql;
+ if (mysql->last_used_slave == old_mysql)
+ mysql->last_used_slave = mysql;
+ for (tmp_prev = mysql, tmp = mysql->next_slave;
+ tmp != old_mysql;tmp = tmp->next_slave)
+ {
+ tmp_prev = tmp;
+ }
+ tmp_prev->next_slave = mysql;
+}
static my_bool mysql_reconnect(MYSQL *mysql)
{
@@ -1586,13 +1922,14 @@ static my_bool mysql_reconnect(MYSQL *mysql)
if (!mysql->reconnect ||
(mysql->server_status & SERVER_STATUS_IN_TRANS) || !mysql->host_info)
{
- /* Allov reconnect next time */
+ /* Allow reconnect next time */
mysql->server_status&= ~SERVER_STATUS_IN_TRANS;
DBUG_RETURN(1);
}
mysql_init(&tmp_mysql);
tmp_mysql.options=mysql->options;
bzero((char*) &mysql->options,sizeof(mysql->options));
+ tmp_mysql.rpl_pivot = mysql->rpl_pivot;
if (!mysql_real_connect(&tmp_mysql,mysql->host,mysql->user,mysql->passwd,
mysql->db, mysql->port, mysql->unix_socket,
mysql->client_flag))
@@ -1601,6 +1938,7 @@ static my_bool mysql_reconnect(MYSQL *mysql)
mysql->free_me=0;
mysql_close(mysql);
*mysql=tmp_mysql;
+ mysql_fix_pointers(mysql, &tmp_mysql); /* adjust connection pointers */
net_clear(&mysql->net);
mysql->affected_rows= ~(my_ulonglong) 0;
DBUG_RETURN(0);
@@ -1626,7 +1964,7 @@ my_bool STDCALL mysql_change_user(MYSQL *mysql, const char *user,
pos=scramble(pos, mysql->scramble_buff, passwd,
(my_bool) (mysql->protocol_version == 9));
pos=strmov(pos+1,db ? db : "");
- if (simple_command(mysql,COM_CHANGE_USER, buff,(uint) (pos-buff),0))
+ if (simple_command(mysql,COM_CHANGE_USER, buff,(ulong) (pos-buff),0))
DBUG_RETURN(1);
my_free(mysql->user,MYF(MY_ALLOW_ZERO_PTR));
@@ -1651,7 +1989,7 @@ mysql_select_db(MYSQL *mysql, const char *db)
DBUG_ENTER("mysql_select_db");
DBUG_PRINT("enter",("db: '%s'",db));
- if ((error=simple_command(mysql,COM_INIT_DB,db,(uint) strlen(db),0)))
+ if ((error=simple_command(mysql,COM_INIT_DB,db,(ulong) strlen(db),0)))
DBUG_RETURN(error);
my_free(mysql->db,MYF(MY_ALLOW_ZERO_PTR));
mysql->db=my_strdup(db,MYF(MY_WME));
@@ -1692,14 +2030,29 @@ mysql_close(MYSQL *mysql)
my_free(mysql->options.my_cnf_group,MYF(MY_ALLOW_ZERO_PTR));
my_free(mysql->options.charset_dir,MYF(MY_ALLOW_ZERO_PTR));
my_free(mysql->options.charset_name,MYF(MY_ALLOW_ZERO_PTR));
+#ifdef HAVE_OPENSSL
+ mysql_ssl_clear(mysql);
+#endif /* HAVE_OPENSSL */
/* Clear pointers for better safety */
mysql->host_info=mysql->user=mysql->passwd=mysql->db=0;
bzero((char*) &mysql->options,sizeof(mysql->options));
mysql->net.vio = 0;
-#ifdef HAVE_OPENSSL
- ((VioConnectorFd*)(mysql->connector_fd))->delete();
- mysql->connector_fd = 0;
-#endif /* HAVE_OPENSSL */
+
+ /* free/close slave list */
+ if (mysql->rpl_pivot)
+ {
+ MYSQL* tmp;
+ for (tmp = mysql->next_slave; tmp != mysql; )
+ {
+ /* trick to avoid following freed pointer */
+ MYSQL* tmp1 = tmp->next_slave;
+ mysql_close(tmp);
+ tmp = tmp1;
+ }
+ mysql->rpl_pivot=0;
+ }
+ if (mysql != mysql->master)
+ mysql_close(mysql->master);
if (mysql->free_me)
my_free((gptr) mysql,MYF(0));
}
@@ -1718,6 +2071,68 @@ mysql_query(MYSQL *mysql, const char *query)
return mysql_real_query(mysql,query, (uint) strlen(query));
}
+
+static MYSQL* spawn_init(MYSQL* parent, const char* host,
+ unsigned int port, const char* user,
+ const char* passwd)
+{
+ MYSQL* child;
+ if (!(child = mysql_init(0)))
+ return 0;
+
+ child->options.user = my_strdup((user) ? user :
+ (parent->user ? parent->user :
+ parent->options.user), MYF(0));
+ child->options.password = my_strdup((passwd) ? passwd :
+ (parent->passwd ?
+ parent->passwd :
+ parent->options.password), MYF(0));
+ child->options.port = port;
+ child->options.host = my_strdup((host) ? host :
+ (parent->host ?
+ parent->host :
+ parent->options.host), MYF(0));
+ if (parent->db)
+ child->options.db = my_strdup(parent->db, MYF(0));
+ else if (parent->options.db)
+ child->options.db = my_strdup(parent->options.db, MYF(0));
+
+ child->options.rpl_parse = child->options.rpl_probe = child->rpl_pivot = 0;
+
+ return child;
+}
+
+
+int
+STDCALL mysql_set_master(MYSQL* mysql, const char* host,
+ unsigned int port, const char* user,
+ const char* passwd)
+{
+ if (mysql->master != mysql && !mysql->master->rpl_pivot)
+ mysql_close(mysql->master);
+ if (!(mysql->master = spawn_init(mysql, host, port, user, passwd)))
+ return 1;
+ mysql->master->rpl_pivot = 0;
+ mysql->master->options.rpl_parse = 0;
+ mysql->master->options.rpl_probe = 0;
+ return 0;
+}
+
+int
+STDCALL mysql_add_slave(MYSQL* mysql, const char* host,
+ unsigned int port,
+ const char* user,
+ const char* passwd)
+{
+ MYSQL* slave;
+ if (!(slave = spawn_init(mysql, host, port, user, passwd)))
+ return 1;
+ slave->next_slave = mysql->next_slave;
+ mysql->next_slave = slave;
+ return 0;
+}
+
+
/*
Send the query and return so we can do something else.
Needs to be followed by mysql_read_query_result() when we want to
@@ -1725,19 +2140,38 @@ mysql_query(MYSQL *mysql, const char *query)
*/
int STDCALL
-mysql_send_query(MYSQL* mysql, const char* query, uint length)
+mysql_send_query(MYSQL* mysql, const char* query, ulong length)
{
+ if (mysql->options.rpl_parse && mysql->rpl_pivot)
+ {
+ switch (mysql_rpl_query_type(query, length)) {
+ case MYSQL_RPL_MASTER:
+ return mysql_master_send_query(mysql, query, length);
+ case MYSQL_RPL_SLAVE:
+ return mysql_slave_send_query(mysql, query, length);
+ case MYSQL_RPL_ADMIN:
+ break; /* fall through */
+ }
+ }
+
+ mysql->last_used_con = mysql;
return simple_command(mysql, COM_QUERY, query, length, 1);
}
+
int STDCALL mysql_read_query_result(MYSQL *mysql)
{
uchar *pos;
ulong field_count;
MYSQL_DATA *fields;
- uint length;
+ ulong length;
DBUG_ENTER("mysql_read_query_result");
+ /* read from the connection which we actually used, which
+ could differ from the original connection if we have slaves
+ */
+ mysql = mysql->last_used_con;
+
if ((length = net_safe_read(mysql)) == packet_error)
DBUG_RETURN(-1);
free_old_query(mysql); /* Free old result */
@@ -1774,74 +2208,80 @@ get_info:
CLIENT_LONG_FLAG))))
DBUG_RETURN(-1);
mysql->status=MYSQL_STATUS_GET_RESULT;
- mysql->field_count=field_count;
+ mysql->field_count= (uint) field_count;
DBUG_RETURN(0);
}
+
int STDCALL
-mysql_real_query(MYSQL *mysql, const char *query, uint length)
+mysql_real_query(MYSQL *mysql, const char *query, ulong length)
{
DBUG_ENTER("mysql_real_query");
DBUG_PRINT("enter",("handle: %lx",mysql));
DBUG_PRINT("query",("Query = \"%s\"",query));
- if (simple_command(mysql,COM_QUERY,query,length,1))
+
+ if (mysql_send_query(mysql,query,length))
DBUG_RETURN(-1);
DBUG_RETURN(mysql_read_query_result(mysql));
}
+
static int
send_file_to_server(MYSQL *mysql, const char *filename)
{
- int fd, readcount;
- char buf[IO_SIZE*15],*tmp_name;
+ int fd, readcount, result= -1;
+ uint packet_length=MY_ALIGN(mysql->net.max_packet-16,IO_SIZE);
+ char *buf, tmp_name[FN_REFLEN];
DBUG_ENTER("send_file_to_server");
- fn_format(buf,filename,"","",4); /* Convert to client format */
- if (!(tmp_name=my_strdup(buf,MYF(0))))
+ if (!(buf=my_malloc(packet_length,MYF(0))))
{
strmov(mysql->net.last_error, ER(mysql->net.last_errno=CR_OUT_OF_MEMORY));
DBUG_RETURN(-1);
}
+
+ fn_format(tmp_name,filename,"","",4); /* Convert to client format */
if ((fd = my_open(tmp_name,O_RDONLY, MYF(0))) < 0)
{
+ my_net_write(&mysql->net,"",0); /* Server needs one packet */
+ net_flush(&mysql->net);
mysql->net.last_errno=EE_FILENOTFOUND;
- sprintf(buf,EE(mysql->net.last_errno),tmp_name,errno);
- strmake(mysql->net.last_error,buf,sizeof(mysql->net.last_error)-1);
- my_net_write(&mysql->net,"",0); net_flush(&mysql->net);
- my_free(tmp_name,MYF(0));
- DBUG_RETURN(-1);
+ my_snprintf(mysql->net.last_error,sizeof(mysql->net.last_error)-1,
+ EE(mysql->net.last_errno),tmp_name, errno);
+ goto err;
}
- while ((readcount = (int) my_read(fd,buf,sizeof(buf),MYF(0))) > 0)
+ while ((readcount = (int) my_read(fd,(byte*) buf,packet_length,MYF(0))) > 0)
{
if (my_net_write(&mysql->net,buf,readcount))
{
+ DBUG_PRINT("error",("Lost connection to MySQL server during LOAD DATA of local file"));
mysql->net.last_errno=CR_SERVER_LOST;
strmov(mysql->net.last_error,ER(mysql->net.last_errno));
- DBUG_PRINT("error",("Lost connection to MySQL server during LOAD DATA of local file"));
- (void) my_close(fd,MYF(0));
- my_free(tmp_name,MYF(0));
- DBUG_RETURN(-1);
+ goto err;
}
}
- (void) my_close(fd,MYF(0));
/* Send empty packet to mark end of file */
if (my_net_write(&mysql->net,"",0) || net_flush(&mysql->net))
{
mysql->net.last_errno=CR_SERVER_LOST;
- sprintf(mysql->net.last_error,ER(mysql->net.last_errno),socket_errno);
- my_free(tmp_name,MYF(0));
- DBUG_RETURN(-1);
+ sprintf(mysql->net.last_error,ER(mysql->net.last_errno),errno);
+ goto err;
}
if (readcount < 0)
{
mysql->net.last_errno=EE_READ; /* the errmsg for not entire file read */
- sprintf(buf,EE(mysql->net.last_errno),tmp_name,errno);
- strmake(mysql->net.last_error,buf,sizeof(mysql->net.last_error)-1);
- my_free(tmp_name,MYF(0));
- DBUG_RETURN(-1);
+ my_snprintf(mysql->net.last_error,sizeof(mysql->net.last_error)-1,
+ tmp_name,errno);
+ goto err;
}
- DBUG_RETURN(0);
+ result=0; /* Ok */
+
+err:
+ if (fd >= 0)
+ (void) my_close(fd,MYF(0));
+ my_free(buf,MYF(0));
+ DBUG_RETURN(result);
}
@@ -1856,6 +2296,9 @@ mysql_store_result(MYSQL *mysql)
MYSQL_RES *result;
DBUG_ENTER("mysql_store_result");
+ /* read from the actually used connection */
+ mysql = mysql->last_used_con;
+
if (!mysql->fields)
DBUG_RETURN(0);
if (mysql->status != MYSQL_STATUS_GET_RESULT)
@@ -1865,8 +2308,9 @@ mysql_store_result(MYSQL *mysql)
DBUG_RETURN(0);
}
mysql->status=MYSQL_STATUS_READY; /* server is ready */
- if (!(result=(MYSQL_RES*) my_malloc(sizeof(MYSQL_RES)+
- sizeof(ulong)*mysql->field_count,
+ if (!(result=(MYSQL_RES*) my_malloc((uint) (sizeof(MYSQL_RES)+
+ sizeof(ulong) *
+ mysql->field_count),
MYF(MY_WME | MY_ZEROFILL))))
{
mysql->net.last_errno=CR_OUT_OF_MEMORY;
@@ -1908,6 +2352,8 @@ mysql_use_result(MYSQL *mysql)
MYSQL_RES *result;
DBUG_ENTER("mysql_use_result");
+ mysql = mysql->last_used_con;
+
if (!mysql->fields)
DBUG_RETURN(0);
if (mysql->status != MYSQL_STATUS_GET_RESULT)
@@ -2022,7 +2468,7 @@ mysql_fetch_lengths(MYSQL_RES *res)
continue;
}
if (start) /* Found end of prev string */
- *prev_length= (uint) (*column-start-1);
+ *prev_length= (ulong) (*column-start-1);
start= *column;
prev_length=lengths;
}
@@ -2123,7 +2569,7 @@ mysql_list_fields(MYSQL *mysql, const char *table, const char *wild)
LINT_INIT(query);
end=strmake(strmake(buff, table,128)+1,wild ? wild : "",128);
- if (simple_command(mysql,COM_FIELD_LIST,buff,(uint) (end-buff),1) ||
+ if (simple_command(mysql,COM_FIELD_LIST,buff,(ulong) (end-buff),1) ||
!(query = read_rows(mysql,(MYSQL_FIELD*) 0,6)))
DBUG_RETURN(NULL);
@@ -2173,12 +2619,13 @@ mysql_list_processes(MYSQL *mysql)
}
+#ifdef USE_OLD_FUNCTIONS
int STDCALL
mysql_create_db(MYSQL *mysql, const char *db)
{
DBUG_ENTER("mysql_createdb");
DBUG_PRINT("enter",("db: %s",db));
- DBUG_RETURN(simple_command(mysql,COM_CREATE_DB,db, (uint) strlen(db),0));
+ DBUG_RETURN(simple_command(mysql,COM_CREATE_DB,db, (ulong) strlen(db),0));
}
@@ -2187,8 +2634,9 @@ mysql_drop_db(MYSQL *mysql, const char *db)
{
DBUG_ENTER("mysql_drop_db");
DBUG_PRINT("enter",("db: %s",db));
- DBUG_RETURN(simple_command(mysql,COM_DROP_DB,db,(uint) strlen(db),0));
+ DBUG_RETURN(simple_command(mysql,COM_DROP_DB,db,(ulong) strlen(db),0));
}
+#endif
int STDCALL
@@ -2369,32 +2817,32 @@ uint STDCALL mysql_field_tell(MYSQL_RES *res)
unsigned int STDCALL mysql_field_count(MYSQL *mysql)
{
- return mysql->field_count;
+ return mysql->last_used_con->field_count;
}
my_ulonglong STDCALL mysql_affected_rows(MYSQL *mysql)
{
- return (mysql)->affected_rows;
+ return mysql->last_used_con->affected_rows;
}
my_ulonglong STDCALL mysql_insert_id(MYSQL *mysql)
{
- return (mysql)->insert_id;
+ return mysql->last_used_con->insert_id;
}
uint STDCALL mysql_errno(MYSQL *mysql)
{
- return (mysql)->net.last_errno;
+ return mysql->net.last_errno;
}
char * STDCALL mysql_error(MYSQL *mysql)
{
- return (mysql)->net.last_error;
+ return mysql->net.last_error;
}
char *STDCALL mysql_info(MYSQL *mysql)
{
- return (mysql)->info;
+ return mysql->info;
}
ulong STDCALL mysql_thread_id(MYSQL *mysql)
diff --git a/libmysql/libmysql.def b/libmysql/libmysql.def
new file mode 100644
index 00000000000..9405ecd58ff
--- /dev/null
+++ b/libmysql/libmysql.def
@@ -0,0 +1,122 @@
+LIBRARY LIBMYSQL
+DESCRIPTION 'MySQL 4.0 Client Library'
+VERSION 4.0
+EXPORTS
+ mysql_affected_rows
+ mysql_close
+ mysql_connect
+ mysql_create_db
+ mysql_data_seek
+ mysql_debug
+ mysql_drop_db
+ mysql_dump_debug_info
+ mysql_eof
+ mysql_errno
+ mysql_error
+ mysql_escape_string
+ mysql_fetch_field
+ mysql_fetch_field_direct
+ mysql_fetch_fields
+ mysql_fetch_lengths
+ mysql_fetch_row
+ mysql_field_count
+ mysql_field_seek
+ mysql_field_tell
+ mysql_free_result
+ mysql_get_client_info
+ mysql_get_host_info
+ mysql_get_proto_info
+ mysql_get_server_info
+ mysql_info
+ mysql_init
+ mysql_insert_id
+ mysql_kill
+ mysql_list_dbs
+ mysql_list_fields
+ mysql_list_processes
+ mysql_list_tables
+ mysql_num_fields
+ mysql_num_rows
+ mysql_odbc_escape_string
+ mysql_options
+ mysql_ping
+ mysql_query
+ mysql_real_connect
+ mysql_real_query
+ mysql_refresh
+ mysql_row_seek
+ mysql_row_tell
+ mysql_select_db
+ mysql_shutdown
+ mysql_stat
+ mysql_store_result
+ mysql_thread_id
+ mysql_use_result
+ bmove_upp
+ delete_dynamic
+ _dig_vec
+ init_dynamic_array
+ insert_dynamic
+ int2str
+ is_prefix
+ list_add
+ list_delete
+ max_allowed_packet
+ my_casecmp
+ my_init
+ my_end
+ my_strdup
+ my_malloc
+ my_memdup
+ my_no_flags_free
+ my_realloc
+ my_thread_end
+ my_thread_init
+ net_buffer_length
+ set_dynamic
+ strcend
+ strdup_root
+ strfill
+ strinstr
+ strmake
+ strmov
+ strxmov
+ myodbc_remove_escape
+ mysql_thread_safe
+ mysql_character_set_name
+ mysql_change_user
+ mysql_send_query
+ mysql_read_query_result
+ mysql_real_escape_string
+ mysql_ssl_set
+ mysql_ssl_clear
+ mysql_real_connect
+ mysql_master_query
+ mysql_master_send_query
+ mysql_slave_query
+ mysql_slave_send_query
+ mysql_enable_rpl_parse
+ mysql_disable_rpl_parse
+ mysql_rpl_parse_enabled
+ mysql_enable_reads_from_master
+ mysql_disable_reads_from_master
+ mysql_reads_from_master_enabled
+ mysql_rpl_query_type
+ mysql_rpl_probe
+ mysql_set_master
+ mysql_add_slave
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/libmysql/manager.c b/libmysql/manager.c
new file mode 100644
index 00000000000..fbf0a0b2c22
--- /dev/null
+++ b/libmysql/manager.c
@@ -0,0 +1,273 @@
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <my_global.h>
+#if defined(THREAD)
+#include <my_pthread.h> /* because of signal() */
+#endif
+#include "mysql.h"
+#include "mysql_version.h"
+#include "mysqld_error.h"
+#include <my_sys.h>
+#include <mysys_err.h>
+#include <m_string.h>
+#include <m_ctype.h>
+#include <my_net.h>
+#include <errmsg.h>
+#include <violite.h>
+#include <sys/stat.h>
+#include <signal.h>
+#include <errno.h>
+
+#if defined(OS2)
+# include <sys/un.h>
+#elif !defined( __WIN__)
+#include <sys/resource.h>
+#ifdef HAVE_SYS_UN_H
+# include <sys/un.h>
+#endif
+#include <netdb.h>
+#ifdef HAVE_SELECT_H
+# include <select.h>
+#endif
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+#include <sys/utsname.h>
+#endif /* __WIN__ */
+
+#ifndef INADDR_NONE
+#define INADDR_NONE -1
+#endif
+
+#define RES_BUF_SHIFT 5
+#ifndef __WIN__
+#define SOCKET_ERROR -1
+#endif
+#define NET_BUF_SIZE 2048
+
+MYSQL_MANAGER* STDCALL mysql_manager_init(MYSQL_MANAGER* con)
+{
+ int net_buf_size=NET_BUF_SIZE;
+ if (!con)
+ {
+ if (!(con=(MYSQL_MANAGER*)my_malloc(sizeof(*con)+net_buf_size,
+ MYF(MY_WME|MY_ZEROFILL))))
+ return 0;
+ con->free_me=1;
+ con->net_buf=(char*)con+sizeof(*con);
+ }
+ else
+ {
+ bzero((char*)con,sizeof(*con));
+ if (!(con->net_buf=my_malloc(net_buf_size,MYF(0))))
+ return 0;
+ }
+ con->net_buf_pos=con->net_data_end=con->net_buf;
+ con->net_buf_size=net_buf_size;
+ return con;
+}
+
+MYSQL_MANAGER* STDCALL mysql_manager_connect(MYSQL_MANAGER* con,
+ const char* host,
+ const char* user,
+ const char* passwd,
+ unsigned int port)
+{
+ my_socket sock;
+ struct sockaddr_in sock_addr;
+ uint32 ip_addr;
+ char msg_buf[MAX_MYSQL_MANAGER_MSG];
+ int msg_len;
+ Vio* vio;
+
+ if (!host)
+ host="localhost";
+ if (!user)
+ user="root";
+ if (!passwd)
+ passwd="";
+
+ if ((sock=(my_socket)socket(AF_INET,SOCK_STREAM,0)) == SOCKET_ERROR)
+ {
+ con->last_errno=errno;
+ strmov(con->last_error,"Cannot create socket");
+ goto err;
+ }
+ if (!(vio=vio_new(sock,VIO_TYPE_TCPIP,FALSE)))
+ {
+ con->last_errno=ENOMEM;
+ strmov(con->last_error,"Cannot create network I/O object");
+ goto err;
+ }
+ vio_blocking(vio,TRUE);
+ my_net_init(&con->net,vio);
+ bzero((char*) &sock_addr,sizeof(sock_addr));
+ sock_addr.sin_family = AF_INET;
+ if ((int) (ip_addr = inet_addr(host)) != (int) INADDR_NONE)
+ {
+ memcpy_fixed(&sock_addr.sin_addr,&ip_addr,sizeof(ip_addr));
+ }
+ else
+#if defined(HAVE_GETHOSTBYNAME_R) && defined(_REENTRANT) && defined(THREAD)
+ {
+ int tmp_errno;
+ struct hostent tmp_hostent,*hp;
+ char buff2[GETHOSTBYNAME_BUFF_SIZE];
+ hp = my_gethostbyname_r(host,&tmp_hostent,buff2,sizeof(buff2),
+ &tmp_errno);
+ if (!hp)
+ {
+ con->last_errno=tmp_errno;
+ sprintf(con->last_error,"Could not resolve host '%s'",host);
+ goto err;
+ }
+ memcpy(&sock_addr.sin_addr,hp->h_addr, (size_t) hp->h_length);
+ }
+#else
+ {
+ struct hostent *hp;
+ if (!(hp=gethostbyname(host)))
+ {
+ con->last_errno=socket_errno;
+ sprintf(con->last_error, "Could not resolve host '%s'", host);
+ goto err;
+ }
+ memcpy(&sock_addr.sin_addr,hp->h_addr, (size_t) hp->h_length);
+ }
+#endif
+ sock_addr.sin_port = (ushort) htons((ushort) port);
+ if (my_connect(sock,(struct sockaddr *) &sock_addr, sizeof(sock_addr),
+ 0) <0)
+ {
+ con->last_errno=errno;
+ sprintf(con->last_error ,"Could not connect to %-.64s", host);
+ goto err;
+ }
+ /* read the greating */
+ if (my_net_read(&con->net) == packet_error)
+ {
+ con->last_errno=errno;
+ strmov(con->last_error,"Read error on socket");
+ goto err;
+ }
+ sprintf(msg_buf,"%-.16s %-.16s\n",user,passwd);
+ msg_len=strlen(msg_buf);
+ if (my_net_write(&con->net,msg_buf,msg_len) || net_flush(&con->net))
+ {
+ con->last_errno=con->net.last_errno;
+ strmov(con->last_error,"Write error on socket");
+ goto err;
+ }
+ if (my_net_read(&con->net) == packet_error)
+ {
+ con->last_errno=errno;
+ strmov(con->last_error,"Read error on socket");
+ goto err;
+ }
+ if ((con->cmd_status=atoi((char*) con->net.read_pos)) != MANAGER_OK)
+ {
+ strmov(con->last_error,"Access denied");
+ goto err;
+ }
+ if (!my_multi_malloc(MYF(0), &con->host, (uint)strlen(host)+1,
+ &con->user, (uint)strlen(user)+1,
+ &con->passwd, (uint)strlen(passwd)+1,
+ NullS))
+ {
+ con->last_errno=ENOMEM;
+ strmov(con->last_error,"Out of memory");
+ goto err;
+ }
+ strmov(con->host,host);
+ strmov(con->user,user);
+ strmov(con->passwd,passwd);
+ return con;
+err:
+ {
+ my_bool free_me=con->free_me;
+ con->free_me=0;
+ mysql_manager_close(con);
+ con->free_me=free_me;
+ }
+ return 0;
+}
+
+void STDCALL mysql_manager_close(MYSQL_MANAGER* con)
+{
+ my_free((gptr)con->host,MYF(MY_ALLOW_ZERO_PTR));
+ /* no need to free con->user and con->passwd, because they were
+ allocated in my_multimalloc() along with con->host, freeing
+ con->hosts frees the whole block
+ */
+ net_end(&con->net);
+ if (con->free_me)
+ my_free((gptr)con,MYF(0));
+}
+
+int STDCALL mysql_manager_command(MYSQL_MANAGER* con,const char* cmd,
+ int cmd_len)
+{
+ if (!cmd_len)
+ cmd_len=strlen(cmd);
+ if (my_net_write(&con->net,(char*)cmd,cmd_len) || net_flush(&con->net))
+ {
+ con->last_errno=errno;
+ strmov(con->last_error,"Write error on socket");
+ return 1;
+ }
+ con->eof=0;
+ return 0;
+}
+
+int STDCALL mysql_manager_fetch_line(MYSQL_MANAGER* con, char* res_buf,
+ int res_buf_size)
+{
+ char* res_buf_end=res_buf+res_buf_size;
+ char* net_buf=(char*) con->net.read_pos, *net_buf_end;
+ int res_buf_shift=RES_BUF_SHIFT;
+ uint num_bytes;
+
+ if (res_buf_size<RES_BUF_SHIFT)
+ {
+ con->last_errno=ENOMEM;
+ strmov(con->last_error,"Result buffer too small");
+ return 1;
+ }
+
+ if ((num_bytes=my_net_read(&con->net)) == packet_error)
+ {
+ con->last_errno=errno;
+ strmov(con->last_error,"socket read failed");
+ return 1;
+ }
+
+ net_buf_end=net_buf+num_bytes;
+
+ if ((con->eof=(net_buf[3]==' ')))
+ res_buf_shift--;
+ net_buf+=res_buf_shift;
+ res_buf_end[-1]=0;
+ for (;net_buf<net_buf_end && res_buf < res_buf_end;res_buf++,net_buf++)
+ {
+ if((*res_buf=*net_buf) == '\r')
+ {
+ *res_buf=0;
+ break;
+ }
+ }
+ return 0;
+}
diff --git a/libmysql/net.c b/libmysql/net.c
index 24e4da3561a..666c572ccee 100644
--- a/libmysql/net.c
+++ b/libmysql/net.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/* Write and read of logical packets to/from socket
** Writes are cached into net_buffer_length big packets.
@@ -22,19 +21,34 @@
** 3 byte length & 1 byte package-number.
*/
+#ifdef EMBEDDED_LIBRARY
+#define net_read_timeout net_read_timeout1
+#define net_write_timeout net_write_timeout1
+#endif
+
#ifdef __WIN__
#include <winsock.h>
#endif
-#include <global.h>
-#include <violite.h>
+#include <my_global.h>
+#include <mysql.h>
+#include <mysql_embed.h>
+#include <mysql_com.h>
+#include <mysqld_error.h>
#include <my_sys.h>
#include <m_string.h>
-#include "mysql.h"
-#include "mysqld_error.h"
+#include <my_net.h>
+#include <violite.h>
#include <signal.h>
#include <errno.h>
-#include <sys/types.h>
-#include <violite.h>
+
+/*
+ The following handles the differences when this is linked between the
+ client and the server.
+
+ This gives an error if a too big packet is found
+ The server can change this with the -O switch, but because the client
+ can't normally do this the client should have a bigger max_allowed_packet.
+*/
#ifdef MYSQL_SERVER
ulong max_allowed_packet=65536;
@@ -45,73 +59,45 @@ ulong max_allowed_packet=16*1024*1024L;
ulong net_read_timeout= NET_READ_TIMEOUT;
ulong net_write_timeout= NET_WRITE_TIMEOUT;
#endif
-ulong net_buffer_length=8192; /* Default length. Enlarged if necessary */
-#if !defined(__WIN__) && !defined(MSDOS)
-#include <sys/socket.h>
-#else
-#undef MYSQL_SERVER /* Win32 can't handle interrupts */
-#endif
-#if !defined(MSDOS) && !defined(__WIN__) && !defined(HAVE_BROKEN_NETINET_INCLUDES) && !defined(__BEOS__)
-#include <netinet/in_systm.h>
-#include <netinet/in.h>
-#include <netinet/ip.h>
-#if !defined(alpha_linux_port)
-#include <netinet/tcp.h>
-#endif
+#ifdef __WIN__
+/* The following is because alarms doesn't work on windows. */
+#undef MYSQL_SERVER
#endif
-#include "mysqld_error.h"
+
#ifdef MYSQL_SERVER
#include "my_pthread.h"
-#include "thr_alarm.h"
void sql_print_error(const char *format,...);
#define RETRY_COUNT mysqld_net_retry_count
extern ulong mysqld_net_retry_count;
-#else
-
-#ifdef OS2 /* avoid name conflict */
-#define thr_alarm_t thr_alarm_t_net
-#define ALARM ALARM_net
-#endif
-
-typedef my_bool thr_alarm_t;
-typedef my_bool ALARM;
-#define thr_alarm_init(A) (*(A))=0
-#define thr_alarm_in_use(A) (*(A)!= 0)
-#define thr_end_alarm(A)
-#define thr_alarm(A,B,C) local_thr_alarm((A),(B),(C))
-inline int local_thr_alarm(my_bool *A,int B __attribute__((unused)),ALARM *C __attribute__((unused)))
-{
- *A=1;
- return 0;
-}
-#define thr_got_alarm(A) 0
-#define RETRY_COUNT 1
-#endif
-
-#ifdef MYSQL_SERVER
-extern ulong bytes_sent, bytes_received;
+extern ulong bytes_sent, bytes_received;
extern pthread_mutex_t LOCK_bytes_sent , LOCK_bytes_received;
+
+extern void query_cache_insert(NET *net, const char *packet, ulong length);
#else
#undef statistic_add
#define statistic_add(A,B,C)
-#endif
+#define DONT_USE_THR_ALARM
+#define RETRY_COUNT 1
+#endif /* MYSQL_SERVER */
-/*
-** Give error if a too big packet is found
-** The server can change this with the -O switch, but because the client
-** can't normally do this the client should have a bigger max-buffer.
-*/
+#include "thr_alarm.h"
#define TEST_BLOCKING 8
-static int net_write_buff(NET *net,const char *packet,uint len);
+#define MAX_THREE_BYTES 255L*255L*255L
+
+ulong net_buffer_length=8192; /* Default length. Enlarged if necessary */
+
+static int net_write_buff(NET *net,const char *packet,ulong len);
/* Init with packet info */
int my_net_init(NET *net, Vio* vio)
{
- if (!(net->buff=(uchar*) my_malloc(net_buffer_length,MYF(MY_WME))))
+ if (!(net->buff=(uchar*) my_malloc((uint32) net_buffer_length+
+ NET_HEADER_SIZE + COMP_HEADER_SIZE,
+ MYF(MY_WME))))
return 1;
if (net_buffer_length > max_allowed_packet)
max_allowed_packet=net_buffer_length;
@@ -120,12 +106,13 @@ int my_net_init(NET *net, Vio* vio)
net->no_send_ok = 0;
net->error=0; net->return_errno=0; net->return_status=0;
net->timeout=(uint) net_read_timeout; /* Timeout for read */
- net->pkt_nr=0;
+ net->pkt_nr=net->compress_pkt_nr=0;
net->write_pos=net->read_pos = net->buff;
net->last_error[0]=0;
net->compress=0; net->reading_or_writing=0;
net->where_b = net->remain_in_buf=0;
net->last_errno=0;
+ net->query_cache_query=0;
if (vio != 0) /* If real connection */
{
@@ -158,8 +145,12 @@ static my_bool net_realloc(NET *net, ulong length)
net->last_errno=ER_NET_PACKET_TOO_LARGE;
return 1;
}
- pkt_length = (length+IO_SIZE-1) & ~(IO_SIZE-1);
- if (!(buff=(uchar*) my_realloc((char*) net->buff, pkt_length, MYF(MY_WME))))
+ pkt_length = (length+IO_SIZE-1) & ~(IO_SIZE-1);
+ /* We must allocate some extra bytes for the end 0 and to be able to
+ read big compressed blocks */
+ if (!(buff=(uchar*) my_realloc((char*) net->buff, (uint32) pkt_length +
+ NET_HEADER_SIZE + COMP_HEADER_SIZE,
+ MYF(MY_WME))))
{
net->error=1;
#ifdef MYSQL_SERVER
@@ -177,21 +168,21 @@ static my_bool net_realloc(NET *net, ulong length)
void net_clear(NET *net)
{
#ifndef EXTRA_DEBUG
- int count;
+ int count; /* One may get 'unused' warn */
bool is_blocking=vio_is_blocking(net->vio);
if (is_blocking)
vio_blocking(net->vio, FALSE);
if (!vio_is_blocking(net->vio)) /* Safety if SSL */
{
while ( (count = vio_read(net->vio, (char*) (net->buff),
- net->max_packet)) > 0)
+ (uint32) net->max_packet)) > 0)
DBUG_PRINT("info",("skipped %d bytes from file: %s",
count,vio_description(net->vio)));
if (is_blocking)
vio_blocking(net->vio, TRUE);
}
#endif /* EXTRA_DEBUG */
- net->pkt_nr=0; /* Ready for new command */
+ net->pkt_nr=net->compress_pkt_nr=0; /* Ready for new command */
net->write_pos=net->buff;
}
@@ -204,9 +195,12 @@ int net_flush(NET *net)
if (net->buff != net->write_pos)
{
error=net_real_write(net,(char*) net->buff,
- (uint) (net->write_pos - net->buff));
+ (ulong) (net->write_pos - net->buff));
net->write_pos=net->buff;
}
+ /* Sync packet number if using compression */
+ if (net->compress)
+ net->pkt_nr=net->compress_pkt_nr;
DBUG_RETURN(error);
}
@@ -215,44 +209,91 @@ int net_flush(NET *net)
** Write something to server/client buffer
*****************************************************************************/
-
/*
** Write a logical packet with packet header
** Format: Packet length (3 bytes), packet number(1 byte)
** When compression is used a 3 byte compression length is added
-** NOTE: If compression is used the original package is destroyed!
+** NOTE: If compression is used the original package is modified!
*/
int
my_net_write(NET *net,const char *packet,ulong len)
{
uchar buff[NET_HEADER_SIZE];
+ /*
+ Big packets are handled by splitting them in packets of MAX_THREE_BYTES
+ length. The last packet is always a packet that is < MAX_THREE_BYTES.
+ (The last packet may even have a lengt of 0)
+ */
+ while (len >= MAX_THREE_BYTES)
+ {
+ const ulong z_size = MAX_THREE_BYTES;
+ int3store(buff, z_size);
+ buff[3]= (uchar) net->pkt_nr++;
+ if (net_write_buff(net, (char*) buff, NET_HEADER_SIZE) ||
+ net_write_buff(net, packet, z_size))
+ return 1;
+ packet += z_size;
+ len-= z_size;
+ }
+ /* Write last packet */
int3store(buff,len);
- buff[3]= (net->compress) ? 0 : (uchar) (net->pkt_nr++);
+ buff[3]= (uchar) net->pkt_nr++;
if (net_write_buff(net,(char*) buff,NET_HEADER_SIZE))
return 1;
return net_write_buff(net,packet,len);
}
+/*
+ Send a command to the server.
+ As the command is part of the first data packet, we have to do some data
+ juggling to put the command in there, without having to create a new
+ packet.
+ This function will split big packets into sub-packets if needed.
+ (Each sub packet can only be 2^24 bytes)
+*/
+
int
net_write_command(NET *net,uchar command,const char *packet,ulong len)
{
+ ulong length=len+1; /* 1 extra byte for command */
uchar buff[NET_HEADER_SIZE+1];
- uint length=len+1; /* 1 extra byte for command */
+ uint header_size=NET_HEADER_SIZE+1;
+ buff[4]=command; /* For first packet */
+ if (length >= MAX_THREE_BYTES)
+ {
+ /* Take into account that we have the command in the first header */
+ len= MAX_THREE_BYTES -1;
+ do
+ {
+ int3store(buff, MAX_THREE_BYTES);
+ buff[3]= (uchar) net->pkt_nr++;
+ if (net_write_buff(net,(char*) buff, header_size) ||
+ net_write_buff(net,packet,len))
+ return 1;
+ packet+= len;
+ length-= MAX_THREE_BYTES;
+ len=MAX_THREE_BYTES;
+ header_size=NET_HEADER_SIZE;
+ } while (length >= MAX_THREE_BYTES);
+ len=length; /* Data left to be written */
+ }
int3store(buff,length);
- buff[3]= (net->compress) ? 0 : (uchar) (net->pkt_nr++);
- buff[4]=command;
- if (net_write_buff(net,(char*) buff,5))
- return 1;
- return test(net_write_buff(net,packet,len) || net_flush(net));
+ buff[3]= (uchar) net->pkt_nr++;
+ return test(net_write_buff(net,(char*) buff,header_size) ||
+ net_write_buff(net,packet,len) || net_flush(net));
}
+/*
+ Caching the data in a local buffer before sending it.
+ One can force the buffer to be flushed with 'net_flush'.
+*/
static int
-net_write_buff(NET *net,const char *packet,uint len)
+net_write_buff(NET *net,const char *packet,ulong len)
{
- uint left_length=(uint) (net->buff_end - net->write_pos);
+ ulong left_length=(ulong) (net->buff_end - net->write_pos);
while (len > left_length)
{
@@ -269,21 +310,29 @@ net_write_buff(NET *net,const char *packet,uint len)
return 0;
}
-/* Read and write using timeouts */
+
+/*
+ Read and write one packet using timeouts.
+ If needed, the packet is compressed before sending.
+*/
int
net_real_write(NET *net,const char *packet,ulong len)
{
- int length;
+ long int length;
char *pos,*end;
thr_alarm_t alarmed;
-#if !defined(__WIN__) && !defined(__EMX__) && !defined(OS2)
+#if defined(MYSQL_SERVER)
ALARM alarm_buff;
#endif
uint retry_count=0;
my_bool net_blocking = vio_is_blocking(net->vio);
DBUG_ENTER("net_real_write");
+#ifdef MYSQL_SERVER
+ query_cache_insert(net, packet, len);
+#endif
+
if (net->error == 2)
DBUG_RETURN(-1); /* socket can't be used */
@@ -294,8 +343,8 @@ net_real_write(NET *net,const char *packet,ulong len)
ulong complen;
uchar *b;
uint header_length=NET_HEADER_SIZE+COMP_HEADER_SIZE;
- if (!(b=(uchar*) my_malloc(len + NET_HEADER_SIZE + COMP_HEADER_SIZE,
- MYF(MY_WME))))
+ if (!(b=(uchar*) my_malloc((uint32) len + NET_HEADER_SIZE +
+ COMP_HEADER_SIZE, MYF(MY_WME))))
{
#ifdef MYSQL_SERVER
net->last_errno=ER_OUT_OF_RESOURCES;
@@ -314,7 +363,7 @@ net_real_write(NET *net,const char *packet,ulong len)
}
int3store(&b[NET_HEADER_SIZE],complen);
int3store(b,len);
- b[3]=(uchar) (net->pkt_nr++);
+ b[3]=(uchar) (net->compress_pkt_nr++);
len+= header_length;
packet= (char*) b;
}
@@ -332,7 +381,7 @@ net_real_write(NET *net,const char *packet,ulong len)
pos=(char*) packet; end=pos+len;
while (pos != end)
{
- if ((int) (length=vio_write(net->vio,pos,(int) (end-pos))) <= 0)
+ if ((long) (length=vio_write(net->vio,pos,(uint32) (end-pos))) <= 0)
{
my_bool interrupted = vio_should_retry(net->vio);
#if (!defined(__WIN__) && !defined(__EMX__) && !defined(OS2))
@@ -416,7 +465,7 @@ net_real_write(NET *net,const char *packet,ulong len)
big packet
*/
-static void my_net_skip_rest(NET *net, ulong remain, thr_alarm_t *alarmed)
+static void my_net_skip_rest(NET *net, uint32 remain, thr_alarm_t *alarmed)
{
ALARM alarm_buff;
uint retry_count=0;
@@ -432,21 +481,27 @@ static void my_net_skip_rest(NET *net, ulong remain, thr_alarm_t *alarmed)
if ((int) (length=vio_read(net->vio,(char*) net->buff,remain)) <= 0L)
{
my_bool interrupted = vio_should_retry(net->vio);
- if (!thr_got_alarm(alarmed) && interrupted)
+ if (!thr_got_alarm(&alarmed) && interrupted)
{ /* Probably in MIT threads */
if (retry_count++ < RETRY_COUNT)
continue;
}
return;
}
- remain -=(ulong) length;
- statistic_add(bytes_received,(ulong) length,&LOCK_bytes_received);
+ remain -= (uint32) length;
+ statistic_add(bytes_received,length,&LOCK_bytes_received);
}
}
#endif /* MYSQL_SERVER */
-static uint
+/*
+ Reads one packet to net->buff + net->where_b
+ Returns length of packet. Long packets are handled by my_net_read().
+ This function reallocates the net->buff buffer if necessary.
+*/
+
+static ulong
my_real_read(NET *net, ulong *complen)
{
uchar *pos;
@@ -454,12 +509,12 @@ my_real_read(NET *net, ulong *complen)
uint i,retry_count=0;
ulong len=packet_error;
thr_alarm_t alarmed;
-#if (!defined(__WIN__) && !defined(__EMX__) && !defined(OS2)) || defined(MYSQL_SERVER)
+#if defined(MYSQL_SERVER)
ALARM alarm_buff;
#endif
my_bool net_blocking=vio_is_blocking(net->vio);
- ulong remain= (net->compress ? NET_HEADER_SIZE+COMP_HEADER_SIZE :
- NET_HEADER_SIZE);
+ uint32 remain= (net->compress ? NET_HEADER_SIZE+COMP_HEADER_SIZE :
+ NET_HEADER_SIZE);
*complen = 0;
net->reading_or_writing=1;
@@ -536,7 +591,7 @@ my_real_read(NET *net, ulong *complen)
continue;
}
#endif
- DBUG_PRINT("error",("Couldn't read packet: remain: %d errno: %d length: %d alarmed: %d", remain,vio_errno(net->vio),length,alarmed));
+ DBUG_PRINT("error",("Couldn't read packet: remain: %lu errno: %d length: %ld alarmed: %d", remain,vio_errno(net->vio),length,alarmed));
len= packet_error;
net->error=2; /* Close socket */
#ifdef MYSQL_SERVER
@@ -545,7 +600,7 @@ my_real_read(NET *net, ulong *complen)
#endif
goto end;
}
- remain -= (ulong) length;
+ remain -= (uint32) length;
pos+= (ulong) length;
statistic_add(bytes_received,(ulong) length,&LOCK_bytes_received);
}
@@ -557,9 +612,9 @@ my_real_read(NET *net, ulong *complen)
if (net->buff[net->where_b] != (uchar) 255)
{
DBUG_PRINT("error",
- ("Packets out of order (Found: %d, expected %d)",
+ ("Packets out of order (Found: %d, expected %u)",
(int) net->buff[net->where_b + 3],
- (uint) (uchar) net->pkt_nr));
+ net->pkt_nr));
#ifdef EXTRA_DEBUG
fprintf(stderr,"Packets out of order (Found: %d, expected %d)\n",
(int) net->buff[net->where_b + 3],
@@ -572,7 +627,7 @@ my_real_read(NET *net, ulong *complen)
#endif
goto end;
}
- net->pkt_nr++;
+ net->compress_pkt_nr= ++net->pkt_nr;
#ifdef HAVE_COMPRESS
if (net->compress)
{
@@ -582,23 +637,24 @@ my_real_read(NET *net, ulong *complen)
#endif
len=uint3korr(net->buff+net->where_b);
+ if (!len) /* End of big multi-packet */
+ goto end;
helping = max(len,*complen) + net->where_b;
/* The necessary size of net->buff */
if (helping >= net->max_packet)
{
- /* We must allocate one extra byte for the end null */
- if (net_realloc(net,helping+1))
+ if (net_realloc(net,helping))
{
#ifdef MYSQL_SERVER
if (i == 1)
- my_net_skip_rest(net, len, &alarmed);
+ my_net_skip_rest(net, (uint32) len, &alarmed);
#endif
len= packet_error; /* Return error */
goto end;
}
}
pos=net->buff + net->where_b;
- remain = len;
+ remain = (uint32) len;
}
}
@@ -612,7 +668,21 @@ end:
return(len);
}
-uint
+
+/*
+ Read a packet from the client/server and return it without the internal
+ package header.
+ If the packet is the first packet of a multi-packet packet
+ (which is indicated by the length of the packet = 0xffffff) then
+ all sub packets are read and concatenated.
+ If the packet was compressed, its uncompressed and the length of the
+ uncompressed packet is returned.
+
+ The function returns the length of the found packet or packet_error.
+ net->read_pos points to the read data.
+*/
+
+ulong
my_net_read(NET *net)
{
ulong len,complen;
@@ -621,65 +691,126 @@ my_net_read(NET *net)
if (!net->compress)
{
#endif
- len = my_real_read (net,&complen);
+ len = my_real_read(net,&complen);
+ if (len == MAX_THREE_BYTES)
+ {
+ /* First packet of a multi-packet. Concatenate the packets */
+ ulong save_pos = net->where_b;
+ ulong total_length=0;
+ do
+ {
+ net->where_b += len;
+ total_length += len;
+ len = my_real_read (net,&complen);
+ } while (len == MAX_THREE_BYTES);
+ if (len != packet_error)
+ len+= total_length;
+ net->where_b = save_pos;
+ }
net->read_pos = net->buff + net->where_b;
if (len != packet_error)
net->read_pos[len]=0; /* Safeguard for mysql_use_result */
return len;
#ifdef HAVE_COMPRESS
}
- if (net->remain_in_buf)
- net->buff[net->buf_length - net->remain_in_buf]=net->save_char;
- for (;;)
+ else
{
+ /* We are using the compressed protocol */
+
+ ulong buf_length= net->buf_length;
+ ulong start_of_packet= net->buf_length - net->remain_in_buf;
+ ulong first_packet_offset=start_of_packet;
+ uint read_length, multi_byte_packet=0;
+
if (net->remain_in_buf)
{
- uchar *pos = net->buff + net->buf_length - net->remain_in_buf;
- if (net->remain_in_buf >= 4)
+ /* Restore the character that was overwritten by the end 0 */
+ net->buff[start_of_packet]=net->save_char;
+ }
+ else
+ {
+ /* reuse buffer, as there is noting in it that we need */
+ buf_length=start_of_packet=first_packet_offset=0;
+ }
+ for (;;)
+ {
+ ulong packet_len;
+
+ if (buf_length - start_of_packet >= NET_HEADER_SIZE)
{
- net->length = uint3korr(pos);
- if (net->length <= net->remain_in_buf - 4)
+ read_length = uint3korr(net->buff+start_of_packet);
+ if (!read_length)
+ {
+ /* End of multi-byte packet */
+ start_of_packet += NET_HEADER_SIZE;
+ break;
+ }
+ if (read_length + NET_HEADER_SIZE <= buf_length - start_of_packet)
{
- /* We have a full packet */
- len=net->length;
- net->remain_in_buf -= net->length + 4;
- net->read_pos=pos + 4;
- break; /* We have a full packet */
+ if (multi_byte_packet)
+ {
+ /* Remove packet header for second packet */
+ memmove(net->buff + first_packet_offset + start_of_packet,
+ net->buff + first_packet_offset + start_of_packet +
+ NET_HEADER_SIZE,
+ buf_length - start_of_packet);
+ start_of_packet += read_length;
+ buf_length -= NET_HEADER_SIZE;
+ }
+ else
+ start_of_packet+= read_length + NET_HEADER_SIZE;
+
+ if (read_length != MAX_THREE_BYTES) /* last package */
+ {
+ multi_byte_packet= 0; /* No last zero len packet */
+ break;
+ }
+ multi_byte_packet= NET_HEADER_SIZE;
+ /* Move data down to read next data packet after current one */
+ if (first_packet_offset)
+ {
+ memmove(net->buff,net->buff+first_packet_offset,
+ buf_length-first_packet_offset);
+ buf_length-=first_packet_offset;
+ start_of_packet -= first_packet_offset;
+ first_packet_offset=0;
+ }
+ continue;
}
}
/* Move data down to read next data packet after current one */
- if (net->buf_length != net->remain_in_buf)
+ if (first_packet_offset)
{
- memmove(net->buff,pos,net->remain_in_buf);
- net->buf_length=net->remain_in_buf;
+ memmove(net->buff,net->buff+first_packet_offset,
+ buf_length-first_packet_offset);
+ buf_length-=first_packet_offset;
+ start_of_packet -= first_packet_offset;
+ first_packet_offset=0;
}
- net->where_b=net->buf_length;
- }
- else
- {
- net->where_b=0;
- net->buf_length=0;
- }
- if ((len = my_real_read(net,&complen)) == packet_error)
- break;
- if (my_uncompress((byte*) net->buff + net->where_b, &len, &complen))
- {
- len= packet_error;
- net->error=2; /* caller will close socket */
+ net->where_b=buf_length;
+ if ((packet_len = my_real_read(net,&complen)) == packet_error)
+ return packet_error;
+ if (my_uncompress((byte*) net->buff + net->where_b, &packet_len,
+ &complen))
+ {
+ net->error=2; /* caller will close socket */
#ifdef MYSQL_SERVER
- net->last_errno=ER_NET_UNCOMPRESS_ERROR;
+ net->last_errno=ER_NET_UNCOMPRESS_ERROR;
#endif
- break;
+ return packet_error;
+ }
+ buf_length+=packet_len;
}
- net->buf_length+=len;
- net->remain_in_buf+=len;
- }
- if (len != packet_error)
- {
+
+ net->read_pos= net->buff+ first_packet_offset + NET_HEADER_SIZE;
+ net->buf_length= buf_length;
+ net->remain_in_buf= (ulong) (buf_length - start_of_packet);
+ len = ((ulong) (start_of_packet - first_packet_offset) - NET_HEADER_SIZE -
+ multi_byte_packet);
net->save_char= net->read_pos[len]; /* Must be saved */
net->read_pos[len]=0; /* Safeguard for mysql_use_result */
}
+#endif /* HAVE_COMPRESS */
return len;
-#endif
}
diff --git a/libmysql/password.c b/libmysql/password.c
index 0fd5861873a..9b154603b98 100644
--- a/libmysql/password.c
+++ b/libmysql/password.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/* password checking routines */
/*****************************************************************************
@@ -35,7 +34,7 @@
This saves a hashed number as a string in the password field.
*****************************************************************************/
-#include <global.h>
+#include <my_global.h>
#include <my_sys.h>
#include <m_string.h>
#include "mysql.h"
diff --git a/libmysql/violite.c b/libmysql/violite.c
deleted file mode 100644
index 37fee6fad3d..00000000000
--- a/libmysql/violite.c
+++ /dev/null
@@ -1,443 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
-
-/*
- Note that we can't have assertion on file descriptors; The reason for
- this is that during mysql shutdown, another thread can close a file
- we are working on. In this case we should just return read errors from
- the file descriptior.
-*/
-
-#include <global.h>
-
-#ifndef HAVE_VIO /* is Vio suppored by the Vio lib ? */
-
-#include <errno.h>
-#include <assert.h>
-#include <violite.h>
-#include <my_sys.h>
-#include <my_net.h>
-#include <m_string.h>
-#ifdef HAVE_POLL
-#include <sys/poll.h>
-#endif
-#ifdef HAVE_SYS_IOCTL_H
-#include <sys/ioctl.h>
-#endif
-#ifdef HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
-
-#if !defined(MSDOS) && !defined(__WIN__) && !defined(HAVE_BROKEN_NETINET_INCLUDES) && !defined(__BEOS__) && !defined(__FreeBSD__)
-#include <netinet/in_systm.h>
-#include <netinet/ip.h>
-#if !defined(alpha_linux_port)
-#include <netinet/tcp.h>
-#endif
-#endif
-
-#if defined(__EMX__) || defined(OS2)
-#define ioctlsocket ioctl
-#endif /* defined(__EMX__) */
-
-#if defined(MSDOS) || defined(__WIN__)
-#define O_NONBLOCK 1 /* For emulation of fcntl() */
-#endif
-#ifndef EWOULDBLOCK
-#define SOCKET_EWOULDBLOCK SOCKET_EAGAIN
-#endif
-
-#ifndef __WIN__
-#define HANDLE void *
-#endif
-
-struct st_vio
-{
- my_socket sd; /* my_socket - real or imaginary */
- HANDLE hPipe;
- my_bool localhost; /* Are we from localhost? */
- int fcntl_mode; /* Buffered fcntl(sd,F_GETFL) */
- struct sockaddr_in local; /* Local internet address */
- struct sockaddr_in remote; /* Remote internet address */
- enum enum_vio_type type; /* Type of connection */
- char desc[30]; /* String description */
-};
-
-typedef void *vio_ptr;
-typedef char *vio_cstring;
-
-/*
- * Helper to fill most of the Vio* with defaults.
- */
-
-static void vio_reset(Vio* vio, enum enum_vio_type type,
- my_socket sd, HANDLE hPipe,
- my_bool localhost)
-{
- bzero((char*) vio, sizeof(*vio));
- vio->type = type;
- vio->sd = sd;
- vio->hPipe = hPipe;
- vio->localhost= localhost;
-}
-
-/* Open the socket or TCP/IP connection and read the fnctl() status */
-
-Vio *vio_new(my_socket sd, enum enum_vio_type type, my_bool localhost)
-{
- Vio *vio;
- DBUG_ENTER("vio_new");
- DBUG_PRINT("enter", ("sd=%d", sd));
- if ((vio = (Vio*) my_malloc(sizeof(*vio),MYF(MY_WME))))
- {
- vio_reset(vio, type, sd, 0, localhost);
- sprintf(vio->desc,
- (vio->type == VIO_TYPE_SOCKET ? "socket (%d)" : "TCP/IP (%d)"),
- vio->sd);
-#if !defined(___WIN__) && !defined(__EMX__) && !defined(OS2)
-#if !defined(NO_FCNTL_NONBLOCK)
- vio->fcntl_mode = fcntl(sd, F_GETFL);
-#elif defined(HAVE_SYS_IOCTL_H) /* hpux */
- /* Non blocking sockets doesn't work good on HPUX 11.0 */
- (void) ioctl(sd,FIOSNBIO,0);
-#endif
-#else /* !defined(__WIN__) && !defined(__EMX__) */
- {
- /* set to blocking mode by default */
- ulong arg=0, r;
- r = ioctlsocket(vio->sd,FIONBIO,(void*) &arg, sizeof(arg));
- }
-#endif
- }
- DBUG_RETURN(vio);
-}
-
-
-#ifdef __WIN__
-
-Vio *vio_new_win32pipe(HANDLE hPipe)
-{
- Vio *vio;
- DBUG_ENTER("vio_new_handle");
- if ((vio = (Vio*) my_malloc(sizeof(Vio),MYF(MY_WME))))
- {
- vio_reset(vio, VIO_TYPE_NAMEDPIPE, 0, hPipe, TRUE);
- strmov(vio->desc, "named pipe");
- }
- DBUG_RETURN(vio);
-}
-
-#endif
-
-void vio_delete(Vio * vio)
-{
- /* It must be safe to delete null pointers. */
- /* This matches the semantics of C++'s delete operator. */
- if (vio)
- {
- if (vio->type != VIO_CLOSED)
- vio_close(vio);
- my_free((gptr) vio,MYF(0));
- }
-}
-
-int vio_errno(Vio *vio __attribute__((unused)))
-{
- return socket_errno; /* On Win32 this mapped to WSAGetLastError() */
-}
-
-
-int vio_read(Vio * vio, gptr buf, int size)
-{
- int r;
- DBUG_ENTER("vio_read");
- DBUG_PRINT("enter", ("sd=%d size=%d", vio->sd, size));
-#if defined( __WIN__) || defined(OS2)
- if (vio->type == VIO_TYPE_NAMEDPIPE)
- {
- DWORD length;
-#ifdef OS2
- if (!DosRead((HFILE)vio->hPipe, buf, size, &length))
- DBUG_RETURN(-1);
-#else
- if (!ReadFile(vio->hPipe, buf, size, &length, NULL))
- DBUG_RETURN(-1);
-#endif
- DBUG_RETURN(length);
- }
- r = recv(vio->sd, buf, size,0);
-#else
- errno=0; /* For linux */
- r = read(vio->sd, buf, size);
-#endif /* __WIN__ */
-#ifndef DBUG_OFF
- if (r < 0)
- {
- DBUG_PRINT("vio_error", ("Got error %d during read",socket_errno));
- }
-#endif /* DBUG_OFF */
- DBUG_PRINT("exit", ("%d", r));
- DBUG_RETURN(r);
-}
-
-
-int vio_write(Vio * vio, const gptr buf, int size)
-{
- int r;
- DBUG_ENTER("vio_write");
- DBUG_PRINT("enter", ("sd=%d size=%d", vio->sd, size));
-#if defined( __WIN__) || defined(OS2)
- if ( vio->type == VIO_TYPE_NAMEDPIPE)
- {
- DWORD length;
-#ifdef OS2
- if (!DosWrite((HFILE)vio->hPipe, (char*) buf, size, &length))
- DBUG_RETURN(-1);
-#else
- if (!WriteFile(vio->hPipe, (char*) buf, size, &length, NULL))
- DBUG_RETURN(-1);
-#endif
- DBUG_RETURN(length);
- }
- r = send(vio->sd, buf, size,0);
-#else
- r = write(vio->sd, buf, size);
-#endif /* __WIN__ */
-#ifndef DBUG_OFF
- if (r < 0)
- {
- DBUG_PRINT("vio_error", ("Got error on write: %d",socket_errno));
- }
-#endif /* DBUG_OFF */
- DBUG_PRINT("exit", ("%d", r));
- DBUG_RETURN(r);
-}
-
-
-int vio_blocking(Vio * vio, my_bool set_blocking_mode)
-{
- int r=0;
- DBUG_ENTER("vio_blocking");
- DBUG_PRINT("enter", ("set_blocking_mode: %d", (int) set_blocking_mode));
-
-#if !defined(___WIN__) && !defined(__EMX__) && !defined(OS2)
-#if !defined(NO_FCNTL_NONBLOCK)
-
- if (vio->sd >= 0)
- {
- int old_fcntl=vio->fcntl_mode;
- if (set_blocking_mode)
- vio->fcntl_mode &= ~O_NONBLOCK; /* clear bit */
- else
- vio->fcntl_mode |= O_NONBLOCK; /* set bit */
- if (old_fcntl != vio->fcntl_mode)
- r = fcntl(vio->sd, F_SETFL, vio->fcntl_mode);
- }
-#endif /* !defined(NO_FCNTL_NONBLOCK) */
-#else /* !defined(__WIN__) && !defined(__EMX__) */
-#ifndef __EMX__
- if (vio->type != VIO_TYPE_NAMEDPIPE)
-#endif
- {
- ulong arg;
- int old_fcntl=vio->fcntl_mode;
- if (set_blocking_mode)
- {
- arg = 0;
- vio->fcntl_mode &= ~O_NONBLOCK; /* clear bit */
- }
- else
- {
- arg = 1;
- vio->fcntl_mode |= O_NONBLOCK; /* set bit */
- }
- if (old_fcntl != vio->fcntl_mode)
- r = ioctlsocket(vio->sd,FIONBIO,(void*) &arg, sizeof(arg));
- }
-#endif /* !defined(__WIN__) && !defined(__EMX__) */
- DBUG_RETURN(r);
-}
-
-my_bool
-vio_is_blocking(Vio * vio)
-{
- my_bool r;
- DBUG_ENTER("vio_is_blocking");
- r = !(vio->fcntl_mode & O_NONBLOCK);
- DBUG_PRINT("exit", ("%d", (int) r));
- DBUG_RETURN(r);
-}
-
-
-int vio_fastsend(Vio * vio __attribute__((unused)))
-{
- int r=0;
- DBUG_ENTER("vio_fastsend");
-
-#ifdef IPTOS_THROUGHPUT
- {
-#ifndef __EMX__
- int tos = IPTOS_THROUGHPUT;
- if (!setsockopt(vio->sd, IPPROTO_IP, IP_TOS, (void *) &tos, sizeof(tos)))
-#endif /* !__EMX__ */
- {
- int nodelay = 1;
- if (setsockopt(vio->sd, IPPROTO_TCP, TCP_NODELAY, (void *) &nodelay,
- sizeof(nodelay))) {
- DBUG_PRINT("warning",
- ("Couldn't set socket option for fast send"));
- r= -1;
- }
- }
- }
-#endif /* IPTOS_THROUGHPUT */
- DBUG_PRINT("exit", ("%d", r));
- DBUG_RETURN(r);
-}
-
-int vio_keepalive(Vio* vio, my_bool set_keep_alive)
-{
- int r=0;
- uint opt = 0;
- DBUG_ENTER("vio_keepalive");
- DBUG_PRINT("enter", ("sd=%d set_keep_alive=%d", vio->sd, (int)
- set_keep_alive));
- if (vio->type != VIO_TYPE_NAMEDPIPE)
- {
- if (set_keep_alive)
- opt = 1;
- r = setsockopt(vio->sd, SOL_SOCKET, SO_KEEPALIVE, (char *) &opt,
- sizeof(opt));
- }
- DBUG_RETURN(r);
-}
-
-
-my_bool
-vio_should_retry(Vio * vio __attribute__((unused)))
-{
- int en = socket_errno;
- return en == SOCKET_EAGAIN || en == SOCKET_EINTR || en == SOCKET_EWOULDBLOCK;
-}
-
-
-int vio_close(Vio * vio)
-{
- int r;
- DBUG_ENTER("vio_close");
-#ifdef __WIN__
- if (vio->type == VIO_TYPE_NAMEDPIPE)
- {
-#if defined(__NT__) && defined(MYSQL_SERVER)
- CancelIo(vio->hPipe);
- DisconnectNamedPipe(vio->hPipe);
-#endif
- r=CloseHandle(vio->hPipe);
- }
- else if (vio->type != VIO_CLOSED)
-#endif /* __WIN__ */
- {
- r=0;
- if (shutdown(vio->sd,2))
- r= -1;
- if (closesocket(vio->sd))
- r= -1;
- }
- if (r)
- {
- DBUG_PRINT("vio_error", ("close() failed, error: %d",socket_errno));
- /* FIXME: error handling (not critical for MySQL) */
- }
- vio->type= VIO_CLOSED;
- vio->sd= -1;
- DBUG_RETURN(r);
-}
-
-
-const char *vio_description(Vio * vio)
-{
- return vio->desc;
-}
-
-enum enum_vio_type vio_type(Vio* vio)
-{
- return vio->type;
-}
-
-my_socket vio_fd(Vio* vio)
-{
- return vio->sd;
-}
-
-
-my_bool vio_peer_addr(Vio * vio, char *buf)
-{
- DBUG_ENTER("vio_peer_addr");
- DBUG_PRINT("enter", ("sd=%d", vio->sd));
- if (vio->localhost)
- {
- strmov(buf,"127.0.0.1");
- }
- else
- {
- size_socket addrLen = sizeof(struct sockaddr);
- if (getpeername(vio->sd, (struct sockaddr *) (& (vio->remote)),
- &addrLen) != 0)
- {
- DBUG_PRINT("exit", ("getpeername, error: %d", socket_errno));
- DBUG_RETURN(1);
- }
- my_inet_ntoa(vio->remote.sin_addr,buf);
- }
- DBUG_PRINT("exit", ("addr=%s", buf));
- DBUG_RETURN(0);
-}
-
-
-void vio_in_addr(Vio *vio, struct in_addr *in)
-{
- DBUG_ENTER("vio_in_addr");
- if (vio->localhost)
- bzero((char*) in, sizeof(*in)); /* This should never be executed */
- else
- *in=vio->remote.sin_addr;
- DBUG_VOID_RETURN;
-}
-
-
-/* Return 0 if there is data to be read */
-
-my_bool vio_poll_read(Vio *vio,uint timeout)
-{
-#ifndef HAVE_POLL
- return 0;
-#else
- struct pollfd fds;
- int res;
- DBUG_ENTER("vio_poll");
- fds.fd=vio->sd;
- fds.events=POLLIN;
- fds.revents=0;
- if ((res=poll(&fds,1,(int) timeout*1000)) <= 0)
- {
- DBUG_RETURN(res < 0 ? 0 : 1); /* Don't return 1 on errors */
- }
- DBUG_RETURN(fds.revents & POLLIN ? 0 : 1);
-#endif
-}
-
-#endif /* HAVE_VIO */
diff --git a/libmysql_r/Makefile.am b/libmysql_r/Makefile.am
index aa1d398f874..22d71e00752 100644
--- a/libmysql_r/Makefile.am
+++ b/libmysql_r/Makefile.am
@@ -22,7 +22,7 @@ target_defs = -DDONT_USE_RAID @LIB_EXTRA_CCFLAGS@
## LIBS = @LIBS@
INCLUDES = @MT_INCLUDES@ -I$(srcdir)/../include -I../include \
- -I$(srcdir)/.. -I$(top_srcdir) -I..
+ -I$(srcdir)/.. -I$(top_srcdir) -I.. $(openssl_includes)
## automake barfs if you don't use $(srcdir) or $(top_srcdir) in include
include $(top_srcdir)/libmysql/Makefile.shared
diff --git a/libmysqld/Makefile.am b/libmysqld/Makefile.am
new file mode 100644
index 00000000000..edee13c98bb
--- /dev/null
+++ b/libmysqld/Makefile.am
@@ -0,0 +1,135 @@
+# Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the Free
+# Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+# MA 02111-1307, USA
+#
+# This file is public domain and comes with NO WARRANTY of any kind
+
+MYSQLDATAdir = $(localstatedir)
+MYSQLSHAREdir = $(pkgdatadir)
+MYSQLBASEdir= $(prefix)
+
+DEFS = -DEMBEDDED_LIBRARY -DMYSQL_SERVER \
+ -DDEFAULT_MYSQL_HOME="\"$(MYSQLBASEdir)\"" \
+ -DDATADIR="\"$(MYSQLDATAdir)\"" \
+ -DSHAREDIR="\"$(MYSQLSHAREdir)\""
+INCLUDES= @MT_INCLUDES@ @bdb_includes@ -I$(srcdir)/../include \
+ -I../include -I$(srcdir)/.. -I$(top_srcdir) -I.. \
+ -I../sql -I../regex
+
+noinst_LIBRARIES = libmysqld_int.a
+pkglib_LIBRARIES = libmysqld.a
+SUBDIRS = . examples
+libmysqld_sources= libmysqld.c lib_sql.cc lib_load.cc
+libmysqlsources = errmsg.c get_password.c password.c
+
+noinst_HEADERS = embedded_priv.h
+
+sqlsources = convert.cc derror.cc field.cc field_conv.cc filesort.cc \
+ ha_innodb.cc ha_berkeley.cc ha_heap.cc ha_isam.cc ha_isammrg.cc \
+ ha_myisam.cc ha_myisammrg.cc handler.cc sql_handler.cc \
+ hostname.cc init.cc \
+ item.cc item_buff.cc item_cmpfunc.cc item_create.cc \
+ item_func.cc item_strfunc.cc item_sum.cc item_timefunc.cc \
+ item_uniq.cc key.cc lock.cc log.cc log_event.cc mf_iocache.cc\
+ mini_client.cc net_pkg.cc net_serv.cc opt_ft.cc opt_range.cc \
+ opt_sum.cc procedure.cc records.cc sql_acl.cc \
+ repl_failsafe.cc slave.cc \
+ sql_analyse.cc sql_base.cc sql_cache.cc sql_class.cc \
+ sql_crypt.cc sql_db.cc sql_delete.cc sql_insert.cc sql_lex.cc \
+ sql_list.cc sql_manager.cc sql_map.cc sql_parse.cc \
+ sql_rename.cc sql_repl.cc sql_select.cc sql_do.cc sql_show.cc \
+ sql_string.cc sql_table.cc sql_test.cc sql_udf.cc \
+ sql_update.cc sql_yacc.cc table.cc thr_malloc.cc time.cc \
+ unireg.cc uniques.cc stacktrace.c sql_union.cc hash_filo.cc
+
+EXTRA_DIST = lib_vio.c
+
+libmysqld_int_a_SOURCES= $(libmysqld_sources) $(libmysqlsources) $(sqlsources)
+libmysqld_a_SOURCES=
+
+# Don't depend on things from mit-pthreads
+
+OMIT_DEPENDENCIES = pthread.h stdio.h __stdio.h stdlib.h __stdlib.h math.h\
+ __math.h time.h __time.h unistd.h __unistd.h types.h \
+ xtypes.h ac-types.h posix.h string.h __string.h \
+ errno.h socket.h inet.h dirent.h netdb.h \
+ cleanup.h cond.h debug_out.h fd.h kernel.h mutex.h \
+ prio_queue.h pthread_attr.h pthread_once.h queue.h\
+ sleep.h specific.h version.h pwd.h timers.h uio.h \
+ cdefs.h machdep.h signal.h __signal.h util.h lex.h \
+ wait.h
+
+# automake misses these
+sql_yacc.cc sql_yacc.h: $(top_srcdir)/sql/sql_yacc.yy
+
+# The following libraries should be included in libmysqld.a
+INC_LIB= $(top_builddir)/regex/libregex.a \
+ $(top_builddir)/myisam/libmyisam.a \
+ $(top_builddir)/myisammrg/libmyisammrg.a \
+ $(top_builddir)/heap/libheap.a \
+ @innodb_libs@ @bdb_libs_with_path@ \
+ $(top_builddir)/mysys/libmysys.a \
+ $(top_builddir)/strings/libmystrings.a \
+ $(top_builddir)/dbug/libdbug.a \
+ $(top_builddir)/regex/libregex.a
+
+#
+# To make it easy for the end user to use the embedded library we
+# generate a total libmysqld.a from all library files,
+
+libmysqld.a: libmysqld_int.a $(INC_LIB)
+ if test ! -d tmp ; then mkdir tmp ; fi
+ rm -f $@ libmysqld_int2.a tmp/*.o tmp/*.a
+ cp $(INC_LIB) tmp
+ cp libmysqld_int.a libmysqld_int2.a ; \
+ cd tmp ; \
+ for file in *.a ; do \
+ bfile=`basename $$file .a` ; \
+ ar x $$file; \
+ for obj in *.o ; do mv $$obj $${bfile}_$$obj ; done ; \
+ ar q ../libmysqld_int2.a *.o ; \
+ rm *.o ; \
+ done
+ mv libmysqld_int2.a libmysqld.a
+ rm tmp/*
+ $(RANLIB) libmysqld.a
+
+## XXX: any time the client interface changes, we'll need to bump
+## the version info for libmysqld; however, it's possible for the
+## libmysqld interface to change without affecting the standard
+## libmysqlclient interface. Should we make a separate version
+## string for the two?
+#libmysqld_la_LDFLAGS = -version-info @SHARED_LIB_VERSION@
+#CLEANFILES = $(libmysqld_la_LIBADD) libmysqld.la
+
+# This is called from the toplevel makefile
+link_sources:
+ set -x; \
+ for f in $(sqlsources); do \
+ rm -f $(srcdir)/$$f; \
+ @LN_CP_F@ $(srcdir)/../sql/$$f $(srcdir)/$$f; \
+ done; \
+ for f in $(libmysqlsources); do \
+ rm -f $(srcdir)/$$f; \
+ @LN_CP_F@ $(srcdir)/../libmysql/$$f $(srcdir)/$$f; \
+ done
+
+clean-local:
+ rm -f `echo $(sqlsources) $(libmysqlsources) | sed "s;\.lo;.c;g"` \
+ $(top_srcdir)/linked_libmysqld_sources
+
+# Don't update the files from bitkeeper
+%::SCCS/s.%
diff --git a/libmysqld/copyright b/libmysqld/copyright
new file mode 100644
index 00000000000..0b4dd1725a2
--- /dev/null
+++ b/libmysqld/copyright
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2000
+ * SWsoft company
+ *
+ * This material is provided "as is", with absolutely no warranty expressed
+ * or implied. Any use is at your own risk.
+ *
+ * Permission to use or copy this software for any purpose is hereby granted
+ * without fee, provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is granted,
+ * provided the above notices are retained, and a notice that the code was
+ * modified is included with the above copyright notice.
+ *
+ */
diff --git a/libmysqld/embedded_priv.h b/libmysqld/embedded_priv.h
new file mode 100644
index 00000000000..96d2c96ed0b
--- /dev/null
+++ b/libmysqld/embedded_priv.h
@@ -0,0 +1,32 @@
+/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+/* Prototypes for the embedded version of MySQL */
+
+#include <my_global.h>
+#include <mysql_embed.h>
+#include <mysql.h>
+#include <mysql_version.h>
+#include <mysqld_error.h>
+#include <my_pthread.h>
+
+C_MODE_START
+extern void start_embedded_connection(NET * net);
+extern void end_embedded_connection(NET * net);
+extern void lib_connection_phase(NET *net, int phase);
+extern bool lib_dispatch_command(enum enum_server_command command, NET *net,
+ const char *arg, ulong length);
+C_MODE_END
diff --git a/libmysqld/examples/Makefile.am b/libmysqld/examples/Makefile.am
new file mode 100644
index 00000000000..d9f9f05ae97
--- /dev/null
+++ b/libmysqld/examples/Makefile.am
@@ -0,0 +1,26 @@
+noinst_PROGRAMS = mysqltest mysql
+client_sources = $(mysqltest_SOURCES) $(mysql_SOURCES)
+
+link_sources:
+ for f in $(client_sources); do \
+ rm -f $(srcdir)/$$f; \
+ @LN_CP_F@ $(srcdir)/../../client/$$f $(srcdir)/$$f; \
+ done;
+
+DEFS = -DEMBEDDED_LIBRARY
+INCLUDES = -I$(top_srcdir)/include $(openssl_includes) \
+ -I$(srcdir) -I$(top_srcdir) -I$(top_srcdir)/client
+LIBS = @LIBS@
+LDADD = ../libmysqld.a @innodb_system_libs@ @LIBDL@ $(CXXLDFLAGS)
+
+mysqltest_SOURCES = mysqltest.c
+
+mysql_SOURCES = mysql.cc readline.cc completion_hash.cc \
+ my_readline.h sql_string.h completion_hash.h
+mysql_LDADD = @readline_link@ @TERMCAP_LIB@ $(LDADD)
+
+clean:
+ rm -f $(client_sources)
+
+# Don't update the files from bitkeeper
+%::SCCS/s.%
diff --git a/libmysqld/examples/test-run b/libmysqld/examples/test-run
new file mode 100755
index 00000000000..c7434488259
--- /dev/null
+++ b/libmysqld/examples/test-run
@@ -0,0 +1,138 @@
+#! /bin/sh
+
+# This is slapped together as a quick way to run the tests and
+# is not meant for prime time. Please hack at it and submit
+# changes, though, so we can gradually turn it into something
+# that will run on all platforms (or incorporate it into the
+# standard mysql-test-run).
+
+# All paths below must be relative to $test_data_dir
+top_builddir=../..
+mysql_test_dir=$top_builddir/mysql-test
+examples=$top_builddir/libmysqld/examples
+mysqltest=$examples/mysqltest
+datadir=$mysql_test_dir/var/master-data
+test_data_dir=test
+gdb=0
+list=0
+run=
+tests=
+start=
+clean=1
+
+cr="
+"
+er="\b\b\b\b\b\b\b\b"
+
+usage () {
+ cat <<EOF
+usage: $0 [-g|-h|-r] [test-name ...]
+
+ -C | --noclean Do not remove old innodb and bdb files at start.
+ -g | --gdb run $mysqltest in gdb
+ -h | --help show this help
+ -l | --list ) list all available tests
+ -r | --run automatically 'run' program in gdb
+ -s t | --start=t start with test t (skip all tests before t)
+EOF
+}
+
+init_args="--server-arg=--language=$top_builddir/sql/share/english"
+while test $# -gt 0
+do
+ arg=
+ argset=0
+ case "$1" in
+ --?*=* ) arg=`echo "$1" | sed -e 's,^[^=][^=]*=,,'`; argset=1 ;;
+ esac
+
+ case "$1" in
+ -g | --gdb ) gdb=1; shift;;
+ -h | --help | -\? ) usage; exit 0;;
+ -l | --list ) list=1 ; shift ;;
+ -r | --run ) run="${cr}run"; shift;;
+ --debug) init_args="$init_args --debug" ; shift ;;
+ -C | --noclean) clean=0 ; shift ;;
+ -s | --start=* )
+ test $argset -eq 0 && { shift; arg="$1"; }
+ start="$arg"
+ shift
+ ;;
+ -* ) usage; exit 1;;
+ * ) tests="$tests $1"; shift;;
+ esac
+done
+
+if test ! -d "$datadir/$test_data_dir"
+then
+ echo "bad setup (is '$datadir/$test_data_dir'', missing ?)" >&2
+ exit 1
+fi
+
+test -n "$tests" ||
+ tests=`/bin/ls -1 "$mysql_test_dir"/t/*.test | grep -v '^.*/rpl[^/]*$' | \
+ sed -e 's,^.*/,,' -e 's,.test$,,'`
+
+echo "cleaning data directory '$datadir/$test_data_dir'"
+if test $clean = 1
+then
+ rm -f $datadir/ib_* $datadir/ibdata*
+ rm -f $datadir/log.00*
+ rm -f $datadir/test/*.db
+fi
+rm -f $datadir/../tmp/*
+rm -f test-gdbinit
+
+TZ=GMT-3; export TZ
+
+# At least one of the tests needs the following environment variable
+MYSQL_TEST_DIR=`( cd $mysql_test_dir ; pwd )` ; export MYSQL_TEST_DIR
+
+skip=1
+test -z "$start" && skip=0
+
+for b in $tests
+do
+ test $list -eq 1 && { echo " $b"; continue; }
+ test $skip -eq 1 && test -n "$start" && test "$start" = "$b" && skip=0
+ test $skip -eq 1 && { echo "skipping '$b'"; continue; }
+
+ t="t/$b.test"
+ r="r/$b.result"
+
+ # Only test if $t exists; there is no $r for some tests
+ test -f $mysql_test_dir/$t || {
+ echo "test '$mysql_test_dir/$t' doesn't exist" >&2
+ continue
+ }
+ args="$init_args -v --basedir=$mysql_test_dir/ -R $r -x $t --server-arg=--datadir=$datadir"
+ if test -f "$mysql_test_dir/t/$b-master.opt" ; then
+ args="$args --server-file=t/$b-master.opt"
+ fi
+
+ args="$args $test_data_dir" # Add database last
+ echo "set args $args$run" > test-gdbinit
+ #if false && test -n "$run"
+ if test -n "$run" -o $gdb -eq 1
+ then
+ echo -e "$er>>> $b"
+ else
+ echo -e "$er>>> $b> \c"
+ read junk
+ fi
+ if test $gdb -eq 1
+ then
+ if [ -x "$top_builddir/libtool" ]; then
+ $top_builddir/libtool gdb -x test-gdbinit -q $mysqltest
+ else
+ gdb -x test-gdbinit -q $mysqltest
+ fi
+ res=$?
+ rm -f test-gdbinit
+ else
+ $mysqltest $args
+ res=$?
+ fi
+
+ test $res -eq 0 -o $res -eq 2 || echo "!!! error: $res"
+done
diff --git a/libmysqld/lib_load.cc b/libmysqld/lib_load.cc
new file mode 100644
index 00000000000..3db5a2488d1
--- /dev/null
+++ b/libmysqld/lib_load.cc
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2000
+ * SWsoft company
+ *
+ * This material is provided "as is", with absolutely no warranty expressed
+ * or implied. Any use is at your own risk.
+ *
+ * Permission to use or copy this software for any purpose is hereby granted
+ * without fee, provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is granted,
+ * provided the above notices are retained, and a notice that the code was
+ * modified is included with the above copyright notice.
+ *
+ */
+/* Copy data from a textfile to table */
+
+#include "mysql_priv.h"
+#include <my_dir.h>
+#include <m_ctype.h>
+
+
+int
+mysql_load_internal(THD * thd, sql_exchange * ex, TABLE_LIST * table_list,
+ List<Item> & fields, enum enum_duplicates handle_duplicates,
+ bool read_file_from_client, thr_lock_type lock_type);
+
+int
+mysql_load(THD * thd, sql_exchange * ex, TABLE_LIST * table_list,
+ List<Item> & fields, enum enum_duplicates handle_duplicates,
+ bool read_file_from_client, thr_lock_type lock_type)
+{
+ read_file_from_client = 0; //server is always in the same process
+ return mysql_load_internal(thd, ex, table_list, fields, handle_duplicates,
+ read_file_from_client, lock_type);
+}
+
+#define mysql_load mysql_load_internal
+
+
+#if defined (__WIN__)
+#include "../sql/sql_load.cpp"
+#else
+#include "../sql/sql_load.cc"
+#endif
diff --git a/libmysqld/lib_sql.cc b/libmysqld/lib_sql.cc
new file mode 100644
index 00000000000..0097aa5068d
--- /dev/null
+++ b/libmysqld/lib_sql.cc
@@ -0,0 +1,602 @@
+/*
+ * Copyright (c) 2000
+ * SWsoft company
+ *
+ * This material is provided "as is", with absolutely no warranty expressed
+ * or implied. Any use is at your own risk.
+ *
+ * Permission to use or copy this software for any purpose is hereby granted
+ * without fee, provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is granted,
+ * provided the above notices are retained, and a notice that the code was
+ * modified is included with the above copyright notice.
+ *
+ */
+#include "embedded_priv.h"
+#include "sys/types.h"
+#include "../regex/regex.h"
+#include "my_sys.h"
+
+/*
+ The following is needed to not cause conflicts when we include mysqld.cc
+*/
+
+#define main main1
+#define mysql_unix_port mysql_inix_port1
+#define mysql_port mysql_port1
+#if !defined(__WIN__)
+#define net_read_timeout net_read_timeout1
+#define net_write_timeout net_write_timeout1
+#endif
+#define changeable_vars changeable_vars1
+
+extern "C"
+{
+#include "mysql_com.h"
+#include "lib_vio.c"
+}
+
+
+class THD;
+
+static int check_connections1(THD * thd);
+static int check_connections2(THD * thd);
+static bool check_user(THD *thd, enum_server_command command,
+ const char *user, const char *passwd, const char *db,
+ bool check_count);
+void free_defaults_internal(char ** argv) {if (argv) free_defaults(argv);}
+#define free_defaults free_defaults_internal
+
+#if defined (__WIN__)
+#include "../sql/mysqld.cpp"
+#else
+#include "../sql/mysqld.cc"
+#endif
+
+#define SCRAMBLE_LENGTH 8
+C_MODE_START
+
+char * get_mysql_home(){ return mysql_home;};
+char * get_mysql_real_data_home(){ return mysql_real_data_home;};
+
+
+bool lib_dispatch_command(enum enum_server_command command, NET *net,
+ const char *arg, ulong length)
+{
+ THD *thd=(THD *) net->vio->dest_thd;
+ thd->store_globals(); // Fix if more than one connect
+ thd->net.last_error[0]=0; // Clear error message
+ thd->net.last_errno=0;
+
+ net_new_transaction(&thd->net);
+ return dispatch_command(command, thd, (char *) arg, length + 1);
+}
+
+
+void lib_connection_phase(NET * net, int phase)
+{
+ THD * thd;
+ thd = (THD *)(net->vio->dest_thd);
+ if (thd)
+ {
+ switch (phase)
+ {
+ case 2:
+ check_connections2(thd);
+ break;
+ }
+ }
+}
+C_MODE_END
+
+
+void start_embedded_conn1(NET * net)
+{
+ THD * thd = new THD;
+ my_net_init(&thd->net,NULL);
+ /* if (protocol_version>9) */
+ thd->net.return_errno=1;
+ thd->thread_id = thread_id++;
+
+ Vio * v = net->vio;
+ if (!v)
+ {
+ v = vio_new(0,VIO_CLOSED,0);
+ net->vio = v;
+ }
+ if (v)
+ {
+ v -> dest_thd = thd;
+ }
+ thd->net.vio = v;
+ if (thd->store_globals())
+ {
+ fprintf(stderr,"store_globals failed.\n");
+ return;
+ }
+
+ thd->mysys_var=my_thread_var;
+ thd->dbug_thread_id=my_thread_id();
+ thd->thread_stack= (char*) &thd;
+
+ if (thd->max_join_size == HA_POS_ERROR)
+ thd->options |= OPTION_BIG_SELECTS;
+ if (thd->options & OPTION_ANSI_MODE)
+ thd->client_capabilities|=CLIENT_IGNORE_SPACE;
+
+ thd->proc_info=0; // Remove 'login'
+ thd->command=COM_SLEEP;
+ thd->version=refresh_version;
+ thd->set_time();
+ init_sql_alloc(&thd->mem_root,8192,8192);
+
+ check_connections1(thd);
+}
+
+
+
+
+static int
+check_connections1(THD *thd)
+{
+ uint connect_errors=0;
+ NET *net= &thd->net;
+ /*
+ ** store the connection details
+ */
+ DBUG_PRINT("info", (("check_connections called by thread %d"),
+ thd->thread_id));
+ DBUG_PRINT("general",("New connection received on %s",
+ vio_description(net->vio)));
+ if (!thd->host) // If TCP/IP connection
+ {
+ thd->host=(char*) localhost;
+ }
+ else /* Hostname given means that the connection was on a socket */
+ {
+ DBUG_PRINT("general",("Host: %s",thd->host));
+ thd->ip=0;
+ bzero((char*) &thd->remote,sizeof(struct sockaddr));
+ }
+ //vio_keepalive(net->vio, TRUE);
+
+ /* nasty, but any other way? */
+ uint pkt_len = 0;
+
+ char buff[80],*end;
+ int client_flags = CLIENT_LONG_FLAG | CLIENT_CONNECT_WITH_DB |
+ CLIENT_TRANSACTIONS;
+ LINT_INIT(pkt_len);
+
+ end=strmov(buff,server_version)+1;
+ int4store((uchar*) end,thd->thread_id);
+ end+=4;
+ memcpy(end,thd->scramble,SCRAMBLE_LENGTH+1);
+ end+=SCRAMBLE_LENGTH +1;
+ int2store(end,client_flags);
+ end[2]=MY_CHARSET_CURRENT;
+
+#define MIN_HANDSHAKE_SIZE 6
+
+ int2store(end+3,thd->server_status);
+ bzero(end+5,13);
+ end+=18;
+ if (net_write_command(net,protocol_version, buff,
+ (uint) (end-buff)))
+ {
+ inc_host_errors(&thd->remote.sin_addr);
+ return(ER_HANDSHAKE_ERROR);
+ }
+ return 0;
+}
+
+static int
+check_connections2(THD * thd)
+{
+ uint connect_errors=0;
+ uint pkt_len = 0;
+ NET * net = &thd -> net;
+ if (protocol_version>9) net -> return_errno=1;
+
+ if ( (pkt_len=my_net_read(net)) == packet_error ||
+ pkt_len < MIN_HANDSHAKE_SIZE)
+ {
+ inc_host_errors(&thd->remote.sin_addr);
+ return(ER_HANDSHAKE_ERROR);
+ }
+
+#ifdef _CUSTOMCONFIG_
+#include "_cust_sql_parse.h"
+#endif
+ if (connect_errors)
+ reset_host_errors(&thd->remote.sin_addr);
+ if (thd->packet.alloc(net_buffer_length))
+ return(ER_OUT_OF_RESOURCES);
+
+ thd->client_capabilities=uint2korr(net->read_pos);
+
+ thd->max_packet_length=uint3korr(net->read_pos+2);
+ char *user= (char*) net->read_pos+5;
+ char *passwd= strend(user)+1;
+ char *db=0;
+ if (passwd[0] && strlen(passwd) != SCRAMBLE_LENGTH)
+ return ER_HANDSHAKE_ERROR;
+ if (thd->client_capabilities & CLIENT_CONNECT_WITH_DB)
+ db=strend(passwd)+1;
+ if (thd->client_capabilities & CLIENT_INTERACTIVE)
+ thd->inactive_timeout=net_interactive_timeout;
+ if (thd->client_capabilities & CLIENT_TRANSACTIONS)
+ thd->net.return_status= &thd->server_status;
+ net->timeout=net_read_timeout;
+ if (check_user(thd,COM_CONNECT, user, passwd, db, 1))
+ return (-1);
+ thd->password=test(passwd[0]);
+ return 0;
+}
+
+static bool check_user(THD *thd,enum_server_command command, const char *user,
+ const char *passwd, const char *db, bool check_count)
+{
+ NET *net= &thd->net;
+ uint max=0;
+ thd->db=0;
+
+ if (!(thd->user = my_strdup(user, MYF(0))))
+ {
+ send_error(net,ER_OUT_OF_RESOURCES);
+ return 1;
+ }
+ thd->master_access=acl_getroot(thd, thd->host, thd->ip, thd->user,
+ passwd, thd->scramble, &thd->priv_user,
+ protocol_version == 9 ||
+ !(thd->client_capabilities &
+ CLIENT_LONG_PASSWORD),&max);
+ DBUG_PRINT("general",
+ ("Capabilities: %d packet_length: %d Host: '%s' User: '%s' Using password: %s Access: %u db: '%s'",
+ thd->client_capabilities, thd->max_packet_length,
+ thd->host ? thd->host : thd->ip, thd->priv_user,
+ passwd[0] ? "yes": "no",
+ thd->master_access, thd->db ? thd->db : "*none*"));
+ if (thd->master_access & NO_ACCESS)
+ {
+ net_printf(net, ER_ACCESS_DENIED_ERROR,
+ thd->user,
+ thd->host ? thd->host : thd->ip,
+ passwd[0] ? ER(ER_YES) : ER(ER_NO));
+ mysql_log.write(thd,COM_CONNECT,ER(ER_ACCESS_DENIED_ERROR),
+ thd->user,
+ thd->host ? thd->host : thd->ip ? thd->ip : "unknown ip",
+ passwd[0] ? ER(ER_YES) : ER(ER_NO));
+ return(1); // Error already given
+ }
+ if (check_count)
+ {
+ VOID(pthread_mutex_lock(&LOCK_thread_count));
+ bool tmp=(thread_count - delayed_insert_threads >= max_connections &&
+ !(thd->master_access & PROCESS_ACL));
+ VOID(pthread_mutex_unlock(&LOCK_thread_count));
+ if (tmp)
+ { // Too many connections
+ send_error(net, ER_CON_COUNT_ERROR);
+ return(1);
+ }
+ }
+ mysql_log.write(thd,command,
+ (thd->priv_user == thd->user ?
+ (char*) "%s@%s on %s" :
+ (char*) "%s@%s as anonymous on %s"),
+ user,
+ thd->host ? thd->host : thd->ip ? thd->ip : "unknown ip",
+ db ? db : (char*) "");
+ thd->db_access=0;
+ if (db && db[0])
+ return test(mysql_change_db(thd,db));
+ else
+ send_ok(net); // Ready to handle questions
+ return 0; // ok
+}
+
+
+extern "C"
+{
+
+static my_bool inited, org_my_init_done;
+
+int STDCALL mysql_server_init(int argc, char **argv, char **groups)
+{
+ char glob_hostname[FN_REFLEN];
+
+ /* This mess is to allow people to call the init function without
+ * having to mess with a fake argv */
+ int *argcp;
+ char ***argvp;
+ int fake_argc = 1;
+ char *fake_argv[] = { (char *)"", 0 };
+ const char *fake_groups[] = { "server", "embedded", 0 };
+ if (argc)
+ {
+ argcp = &argc;
+ argvp = (char***) &argv;
+ }
+ else
+ {
+ argcp = &fake_argc;
+ argvp = (char ***) &fake_argv;
+ }
+ if (!groups)
+ groups = (char**) fake_groups;
+
+ my_umask=0660; // Default umask for new files
+ my_umask_dir=0700; // Default umask for new directories
+
+ /* Only call MY_INIT() if it hasn't been called before */
+ if (!inited)
+ {
+ inited=1;
+ org_my_init_done=my_init_done;
+ }
+ if (!org_my_init_done)
+ {
+ MY_INIT((char *)"mysql_embedded"); // init my_sys library & pthreads
+ }
+
+ tzset(); // Set tzname
+
+ start_time=time((time_t*) 0);
+#ifdef HAVE_TZNAME
+#if defined(HAVE_LOCALTIME_R) && defined(_REENTRANT)
+ {
+ struct tm tm_tmp;
+ localtime_r(&start_time,&tm_tmp);
+ strmov(time_zone,tzname[tm_tmp.tm_isdst != 0 ? 1 : 0]);
+ }
+#else
+ {
+ struct tm *start_tm;
+ start_tm=localtime(&start_time);
+ strmov(time_zone,tzname[start_tm->tm_isdst != 0 ? 1 : 0]);
+ }
+#endif
+#endif
+
+ if (gethostname(glob_hostname,sizeof(glob_hostname)-4) < 0)
+ strmov(glob_hostname,"mysql");
+#ifndef DBUG_OFF
+ strcat(server_version,"-debug");
+#endif
+ strcat(server_version,"-embedded");
+ load_defaults("my", (const char **) groups, argcp, argvp);
+ defaults_argv=*argvp;
+ mysql_tmpdir=getenv("TMPDIR"); /* Use this if possible */
+#if defined( __WIN__) || defined(OS2)
+ if (!mysql_tmpdir)
+ mysql_tmpdir=getenv("TEMP");
+ if (!mysql_tmpdir)
+ mysql_tmpdir=getenv("TMP");
+#endif
+ if (!mysql_tmpdir || !mysql_tmpdir[0])
+ mysql_tmpdir=(char*) P_tmpdir; /* purecov: inspected */
+ set_options();
+ get_options(*argcp, *argvp);
+
+ if (opt_log || opt_update_log || opt_slow_log || opt_bin_log)
+ strcat(server_version,"-log");
+ DBUG_PRINT("info",("%s Ver %s for %s on %s\n",my_progname,
+ server_version, SYSTEM_TYPE,MACHINE_TYPE));
+
+ /* These must be set early */
+
+ (void) pthread_mutex_init(&LOCK_mysql_create_db,MY_MUTEX_INIT_SLOW);
+ (void) pthread_mutex_init(&LOCK_Acl,MY_MUTEX_INIT_SLOW);
+ (void) pthread_mutex_init(&LOCK_grant,MY_MUTEX_INIT_FAST);
+ (void) pthread_mutex_init(&LOCK_open,MY_MUTEX_INIT_FAST);
+ (void) pthread_mutex_init(&LOCK_thread_count,MY_MUTEX_INIT_FAST);
+ (void) pthread_mutex_init(&LOCK_mapped_file,MY_MUTEX_INIT_SLOW);
+ (void) pthread_mutex_init(&LOCK_status,MY_MUTEX_INIT_FAST);
+ (void) pthread_mutex_init(&LOCK_error_log,MY_MUTEX_INIT_FAST);
+ (void) pthread_mutex_init(&LOCK_delayed_insert,MY_MUTEX_INIT_FAST);
+ (void) pthread_mutex_init(&LOCK_delayed_status,MY_MUTEX_INIT_FAST);
+ (void) pthread_mutex_init(&LOCK_delayed_create,MY_MUTEX_INIT_SLOW);
+ (void) pthread_mutex_init(&LOCK_manager,MY_MUTEX_INIT_FAST);
+ (void) pthread_mutex_init(&LOCK_crypt,MY_MUTEX_INIT_FAST);
+ (void) pthread_mutex_init(&LOCK_bytes_sent,MY_MUTEX_INIT_FAST);
+ (void) pthread_mutex_init(&LOCK_bytes_received,MY_MUTEX_INIT_FAST);
+ (void) pthread_mutex_init(&LOCK_timezone,MY_MUTEX_INIT_FAST);
+ (void) pthread_mutex_init(&LOCK_user_conn, MY_MUTEX_INIT_FAST);
+ (void) pthread_cond_init(&COND_thread_count,NULL);
+ (void) pthread_cond_init(&COND_refresh,NULL);
+ (void) pthread_cond_init(&COND_thread_cache,NULL);
+ (void) pthread_cond_init(&COND_flush_thread_cache,NULL);
+ (void) pthread_cond_init(&COND_manager,NULL);
+ (void) pthread_cond_init(&COND_binlog_update, NULL);
+
+ if (set_default_charset_by_name(default_charset, MYF(MY_WME)))
+ {
+ mysql_server_end();
+ return 1;
+ }
+ charsets_list = list_charsets(MYF(MY_COMPILED_SETS|MY_CONFIG_SETS));
+
+ /* Parameter for threads created for connections */
+ (void) pthread_attr_init(&connection_attrib);
+ (void) pthread_attr_setdetachstate(&connection_attrib,
+ PTHREAD_CREATE_DETACHED);
+ pthread_attr_setstacksize(&connection_attrib,thread_stack);
+ pthread_attr_setscope(&connection_attrib, PTHREAD_SCOPE_SYSTEM);
+
+#if defined( SET_RLIMIT_NOFILE) || defined( OS2)
+ /* connections and databases neads lots of files */
+ {
+ uint wanted_files=10+(uint) max(max_connections*5,
+ max_connections+table_cache_size*2);
+ uint files=set_maximum_open_files(wanted_files);
+ if (files && files < wanted_files) // Some systems return 0
+ {
+ max_connections= (ulong) min((files-10),max_connections);
+ table_cache_size= (ulong) max((files-10-max_connections)/2,64);
+ DBUG_PRINT("warning",
+ ("Changed limits: max_connections: %ld table_cache: %ld",
+ max_connections,table_cache_size));
+ sql_print_error("Warning: Changed limits: max_connections: %ld table_cache: %ld",max_connections,table_cache_size);
+ }
+ }
+#endif
+ unireg_init(opt_specialflag); /* Set up extern variabels */
+ init_errmessage(); /* Read error messages from file */
+ lex_init();
+ item_init();
+ mysys_uses_curses=0;
+#ifdef USE_REGEX
+ regex_init();
+#endif
+ if (use_temp_pool && bitmap_init(&temp_pool,1024,1))
+ {
+ mysql_server_end();
+ return 1;
+ }
+
+ /*
+ ** We have enough space for fiddling with the argv, continue
+ */
+ umask(((~my_umask) & 0666));
+ table_cache_init();
+ hostname_cache_init();
+ /*sql_cache_init();*/
+ randominit(&sql_rand,(ulong) start_time,(ulong) start_time/2);
+ reset_floating_point_exceptions();
+ init_thr_lock();
+ init_slave_list();
+
+ /* Setup log files */
+ if (opt_log)
+ open_log(&mysql_log, glob_hostname, opt_logname, ".log", LOG_NORMAL);
+ if (opt_update_log)
+ {
+ open_log(&mysql_update_log, glob_hostname, opt_update_logname, "",
+ LOG_NEW);
+ using_update_log=1;
+ }
+ if (opt_bin_log)
+ {
+ if (!opt_bin_logname)
+ {
+ char tmp[FN_REFLEN];
+ strmake(tmp,glob_hostname,FN_REFLEN-5);
+ strmov(strcend(tmp,'.'),"-bin");
+ opt_bin_logname=my_strdup(tmp,MYF(MY_WME));
+ }
+ mysql_bin_log.set_index_file_name(opt_binlog_index_name);
+ open_log(&mysql_bin_log, glob_hostname, opt_bin_logname, "-bin",
+ LOG_BIN);
+ using_update_log=1;
+ }
+
+ if (opt_slow_log)
+ open_log(&mysql_slow_log, glob_hostname, opt_slow_logname, "-slow.log",
+ LOG_NORMAL);
+ if (ha_init())
+ {
+ sql_print_error("Can't init databases");
+ exit(1);
+ }
+ ha_key_cache();
+#ifdef HAVE_MLOCKALL
+ if (locked_in_memory && !geteuid())
+ {
+ ha_key_cache();
+ if (mlockall(MCL_CURRENT))
+ {
+ sql_print_error("Warning: Failed to lock memory. Errno: %d\n",errno);
+ }
+ else
+ locked_in_memory=1;
+ }
+#else
+ locked_in_memory=0;
+#endif
+
+ if (opt_myisam_log)
+ (void) mi_log( 1 );
+ ft_init_stopwords(ft_precompiled_stopwords); /* SerG */
+
+ /*
+ init signals & alarm
+ After this we can't quit by a simple unireg_abort
+ */
+ error_handler_hook = my_message_sql;
+ if (pthread_key_create(&THR_THD,NULL) || pthread_key_create(&THR_NET,NULL) ||
+ pthread_key_create(&THR_MALLOC,NULL))
+ {
+ sql_print_error("Can't create thread-keys");
+ exit(1);
+ }
+ opt_noacl = 1; // No permissions
+ if (acl_init(opt_noacl))
+ {
+ mysql_server_end();
+ return 1;
+ }
+
+#ifdef HAVE_DLOPEN
+ if (!opt_noacl)
+ udf_init();
+#endif
+
+ (void) thr_setconcurrency(concurrency); // 10 by default
+
+ if (
+#ifdef HAVE_BERKELEY_DB
+ !berkeley_skip ||
+#endif
+ (flush_time && flush_time != ~(ulong) 0L))
+ {
+ pthread_t hThread;
+ if (pthread_create(&hThread,&connection_attrib,handle_manager,0))
+ {
+ sql_print_error("Warning: Can't create thread to manage maintenance");
+ mysql_server_end();
+ return 1;
+ }
+ }
+ return 0;
+}
+
+
+void STDCALL mysql_server_end()
+{
+ clean_up(0);
+#ifdef THREAD
+ /* Don't call my_thread_end() if the application is using MY_INIT() */
+ if (!org_my_init_done)
+ my_thread_end();
+#endif
+}
+
+my_bool STDCALL mysql_thread_init()
+{
+#ifdef THREAD
+ return my_thread_init();
+#else
+ return 0;
+#endif
+}
+
+void STDCALL mysql_thread_end()
+{
+#ifdef THREAD
+ my_thread_end();
+#endif
+}
+
+void start_embedded_connection(NET * net)
+{
+ start_embedded_conn1(net);
+}
+
+void end_embedded_connection(NET * net)
+{
+ THD *thd = (THD *) net->vio->dest_thd;
+ delete thd;
+}
+
+} /* extern "C" */
diff --git a/libmysqld/lib_vio.c b/libmysqld/lib_vio.c
new file mode 100644
index 00000000000..9bf492ed5ea
--- /dev/null
+++ b/libmysqld/lib_vio.c
@@ -0,0 +1,215 @@
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+/*
+ Note that we can't have assertion on file descriptors; The reason for
+ this is that during mysql shutdown, another thread can close a file
+ we are working on. In this case we should just return read errors from
+ the file descriptior.
+*/
+
+#include <my_global.h>
+#include "mysql_embed.h"
+#include "mysql.h"
+
+#ifndef HAVE_VIO /* is Vio enabled */
+
+#include <errno.h>
+#include <my_sys.h>
+#include <violite.h>
+#include <my_sys.h>
+#include <my_net.h>
+#include <m_string.h>
+#include <dbug.h>
+#include <assert.h>
+
+#ifndef __WIN__
+#define HANDLE void *
+#endif
+
+struct st_vio
+{
+ my_socket sd; /* my_socket - real or imaginary */
+ HANDLE hPipe;
+ my_bool localhost; /* Are we from localhost? */
+ int fcntl_mode; /* Buffered fcntl(sd,F_GETFL) */
+ struct sockaddr_in local; /* Local internet address */
+ struct sockaddr_in remote; /* Remote internet address */
+ enum enum_vio_type type; /* Type of connection */
+ char desc[30]; /* String description */
+ void *dest_thd;
+ char *packets, **last_packet;
+ char *where_in_packet, *end_of_packet;
+ my_bool reading;
+ MEM_ROOT root;
+};
+
+/* Initialize the communication buffer */
+
+Vio *vio_new(my_socket sd, enum enum_vio_type type, my_bool localhost)
+{
+ Vio * vio = NULL;
+ vio = (Vio *) my_malloc (sizeof(*vio),MYF(MY_WME|MY_ZEROFILL));
+ if (vio)
+ {
+ init_alloc_root(&vio->root, 8192, 8192);
+ vio->root.min_malloc = sizeof(char *) + 4;
+ vio->last_packet = &vio->packets;
+ }
+ return (vio);
+}
+
+
+#ifdef __WIN__
+
+Vio *vio_new_win32pipe(HANDLE hPipe)
+{
+ return (NULL);
+}
+
+#endif
+
+void vio_delete(Vio * vio)
+{
+ if (vio)
+ {
+ if (vio->type != VIO_CLOSED) vio_close(vio);
+ free_root(&vio->root, MYF(0));
+ my_free((gptr)vio, MYF(0));
+ }
+}
+
+void vio_reset(Vio *vio)
+{
+ free_root(&vio->root, MYF(MY_KEEP_PREALLOC));
+ vio->packets = vio->where_in_packet = vio->end_of_packet = 0;
+ vio->last_packet = &vio->packets;
+}
+
+int vio_errno(Vio *vio __attribute__((unused)))
+{
+ return socket_errno; /* On Win32 this mapped to WSAGetLastError() */
+}
+
+int vio_read(Vio * vio, gptr buf, int size)
+{
+ vio->reading = 1;
+ if (vio->where_in_packet >= vio->end_of_packet)
+ {
+ DBUG_ASSERT(vio->packets);
+ vio->where_in_packet = vio->packets + sizeof(char *) + 4;
+ vio->end_of_packet = vio->where_in_packet +
+ uint4korr(vio->packets + sizeof(char *));
+ vio->packets = *(char **)vio->packets;
+ }
+ if (vio->where_in_packet + size > vio->end_of_packet)
+ size = vio->end_of_packet - vio->where_in_packet;
+ memcpy(buf, vio->where_in_packet, size);
+ vio->where_in_packet += size;
+ return (size);
+}
+
+int vio_write(Vio * vio, const gptr buf, int size)
+{
+ char *packet;
+ if (vio->reading)
+ {
+ vio->reading = 0;
+ vio_reset(vio);
+ }
+ if ((packet = alloc_root(&vio->root, sizeof(char*) + 4 + size)))
+ {
+ *vio->last_packet = packet;
+ vio->last_packet = (char **)packet;
+ *((char **)packet) = 0; /* Set forward link to 0 */
+ packet += sizeof(char *);
+ int4store(packet, size);
+ memcpy(packet + 4, buf, size);
+ }
+ else
+ size= -1;
+ return (size);
+}
+
+int vio_blocking(Vio * vio, my_bool set_blocking_mode)
+{
+ return (0);
+}
+
+my_bool
+vio_is_blocking(Vio * vio)
+{
+ return(0);
+}
+
+int vio_fastsend(Vio * vio)
+{
+ return(0);
+}
+
+int vio_keepalive(Vio* vio, my_bool set_keep_alive)
+{
+ return (0);
+}
+
+
+my_bool
+vio_should_retry(Vio * vio __attribute__((unused)))
+{
+ int en = socket_errno;
+ return (en == SOCKET_EAGAIN || en == SOCKET_EINTR ||
+ en == SOCKET_EWOULDBLOCK);
+}
+
+
+int vio_close(Vio * vio)
+{
+ return(0);
+}
+
+
+const char *vio_description(Vio * vio)
+{
+ return "embedded vio";
+}
+
+enum enum_vio_type vio_type(Vio* vio)
+{
+ return VIO_CLOSED;
+}
+
+my_socket vio_fd(Vio* vio)
+{
+ return 0;
+}
+
+
+my_bool vio_peer_addr(Vio * vio, char *buf)
+{
+ return(0);
+}
+
+
+void vio_in_addr(Vio *vio, struct in_addr *in)
+{
+}
+
+my_bool vio_poll_read(Vio *vio,uint timeout)
+{
+ return 0;
+}
+
+#endif /* HAVE_VIO */
diff --git a/libmysqld/libmysqld.c b/libmysqld/libmysqld.c
new file mode 100644
index 00000000000..82928434cc6
--- /dev/null
+++ b/libmysqld/libmysqld.c
@@ -0,0 +1,2091 @@
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include "embedded_priv.h"
+#include <my_sys.h>
+#include <mysys_err.h>
+#include <m_string.h>
+#include <m_ctype.h>
+#include "errmsg.h"
+#include <violite.h>
+#include <sys/stat.h>
+#include <signal.h>
+#include <time.h>
+#ifdef HAVE_PWD_H
+#include <pwd.h>
+#endif
+#if !defined(MSDOS) && !defined(__WIN__)
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#ifdef HAVE_SELECT_H
+# include <select.h>
+#endif
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+#endif
+#ifdef HAVE_SYS_UN_H
+# include <sys/un.h>
+#endif
+#ifndef INADDR_NONE
+#define INADDR_NONE -1
+#endif
+
+static my_bool mysql_client_init=0;
+uint mysql_port=0;
+my_string mysql_unix_port=0;
+
+#define CLIENT_CAPABILITIES (CLIENT_LONG_PASSWORD | CLIENT_LONG_FLAG | CLIENT_TRANSACTIONS)
+
+#if defined(MSDOS) || defined(__WIN__)
+#define ERRNO WSAGetLastError()
+#define perror(A)
+#else
+#include <errno.h>
+#define ERRNO errno
+#define SOCKET_ERROR -1
+#define closesocket(A) close(A)
+#endif
+
+static void mysql_once_init(void);
+static MYSQL_DATA *read_rows (MYSQL *mysql,MYSQL_FIELD *fields,
+ uint field_count);
+static int read_one_row(MYSQL *mysql,uint fields,MYSQL_ROW row,
+ ulong *lengths);
+static void end_server(MYSQL *mysql);
+static void read_user_name(char *name);
+static void append_wild(char *to,char *end,const char *wild);
+static int send_file_to_server(MYSQL *mysql,const char *filename);
+static ulong mysql_sub_escape_string(CHARSET_INFO *charset_info, char *to,
+ const char *from, ulong length);
+
+#define init_sigpipe_variables
+#define set_sigpipe(mysql)
+#define reset_sigpipe(mysql)
+
+/*****************************************************************************
+** read a packet from server. Give error message if socket was down
+** or packet is an error message
+*****************************************************************************/
+
+ulong
+net_safe_read(MYSQL *mysql)
+{
+ NET *net= &mysql->net;
+ uint len=0;
+ //init_sigpipe_variables
+ /* Don't give sigpipe errors if the client doesn't want them */
+ set_sigpipe(mysql);
+ if (net->vio != 0)
+ len=my_net_read(net);
+ reset_sigpipe(mysql);
+ if (len == packet_error || len == 0)
+ {
+ DBUG_PRINT("error",("Wrong connection or packet. fd: %s len: %d",
+ vio_description(net->vio),len));
+ end_server(mysql);
+ net->last_errno=(net->last_errno == ER_NET_PACKET_TOO_LARGE ?
+ CR_NET_PACKET_TOO_LARGE:
+ CR_SERVER_LOST);
+ strmov(net->last_error,ER(net->last_errno));
+ return(packet_error);
+ }
+ if (net->read_pos[0] == 255)
+ {
+
+ if (len > 3)
+ {
+ char *pos=(char*) net->read_pos+1;
+ if (mysql->protocol_version > 9)
+ { /* New client protocol */
+ net->last_errno=uint2korr(pos);
+ pos+=2;
+ len-=2;
+ }
+ else
+ {
+ net->last_errno=CR_UNKNOWN_ERROR;
+ len--;
+ }
+ (void) strmake(net->last_error,(char*) pos,
+ min(len,sizeof(net->last_error)-1));
+ }
+ else
+ {
+ net->last_errno=CR_UNKNOWN_ERROR;
+ (void) strmov(net->last_error,ER(net->last_errno));
+ }
+ DBUG_PRINT("error",("Got error: %d (%s)", net->last_errno,
+ net->last_error));
+ return(packet_error);
+ }
+ return len;
+}
+
+
+/* Get the length of next field. Change parameter to point at fieldstart */
+static ulong
+net_field_length(uchar **packet)
+{
+ reg1 uchar *pos= *packet;
+ if (*pos < 251)
+ {
+ (*packet)++;
+ return (ulong) *pos;
+ }
+ if (*pos == 251)
+ {
+ (*packet)++;
+ return NULL_LENGTH;
+ }
+ if (*pos == 252)
+ {
+ (*packet)+=3;
+ return (ulong) uint2korr(pos+1);
+ }
+ if (*pos == 253)
+ {
+ (*packet)+=4;
+ return (ulong) uint3korr(pos+1);
+ }
+ (*packet)+=9; /* Must be 254 when here */
+ return (ulong) uint4korr(pos+1);
+}
+
+/* Same as above, but returns ulonglong values */
+
+static my_ulonglong
+net_field_length_ll(uchar **packet)
+{
+ reg1 uchar *pos= *packet;
+ if (*pos < 251)
+ {
+ (*packet)++;
+ return (my_ulonglong) *pos;
+ }
+ if (*pos == 251)
+ {
+ (*packet)++;
+ return (my_ulonglong) NULL_LENGTH;
+ }
+ if (*pos == 252)
+ {
+ (*packet)+=3;
+ return (my_ulonglong) uint2korr(pos+1);
+ }
+ if (*pos == 253)
+ {
+ (*packet)+=4;
+ return (my_ulonglong) uint3korr(pos+1);
+ }
+ (*packet)+=9; /* Must be 254 when here */
+#ifdef NO_CLIENT_LONGLONG
+ return (my_ulonglong) uint4korr(pos+1);
+#else
+ return (my_ulonglong) uint8korr(pos+1);
+#endif
+}
+
+
+static void free_rows(MYSQL_DATA *cur)
+{
+ if (cur)
+ {
+ free_root(&cur->alloc,MYF(0));
+ my_free((gptr) cur,MYF(0));
+ }
+}
+
+
+int
+simple_command(MYSQL *mysql,enum enum_server_command command, const char *arg,
+ ulong length, my_bool skipp_check)
+{
+ NET *net= &mysql->net;
+ int result= -1;
+
+ /* Check that we are calling the client functions in right order */
+ if (mysql->status != MYSQL_STATUS_READY)
+ {
+ strmov(net->last_error,ER(mysql->net.last_errno=CR_COMMANDS_OUT_OF_SYNC));
+ goto end;
+ }
+
+ /* Clear result variables */
+ mysql->net.last_error[0]=0;
+ mysql->net.last_errno=0;
+ mysql->info=0;
+ mysql->affected_rows= ~(my_ulonglong) 0;
+
+ /* Clear receive buffer and vio packet list */
+ net_clear(net);
+ vio_reset(net->vio);
+
+ result = lib_dispatch_command(command, net, arg,length);
+ if (!skipp_check)
+ result= ((mysql->packet_length=net_safe_read(mysql)) == packet_error ?
+ -1 : 0);
+ end:
+ return result;
+}
+
+
+static void free_old_query(MYSQL *mysql)
+{
+ DBUG_ENTER("free_old_query");
+ if (mysql->fields)
+ free_root(&mysql->field_alloc,MYF(0));
+ init_alloc_root(&mysql->field_alloc,8192,0); /* Assume rowlength < 8192 */
+ mysql->fields=0;
+ mysql->field_count=0; /* For API */
+ DBUG_VOID_RETURN;
+}
+
+#ifdef HAVE_GETPWUID
+struct passwd *getpwuid(uid_t);
+char* getlogin(void);
+#endif
+
+#if !defined(MSDOS) && ! defined(VMS) && !defined(__WIN__)
+static void read_user_name(char *name)
+{
+ DBUG_ENTER("read_user_name");
+ if (geteuid() == 0)
+ (void) strmov(name,"root"); /* allow use of surun */
+ else
+ {
+#ifdef HAVE_GETPWUID
+ struct passwd *skr;
+ const char *str;
+/*#ifdef __cplusplus
+ extern "C" struct passwd *getpwuid(uid_t);
+ extern "C" { char* getlogin(void); }
+#else
+ char * getlogin();
+ struct passwd *getpwuid(uid_t);
+#endif
+*/
+ if ((str=getlogin()) == NULL)
+ {
+ if ((skr=getpwuid(geteuid())) != NULL)
+ str=skr->pw_name;
+ else if (!(str=getenv("USER")) && !(str=getenv("LOGNAME")) &&
+ !(str=getenv("LOGIN")))
+ str="UNKNOWN_USER";
+ }
+ (void) strmake(name,str,USERNAME_LENGTH);
+#elif HAVE_CUSERID
+ (void) cuserid(name);
+#else
+ strmov(name,"UNKNOWN_USER");
+#endif
+ }
+ DBUG_VOID_RETURN;
+}
+
+#else /* If MSDOS || VMS */
+
+static void read_user_name(char *name)
+{
+ char *str=getenv("USER");
+ strmov(name,str ? str : "ODBC"); /* ODBC will send user variable */
+}
+
+#endif
+
+#ifdef __WIN__
+static my_bool is_NT(void)
+{
+ char *os=getenv("OS");
+ return (os && !strcmp(os, "Windows_NT")) ? 1 : 0;
+}
+#endif
+
+/*
+** Expand wildcard to a sql string
+*/
+
+static void
+append_wild(char *to, char *end, const char *wild)
+{
+ end-=5; /* Some extra */
+ if (wild && wild[0])
+ {
+ to=strmov(to," like '");
+ while (*wild && to < end)
+ {
+ if (*wild == '\\' || *wild == '\'')
+ *to++='\\';
+ *to++= *wild++;
+ }
+ if (*wild) /* Too small buffer */
+ *to++='%'; /* Nicer this way */
+ to[0]='\'';
+ to[1]=0;
+ }
+}
+
+
+
+/**************************************************************************
+** Init debugging if MYSQL_DEBUG environment variable is found
+**************************************************************************/
+
+void STDCALL
+mysql_debug(const char *debug)
+{
+#ifndef DBUG_OFF
+ char *env;
+ if (_db_on_)
+ return; /* Already using debugging */
+ if (debug)
+ {
+ DEBUGGER_ON;
+ DBUG_PUSH(debug);
+ }
+ else if ((env = getenv("MYSQL_DEBUG")))
+ {
+ DEBUGGER_ON;
+ DBUG_PUSH(env);
+#if !defined(_WINVER) && !defined(WINVER)
+ puts("\n-------------------------------------------------------");
+ puts("MYSQL_DEBUG found. libmysql started with the following:");
+ puts(env);
+ puts("-------------------------------------------------------\n");
+#else
+ {
+ char buff[80];
+ strmov(strmov(buff,"libmysql: "),env);
+ MessageBox((HWND) 0,"Debugging variable MYSQL_DEBUG used",buff,MB_OK);
+ }
+#endif
+ }
+#endif
+}
+
+/**************************************************************************
+** Shut down connection
+**************************************************************************/
+
+static void
+end_server(MYSQL *mysql)
+{
+ DBUG_ENTER("end_server");
+ if (mysql->net.vio != 0)
+ {
+ end_embedded_connection(&mysql->net);
+ mysql->net.vio= 0; /* Marker */
+ }
+ net_end(&mysql->net);
+ free_old_query(mysql);
+ DBUG_VOID_RETURN;
+}
+
+
+void STDCALL
+mysql_free_result(MYSQL_RES *result)
+{
+ DBUG_ENTER("mysql_free_result");
+ DBUG_PRINT("enter",("mysql_res: %lx",result));
+ if (result)
+ {
+ if (result->handle && result->handle->status == MYSQL_STATUS_USE_RESULT)
+ {
+ DBUG_PRINT("warning",("Not all rows in set were read; Ignoring rows"));
+ for (;;)
+ {
+ uint pkt_len;
+ if ((pkt_len=(uint) net_safe_read(result->handle)) == packet_error)
+ break;
+ if (pkt_len == 1 && result->handle->net.read_pos[0] == 254)
+ break; /* End of data */
+ }
+ result->handle->status=MYSQL_STATUS_READY;
+ }
+ free_rows(result->data);
+ if (result->fields)
+ free_root(&result->field_alloc,MYF(0));
+ if (result->row)
+ my_free((gptr) result->row,MYF(0));
+ my_free((gptr) result,MYF(0));
+ }
+ DBUG_VOID_RETURN;
+}
+
+
+/****************************************************************************
+** Get options from my.cnf
+****************************************************************************/
+
+static const char *default_options[]=
+{"port","socket","compress","password","pipe", "timeout", "user",
+ "init-command", "host", "database", "debug", "return-found-rows",
+ "ssl_key" ,"ssl_cert" ,"ssl_ca" ,"ssl_capath",
+ "character-set-dir", "default-character-set",
+ NullS
+};
+
+static TYPELIB option_types={array_elements(default_options)-1,
+ "options",default_options};
+
+static void mysql_read_default_options(struct st_mysql_options *options,
+ const char *filename,const char *group)
+{
+ int argc;
+ char *argv_buff[1],**argv;
+ const char *groups[3];
+ DBUG_ENTER("mysql_read_default_options");
+ DBUG_PRINT("enter",("file: %s group: %s",filename,group ? group :"NULL"));
+
+ argc=1; argv=argv_buff; argv_buff[0]= (char*) "client";
+ groups[0]= (char*) "client"; groups[1]= (char*) group; groups[2]=0;
+
+ load_defaults(filename, groups, &argc, &argv);
+ if (argc != 1) /* If some default option */
+ {
+ char **option=argv;
+ while (*++option)
+ {
+ /* DBUG_PRINT("info",("option: %s",option[0])); */
+ if (option[0][0] == '-' && option[0][1] == '-')
+ {
+ char *end=strcend(*option,'=');
+ char *opt_arg=0;
+ if (*end)
+ {
+ opt_arg=end+1;
+ *end=0; /* Remove '=' */
+ }
+ switch (find_type(*option+2,&option_types,2)) {
+ case 1: /* port */
+ if (opt_arg)
+ options->port=atoi(opt_arg);
+ break;
+ case 2: /* socket */
+ if (opt_arg)
+ {
+ my_free(options->unix_socket,MYF(MY_ALLOW_ZERO_PTR));
+ options->unix_socket=my_strdup(opt_arg,MYF(MY_WME));
+ }
+ break;
+ case 3: /* compress */
+ options->compress=1;
+ break;
+ case 4: /* password */
+ if (opt_arg)
+ {
+ my_free(options->password,MYF(MY_ALLOW_ZERO_PTR));
+ options->password=my_strdup(opt_arg,MYF(MY_WME));
+ }
+ break;
+ case 5: /* pipe */
+ options->named_pipe=1; /* Force named pipe */
+ break;
+ case 6: /* timeout */
+ if (opt_arg)
+ options->connect_timeout=atoi(opt_arg);
+ break;
+ case 7: /* user */
+ if (opt_arg)
+ {
+ my_free(options->user,MYF(MY_ALLOW_ZERO_PTR));
+ options->user=my_strdup(opt_arg,MYF(MY_WME));
+ }
+ break;
+ case 8: /* init-command */
+ if (opt_arg)
+ {
+ my_free(options->init_command,MYF(MY_ALLOW_ZERO_PTR));
+ options->init_command=my_strdup(opt_arg,MYF(MY_WME));
+ }
+ break;
+ case 9: /* host */
+ if (opt_arg)
+ {
+ my_free(options->host,MYF(MY_ALLOW_ZERO_PTR));
+ options->host=my_strdup(opt_arg,MYF(MY_WME));
+ }
+ break;
+ case 10: /* database */
+ if (opt_arg)
+ {
+ my_free(options->db,MYF(MY_ALLOW_ZERO_PTR));
+ options->db=my_strdup(opt_arg,MYF(MY_WME));
+ }
+ break;
+ case 11: /* debug */
+ mysql_debug(opt_arg ? opt_arg : "d:t:o,/tmp/client.trace");
+ break;
+ case 12: /* return-found-rows */
+ options->client_flag|=CLIENT_FOUND_ROWS;
+ break;
+ case 13: /* Ignore SSL options */
+ case 14:
+ case 15:
+ case 16:
+ break;
+ case 17: /* charset-lib */
+ my_free(options->charset_dir,MYF(MY_ALLOW_ZERO_PTR));
+ options->charset_dir = my_strdup(opt_arg, MYF(MY_WME));
+ break;
+ case 18:
+ my_free(options->charset_name,MYF(MY_ALLOW_ZERO_PTR));
+ options->charset_name = my_strdup(opt_arg, MYF(MY_WME));
+ break;
+ default:
+ DBUG_PRINT("warning",("unknown option: %s",option[0]));
+ }
+ }
+ }
+ }
+ free_defaults(argv);
+ DBUG_VOID_RETURN;
+}
+
+
+/***************************************************************************
+** Change field rows to field structs
+***************************************************************************/
+
+static MYSQL_FIELD *
+unpack_fields(MYSQL_DATA *data,MEM_ROOT *alloc,uint fields,
+ my_bool default_value, my_bool long_flag_protocol)
+{
+ MYSQL_ROWS *row;
+ MYSQL_FIELD *field,*result;
+ DBUG_ENTER("unpack_fields");
+
+ field=result=(MYSQL_FIELD*) alloc_root(alloc,sizeof(MYSQL_FIELD)*fields);
+ if (!result)
+ DBUG_RETURN(0);
+
+ for (row=data->data; row ; row = row->next,field++)
+ {
+ field->table= strdup_root(alloc,(char*) row->data[0]);
+ field->name= strdup_root(alloc,(char*) row->data[1]);
+ field->length= (uint) uint3korr(row->data[2]);
+ field->type= (enum enum_field_types) (uchar) row->data[3][0];
+ if (long_flag_protocol)
+ {
+ field->flags= uint2korr(row->data[4]);
+ field->decimals=(uint) (uchar) row->data[4][2];
+ }
+ else
+ {
+ field->flags= (uint) (uchar) row->data[4][0];
+ field->decimals=(uint) (uchar) row->data[4][1];
+ }
+ if (INTERNAL_NUM_FIELD(field))
+ field->flags|= NUM_FLAG;
+ if (default_value && row->data[5])
+ field->def=strdup_root(alloc,(char*) row->data[5]);
+ else
+ field->def=0;
+ field->max_length= 0;
+ }
+ free_rows(data); /* Free old data */
+ DBUG_RETURN(result);
+}
+
+
+/* Read all rows (fields or data) from server */
+
+static MYSQL_DATA *read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields,
+ uint fields)
+{
+ uint field,pkt_len;
+ ulong len;
+ uchar *cp;
+ char *to;
+ MYSQL_DATA *result;
+ MYSQL_ROWS **prev_ptr,*cur;
+ NET *net = &mysql->net;
+ DBUG_ENTER("read_rows");
+
+ if ((pkt_len=(uint) net_safe_read(mysql)) == packet_error)
+ DBUG_RETURN(0);
+ if (!(result=(MYSQL_DATA*) my_malloc(sizeof(MYSQL_DATA),
+ MYF(MY_WME | MY_ZEROFILL))))
+ {
+ net->last_errno=CR_OUT_OF_MEMORY;
+ strmov(net->last_error,ER(net->last_errno));
+ DBUG_RETURN(0);
+ }
+ init_alloc_root(&result->alloc,8192,0); /* Assume rowlength < 8192 */
+ result->alloc.min_malloc=sizeof(MYSQL_ROWS);
+ prev_ptr= &result->data;
+ result->rows=0;
+ result->fields=fields;
+
+ while (*(cp=net->read_pos) != 254 || pkt_len != 1)
+ {
+ result->rows++;
+ if (!(cur= (MYSQL_ROWS*) alloc_root(&result->alloc,
+ sizeof(MYSQL_ROWS))) ||
+ !(cur->data= ((MYSQL_ROW)
+ alloc_root(&result->alloc,
+ (fields+1)*sizeof(char *)+pkt_len))))
+ {
+ free_rows(result);
+ net->last_errno=CR_OUT_OF_MEMORY;
+ strmov(net->last_error,ER(net->last_errno));
+ DBUG_RETURN(0);
+ }
+ *prev_ptr=cur;
+ prev_ptr= &cur->next;
+ to= (char*) (cur->data+fields+1);
+ for (field=0 ; field < fields ; field++)
+ {
+ if ((len=(ulong) net_field_length(&cp)) == NULL_LENGTH)
+ { /* null field */
+ cur->data[field] = 0;
+ }
+ else
+ {
+ cur->data[field] = to;
+ memcpy(to,(char*) cp,len); to[len]=0;
+ to+=len+1;
+ cp+=len;
+ if (mysql_fields)
+ {
+ if (mysql_fields[field].max_length < len)
+ mysql_fields[field].max_length=len;
+ }
+ }
+ }
+ cur->data[field]=to; /* End of last field */
+ if ((pkt_len=net_safe_read(mysql)) == packet_error)
+ {
+ free_rows(result);
+ DBUG_RETURN(0);
+ }
+ }
+ *prev_ptr=0; /* last pointer is null */
+ DBUG_PRINT("exit",("Got %d rows",result->rows));
+ DBUG_RETURN(result);
+}
+
+
+/*
+** Read one row. Uses packet buffer as storage for fields.
+** When next packet is read, the previous field values are destroyed
+*/
+
+
+static int
+read_one_row(MYSQL *mysql,uint fields,MYSQL_ROW row, ulong *lengths)
+{
+ uint field;
+ ulong pkt_len,len;
+ uchar *pos,*prev_pos;
+
+ if ((pkt_len=net_safe_read(mysql)) == packet_error)
+ return -1;
+ if (pkt_len == 1 && mysql->net.read_pos[0] == 254)
+ return 1; /* End of data */
+ prev_pos= 0; /* allowed to write at packet[-1] */
+ pos=mysql->net.read_pos;
+ for (field=0 ; field < fields ; field++)
+ {
+ if ((len=(ulong) net_field_length(&pos)) == NULL_LENGTH)
+ { /* null field */
+ row[field] = 0;
+ *lengths++=0;
+ }
+ else
+ {
+ row[field] = (char*) pos;
+ pos+=len;
+ *lengths++=len;
+ }
+ if (prev_pos)
+ *prev_pos=0; /* Terminate prev field */
+ prev_pos=pos;
+ }
+ row[field]=(char*) prev_pos+1; /* End of last field */
+ *prev_pos=0; /* Terminate last field */
+ return 0;
+}
+
+/****************************************************************************
+** Init MySQL structure or allocate one
+****************************************************************************/
+
+MYSQL * STDCALL
+mysql_init(MYSQL *mysql)
+{
+ mysql_once_init();
+ if (!mysql)
+ {
+ if (!(mysql=(MYSQL*) my_malloc(sizeof(*mysql),MYF(MY_WME | MY_ZEROFILL))))
+ return 0;
+ mysql->free_me=1;
+ mysql->net.vio = 0;
+ }
+ else
+ bzero((char*) (mysql),sizeof(*(mysql)));
+ return mysql;
+}
+
+
+static void mysql_once_init()
+{
+ if (!mysql_client_init)
+ {
+ mysql_client_init=1;
+ my_init(); /* Will init threads */
+ init_client_errs();
+ mysql_port = MYSQL_PORT;
+ mysql_debug(NullS);
+ }
+#ifdef THREAD
+ else
+ my_thread_init(); /* Init if new thread */
+#endif
+}
+
+/**************************************************************************
+** Connect to sql server
+** If host == 0 then use localhost
+**************************************************************************/
+
+MYSQL * STDCALL
+mysql_connect(MYSQL *mysql,const char *host,
+ const char *user, const char *passwd)
+{
+ MYSQL *res;
+ mysql=mysql_init(mysql); /* Make it thread safe */
+ {
+ DBUG_ENTER("mysql_connect");
+ if (!(res=mysql_real_connect(mysql,host,user,passwd,NullS,0,NullS,0)))
+ {
+ if (mysql->free_me)
+ my_free((gptr) mysql,MYF(0));
+ }
+ DBUG_RETURN(res);
+ }
+}
+
+
+/*
+** Note that the mysql argument must be initialized with mysql_init()
+** before calling mysql_real_connect !
+*/
+
+MYSQL * STDCALL
+mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
+ const char *passwd, const char *db,
+ uint port, const char *unix_socket,uint client_flag)
+{
+ char buff[100],charset_name_buff[16],*end,*host_info, *charset_name;
+ uint pkt_length;
+ NET *net= &mysql->net;
+ DBUG_ENTER("mysql_real_connect");
+ DBUG_PRINT("enter",("host: %s db: %s user: %s",
+ host ? host : "(Null)",
+ db ? db : "(Null)",
+ user ? user : "(Null)"));
+
+ net->vio = 0; /* If something goes wrong */
+ /* use default options */
+ if (mysql->options.my_cnf_file || mysql->options.my_cnf_group)
+ {
+ mysql_read_default_options(&mysql->options,
+ (mysql->options.my_cnf_file ?
+ mysql->options.my_cnf_file : "my"),
+ mysql->options.my_cnf_group);
+ my_free(mysql->options.my_cnf_file,MYF(MY_ALLOW_ZERO_PTR));
+ my_free(mysql->options.my_cnf_group,MYF(MY_ALLOW_ZERO_PTR));
+ mysql->options.my_cnf_file=mysql->options.my_cnf_group=0;
+ }
+
+ /* Some empty-string-tests are done because of ODBC */
+ if (!host || !host[0])
+ host=mysql->options.host;
+ if (!user || !user[0])
+ user=mysql->options.user;
+ if (!passwd)
+ {
+ passwd=mysql->options.password;
+ }
+ if (!db || !db[0])
+ db=mysql->options.db;
+ port=0;
+ unix_socket=0;
+ mysql->reconnect=1; /* Reconnect as default */
+ mysql->server_status=SERVER_STATUS_AUTOCOMMIT;
+ host_info=(char*) ER(CR_EMBEDDED_CONNECTION);
+ if (my_net_init(net, net->vio))
+ {
+ vio_delete(net->vio);
+ net->last_errno=CR_OUT_OF_MEMORY;
+ strmov(net->last_error,ER(net->last_errno));
+ goto error;
+ }
+
+ /* Get version info */
+ mysql->protocol_version= PROTOCOL_VERSION; /* Assume this */
+ start_embedded_connection(net);
+
+ if ((pkt_length=net_safe_read(mysql)) == packet_error)
+ goto error;
+
+ /* Check if version of protocoll matches current one */
+
+ mysql->protocol_version= net->read_pos[0];
+ DBUG_DUMP("packet",(char*) net->read_pos,10);
+ DBUG_PRINT("info",("mysql protocol version %d, server=%d",
+ PROTOCOL_VERSION, mysql->protocol_version));
+ if (mysql->protocol_version != PROTOCOL_VERSION &&
+ mysql->protocol_version != PROTOCOL_VERSION-1)
+ {
+ net->last_errno= CR_VERSION_ERROR;
+ sprintf(net->last_error, ER(CR_VERSION_ERROR), mysql->protocol_version,
+ PROTOCOL_VERSION);
+ goto error;
+ }
+ end=strend((char*) net->read_pos+1);
+ mysql->thread_id=uint4korr(end+1);
+ end+=5;
+ strmake(mysql->scramble_buff,end,8);
+ end+=9;
+ if (pkt_length >= (uint) (end+1 - (char*) net->read_pos))
+ mysql->server_capabilities=uint2korr(end);
+ if (pkt_length >= (uint) (end+18 - (char*) net->read_pos))
+ {
+ /* New protocol with 16 bytes to describe server characteristics */
+ mysql->server_language=end[2];
+ mysql->server_status=uint2korr(end+3);
+ }
+
+ /* Set character set */
+ if ((charset_name=mysql->options.charset_name))
+ {
+ const char *save=charsets_dir;
+ if (mysql->options.charset_dir)
+ charsets_dir=mysql->options.charset_dir;
+ mysql->charset=get_charset_by_name(mysql->options.charset_name,
+ MYF(MY_WME));
+ charsets_dir=save;
+ }
+ else if (mysql->server_language)
+ {
+ charset_name=charset_name_buff;
+ sprintf(charset_name,"%d",mysql->server_language); /* In case of errors */
+ mysql->charset=get_charset((uint8) mysql->server_language, MYF(MY_WME));
+ }
+ else
+ mysql->charset=default_charset_info;
+
+ if (!mysql->charset)
+ {
+ net->last_errno=CR_CANT_READ_CHARSET;
+ if (mysql->options.charset_dir)
+ sprintf(net->last_error,ER(net->last_errno),
+ charset_name ? charset_name : "unknown",
+ mysql->options.charset_dir);
+ else
+ {
+ char cs_dir_name[FN_REFLEN];
+ get_charsets_dir(cs_dir_name);
+ sprintf(net->last_error,ER(net->last_errno),
+ charset_name ? charset_name : "unknown",
+ cs_dir_name);
+ }
+ goto error;
+ }
+
+ /* Save connection information */
+ if (!user) user="";
+ if (!passwd) passwd="";
+ host=LOCAL_HOST;
+ if (!my_multi_malloc(MYF(0),
+ &mysql->host_info, (uint) strlen(host_info)+1,
+ &mysql->host, (uint) strlen(host)+1,
+ &mysql->unix_socket,unix_socket ?
+ (uint) strlen(unix_socket)+1 : (uint) 1,
+ &mysql->server_version,
+ (uint) (end - (char*) net->read_pos),
+ NullS) ||
+ !(mysql->user=my_strdup(user,MYF(0))) ||
+ !(mysql->passwd=my_strdup(passwd,MYF(0))))
+ {
+ strmov(net->last_error, ER(net->last_errno=CR_OUT_OF_MEMORY));
+ goto error;
+ }
+ strmov(mysql->host_info,host_info);
+ strmov(mysql->host,host);
+ if (unix_socket)
+ strmov(mysql->unix_socket,unix_socket);
+ else
+ mysql->unix_socket=0;
+ strmov(mysql->server_version,(char*) net->read_pos+1);
+ mysql->port=port;
+ mysql->client_flag=client_flag | mysql->options.client_flag;
+ DBUG_PRINT("info",("Server version = '%s' capabilites: %ld status: %d",
+ mysql->server_version,mysql->server_capabilities,
+ mysql->server_status));
+
+ /* Send client information for access check */
+ client_flag|=CLIENT_CAPABILITIES;
+ client_flag&= ~CLIENT_COMPRESS;
+ if (db)
+ client_flag|=CLIENT_CONNECT_WITH_DB;
+ int2store(buff,client_flag);
+ mysql->client_flag=client_flag;
+
+
+ int3store(buff+2,max_allowed_packet);
+ if (user && user[0])
+ strmake(buff+5,user,32);
+ else
+ read_user_name((char*) buff+5);
+#ifdef _CUSTOMCONFIG_
+#include "_cust_libmysql.h";
+#endif
+ DBUG_PRINT("info",("user: %s",buff+5));
+ end=scramble(strend(buff+5)+1, mysql->scramble_buff, passwd,
+ (my_bool) (mysql->protocol_version == 9));
+
+ if (db)
+ {
+ end=strmov(end+1,db);
+ mysql->db=my_strdup(db,MYF(MY_WME));
+ db=0;
+ }
+ if (my_net_write(net,buff,(ulong) (end-buff)) || net_flush(net))
+ goto error;
+
+ lib_connection_phase(net,2);
+
+ if( net_safe_read(mysql) == packet_error)
+ goto error;
+ if (db && mysql_select_db(mysql,db))
+ goto error;
+ if (mysql->options.init_command)
+ {
+ my_bool reconnect=mysql->reconnect;
+ mysql->reconnect=0;
+ if (mysql_query(mysql,mysql->options.init_command))
+ goto error;
+ mysql_free_result(mysql_use_result(mysql));
+ mysql->reconnect=reconnect;
+ }
+
+ DBUG_PRINT("exit",("Mysql handler: %lx",mysql));
+ reset_sigpipe(mysql);
+ DBUG_RETURN(mysql);
+
+error:
+ reset_sigpipe(mysql);
+ DBUG_PRINT("error",("message: %u (%s)",net->last_errno,net->last_error));
+ {
+ /* Free alloced memory */
+ my_bool free_me=mysql->free_me;
+ end_server(mysql);
+ mysql->free_me=0;
+ mysql_close(mysql);
+ mysql->free_me=free_me;
+ }
+ DBUG_RETURN(0);
+}
+
+
+/**************************************************************************
+** Change user and database
+**************************************************************************/
+
+my_bool STDCALL mysql_change_user(MYSQL *mysql, const char *user,
+ const char *passwd, const char *db)
+{
+ char buff[512],*pos=buff;
+ DBUG_ENTER("mysql_change_user");
+
+ if (!user)
+ user="";
+ if (!passwd)
+ passwd="";
+
+ pos=strmov(pos,user)+1;
+ pos=scramble(pos, mysql->scramble_buff, passwd,
+ (my_bool) (mysql->protocol_version == 9));
+ pos=strmov(pos+1,db ? db : "");
+ if (simple_command(mysql,COM_CHANGE_USER, buff,(ulong) (pos-buff),0))
+ DBUG_RETURN(1);
+
+ my_free(mysql->user,MYF(MY_ALLOW_ZERO_PTR));
+ my_free(mysql->passwd,MYF(MY_ALLOW_ZERO_PTR));
+ my_free(mysql->db,MYF(MY_ALLOW_ZERO_PTR));
+
+ mysql->user= my_strdup(user,MYF(MY_WME));
+ mysql->passwd=my_strdup(passwd,MYF(MY_WME));
+ mysql->db= db ? my_strdup(db,MYF(MY_WME)) : 0;
+ DBUG_RETURN(0);
+}
+
+
+/**************************************************************************
+** Set current database
+**************************************************************************/
+
+int STDCALL
+mysql_select_db(MYSQL *mysql, const char *db)
+{
+ int error;
+ DBUG_ENTER("mysql_select_db");
+ DBUG_PRINT("enter",("db: '%s'",db));
+
+ if ((error=simple_command(mysql,COM_INIT_DB,db,(ulong) strlen(db),0)))
+ DBUG_RETURN(error);
+ my_free(mysql->db,MYF(MY_ALLOW_ZERO_PTR));
+ mysql->db=my_strdup(db,MYF(MY_WME));
+ DBUG_RETURN(0);
+}
+
+
+/*************************************************************************
+** Send a QUIT to the server and close the connection
+** If handle is alloced by mysql connect free it.
+*************************************************************************/
+
+void STDCALL
+mysql_close(MYSQL *mysql)
+{
+ DBUG_ENTER("mysql_close");
+ if (mysql) /* Some simple safety */
+ {
+ if (mysql->net.vio != 0)
+ {
+ free_old_query(mysql);
+ mysql->status=MYSQL_STATUS_READY; /* Force command */
+ simple_command(mysql,COM_QUIT,"",0,1);
+ end_server(mysql);
+ }
+ my_free((gptr) mysql->host_info,MYF(MY_ALLOW_ZERO_PTR));
+ my_free(mysql->user,MYF(MY_ALLOW_ZERO_PTR));
+ my_free(mysql->passwd,MYF(MY_ALLOW_ZERO_PTR));
+ my_free(mysql->db,MYF(MY_ALLOW_ZERO_PTR));
+ my_free(mysql->options.init_command,MYF(MY_ALLOW_ZERO_PTR));
+ my_free(mysql->options.user,MYF(MY_ALLOW_ZERO_PTR));
+ my_free(mysql->options.host,MYF(MY_ALLOW_ZERO_PTR));
+ my_free(mysql->options.password,MYF(MY_ALLOW_ZERO_PTR));
+ my_free(mysql->options.unix_socket,MYF(MY_ALLOW_ZERO_PTR));
+ my_free(mysql->options.db,MYF(MY_ALLOW_ZERO_PTR));
+ my_free(mysql->options.my_cnf_file,MYF(MY_ALLOW_ZERO_PTR));
+ my_free(mysql->options.my_cnf_group,MYF(MY_ALLOW_ZERO_PTR));
+ my_free(mysql->options.charset_dir,MYF(MY_ALLOW_ZERO_PTR));
+ my_free(mysql->options.charset_name,MYF(MY_ALLOW_ZERO_PTR));
+ /* Clear pointers for better safety */
+ mysql->host_info=mysql->user=mysql->passwd=mysql->db=0;
+ bzero((char*) &mysql->options,sizeof(mysql->options));
+ mysql->net.vio = 0;
+#ifdef HAVE_OPENSSL
+ ((VioConnectorFd*)(mysql->connector_fd))->delete();
+ mysql->connector_fd = 0;
+#endif /* HAVE_OPENSSL */
+ if (mysql->free_me)
+ my_free((gptr) mysql,MYF(0));
+ }
+ DBUG_VOID_RETURN;
+}
+
+
+/**************************************************************************
+** Do a query. If query returned rows, free old rows.
+** Read data by mysql_store_result or by repeat call of mysql_fetch_row
+**************************************************************************/
+
+int STDCALL
+mysql_query(MYSQL *mysql, const char *query)
+{
+ return mysql_real_query(mysql,query, (ulong) strlen(query));
+}
+
+int STDCALL
+mysql_send_query(MYSQL* mysql, const char* query, ulong length)
+{
+ return simple_command(mysql, COM_QUERY, query, length, 1);
+}
+
+
+int STDCALL
+mysql_read_query_result(MYSQL *mysql)
+{
+ uchar *pos;
+ ulong field_count;
+ MYSQL_DATA *fields;
+ uint length;
+ DBUG_ENTER("mysql_read_query_result");
+
+ if ((length=net_safe_read(mysql)) == packet_error)
+ DBUG_RETURN(-1);
+ free_old_query(mysql); /* Free old result */
+get_info:
+ pos=(uchar*) mysql->net.read_pos;
+ if ((field_count= net_field_length(&pos)) == 0)
+ {
+ mysql->affected_rows= net_field_length_ll(&pos);
+ mysql->insert_id= net_field_length_ll(&pos);
+ if (mysql->server_capabilities & CLIENT_TRANSACTIONS)
+ {
+ mysql->server_status=uint2korr(pos); pos+=2;
+ }
+ if (pos < mysql->net.read_pos+length && net_field_length(&pos))
+ mysql->info=(char*) pos;
+ DBUG_RETURN(0);
+ }
+ if (field_count == NULL_LENGTH) /* LOAD DATA LOCAL INFILE */
+ {
+ int error=send_file_to_server(mysql,(char*) pos);
+ if ((length=net_safe_read(mysql)) == packet_error || error)
+ DBUG_RETURN(-1);
+ goto get_info; /* Get info packet */
+ }
+ if (!(mysql->server_status & SERVER_STATUS_AUTOCOMMIT))
+ mysql->server_status|= SERVER_STATUS_IN_TRANS;
+
+ mysql->extra_info= net_field_length_ll(&pos); /* Maybe number of rec */
+ if (!(fields=read_rows(mysql,(MYSQL_FIELD*) 0,5)))
+ DBUG_RETURN(-1);
+ if (!(mysql->fields=unpack_fields(fields,&mysql->field_alloc,
+ (uint) field_count,0,
+ (my_bool) test(mysql->server_capabilities &
+ CLIENT_LONG_FLAG))))
+ DBUG_RETURN(-1);
+ mysql->status=MYSQL_STATUS_GET_RESULT;
+ mysql->field_count=field_count;
+ DBUG_RETURN(0);
+}
+
+/****************************************************************************
+* A modified version of connect(). connect2() allows you to specify
+* a timeout value, in seconds, that we should wait until we
+* derermine we can't connect to a particular host. If timeout is 0,
+* my_connect() will behave exactly like connect().
+*
+* Base version coded by Steve Bernacki, Jr. <steve@navinet.net>
+*****************************************************************************/
+
+int my_connect(my_socket s, const struct sockaddr *name, uint namelen,
+ uint timeout)
+{
+#if defined(__WIN__) || defined(OS2)
+ return connect(s, (struct sockaddr*) name, namelen);
+#else
+ int flags, res, s_err;
+ SOCKOPT_OPTLEN_TYPE s_err_size = sizeof(uint);
+ fd_set sfds;
+ struct timeval tv;
+ time_t start_time, now_time;
+
+ /* If they passed us a timeout of zero, we should behave
+ * exactly like the normal connect() call does.
+ */
+
+ if (timeout == 0)
+ return connect(s, (struct sockaddr*) name, namelen);
+
+ flags = fcntl(s, F_GETFL, 0); /* Set socket to not block */
+#ifdef O_NONBLOCK
+ fcntl(s, F_SETFL, flags | O_NONBLOCK); /* and save the flags.. */
+#endif
+
+ res = connect(s, (struct sockaddr*) name, namelen);
+ s_err = errno; /* Save the error... */
+ fcntl(s, F_SETFL, flags);
+ if ((res != 0) && (s_err != EINPROGRESS))
+ {
+ errno = s_err; /* Restore it */
+ return(-1);
+ }
+ if (res == 0) /* Connected quickly! */
+ return(0);
+
+ /* Otherwise, our connection is "in progress." We can use
+ * the select() call to wait up to a specified period of time
+ * for the connection to suceed. If select() returns 0
+ * (after waiting howevermany seconds), our socket never became
+ * writable (host is probably unreachable.) Otherwise, if
+ * select() returns 1, then one of two conditions exist:
+ *
+ * 1. An error occured. We use getsockopt() to check for this.
+ * 2. The connection was set up sucessfully: getsockopt() will
+ * return 0 as an error.
+ *
+ * Thanks goes to Andrew Gierth <andrew@erlenstar.demon.co.uk>
+ * who posted this method of timing out a connect() in
+ * comp.unix.programmer on August 15th, 1997.
+ */
+
+ FD_ZERO(&sfds);
+ FD_SET(s, &sfds);
+ /*
+ * select could be interrupted by a signal, and if it is,
+ * the timeout should be adjusted and the select restarted
+ * to work around OSes that don't restart select and
+ * implementations of select that don't adjust tv upon
+ * failure to reflect the time remaining
+ */
+ start_time = time(NULL);
+ for (;;)
+ {
+ tv.tv_sec = (long) timeout;
+ tv.tv_usec = 0;
+ if ((res = select(s+1, NULL, &sfds, NULL, &tv)) >= 0)
+ break;
+ now_time=time(NULL);
+ timeout-= (uint) (now_time - start_time);
+ if (errno != EINTR || (int) timeout <= 0)
+ return -1;
+ }
+
+ /* select() returned something more interesting than zero, let's
+ * see if we have any errors. If the next two statements pass,
+ * we've got an open socket!
+ */
+
+ s_err=0;
+ if (getsockopt(s, SOL_SOCKET, SO_ERROR, (char*) &s_err, &s_err_size) != 0)
+ return(-1);
+
+ if (s_err)
+ { /* getsockopt could succeed */
+ errno = s_err;
+ return(-1); /* but return an error... */
+ }
+ return(0); /* It's all good! */
+#endif
+}
+
+
+int STDCALL
+mysql_real_query(MYSQL *mysql, const char *query, ulong length)
+{
+ DBUG_ENTER("mysql_real_query");
+ DBUG_PRINT("enter",("handle: %lx",mysql));
+ DBUG_PRINT("query",("Query = \"%s\"",query));
+ if (mysql_send_query(mysql, query, length))
+ DBUG_RETURN(-1);
+ DBUG_RETURN(mysql_read_query_result(mysql));
+}
+
+
+static int
+send_file_to_server(MYSQL *mysql, const char *filename)
+{
+ int fd, readcount;
+ char buf[IO_SIZE*15],*tmp_name;
+ DBUG_ENTER("send_file_to_server");
+
+ fn_format(buf,filename,"","",4); /* Convert to client format */
+ if (!(tmp_name=my_strdup(buf,MYF(0))))
+ {
+ strmov(mysql->net.last_error, ER(mysql->net.last_errno=CR_OUT_OF_MEMORY));
+ DBUG_RETURN(-1);
+ }
+ if ((fd = my_open(tmp_name,O_RDONLY, MYF(0))) < 0)
+ {
+ mysql->net.last_errno=EE_FILENOTFOUND;
+ sprintf(buf,EE(mysql->net.last_errno),tmp_name,errno);
+ strmake(mysql->net.last_error,buf,sizeof(mysql->net.last_error)-1);
+ my_net_write(&mysql->net,"",0); net_flush(&mysql->net);
+ my_free(tmp_name,MYF(0));
+ DBUG_RETURN(-1);
+ }
+
+ while ((readcount = (int) my_read(fd,buf,sizeof(buf),MYF(0))) > 0)
+ {
+ if (my_net_write(&mysql->net,buf,readcount))
+ {
+ mysql->net.last_errno=CR_SERVER_LOST;
+ strmov(mysql->net.last_error,ER(mysql->net.last_errno));
+ DBUG_PRINT("error",("Lost connection to MySQL server during LOAD DATA of local file"));
+ (void) my_close(fd,MYF(0));
+ my_free(tmp_name,MYF(0));
+ DBUG_RETURN(-1);
+ }
+ }
+ (void) my_close(fd,MYF(0));
+ /* Send empty packet to mark end of file */
+ if (my_net_write(&mysql->net,"",0) || net_flush(&mysql->net))
+ {
+ mysql->net.last_errno=CR_SERVER_LOST;
+ sprintf(mysql->net.last_error,ER(mysql->net.last_errno),errno);
+ my_free(tmp_name,MYF(0));
+ DBUG_RETURN(-1);
+ }
+ if (readcount < 0)
+ {
+ mysql->net.last_errno=EE_READ; /* the errmsg for not entire file read */
+ sprintf(buf,EE(mysql->net.last_errno),tmp_name,errno);
+ strmake(mysql->net.last_error,buf,sizeof(mysql->net.last_error)-1);
+ my_free(tmp_name,MYF(0));
+ DBUG_RETURN(-1);
+ }
+ DBUG_RETURN(0);
+}
+
+
+/**************************************************************************
+** Alloc result struct for buffered results. All rows are read to buffer.
+** mysql_data_seek may be used.
+**************************************************************************/
+
+MYSQL_RES * STDCALL
+mysql_store_result(MYSQL *mysql)
+{
+ MYSQL_RES *result;
+ DBUG_ENTER("mysql_store_result");
+
+ if (!mysql->fields)
+ DBUG_RETURN(0);
+ if (mysql->status != MYSQL_STATUS_GET_RESULT)
+ {
+ strmov(mysql->net.last_error,
+ ER(mysql->net.last_errno=CR_COMMANDS_OUT_OF_SYNC));
+ DBUG_RETURN(0);
+ }
+ mysql->status=MYSQL_STATUS_READY; /* server is ready */
+ if (!(result=(MYSQL_RES*) my_malloc(sizeof(MYSQL_RES)+
+ sizeof(ulong)*mysql->field_count,
+ MYF(MY_WME | MY_ZEROFILL))))
+ {
+ mysql->net.last_errno=CR_OUT_OF_MEMORY;
+ strmov(mysql->net.last_error, ER(mysql->net.last_errno));
+ DBUG_RETURN(0);
+ }
+ result->eof=1; /* Marker for buffered */
+ result->lengths=(ulong*) (result+1);
+ if (!(result->data=read_rows(mysql,mysql->fields,mysql->field_count)))
+ {
+ my_free((gptr) result,MYF(0));
+ DBUG_RETURN(0);
+ }
+ mysql->affected_rows= result->row_count= result->data->rows;
+ result->data_cursor= result->data->data;
+ result->fields= mysql->fields;
+ result->field_alloc= mysql->field_alloc;
+ result->field_count= mysql->field_count;
+ result->current_field=0;
+ result->current_row=0; /* Must do a fetch first */
+ mysql->fields=0; /* fields is now in result */
+ DBUG_RETURN(result); /* Data fetched */
+}
+
+
+/**************************************************************************
+** Alloc struct for use with unbuffered reads. Data is fetched by domand
+** when calling to mysql_fetch_row.
+** mysql_data_seek is a noop.
+**
+** No other queries may be specified with the same MYSQL handle.
+** There shouldn't be much processing per row because mysql server shouldn't
+** have to wait for the client (and will not wait more than 30 sec/packet).
+**************************************************************************/
+
+MYSQL_RES * STDCALL
+mysql_use_result(MYSQL *mysql)
+{
+ MYSQL_RES *result;
+ DBUG_ENTER("mysql_use_result");
+
+ if (!mysql->fields)
+ DBUG_RETURN(0);
+ if (mysql->status != MYSQL_STATUS_GET_RESULT)
+ {
+ strmov(mysql->net.last_error,
+ ER(mysql->net.last_errno=CR_COMMANDS_OUT_OF_SYNC));
+ DBUG_RETURN(0);
+ }
+ if (!(result=(MYSQL_RES*) my_malloc(sizeof(*result)+
+ sizeof(ulong)*mysql->field_count,
+ MYF(MY_WME | MY_ZEROFILL))))
+ DBUG_RETURN(0);
+ result->lengths=(ulong*) (result+1);
+ if (!(result->row=(MYSQL_ROW)
+ my_malloc(sizeof(result->row[0])*(mysql->field_count+1), MYF(MY_WME))))
+ { /* Ptrs: to one row */
+ my_free((gptr) result,MYF(0));
+ DBUG_RETURN(0);
+ }
+ result->fields= mysql->fields;
+ result->field_alloc= mysql->field_alloc;
+ result->field_count= mysql->field_count;
+ result->current_field=0;
+ result->handle= mysql;
+ result->current_row= 0;
+ mysql->fields=0; /* fields is now in result */
+ mysql->status=MYSQL_STATUS_USE_RESULT;
+ DBUG_RETURN(result); /* Data is read to be fetched */
+}
+
+
+
+/**************************************************************************
+** Return next field of the query results
+**************************************************************************/
+
+MYSQL_FIELD * STDCALL
+mysql_fetch_field(MYSQL_RES *result)
+{
+ if (result->current_field >= result->field_count)
+ return(NULL);
+ return &result->fields[result->current_field++];
+}
+
+
+/**************************************************************************
+** Return next row of the query results
+**************************************************************************/
+
+MYSQL_ROW STDCALL
+mysql_fetch_row(MYSQL_RES *res)
+{
+ DBUG_ENTER("mysql_fetch_row");
+ if (!res->data)
+ { /* Unbufferred fetch */
+ if (!res->eof)
+ {
+ if (!(read_one_row(res->handle,res->field_count,res->row, res->lengths)))
+ {
+ res->row_count++;
+ DBUG_RETURN(res->current_row=res->row);
+ }
+ else
+ {
+ DBUG_PRINT("info",("end of data"));
+ res->eof=1;
+ res->handle->status=MYSQL_STATUS_READY;
+ }
+ }
+ DBUG_RETURN((MYSQL_ROW) NULL);
+ }
+ {
+ MYSQL_ROW tmp;
+ if (!res->data_cursor)
+ {
+ DBUG_PRINT("info",("end of data"));
+ DBUG_RETURN(res->current_row=(MYSQL_ROW) NULL);
+ }
+ tmp = res->data_cursor->data;
+ res->data_cursor = res->data_cursor->next;
+ DBUG_RETURN(res->current_row=tmp);
+ }
+}
+
+/**************************************************************************
+** Get column lengths of the current row
+** If one uses mysql_use_result, res->lengths contains the length information,
+** else the lengths are calculated from the offset between pointers.
+**************************************************************************/
+
+ulong * STDCALL
+mysql_fetch_lengths(MYSQL_RES *res)
+{
+ ulong *lengths,*prev_length;
+ byte *start;
+ MYSQL_ROW column,end;
+
+ if (!(column=res->current_row))
+ return 0; /* Something is wrong */
+ if (res->data)
+ {
+ start=0;
+ prev_length=0; /* Keep gcc happy */
+ lengths=res->lengths;
+ for (end=column+res->field_count+1 ; column != end ; column++,lengths++)
+ {
+ if (!*column)
+ {
+ *lengths=0; /* Null */
+ continue;
+ }
+ if (start) /* Found end of prev string */
+ *prev_length= (uint) (*column-start-1);
+ start= *column;
+ prev_length=lengths;
+ }
+ }
+ return res->lengths;
+}
+
+/**************************************************************************
+** Move to a specific row and column
+**************************************************************************/
+
+void STDCALL
+mysql_data_seek(MYSQL_RES *result, my_ulonglong row)
+{
+ MYSQL_ROWS *tmp=0;
+ DBUG_PRINT("info",("mysql_data_seek(%ld)",(long) row));
+ if (result->data)
+ for (tmp=result->data->data; row-- && tmp ; tmp = tmp->next) ;
+ result->current_row=0;
+ result->data_cursor = tmp;
+}
+
+/*************************************************************************
+** put the row or field cursor one a position one got from mysql_row_tell()
+** This doesn't restore any data. The next mysql_fetch_row or
+** mysql_fetch_field will return the next row or field after the last used
+*************************************************************************/
+
+MYSQL_ROW_OFFSET STDCALL
+mysql_row_seek(MYSQL_RES *result, MYSQL_ROW_OFFSET row)
+{
+ MYSQL_ROW_OFFSET return_value=result->data_cursor;
+ result->current_row= 0;
+ result->data_cursor= row;
+ return return_value;
+}
+
+
+MYSQL_FIELD_OFFSET STDCALL
+mysql_field_seek(MYSQL_RES *result, MYSQL_FIELD_OFFSET field_offset)
+{
+ MYSQL_FIELD_OFFSET return_value=result->current_field;
+ result->current_field=field_offset;
+ return return_value;
+}
+
+/*****************************************************************************
+** List all databases
+*****************************************************************************/
+
+MYSQL_RES * STDCALL
+mysql_list_dbs(MYSQL *mysql, const char *wild)
+{
+ char buff[255];
+ DBUG_ENTER("mysql_list_dbs");
+
+ append_wild(strmov(buff,"show databases"),buff+sizeof(buff),wild);
+ if (mysql_query(mysql,buff))
+ DBUG_RETURN(0);
+ DBUG_RETURN (mysql_store_result(mysql));
+}
+
+
+/*****************************************************************************
+** List all tables in a database
+** If wild is given then only the tables matching wild is returned
+*****************************************************************************/
+
+MYSQL_RES * STDCALL
+mysql_list_tables(MYSQL *mysql, const char *wild)
+{
+ char buff[255];
+ DBUG_ENTER("mysql_list_tables");
+
+ append_wild(strmov(buff,"show tables"),buff+sizeof(buff),wild);
+ if (mysql_query(mysql,buff))
+ DBUG_RETURN(0);
+ DBUG_RETURN (mysql_store_result(mysql));
+}
+
+
+/**************************************************************************
+** List all fields in a table
+** If wild is given then only the fields matching wild is returned
+** Instead of this use query:
+** show fields in 'table' like "wild"
+**************************************************************************/
+
+MYSQL_RES * STDCALL
+mysql_list_fields(MYSQL *mysql, const char *table, const char *wild)
+{
+ MYSQL_RES *result;
+ MYSQL_DATA *query;
+ char buff[257],*end;
+ DBUG_ENTER("mysql_list_fields");
+ DBUG_PRINT("enter",("table: '%s' wild: '%s'",table,wild ? wild : ""));
+
+ LINT_INIT(query);
+
+ end=strmake(strmake(buff, table,128)+1,wild ? wild : "",128);
+ if (simple_command(mysql,COM_FIELD_LIST,buff,(uint) (end-buff),1) ||
+ !(query = read_rows(mysql,(MYSQL_FIELD*) 0,6)))
+ DBUG_RETURN(NULL);
+
+ free_old_query(mysql);
+ if (!(result = (MYSQL_RES *) my_malloc(sizeof(MYSQL_RES),
+ MYF(MY_WME | MY_ZEROFILL))))
+ {
+ free_rows(query);
+ DBUG_RETURN(NULL);
+ }
+ result->field_alloc=mysql->field_alloc;
+ mysql->fields=0;
+ result->field_count = (uint) query->rows;
+ result->fields= unpack_fields(query,&result->field_alloc,
+ result->field_count,1,
+ (my_bool) test(mysql->server_capabilities &
+ CLIENT_LONG_FLAG));
+ result->eof=1;
+ DBUG_RETURN(result);
+}
+
+/* List all running processes (threads) in server */
+
+MYSQL_RES * STDCALL
+mysql_list_processes(MYSQL *mysql)
+{
+ MYSQL_DATA *fields;
+ uint field_count;
+ uchar *pos;
+ DBUG_ENTER("mysql_list_processes");
+
+ LINT_INIT(fields);
+ if (simple_command(mysql,COM_PROCESS_INFO,"",0,0))
+ DBUG_RETURN(0);
+ free_old_query(mysql);
+ pos=(uchar*) mysql->net.read_pos;
+ field_count=(uint) net_field_length(&pos);
+ if (!(fields = read_rows(mysql,(MYSQL_FIELD*) 0,5)))
+ DBUG_RETURN(NULL);
+ if (!(mysql->fields=unpack_fields(fields,&mysql->field_alloc,field_count,0,
+ (my_bool) test(mysql->server_capabilities &
+ CLIENT_LONG_FLAG))))
+ DBUG_RETURN(0);
+ mysql->status=MYSQL_STATUS_GET_RESULT;
+ mysql->field_count=field_count;
+ DBUG_RETURN(mysql_store_result(mysql));
+}
+
+
+int STDCALL
+mysql_create_db(MYSQL *mysql, const char *db)
+{
+ DBUG_ENTER("mysql_createdb");
+ DBUG_PRINT("enter",("db: %s",db));
+ DBUG_RETURN(simple_command(mysql,COM_CREATE_DB,db, (ulong) strlen(db),0));
+}
+
+
+int STDCALL
+mysql_drop_db(MYSQL *mysql, const char *db)
+{
+ DBUG_ENTER("mysql_drop_db");
+ DBUG_PRINT("enter",("db: %s",db));
+ DBUG_RETURN(simple_command(mysql,COM_DROP_DB,db,(ulong) strlen(db),0));
+}
+
+
+int STDCALL
+mysql_shutdown(MYSQL *mysql)
+{
+ DBUG_ENTER("mysql_shutdown");
+ DBUG_RETURN(simple_command(mysql,COM_SHUTDOWN,"",0,0));
+}
+
+
+int STDCALL
+mysql_refresh(MYSQL *mysql,uint options)
+{
+ uchar bits[1];
+ DBUG_ENTER("mysql_refresh");
+ bits[0]= (uchar) options;
+ DBUG_RETURN(simple_command(mysql,COM_REFRESH,(char*) bits,1,0));
+}
+
+int STDCALL
+mysql_kill(MYSQL *mysql,ulong pid)
+{
+ char buff[12];
+ DBUG_ENTER("mysql_kill");
+ int4store(buff,pid);
+ DBUG_RETURN(simple_command(mysql,COM_PROCESS_KILL,buff,4,0));
+}
+
+
+int STDCALL
+mysql_dump_debug_info(MYSQL *mysql)
+{
+ DBUG_ENTER("mysql_dump_debug_info");
+ DBUG_RETURN(simple_command(mysql,COM_DEBUG,"",0,0));
+}
+
+char * STDCALL
+mysql_stat(MYSQL *mysql)
+{
+ DBUG_ENTER("mysql_stat");
+ if (simple_command(mysql,COM_STATISTICS,"",0,0))
+ return mysql->net.last_error;
+ mysql->net.read_pos[mysql->packet_length]=0; /* End of stat string */
+ if (!mysql->net.read_pos[0])
+ {
+ mysql->net.last_errno=CR_WRONG_HOST_INFO;
+ strmov(mysql->net.last_error, ER(mysql->net.last_errno));
+ return mysql->net.last_error;
+ }
+ DBUG_RETURN((char*) mysql->net.read_pos);
+}
+
+
+int STDCALL
+mysql_ping(MYSQL *mysql)
+{
+ DBUG_ENTER("mysql_ping");
+ DBUG_RETURN(simple_command(mysql,COM_PING,"",0,0));
+}
+
+
+char * STDCALL
+mysql_get_server_info(MYSQL *mysql)
+{
+ return((char*) mysql->server_version);
+}
+
+
+char * STDCALL
+mysql_get_host_info(MYSQL *mysql)
+{
+ return(mysql->host_info);
+}
+
+
+uint STDCALL
+mysql_get_proto_info(MYSQL *mysql)
+{
+ return (mysql->protocol_version);
+}
+
+char * STDCALL
+mysql_get_client_info(void)
+{
+ return (char*) MYSQL_SERVER_VERSION;
+}
+
+
+int STDCALL
+mysql_options(MYSQL *mysql,enum mysql_option option, const char *arg)
+{
+ DBUG_ENTER("mysql_option");
+ DBUG_PRINT("enter",("option: %d",(int) option));
+ switch (option) {
+ case MYSQL_OPT_CONNECT_TIMEOUT:
+ mysql->options.connect_timeout= *(uint*) arg;
+ break;
+ case MYSQL_OPT_COMPRESS:
+ mysql->options.compress=1; /* Remember for connect */
+ break;
+ case MYSQL_OPT_NAMED_PIPE:
+ mysql->options.named_pipe=1; /* Force named pipe */
+ break;
+ case MYSQL_INIT_COMMAND:
+ my_free(mysql->options.init_command,MYF(MY_ALLOW_ZERO_PTR));
+ mysql->options.init_command=my_strdup(arg,MYF(MY_WME));
+ break;
+ case MYSQL_READ_DEFAULT_FILE:
+ my_free(mysql->options.my_cnf_file,MYF(MY_ALLOW_ZERO_PTR));
+ mysql->options.my_cnf_file=my_strdup(arg,MYF(MY_WME));
+ break;
+ case MYSQL_READ_DEFAULT_GROUP:
+ my_free(mysql->options.my_cnf_group,MYF(MY_ALLOW_ZERO_PTR));
+ mysql->options.my_cnf_group=my_strdup(arg,MYF(MY_WME));
+ break;
+ case MYSQL_SET_CHARSET_DIR:
+ my_free(mysql->options.charset_dir,MYF(MY_ALLOW_ZERO_PTR));
+ mysql->options.charset_dir=my_strdup(arg,MYF(MY_WME));
+ break;
+ case MYSQL_SET_CHARSET_NAME:
+ my_free(mysql->options.charset_name,MYF(MY_ALLOW_ZERO_PTR));
+ mysql->options.charset_name=my_strdup(arg,MYF(MY_WME));
+ break;
+ default:
+ DBUG_RETURN(-1);
+ }
+ DBUG_RETURN(0);
+}
+
+/****************************************************************************
+** Functions to get information from the MySQL structure
+** These are functions to make shared libraries more usable.
+****************************************************************************/
+
+/* MYSQL_RES */
+my_ulonglong STDCALL mysql_num_rows(MYSQL_RES *res)
+{
+ return res->row_count;
+}
+
+unsigned int STDCALL mysql_num_fields(MYSQL_RES *res)
+{
+ return res->field_count;
+}
+
+my_bool STDCALL mysql_eof(MYSQL_RES *res)
+{
+ return res->eof;
+}
+
+MYSQL_FIELD * STDCALL mysql_fetch_field_direct(MYSQL_RES *res,uint fieldnr)
+{
+ return &(res)->fields[fieldnr];
+}
+
+MYSQL_FIELD * STDCALL mysql_fetch_fields(MYSQL_RES *res)
+{
+ return (res)->fields;
+}
+
+MYSQL_ROWS * STDCALL mysql_row_tell(MYSQL_RES *res)
+{
+ return res->data_cursor;
+}
+
+uint STDCALL mysql_field_tell(MYSQL_RES *res)
+{
+ return (res)->current_field;
+}
+
+/* MYSQL */
+
+unsigned int STDCALL mysql_field_count(MYSQL *mysql)
+{
+ return mysql->field_count;
+}
+
+my_ulonglong STDCALL mysql_affected_rows(MYSQL *mysql)
+{
+ return (mysql)->affected_rows;
+}
+
+my_ulonglong STDCALL mysql_insert_id(MYSQL *mysql)
+{
+ return (mysql)->insert_id;
+}
+
+uint STDCALL mysql_errno(MYSQL *mysql)
+{
+ return (mysql)->net.last_errno;
+}
+
+char * STDCALL mysql_error(MYSQL *mysql)
+{
+ return (mysql)->net.last_error;
+}
+
+char *STDCALL mysql_info(MYSQL *mysql)
+{
+ return (mysql)->info;
+}
+
+ulong STDCALL mysql_thread_id(MYSQL *mysql)
+{
+ return (mysql)->thread_id;
+}
+
+const char * STDCALL mysql_character_set_name(MYSQL *mysql)
+{
+ return mysql->charset->name;
+}
+
+
+uint STDCALL mysql_thread_safe(void)
+{
+#ifdef THREAD
+ return 1;
+#else
+ return 0;
+#endif
+}
+
+/****************************************************************************
+** Some support functions
+****************************************************************************/
+
+/*
+** Add escape characters to a string (blob?) to make it suitable for a insert
+** to should at least have place for length*2+1 chars
+** Returns the length of the to string
+*/
+
+ulong STDCALL
+mysql_escape_string(char *to,const char *from,ulong length)
+{
+ return mysql_sub_escape_string(default_charset_info,to,from,length);
+}
+
+ulong STDCALL
+mysql_real_escape_string(MYSQL *mysql, char *to,const char *from,
+ ulong length)
+{
+ return mysql_sub_escape_string(mysql->charset,to,from,length);
+}
+
+
+static ulong
+mysql_sub_escape_string(CHARSET_INFO *charset_info, char *to,
+ const char *from, ulong length)
+{
+ const char *to_start=to;
+ const char *end;
+#ifdef USE_MB
+ my_bool use_mb_flag=use_mb(charset_info);
+#endif
+ for (end=from+length; from != end ; from++)
+ {
+#ifdef USE_MB
+ int l;
+ if (use_mb_flag && (l = my_ismbchar(charset_info, from, end)))
+ {
+ while (l--)
+ *to++ = *from++;
+ from--;
+ continue;
+ }
+#endif
+ switch (*from) {
+ case 0: /* Must be escaped for 'mysql' */
+ *to++= '\\';
+ *to++= '0';
+ break;
+ case '\n': /* Must be escaped for logs */
+ *to++= '\\';
+ *to++= 'n';
+ break;
+ case '\r':
+ *to++= '\\';
+ *to++= 'r';
+ break;
+ case '\\':
+ *to++= '\\';
+ *to++= '\\';
+ break;
+ case '\'':
+ *to++= '\\';
+ *to++= '\'';
+ break;
+ case '"': /* Better safe than sorry */
+ *to++= '\\';
+ *to++= '"';
+ break;
+ case '\032': /* This gives problems on Win32 */
+ *to++= '\\';
+ *to++= 'Z';
+ break;
+ default:
+ *to++= *from;
+ }
+ }
+ *to=0;
+ return (ulong) (to-to_start);
+}
+
+
+char * STDCALL
+mysql_odbc_escape_string(MYSQL *mysql,
+ char *to, ulong to_length,
+ const char *from, ulong from_length,
+ void *param,
+ char * (*extend_buffer)
+ (void *, char *, ulong *))
+{
+ char *to_end=to+to_length-5;
+ const char *end;
+#ifdef USE_MB
+ my_bool use_mb_flag=use_mb(mysql->charset);
+#endif
+
+ for (end=from+from_length; from != end ; from++)
+ {
+ if (to >= to_end)
+ {
+ to_length = (ulong) (end-from)+512; /* We want this much more */
+ if (!(to=(*extend_buffer)(param, to, &to_length)))
+ return to;
+ to_end=to+to_length-5;
+ }
+#ifdef USE_MB
+ {
+ int l;
+ if (use_mb_flag && (l = my_ismbchar(mysql->charset, from, end)))
+ {
+ while (l--)
+ *to++ = *from++;
+ from--;
+ continue;
+ }
+ }
+#endif
+ switch (*from) {
+ case 0: /* Must be escaped for 'mysql' */
+ *to++= '\\';
+ *to++= '0';
+ break;
+ case '\n': /* Must be escaped for logs */
+ *to++= '\\';
+ *to++= 'n';
+ break;
+ case '\r':
+ *to++= '\\';
+ *to++= 'r';
+ break;
+ case '\\':
+ *to++= '\\';
+ *to++= '\\';
+ break;
+ case '\'':
+ *to++= '\\';
+ *to++= '\'';
+ break;
+ case '"': /* Better safe than sorry */
+ *to++= '\\';
+ *to++= '"';
+ break;
+ case '\032': /* This gives problems on Win32 */
+ *to++= '\\';
+ *to++= 'Z';
+ break;
+ default:
+ *to++= *from;
+ }
+ }
+ return to;
+}
+
+void STDCALL
+myodbc_remove_escape(MYSQL *mysql,char *name)
+{
+ char *to;
+#ifdef USE_MB
+ my_bool use_mb_flag=use_mb(mysql->charset);
+ char *end;
+ LINT_INIT(end);
+ if (use_mb_flag)
+ for (end=name; *end ; end++) ;
+#endif
+
+ for (to=name ; *name ; name++)
+ {
+#ifdef USE_MB
+ int l;
+ if (use_mb_flag && (l = my_ismbchar( mysql->charset, name , end ) ) )
+ {
+ while (l--)
+ *to++ = *name++;
+ name--;
+ continue;
+ }
+#endif
+ if (*name == '\\' && name[1])
+ name++;
+ *to++= *name;
+ }
+ *to=0;
+}
diff --git a/libmysqld/libmysqld.def b/libmysqld/libmysqld.def
new file mode 100644
index 00000000000..0e126aa9ceb
--- /dev/null
+++ b/libmysqld/libmysqld.def
@@ -0,0 +1,72 @@
+LIBRARY LIBMYSQLD
+DESCRIPTION 'MySQL 4.0 Embedded Server Library'
+VERSION 4.0
+EXPORTS
+ mysql_server_end
+ mysql_server_init
+ mysql_use_result
+ mysql_thread_safe
+ mysql_thread_id
+ mysql_store_result
+ mysql_stat
+ mysql_shutdown
+ mysql_select_db
+ mysql_row_tell
+ mysql_row_seek
+ mysql_real_query
+ mysql_real_connect
+ mysql_query
+ mysql_ping
+ mysql_options
+ mysql_num_rows
+ mysql_num_fields
+ mysql_list_tables
+ mysql_list_processes
+ mysql_list_fields
+ mysql_list_dbs
+ mysql_kill
+ mysql_insert_id
+ mysql_init
+ mysql_info
+ mysql_get_server_info
+ mysql_get_proto_info
+ mysql_get_host_info
+ mysql_get_client_info
+ mysql_free_result
+ mysql_field_tell
+ mysql_field_count
+ mysql_field_seek
+ mysql_fetch_row
+ mysql_fetch_lengths
+ mysql_fetch_fields
+ mysql_fetch_field_direct
+ mysql_fetch_field
+ mysql_escape_string
+ mysql_real_escape_string
+ mysql_error
+ mysql_errno
+ mysql_eof
+ mysql_dump_debug_info
+ mysql_drop_db
+ mysql_debug
+ mysql_data_seek
+ mysql_create_db
+ mysql_character_set_name
+ mysql_change_user
+ mysql_connect
+ mysql_close
+ mysql_affected_rows
+ mysql_thread_init
+ mysql_thread_end
+ mysql_send_query
+ mysql_read_query_result
+ mysql_refresh
+ mysql_odbc_escape_string
+ myodbc_remove_escape
+
+
+
+
+
+
+
diff --git a/ltconfig b/ltconfig
index 18af7c4dce8..b9df847729d 100755
--- a/ltconfig
+++ b/ltconfig
@@ -1308,7 +1308,9 @@ else
hardcode_direct=yes
fi
allow_undefined_flag=' ${wl}-berok'
- archive_cmds="\$CC $shared_flag"' -o $objdir/$soname $libobjs $deplibs $linkopts ${wl}-bexpall ${wl}-bnoentry${allow_undefined_flag}'
+ # -qmkshrobj used to be -bexpall, but MySQL uses symbols which start with
+ # an underscore (e.g., _my_b_write), so -bexpall doesn't work.
+ archive_cmds="\$CC $shared_flag"' -o $objdir/$soname $libobjs $deplibs $linkopts ${wl}-qmkshrobj ${wl}-bnoentry${allow_undefined_flag}'
archive_expsym_cmds="\$CC $shared_flag"' -o $objdir/$soname $libobjs $deplibs $linkopts ${wl}-bE:$export_symbols ${wl}-bnoentry${allow_undefined_flag}'
case "$host_os" in aix4.[01]|aix4.[01].*)
# According to Greg Wooledge, -bexpall is only supported from AIX 4.2 on
diff --git a/man/Makefile.am b/man/Makefile.am
index 186fc01685e..7019d2aa865 100644
--- a/man/Makefile.am
+++ b/man/Makefile.am
@@ -19,7 +19,7 @@
man_MANS = mysql.1 isamchk.1 isamlog.1 mysql_zap.1 mysqlaccess.1 \
mysqladmin.1 mysqld.1 mysqld_multi.1 mysqldump.1 mysqlshow.1 \
- perror.1 replace.1 safe_mysqld.1
+ perror.1 replace.1 mysqld_safe.1
EXTRA_DIST = $(man_MANS)
diff --git a/man/isamchk.1 b/man/isamchk.1
index f225dc35d18..2552d9f80cd 100755..100644
--- a/man/isamchk.1
+++ b/man/isamchk.1
@@ -125,7 +125,7 @@ mysqlshow (1),
msql2mysql (1),
perror (1),
replace (1),
-safe_mysqld (1),
+mysqld_safe (1),
which1 (1),
zap (1),
.SH AUTHOR
diff --git a/man/isamlog.1 b/man/isamlog.1
index efc042ccd7c..ef6ceaff8da 100644
--- a/man/isamlog.1
+++ b/man/isamlog.1
@@ -83,7 +83,7 @@ mysqlshow (1),
msql2mysql (1),
perror (1),
replace (1),
-safe_mysqld (1),
+mysqld_safe (1),
which1 (1),
zap (1),
diff --git a/man/mysql.1 b/man/mysql.1
index 96ccca8f50e..e10fd589092 100644
--- a/man/mysql.1
+++ b/man/mysql.1
@@ -111,7 +111,7 @@ executable
.I /depot/bin/mysqld
executable
.TP
-.I /depot/bin/safe_mysqld
+.I /depot/bin/mysqld_safe
executable shell script for starting mysqld safely
.TP
.I /site/var/mysql/data
@@ -135,7 +135,7 @@ mysqlshow (1),
msql2mysql (1),
perror (1),
replace (1),
-safe_mysqld (1),
+mysqld_safe (1),
which1 (1),
zap (1),
.SH AUTHOR
diff --git a/man/mysql_zap.1 b/man/mysql_zap.1
index 98da195894e..e57eb7a4d07 100644
--- a/man/mysql_zap.1
+++ b/man/mysql_zap.1
@@ -28,7 +28,7 @@ isn't given, ask user for confirmation for each process to kill. If signal isn't
.BR -t
is given the processes is only shown on stdout.
.SH "SEE ALSO"
-isamchk (1), isamlog (1), mysqlaccess (1), mysqladmin (1), mysqlbug (1), mysqld (1), mysqldump (1), mysqlshow (1), msql2mysql (1), perror (1), replace (1), safe_mysqld (1), which1 (1), zap (1),
+isamchk (1), isamlog (1), mysqlaccess (1), mysqladmin (1), mysqlbug (1), mysqld (1), mysqldump (1), mysqlshow (1), msql2mysql (1), perror (1), replace (1), mysqld_safe (1), which1 (1), zap (1),
.SH AUTHOR
Ver 1.0, distribution 3.23.29a Michael (Monty) Widenius (monty@tcx.se), TCX Datakonsult AB (http://www.tcx.se). This software comes with no warranty. Manual page by L. (Kill-9) Pedersen (kill-9@kill-9.dk), Mercurmedia Data Model Architect / system developer (http://www.mercurmedia.com)
.\" end of man page \ No newline at end of file
diff --git a/man/mysqlaccess.1 b/man/mysqlaccess.1
index 888cfe8f646..0ae06dca137 100755..100644
--- a/man/mysqlaccess.1
+++ b/man/mysqlaccess.1
@@ -106,7 +106,7 @@ mysqlshow (1),
msql2mysql (1),
perror (1),
replace (1),
-safe_mysqld (1),
+mysqld_safe (1),
which1 (1),
zap (1),
.SH AUTHOR
diff --git a/man/mysqladmin.1 b/man/mysqladmin.1
index 58bd2070de6..1e435006bb2 100755..100644
--- a/man/mysqladmin.1
+++ b/man/mysqladmin.1
@@ -189,7 +189,7 @@ mysqlshow (1),
msql2mysql (1),
perror (1),
replace (1),
-safe_mysqld (1),
+mysqld_safe (1),
which1 (1),
zap (1),
.SH AUTHOR
diff --git a/man/mysqld.1 b/man/mysqld.1
index d3f22c0be1b..1f87eb9cf32 100755..100644
--- a/man/mysqld.1
+++ b/man/mysqld.1
@@ -137,7 +137,7 @@ Don't check the rows in the table if there isn't any delete blocks.
Before a table is automaticly repaired, mysqld will add a note about this in the error log. If you want to be able to recover from most things without user intervention, you should use the options BACKUP,FORCE. This will force a repair of a table even if some rows would be deleted, but it will keep the old data file as a backup so that you can later examine what happened.
.TP
.BR \-\-pid\-file=\fP\fIpath \fP
-Path to pid file used by safe_mysqld.
+Path to pid file used by mysqld_safe.
.TP
.BR \-P | \-\-port=...
Port number to listen for TCP/IP connections.
@@ -215,7 +215,7 @@ mysqlshow (1),
msql2mysql (1),
perror (1),
replace (1),
-safe_mysqld (1),
+mysqld_safe (1),
which1 (1),
zap (1),
.SH AUTHOR
diff --git a/man/mysqld_multi.1 b/man/mysqld_multi.1
index b68050e92ef..b7aa77f656d 100644
--- a/man/mysqld_multi.1
+++ b/man/mysqld_multi.1
@@ -36,7 +36,7 @@ Log file. Full path to and the name for the log file. NOTE: If the file exists,
mysqladmin binary to be used for a server shutdown.
.TP
.BR --mysqld=...
-mysqld binary to be used. Note that you can give safe_mysqld to this option also. The options are passed to mysqld. Just make sure you have mysqld in your environment variable PATH or fix safe_mysqld.
+mysqld binary to be used. Note that you can give mysqld_safe to this option also. The options are passed to mysqld. Just make sure you have mysqld in your environment variable PATH or fix mysqld_safe.
.TP
.BR --no-log
Print to stdout instead of the log file. By default the log file is turned on.
@@ -70,7 +70,7 @@ mysqlshow (1),
msql2mysql (1),
perror (1),
replace (1),
-safe_mysqld (1),
+mysqld_safe (1),
which1 (1),
zap (1),
diff --git a/man/safe_mysqld.1 b/man/mysqld_safe.1
index 3874801be3b..c900d193929 100755..100644
--- a/man/safe_mysqld.1
+++ b/man/mysqld_safe.1
@@ -1,8 +1,8 @@
.TH SAFE_MYSQLD 1 "19 December 2000" "safe_mysqld (mysql)" mysql.com
.SH NAME
-safe_mysqld \- start the mysqld daemon on Unix.
+mysqld_safe \- start the mysqld daemon on Unix.
.SH SYNOPSIS
-.B safe_mysqld
+.B mysqld_safe
.RB [ \-\-basedir=\fP\fIpath\fP ]
.RB [ \-\-core\-file\-size=# ]
.RB [ \-\-defaults\-extra\-file=\fP\fIpath\fP ]
@@ -20,21 +20,19 @@ safe_mysqld \- start the mysqld daemon on Unix.
.RB [ \-\-timezone=# ]
.RB [ \-\-user=# ]
.SH DESCRIPTION
-safe_mysqld adds some safety features such as restarting the server when an
+mysqld_safe adds some safety features such as restarting the server when an
error occurs and logging run-time information to a log file.
.BR
.TP
.BR \-\-basedir=\fP\fIpath \fP
.TP
-.BR \-\-core\-file\-size=#
+.BR \-\-core\-file\-size=#
+Size of the core file mysqld should be able to create. Passed to ulimit \-c.
.TP
.BR \-\-defaults\-extra\-file=\fP\fIpath \fP
.TP
.BR \-\-defaults\-file=\fP\fIpath \fP
.TP
-.BR \-\-open\-files=#
-Size of the core file mysqld should be able to create. Passed to ulimit \-c.
-.TP
.BR \-\-datadir=\fP\fIpath \fP
.TP
.BR \-\-err\-log=\fP\fIpath \fP
@@ -60,7 +58,7 @@ Set the timezone (the TZ) variable to the value of this parameter.
.TP
.BR \-\-user=#
.SH NOTE
-Note that all options on the command line to safe_mysqld are passed to mysqld. If you wants to use any options in safe_mysqld that mysqld doesn't support, you must specify these in the option file.
+Note that all options on the command line to mysqld_safe are passed to mysqld. If you wants to use any options in mysqld_safe that mysqld doesn't support, you must specify these in the option file.
.SH "SEE ALSO"
isamchk (1),
isamlog (1),
@@ -73,13 +71,13 @@ mysqlshow (1),
msql2mysql (1),
perror (1),
replace (1),
-safe_mysqld (1),
+mysqld_safe (1),
which1 (1),
zap (1),
.SH AUTHOR
Ver 1.0, distribution 3.23.29a
-Michael (Monty) Widenius (monty@tcx.se),
-TCX Datakonsult AB (http://www.tcx.se).
+Michael (Monty) Widenius (monty@mysql.com),
+MySQL AB (http://www.mysql.com).
This software comes with no warranty.
Manual page by L. (Kill-9) Pedersen
(kill-9@kill\-9.dk), Mercurmedia Data Model Architect /
diff --git a/man/mysqldump.1 b/man/mysqldump.1
index f108da17bf9..b9e5aa33791 100755..100644
--- a/man/mysqldump.1
+++ b/man/mysqldump.1
@@ -258,7 +258,7 @@ mysqlshow (1),
msql2mysql (1),
perror (1),
replace (1),
-safe_mysqld (1),
+mysqld_safe (1),
which1 (1),
zap (1),
.SH AUTHOR
diff --git a/man/mysqlshow.1 b/man/mysqlshow.1
index 55a87c1df78..661b2cd02c8 100755..100644
--- a/man/mysqlshow.1
+++ b/man/mysqlshow.1
@@ -78,7 +78,7 @@ mysqlshow (1),
msql2mysql (1),
perror (1),
replace (1),
-safe_mysqld (1),
+mysqld_safe (1),
which1 (1),
zap (1),
.SH AUTHOR
diff --git a/man/perror.1 b/man/perror.1
index 2853f2cb1ba..7adf99ea772 100755..100644
--- a/man/perror.1
+++ b/man/perror.1
@@ -43,7 +43,7 @@ mysqlshow (1),
msql2mysql (1),
perror (1),
replace (1),
-safe_mysqld (1),
+mysqld_safe (1),
which1 (1),
zap (1),
.SH AUTHOR
diff --git a/man/replace.1 b/man/replace.1
index 10bcf64fc88..38ffe998027 100644
--- a/man/replace.1
+++ b/man/replace.1
@@ -52,7 +52,7 @@ mysqlshow (1),
msql2mysql (1),
perror (1),
replace (1),
-safe_mysqld (1),
+mysqld_safe (1),
which1 (1),
zap (1),
.SH AUTHOR
diff --git a/man/which.2 b/man/which.2
index 599b68080a2..30d5557ed01 100644
--- a/man/which.2
+++ b/man/which.2
@@ -48,7 +48,7 @@ Ignore option
.BR --read-alias;
don\'t read stdin.
.SH "SEE ALSO"
-isamchk (1), isamlog (1), mysqlaccess (1), mysqladmin (1), mysqlbug (1), mysqld (1), mysqldump (1), mysqlshow (1), msql2mysql (1), perror (1), replace (1), safe_mysqld (1), which1 (1), zap (1),
+isamchk (1), isamlog (1), mysqlaccess (1), mysqladmin (1), mysqlbug (1), mysqld (1), mysqldump (1), mysqlshow (1), msql2mysql (1), perror (1), replace (1), mysqld_safe (1), which1 (1), zap (1),
.SH AUTHOR
Ver 1.0, distribution 3.23.29a Michael (Monty) Widenius (monty@tcx.se), TCX Datakonsult AB (http://www.tcx.se). This software comes with no warranty. Manual page by L. (Kill-9) Pedersen (kill-9@kill-9.dk), Mercurmedia Data Model Architect / system developer (http://www.mercurmedia.com)
.\" end of man page \ No newline at end of file
diff --git a/merge/Makefile.am b/merge/Makefile.am
index 52abfc4cdc0..94de6d65391 100644
--- a/merge/Makefile.am
+++ b/merge/Makefile.am
@@ -16,10 +16,10 @@
INCLUDES = @MT_INCLUDES@ -I$(srcdir)/../include -I../include
pkglib_LIBRARIES = libmerge.a
-noinst_HEADERS = mrgdef.h
-libmerge_a_SOURCES = open.c extra.c info.c _locking.c \
- rrnd.c update.c delete.c rsame.c panic.c \
- close.c create.c static.c
+noinst_HEADERS = mrg_def.h
+libmerge_a_SOURCES = mrg_open.c mrg_extra.c mrg_info.c mrg_locking.c \
+ mrg_rrnd.c mrg_update.c mrg_delete.c mrg_rsame.c \
+ mrg_panic.c mrg_close.c mrg_create.c mrg_static.c
OMIT_DEPENDENCIES = pthread.h stdio.h __stdio.h stdlib.h __stdlib.h math.h\
__math.h time.h __time.h unistd.h __unistd.h types.h \
diff --git a/merge/close.c b/merge/mrg_close.c
index 2b769ade8e9..e835fd06e47 100644
--- a/merge/close.c
+++ b/merge/mrg_close.c
@@ -1,22 +1,22 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/* close a isam-database */
-#include "mrgdef.h"
+#include "mrg_def.h"
int mrg_close(register MRG_INFO *info)
{
diff --git a/merge/create.c b/merge/mrg_create.c
index fd2c16f9ea2..d55a1421647 100644
--- a/merge/create.c
+++ b/merge/mrg_create.c
@@ -1,22 +1,22 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/* Create a MERGE-file */
-#include "mrgdef.h"
+#include "mrg_def.h"
/* create file named 'name' and save filenames in it
table_names should be NULL or a vector of string-pointers with
diff --git a/merge/mrgdef.h b/merge/mrg_def.h
index 3f22c83589a..8b6be08c32d 100644
--- a/merge/mrgdef.h
+++ b/merge/mrg_def.h
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
diff --git a/merge/delete.c b/merge/mrg_delete.c
index a4ee46eedc2..920156be01e 100644
--- a/merge/delete.c
+++ b/merge/mrg_delete.c
@@ -1,22 +1,22 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/* Delete last read record */
-#include "mrgdef.h"
+#include "mrg_def.h"
int mrg_delete(MRG_INFO *info,const byte *record)
{
diff --git a/merge/extra.c b/merge/mrg_extra.c
index c4f048a4385..d37b1aaa03c 100644
--- a/merge/extra.c
+++ b/merge/mrg_extra.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -20,7 +20,7 @@
record-cache-flags are set in mrg_rrnd when we are changing database.
*/
-#include "mrgdef.h"
+#include "mrg_def.h"
int mrg_extra(
MRG_INFO *info,
diff --git a/merge/info.c b/merge/mrg_info.c
index d44ada8e6e6..57f22276487 100644
--- a/merge/info.c
+++ b/merge/mrg_info.c
@@ -1,20 +1,20 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-#include "mrgdef.h"
+#include "mrg_def.h"
ulong mrg_position(MRG_INFO *info)
{
diff --git a/merge/_locking.c b/merge/mrg_locking.c
index 81582da1312..bd33e047091 100644
--- a/merge/_locking.c
+++ b/merge/mrg_locking.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -18,7 +18,7 @@
Lock databases against read or write.
*/
-#include "mrgdef.h"
+#include "mrg_def.h"
int mrg_lock_database(MRG_INFO *info,int lock_type)
{
diff --git a/merge/open.c b/merge/mrg_open.c
index c1be98b7e18..83b776ea201 100644
--- a/merge/open.c
+++ b/merge/mrg_open.c
@@ -1,22 +1,22 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/* open a MERGE-database */
-#include "mrgdef.h"
+#include "mrg_def.h"
#include <stddef.h>
#include <errno.h>
#ifdef VMS
@@ -36,7 +36,7 @@ int mode,
int handle_locking)
{
int save_errno,i,errpos;
- uint files,dir_length,length;
+ uint files,dir_length,length, options;
ulonglong file_offset;
char name_buff[FN_REFLEN*2],buff[FN_REFLEN],*end;
MRG_INFO info,*m_info;
@@ -90,16 +90,22 @@ int handle_locking)
m_info->open_tables=(MRG_TABLE *) (m_info+1);
m_info->tables=files;
+ options= (uint) ~0;
for (i=files ; i-- > 0 ; )
{
m_info->open_tables[i].table=isam;
m_info->options|=isam->s->base.options;
+ options&=isam->s->base.options;
m_info->records+=isam->s->state.records;
m_info->del+=isam->s->state.del;
m_info->data_file_length=isam->s->state.data_file_length;
if (i)
isam=(N_INFO*) (isam->open_list.next->data);
}
+ /* Don't force readonly if not all tables are readonly */
+ if (! (options & (HA_OPTION_COMPRESS_RECORD | HA_OPTION_READ_ONLY_DATA)))
+ m_info->options&= ~(HA_OPTION_COMPRESS_RECORD | HA_OPTION_READ_ONLY_DATA);
+
/* Fix fileinfo for easyer debugging (actually set by rrnd) */
file_offset=0;
for (i=0 ; (uint) i < files ; i++)
diff --git a/merge/panic.c b/merge/mrg_panic.c
index cf333e3a9bf..e9ad1974d8f 100644
--- a/merge/panic.c
+++ b/merge/mrg_panic.c
@@ -1,20 +1,20 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-#include "mrgdef.h"
+#include "mrg_def.h"
/* if flag == HA_PANIC_CLOSE then all misam files are closed */
/* if flag == HA_PANIC_WRITE then all misam files are unlocked and
diff --git a/merge/rrnd.c b/merge/mrg_rrnd.c
index e53982aca21..206427d74d4 100644
--- a/merge/rrnd.c
+++ b/merge/mrg_rrnd.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -19,7 +19,7 @@
get by mrg_info(). The next record can be read with pos= -1 */
-#include "mrgdef.h"
+#include "mrg_def.h"
static MRG_TABLE *find_table(MRG_TABLE *start,MRG_TABLE *end,mrg_off_t pos);
diff --git a/merge/rsame.c b/merge/mrg_rsame.c
index 4ebf25b21c1..ee840bc3060 100644
--- a/merge/rsame.c
+++ b/merge/mrg_rsame.c
@@ -1,20 +1,20 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-#include "mrgdef.h"
+#include "mrg_def.h"
int mrg_rsame(
diff --git a/merge/static.c b/merge/mrg_static.c
index e5f95ef195a..1b7327c870f 100644
--- a/merge/static.c
+++ b/merge/mrg_static.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -20,7 +20,7 @@
*/
#ifndef stdin
-#include "mrgdef.h"
+#include "mrg_def.h"
#endif
LIST *mrg_open_list=0;
diff --git a/merge/update.c b/merge/mrg_update.c
index 9fcb82089e4..a6650267f36 100644
--- a/merge/update.c
+++ b/merge/mrg_update.c
@@ -1,22 +1,22 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/* Update last read record */
-#include "mrgdef.h"
+#include "mrg_def.h"
int mrg_update(
register MRG_INFO *info,
diff --git a/myisam/Makefile.am b/myisam/Makefile.am
index a18ff55ba9e..6802bcb115f 100644
--- a/myisam/Makefile.am
+++ b/myisam/Makefile.am
@@ -1,15 +1,15 @@
# Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-#
+#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
-#
+#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
-#
+#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
@@ -17,7 +17,7 @@
EXTRA_DIST = mi_test_all.sh mi_test_all.res
pkgdata_DATA = mi_test_all mi_test_all.res
-INCLUDES = @MT_INCLUDES@ -I$(srcdir)/../include -I../include
+INCLUDES = @MT_INCLUDES@ -I$(srcdir)/../include -I../include
LDADD = @CLIENT_EXTRA_LDFLAGS@ libmyisam.a ../mysys/libmysys.a \
../dbug/libdbug.a ../strings/libmystrings.a
pkglib_LIBRARIES = libmyisam.a
@@ -25,13 +25,14 @@ bin_PROGRAMS = myisamchk myisamlog myisampack
myisamchk_DEPENDENCIES= $(LIBRARIES)
myisamlog_DEPENDENCIES= $(LIBRARIES)
myisampack_DEPENDENCIES=$(LIBRARIES)
-noinst_PROGRAMS = mi_test1 mi_test2 mi_test3 ft_test1 ft_eval
+noinst_PROGRAMS = mi_test1 mi_test2 mi_test3 ft_dump #ft_test1 ft_eval
noinst_HEADERS = myisamdef.h fulltext.h ftdefs.h ft_test1.h ft_eval.h
mi_test1_DEPENDENCIES= $(LIBRARIES)
mi_test2_DEPENDENCIES= $(LIBRARIES)
mi_test3_DEPENDENCIES= $(LIBRARIES)
-ft_test1_DEPENDENCIES= $(LIBRARIES)
-ft_eval_DEPENDENCIES= $(LIBRARIES)
+#ft_test1_DEPENDENCIES= $(LIBRARIES)
+#ft_eval_DEPENDENCIES= $(LIBRARIES)
+ft_dump_DEPENDENCIES= $(LIBRARIES)
libmyisam_a_SOURCES = mi_open.c mi_extra.c mi_info.c mi_rkey.c \
mi_rnext.c mi_rnext_same.c \
mi_search.c mi_page.c mi_key.c mi_locking.c \
@@ -44,8 +45,8 @@ libmyisam_a_SOURCES = mi_open.c mi_extra.c mi_info.c mi_rkey.c \
mi_range.c mi_dbug.c mi_checksum.c mi_log.c \
mi_changed.c mi_static.c mi_delete_all.c \
mi_delete_table.c mi_rename.c mi_check.c \
- ft_parser.c ft_search.c ft_stopwords.c ft_static.c \
- ft_update.c sort.c
+ ft_parser.c ft_stopwords.c ft_static.c \
+ ft_update.c ft_boolean_search.c ft_nlq_search.c sort.c
CLEANFILES = test?.MY? FT?.MY? isam.log mi_test_all
DEFS = -DMAP_TO_USE_RAID
# Omit dependency for ../mit-pthreads/include/sys that only exits if
diff --git a/myisam/ft_boolean_search.c b/myisam/ft_boolean_search.c
new file mode 100644
index 00000000000..c4e29bd636b
--- /dev/null
+++ b/myisam/ft_boolean_search.c
@@ -0,0 +1,462 @@
+/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+/* Written by Sergei A. Golubchik, who has a shared copyright to this code */
+
+/* TODO: add caching - pre-read several index entries at once */
+
+#define FT_CORE
+#include "ftdefs.h"
+#include <queues.h>
+
+/* search with boolean queries */
+
+static double _wghts[11]={
+ 0.131687242798354,
+ 0.197530864197531,
+ 0.296296296296296,
+ 0.444444444444444,
+ 0.666666666666667,
+ 1.000000000000000,
+ 1.500000000000000,
+ 2.250000000000000,
+ 3.375000000000000,
+ 5.062500000000000,
+ 7.593750000000000};
+static double *wghts=_wghts+5; /* wghts[i] = 1.5**i */
+
+static double _nwghts[11]={
+ -0.065843621399177,
+ -0.098765432098766,
+ -0.148148148148148,
+ -0.222222222222222,
+ -0.333333333333334,
+ -0.500000000000000,
+ -0.750000000000000,
+ -1.125000000000000,
+ -1.687500000000000,
+ -2.531250000000000,
+ -3.796875000000000};
+static double *nwghts=_nwghts+5; /* nwghts[i] = -0.5*1.5**i */
+
+typedef struct st_ftb_expr FTB_EXPR;
+struct st_ftb_expr {
+ FTB_EXPR *up;
+ float weight;
+ int yesno;
+ my_off_t docid;
+ float cur_weight;
+ int yesses; /* number of "yes" words matched */
+ int nos; /* number of "no" words matched */
+ int ythresh; /* number of "yes" words in expr */
+};
+
+typedef struct {
+ FTB_EXPR *up;
+ float weight;
+ int yesno;
+ int trunc;
+ my_off_t docid;
+ uint ndepth;
+ int len;
+ /* ... there can be docid cache added here. SerG */
+ byte word[1];
+} FTB_WORD;
+
+typedef struct st_ft_info {
+ struct _ft_vft *please;
+ MI_INFO *info;
+ uint keynr;
+ enum { UNINITIALIZED, READY, INDEX_SEARCH, INDEX_DONE, SCAN } state;
+ FTB_EXPR *root;
+ QUEUE queue;
+ MEM_ROOT mem_root;
+} FTB;
+
+int FTB_WORD_cmp(void *v __attribute__((unused)), byte *a, byte *b)
+{
+ /* ORDER BY docid, ndepth DESC */
+ int i=CMP_NUM(((FTB_WORD *)a)->docid, ((FTB_WORD *)b)->docid);
+ if (!i)
+ i=CMP_NUM(((FTB_WORD *)b)->ndepth,((FTB_WORD *)a)->ndepth);
+ return i;
+}
+
+void _ftb_parse_query(FTB *ftb, byte **start, byte *end,
+ FTB_EXPR *up, uint ndepth, uint depth)
+{
+ byte res;
+ FTB_PARAM param;
+ FT_WORD w;
+ FTB_WORD *ftbw;
+ FTB_EXPR *ftbe;
+ uint extra=HA_FT_WLEN+ftb->info->s->rec_reflength; /* just a shortcut */
+
+ if (ftb->state != UNINITIALIZED)
+ return;
+
+ param.prev=' ';
+ while ((res=ft_get_word(start,end,&w,&param)))
+ {
+ byte r=param.plusminus;
+ float weight= (float) (param.pmsign ? nwghts : wghts)[(r>5)?5:((r<-5)?-5:r)];
+ switch (res) {
+ case 1: /* word found */
+ ftbw=(FTB_WORD *)alloc_root(&ftb->mem_root,
+ sizeof(FTB_WORD) +
+ (param.trunc ? MI_MAX_KEY_BUFF :
+ w.len+extra));
+ ftbw->len=w.len+1;
+ ftbw->yesno=param.yesno;
+ ftbw->trunc=param.trunc; /* 0 or 1 */
+ ftbw->weight=weight;
+ ftbw->up=up;
+ ftbw->docid=HA_POS_ERROR;
+ ftbw->ndepth= param.yesno<0 ? depth : ndepth;
+ memcpy(ftbw->word+1, w.pos, w.len);
+ ftbw->word[0]=w.len;
+ if (ftbw->yesno > 0) up->ythresh++;
+ queue_insert(& ftb->queue, (byte *)ftbw);
+ break;
+ case 2: /* left bracket */
+ ftbe=(FTB_EXPR *)alloc_root(&ftb->mem_root, sizeof(FTB_EXPR));
+ ftbe->yesno=param.yesno;
+ ftbe->weight=weight;
+ ftbe->up=up;
+ ftbe->ythresh=0;
+ ftbe->docid=HA_POS_ERROR;
+ if (ftbe->yesno > 0) up->ythresh++;
+ _ftb_parse_query(ftb, start, end, ftbe, depth+1,
+ (param.yesno<0 ? depth+1 : ndepth));
+ break;
+ case 3: /* right bracket */
+ return;
+ }
+ }
+ return;
+}
+
+void _ftb_init_index_search(FT_INFO *ftb)
+{
+ int i, r;
+ FTB_WORD *ftbw;
+ MI_INFO *info=ftb->info;
+ MI_KEYDEF *keyinfo;
+ my_off_t keyroot;
+
+ if (ftb->state != READY || ftb->keynr == NO_SUCH_KEY)
+ return;
+ ftb->state=INDEX_SEARCH;
+
+ keyinfo=info->s->keyinfo+ftb->keynr;
+ keyroot=info->s->state.key_root[ftb->keynr];
+
+ for (i=ftb->queue.elements; i; i--)
+ {
+ ftbw=(FTB_WORD *)(ftb->queue.root[i]);
+
+ r=_mi_search(info, keyinfo, (uchar*) ftbw->word, ftbw->len,
+ SEARCH_FIND | SEARCH_PREFIX, keyroot);
+ if (!r)
+ {
+ r=_mi_compare_text(default_charset_info,
+ info->lastkey+ftbw->trunc,ftbw->len-ftbw->trunc,
+ (uchar*) ftbw->word+ftbw->trunc,ftbw->len-ftbw->trunc,
+ 0);
+ }
+ if (r) /* not found */
+ {
+ if (ftbw->yesno>0 && ftbw->up->up==0)
+ { /* this word MUST BE present in every document returned,
+ so we can abort the search right now */
+ ftb->state=INDEX_DONE;
+ return;
+ }
+ }
+ else
+ {
+ memcpy(ftbw->word, info->lastkey, info->lastkey_length);
+ ftbw->docid=info->lastpos;
+ }
+ }
+ queue_fix(& ftb->queue);
+}
+
+FT_INFO * ft_init_boolean_search(MI_INFO *info, uint keynr, byte *query,
+ uint query_len, my_bool presort __attribute__((unused)))
+{
+ FTB *ftb;
+ FTB_EXPR *ftbe;
+ uint res;
+
+ if (!(ftb=(FTB *)my_malloc(sizeof(FTB), MYF(MY_WME))))
+ return 0;
+ ftb->please= (struct _ft_vft *) & _ft_vft_boolean;
+ ftb->state=UNINITIALIZED;
+ ftb->info=info;
+ ftb->keynr=keynr;
+
+ init_alloc_root(&ftb->mem_root, 1024, 1024);
+
+ /* hack: instead of init_queue, we'll use reinit queue to be able
+ * to alloc queue with alloc_root()
+ */
+ res=ftb->queue.max_elements=query_len/(ft_min_word_len+1);
+ ftb->queue.root=(byte **)alloc_root(&ftb->mem_root, (res+1)*sizeof(void*));
+ reinit_queue(& ftb->queue, res, 0, 0, FTB_WORD_cmp, ftb);
+ ftbe=(FTB_EXPR *)alloc_root(&ftb->mem_root, sizeof(FTB_EXPR));
+ ftbe->weight=1;
+ ftbe->yesno=ftbe->nos=1;
+ ftbe->up=0;
+ ftbe->ythresh=0;
+ ftbe->docid=HA_POS_ERROR;
+ ftb->root=ftbe;
+ _ftb_parse_query(ftb, &query, query+query_len, ftbe, 0, 0);
+ ftb->state=READY;
+ return ftb;
+}
+
+void _ftb_climb_the_tree(FTB_WORD *ftbw)
+{
+ FTB_EXPR *ftbe;
+ float weight=ftbw->weight;
+ int yn=ftbw->yesno;
+ my_off_t curdoc=ftbw->docid;
+
+ for (ftbe=ftbw->up; ftbe; ftbe=ftbe->up)
+ {
+ if (ftbe->docid != curdoc)
+ {
+ ftbe->cur_weight=0;
+ ftbe->yesses=ftbe->nos=0;
+ ftbe->docid=curdoc;
+ }
+ if (ftbe->nos)
+ break;
+ if (yn>0)
+ {
+ ftbe->cur_weight+=weight;
+ if (++ftbe->yesses == ftbe->ythresh)
+ {
+ yn=ftbe->yesno;
+ weight=ftbe->cur_weight*ftbe->weight;
+ }
+ else
+ break;
+ }
+ else
+ if (yn<0)
+ {
+ /* NOTE: special sort function of queue assures that all yn<0
+ * events for every particular subexpression will
+ * "auto-magically" happen BEFORE all the yn>=0 events. So no
+ * already matched expression can become not-matched again.
+ */
+ ++ftbe->nos;
+ break;
+ }
+ else
+ /* if (yn==0) */
+ {
+ ftbe->cur_weight+=weight;
+ if (ftbe->yesses < ftbe->ythresh)
+ break;
+ yn= (ftbe->yesses++ == ftbe->ythresh) * ftbe->yesno;
+ weight*=ftbe->weight;
+ }
+ }
+}
+
+int ft_boolean_read_next(FT_INFO *ftb, char *record)
+{
+ FTB_EXPR *ftbe;
+ FTB_WORD *ftbw;
+ MI_INFO *info=ftb->info;
+ MI_KEYDEF *keyinfo=info->s->keyinfo+ftb->keynr;
+ my_off_t keyroot=info->s->state.key_root[ftb->keynr];
+ my_off_t curdoc;
+ int r;
+
+ if (ftb->state != INDEX_SEARCH && ftb->state != INDEX_DONE)
+ return -1;
+
+ /* black magic ON */
+ if ((int) _mi_check_index(info, ftb->keynr) < 0)
+ return my_errno;
+ if (_mi_readinfo(info, F_RDLCK, 1))
+ return my_errno;
+ /* black magic OFF */
+
+ if (!ftb->queue.elements)
+ return my_errno=HA_ERR_END_OF_FILE;
+
+ while(ftb->state == INDEX_SEARCH &&
+ (curdoc=((FTB_WORD *)queue_top(& ftb->queue))->docid) != HA_POS_ERROR)
+ {
+ while (curdoc==(ftbw=(FTB_WORD *)queue_top(& ftb->queue))->docid)
+ {
+ _ftb_climb_the_tree(ftbw);
+
+ /* update queue */
+ r=_mi_search(info, keyinfo, (uchar*) ftbw->word, USE_WHOLE_KEY,
+ SEARCH_BIGGER , keyroot);
+ if (!r)
+ {
+ r=_mi_compare_text(default_charset_info,
+ info->lastkey+ftbw->trunc,ftbw->len-ftbw->trunc,
+ (uchar*) ftbw->word+ftbw->trunc,
+ ftbw->len-ftbw->trunc,0);
+ }
+ if (r) /* not found */
+ {
+ ftbw->docid=HA_POS_ERROR;
+ if (ftbw->yesno>0 && ftbw->up->up==0)
+ { /* this word MUST BE present in every document returned,
+ so we can stop the search right now */
+ ftb->state=INDEX_DONE;
+ }
+ }
+ else
+ {
+ memcpy(ftbw->word, info->lastkey, info->lastkey_length);
+ ftbw->docid=info->lastpos;
+ }
+ queue_replaced(& ftb->queue);
+ }
+
+ ftbe=ftb->root;
+ if (ftbe->docid==curdoc && ftbe->cur_weight>0 &&
+ ftbe->yesses>=ftbe->ythresh && !ftbe->nos)
+ {
+ /* curdoc matched ! */
+ info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED); /* why is this ? */
+
+ info->lastpos=curdoc;
+ if (!(*info->read_record)(info,curdoc,record))
+ {
+ info->update|= HA_STATE_AKTIV; /* Record is read */
+ return 0;
+ }
+ return my_errno;
+ }
+ }
+ ftb->state=INDEX_DONE;
+ return my_errno=HA_ERR_END_OF_FILE;
+}
+
+float ft_boolean_find_relevance(FT_INFO *ftb, byte *record, uint length)
+{
+ FT_WORD word;
+ FTB_WORD *ftbw;
+ FTB_EXPR *ftbe;
+ FT_SEG_ITERATOR ftsi;
+ const byte *end;
+ uint i;
+ my_off_t docid=ftb->info->lastpos;
+
+ if (docid == HA_POS_ERROR)
+ return -2.0;
+ if (!ftb->queue.elements)
+ return 0;
+ if (ftb->state == READY || ftb->state == INDEX_DONE)
+ {
+ for (i=1; i<=ftb->queue.elements; i++)
+ {
+ ftbw=(FTB_WORD *)(ftb->queue.root[i]);
+ ftbw->docid=HA_POS_ERROR;
+ for (ftbe=ftbw->up; ftbe; ftbe=ftbe->up)
+ {
+ if (ftbe->docid != HA_POS_ERROR)
+ {
+ ftbe->cur_weight=0;
+ ftbe->yesses=ftbe->nos=0;
+ ftbe->docid=HA_POS_ERROR;
+ }
+ else
+ break;
+ }
+ }
+
+ queue_fix(& ftb->queue);
+ ftb->state=SCAN;
+ }
+ else if (ftb->state != SCAN)
+ return -3.0;
+
+ if (ftb->keynr==NO_SUCH_KEY)
+ _mi_ft_segiterator_dummy_init(record, length, &ftsi);
+ else
+ _mi_ft_segiterator_init(ftb->info, ftb->keynr, record, &ftsi);
+
+ while (_mi_ft_segiterator(&ftsi))
+ {
+ if (!ftsi.pos)
+ continue;
+
+ end=ftsi.pos+ftsi.len;
+ while (ft_simple_get_word((byte **)&ftsi.pos,(byte *)end,&word))
+ {
+ uint a, b, c;
+ for (a=1, b=ftb->queue.elements+1, c=(a+b)/2; b-a>1; c=(a+b)/2)
+ {
+ ftbw=(FTB_WORD *)(ftb->queue.root[c]);
+ if (_mi_compare_text(default_charset_info, word.pos,word.len,
+ (uchar*) ftbw->word+1,ftbw->len-1,ftbw->trunc) >0)
+ b=c;
+ else
+ a=c;
+ }
+ for (; c; c--)
+ {
+ ftbw=(FTB_WORD *)(ftb->queue.root[c]);
+ if (_mi_compare_text(default_charset_info, word.pos,word.len,
+ (uchar*) ftbw->word+1,ftbw->len-1,ftbw->trunc))
+ break;
+ if (ftbw->docid == docid)
+ continue;
+ ftbw->docid=docid;
+ _ftb_climb_the_tree(ftbw);
+ }
+ }
+ }
+
+ ftbe=ftb->root;
+ if (ftbe->docid==docid && ftbe->cur_weight>0 &&
+ ftbe->yesses>=ftbe->ythresh && !ftbe->nos)
+ { /* row matched ! */
+ return ftbe->cur_weight;
+ }
+ else
+ { /* match failed ! */
+ return 0.0;
+ }
+}
+
+void ft_boolean_close_search(FT_INFO *ftb)
+{
+ free_root(& ftb->mem_root, MYF(0));
+ my_free((gptr)ftb,MYF(0));
+}
+
+float ft_boolean_get_relevance(FT_INFO *ftb)
+{
+ return ftb->root->cur_weight;
+}
+
+void ft_boolean_reinit_search(FT_INFO *ftb)
+{
+ _ftb_init_index_search(ftb);
+}
diff --git a/myisam/ft_dump.c b/myisam/ft_dump.c
new file mode 100644
index 00000000000..6308694b58e
--- /dev/null
+++ b/myisam/ft_dump.c
@@ -0,0 +1,233 @@
+/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+/* Written by Sergei A. Golubchik, who has a shared copyright to this code */
+
+#include "ftdefs.h"
+#include <getopt.h>
+
+static void get_options(int argc,char *argv[]);
+static void usage(char *argv[]);
+static void complain(int val);
+
+static int count=0, stats=0, dump=0, verbose=0, lstats=0;
+static char *query=NULL;
+static uint lengths[256];
+
+#define MAX_LEN (HA_FT_MAXLEN+10)
+#define HOW_OFTEN_TO_WRITE 10000
+
+int main(int argc,char *argv[])
+{
+ int error=0;
+ uint keylen, keylen2=0, inx, doc_cnt=0;
+ float weight;
+ double gws, min_gws=0, avg_gws=0;
+ MI_INFO *info;
+ char buf[MAX_LEN], buf2[MAX_LEN], buf_maxlen[MAX_LEN], buf_min_gws[MAX_LEN];
+ ulong total=0, maxlen=0, uniq=0, max_doc_cnt=0;
+ struct { MI_INFO *info; } aio0, *aio=&aio0; /* for GWS_IN_USE */
+
+ MY_INIT(argv[0]);
+ get_options(argc,argv);
+ if (count || dump)
+ verbose=0;
+ if (!count && !dump && !lstats && !query)
+ stats=1;
+
+ if (verbose)
+ setbuf(stdout,NULL);
+
+ if (argc-optind < 2)
+ usage(argv);
+
+ if (!(info=mi_open(argv[optind],2,HA_OPEN_ABORT_IF_LOCKED)))
+ goto err;
+
+ inx=atoi(argv[optind+1]);
+ *buf2=0;
+ aio->info=info;
+
+ if ((inx >= info->s->base.keys) || !(info->s->keyinfo[inx].flag & HA_FULLTEXT))
+ {
+ printf("Key %d in table %s is not a FULLTEXT key\n", inx, info->filename);
+ goto err;
+ }
+
+ if (query)
+ {
+#if 0
+ FT_DOCLIST *result;
+ int i;
+
+ ft_init_stopwords(ft_precompiled_stopwords);
+
+ result=ft_nlq_init_search(info,inx,query,strlen(query),1);
+ if(!result)
+ goto err;
+
+ if (verbose)
+ printf("%d rows matched\n",result->ndocs);
+
+ for(i=0 ; i<result->ndocs ; i++)
+ printf("%9qx %20.7f\n",result->doc[i].dpos,result->doc[i].weight);
+
+ ft_nlq_close_search(result);
+#else
+ printf("-e option is disabled\n");
+#endif
+ }
+ else
+ {
+ info->lastpos= HA_OFFSET_ERROR;
+ info->update|= HA_STATE_PREV_FOUND;
+
+ while (!(error=mi_rnext(info,NULL,inx)))
+ {
+ keylen=*(info->lastkey);
+
+#if HA_FT_WTYPE == HA_KEYTYPE_FLOAT
+ mi_float4get(weight,info->lastkey+keylen+1);
+#else
+#error
+#endif
+
+ snprintf(buf,MAX_LEN,"%.*s",(int) keylen,info->lastkey+1);
+ casedn_str(buf);
+ total++;
+ lengths[keylen]++;
+
+ if (count || stats)
+ {
+ doc_cnt++;
+ if (strcmp(buf, buf2))
+ {
+ if (*buf2)
+ {
+ uniq++;
+ avg_gws+=gws=GWS_IN_USE;
+ if (count)
+ printf("%9u %20.7f %s\n",doc_cnt,gws,buf2);
+ if (maxlen<keylen2)
+ {
+ maxlen=keylen2;
+ strcpy(buf_maxlen, buf2);
+ }
+ if (max_doc_cnt < doc_cnt)
+ {
+ max_doc_cnt=doc_cnt;
+ strcpy(buf_min_gws, buf2);
+ min_gws=gws;
+ }
+ }
+ strcpy(buf2, buf);
+ keylen2=keylen;
+ doc_cnt=0;
+ }
+ }
+ if (dump)
+ printf("%9qx %20.7f %s\n",info->lastpos,weight,buf);
+
+ if(verbose && (total%HOW_OFTEN_TO_WRITE)==0)
+ printf("%10ld\r",total);
+ }
+
+ if (stats)
+ {
+ count=0;
+ for (inx=0;inx<256;inx++)
+ {
+ count+=lengths[inx];
+ if ((ulong) count >= total/2)
+ break;
+ }
+ printf("Total rows: %qu\nTotal words: %lu\n"
+ "Unique words: %lu\nLongest word: %lu chars (%s)\n"
+ "Median length: %u\n"
+ "Average global weight: %f\n"
+ "Most common word: %lu times, weight: %f (%s)\n",
+ (ulonglong)info->state->records, total, uniq, maxlen, buf_maxlen,
+ inx, avg_gws/uniq, max_doc_cnt, min_gws, buf_min_gws);
+ }
+ if (lstats)
+ {
+ count=0;
+ for (inx=0; inx<256; inx++)
+ {
+ count+=lengths[inx];
+ if (count && lengths[inx])
+ printf("%3u: %10lu %5.2f%% %20lu %4.1f%%\n", inx,
+ (ulong) lengths[inx],100.0*lengths[inx]/total,(ulong) count,
+ 100.0*count/total);
+ }
+ }
+ }
+
+err:
+ if (error && error != HA_ERR_END_OF_FILE)
+ printf("got error %d\n",my_errno);
+ if (info)
+ mi_close(info);
+ return 0;
+}
+
+const char *options="dslcvh";
+
+static void get_options(int argc, char *argv[])
+{
+ int c;
+
+ while ((c=getopt(argc,argv,options)) != -1)
+ {
+ switch(c) {
+ case 'd': dump=1; complain(count || query); break;
+ case 's': stats=1; complain(query!=0); break;
+ case 'v': verbose=1; break;
+ case 'c': count=1; complain(dump || query); break;
+ case 'l': lstats=1; complain(query!=0); break;
+ case 'e': query=my_strdup(optarg,MYF(MY_FAE)); complain(dump || count || stats); break;
+ case '?':
+ case 'h':
+ default:
+ usage(argv);
+ }
+ }
+ return;
+} /* get options */
+
+static void usage(char *argv[])
+{
+ printf("\n\
+Use: %s [-%s] <table_name> <index_no>\n\
+\n\
+-d Dump index (incl. data offsets and word weights)\n\
+-s Report global stats\n\
+-c Calculate per-word stats (counts and global weights)\n\
+-l Report length distribution\n\
+-v Be verbose\n\
+-h This text\n\
+", *argv, options);
+ exit(1);
+}
+
+static void complain(int val) /* Kinda assert :-) */
+{
+ if (val)
+ {
+ printf("You cannot use these options together!\n");
+ exit(1);
+ }
+}
diff --git a/myisam/ft_eval.c b/myisam/ft_eval.c
index 9466104100a..c498725daab 100644
--- a/myisam/ft_eval.c
+++ b/myisam/ft_eval.c
@@ -32,7 +32,7 @@ int main(int argc,char *argv[])
bzero((char*)recinfo,sizeof(recinfo));
/* First define 2 columns */
- recinfo[0].type=FIELD_SKIPP_ENDSPACE;
+ recinfo[0].type=FIELD_SKIP_ENDSPACE;
recinfo[0].length=docid_length;
recinfo[1].type=FIELD_BLOB;
recinfo[1].length= 4+mi_portable_sizeof_char_ptr;
@@ -83,23 +83,23 @@ int main(int argc,char *argv[])
for(i=1;create_record(record,qf);i++) {
FT_DOCLIST *result; double w; int t,err;
- result=ft_init_search(file,0,blob_record,(uint) strlen(blob_record),1);
+ result=ft_nlq_init_search(file,0,blob_record,(uint) strlen(blob_record),1);
if(!result) {
printf("Query %d failed with errno %3d\n",i,my_errno);
goto err;
}
if (!silent)
printf("Query %d. Found: %d.\n",i,result->ndocs);
- for(j=0;(err=ft_read_next(result, read_record))==0;j++) {
+ for(j=0;(err=ft_nlq_read_next(result, read_record))==0;j++) {
t=uint2korr(read_record);
- w=ft_get_relevance(result);
+ w=ft_nlq_get_relevance(result);
printf("%d %.*s %f\n",i,t,read_record+2,w);
}
if(err != HA_ERR_END_OF_FILE) {
printf("ft_read_next %d failed with errno %3d\n",j,my_errno);
goto err;
}
- ft_close_search(result);
+ ft_nlq_close_search(result);
}
if (mi_close(file)) goto err;
diff --git a/myisam/ft_eval.h b/myisam/ft_eval.h
index d87b6be9c7c..68be3a39f33 100644
--- a/myisam/ft_eval.h
+++ b/myisam/ft_eval.h
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & Sergei A. Golubchik
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -40,4 +40,3 @@ MI_KEYSEG keyseg[10];
#define MAX_LINE_LENGTH 128
char line[MAX_LINE_LENGTH];
-
diff --git a/myisam/ft_search.c b/myisam/ft_nlq_search.c
index 9a728a4c211..ac9fa5a9a8c 100644
--- a/myisam/ft_search.c
+++ b/myisam/ft_nlq_search.c
@@ -16,9 +16,23 @@
/* Written by Sergei A. Golubchik, who has a shared copyright to this code */
+#define FT_CORE
#include "ftdefs.h"
-/* queries isam and returns list of documents matched */
+/* search with natural language queries */
+
+typedef struct ft_doc_rec {
+ my_off_t dpos;
+ double weight;
+} FT_DOC;
+
+struct st_ft_info {
+ struct _ft_vft *please;
+ MI_INFO *info;
+ int ndocs;
+ int curdoc;
+ FT_DOC doc[1];
+};
typedef struct st_all_in_one {
MI_INFO *info;
@@ -35,7 +49,8 @@ typedef struct st_ft_superdoc {
double tmp_weight;
} FT_SUPERDOC;
-static int FT_SUPERDOC_cmp(FT_SUPERDOC *p1, FT_SUPERDOC *p2)
+static int FT_SUPERDOC_cmp(void* cmp_arg __attribute__((unused)),
+ FT_SUPERDOC *p1, FT_SUPERDOC *p2)
{
if (p1->doc.dpos < p2->doc.dpos)
return -1;
@@ -151,65 +166,67 @@ static int FT_DOC_cmp(FT_DOC *a, FT_DOC *b)
return sgn(b->weight - a->weight);
}
-FT_DOCLIST * ft_init_search(void *info, uint keynr, byte *key,
- uint key_len, my_bool presort)
+FT_INFO *ft_init_nlq_search(MI_INFO *info, uint keynr, byte *query,
+ uint query_len, my_bool presort)
{
- TREE *wtree;
- ALL_IN_ONE aio;
- FT_DOCLIST *dlist;
+ TREE allocated_wtree, *wtree=&allocated_wtree;
+ ALL_IN_ONE aio;
FT_DOC *dptr;
- my_off_t saved_lastpos=((MI_INFO *)info)->lastpos;
+ FT_INFO *dlist=NULL;
+ my_off_t saved_lastpos=info->lastpos;
/* black magic ON */
- if ((int) (keynr = _mi_check_index((MI_INFO *)info,keynr)) < 0)
+ if ((int) (keynr = _mi_check_index(info,keynr)) < 0)
return NULL;
- if (_mi_readinfo((MI_INFO *)info,F_RDLCK,1))
+ if (_mi_readinfo(info,F_RDLCK,1))
return NULL;
/* black magic OFF */
- dlist=NULL;
- aio.info=(MI_INFO *)info;
+ aio.info=info;
aio.keynr=keynr;
- aio.keybuff=aio.info->lastkey+aio.info->s->base.max_key_length;
- aio.keyinfo=aio.info->s->keyinfo+keynr;
- aio.key_root=aio.info->s->state.key_root[keynr];
+ aio.keybuff=info->lastkey+info->s->base.max_key_length;
+ aio.keyinfo=info->s->keyinfo+keynr;
+ aio.key_root=info->s->state.key_root[keynr];
- if (!(wtree=ft_parse(NULL,key,key_len))) return NULL;
+ bzero(&allocated_wtree,sizeof(allocated_wtree));
- init_tree(&aio.dtree,0,sizeof(FT_SUPERDOC),(qsort_cmp)&FT_SUPERDOC_cmp,0,
- NULL);
+ init_tree(&aio.dtree,0,0,sizeof(FT_SUPERDOC),(qsort_cmp2)&FT_SUPERDOC_cmp,0,
+ NULL, NULL);
- if (tree_walk(wtree, (tree_walk_action)&walk_and_match, &aio,
- left_root_right))
+ if(ft_parse(&allocated_wtree,query,query_len))
goto err;
- dlist=(FT_DOCLIST *) my_malloc(sizeof(FT_DOCLIST)+sizeof(FT_DOC)*
- (aio.dtree.elements_in_tree-1),MYF(0));
- if (!dlist)
- goto err;
+ if(tree_walk(wtree, (tree_walk_action)&walk_and_match, &aio,
+ left_root_right))
+ goto err2;
+
+ dlist=(FT_INFO *)my_malloc(sizeof(FT_INFO)+
+ sizeof(FT_DOC)*(aio.dtree.elements_in_tree-1),MYF(0));
+ if(!dlist)
+ goto err2;
+ dlist->please= (struct _ft_vft *) & _ft_vft_nlq;
dlist->ndocs=aio.dtree.elements_in_tree;
dlist->curdoc=-1;
dlist->info=aio.info;
dptr=dlist->doc;
- tree_walk(&aio.dtree, (tree_walk_action)&walk_and_copy, &dptr,
- left_root_right);
+ tree_walk(&aio.dtree, (tree_walk_action)&walk_and_copy,
+ &dptr, left_root_right);
- if (presort)
- {
+ if(presort)
qsort(dlist->doc, dlist->ndocs, sizeof(FT_DOC), (qsort_cmp)&FT_DOC_cmp);
- }
-err:
- delete_tree(&aio.dtree);
+err2:
delete_tree(wtree);
- my_free((char*) wtree,MYF(0));
- ((MI_INFO *)info)->lastpos=saved_lastpos;
+ delete_tree(&aio.dtree);
+
+err:
+ info->lastpos=saved_lastpos;
return dlist;
}
-int ft_read_next(FT_DOCLIST *handler, char *record)
+int ft_nlq_read_next(FT_INFO *handler, char *record)
{
MI_INFO *info= (MI_INFO *) handler->info;
@@ -229,3 +246,45 @@ int ft_read_next(FT_DOCLIST *handler, char *record)
}
return my_errno;
}
+
+float ft_nlq_find_relevance(FT_INFO *handler,
+ byte *record __attribute__((unused)),
+ uint length __attribute__((unused)))
+{
+ int a,b,c;
+ FT_DOC *docs=handler->doc;
+ my_off_t docid=handler->info->lastpos;
+
+ if (docid == HA_POS_ERROR)
+ return -5.0;
+
+ /* Assuming docs[] is sorted by dpos... */
+
+ for (a=0, b=handler->ndocs, c=(a+b)/2; b-a>1; c=(a+b)/2)
+ {
+ if (docs[c].dpos > docid)
+ b=c;
+ else
+ a=c;
+ }
+ if (docs[a].dpos == docid)
+ return (float) docs[a].weight;
+ else
+ return 0.0;
+}
+
+void ft_nlq_close_search(FT_INFO *handler)
+{
+ my_free((gptr)handler,MYF(0));
+}
+
+float ft_nlq_get_relevance(FT_INFO *handler)
+{
+ return (float) handler->doc[handler->curdoc].weight;
+}
+
+void ft_nlq_reinit_search(FT_INFO *handler)
+{
+ handler->curdoc=-1;
+}
+
diff --git a/myisam/ft_parser.c b/myisam/ft_parser.c
index 7ea2e240c36..c1b1190bcab 100644
--- a/myisam/ft_parser.c
+++ b/myisam/ft_parser.c
@@ -33,16 +33,14 @@ typedef struct st_ft_docstat {
double max, nsum, nsum2;
#endif /* EVAL_RUN */
- MI_INFO *info;
- uint keynr;
- byte *keybuf;
} FT_DOCSTAT;
-static int FT_WORD_cmp(FT_WORD *w1, FT_WORD *w2)
+static int FT_WORD_cmp(void* cmp_arg, FT_WORD *w1, FT_WORD *w2)
{
return _mi_compare_text(default_charset_info,
- (uchar*) w1->pos,w1->len,
- (uchar*) w2->pos, w2->len,0);
+ (uchar*) w1->pos, w1->len,
+ (uchar*) w2->pos, w2->len,
+ (my_bool) (cmp_arg != 0));
}
static int walk_and_copy(FT_WORD *word,uint32 count,FT_DOCSTAT *docstat)
@@ -63,17 +61,15 @@ static int walk_and_copy(FT_WORD *word,uint32 count,FT_DOCSTAT *docstat)
/* transforms tree of words into the array, applying normalization */
-FT_WORD * ft_linearize(MI_INFO *info, uint keynr, byte *keybuf, TREE *wtree)
+FT_WORD * ft_linearize(TREE *wtree)
{
FT_WORD *wlist,*p;
FT_DOCSTAT docstat;
+ DBUG_ENTER("ft_linearize");
if ((wlist=(FT_WORD *) my_malloc(sizeof(FT_WORD)*
(1+wtree->elements_in_tree),MYF(0))))
{
- docstat.info=info;
- docstat.keynr=keynr;
- docstat.keybuf=keybuf;
docstat.list=wlist;
docstat.uniq=wtree->elements_in_tree;
#ifdef EVAL_RUN
@@ -83,13 +79,12 @@ FT_WORD * ft_linearize(MI_INFO *info, uint keynr, byte *keybuf, TREE *wtree)
tree_walk(wtree,(tree_walk_action)&walk_and_copy,&docstat,left_root_right);
}
delete_tree(wtree);
- my_free((char*) wtree,MYF(0));
if (!wlist)
- return NULL;
+ DBUG_RETURN(NULL);
docstat.list->pos=NULL;
- for(p=wlist;p->pos;p++)
+ for (p=wlist;p->pos;p++)
{
p->weight=PRENORM_IN_USE;
#ifdef EVAL_RUN
@@ -104,48 +99,133 @@ FT_WORD * ft_linearize(MI_INFO *info, uint keynr, byte *keybuf, TREE *wtree)
#endif
#endif /* EVAL_RUN */
- for(p=wlist;p->pos;p++)
+ for (p=wlist;p->pos;p++)
{
p->weight/=NORM_IN_USE;
}
- return wlist;
+ DBUG_RETURN(wlist);
}
+#define true_word_char(X) (isalnum(X) || (X)=='_')
#ifdef HYPHEN_IS_DELIM
-#define word_char(X) (isalnum(X) || (X)=='_' || (X)=='\'')
+#define misc_word_char(X) ((X)=='\'')
#else
-#define word_char(X) (isalnum(X) || (X)=='_' || (X)=='\'' || (X)=='-')
+#define misc_word_char(X) ((X)=='\'' || (X)=='-')
#endif
+#define word_char(X) (true_word_char(X) || misc_word_char(X))
-/* this is rather dumb first version of the parser */
-TREE * ft_parse(TREE *wtree, byte *doc, int doclen)
+
+/* returns:
+ * 0 - eof
+ * 1 - word found
+ * 2 - left bracket
+ * 3 - right bracket
+ */
+byte ft_get_word(byte **start, byte *end, FT_WORD *word, FTB_PARAM *param)
{
- byte *end=doc+doclen;
- FT_WORD w;
+ byte *doc=*start;
+ int mwc;
+
+ param->yesno=(FTB_YES==' ')?1:0;
+ param->plusminus=param->pmsign=0;
- if (!wtree)
+ while (doc<end)
{
- if (!(wtree=(TREE *)my_malloc(sizeof(TREE),MYF(0)))) return NULL;
- init_tree(wtree,0,sizeof(FT_WORD),(qsort_cmp)&FT_WORD_cmp,0,NULL);
+ for (;doc<end;doc++)
+ {
+ if (true_word_char(*doc)) break;
+ if (*doc == FTB_LBR || *doc == FTB_RBR)
+ {
+ /* param->prev=' '; */
+ *start=doc+1;
+ return (*doc == FTB_RBR)+2;
+ }
+ if (param->prev == ' ')
+ {
+ if (*doc == FTB_YES ) { param->yesno=+1; continue; } else
+ if (*doc == FTB_EGAL) { param->yesno= 0; continue; } else
+ if (*doc == FTB_NO ) { param->yesno=-1; continue; } else
+ if (*doc == FTB_INC ) { param->plusminus++; continue; } else
+ if (*doc == FTB_DEC ) { param->plusminus--; continue; } else
+ if (*doc == FTB_NEG ) { param->pmsign=!param->pmsign; continue; }
+ }
+ param->prev=*doc;
+ param->yesno=param->plusminus=param->pmsign=0;
+ }
+
+ mwc=0;
+ for (word->pos=doc; doc<end; doc++)
+ if (true_word_char(*doc))
+ mwc=0;
+ else if (!misc_word_char(*doc) || mwc++)
+ break;
+
+ param->prev='A'; /* be sure *prev is true_word_char */
+ word->len= (uint)(doc-word->pos) - mwc;
+ if ((param->trunc=(doc<end && *doc == FTB_TRUNC)))
+ doc++;
+
+ if (((word->len >= ft_min_word_len && !is_stopword(word->pos, word->len))
+ || param->trunc) && word->len < ft_max_word_len)
+ {
+ *start=doc;
+ return 1;
+ }
}
+ return 0;
+}
+
+byte ft_simple_get_word(byte **start, byte *end, FT_WORD *word)
+{
+ byte *doc=*start;
+ int mwc;
- w.weight=0;
while (doc<end)
{
for (;doc<end;doc++)
- if (word_char(*doc)) break;
- for (w.pos=doc; doc<end; doc++)
- if (!word_char(*doc)) break;
- if ((w.len= (uint) (doc-w.pos)) < MIN_WORD_LEN) continue;
- if (w.len >= HA_FT_MAXLEN) continue;
- if (is_stopword(w.pos, w.len)) continue;
- if (!tree_insert(wtree, &w, 0))
{
- delete_tree(wtree);
- my_free((char*) wtree,MYF(0));
- return NULL;
+ if (true_word_char(*doc)) break;
+ }
+
+ mwc=0;
+ for(word->pos=doc; doc<end; doc++)
+ if (true_word_char(*doc))
+ mwc=0;
+ else if (!misc_word_char(*doc) || mwc++)
+ break;
+
+ word->len= (uint)(doc-word->pos) - mwc;
+
+ if (word->len >= ft_min_word_len && word->len < ft_max_word_len &&
+ !is_stopword(word->pos, word->len))
+ {
+ *start=doc;
+ return 1;
}
}
- return wtree;
+ return 0;
}
+
+int ft_parse(TREE *wtree, byte *doc, int doclen)
+{
+ byte *end=doc+doclen;
+ FT_WORD w;
+
+ if (!is_tree_inited(wtree))
+ {
+ init_tree(wtree,0,0,sizeof(FT_WORD),(qsort_cmp2)&FT_WORD_cmp,0,NULL, NULL);
+ }
+
+ while (ft_simple_get_word(&doc,end,&w))
+ {
+ if (!tree_insert(wtree, &w, 0))
+ goto err;
+ }
+ return 0;
+
+err:
+ delete_tree(wtree);
+ return 1;
+}
+
diff --git a/myisam/ft_static.c b/myisam/ft_static.c
index 00d9d4ed19a..3efb3a3ec74 100644
--- a/myisam/ft_static.c
+++ b/myisam/ft_static.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -18,6 +18,11 @@
#include "ftdefs.h"
+ulong ft_min_word_len=4;
+ulong ft_max_word_len=HA_FT_MAXLEN;
+ulong ft_max_word_len_for_sort=20;
+const char *ft_boolean_syntax="+ -><()~*:\"\"&|";
+
const MI_KEYSEG ft_keysegs[FT_SEGS]={
{
HA_KEYTYPE_VARTEXT, /* type */
@@ -39,10 +44,29 @@ const MI_KEYSEG ft_keysegs[FT_SEGS]={
},
#endif /* EVAL_RUN */
{
- HA_FT_WTYPE, 7, 0, 0, 0, 0, HA_FT_WLEN, 0, 0, NULL
+ HA_FT_WTYPE, 7, 0, 0, 0, HA_NO_SORT, HA_FT_WLEN, 0, 0, NULL
}
};
+const struct _ft_vft _ft_vft_nlq = {
+ ft_nlq_read_next, ft_nlq_find_relevance, ft_nlq_close_search,
+ ft_nlq_get_relevance, ft_nlq_reinit_search
+};
+const struct _ft_vft _ft_vft_boolean = {
+ ft_boolean_read_next, ft_boolean_find_relevance, ft_boolean_close_search,
+ ft_boolean_get_relevance, ft_boolean_reinit_search
+};
+
+FT_INFO *(*_ft_init_vft[2])(MI_INFO *, uint, byte *, uint, my_bool) =
+{ ft_init_nlq_search, ft_init_boolean_search };
+
+FT_INFO *ft_init_search(uint mode, void *info, uint keynr,
+ byte *query, uint query_len, my_bool presort)
+{
+ return (*_ft_init_vft[mode])((MI_INFO *)info, keynr,
+ query, query_len, presort);
+}
+
const char *ft_precompiled_stopwords[] = {
#ifdef COMPILE_STOPWORDS_IN
diff --git a/myisam/ft_stem.c b/myisam/ft_stem.c
index bdfc73b774b..846d5d2247f 100644
--- a/myisam/ft_stem.c
+++ b/myisam/ft_stem.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -17,4 +17,3 @@
/* Written by Sergei A. Golubchik, who has a shared copyright to this code */
/* mulitingual stem */
-
diff --git a/myisam/ft_stopwords.c b/myisam/ft_stopwords.c
index d796b87ed71..9c2047c3b56 100644
--- a/myisam/ft_stopwords.c
+++ b/myisam/ft_stopwords.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -25,7 +25,8 @@ typedef struct st_ft_stopwords {
static TREE *stopwords3=NULL;
-static int FT_STOPWORD_cmp(FT_STOPWORD *w1, FT_STOPWORD *w2)
+static int FT_STOPWORD_cmp(void* cmp_arg __attribute__((unused)),
+ FT_STOPWORD *w1, FT_STOPWORD *w2)
{
return _mi_compare_text(default_charset_info,
(uchar *)w1->pos,w1->len,
@@ -40,15 +41,15 @@ int ft_init_stopwords(const char **sws)
if(!stopwords3)
{
if(!(stopwords3=(TREE *)my_malloc(sizeof(TREE),MYF(0)))) return -1;
- init_tree(stopwords3,0,sizeof(FT_STOPWORD),(qsort_cmp)&FT_STOPWORD_cmp,0,
- NULL);
+ init_tree(stopwords3,0,0,sizeof(FT_STOPWORD),(qsort_cmp2)&FT_STOPWORD_cmp,0,
+ NULL, NULL);
}
if(!sws) return 0;
for(;*sws;sws++)
{
- if( (sw.len= (uint) strlen(sw.pos=*sws)) < MIN_WORD_LEN) continue;
+ if( (sw.len= (uint) strlen(sw.pos=*sws)) < ft_min_word_len) continue;
if(!tree_insert(stopwords3, &sw, 0))
{
delete_tree(stopwords3); /* purecov: inspected */
diff --git a/myisam/ft_test1.c b/myisam/ft_test1.c
index 5093b591fb2..e1a47ff87c3 100644
--- a/myisam/ft_test1.c
+++ b/myisam/ft_test1.c
@@ -20,7 +20,7 @@
#include "ft_test1.h"
#include <getopt.h>
-static int key_field=FIELD_VARCHAR,extra_field=FIELD_SKIPP_ENDSPACE;
+static int key_field=FIELD_VARCHAR,extra_field=FIELD_SKIP_ENDSPACE;
static uint key_length=200,extra_length=50;
static int key_type=HA_KEYTYPE_TEXT;
static int verbose=0,silent=0,skip_update=0,
@@ -137,7 +137,7 @@ static int run_test(const char *filename)
printf("- Reading rows with key\n");
for (i=0 ; i < NQUERIES ; i++)
{ FT_DOCLIST *result;
- result=ft_init_search(file,0,(char*) query[i],strlen(query[i]),1);
+ result=ft_nlq_init_search(file,0,(char*) query[i],strlen(query[i]),1);
if(!result) {
printf("Query %d: `%s' failed with errno %3d\n",i,query[i],my_errno);
continue;
@@ -145,7 +145,7 @@ static int run_test(const char *filename)
printf("Query %d: `%s'. Found: %d. Top five documents:\n",
i,query[i],result->ndocs);
for(j=0;j<5;j++) { double w; int err;
- err=ft_read_next(result, read_record);
+ err=ft_nlq_read_next(result, read_record);
if(err==HA_ERR_END_OF_FILE) {
printf("No more matches!\n");
break;
@@ -153,7 +153,7 @@ static int run_test(const char *filename)
printf("ft_read_next %d failed with errno %3d\n",j,my_errno);
break;
}
- w=ft_get_relevance(result);
+ w=ft_nlq_get_relevance(result);
if(key_field == FIELD_VARCHAR) {
uint l;
char *p;
@@ -164,7 +164,7 @@ static int run_test(const char *filename)
printf("%10.7f: %.*s\n",w,recinfo[1].length,
recinfo[0].length+read_record);
}
- ft_close_search(result);
+ ft_nlq_close_search(result);
}
if (mi_close(file)) goto err;
diff --git a/myisam/ft_test1.h b/myisam/ft_test1.h
index 17b0cae66b7..e360244057b 100644
--- a/myisam/ft_test1.h
+++ b/myisam/ft_test1.h
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -419,4 +419,3 @@ const char *query[NQUERIES]={
"against about after more right the with/without", /* stopwords test */
"mysql license and copyright"
};
-
diff --git a/myisam/ft_update.c b/myisam/ft_update.c
index 753c4dc4029..8ffc35157d2 100644
--- a/myisam/ft_update.c
+++ b/myisam/ft_update.c
@@ -19,6 +19,7 @@
/* functions to work with full-text indices */
#include "ftdefs.h"
+#include <math.h>
/**************************************************************
This is to make ft-code to ignore keyseg.length at all *
@@ -27,46 +28,91 @@
#define set_if_smaller(A,B) /* no op */
/**************************************************************/
+void _mi_ft_segiterator_init(MI_INFO *info, uint keynr, const byte *record,
+ FT_SEG_ITERATOR *ftsi)
+{
+ ftsi->num=info->s->keyinfo[keynr].keysegs-FT_SEGS;
+ ftsi->seg=info->s->keyinfo[keynr].seg;
+ ftsi->rec=record;
+}
-/* parses a document i.e. calls _mi_ft_parse for every keyseg */
-static FT_WORD * _mi_ft_parserecord(MI_INFO *info, uint keynr, byte *keybuf,
- const byte *record)
+void _mi_ft_segiterator_dummy_init(const byte *record, uint len,
+ FT_SEG_ITERATOR *ftsi)
{
- TREE *parsed=NULL;
- MI_KEYSEG *keyseg;
- byte *pos;
- uint i;
+ ftsi->num=1;
+ ftsi->seg=0;
+ ftsi->pos=record;
+ ftsi->len=len;
+}
- keyseg=info->s->keyinfo[keynr].seg;
- for (i=info->s->keyinfo[keynr].keysegs-FT_SEGS ; i-- ; )
- {
- uint len;
+/* This function breaks convention "return 0 in success"
+ but it's easier to use like this
- keyseg--;
- if (keyseg->null_bit && (record[keyseg->null_pos] & keyseg->null_bit))
- continue; /* NULL field */
- pos= (byte *)record+keyseg->start;
- if (keyseg->flag & HA_VAR_LENGTH)
- {
- len=uint2korr(pos);
- pos+=2; /* Skip VARCHAR length */
- set_if_smaller(len,keyseg->length);
- }
- else if (keyseg->flag & HA_BLOB_PART)
- {
- len=_mi_calc_blob_length(keyseg->bit_start,pos);
- memcpy_fixed(&pos,pos+keyseg->bit_start,sizeof(char*));
- set_if_smaller(len,keyseg->length);
- }
- else
- len=keyseg->length;
- if (!(parsed=ft_parse(parsed, pos, len)))
- return NULL;
+ while(_mi_ft_segiterator())
+
+ so "1" means "OK", "0" means "EOF"
+*/
+
+uint _mi_ft_segiterator(register FT_SEG_ITERATOR *ftsi)
+{
+ if (!ftsi->num) return 0; else ftsi->num--;
+ if (!ftsi->seg) return 1; else ftsi->seg--;
+
+ if (ftsi->seg->null_bit &&
+ (ftsi->rec[ftsi->seg->null_pos] & ftsi->seg->null_bit))
+ {
+ ftsi->pos=0;
+ return 1;
+ }
+ ftsi->pos= ftsi->rec+ftsi->seg->start;
+ if (ftsi->seg->flag & HA_VAR_LENGTH)
+ {
+ ftsi->len=uint2korr(ftsi->pos);
+ ftsi->pos+=2; /* Skip VARCHAR length */
+ set_if_smaller(ftsi->len,ftsi->seg->length);
+ return 1;
}
+ if (ftsi->seg->flag & HA_BLOB_PART)
+ {
+ ftsi->len=_mi_calc_blob_length(ftsi->seg->bit_start,ftsi->pos);
+ memcpy_fixed((char*) &ftsi->pos, ftsi->pos+ftsi->seg->bit_start,
+ sizeof(char*));
+ set_if_smaller(ftsi->len,ftsi->seg->length);
+ return 1;
+ }
+ ftsi->len=ftsi->seg->length;
+ return 1;
+}
+
+/* parses a document i.e. calls ft_parse for every keyseg */
+uint _mi_ft_parse(TREE *parsed, MI_INFO *info, uint keynr, const byte *record)
+{
+ FT_SEG_ITERATOR ftsi;
+ _mi_ft_segiterator_init(info, keynr, record, &ftsi);
+
+ while (_mi_ft_segiterator(&ftsi))
+ if (ftsi.pos)
+ if (ft_parse(parsed, (byte *)ftsi.pos, ftsi.len))
+ return 1;
+
/* Handle the case where all columns are NULL */
- if (!parsed && !(parsed=ft_parse(0, (byte*) "", 0)))
+ if (!is_tree_inited(parsed) && ft_parse(parsed, (byte*) "", 0))
+ return 1;
+ else
+ return 0;
+}
+
+FT_WORD * _mi_ft_parserecord(MI_INFO *info, uint keynr,
+ byte *keybuf __attribute__((unused)),
+ const byte *record)
+{
+ TREE ptree;
+
+ bzero((char*) &ptree, sizeof(ptree));
+ if (_mi_ft_parse(&ptree, info, keynr, record))
return NULL;
- return ft_linearize(info, keynr, keybuf, parsed);
+
+ return ft_linearize(/*info, keynr, keybuf, */ &ptree);
}
static int _mi_ft_store(MI_INFO *info, uint keynr, byte *keybuf,
@@ -106,53 +152,70 @@ static int _mi_ft_erase(MI_INFO *info, uint keynr, byte *keybuf, FT_WORD *wlist,
int _mi_ft_cmp(MI_INFO *info, uint keynr, const byte *rec1, const byte *rec2)
{
- MI_KEYSEG *keyseg;
- byte *pos1, *pos2;
- uint i;
+ FT_SEG_ITERATOR ftsi1, ftsi2;
+ _mi_ft_segiterator_init(info, keynr, rec1, &ftsi1);
+ _mi_ft_segiterator_init(info, keynr, rec2, &ftsi2);
- i=info->s->keyinfo[keynr].keysegs-FT_SEGS;
- keyseg=info->s->keyinfo[keynr].seg;
- while(i--)
+ while(_mi_ft_segiterator(&ftsi1) && _mi_ft_segiterator(&ftsi2))
{
- uint len1, len2;
- LINT_INIT(len1); LINT_INIT(len2);
- keyseg--;
- if (keyseg->null_bit)
- {
- if ( (rec1[keyseg->null_pos] ^ rec2[keyseg->null_pos])
- & keyseg->null_bit )
- return THOSE_TWO_DAMN_KEYS_ARE_REALLY_DIFFERENT;
- if (rec1[keyseg->null_pos] & keyseg->null_bit )
- continue; /* NULL field */
- }
- pos1= (byte *)rec1+keyseg->start;
- pos2= (byte *)rec2+keyseg->start;
- if (keyseg->flag & HA_VAR_LENGTH)
- {
- len1=uint2korr(pos1);
- pos1+=2; /* Skip VARCHAR length */
- set_if_smaller(len1,keyseg->length);
- len2=uint2korr(pos2);
- pos2+=2; /* Skip VARCHAR length */
- set_if_smaller(len2,keyseg->length);
- }
- else if (keyseg->flag & HA_BLOB_PART)
+ if ((ftsi1.pos != ftsi2.pos) &&
+ (!ftsi1.pos || !ftsi2.pos ||
+ _mi_compare_text(default_charset_info,
+ (uchar*) ftsi1.pos,ftsi1.len,
+ (uchar*) ftsi2.pos,ftsi2.len,0)))
+ return THOSE_TWO_DAMN_KEYS_ARE_REALLY_DIFFERENT;
+ }
+ return GEE_THEY_ARE_ABSOLUTELY_IDENTICAL;
+}
+
+/* update a document entry */
+int _mi_ft_update(MI_INFO *info, uint keynr, byte *keybuf,
+ const byte *oldrec, const byte *newrec, my_off_t pos)
+{
+ int error= -1;
+ FT_WORD *oldlist,*newlist, *old_word, *new_word;
+ uint key_length;
+ int cmp, cmp2;
+
+ if (!(old_word=oldlist=_mi_ft_parserecord(info, keynr, keybuf, oldrec)))
+ goto err0;
+ if (!(new_word=newlist=_mi_ft_parserecord(info, keynr, keybuf, newrec)))
+ goto err1;
+
+ error=0;
+ while(old_word->pos && new_word->pos)
+ {
+ cmp=_mi_compare_text(default_charset_info,
+ (uchar*) old_word->pos,old_word->len,
+ (uchar*) new_word->pos,new_word->len,0);
+ cmp2= cmp ? 0 : (fabs(old_word->weight - new_word->weight) > 1.e-5);
+
+ if (cmp < 0 || cmp2)
{
- len1=_mi_calc_blob_length(keyseg->bit_start,pos1);
- memcpy_fixed(&pos1,pos1+keyseg->bit_start,sizeof(char*));
- set_if_smaller(len1,keyseg->length);
- len2=_mi_calc_blob_length(keyseg->bit_start,pos2);
- memcpy_fixed(&pos2,pos2+keyseg->bit_start,sizeof(char*));
- set_if_smaller(len2,keyseg->length);
+ key_length=_ft_make_key(info,keynr,keybuf,old_word,pos);
+ if ((error=_mi_ck_delete(info,keynr,(uchar*) keybuf,key_length)))
+ goto err2;
}
- else /* fixed length key */
+ if (cmp > 0 || cmp2)
{
- len1=len2=keyseg->length;
+ key_length=_ft_make_key(info,keynr,keybuf,new_word,pos);
+ if ((error=_mi_ck_write(info,keynr,(uchar*) keybuf,key_length)))
+ goto err2;
}
- if ((len1 != len2) || memcmp(pos1, pos2, len1))
- return THOSE_TWO_DAMN_KEYS_ARE_REALLY_DIFFERENT;
- }
- return GEE_THEY_ARE_ABSOLUTELY_IDENTICAL;
+ if (cmp<=0) old_word++;
+ if (cmp>=0) new_word++;
+ }
+ if (old_word->pos)
+ error=_mi_ft_erase(info,keynr,keybuf,old_word,pos);
+ else if (new_word->pos)
+ error=_mi_ft_store(info,keynr,keybuf,new_word,pos);
+
+err2:
+ my_free((char*) newlist,MYF(0));
+err1:
+ my_free((char*) oldlist,MYF(0));
+err0:
+ return error;
}
/* adds a document to the collection */
diff --git a/myisam/ftdefs.h b/myisam/ftdefs.h
index d9b4ff6b44d..1a3c0ef60dc 100644
--- a/myisam/ftdefs.h
+++ b/myisam/ftdefs.h
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -22,15 +22,18 @@
#include <m_ctype.h>
#include <my_tree.h>
-#define MIN_WORD_LEN 4
-
#define HYPHEN_IS_DELIM
#define HYPHEN_IS_CONCAT /* not used for now */
#define COMPILE_STOPWORDS_IN
-/* Most of the formulae were shamelessly stolen from SMART distribution
- ftp://ftp.cs.cornell.edu/pub/smart/smart.11.0.tar.Z
+/* Interested readers may consult SMART
+ (ftp://ftp.cs.cornell.edu/pub/smart/smart.11.0.tar.Z)
+ for an excellent implementation of vector space model we use.
+ It also demonstrate the usage of different weghting techniques.
+ This code, though, is completely original and is not based on the
+ SMART code but was in some cases inspired by it.
+
NORM_PIVOT was taken from the article
A.Singhal, C.Buckley, M.Mitra, "Pivoted Document Length Normalization",
ACM SIGIR'96, 21-29, 1996
@@ -82,6 +85,17 @@ extern ulong collstat;
#define GWS_ENTROPY (1-(suml/sum-log(sum))/log(aio->info->state->records))
/*=================================================================*/
+/* Boolean search operators */
+#define FTB_YES (ft_boolean_syntax[0])
+#define FTB_EGAL (ft_boolean_syntax[1])
+#define FTB_NO (ft_boolean_syntax[2])
+#define FTB_INC (ft_boolean_syntax[3])
+#define FTB_DEC (ft_boolean_syntax[4])
+#define FTB_LBR (ft_boolean_syntax[5])
+#define FTB_RBR (ft_boolean_syntax[6])
+#define FTB_NEG (ft_boolean_syntax[7])
+#define FTB_TRUNC (ft_boolean_syntax[8])
+
typedef struct st_ft_word {
byte * pos;
uint len;
@@ -91,9 +105,50 @@ typedef struct st_ft_word {
#endif /* EVAL_RUN */
} FT_WORD;
+typedef struct st_ftb_param {
+ byte prev;
+ int yesno;
+ int plusminus;
+ bool pmsign;
+ bool trunc;
+} FTB_PARAM;
+
int is_stopword(char *word, uint len);
uint _ft_make_key(MI_INFO *, uint , byte *, FT_WORD *, my_off_t);
-TREE * ft_parse(TREE *, byte *, int);
-FT_WORD * ft_linearize(MI_INFO *, uint, byte *, TREE *);
+byte ft_get_word(byte **, byte *, FT_WORD *, FTB_PARAM *);
+byte ft_simple_get_word(byte **, byte *, FT_WORD *);
+
+typedef struct _st_ft_seg_iterator {
+ uint num, len;
+ MI_KEYSEG *seg;
+ const byte *rec, *pos;
+} FT_SEG_ITERATOR;
+
+void _mi_ft_segiterator_init(MI_INFO *, uint, const byte *, FT_SEG_ITERATOR *);
+void _mi_ft_segiterator_dummy_init(const byte *, uint, FT_SEG_ITERATOR *);
+uint _mi_ft_segiterator(FT_SEG_ITERATOR *);
+
+int ft_parse(TREE *, byte *, int);
+FT_WORD * ft_linearize(/*MI_INFO *, uint, byte *, */TREE *);
+FT_WORD * _mi_ft_parserecord(MI_INFO *, uint, byte *, const byte *);
+uint _mi_ft_parse(TREE *parsed, MI_INFO *info, uint keynr, const byte *record);
+
+extern const struct _ft_vft _ft_vft_nlq;
+FT_INFO *ft_init_nlq_search(MI_INFO *, uint, byte *, uint, my_bool);
+int ft_nlq_read_next(FT_INFO *, char *);
+float ft_nlq_find_relevance(FT_INFO *, byte *, uint);
+void ft_nlq_close_search(FT_INFO *);
+float ft_nlq_get_relevance(FT_INFO *);
+my_off_t ft_nlq_get_docid(FT_INFO *);
+void ft_nlq_reinit_search(FT_INFO *);
+
+extern const struct _ft_vft _ft_vft_boolean;
+FT_INFO *ft_init_boolean_search(MI_INFO *, uint, byte *, uint, my_bool);
+int ft_boolean_read_next(FT_INFO *, char *);
+float ft_boolean_find_relevance(FT_INFO *, byte *, uint);
+void ft_boolean_close_search(FT_INFO *);
+float ft_boolean_get_relevance(FT_INFO *);
+my_off_t ft_boolean_get_docid(FT_INFO *);
+void ft_boolean_reinit_search(FT_INFO *);
diff --git a/myisam/fulltext.h b/myisam/fulltext.h
index 8fcac8172b1..f787c9bcfe8 100644
--- a/myisam/fulltext.h
+++ b/myisam/fulltext.h
@@ -24,7 +24,6 @@
/* shoudn't be def'ed when linking with mysql */
#undef EVAL_RUN
-#define HA_FT_MAXLEN 254
#define HA_FT_WTYPE HA_KEYTYPE_FLOAT
#define HA_FT_WLEN 4
#ifdef EVAL_RUN
diff --git a/myisam/mi_cache.c b/myisam/mi_cache.c
index 69a1cb0d7a5..55f85fb99d1 100644
--- a/myisam/mi_cache.c
+++ b/myisam/mi_cache.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -45,11 +45,11 @@ int _mi_read_cache(IO_CACHE *info, byte *buff, my_off_t pos, uint length,
buff+=read_length;
}
if ((offset= (my_off_t) (pos - info->pos_in_file)) <
- (my_off_t) (info->rc_end - info->rc_request_pos))
+ (my_off_t) (info->read_end - info->request_pos))
{
- in_buff_pos=info->rc_request_pos+(uint) offset;
- in_buff_length= min(length,(uint) (info->rc_end-in_buff_pos));
- memcpy(buff,info->rc_request_pos+(uint) offset,(size_t) in_buff_length);
+ in_buff_pos=info->request_pos+(uint) offset;
+ in_buff_length= min(length,(uint) (info->read_end-in_buff_pos));
+ memcpy(buff,info->request_pos+(uint) offset,(size_t) in_buff_length);
if (!(length-=in_buff_length))
DBUG_RETURN(0);
pos+=in_buff_length;
@@ -60,19 +60,22 @@ int _mi_read_cache(IO_CACHE *info, byte *buff, my_off_t pos, uint length,
if (flag & READING_NEXT)
{
if (pos != ((info)->pos_in_file +
- (uint) ((info)->rc_end - (info)->rc_request_pos)))
+ (uint) ((info)->read_end - (info)->request_pos)))
{
info->pos_in_file=pos; /* Force start here */
- info->rc_pos=info->rc_end=info->rc_request_pos; /* Everything used */
+ info->read_pos=info->read_end=info->request_pos; /* Everything used */
info->seek_not_done=1;
}
else
- info->rc_pos=info->rc_end; /* All block used */
+ info->read_pos=info->read_end; /* All block used */
if (!(*info->read_function)(info,buff,length))
DBUG_RETURN(0);
if (!(flag & READING_HEADER) || info->error == -1 ||
(uint) info->error+in_buff_length < 3)
{
+ DBUG_PRINT("error",
+ ("Error %d reading next-multi-part block (Got %d bytes)",
+ my_errno, info->error));
if (!my_errno || my_errno == -1)
my_errno=HA_ERR_WRONG_IN_RECORD;
DBUG_RETURN(1);
@@ -87,6 +90,9 @@ int _mi_read_cache(IO_CACHE *info, byte *buff, my_off_t pos, uint length,
if (!(flag & READING_HEADER) || (int) read_length == -1 ||
read_length+in_buff_length < 3)
{
+ DBUG_PRINT("error",
+ ("Error %d reading new block (Got %d bytes)",
+ my_errno, (int) read_length));
if (!my_errno || my_errno == -1)
my_errno=HA_ERR_WRONG_IN_RECORD;
DBUG_RETURN(1);
diff --git a/myisam/mi_changed.c b/myisam/mi_changed.c
index bd6b14b0c6c..c2ab5568eba 100644
--- a/myisam/mi_changed.c
+++ b/myisam/mi_changed.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -24,7 +24,7 @@ int mi_is_changed(MI_INFO *info)
{
int result;
DBUG_ENTER("mi_is_changed");
- if (_mi_readinfo(info,F_RDLCK,1))
+ if (fast_mi_readinfo(info))
DBUG_RETURN(-1);
VOID(_mi_writeinfo(info,0));
result=(int) info->data_changed;
diff --git a/myisam/mi_check.c b/myisam/mi_check.c
index 89fcfe74cea..5b21e9b6ef2 100644
--- a/myisam/mi_check.c
+++ b/myisam/mi_check.c
@@ -16,7 +16,7 @@
/* Descript, check and repair of ISAM tables */
-#include "fulltext.h"
+#include "ftdefs.h"
#include <m_ctype.h>
#include <stdarg.h>
#include <getopt.h>
@@ -46,6 +46,7 @@ static int writekeys(MI_CHECK *param, MI_INFO *info,byte *buff,
static int sort_one_index(MI_CHECK *param, MI_INFO *info,MI_KEYDEF *keyinfo,
my_off_t pagepos, File new_file);
static int sort_key_read(SORT_INFO *sort_info,void *key);
+static int sort_ft_key_read(SORT_INFO *sort_info,void *key);
static int sort_get_next_record(SORT_INFO *sort_info);
static int sort_key_cmp(SORT_INFO *sort_info, const void *a,const void *b);
static int sort_key_write(SORT_INFO *sort_info, const void *a);
@@ -54,7 +55,7 @@ static my_off_t get_record_for_key(MI_INFO *info,MI_KEYDEF *keyinfo,
static int sort_insert_key(MI_CHECK *param, reg1 SORT_KEY_BLOCKS *key_block,
uchar *key, my_off_t prev_block);
static int sort_delete_record(MI_CHECK *param);
-static int flush_pending_blocks(MI_CHECK *param);
+/*static int flush_pending_blocks(MI_CHECK *param);*/
static SORT_KEY_BLOCKS *alloc_key_blocks(MI_CHECK *param, uint blocks,
uint buffer_length);
static void update_key_parts(MI_KEYDEF *keyinfo,
@@ -104,6 +105,7 @@ void myisamchk_init(MI_CHECK *param)
int chk_status(MI_CHECK *param, register MI_INFO *info)
{
MYISAM_SHARE *share=info->s;
+
if (mi_is_crashed_on_repair(info))
mi_check_print_warning(param,
"Table is marked as crashed and last repair failed");
@@ -231,7 +233,7 @@ wrong:
static int check_k_link(MI_CHECK *param, register MI_INFO *info, uint nr)
{
my_off_t next_link;
- uint block_size=(nr+1)*MI_KEY_BLOCK_LENGTH;
+ uint block_size=(nr+1)*MI_MIN_KEY_BLOCK_LENGTH;
ha_rows records;
char llbuff[21],*buff;
DBUG_ENTER("check_k_link");
@@ -1119,6 +1121,10 @@ int mi_repair(MI_CHECK *param, register MI_INFO *info,
share->pack.header_length;
got_error=1;
new_file= -1;
+ sort_info->buff=0;
+ sort_info->buff_length=0;
+ sort_info->record=0;
+
if (!(param->testflag & T_SILENT))
{
printf("- recovering (with keycache) MyISAM-table '%s'\n",name);
@@ -1126,12 +1132,15 @@ int mi_repair(MI_CHECK *param, register MI_INFO *info,
}
if (!param->using_global_keycache)
- VOID(init_key_cache(param->use_buffers,NEAD_MEM));
+ VOID(init_key_cache(param->use_buffers,NEED_MEM));
if (init_io_cache(&param->read_cache,info->dfile,
(uint) param->read_buffer_length,
READ_CACHE,share->pack.header_length,1,MYF(MY_WME)))
+ {
+ bzero(&info->rec_cache,sizeof(info->rec_cache));
goto err;
+ }
if (!rep_quick)
if (init_io_cache(&info->rec_cache,-1,(uint) param->write_buffer_length,
WRITE_CACHE, new_header_length, 1,
@@ -1139,7 +1148,6 @@ int mi_repair(MI_CHECK *param, register MI_INFO *info,
goto err;
info->opt_flag|=WRITE_CACHE_USED;
sort_info->start_recpos=0;
- sort_info->buff=0; sort_info->buff_length=0;
if (!(sort_info->record=(byte*) my_malloc((uint) share->base.pack_reclength,
MYF(0))))
{
@@ -1149,7 +1157,10 @@ int mi_repair(MI_CHECK *param, register MI_INFO *info,
if (!rep_quick)
{
- if ((new_file=my_raid_create(fn_format(param->temp_filename,name,"",
+ /* Get real path for data file */
+ fn_format(param->temp_filename,name,"", MI_NAME_DEXT,2+4+32);
+ if ((new_file=my_raid_create(fn_format(param->temp_filename,
+ param->temp_filename,"",
DATA_TMP_EXT,
2+4),
0,param->tmpfile_createflag,
@@ -1277,8 +1288,6 @@ int mi_repair(MI_CHECK *param, register MI_INFO *info,
my_close(info->dfile,MYF(0));
info->dfile=new_file;
info->state->data_file_length=sort_info->filepos;
- /* Only whole records */
- share->state.split=info->state->records+info->state->del;
share->state.version=(ulong) time((time_t*) 0); /* Force reopen */
}
else
@@ -1311,11 +1320,11 @@ err:
{
my_close(new_file,MYF(0));
info->dfile=new_file= -1;
- if (change_to_newfile(share->filename,MI_NAME_DEXT,
+ if (change_to_newfile(share->data_file_name,MI_NAME_DEXT,
DATA_TMP_EXT, share->base.raid_chunks,
(param->testflag & T_BACKUP_DATA ?
MYF(MY_REDEL_MAKE_BACKUP): MYF(0))) ||
- mi_open_datafile(info,share))
+ mi_open_datafile(info,share,-1))
got_error=1;
}
}
@@ -1501,8 +1510,10 @@ int mi_sort_index(MI_CHECK *param, register MI_INFO *info, my_string name)
if (!(param->testflag & T_SILENT))
printf("- Sorting index for MyISAM-table '%s'\n",name);
- if ((new_file=my_create(fn_format(param->temp_filename,name,"",
- INDEX_TMP_EXT,2+4),
+ /* Get real path for index file */
+ fn_format(param->temp_filename,name,"", MI_NAME_IEXT,2+4+32);
+ if ((new_file=my_create(fn_format(param->temp_filename,param->temp_filename,
+ "", INDEX_TMP_EXT,2+4),
0,param->tmpfile_createflag,MYF(0))) <= 0)
{
mi_check_print_error(param,"Can't create new tempfile: '%s'",
@@ -1522,7 +1533,7 @@ int mi_sort_index(MI_CHECK *param, register MI_INFO *info, my_string name)
if (share->state.key_root[key] != HA_OFFSET_ERROR)
{
- index_pos[key]=param->new_file_pos; /* Write first block here */
+ index_pos[key]=param->new_file_pos; /* Write first block here */
if (sort_one_index(param,info,keyinfo,share->state.key_root[key],
new_file))
goto err;
@@ -1543,7 +1554,7 @@ int mi_sort_index(MI_CHECK *param, register MI_INFO *info, my_string name)
VOID(my_close(share->kfile,MYF(MY_WME)));
share->kfile = -1;
VOID(my_close(new_file,MYF(MY_WME)));
- if (change_to_newfile(share->filename,MI_NAME_IEXT,INDEX_TMP_EXT,0,
+ if (change_to_newfile(share->index_file_name,MI_NAME_IEXT,INDEX_TMP_EXT,0,
MYF(0)) ||
mi_open_keyfile(share))
goto err2;
@@ -1643,9 +1654,14 @@ err:
} /* sort_one_index */
- /* Change to use new file */
- /* Copy stats from old file to new file, deletes orginal and */
- /* changes new file name to old file name */
+ /*
+ Let temporary file replace old file.
+ This assumes that the new file was created in the same
+ directory as given by realpath(filename).
+ This will ensure that any symlinks that are used will still work.
+ Copy stats from old file to new file, deletes orignal and
+ changes new file name to old file name
+ */
int change_to_newfile(const char * filename, const char * old_ext,
const char * new_ext,
@@ -1660,8 +1676,10 @@ int change_to_newfile(const char * filename, const char * old_ext,
raid_chunks,
MYF(MY_WME | MY_LINK_WARNING | MyFlags));
#endif
- return my_redel(fn_format(old_filename,filename,"",old_ext,2+4),
- fn_format(new_filename,filename,"",new_ext,2+4),
+ /* Get real path to filename */
+ (void) fn_format(old_filename,filename,"",old_ext,2+4+32);
+ return my_redel(old_filename,
+ fn_format(new_filename,old_filename,"",new_ext,2+4),
MYF(MY_WME | MY_LINK_WARNING | MyFlags));
} /* change_to_newfile */
@@ -1752,22 +1770,6 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info,
printf("Data records: %s\n", llstr(start_records,llbuff));
}
- /* Hmm, repair_by_sort uses find_all_keys, and find_all_keys strictly
- implies "one row - one key per keynr", while for ft_key one row/keynr
- can produce as many keys as the number of unique words in the text
- that's why I disabled repair_by_sort for ft-keys. (serg)
- */
- for (i=0 ; i < share->base.keys ; i++)
- {
- if ((((ulonglong) 1 << i) & key_map) &&
- (share->keyinfo[i].flag & HA_FULLTEXT))
- {
- mi_check_print_error(param,
- "Can`t use repair_by_sort with FULLTEXT key");
- DBUG_RETURN(1);
- }
- }
-
bzero((char*) sort_info,sizeof(*sort_info));
if (!(sort_info->key_block=
alloc_key_blocks(param,
@@ -1794,7 +1796,10 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info,
}
if (!rep_quick)
{
- if ((new_file=my_raid_create(fn_format(param->temp_filename,name,"",
+ /* Get real path for data file */
+ fn_format(param->temp_filename,name,"", MI_NAME_DEXT,2+4+32);
+ if ((new_file=my_raid_create(fn_format(param->temp_filename,
+ param->temp_filename, "",
DATA_TMP_EXT,
2+4),
0,param->tmpfile_createflag,
@@ -1851,6 +1856,8 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info,
param->read_cache.end_of_file=sort_info->filelength=
my_seek(param->read_cache.file,0L,MY_SEEK_END,MYF(0));
+ sort_info->wordlist=NULL;
+
if (share->data_file_type == DYNAMIC_RECORD)
length=max(share->base.min_pack_length+1,share->base.min_block_length);
else if (share->data_file_type == COMPRESSED_RECORD)
@@ -1862,7 +1869,6 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info,
(ha_rows) (sort_info->filelength/length+1));
sort_param.key_cmp=sort_key_cmp;
sort_param.key_write=sort_key_write;
- sort_param.key_read=sort_key_read;
sort_param.lock_in_memory=lock_memory;
sort_param.tmpdir=param->tmpdir;
sort_param.myf_rw=param->myf_rw;
@@ -1908,6 +1914,17 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info,
info->state->records=info->state->del=share->state.split=0;
info->state->empty=0;
+ if (sort_info->keyinfo->flag & HA_FULLTEXT)
+ {
+ sort_param.max_records=sort_info->max_records=
+ (ha_rows) (sort_info->filelength/ft_max_word_len_for_sort+1);
+
+ sort_param.key_read=sort_ft_key_read;
+ sort_param.key_length+=ft_max_word_len_for_sort-ft_max_word_len;
+ }
+ else
+ sort_param.key_read=sort_key_read;
+
if (_create_index_by_sort(&sort_param,
(my_bool) (!(param->testflag & T_VERBOSE)),
(uint) param->sort_buffer_length))
@@ -1943,7 +1960,6 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info,
share->state.state.data_file_length = info->state->data_file_length
= sort_info->filepos;
/* Only whole records */
- share->state.split=info->state->records+info->state->del;
share->state.version=(ulong) time((time_t*) 0);
my_close(info->dfile,MYF(0));
info->dfile=new_file;
@@ -1953,8 +1969,8 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info,
else
info->state->data_file_length=sort_info->max_pos;
- if (flush_pending_blocks(param))
- goto err;
+ /*if (flush_pending_blocks(param))
+ goto err;*/
param->read_cache.file=info->dfile; /* re-init read cache */
reinit_io_cache(&param->read_cache,READ_CACHE,share->pack.header_length,1,
@@ -2023,11 +2039,11 @@ err:
{
my_close(new_file,MYF(0));
info->dfile=new_file= -1;
- if (change_to_newfile(share->filename,MI_NAME_DEXT,
+ if (change_to_newfile(share->data_file_name,MI_NAME_DEXT,
DATA_TMP_EXT, share->base.raid_chunks,
(param->testflag & T_BACKUP_DATA ?
MYF(MY_REDEL_MAKE_BACKUP): MYF(0))) ||
- mi_open_datafile(info,share))
+ mi_open_datafile(info,share,-1))
got_error=1;
}
}
@@ -2081,12 +2097,57 @@ static int sort_key_read(SORT_INFO *sort_info, void *key)
"Found too many records; Can`t continue");
DBUG_RETURN(1);
}
- (void) _mi_make_key(info,sort_info->key,(uchar*)key,sort_info->record,
- sort_info->filepos);
+ sort_info->real_key_length=(info->s->rec_reflength+
+ _mi_make_key(info, sort_info->key,
+ (uchar*) key, sort_info->record,
+ sort_info->filepos));
DBUG_RETURN(sort_write_record(sort_info));
} /* sort_key_read */
+static int sort_ft_key_read(SORT_INFO *sort_info, void *key)
+{
+ int error;
+ MI_INFO *info;
+ FT_WORD *wptr=0;
+ DBUG_ENTER("sort_ft_key_read");
+
+ info=sort_info->info;
+
+ if (!sort_info->wordlist)
+ {
+ do
+ {
+ my_free((char*) wptr, MYF(MY_ALLOW_ZERO_PTR));
+ if ((error=sort_get_next_record(sort_info)))
+ DBUG_RETURN(error);
+ if (!(wptr=_mi_ft_parserecord(info,sort_info->key,key,sort_info->record)))
+ DBUG_RETURN(1);
+ error=sort_write_record(sort_info);
+ }
+ while (!wptr->pos);
+ sort_info->wordptr=sort_info->wordlist=wptr;
+ }
+ else
+ {
+ error=0;
+ wptr=(FT_WORD*)(sort_info->wordptr);
+ }
+
+ sort_info->real_key_length=info->s->rec_reflength+_ft_make_key(info,
+ sort_info->key,key,wptr++,sort_info->filepos);
+ if (!wptr->pos)
+ {
+ my_free((char*) sort_info->wordlist, MYF(0));
+ sort_info->wordlist=0;
+ }
+ else
+ sort_info->wordptr=(void*)wptr;
+
+
+ DBUG_RETURN(error);
+} /* sort_ft_key_read */
+
/* Read next record from file using parameters in sort_info */
/* Return -1 if end of file, 0 if ok and > 0 if error */
@@ -2119,9 +2180,11 @@ static int sort_get_next_record(SORT_INFO *sort_info)
}
sort_info->start_recpos=sort_info->pos;
if (!sort_info->fix_datafile)
+ {
sort_info->filepos=sort_info->pos;
+ share->state.split++;
+ }
sort_info->max_pos=(sort_info->pos+=share->base.pack_reclength);
- share->state.split++;
if (*sort_info->record)
{
if (param->calc_checksum)
@@ -2292,7 +2355,8 @@ static int sort_get_next_record(SORT_INFO *sort_info)
continue;
}
- share->state.split++;
+ if (!sort_info->fix_datafile)
+ share->state.split++;
if (! found_record++)
{
sort_info->find_length=left_length=block_info.rec_len;
@@ -2430,10 +2494,12 @@ static int sort_get_next_record(SORT_INFO *sort_info)
}
info->checksum=mi_checksum(info,sort_info->record);
if (!sort_info->fix_datafile)
+ {
sort_info->filepos=sort_info->pos;
+ share->state.split++;
+ }
sort_info->max_pos=(sort_info->pos=block_info.filepos+
block_info.rec_len);
- share->state.split++;
info->packed_length=block_info.rec_len;
if (param->calc_checksum)
param->glob_crc+= info->checksum;
@@ -2471,6 +2537,7 @@ int sort_write_record(SORT_INFO *sort_info)
DBUG_RETURN(1);
}
sort_info->filepos+=share->base.pack_reclength;
+ info->s->state.split++;
/* sort_info->param->glob_crc+=mi_static_checksum(info, sort_info->record); */
break;
case DYNAMIC_RECORD:
@@ -2495,20 +2562,28 @@ int sort_write_record(SORT_INFO *sort_info)
}
info->checksum=mi_checksum(info,sort_info->record);
reclength=_mi_rec_pack(info,from,sort_info->record);
- /* sort_info->param->glob_crc+=info->checksum; */
- block_length=reclength+ 3 + test(reclength >= (65520-3));
- if (block_length < share->base.min_block_length)
- block_length=share->base.min_block_length;
flag=0;
- info->update|=HA_STATE_WRITE_AT_END;
- block_length=MY_ALIGN(block_length,MI_DYN_ALIGN_SIZE);
- if (_mi_write_part_record(info,0L,block_length,HA_OFFSET_ERROR,
- &from,&reclength,&flag))
+ /* sort_info->param->glob_crc+=info->checksum; */
+
+ do
{
- mi_check_print_error(param,"%d when writing to datafile",my_errno);
- DBUG_RETURN(1);
- }
- sort_info->filepos+=block_length;
+ block_length=reclength+ 3 + test(reclength >= (65520-3));
+ if (block_length < share->base.min_block_length)
+ block_length=share->base.min_block_length;
+ info->update|=HA_STATE_WRITE_AT_END;
+ block_length=MY_ALIGN(block_length,MI_DYN_ALIGN_SIZE);
+ if (block_length > MI_MAX_BLOCK_LENGTH)
+ block_length=MI_MAX_BLOCK_LENGTH;
+ if (_mi_write_part_record(info,0L,block_length,
+ sort_info->filepos+block_length,
+ &from,&reclength,&flag))
+ {
+ mi_check_print_error(param,"%d when writing to datafile",my_errno);
+ DBUG_RETURN(1);
+ }
+ sort_info->filepos+=block_length;
+ info->s->state.split++;
+ } while (reclength);
/* sort_info->param->glob_crc+=info->checksum; */
break;
case COMPRESSED_RECORD:
@@ -2524,6 +2599,7 @@ int sort_write_record(SORT_INFO *sort_info)
}
/* sort_info->param->glob_crc+=info->checksum; */
sort_info->filepos+=reclength+length;
+ info->s->state.split++;
break;
}
}
@@ -2752,7 +2828,7 @@ static int sort_delete_record(MI_CHECK *param)
/* Fix all pending blocks and flush everything to disk */
-static int flush_pending_blocks(MI_CHECK *param)
+int flush_pending_blocks(MI_CHECK *param)
{
uint nod_flag,length;
my_off_t filepos,key_file_length;
@@ -2846,7 +2922,6 @@ int recreate_table(MI_CHECK *param, MI_INFO **org_info, char *filename)
MI_STATUS_INFO status_info;
uint unpack,key_parts;
ha_rows max_records;
- char name[FN_REFLEN];
ulonglong file_length,tmp_length;
MI_CREATE_INFO create_info;
@@ -2955,8 +3030,9 @@ int recreate_table(MI_CHECK *param, MI_INFO **org_info, char *filename)
create_info.language = (param->language ? param->language :
share.state.header.language);
- if (mi_create(fn_format(name,filename,"",MI_NAME_IEXT,
- 4+ (param->opt_follow_links ? 16 : 0)),
+ /* We don't have to handle symlinks here because we are using
+ HA_DONT_TOUCH_DATA */
+ if (mi_create(filename,
share.base.keys - share.state.header.uniques,
keyinfo, share.base.fields, recdef,
share.state.header.uniques, uniquedef,
@@ -2966,7 +3042,7 @@ int recreate_table(MI_CHECK *param, MI_INFO **org_info, char *filename)
mi_check_print_error(param,"Got error %d when trying to recreate indexfile",my_errno);
goto end;
}
- *org_info=mi_open(name,O_RDWR,
+ *org_info=mi_open(filename,O_RDWR,
(param->testflag & T_WAIT_FOREVER) ? HA_OPEN_WAIT_IF_LOCKED :
(param->testflag & T_DESCRIPT) ? HA_OPEN_IGNORE_IF_LOCKED :
HA_OPEN_ABORT_IF_LOCKED);
@@ -3219,15 +3295,7 @@ my_bool mi_test_if_sort_rep(MI_INFO *info, ha_rows rows,
return FALSE; /* Can't use sort */
for (i=0 ; i < share->base.keys ; i++,key++)
{
-/* It's to disable repair_by_sort for ft-keys.
- Another solution would be to make ft-keys just too_big_key_for_sort,
- but then they won't be disabled by dectivate_non_unique_index
- and so they will be created at the first stage. As ft-key creation
- is very time-consuming process, it's better to leave it to repair stage
- but this repair shouldn't be repair_by_sort (serg)
- */
- if ((!force && mi_too_big_key_for_sort(key,rows)) ||
- (key->flag & HA_FULLTEXT))
+ if (!force && mi_too_big_key_for_sort(key,rows))
return FALSE;
}
return TRUE;
diff --git a/myisam/mi_checksum.c b/myisam/mi_checksum.c
index 9dabe55e239..a760b03a032 100644
--- a/myisam/mi_checksum.c
+++ b/myisam/mi_checksum.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
diff --git a/myisam/mi_close.c b/myisam/mi_close.c
index f30119144bc..bd8b9aff727 100644
--- a/myisam/mi_close.c
+++ b/myisam/mi_close.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
diff --git a/myisam/mi_create.c b/myisam/mi_create.c
index 7abf274d621..91c2c64c3cf 100644
--- a/myisam/mi_create.c
+++ b/myisam/mi_create.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -38,12 +38,13 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
register uint i,j;
File dfile,file;
int errpos,save_errno;
+ myf create_flag;
uint fields,length,max_key_length,packed,pointer,
key_length,info_length,key_segs,options,min_key_length_skipp,
base_pos,varchar_count,long_varchar_count,varchar_length,
max_key_block_length,unique_key_parts,offset;
ulong reclength, real_reclength,min_pack_length;
- char buff[FN_REFLEN];
+ char filename[FN_REFLEN],linkname[FN_REFLEN], *linkname_ptr;
ulong pack_reclength;
ulonglong tot_length,max_rows;
enum en_fieldtype type;
@@ -118,8 +119,8 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
pack_reclength+=(1 << ((rec->length-mi_portable_sizeof_char_ptr)*8)); /* Max blob length */
}
}
- else if (type == FIELD_SKIPP_PRESPACE ||
- type == FIELD_SKIPP_ENDSPACE)
+ else if (type == FIELD_SKIP_PRESPACE ||
+ type == FIELD_SKIP_ENDSPACE)
{
if (pack_reclength != INT_MAX32)
pack_reclength+= rec->length > 255 ? 2 : 1;
@@ -137,7 +138,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
pack_reclength+=2;
}
}
- else if (type != FIELD_SKIPP_ZERO)
+ else if (type != FIELD_SKIP_ZERO)
{
min_pack_length+=rec->length;
packed--; /* Not a pack record type */
@@ -151,7 +152,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
while (rec != recinfo)
{
rec--;
- if (rec->type == (int) FIELD_SKIPP_ZERO && rec->length == 1)
+ if (rec->type == (int) FIELD_SKIP_ZERO && rec->length == 1)
{
rec->type=(int) FIELD_NORMAL;
packed--;
@@ -163,6 +164,9 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
if (packed || (flags & HA_PACK_RECORD))
options|=HA_OPTION_PACK_RECORD; /* Must use packed records */
+ /* We can't use checksum with static length rows */
+ if (!(options & HA_OPTION_PACK_RECORD))
+ options&= ~HA_OPTION_CHECKSUM;
if (options & (HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD))
min_pack_length+=varchar_count; /* Min length to pack */
else
@@ -223,8 +227,8 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
share.state.key_del=key_del;
if (uniques)
{
- max_key_block_length= MI_KEY_BLOCK_LENGTH;
- max_key_length= MI_UNIQUE_HASH_LENGTH;
+ max_key_block_length= myisam_block_size;
+ max_key_length= MI_UNIQUE_HASH_LENGTH;
}
for (i=0, keydef=keydefs ; i < keys ; i++ , keydef++)
@@ -366,7 +370,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
share.state.rec_per_key_part[key_segs-1]=1L;
length+=key_length;
keydef->block_length= MI_BLOCK_SIZE(length,pointer,MI_MAX_KEYPTR_SIZE);
- if (keydef->block_length/MI_KEY_BLOCK_LENGTH > MI_MAX_KEY_BLOCK_SIZE)
+ if (keydef->block_length > MI_MAX_KEY_BLOCK_LENGTH)
{
my_errno=HA_WRONG_CREATE_OPTION;
goto err;
@@ -382,7 +386,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
(length*2)))*
(ulong) keydef->block_length;
}
- for (i=max_key_block_length/MI_KEY_BLOCK_LENGTH ; i-- ; )
+ for (i=max_key_block_length/MI_MIN_KEY_BLOCK_LENGTH ; i-- ; )
key_del[i]=HA_OFFSET_ERROR;
unique_key_parts=0;
@@ -397,7 +401,8 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
key_segs+=uniques; /* Each unique has 1 key seg */
base_pos=(MI_STATE_INFO_SIZE + keys * MI_STATE_KEY_SIZE +
- max_key_block_length/MI_KEY_BLOCK_LENGTH*MI_STATE_KEYBLOCK_SIZE+
+ max_key_block_length/MI_MIN_KEY_BLOCK_LENGTH*
+ MI_STATE_KEYBLOCK_SIZE+
key_segs*MI_STATE_KEYSEG_SIZE);
info_length=base_pos+(uint) (MI_BASE_INFO_SIZE+
keys * MI_KEYDEF_SIZE+
@@ -416,7 +421,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
mi_int2store(share.state.header.base_pos,base_pos);
share.state.header.language= (ci->language ?
ci->language : MY_CHARSET_CURRENT);
- share.state.header.max_block_size=max_key_block_length/MI_KEY_BLOCK_LENGTH;
+ share.state.header.max_block_size=max_key_block_length/MI_MIN_KEY_BLOCK_LENGTH;
share.state.dellink = HA_OFFSET_ERROR;
share.state.process= (ulong) getpid();
@@ -429,7 +434,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
share.base.rec_reflength=pointer;
share.base.key_reflength=
mi_get_pointer_length((tot_length + max_key_block_length * keys *
- MI_INDEX_BLOCK_MARGIN) / MI_KEY_BLOCK_LENGTH,
+ MI_INDEX_BLOCK_MARGIN) / MI_MIN_KEY_BLOCK_LENGTH,
3);
share.base.keys= share.state.header.keys = keys;
share.state.header.uniques= uniques;
@@ -444,7 +449,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
share.base.records=ci->max_rows;
share.base.reloc= ci->reloc_rows;
share.base.reclength=real_reclength;
- share.base.pack_reclength=reclength+ test(options & HA_OPTION_CHECKSUM);;
+ share.base.pack_reclength=reclength+ test(options & HA_OPTION_CHECKSUM);
share.base.max_pack_length=pack_reclength;
share.base.min_pack_length=min_pack_length;
share.base.pack_bits=packed;
@@ -468,17 +473,40 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
if (! (flags & HA_DONT_TOUCH_DATA))
share.state.create_time= (long) time((time_t*) 0);
- if ((file = my_create(fn_format(buff,name,"",MI_NAME_IEXT,4),0,
- O_RDWR | O_TRUNC,MYF(MY_WME))) < 0)
+ if (ci->index_file_name)
+ {
+ fn_format(filename, ci->index_file_name,"",MI_NAME_IEXT,4);
+ fn_format(linkname,name, "",MI_NAME_IEXT,4);
+ linkname_ptr=linkname;
+ /*
+ Don't create the table if the link or file exists to ensure that one
+ doesn't accidently destroy another table.
+ */
+ create_flag=0;
+ }
+ else
+ {
+ fn_format(filename,name,"",MI_NAME_IEXT,(4+ (flags & HA_DONT_TOUCH_DATA) ?
+ 32 : 0));
+ linkname_ptr=0;
+ /* Replace the current file */
+ create_flag=MY_DELETE_OLD;
+ }
+
+ if ((file= my_create_with_symlink(linkname_ptr,
+ filename,
+ 0, O_RDWR | O_TRUNC,
+ MYF(MY_WME | create_flag))) < 0)
goto err;
errpos=1;
- VOID(fn_format(buff,name,"",MI_NAME_DEXT,2+4));
+
if (!(flags & HA_DONT_TOUCH_DATA))
{
#ifdef USE_RAID
if (share.base.raid_type)
{
- if ((dfile=my_raid_create(buff,0,O_RDWR | O_TRUNC,
+ (void) fn_format(filename,name,"",MI_NAME_DEXT,2+4);
+ if ((dfile=my_raid_create(filename,0,O_RDWR | O_TRUNC,
share.base.raid_type,
share.base.raid_chunks,
share.base.raid_chunksize,
@@ -487,9 +515,26 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
}
else
#endif
- if ((dfile = my_create(buff,0,O_RDWR | O_TRUNC,MYF(MY_WME))) < 0)
- goto err;
-
+ {
+ if (ci->data_file_name)
+ {
+ fn_format(filename, ci->data_file_name,"",MI_NAME_DEXT,4);
+ fn_format(linkname, name, "",MI_NAME_DEXT,4);
+ linkname_ptr=linkname;
+ create_flag=0;
+ }
+ else
+ {
+ fn_format(filename,name,"",MI_NAME_DEXT,4);
+ linkname_ptr=0;
+ create_flag=MY_DELETE_OLD;
+ }
+ if ((dfile=
+ my_create_with_symlink(linkname_ptr, filename,
+ 0,O_RDWR | O_TRUNC,
+ MYF(MY_WME | create_flag))) < 0)
+ goto err;
+ }
errpos=3;
}
@@ -508,14 +553,14 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
/* Write key and keyseg definitions */
for (i=0 ; i < share.base.keys - uniques; i++)
{
- uint ft_segs=(keydefs[i].flag & HA_FULLTEXT) ? FT_SEGS : 0; /* SerG */
+ uint ft_segs=(keydefs[i].flag & HA_FULLTEXT) ? FT_SEGS : 0;
if (mi_keydef_write(file, &keydefs[i]))
goto err;
for (j=0 ; j < keydefs[i].keysegs-ft_segs ; j++)
if (mi_keyseg_write(file, &keydefs[i].seg[j]))
goto err;
- for (j=0 ; j < ft_segs ; j++) /* SerG */
+ for (j=0 ; j < ft_segs ; j++)
{
MI_KEYSEG seg=ft_keysegs[j];
seg.language= keydefs[i].seg[0].language;
@@ -531,7 +576,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
{
tmp_keydef.keysegs=1;
tmp_keydef.flag= HA_UNIQUE_CHECK;
- tmp_keydef.block_length= MI_KEY_BLOCK_LENGTH;
+ tmp_keydef.block_length= myisam_block_size;
tmp_keydef.keylength= MI_UNIQUE_HASH_LENGTH + pointer;
tmp_keydef.minlength=tmp_keydef.maxlength=tmp_keydef.keylength;
tmp_keyseg.type= MI_UNIQUE_HASH_TYPE;
@@ -596,20 +641,16 @@ err:
VOID(my_close(dfile,MYF(0)));
/* fall through */
case 2:
- if (! (flags & HA_DONT_TOUCH_DATA))
- {
/* QQ: Tõnu should add a call to my_raid_delete() here */
- VOID(fn_format(buff,name,"",MI_NAME_DEXT,2+4));
- my_delete(buff,MYF(0));
- }
+ if (! (flags & HA_DONT_TOUCH_DATA))
+ my_delete_with_symlink(fn_format(filename,name,"",MI_NAME_DEXT,2+4),
+ MYF(0));
/* fall through */
case 1:
VOID(my_close(file,MYF(0)));
if (! (flags & HA_DONT_TOUCH_DATA))
- {
- VOID(fn_format(buff,name,"",MI_NAME_IEXT,2+4));
- my_delete(buff,MYF(0));
- }
+ my_delete_with_symlink(fn_format(filename,name,"",MI_NAME_IEXT,2+4),
+ MYF(0));
}
my_free((char*) rec_per_key_part, MYF(0));
DBUG_RETURN(my_errno=save_errno); /* return the fatal errno */
diff --git a/myisam/mi_dbug.c b/myisam/mi_dbug.c
index eda1aafecc8..482287938c0 100644
--- a/myisam/mi_dbug.c
+++ b/myisam/mi_dbug.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -162,7 +162,7 @@ my_bool check_table_is_closed(const char *name, const char *where)
{
MI_INFO *info=(MI_INFO*) pos->data;
MYISAM_SHARE *share=info->s;
- if (!strcmp(share->filename,filename))
+ if (!strcmp(share->unique_file_name,filename))
{
if (share->last_version)
{
diff --git a/myisam/mi_delete.c b/myisam/mi_delete.c
index 445e745b07d..6f94e3c4256 100644
--- a/myisam/mi_delete.c
+++ b/myisam/mi_delete.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -97,6 +97,12 @@ int mi_delete(MI_INFO *info,const byte *record)
myisam_log_command(MI_LOG_DELETE,info,(byte*) lastpos,sizeof(lastpos),0);
VOID(_mi_writeinfo(info,WRITEINFO_UPDATE_KEYFILE));
allow_break(); /* Allow SIGHUP & SIGINT */
+ if (info->invalidator != 0)
+ {
+ DBUG_PRINT("info", ("invalidator... '%s' (delete)", info->filename));
+ (*info->invalidator)(info->filename);
+ info->invalidator=0;
+ }
DBUG_RETURN(0);
err:
@@ -196,7 +202,8 @@ static int d_search(register MI_INFO *info, register MI_KEYDEF *keyinfo,
DBUG_ENTER("d_search");
DBUG_DUMP("page",(byte*) anc_buff,mi_getint(anc_buff));
- flag=(*keyinfo->bin_search)(info,keyinfo,anc_buff,key,key_length,SEARCH_SAME,
+ flag=(*keyinfo->bin_search)(info,keyinfo,anc_buff,key, USE_WHOLE_KEY,
+ SEARCH_SAME,
&keypos, lastkey, &last_key);
if (flag == MI_FOUND_WRONG_KEY)
{
diff --git a/myisam/mi_delete_all.c b/myisam/mi_delete_all.c
index c3ed9455e12..82cf9e7a406 100644
--- a/myisam/mi_delete_all.c
+++ b/myisam/mi_delete_all.c
@@ -1,21 +1,21 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/* Remove all rows from a MyISAM table */
-/* This only clears the status information; The files are not truncated */
+/* This only clears the status information and truncates the data file */
#include "myisamdef.h"
@@ -43,13 +43,15 @@ int mi_delete_all_rows(MI_INFO *info)
info->state->empty=info->state->key_empty=0;
state->checksum=0;
- for (i=share->base.max_key_block_length/MI_KEY_BLOCK_LENGTH ; i-- ; )
+ for (i=share->base.max_key_block_length/MI_MIN_KEY_BLOCK_LENGTH ; i-- ; )
state->key_del[i]= HA_OFFSET_ERROR;
for (i=0 ; i < share->base.keys ; i++)
state->key_root[i]= HA_OFFSET_ERROR;
myisam_log_command(MI_LOG_DELETE_ALL,info,(byte*) 0,0,0);
VOID(_mi_writeinfo(info,WRITEINFO_UPDATE_KEYFILE));
+ if (my_chsize(info->dfile, 0, MYF(MY_WME)))
+ goto err;
allow_break(); /* Allow SIGHUP & SIGINT */
DBUG_RETURN(0);
@@ -62,4 +64,3 @@ err:
DBUG_RETURN(my_errno=save_errno);
}
} /* mi_delete */
-
diff --git a/myisam/mi_delete_table.c b/myisam/mi_delete_table.c
index 995106160ef..6d842d7e6a4 100644
--- a/myisam/mi_delete_table.c
+++ b/myisam/mi_delete_table.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -50,12 +50,12 @@ int mi_delete_table(const char *name)
#endif /* USE_RAID */
fn_format(from,name,"",MI_NAME_IEXT,4);
- if (my_delete(from, MYF(MY_WME)))
+ if (my_delete_with_symlink(from, MYF(MY_WME)))
DBUG_RETURN(my_errno);
fn_format(from,name,"",MI_NAME_DEXT,4);
#ifdef USE_RAID
if (raid_type)
DBUG_RETURN(my_raid_delete(from, raid_chunks, MYF(MY_WME)) ? my_errno : 0);
#endif
- DBUG_RETURN(my_delete(from, MYF(MY_WME)) ? my_errno : 0);
+ DBUG_RETURN(my_delete_with_symlink(from, MYF(MY_WME)) ? my_errno : 0);
}
diff --git a/myisam/mi_dynrec.c b/myisam/mi_dynrec.c
index c9fe493744d..b5f5ca7fd33 100644
--- a/myisam/mi_dynrec.c
+++ b/myisam/mi_dynrec.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -64,11 +64,13 @@ int _mi_write_blob_record(MI_INFO *info, const byte *record)
MI_DYN_DELETE_BLOCK_HEADER+1;
reclength=info->s->base.pack_reclength+
_my_calc_total_blob_length(info,record)+ extra;
+#ifdef NOT_USED /* We now support big rows */
if (reclength > MI_DYN_MAX_ROW_LENGTH)
{
my_errno=HA_ERR_TO_BIG_ROW;
return -1;
}
+#endif
if (!(rec_buff=(byte*) my_alloca(reclength)))
{
my_errno=ENOMEM;
@@ -93,11 +95,13 @@ int _mi_update_blob_record(MI_INFO *info, my_off_t pos, const byte *record)
MI_DYN_DELETE_BLOCK_HEADER;
reclength=info->s->base.pack_reclength+
_my_calc_total_blob_length(info,record)+ extra;
+#ifdef NOT_USED /* We now support big rows */
if (reclength > MI_DYN_MAX_ROW_LENGTH)
{
my_errno=HA_ERR_TO_BIG_ROW;
return -1;
}
+#endif
if (!(rec_buff=(byte*) my_alloca(reclength)))
{
my_errno=ENOMEM;
@@ -130,14 +134,14 @@ static int write_dynamic_record(MI_INFO *info, const byte *record,
DBUG_ENTER("write_dynamic_record");
flag=0;
- while (reclength)
+ do
{
if (_mi_find_writepos(info,reclength,&filepos,&length))
goto err;
if (_mi_write_part_record(info,filepos,length,info->s->state.dellink,
(byte**) &record,&reclength,&flag))
goto err;
- }
+ } while (reclength);
DBUG_RETURN(0);
err:
@@ -190,6 +194,8 @@ static int _mi_find_writepos(MI_INFO *info,
my_errno=HA_ERR_RECORD_FILE_FULL;
DBUG_RETURN(-1);
}
+ if (*length > MI_MAX_BLOCK_LENGTH)
+ *length=MI_MAX_BLOCK_LENGTH;
info->state->data_file_length+= *length;
info->s->state.split++;
info->update|=HA_STATE_WRITE_AT_END;
@@ -370,19 +376,30 @@ int _mi_write_part_record(MI_INFO *info,
info->s->state.dellink : info->state->data_file_length;
if (*flag == 0) /* First block */
{
- head_length=5+8+long_block*2;
- temp[0]=5+(uchar) long_block;
- if (long_block)
+ if (*reclength > MI_MAX_BLOCK_LENGTH)
{
- mi_int3store(temp+1,*reclength);
- mi_int3store(temp+4,length-head_length);
- mi_sizestore((byte*) temp+7,next_filepos);
+ head_length= 16;
+ temp[0]=13;
+ mi_int4store(temp+1,*reclength);
+ mi_int3store(temp+5,length-head_length);
+ mi_sizestore((byte*) temp+8,next_filepos);
}
else
{
- mi_int2store(temp+1,*reclength);
- mi_int2store(temp+3,length-head_length);
- mi_sizestore((byte*) temp+5,next_filepos);
+ head_length=5+8+long_block*2;
+ temp[0]=5+(uchar) long_block;
+ if (long_block)
+ {
+ mi_int3store(temp+1,*reclength);
+ mi_int3store(temp+4,length-head_length);
+ mi_sizestore((byte*) temp+7,next_filepos);
+ }
+ else
+ {
+ mi_int2store(temp+1,*reclength);
+ mi_int2store(temp+3,length-head_length);
+ mi_sizestore((byte*) temp+5,next_filepos);
+ }
}
}
else
@@ -629,7 +646,7 @@ uint _mi_rec_pack(MI_INFO *info, register byte *to, register const byte *from)
}
blob++;
}
- else if (type == FIELD_SKIPP_ZERO)
+ else if (type == FIELD_SKIP_ZERO)
{
if (memcmp((byte*) from,zero_string,length) == 0)
flag|=bit;
@@ -638,11 +655,11 @@ uint _mi_rec_pack(MI_INFO *info, register byte *to, register const byte *from)
memcpy((byte*) to,from,(size_t) length); to+=length;
}
}
- else if (type == FIELD_SKIPP_ENDSPACE ||
- type == FIELD_SKIPP_PRESPACE)
+ else if (type == FIELD_SKIP_ENDSPACE ||
+ type == FIELD_SKIP_PRESPACE)
{
pos= (byte*) from; end= (byte*) from + length;
- if (type == FIELD_SKIPP_ENDSPACE)
+ if (type == FIELD_SKIP_ENDSPACE)
{ /* Pack trailing spaces */
while (end > from && *(end-1) == ' ')
end--;
@@ -737,7 +754,7 @@ my_bool _mi_rec_check(MI_INFO *info,const char *record)
if (blob_length)
to+=length - mi_portable_sizeof_char_ptr+ blob_length;
}
- else if (type == FIELD_SKIPP_ZERO)
+ else if (type == FIELD_SKIP_ZERO)
{
if (memcmp((byte*) record,zero_string,length) == 0)
{
@@ -747,11 +764,11 @@ my_bool _mi_rec_check(MI_INFO *info,const char *record)
else
to+=length;
}
- else if (type == FIELD_SKIPP_ENDSPACE ||
- type == FIELD_SKIPP_PRESPACE)
+ else if (type == FIELD_SKIP_ENDSPACE ||
+ type == FIELD_SKIP_PRESPACE)
{
pos= (byte*) record; end= (byte*) record + length;
- if (type == FIELD_SKIPP_ENDSPACE)
+ if (type == FIELD_SKIP_ENDSPACE)
{ /* Pack trailing spaces */
while (end > record && *(end-1) == ' ')
end--;
@@ -863,10 +880,10 @@ ulong _mi_rec_unpack(register MI_INFO *info, register byte *to, byte *from,
}
if (flag & bit)
{
- if (type == FIELD_BLOB || type == FIELD_SKIPP_ZERO)
+ if (type == FIELD_BLOB || type == FIELD_SKIP_ZERO)
bzero((byte*) to,rec_length);
- else if (type == FIELD_SKIPP_ENDSPACE ||
- type == FIELD_SKIPP_PRESPACE)
+ else if (type == FIELD_SKIP_ENDSPACE ||
+ type == FIELD_SKIP_PRESPACE)
{
if (rec->length > 255 && *from & 128)
{
@@ -884,7 +901,7 @@ ulong _mi_rec_unpack(register MI_INFO *info, register byte *to, byte *from,
if (length >= rec_length ||
min_pack_length + length > (uint) (from_end - from))
goto err;
- if (type == FIELD_SKIPP_ENDSPACE)
+ if (type == FIELD_SKIP_ENDSPACE)
{
memcpy(to,(byte*) from,(size_t) length);
bfill((byte*) to+length,rec_length-length,' ');
@@ -911,7 +928,7 @@ ulong _mi_rec_unpack(register MI_INFO *info, register byte *to, byte *from,
}
else
{
- if (type == FIELD_SKIPP_ENDSPACE || type == FIELD_SKIPP_PRESPACE)
+ if (type == FIELD_SKIP_ENDSPACE || type == FIELD_SKIP_PRESPACE)
min_pack_length--;
if (min_pack_length + rec_length > (uint) (from_end - from))
goto err;
@@ -1059,11 +1076,11 @@ int _mi_read_dynamic_record(MI_INFO *info, my_off_t filepos, byte *buf)
} while (left_length);
info->update|= HA_STATE_AKTIV; /* We have a aktive record */
- VOID(_mi_writeinfo(info,0));
+ fast_mi_writeinfo(info);
DBUG_RETURN(_mi_rec_unpack(info,buf,info->rec_buff,block_info.rec_len) !=
MY_FILE_ERROR ? 0 : -1);
}
- VOID(_mi_writeinfo(info,0));
+ fast_mi_writeinfo(info);
DBUG_RETURN(-1); /* Wrong data to read */
panic:
@@ -1393,8 +1410,7 @@ int _mi_read_rnd_dynamic_record(MI_INFO *info, byte *buf,
} while (left_len);
info->update|= HA_STATE_AKTIV | HA_STATE_KEY_CHANGED;
- if (share->r_locks == 0 && share->w_locks == 0)
- VOID(_mi_writeinfo(info,0));
+ fast_mi_writeinfo(info);
if (_mi_rec_unpack(info,buf,info->rec_buff,block_info.rec_len) !=
MY_FILE_ERROR)
DBUG_RETURN(0);
@@ -1429,15 +1445,15 @@ uint _mi_get_block_info(MI_BLOCK_INFO *info, File file, my_off_t filepos)
DBUG_DUMP("header",(byte*) header,MI_BLOCK_INFO_HEADER_LENGTH);
if (info->second_read)
{
- if (info->header[0] <= 6)
+ if (info->header[0] <= 6 || info->header[0] == 13)
return_val=BLOCK_SYNC_ERROR;
}
else
{
- if (info->header[0] > 6)
+ if (info->header[0] > 6 && info->header[0] != 13)
return_val=BLOCK_SYNC_ERROR;
}
- info->next_filepos= HA_OFFSET_ERROR; /* Dummy ifall no next block */
+ info->next_filepos= HA_OFFSET_ERROR; /* Dummy if no next block */
switch (info->header[0]) {
case 0:
@@ -1471,6 +1487,14 @@ uint _mi_get_block_info(MI_BLOCK_INFO *info, File file, my_off_t filepos)
info->filepos=filepos+4;
return return_val | BLOCK_FIRST | BLOCK_LAST;
+ case 13:
+ info->rec_len=mi_uint4korr(header+1);
+ info->block_len=info->data_len=mi_uint3korr(header+5);
+ info->next_filepos=mi_sizekorr(header+8);
+ info->second_read=1;
+ info->filepos=filepos+16;
+ return return_val | BLOCK_FIRST;
+
case 3:
info->rec_len=info->data_len=mi_uint2korr(header+1);
info->block_len=info->rec_len+ (uint) header[3];
diff --git a/myisam/mi_extra.c b/myisam/mi_extra.c
index cf075512ac4..21cd9919ada 100644
--- a/myisam/mi_extra.c
+++ b/myisam/mi_extra.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -34,6 +34,7 @@ int mi_extra(MI_INFO *info, enum ha_extra_function function)
int error=0;
MYISAM_SHARE *share=info->s;
DBUG_ENTER("mi_extra");
+ DBUG_PRINT("enter",("function: %d",(int) function));
switch (function) {
case HA_EXTRA_RESET:
@@ -50,7 +51,7 @@ int mi_extra(MI_INFO *info, enum ha_extra_function function)
if (info->opt_flag & MEMMAP_USED)
madvise(share->file_map,share->state.state.data_file_length,MADV_RANDOM);
#endif
- info->opt_flag&= ~(KEY_READ_USED | REMEMBER_OLD_POS);
+ info->opt_flag&= ~(KEY_READ_USED | REMEMBER_OLD_POS);
info->quick_mode=0;
/* Fall through */
@@ -219,9 +220,17 @@ int mi_extra(MI_INFO *info, enum ha_extra_function function)
}
if (share->state.key_map)
{
- share->state.key_map=0;
- info->state->key_file_length=share->state.state.key_file_length=
- share->base.keystart;
+ MI_KEYDEF *key=share->keyinfo;
+ uint i;
+ for (i=0 ; i < share->base.keys ; i++,key++)
+ {
+ if (!(key->flag & HA_NOSAME) && info->s->base.auto_key != i+1)
+ {
+ share->state.key_map&= ~ ((ulonglong) 1 << i);
+ info->update|= HA_STATE_CHANGED;
+ }
+ }
+
if (!share->changed)
{
share->state.changed|= STATE_CHANGED | STATE_NOT_ANALYZED;
@@ -237,12 +246,15 @@ int mi_extra(MI_INFO *info, enum ha_extra_function function)
}
break;
case HA_EXTRA_FORCE_REOPEN:
+ case HA_EXTRA_PREPARE_FOR_DELETE:
pthread_mutex_lock(&THR_LOCK_myisam);
share->last_version= 0L; /* Impossible version */
#ifdef __WIN__
/* Close the isam and data files as Win32 can't drop an open table */
pthread_mutex_lock(&share->intern_lock);
- if (flush_key_blocks(share->kfile,FLUSH_RELEASE))
+ if (flush_key_blocks(share->kfile,
+ (function == HA_EXTRA_FORCE_REOPEN ?
+ FLUSH_RELEASE : FLUSH_IGNORE_CHANGED)))
{
error=my_errno;
share->changed=1;
@@ -328,6 +340,24 @@ int mi_extra(MI_INFO *info, enum ha_extra_function function)
case HA_EXTRA_QUICK:
info->quick_mode=1;
break;
+ case HA_EXTRA_BULK_INSERT_BEGIN:
+ error=_mi_init_bulk_insert(info);
+ break;
+ case HA_EXTRA_BULK_INSERT_END:
+ if (info->bulk_insert)
+ {
+ uint i;
+ for (i=0 ; i < share->base.keys ; i++)
+ {
+ if (is_tree_inited(& info->bulk_insert[i]))
+ {
+ delete_tree(& info->bulk_insert[i]);
+ }
+ }
+ my_free((void *)info->bulk_insert, MYF(0));
+ info->bulk_insert=0;
+ }
+ break;
case HA_EXTRA_NO_ROWS:
if (!share->state.header.uniques)
info->opt_flag|= OPT_NO_ROWS;
diff --git a/myisam/mi_info.c b/myisam/mi_info.c
index 6e7abfc0914..0be3cc44d80 100644
--- a/myisam/mi_info.c
+++ b/myisam/mi_info.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -45,7 +45,7 @@ int mi_status(MI_INFO *info, register MI_ISAMINFO *x, uint flag)
{
pthread_mutex_lock(&share->intern_lock);
VOID(_mi_readinfo(info,F_RDLCK,0));
- VOID(_mi_writeinfo(info,0));
+ fast_mi_writeinfo(info);
pthread_mutex_unlock(&share->intern_lock);
}
if (flag & HA_STATUS_VARIABLE)
@@ -87,6 +87,8 @@ int mi_status(MI_INFO *info, register MI_ISAMINFO *x, uint flag)
x->raid_chunks= share->base.raid_chunks;
x->raid_chunksize= share->base.raid_chunksize;
x->key_map = share->state.key_map;
+ x->data_file_name = share->data_file_name;
+ x->index_file_name = share->index_file_name;
}
if ((flag & HA_STATUS_TIME) && !my_fstat(info->dfile,&state,MYF(0)))
x->update_time=state.st_mtime;
diff --git a/myisam/mi_key.c b/myisam/mi_key.c
index 9f4e2cb1524..6ec8668ab61 100644
--- a/myisam/mi_key.c
+++ b/myisam/mi_key.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -18,6 +18,9 @@
#include "myisamdef.h"
#include "m_ctype.h"
+#ifdef HAVE_IEEEFP_H
+#include <ieeefp.h>
+#endif
#define CHECK_KEYS
@@ -88,25 +91,28 @@ uint _mi_make_key(register MI_INFO *info, uint keynr, uchar *key,
}
else if (keyseg->flag & HA_SWAP_KEY)
{ /* Numerical column */
-#ifdef NAN_TEST
- float float_nr;
- double dbl_nr;
+#ifdef HAVE_ISNAN
if (type == HA_KEYTYPE_FLOAT)
{
- float_nr=float4get(pos);
- if (float_nr == (float) FLT_MAX)
+ float nr;
+ float4get(nr,pos);
+ if (isnan(nr))
{
- float_nr= (float) FLT_MAX;
- pos= (byte*) &float_nr;
+ /* Replace NAN with zero */
+ bzero(key,length);
+ key+=length;
+ continue;
}
}
else if (type == HA_KEYTYPE_DOUBLE)
{
- dbl_nr=float8get(key);
- if (dbl_nr == DBL_MAX)
+ double nr;
+ float8get(nr,pos);
+ if (isnan(nr))
{
- dbl_nr=DBL_MAX;
- pos=(byte*) &dbl_nr;
+ bzero(key,length);
+ key+=length;
+ continue;
}
}
#endif
@@ -346,7 +352,7 @@ err:
int _mi_read_key_record(MI_INFO *info, my_off_t filepos, byte *buf)
{
- VOID(_mi_writeinfo(info,0));
+ fast_mi_writeinfo(info);
if (filepos != HA_OFFSET_ERROR)
{
if (info->lastinx >= 0)
diff --git a/myisam/mi_locking.c b/myisam/mi_locking.c
index de5f0d0c2cf..ea4966b05c5 100644
--- a/myisam/mi_locking.c
+++ b/myisam/mi_locking.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -43,13 +43,13 @@ int mi_lock_database(MI_INFO *info, int lock_type)
pthread_mutex_lock(&share->intern_lock);
if (share->kfile >= 0) /* May only be false on windows */
{
- switch (lock_type)
- {
+ switch (lock_type) {
case F_UNLCK:
if (info->lock_type == F_RDLCK)
count= --share->r_locks;
else
count= --share->w_locks;
+ --share->tot_locks;
if (info->lock_type == F_WRLCK && !share->w_locks &&
!share->delay_key_write && flush_key_blocks(share->kfile,FLUSH_KEEP))
{
@@ -153,6 +153,7 @@ int mi_lock_database(MI_INFO *info, int lock_type)
}
VOID(_mi_test_if_changed(info));
share->r_locks++;
+ share->tot_locks++;
info->lock_type=lock_type;
break;
case F_WRLCK:
@@ -199,7 +200,9 @@ int mi_lock_database(MI_INFO *info, int lock_type)
}
VOID(_mi_test_if_changed(info));
info->lock_type=lock_type;
+ info->invalidator=info->s->invalidator;
share->w_locks++;
+ share->tot_locks++;
break;
default:
break; /* Impossible */
@@ -295,13 +298,12 @@ my_bool mi_check_status(void* param)
int _mi_readinfo(register MI_INFO *info, int lock_type, int check_keybuffer)
{
- MYISAM_SHARE *share;
DBUG_ENTER("_mi_readinfo");
- share=info->s;
if (info->lock_type == F_UNLCK)
{
- if (!share->r_locks && !share->w_locks)
+ MYISAM_SHARE *share=info->s;
+ if (!share->tot_locks)
{
if (my_lock(share->kfile,lock_type,0L,F_TO_EOF,
info->lock_wait | MY_SEEK_NOT_DONE))
@@ -317,6 +319,7 @@ int _mi_readinfo(register MI_INFO *info, int lock_type, int check_keybuffer)
}
if (check_keybuffer)
VOID(_mi_test_if_changed(info));
+ info->invalidator=info->s->invalidator;
}
else if (lock_type == F_WRLCK && info->lock_type == F_RDLCK)
{
@@ -338,7 +341,7 @@ int _mi_writeinfo(register MI_INFO *info, uint operation)
DBUG_ENTER("_mi_writeinfo");
error=0;
- if (share->r_locks == 0 && share->w_locks == 0)
+ if (share->tot_locks == 0)
{
olderror=my_errno; /* Remember last error */
if (operation)
@@ -411,11 +414,14 @@ int _mi_mark_file_changed(MI_INFO *info)
share->global_changed=1;
share->state.open_count++;
}
- mi_int2store(buff,share->state.open_count);
- buff[2]=1; /* Mark that it's changed */
- return (my_pwrite(share->kfile,buff,sizeof(buff),
- sizeof(share->state.header),
- MYF(MY_NABP)));
+ if (!share->temporary)
+ {
+ mi_int2store(buff,share->state.open_count);
+ buff[2]=1; /* Mark that it's changed */
+ return (my_pwrite(share->kfile,buff,sizeof(buff),
+ sizeof(share->state.header),
+ MYF(MY_NABP)));
+ }
}
return 0;
}
diff --git a/myisam/mi_log.c b/myisam/mi_log.c
index 5c64c130212..1dcfd5250d2 100644
--- a/myisam/mi_log.c
+++ b/myisam/mi_log.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
diff --git a/myisam/mi_open.c b/myisam/mi_open.c
index 617b1cd8d90..bcf8369b439 100644
--- a/myisam/mi_open.c
+++ b/myisam/mi_open.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -48,7 +48,7 @@ static MI_INFO *test_if_reopen(char *filename)
{
MI_INFO *info=(MI_INFO*) pos->data;
MYISAM_SHARE *share=info->s;
- if (!strcmp(share->filename,filename) && share->last_version)
+ if (!strcmp(share->unique_file_name,filename) && share->last_version)
return info;
}
return 0;
@@ -68,7 +68,9 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
int lock_error,kfile,open_mode,save_errno;
uint i,j,len,errpos,head_length,base_pos,offset,info_length,extra,keys,
key_parts,unique_key_parts,tmp_length,uniques;
- char name_buff[FN_REFLEN],*disk_cache,*disk_pos;
+ char name_buff[FN_REFLEN], org_name [FN_REFLEN], index_name[FN_REFLEN],
+ data_name[FN_REFLEN];
+ char *disk_cache,*disk_pos;
MI_INFO info,*m_info,*old_info;
MYISAM_SHARE share_buff,*share;
ulong rec_per_key_part[MI_MAX_POSSIBLE_KEY*MI_MAX_KEY_SEG];
@@ -83,7 +85,7 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
head_length=sizeof(share_buff.state.header);
bzero((byte*) &info,sizeof(info));
- VOID(fn_format(name_buff,name,"",MI_NAME_IEXT,4+16+32));
+ my_realpath(name_buff, fn_format(org_name,name,"",MI_NAME_IEXT,4),MYF(0));
pthread_mutex_lock(&THR_LOCK_myisam);
if (!(old_info=test_if_reopen(name_buff)))
{
@@ -112,7 +114,7 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
DBUG_PRINT("error",("Wrong header in %s",name_buff));
DBUG_DUMP("error_dump",(char*) share->state.header.file_version,
head_length);
- my_errno=HA_ERR_CRASHED;
+ my_errno=HA_ERR_WRONG_TABLE_DEF;
goto err;
}
share->options= mi_uint2korr(share->state.header.options);
@@ -127,6 +129,13 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
my_errno=HA_ERR_OLD_FILE;
goto err;
}
+ /* Don't call realpath() if the name can't be a link */
+ if (strcmp(name_buff, org_name))
+ (void) my_readlink(index_name, org_name, MYF(0));
+ else
+ (void) strmov(index_name, org_name);
+ (void) fn_format(data_name,org_name,"",MI_NAME_DEXT,2+4+16);
+
info_length=mi_uint2korr(share->state.header.header_length);
base_pos=mi_uint2korr(share->state.header.base_pos);
if (!(disk_cache=(char*) my_alloca(info_length)))
@@ -207,7 +216,7 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
(mi_safe_mul(share->base.reclength,
(ulonglong) 1 << (share->base.rec_reflength*8))-1);
max_key_file_length=
- mi_safe_mul(MI_KEY_BLOCK_LENGTH,
+ mi_safe_mul(MI_MIN_KEY_BLOCK_LENGTH,
((ulonglong) 1 << (share->base.key_reflength*8))-1);
#if SIZEOF_OFF_T == 4
set_if_smaller(max_data_file_length, INT_MAX32);
@@ -249,7 +258,9 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
&share->rec,
(share->base.fields+1)*sizeof(MI_COLUMNDEF),
&share->blobs,sizeof(MI_BLOB)*share->base.blobs,
- &share->filename,strlen(name_buff)+1,
+ &share->unique_file_name,strlen(name_buff)+1,
+ &share->index_file_name,strlen(index_name)+1,
+ &share->data_file_name,strlen(data_name)+1,
&share->state.key_root,keys*sizeof(my_off_t),
&share->state.key_del,
(share->state.header.max_block_size*sizeof(my_off_t)),
@@ -267,7 +278,9 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
memcpy((char*) share->state.key_del,
(char*) key_del, (sizeof(my_off_t) *
share->state.header.max_block_size));
- strmov(share->filename,name_buff);
+ strmov(share->unique_file_name, name_buff);
+ strmov(share->index_file_name, index_name);
+ strmov(share->data_file_name, data_name);
share->blocksize=min(IO_SIZE,myisam_block_size);
{
@@ -354,7 +367,7 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
lock_error=1; /* Database unlocked */
}
- if (mi_open_datafile(&info, share))
+ if (mi_open_datafile(&info, share, -1))
goto err;
errpos=5;
@@ -427,7 +440,7 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
my_errno=EACCES; /* Can't open in write mode */
goto err;
}
- if (mi_open_datafile(&info, share))
+ if (mi_open_datafile(&info, share, old_info->dfile))
goto err;
errpos=5;
}
@@ -439,12 +452,12 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
&info.buff,(share->base.max_key_block_length*2+
share->base.max_key_length),
&info.lastkey,share->base.max_key_length*3+1,
- &info.filename,strlen(name)+1,
+ &info.filename,strlen(org_name)+1,
NullS))
goto err;
errpos=6;
- strmov(info.filename,name);
+ strmov(info.filename,org_name);
memcpy(info.blobs,share->blobs,sizeof(MI_BLOB)*share->base.blobs);
info.lastkey2=info.lastkey+share->base.max_key_length;
@@ -462,6 +475,7 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
share->options|=HA_OPTION_READ_ONLY_DATA;
info.lock_type=F_UNLCK;
info.quick_mode=0;
+ info.bulk_insert=0;
info.errkey= -1;
info.page_changed=1;
pthread_mutex_lock(&share->intern_lock);
@@ -515,7 +529,7 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
pthread_mutex_unlock(&THR_LOCK_myisam);
if (myisam_log_file >= 0)
{
- intern_filename(name_buff,share->filename);
+ intern_filename(name_buff,share->index_file_name);
_myisam_log(MI_LOG_OPEN,m_info,name_buff,(uint) strlen(name_buff));
}
DBUG_RETURN(m_info);
@@ -626,15 +640,20 @@ static void setup_key_functions(register MI_KEYDEF *keyinfo)
}
else if (keyinfo->flag & HA_VAR_LENGTH_KEY)
{
- keyinfo->bin_search=_mi_seq_search;
keyinfo->get_key= _mi_get_pack_key;
if (keyinfo->seg[0].flag & HA_PACK_KEY)
{ /* Prefix compression */
+ if (!keyinfo->seg->charset || use_strcoll(keyinfo->seg->charset) ||
+ (keyinfo->seg->flag & HA_NULL_PART))
+ keyinfo->bin_search=_mi_seq_search;
+ else
+ keyinfo->bin_search=_mi_prefix_search;
keyinfo->pack_key=_mi_calc_var_pack_key_length;
keyinfo->store_key=_mi_store_var_pack_key;
}
else
{
+ keyinfo->bin_search=_mi_seq_search;
keyinfo->pack_key=_mi_calc_var_key_length; /* Variable length key */
keyinfo->store_key=_mi_store_static_key;
}
@@ -773,14 +792,17 @@ uint mi_state_info_read_dsk(File file, MI_STATE_INFO *state, my_bool pRead)
{
char buff[MI_STATE_INFO_SIZE + MI_STATE_EXTRA_SIZE];
- if (pRead)
+ if (!myisam_single_user)
{
- if (my_pread(file, buff, state->state_length,0L, MYF(MY_NABP)))
+ if (pRead)
+ {
+ if (my_pread(file, buff, state->state_length,0L, MYF(MY_NABP)))
+ return (MY_FILE_ERROR);
+ }
+ else if (my_read(file, buff, state->state_length,MYF(MY_NABP)))
return (MY_FILE_ERROR);
+ mi_state_info_read(buff, state);
}
- else if (my_read(file, buff, state->state_length,MYF(MY_NABP)))
- return (MY_FILE_ERROR);
- mi_state_info_read(buff, state);
return 0;
}
@@ -892,7 +914,7 @@ char *mi_keydef_read(char *ptr, MI_KEYDEF *keydef)
keydef->keylength = mi_uint2korr(ptr); ptr +=2;
keydef->minlength = mi_uint2korr(ptr); ptr +=2;
keydef->maxlength = mi_uint2korr(ptr); ptr +=2;
- keydef->block_size = keydef->block_length/MI_KEY_BLOCK_LENGTH-1;
+ keydef->block_size = keydef->block_length/MI_MIN_KEY_BLOCK_LENGTH-1;
keydef->underflow_block_length=keydef->block_length/3;
keydef->version = 0; /* Not saved */
return ptr;
@@ -988,37 +1010,37 @@ char *mi_recinfo_read(char *ptr, MI_COLUMNDEF *recinfo)
}
/**************************************************************************
- ** Help functions for recover
- *************************************************************************/
+Open data file with or without RAID
+We can't use dup() here as the data file descriptors need to have different
+active seek-positions.
-int mi_open_datafile(MI_INFO *info, MYISAM_SHARE *share)
-{
- char name_buff[FN_REFLEN];
- (void) fn_format(name_buff, share->filename,"",MI_NAME_DEXT, 2+4);
+The argument file_to_dup is here for the future if there would on some OS
+exist a dup()-like call that would give us two different file descriptors.
+*************************************************************************/
+int mi_open_datafile(MI_INFO *info, MYISAM_SHARE *share, File file_to_dup __attribute__((unused)))
+{
#ifdef USE_RAID
if (share->base.raid_type)
{
- if ((info->dfile=my_raid_open(name_buff,
- share->mode | O_SHARE,
- share->base.raid_type,
- share->base.raid_chunks,
- share->base.raid_chunksize,
- MYF(MY_WME | MY_RAID))) < 0)
- return 1;
+ info->dfile=my_raid_open(share->data_file_name,
+ share->mode | O_SHARE,
+ share->base.raid_type,
+ share->base.raid_chunks,
+ share->base.raid_chunksize,
+ MYF(MY_WME | MY_RAID));
}
else
#endif
- if ((info->dfile=my_open(name_buff, share->mode | O_SHARE,
- MYF(MY_WME))) < 0)
- return 1;
- return 0;
+ info->dfile=my_open(share->data_file_name, share->mode | O_SHARE,
+ MYF(MY_WME));
+ return info->dfile >= 0 ? 0 : 1;
}
int mi_open_keyfile(MYISAM_SHARE *share)
{
- if ((share->kfile=my_open(share->filename, share->mode | O_SHARE,
+ if ((share->kfile=my_open(share->unique_file_name, share->mode | O_SHARE,
MYF(MY_WME))) < 0)
return 1;
return 0;
diff --git a/myisam/mi_packrec.c b/myisam/mi_packrec.c
index 242883a2c4a..d067fdc0fc5 100644
--- a/myisam/mi_packrec.c
+++ b/myisam/mi_packrec.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -465,7 +465,7 @@ static void (*get_unpack_function(MI_COLUMNDEF *rec))
(MI_COLUMNDEF *, MI_BIT_BUFF *, uchar *, uchar *)
{
switch (rec->base_type) {
- case FIELD_SKIPP_ZERO:
+ case FIELD_SKIP_ZERO:
if (rec->pack_type & PACK_TYPE_ZERO_FILL)
return &uf_zerofill_skipp_zero;
return &uf_skipp_zero;
@@ -475,7 +475,7 @@ static void (*get_unpack_function(MI_COLUMNDEF *rec))
if (rec->pack_type & PACK_TYPE_ZERO_FILL)
return &uf_zerofill_normal;
return &decode_bytes;
- case FIELD_SKIPP_ENDSPACE:
+ case FIELD_SKIP_ENDSPACE:
if (rec->pack_type & PACK_TYPE_SPACE_FIELDS)
{
if (rec->pack_type & PACK_TYPE_SELECTED)
@@ -485,7 +485,7 @@ static void (*get_unpack_function(MI_COLUMNDEF *rec))
if (rec->pack_type & PACK_TYPE_SELECTED)
return &uf_endspace_selected;
return &uf_endspace;
- case FIELD_SKIPP_PRESPACE:
+ case FIELD_SKIP_PRESPACE:
if (rec->pack_type & PACK_TYPE_SPACE_FIELDS)
{
if (rec->pack_type & PACK_TYPE_SELECTED)
diff --git a/myisam/mi_page.c b/myisam/mi_page.c
index f8e2a977754..064e9239e73 100644
--- a/myisam/mi_page.c
+++ b/myisam/mi_page.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -64,9 +64,9 @@ int _mi_write_keypage(register MI_INFO *info, register MI_KEYDEF *keyinfo,
#ifndef FAST /* Safety check */
if (page < info->s->base.keystart ||
page+keyinfo->block_length > info->state->key_file_length ||
- page & (myisam_block_size-1))
+ (page & (MI_MIN_KEY_BLOCK_LENGTH-1)))
{
- DBUG_PRINT("error",("Trying to write outside key region: %lu",
+ DBUG_PRINT("error",("Trying to write inside key status region: %lu",
(long) page));
my_errno=EINVAL;
return(-1);
diff --git a/myisam/mi_panic.c b/myisam/mi_panic.c
index 92fc6f3695c..bd0b07b097e 100644
--- a/myisam/mi_panic.c
+++ b/myisam/mi_panic.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
diff --git a/myisam/mi_range.c b/myisam/mi_range.c
index 038f9abc3a6..70694bf4620 100644
--- a/myisam/mi_range.c
+++ b/myisam/mi_range.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -45,7 +45,7 @@ ha_rows mi_records_in_range(MI_INFO *info, int inx, const byte *start_key,
if ((inx = _mi_check_index(info,inx)) < 0)
DBUG_RETURN(HA_POS_ERROR);
- if (_mi_readinfo(info,F_RDLCK,1))
+ if (fast_mi_readinfo(info))
DBUG_RETURN(HA_POS_ERROR);
info->update&= (HA_STATE_CHANGED+HA_STATE_ROW_CHANGED);
if (info->s->concurrent_insert)
@@ -58,7 +58,7 @@ ha_rows mi_records_in_range(MI_INFO *info, int inx, const byte *start_key,
info->state->records+ (ha_rows) 1);
if (info->s->concurrent_insert)
rw_unlock(&info->s->key_root_lock[inx]);
- VOID(_mi_writeinfo(info,0));
+ fast_mi_writeinfo(info);
if (start_pos == HA_POS_ERROR || end_pos == HA_POS_ERROR)
DBUG_RETURN(HA_POS_ERROR);
DBUG_PRINT("info",("records: %ld",(ulong) (end_pos-start_pos)));
@@ -72,7 +72,7 @@ ha_rows mi_records_in_range(MI_INFO *info, int inx, const byte *start_key,
static ha_rows _mi_record_pos(MI_INFO *info, const byte *key, uint key_len,
enum ha_rkey_function search_flag)
{
- uint inx=(uint) info->lastinx;
+ uint inx=(uint) info->lastinx, nextflag;
MI_KEYDEF *keyinfo=info->s->keyinfo+inx;
uchar *key_buff;
double pos;
@@ -86,8 +86,12 @@ static ha_rows _mi_record_pos(MI_INFO *info, const byte *key, uint key_len,
key_len=_mi_pack_key(info,inx,key_buff,(uchar*) key,key_len);
DBUG_EXECUTE("key",_mi_print_key(DBUG_FILE,keyinfo->seg,
(uchar*) key_buff,key_len););
+ nextflag=myisam_read_vec[search_flag];
+ if (!(nextflag & (SEARCH_FIND | SEARCH_NO_FIND | SEARCH_LAST)))
+ key_len=USE_WHOLE_KEY;
+
pos=_mi_search_pos(info,keyinfo,key_buff,key_len,
- myisam_read_vec[search_flag] | SEARCH_SAVE_BUFF,
+ nextflag | SEARCH_SAVE_BUFF,
info->s->state.key_root[inx]);
if (pos >= 0.0)
{
@@ -145,9 +149,9 @@ static double _mi_search_pos(register MI_INFO *info,
** Matches keynr+1
*/
offset=1.0; /* Matches keynr+1 */
- if (nextflag & SEARCH_FIND &&
+ if ((nextflag & SEARCH_FIND) && nod_flag &&
((keyinfo->flag & (HA_NOSAME | HA_NULL_PART)) != HA_NOSAME ||
- key_len) && nod_flag)
+ key_len != USE_WHOLE_KEY))
{
/*
** There may be identical keys in the tree. Try to match on of those.
diff --git a/myisam/mi_rename.c b/myisam/mi_rename.c
index 5c92db3f7ce..db44b8fe28f 100644
--- a/myisam/mi_rename.c
+++ b/myisam/mi_rename.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -51,7 +51,7 @@ int mi_rename(const char *old_name, const char *new_name)
fn_format(from,old_name,"",MI_NAME_IEXT,4);
fn_format(to,new_name,"",MI_NAME_IEXT,4);
- if (my_rename(from, to, MYF(MY_WME)))
+ if (my_rename_with_symlink(from, to, MYF(MY_WME)))
DBUG_RETURN(my_errno);
fn_format(from,old_name,"",MI_NAME_DEXT,4);
fn_format(to,new_name,"",MI_NAME_DEXT,4);
@@ -60,5 +60,5 @@ int mi_rename(const char *old_name, const char *new_name)
DBUG_RETURN(my_raid_rename(from, to, raid_chunks, MYF(MY_WME)) ? my_errno :
0);
#endif
- DBUG_RETURN(my_rename(from, to,MYF(MY_WME)) ? my_errno : 0);
+ DBUG_RETURN(my_rename_with_symlink(from, to,MYF(MY_WME)) ? my_errno : 0);
}
diff --git a/myisam/mi_rfirst.c b/myisam/mi_rfirst.c
index 8928c6332c5..e30f61801a0 100644
--- a/myisam/mi_rfirst.c
+++ b/myisam/mi_rfirst.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
diff --git a/myisam/mi_rkey.c b/myisam/mi_rkey.c
index 0df390412b9..86547d3ef04 100644
--- a/myisam/mi_rkey.c
+++ b/myisam/mi_rkey.c
@@ -27,7 +27,7 @@ int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len,
{
uchar *key_buff;
MYISAM_SHARE *share=info->s;
- uint pack_key_length;
+ uint pack_key_length, use_key_length, nextflag;
DBUG_ENTER("mi_rkey");
DBUG_PRINT("enter",("base: %lx inx: %d search_flag: %d",
info,inx,search_flag));
@@ -55,11 +55,17 @@ int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len,
bmove(key_buff,key,key_len);
}
- if (_mi_readinfo(info,F_RDLCK,1))
+ if (fast_mi_readinfo(info))
goto err;
if (share->concurrent_insert)
rw_rdlock(&share->key_root_lock[inx]);
- if (!_mi_search(info,info->s->keyinfo+inx,key_buff,pack_key_length,
+
+ nextflag=myisam_read_vec[search_flag];
+ use_key_length=pack_key_length;
+ if (!(nextflag & (SEARCH_FIND | SEARCH_NO_FIND | SEARCH_LAST)))
+ use_key_length=USE_WHOLE_KEY;
+
+ if (!_mi_search(info,info->s->keyinfo+inx,key_buff,use_key_length,
myisam_read_vec[search_flag],info->s->state.key_root[inx]))
{
while (info->lastpos >= info->state->data_file_length)
diff --git a/myisam/mi_rlast.c b/myisam/mi_rlast.c
index c08174e9117..61c3ff58fd5 100644
--- a/myisam/mi_rlast.c
+++ b/myisam/mi_rlast.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
diff --git a/myisam/mi_rnext.c b/myisam/mi_rnext.c
index f297740af60..6d135462f96 100644
--- a/myisam/mi_rnext.c
+++ b/myisam/mi_rnext.c
@@ -35,7 +35,7 @@ int mi_rnext(MI_INFO *info, byte *buf, int inx)
if (info->lastpos == HA_OFFSET_ERROR && info->update & HA_STATE_PREV_FOUND)
flag=0; /* Read first */
- if (_mi_readinfo(info,F_RDLCK,1))
+ if (fast_mi_readinfo(info))
DBUG_RETURN(my_errno);
if (info->s->concurrent_insert)
rw_rdlock(&info->s->key_root_lock[inx]);
@@ -51,7 +51,7 @@ int mi_rnext(MI_INFO *info, byte *buf, int inx)
info->s->state.key_root[inx]);
else
error=_mi_search(info,info->s->keyinfo+inx,info->lastkey,
- info->lastkey_length,flag, info->s->state.key_root[inx]);
+ USE_WHOLE_KEY,flag, info->s->state.key_root[inx]);
if (!error)
{
diff --git a/myisam/mi_rnext_same.c b/myisam/mi_rnext_same.c
index 0e172894cdf..662bdb154b3 100644
--- a/myisam/mi_rnext_same.c
+++ b/myisam/mi_rnext_same.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -35,7 +35,7 @@ int mi_rnext_same(MI_INFO *info, byte *buf)
DBUG_RETURN(my_errno=HA_ERR_WRONG_INDEX);
keyinfo=info->s->keyinfo+inx;
flag=SEARCH_BIGGER; /* Read next */
- if (_mi_readinfo(info,F_RDLCK,1))
+ if (fast_mi_readinfo(info))
DBUG_RETURN(my_errno);
memcpy(info->lastkey2,info->lastkey,info->last_rkey_length);
diff --git a/myisam/mi_rprev.c b/myisam/mi_rprev.c
index fff2d2257b6..4807e636252 100644
--- a/myisam/mi_rprev.c
+++ b/myisam/mi_rprev.c
@@ -36,7 +36,7 @@ int mi_rprev(MI_INFO *info, byte *buf, int inx)
if (info->lastpos == HA_OFFSET_ERROR && info->update & HA_STATE_NEXT_FOUND)
flag=0; /* Read last */
- if (_mi_readinfo(info,F_RDLCK,1))
+ if (fast_mi_readinfo(info))
DBUG_RETURN(my_errno);
changed=_mi_test_if_changed(info);
if (share->concurrent_insert)
@@ -50,7 +50,7 @@ int mi_rprev(MI_INFO *info, byte *buf, int inx)
share->state.key_root[inx]);
else
error=_mi_search(info,share->keyinfo+inx,info->lastkey,
- info->lastkey_length, flag, share->state.key_root[inx]);
+ USE_WHOLE_KEY, flag, share->state.key_root[inx]);
if (!error)
{
diff --git a/myisam/mi_rrnd.c b/myisam/mi_rrnd.c
index 11fa2af59bd..f8009441cff 100644
--- a/myisam/mi_rrnd.c
+++ b/myisam/mi_rrnd.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
diff --git a/myisam/mi_rsame.c b/myisam/mi_rsame.c
index a4092b53c0b..56c8d1226ca 100644
--- a/myisam/mi_rsame.c
+++ b/myisam/mi_rsame.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -41,7 +41,7 @@ int mi_rsame(MI_INFO *info, byte *record, int inx)
info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
/* Read row from data file */
- if (_mi_readinfo(info,F_RDLCK,1))
+ if (fast_mi_readinfo(info))
DBUG_RETURN(my_errno);
if (inx >= 0)
@@ -51,7 +51,8 @@ int mi_rsame(MI_INFO *info, byte *record, int inx)
info->lastpos);
if (info->s->concurrent_insert)
rw_rdlock(&info->s->key_root_lock[inx]);
- VOID(_mi_search(info,info->s->keyinfo+inx,info->lastkey,0,SEARCH_SAME,
+ VOID(_mi_search(info,info->s->keyinfo+inx,info->lastkey, USE_WHOLE_KEY,
+ SEARCH_SAME,
info->s->state.key_root[inx]));
if (info->s->concurrent_insert)
rw_unlock(&info->s->key_root_lock[inx]);
diff --git a/myisam/mi_rsamepos.c b/myisam/mi_rsamepos.c
index 28a5b6783b2..a1d96fb7104 100644
--- a/myisam/mi_rsamepos.c
+++ b/myisam/mi_rsamepos.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
diff --git a/myisam/mi_scan.c b/myisam/mi_scan.c
index c06f092ab17..90bc3430ba7 100644
--- a/myisam/mi_scan.c
+++ b/myisam/mi_scan.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
diff --git a/myisam/mi_search.c b/myisam/mi_search.c
index 2c04679ed4c..4114125d6f7 100644
--- a/myisam/mi_search.c
+++ b/myisam/mi_search.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -19,29 +19,27 @@
#include "fulltext.h"
#include "m_ctype.h"
-#define CMP(a,b) (a<b ? -1 : a == b ? 0 : 1)
-
static my_bool _mi_get_prev_key(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *page,
- uchar *key, uchar *keypos,
- uint *return_key_length);
+ uchar *key, uchar *keypos,
+ uint *return_key_length);
- /* Check index */
+ /* Check index */
int _mi_check_index(MI_INFO *info, int inx)
{
- if (inx == -1) /* Use last index */
+ if (inx == -1) /* Use last index */
inx=info->lastinx;
if (inx < 0 || ! (((ulonglong) 1 << inx) & info->s->state.key_map))
{
my_errno=HA_ERR_WRONG_INDEX;
return -1;
}
- if (info->lastinx != inx) /* Index changed */
+ if (info->lastinx != inx) /* Index changed */
{
info->lastinx = inx;
info->page_changed=1;
info->update= ((info->update & (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED)) |
- HA_STATE_NEXT_FOUND | HA_STATE_PREV_FOUND);
+ HA_STATE_NEXT_FOUND | HA_STATE_PREV_FOUND);
}
if (info->opt_flag & WRITE_CACHE_USED && flush_io_cache(&info->rec_cache))
return(-1);
@@ -49,15 +47,15 @@ int _mi_check_index(MI_INFO *info, int inx)
} /* mi_check_index */
- /*
- ** Search after row by a key
- ** Position to row is stored in info->lastpos
- ** Return: -1 if not found
- ** 1 if one should continue search on higher level
- */
+ /*
+ ** Search after row by a key
+ ** Position to row is stored in info->lastpos
+ ** Return: -1 if not found
+ ** 1 if one should continue search on higher level
+ */
int _mi_search(register MI_INFO *info, register MI_KEYDEF *keyinfo,
- uchar *key, uint key_len, uint nextflag, register my_off_t pos)
+ uchar *key, uint key_len, uint nextflag, register my_off_t pos)
{
my_bool last_key;
int error,flag;
@@ -66,25 +64,25 @@ int _mi_search(register MI_INFO *info, register MI_KEYDEF *keyinfo,
uchar lastkey[MI_MAX_KEY_BUFF],*buff;
DBUG_ENTER("_mi_search");
DBUG_PRINT("enter",("pos: %ld nextflag: %d lastpos: %ld",
- pos,nextflag,info->lastpos));
+ pos,nextflag,info->lastpos));
DBUG_EXECUTE("key",_mi_print_key(DBUG_FILE,keyinfo->seg,key,key_len););
if (pos == HA_OFFSET_ERROR)
{
- my_errno=HA_ERR_KEY_NOT_FOUND; /* Didn't find key */
+ my_errno=HA_ERR_KEY_NOT_FOUND; /* Didn't find key */
info->lastpos= HA_OFFSET_ERROR;
if (!(nextflag & (SEARCH_SMALLER | SEARCH_BIGGER | SEARCH_LAST)))
- DBUG_RETURN(-1); /* Not found ; return error */
- DBUG_RETURN(1); /* Search at upper levels */
+ DBUG_RETURN(-1); /* Not found ; return error */
+ DBUG_RETURN(1); /* Search at upper levels */
}
if (!(buff=_mi_fetch_keypage(info,keyinfo,pos,info->buff,
- test(!(nextflag & SEARCH_SAVE_BUFF)))))
+ test(!(nextflag & SEARCH_SAVE_BUFF)))))
goto err;
DBUG_DUMP("page",(byte*) buff,mi_getint(buff));
flag=(*keyinfo->bin_search)(info,keyinfo,buff,key,key_len,nextflag,
- &keypos,lastkey, &last_key);
+ &keypos,lastkey, &last_key);
if (flag == MI_FOUND_WRONG_KEY)
DBUG_RETURN(-1);
nod_flag=mi_test_if_nod(buff);
@@ -93,35 +91,36 @@ int _mi_search(register MI_INFO *info, register MI_KEYDEF *keyinfo,
if (flag)
{
if ((error=_mi_search(info,keyinfo,key,key_len,nextflag,
- _mi_kpos(nod_flag,keypos))) <= 0)
+ _mi_kpos(nod_flag,keypos))) <= 0)
DBUG_RETURN(error);
if (flag >0)
{
if (nextflag & (SEARCH_SMALLER | SEARCH_LAST) &&
- keypos == buff+2+nod_flag)
- DBUG_RETURN(1); /* Bigger than key */
+ keypos == buff+2+nod_flag)
+ DBUG_RETURN(1); /* Bigger than key */
}
else if (nextflag & SEARCH_BIGGER && keypos >= maxpos)
- DBUG_RETURN(1); /* Smaller than key */
+ DBUG_RETURN(1); /* Smaller than key */
}
else
{
- if (nextflag & SEARCH_FIND && (!(keyinfo->flag & HA_NOSAME)
- || key_len) && nod_flag)
+ if ((nextflag & SEARCH_FIND) && nod_flag &&
+ ((keyinfo->flag & (HA_NOSAME | HA_NULL_PART)) != HA_NOSAME ||
+ key_len != USE_WHOLE_KEY))
{
if ((error=_mi_search(info,keyinfo,key,key_len,SEARCH_FIND,
- _mi_kpos(nod_flag,keypos))) >= 0 ||
- my_errno != HA_ERR_KEY_NOT_FOUND)
- DBUG_RETURN(error);
- info->last_keypage= HA_OFFSET_ERROR; /* Buffer not in memory */
+ _mi_kpos(nod_flag,keypos))) >= 0 ||
+ my_errno != HA_ERR_KEY_NOT_FOUND)
+ DBUG_RETURN(error);
+ info->last_keypage= HA_OFFSET_ERROR; /* Buffer not in mem */
}
}
if (pos != info->last_keypage)
{
uchar *old_buff=buff;
if (!(buff=_mi_fetch_keypage(info,keyinfo,pos,info->buff,
- test(!(nextflag & SEARCH_SAVE_BUFF)))))
+ test(!(nextflag & SEARCH_SAVE_BUFF)))))
goto err;
keypos=buff+(keypos-old_buff);
maxpos=buff+(maxpos-old_buff);
@@ -131,13 +130,13 @@ int _mi_search(register MI_INFO *info, register MI_KEYDEF *keyinfo,
{
uint not_used;
if (_mi_get_prev_key(info,keyinfo, buff, info->lastkey, keypos,
- &info->lastkey_length))
+ &info->lastkey_length))
goto err;
if ((nextflag & SEARCH_LAST) &&
- _mi_key_cmp(keyinfo->seg, info->lastkey, key, key_len, SEARCH_FIND,
- &not_used))
+ _mi_key_cmp(keyinfo->seg, info->lastkey, key, key_len, SEARCH_FIND,
+ &not_used))
{
- my_errno=HA_ERR_KEY_NOT_FOUND; /* Didn't find key */
+ my_errno=HA_ERR_KEY_NOT_FOUND; /* Didn't find key */
goto err;
}
}
@@ -156,7 +155,7 @@ int _mi_search(register MI_INFO *info, register MI_KEYDEF *keyinfo,
info->int_keytree_version=keyinfo->version;
info->last_search_keypage=info->last_keypage;
info->page_changed=0;
- info->buff_used= (info->buff != buff); /* If we have to reread buff */
+ info->buff_used= (info->buff != buff); /* If we have to reread buff */
DBUG_PRINT("exit",("found key at %lu",(ulong) info->lastpos));
DBUG_RETURN(0);
@@ -168,14 +167,14 @@ err:
} /* _mi_search */
- /* Search after key in page-block */
- /* If packed key puts smaller or identical key in buff */
- /* ret_pos point to where find or bigger key starts */
- /* ARGSUSED */
+ /* Search after key in page-block */
+ /* If packed key puts smaller or identical key in buff */
+ /* ret_pos point to where find or bigger key starts */
+ /* ARGSUSED */
int _mi_bin_search(MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *page,
- uchar *key, uint key_len, uint comp_flag, uchar **ret_pos,
- uchar *buff __attribute__((unused)), my_bool *last_key)
+ uchar *key, uint key_len, uint comp_flag, uchar **ret_pos,
+ uchar *buff __attribute__((unused)), my_bool *last_key)
{
reg4 int start,mid,end,save_end;
int flag;
@@ -193,17 +192,17 @@ int _mi_bin_search(MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *page,
{
mid= (start+end)/2;
if ((flag=_mi_key_cmp(keyinfo->seg,page+(uint) mid*totlength,key,key_len,
- comp_flag,&not_used))
- >= 0)
+ comp_flag,&not_used))
+ >= 0)
end=mid;
else
start=mid+1;
}
if (mid != start)
flag=_mi_key_cmp(keyinfo->seg,page+(uint) start*totlength,key,key_len,
- comp_flag,&not_used);
+ comp_flag,&not_used);
if (flag < 0)
- start++; /* point at next, bigger key */
+ start++; /* point at next, bigger key */
*ret_pos=page+(uint) start*totlength;
*last_key= end == save_end;
DBUG_PRINT("exit",("flag: %d keypos: %d",flag,start));
@@ -211,13 +210,13 @@ int _mi_bin_search(MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *page,
} /* _mi_bin_search */
- /* Used instead of _mi_bin_search() when key is packed */
- /* Puts smaller or identical key in buff */
- /* Key is searched sequentially */
+ /* Used instead of _mi_bin_search() when key is packed */
+ /* Puts smaller or identical key in buff */
+ /* Key is searched sequentially */
int _mi_seq_search(MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *page,
- uchar *key, uint key_len, uint comp_flag, uchar **ret_pos,
- uchar *buff, my_bool *last_key)
+ uchar *key, uint key_len, uint comp_flag, uchar **ret_pos,
+ uchar *buff, my_bool *last_key)
{
int flag;
uint nod_flag,length,not_used;
@@ -229,7 +228,7 @@ int _mi_seq_search(MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *page,
nod_flag=mi_test_if_nod(page);
page+=2+nod_flag;
*ret_pos=page;
- t_buff[0]=0; /* Avoid bugs */
+ t_buff[0]=0; /* Avoid bugs */
while (page < end)
{
length=(*keyinfo->get_key)(keyinfo,nod_flag,&page,t_buff);
@@ -237,11 +236,11 @@ int _mi_seq_search(MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *page,
{
my_errno=HA_ERR_CRASHED;
DBUG_PRINT("error",("Found wrong key: length: %d page: %lx end: %lx",
- length,page,end));
+ length,page,end));
DBUG_RETURN(MI_FOUND_WRONG_KEY);
}
if ((flag=_mi_key_cmp(keyinfo->seg,t_buff,key,key_len,comp_flag,
- &not_used)) >= 0)
+ &not_used)) >= 0)
break;
#ifdef EXTRA_DEBUG
DBUG_PRINT("loop",("page: %lx key: '%s' flag: %d",page,t_buff,flag));
@@ -250,14 +249,224 @@ int _mi_seq_search(MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *page,
*ret_pos=page;
}
if (flag == 0)
- memcpy(buff,t_buff,length); /* Result is first key */
+ memcpy(buff,t_buff,length); /* Result is first key */
*last_key= page == end;
DBUG_PRINT("exit",("flag: %d ret_pos: %lx",flag,*ret_pos));
DBUG_RETURN(flag);
} /* _mi_seq_search */
- /* Get pos to a key_block */
+int _mi_prefix_search(MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *page,
+ uchar *key, uint key_len, uint nextflag, uchar **ret_pos,
+ uchar *buff, my_bool *last_key)
+{
+ /* my_flag is raw comparison result to be changed according to
+ SEARCH_NO_FIND,SEARCH_LAST and HA_REVERSE_SORT flags.
+ flag is the value returned by _mi_key_cmp and as treated as final */
+ int flag=0, my_flag=-1;
+ uint nod_flag, length, len, matched, cmplen, kseg_len;
+ uint prefix_len,suffix_len;
+ int key_len_skip, seg_len_pack, key_len_left;
+ uchar *end, *kseg, *vseg;
+ uchar *sort_order=keyinfo->seg->charset->sort_order;
+ uchar tt_buff[MI_MAX_KEY_BUFF+2], *t_buff=tt_buff+2;
+ uchar *saved_from, *saved_to, *saved_vseg;
+ uint saved_length=0, saved_prefix_len=0;
+ DBUG_ENTER("_mi_prefix_search");
+
+ LINT_INIT(length);
+ LINT_INIT(prefix_len);
+ LINT_INIT(seg_len_pack);
+ LINT_INIT(saved_from);
+ LINT_INIT(saved_to);
+ LINT_INIT(saved_vseg);
+
+ t_buff[0]=0; /* Avoid bugs */
+ end= page+mi_getint(page);
+ nod_flag=mi_test_if_nod(page);
+ page+=2+nod_flag;
+ *ret_pos=page;
+ kseg=key;
+ {
+ uint lenght_pack;
+ get_key_pack_length(kseg_len,lenght_pack,kseg);
+ key_len_skip=lenght_pack+kseg_len;
+ key_len_left=(int) key_len- (int) key_len_skip;
+ cmplen=(key_len_left>=0) ? kseg_len : key_len-lenght_pack;
+ DBUG_PRINT("info",("key: '%.*s'",kseg_len,kseg));
+ }
+
+/*
+ Keys are compressed the following way:
+
+ If the max length of first key segment <= 127 characters the prefix is
+ 1 byte else it's 2 byte
+
+ prefix The high bit is set if this is a prefix for the prev key
+ length Packed length if the previous was a prefix byte
+ [length] Length character of data
+ next-key-seg Next key segments
+*/
+
+ matched=0; /* how many char's from prefix were alredy matched */
+ len=0; /* length of previous key unpacked */
+
+ while (page < end)
+ {
+ uint packed= *page & 128;
+
+ vseg=page;
+ if (keyinfo->seg->length >= 127)
+ {
+ suffix_len=mi_uint2korr(vseg) & 32767;
+ vseg+=2;
+ }
+ else
+ suffix_len= *vseg++ & 127;
+
+ if (packed)
+ {
+ if (suffix_len == 0) /* Same key */
+ prefix_len=len;
+ else
+ {
+ prefix_len=suffix_len;
+ get_key_length(suffix_len,vseg);
+ }
+ }
+ else
+ prefix_len=0;
+
+ len=prefix_len+suffix_len;
+ seg_len_pack=get_pack_length(len);
+ t_buff=tt_buff+3-seg_len_pack;
+ store_key_length(t_buff,len);
+
+ if (prefix_len > saved_prefix_len)
+ memcpy(t_buff+seg_len_pack+saved_prefix_len,saved_vseg,
+ prefix_len-saved_prefix_len);
+ saved_vseg=vseg;
+ saved_prefix_len=prefix_len;
+
+ DBUG_PRINT("loop",("page: '%.*s%.*s'",prefix_len,t_buff+seg_len_pack,suffix_len,vseg));
+ {
+ uchar *from=vseg+suffix_len;
+ MI_KEYSEG *keyseg;
+ uint l;
+
+ for (keyseg=keyinfo->seg+1 ; keyseg->type ; keyseg++ )
+ {
+
+ if (keyseg->flag & HA_NULL_PART)
+ {
+ if (!(*from++))
+ continue;
+ }
+ if (keyseg->flag & (HA_VAR_LENGTH | HA_BLOB_PART | HA_SPACE_PACK))
+ {
+ get_key_length(l,from);
+ }
+ else
+ l=keyseg->length;
+
+ from+=l;
+ }
+ from+=keyseg->length;
+ page=from+nod_flag;
+ length=from-vseg;
+ }
+
+ if (page > end)
+ {
+ my_errno=HA_ERR_CRASHED;
+ DBUG_PRINT("error",("Found wrong key: length: %d page: %lx end: %lx",
+ length,page,end));
+ DBUG_RETURN(MI_FOUND_WRONG_KEY);
+ }
+
+ if (matched >= prefix_len)
+ {
+ /* We have to compare. But we can still skip part of the key */
+ uint left;
+ uchar *k=kseg+prefix_len;
+
+ left=(len>cmplen) ? cmplen-prefix_len : suffix_len;
+
+ matched=prefix_len+left;
+
+ for(my_flag=0;left;left--)
+ if ((my_flag= (int) sort_order[*vseg++] - (int) sort_order[*k++]))
+ break;
+
+ if (my_flag>0) /* mismatch */
+ break;
+ else if (my_flag==0) /* match */
+ { /*
+ ** len cmplen seg_left_len more_segs
+ ** < matched=len; continue search
+ ** > = prefix ? found : (matched=len; continue search)
+ ** > < - ok, found
+ ** = < - ok, found
+ ** = = - ok, found
+ ** = = + next seg
+ */
+ if (len < cmplen)
+ {
+ my_flag= -1;
+ }
+ else if (len > cmplen)
+ {
+ if ((my_flag= (!(nextflag & SEARCH_PREFIX) || key_len_left>0)))
+ break;
+ goto fix_flag;
+ }
+ else if (key_len_left>0)
+ {
+ uint not_used;
+ if ((flag = _mi_key_cmp(keyinfo->seg+1,vseg,
+ k,key_len_left,nextflag,&not_used)) >= 0)
+ break;
+ }
+ else
+ {
+ /* at this line flag==-1 if the following lines were already
+ visited and 0 otherwise, i.e. flag <=0 here always !!! */
+ fix_flag:
+ if (nextflag & (SEARCH_NO_FIND | SEARCH_LAST))
+ flag=(nextflag & (SEARCH_BIGGER | SEARCH_LAST)) ? -1 : 1;
+ if (flag>=0) break;
+ }
+ }
+ matched-=left;
+ }
+ /* else (matched < prefix_len) ---> do nothing. */
+
+ memcpy(buff,t_buff,saved_length=seg_len_pack+prefix_len);
+ saved_to=buff+saved_length;
+ saved_from=saved_vseg;
+ saved_length=length;
+ *ret_pos=page;
+ }
+ if (my_flag)
+ flag=(keyinfo->seg->flag & HA_REVERSE_SORT) ? -my_flag : my_flag;
+ if (flag == 0)
+ {
+ memcpy(buff,t_buff,saved_length=seg_len_pack+prefix_len);
+ saved_to=buff+saved_length;
+ saved_from=saved_vseg;
+ saved_length=length;
+ }
+ if (saved_length)
+ memcpy(saved_to,saved_from,saved_length);
+
+ *last_key= page == end;
+
+ DBUG_PRINT("exit",("flag: %d ret_pos: %lx",flag,*ret_pos));
+ DBUG_RETURN(flag);
+} /* _mi_prefix_search */
+
+
+ /* Get pos to a key_block */
my_off_t _mi_kpos(uint nod_flag, uchar *after_key)
{
@@ -265,11 +474,11 @@ my_off_t _mi_kpos(uint nod_flag, uchar *after_key)
switch (nod_flag) {
#if SIZEOF_OFF_T > 4
case 7:
- return mi_uint7korr(after_key)*MI_KEY_BLOCK_LENGTH;
+ return mi_uint7korr(after_key)*MI_MIN_KEY_BLOCK_LENGTH;
case 6:
- return mi_uint6korr(after_key)*MI_KEY_BLOCK_LENGTH;
+ return mi_uint6korr(after_key)*MI_MIN_KEY_BLOCK_LENGTH;
case 5:
- return mi_uint5korr(after_key)*MI_KEY_BLOCK_LENGTH;
+ return mi_uint5korr(after_key)*MI_MIN_KEY_BLOCK_LENGTH;
#else
case 7:
after_key++;
@@ -279,25 +488,25 @@ my_off_t _mi_kpos(uint nod_flag, uchar *after_key)
after_key++;
#endif
case 4:
- return ((my_off_t) mi_uint4korr(after_key))*MI_KEY_BLOCK_LENGTH;
+ return ((my_off_t) mi_uint4korr(after_key))*MI_MIN_KEY_BLOCK_LENGTH;
case 3:
- return ((my_off_t) mi_uint3korr(after_key))*MI_KEY_BLOCK_LENGTH;
+ return ((my_off_t) mi_uint3korr(after_key))*MI_MIN_KEY_BLOCK_LENGTH;
case 2:
- return (my_off_t) (mi_uint2korr(after_key)*MI_KEY_BLOCK_LENGTH);
+ return (my_off_t) (mi_uint2korr(after_key)*MI_MIN_KEY_BLOCK_LENGTH);
case 1:
- return (uint) (*after_key)*MI_KEY_BLOCK_LENGTH;
- case 0: /* At leaf page */
- default: /* Impossible */
+ return (uint) (*after_key)*MI_MIN_KEY_BLOCK_LENGTH;
+ case 0: /* At leaf page */
+ default: /* Impossible */
return(HA_OFFSET_ERROR);
}
} /* _kpos */
- /* Save pos to a key_block */
+ /* Save pos to a key_block */
void _mi_kpointer(register MI_INFO *info, register uchar *buff, my_off_t pos)
{
- pos/=MI_KEY_BLOCK_LENGTH;
+ pos/=MI_MIN_KEY_BLOCK_LENGTH;
switch (info->s->base.key_reflength) {
#if SIZEOF_OFF_T > 4
case 7: mi_int7store(buff,pos); break;
@@ -315,12 +524,12 @@ void _mi_kpointer(register MI_INFO *info, register uchar *buff, my_off_t pos)
case 3: mi_int3store(buff,pos); break;
case 2: mi_int2store(buff,(uint) pos); break;
case 1: buff[0]= (uchar) pos; break;
- default: abort(); /* impossible */
+ default: abort(); /* impossible */
}
} /* _mi_kpointer */
- /* Calc pos to a data-record from a key */
+ /* Calc pos to a data-record from a key */
my_off_t _mi_dpos(MI_INFO *info, uint nod_flag, uchar *after_key)
@@ -335,19 +544,19 @@ my_off_t _mi_dpos(MI_INFO *info, uint nod_flag, uchar *after_key)
case 5: pos= (my_off_t) mi_uint5korr(after_key); break;
#else
case 8: pos= (my_off_t) mi_uint4korr(after_key+4); break;
- case 7: pos= (my_off_t) mi_uint4korr(after_key+3); break;
- case 6: pos= (my_off_t) mi_uint4korr(after_key+2); break;
- case 5: pos= (my_off_t) mi_uint4korr(after_key+1); break;
+ case 7: pos= (my_off_t) mi_uint4korr(after_key+3); break;
+ case 6: pos= (my_off_t) mi_uint4korr(after_key+2); break;
+ case 5: pos= (my_off_t) mi_uint4korr(after_key+1); break;
#endif
case 4: pos= (my_off_t) mi_uint4korr(after_key); break;
case 3: pos= (my_off_t) mi_uint3korr(after_key); break;
case 2: pos= (my_off_t) mi_uint2korr(after_key); break;
default:
- pos=0L; /* Shut compiler up */
+ pos=0L; /* Shut compiler up */
}
return (info->s->options &
- (HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD)) ? pos :
- pos*info->s->base.pack_reclength;
+ (HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD)) ? pos :
+ pos*info->s->base.pack_reclength;
}
@@ -361,22 +570,22 @@ my_off_t _mi_rec_pos(MYISAM_SHARE *s, uchar *ptr)
case 8:
pos= (my_off_t) mi_uint8korr(ptr);
if (pos == HA_OFFSET_ERROR)
- return HA_OFFSET_ERROR; /* end of list */
+ return HA_OFFSET_ERROR; /* end of list */
break;
case 7:
pos= (my_off_t) mi_uint7korr(ptr);
if (pos == (((my_off_t) 1) << 56) -1)
- return HA_OFFSET_ERROR; /* end of list */
+ return HA_OFFSET_ERROR; /* end of list */
break;
case 6:
pos= (my_off_t) mi_uint6korr(ptr);
if (pos == (((my_off_t) 1) << 48) -1)
- return HA_OFFSET_ERROR; /* end of list */
+ return HA_OFFSET_ERROR; /* end of list */
break;
case 5:
pos= (my_off_t) mi_uint5korr(ptr);
if (pos == (((my_off_t) 1) << 40) -1)
- return HA_OFFSET_ERROR; /* end of list */
+ return HA_OFFSET_ERROR; /* end of list */
break;
#else
case 8:
@@ -401,20 +610,20 @@ my_off_t _mi_rec_pos(MYISAM_SHARE *s, uchar *ptr)
if (pos == (my_off_t) (1 << 16) -1)
return HA_OFFSET_ERROR;
break;
- default: abort(); /* Impossible */
+ default: abort(); /* Impossible */
}
return ((s->options &
- (HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD)) ? pos :
- pos*s->base.pack_reclength);
+ (HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD)) ? pos :
+ pos*s->base.pack_reclength);
}
- /* save position to record */
+ /* save position to record */
void _mi_dpointer(MI_INFO *info, uchar *buff, my_off_t pos)
{
if (!(info->s->options &
- (HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD)) &&
+ (HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD)) &&
pos != HA_OFFSET_ERROR)
pos/=info->s->base.pack_reclength;
@@ -437,27 +646,27 @@ void _mi_dpointer(MI_INFO *info, uchar *buff, my_off_t pos)
case 4: mi_int4store(buff,pos); break;
case 3: mi_int3store(buff,pos); break;
case 2: mi_int2store(buff,(uint) pos); break;
- default: abort(); /* Impossible */
+ default: abort(); /* Impossible */
}
} /* _mi_dpointer */
int _mi_compare_text(CHARSET_INFO *charset_info, uchar *a, uint a_length,
- uchar *b, uint b_length, my_bool part_key)
+ uchar *b, uint b_length, my_bool part_key)
{
- uint length= min(a_length,b_length);
- uchar *end= a+ length;
int flag;
#ifdef USE_STRCOLL
if (use_strcoll(charset_info))
{
- if ((flag = my_strnncoll(charset_info, a, a_length, b, b_length)))
- return flag;
+ /* QQ: This needs to work with part keys at some point */
+ return my_strnncoll(charset_info, a, a_length, b, b_length);
}
else
#endif
{
+ uint length= min(a_length,b_length);
+ uchar *end= a+ length;
uchar *sort_order=charset_info->sort_order;
while (a < end)
if ((flag= (int) sort_order[*a++] - (int) sort_order[*b++]))
@@ -470,7 +679,7 @@ int _mi_compare_text(CHARSET_INFO *charset_info, uchar *a, uint a_length,
static int compare_bin(uchar *a, uint a_length, uchar *b, uint b_length,
- my_bool part_key)
+ my_bool part_key)
{
uint length= min(a_length,b_length);
uchar *end= a+ length;
@@ -485,19 +694,19 @@ static int compare_bin(uchar *a, uint a_length, uchar *b, uint b_length,
}
- /*
- ** Compare two keys with is bigger
- ** Returns <0, 0, >0 acording to with is bigger
- ** Key_length specifies length of key to use. Number-keys can't
- ** be splited
- ** If flag <> SEARCH_FIND compare also position
- */
+ /*
+ ** Compare two keys
+ ** Returns <0, 0, >0 acording to which is bigger
+ ** Key_length specifies length of key to use. Number-keys can't
+ ** be splited
+ ** If flag <> SEARCH_FIND compare also position
+ */
#define FCMP(A,B) ((int) (A) - (int) (B))
int _mi_key_cmp(register MI_KEYSEG *keyseg, register uchar *a,
- register uchar *b, uint key_length, uint nextflag,
- uint *diff_pos)
+ register uchar *b, uint key_length, uint nextflag,
+ uint *diff_pos)
{
int flag;
int16 s_1,s_2;
@@ -507,129 +716,134 @@ int _mi_key_cmp(register MI_KEYSEG *keyseg, register uchar *a,
double d_1,d_2;
uint next_key_length;
- if (!(nextflag & (SEARCH_FIND | SEARCH_NO_FIND | SEARCH_LAST)))
- key_length=USE_WHOLE_KEY;
*diff_pos=0;
-
for ( ; (int) key_length >0 ; key_length=next_key_length, keyseg++)
{
uchar *end;
+ uint piks=! (keyseg->flag & HA_NO_SORT);
(*diff_pos)++;
/* Handle NULL part */
if (keyseg->null_bit)
{
key_length--;
- if (*a != *b)
+ if (*a != *b && piks)
{
- flag = (int) *a - (int) *b;
- return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
+ flag = (int) *a - (int) *b;
+ return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
}
b++;
- if (!*a++) /* If key was NULL */
+ if (!*a++) /* If key was NULL */
{
- if (nextflag == (SEARCH_FIND | SEARCH_UPDATE))
- nextflag=SEARCH_SAME; /* Allow duplicate keys */
- next_key_length=key_length;
- continue; /* To next key part */
+ if (nextflag == (SEARCH_FIND | SEARCH_UPDATE))
+ nextflag=SEARCH_SAME; /* Allow duplicate keys */
+ next_key_length=key_length;
+ continue; /* To next key part */
}
}
end= a+ min(keyseg->length,key_length);
next_key_length=key_length-keyseg->length;
switch ((enum ha_base_keytype) keyseg->type) {
- case HA_KEYTYPE_TEXT: /* Ascii; Key is converted */
+ case HA_KEYTYPE_TEXT: /* Ascii; Key is converted */
if (keyseg->flag & HA_SPACE_PACK)
{
- int a_length,b_length,pack_length;
- get_key_length(a_length,a);
- get_key_pack_length(b_length,pack_length,b);
- next_key_length=key_length-b_length-pack_length;
-
- if ((flag=_mi_compare_text(keyseg->charset,a,a_length,b,b_length,
- (my_bool) ((nextflag & SEARCH_PREFIX) &&
- next_key_length <= 0))))
- return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
- a+=a_length;
- b+=b_length;
- break;
+ int a_length,b_length,pack_length;
+ get_key_length(a_length,a);
+ get_key_pack_length(b_length,pack_length,b);
+ next_key_length=key_length-b_length-pack_length;
+
+ if (piks &&
+ (flag=_mi_compare_text(keyseg->charset,a,a_length,b,b_length,
+ (my_bool) ((nextflag & SEARCH_PREFIX) && next_key_length <= 0))))
+ return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
+ a+=a_length;
+ b+=b_length;
+ break;
}
else
{
- uint length=(uint) (end-a);
- if ((flag=_mi_compare_text(keyseg->charset,a,length,b,length,
- (my_bool) ((nextflag & SEARCH_PREFIX) &&
- next_key_length <= 0))))
- return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
- a=end;
- b+=length;
+ uint length=(uint) (end-a), a_length=length, b_length=length;
+ if (!(nextflag & SEARCH_PREFIX))
+ {
+ while (a_length && a[a_length-1] == ' ')
+ a_length--;
+ while (b_length && b[b_length-1] == ' ')
+ b_length--;
+ }
+ if (piks &&
+ (flag=_mi_compare_text(keyseg->charset,a,a_length,b,b_length,
+ (my_bool) ((nextflag & SEARCH_PREFIX) && next_key_length <= 0))))
+ return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
+ a=end;
+ b+=length;
}
break;
case HA_KEYTYPE_BINARY:
if (keyseg->flag & HA_SPACE_PACK)
{
- int a_length,b_length,pack_length;
- get_key_length(a_length,a);
- get_key_pack_length(b_length,pack_length,b);
- next_key_length=key_length-b_length-pack_length;
-
- if ((flag=compare_bin(a,a_length,b,b_length,
- (my_bool) ((nextflag & SEARCH_PREFIX) &&
- next_key_length <= 0))))
- return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
- a+=a_length;
- b+=b_length;
- break;
+ int a_length,b_length,pack_length;
+ get_key_length(a_length,a);
+ get_key_pack_length(b_length,pack_length,b);
+ next_key_length=key_length-b_length-pack_length;
+
+ if (piks &&
+ (flag=compare_bin(a,a_length,b,b_length,
+ (my_bool) ((nextflag & SEARCH_PREFIX) && next_key_length <= 0))))
+ return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
+ a+=a_length;
+ b+=b_length;
+ break;
}
else
{
- uint length=keyseg->length;
- if ((flag=compare_bin(a,length,b,length,
- (my_bool) ((nextflag & SEARCH_PREFIX) &&
- next_key_length <= 0))))
- return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
- a+=length;
- b+=length;
+ uint length=keyseg->length;
+ if (piks &&
+ (flag=compare_bin(a,length,b,length,
+ (my_bool) ((nextflag & SEARCH_PREFIX) && next_key_length <= 0))))
+ return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
+ a+=length;
+ b+=length;
}
break;
case HA_KEYTYPE_VARTEXT:
{
- int a_length,b_length,pack_length;
- get_key_length(a_length,a);
- get_key_pack_length(b_length,pack_length,b);
- next_key_length=key_length-b_length-pack_length;
-
- if ((flag=_mi_compare_text(keyseg->charset,a,a_length,b,b_length,
- (my_bool) ((nextflag & SEARCH_PREFIX) &&
- next_key_length <= 0))))
- return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
- a+=a_length;
- b+=b_length;
- break;
+ int a_length,b_length,pack_length;
+ get_key_length(a_length,a);
+ get_key_pack_length(b_length,pack_length,b);
+ next_key_length=key_length-b_length-pack_length;
+
+ if (piks &&
+ (flag=_mi_compare_text(keyseg->charset,a,a_length,b,b_length,
+ (my_bool) ((nextflag & SEARCH_PREFIX) && next_key_length <= 0))))
+ return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
+ a+=a_length;
+ b+=b_length;
+ break;
}
break;
case HA_KEYTYPE_VARBINARY:
{
- int a_length,b_length,pack_length;
- get_key_length(a_length,a);
- get_key_pack_length(b_length,pack_length,b);
- next_key_length=key_length-b_length-pack_length;
-
- if ((flag=compare_bin(a,a_length,b,b_length,
- (my_bool) ((nextflag & SEARCH_PREFIX) &&
- next_key_length <= 0))))
- return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
- a+=a_length;
- b+=b_length;
- break;
+ int a_length,b_length,pack_length;
+ get_key_length(a_length,a);
+ get_key_pack_length(b_length,pack_length,b);
+ next_key_length=key_length-b_length-pack_length;
+
+ if (piks &&
+ (flag=compare_bin(a,a_length,b,b_length,
+ (my_bool) ((nextflag & SEARCH_PREFIX) && next_key_length <= 0))))
+ return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
+ a+=a_length;
+ b+=b_length;
+ break;
}
break;
case HA_KEYTYPE_INT8:
{
int i_1= (int) *((signed char*) a);
int i_2= (int) *((signed char*) b);
- if ((flag = CMP(i_1,i_2)))
- return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
+ if (piks && (flag = CMP_NUM(i_1,i_2)))
+ return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
a= end;
b++;
break;
@@ -637,125 +851,132 @@ int _mi_key_cmp(register MI_KEYSEG *keyseg, register uchar *a,
case HA_KEYTYPE_SHORT_INT:
s_1= mi_sint2korr(a);
s_2= mi_sint2korr(b);
- if ((flag = CMP(s_1,s_2)))
- return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
+ if (piks && (flag = CMP_NUM(s_1,s_2)))
+ return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
a= end;
b+= 2; /* sizeof(short int); */
break;
case HA_KEYTYPE_USHORT_INT:
{
- uint16 us_1,us_2;
- us_1= mi_sint2korr(a);
- us_2= mi_sint2korr(b);
- if ((flag = CMP(us_1,us_2)))
- return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
- a= end;
- b+=2; /* sizeof(short int); */
- break;
+ uint16 us_1,us_2;
+ us_1= mi_sint2korr(a);
+ us_2= mi_sint2korr(b);
+ if (piks && (flag = CMP_NUM(us_1,us_2)))
+ return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
+ a= end;
+ b+=2; /* sizeof(short int); */
+ break;
}
case HA_KEYTYPE_LONG_INT:
l_1= mi_sint4korr(a);
l_2= mi_sint4korr(b);
- if ((flag = CMP(l_1,l_2)))
- return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
+ if (piks && (flag = CMP_NUM(l_1,l_2)))
+ return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
a= end;
b+= 4; /* sizeof(long int); */
break;
case HA_KEYTYPE_ULONG_INT:
u_1= mi_sint4korr(a);
u_2= mi_sint4korr(b);
- if ((flag = CMP(u_1,u_2)))
- return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
+ if (piks && (flag = CMP_NUM(u_1,u_2)))
+ return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
a= end;
b+= 4; /* sizeof(long int); */
break;
case HA_KEYTYPE_INT24:
l_1=mi_sint3korr(a);
l_2=mi_sint3korr(b);
- if ((flag = CMP(l_1,l_2)))
- return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
+ if (piks && (flag = CMP_NUM(l_1,l_2)))
+ return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
a= end;
b+= 3;
break;
case HA_KEYTYPE_UINT24:
l_1=mi_uint3korr(a);
l_2=mi_uint3korr(b);
- if ((flag = CMP(l_1,l_2)))
- return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
+ if (piks && (flag = CMP_NUM(l_1,l_2)))
+ return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
a= end;
b+= 3;
break;
case HA_KEYTYPE_FLOAT:
mi_float4get(f_1,a);
mi_float4get(f_2,b);
- if ((flag = CMP(f_1,f_2)))
- return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
+ if (piks && (flag = CMP_NUM(f_1,f_2)))
+ return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
a= end;
b+= 4; /* sizeof(float); */
break;
case HA_KEYTYPE_DOUBLE:
mi_float8get(d_1,a);
mi_float8get(d_2,b);
- if ((flag = CMP(d_1,d_2)))
- return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
+ if (piks && (flag = CMP_NUM(d_1,d_2)))
+ return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
a= end;
b+= 8; /* sizeof(double); */
break;
- case HA_KEYTYPE_NUM: /* Numeric key */
+ case HA_KEYTYPE_NUM: /* Numeric key */
{
int swap_flag= 0;
int alength,blength;
-
+
if (keyseg->flag & HA_REVERSE_SORT)
{
- swap(uchar*,a,b);
- swap_flag=1; /* Remember swap of a & b */
+ swap(uchar*,a,b);
+ swap_flag=1; /* Remember swap of a & b */
end= a+ (int) (end-b);
}
if (keyseg->flag & HA_SPACE_PACK)
{
- alength= *a++; blength= *b++;
- end=a+alength;
- next_key_length=key_length-blength-1;
+ alength= *a++; blength= *b++;
+ end=a+alength;
+ next_key_length=key_length-blength-1;
}
else
{
- alength= (int) (end-a);
- blength=keyseg->length;
- /* remove pre space from keys */
- for ( ; alength && *a == ' ' ; a++, alength--) ;
- for ( ; blength && *b == ' ' ; b++, blength--) ;
+ alength= (int) (end-a);
+ blength=keyseg->length;
+ /* remove pre space from keys */
+ for ( ; alength && *a == ' ' ; a++, alength--) ;
+ for ( ; blength && *b == ' ' ; b++, blength--) ;
}
-
- if (*a == '-')
+ if (piks)
{
- if (*b != '-')
- return -1;
- a++; b++;
- swap(uchar*,a,b);
- swap(int,alength,blength);
- swap_flag=1-swap_flag;
- alength--; blength--;
- end=a+alength;
+ if (*a == '-')
+ {
+ if (*b != '-')
+ return -1;
+ a++; b++;
+ swap(uchar*,a,b);
+ swap(int,alength,blength);
+ swap_flag=1-swap_flag;
+ alength--; blength--;
+ end=a+alength;
+ }
+ else if (*b == '-')
+ return 1;
+ while (alength && (*a == '+' || *a == '0'))
+ {
+ a++; alength--;
+ }
+ while (blength && (*b == '+' || *b == '0'))
+ {
+ b++; blength--;
+ }
+ if (alength != blength)
+ return (alength < blength) ? -1 : 1;
+ while (a < end)
+ if (*a++ != *b++)
+ return ((int) a[-1] - (int) b[-1]);
}
- else if (*b == '-')
- return 1;
- while (alength && (*a == '+' || *a == '0'))
- {
- a++; alength--;
- }
- while (blength && (*b == '+' || *b == '0'))
+ else
{
- b++; blength--;
+ b+=(end-a);
+ a=end;
}
- if (alength != blength)
- return (alength < blength) ? -1 : 1;
- while (a < end)
- if (*a++ != *b++)
- return ((int) a[-1] - (int) b[-1]);
-
- if (swap_flag) /* Restore pointers */
- swap(uchar*,a,b);
+
+ if (swap_flag) /* Restore pointers */
+ swap(uchar*,a,b);
break;
}
#ifdef HAVE_LONG_LONG
@@ -764,8 +985,8 @@ int _mi_key_cmp(register MI_KEYSEG *keyseg, register uchar *a,
longlong ll_a,ll_b;
ll_a= mi_sint8korr(a);
ll_b= mi_sint8korr(b);
- if ((flag = CMP(ll_a,ll_b)))
- return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
+ if (piks && (flag = CMP_NUM(ll_a,ll_b)))
+ return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
a= end;
b+= 8;
break;
@@ -775,15 +996,15 @@ int _mi_key_cmp(register MI_KEYSEG *keyseg, register uchar *a,
ulonglong ll_a,ll_b;
ll_a= mi_uint8korr(a);
ll_b= mi_uint8korr(b);
- if ((flag = CMP(ll_a,ll_b)))
- return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
+ if (piks && (flag = CMP_NUM(ll_a,ll_b)))
+ return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
a= end;
b+= 8;
break;
}
#endif
- case HA_KEYTYPE_END: /* Ready */
- goto end; /* diff_pos is incremented */
+ case HA_KEYTYPE_END: /* Ready */
+ goto end; /* diff_pos is incremented */
}
}
(*diff_pos)++;
@@ -798,33 +1019,33 @@ end:
{
if (*a++ != *b++)
{
- flag= FCMP(a[-1],b[-1]);
- break;
+ flag= FCMP(a[-1],b[-1]);
+ break;
}
}
if (nextflag & SEARCH_SAME)
- return (flag); /* read same */
+ return (flag); /* read same */
if (nextflag & SEARCH_BIGGER)
- return (flag <= 0 ? -1 : 1); /* read next */
- return (flag < 0 ? -1 : 1); /* read previous */
+ return (flag <= 0 ? -1 : 1); /* read next */
+ return (flag < 0 ? -1 : 1); /* read previous */
}
return 0;
} /* _mi_key_cmp */
- /* Get key from key-block */
- /* page points at previous key; its advanced to point at next key */
- /* key should contain previous key */
- /* Returns length of found key + pointers */
- /* nod_flag is a flag if we are on nod */
+ /* Get key from key-block */
+ /* page points at previous key; its advanced to point at next key */
+ /* key should contain previous key */
+ /* Returns length of found key + pointers */
+ /* nod_flag is a flag if we are on nod */
- /* same as _mi_get_key but used with fixed length keys */
+ /* same as _mi_get_key but used with fixed length keys */
uint _mi_get_static_key(register MI_KEYDEF *keyinfo, uint nod_flag,
- register uchar **page, register uchar *key)
+ register uchar **page, register uchar *key)
{
memcpy((byte*) key,(byte*) *page,
- (size_t) (keyinfo->keylength+nod_flag));
+ (size_t) (keyinfo->keylength+nod_flag));
*page+=keyinfo->keylength+nod_flag;
return(keyinfo->keylength);
} /* _mi_get_static_key */
@@ -833,7 +1054,7 @@ uint _mi_get_static_key(register MI_KEYDEF *keyinfo, uint nod_flag,
/* Key with is packed against previous key or key with a NULL column */
uint _mi_get_pack_key(register MI_KEYDEF *keyinfo, uint nod_flag,
- register uchar **page_pos, register uchar *key)
+ register uchar **page_pos, register uchar *key)
{
reg1 MI_KEYSEG *keyseg;
uchar *start_key,*page=*page_pos;
@@ -849,11 +1070,11 @@ uint _mi_get_pack_key(register MI_KEYDEF *keyinfo, uint nod_flag,
uint packed= *page & 128,tot_length,rest_length;
if (keyseg->length >= 127)
{
- length=mi_uint2korr(page) & 32767;
- page+=2;
+ length=mi_uint2korr(page) & 32767;
+ page+=2;
}
else
- length= *page++ & 127;
+ length= *page++ & 127;
if (packed)
{
@@ -914,23 +1135,23 @@ uint _mi_get_pack_key(register MI_KEYDEF *keyinfo, uint nod_flag,
}
else
{
- if (keyseg->flag & HA_NULL_PART)
- {
- if (!length--) /* Null part */
- {
- *key++=0;
- continue;
- }
- *key++=1; /* Not null */
- }
+ if (keyseg->flag & HA_NULL_PART)
+ {
+ if (!length--) /* Null part */
+ {
+ *key++=0;
+ continue;
+ }
+ *key++=1; /* Not null */
+ }
}
if (length > (uint) keyseg->length)
{
- DBUG_PRINT("error",("Found too long packed key: %d of %d at %lx",
- length, keyseg->length, *page_pos));
- DBUG_DUMP("key",(char*) *page_pos,16);
- my_errno=HA_ERR_CRASHED;
- return 0; /* Error */
+ DBUG_PRINT("error",("Found too long packed key: %d of %d at %lx",
+ length, keyseg->length, *page_pos));
+ DBUG_DUMP("key",(char*) *page_pos,16);
+ my_errno=HA_ERR_CRASHED;
+ return 0; /* Error */
}
store_key_length_inc(key,length);
}
@@ -938,18 +1159,18 @@ uint _mi_get_pack_key(register MI_KEYDEF *keyinfo, uint nod_flag,
{
if (keyseg->flag & HA_NULL_PART)
{
- if (!(*key++ = *page++))
- continue;
+ if (!(*key++ = *page++))
+ continue;
}
if (keyseg->flag &
- (HA_VAR_LENGTH | HA_BLOB_PART | HA_SPACE_PACK))
+ (HA_VAR_LENGTH | HA_BLOB_PART | HA_SPACE_PACK))
{
- uchar *tmp=page;
- get_key_length(length,tmp);
- length+=(uint) (tmp-page);
+ uchar *tmp=page;
+ get_key_length(length,tmp);
+ length+=(uint) (tmp-page);
}
else
- length=keyseg->length;
+ length=keyseg->length;
}
memcpy((byte*) key,(byte*) page,(size_t) length);
key+=length;
@@ -966,7 +1187,7 @@ uint _mi_get_pack_key(register MI_KEYDEF *keyinfo, uint nod_flag,
/* key that is packed relatively to previous */
uint _mi_get_binary_pack_key(register MI_KEYDEF *keyinfo, uint nod_flag,
- register uchar **page_pos, register uchar *key)
+ register uchar **page_pos, register uchar *key)
{
reg1 MI_KEYSEG *keyseg;
uchar *start_key,*page=*page_pos,*page_end,*from,*from_end;
@@ -981,16 +1202,16 @@ uint _mi_get_binary_pack_key(register MI_KEYDEF *keyinfo, uint nod_flag,
if (length > keyinfo->maxlength)
{
DBUG_PRINT("error",("Found too long binary packed key: %d of %d at %lx",
- length, keyinfo->maxlength, *page_pos));
+ length, keyinfo->maxlength, *page_pos));
DBUG_DUMP("key",(char*) *page_pos,16);
my_errno=HA_ERR_CRASHED;
- return 0; /* Wrong key */
+ return 0; /* Wrong key */
}
from=key; from_end=key+length;
}
else
{
- from=page; from_end=page_end; /* Not packed key */
+ from=page; from_end=page_end; /* Not packed key */
}
/*
@@ -1004,7 +1225,7 @@ uint _mi_get_binary_pack_key(register MI_KEYDEF *keyinfo, uint nod_flag,
{
if (from == from_end) { from=page; from_end=page_end; }
if (!(*key++ = *from++))
- continue; /* Null part */
+ continue; /* Null part */
}
if (keyseg->flag & (HA_VAR_LENGTH | HA_BLOB_PART | HA_SPACE_PACK))
{
@@ -1012,10 +1233,10 @@ uint _mi_get_binary_pack_key(register MI_KEYDEF *keyinfo, uint nod_flag,
if (from == from_end) { from=page; from_end=page_end; }
if ((length= (*key++ = *from++)) == 255)
{
- if (from == from_end) { from=page; from_end=page_end; }
- length= (uint) ((*key++ = *from++)) << 8;
- if (from == from_end) { from=page; from_end=page_end; }
- length+= (uint) ((*key++ = *from++));
+ if (from == from_end) { from=page; from_end=page_end; }
+ length= (uint) ((*key++ = *from++)) << 8;
+ if (from == from_end) { from=page; from_end=page_end; }
+ length+= (uint) ((*key++ = *from++));
}
}
else
@@ -1023,7 +1244,7 @@ uint _mi_get_binary_pack_key(register MI_KEYDEF *keyinfo, uint nod_flag,
if ((tmp=(uint) (from_end-from)) <= length)
{
- key+=tmp; /* Use old key */
+ key+=tmp; /* Use old key */
length-=tmp;
from=page; from_end=page_end;
}
@@ -1034,7 +1255,7 @@ uint _mi_get_binary_pack_key(register MI_KEYDEF *keyinfo, uint nod_flag,
length=keyseg->length+nod_flag;
if ((tmp=(uint) (from_end-from)) <= length)
{
- memcpy(key+tmp,page,length-tmp); /* Get last part of key */
+ memcpy(key+tmp,page,length-tmp); /* Get last part of key */
*page_pos= page+length-tmp;
}
else
@@ -1043,7 +1264,7 @@ uint _mi_get_binary_pack_key(register MI_KEYDEF *keyinfo, uint nod_flag,
{
DBUG_PRINT("error",("Error when unpacking key"));
my_errno=HA_ERR_CRASHED;
- return 0; /* Error */
+ return 0; /* Error */
}
memcpy((byte*) key,(byte*) from,(size_t) length);
*page_pos= from+length;
@@ -1052,11 +1273,11 @@ uint _mi_get_binary_pack_key(register MI_KEYDEF *keyinfo, uint nod_flag,
}
- /* Get key at position without knowledge of previous key */
- /* Returns pointer to next key */
+ /* Get key at position without knowledge of previous key */
+ /* Returns pointer to next key */
uchar *_mi_get_key(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *page,
- uchar *key, uchar *keypos, uint *return_key_length)
+ uchar *key, uchar *keypos, uint *return_key_length)
{
uint nod_flag;
DBUG_ENTER("_mi_get_key");
@@ -1070,14 +1291,14 @@ uchar *_mi_get_key(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *page,
else
{
page+=2+nod_flag;
- key[0]=0; /* safety */
+ key[0]=0; /* safety */
while (page <= keypos)
{
*return_key_length=(*keyinfo->get_key)(keyinfo,nod_flag,&page,key);
if (*return_key_length == 0)
{
- my_errno=HA_ERR_CRASHED;
- DBUG_RETURN(0);
+ my_errno=HA_ERR_CRASHED;
+ DBUG_RETURN(0);
}
}
}
@@ -1086,12 +1307,12 @@ uchar *_mi_get_key(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *page,
} /* _mi_get_key */
- /* Get key at position without knowledge of previous key */
- /* Returns 0 if ok */
+ /* Get key at position without knowledge of previous key */
+ /* Returns 0 if ok */
static my_bool _mi_get_prev_key(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *page,
- uchar *key, uchar *keypos,
- uint *return_key_length)
+ uchar *key, uchar *keypos,
+ uint *return_key_length)
{
uint nod_flag;
DBUG_ENTER("_mi_get_prev_key");
@@ -1101,20 +1322,20 @@ static my_bool _mi_get_prev_key(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *page,
{
*return_key_length=keyinfo->keylength;
bmove((byte*) key,(byte*) keypos- *return_key_length-nod_flag,
- *return_key_length);
+ *return_key_length);
DBUG_RETURN(0);
}
else
{
page+=2+nod_flag;
- key[0]=0; /* safety */
+ key[0]=0; /* safety */
while (page < keypos)
{
*return_key_length=(*keyinfo->get_key)(keyinfo,nod_flag,&page,key);
if (*return_key_length == 0)
{
- my_errno=HA_ERR_CRASHED;
- DBUG_RETURN(1);
+ my_errno=HA_ERR_CRASHED;
+ DBUG_RETURN(1);
}
}
}
@@ -1123,11 +1344,11 @@ static my_bool _mi_get_prev_key(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *page,
- /* Get last key from key-page */
- /* Return pointer to where key starts */
+ /* Get last key from key-page */
+ /* Return pointer to where key starts */
uchar *_mi_get_last_key(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *page,
- uchar *lastkey, uchar *endpos, uint *return_key_length)
+ uchar *lastkey, uchar *endpos, uint *return_key_length)
{
uint nod_flag;
uchar *lastpos;
@@ -1152,9 +1373,9 @@ uchar *_mi_get_last_key(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *page,
*return_key_length=(*keyinfo->get_key)(keyinfo,nod_flag,&page,lastkey);
if (*return_key_length == 0)
{
- DBUG_PRINT("error",("Couldn't find last key: page: %lx",page));
- my_errno=HA_ERR_CRASHED;
- DBUG_RETURN(0);
+ DBUG_PRINT("error",("Couldn't find last key: page: %lx",page));
+ my_errno=HA_ERR_CRASHED;
+ DBUG_RETURN(0);
}
}
}
@@ -1163,7 +1384,7 @@ uchar *_mi_get_last_key(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *page,
} /* _mi_get_last_key */
- /* Calculate length of key */
+ /* Calculate length of key */
uint _mi_keylength(MI_KEYDEF *keyinfo, register uchar *key)
{
@@ -1178,7 +1399,7 @@ uint _mi_keylength(MI_KEYDEF *keyinfo, register uchar *key)
{
if (keyseg->flag & HA_NULL_PART)
if (!*key++)
- continue;
+ continue;
if (keyseg->flag & (HA_SPACE_PACK | HA_BLOB_PART | HA_VAR_LENGTH))
{
uint length;
@@ -1192,28 +1413,28 @@ uint _mi_keylength(MI_KEYDEF *keyinfo, register uchar *key)
} /* _mi_keylength */
- /* Move a key */
+ /* Move a key */
uchar *_mi_move_key(MI_KEYDEF *keyinfo, uchar *to, uchar *from)
{
reg1 uint length;
memcpy((byte*) to, (byte*) from,
- (size_t) (length=_mi_keylength(keyinfo,from)));
+ (size_t) (length=_mi_keylength(keyinfo,from)));
return to+length;
}
- /* Find next/previous record with same key */
- /* This can't be used when database is touched after last read */
+ /* Find next/previous record with same key */
+ /* This can't be used when database is touched after last read */
int _mi_search_next(register MI_INFO *info, register MI_KEYDEF *keyinfo,
- uchar *key, uint key_length, uint nextflag, my_off_t pos)
+ uchar *key, uint key_length, uint nextflag, my_off_t pos)
{
int error;
uint nod_flag;
uchar lastkey[MI_MAX_KEY_BUFF];
DBUG_ENTER("_mi_search_next");
DBUG_PRINT("enter",("nextflag: %d lastpos: %ld int_keypos: %lx",
- nextflag,(long) info->lastpos,info->int_keypos));
+ nextflag,(long) info->lastpos,info->int_keypos));
DBUG_EXECUTE("key",_mi_print_key(DBUG_FILE,keyinfo->seg,key,key_length););
/* Force full read if we are at last key or if we are not on a leaf
@@ -1227,51 +1448,53 @@ int _mi_search_next(register MI_INFO *info, register MI_KEYDEF *keyinfo,
info->page_changed ||
(info->int_keytree_version != keyinfo->version &&
(info->int_nod_flag || info->buff_used)))
- DBUG_RETURN(_mi_search(info,keyinfo,key,key_length,
- nextflag | SEARCH_SAVE_BUFF, pos));
+ DBUG_RETURN(_mi_search(info,keyinfo,key, USE_WHOLE_KEY,
+ nextflag | SEARCH_SAVE_BUFF, pos));
if (info->buff_used)
{
if (!_mi_fetch_keypage(info,keyinfo,info->last_search_keypage,
- info->buff,0))
+ info->buff,0))
DBUG_RETURN(-1);
info->buff_used=0;
}
/* Last used buffer is in info->buff */
nod_flag=mi_test_if_nod(info->buff);
- memcpy(lastkey,key,key_length);
- if (nextflag & SEARCH_BIGGER) /* Next key */
+ if (nextflag & SEARCH_BIGGER) /* Next key */
{
my_off_t tmp_pos=_mi_kpos(nod_flag,info->int_keypos);
if (tmp_pos != HA_OFFSET_ERROR)
{
- if ((error=_mi_search(info,keyinfo,key,key_length,
- nextflag | SEARCH_SAVE_BUFF, tmp_pos)) <=0)
- DBUG_RETURN(error);
+ if ((error=_mi_search(info,keyinfo,key, USE_WHOLE_KEY,
+ nextflag | SEARCH_SAVE_BUFF, tmp_pos)) <=0)
+ DBUG_RETURN(error);
}
+ memcpy(lastkey,key,key_length);
if (!(info->lastkey_length=(*keyinfo->get_key)(keyinfo,nod_flag,
- &info->int_keypos,lastkey)))
+ &info->int_keypos,lastkey)))
DBUG_RETURN(-1);
}
- else /* Previous key */
+ else /* Previous key */
{
uint length;
/* Find start of previous key */
info->int_keypos=_mi_get_last_key(info,keyinfo,info->buff,lastkey,
- info->int_keypos, &length);
+ info->int_keypos, &length);
if (!info->int_keypos)
DBUG_RETURN(-1);
if (info->int_keypos == info->buff+2)
- DBUG_RETURN(_mi_search(info,keyinfo,key,key_length,
- nextflag | SEARCH_SAVE_BUFF, pos));
- if ((error=_mi_search(info,keyinfo,key,0,nextflag | SEARCH_SAVE_BUFF,
- _mi_kpos(nod_flag,info->int_keypos))) <= 0)
+ DBUG_RETURN(_mi_search(info,keyinfo,key, USE_WHOLE_KEY,
+ nextflag | SEARCH_SAVE_BUFF, pos));
+ if ((error=_mi_search(info,keyinfo,key, USE_WHOLE_KEY,
+ nextflag | SEARCH_SAVE_BUFF,
+ _mi_kpos(nod_flag,info->int_keypos))) <= 0)
DBUG_RETURN(error);
+ /* QQ: We should be able to optimize away the following call */
if (! _mi_get_last_key(info,keyinfo,info->buff,lastkey,
- info->int_keypos,&info->lastkey_length))
+ info->int_keypos,&info->lastkey_length))
DBUG_RETURN(-1);
}
memcpy(info->lastkey,lastkey,info->lastkey_length);
@@ -1281,11 +1504,11 @@ int _mi_search_next(register MI_INFO *info, register MI_KEYDEF *keyinfo,
} /* _mi_search_next */
- /* Search after position for the first row in an index */
- /* This is stored in info->lastpos */
+ /* Search after position for the first row in an index */
+ /* This is stored in info->lastpos */
int _mi_search_first(register MI_INFO *info, register MI_KEYDEF *keyinfo,
- register my_off_t pos)
+ register my_off_t pos)
{
uint nod_flag;
uchar *page;
@@ -1310,7 +1533,7 @@ int _mi_search_first(register MI_INFO *info, register MI_KEYDEF *keyinfo,
} while ((pos=_mi_kpos(nod_flag,page)) != HA_OFFSET_ERROR);
info->lastkey_length=(*keyinfo->get_key)(keyinfo,nod_flag,&page,
- info->lastkey);
+ info->lastkey);
info->int_keypos=page; info->int_maxpos=info->buff+mi_getint(info->buff)-1;
info->int_nod_flag=nod_flag;
info->int_keytree_version=keyinfo->version;
@@ -1323,11 +1546,11 @@ int _mi_search_first(register MI_INFO *info, register MI_KEYDEF *keyinfo,
} /* _mi_search_first */
- /* Search after position for the last row in an index */
- /* This is stored in info->lastpos */
+ /* Search after position for the last row in an index */
+ /* This is stored in info->lastpos */
int _mi_search_last(register MI_INFO *info, register MI_KEYDEF *keyinfo,
- register my_off_t pos)
+ register my_off_t pos)
{
uint nod_flag;
uchar *buff,*page;
@@ -1335,7 +1558,7 @@ int _mi_search_last(register MI_INFO *info, register MI_KEYDEF *keyinfo,
if (pos == HA_OFFSET_ERROR)
{
- my_errno=HA_ERR_KEY_NOT_FOUND; /* Didn't find key */
+ my_errno=HA_ERR_KEY_NOT_FOUND; /* Didn't find key */
info->lastpos= HA_OFFSET_ERROR;
DBUG_RETURN(-1);
}
@@ -1353,7 +1576,7 @@ int _mi_search_last(register MI_INFO *info, register MI_KEYDEF *keyinfo,
} while ((pos=_mi_kpos(nod_flag,page)) != HA_OFFSET_ERROR);
if (!_mi_get_last_key(info,keyinfo,buff,info->lastkey,page,
- &info->lastkey_length))
+ &info->lastkey_length))
DBUG_RETURN(-1);
info->lastpos=_mi_dpos(info,0,info->lastkey+info->lastkey_length);
info->int_keypos=info->int_maxpos=page;
@@ -1373,22 +1596,22 @@ int _mi_search_last(register MI_INFO *info, register MI_KEYDEF *keyinfo,
** Functions to store and pack a key in a page
**
** mi_calc_xx_key_length takes the following arguments:
-** nod_flag If nod: Length of nod-pointer
-** next_key Position to pos after the new key in buffer
-** org_key Key that was before the next key in buffer
-** prev_key Last key before current key
-** key Key that will be stored
-** s_temp Information how next key will be packed
+** nod_flag If nod: Length of nod-pointer
+** next_key Position to pos after the new key in buffer
+** org_key Key that was before the next key in buffer
+** prev_key Last key before current key
+** key Key that will be stored
+** s_temp Information how next key will be packed
****************************************************************************/
/* Static length key */
int
_mi_calc_static_key_length(MI_KEYDEF *keyinfo,uint nod_flag,
- uchar *next_pos __attribute__((unused)),
- uchar *org_key __attribute__((unused)),
- uchar *prev_key __attribute__((unused)),
- uchar *key, MI_KEY_PARAM *s_temp)
+ uchar *next_pos __attribute__((unused)),
+ uchar *org_key __attribute__((unused)),
+ uchar *prev_key __attribute__((unused)),
+ uchar *key, MI_KEY_PARAM *s_temp)
{
s_temp->key=key;
return (int) (s_temp->totlength=keyinfo->keylength+nod_flag);
@@ -1398,10 +1621,10 @@ _mi_calc_static_key_length(MI_KEYDEF *keyinfo,uint nod_flag,
int
_mi_calc_var_key_length(MI_KEYDEF *keyinfo,uint nod_flag,
- uchar *next_pos __attribute__((unused)),
- uchar *org_key __attribute__((unused)),
- uchar *prev_key __attribute__((unused)),
- uchar *key, MI_KEY_PARAM *s_temp)
+ uchar *next_pos __attribute__((unused)),
+ uchar *org_key __attribute__((unused)),
+ uchar *prev_key __attribute__((unused)),
+ uchar *key, MI_KEY_PARAM *s_temp)
{
s_temp->key=key;
return (int) (s_temp->totlength=_mi_keylength(keyinfo,key)+nod_flag);
@@ -1416,10 +1639,10 @@ _mi_calc_var_key_length(MI_KEYDEF *keyinfo,uint nod_flag,
If the max length of first key segment <= 127 characters the prefix is
1 byte else it's 2 byte
- prefix byte The high bit is set if this is a prefix for the prev key
- length Packed length if the previous was a prefix byte
- [length] Length character of data
- next-key-seg Next key segments
+ prefix byte The high bit is set if this is a prefix for the prev key
+ length Packed length if the previous was a prefix byte
+ [length] Length character of data
+ next-key-seg Next key segments
If the first segment can have NULL:
The length is 0 for NULLS and 1+length for not null columns.
@@ -1428,8 +1651,8 @@ _mi_calc_var_key_length(MI_KEYDEF *keyinfo,uint nod_flag,
int
_mi_calc_var_pack_key_length(MI_KEYDEF *keyinfo,uint nod_flag,uchar *next_key,
- uchar *org_key, uchar *prev_key, uchar *key,
- MI_KEY_PARAM *s_temp)
+ uchar *org_key, uchar *prev_key, uchar *key,
+ MI_KEY_PARAM *s_temp)
{
reg1 MI_KEYSEG *keyseg;
int length;
@@ -1470,15 +1693,15 @@ _mi_calc_var_pack_key_length(MI_KEYDEF *keyinfo,uint nod_flag,uchar *next_key,
s_temp->key=key;
s_temp->ref_length=s_temp->key_length=0;
s_temp->totlength=key_length-1+diff_flag;
- s_temp->next_key_pos=0; /* No next key */
+ s_temp->next_key_pos=0; /* No next key */
return (s_temp->totlength);
}
s_temp->store_not_null=1;
- key_length--; /* We don't store NULL */
+ key_length--; /* We don't store NULL */
if (prev_key && !*prev_key++)
- org_key=prev_key=0; /* Can't pack against prev */
+ org_key=prev_key=0; /* Can't pack against prev */
else if (org_key)
- org_key++; /* Skipp NULL */
+ org_key++; /* Skipp NULL */
}
else
s_temp->store_not_null=0;
@@ -1494,14 +1717,14 @@ _mi_calc_var_pack_key_length(MI_KEYDEF *keyinfo,uint nod_flag,uchar *next_key,
if (prev_key)
{
get_key_length(org_key_length,prev_key);
- s_temp->prev_key=prev_key; /* Pointer at data */
+ s_temp->prev_key=prev_key; /* Pointer at data */
/* Don't use key-pack if length == 0 */
if (new_key_length && new_key_length == org_key_length)
same_length=1;
else if (new_key_length > org_key_length)
end=key + org_key_length;
- if (sort_order) /* SerG */
+ if (sort_order) /* SerG */
{
while (key < end && sort_order[*key] == sort_order[*prev_key])
{
@@ -1512,7 +1735,7 @@ _mi_calc_var_pack_key_length(MI_KEYDEF *keyinfo,uint nod_flag,uchar *next_key,
{
while (key < end && *key == *prev_key)
{
- key++; prev_key++;
+ key++; prev_key++;
}
}
}
@@ -1527,15 +1750,15 @@ _mi_calc_var_pack_key_length(MI_KEYDEF *keyinfo,uint nod_flag,uchar *next_key,
length=(int) key_length-(int) (key_end-start)-length_pack;
length+= diff_flag;
if (next_key)
- { /* Can't combine with next */
- s_temp->n_length= *next_key; /* Needed by _mi_store_key */
+ { /* Can't combine with next */
+ s_temp->n_length= *next_key; /* Needed by _mi_store_key */
next_key=0;
}
}
else
{
if (start != key)
- { /* Starts as prev key */
+ { /* Starts as prev key */
ref_length= (uint) (key-start);
s_temp->ref_length= ref_length + pack_marker;
length= (int) (key_length - ref_length);
@@ -1546,16 +1769,16 @@ _mi_calc_var_pack_key_length(MI_KEYDEF *keyinfo,uint nod_flag,uchar *next_key,
}
else
{
- s_temp->key_length+=s_temp->store_not_null; /* If null */
+ s_temp->key_length+=s_temp->store_not_null; /* If null */
length= key_length - length_pack+ diff_flag;
}
}
s_temp->totlength=(uint) length;
s_temp->prev_length=0;
DBUG_PRINT("test",("tot_length: %d length: %d uniq_key_length: %d",
- key_length,length,s_temp->key_length));
+ key_length,length,s_temp->key_length));
- /* If something after that hasn't length=0, test if we can combine */
+ /* If something after that hasn't length=0, test if we can combine */
if ((s_temp->next_key_pos=next_key))
{
uint packed,n_length;
@@ -1571,134 +1794,134 @@ _mi_calc_var_pack_key_length(MI_KEYDEF *keyinfo,uint nod_flag,uchar *next_key,
if (!packed)
n_length-= s_temp->store_not_null;
- if (n_length || packed) /* Don't pack 0 length keys */
+ if (n_length || packed) /* Don't pack 0 length keys */
{
uint next_length_pack, new_ref_length=s_temp->ref_length;
if (packed)
{
- /* If first key and next key is packed (only on delete) */
- if (!prev_key && org_key)
- {
- get_key_length(org_key_length,org_key);
- key=start;
- if (sort_order) /* SerG */
- {
- while (key < end && sort_order[*key] == sort_order[*org_key])
- {
- key++; org_key++;
- }
- }
- else
- {
- while (key < end && *key == *org_key)
- {
- key++; org_key++;
- }
- }
- if ((new_ref_length= (uint) (key - start)))
- new_ref_length+=pack_marker;
- }
-
- if (!n_length)
- {
- /*
- We put a different key between two identical variable length keys
- Extend next key to have same prefix as this key
- */
- if (new_ref_length) /* prefix of previus key */
- { /* make next key longer */
- s_temp->part_of_prev_key= new_ref_length;
- s_temp->prev_length= org_key_length -
- (new_ref_length-pack_marker);
- s_temp->n_ref_length= s_temp->n_length= s_temp->prev_length;
- n_length= get_pack_length(s_temp->prev_length);
- s_temp->prev_key+= (new_ref_length - pack_marker);
- length+= s_temp->prev_length + n_length;
- }
- else
- { /* Can't use prev key */
- s_temp->part_of_prev_key=0;
- s_temp->prev_length= org_key_length;
- s_temp->n_ref_length=s_temp->n_length= org_key_length;
- length+= org_key_length;
- /* +get_pack_length(org_key_length); */
- }
- return (int) length;
- }
-
- ref_length=n_length;
- get_key_pack_length(n_length,next_length_pack,next_key);
-
- /* Test if new keys has fewer characters that match the previous key */
- if (!new_ref_length)
- { /* Can't use prev key */
- s_temp->part_of_prev_key= 0;
- s_temp->prev_length= ref_length;
- s_temp->n_ref_length= s_temp->n_length= n_length+ref_length;
- /* s_temp->prev_key+= get_pack_length(org_key_length); */
- return (int) length+ref_length-next_length_pack;
- }
- if (ref_length+pack_marker > new_ref_length)
- {
- uint new_pack_length=new_ref_length-pack_marker;
- /* We must copy characters from the original key to the next key */
- s_temp->part_of_prev_key= new_ref_length;
- s_temp->prev_length= ref_length - new_pack_length;
- s_temp->n_ref_length=s_temp->n_length=n_length + s_temp->prev_length;
- s_temp->prev_key+= new_pack_length;
-/* +get_pack_length(org_key_length); */
- length= length-get_pack_length(ref_length)+
- get_pack_length(new_pack_length);
- return (int) length + s_temp->prev_length;
- }
+ /* If first key and next key is packed (only on delete) */
+ if (!prev_key && org_key)
+ {
+ get_key_length(org_key_length,org_key);
+ key=start;
+ if (sort_order) /* SerG */
+ {
+ while (key < end && sort_order[*key] == sort_order[*org_key])
+ {
+ key++; org_key++;
+ }
+ }
+ else
+ {
+ while (key < end && *key == *org_key)
+ {
+ key++; org_key++;
+ }
+ }
+ if ((new_ref_length= (uint) (key - start)))
+ new_ref_length+=pack_marker;
+ }
+
+ if (!n_length)
+ {
+ /*
+ We put a different key between two identical variable length keys
+ Extend next key to have same prefix as this key
+ */
+ if (new_ref_length) /* prefix of previus key */
+ { /* make next key longer */
+ s_temp->part_of_prev_key= new_ref_length;
+ s_temp->prev_length= org_key_length -
+ (new_ref_length-pack_marker);
+ s_temp->n_ref_length= s_temp->n_length= s_temp->prev_length;
+ n_length= get_pack_length(s_temp->prev_length);
+ s_temp->prev_key+= (new_ref_length - pack_marker);
+ length+= s_temp->prev_length + n_length;
+ }
+ else
+ { /* Can't use prev key */
+ s_temp->part_of_prev_key=0;
+ s_temp->prev_length= org_key_length;
+ s_temp->n_ref_length=s_temp->n_length= org_key_length;
+ length+= org_key_length;
+ /* +get_pack_length(org_key_length); */
+ }
+ return (int) length;
+ }
+
+ ref_length=n_length;
+ get_key_pack_length(n_length,next_length_pack,next_key);
+
+ /* Test if new keys has fewer characters that match the previous key */
+ if (!new_ref_length)
+ { /* Can't use prev key */
+ s_temp->part_of_prev_key= 0;
+ s_temp->prev_length= ref_length;
+ s_temp->n_ref_length= s_temp->n_length= n_length+ref_length;
+ /* s_temp->prev_key+= get_pack_length(org_key_length); */
+ return (int) length+ref_length-next_length_pack;
+ }
+ if (ref_length+pack_marker > new_ref_length)
+ {
+ uint new_pack_length=new_ref_length-pack_marker;
+ /* We must copy characters from the original key to the next key */
+ s_temp->part_of_prev_key= new_ref_length;
+ s_temp->prev_length= ref_length - new_pack_length;
+ s_temp->n_ref_length=s_temp->n_length=n_length + s_temp->prev_length;
+ s_temp->prev_key+= new_pack_length;
+/* +get_pack_length(org_key_length); */
+ length= length-get_pack_length(ref_length)+
+ get_pack_length(new_pack_length);
+ return (int) length + s_temp->prev_length;
+ }
}
else
{
- /* Next key wasn't a prefix of previous key */
- ref_length=0;
- next_length_pack=0;
+ /* Next key wasn't a prefix of previous key */
+ ref_length=0;
+ next_length_pack=0;
}
DBUG_PRINT("test",("length: %d next_key: %lx",length,next_key));
{
- uint tmp_length;
- key=(start+=ref_length);
- if (key+n_length < key_end) /* Normalize length based */
- key_end=key+n_length;
- if (sort_order) /* SerG */
- {
+ uint tmp_length;
+ key=(start+=ref_length);
+ if (key+n_length < key_end) /* Normalize length based */
+ key_end=key+n_length;
+ if (sort_order) /* SerG */
+ {
while (key < key_end && sort_order[*key] ==
- sort_order[*next_key])
- {
- key++; next_key++;
- }
- }
- else
- {
- while (key < key_end && *key == *next_key)
- {
- key++; next_key++;
- }
- }
- if (!(tmp_length=(uint) (key-start)))
- { /* Key can't be re-packed */
- s_temp->next_key_pos=0;
- return length;
- }
- ref_length+=tmp_length;
- n_length-=tmp_length;
- length-=tmp_length+next_length_pack; /* We gained these chars */
+ sort_order[*next_key])
+ {
+ key++; next_key++;
+ }
+ }
+ else
+ {
+ while (key < key_end && *key == *next_key)
+ {
+ key++; next_key++;
+ }
+ }
+ if (!(tmp_length=(uint) (key-start)))
+ { /* Key can't be re-packed */
+ s_temp->next_key_pos=0;
+ return length;
+ }
+ ref_length+=tmp_length;
+ n_length-=tmp_length;
+ length-=tmp_length+next_length_pack; /* We gained these chars */
}
if (n_length == 0)
{
- s_temp->n_ref_length=pack_marker; /* Same as prev key */
+ s_temp->n_ref_length=pack_marker; /* Same as prev key */
}
else
{
- s_temp->n_ref_length=ref_length | pack_marker;
- length+= get_pack_length(n_length);
- s_temp->n_length=n_length;
+ s_temp->n_ref_length=ref_length | pack_marker;
+ length+= get_pack_length(n_length);
+ s_temp->n_length=n_length;
}
}
}
@@ -1710,15 +1933,15 @@ _mi_calc_var_pack_key_length(MI_KEYDEF *keyinfo,uint nod_flag,uchar *next_key,
int
_mi_calc_bin_pack_key_length(MI_KEYDEF *keyinfo,uint nod_flag,uchar *next_key,
- uchar *org_key, uchar *prev_key, uchar *key,
- MI_KEY_PARAM *s_temp)
+ uchar *org_key, uchar *prev_key, uchar *key,
+ MI_KEY_PARAM *s_temp)
{
uint length,key_length,ref_length;
s_temp->totlength=key_length=_mi_keylength(keyinfo,key)+nod_flag;
s_temp->key=key;
s_temp->prev_key=org_key;
- if (prev_key) /* If not first key in block */
+ if (prev_key) /* If not first key in block */
{
/* pack key against previous key */
/*
@@ -1737,7 +1960,7 @@ _mi_calc_bin_pack_key_length(MI_KEYDEF *keyinfo,uint nod_flag,uchar *next_key,
s_temp->ref_length=ref_length=0;
length=key_length+1;
}
- if ((s_temp->next_key_pos=next_key)) /* If another key after */
+ if ((s_temp->next_key_pos=next_key)) /* If another key after */
{
/* pack key against next key */
uint next_length,next_length_pack;
@@ -1748,21 +1971,21 @@ _mi_calc_bin_pack_key_length(MI_KEYDEF *keyinfo,uint nod_flag,uchar *next_key,
{
uchar *end;
for (key= s_temp->key, end=key+next_length ;
- *key == *org_key && key < end;
- key++,org_key++) ;
+ *key == *org_key && key < end;
+ key++,org_key++) ;
ref_length= (uint) (key - s_temp->key);
}
if (next_length > ref_length)
{
/* We put a key with different case between two keys with the same prefix
- Extend next key to have same prefix as
- this key */
+ Extend next key to have same prefix as
+ this key */
s_temp->n_ref_length= ref_length;
s_temp->prev_length= next_length-ref_length;
s_temp->prev_key+= ref_length;
return (int) (length+ s_temp->prev_length - next_length_pack +
- get_pack_length(ref_length));
+ get_pack_length(ref_length));
}
/* Check how many characters are identical to next key */
key= s_temp->key+next_length;
@@ -1770,12 +1993,12 @@ _mi_calc_bin_pack_key_length(MI_KEYDEF *keyinfo,uint nod_flag,uchar *next_key,
if ((ref_length= (uint) (key - s_temp->key)-1) == next_length)
{
s_temp->next_key_pos=0;
- return length; /* can't pack next key */
+ return length; /* can't pack next key */
}
s_temp->prev_length=0;
s_temp->n_ref_length=ref_length;
return (int) (length-(ref_length - next_length) - next_length_pack +
- get_pack_length(ref_length));
+ get_pack_length(ref_length));
}
return (int) length;
}
@@ -1788,8 +2011,8 @@ _mi_calc_bin_pack_key_length(MI_KEYDEF *keyinfo,uint nod_flag,uchar *next_key,
/* store key without compression */
void _mi_store_static_key(MI_KEYDEF *keyinfo __attribute__((unused)),
- register uchar *key_pos,
- register MI_KEY_PARAM *s_temp)
+ register uchar *key_pos,
+ register MI_KEY_PARAM *s_temp)
{
memcpy((byte*) key_pos,(byte*) s_temp->key,(size_t) s_temp->totlength);
}
@@ -1803,8 +2026,8 @@ void _mi_store_static_key(MI_KEYDEF *keyinfo __attribute__((unused)),
void _mi_store_var_pack_key(MI_KEYDEF *keyinfo __attribute__((unused)),
- register uchar *key_pos,
- register MI_KEY_PARAM *s_temp)
+ register uchar *key_pos,
+ register MI_KEY_PARAM *s_temp)
{
uint length;
uchar *start;
@@ -1825,9 +2048,9 @@ void _mi_store_var_pack_key(MI_KEYDEF *keyinfo __attribute__((unused)),
store_pack_length(s_temp->pack_marker == 128,key_pos,s_temp->key_length);
}
bmove((byte*) key_pos,(byte*) s_temp->key,
- (length=s_temp->totlength-(uint) (key_pos-start)));
+ (length=s_temp->totlength-(uint) (key_pos-start)));
- if (!s_temp->next_key_pos) /* No following key */
+ if (!s_temp->next_key_pos) /* No following key */
return;
key_pos+=length;
@@ -1837,14 +2060,14 @@ void _mi_store_var_pack_key(MI_KEYDEF *keyinfo __attribute__((unused)),
if (s_temp->part_of_prev_key)
{
store_pack_length(s_temp->pack_marker == 128,key_pos,
- s_temp->part_of_prev_key);
+ s_temp->part_of_prev_key);
store_key_length_inc(key_pos,s_temp->n_length);
}
else
{
s_temp->n_length+= s_temp->store_not_null;
store_pack_length(s_temp->pack_marker == 128,key_pos,
- s_temp->n_length);
+ s_temp->n_length);
}
memcpy(key_pos, s_temp->prev_key, s_temp->prev_length);
}
@@ -1852,7 +2075,7 @@ void _mi_store_var_pack_key(MI_KEYDEF *keyinfo __attribute__((unused)),
{
store_pack_length(s_temp->pack_marker == 128,key_pos,s_temp->n_ref_length);
if (s_temp->n_ref_length == s_temp->pack_marker)
- return; /* Identical key */
+ return; /* Identical key */
store_key_length(key_pos,s_temp->n_length);
}
else
@@ -1866,18 +2089,18 @@ void _mi_store_var_pack_key(MI_KEYDEF *keyinfo __attribute__((unused)),
/* variable length key with prefix compression */
void _mi_store_bin_pack_key(MI_KEYDEF *keyinfo __attribute__((unused)),
- register uchar *key_pos,
- register MI_KEY_PARAM *s_temp)
+ register uchar *key_pos,
+ register MI_KEY_PARAM *s_temp)
{
store_key_length_inc(key_pos,s_temp->ref_length);
memcpy((char*) key_pos,(char*) s_temp->key+s_temp->ref_length,
- (size_t) s_temp->totlength-s_temp->ref_length);
+ (size_t) s_temp->totlength-s_temp->ref_length);
if (s_temp->next_key_pos)
{
key_pos+=(uint) (s_temp->totlength-s_temp->ref_length);
store_key_length_inc(key_pos,s_temp->n_ref_length);
- if (s_temp->prev_length) /* If we must extend key */
+ if (s_temp->prev_length) /* If we must extend key */
{
memcpy(key_pos,s_temp->prev_key,s_temp->prev_length);
}
diff --git a/myisam/mi_static.c b/myisam/mi_static.c
index f790f90ca78..86d7fc38f25 100644
--- a/myisam/mi_static.c
+++ b/myisam/mi_static.c
@@ -1,21 +1,21 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/*
- Static variables for pisam library. All definied here for easy making of
+ Static variables for MyISAM library. All definied here for easy making of
a shared library
*/
@@ -32,7 +32,7 @@ my_string myisam_log_filename=(char*) "myisam.log";
File myisam_log_file= -1;
uint myisam_quick_table_bits=9;
uint myisam_block_size=MI_KEY_BLOCK_LENGTH; /* Best by test */
-my_bool myisam_flush=0,myisam_delay_key_write=0;
+my_bool myisam_flush=0, myisam_delay_key_write=0, myisam_single_user=0;
#if defined(THREAD) && !defined(DONT_USE_RW_LOCKS)
my_bool myisam_concurrent_insert=1;
#else
@@ -40,7 +40,7 @@ my_bool myisam_concurrent_insert=0;
#endif
my_off_t myisam_max_extra_temp_length= MI_MAX_TEMP_LENGTH;
my_off_t myisam_max_temp_length= MAX_FILE_SIZE;
-
+ulong myisam_bulk_insert_tree_size=8192*1024;
/* read_vec[] is used for converting between P_READ_KEY.. and SEARCH_ */
/* Position is , == , >= , <= , > , < */
diff --git a/myisam/mi_statrec.c b/myisam/mi_statrec.c
index 05ff40d8921..ad00b6d2595 100644
--- a/myisam/mi_statrec.c
+++ b/myisam/mi_statrec.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -27,17 +27,16 @@ int _mi_write_static_record(MI_INFO *info, const byte *record)
{
my_off_t filepos=info->s->state.dellink;
info->rec_cache.seek_not_done=1; /* We have done a seek */
- VOID(my_seek(info->dfile,info->s->state.dellink+1,MY_SEEK_SET,MYF(0)));
-
- if (my_read(info->dfile,(char*) &temp[0],info->s->base.rec_reflength,
- MYF(MY_NABP)))
+ if (my_pread(info->dfile,(char*) &temp[0],info->s->base.rec_reflength,
+ info->s->state.dellink+1,
+ MYF(MY_NABP)))
goto err;
info->s->state.dellink= _mi_rec_pos(info->s,temp);
info->state->del--;
info->state->empty-=info->s->base.pack_reclength;
- VOID(my_seek(info->dfile,filepos,MY_SEEK_SET,MYF(0)));
- if (my_write(info->dfile, (char*) record, info->s->base.reclength,
- MYF(MY_NABP)))
+ if (my_pwrite(info->dfile, (char*) record, info->s->base.reclength,
+ filepos,
+ MYF(MY_NABP)))
goto err;
}
else
@@ -64,16 +63,18 @@ int _mi_write_static_record(MI_INFO *info, const byte *record)
else
{
info->rec_cache.seek_not_done=1; /* We have done a seek */
- VOID(my_seek(info->dfile,info->state->data_file_length,
- MY_SEEK_SET,MYF(0)));
- if (my_write(info->dfile,(char*) record,info->s->base.reclength,
- info->s->write_flag))
+ if (my_pwrite(info->dfile,(char*) record,info->s->base.reclength,
+ info->state->data_file_length,
+ info->s->write_flag))
goto err;
if (info->s->base.pack_reclength != info->s->base.reclength)
{
uint length=info->s->base.pack_reclength - info->s->base.reclength;
bzero((char*) temp,length);
- if (my_write(info->dfile, (byte*) temp,length, info->s->write_flag))
+ if (my_pwrite(info->dfile, (byte*) temp,length,
+ info->state->data_file_length+
+ info->s->base.reclength,
+ info->s->write_flag))
goto err;
}
}
@@ -88,9 +89,10 @@ int _mi_write_static_record(MI_INFO *info, const byte *record)
int _mi_update_static_record(MI_INFO *info, my_off_t pos, const byte *record)
{
info->rec_cache.seek_not_done=1; /* We have done a seek */
- VOID(my_seek(info->dfile,pos,MY_SEEK_SET,MYF(0)));
- return (my_write(info->dfile,(char*) record,info->s->base.reclength,
- MYF(MY_NABP)) != 0);
+ return (my_pwrite(info->dfile,
+ (char*) record,info->s->base.reclength,
+ pos,
+ MYF(MY_NABP)) != 0);
}
@@ -104,9 +106,8 @@ int _mi_delete_static_record(MI_INFO *info)
_mi_dpointer(info,temp+1,info->s->state.dellink);
info->s->state.dellink = info->lastpos;
info->rec_cache.seek_not_done=1;
- VOID(my_seek(info->dfile,info->lastpos,MY_SEEK_SET,MYF(0)));
- return (my_write(info->dfile,(byte*) temp, 1+info->s->rec_reflength,
- MYF(MY_NABP)) != 0);
+ return (my_pwrite(info->dfile,(byte*) temp, 1+info->s->rec_reflength,
+ info->lastpos, MYF(MY_NABP)) != 0);
}
@@ -129,9 +130,9 @@ int _mi_cmp_static_record(register MI_INFO *info, register const byte *old)
if ((info->opt_flag & READ_CHECK_USED))
{ /* If check isn't disabled */
info->rec_cache.seek_not_done=1; /* We have done a seek */
- VOID(my_seek(info->dfile,info->lastpos,MY_SEEK_SET,MYF(0)));
- if (my_read(info->dfile, (char*) info->rec_buff, info->s->base.reclength,
- MYF(MY_NABP)))
+ if (my_pread(info->dfile, (char*) info->rec_buff, info->s->base.reclength,
+ info->lastpos,
+ MYF(MY_NABP)))
DBUG_RETURN(-1);
if (memcmp((byte*) info->rec_buff, (byte*) old,
(uint) info->s->base.reclength))
@@ -152,9 +153,8 @@ int _mi_cmp_static_unique(MI_INFO *info, MI_UNIQUEDEF *def,
DBUG_ENTER("_mi_cmp_static_unique");
info->rec_cache.seek_not_done=1; /* We have done a seek */
- VOID(my_seek(info->dfile,pos,MY_SEEK_SET,MYF(0)));
- if (my_read(info->dfile, (char*) info->rec_buff, info->s->base.reclength,
- MYF(MY_NABP)))
+ if (my_pread(info->dfile, (char*) info->rec_buff, info->s->base.reclength,
+ pos, MYF(MY_NABP)))
DBUG_RETURN(-1);
DBUG_RETURN(mi_unique_comp(def, record, info->rec_buff,
def->null_are_equal));
@@ -181,8 +181,7 @@ int _mi_read_static_record(register MI_INFO *info, register my_off_t pos,
error=my_pread(info->dfile,(char*) record,info->s->base.reclength,
pos,MYF(MY_NABP)) != 0;
- if (info->s->r_locks == 0 && info->s->w_locks == 0)
- VOID(_mi_writeinfo(info,0));
+ fast_mi_writeinfo(info);
if (! error)
{
if (!*record)
@@ -195,7 +194,7 @@ int _mi_read_static_record(register MI_INFO *info, register my_off_t pos,
}
return(-1); /* Error on read */
}
- VOID(_mi_writeinfo(info,0)); /* No such record */
+ fast_mi_writeinfo(info); /* No such record */
return(-1);
}
@@ -222,7 +221,7 @@ int _mi_read_rnd_static_record(MI_INFO *info, byte *buf,
(skipp_deleted_blocks || !filepos))
{
cache_read=1; /* Read record using cache */
- cache_length=(uint) (info->rec_cache.rc_end - info->rec_cache.rc_pos);
+ cache_length=(uint) (info->rec_cache.read_end - info->rec_cache.read_pos);
}
else
info->rec_cache.seek_not_done=1; /* Filepos is changed */
@@ -257,7 +256,7 @@ int _mi_read_rnd_static_record(MI_INFO *info, byte *buf,
DBUG_PRINT("test",("filepos: %ld (%ld) records: %ld del: %ld",
filepos/share->base.reclength,filepos,
info->state->records, info->state->del));
- VOID(_mi_writeinfo(info,0));
+ fast_mi_writeinfo(info);
DBUG_RETURN(my_errno=HA_ERR_END_OF_FILE);
}
info->lastpos= filepos;
diff --git a/myisam/mi_test1.c b/myisam/mi_test1.c
index ae09bd4142e..bb32860b575 100644
--- a/myisam/mi_test1.c
+++ b/myisam/mi_test1.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -23,7 +23,7 @@
#define MAX_REC_LENGTH 1024
static int rec_pointer_size=0,verbose=0,flags[50];
-static int key_field=FIELD_SKIPP_PRESPACE,extra_field=FIELD_SKIPP_ENDSPACE;
+static int key_field=FIELD_SKIP_PRESPACE,extra_field=FIELD_SKIP_ENDSPACE;
static int key_type=HA_KEYTYPE_NUM;
static int create_flag=0;
diff --git a/myisam/mi_test2.c b/myisam/mi_test2.c
index b66b02afdf9..81d00893d27 100644
--- a/myisam/mi_test2.c
+++ b/myisam/mi_test2.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -148,15 +148,15 @@ int main(int argc, char *argv[])
keyinfo[5].keysegs=1;
keyinfo[5].flag = pack_type;
- recinfo[0].type=pack_fields ? FIELD_SKIPP_PRESPACE : 0;
+ recinfo[0].type=pack_fields ? FIELD_SKIP_PRESPACE : 0;
recinfo[0].length=7;
recinfo[0].null_bit=0;
recinfo[0].null_pos=0;
- recinfo[1].type=pack_fields ? FIELD_SKIPP_PRESPACE : 0;
+ recinfo[1].type=pack_fields ? FIELD_SKIP_PRESPACE : 0;
recinfo[1].length=5;
recinfo[1].null_bit=0;
recinfo[1].null_pos=0;
- recinfo[2].type=pack_fields ? FIELD_SKIPP_PRESPACE : 0;
+ recinfo[2].type=pack_fields ? FIELD_SKIP_PRESPACE : 0;
recinfo[2].length=9;
recinfo[2].null_bit=0;
recinfo[2].null_pos=0;
@@ -164,11 +164,11 @@ int main(int argc, char *argv[])
recinfo[3].length=STANDARD_LENGTH-7-5-9-4;
recinfo[3].null_bit=0;
recinfo[3].null_pos=0;
- recinfo[4].type=pack_fields ? FIELD_SKIPP_ZERO : 0;
+ recinfo[4].type=pack_fields ? FIELD_SKIP_ZERO : 0;
recinfo[4].length=4;
recinfo[4].null_bit=0;
recinfo[4].null_pos=0;
- recinfo[5].type=pack_fields ? FIELD_SKIPP_ENDSPACE : 0;
+ recinfo[5].type=pack_fields ? FIELD_SKIP_ENDSPACE : 0;
recinfo[5].length=60;
recinfo[5].null_bit=0;
recinfo[5].null_pos=0;
@@ -343,68 +343,72 @@ int main(int argc, char *argv[])
}
if (testflag==3) goto end;
- if (!silent)
- printf("- Same key: first - next -> last - prev -> first\n");
- DBUG_PRINT("progpos",("first - next -> last - prev -> first"));
for (i=999, dupp_keys=j=0 ; i>0 ; i--)
{
- if (key1[i] >dupp_keys) { dupp_keys=key1[i]; j=i; }
+ if (key1[i] > dupp_keys) { dupp_keys=key1[i]; j=i; }
}
sprintf(key,"%6d",j);
- if (verbose) printf(" Using key: \"%s\" Keys: %d\n",key,dupp_keys);
- if (mi_rkey(file,read_record,0,key,0,HA_READ_KEY_EXACT)) goto err;
- if (mi_rsame(file,read_record2,-1)) goto err;
- if (memcmp(read_record,read_record2,reclength) != 0)
- {
- printf("mi_rsame didn't find same record\n");
- goto end;
- }
- info.recpos=mi_position(file);
- if (mi_rfirst(file,read_record2,0) ||
- mi_rsame_with_pos(file,read_record2,0,info.recpos) ||
- memcmp(read_record,read_record2,reclength) != 0)
- {
- printf("mi_rsame_with_pos didn't find same record\n");
- goto end;
- }
+ if (dupp_keys)
{
- int skr=mi_rnext(file,read_record2,0);
- if ((skr && my_errno != HA_ERR_END_OF_FILE) ||
- mi_rprev(file,read_record2,-1) ||
+ if (!silent)
+ printf("- Same key: first - next -> last - prev -> first\n");
+ DBUG_PRINT("progpos",("first - next -> last - prev -> first"));
+ if (verbose) printf(" Using key: \"%s\" Keys: %d\n",key,dupp_keys);
+
+ if (mi_rkey(file,read_record,0,key,0,HA_READ_KEY_EXACT)) goto err;
+ if (mi_rsame(file,read_record2,-1)) goto err;
+ if (memcmp(read_record,read_record2,reclength) != 0)
+ {
+ printf("mi_rsame didn't find same record\n");
+ goto end;
+ }
+ info.recpos=mi_position(file);
+ if (mi_rfirst(file,read_record2,0) ||
+ mi_rsame_with_pos(file,read_record2,0,info.recpos) ||
memcmp(read_record,read_record2,reclength) != 0)
{
- printf("mi_rsame_with_pos lost position\n");
+ printf("mi_rsame_with_pos didn't find same record\n");
+ goto end;
+ }
+ {
+ int skr=mi_rnext(file,read_record2,0);
+ if ((skr && my_errno != HA_ERR_END_OF_FILE) ||
+ mi_rprev(file,read_record2,-1) ||
+ memcmp(read_record,read_record2,reclength) != 0)
+ {
+ printf("mi_rsame_with_pos lost position\n");
+ goto end;
+ }
+ }
+ ant=1;
+ start=keyinfo[0].seg[0].start; length=keyinfo[0].seg[0].length;
+ while (mi_rnext(file,read_record2,0) == 0 &&
+ memcmp(read_record2+start,key,length) == 0) ant++;
+ if (ant != dupp_keys)
+ {
+ printf("next: Found: %d keys of %d\n",ant,dupp_keys);
+ goto end;
+ }
+ ant=0;
+ while (mi_rprev(file,read_record3,0) == 0 &&
+ bcmp(read_record3+start,key,length) == 0) ant++;
+ if (ant != dupp_keys)
+ {
+ printf("prev: Found: %d records of %d\n",ant,dupp_keys);
goto end;
}
- }
- ant=1;
- start=keyinfo[0].seg[0].start; length=keyinfo[0].seg[0].length;
- while (mi_rnext(file,read_record2,0) == 0 &&
- memcmp(read_record2+start,key,length) == 0) ant++;
- if (ant != dupp_keys)
- {
- printf("next: Found: %d keys of %d\n",ant,dupp_keys);
- goto end;
- }
- ant=0;
- while (mi_rprev(file,read_record3,0) == 0 &&
- bcmp(read_record3+start,key,length) == 0) ant++;
- if (ant != dupp_keys)
- {
- printf("prev: Found: %d records of %d\n",ant,dupp_keys);
- goto end;
- }
- /* Check of mi_rnext_same */
- if (mi_rkey(file,read_record,0,key,0,HA_READ_KEY_EXACT))
- goto err;
- ant=1;
- while (!mi_rnext_same(file,read_record3) && ant < dupp_keys+10)
- ant++;
- if (ant != dupp_keys || my_errno != HA_ERR_END_OF_FILE)
- {
- printf("mi_rnext_same: Found: %d records of %d\n",ant,dupp_keys);
- goto end;
+ /* Check of mi_rnext_same */
+ if (mi_rkey(file,read_record,0,key,0,HA_READ_KEY_EXACT))
+ goto err;
+ ant=1;
+ while (!mi_rnext_same(file,read_record3) && ant < dupp_keys+10)
+ ant++;
+ if (ant != dupp_keys || my_errno != HA_ERR_END_OF_FILE)
+ {
+ printf("mi_rnext_same: Found: %d records of %d\n",ant,dupp_keys);
+ goto end;
+ }
}
if (!silent)
@@ -776,9 +780,13 @@ end:
printf("\nFollowing test have been made:\n");
printf("Write records: %d\nUpdate records: %d\nSame-key-read: %d\nDelete records: %d\n", write_count,update,dupp_keys,opt_delete);
if (rec_pointer_size)
- printf("Record pointer size: %d\n",rec_pointer_size);
+ printf("Record pointer size: %d\n",rec_pointer_size);
+ printf("myisam_block_size: %u\n", myisam_block_size);
if (key_cacheing)
+ {
puts("Key cacheing used");
+ printf("key_cache_block_size: %u\n", key_cache_block_size);
+ }
if (write_cacheing)
puts("Write cacheing used");
if (write_cacheing)
@@ -801,7 +809,7 @@ reads: %10lu\n",
end_key_cache();
if (blob_buffer)
my_free(blob_buffer,MYF(0));
- my_end(MY_CHECK_ERROR | MY_GIVE_INFO);
+ my_end(silent ? MY_CHECK_ERROR : MY_CHECK_ERROR | MY_GIVE_INFO);
return(0);
err:
printf("got error: %d when using MyISAM-database\n",my_errno);
@@ -861,7 +869,29 @@ static void get_options(int argc, char **argv)
verbose=1;
break;
case 'm': /* records */
- recant=atoi(++pos);
+ if ((recant=atoi(++pos)) < 10)
+ {
+ fprintf(stderr,"record count must be >= 10\n");
+ exit(1);
+ }
+ break;
+ case 'e': /* myisam_block_length */
+ if ((myisam_block_size=atoi(++pos)) < MI_MIN_KEY_BLOCK_LENGTH ||
+ myisam_block_size > MI_MAX_KEY_BLOCK_LENGTH)
+ {
+ fprintf(stderr,"Wrong myisam_block_length\n");
+ exit(1);
+ }
+ myisam_block_size=1 << my_bit_log2(myisam_block_size);
+ break;
+ case 'E': /* myisam_block_length */
+ if ((key_cache_block_size=atoi(++pos)) < MI_MIN_KEY_BLOCK_LENGTH ||
+ key_cache_block_size > MI_MAX_KEY_BLOCK_LENGTH)
+ {
+ fprintf(stderr,"Wrong key_cache_block_size\n");
+ exit(1);
+ }
+ key_cache_block_size=1 << my_bit_log2(key_cache_block_size);
break;
case 'f':
if ((first_key=atoi(++pos)) < 0 || first_key >= MYISAM_KEYS)
@@ -904,7 +934,7 @@ static void get_options(int argc, char **argv)
case 'V':
printf("%s Ver 1.2 for %s at %s\n",progname,SYSTEM_TYPE,MACHINE_TYPE);
puts("By Monty, for your professional use\n");
- printf("Usage: %s [-?AbBcDIKLPRqSsVWltv] [-k#] [-f#] [-m#] [-t#]\n",
+ printf("Usage: %s [-?AbBcDIKLPRqSsVWltv] [-k#] [-f#] [-m#] [-e#] [-E#] [-t#]\n",
progname);
exit(0);
case '#':
diff --git a/myisam/mi_test3.c b/myisam/mi_test3.c
index 48325b2dcac..36222c3edbc 100644
--- a/myisam/mi_test3.c
+++ b/myisam/mi_test3.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
diff --git a/myisam/mi_test_all.res b/myisam/mi_test_all.res
index d6b4703d702..94355bf1aa2 100644
--- a/myisam/mi_test_all.res
+++ b/myisam/mi_test_all.res
@@ -1,48 +1,50 @@
-Maximum memory usage: 545477 bytes (533k)
-Maximum memory usage: 545477 bytes (533k)
-Maximum memory usage: 545369 bytes (533k)
-mi_test2-i686 -s -L -K -R1 -m2000 ; Should give error 135
+mi_test2 -s -L -K -R1 -m2000 ; Should give error 135
Error: 135 in write at record: 1105
got error: 135 when using MyISAM-database
-Maximum memory usage: 29439 bytes (29k)
-Maximum memory usage: 66541 bytes (65k)
-Maximum memory usage: 5101 bytes (5k)
-Maximum memory usage: 545488 bytes (533k)
+myisamchk: MyISAM file test2
+myisamchk: warning: Datafile is almost full, 65532 of 65534 used
+MyISAM-table 'test2' is usable but should be fixed
Commands Used count Errors Recover errors
-open 1 0 0
-write 50 0 0
-update 5 0 0
-delete 50 0 0
-close 1 0 0
-extra 6 0 0
-Total 113 0 0
-Maximum memory usage: 545744 bytes (533k)
+open 17 0 0
+write 850 0 0
+update 85 0 0
+delete 850 0 0
+close 17 0 0
+extra 102 0 0
+Total 1921 0 0
Commands Used count Errors Recover errors
-open 2 0 0
-write 100 0 0
-update 10 0 0
-delete 100 0 0
-close 2 0 0
-extra 12 0 0
-Total 226 0 0
-Maximum memory usage: 5101 bytes (5k)
-1.12user 0.52system 0:01.71elapsed 95%CPU (0avgtext+0avgdata 0maxresident)k
-0inputs+0outputs (214major+25minor)pagefaults 0swaps
-Maximum memory usage: 21189 bytes (21k)
-1.29user 0.55system 0:01.82elapsed 101%CPU (0avgtext+0avgdata 0maxresident)k
-0inputs+0outputs (215major+29minor)pagefaults 0swaps
-Maximum memory usage: 66541 bytes (65k)
-1.10user 0.51system 0:01.66elapsed 96%CPU (0avgtext+0avgdata 0maxresident)k
-0inputs+0outputs (216major+40minor)pagefaults 0swaps
-Maximum memory usage: 82629 bytes (81k)
-1.33user 0.24system 0:01.54elapsed 101%CPU (0avgtext+0avgdata 0maxresident)k
-0inputs+0outputs (216major+44minor)pagefaults 0swaps
-Maximum memory usage: 545477 bytes (533k)
-1.31user 0.24system 0:01.55elapsed 99%CPU (0avgtext+0avgdata 0maxresident)k
-0inputs+0outputs (216major+173minor)pagefaults 0swaps
-Maximum memory usage: 545389 bytes (533k)
-1.37user 0.18system 0:01.57elapsed 98%CPU (0avgtext+0avgdata 0maxresident)k
-0inputs+0outputs (218major+180minor)pagefaults 0swaps
-Maximum memory usage: 109165 bytes (107k)
-1.42user 0.38system 0:01.78elapsed 101%CPU (0avgtext+0avgdata 0maxresident)k
-0inputs+0outputs (218major+51minor)pagefaults 0swaps
+open 18 0 0
+write 900 0 0
+update 90 0 0
+delete 900 0 0
+close 18 0 0
+extra 108 0 0
+Total 2034 0 0
+
+real 0m1.054s
+user 0m0.410s
+sys 0m0.640s
+
+real 0m1.077s
+user 0m0.550s
+sys 0m0.530s
+
+real 0m1.100s
+user 0m0.420s
+sys 0m0.680s
+
+real 0m0.783s
+user 0m0.590s
+sys 0m0.200s
+
+real 0m0.764s
+user 0m0.560s
+sys 0m0.210s
+
+real 0m0.699s
+user 0m0.570s
+sys 0m0.130s
+
+real 0m0.991s
+user 0m0.630s
+sys 0m0.350s
diff --git a/myisam/mi_test_all.sh b/myisam/mi_test_all.sh
index ccc9c39c64e..a2d57ea1a83 100755
--- a/myisam/mi_test_all.sh
+++ b/myisam/mi_test_all.sh
@@ -66,6 +66,14 @@ myisamchk$suffix -rs test1
myisamchk$suffix -se test1
myisamchk$suffix -rqs test1
myisamchk$suffix -se test1
+myisamchk$suffix -rs --correct-checksum test1
+myisamchk$suffix -se test1
+myisamchk$suffix -rqs --correct-checksum test1
+myisamchk$suffix -se test1
+myisamchk$suffix -ros --correct-checksum test1
+myisamchk$suffix -se test1
+myisamchk$suffix -rqos --correct-checksum test1
+myisamchk$suffix -se test1
# check of myisampack / myisamchk
myisampack$suffix --force -s test1
@@ -105,13 +113,25 @@ mi_test1$suffix $silent --key_multiple -P -S
myisamchk$suffix -sm test1
mi_test2$suffix $silent -L -K -W -P
+myisamchk$suffix -sm test2
mi_test2$suffix $silent -L -K -W -P -A
+myisamchk$suffix -sm test2
mi_test2$suffix $silent -L -K -W -P -S -R1 -m500
echo "mi_test2$suffix $silent -L -K -R1 -m2000 ; Should give error 135"
+myisamchk$suffix -sm test2
mi_test2$suffix $silent -L -K -R1 -m2000
+myisamchk$suffix -sm test2
mi_test2$suffix $silent -L -K -P -S -R3 -m50 -b1000000
+myisamchk$suffix -sm test2
mi_test2$suffix $silent -L -B
+myisamchk$suffix -sm test2
mi_test2$suffix $silent -D -B -c
+myisamchk$suffix -sm test2
+mi_test2$suffix $silent -m10000 -e8192 -K
+myisamchk$suffix -sm test2
+mi_test2$suffix $silent -m10000 -e16384 -E16384 -K -L
+myisamchk$suffix -sm test2
+
mi_test2$suffix $silent -L -K -W -P -m50 -l
myisamlog$suffix
mi_test2$suffix $silent -L -K -W -P -m50 -l -b100
diff --git a/myisam/mi_unique.c b/myisam/mi_unique.c
index e598fbeedb4..5806502823a 100644
--- a/myisam/mi_unique.c
+++ b/myisam/mi_unique.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
diff --git a/myisam/mi_update.c b/myisam/mi_update.c
index 185624f3878..2c6bc42bbdb 100644
--- a/myisam/mi_update.c
+++ b/myisam/mi_update.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -98,9 +98,7 @@ int mi_update(register MI_INFO *info, const byte *oldrec, byte *newrec)
if ((int) i == info->lastinx)
key_changed|=HA_STATE_WRITTEN;
changed|=((ulonglong) 1 << i);
- if (_mi_ft_del(info,i,(char*) old_key,oldrec,pos))
- goto err;
- if (_mi_ft_add(info,i,(char*) new_key,newrec,pos))
+ if (_mi_ft_update(info,i,(char*) old_key,oldrec,newrec,pos))
goto err;
}
}
@@ -138,6 +136,12 @@ int mi_update(register MI_INFO *info, const byte *oldrec, byte *newrec)
myisam_log_record(MI_LOG_UPDATE,info,newrec,info->lastpos,0);
VOID(_mi_writeinfo(info,key_changed ? WRITEINFO_UPDATE_KEYFILE : 0));
allow_break(); /* Allow SIGHUP & SIGINT */
+ if (info->invalidator != 0)
+ {
+ DBUG_PRINT("info", ("invalidator... '%s' (update)", info->filename));
+ (*info->invalidator)(info->filename);
+ info->invalidator=0;
+ }
DBUG_RETURN(0);
err:
diff --git a/myisam/mi_write.c b/myisam/mi_write.c
index f31e43e52ab..1f43a5defcc 100644
--- a/myisam/mi_write.c
+++ b/myisam/mi_write.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -25,7 +25,8 @@
/* Functions declared in this file */
-static int w_search(MI_INFO *info,MI_KEYDEF *keyinfo,uchar *key,
+static int w_search(MI_INFO *info,MI_KEYDEF *keyinfo,
+ uint comp_flag, uchar *key,
uint key_length, my_off_t pos, uchar *father_buff,
uchar *father_keypos, my_off_t father_page,
my_bool insert_last);
@@ -35,17 +36,21 @@ static int _mi_balance_page(MI_INFO *info,MI_KEYDEF *keyinfo,uchar *key,
static uchar *_mi_find_last_pos(MI_KEYDEF *keyinfo, uchar *page,
uchar *key, uint *return_key_length,
uchar **after_key);
-
+int _mi_ck_write_tree(register MI_INFO *info, uint keynr, uchar *key,
+ uint key_length);
+int _mi_ck_write_btree(register MI_INFO *info, uint keynr, uchar *key,
+ uint key_length);
/* Write new record to database */
int mi_write(MI_INFO *info, byte *record)
{
+ MYISAM_SHARE *share=info->s;
uint i;
int save_errno;
my_off_t filepos;
uchar *buff;
- MYISAM_SHARE *share=info->s;
+ my_bool lock_tree= share->concurrent_insert;
DBUG_ENTER("mi_write");
DBUG_PRINT("enter",("isam: %d data: %d",info->s->kfile,info->dfile));
@@ -96,33 +101,36 @@ int mi_write(MI_INFO *info, byte *record)
{
if (((ulonglong) 1 << i) & share->state.key_map)
{
- if (share->concurrent_insert)
+ bool local_lock_tree= (lock_tree &&
+ !(info->bulk_insert &&
+ is_tree_inited(& info->bulk_insert[i])));
+ if (local_lock_tree)
{
rw_wrlock(&share->key_root_lock[i]);
share->keyinfo[i].version++;
}
- if (share->keyinfo[i].flag & HA_FULLTEXT ) /* SerG */
- { /* SerG */
- if (_mi_ft_add(info,i,(char*) buff,record,filepos)) /* SerG */
- { /* SerG */
- if (share->concurrent_insert)
+ if (share->keyinfo[i].flag & HA_FULLTEXT )
+ {
+ if (_mi_ft_add(info,i,(char*) buff,record,filepos))
+ {
+ if (local_lock_tree)
rw_unlock(&share->key_root_lock[i]);
- DBUG_PRINT("error",("Got error: %d on write",my_errno)); /* SerG */
- goto err; /* SerG */
- } /* SerG */
- } /* SerG */
- else /* SerG */
+ DBUG_PRINT("error",("Got error: %d on write",my_errno));
+ goto err;
+ }
+ }
+ else
{
uint key_length=_mi_make_key(info,i,buff,record,filepos);
if (_mi_ck_write(info,i,buff,key_length))
{
- if (share->concurrent_insert)
+ if (local_lock_tree)
rw_unlock(&share->key_root_lock[i]);
DBUG_PRINT("error",("Got error: %d on write",my_errno));
goto err;
}
}
- if (share->concurrent_insert)
+ if (local_lock_tree)
rw_unlock(&share->key_root_lock[i]);
}
}
@@ -142,6 +150,12 @@ int mi_write(MI_INFO *info, byte *record)
info->lastpos=filepos;
myisam_log_record(MI_LOG_WRITE,info,record,filepos,0);
VOID(_mi_writeinfo(info, WRITEINFO_UPDATE_KEYFILE));
+ if (info->invalidator != 0)
+ {
+ DBUG_PRINT("info", ("invalidator... '%s' (update)", info->filename));
+ (*info->invalidator)(info->filename);
+ info->invalidator=0;
+ }
allow_break(); /* Allow SIGHUP & SIGINT */
DBUG_RETURN(0);
@@ -149,19 +163,32 @@ err:
save_errno=my_errno;
if (my_errno == HA_ERR_FOUND_DUPP_KEY || my_errno == HA_ERR_RECORD_FILE_FULL)
{
+ if (info->bulk_insert)
+ {
+ uint j;
+ for (j=0 ; j < share->base.keys ; j++)
+ {
+ if (is_tree_inited(& info->bulk_insert[j]))
+ {
+ reset_tree(& info->bulk_insert[j]);
+ }
+ }
+ }
info->errkey= (int) i;
while ( i-- > 0)
{
if (((ulonglong) 1 << i) & share->state.key_map)
{
- if (share->concurrent_insert)
+ bool local_lock_tree= (lock_tree &&
+ !(info->bulk_insert &&
+ is_tree_inited(& info->bulk_insert[i])));
+ if (local_lock_tree)
rw_wrlock(&share->key_root_lock[i]);
- /* The following code block is for text searching by SerG */
if (share->keyinfo[i].flag & HA_FULLTEXT)
{
if (_mi_ft_del(info,i,(char*) buff,record,filepos))
{
- if (share->concurrent_insert)
+ if (local_lock_tree)
rw_unlock(&share->key_root_lock[i]);
break;
}
@@ -171,12 +198,12 @@ err:
uint key_length=_mi_make_key(info,i,buff,record,filepos);
if (_mi_ck_delete(info,i,buff,key_length))
{
- if (share->concurrent_insert)
+ if (local_lock_tree)
rw_unlock(&share->key_root_lock[i]);
break;
}
}
- if (share->concurrent_insert)
+ if (local_lock_tree)
rw_unlock(&share->key_root_lock[i]);
}
}
@@ -196,19 +223,51 @@ err2:
/* Write one key to btree */
-int _mi_ck_write(register MI_INFO *info, uint keynr, uchar *key,
- uint key_length)
+int _mi_ck_write(MI_INFO *info, uint keynr, uchar *key, uint key_length)
{
- int error;
DBUG_ENTER("_mi_ck_write");
+ if (info->bulk_insert && is_tree_inited(& info->bulk_insert[keynr]))
+ {
+ DBUG_RETURN(_mi_ck_write_tree(info, keynr, key, key_length));
+ }
+ else
+ {
+ DBUG_RETURN(_mi_ck_write_btree(info, keynr, key, key_length));
+ }
+} /* _mi_ck_write */
+
+
+/**********************************************************************
+ * Normal insert code *
+ **********************************************************************/
+
+int _mi_ck_write_btree(register MI_INFO *info, uint keynr, uchar *key,
+ uint key_length)
+{
+ int error;
+ uint comp_flag;
+ MI_KEYDEF *keyinfo=info->s->keyinfo+keynr;
+ DBUG_ENTER("_mi_ck_write_btree");
+
+ if (keyinfo->flag & HA_SORT_ALLOWS_SAME)
+ comp_flag=SEARCH_BIGGER; /* Put after same key */
+ else if (keyinfo->flag & HA_NOSAME)
+ {
+ comp_flag=SEARCH_FIND | SEARCH_UPDATE; /* No dupplicates */
+ if (keyinfo->flag & HA_NULL_ARE_EQUAL)
+ comp_flag|= SEARCH_NULL_ARE_EQUAL;
+ }
+ else
+ comp_flag=SEARCH_SAME; /* Keys in rec-pos order */
+
if (info->s->state.key_root[keynr] == HA_OFFSET_ERROR ||
- (error=w_search(info,info->s->keyinfo+keynr,key, key_length,
+ (error=w_search(info, keyinfo, comp_flag, key, key_length,
info->s->state.key_root[keynr], (uchar *) 0, (uchar*) 0,
(my_off_t) 0, 1)) > 0)
error=_mi_enlarge_root(info,keynr,key);
DBUG_RETURN(error);
-} /* _mi_ck_write */
+} /* _mi_ck_write_btree */
/* Make a new root with key as only pointer */
@@ -246,13 +305,12 @@ int _mi_enlarge_root(register MI_INFO *info, uint keynr, uchar *key)
*/
static int w_search(register MI_INFO *info, register MI_KEYDEF *keyinfo,
- uchar *key, uint key_length, my_off_t page,
- uchar *father_buff,
- uchar *father_keypos, my_off_t father_page,
- my_bool insert_last)
+ uint comp_flag, uchar *key, uint key_length, my_off_t page,
+ uchar *father_buff, uchar *father_keypos,
+ my_off_t father_page, my_bool insert_last)
{
int error,flag;
- uint comp_flag,nod_flag;
+ uint nod_flag, search_key_length;
uchar *temp_buff,*keypos;
uchar keybuff[MI_MAX_KEY_BUFF];
my_bool was_last_key;
@@ -260,21 +318,15 @@ static int w_search(register MI_INFO *info, register MI_KEYDEF *keyinfo,
DBUG_ENTER("w_search");
DBUG_PRINT("enter",("page: %ld",page));
- if (keyinfo->flag & HA_SORT_ALLOWS_SAME)
- comp_flag=SEARCH_BIGGER; /* Put after same key */
- else if (keyinfo->flag & HA_NOSAME)
- comp_flag=SEARCH_FIND | SEARCH_UPDATE; /* No dupplicates */
- else
- comp_flag=SEARCH_SAME; /* Keys in rec-pos order */
-
+ search_key_length= (comp_flag & SEARCH_FIND) ? key_length : USE_WHOLE_KEY;
if (!(temp_buff= (uchar*) my_alloca((uint) keyinfo->block_length+
MI_MAX_KEY_BUFF*2)))
DBUG_RETURN(-1);
if (!_mi_fetch_keypage(info,keyinfo,page,temp_buff,0))
goto err;
- flag=(*keyinfo->bin_search)(info,keyinfo,temp_buff,key,key_length,comp_flag,
- &keypos, keybuff, &was_last_key);
+ flag=(*keyinfo->bin_search)(info,keyinfo,temp_buff,key,search_key_length,
+ comp_flag, &keypos, keybuff, &was_last_key);
nod_flag=mi_test_if_nod(temp_buff);
if (flag == 0)
{
@@ -295,7 +347,7 @@ static int w_search(register MI_INFO *info, register MI_KEYDEF *keyinfo,
insert_last=0;
next_page=_mi_kpos(nod_flag,keypos);
if (next_page == HA_OFFSET_ERROR ||
- (error=w_search(info,keyinfo,key,key_length,next_page,
+ (error=w_search(info, keyinfo, comp_flag, key, key_length, next_page,
temp_buff, keypos, page, insert_last)) >0)
{
error=_mi_insert(info,keyinfo,key,temp_buff,keypos,keybuff,father_buff,
@@ -682,3 +734,118 @@ static int _mi_balance_page(register MI_INFO *info, MI_KEYDEF *keyinfo,
err:
DBUG_RETURN(-1);
} /* _mi_balance_page */
+
+/**********************************************************************
+ * Bulk insert code *
+ **********************************************************************/
+
+typedef struct {
+ MI_INFO *info;
+ uint keynr;
+} bulk_insert_param;
+
+int _mi_ck_write_tree(register MI_INFO *info, uint keynr, uchar *key,
+ uint key_length)
+{
+ int error;
+ DBUG_ENTER("_mi_ck_write_tree");
+
+ error= tree_insert(& info->bulk_insert[keynr], key,
+ key_length + info->s->rec_reflength) ? 0 : HA_ERR_OUT_OF_MEM ;
+
+ DBUG_RETURN(error);
+} /* _mi_ck_write_tree */
+
+
+/* typeof(_mi_keys_compare)=qsort_cmp2 */
+static int keys_compare(bulk_insert_param *param, uchar *key1, uchar *key2)
+{
+ uint not_used;
+ return _mi_key_cmp(param->info->s->keyinfo[param->keynr].seg,
+ key1, key2, USE_WHOLE_KEY, SEARCH_SAME,
+ &not_used);
+}
+
+
+static int keys_free(uchar *key, TREE_FREE mode, bulk_insert_param *param)
+{
+ /*
+ Probably I can use info->lastkey here, but I'm not sure,
+ and to be safe I'd better use local lastkey.
+ */
+ uchar lastkey[MI_MAX_KEY_BUFF];
+ uint keylen;
+ MI_KEYDEF *keyinfo;
+
+ switch (mode) {
+ case free_init:
+ if (param->info->s->concurrent_insert)
+ {
+ rw_wrlock(&param->info->s->key_root_lock[param->keynr]);
+ param->info->s->keyinfo[param->keynr].version++;
+ }
+ return 0;
+ case free_free:
+ keyinfo=param->info->s->keyinfo+param->keynr;
+ keylen=_mi_keylength(keyinfo, key);
+ memcpy(lastkey, key, keylen);
+ return _mi_ck_write_btree(param->info,param->keynr,lastkey,
+ keylen - param->info->s->rec_reflength);
+ case free_end:
+ if (param->info->s->concurrent_insert)
+ rw_unlock(&param->info->s->key_root_lock[param->keynr]);
+ return 0;
+ }
+ return -1;
+}
+
+
+int _mi_init_bulk_insert(MI_INFO *info)
+{
+ MYISAM_SHARE *share=info->s;
+ MI_KEYDEF *key=share->keyinfo;
+ bulk_insert_param *params;
+ uint i, num_keys;
+ ulonglong key_map=0;
+
+ if (info->bulk_insert)
+ return 0;
+
+ for (i=num_keys=0 ; i < share->base.keys ; i++)
+ {
+ if (!(key[i].flag & HA_NOSAME) && share->base.auto_key != i+1
+ && test(share->state.key_map & ((ulonglong) 1 << i)))
+ {
+ num_keys++;
+ key_map |=((ulonglong) 1 << i);
+ }
+ }
+
+ if (num_keys==0 || num_keys>myisam_bulk_insert_tree_size)
+ return 0;
+
+ info->bulk_insert=(TREE *)
+ my_malloc((sizeof(TREE)*share->base.keys+
+ sizeof(bulk_insert_param)*num_keys),MYF(0));
+
+ if (!info->bulk_insert)
+ return HA_ERR_OUT_OF_MEM;
+
+ params=(bulk_insert_param *)(info->bulk_insert+share->base.keys);
+ for (i=0 ; i < share->base.keys ; i++,key++)
+ {
+ if (test(key_map & ((ulonglong) 1 << i)))
+ {
+ params->info=info;
+ params->keynr=i;
+ init_tree(& info->bulk_insert[i], 0,
+ myisam_bulk_insert_tree_size / num_keys, 0,
+ (qsort_cmp2)keys_compare, 0,
+ (tree_element_free) keys_free, (void *)params++);
+ }
+ else
+ info->bulk_insert[i].root=0;
+ }
+
+ return 0;
+}
diff --git a/myisam/myisamchk.c b/myisam/myisamchk.c
index cb321f8fda3..c421d3b5578 100644
--- a/myisam/myisamchk.c
+++ b/myisam/myisamchk.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -20,7 +20,7 @@
#include <m_ctype.h>
#include <stdarg.h>
-#include <getopt.h>
+#include <my_getopt.h>
#include <assert.h>
#ifdef HAVE_SYS_VADVICE_H
#include <sys/vadvise.h>
@@ -44,6 +44,7 @@ static char **default_argv;
static const char *load_default_groups[]= { "myisamchk", 0 };
static const char *set_charset_name;
static CHARSET_INFO *set_charset;
+static long opt_myisam_block_size;
static const char *type_names[]=
{ "?","char","binary", "short", "long", "float",
@@ -141,76 +142,155 @@ int main(int argc, char **argv)
#endif
} /* main */
+enum options {
+ OPT_CHARSETS_DIR=256, OPT_SET_CHARSET,OPT_START_CHECK_POS,
+ OPT_CORRECT_CHECKSUM, OPT_KEY_BUFFER_SIZE, OPT_MYISAM_BLOCK_SIZE,
+ OPT_READ_BUFFER_SIZE, OPT_WRITE_BUFFER_SIZE, OPT_SORT_BUFFER_SIZE,
+ OPT_SORT_KEY_BLOCKS, OPT_DECODE_BITS, OPT_FT_MIN_WORD_LEN,
+ OPT_FT_MAX_WORD_LEN, OPT_FT_MAX_WORD_LEN_FOR_SORT
+};
-static CHANGEABLE_VAR changeable_vars[] = {
- { "key_buffer_size",(long*) &check_param.use_buffers,(long) USE_BUFFER_INIT,
- (long) MALLOC_OVERHEAD, (long) ~0L,(long) MALLOC_OVERHEAD,(long) IO_SIZE },
- { "read_buffer_size", (long*) &check_param.read_buffer_length,(long) READ_BUFFER_INIT,
- (long) MALLOC_OVERHEAD,(long) ~0L,(long) MALLOC_OVERHEAD,(long) 1L },
- { "write_buffer_size", (long*) &check_param.write_buffer_length,(long) READ_BUFFER_INIT,
- (long) MALLOC_OVERHEAD,(long) ~0L,(long) MALLOC_OVERHEAD,(long) 1L },
- { "sort_buffer_size",(long*) &check_param.sort_buffer_length,(long) SORT_BUFFER_INIT,
- (long) (MIN_SORT_BUFFER+MALLOC_OVERHEAD),(long) ~0L,
- (long) MALLOC_OVERHEAD,(long) 1L },
- { "sort_key_blocks",(long*) &check_param.sort_key_blocks,BUFFERS_WHEN_SORTING,4L,100L,0L,
- 1L },
- { "decode_bits",(long*) &decode_bits,9L,4L,17L,0L,1L },
- { NullS,(long*) 0,0L,0L,0L,0L,0L,} };
-
-enum options {OPT_CHARSETS_DIR=256, OPT_SET_CHARSET,OPT_START_CHECK_POS};
-
-
-static struct option long_options[] =
+static struct my_option my_long_options[] =
{
- {"analyze", no_argument, 0, 'a'},
- {"block-search", required_argument,0, 'b'},
- {"backup", no_argument, 0, 'B'},
- {"character-sets-dir",required_argument,0, OPT_CHARSETS_DIR},
- {"check", no_argument, 0, 'c'},
- {"check-only-changed",no_argument, 0, 'C'},
+ {"analyze",
+ "Analyze distribution of keys. Will make some joins in MySQL faster. You can check the calculated distribution.", 0, 0, 0, GET_NO_ARG, NO_ARG, 'a', 0, 0,
+ 0, 0, 0, 0},
+ {"block-search", "No help available.", 0, 0, 0, GET_LONG, REQUIRED_ARG, 'b',
+ 0, 0, 0, 0, 0, 0},
+ {"backup", "Make a backup of the .MYD file as 'filename-time.BAK'", 0, 0, 0,
+ GET_NO_ARG, NO_ARG, 'B', 0, 0, 0, 0, 0, 0},
+ {"character-sets-dir", "Directory where character sets are.",
+ (gptr*) &set_charset_name, 0, 0, GET_STR, REQUIRED_ARG, OPT_CHARSETS_DIR, 0,
+ 0, 0, 0, 0, 0},
+ {"check", "Check table for errors.", 0, 0, 0, GET_NO_ARG, NO_ARG, 'c', 0, 0,
+ 0, 0, 0, 0},
+ {"check-only-changed",
+ "Check only tables that has changed since last check.", 0, 0, 0, GET_NO_ARG,
+ NO_ARG, 'C', 0, 0, 0, 0, 0, 0},
+ {"correct-checksum", "Correct checksum information for table.", 0, 0, 0,
+ GET_NO_ARG, NO_ARG, OPT_CORRECT_CHECKSUM, 0, 0, 0, 0, 0, 0},
#ifndef DBUG_OFF
- {"debug", optional_argument, 0, '#'},
+ {"debug", "Output debug log. Often this is 'd:t:o,filename'.", 0, 0, 0,
+ GET_STR, OPT_ARG, '#', 0, 0, 0, 0, 0, 0},
#endif
- {"description", no_argument, 0, 'd'},
- {"data-file-length", required_argument, 0, 'D'},
- {"extend-check", no_argument, 0, 'e'},
- {"fast", no_argument, 0, 'F'},
- {"force", no_argument, 0, 'f'},
- {"help", no_argument, 0, '?'},
- {"information", no_argument, 0, 'i'},
- {"keys-used", required_argument, 0, 'k'},
- {"medium-check", no_argument, 0, 'm'},
- {"no-symlinks", no_argument, 0, 'l'},
- {"quick", no_argument, 0, 'q'},
- {"read-only", no_argument, 0, 'T'},
- {"recover", no_argument, 0, 'r'},
- {"safe-recover", no_argument, 0, 'o'},
- {"start-check-pos", required_argument, 0, OPT_START_CHECK_POS},
- {"set-auto-increment",optional_argument, 0, 'A'},
- {"set-character-set",required_argument,0,OPT_SET_CHARSET},
- {"set-variable", required_argument, 0, 'O'},
- {"silent", no_argument, 0, 's'},
- {"sort-index", no_argument, 0, 'S'},
- {"sort-records", required_argument, 0, 'R'},
- {"sort-recover", no_argument, 0, 'n'},
- {"tmpdir", required_argument, 0, 't'},
- {"update-state", no_argument, 0, 'U'},
- {"unpack", no_argument, 0, 'u'},
- {"verbose", no_argument, 0, 'v'},
- {"version", no_argument, 0, 'V'},
- {"wait", no_argument, 0, 'w'},
- {0, 0, 0, 0}
+ {"description", "Prints some information about table.", 0, 0, 0, GET_NO_ARG,
+ NO_ARG, 'd', 0, 0, 0, 0, 0, 0},
+ {"data-file-length",
+ "Max length of data file (when recreating data-file when it's full).",
+ (gptr*) &check_param.max_data_file_length,
+ (gptr*) &check_param.max_data_file_length, 0, GET_LONG, REQUIRED_ARG, 'D',
+ 0, 0, 0, 0, 0, 0},
+ {"extend-check",
+ "Try to recover every possible row from the data file. Normally this will also find a lot of garbage rows; Don't use this option if you are not totally desperate.", 0, 0, 0, GET_NO_ARG, NO_ARG, 'e', 0, 0, 0, 0, 0, 0},
+ {"fast", "Check only tables that hasn't been closed properly.", 0, 0, 0,
+ GET_NO_ARG, NO_ARG, 'F', 0, 0, 0, 0, 0, 0},
+ {"force",
+ "Restart with -r if there are any errors in the table. States will be updated as with --update-state.", 0, 0, 0, GET_NO_ARG, NO_ARG, 'f', 0, 0, 0, 0, 0,
+ 0},
+ {"help", "Display this help and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG, '?', 0,
+ 0, 0, 0, 0, 0},
+ {"information", "Print statistics information about table that is checked.",
+ 0, 0, 0, GET_NO_ARG, NO_ARG, 'i', 0, 0, 0, 0, 0, 0},
+ {"keys-used", "Tell MyISAM to update only some specific keys. # is a bit mask of which keys to use. This can be used to get faster inserts!",
+ (gptr*) &check_param.keys_in_use, (gptr*) &check_param.keys_in_use, 0,
+ GET_LL, REQUIRED_ARG, 'k', -1LL, 0, 0, 0, 0, 0},
+ {"medium-check",
+ "Faster than extended-check, but only finds 99.99% of all errors. Should be good enough for most cases.", 0, 0, 0, GET_NO_ARG, NO_ARG, 'm', 0, 0, 0, 0, 0,
+ 0},
+ {"quick", "Faster repair by not modifying the data file.", 0, 0, 0,
+ GET_NO_ARG, NO_ARG, 'q', 0, 0, 0, 0, 0, 0},
+ {"read-only", "Don't mark table as checked.", 0, 0, 0, GET_NO_ARG, NO_ARG,
+ 'T', 0, 0, 0, 0, 0, 0},
+ {"recover",
+ "Can fix almost anything except unique keys that aren't unique.", 0, 0, 0,
+ GET_NO_ARG, NO_ARG, 'r', 0, 0, 0, 0, 0, 0},
+ {"safe-recover",
+ "Uses old recovery method; Slower than '-r' but can handle a couple of cases where '-r' reports that it can't fix the data file.", 0, 0, 0, GET_NO_ARG,
+ NO_ARG, 'o', 0, 0, 0, 0, 0, 0},
+ {"start-check-pos", "No help available.", 0, 0, 0, GET_LONG, REQUIRED_ARG,
+ OPT_START_CHECK_POS, 0, 0, 0, 0, 0, 0},
+ {"set-auto-increment",
+ "Force auto_increment to start at this or higher value. If no value is given, then sets the next auto_increment value to the highest used value for the auto key + 1.", (gptr*) &check_param.auto_increment_value,
+ (gptr*) &check_param.auto_increment_value, 0, GET_LONG, OPT_ARG, 'A', 0, 0,
+ 0, 0, 0, 0},
+ {"set-character-set", "Change the character set used by the index", 0, 0, 0,
+ GET_STR, REQUIRED_ARG, OPT_SET_CHARSET, 0, 0, 0, 0, 0, 0},
+ {"set-variable", "Change the value of a variable. Please note that this option is depricated; you can set variables directly with --variable-name=value.",
+ 0, 0, 0, GET_STR, REQUIRED_ARG, 'O', 0, 0, 0, 0, 0, 0},
+ {"silent",
+ "Only print errors. One can use two -s to make myisamchk very silent.", 0,
+ 0, 0, GET_NO_ARG, NO_ARG, 's', 0, 0, 0, 0, 0, 0},
+ {"sort-index",
+ "Sort index blocks. This speeds up 'read-next' in applications.", 0, 0, 0,
+ GET_NO_ARG, NO_ARG, 'S', 0, 0, 0, 0, 0, 0},
+ {"sort-records",
+ "Sort records according to an index. This makes your data much more localized and may speed up things. (It may be VERY slow to do a sort the first time!)",
+ (gptr*) &check_param.opt_sort_key, (gptr*) &check_param.opt_sort_key, 0,
+ GET_LONG, REQUIRED_ARG, 'R', 0, 0, 0, 0, 0, 0},
+ {"sort-recover",
+ "Force recovering with sorting even if the temporary file was very big.",
+ 0, 0, 0, GET_NO_ARG, NO_ARG, 'n', 0, 0, 0, 0, 0, 0},
+ {"tmpdir", "Path for temporary files.", (gptr*) &check_param.tmpdir, 0, 0,
+ GET_STR, REQUIRED_ARG, 't', 0, 0, 0, 0, 0, 0},
+ {"update-state", "Mark tables as crashed if any errors were found.", 0, 0,
+ 0, GET_NO_ARG, NO_ARG, 'U', 0, 0, 0, 0, 0, 0},
+ {"unpack", "Unpack file packed with myisampack.", 0, 0, 0, GET_NO_ARG,
+ NO_ARG, 'u', 0, 0, 0, 0, 0, 0},
+ {"verbose",
+ "Print more information. This can be used with --describe and --check. Use many -v for more verbosity!", 0, 0, 0, GET_NO_ARG, NO_ARG, 'v', 0, 0, 0, 0, 0,
+ 0},
+ {"version", "Print version and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG, 'V', 0,
+ 0, 0, 0, 0, 0},
+ {"wait", "Wait if table is locked.", 0, 0, 0, GET_NO_ARG, NO_ARG, 'w', 0, 0,
+ 0, 0, 0, 0},
+ { "key_buffer_size", "", (gptr*) &check_param.use_buffers,
+ (gptr*) &check_param.use_buffers, 0, GET_LONG, REQUIRED_ARG,
+ OPT_KEY_BUFFER_SIZE, (long) USE_BUFFER_INIT, (long) MALLOC_OVERHEAD,
+ (long) ~0L, (long) MALLOC_OVERHEAD, (long) IO_SIZE, 0},
+ { "myisam_block_size", "", (gptr*) &opt_myisam_block_size,
+ (gptr*) &opt_myisam_block_size, 0, GET_LONG, REQUIRED_ARG,
+ OPT_MYISAM_BLOCK_SIZE, MI_KEY_BLOCK_LENGTH, MI_MIN_KEY_BLOCK_LENGTH,
+ MI_MAX_KEY_BLOCK_LENGTH, 0, MI_MIN_KEY_BLOCK_LENGTH, 0},
+ { "read_buffer_size", "", (gptr*) &check_param.read_buffer_length,
+ (gptr*) &check_param.read_buffer_length, 0, GET_LONG, REQUIRED_ARG,
+ OPT_READ_BUFFER_SIZE, (long) READ_BUFFER_INIT, (long) MALLOC_OVERHEAD,
+ (long) ~0L, (long) MALLOC_OVERHEAD, (long) 1L, 0},
+ { "write_buffer_size", "", (gptr*) &check_param.write_buffer_length,
+ (gptr*) &check_param.write_buffer_length, 0, GET_LONG, REQUIRED_ARG,
+ OPT_WRITE_BUFFER_SIZE, (long) READ_BUFFER_INIT, (long) MALLOC_OVERHEAD,
+ (long) ~0L, (long) MALLOC_OVERHEAD, (long) 1L, 0},
+ { "sort_buffer_size", "", (gptr*) &check_param.sort_buffer_length,
+ (gptr*) &check_param.sort_buffer_length, 0, GET_LONG, REQUIRED_ARG,
+ OPT_SORT_BUFFER_SIZE, (long) SORT_BUFFER_INIT,
+ (long) (MIN_SORT_BUFFER + MALLOC_OVERHEAD), (long) ~0L,
+ (long) MALLOC_OVERHEAD, (long) 1L, 0},
+ { "sort_key_blocks", "", (gptr*) &check_param.sort_key_blocks,
+ (gptr*) &check_param.sort_key_blocks, 0, GET_LONG, REQUIRED_ARG,
+ OPT_SORT_KEY_BLOCKS, BUFFERS_WHEN_SORTING, 4L, 100L, 0L, 1L, 0},
+ { "decode_bits", "", (gptr*) &decode_bits, (gptr*) &decode_bits, 0,
+ GET_LONG, REQUIRED_ARG, OPT_DECODE_BITS, 9L, 4L, 17L, 0L, 1L, 0},
+ { "ft_min_word_len", "", (gptr*) &ft_min_word_len, (gptr*) &ft_min_word_len,
+ 0, GET_LONG, REQUIRED_ARG, OPT_FT_MIN_WORD_LEN, 4, 1, HA_FT_MAXLEN, 0, 1,
+ 0},
+ { "ft_max_word_len", "", (gptr*) &ft_max_word_len, (gptr*) &ft_max_word_len,
+ 0, GET_LONG, REQUIRED_ARG, OPT_FT_MAX_WORD_LEN, HA_FT_MAXLEN, 10,
+ HA_FT_MAXLEN, 0, 1, 0},
+ { "ft_max_word_len_for_sort", "", (gptr*) &ft_max_word_len_for_sort,
+ (gptr*) &ft_max_word_len_for_sort, 0, GET_LONG, REQUIRED_ARG,
+ OPT_FT_MAX_WORD_LEN_FOR_SORT, 20, 4, HA_FT_MAXLEN, 0, 1, 0},
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
};
+
static void print_version(void)
{
- printf("%s Ver 1.53 for %s at %s\n",my_progname,SYSTEM_TYPE,
+ printf("%s Ver 2.3 for %s at %s\n", my_progname, SYSTEM_TYPE,
MACHINE_TYPE);
}
+
static void usage(void)
{
- uint i;
print_version();
puts("By Monty, for your professional use");
puts("This software comes with NO WARRANTY: see the PUBLIC for details.\n");
@@ -247,6 +327,7 @@ static void usage(void)
puts("Repair options (When using -r or -o) \n\
-B, --backup Make a backup of the .MYD file as 'filename-time.BAK'\n\
+ --correct-checksum Correct checksum information for table.\n\
-D, --data-file-length=# Max length of data file (when recreating data\n\
file when it's full)\n\
-e, --extend-check Try to recover every possible row from the data file\n\
@@ -256,8 +337,6 @@ static void usage(void)
-k, --keys-used=# Tell MyISAM to update only some specific keys. # is a\n\
bit mask of which keys to use. This can be used to\n\
get faster inserts!\n\
- -l, --no-symlinks Do not follow symbolic links. Normally\n\
- myisamchk repairs the table a symlink points at.\n\
-r, --recover Can fix almost anything except unique keys that aren't\n\
unique.\n\
-n, --sort-recover Force recovering with sorting even if the temporary\n\
@@ -292,124 +371,181 @@ static void usage(void)
data much more localized and may speed up things\n\
(It may be VERY slow to do a sort the first time!)");
- print_defaults("my",load_default_groups);
- printf("\nPossible variables for option --set-variable (-O) are:\n");
- for (i=0; changeable_vars[i].name ; i++)
- printf("%-20s current value: %lu\n",
- changeable_vars[i].name,
- *changeable_vars[i].varptr);
+ print_defaults("my", load_default_groups);
+ putchar('\n');
+ my_print_variables(my_long_options);
}
/* Read options */
-static void get_options(register int *argc,register char ***argv)
+static my_bool
+get_one_option(int optid,
+ const struct my_option *opt __attribute__((unused)),
+ char *argument)
{
- int c,option_index=0;
- uint old_testflag;
-
- load_defaults("my",load_default_groups,argc,argv);
- default_argv= *argv;
- set_all_changeable_vars(changeable_vars);
- if (isatty(fileno(stdout)))
- check_param.testflag|=T_WRITE_LOOP;
- while ((c=getopt_long(*argc,*argv,
- "aBcCdeifF?lqrmnosSTuUvVw#:b:D:k:O:R:A::t:",
- long_options, &option_index)) != EOF)
- {
- switch(c) {
- case 'a':
+ switch (optid) {
+ case 'a':
+ if (argument && *argument == '0')
+ check_param.testflag&= ~T_STATISTICS;
+ else
check_param.testflag|= T_STATISTICS;
- break;
- case 'A':
- if (optarg)
- check_param.auto_increment_value=strtoull(optarg,NULL,0);
- else
- check_param.auto_increment_value=0; /* Set to max used value */
- check_param.testflag|= T_AUTO_INC;
- break;
- case 'b':
- check_param.search_after_block=strtoul(optarg,NULL,10);
- break;
- case 'B':
+ break;
+ case 'A':
+ if (argument)
+ check_param.auto_increment_value= strtoull(argument, NULL, 0);
+ else
+ check_param.auto_increment_value= 0; /* Set to max used value */
+ check_param.testflag|= T_AUTO_INC;
+ break;
+ case 'b':
+ check_param.search_after_block= strtoul(argument, NULL, 10);
+ break;
+ case 'B':
+ if (argument && *argument == '0')
+ check_param.testflag&= ~T_BACKUP_DATA;
+ else
check_param.testflag|= T_BACKUP_DATA;
- break;
- case 'c':
+ break;
+ case 'c':
+ if (argument && *argument == '0')
+ check_param.testflag&= ~T_CHECK;
+ else
check_param.testflag|= T_CHECK;
- break;
- case 'C':
+ break;
+ case 'C':
+ if (argument && *argument == '0')
+ check_param.testflag&= ~(T_CHECK | T_CHECK_ONLY_CHANGED);
+ else
check_param.testflag|= T_CHECK | T_CHECK_ONLY_CHANGED;
- break;
- case 'D':
- check_param.max_data_file_length=strtoll(optarg,NULL,10);
- break;
- case 's': /* silent */
+ break;
+ case 'D':
+ check_param.max_data_file_length=strtoll(argument, NULL, 10);
+ break;
+ case 's': /* silent */
+ if (argument && *argument == '0')
+ check_param.testflag&= ~(T_SILENT | T_VERY_SILENT);
+ else
+ {
if (check_param.testflag & T_SILENT)
- check_param.testflag|=T_VERY_SILENT;
+ check_param.testflag|= T_VERY_SILENT;
check_param.testflag|= T_SILENT;
check_param.testflag&= ~T_WRITE_LOOP;
- break;
- case 'w':
+ }
+ break;
+ case 'w':
+ if (argument && *argument == '0')
+ check_param.testflag&= ~T_WAIT_FOREVER;
+ else
check_param.testflag|= T_WAIT_FOREVER;
- break;
- case 'd': /* description if isam-file */
+ break;
+ case 'd': /* description if isam-file */
+ if (argument && *argument == '0')
+ check_param.testflag&= ~T_DESCRIPT;
+ else
check_param.testflag|= T_DESCRIPT;
- break;
- case 'e': /* extend check */
+ break;
+ case 'e': /* extend check */
+ if (argument && *argument == '0')
+ check_param.testflag&= ~T_EXTEND;
+ else
check_param.testflag|= T_EXTEND;
- break;
- case 'i':
+ break;
+ case 'i':
+ if (argument && *argument == '0')
+ check_param.testflag&= ~T_INFO;
+ else
check_param.testflag|= T_INFO;
- break;
- case 'f':
+ break;
+ case 'f':
+ if (argument && *argument == '0')
+ {
+ check_param.tmpfile_createflag= O_RDWR | O_TRUNC | O_EXCL;
+ check_param.testflag&= ~(T_FORCE_CREATE | T_UPDATE_STATE);
+ }
+ else
+ {
check_param.tmpfile_createflag= O_RDWR | O_TRUNC;
check_param.testflag|= T_FORCE_CREATE | T_UPDATE_STATE;
- break;
- case 'F':
- check_param.testflag|=T_FAST;
- break;
- case 'k':
- check_param.keys_in_use= (ulonglong) strtoll(optarg,NULL,10);
- break;
- case 'l':
- check_param.opt_follow_links=0;
- break;
- case 'm':
+ }
+ break;
+ case 'F':
+ if (argument && *argument == '0')
+ check_param.testflag&= ~T_FAST;
+ else
+ check_param.testflag|= T_FAST;
+ break;
+ case 'k':
+ check_param.keys_in_use= (ulonglong) strtoll(argument, NULL, 10);
+ break;
+ case 'm':
+ if (argument && *argument == '0')
+ check_param.testflag&= ~T_MEDIUM;
+ else
check_param.testflag|= T_MEDIUM; /* Medium check */
- break;
- case 'r': /* Repair table */
+ break;
+ case 'r': /* Repair table */
+ if (argument && *argument == '0')
+ check_param.testflag&= ~(T_REP | T_REP_BY_SORT);
+ else
check_param.testflag= (check_param.testflag & ~T_REP) | T_REP_BY_SORT;
- break;
- case 'o':
+ break;
+ case 'o':
+ if (argument && *argument == '0')
+ {
+ check_param.testflag&= ~(T_REP | T_REP_BY_SORT);
+ check_param.force_sort= 0;
+ }
+ else
+ {
check_param.testflag= (check_param.testflag & ~T_REP_BY_SORT) | T_REP;
- check_param.force_sort=0;
- my_disable_async_io=1; /* More safety */
- break;
- case 'n':
+ check_param.force_sort= 0;
+ my_disable_async_io= 1; /* More safety */
+ }
+ break;
+ case 'n':
+ if (argument && *argument == '0')
+ {
+ check_param.testflag&= ~(T_REP | T_REP_BY_SORT);
+ check_param.force_sort= 0;
+ }
+ else
+ {
check_param.testflag= (check_param.testflag & ~T_REP) | T_REP_BY_SORT;
- check_param.force_sort=1;
- break;
- case 'q':
+ check_param.force_sort= 1;
+ }
+ break;
+ case 'q':
+ if (argument && *argument == '0')
+ check_param.opt_rep_quick=0;
+ else
check_param.opt_rep_quick++;
- break;
- case 'u':
+ break;
+ case 'u':
+ if (argument && *argument == '0')
+ check_param.testflag&= ~(T_UNPACK | T_REP_BY_SORT);
+ else
check_param.testflag|= T_UNPACK | T_REP_BY_SORT;
- break;
- case 'v': /* Verbose */
+ break;
+ case 'v': /* Verbose */
+ if (argument && *argument == '0')
+ {
+ check_param.testflag&= ~T_VERBOSE;
+ check_param.verbose=0;
+ }
+ else
+ {
check_param.testflag|= T_VERBOSE;
check_param.verbose++;
- break;
- case 'O':
- if (set_changeable_var(optarg, changeable_vars))
- {
- usage();
- exit(1);
- }
- break;
- case 'R': /* Sort records */
- old_testflag=check_param.testflag;
+ }
+ break;
+ case 'R': /* Sort records */
+ if (argument && *argument == '0')
+ check_param.testflag&= ~T_SORT_RECORDS;
+ else
+ {
check_param.testflag|= T_SORT_RECORDS;
- check_param.opt_sort_key=(uint) atoi(optarg)-1;
+ check_param.opt_sort_key= (uint) atoi(argument) - 1;
if (check_param.opt_sort_key >= MI_MAX_KEY)
{
fprintf(stderr,
@@ -417,49 +553,79 @@ static void get_options(register int *argc,register char ***argv)
MI_MAX_KEY);
exit(1);
}
- break;
- case 'S': /* Sort index */
- old_testflag=check_param.testflag;
+ }
+ break;
+ case 'S': /* Sort index */
+ if (argument && *argument == '0')
+ check_param.testflag&= ~T_SORT_INDEX;
+ else
check_param.testflag|= T_SORT_INDEX;
- break;
- case 't':
- check_param.tmpdir=optarg;
- break;
- case 'T':
+ break;
+ case 'T':
+ if (argument && *argument == '0')
+ check_param.testflag&= ~T_READONLY;
+ else
check_param.testflag|= T_READONLY;
- break;
- case 'U':
+ break;
+ case 'U':
+ if (argument && *argument == '0')
+ check_param.testflag&= ~T_UPDATE_STATE;
+ else
check_param.testflag|= T_UPDATE_STATE;
- break;
- case '#':
- DBUG_PUSH(optarg ? optarg : "d:t:o,/tmp/myisamchk.trace");
- break;
- case 'V':
- print_version();
- exit(0);
- case OPT_CHARSETS_DIR:
- charsets_dir = optarg;
- break;
- case OPT_SET_CHARSET:
- set_charset_name=optarg;
- break;
+ break;
+ case '#':
+ if (argument && *argument == '0')
+ {
+ DBUG_POP();
+ }
+ else
+ {
+ DBUG_PUSH(argument ? argument : "d:t:o,/tmp/myisamchk.trace");
+ }
+ break;
+ case 'V':
+ print_version();
+ exit(0);
+ case OPT_CORRECT_CHECKSUM:
+ if (argument && *argument == '0')
+ check_param.testflag&= ~T_CALC_CHECKSUM;
+ else
+ check_param.testflag|= T_CALC_CHECKSUM;
+ break;
#ifdef DEBUG /* Only useful if debugging */
- case OPT_START_CHECK_POS:
- check_param.start_check_pos=strtoull(optarg,NULL,0);
- break;
+ case OPT_START_CHECK_POS:
+ check_param.start_check_pos= strtoull(argument, NULL, 0);
+ break;
#endif
- case '?':
- usage();
- exit(0);
- }
+ case '?':
+ usage();
+ exit(0);
}
- (*argc)-=optind;
- (*argv)+=optind;
+ return 0;
+}
+
+
+static void get_options(register int *argc,register char ***argv)
+{
+ load_defaults("my", load_default_groups, argc, argv);
+ default_argv= *argv;
+ if (isatty(fileno(stdout)))
+ check_param.testflag|=T_WRITE_LOOP;
+
+ if (handle_options(argc, argv, my_long_options, get_one_option))
+ exit(1);
+
+ /* If using repair, then update checksum if one uses --update-state */
+ if ((check_param.testflag & T_UPDATE_STATE) &&
+ (check_param.testflag & (T_REP | T_REP_BY_SORT)))
+ check_param.testflag|= T_CALC_CHECKSUM;
+
if (*argc == 0)
{
usage();
exit(-1);
}
+
if ((check_param.testflag & T_UNPACK) &&
(check_param.opt_rep_quick || (check_param.testflag & T_SORT_RECORDS)))
{
@@ -483,6 +649,7 @@ static void get_options(register int *argc,register char ***argv)
if (!(set_charset=get_charset_by_name(set_charset_name, MYF(MY_WME))))
exit(1);
+ myisam_block_size=(uint) 1 << my_bit_log2(opt_myisam_block_size);
return;
} /* get options */
@@ -496,7 +663,6 @@ static int myisamchk(MI_CHECK *param, my_string filename)
uint raid_chunks;
MI_INFO *info;
File datafile;
- char fixed_name[FN_REFLEN];
char llbuff[22],llbuff2[22];
my_bool state_updated=0;
MYISAM_SHARE *share;
@@ -610,7 +776,8 @@ static int myisamchk(MI_CHECK *param, my_string filename)
(((ulonglong) 1L << share->base.keys)-1)) ||
test_if_almost_full(info) ||
info->s->state.header.file_version[3] != myisam_file_magic[3] ||
- (set_charset && set_charset->number != share->state.header.language)))
+ (set_charset && set_charset->number != share->state.header.language) ||
+ myisam_block_size != MI_KEY_BLOCK_LENGTH))
{
if (set_charset)
check_param.language=set_charset->number;
@@ -674,9 +841,6 @@ static int myisamchk(MI_CHECK *param, my_string filename)
if (tmp != share->state.key_map)
info->update|=HA_STATE_CHANGED;
}
- VOID(fn_format(fixed_name,filename,"",MI_NAME_IEXT,
- 4+ (param->opt_follow_links ? 16 : 0)));
-
if (rep_quick && chk_del(&check_param, info,
param->testflag & ~T_VERBOSE))
{
@@ -701,11 +865,11 @@ static int myisamchk(MI_CHECK *param, my_string filename)
info->s->state.key_map,
check_param.force_sort))
{
- error=mi_repair_by_sort(&check_param,info,fixed_name,rep_quick);
+ error=mi_repair_by_sort(&check_param,info,filename,rep_quick);
state_updated=1;
}
else if (param->testflag & (T_REP | T_REP_BY_SORT))
- error=mi_repair(&check_param, info,fixed_name,rep_quick);
+ error=mi_repair(&check_param, info,filename,rep_quick);
}
if (!error && param->testflag & T_SORT_RECORDS)
{
@@ -717,10 +881,10 @@ static int myisamchk(MI_CHECK *param, my_string filename)
if (param->out_flag & O_NEW_DATA)
{ /* Change temp file to org file */
VOID(my_close(info->dfile,MYF(MY_WME))); /* Close new file */
- error|=change_to_newfile(fixed_name,MI_NAME_DEXT,DATA_TMP_EXT,
+ error|=change_to_newfile(filename,MI_NAME_DEXT,DATA_TMP_EXT,
raid_chunks,
MYF(0));
- if (mi_open_datafile(info,info->s))
+ if (mi_open_datafile(info,info->s, -1))
error=1;
param->out_flag&= ~O_NEW_DATA; /* We are using new datafile */
param->read_cache.file=info->dfile;
@@ -738,7 +902,7 @@ static int myisamchk(MI_CHECK *param, my_string filename)
if (share->keyinfo[key].flag & HA_BINARY_PACK_KEY)
update_index=0;
- error=mi_sort_records(param,info,fixed_name,param->opt_sort_key,
+ error=mi_sort_records(param,info,filename,param->opt_sort_key,
(my_bool) !(param->testflag & T_REP),
update_index);
datafile=info->dfile; /* This is now locked */
@@ -746,12 +910,12 @@ static int myisamchk(MI_CHECK *param, my_string filename)
{
if (check_param.verbose)
puts("Table had a compressed index; We must now recreate the index");
- error=mi_repair_by_sort(&check_param,info,fixed_name,1);
+ error=mi_repair_by_sort(&check_param,info,filename,1);
}
}
}
if (!error && param->testflag & T_SORT_INDEX)
- error=mi_sort_index(param,info,fixed_name);
+ error=mi_sort_index(param,info,filename);
if (!error)
share->state.changed&= ~(STATE_CHANGED | STATE_CRASHED |
STATE_CRASHED_ON_REPAIR);
@@ -786,7 +950,7 @@ static int myisamchk(MI_CHECK *param, my_string filename)
!(param->testflag & (T_FAST | T_FORCE_CREATE)))
{
if (param->testflag & (T_EXTEND | T_MEDIUM))
- VOID(init_key_cache(param->use_buffers,(uint) NEAD_MEM));
+ VOID(init_key_cache(param->use_buffers,(uint) NEED_MEM));
VOID(init_io_cache(&param->read_cache,datafile,
(uint) param->read_buffer_length,
READ_CACHE,
@@ -848,12 +1012,12 @@ end2:
if (error == 0)
{
if (param->out_flag & O_NEW_DATA)
- error|=change_to_newfile(fixed_name,MI_NAME_DEXT,DATA_TMP_EXT,
+ error|=change_to_newfile(filename,MI_NAME_DEXT,DATA_TMP_EXT,
raid_chunks,
((param->testflag & T_BACKUP_DATA) ?
MYF(MY_REDEL_MAKE_BACKUP) : MYF(0)));
if (param->out_flag & O_NEW_INDEX)
- error|=change_to_newfile(fixed_name,MI_NAME_IEXT,INDEX_TMP_EXT,0,
+ error|=change_to_newfile(filename,MI_NAME_IEXT,INDEX_TMP_EXT,0,
MYF(0));
}
VOID(fflush(stdout)); VOID(fflush(stderr));
@@ -1193,7 +1357,7 @@ static int mi_sort_records(MI_CHECK *param,
if (share->state.key_root[sort_key] == HA_OFFSET_ERROR)
DBUG_RETURN(0); /* Nothing to do */
- init_key_cache(param->use_buffers,NEAD_MEM);
+ init_key_cache(param->use_buffers,NEED_MEM);
if (init_io_cache(&info->rec_cache,-1,(uint) param->write_buffer_length,
WRITE_CACHE,share->pack.header_length,1,
MYF(MY_WME | MY_WAIT_IF_FULL)))
@@ -1211,7 +1375,9 @@ static int mi_sort_records(MI_CHECK *param,
mi_check_print_error(param,"Not enough memory for record");
goto err;
}
- new_file=my_raid_create(fn_format(param->temp_filename,name,"",
+ fn_format(param->temp_filename,name,"", MI_NAME_DEXT,2+4+32);
+ new_file=my_raid_create(fn_format(param->temp_filename,
+ param->temp_filename,"",
DATA_TMP_EXT,2+4),
0,param->tmpfile_createflag,
share->base.raid_type,
diff --git a/myisam/myisamdef.h b/myisam/myisamdef.h
index 260e9665b31..e9d3461fe9a 100644
--- a/myisam/myisamdef.h
+++ b/myisam/myisamdef.h
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -18,6 +18,7 @@
#include "myisam.h" /* Structs & some defines */
#include "myisampack.h" /* packing of keys */
+#include <my_tree.h>
#ifdef THREAD
#include <my_pthread.h>
#include <thr_lock.h>
@@ -37,7 +38,7 @@ typedef struct st_mi_status_info
my_off_t key_empty; /* lost space in indexfile */
my_off_t key_file_length;
my_off_t data_file_length;
-} MI_STATUS_INFO;
+} MI_STATUS_INFO;
typedef struct st_mi_state_info
{
@@ -65,8 +66,10 @@ typedef struct st_mi_state_info
ulong unique; /* Unique number for this process */
ulong update_count; /* Updated for each write lock */
ulong status;
+ ulong *rec_per_key_part;
my_off_t *key_root; /* Start of key trees */
my_off_t *key_del; /* delete links for trees */
+ my_off_t rec_per_key_rows; /* Rows when calculating rec_per_key */
ulong sec_index_changed; /* Updated when new sec_index */
ulong sec_index_used; /* which extra index are in use */
@@ -79,8 +82,6 @@ typedef struct st_mi_state_info
uint sortkey; /* sorted by this key (not used) */
uint open_count;
uint8 changed; /* Changed since myisamchk */
- my_off_t rec_per_key_rows; /* Rows when calculating rec_per_key */
- ulong *rec_per_key_part;
/* the following isn't saved on disk */
uint state_diff_length; /* Should be 0 */
@@ -159,42 +160,45 @@ typedef struct st_mi_isam_share { /* Shared between opens */
MI_COLUMNDEF *rec; /* Pointer to field information */
MI_PACK pack; /* Data about packed records */
MI_BLOB *blobs; /* Pointer to blobs */
- char *filename; /* Name of indexfile */
+ char *unique_file_name; /* realpath() of index file */
+ char *data_file_name, /* Resolved path names from symlinks */
+ *index_file_name;
byte *file_map; /* mem-map of file if possible */
+ MI_DECODE_TREE *decode_trees;
+ uint16 *decode_tables;
+ int (*read_record)(struct st_myisam_info*, my_off_t, byte*);
+ int (*write_record)(struct st_myisam_info*, const byte*);
+ int (*update_record)(struct st_myisam_info*, my_off_t, const byte*);
+ int (*delete_record)(struct st_myisam_info*);
+ int (*read_rnd)(struct st_myisam_info*, byte*, my_off_t, my_bool);
+ int (*compare_record)(struct st_myisam_info*, const byte *);
+ ha_checksum (*calc_checksum)(struct st_myisam_info*, const byte *);
+ int (*compare_unique)(struct st_myisam_info*, MI_UNIQUEDEF *,
+ const byte *record, my_off_t pos);
+ invalidator_by_filename invalidator; /* query cache invalidator */
ulong this_process; /* processid */
ulong last_process; /* For table-change-check */
ulong last_version; /* Version on start */
ulong options; /* Options used */
+ ulong min_pack_length; /* Theese are used by packed data */
+ ulong max_pack_length;
+ ulong state_diff_length;
uint rec_reflength; /* rec_reflength in use now */
- int kfile; /* Shared keyfile */
- int data_file; /* Shared data file */
+ File kfile; /* Shared keyfile */
+ File data_file; /* Shared data file */
int mode; /* mode of file on open */
uint reopen; /* How many times reopened */
- uint w_locks,r_locks; /* Number of read/write locks */
+ uint w_locks,r_locks,tot_locks; /* Number of read/write locks */
uint blocksize; /* blocksize of keyfile */
- ulong min_pack_length; /* Theese are used by packed data */
- ulong max_pack_length;
- ulong state_diff_length;
+ myf write_flag;
+ int rnd; /* rnd-counter */
+ enum data_file_type data_file_type;
my_bool changed, /* If changed since lock */
global_changed, /* If changed since open */
not_flushed,
temporary,delay_key_write,
concurrent_insert,
fulltext_index;
- myf write_flag;
- int rnd; /* rnd-counter */
- MI_DECODE_TREE *decode_trees;
- uint16 *decode_tables;
- enum data_file_type data_file_type;
- int (*read_record)(struct st_myisam_info*, my_off_t, byte*);
- int (*write_record)(struct st_myisam_info*, const byte*);
- int (*update_record)(struct st_myisam_info*, my_off_t, const byte*);
- int (*delete_record)(struct st_myisam_info*);
- int (*read_rnd)(struct st_myisam_info*, byte*, my_off_t, my_bool);
- int (*compare_record)(struct st_myisam_info*, const byte *);
- ha_checksum (*calc_checksum)(struct st_myisam_info*, const byte *);
- int (*compare_unique)(struct st_myisam_info*, MI_UNIQUEDEF *,
- const byte *record, my_off_t pos);
#ifdef THREAD
THR_LOCK lock;
pthread_mutex_t intern_lock; /* Locking for use with _locking */
@@ -212,16 +216,22 @@ typedef struct st_mi_bit_buff { /* Used for packing of record */
uint error;
} MI_BIT_BUFF;
-
struct st_myisam_info {
MYISAM_SHARE *s; /* Shared between open:s */
MI_STATUS_INFO *state,save_state;
MI_BLOB *blobs; /* Pointer to blobs */
- int dfile; /* The datafile */
- MI_BIT_BUFF bit_buff;
- uint opt_flag; /* Optim. for space/speed */
- uint update; /* If file changed since open */
+ MI_BIT_BUFF bit_buff;
+ /* accumulate indexfile changes between write's */
+ TREE *bulk_insert;
char *filename; /* parameter to open filename */
+ uchar *buff, /* Temp area for key */
+ *lastkey,*lastkey2; /* Last used search key */
+ byte *rec_buff, /* Tempbuff for recordpack */
+ *rec_alloc; /* Malloced area for record */
+ uchar *int_keypos, /* Save position for next/previous */
+ *int_maxpos; /* -""- */
+ int (*read_record)(struct st_myisam_info*, my_off_t, byte*);
+ invalidator_by_filename invalidator; /* query cache invalidator */
ulong this_unique; /* uniq filenumber or thread */
ulong last_unique; /* last unique number */
ulong this_loop; /* counter for this open */
@@ -230,20 +240,16 @@ struct st_myisam_info {
nextpos; /* Position to next record */
my_off_t save_lastpos;
my_off_t pos; /* Intern variable */
+ my_off_t last_keypage; /* Last key page read */
+ my_off_t last_search_keypage; /* Last keypage when searching */
+ my_off_t dupp_key_pos;
ha_checksum checksum;
ulong packed_length,blob_length; /* Length of found, packed record */
+ int dfile; /* The datafile */
+ uint opt_flag; /* Optim. for space/speed */
+ uint update; /* If file changed since open */
uint alloced_rec_buff_length; /* Max recordlength malloced */
- uchar *buff, /* Temp area for key */
- *lastkey,*lastkey2; /* Last used search key */
- byte *rec_buff, /* Tempbuff for recordpack */
- *rec_alloc; /* Malloced area for record */
- uchar *int_keypos, /* Save position for next/previous */
- *int_maxpos; /* -""- */
- uint32 int_keytree_version; /* -""- */
uint int_nod_flag; /* -""- */
- my_off_t last_keypage; /* Last key page read */
- my_off_t last_search_keypage; /* Last keypage when searching */
- my_off_t dupp_key_pos;
int lastinx; /* Last used index */
uint lastkey_length; /* Length of key in lastkey */
uint last_rkey_length; /* Last length in mi_rkey() */
@@ -254,15 +260,15 @@ struct st_myisam_info {
uint data_changed; /* Somebody has changed data */
uint save_update; /* When using KEY_READ */
int save_lastinx;
+ uint32 int_keytree_version; /* -""- */
+ LIST open_list;
+ IO_CACHE rec_cache; /* When cacheing records */
+ myf lock_wait; /* is 0 or MY_DONT_WAIT */
my_bool was_locked; /* Was locked in panic */
my_bool quick_mode;
my_bool page_changed; /* If info->buff can't be used for rnext */
my_bool buff_used; /* If info->buff has to be reread for rnext */
my_bool use_packed_key; /* For MYISAMMRG */
- myf lock_wait; /* is 0 or MY_DONT_WAIT */
- int (*read_record)(struct st_myisam_info*, my_off_t, byte*);
- LIST open_list;
- IO_CACHE rec_cache; /* When cacheing records */
#ifdef THREAD
THR_LOCK_DATA lock;
#endif
@@ -285,7 +291,7 @@ struct st_myisam_info {
#define STATE_CHANGED 1
#define STATE_CRASHED 2
-#define STATE_CRASHED_ON_REPAIR 4
+#define STATE_CRASHED_ON_REPAIR 4
#define STATE_NOT_ANALYZED 8
#define STATE_NOT_OPTIMIZED_KEYS 16
#define STATE_NOT_SORTED_PAGES 32
@@ -352,7 +358,8 @@ struct st_myisam_info {
#define MI_DYN_MAX_BLOCK_LENGTH ((1L << 24)-4L)
#define MI_DYN_MAX_ROW_LENGTH (MI_DYN_MAX_BLOCK_LENGTH - MI_SPLIT_LENGTH)
#define MI_DYN_ALIGN_SIZE 4 /* Align blocks on this */
-#define MI_MAX_DYN_HEADER_BYTE 12 /* max header byte for dynamic rows */
+#define MI_MAX_DYN_HEADER_BYTE 13 /* max header byte for dynamic rows */
+#define MI_MAX_BLOCK_LENGTH ((((ulong) 1 << 24)-1) & (~ (ulong) (MI_DYN_ALIGN_SIZE-1)))
#define MEMMAP_EXTRA_MARGIN 7 /* Write this as a suffix for file */
@@ -361,10 +368,8 @@ struct st_myisam_info {
#define PACK_TYPE_ZERO_FILL 4
#define MI_FOUND_WRONG_KEY 32738 /* Impossible value from _mi_key_cmp */
-#define MI_KEY_BLOCK_LENGTH 1024 /* Min key block length */
-#define MI_MAX_KEY_BLOCK_LENGTH 8192
-#define MI_MAX_KEY_BLOCK_SIZE (MI_MAX_KEY_BLOCK_LENGTH/MI_KEY_BLOCK_LENGTH)
-#define MI_BLOCK_SIZE(key_length,data_pointer,key_pointer) ((((key_length+data_pointer+key_pointer)*4+key_pointer+2)/MI_KEY_BLOCK_LENGTH+1)*MI_KEY_BLOCK_LENGTH)
+#define MI_MAX_KEY_BLOCK_SIZE (MI_MAX_KEY_BLOCK_LENGTH/MI_MIN_KEY_BLOCK_LENGTH)
+#define MI_BLOCK_SIZE(key_length,data_pointer,key_pointer) ((((key_length+data_pointer+key_pointer)*4+key_pointer+2)/myisam_block_size+1)*myisam_block_size)
#define MI_MAX_KEYPTR_SIZE 5 /* For calculating block lengths */
#define MI_MIN_KEYBLOCK_LENGTH 50 /* When to split delete blocks */
@@ -473,6 +478,9 @@ extern int _mi_bin_search(struct st_myisam_info *info,MI_KEYDEF *keyinfo,
extern int _mi_seq_search(MI_INFO *info,MI_KEYDEF *keyinfo,uchar *page,
uchar *key,uint key_len,uint comp_flag,
uchar **ret_pos,uchar *buff, my_bool *was_last_key);
+extern int _mi_prefix_search(MI_INFO *info,MI_KEYDEF *keyinfo,uchar *page,
+ uchar *key,uint key_len,uint comp_flag,
+ uchar **ret_pos,uchar *buff, my_bool *was_last_key);
extern int _mi_compare_text(CHARSET_INFO *, uchar *, uint, uchar *, uint ,
my_bool);
extern my_off_t _mi_kpos(uint nod_flag,uchar *after_key);
@@ -528,6 +536,8 @@ extern int _mi_read_rnd_pack_record(MI_INFO*, byte *,my_off_t, my_bool);
extern int _mi_pack_rec_unpack(MI_INFO *info,byte *to,byte *from,
ulong reclength);
extern ulonglong mi_safe_mul(ulonglong a,ulonglong b);
+extern int _mi_ft_update(MI_INFO *info, uint keynr, byte *keybuf,
+ const byte *oldrec, const byte *newrec, my_off_t pos);
struct st_sort_info;
@@ -554,7 +564,7 @@ typedef struct st_mi_block_info { /* Parameter to _mi_get_block_info */
#define BLOCK_SYNC_ERROR 16 /* Right data at wrong place */
#define BLOCK_FATAL_ERROR 32 /* hardware-error */
-#define NEAD_MEM ((uint) 10*4*(IO_SIZE+32)+32) /* Nead for recursion */
+#define NEED_MEM ((uint) 10*4*(IO_SIZE+32)+32) /* Nead for recursion */
#define MAXERR 20
#define BUFFERS_WHEN_SORTING 16 /* Alloc for sort-key-tree */
#define WRITE_COUNT MY_HOW_OFTEN_TO_WRITE
@@ -580,6 +590,9 @@ enum myisam_log_commands {
#define myisam_log_command(a,b,c,d,e) if (myisam_log_file >= 0) _myisam_log_command(a,b,c,d,e)
#define myisam_log_record(a,b,c,d,e) if (myisam_log_file >= 0) _myisam_log_record(a,b,c,d,e)
+#define fast_mi_writeinfo(INFO) if (!(INFO)->s->tot_locks) (void) _mi_writeinfo((INFO),0)
+#define fast_mi_readinfo(INFO) ((INFO)->lock_type == F_UNLCK) && _mi_readinfo((INFO),F_RDLCK,1)
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -633,14 +646,17 @@ my_bool mi_check_status(void* param);
void mi_disable_non_unique_index(MI_INFO *info, ha_rows rows);
my_bool check_table_is_closed(const char *name, const char *where);
-int mi_open_datafile(MI_INFO *info, MYISAM_SHARE *share);
+int mi_open_datafile(MI_INFO *info, MYISAM_SHARE *share, File file_to_dup);
int mi_open_keyfile(MYISAM_SHARE *share);
void mi_setup_functions(register MYISAM_SHARE *share);
-/* Functions needed by mi_check */
+int _mi_init_bulk_insert(MI_INFO *info);
+
+ /* Functions needed by mi_check */
void mi_check_print_error _VARARGS((MI_CHECK *param, const char *fmt,...));
void mi_check_print_warning _VARARGS((MI_CHECK *param, const char *fmt,...));
void mi_check_print_info _VARARGS((MI_CHECK *param, const char *fmt,...));
+int flush_pending_blocks(MI_CHECK *param);
#ifdef __cplusplus
}
diff --git a/myisam/myisamlog.c b/myisam/myisamlog.c
index ddfafb91430..2d4c7570956 100644
--- a/myisam/myisamlog.c
+++ b/myisam/myisamlog.c
@@ -56,7 +56,7 @@ extern int main(int argc,char * *argv);
static void get_options(int *argc,char ***argv);
static int examine_log(my_string file_name,char **table_names);
static int read_string(IO_CACHE *file,gptr *to,uint length);
-static int file_info_compare(void *a,void *b);
+static int file_info_compare(void *cmp_arg, void *a,void *b);
static int test_if_open(struct file_info *key,element_count count,
struct test_if_open_param *param);
static void fix_blob_pointers(MI_INFO *isam,byte *record);
@@ -331,8 +331,8 @@ static int examine_log(my_string file_name, char **table_names)
init_io_cache(&cache,file,0,READ_CACHE,start_offset,0,MYF(0));
bzero((gptr) com_count,sizeof(com_count));
- init_tree(&tree,0,sizeof(file_info),(qsort_cmp) file_info_compare,1,
- (void(*)(void*)) file_info_free);
+ init_tree(&tree,0,0,sizeof(file_info),(qsort_cmp2) file_info_compare,1,
+ (tree_element_free) file_info_free, NULL);
VOID(init_key_cache(KEY_CACHE_SIZE,(uint) (10*4*(IO_SIZE+MALLOC_OVERHEAD))));
files_open=0; access_time=0;
@@ -404,11 +404,7 @@ static int examine_log(my_string file_name, char **table_names)
}
to=isam_file_name;
if (filepath)
- {
- strmov(isam_file_name,filepath);
- convert_dirname(isam_file_name);
- to=strend(isam_file_name);
- }
+ to=convert_dirname(isam_file_name,filepath,NullS);
strmov(to,pos);
fn_ext(isam_file_name)[0]=0; /* Remove extension */
}
@@ -695,7 +691,8 @@ static int read_string(IO_CACHE *file, register gptr *to, register uint length)
} /* read_string */
-static int file_info_compare(void *a, void *b)
+static int file_info_compare(void* cmp_arg __attribute__((unused)),
+ void *a, void *b)
{
long lint;
diff --git a/myisam/myisampack.c b/myisam/myisampack.c
index 98fa8fcb377..4b78145e757 100644
--- a/myisam/myisampack.c
+++ b/myisam/myisampack.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -124,7 +124,8 @@ static void free_counts_and_tree_and_queue(HUFF_TREE *huff_trees,
uint trees,
HUFF_COUNTS *huff_counts,
uint fields);
-static int compare_tree(const uchar *s,const uchar *t);
+static int compare_tree(void* cmp_arg __attribute__((unused)),
+ const uchar *s,const uchar *t);
static int get_statistic(PACK_MRG_INFO *mrg,HUFF_COUNTS *huff_counts);
static void check_counts(HUFF_COUNTS *huff_counts,uint trees,
my_off_t records);
@@ -671,9 +672,9 @@ static HUFF_COUNTS *init_huff_count(MI_INFO *info,my_off_t records)
type = FIELD_NORMAL;
if (count[i].field_length <= 8 &&
(type == FIELD_NORMAL ||
- type == FIELD_SKIPP_ZERO))
+ type == FIELD_SKIP_ZERO))
count[i].max_zero_fill= count[i].field_length;
- init_tree(&count[i].int_tree,0,-1,(qsort_cmp) compare_tree,0,NULL);
+ init_tree(&count[i].int_tree,0,0,-1,(qsort_cmp2) compare_tree,0,NULL,NULL);
if (records && type != FIELD_BLOB && type != FIELD_VARCHAR)
count[i].tree_pos=count[i].tree_buff =
my_malloc(count[i].field_length > 1 ? tree_buff_length : 2,
@@ -795,7 +796,7 @@ static int get_statistic(PACK_MRG_INFO *mrg,HUFF_COUNTS *huff_counts)
/* Save character counters and space-counts and zero-field-counts */
if (count->field_type == FIELD_NORMAL ||
- count->field_type == FIELD_SKIPP_ENDSPACE)
+ count->field_type == FIELD_SKIP_ENDSPACE)
{
for ( ; end_pos > pos ; end_pos--)
if (end_pos[-1] != ' ')
@@ -814,7 +815,7 @@ static int get_statistic(PACK_MRG_INFO *mrg,HUFF_COUNTS *huff_counts)
count->max_end_space = length;
}
if (count->field_type == FIELD_NORMAL ||
- count->field_type == FIELD_SKIPP_PRESPACE)
+ count->field_type == FIELD_SKIP_PRESPACE)
{
for (pos=start_pos; pos < end_pos ; pos++)
if (pos[0] != ' ')
@@ -850,7 +851,7 @@ static int get_statistic(PACK_MRG_INFO *mrg,HUFF_COUNTS *huff_counts)
}
if (count->field_length <= 8 &&
(count->field_type == FIELD_NORMAL ||
- count->field_type == FIELD_SKIPP_ZERO))
+ count->field_type == FIELD_SKIP_ZERO))
{
uint i;
if (!memcmp((byte*) start_pos,zero_string,count->field_length))
@@ -955,7 +956,7 @@ static void check_counts(HUFF_COUNTS *huff_counts, uint trees,
new_length=calc_packed_length(huff_counts,0);
if (old_length < new_length && huff_counts->field_length > 1)
{
- huff_counts->field_type=FIELD_SKIPP_ZERO;
+ huff_counts->field_type=FIELD_SKIP_ZERO;
huff_counts->counts[0]-=length;
huff_counts->bytes_packed=old_length- records/8;
goto found_pack;
@@ -999,7 +1000,7 @@ static void check_counts(HUFF_COUNTS *huff_counts, uint trees,
huff_counts->counts[' ']+=huff_counts->tot_pre_space;
if (test_space_compress(huff_counts,records,huff_counts->max_end_space,
huff_counts->end_space,
- huff_counts->tot_end_space,FIELD_SKIPP_ENDSPACE))
+ huff_counts->tot_end_space,FIELD_SKIP_ENDSPACE))
goto found_pack;
huff_counts->counts[' ']-=huff_counts->tot_pre_space;
}
@@ -1007,7 +1008,7 @@ static void check_counts(HUFF_COUNTS *huff_counts, uint trees,
{
if (test_space_compress(huff_counts,records,huff_counts->max_pre_space,
huff_counts->pre_space,
- huff_counts->tot_pre_space,FIELD_SKIPP_PRESPACE))
+ huff_counts->tot_pre_space,FIELD_SKIP_PRESPACE))
goto found_pack;
}
@@ -1017,10 +1018,10 @@ static void check_counts(HUFF_COUNTS *huff_counts, uint trees,
if (huff_counts->max_zero_fill &&
(huff_counts->field_type == FIELD_NORMAL ||
- huff_counts->field_type == FIELD_SKIPP_ZERO))
+ huff_counts->field_type == FIELD_SKIP_ZERO))
{
huff_counts->counts[0]-=huff_counts->max_zero_fill*
- (huff_counts->field_type == FIELD_SKIPP_ZERO ?
+ (huff_counts->field_type == FIELD_SKIP_ZERO ?
records - huff_counts->zero_fields : records);
huff_counts->pack_type|=PACK_TYPE_ZERO_FILL;
huff_counts->bytes_packed=calc_packed_length(huff_counts,0);
@@ -1060,9 +1061,9 @@ static void check_counts(HUFF_COUNTS *huff_counts, uint trees,
if (verbose)
printf("\nnormal: %3d empty-space: %3d empty-zero: %3d empty-fill: %3d\npre-space: %3d end-space: %3d intervall-fields: %3d zero: %3d\n",
field_count[FIELD_NORMAL],space_fields,
- field_count[FIELD_SKIPP_ZERO],fill_zero_fields,
- field_count[FIELD_SKIPP_PRESPACE],
- field_count[FIELD_SKIPP_ENDSPACE],
+ field_count[FIELD_SKIP_ZERO],fill_zero_fields,
+ field_count[FIELD_SKIP_PRESPACE],
+ field_count[FIELD_SKIP_ENDSPACE],
field_count[FIELD_INTERVALL],
field_count[FIELD_ZERO]);
DBUG_VOID_RETURN;
@@ -1290,7 +1291,8 @@ static int make_huff_tree(HUFF_TREE *huff_tree, HUFF_COUNTS *huff_counts)
return 0;
}
-static int compare_tree(register const uchar *s, register const uchar *t)
+static int compare_tree(void* cmp_arg __attribute__((unused)),
+ register const uchar *s, register const uchar *t)
{
uint length;
for (length=global_count->field_length; length-- ;)
@@ -1727,7 +1729,7 @@ static int compress_isam_file(PACK_MRG_INFO *mrg, HUFF_COUNTS *huff_counts)
field_length-=count->max_zero_fill;
switch(count->field_type) {
- case FIELD_SKIPP_ZERO:
+ case FIELD_SKIP_ZERO:
if (!memcmp((byte*) start_pos,zero_string,field_length))
{
write_bits(1,1);
@@ -1741,7 +1743,7 @@ static int compress_isam_file(PACK_MRG_INFO *mrg, HUFF_COUNTS *huff_counts)
write_bits(tree->code[(uchar) *start_pos],
(uint) tree->code_len[(uchar) *start_pos]);
break;
- case FIELD_SKIPP_ENDSPACE:
+ case FIELD_SKIP_ENDSPACE:
for (pos=end_pos ; pos > start_pos && pos[-1] == ' ' ; pos--) ;
length=(uint) (end_pos-pos);
if (count->pack_type & PACK_TYPE_SELECTED)
@@ -1764,7 +1766,7 @@ static int compress_isam_file(PACK_MRG_INFO *mrg, HUFF_COUNTS *huff_counts)
(uint) tree->code_len[(uchar) *start_pos]);
start_pos=end_pos;
break;
- case FIELD_SKIPP_PRESPACE:
+ case FIELD_SKIP_PRESPACE:
for (pos=start_pos ; pos < end_pos && pos[0] == ' ' ; pos++) ;
length=(uint) (pos-start_pos);
if (count->pack_type & PACK_TYPE_SELECTED)
diff --git a/myisam/sort.c b/myisam/sort.c
index 161a5f92bf5..66a8254732a 100644
--- a/myisam/sort.c
+++ b/myisam/sort.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -19,7 +19,7 @@
them in sorted order through SORT_INFO functions.
*/
-#include "myisamdef.h"
+#include "fulltext.h"
#if defined(MSDOS) || defined(__WIN__)
#include <fcntl.h>
#else
@@ -52,10 +52,12 @@ extern void print_error _VARARGS((const char *fmt,...));
static ha_rows NEAR_F find_all_keys(MI_SORT_PARAM *info,uint keys,
uchar **sort_keys,
- BUFFPEK *buffpek,int *maxbuffer,
- IO_CACHE *tempfile);
+ DYNAMIC_ARRAY *buffpek,int *maxbuffer,
+ IO_CACHE *tempfile,
+ IO_CACHE *tempfile_for_exceptions);
static int NEAR_F write_keys(MI_SORT_PARAM *info,uchar * *sort_keys,
uint count, BUFFPEK *buffpek,IO_CACHE *tempfile);
+static int NEAR_F write_key(MI_SORT_PARAM *info, uchar *key, IO_CACHE *tempfile);
static int NEAR_F write_index(MI_SORT_PARAM *info,uchar * *sort_keys,
uint count);
static int NEAR_F merge_many_buff(MI_SORT_PARAM *info,uint keys,
@@ -70,7 +72,6 @@ static int NEAR_F merge_buffers(MI_SORT_PARAM *info,uint keys,
BUFFPEK *Fb, BUFFPEK *Tb);
static int NEAR_F merge_index(MI_SORT_PARAM *,uint,uchar **,BUFFPEK *, int,
IO_CACHE *);
-static char **make_char_array(uint fields,uint length,myf my_flag);
/* Creates a index of sorted keys */
/* Returns 0 if everything went ok */
@@ -80,15 +81,17 @@ int _create_index_by_sort(MI_SORT_PARAM *info,my_bool no_messages,
{
int error,maxbuffer,skr;
uint memavl,old_memavl,keys,sort_length;
- BUFFPEK *buffpek;
+ DYNAMIC_ARRAY buffpek;
ha_rows records;
uchar **sort_keys;
- IO_CACHE tempfile;
+ IO_CACHE tempfile, tempfile_for_exceptions;
DBUG_ENTER("_create_index_by_sort");
DBUG_PRINT("enter",("sort_length: %d", info->key_length));
my_b_clear(&tempfile);
- buffpek= (BUFFPEK *) NULL; sort_keys= (uchar **) NULL; error= 1;
+ my_b_clear(&tempfile_for_exceptions);
+ bzero((char*) &buffpek,sizeof(buffpek));
+ sort_keys= (uchar **) NULL; error= 1;
maxbuffer=1;
memavl=max(sortbuff_size,MIN_SORT_MEMORY);
@@ -116,14 +119,14 @@ int _create_index_by_sort(MI_SORT_PARAM *info,my_bool no_messages,
}
while ((maxbuffer= (int) (records/(keys-1)+1)) != skr);
- if ((sort_keys= (uchar **) make_char_array(keys,sort_length,MYF(0))))
+ if ((sort_keys=(uchar **)my_malloc(keys*(sort_length+sizeof(char*))+
+ HA_FT_MAXLEN, MYF(0))))
{
- if ((buffpek = (BUFFPEK*) my_malloc((uint) (sizeof(BUFFPEK)*
- (uint) maxbuffer),
- MYF(0))))
- break;
- else
+ if (init_dynamic_array(&buffpek, sizeof(BUFFPEK), maxbuffer,
+ maxbuffer/2))
my_free((gptr) sort_keys,MYF(0));
+ else
+ break;
}
old_memavl=memavl;
if ((memavl=memavl/4*3) < MIN_SORT_MEMORY && old_memavl > MIN_SORT_MEMORY)
@@ -139,7 +142,8 @@ int _create_index_by_sort(MI_SORT_PARAM *info,my_bool no_messages,
if (!no_messages)
printf(" - Searching for keys, allocating buffer for %d keys\n",keys);
- if ((records=find_all_keys(info,keys,sort_keys,buffpek,&maxbuffer,&tempfile))
+ if ((records=find_all_keys(info,keys,sort_keys,&buffpek,&maxbuffer,
+ &tempfile,&tempfile_for_exceptions))
== HA_POS_ERROR)
goto err; /* purecov: tested */
if (maxbuffer == 0)
@@ -156,25 +160,51 @@ int _create_index_by_sort(MI_SORT_PARAM *info,my_bool no_messages,
{
if (!no_messages)
printf(" - Merging %lu keys\n",records); /* purecov: tested */
- if (merge_many_buff(info,keys,sort_keys,buffpek,&maxbuffer,&tempfile))
- goto err; /* purecov: inspected */
+ if (merge_many_buff(info,keys,sort_keys,
+ dynamic_element(&buffpek,0,BUFFPEK *),&maxbuffer,&tempfile))
+ goto err; /* purecov: inspected */
}
if (flush_io_cache(&tempfile) ||
reinit_io_cache(&tempfile,READ_CACHE,0L,0,0))
- goto err; /* purecov: inspected */
+ goto err; /* purecov: inspected */
if (!no_messages)
puts(" - Last merge and dumping keys"); /* purecov: tested */
- if (merge_index(info,keys,sort_keys,buffpek,maxbuffer,&tempfile))
- goto err; /* purecov: inspected */
+ if (merge_index(info,keys,sort_keys,dynamic_element(&buffpek,0,BUFFPEK *),
+ maxbuffer,&tempfile))
+ goto err; /* purecov: inspected */
}
+
+ if (flush_pending_blocks(info->sort_info->param))
+ goto err;
+
+ if (my_b_inited(&tempfile_for_exceptions))
+ {
+ MI_INFO *index=info->sort_info->info;
+ uint keyno=info->sort_info->key;
+ uint key_length, ref_length=index->s->rec_reflength;
+
+ if (flush_io_cache(&tempfile_for_exceptions) ||
+ reinit_io_cache(&tempfile_for_exceptions,READ_CACHE,0L,0,0))
+ goto err;
+
+ while (!my_b_read(&tempfile_for_exceptions,(byte*)&key_length,
+ sizeof(key_length))
+ && !my_b_read(&tempfile_for_exceptions,(byte*)sort_keys,
+ (uint) key_length))
+ {
+ if (_mi_ck_write(index,keyno,(uchar*) sort_keys,key_length-ref_length))
+ goto err;
+ }
+ }
+
error =0;
err:
if (sort_keys)
my_free((gptr) sort_keys,MYF(0));
- if (buffpek)
- my_free((gptr) buffpek,MYF(0));
+ delete_dynamic(&buffpek);
close_cached_file(&tempfile);
+ close_cached_file(&tempfile_for_exceptions);
DBUG_RETURN(error ? -1 : 0);
} /* _create_index_by_sort */
@@ -183,36 +213,51 @@ err:
/* Search after all keys and place them in a temp. file */
static ha_rows NEAR_F find_all_keys(MI_SORT_PARAM *info, uint keys,
- uchar **sort_keys, BUFFPEK *buffpek,
- int *maxbuffer, IO_CACHE *tempfile)
+ uchar **sort_keys, DYNAMIC_ARRAY *buffpek,
+ int *maxbuffer, IO_CACHE *tempfile,
+ IO_CACHE *tempfile_for_exceptions)
{
int error;
- uint idx,indexpos;
+ uint idx;
DBUG_ENTER("find_all_keys");
- idx=indexpos=error=0;
+ idx=error=0;
+ sort_keys[0]=(uchar*) (sort_keys+keys);
- while (!(error=(*info->key_read)(info->sort_info,sort_keys[idx])))
+ while(!(error=(*info->key_read)(info->sort_info,sort_keys[idx])))
{
- if ((uint) ++idx == keys)
+ if (info->sort_info->real_key_length > info->key_length)
{
- if (indexpos >= (uint) *maxbuffer ||
- write_keys(info,sort_keys,idx-1,buffpek+indexpos,tempfile))
- DBUG_RETURN(HA_POS_ERROR); /* purecov: inspected */
+ if (write_key(info,sort_keys[idx],tempfile_for_exceptions))
+ DBUG_RETURN(HA_POS_ERROR); /* purecov: inspected */
+ continue;
+ }
+
+ if (++idx == keys)
+ {
+ if (write_keys(info,sort_keys,idx-1,(BUFFPEK *)alloc_dynamic(buffpek),
+ tempfile))
+ DBUG_RETURN(HA_POS_ERROR); /* purecov: inspected */
+
+ sort_keys[0]=(uchar*) (sort_keys+keys);
memcpy(sort_keys[0],sort_keys[idx-1],(size_t) info->key_length);
- idx=1; indexpos++;
+ idx=1;
}
+ sort_keys[idx]=sort_keys[idx-1]+info->key_length;
}
if (error > 0)
DBUG_RETURN(HA_POS_ERROR); /* Aborted by get_key */ /* purecov: inspected */
- if (indexpos)
- if (indexpos >= (uint) *maxbuffer ||
- write_keys(info,sort_keys,idx,buffpek+indexpos,tempfile))
- DBUG_RETURN(HA_POS_ERROR); /* purecov: inspected */
- *maxbuffer=(int) indexpos;
- DBUG_RETURN(indexpos*(keys-1)+idx);
-} /* find_all_keys */
+ if (buffpek->elements)
+ {
+ if (write_keys(info,sort_keys,idx,(BUFFPEK *)alloc_dynamic(buffpek),tempfile))
+ DBUG_RETURN(HA_POS_ERROR); /* purecov: inspected */
+ *maxbuffer=buffpek->elements-1;
+ }
+ else
+ *maxbuffer=0;
+ DBUG_RETURN((*maxbuffer)*(keys-1)+idx);
+} /* find_all_keys */
/* Write all keys in memory to file for later merge */
@@ -225,11 +270,12 @@ static int NEAR_F write_keys(MI_SORT_PARAM *info, register uchar **sort_keys,
DBUG_ENTER("write_keys");
qsort2((byte*) sort_keys,count,sizeof(byte*),(qsort2_cmp) info->key_cmp,
- info->sort_info);
+ info->sort_info);
if (!my_b_inited(tempfile) &&
open_cached_file(tempfile, info->tmpdir, "ST", DISK_BUFFER_SIZE,
info->myf_rw))
DBUG_RETURN(1); /* purecov: inspected */
+
buffpek->file_pos=my_b_tell(tempfile);
buffpek->count=count;
@@ -240,6 +286,22 @@ static int NEAR_F write_keys(MI_SORT_PARAM *info, register uchar **sort_keys,
} /* write_keys */
+static int NEAR_F write_key(MI_SORT_PARAM *info, uchar *key, IO_CACHE *tempfile)
+{
+ uint key_length=info->sort_info->real_key_length;
+ DBUG_ENTER("write_key");
+
+ if (!my_b_inited(tempfile) &&
+ open_cached_file(tempfile, info->tmpdir, "ST", DISK_BUFFER_SIZE,
+ info->myf_rw))
+ DBUG_RETURN(1);
+
+ if (my_b_write(tempfile,(byte*)&key_length,sizeof(key_length)) ||
+ my_b_write(tempfile,(byte*)key,(uint) key_length))
+ DBUG_RETURN(1);
+ DBUG_RETURN(0);
+} /* write_key */
+
/* Write index */
static int NEAR_F write_index(MI_SORT_PARAM *info, register uchar **sort_keys,
@@ -329,7 +391,7 @@ static uint NEAR_F read_to_buffer(IO_CACHE *fromfile, BUFFPEK *buffpek,
/* If to_file == 0 then use info->key_write */
static int NEAR_F
-merge_buffers(MI_SORT_PARAM *info, uint keys, IO_CACHE *from_file,
+merge_buffers(MI_SORT_PARAM *info, uint keys, IO_CACHE *from_file,
IO_CACHE *to_file, uchar **sort_keys, BUFFPEK *lastbuff,
BUFFPEK *Fb, BUFFPEK *Tb)
{
@@ -475,21 +537,3 @@ merge_index(MI_SORT_PARAM *info, uint keys, uchar **sort_keys,
DBUG_RETURN(0);
} /* merge_index */
-
- /* Make a pointer of arrays to keys */
-
-static char **make_char_array(register uint fields, uint length, myf my_flag)
-{
- register char **pos;
- char **old_pos,*char_pos;
- DBUG_ENTER("make_char_array");
-
- if ((old_pos= (char**) my_malloc( fields*(length+sizeof(char*)), my_flag)))
- {
- pos=old_pos; char_pos=((char*) (pos+fields)) -length;
- while (fields--)
- *(pos++) = (char_pos+= length);
- }
-
- DBUG_RETURN(old_pos);
-} /* make_char_array */
diff --git a/myisammrg/Makefile.am b/myisammrg/Makefile.am
index b09d7d70191..5355534eb77 100644
--- a/myisammrg/Makefile.am
+++ b/myisammrg/Makefile.am
@@ -16,12 +16,12 @@
INCLUDES = @MT_INCLUDES@ -I$(srcdir)/../include -I../include
pkglib_LIBRARIES = libmyisammrg.a
-noinst_HEADERS = mymrgdef.h
+noinst_HEADERS = myrg_def.h
libmyisammrg_a_SOURCES = myrg_open.c myrg_extra.c myrg_info.c myrg_locking.c \
myrg_rrnd.c myrg_update.c myrg_delete.c myrg_rsame.c \
myrg_panic.c myrg_close.c myrg_create.c myrg_static.c \
myrg_rkey.c myrg_rfirst.c myrg_rlast.c myrg_rnext.c \
- myrg_rprev.c myrg_queue.c
+ myrg_rprev.c myrg_queue.c myrg_write.c
OMIT_DEPENDENCIES = pthread.h stdio.h __stdio.h stdlib.h __stdlib.h math.h\
__math.h time.h __time.h unistd.h __unistd.h types.h \
xtypes.h ac-types.h posix.h string.h __string.h \
diff --git a/myisammrg/myrg_close.c b/myisammrg/myrg_close.c
index 7ab73c5ded4..897020c6865 100644
--- a/myisammrg/myrg_close.c
+++ b/myisammrg/myrg_close.c
@@ -1,22 +1,22 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/* close a isam-database */
-#include "mymrgdef.h"
+#include "myrg_def.h"
int myrg_close(MYRG_INFO *info)
{
diff --git a/myisammrg/myrg_create.c b/myisammrg/myrg_create.c
index 113831b9d7f..5fc3c60ff32 100644
--- a/myisammrg/myrg_create.c
+++ b/myisammrg/myrg_create.c
@@ -1,29 +1,30 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/* Create a MYMERGE_-file */
-#include "mymrgdef.h"
+#include "myrg_def.h"
/* create file named 'name' and save filenames in it
table_names should be NULL or a vector of string-pointers with
a NULL-pointer last
*/
-int myrg_create(const char *name, const char **table_names, my_bool fix_names)
+int myrg_create(const char *name, const char **table_names,
+ uint insert_method, my_bool fix_names)
{
int save_errno;
uint errpos;
@@ -50,6 +51,13 @@ int myrg_create(const char *name, const char **table_names, my_bool fix_names)
goto err;
}
}
+ if (insert_method != MERGE_INSERT_DISABLED)
+ {
+ end=strxmov(buff,"#INSERT_METHOD=",
+ get_type(&merge_insert_method,insert_method-1),"\n",NullS);
+ if (my_write(file,buff,(uint) (end-buff),MYF(MY_WME | MY_NABP)))
+ goto err;
+ }
if (my_close(file,MYF(0)))
goto err;
DBUG_RETURN(0);
diff --git a/myisammrg/mymrgdef.h b/myisammrg/myrg_def.h
index aae1d07cd64..d56cf4aa8d8 100644
--- a/myisammrg/mymrgdef.h
+++ b/myisammrg/myrg_def.h
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
diff --git a/myisammrg/myrg_delete.c b/myisammrg/myrg_delete.c
index 9ac32655172..94fa9835d3d 100644
--- a/myisammrg/myrg_delete.c
+++ b/myisammrg/myrg_delete.c
@@ -1,22 +1,22 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/* Delete last read record */
-#include "mymrgdef.h"
+#include "myrg_def.h"
int myrg_delete(
MYRG_INFO *info,
diff --git a/myisammrg/myrg_extra.c b/myisammrg/myrg_extra.c
index c8a634e748f..5434d30a50e 100644
--- a/myisammrg/myrg_extra.c
+++ b/myisammrg/myrg_extra.c
@@ -20,7 +20,7 @@
record-cache-flags are set in myrg_rrnd when we are changing database.
*/
-#include "mymrgdef.h"
+#include "myrg_def.h"
int myrg_extra(MYRG_INFO *info,enum ha_extra_function function)
{
@@ -46,3 +46,14 @@ int myrg_extra(MYRG_INFO *info,enum ha_extra_function function)
}
DBUG_RETURN(save_error);
}
+
+void myrg_extrafunc(MYRG_INFO *info, invalidator_by_filename inv)
+{
+ MYRG_TABLE *file;
+ DBUG_ENTER("myrg_extrafunc");
+
+ for (file=info->open_tables ; file != info->end_table ; file++)
+ file->table->s->invalidator = inv;
+
+ DBUG_VOID_RETURN;
+}
diff --git a/myisammrg/myrg_info.c b/myisammrg/myrg_info.c
index 8ca830339b9..14bc228cc1f 100644
--- a/myisammrg/myrg_info.c
+++ b/myisammrg/myrg_info.c
@@ -14,7 +14,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-#include "mymrgdef.h"
+#include "myrg_def.h"
ulonglong myrg_position(MYRG_INFO *info)
{
diff --git a/myisammrg/myrg_locking.c b/myisammrg/myrg_locking.c
index c89acca3918..41c972f72c0 100644
--- a/myisammrg/myrg_locking.c
+++ b/myisammrg/myrg_locking.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -18,7 +18,7 @@
Lock databases against read or write.
*/
-#include "mymrgdef.h"
+#include "myrg_def.h"
int myrg_lock_database(
MYRG_INFO *info,
diff --git a/myisammrg/myrg_open.c b/myisammrg/myrg_open.c
index df94fb680cb..668744442a6 100644
--- a/myisammrg/myrg_open.c
+++ b/myisammrg/myrg_open.c
@@ -14,29 +14,26 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-/* open a MYMERGE_-database */
+/* open a MyISAM MERGE table */
-#include "mymrgdef.h"
+#include "myrg_def.h"
#include <stddef.h>
#include <errno.h>
#ifdef VMS
#include "mrg_static.c"
#endif
-/* open a MYMERGE_-database.
-
+/*
+ open a MyISAM MERGE table
if handle_locking is 0 then exit with error if some database is locked
if handle_locking is 1 then wait if database is locked
*/
-MYRG_INFO *myrg_open(
-const char *name,
-int mode,
-int handle_locking)
+MYRG_INFO *myrg_open(const char *name, int mode, int handle_locking)
{
int save_errno,i,errpos;
- uint files,dir_length,length;
+ uint files,dir_length,length,options;
ulonglong file_offset;
char name_buff[FN_REFLEN*2],buff[FN_REFLEN],*end;
MYRG_INFO info,*m_info;
@@ -63,25 +60,34 @@ int handle_locking)
{
if ((end=buff+length)[-1] == '\n')
end[-1]='\0';
- if (buff[0] && buff[0] != '#') /* Skipp empty lines and comments */
+ if (!buff[0])
+ continue; /* Skip empty lines */
+ if (buff[0] == '#')
{
- if (!test_if_hard_path(buff))
- {
- VOID(strmake(name_buff+dir_length,buff,
- sizeof(name_buff)-1-dir_length));
- VOID(cleanup_dirname(buff,name_buff));
+ if( !strncmp(buff+1,"INSERT_METHOD=",14))
+ { /* Lookup insert method */
+ int tmp=find_type(buff+15,&merge_insert_method,2);
+ info.merge_insert_method = (uint) (tmp >= 0 ? tmp : 0);
}
- if (!(isam=mi_open(buff,mode,test(handle_locking))))
- goto err;
- files++;
- last_isam=isam;
- if (info.reclength && info.reclength != isam->s->base.reclength)
- {
- my_errno=HA_ERR_WRONG_IN_RECORD;
+ continue; /* Skip comments */
+ }
+
+ if (!test_if_hard_path(buff))
+ {
+ VOID(strmake(name_buff+dir_length,buff,
+ sizeof(name_buff)-1-dir_length));
+ VOID(cleanup_dirname(buff,name_buff));
+ }
+ if (!(isam=mi_open(buff,mode,test(handle_locking))))
goto err;
- }
- info.reclength=isam->s->base.reclength;
+ files++;
+ last_isam=isam;
+ if (info.reclength && info.reclength != isam->s->base.reclength)
+ {
+ my_errno=HA_ERR_WRONG_IN_RECORD;
+ goto err;
}
+ info.reclength=isam->s->base.reclength;
}
if (!(m_info= (MYRG_INFO*) my_malloc(sizeof(MYRG_INFO)+
files*sizeof(MYRG_TABLE),
@@ -92,16 +98,22 @@ int handle_locking)
m_info->tables=files;
errpos=2;
+ options= (uint) ~0;
for (i=files ; i-- > 0 ; )
{
m_info->open_tables[i].table=isam;
m_info->options|=isam->s->options;
+ options&=isam->s->options;
m_info->records+=isam->state->records;
m_info->del+=isam->state->del;
m_info->data_file_length+=isam->state->data_file_length;
if (i)
isam=(MI_INFO*) (isam->open_list.next->data);
}
+ /* Don't force readonly if not all tables are readonly */
+ if (! (options & (HA_OPTION_COMPRESS_RECORD | HA_OPTION_READ_ONLY_DATA)))
+ m_info->options&= ~(HA_OPTION_COMPRESS_RECORD | HA_OPTION_READ_ONLY_DATA);
+
/* Fix fileinfo for easyer debugging (actually set by rrnd) */
file_offset=0;
for (i=0 ; (uint) i < files ; i++)
diff --git a/myisammrg/myrg_panic.c b/myisammrg/myrg_panic.c
index 99a1f6828d1..ab08b8082c3 100644
--- a/myisammrg/myrg_panic.c
+++ b/myisammrg/myrg_panic.c
@@ -1,20 +1,20 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-#include "mymrgdef.h"
+#include "myrg_def.h"
/* if flag == HA_PANIC_CLOSE then all misam files are closed */
/* if flag == HA_PANIC_WRITE then all misam files are unlocked and
diff --git a/myisammrg/myrg_queue.c b/myisammrg/myrg_queue.c
index d6f831db48c..b4f729fc2cf 100644
--- a/myisammrg/myrg_queue.c
+++ b/myisammrg/myrg_queue.c
@@ -16,7 +16,7 @@
/* Read record based on a key */
-#include "mymrgdef.h"
+#include "myrg_def.h"
static int queue_key_cmp(void *keyseg, byte *a, byte *b)
{
diff --git a/myisammrg/myrg_rfirst.c b/myisammrg/myrg_rfirst.c
index 0625e848660..2ee9c015a84 100644
--- a/myisammrg/myrg_rfirst.c
+++ b/myisammrg/myrg_rfirst.c
@@ -14,7 +14,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-#include "mymrgdef.h"
+#include "myrg_def.h"
/* Read first row according to specific key */
diff --git a/myisammrg/myrg_rkey.c b/myisammrg/myrg_rkey.c
index cd2c73c8ec2..ba042352a51 100644
--- a/myisammrg/myrg_rkey.c
+++ b/myisammrg/myrg_rkey.c
@@ -27,7 +27,7 @@
*/
-#include "mymrgdef.h"
+#include "myrg_def.h"
/* todo: we could store some additional info to speedup lookups:
column (key, keyseg) can be constant per table
diff --git a/myisammrg/myrg_rlast.c b/myisammrg/myrg_rlast.c
index f41844dfd5c..e03a07c295a 100644
--- a/myisammrg/myrg_rlast.c
+++ b/myisammrg/myrg_rlast.c
@@ -14,7 +14,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-#include "mymrgdef.h"
+#include "myrg_def.h"
/* Read last row with the same key as the previous read. */
diff --git a/myisammrg/myrg_rnext.c b/myisammrg/myrg_rnext.c
index 5a3fbdfb299..abb9ef95e44 100644
--- a/myisammrg/myrg_rnext.c
+++ b/myisammrg/myrg_rnext.c
@@ -14,7 +14,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-#include "mymrgdef.h"
+#include "myrg_def.h"
/*
Read next row with the same key as previous read
diff --git a/myisammrg/myrg_rprev.c b/myisammrg/myrg_rprev.c
index d8089e80498..bd7e6a1f6d2 100644
--- a/myisammrg/myrg_rprev.c
+++ b/myisammrg/myrg_rprev.c
@@ -14,7 +14,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-#include "mymrgdef.h"
+#include "myrg_def.h"
/*
Read previous row with the same key as previous read
diff --git a/myisammrg/myrg_rrnd.c b/myisammrg/myrg_rrnd.c
index de731e58d5b..d50d077e6ba 100644
--- a/myisammrg/myrg_rrnd.c
+++ b/myisammrg/myrg_rrnd.c
@@ -19,7 +19,7 @@
get by myrg_info(). The next record can be read with pos= -1 */
-#include "mymrgdef.h"
+#include "myrg_def.h"
static MYRG_TABLE *find_table(MYRG_TABLE *start,MYRG_TABLE *end,ulonglong pos);
diff --git a/myisammrg/myrg_rsame.c b/myisammrg/myrg_rsame.c
index 301b96e667b..ddc77f85913 100644
--- a/myisammrg/myrg_rsame.c
+++ b/myisammrg/myrg_rsame.c
@@ -1,20 +1,20 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-#include "mymrgdef.h"
+#include "myrg_def.h"
int myrg_rsame(MYRG_INFO *info,byte *record,int inx)
{
diff --git a/myisammrg/myrg_static.c b/myisammrg/myrg_static.c
index 88eb095382b..b21b834ac24 100644
--- a/myisammrg/myrg_static.c
+++ b/myisammrg/myrg_static.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -20,7 +20,11 @@
*/
#ifndef stdin
-#include "mymrgdef.h"
+#include "myrg_def.h"
#endif
LIST *myrg_open_list=0;
+static const char *merge_insert_methods[] =
+{ "FIRST", "LAST", NullS };
+TYPELIB merge_insert_method= { array_elements(merge_insert_methods)-1,"",
+ merge_insert_methods};
diff --git a/myisammrg/myrg_update.c b/myisammrg/myrg_update.c
index b75c6ea6f9b..cb1b0b51ef9 100644
--- a/myisammrg/myrg_update.c
+++ b/myisammrg/myrg_update.c
@@ -1,22 +1,22 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/* Update last read record */
-#include "mymrgdef.h"
+#include "myrg_def.h"
int myrg_update(register MYRG_INFO *info,const byte *oldrec, byte *newrec)
{
diff --git a/myisammrg/myrg_write.c b/myisammrg/myrg_write.c
new file mode 100644
index 00000000000..4e597005503
--- /dev/null
+++ b/myisammrg/myrg_write.c
@@ -0,0 +1,30 @@
+/* Copyright (C) 2001 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+/* Write a row to a MyISAM MERGE table */
+
+#include "myrg_def.h"
+
+int myrg_write(register MYRG_INFO *info, byte *rec)
+{
+ /* [phi] MERGE_WRITE_DISABLED is handled by the else case */
+ if (info->merge_insert_method == MERGE_INSERT_TO_FIRST)
+ return mi_write(info->open_tables[0].table,rec);
+ else if (info->merge_insert_method == MERGE_INSERT_TO_LAST)
+ return mi_write(info->end_table[-1].table,rec);
+ else /* unsupported insertion method */
+ return (my_errno=HA_ERR_WRONG_COMMAND);
+}
diff --git a/mysql-test/Makefile.am b/mysql-test/Makefile.am
index d98c10a29a9..91333dfad9b 100644
--- a/mysql-test/Makefile.am
+++ b/mysql-test/Makefile.am
@@ -59,6 +59,8 @@ SUFFIXES = .sh
-e 's!@''libexecdir''@!$(libexecdir)!g' \
-e 's!@''PERL''@!@PERL@!' \
-e 's!@''VERSION''@!@VERSION@!' \
+ -e 's!@''MYSQL_BASE_VERSION''@!@MYSQL_BASE_VERSION@!' \
+ -e 's!@''MYSQL_NO_DASH_VERSION''@!@MYSQL_NO_DASH_VERSION@!' \
-e 's!@''MYSQL_SERVER_SUFFIX''@!@MYSQL_SERVER_SUFFIX@!' \
$< > $@-t
@CHMOD@ +x $@-t
diff --git a/mysql-test/create-test-result b/mysql-test/create-test-result
index 24c3d175303..bfd64f32fc5 100755
--- a/mysql-test/create-test-result
+++ b/mysql-test/create-test-result
@@ -5,7 +5,7 @@
# If you have a spare moment feel free to improve it - the right way is
# to start mysqld yourself and run mysqltest -r
-RESULT_DIR=r/3.23
+RESULT_DIR=r
if [ -z $EDITOR] ; then
EDITOR=vi
fi
@@ -32,7 +32,7 @@ result_file=$RESULT_DIR/$test_name.result
touch $result_file
echo "Running the test case against empty file, will fail, but don't worry"
-./mysql-test-run $test_name
+./mysql-test-run --do-test=$test_name
reject_file=$result_file.reject
diff --git a/mysql-test/fix-result b/mysql-test/fix-result
new file mode 100755
index 00000000000..bd380332ff5
--- /dev/null
+++ b/mysql-test/fix-result
@@ -0,0 +1,22 @@
+#! /bin/sh
+
+# Sasha's hack to fix results generated with mysql-test-run --record
+# to be version and test port independent. In some cases, further minor
+# manual edititing may be required, but most of the time it should not
+# happen
+
+#It is assumed we are running the script in mysql-test directory
+
+VERSION=4.0.1-alpha-debug-log
+TEST_CASE=$1
+
+if [ -z "$TEST_CASE" ] ;
+then
+ echo "usage: $0 test_case_name"
+ exit 1
+fi
+
+../extra/replace $VERSION '$VERSION' 9306 '$MASTER_MYPORT' 9307 \
+'$SLAVE_MYPORT' \\ \\\\ -- r/$TEST_CASE.result
+
+
diff --git a/mysql-test/include/have_bdb.inc b/mysql-test/include/have_bdb.inc
index 0126e30210f..3f7377e7515 100644
--- a/mysql-test/include/have_bdb.inc
+++ b/mysql-test/include/have_bdb.inc
@@ -1,2 +1,4 @@
-- require r/have_bdb.require
+disable_query_log;
show variables like "have_bdb";
+enable_query_log;
diff --git a/mysql-test/include/have_gemini.inc b/mysql-test/include/have_gemini.inc
deleted file mode 100644
index 78a84ac6f3e..00000000000
--- a/mysql-test/include/have_gemini.inc
+++ /dev/null
@@ -1,2 +0,0 @@
--- require r/have_gemini.require
-show variables like "have_gemini";
diff --git a/mysql-test/include/have_innodb.inc b/mysql-test/include/have_innodb.inc
index 7dcaef44878..4f83d378cbc 100644
--- a/mysql-test/include/have_innodb.inc
+++ b/mysql-test/include/have_innodb.inc
@@ -1,2 +1,4 @@
-- require r/have_innodb.require
+disable_query_log;
show variables like "have_innodb";
+enable_query_log;
diff --git a/mysql-test/include/have_isam.inc b/mysql-test/include/have_isam.inc
index d83328f70f4..830170c921f 100644
--- a/mysql-test/include/have_isam.inc
+++ b/mysql-test/include/have_isam.inc
@@ -1,2 +1,4 @@
-- require r/have_isam.require
+disable_query_log;
show variables like "have_isam";
+enable_query_log;
diff --git a/mysql-test/include/have_openssl.inc b/mysql-test/include/have_openssl.inc
new file mode 100644
index 00000000000..54c5b04b3e4
--- /dev/null
+++ b/mysql-test/include/have_openssl.inc
@@ -0,0 +1,4 @@
+-- require r/have_openssl.require
+disable_query_log;
+show variables like "have_openssl";
+enable_query_log;
diff --git a/mysql-test/include/have_openssl_1.inc b/mysql-test/include/have_openssl_1.inc
new file mode 100644
index 00000000000..4d3646abdc2
--- /dev/null
+++ b/mysql-test/include/have_openssl_1.inc
@@ -0,0 +1,4 @@
+-- require r/have_openssl_1.require
+disable_query_log;
+show variables like "have_openssl";
+enable_query_log;
diff --git a/mysql-test/include/have_openssl_2.inc b/mysql-test/include/have_openssl_2.inc
new file mode 100644
index 00000000000..724d295a398
--- /dev/null
+++ b/mysql-test/include/have_openssl_2.inc
@@ -0,0 +1,4 @@
+-- require r/have_openssl_2.require
+disable_query_log;
+SHOW STATUS LIKE "SSL_get_cipher";
+enable_query_log;
diff --git a/mysql-test/include/master-slave.inc b/mysql-test/include/master-slave.inc
index 61077f898f6..23392690239 100644
--- a/mysql-test/include/master-slave.inc
+++ b/mysql-test/include/master-slave.inc
@@ -1,8 +1,9 @@
-connect (master,localhost,root,,test,0,mysql-master.sock);
-connect (master1,localhost,root,,test,0,mysql-master.sock);
-connect (slave,localhost,root,,test,0,mysql-slave.sock);
-connect (slave1,localhost,root,,test,0,mysql-slave.sock);
+connect (master,127.0.0.1,root,,test,$MASTER_MYPORT,);
+connect (master1,127.0.0.1,root,,test,$MASTER_MYPORT,);
+connect (slave,127.0.0.1,root,,test,$SLAVE_MYPORT,);
+connect (slave1,127.0.0.1,root,,test,$SLAVE_MYPORT,);
connection slave;
+--error 0,1199
!slave stop;
@r/slave-stopped.result show status like 'Slave_running';
connection master;
diff --git a/mysql-test/include/not_embedded.inc b/mysql-test/include/not_embedded.inc
new file mode 100644
index 00000000000..52ae026ece3
--- /dev/null
+++ b/mysql-test/include/not_embedded.inc
@@ -0,0 +1,5 @@
+-- require r/not_embedded.require
+disable_query_log;
+select version() like "%embedded%" as "have_embedded";
+enable_query_log;
+
diff --git a/mysql-test/install_test_db.sh b/mysql-test/install_test_db.sh
index 6fe736644d3..acf8cebc723 100644
--- a/mysql-test/install_test_db.sh
+++ b/mysql-test/install_test_db.sh
@@ -30,7 +30,7 @@ else
fi
mdata=$data/mysql
-
+EXTRA_ARG=""
if test ! -x $execdir/mysqld
then
@@ -57,9 +57,7 @@ if [ x$BINARY_DIST = x1 ] ; then
basedir=..
else
basedir=.
-rm -rf share
-mkdir share
-ln -f -s ../../sql/share share/mysql
+EXTRA_ARG="--language=../sql/share/english/"
fi
# Initialize variables
@@ -136,16 +134,20 @@ then
c_u="$c_u References_priv enum('N','Y') DEFAULT 'N' NOT NULL,"
c_u="$c_u Index_priv enum('N','Y') DEFAULT 'N' NOT NULL,"
c_u="$c_u Alter_priv enum('N','Y') DEFAULT 'N' NOT NULL,"
+ c_u="$c_u ssl_type enum('NONE','ANY', 'X509', 'SPECIFIED') NOT NULL,"
+ c_u="$c_u ssl_cipher char(60) NULL,"
+ c_u="$c_u x509_issuer blob NULL,"
+ c_u="$c_u x509_subject blob NULL,"
c_u="$c_u PRIMARY KEY Host (Host,User)"
c_u="$c_u )"
c_u="$c_u comment='Users and global privileges';"
- i_u="INSERT INTO user VALUES ('localhost','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y');
- INSERT INTO user VALUES ('$hostname','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y');
- REPLACE INTO user VALUES ('127.0.0.1','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y');
+ i_u="INSERT INTO user VALUES ('localhost','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','none',NULL,NULL,NULL);
+ INSERT INTO user VALUES ('$hostname','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','none',NULL,NULL,NULL);
+ REPLACE INTO user VALUES ('127.0.0.1','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','none',NULL,NULL,NULL);
- INSERT INTO user VALUES ('localhost','','','N','N','N','N','N','N','N','N','N','N','N','N','N','N');
- INSERT INTO user VALUES ('$hostname','','','N','N','N','N','N','N','N','N','N','N','N','N','N','N');"
+ INSERT INTO user VALUES ('localhost','','','N','N','N','N','N','N','N','N','N','N','N','N','N','N','none',NULL,NULL,NULL);
+ INSERT INTO user VALUES ('$hostname','','','N','N','N','N','N','N','N','N','N','N','N','N','N','N','none',NULL,NULL,NULL);"
fi
if test ! -f $mdata/func.frm
@@ -192,8 +194,11 @@ then
c_c="$c_c comment='Column privileges';"
fi
-if $execdir/mysqld --no-defaults --bootstrap --skip-grant-tables \
- --basedir=$basedir --datadir=$ldata --skip-innodb --skip-bdb --skip-gemini << END_OF_DATA
+mysqld_boot=" $execdir/mysqld --no-defaults --bootstrap --skip-grant-tables \
+ --basedir=$basedir --datadir=$ldata --skip-innodb --skip-bdb $EXTRA_ARG"
+echo "running $mysqld_boot"
+
+if $mysqld_boot << END_OF_DATA
use mysql;
$c_d
$i_d
@@ -213,5 +218,6 @@ END_OF_DATA
then
exit 0
else
+ echo "Error executing mysqld --boostrap"
exit 1
fi
diff --git a/mysql-test/mysql-test-run.sh b/mysql-test/mysql-test-run.sh
index 09cdab9664b..465c1cfdaa2 100644
--- a/mysql-test/mysql-test-run.sh
+++ b/mysql-test/mysql-test-run.sh
@@ -12,13 +12,15 @@
DB=test
DBPASSWD=
VERBOSE=""
+USE_MANAGER=0
TZ=GMT-3; export TZ # for UNIX_TIMESTAMP tests to work
#++
# Program Definitions
#--
-PATH=/bin:/usr/bin:/usr/local/bin:/usr/bsd:/usr/X11R6/bin
+PATH=/bin:/usr/bin:/usr/local/bin:/usr/bsd:/usr/X11R6/bin:/usr/openwin/bin
+MASTER_40_ARGS="--rpl-recovery-rank=1 --init-rpl-role=master"
# Standard functions
@@ -42,12 +44,46 @@ which ()
}
+sleep_until_file_deleted ()
+{
+ file=$1
+ loop=$SLEEP_TIME_FOR_DELETE
+ while (test $loop -gt 0)
+ do
+ if [ ! -r $file ]
+ then
+ sleep $SLEEP_TIME_AFTER_RESTART
+ return
+ fi
+ loop=`expr $loop - 1`
+ done
+}
+
+sleep_until_file_created ()
+{
+ file=$1
+ loop=$2
+ org_time=$2
+ while (test $loop -gt 0)
+ do
+ if [ -r $file ]
+ then
+ return
+ fi
+ sleep 1
+ loop=`expr $loop - 1`
+ done
+ echo "ERROR: $file was not created in $org_time seconds; Aborting"
+ exit 1;
+}
+
# No paths below as we can't be sure where the program is!
BASENAME=`which basename | head -1`
DIFF=`which diff | head -1`
CAT=cat
CUT=cut
+HEAD=head
TAIL=tail
ECHO=echo # use internal echo if possible
EXPR=expr # use internal if possible
@@ -89,7 +125,7 @@ else
BINARY_DIST=1
fi
-#BASEDIR is always one above mysql-test directory
+#BASEDIR is always one above mysql-test directory
CWD=`pwd`
cd ..
BASEDIR=`pwd`
@@ -98,7 +134,8 @@ MYSQL_TEST_DIR=$BASEDIR/mysql-test
export MYSQL_TEST_DIR
STD_DATA=$MYSQL_TEST_DIR/std_data
hostname=`hostname` # Installed in the mysql privilege table
-
+
+MANAGER_QUIET_OPT="-q"
TESTDIR="$MYSQL_TEST_DIR/t"
TESTSUFFIX=test
TOT_SKIP=0
@@ -113,16 +150,21 @@ SLAVE_LOAD_TMPDIR=../../var/tmp #needs to be same length to test logging
RES_SPACE=" "
MYSQLD_SRC_DIRS="strings mysys include extra regex isam merge myisam \
myisammrg heap sql"
+MY_LOG_DIR="$MYSQL_TEST_DIR/var/log"
#
# Set LD_LIBRARY_PATH if we are using shared libraries
#
-LD_LIBRARY_PATH="$BASEDIR/lib:$LD_LIBRARY_PATH"
+LD_LIBRARY_PATH="$BASEDIR/lib:$BASEDIR/libmysql/.libs:$LD_LIBRARY_PATH"
export LD_LIBRARY_PATH
MASTER_RUNNING=0
MASTER_MYPORT=9306
SLAVE_RUNNING=0
SLAVE_MYPORT=9307
+MYSQL_MANAGER_PORT=9305 # needs to be out of the way of slaves
+MYSQL_MANAGER_PW_FILE=$MYSQL_TEST_DIR/var/tmp/manager.pwd
+MYSQL_MANAGER_LOG=$MYSQL_TEST_DIR/var/log/manager.log
+MYSQL_MANAGER_USER=root
NO_SLAVE=0
EXTRA_MASTER_OPT=""
@@ -130,19 +172,40 @@ EXTRA_MYSQL_TEST_OPT=""
USE_RUNNING_SERVER=1
DO_GCOV=""
DO_GDB=""
+MANUAL_GDB=""
DO_DDD=""
DO_CLIENT_GDB=""
-SLEEP_TIME=2
+SLEEP_TIME_AFTER_RESTART=1
+SLEEP_TIME_FOR_DELETE=10
+SLEEP_TIME_FOR_FIRST_MASTER=400 # Enough time to create innodb tables
+SLEEP_TIME_FOR_SECOND_MASTER=30
+SLEEP_TIME_FOR_FIRST_SLAVE=400
+SLEEP_TIME_FOR_SECOND_SLAVE=30
+CHARACTER_SET=latin1
DBUSER=""
+START_WAIT_TIMEOUT=10
+STOP_WAIT_TIMEOUT=10
while test $# -gt 0; do
case "$1" in
--user=*) DBUSER=`$ECHO "$1" | $SED -e "s;--user=;;"` ;;
--force) FORCE=1 ;;
+ --verbose-manager) MANAGER_QUIET_OPT="" ;;
+ --old-master) MASTER_40_ARGS="";;
+ --master-binary=*)
+ MASTER_MYSQLD=`$ECHO "$1" | $SED -e "s;--master-binary=;;"` ;;
+ --slave-binary=*)
+ SLAVE_MYSQLD=`$ECHO "$1" | $SED -e "s;--slave-binary=;;"` ;;
--local) USE_RUNNING_SERVER="" ;;
--tmpdir=*) MYSQL_TMP_DIR=`$ECHO "$1" | $SED -e "s;--tmpdir=;;"` ;;
+ --local-master)
+ MASTER_MYPORT=3306;
+ EXTRA_MYSQL_TEST_OPT="$EXTRA_MYSQL_TEST_OPT --host=127.0.0.1 \
+ --port=$MYSQL_MYPORT"
+ LOCAL_MASTER=1 ;;
--master_port=*) MASTER_MYPORT=`$ECHO "$1" | $SED -e "s;--master_port=;;"` ;;
--slave_port=*) SLAVE_MYPORT=`$ECHO "$1" | $SED -e "s;--slave_port=;;"` ;;
+ --manager-port=*) MYSQL_MANAGER_PORT=`$ECHO "$1" | $SED -e "s;--manager_port=;;"` ;;
--with-openssl)
EXTRA_MASTER_MYSQLD_OPT="$EXTRA_MASTER_MYSQLD_OPT \
--ssl-ca=$BASEDIR/SSL/cacert.pem \
@@ -152,27 +215,40 @@ while test $# -gt 0; do
--ssl-ca=$BASEDIR/SSL/cacert.pem \
--ssl-cert=$BASEDIR/SSL/server-cert.pem \
--ssl-key=$BASEDIR/SSL/server-key.pem" ;;
- --skip-innobase)
- EXTRA_MASTER_MYSQLD_OPT="$EXTRA_MASTER_MYSQLD_OPT --skip-innobase"
- EXTRA_SLAVE_MYSQLD_OPT="$EXTRA_SLAVE_MYSQLD_OPT --skip-innobase" ;;
+ --no-manager | --skip-manager) USE_MANAGER=0 ;;
+ --manager)
+ USE_MANAGER=1
+ USE_RUNNING_SERVER=
+ ;;
+ --start-and-exit)
+ START_AND_EXIT=1
+ ;;
+ --skip-innodb)
+ EXTRA_MASTER_MYSQLD_OPT="$EXTRA_MASTER_MYSQLD_OPT --skip-innodb"
+ EXTRA_SLAVE_MYSQLD_OPT="$EXTRA_SLAVE_MYSQLD_OPT --skip-innodb" ;;
--skip-bdb)
EXTRA_MASTER_MYSQLD_OPT="$EXTRA_MASTER_MYSQLD_OPT --skip-bdb"
EXTRA_SLAVE_MYSQLD_OPT="$EXTRA_SLAVE_MYSQLD_OPT --skip-bdb" ;;
--skip-rpl) NO_SLAVE=1 ;;
--skip-test=*) SKIP_TEST=`$ECHO "$1" | $SED -e "s;--skip-test=;;"`;;
--do-test=*) DO_TEST=`$ECHO "$1" | $SED -e "s;--do-test=;;"`;;
+ --wait-timeout=*)
+ START_WAIT_TIMEOUT=`$ECHO "$1" | $SED -e "s;--wait-timeout=;;"`
+ STOP_WAIT_TIMEOUT=$START_WAIT_TIMEOUT;;
--record)
RECORD=1;
EXTRA_MYSQL_TEST_OPT="$EXTRA_MYSQL_TEST_OPT $1" ;;
--bench)
DO_BENCH=1
NO_SLAVE=1
- ;;
+ ;;
--big*) # Actually --big-test
EXTRA_MYSQL_TEST_OPT="$EXTRA_MYSQL_TEST_OPT $1" ;;
+ --compress)
+ EXTRA_MYSQL_TEST_OPT="$EXTRA_MYSQL_TEST_OPT $1" ;;
--sleep=*)
EXTRA_MYSQL_TEST_OPT="$EXTRA_MYSQL_TEST_OPT $1"
- SLEEP_TIME=`$ECHO "$1" | $SED -e "s;--sleep=;;"`
+ SLEEP_TIME_AFTER_RESTART=`$ECHO "$1" | $SED -e "s;--sleep=;;"`
;;
--mysqld=*)
TMP=`$ECHO "$1" | $SED -e "s;--mysqld=;;"`
@@ -188,12 +264,16 @@ while test $# -gt 0; do
;;
--gprof )
DO_GPROF=1
- ;;
+ ;;
--gdb )
+ START_WAIT_TIMEOUT=300
+ STOP_WAIT_TIMEOUT=300
if [ x$BINARY_DIST = x1 ] ; then
$ECHO "Note: you will get more meaningful output on a source distribution compiled with debugging option when running tests with --gdb option"
fi
DO_GDB=1
+ # This needs to be checked properly
+ # USE_MANAGER=1
USE_RUNNING_SERVER=""
;;
--client-gdb )
@@ -202,6 +282,11 @@ while test $# -gt 0; do
fi
DO_CLIENT_GDB=1
;;
+ --manual-gdb )
+ DO_GDB=1
+ MANUAL_GDB=1
+ USE_RUNNING_SERVER=""
+ ;;
--ddd )
if [ x$BINARY_DIST = x1 ] ; then
$ECHO "Note: you will get more meaningful output on a source distribution compiled with debugging option when running tests with --ddd option"
@@ -213,6 +298,9 @@ while test $# -gt 0; do
EXTRA_MASTER_MYSQLD_OPT="$EXTRA_MASTER_MYSQLD_OPT $1"
EXTRA_SLAVE_MYSQLD_OPT="$EXTRA_SLAVE_MYSQLD_OPT $1"
;;
+ --strace-client )
+ STRACE_CLIENT=1
+ ;;
--debug)
EXTRA_MASTER_MYSQLD_OPT="$EXTRA_MASTER_MYSQLD_OPT \
--debug=d:t:i:O,$MYSQL_TEST_DIR/var/log/master.trace"
@@ -232,17 +320,19 @@ done
#--
MYRUN_DIR=$MYSQL_TEST_DIR/var/run
+MANAGER_PID_FILE="$MYRUN_DIR/manager.pid"
+
MASTER_MYDDIR="$MYSQL_TEST_DIR/var/master-data"
-MASTER_MYSOCK="$MYSQL_TMP_DIR/mysql-master.sock"
-MASTER_MYPID="$MYRUN_DIR/mysqld.pid"
-MASTER_MYLOG="$MYSQL_TEST_DIR/var/log/mysqld.log"
-MASTER_MYERR="$MYSQL_TEST_DIR/var/log/mysqld.err"
+MASTER_MYSOCK="$MYSQL_TMP_DIR/master.sock"
+MASTER_MYPID="$MYRUN_DIR/master.pid"
+MASTER_MYLOG="$MYSQL_TEST_DIR/var/log/master.log"
+MASTER_MYERR="$MYSQL_TEST_DIR/var/log/master.err"
SLAVE_MYDDIR="$MYSQL_TEST_DIR/var/slave-data"
-SLAVE_MYSOCK="$MYSQL_TMP_DIR/mysql-slave.sock"
-SLAVE_MYPID="$MYRUN_DIR/mysqld-slave.pid"
-SLAVE_MYLOG="$MYSQL_TEST_DIR/var/log/mysqld-slave.log"
-SLAVE_MYERR="$MYSQL_TEST_DIR/var/log/mysqld-slave.err"
+SLAVE_MYSOCK="$MYSQL_TMP_DIR/slave.sock"
+SLAVE_MYPID="$MYRUN_DIR/slave.pid"
+SLAVE_MYLOG="$MYSQL_TEST_DIR/var/log/slave.log"
+SLAVE_MYERR="$MYSQL_TEST_DIR/var/log/slave.err"
SMALL_SERVER="-O key_buffer_size=1M -O sort_buffer=256K -O max_heap_table_size=1M"
@@ -253,7 +343,7 @@ if [ x$SOURCE_DIST = x1 ] ; then
MY_BASEDIR=$MYSQL_TEST_DIR
else
MY_BASEDIR=$BASEDIR
-fi
+fi
# Create the directories
@@ -264,7 +354,7 @@ fi
[ -d $MYSQL_TEST_DIR/var/tmp ] || mkdir $MYSQL_TEST_DIR/var/tmp
[ -d $MYSQL_TEST_DIR/var/run ] || mkdir $MYSQL_TEST_DIR/var/run
-[ -z "$COLUMNS" ] && COLUMNS=80
+if test ${COLUMNS:-0} -lt 80 ; then COLUMNS=80 ; fi
E=`$EXPR $COLUMNS - 8`
DASH72=`$ECHO '------------------------------------------------------------------------'|$CUT -c 1-$E`
@@ -274,10 +364,19 @@ if [ x$SOURCE_DIST = x1 ] ; then
MYSQLD="$BASEDIR/sql/mysqld"
if [ -f "$BASEDIR/client/.libs/lt-mysqltest" ] ; then
MYSQL_TEST="$BASEDIR/client/.libs/lt-mysqltest"
+ elif [ -f "$BASEDIR/client/.libs/mysqltest" ] ; then
+ MYSQL_TEST="$BASEDIR/client/.libs/mysqltest"
else
MYSQL_TEST="$BASEDIR/client/mysqltest"
fi
+ if [ -n "$STRACE_CLIENT" ]; then
+ MYSQL_TEST="strace -o $MYSQL_TEST_DIR/var/log/mysqltest.strace $MYSQL_TEST"
+ fi
+
MYSQLADMIN="$BASEDIR/client/mysqladmin"
+ MYSQL_MANAGER_CLIENT="$BASEDIR/client/mysqlmanagerc"
+ MYSQL_MANAGER="$BASEDIR/tools/mysqlmanager"
+ MYSQL_MANAGER_PWGEN="$BASEDIR/client/mysqlmanager-pwgen"
MYSQL="$BASEDIR/client/mysql"
LANGUAGE="$BASEDIR/sql/share/english/"
CHARSETSDIR="$BASEDIR/sql/share/charsets"
@@ -286,9 +385,12 @@ else
MYSQLD="$BASEDIR/bin/mysqld"
MYSQL_TEST="$BASEDIR/bin/mysqltest"
MYSQLADMIN="$BASEDIR/bin/mysqladmin"
+ MYSQL_MANAGER="$BASEDIR/bin/mysqlmanager"
+ MYSQL_MANAGER_CLIENT="$BASEDIR/bin/mysqlmanagerc"
+ MYSQL_MANAGER_PWGEN="$BASEDIR/bin/mysqlmanager-pwgen"
MYSQL="$BASEDIR/bin/mysql"
INSTALL_DB="./install_test_db -bin"
- if test -d "$BASEDIR/share/mysql/english"
+ if test -d "$BASEDIR/share/mysql/english"
then
LANGUAGE="$BASEDIR/share/mysql/english/"
CHARSETSDIR="$BASEDIR/share/mysql/charsets"
@@ -298,6 +400,16 @@ else
fi
fi
+if [ -z "$MASTER_MYSQLD" ]
+then
+MASTER_MYSQLD=$MYSQLD
+fi
+
+if [ -z "$SLAVE_MYSQLD" ]
+then
+SLAVE_MYSQLD=$MYSQLD
+fi
+
# If we should run all tests cases, we will use a local server for that
if [ -z "$1" ]
@@ -320,7 +432,9 @@ then
fi
-MYSQL_TEST_ARGS="--no-defaults --socket=$MASTER_MYSOCK --database=$DB --user=$DBUSER --password=$DBPASSWD --silent -v --tmpdir=$MYSQL_TMP_DIR"
+MYSQL_TEST_ARGS="--no-defaults --socket=$MASTER_MYSOCK --database=$DB \
+ --user=$DBUSER --password=$DBPASSWD --silent -v \
+ --tmpdir=$MYSQL_TMP_DIR"
MYSQL_TEST_BIN=$MYSQL_TEST
MYSQL_TEST="$MYSQL_TEST $MYSQL_TEST_ARGS"
GDB_CLIENT_INIT=$MYSQL_TMP_DIR/gdbinit.client
@@ -331,8 +445,8 @@ GCOV_ERR=$MYSQL_TMP_DIR/mysqld-gcov.err
GPROF_DIR=$MYSQL_TMP_DIR/gprof
GPROF_MASTER=$GPROF_DIR/master.gprof
GPROF_SLAVE=$GPROF_DIR/slave.gprof
-TIMEFILE="$MYSQL_TMP_DIR/mysqltest-time"
-SLAVE_MYSQLD=$MYSQLD #this can be changed later if we are doing gcov
+TIMEFILE="$MYSQL_TEST_DIR/var/log/mysqltest-time"
+XTERM=`which xterm`
#++
# Function Definitions
@@ -355,12 +469,12 @@ show_failed_diff ()
reject_file=r/$1.reject
result_file=r/$1.result
eval_file=r/$1.eval
-
+
if [ -f $eval_file ]
then
result_file=$eval_file
fi
-
+
if [ -x "$DIFF" ] && [ -f $reject_file ]
then
echo "Below are the diffs between actual and expected results:"
@@ -370,7 +484,7 @@ show_failed_diff ()
echo "Please follow the instructions outlined at"
echo "http://www.mysql.com/doc/R/e/Reporting_mysqltest_bugs.html"
echo "to find the reason to this problem and how to report this."
- fi
+ fi
}
do_gdb_test ()
@@ -379,7 +493,7 @@ do_gdb_test ()
$ECHO "set args $mysql_test_args < $2" > $GDB_CLIENT_INIT
echo "Set breakpoints ( if needed) and type 'run' in gdb window"
#this xterm should not be backgrounded
- xterm -title "Client" -e gdb -x $GDB_CLIENT_INIT $MYSQL_TEST_BIN
+ $XTERM -title "Client" -e gdb -x $GDB_CLIENT_INIT $MYSQL_TEST_BIN
}
error () {
@@ -388,7 +502,7 @@ error () {
}
error_is () {
- $TR "\n" " " < $TIMEFILE | $SED -e 's/.* At line \(.*\)\: \(.*\)Command .*$/ \>\> Error at line \1: \2<\</'
+ $CAT < $TIMEFILE | $SED -e 's/.* At line \(.*\)\: \(.*\)/ \>\> Error at line \1: \2<\</' | $HEAD -1
}
prefix_to_8() {
@@ -415,15 +529,15 @@ report_stats () {
if [ $TOT_FAIL = 0 ]; then
$ECHO "All $TOT_TEST tests were successful."
else
- xten=`$EXPR $TOT_PASS \* 10000`
- raw=`$EXPR $xten / $TOT_TEST`
- raw=`$PRINTF %.4d $raw`
- whole=`$PRINTF %.2s $raw`
- xwhole=`$EXPR $whole \* 100`
- deci=`$EXPR $raw - $xwhole`
+ xten=`$EXPR $TOT_PASS \* 10000`
+ raw=`$EXPR $xten / $TOT_TEST`
+ raw=`$PRINTF %.4d $raw`
+ whole=`$PRINTF %.2s $raw`
+ xwhole=`$EXPR $whole \* 100`
+ deci=`$EXPR $raw - $xwhole`
$ECHO "Failed ${TOT_FAIL}/${TOT_TEST} tests, ${whole}.${deci}% successful."
$ECHO ""
- $ECHO "The log files in $MYSQL_TEST_DIR/var/log may give you some hint"
+ $ECHO "The log files in $MY_LOG_DIR may give you some hint"
$ECHO "of what when wrong."
$ECHO "If you want to report this error, please read first the documentation at"
$ECHO "http://www.mysql.com/doc/M/y/MySQL_test_suite.html"
@@ -432,8 +546,7 @@ report_stats () {
mysql_install_db () {
$ECHO "Removing Stale Files"
- $RM -rf $MASTER_MYDDIR $SLAVE_MYDDIR $SLAVE_MYLOG $MASTER_MYLOG \
- $SLAVE_MYERR $MASTER_MYERR
+ $RM -rf $MASTER_MYDDIR $SLAVE_MYDDIR $MY_LOG_DIR/*
$ECHO "Installing Master Databases"
$INSTALL_DB
if [ $? != 0 ]; then
@@ -446,25 +559,31 @@ mysql_install_db () {
error "Could not install slave test DBs"
exit 1
fi
- # Give mysqld some time to die.
- sleep $SLEEP_TIME
+
+ for slave_num in 1 2 ;
+ do
+ $RM -rf var/slave$slave_num-data/
+ mkdir -p var/slave$slave_num-data/mysql
+ mkdir -p var/slave$slave_num-data/test
+ cp var/slave-data/mysql/* var/slave$slave_num-data/mysql
+ done
return 0
}
gprof_prepare ()
{
- rm -rf $GPROF_DIR
- mkdir -p $GPROF_DIR
+ $RM -rf $GPROF_DIR
+ mkdir -p $GPROF_DIR
}
gprof_collect ()
{
if [ -f $MASTER_MYDDIR/gmon.out ]; then
- gprof $MYSQLD $MASTER_MYDDIR/gmon.out > $GPROF_MASTER
+ gprof $MASTER_MYSQLD $MASTER_MYDDIR/gmon.out > $GPROF_MASTER
echo "Master execution profile has been saved in $GPROF_MASTER"
fi
if [ -f $SLAVE_MYDDIR/gmon.out ]; then
- gprof $MYSQLD $SLAVE_MYDDIR/gmon.out > $GPROF_SLAVE
+ gprof $SLAVE_MYSQLD $SLAVE_MYDDIR/gmon.out > $GPROF_SLAVE
echo "Slave execution profile has been saved in $GPROF_SLAVE"
fi
}
@@ -489,173 +608,355 @@ gcov_collect () {
$ECHO "gcov info in $GCOV_MSG, errors in $GCOV_ERR"
}
+abort_if_failed()
+{
+ if [ ! $? = 0 ] ; then
+ echo $1
+ exit 1
+ fi
+}
+
+start_manager()
+{
+ if [ $USE_MANAGER = 0 ] ; then
+ echo "Manager disabled, skipping manager start."
+ $RM -f $MYSQL_MANAGER_LOG
+ return
+ fi
+ $ECHO "Starting MySQL Manager"
+ if [ -f "$MANAGER_PID_FILE" ] ; then
+ kill `cat $MANAGER_PID_FILE`
+ sleep 1
+ if [ -f "$MANAGER_PID_FILE" ] ; then
+ kill -9 `cat $MANAGER_PID_FILE`
+ sleep 1
+ fi
+ fi
+
+ $RM -f $MANAGER_PID_FILE
+ MYSQL_MANAGER_PW=`$MYSQL_MANAGER_PWGEN -u $MYSQL_MANAGER_USER \
+ -o $MYSQL_MANAGER_PW_FILE`
+ $MYSQL_MANAGER --log=$MYSQL_MANAGER_LOG --port=$MYSQL_MANAGER_PORT \
+ --password-file=$MYSQL_MANAGER_PW_FILE --pid-file=$MANAGER_PID_FILE
+ abort_if_failed "Could not start MySQL manager"
+ mysqltest_manager_args="--manager-host=localhost \
+ --manager-user=$MYSQL_MANAGER_USER \
+ --manager-password=$MYSQL_MANAGER_PW \
+ --manager-port=$MYSQL_MANAGER_PORT \
+ --manager-wait-timeout=$START_WAIT_TIMEOUT"
+ MYSQL_TEST="$MYSQL_TEST $mysqltest_manager_args"
+ MYSQL_TEST_ARGS="$MYSQL_TEST_ARGS $mysqltest_manager_args"
+ while [ ! -f $MANAGER_PID_FILE ] ; do
+ sleep 1
+ done
+ echo "Manager started"
+}
+
+stop_manager()
+{
+ if [ $USE_MANAGER = 0 ] ; then
+ return
+ fi
+ $MYSQL_MANAGER_CLIENT $MANAGER_QUIET_OPT -u$MYSQL_MANAGER_USER \
+ -p$MYSQL_MANAGER_PW -P $MYSQL_MANAGER_PORT <<EOF
+shutdown
+EOF
+ echo "Manager terminated"
+
+}
+
+manager_launch()
+{
+ ident=$1
+ shift
+ if [ $USE_MANAGER = 0 ] ; then
+ $@ >$CUR_MYERR 2>&1 &
+ sleep 2 #hack
+ return
+ fi
+ $MYSQL_MANAGER_CLIENT $MANAGER_QUIET_OPT --user=$MYSQL_MANAGER_USER \
+ --password=$MYSQL_MANAGER_PW --port=$MYSQL_MANAGER_PORT <<EOF
+def_exec $ident $@
+set_exec_stdout $ident $CUR_MYERR
+set_exec_stderr $ident $CUR_MYERR
+set_exec_con $ident root localhost $CUR_MYSOCK
+start_exec $ident $START_WAIT_TIMEOUT
+EOF
+ abort_if_failed "Could not execute manager command"
+}
+
+manager_term()
+{
+ ident=$1
+ shift
+ if [ $USE_MANAGER = 0 ] ; then
+ $MYSQLADMIN --no-defaults -uroot --socket=$MYSQL_TMP_DIR/$ident.sock -O \
+ connect_timeout=5 -O shutdown_timeout=20 shutdown >> $MYSQL_MANAGER_LOG 2>&1
+ return
+ fi
+ $MYSQL_MANAGER_CLIENT $MANAGER_QUIET_OPT --user=$MYSQL_MANAGER_USER \
+ --password=$MYSQL_MANAGER_PW --port=$MYSQL_MANAGER_PORT <<EOF
+stop_exec $ident $STOP_WAIT_TIMEOUT
+EOF
+ abort_if_failed "Could not execute manager command"
+}
+
start_master()
{
- [ x$MASTER_RUNNING = 1 ] && return
- #run master initialization shell script if one exists
- if [ -f "$master_init_script" ] ;
- then
- /bin/sh $master_init_script
- fi
- cd $BASEDIR # for gcov
- # Remove old berkeley db log files that can confuse the server
- $RM -f $MASTER_MYDDIR/log.*
- #start master
- if [ -z "$DO_BENCH" ]
- then
- master_args="--no-defaults --log-bin=master-bin \
- --server-id=1 \
- --basedir=$MY_BASEDIR \
- --port=$MASTER_MYPORT \
- --exit-info=256 \
- --core \
- --datadir=$MASTER_MYDDIR \
- --pid-file=$MASTER_MYPID \
- --socket=$MASTER_MYSOCK \
- --log=$MASTER_MYLOG \
- --character-sets-dir=$CHARSETSDIR \
- --tmpdir=$MYSQL_TMP_DIR \
- --language=$LANGUAGE \
- --innodb_data_file_path=ibdata1:50M \
- $SMALL_SERVER \
- $EXTRA_MASTER_OPT $EXTRA_MASTER_MYSQLD_OPT"
- else
- master_args="--no-defaults --log-bin=master-bin --server-id=1 \
- --basedir=$MY_BASEDIR \
- --port=$MASTER_MYPORT \
- --datadir=$MASTER_MYDDIR \
- --pid-file=$MASTER_MYPID \
- --socket=$MASTER_MYSOCK \
- --default-character-set=$CHARACTER_SET \
- --core \
- --tmpdir=$MYSQL_TMP_DIR \
- --language=$LANGUAGE \
- --innodb_data_file_path=ibdata1:50M \
- $SMALL_SERVER \
- $EXTRA_MASTER_OPT $EXTRA_MASTER_MYSQLD_OPT"
- fi
- if [ x$DO_DDD = x1 ]
- then
- $ECHO "set args $master_args" > $GDB_MASTER_INIT
- ddd --debugger "gdb -x $GDB_MASTER_INIT" $MYSQLD &
- prompt_user "Hit enter to continue after you've started the master"
- elif [ x$DO_GDB = x1 ]
+ if [ x$MASTER_RUNNING = x1 ] || [ x$LOCAL_MASTER = x1 ] ; then
+ return
+ fi
+ # Remove old berkeley db log files that can confuse the server
+ $RM -f $MASTER_MYDDIR/log.*
+ # Remove stale binary logs
+ $RM -f $MYSQL_TEST_DIR/var/log/master-bin.*
+
+ #run master initialization shell script if one exists
+
+ if [ -f "$master_init_script" ] ;
+ then
+ /bin/sh $master_init_script
+ fi
+ cd $BASEDIR # for gcov
+ #start master
+ if [ -z "$DO_BENCH" ]
+ then
+ master_args="--no-defaults --log-bin=$MYSQL_TEST_DIR/var/log/master-bin \
+ --server-id=1 \
+ --basedir=$MY_BASEDIR \
+ --port=$MASTER_MYPORT \
+ --exit-info=256 \
+ --core \
+ --datadir=$MASTER_MYDDIR \
+ --pid-file=$MASTER_MYPID \
+ --socket=$MASTER_MYSOCK \
+ --log=$MASTER_MYLOG \
+ --character-sets-dir=$CHARSETSDIR \
+ --default-character-set=$CHARACTER_SET \
+ --tmpdir=$MYSQL_TMP_DIR \
+ --language=$LANGUAGE \
+ --innodb_data_file_path=ibdata1:50M \
+ $MASTER_40_ARGS \
+ $SMALL_SERVER \
+ $EXTRA_MASTER_OPT $EXTRA_MASTER_MYSQLD_OPT"
+ else
+ master_args="--no-defaults --log-bin=$MYSQL_TEST_DIR/var/log/master-bin \
+ --server-id=1 --rpl-recovery-rank=1 \
+ --basedir=$MY_BASEDIR --init-rpl-role=master \
+ --port=$MASTER_MYPORT \
+ --datadir=$MASTER_MYDDIR \
+ --pid-file=$MASTER_MYPID \
+ --socket=$MASTER_MYSOCK \
+ --character-sets-dir=$CHARSETSDIR \
+ --default-character-set=$CHARACTER_SET \
+ --core \
+ --tmpdir=$MYSQL_TMP_DIR \
+ --language=$LANGUAGE \
+ --innodb_data_file_path=ibdata1:50M \
+ $MASTER_40_ARGS \
+ $SMALL_SERVER \
+ $EXTRA_MASTER_OPT $EXTRA_MASTER_MYSQLD_OPT"
+ fi
+
+ CUR_MYERR=$MASTER_MYERR
+ CUR_MYSOCK=$MASTER_MYSOCK
+
+ if [ x$DO_DDD = x1 ]
+ then
+ $ECHO "set args $master_args" > $GDB_MASTER_INIT
+ manager_launch master ddd -display $DISPLAY --debugger \
+ "gdb -x $GDB_MASTER_INIT" $MASTER_MYSQLD
+ elif [ x$DO_GDB = x1 ]
+ then
+ if [ x$MANUAL_GDB = x1 ]
then
$ECHO "set args $master_args" > $GDB_MASTER_INIT
- xterm -title "Master" -e gdb -x $GDB_MASTER_INIT $MYSQLD &
- prompt_user "Hit enter to continue after you've started the master"
- else
- $MYSQLD $master_args >> $MASTER_MYERR 2>&1 &
- fi
- wait_for_server_start $MASTER_MYPORT
+ $ECHO "To start gdb for the master , type in another window:"
+ $ECHO "cd $CWD ; gdb -x $GDB_MASTER_INIT $MASTER_MYSQLD"
+ wait_for_master=1500
+ else
+ ( $ECHO set args $master_args;
+ if [ $USE_MANAGER = 0 ] ; then
+ cat <<EOF
+b mysql_parse
+commands 1
+disa 1
+end
+r
+EOF
+ fi ) > $GDB_MASTER_INIT
+ manager_launch master $XTERM -display $DISPLAY \
+ -title "Master" -e gdb -x $GDB_MASTER_INIT $MASTER_MYSQLD
+ fi
+ else
+ manager_launch master $MASTER_MYSQLD $master_args
+ fi
+ sleep_until_file_created $MASTER_MYPID $wait_for_master
+ wait_for_master=$SLEEP_TIME_FOR_SECOND_MASTER
MASTER_RUNNING=1
}
start_slave()
{
- [ x$SKIP_SLAVE = x1 ] && return
- [ x$SLAVE_RUNNING = 1 ] && return
-
- #run slave initialization shell script if one exists
- if [ -f "$slave_init_script" ] ;
- then
- /bin/sh $slave_init_script
- fi
-
- if [ -z "$SLAVE_MASTER_INFO" ] ; then
- master_info="--master-user=root \
- --master-connect-retry=1 \
- --master-host=127.0.0.1 \
- --master-password= \
- --master-port=$MASTER_MYPORT \
- --server-id=2"
- else
- master_info=$SLAVE_MASTER_INFO
- fi
-
- $RM -f $SLAVE_MYDDIR/log.*
- slave_args="--no-defaults $master_info \
- --exit-info=256 \
- --log-bin=slave-bin --log-slave-updates \
- --log=$SLAVE_MYLOG \
- --basedir=$MY_BASEDIR \
- --datadir=$SLAVE_MYDDIR \
- --pid-file=$SLAVE_MYPID \
- --port=$SLAVE_MYPORT \
- --socket=$SLAVE_MYSOCK \
- --character-sets-dir=$CHARSETSDIR \
- --core \
- --tmpdir=$MYSQL_TMP_DIR \
- --language=$LANGUAGE \
- --skip-innodb --skip-slave-start \
- --master-retry-count=5 \
- $SMALL_SERVER \
- $EXTRA_SLAVE_OPT $EXTRA_SLAVE_MYSQLD_OPT"
- if [ x$DO_DDD = x1 ]
- then
- $ECHO "set args $master_args" > $GDB_SLAVE_INIT
- ddd --debugger "gdb -x $GDB_SLAVE_INIT" $SLAVE_MYSQLD &
- prompt_user "Hit enter to continue after you've started the slave"
- elif [ x$DO_GDB = x1 ]
+ [ x$SKIP_SLAVE = x1 ] && return
+ eval "this_slave_running=\$SLAVE$1_RUNNING"
+ [ x$this_slave_running = 1 ] && return
+ #when testing fail-safe replication, we will have more than one slave
+ #in this case, we start secondary slaves with an argument
+ slave_ident="slave$1"
+ if [ -n "$1" ] ;
+ then
+ slave_server_id=`$EXPR 2 + $1`
+ slave_rpl_rank=$slave_server_id
+ slave_port=`expr $SLAVE_MYPORT + $1`
+ slave_log="$SLAVE_MYLOG.$1"
+ slave_err="$SLAVE_MYERR.$1"
+ slave_datadir="var/$slave_ident-data/"
+ slave_pid="$MYRUN_DIR/mysqld-$slave_ident.pid"
+ slave_sock="$SLAVE_MYSOCK-$1"
+ else
+ slave_server_id=2
+ slave_rpl_rank=2
+ slave_port=$SLAVE_MYPORT
+ slave_log=$SLAVE_MYLOG
+ slave_err=$SLAVE_MYERR
+ slave_datadir=$SLAVE_MYDDIR
+ slave_pid=$SLAVE_MYPID
+ slave_sock="$SLAVE_MYSOCK"
+ fi
+ # Remove stale binary logs
+ $RM -f $MYSQL_TEST_DIR/var/log/$slave_ident-bin.*
+
+ #run slave initialization shell script if one exists
+ if [ -f "$slave_init_script" ] ;
+ then
+ /bin/sh $slave_init_script
+ fi
+
+ if [ -z "$SLAVE_MASTER_INFO" ] ; then
+ master_info="--master-user=root \
+ --master-connect-retry=1 \
+ --master-host=127.0.0.1 \
+ --master-password= \
+ --master-port=$MASTER_MYPORT \
+ --server-id=$slave_server_id --rpl-recovery-rank=$slave_rpl_rank"
+ else
+ master_info=$SLAVE_MASTER_INFO
+ fi
+
+ $RM -f $slave_datadir/log.*
+ slave_args="--no-defaults $master_info \
+ --exit-info=256 \
+ --log-bin=$MYSQL_TEST_DIR/var/log/$slave_ident-bin \
+ --relay-log=$MYSQL_TEST_DIR/var/log/$slave_ident-relay-bin \
+ --log-slave-updates \
+ --log=$slave_log \
+ --basedir=$MY_BASEDIR \
+ --datadir=$slave_datadir \
+ --pid-file=$slave_pid \
+ --port=$slave_port \
+ --socket=$slave_sock \
+ --character-sets-dir=$CHARSETSDIR \
+ --default-character-set=$CHARACTER_SET \
+ --core --init-rpl-role=slave \
+ --tmpdir=$MYSQL_TMP_DIR \
+ --language=$LANGUAGE \
+ --skip-innodb --skip-slave-start \
+ --slave-load-tmpdir=$SLAVE_LOAD_TMPDIR \
+ --report-host=127.0.0.1 --report-user=root \
+ --report-port=$slave_port \
+ --master-retry-count=5 \
+ $SMALL_SERVER \
+ $EXTRA_SLAVE_OPT $EXTRA_SLAVE_MYSQLD_OPT"
+ CUR_MYERR=$slave_err
+ CUR_MYSOCK=$slave_sock
+
+ if [ x$DO_DDD = x1 ]
+ then
+ $ECHO "set args $master_args" > $GDB_SLAVE_INIT
+ manager_launch $slave_ident ddd -display $DISPLAY --debugger \
+ "gdb -x $GDB_SLAVE_INIT" $SLAVE_MYSQLD
+ elif [ x$DO_GDB = x1 ]
+ then
+ $ECHO "set args $slave_args" > $GDB_SLAVE_INIT
+ if [ x$MANUAL_GDB = x1 ]
then
- $ECHO "set args $slave_args" > $GDB_SLAVE_INIT
- xterm -title "Slave" -e gdb -x $GDB_SLAVE_INIT $SLAVE_MYSQLD &
- prompt_user "Hit enter to continue after you've started the slave"
+ echo "To start gdb for the slave, type in another window:"
+ echo "cd $CWD ; gdb -x $GDB_SLAVE_INIT $SLAVE_MYSQLD"
+ wait_for_slave=1500
else
- $SLAVE_MYSQLD $slave_args >> $SLAVE_MYERR 2>&1 &
+ manager_launch $slave_ident $XTERM -display $DISPLAY -title "Slave" -e \
+ gdb -x $GDB_SLAVE_INIT $SLAVE_MYSQLD
fi
- wait_for_server_start $SLAVE_MYPORT
- SLAVE_RUNNING=1
+ else
+ manager_launch $slave_ident $SLAVE_MYSQLD $slave_args
+ fi
+ eval "SLAVE$1_RUNNING=1"
+ sleep_until_file_created $slave_pid $wait_for_slave
+ wait_for_slave=$SLEEP_TIME_FOR_SECOND_SLAVE
}
-mysql_start () {
- $ECHO "Starting MySQL daemon"
- start_master
- start_slave
- cd $MYSQL_TEST_DIR
- return 1
+mysql_start ()
+{
+ $ECHO "Starting MySQL daemon"
+ start_master
+ start_slave
+ cd $MYSQL_TEST_DIR
+ return 1
}
stop_slave ()
{
- if [ x$SLAVE_RUNNING = x1 ]
+ eval "this_slave_running=\$SLAVE$1_RUNNING"
+ slave_ident="slave$1"
+ if [ -n "$1" ] ;
then
- $MYSQLADMIN --no-defaults --socket=$SLAVE_MYSOCK -u root -O shutdown_timeout=20 shutdown
- if [ $? != 0 ] && [ -f $SLAVE_MYPID ]
+ slave_pid="$MYRUN_DIR/mysqld-$slave_ident.pid"
+ else
+ slave_pid=$SLAVE_MYPID
+ fi
+ if [ x$this_slave_running = x1 ]
+ then
+ manager_term $slave_ident
+ if [ $? != 0 ] && [ -f $slave_pid ]
then # try harder!
- $ECHO "slave not cooperating with mysqladmin, will try manual kill"
- kill `$CAT $SLAVE_MYPID`
- sleep $SLEEP_TIME
- if [ -f $SLAVE_MYPID ] ; then
- $ECHO "slave refused to die. Sending SIGKILL"
- kill -9 `$CAT $SLAVE_MYPID`
- $RM -f $SLAVE_MYPID
- else
- $ECHO "slave responded to SIGTERM "
- fi
+ $ECHO "slave not cooperating with mysqladmin, will try manual kill"
+ kill `$CAT $slave_pid`
+ sleep_until_file_deleted $slave_pid
+ if [ -f $slave_pid ] ; then
+ $ECHO "slave refused to die. Sending SIGKILL"
+ kill -9 `$CAT $slave_pid`
+ $RM -f $slave_pid
+ else
+ $ECHO "slave responded to SIGTERM "
+ fi
+ else
+ sleep $SLEEP_TIME_AFTER_RESTART
fi
- SLAVE_RUNNING=0
- fi
+ eval "SLAVE$1_RUNNING=0"
+ fi
}
stop_master ()
{
if [ x$MASTER_RUNNING = x1 ]
then
- $MYSQLADMIN --no-defaults --socket=$MASTER_MYSOCK -u root -O shutdown_timeout=20 shutdown
+ manager_term master
if [ $? != 0 ] && [ -f $MASTER_MYPID ]
then # try harder!
- $ECHO "master not cooperating with mysqladmin, will try manual kill"
- kill `$CAT $MASTER_MYPID`
- sleep $SLEEP_TIME
- if [ -f $MASTER_MYPID ] ; then
- $ECHO "master refused to die. Sending SIGKILL"
- kill -9 `$CAT $MASTER_MYPID`
- $RM -f $MASTER_MYPID
- else
- $ECHO "master responded to SIGTERM "
- fi
+ $ECHO "master not cooperating with mysqladmin, will try manual kill"
+ kill `$CAT $MASTER_MYPID`
+ sleep_until_file_deleted $MASTER_MYPID
+ if [ -f $MASTER_MYPID ] ; then
+ $ECHO "master refused to die. Sending SIGKILL"
+ kill -9 `$CAT $MASTER_MYPID`
+ $RM -f $MASTER_MYPID
+ else
+ $ECHO "master responded to SIGTERM "
+ fi
+ else
+ sleep $SLEEP_TIME_AFTER_RESTART
fi
MASTER_RUNNING=0
fi
@@ -669,22 +970,23 @@ mysql_stop ()
stop_master
$ECHO "Master shutdown finished"
stop_slave
+ stop_slave 1
+ stop_slave 2
$ECHO "Slave shutdown finished"
-
+
return 1
}
-mysql_restart () {
-
- mysql_stop
- mysql_start
-
- return 1
+mysql_restart ()
+{
+ mysql_stop
+ mysql_start
+ return 1
}
mysql_loadstd () {
-
- # cp $STD_DATA/*.frm $STD_DATA/*.MRG $MASTER_MYDDIR/test
+
+ # cp $STD_DATA/*.frm $STD_DATA/*.MRG $MASTER_MYDDIR/test
return 1
}
@@ -698,7 +1000,11 @@ run_testcase ()
slave_init_script=$TESTDIR/$tname-slave.sh
slave_master_info_file=$TESTDIR/$tname-slave-master-info.opt
SKIP_SLAVE=`$EXPR \( $tname : rpl \) = 0`
- if [ -n "$SKIP_TEST" ] ; then
+ if [ $USE_MANAGER = 1 ] ; then
+ many_slaves=`$EXPR \( $tname : rpl_failsafe \) != 0`
+ fi
+
+ if [ -n "$SKIP_TEST" ] ; then
SKIP_THIS_TEST=`$EXPR \( $tname : "$SKIP_TEST" \) != 0`
if [ x$SKIP_THIS_TEST = x1 ] ;
then
@@ -706,7 +1012,7 @@ run_testcase ()
fi
fi
- if [ -n "$DO_TEST" ] ; then
+ if [ -n "$DO_TEST" ] ; then
DO_THIS_TEST=`$EXPR \( $tname : "$DO_TEST" \) != 0`
if [ x$DO_THIS_TEST = x0 ] ;
then
@@ -732,7 +1038,7 @@ run_testcase ()
then
if [ -f $master_opt_file ] ;
then
- EXTRA_MASTER_OPT=`$CAT $master_opt_file`
+ EXTRA_MASTER_OPT=`$CAT $master_opt_file | $SED -e "s;\\$MYSQL_TEST_DIR;$MYSQL_TEST_DIR;"`
stop_master
start_master
else
@@ -741,20 +1047,20 @@ run_testcase ()
EXTRA_MASTER_OPT=""
stop_master
start_master
- fi
+ fi
fi
do_slave_restart=0
-
+
if [ -f $slave_opt_file ] ;
then
- EXTRA_SLAVE_OPT=`$CAT $slave_opt_file`
+ EXTRA_SLAVE_OPT=`$CAT $slave_opt_file | $SED -e "s;\\$MYSQL_TEST_DIR;$MYSQL_TEST_DIR;"`
do_slave_restart=1
else
if [ ! -z "$EXTRA_SLAVE_OPT" ] || [ x$SLAVE_RUNNING != x1 ] ;
then
EXTRA_SLAVE_OPT=""
- do_slave_restart=1
- fi
+ do_slave_restart=1
+ fi
fi
if [ -f $slave_master_info_file ] ; then
@@ -764,26 +1070,30 @@ run_testcase ()
if [ ! -z "$SLAVE_MASTER_INFO" ] || [ x$SLAVE_RUNNING != x1 ] ;
then
SLAVE_MASTER_INFO=""
- do_slave_restart=1
- fi
+ do_slave_restart=1
+ fi
fi
if [ x$do_slave_restart = x1 ] ; then
stop_slave
start_slave
fi
+ if [ x$many_slaves = x1 ]; then
+ start_slave 1
+ start_slave 2
+ fi
fi
cd $MYSQL_TEST_DIR
-
+
if [ -f $tf ] ; then
$RM -f r/$tname.*reject
mysql_test_args="-R r/$tname.result $EXTRA_MYSQL_TEST_OPT"
- if [ -z "$DO_CLIENT_GDB" ] ; then
- mytime=`$TIME -p $MYSQL_TEST $mysql_test_args < $tf 2> $TIMEFILE`
+ if [ -z "$DO_CLIENT_GDB" ] ; then
+ mytime=`$TIME -p $MYSQL_TEST $mysql_test_args < $tf 2> $TIMEFILE`
else
- do_gdb_test "$mysql_test_args" "$tf"
+ do_gdb_test "$mysql_test_args" "$tf"
fi
-
+
res=$?
if [ $res = 0 ]; then
@@ -805,6 +1115,11 @@ run_testcase ()
pname=`$ECHO "$tname "|$CUT -c 1-24`
RES="$pname $timestr"
+ if [ x$many_slaves = x1 ] ; then
+ stop_slave 1
+ stop_slave 2
+ fi
+
if [ $res = 0 ]; then
total_inc
pass_inc
@@ -828,10 +1143,11 @@ run_testcase ()
if [ -z "$DO_GDB" ] && [ -z "$USE_RUNNING_SERVER" ] && [ -z "$DO_DDD" ]
then
mysql_stop
+ stop_manager
fi
exit 1
fi
-
+
if [ -z "$DO_GDB" ] && [ -z "$USE_RUNNING_SERVER" ] && [ -z "$DO_DDD" ]
then
mysql_restart
@@ -843,26 +1159,49 @@ run_testcase ()
fi
}
-
######################################################################
# Main script starts here
######################################################################
[ "$DO_GCOV" -a ! -x "$GCOV" ] && error "No gcov found"
-[ "$DO_GCOV" ] && gcov_prepare
-[ "$DO_GPROF" ] && gprof_prepare
+[ "$DO_GCOV" ] && gcov_prepare
+[ "$DO_GPROF" ] && gprof_prepare
-# Ensure that no old mysqld test servers are running
if [ -z "$USE_RUNNING_SERVER" ]
then
- $MYSQLADMIN --no-defaults --socket=$MASTER_MYSOCK -u root -O connect_timeout=5 shutdown > /dev/null 2>&1
- $MYSQLADMIN --no-defaults --socket=$SLAVE_MYSOCK -u root -O connect_timeout=5 shutdown > /dev/null 2>&1
+ # Ensure that no old mysqld test servers are running
+ $MYSQLADMIN --no-defaults --socket=$MASTER_MYSOCK -u root -O connect_timeout=5 -O shutdown_timeout=20 shutdown > /dev/null 2>&1
+ $MYSQLADMIN --no-defaults --socket=$SLAVE_MYSOCK -u root -O connect_timeout=5 -O shutdown_timeout=20 shutdown > /dev/null 2>&1
+ $MYSQLADMIN --no-defaults --host=$hostname --port=$MASTER_MYPORT -u root -O connect_timeout=5 -O shutdown_timeout=20 shutdown > /dev/null 2>&1
+ $MYSQLADMIN --no-defaults --host=$hostname --port=$SLAVE_MYPORT -u root -O connect_timeout=5 -O shutdown_timeout=20 shutdown > /dev/null 2>&1
+ $MYSQLADMIN --no-defaults --host=$hostname --port=`expr $SLAVE_MYPORT + 1` -u root -O connect_timeout=5 -O shutdown_timeout=20 shutdown > /dev/null 2>&1
+ sleep_until_file_deleted $MASTER_MYPID
+ sleep_until_file_deleted $SLAVE_MYPID
+
+ # Kill any running managers
+ if [ -f "$MANAGER_PID_FILE" ]
+ then
+ kill `cat $MANAGER_PID_FILE`
+ sleep 1
+ if [ -f "$MANAGER_PID_FILE" ]
+ then
+ kill -9 `cat $MANAGER_PID_FILE`
+ sleep 1
+ fi
+ fi
+
+ # Remove files that can cause problems
+ $RM -f $MYSQL_TEST_DIR/var/run/* $MYSQL_TEST_DIR/var/tmp/*
+
+ wait_for_master=$SLEEP_TIME_FOR_FIRST_MASTER
+ wait_for_slave=$SLEEP_TIME_FOR_FIRST_SLAVE
$ECHO "Installing Test Databases"
mysql_install_db
+ start_manager
-#do not automagically start deamons if we are in gdb or running only one test
-#case
+# Do not automagically start deamons if we are in gdb or running only one test
+# case
if [ -z "$DO_GDB" ] && [ -z "$DO_DDD" ]
then
mysql_start
@@ -871,31 +1210,35 @@ then
mysql_loadstd
fi
+if [ "x$START_AND_EXIT" = "x1" ] ; then
+ echo "Servers started, exiting"
+ exit
+fi
$ECHO "Starting Tests"
if [ "$DO_BENCH" = 1 ]
then
- BENCHDIR=$BASEDIR/sql-bench/
- savedir=`pwd`
- cd $BENCHDIR
- if [ -z "$1" ]
- then
- ./run-all-tests --socket=$MASTER_MYSOCK --user=root
- else
- if [ -x "./$1" ]
+ BENCHDIR=$BASEDIR/sql-bench/
+ savedir=`pwd`
+ cd $BENCHDIR
+ if [ -z "$1" ]
then
- ./$1 --socket=$MASTER_MYSOCK --user=root
+ ./run-all-tests --socket=$MASTER_MYSOCK --user=root
else
- echo "benchmark $1 not found"
+ if [ -x "./$1" ]
+ then
+ ./$1 --socket=$MASTER_MYSOCK --user=root
+ else
+ echo "benchmark $1 not found"
+ fi
fi
- fi
- cd $savedir
- mysql_stop
- exit
+ cd $savedir
+ mysql_stop
+ stop_manager
+ exit
fi
-
$ECHO
$ECHO " TEST USER SYSTEM ELAPSED RESULT"
$ECHO $DASH72
@@ -911,14 +1254,17 @@ then
done
$RM -f $TIMEFILE # Remove for full test
fi
-else
-tname=`$BASENAME $1 .test`
- tf=$TESTDIR/$tname.$TESTSUFFIX
- if [ -f $tf ] ; then
- run_testcase $tf
- else
- $ECHO "Test case $tf does not exist."
- fi
+else
+ while [ ! -z "$1" ]; do
+ tname=`$BASENAME $1 .test`
+ tf=$TESTDIR/$tname.$TESTSUFFIX
+ if [ -f $tf ] ; then
+ run_testcase $tf
+ else
+ $ECHO "Test case $tf does not exist."
+ fi
+ shift
+ done
fi
$ECHO $DASH72
@@ -929,6 +1275,7 @@ then
mysql_stop
fi
+stop_manager
report_stats
$ECHO
diff --git a/mysql-test/r/alias.result b/mysql-test/r/alias.result
index 61a65f68007..3954c2d0170 100644
--- a/mysql-test/r/alias.result
+++ b/mysql-test/r/alias.result
@@ -1,2 +1,61 @@
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (
+cont_nr int(11) NOT NULL auto_increment,
+ver_nr int(11) NOT NULL default '0',
+aufnr int(11) NOT NULL default '0',
+username varchar(50) NOT NULL default '',
+hdl_nr int(11) NOT NULL default '0',
+eintrag date NOT NULL default '0000-00-00',
+st_klasse varchar(40) NOT NULL default '',
+st_wert varchar(40) NOT NULL default '',
+st_zusatz varchar(40) NOT NULL default '',
+st_bemerkung varchar(255) NOT NULL default '',
+kunden_art varchar(40) NOT NULL default '',
+mcbs_knr int(11) default NULL,
+mcbs_aufnr int(11) NOT NULL default '0',
+schufa_status char(1) default '?',
+bemerkung text,
+wirknetz text,
+wf_igz int(11) NOT NULL default '0',
+tarifcode varchar(80) default NULL,
+recycle char(1) default NULL,
+sim varchar(30) default NULL,
+mcbs_tpl varchar(30) default NULL,
+emp_nr int(11) NOT NULL default '0',
+laufzeit int(11) default NULL,
+hdl_name varchar(30) default NULL,
+prov_hdl_nr int(11) NOT NULL default '0',
+auto_wirknetz varchar(50) default NULL,
+auto_billing varchar(50) default NULL,
+touch timestamp(14) NOT NULL,
+kategorie varchar(50) default NULL,
+kundentyp varchar(20) NOT NULL default '',
+sammel_rech_msisdn varchar(30) NOT NULL default '',
+p_nr varchar(9) NOT NULL default '',
+suffix char(3) NOT NULL default '',
+PRIMARY KEY (cont_nr),
+KEY idx_aufnr(aufnr),
+KEY idx_hdl_nr(hdl_nr),
+KEY idx_st_klasse(st_klasse),
+KEY ver_nr(ver_nr),
+KEY eintrag_idx(eintrag),
+KEY emp_nr_idx(emp_nr),
+KEY wf_igz(wf_igz),
+KEY touch(touch),
+KEY hdl_tag(eintrag,hdl_nr),
+KEY prov_hdl_nr(prov_hdl_nr),
+KEY mcbs_aufnr(mcbs_aufnr),
+KEY kundentyp(kundentyp),
+KEY p_nr(p_nr,suffix)
+) TYPE=MyISAM;
+INSERT INTO t1 VALUES (3359356,405,3359356,'Mustermann Musterfrau',52500,'2000-05-20','workflow','Auftrag erledigt','Originalvertrag eingegangen und geprüft','','privat',1485525,2122316,'+','','N',1909160,'MobilComSuper92000D2',NULL,NULL,'MS9ND2',3,24,'MobilCom Shop Koeln',52500,NULL,'auto',20010202105916,'Mobilfunk','PP','','','');
+INSERT INTO t1 VALUES (3359357,468,3359357,'Mustermann Musterfrau',7001,'2000-05-20','workflow','Auftrag erledigt','Originalvertrag eingegangen und geprüft','','privat',1503580,2139699,'+','','P',1909171,'MobilComSuper9D1T10SFreisprech(Akquise)',NULL,NULL,'MS9NS1',327,24,'MobilCom Intern',7003,NULL,'auto',20010202105916,'Mobilfunk','PP','','','');
+INSERT INTO t1 VALUES (3359358,407,3359358,'Mustermann Musterfrau',7001,'2000-05-20','workflow','Auftrag erledigt','Originalvertrag eingegangen und geprüft','','privat',1501358,2137473,'N','','N',1909159,'MobilComSuper92000D2',NULL,NULL,'MS9ND2',325,24,'MobilCom Intern',7003,NULL,'auto',20010202105916,'Mobilfunk','PP','','','');
+INSERT INTO t1 VALUES (3359359,468,3359359,'Mustermann Musterfrau',7001,'2000-05-20','workflow','Auftrag erledigt','Originalvertrag eingegangen und geprüft','','privat',1507831,2143894,'+','','P',1909162,'MobilComSuper9D1T10SFreisprech(Akquise)',NULL,NULL,'MS9NS1',327,24,'MobilCom Intern',7003,NULL,'auto',20010202105916,'Mobilfunk','PP','','','');
+INSERT INTO t1 VALUES (3359360,0,0,'Mustermann Musterfrau',29674907,'2000-05-20','workflow','Auftrag erledigt','Originalvertrag eingegangen und geprüft','','privat',1900169997,2414578,'+',NULL,'N',1909148,'',NULL,NULL,'RV99066_2',20,NULL,'POS',29674907,NULL,NULL,20010202105916,'Mobilfunk','','','97317481','007');
+INSERT INTO t1 VALUES (3359361,406,3359361,'Mustermann Musterfrau',7001,'2000-05-20','workflow','Auftrag storniert','','(7001-84):Storno, Kd. möchte nicht mehr','privat',NULL,0,'+','','P',1909150,'MobilComSuper92000D1(Akquise)',NULL,NULL,'MS9ND1',325,24,'MobilCom Intern',7003,NULL,'auto',20010202105916,'Mobilfunk','PP','','','');
+INSERT INTO t1 VALUES (3359362,406,3359362,'Mustermann Musterfrau',7001,'2000-05-20','workflow','Auftrag erledigt','Originalvertrag eingegangen und geprüft','','privat',1509984,2145874,'+','','P',1909154,'MobilComSuper92000D1(Akquise)',NULL,NULL,'MS9ND1',327,24,'MobilCom Intern',7003,NULL,'auto',20010202105916,'Mobilfunk','PP','','','');
+SELECT ELT(FIELD(kundentyp,'PP','PPA','PG','PGA','FK','FKA','FP','FPA','K','KA','V','VA',''), 'Privat (Private Nutzung)','Privat (Private Nutzung) Sitz im Ausland','Privat (geschaeftliche Nutzung)','Privat (geschaeftliche Nutzung) Sitz im Ausland','Firma (Kapitalgesellschaft)','Firma (Kapitalgesellschaft) Sitz im Ausland','Firma (Personengesellschaft)','Firma (Personengesellschaft) Sitz im Ausland','oeff. rechtl. Koerperschaft','oeff. rechtl. Koerperschaft Sitz im Ausland','Eingetragener Verein','Eingetragener Verein Sitz im Ausland','Typ unbekannt') AS Kundentyp ,kategorie FROM t1 WHERE hdl_nr < 2000000 AND kategorie IN ('Prepaid','Mobilfunk') AND st_klasse = 'Workflow' GROUP BY kundentyp ORDER BY kategorie;
Kundentyp kategorie
Privat (Private Nutzung) Mobilfunk
+drop table t1;
diff --git a/mysql-test/r/alter_table.result b/mysql-test/r/alter_table.result
index dbdbb7f57a9..f0c3e2d162a 100644
--- a/mysql-test/r/alter_table.result
+++ b/mysql-test/r/alter_table.result
@@ -1,3 +1,26 @@
+drop table if exists t1;
+create table t1 (
+col1 int not null auto_increment primary key,
+col2 varchar(30) not null,
+col3 varchar (20) not null,
+col4 varchar(4) not null,
+col5 enum('PENDING', 'ACTIVE', 'DISABLED') not null,
+col6 int not null, to_be_deleted int);
+insert into t1 values (2,4,3,5,"PENDING",1,7);
+alter table t1
+add column col4_5 varchar(20) not null after col4,
+add column col7 varchar(30) not null after col5,
+add column col8 datetime not null, drop column to_be_deleted,
+change column col2 fourth varchar(30) not null after col3,
+modify column col6 int not null first;
+select * from t1;
+col6 col1 col3 fourth col4 col4_5 col5 col7 col8
+1 2 3 4 5 PENDING 0000-00-00 00:00:00
+drop table t1;
+create table t1 (bandID MEDIUMINT UNSIGNED NOT NULL PRIMARY KEY, payoutID SMALLINT UNSIGNED NOT NULL);
+insert into t1 (bandID,payoutID) VALUES (1,6),(2,6),(3,4),(4,9),(5,10),(6,1),(7,12),(8,12);
+alter table t1 add column new_col int, order by payoutid,bandid;
+select * from t1;
bandID payoutID new_col
6 1 NULL
3 4 NULL
@@ -7,6 +30,8 @@ bandID payoutID new_col
5 10 NULL
7 12 NULL
8 12 NULL
+alter table t1 order by bandid,payoutid;
+select * from t1;
bandID payoutID new_col
1 6 NULL
2 6 NULL
@@ -16,19 +41,76 @@ bandID payoutID new_col
6 1 NULL
7 12 NULL
8 12 NULL
+drop table t1;
+CREATE TABLE t1 (
+GROUP_ID int(10) unsigned DEFAULT '0' NOT NULL,
+LANG_ID smallint(5) unsigned DEFAULT '0' NOT NULL,
+NAME varchar(80) DEFAULT '' NOT NULL,
+PRIMARY KEY (GROUP_ID,LANG_ID),
+KEY NAME (NAME));
+ALTER TABLE t1 CHANGE NAME NAME CHAR(80) not null;
+SHOW FULL COLUMNS FROM t1;
Field Type Null Key Default Extra Privileges
GROUP_ID int(10) unsigned PRI 0 select,insert,update,references
LANG_ID smallint(5) unsigned PRI 0 select,insert,update,references
NAME char(80) MUL select,insert,update,references
+DROP TABLE t1;
+create table t1 (n int);
+insert into t1 values(9),(3),(12),(10);
+alter table t1 order by n;
+select * from t1;
n
3
9
10
12
+drop table t1;
+CREATE TABLE t1 (
+id int(11) unsigned NOT NULL default '0',
+category_id tinyint(4) unsigned NOT NULL default '0',
+type_id tinyint(4) unsigned NOT NULL default '0',
+body text NOT NULL,
+user_id int(11) unsigned NOT NULL default '0',
+status enum('new','old') NOT NULL default 'new',
+PRIMARY KEY (id)
+) TYPE=MyISAM;
+ALTER TABLE t1 ORDER BY t1.id, t1.status, t1.type_id, t1.user_id, t1.body;
+DROP TABLE t1;
+CREATE TABLE t1 (AnamneseId int(10) unsigned NOT NULL auto_increment,B BLOB,PRIMARY KEY (AnamneseId)) type=myisam;
+insert into t1 values (null,"hello");
+LOCK TABLES t1 WRITE;
+ALTER TABLE t1 ADD Column new_col int not null;
+UNLOCK TABLES;
+OPTIMIZE TABLE t1;
Table Op Msg_type Msg_text
test.t1 optimize status OK
+DROP TABLE t1;
+create table t1 (n1 int not null, n2 int, n3 int, n4 float,
+unique(n1),
+key (n1, n2, n3, n4),
+key (n2, n3, n4, n1),
+key (n3, n4, n1, n2),
+key (n4, n1, n2, n3) );
+alter table t1 disable keys;
+insert into t1 values(10,RAND()*1000,RAND()*1000,RAND());
+insert into t1 values(9,RAND()*1000,RAND()*1000,RAND());
+insert into t1 values(8,RAND()*1000,RAND()*1000,RAND());
+insert into t1 values(7,RAND()*1000,RAND()*1000,RAND());
+insert into t1 values(6,RAND()*1000,RAND()*1000,RAND());
+insert into t1 values(5,RAND()*1000,RAND()*1000,RAND());
+insert into t1 values(4,RAND()*1000,RAND()*1000,RAND());
+insert into t1 values(3,RAND()*1000,RAND()*1000,RAND());
+insert into t1 values(2,RAND()*1000,RAND()*1000,RAND());
+insert into t1 values(1,RAND()*1000,RAND()*1000,RAND());
+alter table t1 enable keys;
+drop table t1;
+create table t1 (i int unsigned not null auto_increment primary key);
+insert into t1 values (null),(null),(null),(null);
+alter table t1 drop i,add i int unsigned not null auto_increment, drop primary key, add primary key (i);
+select * from t1;
i
1
2
3
4
+drop table t1;
diff --git a/mysql-test/r/analyse.result b/mysql-test/r/analyse.result
index f6b8cc2fcbf..c183530df48 100644
--- a/mysql-test/r/analyse.result
+++ b/mysql-test/r/analyse.result
@@ -1,6 +1,13 @@
+drop table if exists t1,t2;
+create table t1 (i int, j int);
+insert into t1 values (1,2), (3,4), (5,6), (7,8);
+select * from t1 procedure analyse();
Field_name Min_value Max_value Min_length Max_length Empties_or_zeros Nulls Avg_value_or_avg_length Std Optimal_fieldtype
t1.i 1 7 1 1 0 0 4.0000 2.2361 ENUM('1','3','5','7') NOT NULL
t1.j 2 8 1 1 0 0 5.0000 2.2361 ENUM('2','4','6','8') NOT NULL
+create table t2 select * from t1 procedure analyse();
+select * from t2;
Field_name Min_value Max_value Min_length Max_length Empties_or_zeros Nulls Avg_value_or_avg_length Std Optimal_fieldtype
t1.i 1 7 1 1 0 0 4.0000 2.2361 ENUM('1','3','5','7') NOT NULL
t1.j 2 8 1 1 0 0 5.0000 2.2361 ENUM('2','4','6','8') NOT NULL
+drop table t1,t2;
diff --git a/mysql-test/r/auto_increment.result b/mysql-test/r/auto_increment.result
index bf6265e5b64..66efd2ba567 100644
--- a/mysql-test/r/auto_increment.result
+++ b/mysql-test/r/auto_increment.result
@@ -1,32 +1,52 @@
+drop table if exists t1;
+create table t1 (a int not null auto_increment,b int, primary key (a)) type=myisam auto_increment=3;
+insert into t1 values (1,1),(NULL,3),(NULL,4);
+delete from t1 where a=4;
+insert into t1 values (NULL,5),(NULL,6);
+select * from t1;
a b
1 1
3 3
5 5
6 6
+delete from t1 where a=6;
+replace t1 values (3,1);
+ALTER TABLE t1 add c int;
+replace t1 values (3,3,3);
+insert into t1 values (NULL,7,7);
+update t1 set a=8,b=b+1,c=c+1 where a=7;
+insert into t1 values (NULL,9,9);
+select * from t1;
a b c
1 1 NULL
3 3 3
5 5 NULL
8 8 8
9 9 9
-a b
-1 1
-5 5
-3 3
-4 4
-6 6
-a b c
-1 1 NULL
-5 5 NULL
-3 3 NULL
-4 4 NULL
-6 6 6
+drop table t1;
+create table t1 (
+skey tinyint unsigned NOT NULL auto_increment PRIMARY KEY,
+sval char(20)
+);
+insert into t1 values (NULL, "hello");
+insert into t1 values (NULL, "hey");
+select * from t1;
skey sval
1 hello
2 hey
+select _rowid,t1._rowid,skey,sval from t1;
_rowid _rowid skey sval
1 1 1 hello
2 2 2 hey
+drop table t1;
+create table t1 (a char(10) not null, b int not null auto_increment, primary key(a,b));
+insert into t1 values ("a",1),("b",2),("a",2),("c",1);
+insert into t1 values ("a",NULL),("b",NULL),("c",NULL),("e",NULL);
+insert into t1 (a) values ("a"),("b"),("c"),("d");
+insert into t1 (a) values ('k'),('d');
+insert into t1 (a) values ("a");
+insert into t1 values ("d",last_insert_id());
+select * from t1;
a b
a 1
a 2
@@ -44,9 +64,17 @@ d 2
d 5
e 1
k 1
+drop table t1;
+create table t1 (ordid int(8) not null auto_increment, ord varchar(50) not null, primary key (ordid), index(ord,ordid));
+insert into t1 (ordid,ord) values (NULL,'sdj'),(NULL,'sdj');
+select * from t1;
ordid ord
1 sdj
2 sdj
+drop table t1;
+create table t1 (ordid int(8) not null auto_increment, ord varchar(50) not null, primary key (ord,ordid));
+insert into t1 values (NULL,'sdj'),(NULL,'sdj'),(NULL,"abc"),(NULL,'abc'),(NULL,'zzz'),(NULL,'sdj'),(NULL,'abc');
+select * from t1;
ordid ord
1 abc
2 abc
@@ -55,8 +83,15 @@ ordid ord
2 sdj
3 sdj
1 zzz
+drop table t1;
+create table t1 (a int not null primary key auto_increment);
+insert into t1 values (0);
+update t1 set a=0;
+select * from t1;
a
0
+check table t1;
Table Op Msg_type Msg_text
test.t1 check warning Found row where the auto_increment column has the value 0
test.t1 check status OK
+drop table t1;
diff --git a/mysql-test/r/backup.result b/mysql-test/r/backup.result
index 2bbe15954dc..43d57d2d4f7 100644
--- a/mysql-test/r/backup.result
+++ b/mysql-test/r/backup.result
@@ -1,43 +1,73 @@
+set SQL_LOG_BIN=0;
+drop table if exists t1;
+create table t1(n int);
+backup table t1 to '../bogus';
Table Op Msg_type Msg_text
test.t1 backup error Failed copying .frm file: errno = X
test.t1 backup status Operation failed
+backup table t1 to '../tmp';
Table Op Msg_type Msg_text
test.t1 backup status OK
+drop table t1;
+restore table t1 from '../tmp';
Table Op Msg_type Msg_text
test.t1 restore status OK
+select count(*) from t1;
count(*)
0
+insert into t1 values (23),(45),(67);
+backup table t1 to '../tmp';
Table Op Msg_type Msg_text
test.t1 backup status OK
+drop table t1;
+restore table t1 from '../bogus';
Table Op Msg_type Msg_text
t1 restore error Failed copying .frm file
+restore table t1 from '../tmp';
Table Op Msg_type Msg_text
test.t1 restore status OK
+select n from t1;
n
23
45
67
+create table t2(m int not null primary key);
+create table t3(k int not null primary key);
+insert into t2 values (123),(145),(167);
+insert into t3 values (223),(245),(267);
+backup table t1,t2,t3 to '../tmp';
Table Op Msg_type Msg_text
test.t1 backup status OK
test.t2 backup status OK
test.t3 backup status OK
+drop table t1,t2,t3;
+restore table t1,t2,t3 from '../tmp';
Table Op Msg_type Msg_text
test.t1 restore status OK
test.t2 restore status OK
test.t3 restore status OK
+select n from t1;
n
23
45
67
+select m from t2;
m
123
145
167
+select k from t3;
k
223
245
267
+drop table t1,t2,t3;
+restore table t1 from '../tmp';
Table Op Msg_type Msg_text
test.t1 restore status OK
+lock tables t1 write;
+backup table t1 to '../tmp';
+unlock tables;
Table Op Msg_type Msg_text
test.t1 backup status OK
+drop table t1;
diff --git a/mysql-test/r/bdb-crash.result b/mysql-test/r/bdb-crash.result
index 8fa8378640b..42c826d55da 100644
--- a/mysql-test/r/bdb-crash.result
+++ b/mysql-test/r/bdb-crash.result
@@ -1,3 +1,32 @@
+drop table if exists t1;
+CREATE TABLE t1 (
+ChargeID int(10) unsigned DEFAULT '0' NOT NULL auto_increment,
+ServiceID int(10) unsigned DEFAULT '0' NOT NULL,
+ChargeDate date DEFAULT '0000-00-00' NOT NULL,
+ChargeAmount decimal(20,2) DEFAULT '0.00' NOT NULL,
+FedTaxes decimal(20,2) DEFAULT '0.00' NOT NULL,
+ProvTaxes decimal(20,2) DEFAULT '0.00' NOT NULL,
+ChargeStatus enum('New','Auth','Unauth','Sale','Denied','Refund')
+DEFAULT 'New' NOT NULL,
+ChargeAuthorizationMessage text,
+ChargeComment text,
+ChargeTimeStamp varchar(20),
+PRIMARY KEY (ChargeID),
+KEY ServiceID (ServiceID),
+KEY ChargeDate (ChargeDate)
+) type=BDB;
+BEGIN;
+INSERT INTO t1
+VALUES(NULL,1,'2001-03-01',1,1,1,'New',NULL,NULL,'now');
+COMMIT;
+BEGIN;
+UPDATE t1 SET ChargeAuthorizationMessage = 'blablabla' WHERE
+ChargeID = 1;
+COMMIT;
+INSERT INTO t1
+VALUES(NULL,1,'2001-03-01',1,1,1,'New',NULL,NULL,'now');
+select * from t1;
ChargeID ServiceID ChargeDate ChargeAmount FedTaxes ProvTaxes ChargeStatus ChargeAuthorizationMessage ChargeComment ChargeTimeStamp
1 1 2001-03-01 1.00 1.00 1.00 New blablabla NULL now
2 1 2001-03-01 1.00 1.00 1.00 New NULL NULL now
+drop table t1;
diff --git a/mysql-test/r/bdb-deadlock.result b/mysql-test/r/bdb-deadlock.result
index 89077d16980..55b3d3ea2a5 100644
--- a/mysql-test/r/bdb-deadlock.result
+++ b/mysql-test/r/bdb-deadlock.result
@@ -1,10 +1,31 @@
+drop table if exists t1,t2;
+create table t1 (id integer, x integer) type=BDB;
+create table t2 (id integer, x integer) type=BDB;
+insert into t1 values(0, 0);
+insert into t2 values(0, 0);
+set autocommit=0;
+update t1 set x = 1 where id = 0;
+set autocommit=0;
+update t2 set x = 1 where id = 0;
+select x from t1 where id = 0;
+select x from t2 where id = 0;
+Deadlock found when trying to get lock; Try restarting transaction
+commit;
x
1
+commit;
+select * from t1;
id x
0 1
+select * from t2;
id x
0 1
+commit;
+select * from t1;
id x
0 1
+select * from t2;
id x
0 1
+commit;
+drop table t1,t2;
diff --git a/mysql-test/r/bdb.result b/mysql-test/r/bdb.result
index 4d26304db4c..7374e936c36 100644
--- a/mysql-test/r/bdb.result
+++ b/mysql-test/r/bdb.result
@@ -1,3 +1,7 @@
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8;
+create table t1 (id int unsigned not null auto_increment, code tinyint unsigned not null, name char(20) not null, primary key (id), key (code), unique (name)) type=bdb;
+insert into t1 (code, name) values (1, 'Tim'), (1, 'Monty'), (2, 'David'), (2, 'Erik'), (3, 'Sasha'), (3, 'Jeremy'), (4, 'Matt');
+select id, code, name from t1 order by id;
id code name
1 1 Tim
2 1 Monty
@@ -6,6 +10,8 @@ id code name
5 3 Sasha
6 3 Jeremy
7 4 Matt
+update ignore t1 set id = 8, name = 'Sinisa' where id < 3;
+select id, code, name from t1 order by id;
id code name
2 1 Monty
3 2 David
@@ -14,6 +20,8 @@ id code name
6 3 Jeremy
7 4 Matt
8 1 Sinisa
+update ignore t1 set id = id + 10, name = 'Ralph' where id < 4;
+select id, code, name from t1 order by id;
id code name
3 2 David
4 2 Erik
@@ -22,10 +30,26 @@ id code name
7 4 Matt
8 1 Sinisa
12 1 Ralph
+drop table t1;
+CREATE TABLE t1 (
+id int(11) NOT NULL auto_increment,
+parent_id int(11) DEFAULT '0' NOT NULL,
+level tinyint(4) DEFAULT '0' NOT NULL,
+PRIMARY KEY (id),
+KEY parent_id (parent_id),
+KEY level (level)
+) type=bdb;
+INSERT INTO t1 VALUES (1,0,0),(3,1,1),(4,1,1),(8,2,2),(9,2,2),(17,3,2),(22,4,2),(24,4,2),(28,5,2),(29,5,2),(30,5,2),(31,6,2),(32,6,2),(33,6,2),(203,7,2),(202,7,2),(20,3,2),(157,0,0),(193,5,2),(40,7,2),(2,1,1),(15,2,2),(6,1,1),(34,6,2),(35,6,2),(16,3,2),(7,1,1),(36,7,2),(18,3,2),(26,5,2),(27,5,2),(183,4,2),(38,7,2),(25,5,2),(37,7,2),(21,4,2),(19,3,2),(5,1,1),(179,5,2);
+update t1 set parent_id=parent_id+100;
+select * from t1 where parent_id=102;
id parent_id level
8 102 2
9 102 2
15 102 2
+update t1 set id=id+1000;
+update t1 set id=1024 where id=1009;
+Duplicate entry '1024' for key 1
+select * from t1;
id parent_id level
1001 100 0
1002 101 1
@@ -66,6 +90,8 @@ id parent_id level
1193 105 2
1202 107 2
1203 107 2
+update ignore t1 set id=id+1;
+select * from t1;
id parent_id level
1001 100 0
1002 101 1
@@ -106,16 +132,22 @@ id parent_id level
1194 105 2
1202 107 2
1204 107 2
+update ignore t1 set id=1023 where id=1010;
+select * from t1 where parent_id=102;
id parent_id level
1008 102 2
1015 102 2
1010 102 2
+explain select level from t1 where level=1;
table type possible_keys key key_len ref rows Extra
t1 ref level level 1 const 1 where used; Using index
+explain select level,id from t1 where level=1;
table type possible_keys key key_len ref rows Extra
t1 ref level level 1 const 1 where used; Using index
+explain select level,id,parent_id from t1 where level=1;
table type possible_keys key key_len ref rows Extra
t1 ref level level 1 const 1 where used
+select level,id from t1 where level=1;
level id
1 1002
1 1003
@@ -123,6 +155,7 @@ level id
1 1005
1 1006
1 1007
+select level,id,parent_id from t1 where level=1;
level id parent_id
1 1002 101
1 1003 101
@@ -130,31 +163,77 @@ level id parent_id
1 1005 101
1 1006 101
1 1007 101
+optimize table t1;
Table Op Msg_type Msg_text
test.t1 optimize status OK
-Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Comment
-t1 0 PRIMARY 1 id A 39 NULL NULL
-t1 1 parent_id 1 parent_id A 9 NULL NULL
-t1 1 level 1 level A 3 NULL NULL
+show keys from t1;
+Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
+t1 0 PRIMARY 1 id A 39 NULL NULL BTREE
+t1 1 parent_id 1 parent_id A 9 NULL NULL BTREE
+t1 1 level 1 level A 3 NULL NULL BTREE
+drop table t1;
+CREATE TABLE t1 (
+gesuchnr int(11) DEFAULT '0' NOT NULL,
+benutzer_id int(11) DEFAULT '0' NOT NULL,
+PRIMARY KEY (gesuchnr,benutzer_id)
+) type=BDB;
+replace into t1 (gesuchnr,benutzer_id) values (2,1);
+replace into t1 (gesuchnr,benutzer_id) values (1,1);
+replace into t1 (gesuchnr,benutzer_id) values (1,1);
+select * from t1;
gesuchnr benutzer_id
1 1
2 1
+drop table t1;
+create table t1 (id int not null primary key, x int not null, key (x)) type=bdb;
+insert into t1 (id, x) values (1, 1);
+replace into t1 (id, x) values (1, 2);
+select * from t1;
id x
1 2
+drop table t1;
+create table t1 (a int) type=bdb;
+insert into t1 values (1), (2);
+optimize table t1;
Table Op Msg_type Msg_text
test.t1 optimize status OK
+delete from t1 where a = 1;
+select * from t1;
a
2
+check table t1;
Table Op Msg_type Msg_text
test.t1 check error The handler for the table doesn't support check/repair
+drop table t1;
+create table t1 (a int,b varchar(20)) type=bdb;
+insert into t1 values (1,""), (2,"testing");
+delete from t1 where a = 1;
+select * from t1;
a b
2 testing
+create index skr on t1 (a);
+insert into t1 values (3,""), (4,"testing");
+analyze table t1;
Table Op Msg_type Msg_text
test.t1 analyze status OK
-Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Comment
-t1 1 skr 1 a A 3 NULL NULL
+show keys from t1;
+Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
+t1 1 skr 1 a A 3 NULL NULL YES BTREE
+drop table t1;
+create table t1 (a int,b varchar(20),key(a)) type=bdb;
+insert into t1 values (1,""), (2,"testing");
+select * from t1 where a = 1;
a b
1
+drop table t1;
+create table t1 (a char(10) not null, b int not null auto_increment, primary key(a,b)) type=BDB;
+insert into t1 values ("a",1),("b",2),("a",2),("c",1);
+insert into t1 values ("a",NULL),("b",NULL),("c",NULL),("e",NULL);
+insert into t1 (a) values ("a"),("b"),("c"),("d");
+insert into t1 (a) values ('k'),('d');
+insert into t1 (a) values ("a");
+insert into t1 values ("d",last_insert_id());
+select * from t1;
a b
a 1
a 2
@@ -172,121 +251,290 @@ d 2
d 5
e 1
k 1
+flush tables;
+select count(*) from t1;
count(*)
16
+drop table t1;
+create table t1 (n int not null primary key) type=bdb;
+set autocommit=0;
+insert into t1 values (4);
+rollback;
+select n, "after rollback" from t1;
n after rollback
+insert into t1 values (4);
+commit;
+select n, "after commit" from t1;
n after commit
4 after commit
+commit;
+insert into t1 values (5);
+insert into t1 values (4);
+Duplicate entry '4' for key 1
+commit;
+select n, "after commit" from t1;
n after commit
4 after commit
5 after commit
+set autocommit=1;
+insert into t1 values (6);
+insert into t1 values (4);
+Duplicate entry '4' for key 1
+select n from t1;
n
4
5
6
+rollback;
+drop table t1;
+create table t1 ( id int NOT NULL PRIMARY KEY, nom varchar(64)) type=BDB;
+begin;
+insert into t1 values(1,'hamdouni');
+select id as afterbegin_id,nom as afterbegin_nom from t1;
afterbegin_id afterbegin_nom
1 hamdouni
+rollback;
+select id as afterrollback_id,nom as afterrollback_nom from t1;
afterrollback_id afterrollback_nom
+set autocommit=0;
+insert into t1 values(2,'mysql');
+select id as afterautocommit0_id,nom as afterautocommit0_nom from t1;
afterautocommit0_id afterautocommit0_nom
2 mysql
+rollback;
+select id as afterrollback_id,nom as afterrollback_nom from t1;
afterrollback_id afterrollback_nom
+set autocommit=1;
+drop table t1;
+CREATE TABLE t1 (id char(8) not null primary key, val int not null) type=bdb;
+insert into t1 values ('pippo', 12);
+insert into t1 values ('pippo', 12);
+Duplicate entry 'pippo' for key 1
+delete from t1;
+delete from t1 where id = 'pippo';
+select * from t1;
id val
+insert into t1 values ('pippo', 12);
+set autocommit=0;
+delete from t1;
+rollback;
+select * from t1;
id val
pippo 12
+delete from t1;
+commit;
+select * from t1;
id val
+drop table t1;
+set autocommit=1;
+CREATE TABLE t1 (ID INTEGER NOT NULL PRIMARY KEY, NAME VARCHAR(64)) TYPE=BDB;
+INSERT INTO t1 VALUES (1, 'Jochen');
+select * from t1;
ID NAME
1 Jochen
+drop table t1;
+CREATE TABLE t1 ( _userid VARCHAR(60) NOT NULL PRIMARY KEY) TYPE=BDB;
+set autocommit=0;
+INSERT INTO t1 SET _userid='marc@anyware.co.uk';
+COMMIT;
+SELECT * FROM t1;
_userid
marc@anyware.co.uk
+SELECT _userid FROM t1 WHERE _userid='marc@anyware.co.uk';
_userid
marc@anyware.co.uk
+drop table t1;
+set autocommit=1;
+CREATE TABLE t1 (
+user_id int(10) DEFAULT '0' NOT NULL,
+name varchar(100),
+phone varchar(100),
+ref_email varchar(100) DEFAULT '' NOT NULL,
+detail varchar(200),
+PRIMARY KEY (user_id,ref_email)
+)type=bdb;
+INSERT INTO t1 VALUES (10292,'sanjeev','29153373','sansh777@hotmail.com','xxx'),(10292,'shirish','2333604','shirish@yahoo.com','ddsds'),(10292,'sonali','323232','sonali@bolly.com','filmstar');
+select * from t1 where user_id=10292;
user_id name phone ref_email detail
10292 sanjeev 29153373 sansh777@hotmail.com xxx
10292 shirish 2333604 shirish@yahoo.com ddsds
10292 sonali 323232 sonali@bolly.com filmstar
+INSERT INTO t1 VALUES (10291,'sanjeev','29153373','sansh777@hotmail.com','xxx'),(10293,'shirish','2333604','shirish@yahoo.com','ddsds');
+select * from t1 where user_id=10292;
user_id name phone ref_email detail
10292 sanjeev 29153373 sansh777@hotmail.com xxx
10292 shirish 2333604 shirish@yahoo.com ddsds
10292 sonali 323232 sonali@bolly.com filmstar
+select * from t1 where user_id>=10292;
user_id name phone ref_email detail
10292 sanjeev 29153373 sansh777@hotmail.com xxx
10292 shirish 2333604 shirish@yahoo.com ddsds
10292 sonali 323232 sonali@bolly.com filmstar
10293 shirish 2333604 shirish@yahoo.com ddsds
+select * from t1 where user_id>10292;
user_id name phone ref_email detail
10293 shirish 2333604 shirish@yahoo.com ddsds
+select * from t1 where user_id<10292;
user_id name phone ref_email detail
10291 sanjeev 29153373 sansh777@hotmail.com xxx
-Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Comment
-t1 0 PRIMARY 1 a A NULL NULL NULL
-t1 0 PRIMARY 2 b A 0 NULL NULL
-t1 0 b 1 b A 0 NULL NULL
-t1 0 c 1 c A 0 NULL NULL
-t1 1 a 1 a A NULL NULL NULL
-t1 1 a_2 1 a A NULL NULL NULL
+drop table t1;
+CREATE TABLE t1 (a int not null, b int not null,c int not null,
+key(a),primary key(a,b), unique(c),key(a),unique(b));
+show index from t1;
+Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
+t1 0 PRIMARY 1 a A NULL NULL NULL BTREE
+t1 0 PRIMARY 2 b A 0 NULL NULL BTREE
+t1 0 c 1 c A 0 NULL NULL BTREE
+t1 0 b 1 b A 0 NULL NULL BTREE
+t1 1 a 1 a A NULL NULL NULL BTREE
+t1 1 a_2 1 a A NULL NULL NULL BTREE
+drop table t1;
+create table t1 (col1 int not null, col2 char(4) not null, primary key(col1));
+alter table t1 type=BDB;
+insert into t1 values ('1','1'),('5','2'),('2','3'),('3','4'),('4','4');
+select * from t1;
col1 col2
1 1
2 3
3 4
4 4
5 2
+update t1 set col2='7' where col1='4';
+select * from t1;
col1 col2
1 1
2 3
3 4
4 7
5 2
+alter table t1 add co3 int not null;
+select * from t1;
col1 col2 co3
1 1 0
2 3 0
3 4 0
4 7 0
5 2 0
+update t1 set col2='9' where col1='2';
+select * from t1;
col1 col2 co3
1 1 0
2 9 0
3 4 0
4 7 0
5 2 0
+drop table t1;
+create table t1 (a int not null , b int, primary key (a)) type = BDB;
+create table t2 (a int not null , b int, primary key (a)) type = myisam;
+insert into t1 VALUES (1,3) , (2,3), (3,3);
+select * from t1;
a b
1 3
2 3
3 3
+insert into t2 select * from t1;
+select * from t2;
a b
1 3
2 3
3 3
+delete from t1 where b = 3;
+select * from t1;
a b
+insert into t1 select * from t2;
+select * from t1;
a b
1 3
2 3
3 3
+select * from t2;
a b
1 3
2 3
3 3
+drop table t1,t2;
+CREATE TABLE t1 (
+id int(11) NOT NULL auto_increment,
+ggid varchar(32) binary DEFAULT '' NOT NULL,
+email varchar(64) DEFAULT '' NOT NULL,
+passwd varchar(32) binary DEFAULT '' NOT NULL,
+PRIMARY KEY (id),
+UNIQUE ggid (ggid)
+) TYPE=BDB;
+insert into t1 (ggid,passwd) values ('test1','xxx');
+insert into t1 (ggid,passwd) values ('test2','yyy');
+insert into t1 (ggid,passwd) values ('test2','this will fail');
+Duplicate entry 'test2' for key 2
+insert into t1 (ggid,id) values ('this will fail',1);
+Duplicate entry '1' for key 1
+select * from t1 where ggid='test1';
id ggid email passwd
1 test1 xxx
+select * from t1 where passwd='xxx';
id ggid email passwd
1 test1 xxx
+select * from t1 where id=2;
id ggid email passwd
2 test2 yyy
+replace into t1 (ggid,id) values ('this will work',1);
+replace into t1 (ggid,passwd) values ('test2','this will work');
+update t1 set id=100,ggid='test2' where id=1;
+Duplicate entry 'test2' for key 2
+select * from t1;
id ggid email passwd
1 this will work
3 test2 this will work
+select * from t1 where id=1;
id ggid email passwd
1 this will work
+select * from t1 where id=999;
id ggid email passwd
+drop table t1;
+CREATE TABLE t1 (
+user_name varchar(12),
+password text,
+subscribed char(1),
+user_id int(11) DEFAULT '0' NOT NULL,
+quota bigint(20),
+weight double,
+access_date date,
+access_time time,
+approved datetime,
+dummy_primary_key int(11) NOT NULL auto_increment,
+PRIMARY KEY (dummy_primary_key)
+) TYPE=BDB;
+INSERT INTO t1 VALUES ('user_0','somepassword','N',0,0,0,'2000-09-07','23:06:59','2000-09-07 23:06:59',1);
+INSERT INTO t1 VALUES ('user_1','somepassword','Y',1,1,1,'2000-09-07','23:06:59','2000-09-07 23:06:59',2);
+INSERT INTO t1 VALUES ('user_2','somepassword','N',2,2,1.4142135623731,'2000-09-07','23:06:59','2000-09-07 23:06:59',3);
+INSERT INTO t1 VALUES ('user_3','somepassword','Y',3,3,1.7320508075689,'2000-09-07','23:06:59','2000-09-07 23:06:59',4);
+INSERT INTO t1 VALUES ('user_4','somepassword','N',4,4,2,'2000-09-07','23:06:59','2000-09-07 23:06:59',5);
+select user_name, password , subscribed, user_id, quota, weight, access_date, access_time, approved, dummy_primary_key from t1 order by user_name;
user_name password subscribed user_id quota weight access_date access_time approved dummy_primary_key
user_0 somepassword N 0 0 0 2000-09-07 23:06:59 2000-09-07 23:06:59 1
user_1 somepassword Y 1 1 1 2000-09-07 23:06:59 2000-09-07 23:06:59 2
user_2 somepassword N 2 2 1.4142135623731 2000-09-07 23:06:59 2000-09-07 23:06:59 3
user_3 somepassword Y 3 3 1.7320508075689 2000-09-07 23:06:59 2000-09-07 23:06:59 4
user_4 somepassword N 4 4 2 2000-09-07 23:06:59 2000-09-07 23:06:59 5
+drop table t1;
+CREATE TABLE t1 (
+id int(11) NOT NULL auto_increment,
+parent_id int(11) DEFAULT '0' NOT NULL,
+level tinyint(4) DEFAULT '0' NOT NULL,
+KEY (id),
+KEY parent_id (parent_id),
+KEY level (level)
+) type=bdb;
+INSERT INTO t1 VALUES (1,0,0),(3,1,1),(4,1,1),(8,2,2),(9,2,2),(17,3,2),(22,4,2),(24,4,2),(28,5,2),(29,5,2),(30,5,2),(31,6,2),(32,6,2),(33,6,2),(203,7,2),(202,7,2),(20,3,2),(157,0,0),(193,5,2),(40,7,2),(2,1,1),(15,2,2),(6,1,1),(34,6,2),(35,6,2),(16,3,2),(7,1,1),(36,7,2),(18,3,2),(26,5,2),(27,5,2),(183,4,2),(38,7,2),(25,5,2),(37,7,2),(21,4,2),(19,3,2),(5,1,1);
+INSERT INTO t1 values (179,5,2);
+update t1 set parent_id=parent_id+100;
+select * from t1 where parent_id=102;
id parent_id level
8 102 2
9 102 2
15 102 2
+update t1 set id=id+1000;
+update t1 set id=1024 where id=1009;
+select * from t1;
id parent_id level
1001 100 0
1003 101 1
@@ -327,6 +575,8 @@ id parent_id level
1019 103 2
1005 101 1
1179 105 2
+update ignore t1 set id=id+1;
+select * from t1;
id parent_id level
1002 100 0
1004 101 1
@@ -367,12 +617,16 @@ id parent_id level
1020 103 2
1006 101 1
1180 105 2
+update ignore t1 set id=1023 where id=1010;
+select * from t1 where parent_id=102;
id parent_id level
1009 102 2
1025 102 2
1016 102 2
+explain select level from t1 where level=1;
table type possible_keys key key_len ref rows Extra
t1 ref level level 1 const 1 where used; Using index
+select level,id from t1 where level=1;
level id
1 1004
1 1005
@@ -380,6 +634,7 @@ level id
1 1007
1 1008
1 1006
+select level,id,parent_id from t1 where level=1;
level id parent_id
1 1004 101
1 1005 101
@@ -387,6 +642,7 @@ level id parent_id
1 1007 101
1 1008 101
1 1006 101
+select level,id from t1 where level=1 order by id;
level id
1 1003
1 1004
@@ -394,6 +650,8 @@ level id
1 1006
1 1007
1 1008
+delete from t1 where level=1;
+select * from t1;
id parent_id level
1002 100 0
1009 102 2
@@ -428,43 +686,86 @@ id parent_id level
1022 104 2
1020 103 2
1180 105 2
+drop table t1;
+CREATE TABLE t1 (
+sca_code char(6) NOT NULL,
+cat_code char(6) NOT NULL,
+sca_desc varchar(50),
+lan_code char(2) NOT NULL,
+sca_pic varchar(100),
+sca_sdesc varchar(50),
+sca_sch_desc varchar(16),
+PRIMARY KEY (sca_code, cat_code, lan_code),
+INDEX sca_pic (sca_pic)
+) type = bdb ;
+INSERT INTO t1 ( sca_code, cat_code, sca_desc, lan_code, sca_pic, sca_sdesc, sca_sch_desc) VALUES ( 'PD', 'J', 'PENDANT', 'EN', NULL, NULL, 'PENDANT'),( 'RI', 'J', 'RING', 'EN', NULL, NULL, 'RING'),( 'QQ', 'N', 'RING', 'EN', 'not null', NULL, 'RING');
+select count(*) from t1 where sca_code = 'PD';
count(*)
1
+select count(*) from t1 where sca_code <= 'PD';
count(*)
1
+select count(*) from t1 where sca_pic is null;
count(*)
2
+alter table t1 drop index sca_pic, add index sca_pic (cat_code, sca_pic);
+select count(*) from t1 where sca_code='PD' and sca_pic is null;
count(*)
1
+select count(*) from t1 where cat_code='E';
count(*)
0
+alter table t1 drop index sca_pic, add index (sca_pic, cat_code);
+select count(*) from t1 where sca_code='PD' and sca_pic is null;
count(*)
1
+select count(*) from t1 where sca_pic >= 'n';
count(*)
1
+select sca_pic from t1 where sca_pic is null;
sca_pic
NULL
NULL
+update t1 set sca_pic="test" where sca_pic is null;
+delete from t1 where sca_code='pd';
+drop table t1;
+set @a:=now();
+CREATE TABLE t1 (a int not null, b timestamp not null, primary key (a)) type=bdb;
+insert into t1 (a) values(1),(2),(3);
+select t1.a from t1 natural join t1 as t2 where t1.b >= @a order by t1.a;
a
1
2
3
+update t1 set a=5 where a=1;
+select a from t1;
a
2
3
5
+drop table t1;
+flush logs;
+create table t1 (b blob, i int, key (b(100)), key (i), key (i, b(20))) type=bdb;
+insert into t1 values ('this is a blob', 1), (null, -1), (null, null),("",1),("",2),("",3);
+select b from t1 where b = 'this is a blob';
b
this is a blob
+select * from t1 where b like 't%';
b i
this is a blob 1
+select b, i from t1 where b is not null;
b i
this is a blob 1
1
2
3
+select * from t1 where b is null and i > 0;
b i
+select * from t1 where i is NULL;
b i
NULL NULL
+update t1 set b='updated' where i=1;
+select * from t1;
b i
updated 1
NULL -1
@@ -472,63 +773,353 @@ NULL NULL
updated 1
2
3
+drop table t1;
+create table t1 (a varchar(100) not null, primary key(a), b int not null) type=bdb;
+insert into t1 values("hello",1),("world",2);
+select * from t1 order by b desc;
a b
world 2
hello 1
+optimize table t1;
Table Op Msg_type Msg_text
test.t1 optimize status OK
-Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Comment
-t1 0 PRIMARY 1 a A 2 NULL NULL
+show keys from t1;
+Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
+t1 0 PRIMARY 1 a A 2 NULL NULL BTREE
+drop table t1;
+create table t1 (i int, j int )TYPE=BDB;
+insert into t1 values (1,2);
+select * from t1 where i=1 and j=2;
i j
1 2
+create index ax1 on t1 (i,j);
+select * from t1 where i=1 and j=2;
i j
1 2
+drop table t1;
+drop table if exists t1, t2, t3, t4, t5, t6, t7;
+create table t1
+(
+branch_id int auto_increment primary key,
+branch_name varchar(255) not null,
+branch_active int not null default 1,
+unique branch_name(branch_name),
+index branch_active(branch_active)
+) type=bdb;
+drop table if exists t2 ;
+create table t2
+(
+target_id int auto_increment primary key,
+target_name varchar(255) not null,
+target_active int not null default 1,
+unique target_name(target_name),
+index target_active(target_active)
+) type=bdb;
+drop table if exists t3 ;
+create table t3
+(
+platform_id int auto_increment primary key,
+platform_name varchar(255) not null,
+platform_active int not null default 1,
+unique platform_name(platform_name),
+index platform_active(platform_active)
+) type=bdb;
+drop table if exists t4 ;
+create table t4
+(
+product_id int auto_increment primary key,
+product_name varchar(255) not null,
+version_file varchar(255) not null,
+product_active int not null default 1,
+unique product_name(product_name),
+index product_active(product_active)
+) type=bdb;
+drop table if exists t5 ;
+create table t5
+(
+product_file_id int auto_increment primary key,
+product_id int not null,
+file_name varchar(255) not null,
+/* cvs module used to find the file version */
+module_name varchar(255) not null,
+/* flag whether the file is still included in the product */
+file_included int not null default 1,
+unique product_file(product_id,file_name),
+index file_included(file_included)
+) type=bdb;
+drop table if exists t6 ;
+create table t6
+(
+file_platform_id int auto_increment primary key,
+product_file_id int not null,
+platform_id int not null,
+branch_id int not null,
+/* filename in the build system */
+build_filename varchar(255) not null,
+/* default filename in the build archive */
+archive_filename varchar(255) not null,
+unique file_platform(product_file_id,platform_id,branch_id)
+) type=bdb;
+drop table if exists t8 ;
+create table t8
+(
+archive_id int auto_increment primary key,
+branch_id int not null,
+target_id int not null,
+platform_id int not null,
+product_id int not null,
+status_id int not null default 1,
+unique archive(branch_id,target_id,platform_id,product_id),
+index status_id(status_id)
+) type=bdb;
+drop table if exists t7 ;
+create table t7
+(
+build_id int auto_increment primary key,
+branch_id int not null,
+target_id int not null,
+build_number int not null,
+build_date date not null,
+/* build system tag, e.g. 'rmanight-022301-1779' */
+build_tag varchar(255) not null,
+/* path relative to the build archive root, e.g. 'current' */
+build_path text not null,
+unique build(branch_id,target_id,build_number)
+) type=bdb;
+insert into t1 (branch_name)
+values ('RealMedia');
+insert into t1 (branch_name)
+values ('RP8REV');
+insert into t1 (branch_name)
+values ('SERVER_8_0_GOLD');
+insert into t2 (target_name)
+values ('rmanight');
+insert into t2 (target_name)
+values ('playerall');
+insert into t2 (target_name)
+values ('servproxyall');
+insert into t3 (platform_name)
+values ('linux-2.0-libc6-i386');
+insert into t3 (platform_name)
+values ('win32-i386');
+insert into t4 (product_name, version_file)
+values ('realserver', 'servinst');
+insert into t4 (product_name, version_file)
+values ('realproxy', 'prxyinst');
+insert into t4 (product_name, version_file)
+values ('realplayer', 'playinst');
+insert into t4 (product_name, version_file)
+values ('plusplayer', 'plusinst');
+create temporary table tmp1
+select branch_id, target_id, platform_id, product_id
+from t1, t2, t3, t4 ;
+create temporary table tmp2
+select tmp1.branch_id, tmp1.target_id, tmp1.platform_id, tmp1.product_id
+from tmp1 left join t8
+using (branch_id,target_id,platform_id,product_id)
+where t8.archive_id is null ;
+insert into t8
+(branch_id, target_id, platform_id, product_id, status_id)
+select branch_id, target_id, platform_id, product_id, 1
+from tmp2 ;
+drop table tmp1 ;
+drop table tmp2 ;
+insert into t5 (product_id, file_name, module_name)
+values (1, 'servinst', 'server');
+insert into t5 (product_id, file_name, module_name)
+values (2, 'prxyinst', 'server');
+insert into t5 (product_id, file_name, module_name)
+values (3, 'playinst', 'rpapp');
+insert into t5 (product_id, file_name, module_name)
+values (4, 'plusinst', 'rpapp');
+insert into t6
+(product_file_id,platform_id,branch_id,build_filename,archive_filename)
+values (1, 2, 3, 'servinst.exe', 'win32-servinst.exe');
+insert into t6
+(product_file_id,platform_id,branch_id,build_filename,archive_filename)
+values (1, 1, 3, 'v80_linux-2.0-libc6-i386_servinst.bin', 'linux2-servinst.exe');
+insert into t6
+(product_file_id,platform_id,branch_id,build_filename,archive_filename)
+values (3, 2, 2, 'playinst.exe', 'win32-playinst.exe');
+insert into t6
+(product_file_id,platform_id,branch_id,build_filename,archive_filename)
+values (4, 2, 2, 'playinst.exe', 'win32-playinst.exe');
+insert into t7
+(branch_id,target_id,build_number,build_tag,build_date,build_path)
+values (2, 2, 1071, 'playerall-022101-1071', '2001-02-21', 'current');
+insert into t7
+(branch_id,target_id,build_number,build_tag,build_date,build_path)
+values (2, 2, 1072, 'playerall-022201-1072', '2001-02-22', 'current');
+insert into t7
+(branch_id,target_id,build_number,build_tag,build_date,build_path)
+values (3, 3, 388, 'servproxyall-022201-388', '2001-02-22', 'current');
+insert into t7
+(branch_id,target_id,build_number,build_tag,build_date,build_path)
+values (3, 3, 389, 'servproxyall-022301-389', '2001-02-23', 'current');
+insert into t7
+(branch_id,target_id,build_number,build_tag,build_date,build_path)
+values (4, 4, 100, 'foo target-010101-100', '2001-01-01', 'current');
+update t8
+set status_id=2
+where branch_id=2 and target_id=2 and platform_id=2 and product_id=1;
+select t7.build_path
+from
+t1,
+t7,
+t2,
+t3,
+t4,
+t5,
+t6
+where
+t7.branch_id = t1.branch_id and
+t7.target_id = t2.target_id and
+t5.product_id = t4.product_id and
+t6.product_file_id = t5.product_file_id and
+t6.platform_id = t3.platform_id and
+t6.branch_id = t6.branch_id and
+t7.build_id = 1 and
+t4.product_id = 3 and
+t5.file_name = 'playinst' and
+t3.platform_id = 2;
build_path
current
+drop table t1, t2, t3, t4, t5, t6, t7, t8;
+CREATE TABLE t1 (
+a tinytext NOT NULL,
+b tinyint(3) unsigned NOT NULL default '0',
+PRIMARY KEY (a(32),b)
+) TYPE=BDB;
+INSERT INTO t1 VALUES ('a',1),('a',2);
+SELECT * FROM t1 WHERE a='a' AND b=2;
a b
a 2
+SELECT * FROM t1 WHERE a='a' AND b in (2);
a b
a 2
+SELECT * FROM t1 WHERE a='a' AND b in (1,2);
a b
a 1
a 2
+drop table t1;
+CREATE TABLE t1 (
+a int3 unsigned NOT NULL,
+b int1 unsigned NOT NULL,
+UNIQUE (a, b)
+) TYPE = BDB;
+INSERT INTO t1 VALUES (1, 1);
+SELECT MIN(B),MAX(b) FROM t1 WHERE t1.a = 1;
MIN(B) MAX(b)
1 1
+drop table t1;
+create table t1 (id int NOT NULL,id2 int NOT NULL,id3 int NOT NULL,dummy1 char(30),primary key (id,id2),index index_id3 (id3)) type=bdb;
+insert into t1 values (0,0,0,'ABCDEFGHIJ'),(2,2,2,'BCDEFGHIJK'),(1,1,1,'CDEFGHIJKL');
+LOCK TABLES t1 WRITE;
+insert into t1 values (99,1,2,'D'),(1,1,2,'D');
+Duplicate entry '1-1' for key 1
+select id from t1;
id
0
1
2
+select id from t1;
id
0
1
2
+UNLOCK TABLES;
+DROP TABLE t1;
+create table t1 (id int NOT NULL,id2 int NOT NULL,id3 int NOT NULL,dummy1 char(30),primary key (id,id2),index index_id3 (id3)) type=bdb;
+insert into t1 values (0,0,0,'ABCDEFGHIJ'),(2,2,2,'BCDEFGHIJK'),(1,1,1,'CDEFGHIJKL');
+LOCK TABLES t1 WRITE;
+begin;
+insert into t1 values (99,1,2,'D'),(1,1,2,'D');
+Duplicate entry '1-1' for key 1
+select id from t1;
id
0
1
2
+insert ignore into t1 values (100,1,2,'D'),(1,1,99,'D');
+commit;
+select id,id3 from t1;
id id3
0 0
1 1
2 2
100 2
+UNLOCK TABLES;
+DROP TABLE t1;
+CREATE TABLE t1 (SYAIN_NO char(5) NOT NULL default '', KINMU_DATE char(6) NOT NULL default '', PRIMARY KEY (SYAIN_NO,KINMU_DATE)) TYPE=BerkeleyDB;
+CREATE TABLE t2 ( SYAIN_NO char(5) NOT NULL default '',STR_DATE char(8) NOT NULL default '',PRIMARY KEY (SYAIN_NO,STR_DATE) ) TYPE=BerkeleyDB;
+select T1.KINMU_DATE from t1 T1 ,t2 T2 where T1.SYAIN_NO = '12345' and T1.KINMU_DATE = '200106' and T2.SYAIN_NO = T1.SYAIN_NO;
KINMU_DATE
+select T1.KINMU_DATE from t1 T1 ,t2 T2 where T1.SYAIN_NO = '12345' and T1.KINMU_DATE = '200106' and T2.SYAIN_NO = T1.SYAIN_NO;
KINMU_DATE
+DROP TABLE t1,t2;
+drop table if exists t1;
+create table t1 (a int(11) not null, b int(11) not null, unique (a,b)) type=bdb;
+insert into t1 values (1,1), (1,2);
+select * from t1 where a = 1;
a b
1 1
1 2
+select t1.*, t2.* from t1, t1 t2 where t1.a = t2.a and t2.a = 1;
a b a b
1 1 1 1
1 1 1 2
1 2 1 1
1 2 1 2
+select * from t1 where a = 1;
a b
1 1
1 2
+drop table t1;
+create table t1 (id int NOT NULL,id2 int NOT NULL,id3 int NOT NULL,dummy1 char(30),primary key (id,id2),index index_id3 (id3)) type=bdb;
+insert into t1 values (0,0,0,'ABCDEFGHIJ');
+create table t2 (id int NOT NULL,primary key (id)) type=bdb;
+LOCK TABLES t1 WRITE, t2 WRITE;
+insert into t2 values(1);
+SELECT t1.* FROM t1 WHERE id IN (1);
id id2 id3 dummy1
+SELECT t1.* FROM t2 left outer join t1 on (t1.id=t2.id);
id id2 id3 dummy1
NULL NULL NULL NULL
+delete from t1 where id3 >= 0 and id3 <= 0;
+drop table t1,t2;
+CREATE TABLE t1 (i varchar(48) NOT NULL default '', p varchar(255) default NULL,s varchar(48) NOT NULL default '', PRIMARY KEY (i), UNIQUE(p,s)) TYPE=BDB;
+INSERT INTO t1 VALUES ('00000000-e6c4ddeaa6-003b8-83458387','programs/xxxxxxxx.wmv','00000000-e6c4ddeb32-003bc-83458387');
+SELECT * FROM t1 WHERE p='programs/xxxxxxxx.wmv';
i p s
00000000-e6c4ddeaa6-003b8-83458387 programs/xxxxxxxx.wmv 00000000-e6c4ddeb32-003bc-83458387
+drop table t1;
+CREATE TABLE t1 ( STR_DATE varchar(8) NOT NULL default '',INFO_NOTE varchar(200) default NULL,PRIMARY KEY (STR_DATE) ) TYPE=BerkeleyDB;
+select INFO_NOTE from t1 where STR_DATE = '20010610';
INFO_NOTE
+select INFO_NOTE from t1 where STR_DATE < '20010610';
INFO_NOTE
+select INFO_NOTE from t1 where STR_DATE > '20010610';
INFO_NOTE
+drop table t1;
+create table t1 (a int not null, b int, primary key (a)) type =bdb;
+create table t2 (a int not null, b int, primary key (a)) type =bdb;
+insert into t1 values (2, 3),(1, 7),(10, 7);
+insert into t2 values (2, 3),(1, 7),(10, 7);
+select * from t1;
+a b
+1 7
+2 3
+10 7
+select * from t2;
+a b
+1 7
+2 3
+10 7
+delete t1, t2 from t1, t2 where t1.a = t2.a;
+select * from t1;
+a b
+select * from t2;
+a b
+select * from t2;
+a b
+drop table t1,t2;
diff --git a/mysql-test/r/bench_count_distinct.result b/mysql-test/r/bench_count_distinct.result
index 20f23c0abbe..d414e8e466e 100644
--- a/mysql-test/r/bench_count_distinct.result
+++ b/mysql-test/r/bench_count_distinct.result
@@ -1,2 +1,6 @@
+drop table if exists t1;
+create table t1(n int not null, key(n)) delay_key_write = 1;
+select count(distinct n) from t1;
count(distinct n)
100
+drop table t1;
diff --git a/mysql-test/r/big_test.require b/mysql-test/r/big_test.require
new file mode 100644
index 00000000000..001b903496b
--- /dev/null
+++ b/mysql-test/r/big_test.require
@@ -0,0 +1,2 @@
+using_big_test
+1
diff --git a/mysql-test/r/bigint.result b/mysql-test/r/bigint.result
index 46ce0fda2c1..f2cb6437f8f 100644
--- a/mysql-test/r/bigint.result
+++ b/mysql-test/r/bigint.result
@@ -1,15 +1,78 @@
+select 0,256,00000000000000065536,2147483647,-2147483648,2147483648,+4294967296;
0 256 00000000000000065536 2147483647 -2147483648 2147483648 +4294967296
0 256 65536 2147483647 -2147483648 2147483648 4294967296
+select 9223372036854775807,-009223372036854775808;
9223372036854775807 -009223372036854775808
9223372036854775807 -9223372036854775808
+select +9999999999999999999,-9999999999999999999;
+9999999999999999999 -9999999999999999999
10000000000000000000 -10000000000000000000
+drop table if exists t1;
+create table t1 (a bigint unsigned not null, primary key(a));
+insert into t1 values (18446744073709551615), (0xFFFFFFFFFFFFFFFE);
+select * from t1;
a
18446744073709551614
18446744073709551615
+select * from t1 where a=18446744073709551615;
a
18446744073709551615
+select * from t1 where a='18446744073709551615';
a
18446744073709551615
+delete from t1 where a=18446744073709551615;
+select * from t1;
a
18446744073709551614
+drop table t1;
+create table t1 ( a int not null default 1, big bigint );
+insert into t1 (big) values (-1),(12345678901234567),(9223372036854775807),(18446744073709551615);
+select min(big),max(big),max(big)-1 from t1;
+min(big) max(big) max(big)-1
+-1 9223372036854775807 9223372036854775806
+select min(big),max(big),max(big)-1 from t1 group by a;
+min(big) max(big) max(big)-1
+-1 9223372036854775807 9223372036854775806
+alter table t1 modify big bigint unsigned not null;
+select min(big),max(big),max(big)-1 from t1;
+min(big) max(big) max(big)-1
+12345678901234567 18446744073709551615 18446744073709551614
+select min(big),max(big),max(big)-1 from t1 group by a;
+min(big) max(big) max(big)-1
+12345678901234567 18446744073709551615 18446744073709551614
+alter table t1 add key (big);
+select min(big),max(big),max(big)-1 from t1;
+min(big) max(big) max(big)-1
+12345678901234567 18446744073709551615 18446744073709551614
+select min(big),max(big),max(big)-1 from t1 group by a;
+min(big) max(big) max(big)-1
+12345678901234567 18446744073709551615 18446744073709551614
+alter table t1 modify big bigint not null;
+select min(big),max(big),max(big)-1 from t1;
+min(big) max(big) max(big)-1
+-1 9223372036854775807 9223372036854775806
+select min(big),max(big),max(big)-1 from t1 group by a;
+min(big) max(big) max(big)-1
+-1 9223372036854775807 9223372036854775806
+drop table t1;
+select CAST(1-2 AS UNSIGNED);
+CAST(1-2 AS UNSIGNED)
+18446744073709551615
+select CAST(CAST(1-2 AS UNSIGNED) AS SIGNED INTEGER);
+CAST(CAST(1-2 AS UNSIGNED) AS SIGNED INTEGER)
+-1
+select CONVERT('-1',UNSIGNED);
+CONVERT('-1',UNSIGNED)
+18446744073709551615
+select cast(-5 as unsigned) | 1, cast(-5 as unsigned) & -1;
+cast(-5 as unsigned) | 1 cast(-5 as unsigned) & -1
+18446744073709551611 18446744073709551611
+select cast(-5 as unsigned) -1, cast(-5 as unsigned) + 1;
+cast(-5 as unsigned) -1 cast(-5 as unsigned) + 1
+18446744073709551610 18446744073709551612
+select ~5, cast(~5 as signed);
+~5 cast(~5 as signed)
+18446744073709551610 -6
+select cast(5 as unsigned) -6.0;
+cast(5 as unsigned) -6.0
+-1.0
diff --git a/mysql-test/r/binary.result b/mysql-test/r/binary.result
index c5f9961699d..9f1c8ffac41 100644
--- a/mysql-test/r/binary.result
+++ b/mysql-test/r/binary.result
@@ -1,33 +1,55 @@
+create table t1 (name char(20) not null, primary key (name));
+create table t2 (name char(20) binary not null, primary key (name));
+insert into t1 values ("å");
+insert into t1 values ("ä");
+insert into t1 values ("ö");
+insert into t2 select * from t1;
+select * from t1 order by name;
name
å
ä
ö
+select concat("*",name,"*") from t1 order by 1;
concat("*",name,"*")
*å*
*ä*
*ö*
+select min(name),min(concat("*",name,"*")),max(name),max(concat("*",name,"*")) from t1;
min(name) min(concat("*",name,"*")) max(name) max(concat("*",name,"*"))
å *å* ö *ö*
+select * from t2 order by name;
name
ä
å
ö
+select concat("*",name,"*") from t2 order by 1;
concat("*",name,"*")
*ä*
*å*
*ö*
+select min(name),min(concat("*",name,"*")),max(name),max(concat("*",name,"*")) from t2;
min(name) min(concat("*",name,"*")) max(name) max(concat("*",name,"*"))
ä *ä* ö *ö*
+select name from t1 where name between 'Ä' and 'Ö';
name
ä
ö
+select name from t2 where name between 'ä' and 'ö';
name
ä
å
ö
+select name from t2 where name between 'Ä' and 'Ö';
name
+drop table t1,t2;
+create table t1 (a char(10) not null, b char(10) binary not null,index (a));
+insert into t1 values ("hello ","hello "),("hello2 ","hello2 ");
+select * from t1 where a="hello ";
a b
hello hello
+select * from t1 where b="hello ";
a b
+select * from t1 where b="hello";
a b
hello hello
+drop table t1;
diff --git a/mysql-test/r/bulk_replace.result b/mysql-test/r/bulk_replace.result
new file mode 100644
index 00000000000..0a079965b82
--- /dev/null
+++ b/mysql-test/r/bulk_replace.result
@@ -0,0 +1,11 @@
+drop table if exists t1;
+CREATE TABLE t1 (a int, unique (a), b int not null, unique(b), c int not null, index(c));
+replace into t1 values (1,1,1),(2,2,2),(3,1,3);
+select * from t1;
+a b c
+3 1 3
+2 2 2
+check table t1;
+Table Op Msg_type Msg_text
+test.t1 check status OK
+drop table t1;
diff --git a/mysql-test/r/case.result b/mysql-test/r/case.result
index 073164aa035..ec37c9a5763 100644
--- a/mysql-test/r/case.result
+++ b/mysql-test/r/case.result
@@ -1,42 +1,65 @@
+drop table if exists t1;
+select CASE "b" when "a" then 1 when "b" then 2 END;
CASE "b" when "a" then 1 when "b" then 2 END
2
+select CASE "c" when "a" then 1 when "b" then 2 END;
CASE "c" when "a" then 1 when "b" then 2 END
NULL
+select CASE "c" when "a" then 1 when "b" then 2 ELSE 3 END;
CASE "c" when "a" then 1 when "b" then 2 ELSE 3 END
3
+select CASE BINARY "b" when "a" then 1 when "B" then 2 WHEN "b" then "ok" END;
CASE BINARY "b" when "a" then 1 when "B" then 2 WHEN "b" then "ok" END
ok
+select CASE "b" when "a" then 1 when binary "B" then 2 WHEN "b" then "ok" END;
CASE "b" when "a" then 1 when binary "B" then 2 WHEN "b" then "ok" END
ok
+select CASE concat("a","b") when concat("ab","") then "a" when "b" then "b" end;
CASE concat("a","b") when concat("ab","") then "a" when "b" then "b" end
a
+select CASE when 1=0 then "true" else "false" END;
CASE when 1=0 then "true" else "false" END
false
+select CASE 1 when 1 then "one" WHEN 2 then "two" ELSE "more" END;
CASE 1 when 1 then "one" WHEN 2 then "two" ELSE "more" END
one
+select CASE 2.0 when 1 then "one" WHEN 2.0 then "two" ELSE "more" END;
CASE 2.0 when 1 then "one" WHEN 2.0 then "two" ELSE "more" END
two
+select (CASE "two" when "one" then "1" WHEN "two" then "2" END) | 0;
(CASE "two" when "one" then "1" WHEN "two" then "2" END) | 0
2
+select (CASE "two" when "one" then 1.00 WHEN "two" then 2.00 END) +0.0;
(CASE "two" when "one" then 1.00 WHEN "two" then 2.00 END) +0.0
2.00
+select case 1/0 when "a" then "true" else "false" END;
case 1/0 when "a" then "true" else "false" END
false
+select case 1/0 when "a" then "true" END;
case 1/0 when "a" then "true" END
NULL
+select (case 1/0 when "a" then "true" END) | 0;
(case 1/0 when "a" then "true" END) | 0
NULL
+select (case 1/0 when "a" then "true" END) + 0.0;
(case 1/0 when "a" then "true" END) + 0.0
NULL
+select case when 1>0 then "TRUE" else "FALSE" END;
case when 1>0 then "TRUE" else "FALSE" END
TRUE
+select case when 1<0 then "TRUE" else "FALSE" END;
case when 1<0 then "TRUE" else "FALSE" END
FALSE
+create table t1 (a int);
+insert into t1 values(1),(2),(3),(4);
+select case a when 1 then 2 when 2 then 3 else 0 end as fcase, count(*) from t1 group by fcase;
fcase count(*)
0 2
2 1
3 1
+select case a when 1 then "one" when 2 then "two" else "nothing" end as fcase, count(*) from t1 group by fcase;
fcase count(*)
nothing 2
one 1
two 1
+drop table t1;
diff --git a/mysql-test/r/check.result b/mysql-test/r/check.result
index 694d7429a14..b13151cf514 100644
--- a/mysql-test/r/check.result
+++ b/mysql-test/r/check.result
@@ -1,2 +1,7 @@
+drop table if exists t1;
+create table t1(n int not null, key(n), key(n), key(n), key(n));
+ check table t1 type=extended;
+insert into t1 values (200000);
Table Op Msg_type Msg_text
test.t1 check status OK
+drop table t1;
diff --git a/mysql-test/r/comments.result b/mysql-test/r/comments.result
index 7044667e4af..521b5c9509d 100644
--- a/mysql-test/r/comments.result
+++ b/mysql-test/r/comments.result
@@ -1,15 +1,27 @@
+select 1+2/*hello*/+3;
1+2/*hello*/+3
6
+select 1 /* long
+multi line comment */;
1
1
+/* empty query */;
+Query was empty
+select 1 /*!32301 +1 */;
1 /*!32301 +1
2
+select 1 /*!52301 +1 */;
1
1
+select 1--1;
1--1
2
+select 1 --2
++1;
1 --2
+1
4
+select 1 # The rest of the row will be ignored
+;
1
1
diff --git a/mysql-test/r/compare.result b/mysql-test/r/compare.result
index 6af85c16dff..07f9ce4e81a 100644
--- a/mysql-test/r/compare.result
+++ b/mysql-test/r/compare.result
@@ -1,6 +1,14 @@
+drop table if exists t1;
+CREATE TABLE t1 (id CHAR(12) not null, PRIMARY KEY (id));
+insert into t1 values ('000000000001'),('000000000002');
+explain select * from t1 where id=000000000001;
table type possible_keys key key_len ref rows Extra
t1 index PRIMARY PRIMARY 12 NULL 2 where used; Using index
+select * from t1 where id=000000000001;
id
000000000001
+delete from t1 where id=000000000002;
+select * from t1;
id
000000000001
+drop table t1;
diff --git a/mysql-test/r/count_distinct.result b/mysql-test/r/count_distinct.result
index 97d7b57f249..3bff6c6ad88 100644
--- a/mysql-test/r/count_distinct.result
+++ b/mysql-test/r/count_distinct.result
@@ -1,11 +1,46 @@
+drop table if exists t1,t2,t3;
+create table t1 (libname varchar(21) not null, city text, primary key (libname));
+create table t2 (isbn varchar(21) not null, author text, title text, primary key (isbn));
+create table t3 (isbn varchar(21) not null, libname varchar(21) not null, quantity int ,primary key (isbn,libname));
+insert into t2 values ('001','Daffy','A duck''s life');
+insert into t2 values ('002','Bugs','A rabbit\'s life');
+insert into t2 values ('003','Cowboy','Life on the range');
+insert into t2 values ('000','Anonymous','Wanna buy this book?');
+insert into t2 values ('004','Best Seller','One Heckuva book');
+insert into t2 values ('005','EveryoneBuys','This very book');
+insert into t2 values ('006','San Fran','It is a san fran lifestyle');
+insert into t2 values ('007','BerkAuthor','Cool.Berkley.the.book');
+insert into t3 values('000','New York Public Libra','1');
+insert into t3 values('001','New York Public Libra','2');
+insert into t3 values('002','New York Public Libra','3');
+insert into t3 values('003','New York Public Libra','4');
+insert into t3 values('004','New York Public Libra','5');
+insert into t3 values('005','New York Public Libra','6');
+insert into t3 values('006','San Fransisco Public','5');
+insert into t3 values('007','Berkeley Public1','3');
+insert into t3 values('007','Berkeley Public2','3');
+insert into t3 values('001','NYC Lib','8');
+insert into t1 values ('New York Public Libra','New York');
+insert into t1 values ('San Fransisco Public','San Fran');
+insert into t1 values ('Berkeley Public1','Berkeley');
+insert into t1 values ('Berkeley Public2','Berkeley');
+insert into t1 values ('NYC Lib','New York');
+select t2.isbn,city,t1.libname,count(t1.libname) as a from t3 left join t1 on t3.libname=t1.libname left join t2 on t3.isbn=t2.isbn group by city,t1.libname;
isbn city libname a
007 Berkeley Berkeley Public1 1
007 Berkeley Berkeley Public2 1
000 New York New York Public Libra 6
001 New York NYC Lib 1
006 San Fran San Fransisco Public 1
+select t2.isbn,city,t1.libname,count(distinct t1.libname) as a from t3 left join t1 on t3.libname=t1.libname left join t2 on t3.isbn=t2.isbn group by city having count(distinct t1.libname) > 1;
isbn city libname a
007 Berkeley Berkeley Public1 2
000 New York New York Public Libra 2
+drop table t1, t2, t3;
+create table t1 (f1 int);
+insert into t1 values (1);
+create table t2 (f1 int,f2 int);
+select t1.f1,count(distinct t2.f2),count(distinct 1,NULL) from t1 left join t2 on t1.f1=t2.f1 group by t1.f1;
f1 count(distinct t2.f2) count(distinct 1,NULL)
1 0 0
+drop table t1,t2;
diff --git a/mysql-test/r/count_distinct2.result b/mysql-test/r/count_distinct2.result
new file mode 100644
index 00000000000..131e3b325ec
--- /dev/null
+++ b/mysql-test/r/count_distinct2.result
@@ -0,0 +1,129 @@
+drop table if exists t1;
+create table t1(n1 int, n2 int, s char(20), vs varchar(20), t text);
+insert into t1 values (1,11, 'one','eleven', 'eleven'),
+(1,11, 'one','eleven', 'eleven'),
+(2,11, 'two','eleven', 'eleven'),
+(2,12, 'two','twevle', 'twelve'),
+(2,13, 'two','thirteen', 'foo'),
+(2,13, 'two','thirteen', 'foo'),
+(2,13, 'two','thirteen', 'bar'),
+(NULL,13, 'two','thirteen', 'bar'),
+(2,NULL, 'two','thirteen', 'bar'),
+(2,13, NULL,'thirteen', 'bar'),
+(2,13, 'two',NULL, 'bar'),
+(2,13, 'two','thirteen', NULL);
+select distinct n1 from t1;
+n1
+1
+2
+NULL
+select count(distinct n1) from t1;
+count(distinct n1)
+2
+select distinct n2 from t1;
+n2
+11
+12
+13
+NULL
+select count(distinct n2) from t1;
+count(distinct n2)
+3
+select distinct s from t1;
+s
+one
+two
+NULL
+select count(distinct s) from t1;
+count(distinct s)
+2
+select distinct vs from t1;
+vs
+eleven
+twevle
+thirteen
+NULL
+select count(distinct vs) from t1;
+count(distinct vs)
+3
+select distinct t from t1;
+t
+eleven
+twelve
+foo
+bar
+NULL
+select count(distinct t) from t1;
+count(distinct t)
+4
+select distinct n1,n2 from t1;
+n1 n2
+1 11
+2 11
+2 12
+2 13
+NULL 13
+2 NULL
+select count(distinct n1,n2) from t1;
+count(distinct n1,n2)
+4
+select distinct n1,s from t1;
+n1 s
+1 one
+2 two
+NULL two
+2 NULL
+select count(distinct n1,s) from t1;
+count(distinct n1,s)
+2
+select distinct s,n1,vs from t1;
+s n1 vs
+one 1 eleven
+two 2 eleven
+two 2 twevle
+two 2 thirteen
+two NULL thirteen
+NULL 2 thirteen
+two 2 NULL
+select count(distinct s,n1,vs) from t1;
+count(distinct s,n1,vs)
+4
+select distinct s,t from t1;
+s t
+one eleven
+two eleven
+two twelve
+two foo
+two bar
+NULL bar
+two NULL
+select count(distinct s,t) from t1;
+count(distinct s,t)
+5
+select count(distinct n1), count(distinct n2) from t1;
+count(distinct n1) count(distinct n2)
+2 3
+select count(distinct n2), n1 from t1 group by n1;
+count(distinct n2) n1
+1 NULL
+1 1
+3 2
+drop table t1;
+create table t1 (n int default NULL);
+flush status;
+select count(distinct n) from t1;
+count(distinct n)
+5000
+show status like 'Created_tmp_disk_tables';
+Variable_name Value
+Created_tmp_disk_tables 1
+drop table t1;
+create table t1 (s text);
+flush status;
+select count(distinct s) from t1;
+count(distinct s)
+5000
+show status like 'Created_tmp_disk_tables';
+Variable_name Value
+Created_tmp_disk_tables 1
+drop table t1;
diff --git a/mysql-test/r/create.result b/mysql-test/r/create.result
index 7940d51868a..625b84ae837 100644
--- a/mysql-test/r/create.result
+++ b/mysql-test/r/create.result
@@ -1,14 +1,96 @@
+drop table if exists t1,t2;
+create table t1 (b char(0));
+insert into t1 values (""),(null);
+select * from t1;
b
NULL
+drop table if exists t1;
+create table t1 (b char(0) not null);
+create table if not exists t1 (b char(0) not null);
+insert into t1 values (""),(null);
+select * from t1;
b
+drop table if exists t1;
+create table t2 type=heap select * from t1;
+Table 'test.t1' doesn't exist
+create table t2 select auto+1 from t1;
+Table 'test.t1' doesn't exist
+drop table if exists t1,t2;
+create table t1 (b char(0) not null, index(b));
+The used table handler can't index column 'b'
+create table t1 (a int not null auto_increment,primary key (a)) type=heap;
+The used table type doesn't support AUTO_INCREMENT columns
+create table t1 (a int not null,b text) type=heap;
+The used table type doesn't support BLOB/TEXT columns
+create table t1 (a int ,primary key(a)) type=heap;
+All parts of a PRIMARY KEY must be NOT NULL; If you need NULL in a key, use UNIQUE instead
+drop table if exists t1;
+create table t1 (ordid int(8) not null auto_increment, ord varchar(50) not null, primary key (ord,ordid)) type=heap;
+The used table type doesn't support AUTO_INCREMENT columns
+create table t1 (ordid int(8), primary key (ordid));
+All parts of a PRIMARY KEY must be NOT NULL; If you need NULL in a key, use UNIQUE instead
+create table not_existing_database.test (a int);
+Got one of the listed errors
+create table `a/a` (a int);
+Incorrect table name 'a/a'
+create table `aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa` (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa int);
+Incorrect table name 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'
+create table a (`aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa` int);
+Identifier name 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' is too long
+create table 1ea10 (1a20 int,1e int);
+insert into 1ea10 values(1,1);
+select 1ea10.1a20,1e+ 1e+10 from 1ea10;
1a20 1e+ 1e+10
1 10000000001
+drop table 1ea10;
+create table t1 (t1.index int);
+drop table t1;
+drop database if exists test_$1;
+create database test_$1;
+create table test_$1.$test1 (a$1 int, $b int, c$ int);
+insert into test_$1.$test1 values (1,2,3);
+select a$1, $b, c$ from test_$1.$test1;
a$1 $b c$
1 2 3
+create table test_$1.test2$ (a int);
+drop table test_$1.test2$;
+drop database test_$1;
+create table t1 (a int auto_increment not null primary key, B CHAR(20));
+insert into t1 (b) values ("hello"),("my"),("world");
+create table t2 (key (b)) select * from t1;
+explain select * from t2 where b="world";
table type possible_keys key key_len ref rows Extra
t2 ref B B 21 const 1 where used
+select * from t2 where b="world";
a B
3 world
+drop table t1,t2;
+create table t1(x varchar(50) );
+create table t2 select x from t1 where 1=2;
+describe t1;
+Field Type Null Key Default Extra
+x varchar(50) YES NULL
+describe t2;
+Field Type Null Key Default Extra
+x char(50) YES NULL
+drop table t2;
+create table t2 select now() as a , curtime() as b, curdate() as c , 1+1 as d , 1.0 + 1 as e , 33333333333333333 + 3 as f;
+describe t2;
+Field Type Null Key Default Extra
+a datetime 0000-00-00 00:00:00
+b time 00:00:00
+c date 0000-00-00
+d bigint(17) 0
+e double(18,1) 0.0
+f bigint(17) 0
+drop table t2;
+create table t2 select CAST("2001-12-29" AS DATE) as d, CAST("20:45:11" AS TIME) as t, CAST("2001-12-29 20:45:11" AS DATETIME) as dt;
+describe t2;
+Field Type Null Key Default Extra
+d date 0000-00-00
+t time 00:00:00
+dt datetime 0000-00-00 00:00:00
+drop table t1,t2;
diff --git a/mysql-test/r/ctype_latin1_de.result b/mysql-test/r/ctype_latin1_de.result
new file mode 100644
index 00000000000..58ed0dfdbf3
--- /dev/null
+++ b/mysql-test/r/ctype_latin1_de.result
@@ -0,0 +1,207 @@
+drop table if exists t1;
+create table t1 (a char (20) not null, b int not null auto_increment, index (a,b),index(b));
+insert into t1 (a) values ('ä'),('ac'),('ae'),('ad'),('Äc'),('aeb');
+insert into t1 (a) values ('üc'),('uc'),('ue'),('ud'),('Ü'),('ueb'),('uf');
+insert into t1 (a) values ('ö'),('oc'),('Öa'),('oe'),('od'),('Öc'),('oeb');
+insert into t1 (a) values ('s'),('ss'),('ß'),('ßb'),('ssa'),('ssc'),('ßa');
+insert into t1 (a) values ('eä'),('uü'),('öo'),('ää'),('ääa'),('aeae');
+insert into t1 (a) values ('q'),('a'),('u'),('o'),('é'),('É');
+select a,b from t1 order by a,b;
+a b
+a 35
+ac 2
+ad 4
+ä 1
+ae 3
+ää 31
+aeae 33
+ääa 32
+aeb 6
+Äc 5
+é 38
+É 39
+eä 28
+o 37
+oc 15
+od 18
+ö 14
+oe 17
+Öa 16
+oeb 20
+Öc 19
+öo 30
+q 34
+s 21
+ss 22
+ß 23
+ssa 25
+ßa 27
+ßb 24
+ssc 26
+u 36
+uc 8
+ud 10
+ue 9
+Ü 11
+ueb 12
+üc 7
+uf 13
+uü 29
+select a,b from t1 order by upper(a),b;
+a b
+a 35
+ac 2
+ad 4
+ä 1
+ae 3
+ää 31
+aeae 33
+ääa 32
+aeb 6
+Äc 5
+é 38
+É 39
+eä 28
+o 37
+oc 15
+od 18
+ö 14
+oe 17
+Öa 16
+oeb 20
+Öc 19
+öo 30
+q 34
+s 21
+ss 22
+ß 23
+ssa 25
+ßa 27
+ßb 24
+ssc 26
+u 36
+uc 8
+ud 10
+ue 9
+Ü 11
+ueb 12
+üc 7
+uf 13
+uü 29
+select a from t1 order by a desc;
+a
+uü
+uf
+üc
+ueb
+ue
+ud
+uc
+u
+ssc
+ßb
+ßa
+ssa
+ss
+s
+q
+öo
+Öc
+oeb
+Öa
+oe
+od
+oc
+o
+eä
+Äc
+aeb
+ääa
+aeae
+ää
+ae
+ad
+ac
+a
+check table t1;
+Table Op Msg_type Msg_text
+test.t1 check status OK
+select * from t1 where a like "ö%";
+a b
+ö 14
+Öa 16
+Öc 19
+öo 30
+select * from t1 where a like binary "%É%";
+a b
+É 39
+select * from t1 where a like "%Á%";
+a b
+a 35
+ac 2
+ad 4
+ae 3
+aeae 33
+ääa 32
+aeb 6
+Öa 16
+ssa 25
+ßa 27
+select * from t1 where a like "%U%";
+a b
+u 36
+uc 8
+ud 10
+ue 9
+ueb 12
+uf 13
+uü 29
+select * from t1 where a like "%ss%";
+a b
+ss 22
+ssa 25
+ssc 26
+drop table t1;
+select strcmp('ä','ae'),strcmp('ae','ä'),strcmp('aeq','äq'),strcmp('äq','aeq');
+strcmp('ä','ae') strcmp('ae','ä') strcmp('aeq','äq') strcmp('äq','aeq')
+0 0 0 0
+select strcmp('ss','ß'),strcmp('ß','ss'),strcmp('ßs','sss'),strcmp('ßq','ssq');
+strcmp('ss','ß') strcmp('ß','ss') strcmp('ßs','sss') strcmp('ßq','ssq')
+0 0 0 0
+select strcmp('ä','af'),strcmp('a','ä'),strcmp('ää','aeq'),strcmp('ää','aeaeq');
+strcmp('ä','af') strcmp('a','ä') strcmp('ää','aeq') strcmp('ää','aeaeq')
+-1 -1 -1 -1
+select strcmp('ss','ßa'),strcmp('ß','ssa'),strcmp('sßa','sssb'),strcmp('s','ß');
+strcmp('ss','ßa') strcmp('ß','ssa') strcmp('sßa','sssb') strcmp('s','ß')
+-1 -1 -1 -1
+select strcmp('ö','oö'),strcmp('Ü','uü'),strcmp('ö','oeb');
+strcmp('ö','oö') strcmp('Ü','uü') strcmp('ö','oeb')
+-1 -1 -1
+select strcmp('af','ä'),strcmp('ä','a'),strcmp('aeq','ää'),strcmp('aeaeq','ää');
+strcmp('af','ä') strcmp('ä','a') strcmp('aeq','ää') strcmp('aeaeq','ää')
+1 1 1 1
+select strcmp('ßa','ss'),strcmp('ssa','ß'),strcmp('sssb','sßa'),strcmp('ß','s');
+strcmp('ßa','ss') strcmp('ssa','ß') strcmp('sssb','sßa') strcmp('ß','s')
+1 1 1 1
+select strcmp('u','öa'),strcmp('u','ö');
+strcmp('u','öa') strcmp('u','ö')
+1 1
+create table t1 (a varchar(10), key(a));
+insert into t1 values ("a"),("abc"),("abcd"),("hello"),("test");
+select * from t1 where a like "abc%";
+a
+abc
+abcd
+select * from t1 where a like "test%";
+a
+test
+select * from t1 where a like "te_t";
+a
+test
+drop table t1;
diff --git a/mysql-test/r/delayed.result b/mysql-test/r/delayed.result
index d1914341a8d..44aef139ad2 100644
--- a/mysql-test/r/delayed.result
+++ b/mysql-test/r/delayed.result
@@ -1,10 +1,30 @@
+create table t1 (a char(10), tmsp timestamp);
+insert into t1 set a = 1;
+insert delayed into t1 set a = 2;
+insert into t1 set a = 3, tmsp=NULL;
+insert delayed into t1 set a = 4;
+insert delayed into t1 set a = 5, tmsp = 19711006010203;
+insert delayed into t1 (a, tmsp) values (6, 19711006010203);
+insert delayed into t1 (a, tmsp) values (7, NULL);
+insert into t1 set a = 8,tmsp=19711006010203;
+select * from t1 where tmsp=0;
a tmsp
+select * from t1 where tmsp=19711006010203;
a tmsp
5 19711006010203
6 19711006010203
8 19711006010203
+drop table t1;
+create table t1 (a int not null auto_increment primary key, b char(10));
+insert delayed into t1 values (1,"b");
+insert delayed into t1 values (null,"c");
+insert delayed into t1 values (3,"d"),(null,"e");
+insert delayed into t1 values (3,"this will give an","error");
+Column count doesn't match value count at row 1
+select * from t1;
a b
1 b
2 c
3 d
4 e
+drop table t1;
diff --git a/mysql-test/r/delete.result b/mysql-test/r/delete.result
new file mode 100644
index 00000000000..c2230722aa6
--- /dev/null
+++ b/mysql-test/r/delete.result
@@ -0,0 +1,26 @@
+drop table if exists t1;
+CREATE TABLE t1 (a tinyint(3), b tinyint(5));
+INSERT INTO t1 VALUES (1,1);
+INSERT LOW_PRIORITY INTO t1 VALUES (1,2);
+INSERT INTO t1 VALUES (1,3);
+DELETE from t1 where a=1 limit 1;
+DELETE LOW_PRIORITY from t1 where a=1;
+INSERT INTO t1 VALUES (1,1);
+DELETE from t1;
+LOCK TABLE t1 write;
+INSERT INTO t1 VALUES (1,2);
+DELETE from t1;
+UNLOCK TABLES;
+INSERT INTO t1 VALUES (1,2);
+SET AUTOCOMMIT=0;
+DELETE from t1;
+SET AUTOCOMMIT=1;
+drop table t1;
+create table t1 (a bigint not null, primary key (a,a,a,a,a,a,a,a,a,a));
+insert into t1 values (2),(4),(6),(8),(10),(12),(14),(16),(18),(20),(22),(24),(26),(23);
+delete from t1 where a=26;
+drop table t1;
+create table t1 (a bigint not null, primary key (a,a,a,a,a,a,a,a,a,a));
+insert into t1 values (2),(4),(6),(8),(10),(12),(14),(16),(18),(20),(22),(24),(26),(23),(27);
+delete from t1 where a=27;
+drop table t1;
diff --git a/mysql-test/r/dirty-close.result b/mysql-test/r/dirty-close.result
deleted file mode 100644
index f85b057eefa..00000000000
--- a/mysql-test/r/dirty-close.result
+++ /dev/null
@@ -1,4 +0,0 @@
-n
-1
-2
-3
diff --git a/mysql-test/r/dirty_close.result b/mysql-test/r/dirty_close.result
new file mode 100644
index 00000000000..c4fc19a35f8
--- /dev/null
+++ b/mysql-test/r/dirty_close.result
@@ -0,0 +1,9 @@
+drop table if exists t1;
+create table t1 (n int);
+insert into t1 values (1),(2),(3);
+select * from t1;
+n
+1
+2
+3
+drop table t1;
diff --git a/mysql-test/r/distinct.result b/mysql-test/r/distinct.result
index 8f8770e5602..21f87a11a53 100644
--- a/mysql-test/r/distinct.result
+++ b/mysql-test/r/distinct.result
@@ -1,3 +1,21 @@
+drop table if exists t1,t2,t3;
+CREATE TABLE t1 (id int,facility char(20));
+CREATE TABLE t2 (facility char(20));
+INSERT INTO t1 VALUES (NULL,NULL);
+INSERT INTO t1 VALUES (-1,'');
+INSERT INTO t1 VALUES (0,'');
+INSERT INTO t1 VALUES (1,'/L');
+INSERT INTO t1 VALUES (2,'A01');
+INSERT INTO t1 VALUES (3,'ANC');
+INSERT INTO t1 VALUES (4,'F01');
+INSERT INTO t1 VALUES (5,'FBX');
+INSERT INTO t1 VALUES (6,'MT');
+INSERT INTO t1 VALUES (7,'P');
+INSERT INTO t1 VALUES (8,'RV');
+INSERT INTO t1 VALUES (9,'SRV');
+INSERT INTO t1 VALUES (10,'VMT');
+INSERT INTO t2 SELECT DISTINCT FACILITY FROM t1;
+select id from t1 group by id;
id
NULL
-1
@@ -12,6 +30,7 @@ NULL
8
9
10
+select * from t1 order by id;
id facility
NULL NULL
-1
@@ -26,6 +45,7 @@ NULL NULL
8 RV
9 SRV
10 VMT
+select id-5,facility from t1 order by "id-5";
id-5 facility
NULL NULL
-6
@@ -40,6 +60,7 @@ NULL NULL
3 RV
4 SRV
5 VMT
+select id,concat(facility) from t1 group by id ;
id concat(facility)
NULL NULL
-1
@@ -54,6 +75,7 @@ NULL NULL
8 RV
9 SRV
10 VMT
+select id+0 as a,max(id),concat(facility) as b from t1 group by a order by b desc,a;
a max(id) b
10 10 VMT
9 9 SRV
@@ -68,9 +90,11 @@ a max(id) b
-1 -1
0 0
NULL NULL NULL
+select id >= 0 and id <= 5 as grp,count(*) from t1 group by grp;
grp count(*)
0 7
1 6
+SELECT DISTINCT FACILITY FROM t1;
FACILITY
NULL
@@ -84,6 +108,7 @@ P
RV
SRV
VMT
+SELECT FACILITY FROM t2;
FACILITY
NULL
@@ -97,52 +122,157 @@ P
RV
SRV
VMT
+SELECT count(*) from t1,t2 where t1.facility=t2.facility;
count(*)
12
+select count(facility) from t1;
count(facility)
12
+select count(*) from t1;
count(*)
13
+select count(*) from t1 where facility IS NULL;
count(*)
1
+select count(*) from t1 where facility = NULL;
count(*)
0
+select count(*) from t1 where facility IS NOT NULL;
count(*)
12
+select count(*) from t1 where id IS NULL;
count(*)
1
+select count(*) from t1 where id IS NOT NULL;
count(*)
12
+drop table t1,t2;
+CREATE TABLE t1 (UserId int(11) DEFAULT '0' NOT NULL);
+INSERT INTO t1 VALUES (20);
+INSERT INTO t1 VALUES (27);
+SELECT UserId FROM t1 WHERE Userid=22;
UserId
+SELECT UserId FROM t1 WHERE UserId=22 group by Userid;
UserId
+SELECT DISTINCT UserId FROM t1 WHERE UserId=22 group by Userid;
UserId
+SELECT DISTINCT UserId FROM t1 WHERE UserId=22;
UserId
+drop table t1;
+CREATE TABLE t1 (a int(10) unsigned not null primary key,b int(10) unsigned);
+INSERT INTO t1 VALUES (1,1),(2,1);
+CREATE TABLE t2 (a int(10) unsigned not null, key (A));
+INSERT INTO t2 VALUES (1),(2);
+CREATE TABLE t3 (a int(10) unsigned, key(A), b text);
+INSERT INTO t3 VALUES (1,'1'),(2,'2');
+SELECT DISTINCT t3.b FROM t3,t2,t1 WHERE t3.a=t1.b AND t1.a=t2.a;
b
1
+INSERT INTO t2 values (1),(2),(3);
+INSERT INTO t3 VALUES (1,'1'),(2,'2'),(1,'1'),(2,'2');
+explain SELECT distinct t3.a FROM t3,t2,t1 WHERE t3.a=t1.b AND t1.a=t2.a;
table type possible_keys key key_len ref rows Extra
t3 index a a 5 NULL 6 Using index; Using temporary
t2 index a a 4 NULL 5 Using index; Distinct
t1 eq_ref PRIMARY PRIMARY 4 t2.a 1 where used; Distinct
+SELECT distinct t3.a FROM t3,t2,t1 WHERE t3.a=t1.b AND t1.a=t2.a;
a
1
+create temporary table t4 select * from t3;
+insert into t3 select * from t4;
+insert into t4 select * from t3;
+insert into t3 select * from t4;
+insert into t4 select * from t3;
+insert into t3 select * from t4;
+insert into t4 select * from t3;
+insert into t3 select * from t4;
+explain select distinct t1.a from t1,t3 where t1.a=t3.a;
table type possible_keys key key_len ref rows Extra
t1 index PRIMARY PRIMARY 4 NULL 2 Using index; Using temporary
t3 ref a a 5 t1.a 10 Using index; Distinct
+select distinct t1.a from t1,t3 where t1.a=t3.a;
a
1
2
+select distinct 1 from t1,t3 where t1.a=t3.a;
1
1
+drop table t1,t2,t3,t4;
+CREATE TABLE t1 (name varchar(255));
+INSERT INTO t1 VALUES ('aa'),('ab'),('ac'),('ad'),('ae');
+SELECT DISTINCT * FROM t1 LIMIT 2;
name
aa
ab
+SELECT DISTINCT name FROM t1 LIMIT 2;
name
aa
ab
+SELECT DISTINCT 1 FROM t1 LIMIT 2;
1
1
+drop table t1;
+CREATE TABLE t1 (
+ID int(11) NOT NULL auto_increment,
+NAME varchar(75) DEFAULT '' NOT NULL,
+LINK_ID int(11) DEFAULT '0' NOT NULL,
+PRIMARY KEY (ID),
+KEY NAME (NAME),
+KEY LINK_ID (LINK_ID)
+);
+INSERT INTO t1 (ID, NAME, LINK_ID) VALUES (1,'Mike',0),(2,'Jack',0),(3,'Bill',0);
+CREATE TABLE t2 (
+ID int(11) NOT NULL auto_increment,
+NAME varchar(150) DEFAULT '' NOT NULL,
+PRIMARY KEY (ID),
+KEY NAME (NAME)
+);
+SELECT DISTINCT
+t2.id AS key_link_id,
+t2.name AS link
+FROM t1
+LEFT JOIN t2 ON t1.link_id=t2.id
+GROUP BY t1.id
+ORDER BY link;
key_link_id link
NULL NULL
+drop table t1,t2;
+create table t1 (
+id int not null,
+name tinytext not null,
+unique (id)
+);
+create table t2 (
+id int not null,
+idx int not null,
+unique (id, idx)
+);
+create table t3 (
+id int not null,
+idx int not null,
+unique (id, idx)
+);
+insert into t1 values (1,'yes'), (2,'no');
+insert into t2 values (1,1);
+insert into t3 values (1,1);
+EXPLAIN
+SELECT DISTINCT
+t1.id
+from
+t1
+straight_join
+t2
+straight_join
+t3
+straight_join
+t1 as j_lj_t2 left join t2 as t2_lj
+on j_lj_t2.id=t2_lj.id
+straight_join
+t1 as j_lj_t3 left join t3 as t3_lj
+on j_lj_t3.id=t3_lj.id
+WHERE
+((t1.id=j_lj_t2.id AND t2_lj.id IS NULL) OR (t1.id=t2.id AND t2.idx=2))
+AND ((t1.id=j_lj_t3.id AND t3_lj.id IS NULL) OR (t1.id=t3.id AND t3.idx=2));
table type possible_keys key key_len ref rows Extra
t1 index id id 4 NULL 2 Using index; Using temporary
t2 index id id 8 NULL 1 Using index; Distinct
@@ -151,25 +281,58 @@ j_lj_t2 index id id 4 NULL 2 where used; Using index; Distinct
t2_lj index id id 8 NULL 1 where used; Using index; Distinct
j_lj_t3 index id id 4 NULL 2 where used; Using index; Distinct
t3_lj index id id 8 NULL 1 where used; Using index; Distinct
+SELECT DISTINCT
+t1.id
+from
+t1
+straight_join
+t2
+straight_join
+t3
+straight_join
+t1 as j_lj_t2 left join t2 as t2_lj
+on j_lj_t2.id=t2_lj.id
+straight_join
+t1 as j_lj_t3 left join t3 as t3_lj
+on j_lj_t3.id=t3_lj.id
+WHERE
+((t1.id=j_lj_t2.id AND t2_lj.id IS NULL) OR (t1.id=t2.id AND t2.idx=2))
+AND ((t1.id=j_lj_t3.id AND t3_lj.id IS NULL) OR (t1.id=t3.id AND t3.idx=2));
id
2
+drop table t1,t2,t3;
+drop table if exists t1;
+create table t1 (a int not null, b int not null, t time);
+insert into t1 values (1,1,"00:06:15"),(1,2,"00:06:15"),(1,2,"00:30:15"),(1,3,"00:06:15"),(1,3,"00:30:15");
+select a,sec_to_time(sum(time_to_sec(t))) from t1 group by a,b;
a sec_to_time(sum(time_to_sec(t)))
1 00:06:15
1 00:36:30
1 00:36:30
+select distinct a,sec_to_time(sum(time_to_sec(t))) from t1 group by a,b;
a sec_to_time(sum(time_to_sec(t)))
1 00:06:15
1 00:36:30
+create table t2 (a int not null primary key, b int);
+insert into t2 values (1,1),(2,2),(3,3);
+select t1.a,sec_to_time(sum(time_to_sec(t))) from t1 left join t2 on (t1.b=t2.a) group by t1.a,t2.b;
a sec_to_time(sum(time_to_sec(t)))
1 00:06:15
1 00:36:30
1 00:36:30
+select distinct t1.a,sec_to_time(sum(time_to_sec(t))) from t1 left join t2 on (t1.b=t2.a) group by t1.a,t2.b;
a sec_to_time(sum(time_to_sec(t)))
1 00:06:15
1 00:36:30
+drop table t1,t2;
+create table t1 (a int not null,b char(5), c text);
+insert into t1 (a) values (1),(2),(3),(4),(1),(2),(3),(4);
+select distinct a from t1 group by b,a having a > 2 order by a desc;
a
4
3
+select distinct a,c from t1 group by b,c,a having a > 2 order by a desc;
a c
4 NULL
3 NULL
+drop table t1;
diff --git a/mysql-test/r/drop.result b/mysql-test/r/drop.result
index 741fc6bba85..178c3a8cb4f 100644
--- a/mysql-test/r/drop.result
+++ b/mysql-test/r/drop.result
@@ -1,11 +1,48 @@
+drop table if exists t1;
+drop table if exists t1;
+drop table t1;
+Unknown table 't1'
+create table t1(n int);
+insert into t1 values(1);
+create temporary table t1( n int);
+insert into t1 values(2);
+create table t1(n int);
+Table 't1' already exists
+drop table t1;
+select * from t1;
n
1
+drop database if exists mysqltest;
+create database mysqltest;
+drop database if exists mysqltest;
+create database mysqltest;
+create table mysqltest.mysqltest (n int);
+insert into mysqltest.mysqltest values (4);
+select * from mysqltest.mysqltest;
n
4
+drop database if exists mysqltest;
+create database mysqltest;
+drop database mysqltest;
+drop database if exists mysqltest;
+flush tables with read lock;
+create database mysqltest;
+Got one of the listed errors
+unlock tables;
+create database mysqltest;
+show databases;
Database
-foo
mysql
+mysqltest
test
+flush tables with read lock;
+drop database mysqltest;
+Got one of the listed errors
+unlock tables;
+drop database mysqltest;
+show databases;
Database
mysql
test
+drop database mysqltest;
+Can't drop database 'mysqltest'. Database doesn't exist
diff --git a/mysql-test/r/empty_table.result b/mysql-test/r/empty_table.result
index 284ed65ee3b..cea787f4abd 100644
--- a/mysql-test/r/empty_table.result
+++ b/mysql-test/r/empty_table.result
@@ -1,4 +1,10 @@
+drop table if exists t1;
+create table t1 (nr int(5) not null auto_increment,b blob,str char(10), primary key (nr));
+select count(*) from t1;
count(*)
0
+select * from t1;
nr b str
+select * from t1 limit 0;
nr b str
+drop table t1;
diff --git a/mysql-test/r/err000001.result b/mysql-test/r/err000001.result
new file mode 100644
index 00000000000..5afecc6d600
--- /dev/null
+++ b/mysql-test/r/err000001.result
@@ -0,0 +1,25 @@
+drop table if exists t1;
+insert into t1 values(1);
+Table 'test.t1' doesn't exist
+delete from t1;
+Table 'test.t1' doesn't exist
+update t1 set a=1;
+Table 'test.t1' doesn't exist
+create table t1 (a int);
+select count(test.t1.b) from t1;
+Unknown column 'test.t1.b' in 'field list'
+select count(not_existing_database.t1) from t1;
+Unknown table 'not_existing_database' in field list
+select count(not_existing_database.t1.a) from t1;
+Unknown table 'not_existing_database.t1' in field list
+select count(not_existing_database.t1.a) from not_existing_database.t1;
+Got one of the listed errors
+select 1 from t1 order by 2;
+Unknown column '2' in 'order clause'
+select 1 from t1 group by 2;
+Unknown column '2' in 'group statement'
+select 1 from t1 order by t1.b;
+Unknown column 't1.b' in 'order clause'
+select count(*),b from t1;
+Unknown column 'b' in 'field list'
+drop table t1;
diff --git a/mysql-test/r/explain.result b/mysql-test/r/explain.result
index 558feb10f84..5b4da25d535 100644
--- a/mysql-test/r/explain.result
+++ b/mysql-test/r/explain.result
@@ -1,15 +1,30 @@
+drop table if exists t1;
+create table t1 (id int not null, str char(10), unique(str));
+insert into t1 values (1, null),(2, null),(3, "foo"),(4, "bar");
+select * from t1 where str is null;
id str
1 NULL
2 NULL
+select * from t1 where str="foo";
id str
3 foo
+explain select * from t1 where str is null;
table type possible_keys key key_len ref rows Extra
t1 ref str str 11 const 1 where used
+explain select * from t1 where str="foo";
table type possible_keys key key_len ref rows Extra
t1 const str str 11 const 1
+explain select * from t1 ignore key (str) where str="foo";
table type possible_keys key key_len ref rows Extra
-t1 ALL str NULL NULL NULL 4 where used
+t1 ALL NULL NULL NULL NULL 4 where used
+explain select * from t1 use key (str,str) where str="foo";
table type possible_keys key key_len ref rows Extra
t1 const str str 11 const 1
+explain select * from t1 use key (str,str,foo) where str="foo";
+Key column 'foo' doesn't exist in table
+explain select * from t1 ignore key (str,str,foo) where str="foo";
+Key column 'foo' doesn't exist in table
+drop table t1;
+explain select 1;
Comment
No tables used
diff --git a/mysql-test/r/flush.result b/mysql-test/r/flush.result
index fca84de710c..a7f73a6840b 100644
--- a/mysql-test/r/flush.result
+++ b/mysql-test/r/flush.result
@@ -1,6 +1,35 @@
+drop table if exists t1;
+create temporary table t1(n int not null primary key);
+drop table if exists t2;
+create table t2(n int);
+insert into t2 values(3);
+select * from t1;
n
3
+flush tables with read lock;
+drop table t2;
+Table 't2' was locked with a READ lock and can't be updated
+ drop table t2;
+unlock tables;
+drop database if exists mysqltest;
+create database mysqltest;
+create table mysqltest.t1(n int);
+insert into mysqltest.t1 values (23);
+flush tables with read lock;
+ drop database mysqltest;
+select * from mysqltest.t1;
n
23
+unlock tables;
+create table t1 (n int);
+flush tables with read lock;
+insert into t1 values (345);
+select * from t1;
n
345
+drop table t1;
+flush query cache;
+reset query cache;
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 0
diff --git a/mysql-test/r/foreign_key.result b/mysql-test/r/foreign_key.result
new file mode 100644
index 00000000000..ece53db2e9a
--- /dev/null
+++ b/mysql-test/r/foreign_key.result
@@ -0,0 +1,15 @@
+drop table if exists t1;
+create table t1 (
+a int not null references t2,
+b int not null references t2 (c),
+primary key (a,b),
+foreign key (a) references t3 match full,
+foreign key (a) references t3 match partial,
+foreign key (a,b) references t3 (c,d) on delete no action
+on update no action,
+foreign key (a,b) references t3 (c,d) on update cascade,
+foreign key (a,b) references t3 (c,d) on delete set default,
+foreign key (a,b) references t3 (c,d) on update set null);
+create index a on t1 (a);
+create unique index b on t1 (a,b);
+drop table t1;
diff --git a/mysql-test/r/fulltext.result b/mysql-test/r/fulltext.result
index c39210107ae..1d03dffa76a 100644
--- a/mysql-test/r/fulltext.result
+++ b/mysql-test/r/fulltext.result
@@ -1,22 +1,110 @@
+drop table if exists t1,t2,t3;
+CREATE TABLE t1 (a VARCHAR(200), b TEXT, FULLTEXT (a,b));
+INSERT INTO t1 VALUES('MySQL has now support', 'for full-text search'),
+('Full-text indexes', 'are called collections'),
+('Only MyISAM tables','support collections'),
+('Function MATCH ... AGAINST()','is used to do a search'),
+('Full-text search in MySQL', 'implements vector space model');
+select * from t1 where MATCH(a,b) AGAINST ("collections");
a b
Only MyISAM tables support collections
Full-text indexes are called collections
+select * from t1 where MATCH(a,b) AGAINST ("indexes");
a b
Full-text indexes are called collections
+select * from t1 where MATCH(a,b) AGAINST ("indexes collections");
a b
Full-text indexes are called collections
Only MyISAM tables support collections
+select * from t1 where MATCH(a,b) AGAINST("support -collections" IN BOOLEAN MODE);
+a b
+MySQL has now support for full-text search
+select * from t1 where MATCH(a,b) AGAINST("support collections" IN BOOLEAN MODE);
+a b
+MySQL has now support for full-text search
+Full-text indexes are called collections
+Only MyISAM tables support collections
+select * from t1 where MATCH(a,b) AGAINST("support +collections" IN BOOLEAN MODE);
+a b
+Full-text indexes are called collections
+Only MyISAM tables support collections
+select * from t1 where MATCH(a,b) AGAINST("sear*" IN BOOLEAN MODE);
+a b
+MySQL has now support for full-text search
+Function MATCH ... AGAINST() is used to do a search
+Full-text search in MySQL implements vector space model
+select * from t1 where MATCH(a,b) AGAINST("+support +collections" IN BOOLEAN MODE);
+a b
+Only MyISAM tables support collections
+select * from t1 where MATCH(a,b) AGAINST("+search" IN BOOLEAN MODE);
+a b
+MySQL has now support for full-text search
+Function MATCH ... AGAINST() is used to do a search
+Full-text search in MySQL implements vector space model
+select * from t1 where MATCH(a,b) AGAINST("+search +(support vector)" IN BOOLEAN MODE);
+a b
+MySQL has now support for full-text search
+Full-text search in MySQL implements vector space model
+select * from t1 where MATCH(a,b) AGAINST("+search -(support vector)" IN BOOLEAN MODE);
+a b
+Function MATCH ... AGAINST() is used to do a search
+select *, MATCH(a,b) AGAINST("support collections" IN BOOLEAN MODE) as x from t1;
+a b x
+MySQL has now support for full-text search 1
+Full-text indexes are called collections 1
+Only MyISAM tables support collections 2
+Function MATCH ... AGAINST() is used to do a search 0
+Full-text search in MySQL implements vector space model 0
+select * from t1 where MATCH a AGAINST ("search" IN BOOLEAN MODE);
+a b
+Full-text search in MySQL implements vector space model
+select * from t1 where MATCH b AGAINST ("sear*" IN BOOLEAN MODE);
+a b
+MySQL has now support for full-text search
+Function MATCH ... AGAINST() is used to do a search
+delete from t1 where a like "MySQL%";
+update t1 set a='some test foobar' where MATCH a,b AGAINST ('model');
+delete from t1 where MATCH(a,b) AGAINST ("indexes");
+select * from t1;
a b
Only MyISAM tables support collections
Function MATCH ... AGAINST() is used to do a search
some test foobar implements vector space model
+drop table t1;
+CREATE TABLE t1 (
+id int(11),
+ticket int(11),
+KEY ti (id),
+KEY tit (ticket)
+);
+INSERT INTO t1 VALUES (2,3),(1,2);
+CREATE TABLE t2 (
+ticket int(11),
+inhalt text,
+KEY tig (ticket),
+fulltext index tix (inhalt)
+);
+INSERT INTO t2 VALUES (1,'foo'),(2,'bar'),(3,'foobar');
+select t1.id FROM t2 as ttxt,t1,t1 as ticket2
+WHERE ticket2.id = ttxt.ticket AND t1.id = ticket2.ticket and
+match(ttxt.inhalt) against ('foobar');
id
+select t1.id FROM t2 as ttxt,t1 INNER JOIN t1 as ticket2 ON
+ticket2.id = ttxt.ticket
+WHERE t1.id = ticket2.ticket and match(ttxt.inhalt) against ('foobar');
id
+INSERT INTO t1 VALUES (3,3);
+select t1.id FROM t2 as ttxt,t1
+INNER JOIN t1 as ticket2 ON ticket2.id = ttxt.ticket
+WHERE t1.id = ticket2.ticket and
+match(ttxt.inhalt) against ('foobar');
id
3
-Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Comment
-t2 1 tig 1 ticket A NULL NULL NULL
-t2 1 tix 1 inhalt A NULL 1 NULL FULLTEXT
+show keys from t2;
+Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
+t2 1 tig 1 ticket A NULL NULL NULL YES BTREE
+t2 1 tix 1 inhalt A NULL 1 NULL YES FULLTEXT
+show create table t2;
Table Create Table
t2 CREATE TABLE `t2` (
`ticket` int(11) default NULL,
@@ -24,8 +112,41 @@ t2 CREATE TABLE `t2` (
KEY `tig` (`ticket`),
FULLTEXT KEY `tix` (`inhalt`)
) TYPE=MyISAM
+select * from t2 where MATCH inhalt AGAINST (NULL);
ticket inhalt
+select * from t2 where MATCH inhalt AGAINST ('foobar');
ticket inhalt
3 foobar
+select * from t2 having MATCH inhalt AGAINST ('foobar');
ticket inhalt
3 foobar
+CREATE TABLE t3 (
+ticket int(11),
+inhalt text,
+KEY tig (ticket),
+fulltext index tix (inhalt)
+);
+select * from t2 where MATCH inhalt AGAINST (t2.inhalt);
+Wrong arguments to AGAINST
+select * from t2 where MATCH ticket AGAINST ('foobar');
+Can't find FULLTEXT index matching the column list
+select * from t2,t3 where MATCH (t2.inhalt,t3.inhalt) AGAINST ('foobar');
+Wrong arguments to MATCH
+drop table t1,t2,t3;
+CREATE TABLE t1 (
+id int(11) auto_increment,
+title varchar(100) default '',
+PRIMARY KEY (id),
+KEY ind5 (title),
+FULLTEXT KEY FT1 (title)
+) TYPE=MyISAM;
+insert into t1 (title) values ('this is a test');
+update t1 set title='this is A test' where id=1;
+check table t1;
+Table Op Msg_type Msg_text
+test.t1 check status OK
+update t1 set title='this test once revealed a bug' where id=1;
+select * from t1;
+id title
+1 this test once revealed a bug
+update t1 set title=NULL where id=1;
diff --git a/mysql-test/r/fulltext_cache.result b/mysql-test/r/fulltext_cache.result
index a580437b0ce..c489bdefeb8 100644
--- a/mysql-test/r/fulltext_cache.result
+++ b/mysql-test/r/fulltext_cache.result
@@ -1,5 +1,30 @@
+drop table if exists t1, t2;
+CREATE TABLE t1 (
+id int(10) unsigned NOT NULL auto_increment,
+q varchar(255) default NULL,
+PRIMARY KEY (id)
+);
+INSERT INTO t1 VALUES (1,'aaaaaaaaa dsaass de');
+INSERT INTO t1 VALUES (2,'ssde df s fsda sad er');
+CREATE TABLE t2 (
+id int(10) unsigned NOT NULL auto_increment,
+id2 int(10) unsigned default NULL,
+item varchar(255) default NULL,
+PRIMARY KEY (id),
+FULLTEXT KEY item(item)
+);
+INSERT INTO t2 VALUES (1,1,'sushi');
+INSERT INTO t2 VALUES (2,1,'Bolo de Chocolate');
+INSERT INTO t2 VALUES (3,1,'Feijoada');
+INSERT INTO t2 VALUES (4,1,'Mousse de Chocolate');
+INSERT INTO t2 VALUES (5,2,'um copo de Vodka');
+INSERT INTO t2 VALUES (6,2,'um chocolate Snickers');
+INSERT INTO t2 VALUES (7,1,'Bife');
+INSERT INTO t2 VALUES (8,1,'Pizza de Salmao');
+SELECT t1.q, t2.item, t2.id, MATCH t2.item AGAINST ('sushi')
+as x FROM t1, t2 WHERE (t2.id2 = t1.id) ORDER BY x DESC,t2.id;
q item id x
-aaaaaaaaa dsaass de sushi 1 1.92378665219675
+aaaaaaaaa dsaass de sushi 1 1.92378664016724
aaaaaaaaa dsaass de Bolo de Chocolate 2 0
aaaaaaaaa dsaass de Feijoada 3 0
aaaaaaaaa dsaass de Mousse de Chocolate 4 0
@@ -7,8 +32,10 @@ ssde df s fsda sad er um copo de Vodka 5 0
ssde df s fsda sad er um chocolate Snickers 6 0
aaaaaaaaa dsaass de Bife 7 0
aaaaaaaaa dsaass de Pizza de Salmao 8 0
+SELECT t1.q, t2.item, t2.id, MATCH t2.item AGAINST ('sushi' IN BOOLEAN MODE)
+as x FROM t1, t2 WHERE (t2.id2 = t1.id) ORDER BY x DESC,t2.id;
q item id x
-aaaaaaaaa dsaass de sushi 1 1.92378665219675
+aaaaaaaaa dsaass de sushi 1 1
aaaaaaaaa dsaass de Bolo de Chocolate 2 0
aaaaaaaaa dsaass de Feijoada 3 0
aaaaaaaaa dsaass de Mousse de Chocolate 4 0
@@ -16,3 +43,26 @@ ssde df s fsda sad er um copo de Vodka 5 0
ssde df s fsda sad er um chocolate Snickers 6 0
aaaaaaaaa dsaass de Bife 7 0
aaaaaaaaa dsaass de Pizza de Salmao 8 0
+SELECT t1.q, t2.item, t2.id, MATCH t2.item AGAINST ('sushi')
+as x FROM t2, t1 WHERE (t2.id2 = t1.id) ORDER BY x DESC,t2.id;
+q item id x
+aaaaaaaaa dsaass de sushi 1 1.92378664016724
+aaaaaaaaa dsaass de Bolo de Chocolate 2 0
+aaaaaaaaa dsaass de Feijoada 3 0
+aaaaaaaaa dsaass de Mousse de Chocolate 4 0
+ssde df s fsda sad er um copo de Vodka 5 0
+ssde df s fsda sad er um chocolate Snickers 6 0
+aaaaaaaaa dsaass de Bife 7 0
+aaaaaaaaa dsaass de Pizza de Salmao 8 0
+SELECT t1.q, t2.item, t2.id, MATCH t2.item AGAINST ('sushi' IN BOOLEAN MODE)
+as x FROM t2, t1 WHERE (t2.id2 = t1.id) ORDER BY x DESC,t2.id;
+q item id x
+aaaaaaaaa dsaass de sushi 1 1
+aaaaaaaaa dsaass de Bolo de Chocolate 2 0
+aaaaaaaaa dsaass de Feijoada 3 0
+aaaaaaaaa dsaass de Mousse de Chocolate 4 0
+ssde df s fsda sad er um copo de Vodka 5 0
+ssde df s fsda sad er um chocolate Snickers 6 0
+aaaaaaaaa dsaass de Bife 7 0
+aaaaaaaaa dsaass de Pizza de Salmao 8 0
+drop table t1, t2;
diff --git a/mysql-test/r/fulltext_distinct.result b/mysql-test/r/fulltext_distinct.result
new file mode 100644
index 00000000000..abb4929d0ec
--- /dev/null
+++ b/mysql-test/r/fulltext_distinct.result
@@ -0,0 +1,43 @@
+DROP TABLE IF EXISTS t1, t2;
+CREATE TABLE t1 (
+id mediumint unsigned NOT NULL auto_increment,
+tag char(6) NOT NULL default '',
+value text NOT NULL default '',
+PRIMARY KEY (id),
+KEY kt(tag),
+KEY kv(value(15)),
+FULLTEXT KEY kvf(value)
+) TYPE=MyISAM;
+CREATE TABLE t2 (
+id_t2 mediumint unsigned NOT NULL default '0',
+id_t1 mediumint unsigned NOT NULL default '0',
+field_number tinyint unsigned NOT NULL default '0',
+PRIMARY KEY (id_t2,id_t1,field_number),
+KEY id_t1(id_t1)
+) TYPE=MyISAM;
+INSERT INTO t1 (tag,value) VALUES ('foo123','bar111');
+INSERT INTO t1 (tag,value) VALUES ('foo123','bar222');
+INSERT INTO t1 (tag,value) VALUES ('bar345','baz333 ar');
+INSERT INTO t2 VALUES (2231626,64280,0);
+INSERT INTO t2 VALUES (2231626,64281,0);
+INSERT INTO t2 VALUES (12346, 3, 1);
+SELECT * FROM t1;
+id tag value
+1 foo123 bar111
+2 foo123 bar222
+3 bar345 baz333 ar
+SELECT * FROM t2;
+id_t2 id_t1 field_number
+12346 3 1
+2231626 64280 0
+2231626 64281 0
+SELECT DISTINCT t2.id_t2 FROM t2, t1
+WHERE MATCH (t1.value) AGAINST ('baz333') AND t1.id = t2.id_t1;
+id_t2
+12346
+SELECT DISTINCT t2.id_t2 FROM t2, t1
+WHERE MATCH (t1.value) AGAINST ('baz333' IN BOOLEAN MODE)
+AND t1.id = t2.id_t1;
+id_t2
+12346
+DROP TABLE t1, t2;
diff --git a/mysql-test/r/fulltext_left_join.result b/mysql-test/r/fulltext_left_join.result
index 04244e309e5..9f2ba6a5947 100644
--- a/mysql-test/r/fulltext_left_join.result
+++ b/mysql-test/r/fulltext_left_join.result
@@ -1,5 +1,32 @@
+CREATE TABLE t1 (
+id VARCHAR(255) NOT NULL PRIMARY KEY,
+sujet VARCHAR(255),
+motsclefs TEXT,
+texte MEDIUMTEXT,
+FULLTEXT(sujet, motsclefs, texte)
+);
+INSERT INTO t1 VALUES('123','toto','essai','test');
+INSERT INTO t1 VALUES('456','droit','penal','lawyer');
+INSERT INTO t1 VALUES('789','aaaaa','bbbbb','cccccc');
+CREATE TABLE t2 (
+id VARCHAR(255) NOT NULL,
+author VARCHAR(255) NOT NULL
+);
+INSERT INTO t2 VALUES('123', 'moi');
+INSERT INTO t2 VALUES('123', 'lui');
+INSERT INTO t2 VALUES('456', 'lui');
+select match(t1.texte,t1.sujet,t1.motsclefs) against('droit')
+from t1 left join t2 on t2.id=t1.id;
match(t1.texte,t1.sujet,t1.motsclefs) against('droit')
0
0
-0.67003110026735
+0.67003107070923
0
+select match(t1.texte,t1.sujet,t1.motsclefs) against('droit' IN BOOLEAN MODE)
+from t1 left join t2 on t2.id=t1.id;
+match(t1.texte,t1.sujet,t1.motsclefs) against('droit' IN BOOLEAN MODE)
+0
+0
+1
+0
+drop table t1, t2;
diff --git a/mysql-test/r/fulltext_multi.result b/mysql-test/r/fulltext_multi.result
index d78d88172b5..72b7102fd3f 100644
--- a/mysql-test/r/fulltext_multi.result
+++ b/mysql-test/r/fulltext_multi.result
@@ -1,12 +1,30 @@
+use test;
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (
+a int(11) NOT NULL auto_increment,
+b text,
+c varchar(254) default NULL,
+PRIMARY KEY (a),
+FULLTEXT KEY bb(b),
+FULLTEXT KEY cc(c),
+FULLTEXT KEY a(b,c)
+);
+INSERT INTO t1 VALUES (1,'lala lolo lili','oooo aaaa pppp');
+INSERT INTO t1 VALUES (2,'asdf fdsa','lkjh fghj');
+INSERT INTO t1 VALUES (3,'qpwoei','zmxnvb');
+SELECT a, MATCH b AGAINST ('lala lkjh') FROM t1;
a MATCH b AGAINST ('lala lkjh')
-1 0.67003110026735
+1 0.67003107070923
2 0
3 0
+SELECT a, MATCH c AGAINST ('lala lkjh') FROM t1;
a MATCH c AGAINST ('lala lkjh')
1 0
-2 0.67756324121582
+2 0.67756325006485
3 0
+SELECT a, MATCH b,c AGAINST ('lala lkjh') FROM t1;
a MATCH b,c AGAINST ('lala lkjh')
-1 0.64840710366884
-2 0.66266459031789
+1 0.64840710163116
+2 0.66266459226608
3 0
+drop table t1;
diff --git a/mysql-test/r/fulltext_order_by.result b/mysql-test/r/fulltext_order_by.result
index 3ac5285151b..8d88b8d6ebf 100644
--- a/mysql-test/r/fulltext_order_by.result
+++ b/mysql-test/r/fulltext_order_by.result
@@ -1,19 +1,66 @@
+use test;
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (
+a INT AUTO_INCREMENT PRIMARY KEY,
+message CHAR(20),
+FULLTEXT(message)
+) comment = 'original testcase by sroussey@network54.com';
+INSERT INTO t1 (message) VALUES ("Testing"),("table"),("testbug"),
+("steve"),("is"),("cool"),("steve is cool");
+SELECT a, MATCH (message) AGAINST ('steve') FROM t1 WHERE MATCH (message) AGAINST ('steve');
a MATCH (message) AGAINST ('steve')
-4 0.90587321329654
-7 0.89568988462614
+4 0.90587323904037
+7 0.89568990468979
+SELECT a, MATCH (message) AGAINST ('steve' IN BOOLEAN MODE) FROM t1 WHERE MATCH (message) AGAINST ('steve');
+a MATCH (message) AGAINST ('steve' IN BOOLEAN MODE)
+4 1
+7 1
+SELECT a, MATCH (message) AGAINST ('steve') FROM t1 WHERE MATCH (message) AGAINST ('steve' IN BOOLEAN MODE);
a MATCH (message) AGAINST ('steve')
-4 0.90587321329654
-7 0.89568988462614
+4 0.90587323904037
+7 0.89568990468979
+SELECT a, MATCH (message) AGAINST ('steve' IN BOOLEAN MODE) FROM t1 WHERE MATCH (message) AGAINST ('steve' IN BOOLEAN MODE);
+a MATCH (message) AGAINST ('steve' IN BOOLEAN MODE)
+4 1
+7 1
+SELECT a, MATCH (message) AGAINST ('steve') FROM t1 WHERE MATCH (message) AGAINST ('steve') ORDER BY a;
a MATCH (message) AGAINST ('steve')
-7 0.89568988462614
-4 0.90587321329654
+4 0.90587323904037
+7 0.89568990468979
+SELECT a, MATCH (message) AGAINST ('steve' IN BOOLEAN MODE) FROM t1 WHERE MATCH (message) AGAINST ('steve' IN BOOLEAN MODE) ORDER BY a;
+a MATCH (message) AGAINST ('steve' IN BOOLEAN MODE)
+4 1
+7 1
+SELECT a, MATCH (message) AGAINST ('steve') FROM t1 WHERE a in (2,7,4) and MATCH (message) AGAINST ('steve') ORDER BY a DESC;
a MATCH (message) AGAINST ('steve')
-7 0.89568988462614
+7 0.89568990468979
+4 0.90587323904037
+SELECT a, MATCH (message) AGAINST ('steve' IN BOOLEAN MODE) FROM t1 WHERE a in (2,7,4) and MATCH (message) AGAINST ('steve' IN BOOLEAN MODE) ORDER BY a DESC;
+a MATCH (message) AGAINST ('steve' IN BOOLEAN MODE)
+7 1
+4 1
+SELECT a, MATCH (message) AGAINST ('steve') FROM t1 WHERE a=7 and MATCH (message) AGAINST ('steve') ORDER BY 1;
+a MATCH (message) AGAINST ('steve')
+7 0.89568990468979
+SELECT a, MATCH (message) AGAINST ('steve' IN BOOLEAN MODE) FROM t1 WHERE a=7 and MATCH (message) AGAINST ('steve' IN BOOLEAN MODE) ORDER BY 1;
+a MATCH (message) AGAINST ('steve' IN BOOLEAN MODE)
+7 1
+SELECT a, MATCH (message) AGAINST ('steve') as rel FROM t1 ORDER BY rel;
+a rel
+1 0
+2 0
+3 0
+5 0
+6 0
+7 0.89568990468979
+4 0.90587323904037
+SELECT a, MATCH (message) AGAINST ('steve' IN BOOLEAN MODE) as rel FROM t1 ORDER BY rel;
a rel
1 0
2 0
3 0
5 0
6 0
-7 0.89568988462614
-4 0.90587321329654
+4 1
+7 1
+drop table t1;
diff --git a/mysql-test/r/fulltext_update.result b/mysql-test/r/fulltext_update.result
index 77ee76ad30d..5d3f95b318c 100644
--- a/mysql-test/r/fulltext_update.result
+++ b/mysql-test/r/fulltext_update.result
@@ -1,2 +1,22 @@
+drop table if exists test;
+CREATE TABLE test (
+gnr INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
+url VARCHAR(80) DEFAULT '' NOT NULL,
+shortdesc VARCHAR(200) DEFAULT '' NOT NULL,
+longdesc text DEFAULT '' NOT NULL,
+description VARCHAR(80) DEFAULT '' NOT NULL,
+name VARCHAR(80) DEFAULT '' NOT NULL,
+FULLTEXT(url,description,shortdesc,longdesc),
+PRIMARY KEY(gnr)
+);
+insert into test (url,shortdesc,longdesc,description,name) VALUES
+("http:/test.at", "kurz", "lang","desc", "name");
+insert into test (url,shortdesc,longdesc,description,name) VALUES
+("http:/test.at", "kurz", "","desc", "name");
+update test set url='test', description='ddd', name='nam' where gnr=2;
+update test set url='test', shortdesc='ggg', longdesc='mmm',
+description='ddd', name='nam' where gnr=2;
+check table test;
Table Op Msg_type Msg_text
test.test check status OK
+drop table test;
diff --git a/mysql-test/r/fulltext_var.result b/mysql-test/r/fulltext_var.result
new file mode 100644
index 00000000000..eb71e87538d
--- /dev/null
+++ b/mysql-test/r/fulltext_var.result
@@ -0,0 +1,6 @@
+show variables like "ft\_%";
+Variable_name Value
+ft_min_word_len 4
+ft_max_word_len 254
+ft_max_word_len_for_sort 20
+ft_boolean_syntax + -><()~*:""&|
diff --git a/mysql-test/r/func_crypt.result b/mysql-test/r/func_crypt.result
index 021989add8d..cf464ec21b2 100644
--- a/mysql-test/r/func_crypt.result
+++ b/mysql-test/r/func_crypt.result
@@ -1,2 +1,6 @@
+select length(encrypt('foo', 'ff')) <> 0;
length(encrypt('foo', 'ff')) <> 0
1
+select password('test'),length(encrypt('test')),encrypt('test','aa');
+password('test') length(encrypt('test')) encrypt('test','aa')
+378b243e220ca493 13 aaqPiZY5xR5l.
diff --git a/mysql-test/r/func_date_add.result b/mysql-test/r/func_date_add.result
index 3bc0fb1aff3..acdf2c5d7be 100644
--- a/mysql-test/r/func_date_add.result
+++ b/mysql-test/r/func_date_add.result
@@ -1,12 +1,47 @@
+drop table if exists t1;
+CREATE TABLE t1 (
+visitor_id int(10) unsigned DEFAULT '0' NOT NULL,
+group_id int(10) unsigned DEFAULT '0' NOT NULL,
+hits int(10) unsigned DEFAULT '0' NOT NULL,
+sessions int(10) unsigned DEFAULT '0' NOT NULL,
+ts timestamp(14),
+PRIMARY KEY (visitor_id,group_id)
+)/*! type=MyISAM */;
+INSERT INTO t1 VALUES (465931136,7,2,2,20000318160952);
+INSERT INTO t1 VALUES (173865424,2,2,2,20000318233615);
+INSERT INTO t1 VALUES (173865424,8,2,2,20000318233615);
+INSERT INTO t1 VALUES (173865424,39,2,2,20000318233615);
+INSERT INTO t1 VALUES (173865424,7,2,2,20000318233615);
+INSERT INTO t1 VALUES (173865424,3,2,2,20000318233615);
+INSERT INTO t1 VALUES (173865424,6,2,2,20000318233615);
+INSERT INTO t1 VALUES (173865424,60,2,2,20000318233615);
+INSERT INTO t1 VALUES (173865424,1502,2,2,20000318233615);
+INSERT INTO t1 VALUES (48985536,2,2,2,20000319013932);
+INSERT INTO t1 VALUES (48985536,8,2,2,20000319013932);
+INSERT INTO t1 VALUES (48985536,39,2,2,20000319013932);
+INSERT INTO t1 VALUES (48985536,7,2,2,20000319013932);
+INSERT INTO t1 VALUES (465931136,3,2,2,20000318160951);
+INSERT INTO t1 VALUES (465931136,119,1,1,20000318160953);
+INSERT INTO t1 VALUES (465931136,2,1,1,20000318160950);
+INSERT INTO t1 VALUES (465931136,8,1,1,20000318160950);
+INSERT INTO t1 VALUES (465931136,39,1,1,20000318160950);
+INSERT INTO t1 VALUES (1092858576,14,1,1,20000319013445);
+INSERT INTO t1 VALUES (357917728,3,2,2,20000319145026);
+INSERT INTO t1 VALUES (357917728,7,2,2,20000319145027);
+select visitor_id,max(ts) as mts from t1 group by visitor_id
+having mts < DATE_SUB(NOW(),INTERVAL 3 MONTH);
visitor_id mts
48985536 20000319013932
173865424 20000318233615
357917728 20000319145027
465931136 20000318160953
1092858576 20000319013445
+select visitor_id,max(ts) as mts from t1 group by visitor_id
+having DATE_ADD(mts,INTERVAL 3 MONTH) < NOW();
visitor_id mts
48985536 20000319013932
173865424 20000318233615
357917728 20000319145027
465931136 20000318160953
1092858576 20000319013445
+drop table t1;
diff --git a/mysql-test/r/func_encrypt.result b/mysql-test/r/func_encrypt.result
new file mode 100644
index 00000000000..39c734999b2
--- /dev/null
+++ b/mysql-test/r/func_encrypt.result
@@ -0,0 +1,136 @@
+drop table if exists t1;
+create table t1 (x blob);
+insert into t1 values (des_encrypt('The quick red fox jumped over the lazy brown dog','The quick red fox jumped over the lazy brown dog'));
+insert into t1 values (des_encrypt('a','The quick red fox jumped over the lazy brown dog'));
+insert into t1 values (des_encrypt('The quick red fox jumped over the lazy brown dog','a'));
+insert into t1 values (des_encrypt('ab','The quick red fox jumped over the lazy brown dog'));
+insert into t1 values (des_encrypt('The quick red fox jumped over the lazy brown dog','ab'));
+insert into t1 values (des_encrypt('abc','The quick red fox jumped over the lazy brown dog'));
+insert into t1 values (des_encrypt('The quick red fox jumped over the lazy brown dog','abc'));
+insert into t1 values (des_encrypt('abcd','The quick red fox jumped over the lazy brown dog'));
+insert into t1 values (des_encrypt('The quick red fox jumped over the lazy brown dog','abcd'));
+insert into t1 values (des_encrypt('abcde','The quick red fox jumped over the lazy brown dog'));
+insert into t1 values (des_encrypt('The quick red fox jumped over the lazy brown dog','abcde'));
+insert into t1 values (des_encrypt('abcdef','The quick red fox jumped over the lazy brown dog'));
+insert into t1 values (des_encrypt('The quick red fox jumped over the lazy brown dog','abcdef'));
+insert into t1 values (des_encrypt('abcdefg','The quick red fox jumped over the lazy brown dog'));
+insert into t1 values (des_encrypt('The quick red fox jumped over the lazy brown dog','abcdefg'));
+insert into t1 values (des_encrypt('abcdefgh','The quick red fox jumped over the lazy brown dog'));
+insert into t1 values (des_encrypt('The quick red fox jumped over the lazy brown dog','abcdefgh'));
+insert into t1 values (des_encrypt('abcdefghi','The quick red fox jumped over the lazy brown dog'));
+insert into t1 values (des_encrypt('The quick red fox jumped over the lazy brown dog','abcdefghi'));
+insert into t1 values (des_encrypt('abcdefghij','The quick red fox jumped over the lazy brown dog'));
+insert into t1 values (des_encrypt('The quick red fox jumped over the lazy brown dog','abcdefghij'));
+insert into t1 values (des_encrypt('abcdefghijk','The quick red fox jumped over the lazy brown dog'));
+insert into t1 values (des_encrypt('The quick red fox jumped over the lazy brown dog','abcdefghijk'));
+insert into t1 values (des_encrypt('The quick red fox jumped over the lazy brown dog','sabakala'));
+insert into t1 values (des_encrypt('quick red fox jumped over the lazy brown dog','sabakala'));
+insert into t1 values (des_encrypt('red fox jumped over the lazy brown dog','sabakala'));
+insert into t1 values (des_encrypt('fox jumped over the lazy brown dog','sabakala'));
+insert into t1 values (des_encrypt('jumped over the lazy brown dog','sabakala'));
+insert into t1 values (des_encrypt('over the lazy brown dog','sabakala'));
+insert into t1 values (des_encrypt('the lazy brown dog','sabakala'));
+insert into t1 values (des_encrypt('lazy brown dog','sabakala'));
+insert into t1 values (des_encrypt('brown dog','sabakala'));
+insert into t1 values (des_encrypt('dog','sabakala'));
+insert into t1 values (des_encrypt('dog!','sabakala'));
+insert into t1 values (des_encrypt('dog!!','sabakala'));
+insert into t1 values (des_encrypt('dog!!!','sabakala'));
+insert into t1 values (des_encrypt('dog!!!!','sabakala'));
+insert into t1 values (des_encrypt('dog!!!!!','sabakala'));
+insert into t1 values (des_encrypt('jumped over the lazy brown dog','sabakala'));
+insert into t1 values (des_encrypt('jumped over the lazy brown dog','sabakala'));
+select hex(x), hex(des_decrypt(x,'sabakala')) from t1;
+hex(x) hex(des_decrypt(x,'sabakala'))
+FFA185A4656D113445E31D7A5B31BB57671A4CA9E21E63FE5D9C801E0CC7AA6190C13E269C2AE8D8060D3FB3FEA94FEC7FB006B9DCAC3E3E41 NULL
+FFC620C3B84E926A54 NULL
+FFA4F77D4220A16C980AF7CB576F8DC0A864F357825C16F329F24F66EBA775765B7C1538B90970740F853B556AEBD35AC31B962EA9B12B5AD4 NULL
+FFACFF5921BB876A90 NULL
+FFA6F18760E7CC5A4C325244B8486F692AAA11D229AF9ED4E4C9D56D7C0278C0DDA58F73E15E2B5F6C1DDD19B22B8071C454C930585449AAEB NULL
+FF3736DFEDC4B765F4 NULL
+FF598681EA5F03CD6D6AEA2B118DF4885DD78BECDFB012BBB05386E436DC403D3CB9DE3BE8D5D3BB7FD90A1F9F9A3E055BB3B4FD3F6A869473 NULL
+FF15B8B5952D630CAE NULL
+FF11EE3A400685226B76D5EC567681FA90247CE3C9DBE43341311C22F74562B1199957D80E300737791F6345BBC61AE03F28F52E5A6DCC78B2 NULL
+FF0A832AE10DC85483 NULL
+FF6F5C0BF4C5F899B4E7C091D9B1F1E92A7623B651B150CA3E7F420B4DD316D2C1BF76FCF9F9A046C000A9E21C106591E8C1930201B1750269 NULL
+FFA08D5FB849A9FC90 NULL
+FFF7331312FE153A39B1EC0D65BC1D3A0B6FCD49DA8C95D6161F53B11D297BAE142BCA6B9492DAE9A02AF455F16CA2C1CF4E1AD17297E947E2 NULL
+FFDEE60A938478E059 NULL
+FF95A729E73D5D87416A53055029E8CAA95B4F7B49F3D2D821A95D1FCE70F4B7A3226077176723F3DCC0A44D3B2EE9EFBC4D31AA87C948916C NULL
+FF1C78557F542A1FDC91943761B2EED14F NULL
+FF1E35B0775EEE512544A75BDAF58EA1655F5C899D3C5191A47263E2D11C3E688F662AB79F66D3B1DF9C75BD869EB8E04FDAE85719CB573A43 NULL
+FF1C78557F542A1FDCDC4182B5314185E5 NULL
+FF783123DCB36F98A51C39A560C92E129F1DDEEAB170825406A61260FBFBBFB0F2E48DB3282588A975C9C71E0EACA71A2B642A8C9C2E921A9F NULL
+FF1C78557F542A1FDCAC4B1B6B47206306 NULL
+FF6D9B450837017D06CA1F1C9A0E700D03DEF06A4F954527A961CA805F70320E9F3F0007636B80768A253A5F7ADABC18B78F1A2FA560CC0B21 NULL
+FF1C78557F542A1FDCE9038BD99DD43F2E NULL
+FF23FD03BA7548DD0957EBA7A8FBF7A18589762F3913E9A935BDA72F6F28202DC64572E0D633A54EA55BFD2C749E408C8632CCE36A7AE00619 NULL
+FFD8DD3C4ABCB02FCDFE1383ECC0F61E7D02CD3BA72BBAEA26384D14835796501B3DC9A2F7EC2FC1633BDA6D56464536FE12010049C53A1991 54686520717569636B2072656420666F78206A756D706564206F76657220746865206C617A792062726F776E20646F67
+FFACC5C5479575CBCA518B05778139B1BFC10F07299C98D04F580BC2F816828722D65A89C1831BD29DA626D319813BD374 717569636B2072656420666F78206A756D706564206F76657220746865206C617A792062726F776E20646F67
+FF128D5517241DEEC631ABD2A47FA66E57930001417F18204328B0B2CB13F7AD2F50B8336EFAE7DE21 72656420666F78206A756D706564206F76657220746865206C617A792062726F776E20646F67
+FF7CF971283B4DC2D050B3DB22684737B74B5B1CF12CF2FAC5A5995A298505F56D82BBFB9FC3E70059 666F78206A756D706564206F76657220746865206C617A792062726F776E20646F67
+FF8333F3DD21E4488F967E03DD12394813A49F72848BB49473D3CB1C8A1AACF220 6A756D706564206F76657220746865206C617A792062726F776E20646F67
+FFE8CB7FD80E6262C5FEB042A2DCC73B699CEEDCA6DC4458A0 6F76657220746865206C617A792062726F776E20646F67
+FFA29334D7CDB1B403DF3EB992067DD524C7D568E8D98EBFE5 746865206C617A792062726F776E20646F67
+FF4F0C5858FE2358D400E38831D5577C85 6C617A792062726F776E20646F67
+FFB370CD6BAFD1CB95974D21DCCA2DD9D7 62726F776E20646F67
+FF8F7777B28C7A459A 646F67
+FF75213A4D7D01D715 646F6721
+FF2DCAF574B173FB4D 646F672121
+FFFA775787BE776B15 646F67212121
+FF3FC2E42D7C840905 646F6721212121
+FF9723312D26D9E6DA01D01A784A64DB9D 646F672121212121
+FF8333F3DD21E4488F967E03DD12394813A49F72848BB49473D3CB1C8A1AACF220 6A756D706564206F76657220746865206C617A792062726F776E20646F67
+FF8333F3DD21E4488F967E03DD12394813A49F72848BB49473D3CB1C8A1AACF220 6A756D706564206F76657220746865206C617A792062726F776E20646F67
+select des_decrypt(x,'sabakala') as s from t1 having s like '%dog%';
+s
+The quick red fox jumped over the lazy brown dog
+quick red fox jumped over the lazy brown dog
+red fox jumped over the lazy brown dog
+fox jumped over the lazy brown dog
+jumped over the lazy brown dog
+over the lazy brown dog
+the lazy brown dog
+lazy brown dog
+brown dog
+dog
+dog!
+dog!!
+dog!!!
+dog!!!!
+dog!!!!!
+jumped over the lazy brown dog
+jumped over the lazy brown dog
+drop table t1;
+select hex(des_encrypt("hello")),des_decrypt(des_encrypt("hello"));
+hex(des_encrypt("hello")) des_decrypt(des_encrypt("hello"))
+85D6DC8859F9759BBB hello
+select des_decrypt(des_encrypt("hello",4));
+des_decrypt(des_encrypt("hello",4))
+hello
+select des_decrypt(des_encrypt("hello",'test'),'test');
+des_decrypt(des_encrypt("hello",'test'),'test')
+hello
+select hex(des_encrypt("hello")),hex(des_encrypt("hello",5)),hex(des_encrypt("hello",'default_password'));
+hex(des_encrypt("hello")) hex(des_encrypt("hello",5)) hex(des_encrypt("hello",'default_password'))
+85D6DC8859F9759BBB 85D6DC8859F9759BBB FFD6DC8859F9759BBB
+select des_decrypt(des_encrypt("hello"),'default_password');
+des_decrypt(des_encrypt("hello"),'default_password')
+hello
+select des_decrypt(des_encrypt("hello",4),'password4');
+des_decrypt(des_encrypt("hello",4),'password4')
+hello
+SET @a=des_decrypt(des_encrypt("hello"));
+flush des_key_file;
+select @a = des_decrypt(des_encrypt("hello"));
+@a = des_decrypt(des_encrypt("hello"))
+1
+select hex("hello");
+hex("hello")
+68656C6C6F
+select hex(des_decrypt(des_encrypt("hello",4),'password2'));
+hex(des_decrypt(des_encrypt("hello",4),'password2'))
+NULL
+select hex(des_decrypt(des_encrypt("hello","hidden")));
+hex(des_decrypt(des_encrypt("hello","hidden")))
+NULL
diff --git a/mysql-test/r/func_equal.result b/mysql-test/r/func_equal.result
index 6e2933641aa..32a911eedf8 100644
--- a/mysql-test/r/func_equal.result
+++ b/mysql-test/r/func_equal.result
@@ -1,15 +1,29 @@
+select 0<=>0,0.0<=>0.0,"A"<=>"A",NULL<=>NULL;
0<=>0 0.0<=>0.0 "A"<=>"A" NULL<=>NULL
1 1 1 1
+select 1<=>0,0<=>NULL,NULL<=>0;
1<=>0 0<=>NULL NULL<=>0
0 0 0
+select 1.0<=>0.0,0.0<=>NULL,NULL<=>0.0;
1.0<=>0.0 0.0<=>NULL NULL<=>0.0
0 0 0
+select "A"<=>"B","A"<=>NULL,NULL<=>"A";
"A"<=>"B" "A"<=>NULL NULL<=>"A"
0 0 0
+drop table if exists t1,t2;
+create table t1 (id int, value int);
+create table t2 (id int, value int);
+insert into t1 values (1,null);
+insert into t2 values (1,null);
+select t1.*, t2.*, t1.value<=>t2.value from t1, t2 where t1.id=t2.id and t1.id=1;
id value id value t1.value<=>t2.value
1 NULL 1 NULL 1
+select * from t1 where id <=>id;
id value
1 NULL
+select * from t1 where value <=> value;
id value
1 NULL
+select * from t1 where id <=> value or value<=>id;
id value
+drop table t1,t2;
diff --git a/mysql-test/r/func_group.result b/mysql-test/r/func_group.result
index ea9a06123ae..2d24b8ffd4e 100644
--- a/mysql-test/r/func_group.result
+++ b/mysql-test/r/func_group.result
@@ -1,3 +1,11 @@
+create table t1 (grp int, a bigint unsigned, c char(10) not null);
+insert into t1 values (1,1,"a");
+insert into t1 values (2,2,"b");
+insert into t1 values (2,3,"c");
+insert into t1 values (3,4,"E");
+insert into t1 values (3,5,"C");
+insert into t1 values (3,6,"D");
+select a,c,sum(a) from t1 group by a;
a c sum(a)
1 a 1
2 b 2
@@ -5,82 +13,140 @@ a c sum(a)
4 E 4
5 C 5
6 D 6
+select a,c,sum(a) from t1 where a > 10 group by a;
a c sum(a)
+select sum(a) from t1 where a > 10;
sum(a)
NULL
+select a from t1 order by rand(10);
a
+2
+6
1
3
-6
5
-2
4
+select distinct a from t1 order by rand(10);
a
+2
+6
1
3
-6
5
-2
4
+select count(distinct a),count(distinct grp) from t1;
count(distinct a) count(distinct grp)
6 3
+insert into t1 values (null,null,'');
+select count(distinct a),count(distinct grp) from t1;
count(distinct a) count(distinct grp)
6 3
+select sum(a),count(a),avg(a),std(a),bit_or(a),bit_and(a),min(a),max(a),min(c),max(c) from t1;
sum(a) count(a) avg(a) std(a) bit_or(a) bit_and(a) min(a) max(a) min(c) max(c)
21 6 3.5000 1.7078 7 0 1 6 E
+select grp, sum(a),count(a),avg(a),std(a),bit_or(a),bit_and(a),min(a),max(a),min(c),max(c) from t1 group by grp;
grp sum(a) count(a) avg(a) std(a) bit_or(a) bit_and(a) min(a) max(a) min(c) max(c)
NULL 0 0 NULL NULL 0 0 NULL NULL
1 1 1 1.0000 0.0000 1 1 1 1 a a
2 5 2 2.5000 0.5000 3 2 2 3 b c
3 15 3 5.0000 0.8165 7 4 4 6 C E
+select grp, sum(a)+count(a)+avg(a)+std(a)+bit_or(a)+bit_and(a)+min(a)+max(a)+min(c)+max(c) as sum from t1 group by grp;
grp sum
NULL NULL
1 7
2 20
3 44.816496580928
+create table t2 (grp int, a bigint unsigned, c char(10));
+insert into t2 select grp,max(a)+max(grp),max(c) from t1 group by grp;
+replace into t2 select grp, a, c from t1 limit 2,1;
+select * from t2;
grp a c
NULL NULL
1 2 a
2 5 c
3 9 E
2 3 c
+drop table t1,t2;
+CREATE TABLE t1 (id int(11),value1 float(10,2));
+INSERT INTO t1 VALUES (1,0.00),(1,1.00), (1,2.00), (2,10.00), (2,11.00), (2,12.00);
+CREATE TABLE t2 (id int(11),name char(20));
+INSERT INTO t2 VALUES (1,'Set One'),(2,'Set Two');
+select id, avg(value1), std(value1) from t1 group by id;
id avg(value1) std(value1)
1 1.000000 0.816497
2 11.000000 0.816497
+select name, avg(value1), std(value1) from t1, t2 where t1.id = t2.id group by t1.id;
name avg(value1) std(value1)
Set One 1.000000 0.816497
Set Two 11.000000 0.816497
+drop table t1,t2;
+create table t1 (id int not null);
+create table t2 (id int not null,rating int null);
+insert into t1 values(1),(2),(3);
+insert into t2 values(1, 3),(2, NULL),(2, NULL),(3, 2),(3, NULL);
+select t1.id, avg(rating) from t1 left join t2 on ( t1.id = t2.id ) group by t1.id;
id avg(rating)
1 3.0000
2 NULL
3 2.0000
+drop table t1,t2;
+create table t1 (a smallint(6) primary key, c char(10), b text);
+INSERT INTO t1 VALUES (1,'1','1');
+INSERT INTO t1 VALUES (2,'2','2');
+INSERT INTO t1 VALUES (4,'4','4');
+select count(*) from t1;
count(*)
3
+select count(*) from t1 where a = 1;
count(*)
1
+select count(*) from t1 where a = 100;
count(*)
0
+select count(*) from t1 where a >= 10;
count(*)
0
+select count(a) from t1 where a = 1;
count(a)
1
+select count(a) from t1 where a = 100;
count(a)
0
+select count(a) from t1 where a >= 10;
count(a)
0
+select count(b) from t1 where b >= 2;
count(b)
2
+select count(b) from t1 where b >= 10;
count(b)
0
+select count(c) from t1 where c = 10;
count(c)
0
+drop table t1;
+CREATE TABLE t1 (d DATETIME, i INT);
+INSERT INTO t1 VALUES (NOW(), 1);
+SELECT COUNT(i), i, COUNT(i)*i FROM t1 GROUP BY i;
COUNT(i) i COUNT(i)*i
1 1 1
+SELECT COUNT(i), (i+0), COUNT(i)*(i+0) FROM t1 GROUP BY i;
COUNT(i) (i+0) COUNT(i)*(i+0)
1 1 1
+DROP TABLE t1;
+create table t1 (
+num float(5,2),
+user char(20)
+);
+insert into t1 values (10.3,'nem'),(20.53,'monty'),(30.23,'sinisa');
+insert into t1 values (30.13,'nem'),(20.98,'monty'),(10.45,'sinisa');
+insert into t1 values (5.2,'nem'),(8.64,'monty'),(11.12,'sinisa');
+select sum(num) from t1;
sum(num)
147.58
+select sum(num) from t1 group by user;
sum(num)
50.15
45.63
51.80
+drop table t1;
diff --git a/mysql-test/r/func_in.result b/mysql-test/r/func_in.result
index f201d371876..8c991dee8d8 100644
--- a/mysql-test/r/func_in.result
+++ b/mysql-test/r/func_in.result
@@ -1,14 +1,27 @@
+CREATE TABLE t1 (field char(1));
+INSERT INTO t1 VALUES ('A'),(NULL);
+SELECT * from t1 WHERE field IN (NULL);
field
+SELECT * from t1 WHERE field NOT IN (NULL);
field
A
+SELECT * from t1 where field = field;
field
A
+SELECT * from t1 where field <=> field;
field
A
NULL
+DELETE FROM t1 WHERE field NOT IN (NULL);
+SELECT * FROM t1;
field
NULL
+drop table t1;
+create table t1 (id int(10) primary key);
+insert into t1 values (1),(2),(3),(4),(5),(6),(7),(8),(9);
+select * from t1 where id in (2,5,9);
id
2
5
9
+drop table t1;
diff --git a/mysql-test/r/func_like.result b/mysql-test/r/func_like.result
index 78bede19762..796674b5fa4 100644
--- a/mysql-test/r/func_like.result
+++ b/mysql-test/r/func_like.result
@@ -1,7 +1,18 @@
+drop table if exists t1;
+create table t1 (a varchar(10), key(a));
+insert into t1 values ("a"),("abc"),("abcd"),("hello"),("test");
+select * from t1 where a like "abc%";
a
abc
abcd
+select * from t1 where a like "ABC%";
+a
+abc
+abcd
+select * from t1 where a like "test%";
a
test
+select * from t1 where a like "te_t";
a
test
+drop table t1;
diff --git a/mysql-test/r/func_math.result b/mysql-test/r/func_math.result
index cee67a3e25c..fce98a58682 100644
--- a/mysql-test/r/func_math.result
+++ b/mysql-test/r/func_math.result
@@ -1,22 +1,33 @@
+select floor(5.5),floor(-5.5);
floor(5.5) floor(-5.5)
5 -6
+select ceiling(5.5),ceiling(-5.5);
ceiling(5.5) ceiling(-5.5)
6 -5
+select truncate(52.64,1),truncate(52.64,2),truncate(52.64,-1),truncate(52.64,-2);
truncate(52.64,1) truncate(52.64,2) truncate(52.64,-1) truncate(52.64,-2)
52.6 52.64 50 0
+select round(5.5),round(-5.5);
round(5.5) round(-5.5)
6 -6
+select round(5.64,1),round(5.64,2),round(5.64,-1),round(5.64,-2);
round(5.64,1) round(5.64,2) round(5.64,-1) round(5.64,-2)
5.6 5.64 10 0
+select abs(-10), sign(-5), sign(5), sign(0);
abs(-10) sign(-5) sign(5) sign(0)
10 -1 1 0
+select log(exp(10)),exp(log(sqrt(10))*2);
log(exp(10)) exp(log(sqrt(10))*2)
10.000000 10.000000
+select pow(10,log10(10)),power(2,4);
pow(10,log10(10)) power(2,4)
10.000000 16.000000
+select rand(999999),rand();
rand(999999) rand()
-0.18435012473199 0.76373626176616
+0.014231365187309 0.8078568166195
+select pi(),sin(pi()/2),cos(pi()/2),abs(tan(pi())),cot(1),asin(1),acos(0),atan(1);
PI() sin(pi()/2) cos(pi()/2) abs(tan(pi())) cot(1) asin(1) acos(0) atan(1)
3.141593 1.000000 0.000000 0.000000 0.64209262 1.570796 1.570796 0.785398
+select degrees(pi()),radians(360);
degrees(pi()) radians(360)
180 6.2831853071796
diff --git a/mysql-test/r/func_misc.result b/mysql-test/r/func_misc.result
index 5448127548b..575f5e5429a 100644
--- a/mysql-test/r/func_misc.result
+++ b/mysql-test/r/func_misc.result
@@ -1,8 +1,12 @@
+select format(1.5555,0),format(123.5555,1),format(1234.5555,2),format(12345.5555,3),format(123456.5555,4),format(1234567.5555,5),format("12345.2399",2);
format(1.5555,0) format(123.5555,1) format(1234.5555,2) format(12345.5555,3) format(123456.5555,4) format(1234567.5555,5) format("12345.2399",2)
2 123.6 1,234.56 12,345.556 123,456.5555 1,234,567.55550 12,345.24
+select inet_ntoa(inet_aton("255.255.255.255.255.255.255.255"));
inet_ntoa(inet_aton("255.255.255.255.255.255.255.255"))
255.255.255.255.255.255.255.255
+select inet_aton("255.255.255.255.255"),inet_aton("255.255.1.255"),inet_aton("0.1.255");
inet_aton("255.255.255.255.255") inet_aton("255.255.1.255") inet_aton("0.1.255")
1099511627775 4294902271 511
+select inet_ntoa(1099511627775),inet_ntoa(4294902271),inet_ntoa(511);
inet_ntoa(1099511627775) inet_ntoa(4294902271) inet_ntoa(511)
255.255.255.255.255 255.255.1.255 0.0.1.255
diff --git a/mysql-test/r/func_op.result b/mysql-test/r/func_op.result
index b14f575c998..9f49b5809df 100644
--- a/mysql-test/r/func_op.result
+++ b/mysql-test/r/func_op.result
@@ -1,6 +1,9 @@
+select 1+1,1-1,1+1*2,8/5,8%5,mod(8,5),mod(8,5)|0,-(1+1)*-2;
1+1 1-1 1+1*2 8/5 8%5 mod(8,5) mod(8,5)|0 -(1+1)*-2
2 0 3 1.60 3 3 3 4
+select 1 | (1+1),5 & 3,bit_count(7) ;
1 | (1+1) 5 & 3 bit_count(7)
3 1 3
+select 1 << 32,1 << 63, 1 << 64, 4 >> 2, 4 >> 63, 1<< 63 >> 60;
1 << 32 1 << 63 1 << 64 4 >> 2 4 >> 63 1<< 63 >> 60
-4294967296 -9223372036854775808 0 1 0 8
+4294967296 9223372036854775808 0 1 0 8
diff --git a/mysql-test/r/func_regexp.result b/mysql-test/r/func_regexp.result
index 5927dba0974..8d22994ef2b 100644
--- a/mysql-test/r/func_regexp.result
+++ b/mysql-test/r/func_regexp.result
@@ -1,3 +1,20 @@
+drop table if exists t1;
+create table t1 (s1 char(64),s2 char(64));
+insert into t1 values('aaa','aaa');
+insert into t1 values('aaa|qqq','qqq');
+insert into t1 values('gheis','^[^a-dXYZ]+$');
+insert into t1 values('aab','^aa?b');
+insert into t1 values('Baaan','^Ba*n');
+insert into t1 values('aaa','qqq|aaa');
+insert into t1 values('qqq','qqq|aaa');
+insert into t1 values('bbb','qqq|aaa');
+insert into t1 values('bbb','qqq');
+insert into t1 values('aaa','aba');
+insert into t1 values(null,'abc');
+insert into t1 values('def',null);
+insert into t1 values(null,null);
+insert into t1 values('ghi','ghi[');
+select HIGH_PRIORITY s1 regexp s2 from t1;
s1 regexp s2
1
1
@@ -13,13 +30,25 @@ NULL
NULL
NULL
NULL
+drop table t1;
+create table t1 (xxx char(128));
+insert into t1 (xxx) values('this is a test of some long text to see what happens');
+select * from t1 where xxx regexp('is a test of some long text to');
xxx
this is a test of some long text to see what happens
+select * from t1 where xxx regexp('is a test of some long text to ');
xxx
this is a test of some long text to see what happens
+select * from t1 where xxx regexp('is a test of some long text to s');
xxx
this is a test of some long text to see what happens
+select * from t1 where xxx regexp('is a test of some long text to se');
xxx
this is a test of some long text to see what happens
+drop table t1;
+create table t1 (xxx char(128));
+insert into t1 (xxx) values('this is some text: to test - out.reg exp (22/45)');
+select * from t1 where xxx REGEXP '^this is some text: to test - out\\.reg exp [[(][0-9]+[/\\][0-9]+[])][ ]*$';
xxx
this is some text: to test - out.reg exp (22/45)
+drop table t1;
diff --git a/mysql-test/r/func_set.result b/mysql-test/r/func_set.result
index b82fffc3dbd..5305c16c5d9 100644
--- a/mysql-test/r/func_set.result
+++ b/mysql-test/r/func_set.result
@@ -1,18 +1,27 @@
+select interval(55,10,20,30,40,50,60,70,80,90,100),interval(3,1,1+1,1+1+1+1),field("IBM","NCA","ICL","SUN","IBM","DIGITAL"),field("A","B","C"),elt(2,"ONE","TWO","THREE"),interval(0,1,2,3,4),elt(1,1,2,3)|0,elt(1,1.1,1.2,1.3)+0;
interval(55,10,20,30,40,50,60,70,80,90,100) interval(3,1,1+1,1+1+1+1) field("IBM","NCA","ICL","SUN","IBM","DIGITAL") field("A","B","C") elt(2,"ONE","TWO","THREE") interval(0,1,2,3,4) elt(1,1,2,3)|0 elt(1,1.1,1.2,1.3)+0
5 2 4 0 TWO 0 1 1.1
+select find_in_set("b","a,b,c"),find_in_set("c","a,b,c"),find_in_set("dd","a,bbb,dd"),find_in_set("bbb","a,bbb,dd");
find_in_set("b","a,b,c") find_in_set("c","a,b,c") find_in_set("dd","a,bbb,dd") find_in_set("bbb","a,bbb,dd")
2 3 3 2
+select find_in_set("d","a,b,c"),find_in_set("dd","a,bbb,d"),find_in_set("bb","a,bbb,dd");
find_in_set("d","a,b,c") find_in_set("dd","a,bbb,d") find_in_set("bb","a,bbb,dd")
0 0 0
+select make_set(0,'a','b','c'),make_set(-1,'a','b','c'),make_set(1,'a','b','c'),make_set(2,'a','b','c'),make_set(1+2,concat('a','b'),'c');
make_set(0,'a','b','c') make_set(-1,'a','b','c') make_set(1,'a','b','c') make_set(2,'a','b','c') make_set(1+2,concat('a','b'),'c')
a,b,c a b ab,c
+select make_set(NULL,'a','b','c'),make_set(1|4,'a',NULL,'c'),make_set(1+2,'a',NULL,'c');
make_set(NULL,'a','b','c') make_set(1|4,'a',NULL,'c') make_set(1+2,'a',NULL,'c')
NULL a,c a
+select export_set(9,"Y","N","-",5),export_set(9,"Y","N"),export_set(9,"Y","N","");
export_set(9,"Y","N","-",5) export_set(9,"Y","N") export_set(9,"Y","N","")
Y-N-N-Y-N Y,N,N,Y,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N YNNYNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN
+select elt(2,1),field(NULL,"a","b","c");
elt(2,1) field(NULL,"a","b","c")
NULL 0
+select find_in_set("","a,b,c"),find_in_set("","a,b,c,"),find_in_set("",",a,b,c");
find_in_set("","a,b,c") find_in_set("","a,b,c,") find_in_set("",",a,b,c")
0 4 1
+select find_in_set("abc","abc"),find_in_set("ab","abc"),find_in_set("abcd","abc");
find_in_set("abc","abc") find_in_set("ab","abc") find_in_set("abcd","abc")
1 0 0
diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result
index ec421e9f31b..a58f3c57169 100644
--- a/mysql-test/r/func_str.result
+++ b/mysql-test/r/func_str.result
@@ -1,112 +1,186 @@
+drop table if exists t1;
+select 'hello',"'hello'",'""hello""','''h''e''l''l''o''',"hel""lo",'hel\'lo';
hello 'hello' ""hello"" 'h'e'l'l'o' hel"lo hel'lo
hello 'hello' ""hello"" 'h'e'l'l'o' hel"lo hel'lo
+select 'hello' 'monty';
hello
hellomonty
+select length('\n\t\r\b\0\_\%\\');
length('\n\t\r\b\0\_\%\\')
10
+select bit_length('\n\t\r\b\0\_\%\\');
+bit_length('\n\t\r\b\0\_\%\\')
+80
+select concat('monty',' was here ','again'),length('hello'),char(ascii('h'));
concat('monty',' was here ','again') length('hello') char(ascii('h'))
monty was here again 5 h
+select locate('he','hello'),locate('he','hello',2),locate('lo','hello',2) ;
locate('he','hello') locate('he','hello',2) locate('lo','hello',2)
1 0 4
-instr('hello','he')
-1
-position('ll' in 'hello') position('a' in 'hello')
+select instr('hello','HE'), instr('hello',binary 'HE'), instr(binary 'hello','HE');
+instr('hello','HE') instr('hello',binary 'HE') instr(binary 'hello','HE')
+1 0 0
+select position(binary 'll' in 'hello'),position('a' in binary 'hello');
+position(binary 'll' in 'hello') position('a' in binary 'hello')
3 0
+select left('hello',2),right('hello',2),substring('hello',2,2),mid('hello',1,5) ;
left('hello',2) right('hello',2) substring('hello',2,2) mid('hello',1,5)
he lo el hello
+select concat('',left(right(concat('what ',concat('is ','happening')),9),4),'',substring('monty',5,1)) ;
concat('',left(right(concat('what ',concat('is ','happening')),9),4),'',substring('monty',5,1))
happy
+select substring_index('www.tcx.se','.',-2),substring_index('www.tcx.se','.',1);
substring_index('www.tcx.se','.',-2) substring_index('www.tcx.se','.',1)
tcx.se www
+select substring_index('www.tcx.se','tcx',1),substring_index('www.tcx.se','tcx',-1);
substring_index('www.tcx.se','tcx',1) substring_index('www.tcx.se','tcx',-1)
www. .se
+select substring_index('.tcx.se','.',-2),substring_index('.tcx.se','.tcx',-1);
substring_index('.tcx.se','.',-2) substring_index('.tcx.se','.tcx',-1)
tcx.se .se
+select concat(':',ltrim(' left '),':',rtrim(' right '),':');
concat(':',ltrim(' left '),':',rtrim(' right '),':')
:left : right:
+select concat(':',trim(LEADING FROM ' left'),':',trim(TRAILING FROM ' right '),':');
concat(':',trim(LEADING FROM ' left'),':',trim(TRAILING FROM ' right '),':')
:left: right:
+select concat(':',trim(' m '),':',trim(BOTH FROM ' y '),':',trim('*' FROM '*s*'),':');
concat(':',trim(' m '),':',trim(BOTH FROM ' y '),':',trim('*' FROM '*s*'),':')
:m:y:s:
+select concat(':',trim(BOTH 'ab' FROM 'ababmyabab'),':',trim(BOTH '*' FROM '***sql'),':');
concat(':',trim(BOTH 'ab' FROM 'ababmyabab'),':',trim(BOTH '*' FROM '***sql'),':')
:my:sql:
+select concat(':',trim(LEADING '.*' FROM '.*my'),':',trim(TRAILING '.*' FROM 'sql.*.*'),':');
concat(':',trim(LEADING '.*' FROM '.*my'),':',trim(TRAILING '.*' FROM 'sql.*.*'),':')
:my:sql:
+select TRIM("foo" FROM "foo"), TRIM("foo" FROM "foook"), TRIM("foo" FROM "okfoo");
TRIM("foo" FROM "foo") TRIM("foo" FROM "foook") TRIM("foo" FROM "okfoo")
ok ok
+select concat_ws(', ','monty','was here','again');
concat_ws(', ','monty','was here','again')
monty, was here, again
+select concat_ws(NULL,'a'),concat_ws(',',NULL,'');
concat_ws(NULL,'a') concat_ws(',',NULL,'')
NULL
+select concat_ws(',','',NULL,'a');
concat_ws(',','',NULL,'a')
a
+SELECT CONCAT('"',CONCAT_WS('";"',repeat('a',60),repeat('b',60),repeat('c',60),repeat('d',100)), '"');
CONCAT('"',CONCAT_WS('";"',repeat('a',60),repeat('b',60),repeat('c',60),repeat('d',100)), '"')
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb";"cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc";"dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd"
+select insert('txs',2,1,'hi'),insert('is ',4,0,'a'),insert('txxxxt',2,4,'es');
insert('txs',2,1,'hi') insert('is ',4,0,'a') insert('txxxxt',2,4,'es')
this is a test
+select replace('aaaa','a','b'),replace('aaaa','aa','b'),replace('aaaa','a','bb'),replace('aaaa','','b'),replace('bbbb','a','c');
replace('aaaa','a','b') replace('aaaa','aa','b') replace('aaaa','a','bb') replace('aaaa','','b') replace('bbbb','a','c')
bbbb bb bbbbbbbb aaaa bbbb
+select replace(concat(lcase(concat('THIS',' ','IS',' ','A',' ')),ucase('false'),' ','test'),'FALSE','REAL') ;
replace(concat(lcase(concat('THIS',' ','IS',' ','A',' ')),ucase('false'),' ','test'),'FALSE','REAL')
this is a REAL test
+select soundex(''),soundex('he'),soundex('hello all folks');
soundex('') soundex('he') soundex('hello all folks')
H000 H4142
-password('test') length(encrypt('test')) encrypt('test','aa')
-378b243e220ca493 13 aaqPiZY5xR5l.
+select md5('hello');
md5('hello')
5d41402abc4b2a76b9719d911017c592
+select repeat('monty',5),concat('*',space(5),'*');
repeat('monty',5) concat('*',space(5),'*')
montymontymontymontymonty * *
+select reverse('abc'),reverse('abcd');
reverse('abc') reverse('abcd')
cba dcba
+select rpad('a',4,'1'),rpad('a',4,'12'),rpad('abcd',3,'12');
rpad('a',4,'1') rpad('a',4,'12') rpad('abcd',3,'12')
a111 a121 abc
+select lpad('a',4,'1'),lpad('a',4,'12'),lpad('abcd',3,'12');
lpad('a',4,'1') lpad('a',4,'12') lpad('abcd',3,'12')
111a 121a abc
+select rpad(741653838,17,'0'),lpad(741653838,17,'0');
rpad(741653838,17,'0') lpad(741653838,17,'0')
74165383800000000 00000000741653838
+select rpad('abcd',7,'ab'),lpad('abcd',7,'ab');
rpad('abcd',7,'ab') lpad('abcd',7,'ab')
abcdaba abaabcd
+select rpad('abcd',1,'ab'),lpad('abcd',1,'ab');
rpad('abcd',1,'ab') lpad('abcd',1,'ab')
a a
+select LEAST(NULL,'HARRY','HARRIOT',NULL,'HAROLD'),GREATEST(NULL,'HARRY','HARRIOT',NULL,'HAROLD');
LEAST(NULL,'HARRY','HARRIOT',NULL,'HAROLD') GREATEST(NULL,'HARRY','HARRIOT',NULL,'HAROLD')
HAROLD HARRY
+select least(1,2,3) | greatest(16,32,8), least(5,4)*1,greatest(-1.0,1.0)*1,least(3,2,1)*1.0,greatest(1,1.1,1.0),least("10",9),greatest("A","B","0");
least(1,2,3) | greatest(16,32,8) least(5,4)*1 greatest(-1.0,1.0)*1 least(3,2,1)*1.0 greatest(1,1.1,1.0) least("10",9) greatest("A","B","0")
33 4 1.0 1.0 1.1 9 B
+select decode(encode(repeat("a",100000),"monty"),"monty")=repeat("a",100000);
decode(encode(repeat("a",100000),"monty"),"monty")=repeat("a",100000)
1
+select decode(encode("abcdef","monty"),"monty")="abcdef";
decode(encode("abcdef","monty"),"monty")="abcdef"
1
+select reverse("");
reverse("")
+select insert("aa",100,1,"b"),insert("aa",1,3,"b"),left("aa",-1),substring("a",1,2);
insert("aa",100,1,"b") insert("aa",1,3,"b") left("aa",-1) substring("a",1,2)
aa b a
+select elt(2,1),field(NULL,"a","b","c"),reverse("");
elt(2,1) field(NULL,"a","b","c") reverse("")
NULL 0
+select locate("a","b",2),locate("","a",1);
locate("a","b",2) locate("","a",1)
0 1
+select ltrim("a"),rtrim("a"),trim(BOTH "" from "a"),trim(BOTH " " from "a");
ltrim("a") rtrim("a") trim(BOTH "" from "a") trim(BOTH " " from "a")
a a a a
+select concat("1","2")|0,concat("1",".5")+0.0;
concat("1","2")|0 concat("1",".5")+0.0
12 1.5
+select substring_index("www.tcx.se","",3);
substring_index("www.tcx.se","",3)
+select length(repeat("a",100000000)),length(repeat("a",1000*64));
length(repeat("a",100000000)) length(repeat("a",1000*64))
NULL 64000
+select position("0" in "baaa" in (1)),position("0" in "1" in (1,2,3)),position("sql" in ("mysql"));
position("0" in "baaa" in (1)) position("0" in "1" in (1,2,3)) position("sql" in ("mysql"))
1 0 3
+select position(("1" in (1,2,3)) in "01");
position(("1" in (1,2,3)) in "01")
2
+select length(repeat("a",65500)),length(concat(repeat("a",32000),repeat("a",32000))),length(replace("aaaaa","a",concat(repeat("a",10000)))),length(insert(repeat("a",40000),1,30000,repeat("b",50000)));
length(repeat("a",65500)) length(concat(repeat("a",32000),repeat("a",32000))) length(replace("aaaaa","a",concat(repeat("a",10000)))) length(insert(repeat("a",40000),1,30000,repeat("b",50000)))
65500 64000 50000 60000
+select length(repeat("a",1000000)),length(concat(repeat("a",32000),repeat("a",32000),repeat("a",32000))),length(replace("aaaaa","a",concat(repeat("a",32000)))),length(insert(repeat("a",48000),1,1000,repeat("a",48000)));
length(repeat("a",1000000)) length(concat(repeat("a",32000),repeat("a",32000),repeat("a",32000))) length(replace("aaaaa","a",concat(repeat("a",32000)))) length(insert(repeat("a",48000),1,1000,repeat("a",48000)))
1000000 96000 160000 95000
+create table t1 ( domain char(50) );
+insert into t1 VALUES ("hello.de" ), ("test.de" );
+select domain from t1 where concat('@', trim(leading '.' from concat('.', domain))) = '@hello.de';
domain
hello.de
+select domain from t1 where concat('@', trim(leading '.' from concat('.', domain))) = '@test.de';
domain
test.de
+drop table t1;
+CREATE TABLE t1 (
+id int(10) unsigned NOT NULL,
+title varchar(255) default NULL,
+prio int(10) unsigned default NULL,
+category int(10) unsigned default NULL,
+program int(10) unsigned default NULL,
+bugdesc text,
+created datetime default NULL,
+modified timestamp(14) NOT NULL,
+bugstatus int(10) unsigned default NULL,
+submitter int(10) unsigned default NULL
+) TYPE=MyISAM;
+INSERT INTO t1 VALUES (1,'Link',1,1,1,'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa','2001-02-28 08:40:16',20010228084016,0,4);
+SELECT CONCAT('"',CONCAT_WS('";"',title,prio,category,program,bugdesc,created,modified,bugstatus,submitter), '"') FROM t1;
CONCAT('"',CONCAT_WS('";"',title,prio,category,program,bugdesc,created,modified,bugstatus,submitter), '"')
"Link";"1";"1";"1";"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";"2001-02-28 08:40:16";"20010228084016";"0";"4"
+SELECT CONCAT('"',CONCAT_WS('";"',title,prio,category,program,bugstatus,submitter), '"') FROM t1;
CONCAT('"',CONCAT_WS('";"',title,prio,category,program,bugstatus,submitter), '"')
"Link";"1";"1";"1";"0";"4"
+SELECT CONCAT_WS('";"',title,prio,category,program,bugdesc,created,modified,bugstatus,submitter) FROM t1;
CONCAT_WS('";"',title,prio,category,program,bugdesc,created,modified,bugstatus,submitter)
Link";"1";"1";"1";"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";"2001-02-28 08:40:16";"20010228084016";"0";"4
+drop table t1;
diff --git a/mysql-test/r/func_system.result b/mysql-test/r/func_system.result
index c6ec28bfd34..5ea4ed5e4e0 100644
--- a/mysql-test/r/func_system.result
+++ b/mysql-test/r/func_system.result
@@ -1,4 +1,6 @@
-database() user()
-test root@localhost
+select database(),user() like "%@%";
+database() user() like "%@%"
+test 1
+select version()>="3.23.29";
version()>="3.23.29"
1
diff --git a/mysql-test/r/func_test.result b/mysql-test/r/func_test.result
index 5d2211baf50..0a45f9e8b5c 100644
--- a/mysql-test/r/func_test.result
+++ b/mysql-test/r/func_test.result
@@ -1,38 +1,61 @@
+select 0=0,1>0,1>=1,1<0,1<=0,1!=0,strcmp("abc","abcd"),strcmp("b","a"),strcmp("a","a") ;
0=0 1>0 1>=1 1<0 1<=0 1!=0 strcmp("abc","abcd") strcmp("b","a") strcmp("a","a")
1 1 1 0 0 1 -1 1 0
+select "a"<"b","a"<="b","b">="a","b">"a","a"="A","a"<>"b";
"a"<"b" "a"<="b" "b">="a" "b">"a" "a"="A" "a"<>"b"
1 1 1 1 1 1
+select "a "="A", "A "="a", "a " <= "A b";
"a "="A" "A "="a" "a " <= "A b"
1 1 1
+select "abc" like "a%", "abc" not like "%d%", "a%" like "a\%","abc%" like "a%\%","abcd" like "a%b_%d", "a" like "%%a","abcde" like "a%_e","abc" like "abc%";
"abc" like "a%" "abc" not like "%d%" "a%" like "a\%" "abc%" like "a%\%" "abcd" like "a%b_%d" "a" like "%%a" "abcde" like "a%_e" "abc" like "abc%"
1 1 1 1 1 1 1 1
+select "a" like "%%b","a" like "%%ab","ab" like "a\%", "ab" like "_", "ab" like "ab_", "abc" like "%_d", "abc" like "abc%d";
"a" like "%%b" "a" like "%%ab" "ab" like "a\%" "ab" like "_" "ab" like "ab_" "abc" like "%_d" "abc" like "abc%d"
0 0 0 0 0 0 0
+select '?' like '|%', '?' like '|%' ESCAPE '|', '%' like '|%', '%' like '|%' ESCAPE '|', '%' like '%';
'?' like '|%' '?' like '|%' ESCAPE '|' '%' like '|%' '%' like '|%' ESCAPE '|' '%' like '%'
0 0 0 1 1
+select 'abc' like '%c','abcabc' like '%c', "ab" like "", "ab" like "a", "ab" like "ab";
'abc' like '%c' 'abcabc' like '%c' "ab" like "" "ab" like "a" "ab" like "ab"
1 1 0 0 1
+select "Det här är svenska" regexp "h[[:alpha:]]+r", "aba" regexp "^(a|b)*$";
"Det här är svenska" regexp "h[[:alpha:]]+r" "aba" regexp "^(a|b)*$"
1 1
+select "aba" regexp concat("^","a");
"aba" regexp concat("^","a")
1
+select !0,NOT 0=1,!(0=0),1 AND 1,1 && 0,0 OR 1,1 || NULL, 1=1 or 1=1 and 1=0;
!0 NOT 0=1 !(0=0) 1 AND 1 1 && 0 0 OR 1 1 || NULL 1=1 or 1=1 and 1=0
1 1 0 1 0 1 1 1
+select IF(0,"ERROR","this"),IF(1,"is","ERROR"),IF(NULL,"ERROR","a"),IF(1,2,3)|0,IF(1,2.0,3.0)+0 ;
IF(0,"ERROR","this") IF(1,"is","ERROR") IF(NULL,"ERROR","a") IF(1,2,3)|0 IF(1,2.0,3.0)+0
this is a 2 2.0
+select 2 between 1 and 3, "monty" between "max" and "my",2=2 and "monty" between "max" and "my" and 3=3;
2 between 1 and 3 "monty" between "max" and "my" 2=2 and "monty" between "max" and "my" and 3=3
1 1 1
+select 'b' between 'a' and 'c', 'B' between 'a' and 'c';
'b' between 'a' and 'c' 'B' between 'a' and 'c'
1 1
+select 2 in (3,2,5,9,5,1),"monty" in ("david","monty","allan"), 1.2 in (1.4,1.2,1.0);
2 in (3,2,5,9,5,1) "monty" in ("david","monty","allan") 1.2 in (1.4,1.2,1.0)
1 1 1
+select -1.49 or -1.49,0.6 or 0.6;
-1.49 or -1.49 0.6 or 0.6
1 1
+select 5 between 0 and 10 between 0 and 1,(5 between 0 and 10) between 0 and 1;
5 between 0 and 10 between 0 and 1 (5 between 0 and 10) between 0 and 1
0 1
+select 1 and 2 between 2 and 10, 2 between 2 and 10 and 1;
1 and 2 between 2 and 10 2 between 2 and 10 and 1
1 1
+select 1 and 0 or 2, 2 or 1 and 0;
1 and 0 or 2 2 or 1 and 0
1 1
+drop table if exists t1;
+create table t1 (num double(12,2));
+insert into t1 values (144.54);
+select sum(if(num is null,0.00,num)) from t1;
sum(if(num is null,0.00,num))
144.54
+drop table t1;
diff --git a/mysql-test/r/func_time.result b/mysql-test/r/func_time.result
index 71fc7e4b90b..5433194c719 100644
--- a/mysql-test/r/func_time.result
+++ b/mysql-test/r/func_time.result
@@ -1,222 +1,374 @@
+drop table if exists t1,t2;
+select from_days(to_days("960101")),to_days(960201)-to_days("19960101"),to_days(date_add(curdate(), interval 1 day))-to_days(curdate()),weekday("1997-11-29");
from_days(to_days("960101")) to_days(960201)-to_days("19960101") to_days(date_add(curdate(), interval 1 day))-to_days(curdate()) weekday("1997-11-29")
1996-01-01 31 1 5
+select period_add("9602",-12),period_diff(199505,"9404") ;
period_add("9602",-12) period_diff(199505,"9404")
199502 13
+select now()-now(),weekday(curdate())-weekday(now()),unix_timestamp()-unix_timestamp(now());
now()-now() weekday(curdate())-weekday(now()) unix_timestamp()-unix_timestamp(now())
0 0 0
+select from_unixtime(unix_timestamp("1994-03-02 10:11:12")),from_unixtime(unix_timestamp("1994-03-02 10:11:12"),"%Y-%m-%d %h:%i:%s"),from_unixtime(unix_timestamp("1994-03-02 10:11:12"))+0;
from_unixtime(unix_timestamp("1994-03-02 10:11:12")) from_unixtime(unix_timestamp("1994-03-02 10:11:12"),"%Y-%m-%d %h:%i:%s") from_unixtime(unix_timestamp("1994-03-02 10:11:12"))+0
1994-03-02 10:11:12 1994-03-02 10:11:12 19940302101112
+select sec_to_time(9001),sec_to_time(9001)+0,time_to_sec("15:12:22"),
+sec_to_time(time_to_sec("0:30:47")/6.21);
sec_to_time(9001) sec_to_time(9001)+0 time_to_sec("15:12:22") sec_to_time(time_to_sec("0:30:47")/6.21)
02:30:01 23001 54742 00:04:57
+select sec_to_time(time_to_sec('-838:59:59'));
sec_to_time(time_to_sec('-838:59:59'))
-838:59:59
+select now()-curdate()*1000000-curtime();
now()-curdate()*1000000-curtime()
0
+select strcmp(current_timestamp(),concat(current_date()," ",current_time()));
strcmp(current_timestamp(),concat(current_date()," ",current_time()))
0
+select date_format("1997-01-02 03:04:05", "%M %W %D %Y %y %m %d %h %i %s %w");
date_format("1997-01-02 03:04:05", "%M %W %D %Y %y %m %d %h %i %s %w")
January Thursday 2nd 1997 97 01 02 03 04 05 4
+select date_format("1997-01-02", concat("%M %W %D ","%Y %y %m %d %h %i %s %w"));
date_format("1997-01-02", concat("%M %W %D ","%Y %y %m %d %h %i %s %w"))
January Thursday 2nd 1997 97 01 02 12 00 00 4
+select dayofmonth("1997-01-02"),dayofmonth(19970323);
dayofmonth("1997-01-02") dayofmonth(19970323)
2 23
+select month("1997-01-02"),year("98-02-03"),dayofyear("1997-12-31");
month("1997-01-02") year("98-02-03") dayofyear("1997-12-31")
1 1998 365
+select month("2001-02-00"),year("2001-00-00");
month("2001-02-00") year("2001-00-00")
2 2001
+select DAYOFYEAR("1997-03-03"), WEEK("1998-03-03"), QUARTER(980303);
DAYOFYEAR("1997-03-03") WEEK("1998-03-03") QUARTER(980303)
62 9 1
+select HOUR("1997-03-03 23:03:22"), MINUTE("23:03:22"), SECOND(230322);
HOUR("1997-03-03 23:03:22") MINUTE("23:03:22") SECOND(230322)
23 3 22
+select week(19980101),week(19970101),week(19980101,1),week(19970101,1);
week(19980101) week(19970101) week(19980101,1) week(19970101,1)
-0 1 1 1
+0 0 1 1
+select week(19981231),week(19971231),week(19981231,1),week(19971231,1);
week(19981231) week(19971231) week(19981231,1) week(19971231,1)
-52 53 53 53
+52 52 53 53
+select week(19950101),week(19950101,1);
week(19950101) week(19950101,1)
1 0
+select yearweek('1981-12-31',1),yearweek('1982-01-01',1),yearweek('1982-12-31',1),yearweek('1983-01-01',1);
yearweek('1981-12-31',1) yearweek('1982-01-01',1) yearweek('1982-12-31',1) yearweek('1983-01-01',1)
198153 198153 198252 198252
+select yearweek('1987-01-01',1),yearweek('1987-01-01');
+yearweek('1987-01-01',1) yearweek('1987-01-01')
+198701 198652
+select week("2000-01-01",0) as '2000', week("2001-01-01",0) as '2001', week("2002-01-01",0) as '2002',week("2003-01-01",0) as '2003', week("2004-01-01",0) as '2004', week("2005-01-01",0) as '2005', week("2006-01-01",0) as '2006';
+2000 2001 2002 2003 2004 2005 2006
+0 0 0 0 0 0 1
+select week("2000-01-06",0) as '2000', week("2001-01-06",0) as '2001', week("2002-01-06",0) as '2002',week("2003-01-06",0) as '2003', week("2004-01-06",0) as '2004', week("2005-01-06",0) as '2005', week("2006-01-06",0) as '2006';
+2000 2001 2002 2003 2004 2005 2006
+1 0 1 1 1 1 1
+select week("2000-01-01",1) as '2000', week("2001-01-01",1) as '2001', week("2002-01-01",1) as '2002',week("2003-01-01",1) as '2003', week("2004-01-01",1) as '2004', week("2005-01-01",1) as '2005', week("2006-01-01",1) as '2006';
+2000 2001 2002 2003 2004 2005 2006
+0 1 1 1 1 0 0
+select week("2000-01-06",1) as '2000', week("2001-01-06",1) as '2001', week("2002-01-06",1) as '2002',week("2003-01-06",1) as '2003', week("2004-01-06",1) as '2004', week("2005-01-06",1) as '2005', week("2006-01-06",1) as '2006';
+2000 2001 2002 2003 2004 2005 2006
+1 1 1 2 2 1 1
+select yearweek("2000-01-01",0) as '2000', yearweek("2001-01-01",0) as '2001', yearweek("2002-01-01",0) as '2002',yearweek("2003-01-01",0) as '2003', yearweek("2004-01-01",0) as '2004', yearweek("2005-01-01",0) as '2005', yearweek("2006-01-01",0) as '2006';
+2000 2001 2002 2003 2004 2005 2006
+199952 200053 200152 200252 200352 200452 200601
+select yearweek("2000-01-06",0) as '2000', yearweek("2001-01-06",0) as '2001', yearweek("2002-01-06",0) as '2002',yearweek("2003-01-06",0) as '2003', yearweek("2004-01-06",0) as '2004', yearweek("2005-01-06",0) as '2005', yearweek("2006-01-06",0) as '2006';
+2000 2001 2002 2003 2004 2005 2006
+200001 200053 200201 200301 200401 200501 200601
+select yearweek("2000-01-01",1) as '2000', yearweek("2001-01-01",1) as '2001', yearweek("2002-01-01",1) as '2002',yearweek("2003-01-01",1) as '2003', yearweek("2004-01-01",1) as '2004', yearweek("2005-01-01",1) as '2005', yearweek("2006-01-01",1) as '2006';
+2000 2001 2002 2003 2004 2005 2006
+199952 200101 200201 200301 200401 200453 200552
+select yearweek("2000-01-06",1) as '2000', yearweek("2001-01-06",1) as '2001', yearweek("2002-01-06",1) as '2002',yearweek("2003-01-06",1) as '2003', yearweek("2004-01-06",1) as '2004', yearweek("2005-01-06",1) as '2005', yearweek("2006-01-06",1) as '2006';
+2000 2001 2002 2003 2004 2005 2006
+200001 200101 200201 200302 200402 200501 200601
+select date_format('1998-12-31','%x-%v'),date_format('1999-01-01','%x-%v');
date_format('1998-12-31','%x-%v') date_format('1999-01-01','%x-%v')
1998-53 1998-53
+select date_format('1999-12-31','%x-%v'),date_format('2000-01-01','%x-%v');
date_format('1999-12-31','%x-%v') date_format('2000-01-01','%x-%v')
1999-52 1999-52
-yearweek('1987-01-01',1) yearweek('1987-01-01')
-198701 198653
+select dayname("1962-03-03"),dayname("1962-03-03")+0;
dayname("1962-03-03") dayname("1962-03-03")+0
Saturday 5
+select monthname("1972-03-04"),monthname("1972-03-04")+0;
monthname("1972-03-04") monthname("1972-03-04")+0
March 3
+select time_format(19980131000000,'%H|%I|%k|%l|%i|%p|%r|%S|%T');
time_format(19980131000000,'%H|%I|%k|%l|%i|%p|%r|%S|%T')
00|12|0|12|00|AM|12:00:00 AM|00|00:00:00
+select time_format(19980131010203,'%H|%I|%k|%l|%i|%p|%r|%S|%T');
time_format(19980131010203,'%H|%I|%k|%l|%i|%p|%r|%S|%T')
01|01|1|1|02|AM|01:02:03 AM|03|01:02:03
+select time_format(19980131131415,'%H|%I|%k|%l|%i|%p|%r|%S|%T');
time_format(19980131131415,'%H|%I|%k|%l|%i|%p|%r|%S|%T')
13|01|13|1|14|PM|01:14:15 PM|15|13:14:15
+select time_format(19980131010015,'%H|%I|%k|%l|%i|%p|%r|%S|%T');
time_format(19980131010015,'%H|%I|%k|%l|%i|%p|%r|%S|%T')
01|01|1|1|00|AM|01:00:15 AM|15|01:00:15
+select date_format(concat('19980131',131415),'%H|%I|%k|%l|%i|%p|%r|%S|%T| %M|%W|%D|%Y|%y|%a|%b|%j|%m|%d|%h|%s|%w');
date_format(concat('19980131',131415),'%H|%I|%k|%l|%i|%p|%r|%S|%T| %M|%W|%D|%Y|%y|%a|%b|%j|%m|%d|%h|%s|%w')
13|01|13|1|14|PM|01:14:15 PM|15|13:14:15| January|Saturday|31st|1998|98|Sat|Jan|031|01|31|01|15|6
+select date_format(19980021000000,'%H|%I|%k|%l|%i|%p|%r|%S|%T| %M|%W|%D|%Y|%y|%a|%b|%j|%m|%d|%h|%s|%w');
date_format(19980021000000,'%H|%I|%k|%l|%i|%p|%r|%S|%T| %M|%W|%D|%Y|%y|%a|%b|%j|%m|%d|%h|%s|%w')
NULL
+select date_add("1997-12-31 23:59:59",INTERVAL 1 SECOND);
date_add("1997-12-31 23:59:59",INTERVAL 1 SECOND)
1998-01-01 00:00:00
+select date_add("1997-12-31 23:59:59",INTERVAL 1 MINUTE);
date_add("1997-12-31 23:59:59",INTERVAL 1 MINUTE)
1998-01-01 00:00:59
+select date_add("1997-12-31 23:59:59",INTERVAL 1 HOUR);
date_add("1997-12-31 23:59:59",INTERVAL 1 HOUR)
1998-01-01 00:59:59
+select date_add("1997-12-31 23:59:59",INTERVAL 1 DAY);
date_add("1997-12-31 23:59:59",INTERVAL 1 DAY)
1998-01-01 23:59:59
+select date_add("1997-12-31 23:59:59",INTERVAL 1 MONTH);
date_add("1997-12-31 23:59:59",INTERVAL 1 MONTH)
1998-01-31 23:59:59
+select date_add("1997-12-31 23:59:59",INTERVAL 1 YEAR);
date_add("1997-12-31 23:59:59",INTERVAL 1 YEAR)
1998-12-31 23:59:59
+select date_add("1997-12-31 23:59:59",INTERVAL "1:1" MINUTE_SECOND);
date_add("1997-12-31 23:59:59",INTERVAL "1:1" MINUTE_SECOND)
1998-01-01 00:01:00
+select date_add("1997-12-31 23:59:59",INTERVAL "1:1" HOUR_MINUTE);
date_add("1997-12-31 23:59:59",INTERVAL "1:1" HOUR_MINUTE)
1998-01-01 01:00:59
+select date_add("1997-12-31 23:59:59",INTERVAL "1:1" DAY_HOUR);
date_add("1997-12-31 23:59:59",INTERVAL "1:1" DAY_HOUR)
1998-01-02 00:59:59
+select date_add("1997-12-31 23:59:59",INTERVAL "1 1" YEAR_MONTH);
date_add("1997-12-31 23:59:59",INTERVAL "1 1" YEAR_MONTH)
1999-01-31 23:59:59
+select date_add("1997-12-31 23:59:59",INTERVAL "1:1:1" HOUR_SECOND);
date_add("1997-12-31 23:59:59",INTERVAL "1:1:1" HOUR_SECOND)
1998-01-01 01:01:00
+select date_add("1997-12-31 23:59:59",INTERVAL "1 1:1" DAY_MINUTE);
date_add("1997-12-31 23:59:59",INTERVAL "1 1:1" DAY_MINUTE)
1998-01-02 01:00:59
+select date_add("1997-12-31 23:59:59",INTERVAL "1 1:1:1" DAY_SECOND);
date_add("1997-12-31 23:59:59",INTERVAL "1 1:1:1" DAY_SECOND)
1998-01-02 01:01:00
+select date_sub("1998-01-01 00:00:00",INTERVAL 1 SECOND);
date_sub("1998-01-01 00:00:00",INTERVAL 1 SECOND)
1997-12-31 23:59:59
+select date_sub("1998-01-01 00:00:00",INTERVAL 1 MINUTE);
date_sub("1998-01-01 00:00:00",INTERVAL 1 MINUTE)
1997-12-31 23:59:00
+select date_sub("1998-01-01 00:00:00",INTERVAL 1 HOUR);
date_sub("1998-01-01 00:00:00",INTERVAL 1 HOUR)
1997-12-31 23:00:00
+select date_sub("1998-01-01 00:00:00",INTERVAL 1 DAY);
date_sub("1998-01-01 00:00:00",INTERVAL 1 DAY)
1997-12-31 00:00:00
+select date_sub("1998-01-01 00:00:00",INTERVAL 1 MONTH);
date_sub("1998-01-01 00:00:00",INTERVAL 1 MONTH)
1997-12-01 00:00:00
+select date_sub("1998-01-01 00:00:00",INTERVAL 1 YEAR);
date_sub("1998-01-01 00:00:00",INTERVAL 1 YEAR)
1997-01-01 00:00:00
+select date_sub("1998-01-01 00:00:00",INTERVAL "1:1" MINUTE_SECOND);
date_sub("1998-01-01 00:00:00",INTERVAL "1:1" MINUTE_SECOND)
1997-12-31 23:58:59
+select date_sub("1998-01-01 00:00:00",INTERVAL "1:1" HOUR_MINUTE);
date_sub("1998-01-01 00:00:00",INTERVAL "1:1" HOUR_MINUTE)
1997-12-31 22:59:00
+select date_sub("1998-01-01 00:00:00",INTERVAL "1:1" DAY_HOUR);
date_sub("1998-01-01 00:00:00",INTERVAL "1:1" DAY_HOUR)
1997-12-30 23:00:00
+select date_sub("1998-01-01 00:00:00",INTERVAL "1 1" YEAR_MONTH);
date_sub("1998-01-01 00:00:00",INTERVAL "1 1" YEAR_MONTH)
1996-12-01 00:00:00
+select date_sub("1998-01-01 00:00:00",INTERVAL "1:1:1" HOUR_SECOND);
date_sub("1998-01-01 00:00:00",INTERVAL "1:1:1" HOUR_SECOND)
1997-12-31 22:58:59
+select date_sub("1998-01-01 00:00:00",INTERVAL "1 1:1" DAY_MINUTE);
date_sub("1998-01-01 00:00:00",INTERVAL "1 1:1" DAY_MINUTE)
1997-12-30 22:59:00
+select date_sub("1998-01-01 00:00:00",INTERVAL "1 1:1:1" DAY_SECOND);
date_sub("1998-01-01 00:00:00",INTERVAL "1 1:1:1" DAY_SECOND)
1997-12-30 22:58:59
+select date_add("1997-12-31 23:59:59",INTERVAL 100000 SECOND);
date_add("1997-12-31 23:59:59",INTERVAL 100000 SECOND)
1998-01-02 03:46:39
+select date_add("1997-12-31 23:59:59",INTERVAL -100000 MINUTE);
date_add("1997-12-31 23:59:59",INTERVAL -100000 MINUTE)
1997-10-23 13:19:59
+select date_add("1997-12-31 23:59:59",INTERVAL 100000 HOUR);
date_add("1997-12-31 23:59:59",INTERVAL 100000 HOUR)
2009-05-29 15:59:59
+select date_add("1997-12-31 23:59:59",INTERVAL -100000 DAY);
date_add("1997-12-31 23:59:59",INTERVAL -100000 DAY)
1724-03-17 23:59:59
+select date_add("1997-12-31 23:59:59",INTERVAL 100000 MONTH);
date_add("1997-12-31 23:59:59",INTERVAL 100000 MONTH)
NULL
+select date_add("1997-12-31 23:59:59",INTERVAL -100000 YEAR);
date_add("1997-12-31 23:59:59",INTERVAL -100000 YEAR)
NULL
+select date_add("1997-12-31 23:59:59",INTERVAL "10000:1" MINUTE_SECOND);
date_add("1997-12-31 23:59:59",INTERVAL "10000:1" MINUTE_SECOND)
1998-01-07 22:40:00
+select date_add("1997-12-31 23:59:59",INTERVAL "-10000:1" HOUR_MINUTE);
date_add("1997-12-31 23:59:59",INTERVAL "-10000:1" HOUR_MINUTE)
1996-11-10 07:58:59
+select date_add("1997-12-31 23:59:59",INTERVAL "10000:1" DAY_HOUR);
date_add("1997-12-31 23:59:59",INTERVAL "10000:1" DAY_HOUR)
2025-05-19 00:59:59
+select date_add("1997-12-31 23:59:59",INTERVAL "-100 1" YEAR_MONTH);
date_add("1997-12-31 23:59:59",INTERVAL "-100 1" YEAR_MONTH)
1897-11-30 23:59:59
+select date_add("1997-12-31 23:59:59",INTERVAL "10000:99:99" HOUR_SECOND);
date_add("1997-12-31 23:59:59",INTERVAL "10000:99:99" HOUR_SECOND)
1999-02-21 17:40:38
+select date_add("1997-12-31 23:59:59",INTERVAL " -10000 99:99" DAY_MINUTE);
date_add("1997-12-31 23:59:59",INTERVAL " -10000 99:99" DAY_MINUTE)
1970-08-11 19:20:59
+select date_add("1997-12-31 23:59:59",INTERVAL "10000 99:99:99" DAY_SECOND);
date_add("1997-12-31 23:59:59",INTERVAL "10000 99:99:99" DAY_SECOND)
2025-05-23 04:40:38
+select "1997-12-31 23:59:59" + INTERVAL 1 SECOND;
"1997-12-31 23:59:59" + INTERVAL 1 SECOND
1998-01-01 00:00:00
+select INTERVAL 1 DAY + "1997-12-31";
INTERVAL 1 DAY + "1997-12-31"
1998-01-01
+select "1998-01-01 00:00:00" - INTERVAL 1 SECOND;
"1998-01-01 00:00:00" - INTERVAL 1 SECOND
1997-12-31 23:59:59
+select date_sub("1998-01-02",INTERVAL 31 DAY);
date_sub("1998-01-02",INTERVAL 31 DAY)
1997-12-02
+select date_add("1997-12-31",INTERVAL 1 SECOND);
date_add("1997-12-31",INTERVAL 1 SECOND)
1997-12-31 00:00:01
+select date_add("1997-12-31",INTERVAL 1 DAY);
date_add("1997-12-31",INTERVAL 1 DAY)
1998-01-01
+select date_add(NULL,INTERVAL 100000 SECOND);
date_add(NULL,INTERVAL 100000 SECOND)
NULL
+select date_add("1997-12-31 23:59:59",INTERVAL NULL SECOND);
date_add("1997-12-31 23:59:59",INTERVAL NULL SECOND)
NULL
+select date_add("1997-12-31 23:59:59",INTERVAL NULL MINUTE_SECOND);
date_add("1997-12-31 23:59:59",INTERVAL NULL MINUTE_SECOND)
NULL
+select date_add("9999-12-31 23:59:59",INTERVAL 1 SECOND);
date_add("9999-12-31 23:59:59",INTERVAL 1 SECOND)
NULL
+select date_sub("0000-00-00 00:00:00",INTERVAL 1 SECOND);
date_sub("0000-00-00 00:00:00",INTERVAL 1 SECOND)
NULL
+select date_add('1998-01-30',Interval 1 month);
date_add('1998-01-30',Interval 1 month)
1998-02-28
+select date_add('1998-01-30',Interval '2:1' year_month);
date_add('1998-01-30',Interval '2:1' year_month)
2000-02-29
+select date_add('1996-02-29',Interval '1' year);
date_add('1996-02-29',Interval '1' year)
1997-02-28
+select extract(YEAR FROM "1999-01-02 10:11:12");
extract(YEAR FROM "1999-01-02 10:11:12")
1999
+select extract(YEAR_MONTH FROM "1999-01-02");
extract(YEAR_MONTH FROM "1999-01-02")
199901
+select extract(DAY FROM "1999-01-02");
extract(DAY FROM "1999-01-02")
2
+select extract(DAY_HOUR FROM "1999-01-02 10:11:12");
extract(DAY_HOUR FROM "1999-01-02 10:11:12")
210
+select extract(DAY_MINUTE FROM "02 10:11:12");
extract(DAY_MINUTE FROM "02 10:11:12")
21011
+select extract(DAY_SECOND FROM "225 10:11:12");
extract(DAY_SECOND FROM "225 10:11:12")
225101112
+select extract(HOUR FROM "1999-01-02 10:11:12");
extract(HOUR FROM "1999-01-02 10:11:12")
10
+select extract(HOUR_MINUTE FROM "10:11:12");
extract(HOUR_MINUTE FROM "10:11:12")
1011
+select extract(HOUR_SECOND FROM "10:11:12");
extract(HOUR_SECOND FROM "10:11:12")
101112
+select extract(MINUTE FROM "10:11:12");
extract(MINUTE FROM "10:11:12")
11
+select extract(MINUTE_SECOND FROM "10:11:12");
extract(MINUTE_SECOND FROM "10:11:12")
1112
+select extract(SECOND FROM "1999-01-02 10:11:12");
extract(SECOND FROM "1999-01-02 10:11:12")
12
+select extract(MONTH FROM "2001-02-00");
extract(MONTH FROM "2001-02-00")
2
+create table t1 (ctime varchar(20));
+insert into t1 values ('2001-01-12 12:23:40');
+select ctime, hour(ctime) from t1;
ctime hour(ctime)
2001-01-12 12:23:40 12
+drop table t1;
+create table t1 (id int);
+create table t2 (id int, date date);
+insert into t1 values (1);
+insert into t2 values (1, "0000-00-00");
+insert into t1 values (2);
+insert into t2 values (2, "2000-01-01");
+select monthname(date) from t1 inner join t2 on t1.id = t2.id;
monthname(date)
NULL
January
+select monthname(date) from t1 inner join t2 on t1.id = t2.id order by t1.id;
monthname(date)
NULL
January
+drop table t1,t2;
+CREATE TABLE t1 (updated text) TYPE=MyISAM;
+INSERT INTO t1 VALUES ('');
+SELECT month(updated) from t1;
month(updated)
NULL
+SELECT year(updated) from t1;
year(updated)
NULL
+drop table t1;
+create table t1 (d date, dt datetime, t timestamp, c char(10));
+insert into t1 values ("0000-00-00", "0000-00-00", "0000-00-00", "0000-00-00");
+select dayofyear("0000-00-00"),dayofyear(d),dayofyear(dt),dayofyear(t),dayofyear(c) from t1;
dayofyear("0000-00-00") dayofyear(d) dayofyear(dt) dayofyear(t) dayofyear(c)
NULL NULL NULL NULL NULL
+select dayofmonth("0000-00-00"),dayofmonth(d),dayofmonth(dt),dayofmonth(t),dayofmonth(c) from t1;
dayofmonth("0000-00-00") dayofmonth(d) dayofmonth(dt) dayofmonth(t) dayofmonth(c)
0 0 0 0 0
+select month("0000-00-00"),month(d),month(dt),month(t),month(c) from t1;
month("0000-00-00") month(d) month(dt) month(t) month(c)
0 0 0 0 0
+select quarter("0000-00-00"),quarter(d),quarter(dt),quarter(t),quarter(c) from t1;
quarter("0000-00-00") quarter(d) quarter(dt) quarter(t) quarter(c)
0 0 0 0 0
+select week("0000-00-00"),week(d),week(dt),week(t),week(c) from t1;
week("0000-00-00") week(d) week(dt) week(t) week(c)
NULL NULL NULL NULL NULL
+select year("0000-00-00"),year(d),year(dt),year(t),year(c) from t1;
year("0000-00-00") year(d) year(dt) year(t) year(c)
0 0 0 0 0
+select yearweek("0000-00-00"),yearweek(d),yearweek(dt),yearweek(t),yearweek(c) from t1;
yearweek("0000-00-00") yearweek(d) yearweek(dt) yearweek(t) yearweek(c)
NULL NULL NULL NULL NULL
+select to_days("0000-00-00"),to_days(d),to_days(dt),to_days(t),to_days(c) from t1;
to_days("0000-00-00") to_days(d) to_days(dt) to_days(t) to_days(c)
NULL NULL NULL NULL NULL
+select extract(MONTH FROM "0000-00-00"),extract(MONTH FROM d),extract(MONTH FROM dt),extract(MONTH FROM t),extract(MONTH FROM c) from t1;
extract(MONTH FROM "0000-00-00") extract(MONTH FROM d) extract(MONTH FROM dt) extract(MONTH FROM t) extract(MONTH FROM c)
0 0 0 0 0
+drop table t1;
diff --git a/mysql-test/r/func_timestamp.result b/mysql-test/r/func_timestamp.result
index 4d4a5b541ac..d9912f08b72 100644
--- a/mysql-test/r/func_timestamp.result
+++ b/mysql-test/r/func_timestamp.result
@@ -1,3 +1,11 @@
+drop table if exists t1;
+create table t1 (Zeit time, Tag tinyint not null, Monat tinyint not null,
+Jahr smallint not null, index(Tag), index(Monat), index(Jahr) );
+insert into t1 values ("09:26:00",16,9,1998),("09:26:00",16,9,1998);
+SELECT CONCAT(Jahr,'-',Monat,'-',Tag,' ',Zeit) AS Date,
+UNIX_TIMESTAMP(CONCAT(Jahr,'-',Monat,'-',Tag,' ',Zeit)) AS Unix
+FROM t1;
Date Unix
1998-9-16 09:26:00 905927160
1998-9-16 09:26:00 905927160
+drop table t1;
diff --git a/mysql-test/r/gcc296.result b/mysql-test/r/gcc296.result
index 7184bfb9cdc..8f78f70cc1f 100644
--- a/mysql-test/r/gcc296.result
+++ b/mysql-test/r/gcc296.result
@@ -1,5 +1,20 @@
+drop table if exists obory;
+CREATE TABLE obory (
+kodoboru varchar(10) default NULL,
+obor tinytext,
+aobor tinytext,
+UNIQUE INDEX kodoboru (kodoboru),
+FULLTEXT KEY obor (obor),
+FULLTEXT KEY aobor (aobor)
+);
+INSERT INTO obory VALUES ('0101000000','aaa','AAA');
+INSERT INTO obory VALUES ('0102000000','bbb','BBB');
+INSERT INTO obory VALUES ('0103000000','ccc','CCC');
+INSERT INTO obory VALUES ('0104000000','xxx','XXX');
+select * from obory;
kodoboru obor aobor
0101000000 aaa AAA
0102000000 bbb BBB
0103000000 ccc CCC
0104000000 xxx XXX
+drop table obory;
diff --git a/mysql-test/r/gemini.result b/mysql-test/r/gemini.result
deleted file mode 100644
index 0b43b4f5192..00000000000
--- a/mysql-test/r/gemini.result
+++ /dev/null
@@ -1,370 +0,0 @@
-id code name
-1 1 Tim
-2 1 Monty
-3 2 David
-4 2 Erik
-5 3 Sasha
-6 3 Jeremy
-7 4 Matt
-id code name
-2 1 Monty
-3 2 David
-4 2 Erik
-5 3 Sasha
-6 3 Jeremy
-7 4 Matt
-8 1 Sinisa
-id code name
-3 2 David
-4 2 Erik
-5 3 Sasha
-6 3 Jeremy
-7 4 Matt
-8 1 Sinisa
-12 1 Ralph
-id parent_id level
-8 102 2
-9 102 2
-15 102 2
-id parent_id level
-1001 100 0
-1003 101 1
-1004 101 1
-1008 102 2
-1009 102 2
-1017 103 2
-1022 104 2
-1024 104 2
-1028 105 2
-1029 105 2
-1030 105 2
-1031 106 2
-1032 106 2
-1033 106 2
-1203 107 2
-1202 107 2
-1020 103 2
-1157 100 0
-1193 105 2
-1040 107 2
-1002 101 1
-1015 102 2
-1006 101 1
-1034 106 2
-1035 106 2
-1016 103 2
-1007 101 1
-1036 107 2
-1018 103 2
-1026 105 2
-1027 105 2
-1183 104 2
-1038 107 2
-1025 105 2
-1037 107 2
-1021 104 2
-1019 103 2
-1005 101 1
-1179 105 2
-id parent_id level
-1001 100 0
-1003 101 1
-1004 101 1
-1008 102 2
-1010 102 2
-1017 103 2
-1023 104 2
-1024 104 2
-1028 105 2
-1029 105 2
-1030 105 2
-1031 106 2
-1032 106 2
-1033 106 2
-1204 107 2
-1203 107 2
-1020 103 2
-1158 100 0
-1194 105 2
-1041 107 2
-1002 101 1
-1015 102 2
-1006 101 1
-1034 106 2
-1035 106 2
-1016 103 2
-1007 101 1
-1036 107 2
-1018 103 2
-1026 105 2
-1027 105 2
-1184 104 2
-1039 107 2
-1025 105 2
-1038 107 2
-1022 104 2
-1019 103 2
-1005 101 1
-1180 105 2
-id parent_id level
-1008 102 2
-1010 102 2
-1015 102 2
-table type possible_keys key key_len ref rows Extra
-t1 ref level level 1 const 6 where used; Using index
-table type possible_keys key key_len ref rows Extra
-t1 ref level level 1 const 6 where used
-table type possible_keys key key_len ref rows Extra
-t1 ref level level 1 const 6 where used
-level id
-1 1003
-1 1004
-1 1002
-1 1006
-1 1007
-1 1005
-level id parent_id
-1 1003 101
-1 1004 101
-1 1002 101
-1 1006 101
-1 1007 101
-1 1005 101
-gesuchnr benutzer_id
-1 1
-2 1
-a
-2
-user_id name phone ref_email detail
-10292 sanjeev 29153373 sansh777@hotmail.com xxx
-10292 shirish 2333604 shirish@yahoo.com ddsds
-10292 sonali 323232 sonali@bolly.com filmstar
-user_id name phone ref_email detail
-10292 sanjeev 29153373 sansh777@hotmail.com xxx
-10292 shirish 2333604 shirish@yahoo.com ddsds
-10292 sonali 323232 sonali@bolly.com filmstar
-user_id name phone ref_email detail
-10292 sanjeev 29153373 sansh777@hotmail.com xxx
-10292 shirish 2333604 shirish@yahoo.com ddsds
-10292 sonali 323232 sonali@bolly.com filmstar
-10293 shirish 2333604 shirish@yahoo.com ddsds
-user_id name phone ref_email detail
-10293 shirish 2333604 shirish@yahoo.com ddsds
-user_id name phone ref_email detail
-10291 sanjeev 29153373 sansh777@hotmail.com xxx
-a b
-1 3
-2 3
-3 3
-a b
-1 3
-2 3
-3 3
-a b
-a b
-1 3
-2 3
-3 3
-a b
-1 3
-2 3
-3 3
-id ggid email passwd
-1 test1 xxx
-id ggid email passwd
-1 test1 xxx
-id ggid email passwd
-2 test2 yyy
-id parent_id level
-8 102 2
-9 102 2
-15 102 2
-id parent_id level
-1001 100 0
-1003 101 1
-1004 101 1
-1008 102 2
-1024 102 2
-1017 103 2
-1022 104 2
-1024 104 2
-1028 105 2
-1029 105 2
-1030 105 2
-1031 106 2
-1032 106 2
-1033 106 2
-1203 107 2
-1202 107 2
-1020 103 2
-1157 100 0
-1193 105 2
-1040 107 2
-1002 101 1
-1015 102 2
-1006 101 1
-1034 106 2
-1035 106 2
-1016 103 2
-1007 101 1
-1036 107 2
-1018 103 2
-1026 105 2
-1027 105 2
-1183 104 2
-1038 107 2
-1025 105 2
-1037 107 2
-1021 104 2
-1019 103 2
-1005 101 1
-1179 105 2
-id parent_id level
-1002 100 0
-1004 101 1
-1005 101 1
-1009 102 2
-1025 102 2
-1018 103 2
-1023 104 2
-1025 104 2
-1029 105 2
-1030 105 2
-1031 105 2
-1032 106 2
-1033 106 2
-1034 106 2
-1204 107 2
-1203 107 2
-1021 103 2
-1158 100 0
-1194 105 2
-1041 107 2
-1003 101 1
-1016 102 2
-1007 101 1
-1035 106 2
-1036 106 2
-1017 103 2
-1008 101 1
-1037 107 2
-1019 103 2
-1027 105 2
-1028 105 2
-1184 104 2
-1039 107 2
-1026 105 2
-1038 107 2
-1022 104 2
-1020 103 2
-1006 101 1
-1180 105 2
-id parent_id level
-1009 102 2
-1025 102 2
-1016 102 2
-table type possible_keys key key_len ref rows Extra
-t1 ref level level 1 const 6 where used; Using index
-level id
-1 1004
-1 1005
-1 1003
-1 1007
-1 1008
-1 1006
-level id parent_id
-1 1004 101
-1 1005 101
-1 1003 101
-1 1007 101
-1 1008 101
-1 1006 101
-level id
-1 1003
-1 1004
-1 1005
-1 1006
-1 1007
-1 1008
-id parent_id level
-1002 100 0
-1009 102 2
-1025 102 2
-1018 103 2
-1023 104 2
-1025 104 2
-1029 105 2
-1030 105 2
-1031 105 2
-1032 106 2
-1033 106 2
-1034 106 2
-1204 107 2
-1203 107 2
-1021 103 2
-1158 100 0
-1194 105 2
-1041 107 2
-1016 102 2
-1035 106 2
-1036 106 2
-1017 103 2
-1037 107 2
-1019 103 2
-1027 105 2
-1028 105 2
-1184 104 2
-1039 107 2
-1026 105 2
-1038 107 2
-1022 104 2
-1020 103 2
-1180 105 2
-count(*)
-1
-a
-1
-2
-3
-test for rollback
-test for rollback
-n after rollback
-4 after rollback
-n after commit
-4 after commit
-5 after commit
-n after commit
-4 after commit
-5 after commit
-6 after commit
-n
-4
-5
-6
-7
-afterbegin_id afterbegin_nom
-1 first
-2 hamdouni
-afterrollback_id afterrollback_nom
-1 first
-afterautocommit0_id afterautocommit0_nom
-1 first
-3 mysql
-afterrollback_id afterrollback_nom
-1 first
-id val
-id val
-pippo 12
-id val
-ID NAME
-1 Jochen
-_userid
-marc@anyware.co.uk
-_userid
-marc@anyware.co.uk
-f1
-65
-379
-468
-469
-508
diff --git a/mysql-test/r/grant_cache.result b/mysql-test/r/grant_cache.result
new file mode 100644
index 00000000000..d236c26d71a
--- /dev/null
+++ b/mysql-test/r/grant_cache.result
@@ -0,0 +1,153 @@
+drop table if exists test.t1,mysqltest.t1,mysqltest.t2;
+reset query cache;
+flush status;
+create database if not exists mysqltest;
+create table mysqltest.t1 (a int,b int,c int);
+create table mysqltest.t2 (a int,b int,c int);
+insert into mysqltest.t1 values (1,1,1),(2,2,2);
+insert into mysqltest.t2 values (3,3,3);
+create table test.t1 (a char (10));
+insert into test.t1 values ("test.t1");
+select * from t1;
+a
+test.t1
+select * from t1;
+a b c
+1 1 1
+2 2 2
+select a from t1;
+a
+1
+2
+select c from t1;
+c
+1
+2
+select * from t2;
+a b c
+3 3 3
+select * from mysqltest.t1,test.t1;
+a b c a
+1 1 1 test.t1
+2 2 2 test.t1
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 6
+show status like "Qcache_hits%";
+Variable_name Value
+Qcache_hits 0
+grant SELECT on mysqltest.* to mysqltest_1@localhost;
+grant SELECT on mysqltest.t1 to mysqltest_2@localhost;
+grant SELECT on test.t1 to mysqltest_2@localhost;
+grant SELECT(a) on mysqltest.t1 to mysqltest_3@localhost;
+select "user1";
+user1
+user1
+select * from t1;
+a b c
+1 1 1
+2 2 2
+select a from t1 ;
+a
+1
+2
+select c from t1;
+c
+1
+2
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 6
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 3
+show status like "Qcache_not_cached";
+Variable_name Value
+Qcache_not_cached 1
+select "user2";
+user2
+user2
+select * from t1;
+a b c
+1 1 1
+2 2 2
+select a from t1;
+a
+1
+2
+select c from t1;
+c
+1
+2
+select * from mysqltest.t1,test.t1;
+a b c a
+1 1 1 test.t1
+2 2 2 test.t1
+select * from t2;
+select command denied to user: 'mysqltest_2@localhost' for table 't2'
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 6
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 7
+show status like "Qcache_not_cached";
+Variable_name Value
+Qcache_not_cached 3
+select "user3";
+user3
+user3
+select * from t1;
+select command denied to user: 'mysqltest_3@localhost' for column 'b' in table 't1'
+select a from t1;
+a
+1
+2
+select c from t1;
+select command denied to user: 'mysqltest_3@localhost' for column 'c' in table 't1'
+select * from t2;
+select command denied to user: 'mysqltest_3@localhost' for table 't2'
+select mysqltest.t1.c from test.t1,mysqltest.t1;
+select command denied to user: 'mysqltest_3@localhost' for column 'c' in table 't1'
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 6
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 7
+show status like "Qcache_not_cached";
+Variable_name Value
+Qcache_not_cached 8
+select "user4";
+user4
+user4
+select a from t1;
+No Database Selected
+select * from mysqltest.t1,test.t1;
+a b c a
+1 1 1 test.t1
+2 2 2 test.t1
+select a from mysqltest.t1;
+a
+1
+2
+select a from mysqltest.t1;
+a
+1
+2
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 8
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 8
+show status like "Qcache_not_cached";
+Variable_name Value
+Qcache_not_cached 9
+delete from mysql.user where user in ("mysqltest_1","mysqltest_2","mysqltest_3");
+delete from mysql.db where user in ("mysqltest_1","mysqltest_2","mysqltest_3");
+delete from mysql.tables_priv where user in ("mysqltest_1","mysqltest_2","mysqltest_3");
+delete from mysql.columns_priv where user in ("mysqltest_1","mysqltest_2","mysqltest_3");
+flush privileges;
+drop table test.t1,mysqltest.t1,mysqltest.t2;
+drop database mysqltest;
diff --git a/mysql-test/r/group_by.result b/mysql-test/r/group_by.result
index d5fcc7d85e8..9845e12ef5f 100644
--- a/mysql-test/r/group_by.result
+++ b/mysql-test/r/group_by.result
@@ -1,15 +1,189 @@
+drop table if exists t1,t2;
+CREATE TABLE t1 (
+spID int(10) unsigned,
+userID int(10) unsigned,
+score smallint(5) unsigned,
+lsg char(40),
+date date
+);
+INSERT INTO t1 VALUES (1,1,1,'','0000-00-00');
+INSERT INTO t1 VALUES (2,2,2,'','0000-00-00');
+INSERT INTO t1 VALUES (2,1,1,'','0000-00-00');
+INSERT INTO t1 VALUES (3,3,3,'','0000-00-00');
+CREATE TABLE t2 (
+userID int(10) unsigned DEFAULT '0' NOT NULL auto_increment,
+niName char(15),
+passwd char(8),
+mail char(50),
+isAukt enum('N','Y') DEFAULT 'N',
+vName char(30),
+nName char(40),
+adr char(60),
+plz char(5),
+ort char(35),
+land char(20),
+PRIMARY KEY (userID)
+);
+INSERT INTO t2 VALUES (1,'name','pass','mail','Y','v','n','adr','1','1','1');
+INSERT INTO t2 VALUES (2,'name','pass','mail','Y','v','n','adr','1','1','1');
+INSERT INTO t2 VALUES (3,'name','pass','mail','Y','v','n','adr','1','1','1');
+SELECT t2.userid, MIN(t1.score) FROM t1, t2 WHERE t1.userID=t2.userID GROUP BY t2.userid;
userid MIN(t1.score)
1 1
2 2
3 3
+SELECT t2.userid, MIN(t1.score) FROM t1, t2 WHERE t1.userID=t2.userID AND t1.spID=2 GROUP BY t2.userid;
userid MIN(t1.score)
1 1
2 2
+SELECT t2.userid, MIN(t1.score+0.0) FROM t1, t2 WHERE t1.userID=t2.userID AND t1.spID=2 GROUP BY t2.userid;
userid MIN(t1.score+0.0)
1 1.0
2 2.0
+drop table test.t1,test.t2;
+CREATE TABLE t1 (
+PID int(10) unsigned DEFAULT '0' NOT NULL auto_increment,
+payDate date DEFAULT '0000-00-00' NOT NULL,
+recDate datetime DEFAULT '0000-00-00 00:00:00' NOT NULL,
+URID int(10) unsigned DEFAULT '0' NOT NULL,
+CRID int(10) unsigned DEFAULT '0' NOT NULL,
+amount int(10) unsigned DEFAULT '0' NOT NULL,
+operator int(10) unsigned,
+method enum('unknown','cash','dealer','check','card','lazy','delayed','test') DEFAULT 'unknown' NOT NULL,
+DIID int(10) unsigned,
+reason char(1) binary DEFAULT '' NOT NULL,
+code_id int(10) unsigned,
+qty mediumint(8) unsigned DEFAULT '0' NOT NULL,
+PRIMARY KEY (PID),
+KEY URID (URID),
+KEY reason (reason),
+KEY method (method),
+KEY payDate (payDate)
+);
+INSERT INTO t1 VALUES (1,'1970-01-01','1997-10-17 00:00:00',2529,1,21000,11886,'check',0,'F',16200,6);
+SELECT COUNT(P.URID),SUM(P.amount),P.method, MIN(PP.recdate+0) > 19980501000000 AS IsNew FROM t1 AS P JOIN t1 as PP WHERE P.URID = PP.URID GROUP BY method,IsNew;
+Can't group on 'IsNew'
+drop table t1;
+CREATE TABLE t1 (
+cid mediumint(9) DEFAULT '0' NOT NULL auto_increment,
+firstname varchar(32) DEFAULT '' NOT NULL,
+surname varchar(32) DEFAULT '' NOT NULL,
+PRIMARY KEY (cid)
+);
+INSERT INTO t1 VALUES (1,'That','Guy');
+INSERT INTO t1 VALUES (2,'Another','Gent');
+CREATE TABLE t2 (
+call_id mediumint(8) DEFAULT '0' NOT NULL auto_increment,
+contact_id mediumint(8) DEFAULT '0' NOT NULL,
+PRIMARY KEY (call_id),
+KEY contact_id (contact_id)
+);
+lock tables t1 read,t2 write;
+INSERT INTO t2 VALUES (10,2);
+INSERT INTO t2 VALUES (18,2);
+INSERT INTO t2 VALUES (62,2);
+INSERT INTO t2 VALUES (91,2);
+INSERT INTO t2 VALUES (92,2);
+SELECT cid, CONCAT(firstname, ' ', surname), COUNT(call_id) FROM t1 LEFT JOIN t2 ON cid=contact_id WHERE firstname like '%foo%' GROUP BY cid;
cid CONCAT(firstname, ' ', surname) COUNT(call_id)
+SELECT HIGH_PRIORITY cid, CONCAT(firstname, ' ', surname), COUNT(call_id) FROM t1 LEFT JOIN t2 ON cid=contact_id WHERE firstname like '%foo%' GROUP BY cid ORDER BY surname, firstname;
cid CONCAT(firstname, ' ', surname) COUNT(call_id)
+drop table t1,t2;
+unlock tables;
+CREATE TABLE t1 (
+bug_id mediumint(9) DEFAULT '0' NOT NULL auto_increment,
+groupset bigint(20) DEFAULT '0' NOT NULL,
+assigned_to mediumint(9) DEFAULT '0' NOT NULL,
+bug_file_loc text,
+bug_severity enum('blocker','critical','major','normal','minor','trivial','enhancement') DEFAULT 'blocker' NOT NULL,
+bug_status enum('NEW','ASSIGNED','REOPENED','RESOLVED','VERIFIED','CLOSED') DEFAULT 'NEW' NOT NULL,
+creation_ts datetime DEFAULT '0000-00-00 00:00:00' NOT NULL,
+delta_ts timestamp(14),
+short_desc mediumtext,
+long_desc mediumtext,
+op_sys enum('All','Windows 3.1','Windows 95','Windows 98','Windows NT','Windows 2000','Linux','other') DEFAULT 'All' NOT NULL,
+priority enum('P1','P2','P3','P4','P5') DEFAULT 'P1' NOT NULL,
+product varchar(64) DEFAULT '' NOT NULL,
+rep_platform enum('All','PC','VTD-8','Other'),
+reporter mediumint(9) DEFAULT '0' NOT NULL,
+version varchar(16) DEFAULT '' NOT NULL,
+component varchar(50) DEFAULT '' NOT NULL,
+resolution enum('','FIXED','INVALID','WONTFIX','LATER','REMIND','DUPLICATE','WORKSFORME') DEFAULT '' NOT NULL,
+target_milestone varchar(20) DEFAULT '' NOT NULL,
+qa_contact mediumint(9) DEFAULT '0' NOT NULL,
+status_whiteboard mediumtext NOT NULL,
+votes mediumint(9) DEFAULT '0' NOT NULL,
+PRIMARY KEY (bug_id),
+KEY assigned_to (assigned_to),
+KEY creation_ts (creation_ts),
+KEY delta_ts (delta_ts),
+KEY bug_severity (bug_severity),
+KEY bug_status (bug_status),
+KEY op_sys (op_sys),
+KEY priority (priority),
+KEY product (product),
+KEY reporter (reporter),
+KEY version (version),
+KEY component (component),
+KEY resolution (resolution),
+KEY target_milestone (target_milestone),
+KEY qa_contact (qa_contact),
+KEY votes (votes)
+);
+INSERT INTO t1 VALUES (1,0,0,'','normal','','2000-02-10 09:25:12',20000321114747,'','','Linux','P1','TestProduct','PC',3,'other','TestComponent','','M1',0,'',0);
+INSERT INTO t1 VALUES (9,0,0,'','enhancement','','2000-03-10 11:49:36',20000321114747,'','','All','P5','AAAAA','PC',3,'2.00 CD - Pre','BBBBBBBBBBBBB - conversion','','',0,'',0);
+INSERT INTO t1 VALUES (10,0,0,'','enhancement','','2000-03-10 18:10:16',20000321114747,'','','All','P4','AAAAA','PC',3,'2.00 CD - Pre','BBBBBBBBBBBBB - conversion','','',0,'',0);
+INSERT INTO t1 VALUES (7,0,0,'','critical','','2000-03-09 10:50:21',20000321114747,'','','All','P1','AAAAA','PC',3,'2.00 CD - Pre','BBBBBBBBBBBBB - generic','','',0,'',0);
+INSERT INTO t1 VALUES (6,0,0,'','normal','','2000-03-09 10:42:44',20000321114747,'','','All','P2','AAAAA','PC',3,'2.00 CD - Pre','kkkkkkkkkkk lllllllllll','','',0,'',0);
+INSERT INTO t1 VALUES (8,0,0,'','major','','2000-03-09 11:32:14',20000321114747,'','','All','P3','AAAAA','PC',3,'2.00 CD - Pre','kkkkkkkkkkk lllllllllll','','',0,'',0);
+INSERT INTO t1 VALUES (5,0,0,'','enhancement','','2000-03-09 10:38:59',20000321114747,'','','All','P5','CCC/CCCCCC','PC',5,'7.00','Administration','','',0,'',0);
+INSERT INTO t1 VALUES (4,0,0,'','normal','','2000-03-08 18:32:14',20000321114747,'','','other','P2','TestProduct','Other',3,'other','TestComponent2','','',0,'',0);
+INSERT INTO t1 VALUES (3,0,0,'','normal','','2000-03-08 18:30:52',20000321114747,'','','other','P2','TestProduct','Other',3,'other','TestComponent','','',0,'',0);
+INSERT INTO t1 VALUES (2,0,0,'','enhancement','','2000-03-08 18:24:51',20000321114747,'','','All','P2','TestProduct','Other',4,'other','TestComponent2','','',0,'',0);
+INSERT INTO t1 VALUES (11,0,0,'','blocker','','2000-03-13 09:43:41',20000321114747,'','','All','P2','CCC/CCCCCC','PC',5,'7.00','DDDDDDDDD','','',0,'',0);
+INSERT INTO t1 VALUES (12,0,0,'','normal','','2000-03-13 16:14:31',20000321114747,'','','All','P2','AAAAA','PC',3,'2.00 CD - Pre','kkkkkkkkkkk lllllllllll','','',0,'',0);
+INSERT INTO t1 VALUES (13,0,0,'','normal','','2000-03-15 16:20:44',20000321114747,'','','other','P2','TestProduct','Other',3,'other','TestComponent','','',0,'',0);
+INSERT INTO t1 VALUES (14,0,0,'','blocker','','2000-03-15 18:13:47',20000321114747,'','','All','P1','AAAAA','PC',3,'2.00 CD - Pre','BBBBBBBBBBBBB - generic','','',0,'',0);
+INSERT INTO t1 VALUES (15,0,0,'','minor','','2000-03-16 18:03:28',20000321114747,'','','All','P2','CCC/CCCCCC','Other',5,'7.00','DDDDDDDDD','','',0,'',0);
+INSERT INTO t1 VALUES (16,0,0,'','normal','','2000-03-16 18:33:41',20000321114747,'','','All','P2','CCC/CCCCCC','Other',5,'7.00','Administration','','',0,'',0);
+INSERT INTO t1 VALUES (17,0,0,'','normal','','2000-03-16 18:34:18',20000321114747,'','','All','P2','CCC/CCCCCC','Other',5,'7.00','Administration','','',0,'',0);
+INSERT INTO t1 VALUES (18,0,0,'','normal','','2000-03-16 18:34:56',20000321114747,'','','All','P2','CCC/CCCCCC','Other',5,'7.00','Administration','','',0,'',0);
+INSERT INTO t1 VALUES (19,0,0,'','enhancement','','2000-03-16 18:35:34',20000321114747,'','','All','P2','CCC/CCCCCC','Other',5,'7.00','Administration','','',0,'',0);
+INSERT INTO t1 VALUES (20,0,0,'','enhancement','','2000-03-16 18:36:23',20000321114747,'','','All','P2','CCC/CCCCCC','Other',5,'7.00','Administration','','',0,'',0);
+INSERT INTO t1 VALUES (21,0,0,'','enhancement','','2000-03-16 18:37:23',20000321114747,'','','All','P2','CCC/CCCCCC','Other',5,'7.00','Administration','','',0,'',0);
+INSERT INTO t1 VALUES (22,0,0,'','enhancement','','2000-03-16 18:38:16',20000321114747,'','','All','P2','CCC/CCCCCC','Other',5,'7.00','Administration','','',0,'',0);
+INSERT INTO t1 VALUES (23,0,0,'','normal','','2000-03-16 18:58:12',20000321114747,'','','All','P2','CCC/CCCCCC','Other',5,'7.00','DDDDDDDDD','','',0,'',0);
+INSERT INTO t1 VALUES (24,0,0,'','normal','','2000-03-17 11:08:10',20000321114747,'','','All','P2','AAAAAAAA-AAA','PC',3,'2.8','Web Interface','','',0,'',0);
+INSERT INTO t1 VALUES (25,0,0,'','normal','','2000-03-17 11:10:45',20000321114747,'','','All','P2','AAAAAAAA-AAA','PC',3,'2.8','Web Interface','','',0,'',0);
+INSERT INTO t1 VALUES (26,0,0,'','normal','','2000-03-17 11:15:47',20000321114747,'','','All','P2','AAAAAAAA-AAA','PC',3,'2.8','Web Interface','','',0,'',0);
+INSERT INTO t1 VALUES (27,0,0,'','normal','','2000-03-17 17:45:41',20000321114747,'','','All','P2','CCC/CCCCCC','PC',5,'7.00','DDDDDDDDD','','',0,'',0);
+INSERT INTO t1 VALUES (28,0,0,'','normal','','2000-03-20 09:51:45',20000321114747,'','','Windows NT','P2','TestProduct','PC',8,'other','TestComponent','','',0,'',0);
+INSERT INTO t1 VALUES (29,0,0,'','normal','','2000-03-20 11:15:09',20000321114747,'','','All','P5','AAAAAAAA-AAA','PC',3,'2.8','Web Interface','','',0,'',0);
+CREATE TABLE t2 (
+value tinytext,
+program varchar(64),
+initialowner tinytext NOT NULL,
+initialqacontact tinytext NOT NULL,
+description mediumtext NOT NULL
+);
+INSERT INTO t2 VALUES ('TestComponent','TestProduct','id0001','','');
+INSERT INTO t2 VALUES ('BBBBBBBBBBBBB - conversion','AAAAA','id0001','','');
+INSERT INTO t2 VALUES ('BBBBBBBBBBBBB - generic','AAAAA','id0001','','');
+INSERT INTO t2 VALUES ('TestComponent2','TestProduct','id0001','','');
+INSERT INTO t2 VALUES ('BBBBBBBBBBBBB - eeeeeeeee','AAAAA','id0001','','');
+INSERT INTO t2 VALUES ('kkkkkkkkkkk lllllllllll','AAAAA','id0001','','');
+INSERT INTO t2 VALUES ('Test Procedures','AAAAA','id0001','','');
+INSERT INTO t2 VALUES ('Documentation','AAAAA','id0003','','');
+INSERT INTO t2 VALUES ('DDDDDDDDD','CCC/CCCCCC','id0002','','');
+INSERT INTO t2 VALUES ('Eeeeeeee Lite','CCC/CCCCCC','id0002','','');
+INSERT INTO t2 VALUES ('Eeeeeeee Full','CCC/CCCCCC','id0002','','');
+INSERT INTO t2 VALUES ('Administration','CCC/CCCCCC','id0002','','');
+INSERT INTO t2 VALUES ('Distribution','CCC/CCCCCC','id0002','','');
+INSERT INTO t2 VALUES ('Setup','CCC/CCCCCC','id0002','','');
+INSERT INTO t2 VALUES ('Unspecified','CCC/CCCCCC','id0002','','');
+INSERT INTO t2 VALUES ('Web Interface','AAAAAAAA-AAA','id0001','','');
+INSERT INTO t2 VALUES ('Host communication','AAAAA','id0001','','');
+select value,description,bug_id from t2 left join t1 on t2.program=t1.product and t2.value=t1.component where program="AAAAA";
value description bug_id
BBBBBBBBBBBBB - conversion 9
BBBBBBBBBBBBB - conversion 10
@@ -22,6 +196,7 @@ kkkkkkkkkkk lllllllllll 12
Test Procedures NULL
Documentation NULL
Host communication NULL
+select value,description,COUNT(bug_id) from t2 left join t1 on t2.program=t1.product and t2.value=t1.component where program="AAAAA" group by value;
value description COUNT(bug_id)
BBBBBBBBBBBBB - conversion 2
BBBBBBBBBBBBB - eeeeeeeee 0
@@ -30,37 +205,169 @@ Documentation 0
Host communication 0
kkkkkkkkkkk lllllllllll 3
Test Procedures 0
+drop table t1,t2;
+create table t1 (foo int);
+insert into t1 values (1);
+select 1+1, "a",count(*) from t1 where foo in (2);
1+1 a count(*)
2 a 0
+insert into t1 values (1);
+select 1+1,"a",count(*) from t1 where foo in (2);
1+1 a count(*)
2 a 0
+drop table t1;
+CREATE TABLE t1 (
+spID int(10) unsigned,
+userID int(10) unsigned,
+score smallint(5) unsigned,
+key (spid),
+key (score)
+);
+INSERT INTO t1 VALUES (1,1,1),(2,2,2),(2,1,1),(3,3,3),(4,3,3),(5,3,3);
+explain select userid,count(*) from t1 group by userid desc;
table type possible_keys key key_len ref rows Extra
t1 ALL NULL NULL NULL NULL 6 Using temporary
+select userid,count(*) from t1 group by userid desc;
userid count(*)
3 3
2 1
1 2
+explain select spid,count(*) from t1 where spid between 1 and 2 group by spid desc;
table type possible_keys key key_len ref rows Extra
-t1 range spID spID 5 NULL 2 where used; Using index; Using temporary
+t1 range spID spID 5 NULL 2 where used; Using index
+explain select spid,count(*) from t1 where spid between 1 and 2 group by spid;
table type possible_keys key key_len ref rows Extra
t1 range spID spID 5 NULL 2 where used; Using index
+select spid,count(*) from t1 where spid between 1 and 2 group by spid;
spid count(*)
1 1
2 2
+select spid,count(*) from t1 where spid between 1 and 2 group by spid desc;
spid count(*)
-2 2
-1 1
+explain select sql_big_result spid,sum(userid) from t1 group by spid desc;
table type possible_keys key key_len ref rows Extra
t1 ALL NULL NULL NULL NULL 6 Using filesort
+select sql_big_result spid,sum(userid) from t1 group by spid desc;
spid sum(userid)
5 3
4 3
3 3
2 3
1 1
+explain select sql_big_result score,count(*) from t1 group by score desc;
table type possible_keys key key_len ref rows Extra
t1 index NULL score 3 NULL 6 Using index
+select sql_big_result score,count(*) from t1 group by score desc;
score count(*)
3 3
2 1
1 2
+drop table t1;
+CREATE TABLE t1 (a char(1));
+INSERT INTO t1 VALUES ('A'),('B'),('A'),('B'),('A'),('B'),(NULL),('a'),('b'),(NULL),('A'),('B'),(NULL);
+SELECT a FROM t1 GROUP BY a;
+a
+NULL
+A
+B
+SELECT a,count(*) FROM t1 GROUP BY a;
+a count(*)
+NULL 3
+A 5
+B 5
+SELECT a FROM t1 GROUP BY binary a;
+a
+NULL
+A
+B
+a
+b
+SELECT a,count(*) FROM t1 GROUP BY binary a;
+a count(*)
+NULL 3
+A 4
+B 4
+a 1
+b 1
+SELECT binary a FROM t1 GROUP BY 1;
+binary a
+NULL
+A
+B
+a
+b
+SELECT binary a,count(*) FROM t1 GROUP BY 1;
+binary a count(*)
+NULL 3
+A 4
+B 4
+a 1
+b 1
+SET SQL_BIG_TABLES=1;
+SELECT a FROM t1 GROUP BY a;
+a
+NULL
+A
+B
+SELECT a,count(*) FROM t1 GROUP BY a;
+a count(*)
+NULL 3
+A 5
+B 5
+SELECT a FROM t1 GROUP BY binary a;
+a
+NULL
+A
+B
+a
+b
+SELECT a,count(*) FROM t1 GROUP BY binary a;
+a count(*)
+NULL 3
+A 4
+B 4
+a 1
+b 1
+SELECT binary a FROM t1 GROUP BY 1;
+binary a
+NULL
+A
+B
+a
+b
+SELECT binary a,count(*) FROM t1 GROUP BY 1;
+binary a count(*)
+NULL 3
+A 4
+B 4
+a 1
+b 1
+SET SQL_BIG_TABLES=0;
+drop table t1;
+CREATE TABLE t1 (
+`a` char(193) default NULL,
+`b` char(63) default NULL
+);
+INSERT INTO t1 VALUES ('abc','def'),('hij','klm');
+SELECT CONCAT(a, b) FROM t1 GROUP BY 1;
+CONCAT(a, b)
+abcdef
+hijklm
+SELECT CONCAT(a, b),count(*) FROM t1 GROUP BY 1;
+CONCAT(a, b) count(*)
+abcdef 1
+hijklm 1
+SELECT CONCAT(a, b),count(distinct a) FROM t1 GROUP BY 1;
+CONCAT(a, b) count(distinct a)
+abcdef 1
+hijklm 1
+SELECT 1 FROM t1 GROUP BY CONCAT(a, b);
+1
+1
+1
+INSERT INTO t1 values ('hij','klm');
+SELECT CONCAT(a, b),count(*) FROM t1 GROUP BY 1;
+CONCAT(a, b) count(*)
+abcdef 1
+hijklm 2
+DROP TABLE t1;
diff --git a/mysql-test/r/handler.result b/mysql-test/r/handler.result
new file mode 100644
index 00000000000..d495dde75bf
--- /dev/null
+++ b/mysql-test/r/handler.result
@@ -0,0 +1,139 @@
+drop table if exists t1;
+create table t1 (a int, b char(10), key a(a), key b(a,b));
+insert into t1 values
+(17,"ddd"),(18,"eee"),(19,"fff"),(19,"yyy"),
+(14,"aaa"),(15,"bbb"),(16,"ccc"),(16,"xxx"),
+(20,"ggg"),(21,"hhh"),(22,"iii");
+handler t1 open as t2;
+handler t2 read a first;
+a b
+14 aaa
+handler t2 read a next;
+a b
+15 bbb
+handler t2 read a next;
+a b
+16 ccc
+handler t2 read a prev;
+a b
+15 bbb
+handler t2 read a last;
+a b
+22 iii
+handler t2 read a prev;
+a b
+21 hhh
+handler t2 read a prev;
+a b
+20 ggg
+handler t2 read a first;
+a b
+14 aaa
+handler t2 read a prev;
+a b
+handler t2 read a last;
+a b
+22 iii
+handler t2 read a prev;
+a b
+21 hhh
+handler t2 read a next;
+a b
+22 iii
+handler t2 read a next;
+a b
+handler t2 read a=(15);
+a b
+15 bbb
+handler t2 read a=(16);
+a b
+16 ccc
+handler t2 read a=(19,"fff");
+Too many key parts specified. Max 1 parts allowed
+handler t2 read b=(19,"fff");
+a b
+19 fff
+handler t2 read b=(19,"yyy");
+a b
+19 yyy
+handler t2 read b=(19);
+a b
+19 fff
+handler t1 read a last;
+Unknown table 't1' in HANDLER
+handler t2 read a=(11);
+a b
+handler t2 read a>=(11);
+a b
+14 aaa
+handler t2 read a=(18);
+a b
+18 eee
+handler t2 read a>=(18);
+a b
+18 eee
+handler t2 read a>(18);
+a b
+19 fff
+handler t2 read a<=(18);
+a b
+18 eee
+handler t2 read a<(18);
+a b
+17 ddd
+handler t2 read a first limit 5;
+a b
+14 aaa
+15 bbb
+16 ccc
+16 xxx
+17 ddd
+handler t2 read a next limit 3;
+a b
+18 eee
+19 fff
+19 yyy
+handler t2 read a prev limit 10;
+a b
+19 fff
+18 eee
+17 ddd
+16 xxx
+16 ccc
+15 bbb
+14 aaa
+handler t2 read a>=(16) limit 4;
+a b
+16 ccc
+16 xxx
+17 ddd
+18 eee
+handler t2 read a>=(16) limit 2,2;
+a b
+17 ddd
+18 eee
+handler t2 read a last limit 3;
+a b
+22 iii
+21 hhh
+20 ggg
+handler t2 read a=(19);
+a b
+19 fff
+handler t2 read a=(19) where b="yyy";
+a b
+19 yyy
+handler t2 read first;
+a b
+17 ddd
+handler t2 read next;
+a b
+18 eee
+alter table t1 type=MyISAM;
+handler t2 read next;
+a b
+19 fff
+handler t2 read last;
+You have an error in your SQL syntax near '' at line 1
+handler t2 close;
+drop table if exists t1;
diff --git a/mysql-test/r/have_openssl.require b/mysql-test/r/have_openssl.require
new file mode 100644
index 00000000000..dae48a472b5
--- /dev/null
+++ b/mysql-test/r/have_openssl.require
@@ -0,0 +1,2 @@
+Variable_name Value
+have_openssl YES
diff --git a/mysql-test/r/have_openssl_1.require b/mysql-test/r/have_openssl_1.require
new file mode 100644
index 00000000000..dae48a472b5
--- /dev/null
+++ b/mysql-test/r/have_openssl_1.require
@@ -0,0 +1,2 @@
+Variable_name Value
+have_openssl YES
diff --git a/mysql-test/r/have_gemini.require b/mysql-test/r/have_openssl_2.require
index 0ffe0e40d3b..09a65d7d9bc 100644
--- a/mysql-test/r/have_gemini.require
+++ b/mysql-test/r/have_openssl_2.require
@@ -1,2 +1,2 @@
Variable_name Value
-have_gemini YES
+jkhjkhfs
diff --git a/mysql-test/r/have_symlink.require b/mysql-test/r/have_symlink.require
new file mode 100644
index 00000000000..55ad9437034
--- /dev/null
+++ b/mysql-test/r/have_symlink.require
@@ -0,0 +1,2 @@
+Variable_name Value
+have_symlink YES
diff --git a/mysql-test/r/having.result b/mysql-test/r/having.result
index 69943c505f0..df99f2545cb 100644
--- a/mysql-test/r/having.result
+++ b/mysql-test/r/having.result
@@ -1,6 +1,46 @@
+drop table if exists t1,t2;
+create table t1 (a int);
+select count(a) as b from t1 where a=0 having b > 0;
b
+insert into t1 values (null);
+select count(a) as b from t1 where a=0 having b > 0;
b
+select count(a) as b from t1 where a=0 having b >=0;
b
0
+drop table t1;
+CREATE TABLE t1 (
+raw_id int(10) NOT NULL default '0',
+chr_start int(10) NOT NULL default '0',
+chr_end int(10) NOT NULL default '0',
+raw_start int(10) NOT NULL default '0',
+raw_end int(10) NOT NULL default '0',
+raw_ori int(2) NOT NULL default '0'
+);
+INSERT INTO t1 VALUES (469713,1,164123,1,164123,1),(317330,164124,317193,101,153170,1),(469434,317194,375620,101,58527,1),(591816,375621,484273,1,108653,1),(591807,484274,534671,91,50488,1),(318885,534672,649362,101,114791,1),(318728,649363,775520,102,126259,1),(336829,775521,813997,101,38577,1),(317740,813998,953227,101,139330,1),(1,813998,953227,101,139330,1);
+CREATE TABLE t2 (
+id int(10) unsigned NOT NULL default '0',
+contig_id int(10) unsigned NOT NULL default '0',
+seq_start int(10) NOT NULL default '0',
+seq_end int(10) NOT NULL default '0',
+strand tinyint(2) NOT NULL default '0',
+KEY id (id)
+);
+INSERT INTO t2 VALUES (133195,469713,61327,61384,1),(133196,469713,64113,64387,1),(133197,1,1,1,0),(133197,1,1,1,-2);
+SELECT e.id,
+MIN( IF(sgp.raw_ori=1,
+(e.seq_start+sgp.chr_start-sgp.raw_start),
+(sgp.chr_start+sgp.raw_end-e.seq_end))) as start,
+MAX( IF(sgp.raw_ori=1,
+(e.seq_end+sgp.chr_start-sgp.raw_start),
+(sgp.chr_start+sgp.raw_end-e.seq_start))) as end,
+AVG(IF (sgp.raw_ori=1,e.strand,(-e.strand))) as chr_strand
+FROM t1 sgp,
+t2 e
+WHERE sgp.raw_id=e.contig_id
+GROUP BY e.id
+HAVING chr_strand= -1 and end >= 0
+AND start <= 999660;
id start end chr_strand
133197 813898 813898 -1.0000
+drop table t1,t2;
diff --git a/mysql-test/r/heap.result b/mysql-test/r/heap.result
index d3d16128ebd..fc4a116307e 100644
--- a/mysql-test/r/heap.result
+++ b/mysql-test/r/heap.result
@@ -1,41 +1,75 @@
-Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Comment
-t1 0 PRIMARY 1 a NULL NULL NULL NULL
+drop table if exists t1;
+create table t1 (a int not null,b int not null, primary key (a)) type=heap comment="testing heaps" avg_row_length=100 min_rows=1 max_rows=100;
+insert into t1 values(1,1),(2,2),(3,3),(4,4);
+delete from t1 where a=1 or a=0;
+show keys from t1;
+Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
+t1 0 PRIMARY 1 a NULL NULL NULL NULL HASH
+select * from t1;
a b
2 2
3 3
4 4
+select * from t1 where a=4;
a b
4 4
+update t1 set b=5 where a=4;
+update t1 set b=b+1 where a>=3;
+replace t1 values (3,3);
+select * from t1;
a b
2 2
3 3
4 6
+alter table t1 add c int not null, add key (c,a);
+drop table t1;
+create table t1 (a int not null,b int not null, primary key (a)) type=heap comment="testing heaps";
+insert into t1 values(1,1),(2,2),(3,3),(4,4);
+alter table t1 modify a int not null auto_increment, type=myisam, comment="new myisam table";
+select * from t1;
a b
1 1
2 2
3 3
4 4
+drop table t1;
+create table t1 (a int not null) type=heap;
+insert into t1 values (869751),(736494),(226312),(802616);
+select * from t1 where a > 736494;
a
869751
802616
+alter table t1 add unique uniq_id(a);
+select * from t1 where a > 736494;
a
869751
802616
+select * from t1 where a = 736494;
a
736494
+select * from t1 where a=869751 or a=736494;
a
736494
869751
+select * from t1 where a in (869751,736494,226312,802616);
a
226312
736494
802616
869751
+alter table t1 type=myisam;
+explain select * from t1 where a in (869751,736494,226312,802616);
table type possible_keys key key_len ref rows Extra
t1 range uniq_id uniq_id 4 NULL 4 where used; Using index
+drop table t1;
+create table t1 (x int not null, y int not null, key x(x), unique y(y))
+type=heap;
+insert into t1 values (1,1),(2,2),(1,3),(2,4),(2,5),(2,6);
+select * from t1 where x=1;
x y
1 3
1 1
+select * from t1,t1 as t2 where t1.x=t2.y;
x y x y
1 1 1 1
2 2 2 2
@@ -43,11 +77,20 @@ x y x y
2 4 2 2
2 5 2 2
2 6 2 2
+explain select * from t1,t1 as t2 where t1.x=t2.y;
table type possible_keys key key_len ref rows Extra
t1 ALL x NULL NULL NULL 6
t2 eq_ref y y 4 t1.x 1
+drop table t1;
+create table t1 (a int) type=heap;
+insert into t1 values(1);
+select max(a) from t1;
max(a)
1
+drop table t1;
+CREATE TABLE t1 ( a int not null default 0, b int not null default 0, key(a), key(b) ) TYPE=HEAP;
+insert into t1 values(1,1),(1,2),(2,3),(1,3),(1,4),(1,5),(1,6);
+select * from t1 where a=1;
a b
1 6
1 5
@@ -55,6 +98,8 @@ a b
1 3
1 2
1 1
+insert into t1 values(1,1),(1,2),(2,3),(1,3),(1,4),(1,5),(1,6);
+select * from t1 where a=1;
a b
1 6
1 5
@@ -68,20 +113,81 @@ a b
1 3
1 2
1 1
+drop table t1;
+create table t1 (id int unsigned not null, primary key (id)) type=HEAP;
+insert into t1 values(1);
+select max(id) from t1;
max(id)
1
+insert into t1 values(2);
+select max(id) from t1;
max(id)
2
+replace into t1 values(1);
+drop table t1;
+create table t1 (n int) type=heap;
+drop table t1;
+create table t1 (n int) type=heap;
+drop table if exists t1;
+CREATE table t1(f1 int not null,f2 char(20) not
+null,index(f2)) type=heap;
+INSERT into t1 set f1=12,f2="bill";
+INSERT into t1 set f1=13,f2="bill";
+INSERT into t1 set f1=14,f2="bill";
+INSERT into t1 set f1=15,f2="bill";
+INSERT into t1 set f1=16,f2="ted";
+INSERT into t1 set f1=12,f2="ted";
+INSERT into t1 set f1=12,f2="ted";
+INSERT into t1 set f1=12,f2="ted";
+INSERT into t1 set f1=12,f2="ted";
+delete from t1 where f2="bill";
+select * from t1;
f1 f2
16 ted
12 ted
12 ted
12 ted
12 ted
+drop table t1;
+create table t1 (btn char(10) not null, key(btn)) type=heap;
+insert into t1 values ("hello"),("hello"),("hello"),("hello"),("hello"),("a"),("b"),("c"),("d"),("e"),("f"),("g"),("h"),("i");
+explain select * from t1 where btn like "q%";
table type possible_keys key key_len ref rows Extra
t1 ALL btn NULL NULL NULL 14 where used
+select * from t1 where btn like "q%";
btn
+alter table t1 add column new_col char(1) not null, add key (btn,new_col), drop key btn;
+update t1 set new_col=btn;
+explain select * from t1 where btn="a";
table type possible_keys key key_len ref rows Extra
t1 ALL btn NULL NULL NULL 14 where used
+explain select * from t1 where btn="a" and new_col="a";
table type possible_keys key key_len ref rows Extra
t1 ref btn btn 11 const,const 10 where used
+drop table t1;
+CREATE TABLE t1 (
+a int default NULL,
+b int default NULL,
+KEY a (a),
+UNIQUE b (b)
+) type=heap;
+INSERT INTO t1 VALUES (NULL,99),(99,NULL),(1,1),(2,2),(1,3);
+SELECT * FROM t1 WHERE a=NULL;
+a b
+explain SELECT * FROM t1 WHERE a IS NULL;
+table type possible_keys key key_len ref rows Extra
+t1 ref a a 5 const 10 where used
+SELECT * FROM t1 WHERE a<=>NULL;
+a b
+NULL 99
+SELECT * FROM t1 WHERE b=NULL;
+a b
+explain SELECT * FROM t1 WHERE b IS NULL;
+table type possible_keys key key_len ref rows Extra
+t1 ref b b 5 const 1 where used
+SELECT * FROM t1 WHERE b<=>NULL;
+a b
+99 NULL
+INSERT INTO t1 VALUES (1,3);
+Duplicate entry '3' for key 1
+DROP TABLE t1;
diff --git a/mysql-test/r/identity.result b/mysql-test/r/identity.result
index 45968248d26..39123e9c127 100644
--- a/mysql-test/r/identity.result
+++ b/mysql-test/r/identity.result
@@ -1,4 +1,6 @@
+select last_insert_id(345);
last_insert_id(345)
345
+select @@IDENTITY,last_insert_id();
@@IDENTITY last_insert_id()
345 345
diff --git a/mysql-test/r/innodb.result b/mysql-test/r/innodb.result
index d13347b7903..1c5e4165885 100644
--- a/mysql-test/r/innodb.result
+++ b/mysql-test/r/innodb.result
@@ -1,3 +1,7 @@
+drop table if exists t1,t2;
+create table t1 (id int unsigned not null auto_increment, code tinyint unsigned not null, name char(20) not null, primary key (id), key (code), unique (name)) type=innodb;
+insert into t1 (code, name) values (1, 'Tim'), (1, 'Monty'), (2, 'David'), (2, 'Erik'), (3, 'Sasha'), (3, 'Jeremy'), (4, 'Matt');
+select id, code, name from t1 order by id;
id code name
1 1 Tim
2 1 Monty
@@ -6,6 +10,8 @@ id code name
5 3 Sasha
6 3 Jeremy
7 4 Matt
+update ignore t1 set id = 8, name = 'Sinisa' where id < 3;
+select id, code, name from t1 order by id;
id code name
2 1 Monty
3 2 David
@@ -14,6 +20,8 @@ id code name
6 3 Jeremy
7 4 Matt
8 1 Sinisa
+update ignore t1 set id = id + 10, name = 'Ralph' where id < 4;
+select id, code, name from t1 order by id;
id code name
3 2 David
4 2 Erik
@@ -22,10 +30,26 @@ id code name
7 4 Matt
8 1 Sinisa
12 1 Ralph
+drop table t1;
+CREATE TABLE t1 (
+id int(11) NOT NULL auto_increment,
+parent_id int(11) DEFAULT '0' NOT NULL,
+level tinyint(4) DEFAULT '0' NOT NULL,
+PRIMARY KEY (id),
+KEY parent_id (parent_id),
+KEY level (level)
+) type=innodb;
+INSERT INTO t1 VALUES (1,0,0),(3,1,1),(4,1,1),(8,2,2),(9,2,2),(17,3,2),(22,4,2),(24,4,2),(28,5,2),(29,5,2),(30,5,2),(31,6,2),(32,6,2),(33,6,2),(203,7,2),(202,7,2),(20,3,2),(157,0,0),(193,5,2),(40,7,2),(2,1,1),(15,2,2),(6,1,1),(34,6,2),(35,6,2),(16,3,2),(7,1,1),(36,7,2),(18,3,2),(26,5,2),(27,5,2),(183,4,2),(38,7,2),(25,5,2),(37,7,2),(21,4,2),(19,3,2),(5,1,1),(179,5,2);
+update t1 set parent_id=parent_id+100;
+select * from t1 where parent_id=102;
id parent_id level
8 102 2
9 102 2
15 102 2
+update t1 set id=id+1000;
+update t1 set id=1024 where id=1009;
+Got one of the listed errors
+select * from t1;
id parent_id level
1001 100 0
1002 101 1
@@ -66,6 +90,8 @@ id parent_id level
1193 105 2
1202 107 2
1203 107 2
+update ignore t1 set id=id+1;
+select * from t1;
id parent_id level
1001 100 0
1002 101 1
@@ -106,16 +132,22 @@ id parent_id level
1194 105 2
1202 107 2
1204 107 2
+update ignore t1 set id=1023 where id=1010;
+select * from t1 where parent_id=102;
id parent_id level
1008 102 2
1010 102 2
1015 102 2
+explain select level from t1 where level=1;
table type possible_keys key key_len ref rows Extra
t1 ref level level 1 const 12 where used; Using index
+explain select level,id from t1 where level=1;
table type possible_keys key key_len ref rows Extra
t1 ref level level 1 const 12 where used; Using index
+explain select level,id,parent_id from t1 where level=1;
table type possible_keys key key_len ref rows Extra
t1 ref level level 1 const 12 where used
+select level,id from t1 where level=1;
level id
1 1002
1 1003
@@ -123,6 +155,7 @@ level id
1 1005
1 1006
1 1007
+select level,id,parent_id from t1 where level=1;
level id parent_id
1 1002 101
1 1003 101
@@ -130,142 +163,350 @@ level id parent_id
1 1005 101
1 1006 101
1 1007 101
+optimize table t1;
Table Op Msg_type Msg_text
test.t1 optimize error The handler for the table doesn't support check/repair
-Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Comment
-t1 0 PRIMARY 1 id A 87 NULL NULL
-t1 1 parent_id 1 parent_id A 43 NULL NULL
-t1 1 level 1 level A 8 NULL NULL
+show keys from t1;
+Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
+t1 0 PRIMARY 1 id A 87 NULL NULL BTREE
+t1 1 parent_id 1 parent_id A 43 NULL NULL BTREE
+t1 1 level 1 level A 8 NULL NULL BTREE
+drop table t1;
+CREATE TABLE t1 (
+gesuchnr int(11) DEFAULT '0' NOT NULL,
+benutzer_id int(11) DEFAULT '0' NOT NULL,
+PRIMARY KEY (gesuchnr,benutzer_id)
+) type=innodb;
+replace into t1 (gesuchnr,benutzer_id) values (2,1);
+replace into t1 (gesuchnr,benutzer_id) values (1,1);
+replace into t1 (gesuchnr,benutzer_id) values (1,1);
+select * from t1;
gesuchnr benutzer_id
1 1
2 1
+drop table t1;
+create table t1 (a int) type=innodb;
+insert into t1 values (1), (2);
+optimize table t1;
Table Op Msg_type Msg_text
test.t1 optimize error The handler for the table doesn't support check/repair
+delete from t1 where a = 1;
+select * from t1;
a
2
+check table t1;
Table Op Msg_type Msg_text
test.t1 check status OK
+drop table t1;
+create table t1 (a int,b varchar(20)) type=innodb;
+insert into t1 values (1,""), (2,"testing");
+delete from t1 where a = 1;
+select * from t1;
a b
2 testing
+create index skr on t1 (a);
+insert into t1 values (3,""), (4,"testing");
+analyze table t1;
Table Op Msg_type Msg_text
test.t1 analyze error The handler for the table doesn't support check/repair
-Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Comment
-t1 1 skr 1 a A 3 NULL NULL
+show keys from t1;
+Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
+t1 1 skr 1 a A 3 NULL NULL YES BTREE
+drop table t1;
+create table t1 (a int,b varchar(20),key(a)) type=innodb;
+insert into t1 values (1,""), (2,"testing");
+select * from t1 where a = 1;
a b
1
+drop table t1;
+create table t1 (n int not null primary key) type=innodb;
+set autocommit=0;
+insert into t1 values (4);
+rollback;
+select n, "after rollback" from t1;
n after rollback
+insert into t1 values (4);
+commit;
+select n, "after commit" from t1;
n after commit
4 after commit
+commit;
+insert into t1 values (5);
+insert into t1 values (4);
+Duplicate entry '4' for key 1
+commit;
+select n, "after commit" from t1;
n after commit
4 after commit
5 after commit
+set autocommit=1;
+insert into t1 values (6);
+insert into t1 values (4);
+Duplicate entry '4' for key 1
+select n from t1;
n
4
5
6
+rollback;
+drop table t1;
+create table t1 ( id int NOT NULL PRIMARY KEY, nom varchar(64)) type=innodb;
+begin;
+insert into t1 values(1,'hamdouni');
+select id as afterbegin_id,nom as afterbegin_nom from t1;
afterbegin_id afterbegin_nom
1 hamdouni
+rollback;
+select id as afterrollback_id,nom as afterrollback_nom from t1;
afterrollback_id afterrollback_nom
+set autocommit=0;
+insert into t1 values(2,'mysql');
+select id as afterautocommit0_id,nom as afterautocommit0_nom from t1;
afterautocommit0_id afterautocommit0_nom
2 mysql
+rollback;
+select id as afterrollback_id,nom as afterrollback_nom from t1;
afterrollback_id afterrollback_nom
+set autocommit=1;
+drop table t1;
+CREATE TABLE t1 (id char(8) not null primary key, val int not null) type=innodb;
+insert into t1 values ('pippo', 12);
+insert into t1 values ('pippo', 12);
+Duplicate entry 'pippo' for key 1
+delete from t1;
+delete from t1 where id = 'pippo';
+select * from t1;
id val
+insert into t1 values ('pippo', 12);
+set autocommit=0;
+delete from t1;
+rollback;
+select * from t1;
id val
pippo 12
+delete from t1;
+commit;
+select * from t1;
id val
+drop table t1;
+create table t1 (a integer) type=innodb;
+begin;
+rename table t1 to t2;
+create table t1 (b integer) type=innodb;
+insert into t1 values (1);
+rollback;
+drop table t1;
+rename table t2 to t1;
+drop table t1;
+set autocommit=1;
+CREATE TABLE t1 (ID INTEGER NOT NULL PRIMARY KEY, NAME VARCHAR(64)) TYPE=innodb;
+INSERT INTO t1 VALUES (1, 'Jochen');
+select * from t1;
ID NAME
1 Jochen
+drop table t1;
+CREATE TABLE t1 ( _userid VARCHAR(60) NOT NULL PRIMARY KEY) TYPE=innodb;
+set autocommit=0;
+INSERT INTO t1 SET _userid='marc@anyware.co.uk';
+COMMIT;
+SELECT * FROM t1;
_userid
marc@anyware.co.uk
+SELECT _userid FROM t1 WHERE _userid='marc@anyware.co.uk';
_userid
marc@anyware.co.uk
+drop table t1;
+set autocommit=1;
+CREATE TABLE t1 (
+user_id int(10) DEFAULT '0' NOT NULL,
+name varchar(100),
+phone varchar(100),
+ref_email varchar(100) DEFAULT '' NOT NULL,
+detail varchar(200),
+PRIMARY KEY (user_id,ref_email)
+)type=innodb;
+INSERT INTO t1 VALUES (10292,'sanjeev','29153373','sansh777@hotmail.com','xxx'),(10292,'shirish','2333604','shirish@yahoo.com','ddsds'),(10292,'sonali','323232','sonali@bolly.com','filmstar');
+select * from t1 where user_id=10292;
user_id name phone ref_email detail
10292 sanjeev 29153373 sansh777@hotmail.com xxx
10292 shirish 2333604 shirish@yahoo.com ddsds
10292 sonali 323232 sonali@bolly.com filmstar
+INSERT INTO t1 VALUES (10291,'sanjeev','29153373','sansh777@hotmail.com','xxx'),(10293,'shirish','2333604','shirish@yahoo.com','ddsds');
+select * from t1 where user_id=10292;
user_id name phone ref_email detail
10292 sanjeev 29153373 sansh777@hotmail.com xxx
10292 shirish 2333604 shirish@yahoo.com ddsds
10292 sonali 323232 sonali@bolly.com filmstar
+select * from t1 where user_id>=10292;
user_id name phone ref_email detail
10292 sanjeev 29153373 sansh777@hotmail.com xxx
10292 shirish 2333604 shirish@yahoo.com ddsds
10292 sonali 323232 sonali@bolly.com filmstar
10293 shirish 2333604 shirish@yahoo.com ddsds
+select * from t1 where user_id>10292;
user_id name phone ref_email detail
10293 shirish 2333604 shirish@yahoo.com ddsds
+select * from t1 where user_id<10292;
user_id name phone ref_email detail
10291 sanjeev 29153373 sansh777@hotmail.com xxx
-Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Comment
-t1 0 PRIMARY 1 a A NULL NULL NULL
-t1 0 PRIMARY 2 b A 0 NULL NULL
-t1 0 b 1 b A 0 NULL NULL
-t1 0 c 1 c A 0 NULL NULL
-t1 1 a 1 a A NULL NULL NULL
-t1 1 a_2 1 a A NULL NULL NULL
+drop table t1;
+CREATE TABLE t1 (a int not null, b int not null,c int not null,
+key(a),primary key(a,b), unique(c),key(a),unique(b));
+show index from t1;
+Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
+t1 0 PRIMARY 1 a A NULL NULL NULL BTREE
+t1 0 PRIMARY 2 b A 0 NULL NULL BTREE
+t1 0 c 1 c A 0 NULL NULL BTREE
+t1 0 b 1 b A 0 NULL NULL BTREE
+t1 1 a 1 a A NULL NULL NULL BTREE
+t1 1 a_2 1 a A NULL NULL NULL BTREE
+drop table t1;
+create table t1 (col1 int not null, col2 char(4) not null, primary key(col1));
+alter table t1 type=innodb;
+insert into t1 values ('1','1'),('5','2'),('2','3'),('3','4'),('4','4');
+select * from t1;
col1 col2
1 1
2 3
3 4
4 4
5 2
+update t1 set col2='7' where col1='4';
+select * from t1;
col1 col2
1 1
2 3
3 4
4 7
5 2
+alter table t1 add co3 int not null;
+select * from t1;
col1 col2 co3
1 1 0
2 3 0
3 4 0
4 7 0
5 2 0
+update t1 set col2='9' where col1='2';
+select * from t1;
col1 col2 co3
1 1 0
2 9 0
3 4 0
4 7 0
5 2 0
+drop table t1;
+create table t1 (a int not null , b int, primary key (a)) type = innodb;
+create table t2 (a int not null , b int, primary key (a)) type = myisam;
+insert into t1 VALUES (1,3) , (2,3), (3,3);
+select * from t1;
a b
1 3
2 3
3 3
+insert into t2 select * from t1;
+select * from t2;
a b
1 3
2 3
3 3
+delete from t1 where b = 3;
+select * from t1;
a b
+insert into t1 select * from t2;
+select * from t1;
a b
1 3
2 3
3 3
+select * from t2;
a b
1 3
2 3
3 3
+drop table t1,t2;
+CREATE TABLE t1 (
+id int(11) NOT NULL auto_increment,
+ggid varchar(32) binary DEFAULT '' NOT NULL,
+email varchar(64) DEFAULT '' NOT NULL,
+passwd varchar(32) binary DEFAULT '' NOT NULL,
+PRIMARY KEY (id),
+UNIQUE ggid (ggid)
+) TYPE=innodb;
+insert into t1 (ggid,passwd) values ('test1','xxx');
+insert into t1 (ggid,passwd) values ('test2','yyy');
+insert into t1 (ggid,passwd) values ('test2','this will fail');
+Duplicate entry 'test2' for key 2
+insert into t1 (ggid,id) values ('this will fail',1);
+Duplicate entry '1' for key 1
+select * from t1 where ggid='test1';
id ggid email passwd
1 test1 xxx
+select * from t1 where passwd='xxx';
id ggid email passwd
1 test1 xxx
+select * from t1 where id=2;
id ggid email passwd
2 test2 yyy
+replace into t1 (ggid,id) values ('this will work',1);
+replace into t1 (ggid,passwd) values ('test2','this will work');
+update t1 set id=100,ggid='test2' where id=1;
+Duplicate entry 'test2' for key 2
+select * from t1;
id ggid email passwd
1 this will work
4 test2 this will work
+select * from t1 where id=1;
id ggid email passwd
1 this will work
+select * from t1 where id=999;
id ggid email passwd
+drop table t1;
+CREATE TABLE t1 (
+user_name varchar(12),
+password text,
+subscribed char(1),
+user_id int(11) DEFAULT '0' NOT NULL,
+quota bigint(20),
+weight double,
+access_date date,
+access_time time,
+approved datetime,
+dummy_primary_key int(11) NOT NULL auto_increment,
+PRIMARY KEY (dummy_primary_key)
+) TYPE=innodb;
+INSERT INTO t1 VALUES ('user_0','somepassword','N',0,0,0,'2000-09-07','23:06:59','2000-09-07 23:06:59',1);
+INSERT INTO t1 VALUES ('user_1','somepassword','Y',1,1,1,'2000-09-07','23:06:59','2000-09-07 23:06:59',2);
+INSERT INTO t1 VALUES ('user_2','somepassword','N',2,2,1.4142135623731,'2000-09-07','23:06:59','2000-09-07 23:06:59',3);
+INSERT INTO t1 VALUES ('user_3','somepassword','Y',3,3,1.7320508075689,'2000-09-07','23:06:59','2000-09-07 23:06:59',4);
+INSERT INTO t1 VALUES ('user_4','somepassword','N',4,4,2,'2000-09-07','23:06:59','2000-09-07 23:06:59',5);
+select user_name, password , subscribed, user_id, quota, weight, access_date, access_time, approved, dummy_primary_key from t1 order by user_name;
user_name password subscribed user_id quota weight access_date access_time approved dummy_primary_key
user_0 somepassword N 0 0 0 2000-09-07 23:06:59 2000-09-07 23:06:59 1
user_1 somepassword Y 1 1 1 2000-09-07 23:06:59 2000-09-07 23:06:59 2
user_2 somepassword N 2 2 1.4142135623731 2000-09-07 23:06:59 2000-09-07 23:06:59 3
user_3 somepassword Y 3 3 1.7320508075689 2000-09-07 23:06:59 2000-09-07 23:06:59 4
user_4 somepassword N 4 4 2 2000-09-07 23:06:59 2000-09-07 23:06:59 5
+drop table t1;
+CREATE TABLE t1 (
+id int(11) NOT NULL auto_increment,
+parent_id int(11) DEFAULT '0' NOT NULL,
+level tinyint(4) DEFAULT '0' NOT NULL,
+KEY (id),
+KEY parent_id (parent_id),
+KEY level (level)
+) type=innodb;
+INSERT INTO t1 VALUES (1,0,0),(3,1,1),(4,1,1),(8,2,2),(9,2,2),(17,3,2),(22,4,2),(24,4,2),(28,5,2),(29,5,2),(30,5,2),(31,6,2),(32,6,2),(33,6,2),(203,7,2),(202,7,2),(20,3,2),(157,0,0),(193,5,2),(40,7,2),(2,1,1),(15,2,2),(6,1,1),(34,6,2),(35,6,2),(16,3,2),(7,1,1),(36,7,2),(18,3,2),(26,5,2),(27,5,2),(183,4,2),(38,7,2),(25,5,2),(37,7,2),(21,4,2),(19,3,2),(5,1,1);
+INSERT INTO t1 values (179,5,2);
+update t1 set parent_id=parent_id+100;
+select * from t1 where parent_id=102;
id parent_id level
8 102 2
9 102 2
15 102 2
+update t1 set id=id+1000;
+update t1 set id=1024 where id=1009;
+select * from t1;
id parent_id level
1001 100 0
1003 101 1
@@ -306,6 +547,8 @@ id parent_id level
1019 103 2
1005 101 1
1179 105 2
+update ignore t1 set id=id+1;
+select * from t1;
id parent_id level
1002 100 0
1004 101 1
@@ -346,12 +589,16 @@ id parent_id level
1020 103 2
1006 101 1
1180 105 2
+update ignore t1 set id=1023 where id=1010;
+select * from t1 where parent_id=102;
id parent_id level
1009 102 2
1025 102 2
1016 102 2
+explain select level from t1 where level=1;
table type possible_keys key key_len ref rows Extra
t1 ref level level 1 const 6 where used; Using index
+select level,id from t1 where level=1;
level id
1 1004
1 1005
@@ -359,6 +606,7 @@ level id
1 1007
1 1008
1 1006
+select level,id,parent_id from t1 where level=1;
level id parent_id
1 1004 101
1 1005 101
@@ -366,6 +614,7 @@ level id parent_id
1 1007 101
1 1008 101
1 1006 101
+select level,id from t1 where level=1 order by id;
level id
1 1003
1 1004
@@ -373,6 +622,8 @@ level id
1 1006
1 1007
1 1008
+delete from t1 where level=1;
+select * from t1;
id parent_id level
1002 100 0
1009 102 2
@@ -407,97 +658,334 @@ id parent_id level
1022 104 2
1020 103 2
1180 105 2
+drop table t1;
+CREATE TABLE t1 (
+sca_code char(6) NOT NULL,
+cat_code char(6) NOT NULL,
+sca_desc varchar(50),
+lan_code char(2) NOT NULL,
+sca_pic varchar(100),
+sca_sdesc varchar(50),
+sca_sch_desc varchar(16),
+PRIMARY KEY (sca_code, cat_code, lan_code),
+INDEX sca_pic (sca_pic)
+) type = innodb ;
+INSERT INTO t1 ( sca_code, cat_code, sca_desc, lan_code, sca_pic, sca_sdesc, sca_sch_desc) VALUES ( 'PD', 'J', 'PENDANT', 'EN', NULL, NULL, 'PENDANT'),( 'RI', 'J', 'RING', 'EN', NULL, NULL, 'RING'),( 'QQ', 'N', 'RING', 'EN', 'not null', NULL, 'RING');
+select count(*) from t1 where sca_code = 'PD';
count(*)
1
+select count(*) from t1 where sca_code <= 'PD';
count(*)
1
+select count(*) from t1 where sca_pic is null;
count(*)
2
+alter table t1 drop index sca_pic, add index sca_pic (cat_code, sca_pic);
+select count(*) from t1 where sca_code='PD' and sca_pic is null;
count(*)
1
+select count(*) from t1 where cat_code='E';
count(*)
0
+alter table t1 drop index sca_pic, add index (sca_pic, cat_code);
+select count(*) from t1 where sca_code='PD' and sca_pic is null;
count(*)
1
+select count(*) from t1 where sca_pic >= 'n';
count(*)
1
+select sca_pic from t1 where sca_pic is null;
sca_pic
NULL
NULL
+update t1 set sca_pic="test" where sca_pic is null;
+delete from t1 where sca_code='pd';
+drop table t1;
+set @a:=now();
+CREATE TABLE t1 (a int not null, b timestamp not null, primary key (a)) type=innodb;
+insert into t1 (a) values(1),(2),(3);
+select t1.a from t1 natural join t1 as t2 where t1.b >= @a order by t1.a;
a
1
2
3
+update t1 set a=5 where a=1;
+select a from t1;
a
2
3
5
+drop table t1;
+create table t1 (a varchar(100) not null, primary key(a), b int not null) type=innodb;
+insert into t1 values("hello",1),("world",2);
+select * from t1 order by b desc;
a b
world 2
hello 1
+optimize table t1;
Table Op Msg_type Msg_text
test.t1 optimize error The handler for the table doesn't support check/repair
-Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Comment
-t1 0 PRIMARY 1 a A 2 NULL NULL
+show keys from t1;
+Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
+t1 0 PRIMARY 1 a A 2 NULL NULL BTREE
+drop table t1;
+create table t1 (i int, j int ) TYPE=innodb;
+insert into t1 values (1,2);
+select * from t1 where i=1 and j=2;
i j
1 2
+create index ax1 on t1 (i,j);
+select * from t1 where i=1 and j=2;
i j
1 2
+drop table t1;
+CREATE TABLE t1 (
+a int3 unsigned NOT NULL,
+b int1 unsigned NOT NULL,
+UNIQUE (a, b)
+) TYPE = innodb;
+INSERT INTO t1 VALUES (1, 1);
+SELECT MIN(B),MAX(b) FROM t1 WHERE t1.a = 1;
MIN(B) MAX(b)
1 1
+drop table t1;
+CREATE TABLE t1 (a int unsigned NOT NULL) type=innodb;
+INSERT INTO t1 VALUES (1);
+SELECT * FROM t1;
a
1
+DROP TABLE t1;
+create table t1 (a int primary key,b int, c int, d int, e int, f int, g int, h int, i int, j int, k int, l int, m int, n int, o int, p int, q int, r int, s int, t int, u int, v int, w int, x int, y int, z int, a1 int, a2 int, a3 int, a4 int, a5 int, a6 int, a7 int, a8 int, a9 int, b1 int, b2 int, b3 int, b4 int, b5 int, b6 int) type = innodb;
+insert into t1 values (1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1);
+explain select * from t1 where a > 0 and a < 50;
table type possible_keys key key_len ref rows Extra
t1 range PRIMARY PRIMARY 4 NULL 1 where used
+drop table t1;
+create table t1 (id int NOT NULL,id2 int NOT NULL,id3 int NOT NULL,dummy1 char(30),primary key (id,id2),index index_id3 (id3)) type=innodb;
+insert into t1 values (0,0,0,'ABCDEFGHIJ'),(2,2,2,'BCDEFGHIJK'),(1,1,1,'CDEFGHIJKL');
+LOCK TABLES t1 WRITE;
+insert into t1 values (99,1,2,'D'),(1,1,2,'D');
+Duplicate entry '1-1' for key 1
+select id from t1;
id
0
1
2
+select id from t1;
id
0
1
2
+UNLOCK TABLES;
+DROP TABLE t1;
+create table t1 (id int NOT NULL,id2 int NOT NULL,id3 int NOT NULL,dummy1 char(30),primary key (id,id2),index index_id3 (id3)) type=innodb;
+insert into t1 values (0,0,0,'ABCDEFGHIJ'),(2,2,2,'BCDEFGHIJK'),(1,1,1,'CDEFGHIJKL');
+LOCK TABLES t1 WRITE;
+begin;
+insert into t1 values (99,1,2,'D'),(1,1,2,'D');
+Duplicate entry '1-1' for key 1
+select id from t1;
id
0
1
2
+insert ignore into t1 values (100,1,2,'D'),(1,1,99,'D');
+commit;
+select id,id3 from t1;
id id3
0 0
1 1
2 2
100 2
+UNLOCK TABLES;
+DROP TABLE t1;
+create table t1 (a char(20), unique (a(5))) type=innodb;
+Incorrect sub part key. The used key part isn't a string, the used length is longer than the key part or the table handler doesn't support unique sub keys
+create table t1 (a char(20), index (a(5))) type=innodb;
+show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` char(20) default NULL,
KEY `a` (`a`)
) TYPE=InnoDB
+drop table t1;
+create temporary table t1 (a int not null auto_increment, primary key(a)) type=innodb;
+insert into t1 values (NULL),(NULL),(NULL);
+delete from t1 where a=3;
+insert into t1 values (NULL);
+select * from t1;
a
1
2
4
+alter table t1 add b int;
+select * from t1;
a b
1 NULL
2 NULL
4 NULL
+drop table t1;
+create table t1
+(
+id int auto_increment primary key,
+name varchar(32) not null,
+value text not null,
+uid int not null,
+unique key(name,uid)
+) type=innodb;
+insert into t1 values (1,'one','one value',101),
+(2,'two','two value',102),(3,'three','three value',103);
+set insert_id=5;
+replace into t1 (value,name,uid) values ('other value','two',102);
+delete from t1 where uid=102;
+set insert_id=5;
+replace into t1 (value,name,uid) values ('other value','two',102);
+set insert_id=6;
+replace into t1 (value,name,uid) values ('other value','two',102);
+select * from t1;
id name value uid
1 one one value 101
3 three three value 103
6 two other value 102
+drop table t1;
+create database mysqltest;
+create table mysqltest.t1 (a int not null) type= innodb;
+insert into mysqltest.t1 values(1);
+create table mysqltest.t2 (a int not null) type= myisam;
+insert into mysqltest.t2 values(1);
+create table mysqltest.t3 (a int not null) type= heap;
+insert into mysqltest.t3 values(1);
+commit;
+drop database mysqltest;
+show tables from mysqltest;
+Got one of the listed errors
+set autocommit=0;
+create table t1 (a int not null) type= innodb;
+insert into t1 values(1),(2);
+truncate table t1;
+Can't execute the given command because you have active locked tables or an active transaction
+commit;
+truncate table t1;
+select * from t1;
+a
+insert into t1 values(1),(2);
+delete from t1;
+select * from t1;
+a
+commit;
+drop table t1;
+set autocommit=1;
+create table t1 (a int not null) type= innodb;
+insert into t1 values(1),(2);
+truncate table t1;
+insert into t1 values(1),(2);
+select * from t1;
+a
+1
+2
+truncate table t1;
+insert into t1 values(1),(2);
+delete from t1;
+select * from t1;
+a
+drop table t1;
+create table t1 (a int not null, b int not null, c int not null, primary key (a),key(b)) type=innodb;
+insert into t1 values (3,3,3),(1,1,1),(2,2,2),(4,4,4);
+explain select * from t1 order by a;
table type possible_keys key key_len ref rows Extra
t1 index NULL PRIMARY 4 NULL 4
+explain select * from t1 order by b;
table type possible_keys key key_len ref rows Extra
t1 index NULL b 4 NULL 4
+explain select * from t1 order by c;
table type possible_keys key key_len ref rows Extra
t1 ALL NULL NULL NULL NULL 4 Using filesort
+explain select a from t1 order by a;
table type possible_keys key key_len ref rows Extra
t1 index NULL PRIMARY 4 NULL 4 Using index
+explain select b from t1 order by b;
table type possible_keys key key_len ref rows Extra
t1 index NULL b 4 NULL 4 Using index
+explain select a,b from t1 order by b;
table type possible_keys key key_len ref rows Extra
t1 index NULL b 4 NULL 4 Using index
+explain select a,b from t1;
table type possible_keys key key_len ref rows Extra
t1 index NULL b 4 NULL 4 Using index
+explain select a,b,c from t1;
table type possible_keys key key_len ref rows Extra
t1 ALL NULL NULL NULL NULL 4
+drop table t1;
+create table t1 (t int not null default 1, key (t)) type=innodb;
+desc t1;
Field Type Null Key Default Extra
-testint int(11) 1
+t int(11) MUL 1
+handler t1 open t1;
+Table handler for 't1' doesn't have this option
+handler t1 read t first;
+Unknown table 't1' in HANDLER
+handler t1 close;
+Unknown table 't1' in HANDLER
+drop table t1;
+CREATE TABLE t1 (
+number bigint(20) NOT NULL default '0',
+cname char(15) NOT NULL default '',
+carrier_id smallint(6) NOT NULL default '0',
+privacy tinyint(4) NOT NULL default '0',
+last_mod_date timestamp(14) NOT NULL,
+last_mod_id smallint(6) NOT NULL default '0',
+last_app_date timestamp(14) NOT NULL,
+last_app_id smallint(6) default '-1',
+version smallint(6) NOT NULL default '0',
+assigned_scps int(11) default '0',
+status tinyint(4) default '0'
+) TYPE=InnoDB;
+INSERT INTO t1 VALUES (4077711111,'SeanWheeler',90,2,20020111112846,500,00000000000000,-1,2,3,1);
+INSERT INTO t1 VALUES (9197722223,'berry',90,3,20020111112809,500,20020102114532,501,4,10,0);
+INSERT INTO t1 VALUES (650,'San Francisco',0,0,20011227111336,342,00000000000000,-1,1,24,1);
+INSERT INTO t1 VALUES (302467,'Sue\'s Subshop',90,3,20020109113241,500,20020102115111,501,7,24,0);
+INSERT INTO t1 VALUES (6014911113,'SudzCarwash',520,1,20020102115234,500,20020102115259,501,33,32768,0);
+INSERT INTO t1 VALUES (333,'tubs',99,2,20020109113440,501,20020109113440,500,3,10,0);
+CREATE TABLE t2 (
+number bigint(20) NOT NULL default '0',
+cname char(15) NOT NULL default '',
+carrier_id smallint(6) NOT NULL default '0',
+privacy tinyint(4) NOT NULL default '0',
+last_mod_date timestamp(14) NOT NULL,
+last_mod_id smallint(6) NOT NULL default '0',
+last_app_date timestamp(14) NOT NULL,
+last_app_id smallint(6) default '-1',
+version smallint(6) NOT NULL default '0',
+assigned_scps int(11) default '0',
+status tinyint(4) default '0'
+) TYPE=InnoDB;
+INSERT INTO t2 VALUES (4077711111,'SeanWheeler',0,2,20020111112853,500,00000000000000,-1,2,3,1);
+INSERT INTO t2 VALUES (9197722223,'berry',90,3,20020111112818,500,20020102114532,501,4,10,0);
+INSERT INTO t2 VALUES (650,'San Francisco',90,0,20020109113158,342,00000000000000,-1,1,24,1);
+INSERT INTO t2 VALUES (333,'tubs',99,2,20020109113453,501,20020109113453,500,3,10,0);
+select * from t1;
+number cname carrier_id privacy last_mod_date last_mod_id last_app_date last_app_id version assigned_scps status
+4077711111 SeanWheeler 90 2 20020111112846 500 00000000000000 -1 2 3 1
+9197722223 berry 90 3 20020111112809 500 20020102114532 501 4 10 0
+650 San Francisco 0 0 20011227111336 342 00000000000000 -1 1 24 1
+302467 Sue's Subshop 90 3 20020109113241 500 20020102115111 501 7 24 0
+6014911113 SudzCarwash 520 1 20020102115234 500 20020102115259 501 33 32768 0
+333 tubs 99 2 20020109113440 501 20020109113440 500 3 10 0
+select * from t2;
+number cname carrier_id privacy last_mod_date last_mod_id last_app_date last_app_id version assigned_scps status
+4077711111 SeanWheeler 0 2 20020111112853 500 00000000000000 -1 2 3 1
+9197722223 berry 90 3 20020111112818 500 20020102114532 501 4 10 0
+650 San Francisco 90 0 20020109113158 342 00000000000000 -1 1 24 1
+333 tubs 99 2 20020109113453 501 20020109113453 500 3 10 0
+delete t1, t2 from t1 left join t2 on t1.number=t2.number where (t1.carrier_id=90 and t1.number=t2.number) or (t2.carrier_id=90 and t1.number=t2.number) or (t1.carrier_id=90 and t2.number is null);
+select * from t1;
+number cname carrier_id privacy last_mod_date last_mod_id last_app_date last_app_id version assigned_scps status
+6014911113 SudzCarwash 520 1 20020102115234 500 20020102115259 501 33 32768 0
+333 tubs 99 2 20020109113440 501 20020109113440 500 3 10 0
+select * from t2;
+number cname carrier_id privacy last_mod_date last_mod_id last_app_date last_app_id version assigned_scps status
+333 tubs 99 2 20020109113453 501 20020109113453 500 3 10 0
+select * from t2;
+number cname carrier_id privacy last_mod_date last_mod_id last_app_date last_app_id version assigned_scps status
+333 tubs 99 2 20020109113453 501 20020109113453 500 3 10 0
+drop table t1,t2;
diff --git a/mysql-test/r/innodb_cache.result b/mysql-test/r/innodb_cache.result
new file mode 100644
index 00000000000..df331addb99
--- /dev/null
+++ b/mysql-test/r/innodb_cache.result
@@ -0,0 +1,15 @@
+drop table if exists t1;
+set autocommit=0;
+create table t1 (a int not null) type=innodb;
+insert into t1 values (1),(2),(3);
+select * from t1;
+a
+1
+2
+3
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 0
+drop table t1;
+commit;
+set autocommit=1;
diff --git a/mysql-test/r/ins000001.result b/mysql-test/r/ins000001.result
index 283f31ffb43..ec4f73e7a5d 100644
--- a/mysql-test/r/ins000001.result
+++ b/mysql-test/r/ins000001.result
@@ -1,3 +1,12 @@
+use test;
+drop table if exists t1,t2;
+create table t1 (email varchar(50));
+insert into t1 values ('sasha@mysql.com'),('monty@mysql.com'),
+('foo@hotmail.com'),('foo@aol.com'),('bar@aol.com');
+create table t2(id int not null auto_increment primary key,
+t2 varchar(50), unique(t2));
+insert into t2 (t2) select distinct substring(email, locate('@', email)+1) from t1;
+select * from t2;
id t2
1 mysql.com
2 hotmail.com
diff --git a/mysql-test/r/insert.result b/mysql-test/r/insert.result
index 145ec8a5cf4..f57efa33020 100644
--- a/mysql-test/r/insert.result
+++ b/mysql-test/r/insert.result
@@ -1,6 +1,21 @@
+drop table if exists t1;
+create table t1 (a int not null);
+insert into t1 values (1);
+insert into t1 values (a+2);
+insert into t1 values (a+3);
+insert into t1 values (4),(a+5);
+select * from t1;
a
1
2
3
4
5
+drop table t1;
+create table t1 (id int not null auto_increment primary key, username varchar(32) not null, unique (username));
+insert into t1 values (0,"mysql");
+insert into t1 values (0,"mysql ab");
+insert into t1 values (0,"mysql a");
+insert into t1 values (0,"r1manic");
+insert into t1 values (0,"r1man");
+drop table t1;
diff --git a/mysql-test/r/insert_select.result b/mysql-test/r/insert_select.result
index c754085ccb3..d61b6c67030 100644
--- a/mysql-test/r/insert_select.result
+++ b/mysql-test/r/insert_select.result
@@ -1,3 +1,12 @@
+drop table if exists t1,t2;
+create table t1 (bandID MEDIUMINT UNSIGNED NOT NULL PRIMARY KEY, payoutID SMALLINT UNSIGNED NOT NULL);
+insert into t1 (bandID,payoutID) VALUES (1,6),(2,6),(3,4),(4,9),(5,10),(6,1),(7,12),(8,12);
+create table t2 (payoutID SMALLINT UNSIGNED NOT NULL PRIMARY KEY);
+insert into t2 (payoutID) SELECT DISTINCT payoutID FROM t1;
+insert into t2 (payoutID) SELECT payoutID+10 FROM t1;
+Duplicate entry '16' for key 1
+insert ignore into t2 (payoutID) SELECT payoutID+10 FROM t1;
+select * from t2;
payoutID
1
4
@@ -11,3 +20,49 @@ payoutID
19
20
22
+drop table t1,t2;
+DROP TABLE IF EXISTS crash1,crash2;
+CREATE TABLE `crash1` (
+`numeropost` bigint(20) unsigned NOT NULL default '0',
+`icone` tinyint(4) unsigned NOT NULL default '0',
+`numreponse` bigint(20) unsigned NOT NULL auto_increment,
+`contenu` text NOT NULL,
+`pseudo` varchar(50) NOT NULL default '',
+`date` datetime NOT NULL default '0000-00-00 00:00:00',
+`ip` bigint(11) NOT NULL default '0',
+`signature` tinyint(1) unsigned NOT NULL default '0',
+PRIMARY KEY (`numeropost`,`numreponse`)
+,KEY `ip` (`ip`),
+KEY `date` (`date`),
+KEY `pseudo` (`pseudo`),
+KEY `numreponse` (`numreponse`)
+) TYPE=MyISAM;
+CREATE TABLE `crash2` (
+`numeropost` bigint(20) unsigned NOT NULL default '0',
+`icone` tinyint(4) unsigned NOT NULL default '0',
+`numreponse` bigint(20) unsigned NOT NULL auto_increment,
+`contenu` text NOT NULL,
+`pseudo` varchar(50) NOT NULL default '',
+`date` datetime NOT NULL default '0000-00-00 00:00:00',
+`ip` bigint(11) NOT NULL default '0',
+`signature` tinyint(1) unsigned NOT NULL default '0',
+PRIMARY KEY (`numeropost`,`numreponse`),
+KEY `ip` (`ip`),
+KEY `date` (`date`),
+KEY `pseudo` (`pseudo`),
+KEY `numreponse` (`numreponse`)
+) TYPE=MyISAM;
+INSERT INTO crash2
+(numeropost,icone,numreponse,contenu,pseudo,date,ip,signature) VALUES
+(9,1,56,'test','joce','2001-07-25 13:50:53'
+,3649052399,0);
+INSERT INTO crash1 (numeropost,icone,contenu,pseudo,date,signature,ip)
+SELECT 1618,icone,contenu,pseudo,date,signature,ip FROM crash2
+WHERE numeropost=9 ORDER BY numreponse ASC;
+show variables like '%bulk%';
+Variable_name Value
+myisam_bulk_insert_tree_size 8388608
+INSERT INTO crash1 (numeropost,icone,contenu,pseudo,date,signature,ip)
+SELECT 1718,icone,contenu,pseudo,date,signature,ip FROM crash2
+WHERE numeropost=9 ORDER BY numreponse ASC;
+DROP TABLE IF EXISTS crash1,crash2;
diff --git a/mysql-test/r/isam.result b/mysql-test/r/isam.result
index ba12ca05feb..d19352aad42 100644
--- a/mysql-test/r/isam.result
+++ b/mysql-test/r/isam.result
@@ -1,10 +1,79 @@
+drop table if exists t1,t2;
+create table t1 (a tinyint not null auto_increment, b blob not null, primary key (a)) type=isam;
+delete from t1 where (a & 1);
+select sum(length(b)) from t1;
+sum(length(b))
+3274494
+drop table t1;
+create table t1 (a int not null auto_increment,b int, primary key (a)) type=isam;
+insert into t1 values (1,1),(NULL,2),(3,3),(NULL,4);
+delete from t1 where a=4 or a=2;
+insert into t1 values (NULL,4),(NULL,5),(6,6);
+select * from t1;
+a b
+1 1
+5 5
+3 3
+4 4
+6 6
+delete from t1 where a=6;
+replace t1 values (3,1);
+replace t1 values (3,3);
+ALTER TABLE t1 add c int;
+insert into t1 values (NULL,6,6);
+select * from t1;
+a b c
+1 1 NULL
+5 5 NULL
+3 3 NULL
+4 4 NULL
+6 6 6
+drop table t1;
+create table t1 (a int,b text, index(a)) type=isam;
+Column 'a' is used with UNIQUE or INDEX but is not defined as NOT NULL
+create table t1 (a int,b text, index(b)) type=isam;
+BLOB column 'b' can't be used in key specification with the used table type
+create table t1 (ordid int(8) not null auto_increment, ord varchar(50) not null, primary key (ord,ordid)) type=isam;
+Incorrect table definition; There can only be one auto column and it must be defined as a key
+create table t1 (ordid int(8), unique (ordid)) type=isam;
+Column 'ordid' is used with UNIQUE or INDEX but is not defined as NOT NULL
+drop table if exists t1;
+create table t1 (a int not null primary key, b int not null,c int not null, key(b,c));
+insert into t1 values (1,2,2),(2,2,3),(3,2,4),(4,2,4);
+create table t2 type=isam select * from t1;
+optimize table t1;
+Table Op Msg_type Msg_text
+test.t1 optimize status OK
+check table t1,t2;
Table Op Msg_type Msg_text
test.t1 check status OK
+test.t2 check error The handler for the table doesn't support check/repair
+repair table t1,t2;
Table Op Msg_type Msg_text
test.t1 repair status OK
+test.t2 repair error The handler for the table doesn't support check/repair
+check table t2,t1;
Table Op Msg_type Msg_text
+test.t2 check error The handler for the table doesn't support check/repair
test.t1 check status OK
+lock tables t1 write;
+check table t2,t1;
Table Op Msg_type Msg_text
-test.t1 repair status OK
-Table Op Msg_type Msg_text
+test.t2 check error Table 't2' was not locked with LOCK TABLES
test.t1 check status OK
+show columns from t1;
+Field Type Null Key Default Extra
+a int(11) PRI 0
+b int(11) MUL 0
+c int(11) 0
+show full columns from t1;
+Field Type Null Key Default Extra Privileges
+a int(11) PRI 0 select,insert,update,references
+b int(11) MUL 0 select,insert,update,references
+c int(11) 0 select,insert,update,references
+show index from t1;
+Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
+t1 0 PRIMARY 1 a A 4 NULL NULL BTREE
+t1 1 b 1 b A 1 NULL NULL BTREE
+t1 1 b 2 c A 4 NULL NULL BTREE
+drop table t1,t2;
diff --git a/mysql-test/r/isolation.result b/mysql-test/r/isolation.result
deleted file mode 100644
index 60b71e217bb..00000000000
--- a/mysql-test/r/isolation.result
+++ /dev/null
@@ -1,61 +0,0 @@
-f1
-test1
-bar
-f1
-test2
-bar
-f1
-test3
-bar
-f1
-f1
-test4
-bar
-f1
-test5
-bar
-f1
-test6
-bar
-f1
-test7
-bar
-f1
-test8
-bar
-f1
-test9
-bar
-f1
-test10
-bar
-f1
-test11
-bar
-f1
-test12
-bar
-f1
-test13
-bar
-f1
-test14
-bar
-f1
-test15
-bar
-f1
-test16
-bar
-f1
-test17
-bar
-f1
-test18
-bar
-f1
-test19
-bar
-f1
-test20
-bar
diff --git a/mysql-test/r/join.result b/mysql-test/r/join.result
index c99c63245dd..b8ec13e9f50 100644
--- a/mysql-test/r/join.result
+++ b/mysql-test/r/join.result
@@ -1,36 +1,210 @@
+drop table if exists t1,t2,t3;
+create table t1 (id int primary key);
+create table t2 (id int);
+insert into t1 values (75);
+insert into t1 values (79);
+insert into t1 values (78);
+insert into t1 values (77);
+replace into t1 values (76);
+replace into t1 values (76);
+insert into t1 values (104);
+insert into t1 values (103);
+insert into t1 values (102);
+insert into t1 values (101);
+insert into t1 values (105);
+insert into t1 values (106);
+insert into t1 values (107);
+insert into t2 values (107);
+insert into t2 values (75);
+select t1.id, t2.id from t1, t2 where t2.id = t1.id;
id id
107 107
75 75
+select t1.id, count(t2.id) from t1,t2 where t2.id = t1.id group by t1.id;
id count(t2.id)
75 1
107 1
+select t1.id, count(t2.id) from t1,t2 where t2.id = t1.id group by t2.id;
id count(t2.id)
75 1
107 1
+drop table t1,t2;
+CREATE TABLE t1 (
+id int(11) NOT NULL auto_increment,
+token varchar(100) DEFAULT '' NOT NULL,
+count int(11) DEFAULT '0' NOT NULL,
+qty int(11),
+phone char(1) DEFAULT '' NOT NULL,
+timestamp datetime DEFAULT '0000-00-00 00:00:00' NOT NULL,
+PRIMARY KEY (id),
+KEY token (token(15)),
+KEY timestamp (timestamp),
+UNIQUE token_2 (token(75),count,phone)
+);
+INSERT INTO t1 VALUES (21,'e45703b64de71482360de8fec94c3ade',3,7800,'n','1999-12-23 17:22:21');
+INSERT INTO t1 VALUES (22,'e45703b64de71482360de8fec94c3ade',4,5000,'y','1999-12-23 17:22:21');
+INSERT INTO t1 VALUES (18,'346d1cb63c89285b2351f0ca4de40eda',3,13200,'b','1999-12-23 11:58:04');
+INSERT INTO t1 VALUES (17,'ca6ddeb689e1b48a04146b1b5b6f936a',4,15000,'b','1999-12-23 11:36:53');
+INSERT INTO t1 VALUES (16,'ca6ddeb689e1b48a04146b1b5b6f936a',3,13200,'b','1999-12-23 11:36:53');
+INSERT INTO t1 VALUES (26,'a71250b7ed780f6ef3185bfffe027983',5,1500,'b','1999-12-27 09:44:24');
+INSERT INTO t1 VALUES (24,'4d75906f3c37ecff478a1eb56637aa09',3,5400,'y','1999-12-23 17:29:12');
+INSERT INTO t1 VALUES (25,'4d75906f3c37ecff478a1eb56637aa09',4,6500,'y','1999-12-23 17:29:12');
+INSERT INTO t1 VALUES (27,'a71250b7ed780f6ef3185bfffe027983',3,6200,'b','1999-12-27 09:44:24');
+INSERT INTO t1 VALUES (28,'a71250b7ed780f6ef3185bfffe027983',3,5400,'y','1999-12-27 09:44:36');
+INSERT INTO t1 VALUES (29,'a71250b7ed780f6ef3185bfffe027983',4,17700,'b','1999-12-27 09:45:05');
+CREATE TABLE t2 (
+id int(11) NOT NULL auto_increment,
+category int(11) DEFAULT '0' NOT NULL,
+county int(11) DEFAULT '0' NOT NULL,
+state int(11) DEFAULT '0' NOT NULL,
+phones int(11) DEFAULT '0' NOT NULL,
+nophones int(11) DEFAULT '0' NOT NULL,
+PRIMARY KEY (id),
+KEY category (category,county,state)
+);
+INSERT INTO t2 VALUES (3,2,11,12,5400,7800);
+INSERT INTO t2 VALUES (4,2,25,12,6500,11200);
+INSERT INTO t2 VALUES (5,1,37,6,10000,12000);
+select a.id, b.category as catid, b.state as stateid, b.county as
+countyid from t1 a, t2 b where (a.token =
+'a71250b7ed780f6ef3185bfffe027983') and (a.count = b.id);
id catid stateid countyid
27 2 12 11
28 2 12 11
29 2 12 25
26 1 6 37
+select a.id, b.category as catid, b.state as stateid, b.county as
+countyid from t1 a, t2 b where (a.token =
+'a71250b7ed780f6ef3185bfffe027983') and (a.count = b.id) order by a.id;
id catid stateid countyid
26 1 6 37
27 2 12 11
28 2 12 11
29 2 12 25
+drop table t1, t2;
+create table t1 (a int primary key);
+insert into t1 values(1),(2);
+select t1.a from t1 as t1 left join t1 as t2 using (a) left join t1 as t3 using (a) left join t1 as t4 using (a) left join t1 as t5 using (a) left join t1 as t6 using (a) left join t1 as t7 using (a) left join t1 as t8 using (a) left join t1 as t9 using (a) left join t1 as t10 using (a) left join t1 as t11 using (a) left join t1 as t12 using (a) left join t1 as t13 using (a) left join t1 as t14 using (a) left join t1 as t15 using (a) left join t1 as t16 using (a) left join t1 as t17 using (a) left join t1 as t18 using (a) left join t1 as t19 using (a) left join t1 as t20 using (a) left join t1 as t21 using (a) left join t1 as t22 using (a) left join t1 as t23 using (a) left join t1 as t24 using (a) left join t1 as t25 using (a) left join t1 as t26 using (a) left join t1 as t27 using (a) left join t1 as t28 using (a) left join t1 as t29 using (a) left join t1 as t30 using (a) left join t1 as t31 using (a);
a
1
2
+select t1.a from t1 as t1 left join t1 as t2 using (a) left join t1 as t3 using (a) left join t1 as t4 using (a) left join t1 as t5 using (a) left join t1 as t6 using (a) left join t1 as t7 using (a) left join t1 as t8 using (a) left join t1 as t9 using (a) left join t1 as t10 using (a) left join t1 as t11 using (a) left join t1 as t12 using (a) left join t1 as t13 using (a) left join t1 as t14 using (a) left join t1 as t15 using (a) left join t1 as t16 using (a) left join t1 as t17 using (a) left join t1 as t18 using (a) left join t1 as t19 using (a) left join t1 as t20 using (a) left join t1 as t21 using (a) left join t1 as t22 using (a) left join t1 as t23 using (a) left join t1 as t24 using (a) left join t1 as t25 using (a) left join t1 as t26 using (a) left join t1 as t27 using (a) left join t1 as t28 using (a) left join t1 as t29 using (a) left join t1 as t30 using (a) left join t1 as t31 using (a) left join t1 as t32 using (a) left join t1 as t33 using (a) left join t1 as t34 using (a) left join t1 as t35 using (a) left join t1 as t36 using (a) left join t1 as t37 using (a) left join t1 as t38 using (a) left join t1 as t39 using (a) left join t1 as t40 using (a) left join t1 as t41 using (a) left join t1 as t42 using (a) left join t1 as t43 using (a) left join t1 as t44 using (a) left join t1 as t45 using (a) left join t1 as t46 using (a) left join t1 as t47 using (a) left join t1 as t48 using (a) left join t1 as t49 using (a) left join t1 as t50 using (a) left join t1 as t51 using (a) left join t1 as t52 using (a) left join t1 as t53 using (a) left join t1 as t54 using (a) left join t1 as t55 using (a) left join t1 as t56 using (a) left join t1 as t57 using (a) left join t1 as t58 using (a) left join t1 as t59 using (a) left join t1 as t60 using (a) left join t1 as t61 using (a) left join t1 as t62 using (a) left join t1 as t63 using (a) left join t1 as t64 using (a) left join t1 as t65 using (a);
+Too many tables. MySQL can only use XX tables in a join
+drop table t1;
+CREATE TABLE t1 (
+a int(11) NOT NULL,
+b int(11) NOT NULL,
+PRIMARY KEY (a,b)
+) TYPE=MyISAM;
+INSERT INTO t1 VALUES (1,1),(1,2),(1,3),(1,4),(1,5),(1,6),(1,7),(2,3);
+CREATE TABLE t2 (
+a int(11) default NULL
+) TYPE=MyISAM;
+INSERT INTO t2 VALUES (2),(3);
+SELECT t1.a,t2.a,b FROM t1,t2 WHERE t1.a=t2.a AND (t1.a=1 OR t1.a=2) AND b>=1 AND b<=3;
a a b
2 2 3
+DROP TABLE t1, t2;
+CREATE TABLE t1 (d DATE NOT NULL);
+CREATE TABLE t2 (d DATE NOT NULL);
+INSERT INTO t1 (d) VALUES ('2001-08-01'),('0000-00-00');
+SELECT * FROM t1 LEFT JOIN t2 USING (d) WHERE t2.d IS NULL;
d d
2001-08-01 NULL
0000-00-00 NULL
+SELECT * from t1 WHERE t1.d IS NULL;
d
0000-00-00
+DROP TABLE t1,t2;
+CREATE TABLE t1 (
+Document_ID varchar(50) NOT NULL default '',
+Contractor_ID varchar(6) NOT NULL default '',
+Language_ID char(3) NOT NULL default '',
+Expiration_Date datetime default NULL,
+Publishing_Date datetime default NULL,
+Title text,
+Column_ID varchar(50) NOT NULL default '',
+PRIMARY KEY (Language_ID,Document_ID,Contractor_ID)
+);
+INSERT INTO t1 VALUES ('xep80','1','ger','2001-12-31 20:00:00','2001-11-12 10:58:00','Kartenbestellung - jetzt auch online','anle'),('','999998','',NULL,NULL,NULL,'');
+CREATE TABLE t2 (
+Contractor_ID char(6) NOT NULL default '',
+Language_ID char(3) NOT NULL default '',
+Document_ID char(50) NOT NULL default '',
+CanRead char(1) default NULL,
+Customer_ID int(11) NOT NULL default '0',
+PRIMARY KEY (Contractor_ID,Language_ID,Document_ID,Customer_ID)
+);
+INSERT INTO t2 VALUES ('5','ger','xep80','1',999999),('1','ger','xep80','1',999999);
+CREATE TABLE t3 (
+Language_ID char(3) NOT NULL default '',
+Column_ID char(50) NOT NULL default '',
+Contractor_ID char(6) NOT NULL default '',
+CanRead char(1) default NULL,
+Active char(1) default NULL,
+PRIMARY KEY (Language_ID,Column_ID,Contractor_ID)
+);
+INSERT INTO t3 VALUES ('ger','home','1','1','1'),('ger','Test','1','0','0'),('ger','derclu','1','0','0'),('ger','clubne','1','0','0'),('ger','philos','1','0','0'),('ger','clubko','1','0','0'),('ger','clubim','1','1','1'),('ger','progra','1','0','0'),('ger','progvo','1','0','0'),('ger','progsp','1','0','0'),('ger','progau','1','0','0'),('ger','progku','1','0','0'),('ger','progss','1','0','0'),('ger','nachl','1','0','0'),('ger','mitgli','1','0','0'),('ger','mitsu','1','0','0'),('ger','mitbus','1','0','0'),('ger','ergmar','1','1','1'),('ger','home','4','1','1'),('ger','derclu','4','1','1'),('ger','clubne','4','0','0'),('ger','philos','4','1','1'),('ger','clubko','4','1','1'),('ger','clubim','4','1','1'),('ger','progra','4','1','1'),('ger','progvo','4','1','1'),('ger','progsp','4','1','1'),('ger','progau','4','0','0'),('ger','progku','4','1','1'),('ger','progss','4','1','1'),('ger','nachl','4','1','1'),('ger','mitgli','4','0','0'),('ger','mitsu','4','0','0'),('ger','mitbus','4','0','0'),('ger','ergmar','4','1','1'),('ger','progra2','1','0','0'),('ger','archiv','4','1','1'),('ger','anmeld','4','1','1'),('ger','thema','4','1','1'),('ger','edito','4','1','1'),('ger','madis','4','1','1'),('ger','enma','4','1','1'),('ger','madis','1','1','1'),('ger','enma','1','1','1'),('ger','vorsch','4','0','0'),('ger','veranst','4','0','0'),('ger','anle','4','1','1'),('ger','redak','4','1','1'),('ger','nele','4','1','1'),('ger','aukt','4','1','1'),('ger','callcenter','4','1','1'),('ger','anle','1','0','0');
+delete from t1 where Contractor_ID='999998';
+insert into t1 (Contractor_ID) Values ('999998');
+SELECT DISTINCT COUNT(t1.Title) FROM t1,
+t2, t3 WHERE
+t1.Document_ID='xep80' AND t1.Contractor_ID='1' AND
+t1.Language_ID='ger' AND '2001-12-21 23:14:24' >=
+Publishing_Date AND '2001-12-21 23:14:24' <= Expiration_Date AND
+t1.Document_ID = t2.Document_ID AND
+t1.Language_ID = t2.Language_ID AND
+t1.Contractor_ID = t2.Contractor_ID AND (
+t2.Customer_ID = '4' OR
+t2.Customer_ID = '999999' OR
+t2.Customer_ID = '1' )AND t2.CanRead
+= '1' AND t1.Column_ID=t3.Column_ID AND
+t1.Language_ID=t3.Language_ID AND (
+t3.Contractor_ID = '4' OR
+t3.Contractor_ID = '999999' OR
+t3.Contractor_ID = '1') AND
+t3.CanRead='1' AND t3.Active='1';
COUNT(t1.Title)
1
+SELECT DISTINCT COUNT(t1.Title) FROM t1,
+t2, t3 WHERE
+t1.Document_ID='xep80' AND t1.Contractor_ID='1' AND
+t1.Language_ID='ger' AND '2001-12-21 23:14:24' >=
+Publishing_Date AND '2001-12-21 23:14:24' <= Expiration_Date AND
+t1.Document_ID = t2.Document_ID AND
+t1.Language_ID = t2.Language_ID AND
+t1.Contractor_ID = t2.Contractor_ID AND (
+t2.Customer_ID = '4' OR
+t2.Customer_ID = '999999' OR
+t2.Customer_ID = '1' )AND t2.CanRead
+= '1' AND t1.Column_ID=t3.Column_ID AND
+t1.Language_ID=t3.Language_ID AND (
+t3.Contractor_ID = '4' OR
+t3.Contractor_ID = '999999' OR
+t3.Contractor_ID = '1') AND
+t3.CanRead='1' AND t3.Active='1';
COUNT(t1.Title)
1
+drop table t1,t2,t3;
+CREATE TABLE t1 (
+t1_id int(11) default NULL,
+t2_id int(11) default NULL,
+type enum('Cost','Percent') default NULL,
+cost_unit enum('Cost','Unit') default NULL,
+min_value double default NULL,
+max_value double default NULL,
+t3_id int(11) default NULL,
+item_id int(11) default NULL
+) TYPE=MyISAM;
+INSERT INTO t1 VALUES (12,5,'Percent','Cost',-1,0,-1,-1),(14,4,'Percent','Cost',-1,0,-1,-1),(18,5,'Percent','Cost',-1,0,-1,-1),(19,4,'Percent','Cost',-1,0,-1,-1),(20,5,'Percent','Cost',100,-1,22,291),(21,5,'Percent','Cost',100,-1,18,291),(22,1,'Percent','Cost',100,-1,6,291),(23,1,'Percent','Cost',100,-1,21,291),(24,1,'Percent','Cost',100,-1,9,291),(25,1,'Percent','Cost',100,-1,4,291),(26,1,'Percent','Cost',100,-1,20,291),(27,4,'Percent','Cost',100,-1,7,202),(28,1,'Percent','Cost',50,-1,-1,137),(29,2,'Percent','Cost',100,-1,4,354),(30,2,'Percent','Cost',100,-1,9,137),(93,2,'Cost','Cost',-1,10000000,-1,-1);
+CREATE TABLE t2 (
+id int(10) unsigned NOT NULL auto_increment,
+name varchar(255) default NULL,
+PRIMARY KEY (id)
+) TYPE=MyISAM;
+INSERT INTO t2 VALUES (1,'s1'),(2,'s2'),(3,'s3'),(4,'s4'),(5,'s5');
+select t1.*, t2.* from t1, t2 where t2.id=t1.t2_id limit 2;
t1_id t2_id type cost_unit min_value max_value t3_id item_id id name
22 1 Percent Cost 100 -1 6 291 1 s1
23 1 Percent Cost 100 -1 21 291 1 s1
+drop table t1,t2;
diff --git a/mysql-test/r/join_crash.result b/mysql-test/r/join_crash.result
index f7bef8af8ec..c7bca9f7497 100644
--- a/mysql-test/r/join_crash.result
+++ b/mysql-test/r/join_crash.result
@@ -1 +1,110 @@
+DROP TABLE IF EXISTS t1,t2,t3,t4;
+CREATE TABLE t1 (
+project_id int(11) NOT NULL auto_increment,
+project_row_lock int(11) NOT NULL default '0',
+project_name varchar(80) NOT NULL default '',
+client_ptr int(11) NOT NULL default '0',
+project_contact_ptr int(11) default NULL,
+client_contact_ptr int(11) default NULL,
+billing_contact_ptr int(11) default NULL,
+comments mediumtext,
+PRIMARY KEY (project_id),
+UNIQUE KEY project (client_ptr,project_name)
+) TYPE=MyISAM PACK_KEYS=1;
+INSERT INTO t1 VALUES (1,0,'Rejected Time',1,NULL,NULL,NULL,NULL);
+INSERT INTO t1 VALUES (209,0,'MDGRAD Proposal/Investigation',97,NULL,NULL,NULL,'');
+INSERT INTO t1 VALUES (208,0,'Font 9 Design',84,NULL,NULL,NULL,'');
+INSERT INTO t1 VALUES (207,0,'Web Based Order Processing',95,NULL,NULL,NULL,'');
+INSERT INTO t1 VALUES (205,0,'Mac Screen Saver',95,NULL,NULL,NULL,'');
+INSERT INTO t1 VALUES (206,0,'Web Site',96,NULL,NULL,NULL,'');
+INSERT INTO t1 VALUES (204,0,'Magnafire Glue',94,NULL,NULL,NULL,'');
+INSERT INTO t1 VALUES (203,0,'Print Bid',93,NULL,NULL,NULL,'');
+INSERT INTO t1 VALUES (202,0,'EPOC Port',92,NULL,NULL,NULL,'');
+INSERT INTO t1 VALUES (201,0,'TravelMate',88,NULL,NULL,NULL,'');
+CREATE TABLE t2 (
+period_id int(11) NOT NULL auto_increment,
+period_type enum('user_table','client_table','role_table','member_table','project_table') default NULL,
+period_key int(11) default NULL,
+start_date datetime default NULL,
+end_date datetime default NULL,
+work_load int(11) default NULL,
+PRIMARY KEY (period_id),
+KEY period_index (period_type,period_key),
+KEY date_index (start_date,end_date)
+) TYPE=MyISAM PACK_KEYS=1;
+INSERT INTO t2 VALUES (1,'user_table',98,'2000-01-01 00:00:00',NULL,NULL);
+INSERT INTO t2 VALUES (2,'user_table',99,'2000-01-01 00:00:00',NULL,NULL);
+INSERT INTO t2 VALUES (3,'user_table',100,'2000-01-01 00:00:00',NULL,NULL);
+INSERT INTO t2 VALUES (49,'project_table',148,'2000-01-01 00:00:00',NULL,NULL);
+INSERT INTO t2 VALUES (50,'client_table',68,'2000-01-01 00:00:00',NULL,NULL);
+INSERT INTO t2 VALUES (51,'project_table',149,'2000-01-01 00:00:00',NULL,NULL);
+INSERT INTO t2 VALUES (52,'project_table',150,'2000-01-01 00:00:00',NULL,NULL);
+INSERT INTO t2 VALUES (53,'client_table',69,'2000-01-01 00:00:00',NULL,NULL);
+INSERT INTO t2 VALUES (54,'project_table',151,'2000-01-01 00:00:00',NULL,NULL);
+INSERT INTO t2 VALUES (55,'client_table',70,'2000-01-01 00:00:00',NULL,NULL);
+INSERT INTO t2 VALUES (155,'role_table',1,'2000-01-01 00:00:00',NULL,NULL);
+INSERT INTO t2 VALUES (156,'role_table',2,'2000-01-01 00:00:00',NULL,NULL);
+INSERT INTO t2 VALUES (160,'member_table',1,'2000-01-01 00:00:00',NULL,1);
+INSERT INTO t2 VALUES (161,'member_table',2,'2000-01-01 00:00:00',NULL,1);
+INSERT INTO t2 VALUES (162,'member_table',3,'2000-01-01 00:00:00',NULL,1);
+CREATE TABLE t3 (
+budget_id int(11) NOT NULL auto_increment,
+project_ptr int(11) NOT NULL default '0',
+po_number varchar(20) NOT NULL default '',
+status enum('open','closed') default NULL,
+date_received datetime default NULL,
+amount_received float(10,2) default NULL,
+adjustment float(10,2) default NULL,
+PRIMARY KEY (budget_id),
+UNIQUE KEY po (project_ptr,po_number)
+) TYPE=MyISAM PACK_KEYS=1;
+CREATE TABLE t4 (
+client_id int(11) NOT NULL auto_increment,
+client_row_lock int(11) NOT NULL default '0',
+client_name varchar(80) NOT NULL default '',
+contact_ptr int(11) default NULL,
+comments mediumtext,
+PRIMARY KEY (client_id),
+UNIQUE KEY client_name (client_name)
+) TYPE=MyISAM PACK_KEYS=1;
+INSERT INTO t4 VALUES (1,0,'CPS',NULL,NULL);
+select distinct
+t1.project_id as project_id,
+t1.project_name as project_name,
+t1.client_ptr as client_ptr,
+t1.comments as comments,
+sum( t3.amount_received ) + sum( t3.adjustment ) as total_budget
+from
+t1 ,
+t2 as client_period ,
+t2 as project_period
+left join
+t3
+on
+t3.project_ptr = t1.project_id
+and t3.date_received <= '2001-03-22 14:15:09'
+ left join
+t4
+on
+t4.client_id = t1.client_ptr
+where
+1
+and ( client_period.period_type = 'client_table'
+ and client_period.period_key = t4.client_id
+and ( client_period.start_date <= '2001-03-22 14:15:09' or isnull( client_period.start_date ))
+and ( client_period.end_date > '2001-03-21 14:15:09' or isnull( client_period.end_date ))
+)
+and ( project_period.period_type = 'project_table'
+ and project_period.period_key = t1.project_id
+and ( project_period.start_date <= '2001-03-22 14:15:09' or isnull( project_period.start_date ))
+and ( project_period.end_date > '2001-03-21 14:15:09' or isnull( project_period.end_date )) )
+group by
+client_id,
+project_id ,
+client_period.period_id ,
+project_period.period_id
+order by
+client_name asc,
+project_name asc;
project_id project_name client_ptr comments total_budget
+DROP TABLE t1,t2,t3,t4;
diff --git a/mysql-test/r/join_outer.result b/mysql-test/r/join_outer.result
index f5e643a9bbf..9d3c152e516 100644
--- a/mysql-test/r/join_outer.result
+++ b/mysql-test/r/join_outer.result
@@ -1,8 +1,19 @@
+drop table if exists t1,t2,t3,t4,t5;
+CREATE TABLE t1 (
+grp int(11) default NULL,
+a bigint(20) unsigned default NULL,
+c char(10) NOT NULL default ''
+) TYPE=MyISAM;
+INSERT INTO t1 VALUES (1,1,'a'),(2,2,'b'),(2,3,'c'),(3,4,'E'),(3,5,'C'),(3,6,'D'),(NULL,NULL,'');
+create table t2 (id int, a bigint unsigned not null, c char(10), d int, primary key (a));
+insert into t2 values (1,1,"a",1),(3,4,"A",4),(3,5,"B",5),(3,6,"C",6),(4,7,"D",7);
+select t1.*,t2.* from t1 JOIN t2 where t1.a=t2.a;
grp a c id a c d
1 1 a 1 1 a 1
3 4 E 3 4 A 4
3 5 C 3 5 B 5
3 6 D 3 6 C 6
+select t1.*,t2.* from t1 left join t2 on (t1.a=t2.a) order by t1.grp,t1.a,t2.c;
grp a c id a c d
NULL NULL NULL NULL NULL NULL
1 1 a 1 1 a 1
@@ -11,18 +22,21 @@ NULL NULL NULL NULL NULL NULL
3 4 E 3 4 A 4
3 5 C 3 5 B 5
3 6 D 3 6 C 6
+select t1.*,t2.* from { oj t2 left outer join t1 on (t1.a=t2.a) };
grp a c id a c d
1 1 a 1 1 a 1
3 4 E 3 4 A 4
3 5 C 3 5 B 5
3 6 D 3 6 C 6
NULL NULL NULL 4 7 D 7
+select t1.*,t2.* from t1 as t0,{ oj t2 left outer join t1 on (t1.a=t2.a) } WHERE t0.a=2;
grp a c id a c d
1 1 a 1 1 a 1
3 4 E 3 4 A 4
3 5 C 3 5 B 5
3 6 D 3 6 C 6
NULL NULL NULL 4 7 D 7
+select t1.*,t2.* from t1 left join t2 using (a);
grp a c id a c d
1 1 a 1 1 a 1
2 2 b NULL NULL NULL NULL
@@ -31,11 +45,13 @@ grp a c id a c d
3 5 C 3 5 B 5
3 6 D 3 6 C 6
NULL NULL NULL NULL NULL NULL
+select t1.*,t2.* from t1 left join t2 using (a) where t1.a=t2.a;
grp a c id a c d
1 1 a 1 1 a 1
3 4 E 3 4 A 4
3 5 C 3 5 B 5
3 6 D 3 6 C 6
+select t1.*,t2.* from t1 left join t2 using (a,c);
grp a c id a c d
1 1 a 1 1 a 1
2 2 b NULL NULL NULL NULL
@@ -44,6 +60,7 @@ grp a c id a c d
3 5 C NULL NULL NULL NULL
3 6 D NULL NULL NULL NULL
NULL NULL NULL NULL NULL NULL
+select t1.*,t2.* from t1 left join t2 using (c);
grp a c id a c d
1 1 a 1 1 a 1
1 1 a 3 4 A 4
@@ -53,6 +70,7 @@ grp a c id a c d
3 5 C 3 6 C 6
3 6 D 4 7 D 7
NULL NULL NULL NULL NULL NULL
+select t1.*,t2.* from t1 natural left outer join t2;
grp a c id a c d
1 1 a 1 1 a 1
2 2 b NULL NULL NULL NULL
@@ -61,19 +79,24 @@ grp a c id a c d
3 5 C NULL NULL NULL NULL
3 6 D NULL NULL NULL NULL
NULL NULL NULL NULL NULL NULL
+select t1.*,t2.* from t1 left join t2 on (t1.a=t2.a) where t2.id=3;
grp a c id a c d
3 4 E 3 4 A 4
3 5 C 3 5 B 5
3 6 D 3 6 C 6
+select t1.*,t2.* from t1 left join t2 on (t1.a=t2.a) where t2.id is null;
grp a c id a c d
2 2 b NULL NULL NULL NULL
2 3 c NULL NULL NULL NULL
NULL NULL NULL NULL NULL NULL
+explain select t1.*,t2.* from t1,t2 where t1.a=t2.a and isnull(t2.a)=1;
Comment
Impossible WHERE noticed after reading const tables
+explain select t1.*,t2.* from t1 left join t2 on t1.a=t2.a where isnull(t2.a)=1;
table type possible_keys key key_len ref rows Extra
t1 ALL NULL NULL NULL NULL 7
t2 eq_ref PRIMARY PRIMARY 8 t1.a 1 where used
+select t1.*,t2.*,t3.a from t1 left join t2 on (t1.a=t2.a) left join t1 as t3 on (t2.a=t3.a);
grp a c id a c d a
1 1 a 1 1 a 1 1
2 2 b NULL NULL NULL NULL NULL
@@ -82,28 +105,161 @@ grp a c id a c d a
3 5 C 3 5 B 5 5
3 6 D 3 6 C 6 6
NULL NULL NULL NULL NULL NULL NULL
+explain select t1.*,t2.*,t3.a from t1 left join t2 on (t3.a=t2.a) left join t1 as t3 on (t1.a=t3.a);
+Cross dependency found in OUTER JOIN. Examine your ON conditions
+select t1.*,t2.*,t3.a from t1 left join t2 on (t3.a=t2.a) left join t1 as t3 on (t1.a=t3.a);
+Cross dependency found in OUTER JOIN. Examine your ON conditions
+select t1.*,t2.*,t3.a from t1 left join t2 on (t3.a=t2.a) left join t1 as t3 on (t2.a=t3.a);
+Cross dependency found in OUTER JOIN. Examine your ON conditions
+select t1.*,t2.* from t1 inner join t2 using (a);
grp a c id a c d
1 1 a 1 1 a 1
3 4 E 3 4 A 4
3 5 C 3 5 B 5
3 6 D 3 6 C 6
+select t1.*,t2.* from t1 inner join t2 on (t1.a=t2.a);
grp a c id a c d
1 1 a 1 1 a 1
3 4 E 3 4 A 4
3 5 C 3 5 B 5
3 6 D 3 6 C 6
+select t1.*,t2.* from t1 natural join t2;
grp a c id a c d
1 1 a 1 1 a 1
+drop table t1,t2;
+CREATE TABLE t1 (
+usr_id INT unsigned NOT NULL,
+uniq_id INT unsigned NOT NULL AUTO_INCREMENT,
+start_num INT unsigned NOT NULL DEFAULT 1,
+increment INT unsigned NOT NULL DEFAULT 1,
+PRIMARY KEY (uniq_id),
+INDEX usr_uniq_idx (usr_id, uniq_id),
+INDEX uniq_usr_idx (uniq_id, usr_id)
+);
+CREATE TABLE t2 (
+id INT unsigned NOT NULL DEFAULT 0,
+usr2_id INT unsigned NOT NULL DEFAULT 0,
+max INT unsigned NOT NULL DEFAULT 0,
+c_amount INT unsigned NOT NULL DEFAULT 0,
+d_max INT unsigned NOT NULL DEFAULT 0,
+d_num INT unsigned NOT NULL DEFAULT 0,
+orig_time INT unsigned NOT NULL DEFAULT 0,
+c_time INT unsigned NOT NULL DEFAULT 0,
+active ENUM ("no","yes") NOT NULL,
+PRIMARY KEY (id,usr2_id),
+INDEX id_idx (id),
+INDEX usr2_idx (usr2_id)
+);
+INSERT INTO t1 VALUES (3,NULL,0,50),(3,NULL,0,200),(3,NULL,0,25),(3,NULL,0,84676),(3,NULL,0,235),(3,NULL,0,10),(3,NULL,0,3098),(3,NULL,0,2947),(3,NULL,0,8987),(3,NULL,0,8347654),(3,NULL,0,20398),(3,NULL,0,8976),(3,NULL,0,500),(3,NULL,0,198);
+SELECT t1.usr_id,t1.uniq_id,t1.increment,
+t2.usr2_id,t2.c_amount,t2.max
+FROM t1
+LEFT JOIN t2 ON t2.id = t1.uniq_id
+WHERE t1.uniq_id = 4
+ORDER BY t2.c_amount;
usr_id uniq_id increment usr2_id c_amount max
3 4 84676 NULL NULL NULL
+SELECT t1.usr_id,t1.uniq_id,t1.increment,
+t2.usr2_id,t2.c_amount,t2.max
+FROM t2
+RIGHT JOIN t1 ON t2.id = t1.uniq_id
+WHERE t1.uniq_id = 4
+ORDER BY t2.c_amount;
usr_id uniq_id increment usr2_id c_amount max
3 4 84676 NULL NULL NULL
+INSERT INTO t2 VALUES (2,3,3000,6000,0,0,746584,837484,'yes');
+INSERT INTO t2 VALUES (2,3,3000,6000,0,0,746584,837484,'yes');
+Duplicate entry '2-3' for key 1
+INSERT INTO t2 VALUES (7,3,1000,2000,0,0,746294,937484,'yes');
+SELECT t1.usr_id,t1.uniq_id,t1.increment,t2.usr2_id,t2.c_amount,t2.max FROM t1 LEFT JOIN t2 ON t2.id = t1.uniq_id WHERE t1.uniq_id = 4 ORDER BY t2.c_amount;
usr_id uniq_id increment usr2_id c_amount max
3 4 84676 NULL NULL NULL
+SELECT t1.usr_id,t1.uniq_id,t1.increment,t2.usr2_id,t2.c_amount,t2.max FROM t1 LEFT JOIN t2 ON t2.id = t1.uniq_id WHERE t1.uniq_id = 4 GROUP BY t2.c_amount;
usr_id uniq_id increment usr2_id c_amount max
3 4 84676 NULL NULL NULL
+SELECT t1.usr_id,t1.uniq_id,t1.increment,t2.usr2_id,t2.c_amount,t2.max FROM t1 LEFT JOIN t2 ON t2.id = t1.uniq_id WHERE t1.uniq_id = 4;
usr_id uniq_id increment usr2_id c_amount max
3 4 84676 NULL NULL NULL
+drop table t1,t2;
+drop table if exists t1,t2,t3,t4;
+CREATE TABLE t1 (
+cod_asig int(11) DEFAULT '0' NOT NULL,
+desc_larga_cat varchar(80) DEFAULT '' NOT NULL,
+desc_larga_cas varchar(80) DEFAULT '' NOT NULL,
+desc_corta_cat varchar(40) DEFAULT '' NOT NULL,
+desc_corta_cas varchar(40) DEFAULT '' NOT NULL,
+cred_total double(3,1) DEFAULT '0.0' NOT NULL,
+pre_requisit int(11),
+co_requisit int(11),
+preco_requisit int(11),
+PRIMARY KEY (cod_asig)
+);
+INSERT INTO t1 VALUES (10360,'asdfggfg','Introduccion a los Ordenadores I','asdfggfg','Introduccio Ordinadors I',6.0,NULL,NULL,NULL);
+INSERT INTO t1 VALUES (10361,'Components i Circuits Electronics I','Componentes y Circuitos Electronicos I','Components i Circuits Electronics I','Comp. i Circ. Electr. I',6.0,NULL,NULL,NULL);
+INSERT INTO t1 VALUES (10362,'Laboratori d`Ordinadors','Laboratorio de Ordenadores','Laboratori d`Ordinadors','Laboratori Ordinadors',4.5,NULL,NULL,NULL);
+INSERT INTO t1 VALUES (10363,'Tecniques de Comunicacio Oral i Escrita','Tecnicas de Comunicacion Oral y Escrita','Tecniques de Comunicacio Oral i Escrita','Tec. Com. Oral i Escrita',4.5,NULL,NULL,NULL);
+INSERT INTO t1 VALUES (11403,'Projecte Fi de Carrera','Proyecto Fin de Carrera','Projecte Fi de Carrera','PFC',9.0,NULL,NULL,NULL);
+INSERT INTO t1 VALUES (11404,'+lgebra lineal','Algebra lineal','+lgebra lineal','+lgebra lineal',15.0,NULL,NULL,NULL);
+INSERT INTO t1 VALUES (11405,'+lgebra lineal','Algebra lineal','+lgebra lineal','+lgebra lineal',18.0,NULL,NULL,NULL);
+INSERT INTO t1 VALUES (11406,'Calcul Infinitesimal','Cßlculo Infinitesimal','Calcul Infinitesimal','Calcul Infinitesimal',15.0,NULL,NULL,NULL);
+CREATE TABLE t2 (
+idAssignatura int(11) DEFAULT '0' NOT NULL,
+Grup int(11) DEFAULT '0' NOT NULL,
+Places smallint(6) DEFAULT '0' NOT NULL,
+PlacesOcupades int(11) DEFAULT '0',
+PRIMARY KEY (idAssignatura,Grup)
+);
+INSERT INTO t2 VALUES (10360,12,333,0);
+INSERT INTO t2 VALUES (10361,30,2,0);
+INSERT INTO t2 VALUES (10361,40,3,0);
+INSERT INTO t2 VALUES (10360,45,10,0);
+INSERT INTO t2 VALUES (10362,10,12,0);
+INSERT INTO t2 VALUES (10360,55,2,0);
+INSERT INTO t2 VALUES (10360,70,0,0);
+INSERT INTO t2 VALUES (10360,565656,0,0);
+INSERT INTO t2 VALUES (10360,32767,7,0);
+INSERT INTO t2 VALUES (10360,33,8,0);
+INSERT INTO t2 VALUES (10360,7887,85,0);
+INSERT INTO t2 VALUES (11405,88,8,0);
+INSERT INTO t2 VALUES (10360,0,55,0);
+INSERT INTO t2 VALUES (10360,99,0,0);
+INSERT INTO t2 VALUES (11411,30,10,0);
+INSERT INTO t2 VALUES (11404,0,0,0);
+INSERT INTO t2 VALUES (10362,11,111,0);
+INSERT INTO t2 VALUES (10363,33,333,0);
+INSERT INTO t2 VALUES (11412,55,0,0);
+INSERT INTO t2 VALUES (50003,66,6,0);
+INSERT INTO t2 VALUES (11403,5,0,0);
+INSERT INTO t2 VALUES (11406,11,11,0);
+INSERT INTO t2 VALUES (11410,11410,131,0);
+INSERT INTO t2 VALUES (11416,11416,32767,0);
+INSERT INTO t2 VALUES (11409,0,0,0);
+CREATE TABLE t3 (
+id int(11) DEFAULT '0' NOT NULL auto_increment,
+dni_pasaporte char(16) DEFAULT '' NOT NULL,
+idPla int(11) DEFAULT '0' NOT NULL,
+cod_asig int(11) DEFAULT '0' NOT NULL,
+any smallint(6) DEFAULT '0' NOT NULL,
+quatrimestre smallint(6) DEFAULT '0' NOT NULL,
+estat char(1) DEFAULT 'M' NOT NULL,
+PRIMARY KEY (id),
+UNIQUE dni_pasaporte (dni_pasaporte,idPla),
+UNIQUE dni_pasaporte_2 (dni_pasaporte,idPla,cod_asig,any,quatrimestre)
+);
+INSERT INTO t3 VALUES (1,'11111111',1,10362,98,1,'M');
+CREATE TABLE t4 (
+id int(11) DEFAULT '0' NOT NULL auto_increment,
+papa int(11) DEFAULT '0' NOT NULL,
+fill int(11) DEFAULT '0' NOT NULL,
+idPla int(11) DEFAULT '0' NOT NULL,
+PRIMARY KEY (id),
+KEY papa (idPla,papa),
+UNIQUE papa_2 (idPla,papa,fill)
+);
+INSERT INTO t4 VALUES (1,-1,10360,1);
+INSERT INTO t4 VALUES (2,-1,10361,1);
+INSERT INTO t4 VALUES (3,-1,10362,1);
+SELECT DISTINCT fill,desc_larga_cat,cred_total,Grup,Places,PlacesOcupades FROM t4 LEFT JOIN t3 ON t3.cod_asig=fill AND estat='S' AND dni_pasaporte='11111111' AND t3.idPla=1 , t2,t1 WHERE fill=t1.cod_asig AND Places>PlacesOcupades AND fill=idAssignatura AND t4.idPla=1 AND papa=-1;
fill desc_larga_cat cred_total Grup Places PlacesOcupades
10360 asdfggfg 6.0 0 55 0
10360 asdfggfg 6.0 12 333 0
@@ -116,49 +272,82 @@ fill desc_larga_cat cred_total Grup Places PlacesOcupades
10361 Components i Circuits Electronics I 6.0 40 3 0
10362 Laboratori d`Ordinadors 4.5 10 12 0
10362 Laboratori d`Ordinadors 4.5 11 111 0
+SELECT DISTINCT fill,t3.idPla FROM t4 LEFT JOIN t3 ON t3.cod_asig=t4.fill AND t3.estat='S' AND t3.dni_pasaporte='1234' AND t3.idPla=1 ;
fill idPla
10360 NULL
10361 NULL
10362 NULL
+INSERT INTO t3 VALUES (3,'1234',1,10360,98,1,'S');
+SELECT DISTINCT fill,t3.idPla FROM t4 LEFT JOIN t3 ON t3.cod_asig=t4.fill AND t3.estat='S' AND t3.dni_pasaporte='1234' AND t3.idPla=1 ;
fill idPla
10360 1
10361 NULL
10362 NULL
+drop table t1,t2,t3,test.t4;
+CREATE TABLE t1 (
+id smallint(5) unsigned DEFAULT '0' NOT NULL auto_increment,
+name char(60) DEFAULT '' NOT NULL,
+PRIMARY KEY (id)
+);
+INSERT INTO t1 VALUES (1,'Antonio Paz');
+INSERT INTO t1 VALUES (2,'Lilliana Angelovska');
+INSERT INTO t1 VALUES (3,'Thimble Smith');
+CREATE TABLE t2 (
+id smallint(5) unsigned DEFAULT '0' NOT NULL auto_increment,
+owner smallint(5) unsigned DEFAULT '0' NOT NULL,
+name char(60),
+PRIMARY KEY (id)
+);
+INSERT INTO t2 VALUES (1,1,'El Gato');
+INSERT INTO t2 VALUES (2,1,'Perrito');
+INSERT INTO t2 VALUES (3,3,'Happy');
+select t1.name, t2.name, t2.id from t1 left join t2 on (t1.id = t2.owner);
name name id
Antonio Paz El Gato 1
Antonio Paz Perrito 2
Lilliana Angelovska NULL NULL
Thimble Smith Happy 3
+select t1.name, t2.name, t2.id from t1 left join t2 on (t1.id = t2.owner) where t2.id is null;
name name id
Lilliana Angelovska NULL NULL
+explain select t1.name, t2.name, t2.id from t1 left join t2 on (t1.id = t2.owner) where t2.id is null;
table type possible_keys key key_len ref rows Extra
t1 ALL NULL NULL NULL NULL 3
t2 ALL NULL NULL NULL NULL 3 where used; Not exists
+explain select t1.name, t2.name, t2.id from t1 left join t2 on (t1.id = t2.owner) where t2.name is null;
table type possible_keys key key_len ref rows Extra
t1 ALL NULL NULL NULL NULL 3
t2 ALL NULL NULL NULL NULL 3 where used
+select count(*) from t1 left join t2 on (t1.id = t2.owner);
count(*)
4
+select t1.name, t2.name, t2.id from t2 right join t1 on (t1.id = t2.owner);
name name id
Antonio Paz El Gato 1
Antonio Paz Perrito 2
Lilliana Angelovska NULL NULL
Thimble Smith Happy 3
+select t1.name, t2.name, t2.id from t2 right join t1 on (t1.id = t2.owner) where t2.id is null;
name name id
Lilliana Angelovska NULL NULL
+explain select t1.name, t2.name, t2.id from t2 right join t1 on (t1.id = t2.owner) where t2.id is null;
table type possible_keys key key_len ref rows Extra
t1 ALL NULL NULL NULL NULL 3
t2 ALL NULL NULL NULL NULL 3 where used; Not exists
+explain select t1.name, t2.name, t2.id from t2 right join t1 on (t1.id = t2.owner) where t2.name is null;
table type possible_keys key key_len ref rows Extra
t1 ALL NULL NULL NULL NULL 3
t2 ALL NULL NULL NULL NULL 3 where used
+select count(*) from t2 right join t1 on (t1.id = t2.owner);
count(*)
4
+select t1.name, t2.name, t2.id,t3.id from t2 right join t1 on (t1.id = t2.owner) left join t1 as t3 on t3.id=t2.owner;
name name id id
Antonio Paz El Gato 1 1
Antonio Paz Perrito 2 1
Lilliana Angelovska NULL NULL NULL
Thimble Smith Happy 3 3
+select t1.name, t2.name, t2.id,t3.id from t1 right join t2 on (t1.id = t2.owner) right join t1 as t3 on t3.id=t2.owner;
name name id id
Antonio Paz El Gato 1 1
Antonio Paz Perrito 2 1
@@ -169,6 +358,7 @@ NULL Happy 3 2
NULL El Gato 1 3
NULL Perrito 2 3
Thimble Smith Happy 3 3
+select t1.name, t2.name, t2.id, t2.owner, t3.id from t1 left join t2 on (t1.id = t2.owner) right join t1 as t3 on t3.id=t2.owner;
name name id owner id
Antonio Paz El Gato 1 1 1
Antonio Paz Perrito 2 1 1
@@ -180,49 +370,136 @@ Thimble Smith NULL NULL NULL 2
Antonio Paz NULL NULL NULL 3
Lilliana Angelovska NULL NULL NULL 3
Thimble Smith Happy 3 3 3
+drop table t1,t2;
+create table t1 (id int not null, str char(10), index(str));
+insert into t1 values (1, null), (2, null), (3, "foo"), (4, "bar");
+select * from t1 where str is not null;
id str
4 bar
3 foo
+select * from t1 where str is null;
id str
1 NULL
2 NULL
+drop table t1;
+CREATE TABLE t1 (
+t1_id bigint(21) DEFAULT '0' NOT NULL auto_increment,
+PRIMARY KEY (t1_id)
+);
+CREATE TABLE t2 (
+t2_id bigint(21) DEFAULT '0' NOT NULL auto_increment,
+PRIMARY KEY (t2_id)
+);
+CREATE TABLE t3 (
+t3_id bigint(21) DEFAULT '0' NOT NULL auto_increment,
+PRIMARY KEY (t3_id)
+);
+CREATE TABLE t4 (
+seq_0_id bigint(21) DEFAULT '0' NOT NULL,
+seq_1_id bigint(21) DEFAULT '0' NOT NULL,
+KEY seq_0_id (seq_0_id),
+KEY seq_1_id (seq_1_id)
+);
+CREATE TABLE t5 (
+seq_0_id bigint(21) DEFAULT '0' NOT NULL,
+seq_1_id bigint(21) DEFAULT '0' NOT NULL,
+KEY seq_1_id (seq_1_id),
+KEY seq_0_id (seq_0_id)
+);
+insert into t1 values (1);
+insert into t2 values (1);
+insert into t3 values (1);
+insert into t4 values (1,1);
+insert into t5 values (1,1);
+explain select * from t3 left join t4 on t4.seq_1_id = t2.t2_id left join t1 on t1.t1_id = t4.seq_0_id left join t5 on t5.seq_0_id = t1.t1_id left join t2 on t2.t2_id = t5.seq_1_id where t3.t3_id = 23;
+Cross dependency found in OUTER JOIN. Examine your ON conditions
+drop table t1,t2,t3,t4,t5;
+create table t1 (n int, m int, o int, key(n));
+create table t2 (n int not null, m int, o int, primary key(n));
+insert into t1 values (1, 2, 11), (1, 2, 7), (2, 2, 8), (1,2,9),(1,3,9);
+insert into t2 values (1, 2, 3),(2, 2, 8), (4,3,9),(3,2,10);
+select t1.*, t2.* from t1 left join t2 on t1.n = t2.n and
+t1.m = t2.m where t1.n = 1;
n m o n m o
1 2 11 1 2 3
1 2 7 1 2 3
1 2 9 1 2 3
1 3 9 NULL NULL NULL
+select t1.*, t2.* from t1 left join t2 on t1.n = t2.n and
+t1.m = t2.m where t1.n = 1 order by t1.o;
n m o n m o
1 2 7 1 2 3
1 2 9 1 2 3
1 3 9 NULL NULL NULL
1 2 11 1 2 3
+drop table t1,t2;
+CREATE TABLE t1 (id1 INT NOT NULL PRIMARY KEY, dat1 CHAR(1), id2 INT);
+INSERT INTO t1 VALUES (1,'a',1);
+INSERT INTO t1 VALUES (2,'b',1);
+INSERT INTO t1 VALUES (3,'c',2);
+CREATE TABLE t2 (id2 INT NOT NULL PRIMARY KEY, dat2 CHAR(1));
+INSERT INTO t2 VALUES (1,'x');
+INSERT INTO t2 VALUES (2,'y');
+INSERT INTO t2 VALUES (3,'z');
+SELECT t2.id2 FROM t2 LEFT OUTER JOIN t1 ON t1.id2 = t2.id2 WHERE id1 IS NULL;
id2
3
+SELECT t2.id2 FROM t2 NATURAL LEFT OUTER JOIN t1 WHERE id1 IS NULL;
id2
3
+drop table t1,t2;
+create table t1 ( color varchar(20), name varchar(20) );
+insert into t1 values ( 'red', 'apple' );
+insert into t1 values ( 'yellow', 'banana' );
+insert into t1 values ( 'green', 'lime' );
+insert into t1 values ( 'black', 'grape' );
+insert into t1 values ( 'blue', 'blueberry' );
+create table t2 ( count int, color varchar(20) );
+insert into t2 values (10, 'green');
+insert into t2 values (5, 'black');
+insert into t2 values (15, 'white');
+insert into t2 values (7, 'green');
+select * from t1;
color name
red apple
yellow banana
green lime
black grape
blue blueberry
+select * from t2;
count color
10 green
5 black
15 white
7 green
+select * from t2 natural join t1;
count color color name
10 green green lime
7 green green lime
5 black black grape
+select t2.count, t1.name from t2 natural join t1;
count name
10 lime
7 lime
5 grape
+select t2.count, t1.name from t2 inner join t1 using (color);
count name
10 lime
7 lime
5 grape
+drop table t1;
+drop table t2;
+CREATE TABLE t1 (
+pcode varchar(8) DEFAULT '' NOT NULL
+);
+INSERT INTO t1 VALUES ('kvw2000'),('kvw2001'),('kvw3000'),('kvw3001'),('kvw3002'),('kvw3500'),('kvw3501'),('kvw3502'),('kvw3800'),('kvw3801'),('kvw3802'),('kvw3900'),('kvw3901'),('kvw3902'),('kvw4000'),('kvw4001'),('kvw4002'),('kvw4200'),('kvw4500'),('kvw5000'),('kvw5001'),('kvw5500'),('kvw5510'),('kvw5600'),('kvw5601'),('kvw6000'),('klw1000'),('klw1020'),('klw1500'),('klw2000'),('klw2001'),('klw2002'),('kld2000'),('klw2500'),('kmw1000'),('kmw1500'),('kmw2000'),('kmw2001'),('kmw2100'),('kmw3000'),('kmw3200');
+CREATE TABLE t2 (
+pcode varchar(8) DEFAULT '' NOT NULL,
+KEY pcode (pcode)
+);
+INSERT INTO t2 VALUES ('kvw2000'),('kvw2000'),('kvw2000'),('kvw2000'),('kvw2000'),('kvw2000'),('kvw2000'),('kvw2000'),('kvw2000'),('kvw2000'),('kvw2000'),('kvw2000'),('kvw2000'),('kvw2000'),('kvw2000'),('kvw2000'),('kvw2000'),('kvw2000'),('kvw2000'),('kvw2000'),('kvw2000'),('kvw2000'),('kvw2000'),('kvw2000'),('kvw2000'),('kvw2000'),('kvw3000'),('kvw3000'),('kvw3000'),('kvw3000'),('kvw3000'),('kvw3000'),('kvw3000'),('kvw3000'),('kvw3000'),('kvw3000'),('kvw3000'),('kvw3000'),('kvw3000'),('kvw3000'),('kvw3000'),('kvw3000'),('kvw3000'),('kvw3000'),('kvw3000'),('kvw3000'),('kvw3000'),('kvw3000'),('kvw3000'),('kvw3000'),('kvw3000'),('kvw3000'),('kvw3000'),('kvw3000'),('kvw3000'),('kvw3000'),('kvw3000'),('kvw3000'),('kvw3000'),('kvw3000'),('kvw3000'),('kvw3000'),('kvw3500'),('kvw3500'),('kvw3500'),('kvw3500'),('kvw3500'),('kvw3500'),('kvw3500'),('kvw3500'),('kvw3500'),('kvw3500'),('kvw3500'),('kvw3500'),('kvw3500'),('kvw3500'),('kvw3500'),('kvw3500'),('kvw3500'),('kvw3500'),('kvw3500'),('kvw3500'),('kvw3500'),('kvw3500'),('kvw3500'),('kvw3500'),('kvw3500'),('kvw3500'),('kvw6000'),('kvw6000'),('kld2000');
+SELECT t1.pcode, IF(ISNULL(t2.pcode), 0, COUNT(*)) AS count FROM t1
+LEFT JOIN t2 ON t1.pcode = t2.pcode GROUP BY t1.pcode;
pcode count
kld2000 1
klw1000 0
@@ -265,6 +542,7 @@ kvw5510 0
kvw5600 0
kvw5601 0
kvw6000 2
+SELECT SQL_BIG_RESULT t1.pcode, IF(ISNULL(t2.pcode), 0, COUNT(*)) AS count FROM t1 LEFT JOIN t2 ON t1.pcode = t2.pcode GROUP BY t1.pcode;
pcode count
kld2000 1
klw1000 0
@@ -307,27 +585,70 @@ kvw5510 0
kvw5600 0
kvw5601 0
kvw6000 2
+drop table t1,t2;
+CREATE TABLE t1 (
+id int(11),
+pid int(11),
+rep_del tinyint(4),
+KEY id (id),
+KEY pid (pid)
+);
+INSERT INTO t1 VALUES (1,NULL,NULL);
+INSERT INTO t1 VALUES (2,1,NULL);
+select * from t1 LEFT JOIN t1 t2 ON (t1.id=t2.pid) AND t2.rep_del IS NULL;
id pid rep_del id pid rep_del
1 NULL NULL 2 1 NULL
2 1 NULL NULL NULL NULL
+create index rep_del ON t1(rep_del);
+select * from t1 LEFT JOIN t1 t2 ON (t1.id=t2.pid) AND t2.rep_del IS NULL;
id pid rep_del id pid rep_del
1 NULL NULL 2 1 NULL
2 1 NULL NULL NULL NULL
+drop table t1;
+CREATE TABLE t1 (
+id int(11) DEFAULT '0' NOT NULL,
+name tinytext DEFAULT '' NOT NULL,
+UNIQUE id (id)
+);
+INSERT INTO t1 VALUES (1,'yes'),(2,'no');
+CREATE TABLE t2 (
+id int(11) DEFAULT '0' NOT NULL,
+idx int(11) DEFAULT '0' NOT NULL,
+UNIQUE id (id,idx)
+);
+INSERT INTO t2 VALUES (1,1);
+explain SELECT * from t1 left join t2 on t1.id=t2.id where t2.id IS NULL;
table type possible_keys key key_len ref rows Extra
t1 ALL NULL NULL NULL NULL 2
t2 index id id 8 NULL 1 where used; Using index; Not exists
+SELECT * from t1 left join t2 on t1.id=t2.id where t2.id IS NULL;
id name id idx
2 no NULL NULL
+drop table t1,t2;
+create table t1 (bug_id mediumint, reporter mediumint);
+create table t2 (bug_id mediumint, who mediumint, index(who));
+insert into t2 values (1,1),(1,2);
+insert into t1 values (1,1),(2,1);
+SELECT * FROM t1 LEFT JOIN t2 ON (t1.bug_id = t2.bug_id AND t2.who = 2) WHERE (t1.reporter = 2 OR t2.who = 2);
bug_id reporter bug_id who
1 1 1 2
+drop table t1,t2;
+create table t1 (fooID smallint unsigned auto_increment, primary key (fooID));
+create table t2 (fooID smallint unsigned not null, barID smallint unsigned not null, primary key (fooID,barID));
+insert into t1 (fooID) values (10),(20),(30);
+insert into t2 values (10,1),(20,2),(30,3);
+explain select * from t2 left join t1 on t1.fooID = t2.fooID and t1.fooID = 30;
table type possible_keys key key_len ref rows Extra
t2 index NULL PRIMARY 4 NULL 3 Using index
t1 eq_ref PRIMARY PRIMARY 2 const 1 where used; Using index
+select * from t2 left join t1 on t1.fooID = t2.fooID and t1.fooID = 30;
fooID barID fooID
10 1 NULL
20 2 NULL
30 3 30
+select * from t2 left join t1 ignore index(primary) on t1.fooID = t2.fooID and t1.fooID = 30;
fooID barID fooID
10 1 NULL
20 2 NULL
30 3 30
+drop table t1,t2;
diff --git a/mysql-test/r/key.result b/mysql-test/r/key.result
index dbdec824d3b..6dfe0809e7f 100644
--- a/mysql-test/r/key.result
+++ b/mysql-test/r/key.result
@@ -1,19 +1,149 @@
+drop table if exists t1,t2,t3;
+CREATE TABLE t1 (
+ID CHAR(32) NOT NULL,
+name CHAR(32) NOT NULL,
+value CHAR(255),
+INDEX indexIDname (ID(8),name(8))
+) ;
+INSERT INTO t1 VALUES
+('keyword','indexdir','/export/home/local/www/database/indexes/keyword');
+INSERT INTO t1 VALUES ('keyword','urlprefix','text/ /text');
+INSERT INTO t1 VALUES ('keyword','urlmap','/text/ /');
+INSERT INTO t1 VALUES ('keyword','attr','personal employee company');
+INSERT INTO t1 VALUES
+('emailgids','indexdir','/export/home/local/www/database/indexes/emailgids');
+INSERT INTO t1 VALUES ('emailgids','urlprefix','text/ /text');
+INSERT INTO t1 VALUES ('emailgids','urlmap','/text/ /');
+INSERT INTO t1 VALUES ('emailgids','attr','personal employee company');
+SELECT value FROM t1 WHERE ID='emailgids' AND name='attr';
value
personal employee company
+drop table t1;
+CREATE TABLE t1 (
+price int(5) DEFAULT '0' NOT NULL,
+area varchar(40) DEFAULT '' NOT NULL,
+type varchar(40) DEFAULT '' NOT NULL,
+transityes enum('Y','N') DEFAULT 'Y' NOT NULL,
+shopsyes enum('Y','N') DEFAULT 'Y' NOT NULL,
+schoolsyes enum('Y','N') DEFAULT 'Y' NOT NULL,
+petsyes enum('Y','N') DEFAULT 'Y' NOT NULL,
+KEY price (price,area,type,transityes,shopsyes,schoolsyes,petsyes)
+);
+INSERT INTO t1 VALUES (900,'Vancouver','Shared/Roomate','N','N','N','N');
+INSERT INTO t1 VALUES (900,'Vancouver','Shared/Roomate','N','N','N','N');
+INSERT INTO t1 VALUES (900,'Vancouver','Shared/Roomate','','','','');
+INSERT INTO t1 VALUES (900,'Vancouver','Shared/Roomate','Y','Y','Y','Y');
+INSERT INTO t1 VALUES (900,'Vancouver','Shared/Roomate','Y','Y','Y','Y');
+INSERT INTO t1 VALUES (900,'Vancouver','Shared/Roomate','Y','Y','Y','Y');
+INSERT INTO t1 VALUES (900,'Vancouver','Shared/Roomate','Y','Y','Y','Y');
+INSERT INTO t1 VALUES (900,'Vancouver','Shared/Roomate','Y','Y','Y','Y');
+SELECT * FROM t1 WHERE area='Vancouver' and transityes='y' and schoolsyes='y' and ( ((type='1 Bedroom' or type='Studio/Bach') and (price<=500)) or ((type='2 Bedroom') and (price<=550)) or ((type='Shared/Roomate') and (price<=300)) or ((type='Room and Board') and (price<=500)) ) and price <= 400;
price area type transityes shopsyes schoolsyes petsyes
+drop table t1;
+CREATE TABLE t1 (program enum('signup','unique','sliding') not null, type enum('basic','sliding','signup'), sites set('mt'), PRIMARY KEY (program));
+ALTER TABLE t1 modify program enum('signup','unique','sliding');
+All parts of a PRIMARY KEY must be NOT NULL; If you need NULL in a key, use UNIQUE instead
+drop table t1;
+CREATE TABLE t1 (
+name varchar(50) DEFAULT '' NOT NULL,
+author varchar(50) DEFAULT '' NOT NULL,
+category decimal(10,0) DEFAULT '0' NOT NULL,
+email varchar(50),
+password varchar(50),
+proxy varchar(50),
+bitmap varchar(20),
+msg varchar(255),
+urlscol varchar(127),
+urlhttp varchar(127),
+timeout decimal(10,0),
+nbcnx decimal(10,0),
+creation decimal(10,0),
+livinguntil decimal(10,0),
+lang decimal(10,0),
+type decimal(10,0),
+subcat decimal(10,0),
+subtype decimal(10,0),
+reg char(1),
+scs varchar(255),
+capacity decimal(10,0),
+userISP varchar(50),
+CCident varchar(50) DEFAULT '' NOT NULL,
+PRIMARY KEY (name,author,category)
+);
+INSERT INTO t1 VALUES
+('patnom','patauteur',0,'p.favre@cryo-networks.fr',NULL,NULL,'#p2sndnq6ae5g1u6t','essai\nsalut','scol://195.242.78.119:patauteur.patnom',NULL,NULL,NULL,950036174,-882087474,NULL,3,0,3,'1','Pub/patnom/futur_divers.scs',NULL,'pat','CC1');
+INSERT INTO t1 VALUES
+('LeNomDeMonSite','Marc',0,'m.barilley@cryo-networks.fr',NULL,NULL,NULL,NULL,'scol://195.242.78.119:Marc.LeNomDeMonSite',NULL,NULL,NULL,950560434,-881563214,NULL,3,0,3,'1','Pub/LeNomDeMonSite/domus_hibere.scs',NULL,'Marq','CC1');
+select * from t1 where name='patnom' and author='patauteur' and category=0;
name author category email password proxy bitmap msg urlscol urlhttp timeout nbcnx creation livinguntil lang type subcat subtype reg scs capacity userISP CCident
patnom patauteur 0 p.favre@cryo-networks.fr NULL NULL #p2sndnq6ae5g1u6t essai
salut scol://195.242.78.119:patauteur.patnom NULL NULL NULL 950036174 -882087474 NULL 3 0 3 1 Pub/patnom/futur_divers.scs NULL pat CC1
+drop table t1;
+create table t1
+(
+name_id int not null auto_increment,
+name blob,
+INDEX name_idx (name(5)),
+primary key (name_id)
+);
+INSERT t1 VALUES(NULL,'/');
+INSERT t1 VALUES(NULL,'[T,U]_axpby');
+SELECT * FROM t1 WHERE name='[T,U]_axpy';
name_id name
+SELECT * FROM t1 WHERE name='[T,U]_axpby';
name_id name
2 [T,U]_axpby
+create table t2
+(
+name_id int not null auto_increment,
+name char(255) binary,
+INDEX name_idx (name(5)),
+primary key (name_id)
+);
+INSERT t2 select * from t1;
+SELECT * FROM t2 WHERE name='[T,U]_axpy';
name_id name
+SELECT * FROM t2 WHERE name='[T,U]_axpby';
name_id name
2 [T,U]_axpby
+drop table t1,t2;
+create table t1
+(
+SEQNO numeric(12 ) not null,
+MOTYPEID numeric(12 ) not null,
+MOINSTANCEID numeric(12 ) not null,
+ATTRID numeric(12 ) not null,
+VALUE varchar(120) not null,
+primary key (SEQNO, MOTYPEID, MOINSTANCEID, ATTRID, VALUE )
+);
+INSERT INTO t1 VALUES (1, 1, 1, 1, 'a');
+INSERT INTO t1 VALUES (1, 1, 1, 1, 'b');
+INSERT INTO t1 VALUES (1, 1, 1, 1, 'a');
+Duplicate entry '1-1-1-1-a' for key 1
+drop table t1;
+CREATE TABLE t1 (
+a tinytext NOT NULL,
+b tinyint(3) unsigned NOT NULL default '0',
+PRIMARY KEY (a(32),b)
+) TYPE=MyISAM;
+INSERT INTO t1 VALUES ('a',1),('a',2);
+SELECT * FROM t1 WHERE a='a' AND b=2;
a b
a 2
+SELECT * FROM t1 WHERE a='a' AND b in (2);
a b
a 2
+SELECT * FROM t1 WHERE a='a' AND b in (1,2);
a b
a 1
a 2
+drop table t1;
+create table t1 (a int not null unique, b int unique, c int, d int not null primary key, key(c), e int not null unique);
+show keys from t1;
+Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
+t1 0 PRIMARY 1 d A 0 NULL NULL BTREE
+t1 0 a 1 a A 0 NULL NULL BTREE
+t1 0 e 1 e A 0 NULL NULL BTREE
+t1 0 b 1 b A NULL NULL NULL YES BTREE
+t1 1 c 1 c A NULL NULL NULL YES BTREE
+drop table t1;
diff --git a/mysql-test/r/key_diff.result b/mysql-test/r/key_diff.result
index ab5b9bcc0e7..0886850f38a 100644
--- a/mysql-test/r/key_diff.result
+++ b/mysql-test/r/key_diff.result
@@ -1,3 +1,12 @@
+drop table if exists t1;
+CREATE TABLE t1 (
+a char(5) NOT NULL,
+b char(4) NOT NULL,
+KEY (a),
+KEY (b)
+);
+INSERT INTO t1 VALUES ('A','B'),('b','A'),('C','c'),('D','E'),('a','a');
+select * from t1,t1 as t2;
a b a b
A B A B
b A A B
@@ -24,9 +33,11 @@ b A a a
C c a a
D E a a
a a a a
+explain select t1.*,t2.* from t1,t1 as t2 where t1.A=t2.B;
table type possible_keys key key_len ref rows Extra
t1 ALL a NULL NULL NULL 5
t2 ALL b NULL NULL NULL 5 where used
+select t1.*,t2.* from t1,t1 as t2 where t1.A=t2.B order by binary t1.a,t2.a;
a b a b
A B a a
A B b A
@@ -34,6 +45,8 @@ C c C c
a a a a
a a b A
b A A B
+select * from t1 where a='a';
a b
A B
a a
+drop table t1;
diff --git a/mysql-test/r/key_primary.result b/mysql-test/r/key_primary.result
index ee0c1c957dc..10771a134fc 100644
--- a/mysql-test/r/key_primary.result
+++ b/mysql-test/r/key_primary.result
@@ -1,9 +1,19 @@
+create table t1 (t1 char(3) primary key);
+insert into t1 values("ABC");
+insert into t1 values("ABA");
+insert into t1 values("AB%");
+select * from t1 where t1="ABC";
t1
ABC
+select * from t1 where t1="ABCD";
t1
+select * from t1 where t1 like "a_\%";
t1
AB%
+describe select * from t1 where t1="ABC";
table type possible_keys key key_len ref rows Extra
t1 const PRIMARY PRIMARY 3 const 1
+describe select * from t1 where t1="ABCD";
Comment
Impossible WHERE noticed after reading const tables
+drop table t1;
diff --git a/mysql-test/r/keywords.result b/mysql-test/r/keywords.result
index f49681ad93b..2ca36425841 100644
--- a/mysql-test/r/keywords.result
+++ b/mysql-test/r/keywords.result
@@ -1,4 +1,16 @@
+drop table if exists t1;
+create table t1 (time time, date date, timestamp timestamp);
+insert into t1 values ("12:22:22","97:02:03","1997-01-02");
+select * from t1;
time date timestamp
12:22:22 1997-02-03 19970102000000
+select t1.time+0,t1.date+0,t1.timestamp+0,concat(date," ",time) from t1;
t1.time+0 t1.date+0 t1.timestamp+0 concat(date," ",time)
122222 19970203 19970102000000 1997-02-03 12:22:22
+drop table t1;
+create table events(binlog int);
+insert into events values(1);
+select events.binlog from events;
+binlog
+1
+drop table events;
diff --git a/mysql-test/r/kill.result b/mysql-test/r/kill.result
index 628c6d21094..788fab8d31a 100644
--- a/mysql-test/r/kill.result
+++ b/mysql-test/r/kill.result
@@ -1,4 +1,11 @@
+drop table if exists t1;
+create table t1 (kill_id int);
+insert into t1 values(connection_id());
+select ((@id := kill_id) - kill_id) from t1;
((@id := kill_id) - kill_id)
0
+kill @id;
+select 4;
4
4
+drop table t1;
diff --git a/mysql-test/r/limit.result b/mysql-test/r/limit.result
index 6c3a1ed17e4..5a8edc99c12 100644
--- a/mysql-test/r/limit.result
+++ b/mysql-test/r/limit.result
@@ -1,25 +1,52 @@
+drop table if exists t1;
+create table t1 (a int primary key, b int not null);
+insert into t1 () values ();
+insert into t1 values (1,1),(2,1),(3,1);
+update t1 set a=4 where b=1 limit 1;
+select * from t1;
a b
0 0
4 1
2 1
3 1
+update t1 set b=2 where b=1 limit 2;
+select * from t1;
a b
0 0
4 2
2 2
3 1
+update t1 set b=4 where b=1;
+select * from t1;
a b
0 0
4 2
2 2
3 4
+delete from t1 where b=2 limit 1;
+select * from t1;
a b
0 0
2 2
3 4
+delete from t1 limit 1;
+select * from t1;
a b
2 2
3 4
+drop table t1;
+create table t1 (i int);
+insert into t1 (i) values(1);
+insert into t1 (i) values(1);
+insert into t1 (i) values(1);
+delete from t1 limit 1;
+update t1 set i=2 limit 1;
+delete from t1 limit 0;
+update t1 set i=3 limit 0;
+select * from t1;
i
2
1
+drop table t1;
+select 0 limit 0;
+0
diff --git a/mysql-test/r/lock.result b/mysql-test/r/lock.result
index ccd3c02558d..ad5251b9110 100644
--- a/mysql-test/r/lock.result
+++ b/mysql-test/r/lock.result
@@ -1,10 +1,45 @@
+drop table if exists t1,t2;
+CREATE TABLE t1 ( `id` int(11) NOT NULL default '0', `id2` int(11) NOT NULL default '0', `id3` int(11) NOT NULL default '0', `dummy1` char(30) default NULL, PRIMARY KEY (`id`,`id2`), KEY `index_id3` (`id3`)) TYPE=MyISAM;
+insert into t1 (id,id2) values (1,1),(1,2),(1,3);
+LOCK TABLE t1 WRITE;
+select dummy1,count(distinct id) from t1 group by dummy1;
dummy1 count(distinct id)
NULL 1
+update t1 set id=-1 where id=1;
+LOCK TABLE t1 READ;
+update t1 set id=1 where id=1;
+Table 't1' was locked with a READ lock and can't be updated
+create table t2 SELECT * from t1;
+Table 't2' was not locked with LOCK TABLES
+create temporary table t2 SELECT * from t1;
+drop table if exists t2;
+unlock tables;
+create table t2 SELECT * from t1;
+LOCK TABLE t1 WRITE,t2 write;
+insert into t2 SELECT * from t1;
+update t1 set id=1 where id=-1;
+drop table t1,t2;
+CREATE TABLE t1 (
+index1 smallint(6) default NULL,
+nr smallint(6) default NULL,
+KEY index1(index1)
+) TYPE=MyISAM;
+CREATE TABLE t2 (
+nr smallint(6) default NULL,
+name varchar(20) default NULL
+) TYPE=MyISAM;
+INSERT INTO t2 VALUES (1,'item1');
+INSERT INTO t2 VALUES (2,'item2');
+lock tables t1 write, t2 read;
+insert into t1 select 1,nr from t2 where name='item1';
+insert into t1 select 2,nr from t2 where name='item2';
+unlock tables;
+check table t1;
Table Op Msg_type Msg_text
test.t1 check status OK
+lock tables t1 write;
+check table t2;
Table Op Msg_type Msg_text
test.t2 check error Table 't2' was not locked with LOCK TABLES
-n
-4
-n
-1
+unlock tables;
+drop table t1,t2;
diff --git a/mysql-test/r/lock_multi.result b/mysql-test/r/lock_multi.result
new file mode 100644
index 00000000000..6fe8cc71185
--- /dev/null
+++ b/mysql-test/r/lock_multi.result
@@ -0,0 +1,18 @@
+create table t1(n int);
+insert into t1 values (1);
+lock tables t1 write;
+ update low_priority t1 set n = 4;
+ select n from t1;
+unlock tables;
+n
+4
+drop table t1;
+create table t1(n int);
+insert into t1 values (1);
+lock tables t1 read;
+ update low_priority t1 set n = 4;
+ select n from t1;
+unlock tables;
+n
+1
+drop table t1;
diff --git a/mysql-test/r/merge.result b/mysql-test/r/merge.result
index 653e25af799..9b72ff26350 100644
--- a/mysql-test/r/merge.result
+++ b/mysql-test/r/merge.result
@@ -1,3 +1,10 @@
+drop table if exists t1,t2,t3,t4,t5,t6;
+create table t1 (a int not null primary key auto_increment, message char(20));
+create table t2 (a int not null primary key auto_increment, message char(20));
+INSERT INTO t1 (message) VALUES ("Testing"),("table"),("t1");
+INSERT INTO t2 (message) VALUES ("Testing"),("table"),("t2");
+create table t3 (a int not null, b char(20), key(a)) type=MERGE UNION=(t1,t2);
+select * from t3;
a b
1 Testing
2 table
@@ -5,6 +12,7 @@ a b
1 Testing
2 table
3 t2
+select * from t3 order by a desc;
a b
3 t1
3 t2
@@ -12,13 +20,30 @@ a b
2 table
1 Testing
1 Testing
+drop table t3;
+insert into t1 select NULL,message from t2;
+insert into t2 select NULL,message from t1;
+insert into t1 select NULL,message from t2;
+insert into t2 select NULL,message from t1;
+insert into t1 select NULL,message from t2;
+insert into t2 select NULL,message from t1;
+insert into t1 select NULL,message from t2;
+insert into t2 select NULL,message from t1;
+insert into t1 select NULL,message from t2;
+insert into t2 select NULL,message from t1;
+insert into t1 select NULL,message from t2;
+create table t3 (a int not null, b char(20), key(a)) type=MERGE UNION=(test.t1,test.t2);
+explain select * from t3 where a < 10;
table type possible_keys key key_len ref rows Extra
t3 range a a 4 NULL 10 where used
+explain select * from t3 where a > 10 and a < 20;
table type possible_keys key key_len ref rows Extra
t3 range a a 4 NULL 10 where used
+select * from t3 where a = 10;
a b
10 Testing
10 Testing
+select * from t3 where a < 10;
a b
1 Testing
1 Testing
@@ -38,6 +63,7 @@ a b
8 table
9 t2
9 t2
+select * from t3 where a > 10 and a < 20;
a b
11 table
11 table
@@ -57,8 +83,10 @@ a b
18 t2
19 Testing
19 Testing
+explain select a from t3 order by a desc limit 10;
table type possible_keys key key_len ref rows Extra
t3 index NULL a 4 NULL 1131 Using index
+select a from t3 order by a desc limit 10;
a
699
698
@@ -70,6 +98,7 @@ a
692
691
690
+select a from t3 order by a desc limit 300,10;
a
416
415
@@ -81,12 +110,87 @@ a
412
412
411
+delete from t3 where a=3;
+select * from t3 where a < 10;
+a b
+1 Testing
+1 Testing
+2 table
+2 table
+4 Testing
+4 Testing
+5 table
+5 table
+6 t2
+6 t1
+7 Testing
+7 Testing
+8 table
+8 table
+9 t2
+9 t2
+delete from t3 where a >= 6 and a <= 8;
+select * from t3 where a < 10;
+a b
+1 Testing
+1 Testing
+2 table
+2 table
+4 Testing
+4 Testing
+5 table
+5 table
+9 t2
+9 t2
+update t3 set a=3 where a=9;
+select * from t3 where a < 10;
+a b
+1 Testing
+1 Testing
+2 table
+2 table
+3 t2
+3 t2
+4 Testing
+4 Testing
+5 table
+5 table
+update t3 set a=6 where a=7;
+select * from t3 where a < 10;
+a b
+1 Testing
+1 Testing
+2 table
+2 table
+3 t2
+3 t2
+4 Testing
+4 Testing
+5 table
+5 table
+show create table t3;
Table Create Table
t3 CREATE TABLE `t3` (
`a` int(11) NOT NULL default '0',
`b` char(20) default NULL,
KEY `a` (`a`)
) TYPE=MRG_MyISAM UNION=(t1,t2)
+create table t4 (a int not null, b char(10), key(a)) type=MERGE UNION=(t1,t2);
+select * from t4;
+Can't open file: 't4.MRG'. (errno: 143)
+create table t5 (a int not null, b char(10), key(a)) type=MERGE UNION=(test.t1,test_2.t2);
+Incorrect table definition; All MERGE tables must be in the same database
+drop table if exists t5,t4,t3,t1,t2;
+create table t1 (c char(10)) type=myisam;
+create table t2 (c char(10)) type=myisam;
+create table t3 (c char(10)) union=(t1,t2) type=merge;
+insert into t1 (c) values ('test1');
+insert into t1 (c) values ('test1');
+insert into t1 (c) values ('test1');
+insert into t2 (c) values ('test2');
+insert into t2 (c) values ('test2');
+insert into t2 (c) values ('test2');
+select * from t3;
c
test1
test1
@@ -94,6 +198,7 @@ test1
test2
test2
test2
+select * from t3;
c
test1
test1
@@ -101,32 +206,259 @@ test1
test2
test2
test2
+delete from t3 where 1=1;
+select * from t3;
c
+select * from t1;
c
+drop table t3,t2,t1;
+CREATE TABLE t1 (incr int not null, othr int not null, primary key(incr));
+CREATE TABLE t2 (incr int not null, othr int not null, primary key(incr));
+CREATE TABLE t3 (incr int not null, othr int not null, primary key(incr))
+TYPE=MERGE UNION=(t1,t2);
+SELECT * from t3;
incr othr
+INSERT INTO t1 VALUES ( 1,10),( 3,53),( 5,21),( 7,12),( 9,17);
+INSERT INTO t2 VALUES ( 2,24),( 4,33),( 6,41),( 8,26),( 0,32);
+INSERT INTO t1 VALUES (11,20),(13,43),(15,11),(17,22),(19,37);
+INSERT INTO t2 VALUES (12,25),(14,31),(16,42),(18,27),(10,30);
+SELECT * from t3 where incr in (1,2,3,4) order by othr;
incr othr
1 10
2 24
4 33
3 53
+alter table t3 UNION=(t1);
+select count(*) from t3;
count(*)
10
+alter table t3 UNION=(t1,t2);
+select count(*) from t3;
count(*)
20
+alter table t3 TYPE=MYISAM;
+select count(*) from t3;
count(*)
20
+drop table t3;
+CREATE TABLE t3 (incr int not null, othr int not null, primary key(incr))
+TYPE=MERGE UNION=(t1,t2);
+show create table t3;
Table Create Table
t3 CREATE TABLE `t3` (
`incr` int(11) NOT NULL default '0',
`othr` int(11) NOT NULL default '0',
PRIMARY KEY (`incr`)
) TYPE=MRG_MyISAM UNION=(t1,t2)
+alter table t3 drop primary key;
+show create table t3;
Table Create Table
t3 CREATE TABLE `t3` (
`incr` int(11) NOT NULL default '0',
`othr` int(11) NOT NULL default '0'
) TYPE=MRG_MyISAM UNION=(t1,t2)
+drop table t3,t2,t1;
+create table t1 (a int not null) type=merge;
+select * from t1;
a
+drop table t1;
+drop table if exists t3, t2, t1;
+create table t1 (a int not null, b int not null, key(a,b));
+create table t2 (a int not null, b int not null, key(a,b));
+create table t3 (a int not null, b int not null, key(a,b)) TYPE=MERGE UNION=(t1,t2);
+insert into t1 values (1,2),(2,1),(0,0),(4,4),(5,5),(6,6);
+insert into t2 values (1,1),(2,2),(0,0),(4,4),(5,5),(6,6);
+flush tables;
+select * from t3 where a=1 order by b limit 2;
+a b
+1 1
+1 2
+drop table t3,t1,t2;
+drop table if exists t6, t5, t4, t3, t2, t1;
+create table t1 (a int not null, b int not null, key(a,b));
+create table t2 (a int not null, b int not null, key(a,b));
+create table t3 (a int not null, b int not null, key(a,b)) UNION=(t1,t2) INSERT_METHOD=NO;
+create table t4 (a int not null, b int not null, key(a,b)) TYPE=MERGE UNION=(t1,t2) INSERT_METHOD=NO;
+create table t5 (a int not null, b int not null, key(a,b)) TYPE=MERGE UNION=(t1,t2) INSERT_METHOD=FIRST;
+create table t6 (a int not null, b int not null, key(a,b)) TYPE=MERGE UNION=(t1,t2) INSERT_METHOD=LAST;
+show create table t3;
+Table Create Table
+t3 CREATE TABLE `t3` (
+ `a` int(11) NOT NULL default '0',
+ `b` int(11) NOT NULL default '0',
+ KEY `a` (`a`,`b`)
+) TYPE=MyISAM
+show create table t4;
+Table Create Table
+t4 CREATE TABLE `t4` (
+ `a` int(11) NOT NULL default '0',
+ `b` int(11) NOT NULL default '0',
+ KEY `a` (`a`,`b`)
+) TYPE=MRG_MyISAM UNION=(t1,t2)
+show create table t5;
+Table Create Table
+t5 CREATE TABLE `t5` (
+ `a` int(11) NOT NULL default '0',
+ `b` int(11) NOT NULL default '0',
+ KEY `a` (`a`,`b`)
+) TYPE=MRG_MyISAM INSERT_METHOD=FIRST UNION=(t1,t2)
+show create table t6;
+Table Create Table
+t6 CREATE TABLE `t6` (
+ `a` int(11) NOT NULL default '0',
+ `b` int(11) NOT NULL default '0',
+ KEY `a` (`a`,`b`)
+) TYPE=MRG_MyISAM INSERT_METHOD=LAST UNION=(t1,t2)
+insert into t1 values (1,1),(1,2),(1,3),(1,4);
+insert into t2 values (2,1),(2,2),(2,3),(2,4);
+select * from t3 order by b,a limit 3;
+a b
+select * from t4 order by b,a limit 3;
+a b
+1 1
+2 1
+1 2
+select * from t5 order by b,a limit 3,3;
+a b
+2 2
+1 3
+2 3
+select * from t6 order by b,a limit 6,3;
+a b
+1 4
+2 4
+insert into t5 values (5,1),(5,2);
+insert into t6 values (6,1),(6,2);
+select * from t1 order by a,b;
+a b
+1 1
+1 2
+1 3
+1 4
+5 1
+5 2
+select * from t2 order by a,b;
+a b
+2 1
+2 2
+2 3
+2 4
+6 1
+6 2
+select * from t4 order by a,b;
+a b
+1 1
+1 2
+1 3
+1 4
+2 1
+2 2
+2 3
+2 4
+5 1
+5 2
+6 1
+6 2
+insert into t3 values (3,1),(3,2),(3,3),(3,4);
+select * from t3 order by a,b;
+a b
+3 1
+3 2
+3 3
+3 4
+alter table t4 UNION=(t1,t2,t3);
+show create table t4;
+Table Create Table
+t4 CREATE TABLE `t4` (
+ `a` int(11) NOT NULL default '0',
+ `b` int(11) NOT NULL default '0',
+ KEY `a` (`a`,`b`)
+) TYPE=MRG_MyISAM UNION=(t1,t2,t3)
+select * from t4 order by a,b;
+a b
+1 1
+1 2
+1 3
+1 4
+2 1
+2 2
+2 3
+2 4
+3 1
+3 2
+3 3
+3 4
+5 1
+5 2
+6 1
+6 2
+alter table t4 INSERT_METHOD=FIRST;
+show create table t4;
+Table Create Table
+t4 CREATE TABLE `t4` (
+ `a` int(11) NOT NULL default '0',
+ `b` int(11) NOT NULL default '0',
+ KEY `a` (`a`,`b`)
+) TYPE=MRG_MyISAM INSERT_METHOD=FIRST UNION=(t1,t2,t3)
+insert into t4 values (4,1),(4,2);
+select * from t1 order by a,b;
+a b
+1 1
+1 2
+1 3
+1 4
+4 1
+4 2
+5 1
+5 2
+select * from t2 order by a,b;
+a b
+2 1
+2 2
+2 3
+2 4
+6 1
+6 2
+select * from t3 order by a,b;
+a b
+3 1
+3 2
+3 3
+3 4
+select * from t4 order by a,b;
+a b
+1 1
+1 2
+1 3
+1 4
+2 1
+2 2
+2 3
+2 4
+3 1
+3 2
+3 3
+3 4
+4 1
+4 2
+5 1
+5 2
+6 1
+6 2
+select * from t5 order by a,b;
a b
1 1
1 2
+1 3
+1 4
+2 1
+2 2
+2 3
+2 4
+4 1
+4 2
+5 1
+5 2
+6 1
+6 2
+drop table if exists t6, t5, t4, t3, t2, t1;
diff --git a/mysql-test/r/multi_update.result b/mysql-test/r/multi_update.result
new file mode 100644
index 00000000000..b1423667c44
--- /dev/null
+++ b/mysql-test/r/multi_update.result
@@ -0,0 +1,41 @@
+drop table if exists t1,t2,t3;
+create table t1(id1 int not null auto_increment primary key, t char(12));
+create table t2(id2 int not null, t char(12));
+create table t3(id3 int not null, t char(12), index(id3));
+update t1,t2,t3 set t1.t="aaa", t2.t="bbb", t3.t="cc" where t1.id1 = t2.id2 and t2.id2 = t3.id3 and t1.id1 > 90;
+delete t1.*, t2.*, t3.* from t1,t2,t3 where t1.id1 = t2.id2 and t2.id2 = t3.id3 and t1.id1 > 95;
+check table t1, t2, t3;
+Table Op Msg_type Msg_text
+test.t1 check status OK
+test.t2 check status OK
+test.t3 check status OK
+select count(*) from t1 where id1 > 95;
+count(*)
+0
+select count(*) from t2 where id2 > 95;
+count(*)
+0
+select count(*) from t3 where id3 > 95;
+count(*)
+0
+delete t1, t2, t3 from t1,t2,t3 where t1.id1 = t2.id2 and t2.id2 = t3.id3 and t1.id1 > 5;
+select count(*) from t1 where id1 > 5;
+count(*)
+0
+select count(*) from t2 where id2 > 5;
+count(*)
+0
+select count(*) from t3 where id3 > 5;
+count(*)
+0
+delete from t1, t2, t3 using t1,t2,t3 where t1.id1 = t2.id2 and t2.id2 = t3.id3 and t1.id1 > 0;
+select count(*) from t1 where id1;
+count(*)
+0
+select count(*) from t2 where id2;
+count(*)
+0
+select count(*) from t3 where id3;
+count(*)
+0
+drop table t1,t2,t3;
diff --git a/mysql-test/r/myisam.result b/mysql-test/r/myisam.result
index a8f97c57d33..c5c69c1ba7b 100644
--- a/mysql-test/r/myisam.result
+++ b/mysql-test/r/myisam.result
@@ -1,38 +1,77 @@
+drop table if exists t1;
+CREATE TABLE t1 (
+STRING_DATA char(255) default NULL,
+KEY STRING_DATA (STRING_DATA)
+) TYPE=MyISAM;
+INSERT INTO t1 VALUES ('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA');
+INSERT INTO t1 VALUES ('DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD');
+INSERT INTO t1 VALUES ('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF');
+INSERT INTO t1 VALUES ('FGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG');
+INSERT INTO t1 VALUES ('HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH');
+INSERT INTO t1 VALUES ('WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW');
+CHECK TABLE t1;
Table Op Msg_type Msg_text
test.t1 check status OK
+drop table t1;
+create table t1 (a tinyint not null auto_increment, b blob not null, primary key (a));
+check table t1;
Table Op Msg_type Msg_text
test.t1 check status OK
+repair table t1;
Table Op Msg_type Msg_text
test.t1 repair status OK
+delete from t1 where (a & 1);
+check table t1;
Table Op Msg_type Msg_text
test.t1 check status OK
+repair table t1;
Table Op Msg_type Msg_text
test.t1 repair status OK
+check table t1;
Table Op Msg_type Msg_text
test.t1 check status OK
+drop table t1;
+create table t1 (a int not null auto_increment, b int not null, primary key (a), index(b));
+insert into t1 (b) values (1),(2),(2),(2),(2);
+optimize table t1;
Table Op Msg_type Msg_text
test.t1 optimize status OK
-Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Comment
-t1 0 PRIMARY 1 a A 5 NULL NULL
-t1 1 b 1 b A 1 NULL NULL
+show index from t1;
+Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
+t1 0 PRIMARY 1 a A 5 NULL NULL BTREE
+t1 1 b 1 b A 1 NULL NULL BTREE
+optimize table t1;
Table Op Msg_type Msg_text
test.t1 optimize status Table is already up to date
-Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Comment
-t1 0 PRIMARY 1 a A 5 NULL NULL
-t1 1 b 1 b A 1 NULL NULL
+show index from t1;
+Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
+t1 0 PRIMARY 1 a A 5 NULL NULL BTREE
+t1 1 b 1 b A 1 NULL NULL BTREE
+drop table t1;
+create table t1 (a int not null, b int not null, c int not null, primary key (a),key(b)) type=myisam;
+insert into t1 values (3,3,3),(1,1,1),(2,2,2),(4,4,4);
+explain select * from t1 order by a;
table type possible_keys key key_len ref rows Extra
t1 ALL NULL NULL NULL NULL 4 Using filesort
+explain select * from t1 order by b;
table type possible_keys key key_len ref rows Extra
t1 ALL NULL NULL NULL NULL 4 Using filesort
+explain select * from t1 order by c;
table type possible_keys key key_len ref rows Extra
t1 ALL NULL NULL NULL NULL 4 Using filesort
+explain select a from t1 order by a;
table type possible_keys key key_len ref rows Extra
t1 index NULL PRIMARY 4 NULL 4 Using index
+explain select b from t1 order by b;
table type possible_keys key key_len ref rows Extra
t1 index NULL b 4 NULL 4 Using index
+explain select a,b from t1 order by b;
table type possible_keys key key_len ref rows Extra
t1 ALL NULL NULL NULL NULL 4 Using filesort
+explain select a,b from t1;
table type possible_keys key key_len ref rows Extra
t1 ALL NULL NULL NULL NULL 4
+explain select a,b,c from t1;
table type possible_keys key key_len ref rows Extra
t1 ALL NULL NULL NULL NULL 4
+drop table t1;
diff --git a/mysql-test/r/not_embedded.require b/mysql-test/r/not_embedded.require
new file mode 100644
index 00000000000..b2ea98bcd0a
--- /dev/null
+++ b/mysql-test/r/not_embedded.require
@@ -0,0 +1,2 @@
+have_embedded
+0
diff --git a/mysql-test/r/null.result b/mysql-test/r/null.result
index 9f0bdb07973..e6e3b7155a3 100644
--- a/mysql-test/r/null.result
+++ b/mysql-test/r/null.result
@@ -1,32 +1,58 @@
+select null,\N,isnull(null),isnull(1/0),isnull(1/0 = null),ifnull(null,1),ifnull(null,"TRUE"),ifnull("TRUE","ERROR"),1/0 is null,1 is not null;
NULL NULL isnull(null) isnull(1/0) isnull(1/0 = null) ifnull(null,1) ifnull(null,"TRUE") ifnull("TRUE","ERROR") 1/0 is null 1 is not null
NULL NULL 1 1 1 1 TRUE TRUE 1 1
+select 1 | NULL,1 & NULL,1+NULL,1-NULL;
1 | NULL 1 & NULL 1+NULL 1-NULL
NULL NULL NULL NULL
+select NULL=NULL,NULL<>NULL,IFNULL(NULL,1.1)+0,IFNULL(NULL,1) | 0;
NULL=NULL NULL<>NULL IFNULL(NULL,1.1)+0 IFNULL(NULL,1) | 0
NULL NULL 1.1 1
+select strcmp("a",NULL),(1<NULL)+0.0,NULL regexp "a",null like "a%","a%" like null;
strcmp("a",NULL) (1<NULL)+0.0 NULL regexp "a" null like "a%" "a%" like null
NULL NULL NULL NULL NULL
+select concat("a",NULL),replace(NULL,"a","b"),replace("string","i",NULL),replace("string",NULL,"i"),insert("abc",1,1,NULL),left(NULL,1);
concat("a",NULL) replace(NULL,"a","b") replace("string","i",NULL) replace("string",NULL,"i") insert("abc",1,1,NULL) left(NULL,1)
NULL NULL NULL NULL NULL NULL
+select repeat("a",0),repeat("ab",5+5),repeat("ab",-1),reverse(NULL);
repeat("a",0) repeat("ab",5+5) repeat("ab",-1) reverse(NULL)
abababababababababab NULL
+select field(NULL,"a","b","c");
field(NULL,"a","b","c")
0
+select 2 between null and 1,2 between 3 AND NULL,NULL between 1 and 2,2 between NULL and 3, 2 between 1 AND null;
2 between null and 1 2 between 3 AND NULL NULL between 1 and 2 2 between NULL and 3 2 between 1 AND null
0 0 NULL NULL NULL
+SELECT NULL AND NULL, 1 AND NULL, NULL AND 1, NULL OR NULL, 0 OR NULL, NULL OR 0;
NULL AND NULL 1 AND NULL NULL AND 1 NULL OR NULL 0 OR NULL NULL OR 0
NULL NULL NULL NULL NULL NULL
+SELECT (NULL OR NULL) IS NULL;
(NULL OR NULL) IS NULL
1
+select NULL AND 0, 0 and NULL;
NULL AND 0 0 and NULL
NULL 0
+select inet_ntoa(null),inet_aton(null),inet_aton("122.256"),inet_aton("122.226."),inet_aton("");
inet_ntoa(null) inet_aton(null) inet_aton("122.256") inet_aton("122.226.") inet_aton("")
NULL NULL NULL NULL NULL
+drop table if exists t1;
+create table t1 (x int);
+insert into t1 values (null);
+select * from t1 where x != 0;
x
+drop table t1;
+CREATE TABLE t1 (
+indexed_field int default NULL,
+KEY indexed_field (indexed_field)
+);
+INSERT INTO t1 VALUES (NULL),(NULL);
+SELECT * FROM t1 WHERE indexed_field=NULL;
indexed_field
+SELECT * FROM t1 WHERE indexed_field IS NULL;
indexed_field
NULL
NULL
+SELECT * FROM t1 WHERE indexed_field<=>NULL;
indexed_field
NULL
NULL
+DROP TABLE t1;
diff --git a/mysql-test/r/null_key.result b/mysql-test/r/null_key.result
index ead1dc29326..a28830a696d 100644
--- a/mysql-test/r/null_key.result
+++ b/mysql-test/r/null_key.result
@@ -1,101 +1,164 @@
+drop table if exists t1;
+create table t1 (a int, b int not null,unique key (a,b),index(b)) type=myisam;
+insert ignore into t1 values (1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(null,7),(9,9),(8,8),(7,7),(null,9),(null,9),(6,6);
+explain select * from t1 where a is null;
table type possible_keys key key_len ref rows Extra
t1 ref a a 5 const 3 where used; Using index
+explain select * from t1 where a is null and b = 2;
table type possible_keys key key_len ref rows Extra
t1 ref a,b a 9 const,const 1 where used; Using index
+explain select * from t1 where a is null and b = 7;
table type possible_keys key key_len ref rows Extra
t1 ref a,b a 9 const,const 1 where used; Using index
+explain select * from t1 where a=2 and b = 2;
table type possible_keys key key_len ref rows Extra
t1 const a,b a 9 const,const 1
+explain select * from t1 where a<=>b limit 2;
table type possible_keys key key_len ref rows Extra
t1 index NULL a 9 NULL 12 where used; Using index
+explain select * from t1 where (a is null or a > 0 and a < 3) and b < 5 limit 3;
table type possible_keys key key_len ref rows Extra
t1 range a,b a 9 NULL 3 where used; Using index
+explain select * from t1 where (a is null or a = 7) and b=7;
table type possible_keys key key_len ref rows Extra
t1 ref a,b b 4 const 2 where used
+explain select * from t1 where (a is null and b>a) or a is null and b=7 limit 2;
table type possible_keys key key_len ref rows Extra
t1 ref a,b a 5 const 3 where used; Using index
+explain select * from t1 where a is null and b=9 or a is null and b=7 limit 3;
table type possible_keys key key_len ref rows Extra
t1 range a,b a 9 NULL 2 where used; Using index
+explain select * from t1 where a > 1 and a < 3 limit 1;
table type possible_keys key key_len ref rows Extra
t1 range a a 5 NULL 1 where used; Using index
+explain select * from t1 where a > 8 and a < 9;
table type possible_keys key key_len ref rows Extra
t1 range a a 5 NULL 1 where used; Using index
+select * from t1 where a is null;
a b
NULL 7
NULL 9
NULL 9
+select * from t1 where a is null and b = 7;
a b
NULL 7
+select * from t1 where a<=>b limit 2;
a b
1 1
2 2
+select * from t1 where (a is null or a > 0 and a < 3) and b < 5 limit 3;
a b
1 1
2 2
+select * from t1 where (a is null or a > 0 and a < 3) and b > 7 limit 3;
a b
NULL 9
NULL 9
+select * from t1 where (a is null or a = 7) and b=7;
a b
NULL 7
7 7
+select * from t1 where a is null and b=9 or a is null and b=7 limit 3;
a b
NULL 7
NULL 9
NULL 9
+alter table t1 modify b blob not null, add c int not null, drop key a, add unique key (a,b(20),c), drop key b, add key (b(10));
+explain select * from t1 where a is null and b = 2;
table type possible_keys key key_len ref rows Extra
t1 ref a,b a 5 const 3 where used
+explain select * from t1 where a is null and b = 2 and c=0;
table type possible_keys key key_len ref rows Extra
t1 ref a,b a 5 const 3 where used
+explain select * from t1 where a is null and b = 7 and c=0;
table type possible_keys key key_len ref rows Extra
t1 ref a,b a 5 const 3 where used
+explain select * from t1 where a=2 and b = 2;
table type possible_keys key key_len ref rows Extra
t1 ref a,b a 5 const 1 where used
+explain select * from t1 where a<=>b limit 2;
table type possible_keys key key_len ref rows Extra
t1 ALL NULL NULL NULL NULL 12 where used
+explain select * from t1 where (a is null or a > 0 and a < 3) and b < 5 and c=0 limit 3;
table type possible_keys key key_len ref rows Extra
-t1 range a,b a 5 NULL 12 where used
+t1 range a,b a 5 NULL 5 where used
+explain select * from t1 where (a is null or a = 7) and b=7 and c=0;
table type possible_keys key key_len ref rows Extra
t1 range a,b a 5 NULL 4 where used
+explain select * from t1 where (a is null and b>a) or a is null and b=7 limit 2;
table type possible_keys key key_len ref rows Extra
t1 ref a,b a 5 const 3 where used
+explain select * from t1 where a is null and b=9 or a is null and b=7 limit 3;
table type possible_keys key key_len ref rows Extra
t1 ref a,b a 5 const 3 where used
+explain select * from t1 where a > 1 and a < 3 limit 1;
table type possible_keys key key_len ref rows Extra
t1 range a a 5 NULL 1 where used
+explain select * from t1 where a is null and b=7 or a > 1 and a < 3 limit 1;
table type possible_keys key key_len ref rows Extra
t1 range a,b a 5 NULL 4 where used
+explain select * from t1 where a > 8 and a < 9;
table type possible_keys key key_len ref rows Extra
t1 range a a 5 NULL 1 where used
+explain select * from t1 where b like "6%";
table type possible_keys key key_len ref rows Extra
t1 range b b 12 NULL 1 where used
+select * from t1 where a is null;
a b c
NULL 7 0
NULL 9 0
NULL 9 0
+select * from t1 where a is null and b = 7 and c=0;
a b c
NULL 7 0
+select * from t1 where a<=>b limit 2;
a b c
1 1 0
2 2 0
+select * from t1 where (a is null or a > 0 and a < 3) and b < 5 limit 3;
a b c
1 1 0
2 2 0
+select * from t1 where (a is null or a > 0 and a < 3) and b > 7 limit 3;
a b c
NULL 9 0
NULL 9 0
+select * from t1 where (a is null or a = 7) and b=7 and c=0;
a b c
NULL 7 0
7 7 0
+select * from t1 where a is null and b=9 or a is null and b=7 limit 3;
a b c
NULL 7 0
NULL 9 0
NULL 9 0
+select * from t1 where b like "6%";
a b c
6 6 0
+drop table t1;
+DROP TABLE IF EXISTS t1,t2;
+CREATE TABLE t1 (
+id int(10) unsigned NOT NULL auto_increment,
+uniq_id int(10) unsigned default NULL,
+PRIMARY KEY (id),
+UNIQUE KEY idx1 (uniq_id)
+) TYPE=MyISAM;
+CREATE TABLE t2 (
+id int(10) unsigned NOT NULL auto_increment,
+uniq_id int(10) unsigned default NULL,
+PRIMARY KEY (id)
+) TYPE=MyISAM;
+INSERT INTO t1 VALUES (1,NULL),(2,NULL),(3,1),(4,2),(5,NULL),(6,NULL),(7,3),(8,4),(9,NULL),(10,NULL);
+INSERT INTO t2 VALUES (1,NULL),(2,NULL),(3,1),(4,2),(5,NULL),(6,NULL),(7,3),(8,4),(9,NULL),(10,NULL);
+explain select id from t1 where uniq_id is null;
table type possible_keys key key_len ref rows Extra
t1 ref idx1 idx1 5 const 1 where used
+explain select id from t1 where uniq_id =1;
table type possible_keys key key_len ref rows Extra
t1 const idx1 idx1 5 const 1
+UPDATE t1 SET id=id+100 where uniq_id is null;
+UPDATE t2 SET id=id+100 where uniq_id is null;
+select id from t1 where uniq_id is null;
id
101
102
@@ -103,6 +166,7 @@ id
106
109
110
+select id from t2 where uniq_id is null;
id
101
102
@@ -110,13 +174,18 @@ id
106
109
110
+DELETE FROM t1 WHERE uniq_id IS NULL;
+DELETE FROM t2 WHERE uniq_id IS NULL;
+SELECT * FROM t1 ORDER BY uniq_id, id;
id uniq_id
3 1
4 2
7 3
8 4
+SELECT * FROM t2 ORDER BY uniq_id, id;
id uniq_id
3 1
4 2
7 3
8 4
+DROP table t1,t2;
diff --git a/mysql-test/r/odbc.result b/mysql-test/r/odbc.result
index 753d80e4539..c696cf94e9d 100644
--- a/mysql-test/r/odbc.result
+++ b/mysql-test/r/odbc.result
@@ -1,7 +1,15 @@
+select {fn length("hello")}, { date "1997-10-20" };
{fn length("hello")} 1997-10-20
5 1997-10-20
+create table t1 (a int not null auto_increment,b int not null,primary key (a,b));
+insert into t1 SET A=NULL,B=1;
+insert into t1 SET a=null,b=2;
+select * from t1 where a is null and b=2;
a b
2 2
+select * from t1 where a is null;
a b
+explain select * from t1 where b is null;
Comment
Impossible WHERE noticed after reading const tables
+drop table t1;
diff --git a/mysql-test/r/openssl_1.result b/mysql-test/r/openssl_1.result
new file mode 100644
index 00000000000..b5c67dfbcb0
--- /dev/null
+++ b/mysql-test/r/openssl_1.result
@@ -0,0 +1,2 @@
+SHOW STATUS LIKE 'SSL%';
+Variable_name Value
diff --git a/mysql-test/r/openssl_2.result b/mysql-test/r/openssl_2.result
new file mode 100644
index 00000000000..b5c67dfbcb0
--- /dev/null
+++ b/mysql-test/r/openssl_2.result
@@ -0,0 +1,2 @@
+SHOW STATUS LIKE 'SSL%';
+Variable_name Value
diff --git a/mysql-test/r/order_by.result b/mysql-test/r/order_by.result
index 1a292b1203c..9bc716ee8b9 100644
--- a/mysql-test/r/order_by.result
+++ b/mysql-test/r/order_by.result
@@ -1,3 +1,39 @@
+drop table if exists t1,t2,t3;
+CREATE TABLE t1 (
+id int(6) DEFAULT '0' NOT NULL,
+idservice int(5),
+clee char(20) NOT NULL,
+flag char(1),
+KEY id (id),
+PRIMARY KEY (clee)
+);
+INSERT INTO t1 VALUES (2,4,'6067169d','Y');
+INSERT INTO t1 VALUES (2,5,'606716d1','Y');
+INSERT INTO t1 VALUES (2,1,'606717c1','Y');
+INSERT INTO t1 VALUES (3,1,'6067178d','Y');
+INSERT INTO t1 VALUES (2,6,'60671515','Y');
+INSERT INTO t1 VALUES (2,7,'60671569','Y');
+INSERT INTO t1 VALUES (2,3,'dd','Y');
+CREATE TABLE t2 (
+id int(6) DEFAULT '0' NOT NULL auto_increment,
+description varchar(40) NOT NULL,
+idform varchar(40),
+ordre int(6) unsigned DEFAULT '0' NOT NULL,
+image varchar(60),
+PRIMARY KEY (id),
+KEY id (id,ordre)
+);
+INSERT INTO t2 VALUES (1,'Emettre un appel d''offres','en_construction.html',10,'emettre.gif');
+INSERT INTO t2 VALUES (2,'Emettre des soumissions','en_construction.html',20,'emettre.gif');
+INSERT INTO t2 VALUES (7,'Liste des t2','t2_liste_form.phtml',51060,'link.gif');
+INSERT INTO t2 VALUES (8,'Consulter les soumissions','consulter_soumissions.phtml',200,'link.gif');
+INSERT INTO t2 VALUES (9,'Ajouter un type de materiel','typeMateriel_ajoute_form.phtml',51000,'link.gif');
+INSERT INTO t2 VALUES (10,'Lister/modifier un type de materiel','typeMateriel_liste_form.phtml',51010,'link.gif');
+INSERT INTO t2 VALUES (3,'Créer une fiche de client','clients_ajoute_form.phtml',40000,'link.gif');
+INSERT INTO t2 VALUES (4,'Modifier des clients','en_construction.html',40010,'link.gif');
+INSERT INTO t2 VALUES (5,'Effacer des clients','en_construction.html',40020,'link.gif');
+INSERT INTO t2 VALUES (6,'Ajouter un service','t2_ajoute_form.phtml',51050,'link.gif');
+select t1.id,t1.idservice,t2.ordre,t2.description from t1, t2 where t1.id = 2 and t1.idservice = t2.id order by t2.ordre;
id idservice ordre description
2 1 10 Emettre un appel d'offres
2 3 40000 Créer une fiche de client
@@ -5,34 +41,53 @@ id idservice ordre description
2 5 40020 Effacer des clients
2 6 51050 Ajouter un service
2 7 51060 Liste des t2
+drop table t1,t2;
+create table t1 (first char(10),last char(10));
+insert into t1 values ("Michael","Widenius");
+insert into t1 values ("Allan","Larsson");
+insert into t1 values ("David","Axmark");
+select concat(first," ",last) as name from t1 order by name;
name
Allan Larsson
David Axmark
Michael Widenius
+select concat(last," ",first) as name from t1 order by name;
name
Axmark David
Larsson Allan
Widenius Michael
+drop table t1;
+create table t1 (i int);
+insert into t1 values(1),(2),(1),(2),(1),(2),(3);
+select distinct i from t1;
i
1
2
3
+select distinct i from t1 order by rand(5);
i
1
3
2
+select distinct i from t1 order by i desc;
i
3
2
1
+select distinct i from t1 order by 1-i;
i
3
2
1
+select distinct i from t1 order by mod(i,2),i;
i
2
1
3
+drop table t1;
+create table t1 (id int not null,col1 int not null,col2 int not null,index(col1));
+insert into t1 values(1,2,2),(2,2,1),(3,1,2),(4,1,1),(5,1,4),(6,2,3),(7,3,1),(8,2,4);
+select * from t1 order by col1,col2;
id col1 col2
4 1 1
3 1 2
@@ -42,6 +97,7 @@ id col1 col2
6 2 3
8 2 4
7 3 1
+select col1 from t1 order by id;
col1
2
2
@@ -51,6 +107,7 @@ col1
2
3
2
+select col1 as id from t1 order by t1.id;
id
1
1
@@ -60,6 +117,7 @@ id
2
2
3
+select concat(col1) as id from t1 order by t1.id;
id
2
2
@@ -69,21 +127,75 @@ id
2
3
2
+drop table t1;
+CREATE TABLE t1 (id int auto_increment primary key,aika varchar(40),aikakentta timestamp);
+insert into t1 (aika) values ('Keskiviikko');
+insert into t1 (aika) values ('Tiistai');
+insert into t1 (aika) values ('Maanantai');
+insert into t1 (aika) values ('Sunnuntai');
+SELECT FIELD(SUBSTRING(t1.aika,1,2),'Ma','Ti','Ke','To','Pe','La','Su') AS test FROM t1 ORDER by test;
test
1
2
3
7
+drop table t1;
+CREATE TABLE t1
+(
+a int unsigned NOT NULL,
+b int unsigned NOT NULL,
+c int unsigned NOT NULL,
+UNIQUE(a),
+INDEX(b),
+INDEX(c)
+);
+CREATE TABLE t2
+(
+c int unsigned NOT NULL,
+i int unsigned NOT NULL,
+INDEX(c)
+);
+CREATE TABLE t3
+(
+c int unsigned NOT NULL,
+v varchar(64),
+INDEX(c)
+);
+INSERT INTO t1 VALUES (1,1,1);
+INSERT INTO t1 VALUES (2,1,2);
+INSERT INTO t1 VALUES (3,2,1);
+INSERT INTO t1 VALUES (4,2,2);
+INSERT INTO t2 VALUES (1,50);
+INSERT INTO t2 VALUES (2,25);
+INSERT INTO t3 VALUES (1,'123 Park Place');
+INSERT INTO t3 VALUES (2,'453 Boardwalk');
+SELECT a,b,if(b = 1,i,if(b = 2,v,''))
+FROM t1
+LEFT JOIN t2 USING(c)
+LEFT JOIN t3 ON t3.c = t1.c;
a b if(b = 1,i,if(b = 2,v,''))
1 1 50
2 1 25
3 2 123 Park Place
4 2 453 Boardwalk
+SELECT a,b,if(b = 1,i,if(b = 2,v,''))
+FROM t1
+LEFT JOIN t2 USING(c)
+LEFT JOIN t3 ON t3.c = t1.c
+ORDER BY a;
a b if(b = 1,i,if(b = 2,v,''))
1 1 50
2 1 25
3 2 123 Park Place
4 2 453 Boardwalk
+drop table t1,t2,t3;
+create table t1 (ID int not null primary key, TransactionID int not null);
+insert into t1 (ID, TransactionID) values (1, 87), (2, 89), (3, 92), (4, 94), (5, 486), (6, 490), (7, 753), (9, 828), (10, 832), (11, 834), (12, 840);
+create table t2 (ID int not null primary key, GroupID int not null);
+insert into t2 (ID, GroupID) values (87, 87), (89, 89), (92, 92), (94, 94), (486, 486), (490, 490),(753, 753), (828, 828), (832, 832), (834, 834), (840, 840);
+create table t3 (ID int not null primary key, DateOfAction date not null);
+insert into t3 (ID, DateOfAction) values (87, '1999-07-19'), (89, '1999-07-19'), (92, '1999-07-19'), (94, '1999-07-19'), (486, '1999-07-18'), (490, '2000-03-27'), (753, '2000-03-28'), (828, '1999-07-27'), (832, '1999-07-27'),(834, '1999-07-27'), (840, '1999-07-27');
+select t3.DateOfAction, t1.TransactionID from t1 join t2 join t3 where t2.ID = t1.TransactionID and t3.ID = t2.GroupID order by t3.DateOfAction, t1.TransactionID;
DateOfAction TransactionID
1999-07-18 486
1999-07-19 87
@@ -96,6 +208,7 @@ DateOfAction TransactionID
1999-07-27 840
2000-03-27 490
2000-03-28 753
+select t3.DateOfAction, t1.TransactionID from t1 join t2 join t3 where t2.ID = t1.TransactionID and t3.ID = t2.GroupID order by t1.TransactionID,t3.DateOfAction;
DateOfAction TransactionID
1999-07-19 87
1999-07-19 89
@@ -108,9 +221,218 @@ DateOfAction TransactionID
1999-07-27 832
1999-07-27 834
1999-07-27 840
+drop table t1,t2,t3;
+drop table if exists t1;
+CREATE TABLE t1 (
+member_id int(11) NOT NULL auto_increment,
+inschrijf_datum varchar(20) NOT NULL default '',
+lastchange_datum varchar(20) NOT NULL default '',
+nickname varchar(20) NOT NULL default '',
+password varchar(8) NOT NULL default '',
+voornaam varchar(30) NOT NULL default '',
+tussenvoegsels varchar(10) NOT NULL default '',
+achternaam varchar(50) NOT NULL default '',
+straat varchar(100) NOT NULL default '',
+postcode varchar(10) NOT NULL default '',
+wijk varchar(40) NOT NULL default '',
+plaats varchar(50) NOT NULL default '',
+telefoon varchar(10) NOT NULL default '',
+geboortedatum date NOT NULL default '0000-00-00',
+geslacht varchar(5) NOT NULL default '',
+email varchar(80) NOT NULL default '',
+uin varchar(15) NOT NULL default '',
+homepage varchar(100) NOT NULL default '',
+internet varchar(15) NOT NULL default '',
+scherk varchar(30) NOT NULL default '',
+favo_boek varchar(50) NOT NULL default '',
+favo_tijdschrift varchar(50) NOT NULL default '',
+favo_tv varchar(50) NOT NULL default '',
+favo_eten varchar(50) NOT NULL default '',
+favo_muziek varchar(30) NOT NULL default '',
+info text NOT NULL,
+ipnr varchar(30) NOT NULL default '',
+PRIMARY KEY (member_id)
+) TYPE=MyISAM PACK_KEYS=1;
+insert into t1 (member_id) values (1),(2),(3);
+select member_id, nickname, voornaam FROM t1
+ORDER by lastchange_datum DESC LIMIT 2;
member_id nickname voornaam
1
2
+drop table t1;
+create table t1 (a int not null, b int, c varchar(10), key (a, b, c));
+insert into t1 values (1, NULL, NULL), (1, NULL, 'b'), (1, 1, NULL), (1, 1, 'b'), (1, 1, 'b'), (2, 1, 'a'), (2, 1, 'b'), (2, 2, 'a'), (2, 2, 'b'), (2, 3, 'c'),(1,3,'b');
+explain select * from t1 where (a = 1 and b is null and c = 'b') or (a > 2) order by a desc;
+table type possible_keys key key_len ref rows Extra
+t1 range a a 20 NULL 2 where used; Using index
+select * from t1 where (a = 1 and b is null and c = 'b') or (a > 2) order by a desc;
+a b c
+1 NULL b
+explain select * from t1 where a >= 1 and a < 3 order by a desc;
+table type possible_keys key key_len ref rows Extra
+t1 range a a 4 NULL 10 where used; Using index
+select * from t1 where a >= 1 and a < 3 order by a desc;
+a b c
+2 3 c
+2 2 b
+2 2 a
+2 1 b
+2 1 a
+1 3 b
+1 1 b
+1 1 b
+1 1 NULL
+1 NULL b
+1 NULL NULL
+explain select * from t1 where a = 1 order by a desc, b desc;
+table type possible_keys key key_len ref rows Extra
+t1 ref a a 4 const 5 where used; Using index
+select * from t1 where a = 1 order by a desc, b desc;
+a b c
+1 3 b
+1 1 b
+1 1 b
+1 1 NULL
+1 NULL b
+1 NULL NULL
+explain select * from t1 where a = 1 and b is null order by a desc, b desc;
+table type possible_keys key key_len ref rows Extra
+t1 ref a a 9 const,const 2 where used; Using index; Using filesort
+select * from t1 where a = 1 and b is null order by a desc, b desc;
+a b c
+1 NULL NULL
+1 NULL b
+explain select * from t1 where a >= 1 and a < 3 and b >0 order by a desc,b desc;
+table type possible_keys key key_len ref rows Extra
+t1 range a a 9 NULL 8 where used; Using index; Using filesort
+explain select * from t1 where a = 2 and b >0 order by a desc,b desc;
+table type possible_keys key key_len ref rows Extra
+t1 range a a 9 NULL 5 where used; Using index
+explain select * from t1 where a = 2 and b is null order by a desc,b desc;
+table type possible_keys key key_len ref rows Extra
+t1 ref a a 9 const,const 1 where used; Using index; Using filesort
+explain select * from t1 where a = 2 and (b is null or b > 0) order by a
+desc,b desc;
+table type possible_keys key key_len ref rows Extra
+t1 range a a 9 NULL 6 where used; Using index
+explain select * from t1 where a = 2 and b > 0 order by a desc,b desc;
+table type possible_keys key key_len ref rows Extra
+t1 range a a 9 NULL 5 where used; Using index
+explain select * from t1 where a = 2 and b < 2 order by a desc,b desc;
+table type possible_keys key key_len ref rows Extra
+t1 range a a 9 NULL 2 where used; Using index; Using filesort
+alter table t1 modify b int not null, modify c varchar(10) not null;
+explain select * from t1 order by a, b, c;
+table type possible_keys key key_len ref rows Extra
+t1 index NULL a 18 NULL 11 Using index
+select * from t1 order by a, b, c;
+a b c
+1 0
+1 0 b
+1 1
+1 1 b
+1 1 b
+1 3 b
+2 1 a
+2 1 b
+2 2 a
+2 2 b
+2 3 c
+explain select * from t1 order by a desc, b desc, c desc;
+table type possible_keys key key_len ref rows Extra
+t1 index NULL a 18 NULL 11 Using index
+select * from t1 order by a desc, b desc, c desc;
+a b c
+2 3 c
+2 2 b
+2 2 a
+2 1 b
+2 1 a
+1 3 b
+1 1 b
+1 1 b
+1 1
+1 0 b
+1 0
+explain select * from t1 where (a = 1 and b = 1 and c = 'b') or (a > 2) order by a desc;
+table type possible_keys key key_len ref rows Extra
+t1 range a a 18 NULL 3 where used; Using index
+select * from t1 where (a = 1 and b = 1 and c = 'b') or (a > 2) order by a desc;
+a b c
+1 1 b
+1 1 b
+explain select * from t1 where a < 2 and b <= 1 order by a desc, b desc;
+table type possible_keys key key_len ref rows Extra
+t1 range a a 4 NULL 6 where used; Using index
+select * from t1 where a < 2 and b <= 1 order by a desc, b desc;
+a b c
+1 1 b
+1 1 b
+1 1
+1 0 b
+1 0
+select count(*) from t1 where a < 5 and b > 0;
+count(*)
+9
+select * from t1 where a < 5 and b > 0 order by a desc,b desc;
+a b c
+2 3 c
+2 2 b
+2 2 a
+2 1 b
+2 1 a
+1 3 b
+1 1 b
+1 1 b
+1 1
+explain select * from t1 where a between 1 and 3 and b <= 1 order by a desc, b desc;
+table type possible_keys key key_len ref rows Extra
+t1 range a a 8 NULL 10 where used; Using index
+select * from t1 where a between 1 and 3 and b <= 1 order by a desc, b desc;
+a b c
+2 1 b
+2 1 a
+1 1 b
+1 1 b
+1 1
+1 0 b
+1 0
+explain select * from t1 where a between 0 and 1 order by a desc, b desc;
+table type possible_keys key key_len ref rows Extra
+t1 range a a 4 NULL 5 where used; Using index
+select * from t1 where a between 0 and 1 order by a desc, b desc;
+a b c
+1 3 b
+1 1 b
+1 1 b
+1 1
+1 0 b
+1 0
+drop table t1;
+CREATE TABLE t1 (
+gid int(10) unsigned NOT NULL auto_increment,
+cid smallint(5) unsigned NOT NULL default '0',
+PRIMARY KEY (gid),
+KEY component_id (cid)
+) TYPE=MyISAM;
+INSERT INTO t1 VALUES (103853,108),(103867,108),(103962,108),(104505,108),(104619,108),(104620,108);
+ALTER TABLE t1 add skr int(10) not null;
+CREATE TABLE t2 (
+gid int(10) unsigned NOT NULL default '0',
+uid smallint(5) unsigned NOT NULL default '1',
+sid tinyint(3) unsigned NOT NULL default '1',
+PRIMARY KEY (gid),
+KEY uid (uid),
+KEY status_id (sid)
+) TYPE=MyISAM;
+INSERT INTO t2 VALUES (103853,250,5),(103867,27,5),(103962,27,5),(104505,117,5),(104619,75,5),(104620,15,5);
+CREATE TABLE t3 (
+uid smallint(6) NOT NULL auto_increment,
+PRIMARY KEY (uid)
+) TYPE=MyISAM;
+INSERT INTO t3 VALUES (1),(15),(27),(75),(117),(250);
+ALTER TABLE t3 add skr int(10) not null;
+select t1.gid, t2.sid, t3.uid from t2, t1, t3 where t2.gid = t1.gid and t2.uid = t3.uid order by t3.uid, t1.gid;
gid sid uid
104620 5 15
103867 5 27
@@ -118,6 +440,7 @@ gid sid uid
104619 5 75
104505 5 117
103853 5 250
+select t1.gid, t2.sid, t3.uid from t3, t2, t1 where t2.gid = t1.gid and t2.uid = t3.uid order by t3.uid, t1.gid;
gid sid uid
104620 5 15
103867 5 27
@@ -125,20 +448,26 @@ gid sid uid
104619 5 75
104505 5 117
103853 5 250
+EXPLAIN select t1.gid, t2.sid, t3.uid from t3, t2, t1 where t2.gid = t1.gid and t2.uid = t3.uid order by t1.gid, t3.uid;
table type possible_keys key key_len ref rows Extra
t1 index PRIMARY PRIMARY 4 NULL 6 Using index
t2 eq_ref PRIMARY,uid PRIMARY 4 t1.gid 1
t3 eq_ref PRIMARY PRIMARY 2 t2.uid 1 where used; Using index
+EXPLAIN SELECT t1.gid, t3.uid from t1, t3 where t1.gid = t3.uid order by t1.gid,t3.skr;
table type possible_keys key key_len ref rows Extra
t1 index PRIMARY PRIMARY 4 NULL 6 Using index
t3 eq_ref PRIMARY PRIMARY 2 t1.gid 1 where used
+EXPLAIN SELECT t1.gid, t2.sid, t3.uid from t2, t1, t3 where t2.gid = t1.gid and t2.uid = t3.uid order by t3.uid, t1.gid;
table type possible_keys key key_len ref rows Extra
t1 index PRIMARY PRIMARY 4 NULL 6 Using index; Using temporary; Using filesort
t2 eq_ref PRIMARY,uid PRIMARY 4 t1.gid 1
t3 eq_ref PRIMARY PRIMARY 2 t2.uid 1 where used; Using index
+EXPLAIN SELECT t1.gid, t3.uid from t1, t3 where t1.gid = t3.uid order by t3.skr,t1.gid;
table type possible_keys key key_len ref rows Extra
t1 index PRIMARY PRIMARY 4 NULL 6 Using index; Using temporary; Using filesort
t3 eq_ref PRIMARY PRIMARY 2 t1.gid 1 where used
+EXPLAIN SELECT t1.gid, t3.uid from t1, t3 where t1.skr = t3.uid order by t1.gid,t3.skr;
table type possible_keys key key_len ref rows Extra
t1 ALL NULL NULL NULL NULL 6 Using temporary; Using filesort
t3 eq_ref PRIMARY PRIMARY 2 t1.skr 1 where used
+drop table t1,t2,t3;
diff --git a/mysql-test/r/order_fill_sortbuf.result b/mysql-test/r/order_fill_sortbuf.result
new file mode 100644
index 00000000000..2226e842901
--- /dev/null
+++ b/mysql-test/r/order_fill_sortbuf.result
@@ -0,0 +1,10 @@
+drop table if exists t1,t2;
+CREATE TABLE `t1` (
+`id` int(11) NOT NULL default '0',
+`id2` int(11) NOT NULL default '0',
+`id3` int(11) NOT NULL default '0');
+create table t2 select id2 from t1 order by id3;
+select count(*) from t2;
+count(*)
+4000
+drop table t1,t2;
diff --git a/mysql-test/r/overflow.result b/mysql-test/r/overflow.result
new file mode 100644
index 00000000000..a5fa7154833
--- /dev/null
+++ b/mysql-test/r/overflow.result
@@ -0,0 +1,2 @@
+drop database AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA;
+Got one of the listed errors
diff --git a/mysql-test/r/query_cache.result b/mysql-test/r/query_cache.result
new file mode 100644
index 00000000000..af14575a812
--- /dev/null
+++ b/mysql-test/r/query_cache.result
@@ -0,0 +1,492 @@
+flush query cache;
+flush query cache;
+reset query cache;
+flush status;
+drop table if exists t1,t2,t3,t11,t21, mysqltest.t1;
+create table t1 (a int not null);
+insert into t1 values (1),(2),(3);
+select * from t1;
+a
+1
+2
+3
+select * from t1;
+a
+1
+2
+3
+select sql_no_cache * from t1;
+a
+1
+2
+3
+select length(now()) from t1;
+length(now())
+19
+19
+19
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 1
+show status like "Qcache_inserts";
+Variable_name Value
+Qcache_inserts 1
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 1
+drop table t1;
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 0
+create table t1 (a int not null);
+insert into t1 values (1),(2),(3);
+create table t2 (a int not null);
+insert into t2 values (4),(5),(6);
+create table t3 (a int not null) type=MERGE UNION=(t1,t2) INSERT_METHOD=FIRST;
+select * from t3;
+a
+1
+2
+3
+4
+5
+6
+select * from t3;
+a
+1
+2
+3
+4
+5
+6
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 2
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 1
+insert into t2 values (7);
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 0
+select * from t1;
+a
+1
+2
+3
+select * from t1;
+a
+1
+2
+3
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 3
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 1
+insert into t3 values (8);
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 0
+select * from t3;
+a
+1
+2
+3
+8
+4
+5
+6
+7
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 1
+update t2 set a=9 where a=7;
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 0
+select * from t1;
+a
+1
+2
+3
+8
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 1
+update t3 set a=10 where a=1;
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 0
+select * from t3;
+a
+10
+2
+3
+8
+4
+5
+6
+9
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 1
+delete from t2 where a=9;
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 0
+select * from t1;
+a
+10
+2
+3
+8
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 1
+delete from t3 where a=10;
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 0
+drop table t1, t2, t3;
+create table t1 (a int not null);
+insert into t1 values (1),(2),(3);
+create table t2 (a int not null);
+insert into t2 values (1),(2),(3);
+select * from t1;
+a
+1
+2
+3
+select * from t2;
+a
+1
+2
+3
+insert into t1 values (4);
+show status like "Qcache_free_blocks";
+Variable_name Value
+Qcache_free_blocks 2
+flush query cache;
+show status like "Qcache_free_blocks";
+Variable_name Value
+Qcache_free_blocks 1
+drop table t1, t2;
+create table t1 (a text not null);
+create table t11 (a text not null);
+create table t2 (a text not null);
+create table t21 (a text not null);
+create table t3 (a text not null);
+insert into t1 values("1111111111111111111111111111111111111111111111111111");
+insert into t2 select * from t1;
+insert into t1 select * from t2;
+insert into t2 select * from t1;
+insert into t1 select * from t2;
+insert into t2 select * from t1;
+insert into t1 select * from t2;
+insert into t2 select * from t1;
+insert into t1 select * from t2;
+insert into t2 select * from t1;
+insert into t1 select * from t2;
+insert into t2 select * from t1;
+insert into t1 select * from t2;
+insert into t2 select * from t1;
+insert into t1 select * from t2;
+insert into t2 select * from t1;
+insert into t11 select * from t1;
+insert into t21 select * from t1;
+insert into t1 select * from t2;
+insert into t2 select * from t1;
+insert into t1 select * from t2;
+insert into t3 select * from t1;
+insert into t3 select * from t2;
+insert into t3 select * from t1;
+select * from t11;
+select * from t21;
+show status like "Qcache_total_blocks";
+Variable_name Value
+Qcache_total_blocks 7
+show status like "Qcache_free_blocks";
+Variable_name Value
+Qcache_free_blocks 1
+insert into t11 values("");
+select * from t3;
+show status like "Qcache_total_blocks";
+Variable_name Value
+Qcache_total_blocks 8
+show status like "Qcache_free_blocks";
+Variable_name Value
+Qcache_free_blocks 1
+flush query cache;
+show status like "Qcache_total_blocks";
+Variable_name Value
+Qcache_total_blocks 7
+show status like "Qcache_free_blocks";
+Variable_name Value
+Qcache_free_blocks 1
+drop table t1, t2, t3, t11, t21;
+set sql_query_cache_type=demand;
+create table t1 (a int not null);
+insert into t1 values (1),(2),(3);
+select * from t1;
+a
+1
+2
+3
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 0
+select sql_cache * from t1;
+a
+1
+2
+3
+set sql_query_cache_type=2;
+select sql_cache * from t1;
+a
+1
+2
+3
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 4
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 1
+set sql_query_cache_type=on;
+reset query cache;
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 0
+select sql_no_cache * from t1;
+a
+1
+2
+3
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 0
+drop table t1;
+create table t1 (a text not null);
+select CONNECTION_ID() from t1;
+CONNECTION_ID()
+select FOUND_ROWS();
+FOUND_ROWS()
+0
+select NOW() from t1;
+NOW()
+select CURDATE() from t1;
+CURDATE()
+select CURTIME() from t1;
+CURTIME()
+select DATABASE() from t1;
+DATABASE()
+select ENCRYPT("test") from t1;
+ENCRYPT("test")
+select LAST_INSERT_ID() from t1;
+last_insert_id()
+select RAND() from t1;
+RAND()
+select UNIX_TIMESTAMP() from t1;
+UNIX_TIMESTAMP()
+select USER() from t1;
+USER()
+select benchmark(1,1) from t1;
+benchmark(1,1)
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 0
+create table t2 (a text not null);
+insert into t1 values("1111111111111111111111111111111111111111111111111111");
+insert into t2 select * from t1;
+insert into t1 select * from t2;
+insert into t2 select * from t1;
+insert into t1 select * from t2;
+insert into t2 select * from t1;
+insert into t1 select * from t2;
+insert into t2 select * from t1;
+insert into t1 select * from t2;
+insert into t2 select * from t1;
+insert into t1 select * from t2;
+insert into t2 select * from t1;
+insert into t1 select * from t2;
+insert into t2 select * from t1;
+insert into t1 select * from t2;
+insert into t2 select * from t1;
+insert into t1 select * from t2;
+insert into t2 select * from t1;
+insert into t1 select * from t2;
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 4
+select a as a1, a as a2 from t1;
+select a as a2, a as a3 from t1;
+select a as a3, a as a4 from t1;
+select a as a1, a as a2 from t1;
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 4
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 2
+reset query cache;
+insert into t2 select * from t1;
+insert into t1 select * from t2;
+insert into t2 select * from t1;
+insert into t1 select * from t2;
+insert into t2 select * from t1;
+insert into t1 select * from t2;
+insert into t2 select * from t1;
+insert into t1 select * from t2;
+insert into t2 select * from t1;
+insert into t1 select * from t2;
+select * from t1;
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 0
+drop table t1,t2;
+create database if not exists mysqltest;
+create table mysqltest.t1 (i int not null auto_increment, a int, primary key (i));
+insert into mysqltest.t1 (a) values (1);
+select * from mysqltest.t1 where i is null;
+i a
+1 1
+select * from mysqltest.t1;
+i a
+1 1
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 1
+drop database mysqltest;
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 0
+create table t1 (a char(1) not null);
+insert into t1 values("á");
+select * from t1;
+a
+set CHARACTER SET cp1251_koi8;
+select * from t1;
+a
+set CHARACTER SET DEFAULT;
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 2
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 4
+drop table t1;
+create database if not exists mysqltest;
+create table mysqltest.t1 (i int not null);
+create table t1 (i int not null);
+insert into mysqltest.t1 (i) values (1);
+insert into t1 (i) values (2);
+select * from t1;
+i
+2
+use mysqltest;
+select * from t1;
+i
+1
+select * from t1;
+i
+1
+use test;
+select * from t1;
+i
+2
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 2
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 6
+drop database mysqltest;
+drop table t1;
+create table t1 (i int not null);
+insert into t1 (i) values (1),(2),(3),(4);
+select SQL_CALC_FOUND_ROWS * from t1 limit 2;
+i
+1
+2
+select FOUND_ROWS();
+FOUND_ROWS()
+4
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 6
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 1
+select * from t1 where i=1;
+i
+1
+select FOUND_ROWS();
+FOUND_ROWS()
+1
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 6
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 2
+select SQL_CALC_FOUND_ROWS * from t1 limit 2;
+i
+1
+2
+select FOUND_ROWS();
+FOUND_ROWS()
+4
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 7
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 2
+select * from t1 where i=1;
+i
+1
+select FOUND_ROWS();
+FOUND_ROWS()
+1
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 8
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 2
+drop table t1;
+flush query cache;
+reset query cache;
+create table t1 (a int not null);
+insert into t1 values (1),(2),(3);
+select * from t1;
+a
+1
+2
+3
+select * from t1;
+a
+1
+2
+3
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 1
+insert delayed into t1 values (4);
+select a from t1;
+a
+1
+2
+3
+4
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 1
+drop table t1;
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 0
diff --git a/mysql-test/r/raid.result b/mysql-test/r/raid.result
index ffda2a6966d..41af50851e9 100644
--- a/mysql-test/r/raid.result
+++ b/mysql-test/r/raid.result
@@ -1,8 +1,196 @@
+DROP TABLE IF EXISTS t1,t2;
+CREATE TABLE t1 (
+id int unsigned not null auto_increment primary key,
+c char(255) not null
+) RAID_TYPE=STRIPED RAID_CHUNKS=2 RAID_CHUNKSIZE=123;
+INSERT INTO t1 VALUES
+(NULL,'1'),(NULL,'a'),(NULL,'a'),(NULL,'a'),(NULL,'p'),(NULL,'a'),
+(NULL,'2'),(NULL,'b'),(NULL,'a'),(NULL,'a'),(NULL,'q'),(NULL,'a'),
+(NULL,'3'),(NULL,'c'),(NULL,'a'),(NULL,'a'),(NULL,'r'),(NULL,'a'),
+(NULL,'4'),(NULL,'d'),(NULL,'a'),(NULL,'a'),(NULL,'s'),(NULL,'a'),
+(NULL,'5'),(NULL,'e'),(NULL,'a'),(NULL,'a'),(NULL,'t'),(NULL,'a'),
+(NULL,'6'),(NULL,'f'),(NULL,'a'),(NULL,'a'),(NULL,'u'),(NULL,'a'),
+(NULL,'7'),(NULL,'g'),(NULL,'a'),(NULL,'a'),(NULL,'v'),(NULL,'a'),
+(NULL,'8'),(NULL,'h'),(NULL,'a'),(NULL,'a'),(NULL,'w'),(NULL,'a'),
+(NULL,'9'),(NULL,'i'),(NULL,'a'),(NULL,'a'),(NULL,'x'),(NULL,'a'),
+(NULL,'0'),(NULL,'j'),(NULL,'a'),(NULL,'a'),(NULL,'y'),(NULL,'a'),
+(NULL,'1'),(NULL,'k'),(NULL,'a'),(NULL,'a'),(NULL,'z'),(NULL,'a'),
+(NULL,'2'),(NULL,'l'),(NULL,'a'),(NULL,'a'),(NULL,'/'),(NULL,'a'),
+(NULL,'3'),(NULL,'m'),(NULL,'a'),(NULL,'a'),(NULL,'*'),(NULL,'a'),
+(NULL,'4'),(NULL,'n'),(NULL,'a'),(NULL,'a'),(NULL,'+'),(NULL,'a'),
+(NULL,'5'),(NULL,'o'),(NULL,'a'),(NULL,'a'),(NULL,'?'),(NULL,'a');
+INSERT INTO t1 VALUES
+(NULL,'1'),(NULL,'a'),(NULL,'a'),(NULL,'a'),(NULL,'p'),(NULL,'a'),
+(NULL,'2'),(NULL,'b'),(NULL,'a'),(NULL,'a'),(NULL,'q'),(NULL,'a'),
+(NULL,'3'),(NULL,'c'),(NULL,'a'),(NULL,'a'),(NULL,'r'),(NULL,'a'),
+(NULL,'4'),(NULL,'d'),(NULL,'a'),(NULL,'a'),(NULL,'s'),(NULL,'a'),
+(NULL,'5'),(NULL,'e'),(NULL,'a'),(NULL,'a'),(NULL,'t'),(NULL,'a'),
+(NULL,'6'),(NULL,'f'),(NULL,'a'),(NULL,'a'),(NULL,'u'),(NULL,'a'),
+(NULL,'7'),(NULL,'g'),(NULL,'a'),(NULL,'a'),(NULL,'v'),(NULL,'a'),
+(NULL,'8'),(NULL,'h'),(NULL,'a'),(NULL,'a'),(NULL,'w'),(NULL,'a'),
+(NULL,'9'),(NULL,'i'),(NULL,'a'),(NULL,'a'),(NULL,'x'),(NULL,'a'),
+(NULL,'0'),(NULL,'j'),(NULL,'a'),(NULL,'a'),(NULL,'y'),(NULL,'a'),
+(NULL,'1'),(NULL,'k'),(NULL,'a'),(NULL,'a'),(NULL,'z'),(NULL,'a'),
+(NULL,'2'),(NULL,'l'),(NULL,'a'),(NULL,'a'),(NULL,'/'),(NULL,'a'),
+(NULL,'3'),(NULL,'m'),(NULL,'a'),(NULL,'a'),(NULL,'*'),(NULL,'a'),
+(NULL,'4'),(NULL,'n'),(NULL,'a'),(NULL,'a'),(NULL,'+'),(NULL,'a'),
+(NULL,'5'),(NULL,'o'),(NULL,'a'),(NULL,'a'),(NULL,'?'),(NULL,'a');
+INSERT INTO t1 VALUES
+(NULL,'1'),(NULL,'a'),(NULL,'a'),(NULL,'a'),(NULL,'p'),(NULL,'a'),
+(NULL,'2'),(NULL,'b'),(NULL,'a'),(NULL,'a'),(NULL,'q'),(NULL,'a'),
+(NULL,'3'),(NULL,'c'),(NULL,'a'),(NULL,'a'),(NULL,'r'),(NULL,'a'),
+(NULL,'4'),(NULL,'d'),(NULL,'a'),(NULL,'a'),(NULL,'s'),(NULL,'a'),
+(NULL,'5'),(NULL,'e'),(NULL,'a'),(NULL,'a'),(NULL,'t'),(NULL,'a'),
+(NULL,'6'),(NULL,'f'),(NULL,'a'),(NULL,'a'),(NULL,'u'),(NULL,'a'),
+(NULL,'7'),(NULL,'g'),(NULL,'a'),(NULL,'a'),(NULL,'v'),(NULL,'a'),
+(NULL,'8'),(NULL,'h'),(NULL,'a'),(NULL,'a'),(NULL,'w'),(NULL,'a'),
+(NULL,'9'),(NULL,'i'),(NULL,'a'),(NULL,'a'),(NULL,'x'),(NULL,'a'),
+(NULL,'0'),(NULL,'j'),(NULL,'a'),(NULL,'a'),(NULL,'y'),(NULL,'a'),
+(NULL,'1'),(NULL,'k'),(NULL,'a'),(NULL,'a'),(NULL,'z'),(NULL,'a'),
+(NULL,'2'),(NULL,'l'),(NULL,'a'),(NULL,'a'),(NULL,'/'),(NULL,'a'),
+(NULL,'3'),(NULL,'m'),(NULL,'a'),(NULL,'a'),(NULL,'*'),(NULL,'a'),
+(NULL,'4'),(NULL,'n'),(NULL,'a'),(NULL,'a'),(NULL,'+'),(NULL,'a'),
+(NULL,'5'),(NULL,'o'),(NULL,'a'),(NULL,'a'),(NULL,'?'),(NULL,'a');
+INSERT INTO t1 VALUES
+(NULL,'1'),(NULL,'a'),(NULL,'a'),(NULL,'a'),(NULL,'p'),(NULL,'a'),
+(NULL,'2'),(NULL,'b'),(NULL,'a'),(NULL,'a'),(NULL,'q'),(NULL,'a'),
+(NULL,'3'),(NULL,'c'),(NULL,'a'),(NULL,'a'),(NULL,'r'),(NULL,'a'),
+(NULL,'4'),(NULL,'d'),(NULL,'a'),(NULL,'a'),(NULL,'s'),(NULL,'a'),
+(NULL,'5'),(NULL,'e'),(NULL,'a'),(NULL,'a'),(NULL,'t'),(NULL,'a'),
+(NULL,'6'),(NULL,'f'),(NULL,'a'),(NULL,'a'),(NULL,'u'),(NULL,'a'),
+(NULL,'7'),(NULL,'g'),(NULL,'a'),(NULL,'a'),(NULL,'v'),(NULL,'a'),
+(NULL,'8'),(NULL,'h'),(NULL,'a'),(NULL,'a'),(NULL,'w'),(NULL,'a'),
+(NULL,'9'),(NULL,'i'),(NULL,'a'),(NULL,'a'),(NULL,'x'),(NULL,'a'),
+(NULL,'0'),(NULL,'j'),(NULL,'a'),(NULL,'a'),(NULL,'y'),(NULL,'a'),
+(NULL,'1'),(NULL,'k'),(NULL,'a'),(NULL,'a'),(NULL,'z'),(NULL,'a'),
+(NULL,'2'),(NULL,'l'),(NULL,'a'),(NULL,'a'),(NULL,'/'),(NULL,'a'),
+(NULL,'3'),(NULL,'m'),(NULL,'a'),(NULL,'a'),(NULL,'*'),(NULL,'a'),
+(NULL,'4'),(NULL,'n'),(NULL,'a'),(NULL,'a'),(NULL,'+'),(NULL,'a'),
+(NULL,'5'),(NULL,'o'),(NULL,'a'),(NULL,'a'),(NULL,'?'),(NULL,'a');
+INSERT INTO t1 VALUES
+(NULL,'1'),(NULL,'a'),(NULL,'a'),(NULL,'a'),(NULL,'p'),(NULL,'a'),
+(NULL,'2'),(NULL,'b'),(NULL,'a'),(NULL,'a'),(NULL,'q'),(NULL,'a'),
+(NULL,'3'),(NULL,'c'),(NULL,'a'),(NULL,'a'),(NULL,'r'),(NULL,'a'),
+(NULL,'4'),(NULL,'d'),(NULL,'a'),(NULL,'a'),(NULL,'s'),(NULL,'a'),
+(NULL,'5'),(NULL,'e'),(NULL,'a'),(NULL,'a'),(NULL,'t'),(NULL,'a'),
+(NULL,'6'),(NULL,'f'),(NULL,'a'),(NULL,'a'),(NULL,'u'),(NULL,'a'),
+(NULL,'7'),(NULL,'g'),(NULL,'a'),(NULL,'a'),(NULL,'v'),(NULL,'a'),
+(NULL,'8'),(NULL,'h'),(NULL,'a'),(NULL,'a'),(NULL,'w'),(NULL,'a'),
+(NULL,'9'),(NULL,'i'),(NULL,'a'),(NULL,'a'),(NULL,'x'),(NULL,'a'),
+(NULL,'0'),(NULL,'j'),(NULL,'a'),(NULL,'a'),(NULL,'y'),(NULL,'a'),
+(NULL,'1'),(NULL,'k'),(NULL,'a'),(NULL,'a'),(NULL,'z'),(NULL,'a'),
+(NULL,'2'),(NULL,'l'),(NULL,'a'),(NULL,'a'),(NULL,'/'),(NULL,'a'),
+(NULL,'3'),(NULL,'m'),(NULL,'a'),(NULL,'a'),(NULL,'*'),(NULL,'a'),
+(NULL,'4'),(NULL,'n'),(NULL,'a'),(NULL,'a'),(NULL,'+'),(NULL,'a'),
+(NULL,'5'),(NULL,'o'),(NULL,'a'),(NULL,'a'),(NULL,'?'),(NULL,'a');
+select count(*) from t1;
count(*)
450
+ALTER TABLE t1 ADD COLUMN x INT UNSIGNED NOT NULL;
+ALTER TABLE t1 ADD KEY c (c);
+ALTER TABLE t1 DROP KEY c;
+ALTER TABLE t1 DROP COLUMN x;
+ALTER TABLE t1 RENAME t2;
+select count(*) from t2;
count(*)
450
+DROP TABLE t2;
+/* variable rows */
+DROP TABLE IF EXISTS t2;
+CREATE TABLE t1 (
+id int unsigned not null auto_increment primary key,
+c varchar(255) not null
+) RAID_TYPE=STRIPED RAID_CHUNKS=5 RAID_CHUNKSIZE=121;
+INSERT INTO t1 VALUES
+(NULL,'1'),(NULL,'a'),(NULL,'a'),(NULL,'a'),(NULL,'p'),(NULL,'a'),
+(NULL,'2'),(NULL,'b'),(NULL,'a'),(NULL,'a'),(NULL,'q'),(NULL,'a'),
+(NULL,'3'),(NULL,'c'),(NULL,'a'),(NULL,'a'),(NULL,'r'),(NULL,'a'),
+(NULL,'4'),(NULL,'d'),(NULL,'a'),(NULL,'a'),(NULL,'s'),(NULL,'a'),
+(NULL,'5'),(NULL,'e'),(NULL,'a'),(NULL,'a'),(NULL,'t'),(NULL,'a'),
+(NULL,'6'),(NULL,'f'),(NULL,'a'),(NULL,'a'),(NULL,'u'),(NULL,'a'),
+(NULL,'7'),(NULL,'g'),(NULL,'a'),(NULL,'a'),(NULL,'v'),(NULL,'a'),
+(NULL,'8'),(NULL,'h'),(NULL,'a'),(NULL,'a'),(NULL,'w'),(NULL,'a'),
+(NULL,'9'),(NULL,'i'),(NULL,'a'),(NULL,'a'),(NULL,'x'),(NULL,'a'),
+(NULL,'0'),(NULL,'j'),(NULL,'a'),(NULL,'a'),(NULL,'y'),(NULL,'a'),
+(NULL,'1'),(NULL,'k'),(NULL,'a'),(NULL,'a'),(NULL,'z'),(NULL,'a'),
+(NULL,'2'),(NULL,'l'),(NULL,'a'),(NULL,'a'),(NULL,'/'),(NULL,'a'),
+(NULL,'3'),(NULL,'m'),(NULL,'a'),(NULL,'a'),(NULL,'*'),(NULL,'a'),
+(NULL,'4'),(NULL,'n'),(NULL,'a'),(NULL,'a'),(NULL,'+'),(NULL,'a'),
+(NULL,'5'),(NULL,'o'),(NULL,'a'),(NULL,'a'),(NULL,'?'),(NULL,'a');
+INSERT INTO t1 VALUES
+(NULL,'1'),(NULL,'a'),(NULL,'a'),(NULL,'a'),(NULL,'p'),(NULL,'a'),
+(NULL,'2'),(NULL,'b'),(NULL,'a'),(NULL,'a'),(NULL,'q'),(NULL,'a'),
+(NULL,'3'),(NULL,'c'),(NULL,'a'),(NULL,'a'),(NULL,'r'),(NULL,'a'),
+(NULL,'4'),(NULL,'d'),(NULL,'a'),(NULL,'a'),(NULL,'s'),(NULL,'a'),
+(NULL,'5'),(NULL,'e'),(NULL,'a'),(NULL,'a'),(NULL,'t'),(NULL,'a'),
+(NULL,'6'),(NULL,'f'),(NULL,'a'),(NULL,'a'),(NULL,'u'),(NULL,'a'),
+(NULL,'7'),(NULL,'g'),(NULL,'a'),(NULL,'a'),(NULL,'v'),(NULL,'a'),
+(NULL,'8'),(NULL,'h'),(NULL,'a'),(NULL,'a'),(NULL,'w'),(NULL,'a'),
+(NULL,'9'),(NULL,'i'),(NULL,'a'),(NULL,'a'),(NULL,'x'),(NULL,'a'),
+(NULL,'0'),(NULL,'j'),(NULL,'a'),(NULL,'a'),(NULL,'y'),(NULL,'a'),
+(NULL,'1'),(NULL,'k'),(NULL,'a'),(NULL,'a'),(NULL,'z'),(NULL,'a'),
+(NULL,'2'),(NULL,'l'),(NULL,'a'),(NULL,'a'),(NULL,'/'),(NULL,'a'),
+(NULL,'3'),(NULL,'m'),(NULL,'a'),(NULL,'a'),(NULL,'*'),(NULL,'a'),
+(NULL,'4'),(NULL,'n'),(NULL,'a'),(NULL,'a'),(NULL,'+'),(NULL,'a'),
+(NULL,'5'),(NULL,'o'),(NULL,'a'),(NULL,'a'),(NULL,'?'),(NULL,'a');
+INSERT INTO t1 VALUES
+(NULL,'1'),(NULL,'a'),(NULL,'a'),(NULL,'a'),(NULL,'p'),(NULL,'a'),
+(NULL,'2'),(NULL,'b'),(NULL,'a'),(NULL,'a'),(NULL,'q'),(NULL,'a'),
+(NULL,'3'),(NULL,'c'),(NULL,'a'),(NULL,'a'),(NULL,'r'),(NULL,'a'),
+(NULL,'4'),(NULL,'d'),(NULL,'a'),(NULL,'a'),(NULL,'s'),(NULL,'a'),
+(NULL,'5'),(NULL,'e'),(NULL,'a'),(NULL,'a'),(NULL,'t'),(NULL,'a'),
+(NULL,'6'),(NULL,'f'),(NULL,'a'),(NULL,'a'),(NULL,'u'),(NULL,'a'),
+(NULL,'7'),(NULL,'g'),(NULL,'a'),(NULL,'a'),(NULL,'v'),(NULL,'a'),
+(NULL,'8'),(NULL,'h'),(NULL,'a'),(NULL,'a'),(NULL,'w'),(NULL,'a'),
+(NULL,'9'),(NULL,'i'),(NULL,'a'),(NULL,'a'),(NULL,'x'),(NULL,'a'),
+(NULL,'0'),(NULL,'j'),(NULL,'a'),(NULL,'a'),(NULL,'y'),(NULL,'a'),
+(NULL,'1'),(NULL,'k'),(NULL,'a'),(NULL,'a'),(NULL,'z'),(NULL,'a'),
+(NULL,'2'),(NULL,'l'),(NULL,'a'),(NULL,'a'),(NULL,'/'),(NULL,'a'),
+(NULL,'3'),(NULL,'m'),(NULL,'a'),(NULL,'a'),(NULL,'*'),(NULL,'a'),
+(NULL,'4'),(NULL,'n'),(NULL,'a'),(NULL,'a'),(NULL,'+'),(NULL,'a'),
+(NULL,'5'),(NULL,'o'),(NULL,'a'),(NULL,'a'),(NULL,'?'),(NULL,'a');
+INSERT INTO t1 VALUES
+(NULL,'1'),(NULL,'a'),(NULL,'a'),(NULL,'a'),(NULL,'p'),(NULL,'a'),
+(NULL,'2'),(NULL,'b'),(NULL,'a'),(NULL,'a'),(NULL,'q'),(NULL,'a'),
+(NULL,'3'),(NULL,'c'),(NULL,'a'),(NULL,'a'),(NULL,'r'),(NULL,'a'),
+(NULL,'4'),(NULL,'d'),(NULL,'a'),(NULL,'a'),(NULL,'s'),(NULL,'a'),
+(NULL,'5'),(NULL,'e'),(NULL,'a'),(NULL,'a'),(NULL,'t'),(NULL,'a'),
+(NULL,'6'),(NULL,'f'),(NULL,'a'),(NULL,'a'),(NULL,'u'),(NULL,'a'),
+(NULL,'7'),(NULL,'g'),(NULL,'a'),(NULL,'a'),(NULL,'v'),(NULL,'a'),
+(NULL,'8'),(NULL,'h'),(NULL,'a'),(NULL,'a'),(NULL,'w'),(NULL,'a'),
+(NULL,'9'),(NULL,'i'),(NULL,'a'),(NULL,'a'),(NULL,'x'),(NULL,'a'),
+(NULL,'0'),(NULL,'j'),(NULL,'a'),(NULL,'a'),(NULL,'y'),(NULL,'a'),
+(NULL,'1'),(NULL,'k'),(NULL,'a'),(NULL,'a'),(NULL,'z'),(NULL,'a'),
+(NULL,'2'),(NULL,'l'),(NULL,'a'),(NULL,'a'),(NULL,'/'),(NULL,'a'),
+(NULL,'3'),(NULL,'m'),(NULL,'a'),(NULL,'a'),(NULL,'*'),(NULL,'a'),
+(NULL,'4'),(NULL,'n'),(NULL,'a'),(NULL,'a'),(NULL,'+'),(NULL,'a'),
+(NULL,'5'),(NULL,'o'),(NULL,'a'),(NULL,'a'),(NULL,'?'),(NULL,'a');
+INSERT INTO t1 VALUES
+(NULL,'1'),(NULL,'a'),(NULL,'a'),(NULL,'a'),(NULL,'p'),(NULL,'a'),
+(NULL,'2'),(NULL,'b'),(NULL,'a'),(NULL,'a'),(NULL,'q'),(NULL,'a'),
+(NULL,'3'),(NULL,'c'),(NULL,'a'),(NULL,'a'),(NULL,'r'),(NULL,'a'),
+(NULL,'4'),(NULL,'d'),(NULL,'a'),(NULL,'a'),(NULL,'s'),(NULL,'a'),
+(NULL,'5'),(NULL,'e'),(NULL,'a'),(NULL,'a'),(NULL,'t'),(NULL,'a'),
+(NULL,'6'),(NULL,'f'),(NULL,'a'),(NULL,'a'),(NULL,'u'),(NULL,'a'),
+(NULL,'7'),(NULL,'g'),(NULL,'a'),(NULL,'a'),(NULL,'v'),(NULL,'a'),
+(NULL,'8'),(NULL,'h'),(NULL,'a'),(NULL,'a'),(NULL,'w'),(NULL,'a'),
+(NULL,'9'),(NULL,'i'),(NULL,'a'),(NULL,'a'),(NULL,'x'),(NULL,'a'),
+(NULL,'0'),(NULL,'j'),(NULL,'a'),(NULL,'a'),(NULL,'y'),(NULL,'a'),
+(NULL,'1'),(NULL,'k'),(NULL,'a'),(NULL,'a'),(NULL,'z'),(NULL,'a'),
+(NULL,'2'),(NULL,'l'),(NULL,'a'),(NULL,'a'),(NULL,'/'),(NULL,'a'),
+(NULL,'3'),(NULL,'m'),(NULL,'a'),(NULL,'a'),(NULL,'*'),(NULL,'a'),
+(NULL,'4'),(NULL,'n'),(NULL,'a'),(NULL,'a'),(NULL,'+'),(NULL,'a'),
+(NULL,'5'),(NULL,'o'),(NULL,'a'),(NULL,'a'),(NULL,'?'),(NULL,'a');
+select count(*) from t1;
count(*)
450
+ALTER TABLE t1 ADD COLUMN x INT UNSIGNED NOT NULL;
+ALTER TABLE t1 ADD KEY c (c);
+ALTER TABLE t1 DROP KEY c;
+ALTER TABLE t1 DROP COLUMN x;
+ALTER TABLE t1 RENAME t2;
+ALTER TABLE t2 CHANGE COLUMN c c VARCHAR(251) NOT NULL;
+select count(*) from t2;
count(*)
450
+DROP TABLE t2;
diff --git a/mysql-test/r/range.result b/mysql-test/r/range.result
index e0e43f44a4b..990b00fc818 100644
--- a/mysql-test/r/range.result
+++ b/mysql-test/r/range.result
@@ -1,3 +1,12 @@
+drop table if exists t1;
+CREATE TABLE t1 (
+event_date date DEFAULT '0000-00-00' NOT NULL,
+type int(11) DEFAULT '0' NOT NULL,
+event_id int(11) DEFAULT '0' NOT NULL,
+PRIMARY KEY (event_date,type,event_id)
+);
+INSERT INTO t1 VALUES ('1999-07-10',100100,24),('1999-07-11',100100,25),('1999-07-13',100600,0),('1999-07-13',100600,4),('1999-07-13',100600,26),('1999-07-14',100600,10),('1999-07-15',100600,16),('1999-07-15',100800,45),('1999-07-15',101000,47),('1999-07-16',100800,46),('1999-07-20',100600,5),('1999-07-20',100600,27),('1999-07-21',100600,11),('1999-07-22',100600,17),('1999-07-23',100100,39),('1999-07-24',100100,39),('1999-07-24',100500,40),('1999-07-25',100100,39),('1999-07-27',100600,1),('1999-07-27',100600,6),('1999-07-27',100600,28),('1999-07-28',100600,12),('1999-07-29',100500,41),('1999-07-29',100600,18),('1999-07-30',100500,41),('1999-07-31',100500,41),('1999-08-01',100700,34),('1999-08-03',100600,7),('1999-08-03',100600,29),('1999-08-04',100600,13),('1999-08-05',100500,42),('1999-08-05',100600,19),('1999-08-06',100500,42),('1999-08-07',100500,42),('1999-08-08',100500,42),('1999-08-10',100600,2),('1999-08-10',100600,9),('1999-08-10',100600,30),('1999-08-11',100600,14),('1999-08-12',100600,20),('1999-08-17',100500,8),('1999-08-17',100600,31),('1999-08-18',100600,15),('1999-08-19',100600,22),('1999-08-24',100600,3),('1999-08-24',100600,32),('1999-08-27',100500,43),('1999-08-31',100600,33),('1999-09-17',100100,37),('1999-09-18',100100,37),('1999-09-19',100100,37),('2000-12-18',100700,38);
+select event_date,type,event_id from t1 WHERE event_date >= "1999-07-01" AND event_date < "1999-07-15" AND (type=100600 OR type=100100) ORDER BY event_date;
event_date type event_id
1999-07-10 100100 24
1999-07-11 100100 25
@@ -5,8 +14,10 @@ event_date type event_id
1999-07-13 100600 4
1999-07-13 100600 26
1999-07-14 100600 10
+explain select event_date,type,event_id from t1 WHERE type = 100601 and event_date >= "1999-07-01" AND event_date < "1999-07-15" AND (type=100600 OR type=100100) ORDER BY event_date;
Comment
Impossible WHERE
+select event_date,type,event_id from t1 WHERE event_date >= "1999-07-01" AND event_date <= "1999-07-15" AND (type=100600 OR type=100100) or event_date >= "1999-07-01" AND event_date <= "1999-07-15" AND type=100099;
event_date type event_id
1999-07-10 100100 24
1999-07-11 100100 25
@@ -15,6 +26,45 @@ event_date type event_id
1999-07-13 100600 26
1999-07-14 100600 10
1999-07-15 100600 16
+drop table t1;
+CREATE TABLE t1 (
+PAPER_ID smallint(6) DEFAULT '0' NOT NULL,
+YEAR smallint(6) DEFAULT '0' NOT NULL,
+ISSUE smallint(6) DEFAULT '0' NOT NULL,
+CLOSED tinyint(4) DEFAULT '0' NOT NULL,
+ISS_DATE date DEFAULT '0000-00-00' NOT NULL,
+PRIMARY KEY (PAPER_ID,YEAR,ISSUE)
+);
+INSERT INTO t1 VALUES (3,1999,34,0,'1999-07-12');
+INSERT INTO t1 VALUES (1,1999,111,0,'1999-03-23');
+INSERT INTO t1 VALUES (1,1999,222,0,'1999-03-23');
+INSERT INTO t1 VALUES (3,1999,33,0,'1999-07-12');
+INSERT INTO t1 VALUES (3,1999,32,0,'1999-07-12');
+INSERT INTO t1 VALUES (3,1999,31,0,'1999-07-12');
+INSERT INTO t1 VALUES (3,1999,30,0,'1999-07-12');
+INSERT INTO t1 VALUES (3,1999,29,0,'1999-07-12');
+INSERT INTO t1 VALUES (3,1999,28,0,'1999-07-12');
+INSERT INTO t1 VALUES (1,1999,40,1,'1999-05-01');
+INSERT INTO t1 VALUES (1,1999,41,1,'1999-05-01');
+INSERT INTO t1 VALUES (1,1999,42,1,'1999-05-01');
+INSERT INTO t1 VALUES (1,1999,46,1,'1999-05-01');
+INSERT INTO t1 VALUES (1,1999,47,1,'1999-05-01');
+INSERT INTO t1 VALUES (1,1999,48,1,'1999-05-01');
+INSERT INTO t1 VALUES (1,1999,49,1,'1999-05-01');
+INSERT INTO t1 VALUES (1,1999,50,0,'1999-05-01');
+INSERT INTO t1 VALUES (1,1999,51,0,'1999-05-01');
+INSERT INTO t1 VALUES (1,1999,200,0,'1999-06-28');
+INSERT INTO t1 VALUES (1,1999,52,0,'1999-06-28');
+INSERT INTO t1 VALUES (1,1999,53,0,'1999-06-28');
+INSERT INTO t1 VALUES (1,1999,54,0,'1999-06-28');
+INSERT INTO t1 VALUES (1,1999,55,0,'1999-06-28');
+INSERT INTO t1 VALUES (1,1999,56,0,'1999-07-01');
+INSERT INTO t1 VALUES (1,1999,57,0,'1999-07-01');
+INSERT INTO t1 VALUES (1,1999,58,0,'1999-07-01');
+INSERT INTO t1 VALUES (1,1999,59,0,'1999-07-01');
+INSERT INTO t1 VALUES (1,1999,60,0,'1999-07-01');
+INSERT INTO t1 VALUES (3,1999,35,0,'1999-07-12');
+select YEAR,ISSUE from t1 where PAPER_ID=3 and (YEAR>1999 or (YEAR=1999 and ISSUE>28)) order by YEAR,ISSUE;
YEAR ISSUE
1999 29
1999 30
@@ -23,10 +73,23 @@ YEAR ISSUE
1999 33
1999 34
1999 35
+check table t1;
Table Op Msg_type Msg_text
test.t1 check status OK
+repair table t1;
Table Op Msg_type Msg_text
test.t1 repair status OK
+drop table t1;
+CREATE TABLE t1 (
+id int(11) NOT NULL auto_increment,
+parent_id int(11) DEFAULT '0' NOT NULL,
+level tinyint(4) DEFAULT '0' NOT NULL,
+PRIMARY KEY (id),
+KEY parent_id (parent_id),
+KEY level (level)
+);
+INSERT INTO t1 VALUES (1,0,0),(3,1,1),(4,1,1),(8,2,2),(9,2,2),(17,3,2),(22,4,2),(24,4,2),(28,5,2),(29,5,2),(30,5,2),(31,6,2),(32,6,2),(33,6,2),(203,7,2),(202,7,2),(20,3,2),(157,0,0),(193,5,2),(40,7,2),(2,1,1),(15,2,2),(6,1,1),(34,6,2),(35,6,2),(16,3,2),(7,1,1),(36,7,2),(18,3,2),(26,5,2),(27,5,2),(183,4,2),(38,7,2),(25,5,2),(37,7,2),(21,4,2),(19,3,2),(5,1,1),(179,5,2);
+SELECT * FROM t1 WHERE level = 1 AND parent_id = 1;
id parent_id level
3 1 1
4 1 1
@@ -34,6 +97,7 @@ id parent_id level
6 1 1
7 1 1
5 1 1
+SELECT * FROM t1 WHERE level = 1 AND parent_id = 1 order by id;
id parent_id level
2 1 1
3 1 1
@@ -41,17 +105,38 @@ id parent_id level
5 1 1
6 1 1
7 1 1
+drop table t1;
+create table t1(
+Satellite varchar(25) not null,
+SensorMode varchar(25) not null,
+FullImageCornersUpperLeftLongitude double not null,
+FullImageCornersUpperRightLongitude double not null,
+FullImageCornersUpperRightLatitude double not null,
+FullImageCornersLowerRightLatitude double not null,
+index two (Satellite, SensorMode, FullImageCornersUpperLeftLongitude, FullImageCornersUpperRightLongitude, FullImageCornersUpperRightLatitude, FullImageCornersLowerRightLatitude));
+insert into t1 values("OV-3","PAN1",91,-92,40,50);
+insert into t1 values("OV-4","PAN1",91,-92,40,50);
+select * from t1 where t1.Satellite = "OV-3" and t1.SensorMode = "PAN1" and t1.FullImageCornersUpperLeftLongitude > -90.000000 and t1.FullImageCornersUpperRightLongitude < -82.000000;
Satellite SensorMode FullImageCornersUpperLeftLongitude FullImageCornersUpperRightLongitude FullImageCornersUpperRightLatitude FullImageCornersLowerRightLatitude
OV-3 PAN1 91 -92 40 50
+drop table t1;
+create table t1 ( aString char(100) not null default "", key aString (aString(10)) );
+insert t1 (aString) values ( "believe in myself" ), ( "believe" ), ("baaa" ), ( "believe in love");
+select * from t1 where aString < "believe in myself" order by aString;
aString
baaa
believe
believe in love
+select * from t1 where aString > "believe in love" order by aString;
aString
believe in myself
+alter table t1 drop key aString;
+select * from t1 where aString < "believe in myself" order by aString;
aString
baaa
believe
believe in love
+select * from t1 where aString > "believe in love" order by aString;
aString
believe in myself
+drop table t1;
diff --git a/mysql-test/r/rename.result b/mysql-test/r/rename.result
index 57ef20e41b1..b2bb659502a 100644
--- a/mysql-test/r/rename.result
+++ b/mysql-test/r/rename.result
@@ -1,14 +1,39 @@
+drop table if exists t0,t1,t2,t3,t4;
+create table t0 SELECT 1,"table 1";
+create table t2 SELECT 2,"table 2";
+create table t3 SELECT 3,"table 3";
+rename table t0 to t1;
+rename table t3 to t4, t2 to t3, t1 to t2, t4 to t1;
+select * from t1;
3 table 3
3 table 3
+rename table t3 to t4, t2 to t3, t1 to t2, t4 to t1;
+rename table t3 to t4, t2 to t3, t1 to t2, t4 to t1;
+select * from t1;
1 table 1
1 table 1
+rename table t1 to t2;
+Got one of the listed errors
+rename table t1 to t1;
+Got one of the listed errors
+rename table t3 to t4, t2 to t3, t1 to t2, t4 to t2;
+Got one of the listed errors
+show tables like "t_";
Tables_in_test (t_)
t1
t2
t3
+rename table t3 to t1, t2 to t3, t1 to t2, t4 to t1;
+Got one of the listed errors
+rename table t3 to t4, t5 to t3, t1 to t2, t4 to t1;
+Got one of the listed errors
+select * from t1;
1 table 1
1 table 1
+select * from t2;
2 table 2
2 table 2
+select * from t3;
3 table 3
3 table 3
+drop table if exists t1,t2,t3,t4;
diff --git a/mysql-test/r/replace.result b/mysql-test/r/replace.result
index 25a6a17da35..0aa80e18ccc 100644
--- a/mysql-test/r/replace.result
+++ b/mysql-test/r/replace.result
@@ -1,3 +1,26 @@
+drop table if exists t1;
+CREATE TABLE t1 (
+gesuchnr int(11) DEFAULT '0' NOT NULL,
+benutzer_id int(11) DEFAULT '0' NOT NULL,
+PRIMARY KEY (gesuchnr,benutzer_id)
+) type=ISAM;
+replace into t1 (gesuchnr,benutzer_id) values (2,1);
+replace into t1 (gesuchnr,benutzer_id) values (1,1);
+replace into t1 (gesuchnr,benutzer_id) values (1,1);
+alter table t1 type=myisam;
+replace into t1 (gesuchnr,benutzer_id) values (1,1);
+alter table t1 type=heap;
+replace into t1 (gesuchnr,benutzer_id) values (1,1);
+drop table t1;
+create table t1 (a tinyint not null auto_increment primary key, b char(20));
+insert into t1 values (126,"first"),(0,"last");
+insert into t1 values (0,"error");
+Duplicate entry '127' for key 1
+replace into t1 values (0,"error");
+Duplicate entry '127' for key 1
+replace into t1 values (126,"first updated");
+select * from t1;
a b
126 first updated
127 last
+drop table t1;
diff --git a/mysql-test/r/rollback.result b/mysql-test/r/rollback.result
index ac3743e1dc7..a5eb6f8729f 100644
--- a/mysql-test/r/rollback.result
+++ b/mysql-test/r/rollback.result
@@ -1,3 +1,12 @@
+drop table if exists t1;
+create table t1 (n int not null primary key) type=myisam;
+begin work;
+insert into t1 values (4);
+insert into t1 values (5);
+rollback;
+Warning: Some non-transactional changed tables couldn't be rolled back
+select * from t1;
n
4
5
+drop table t1;
diff --git a/mysql-test/r/rpl000001.result b/mysql-test/r/rpl000001.result
index ebccb1e1e6b..60a5db1de3a 100644
--- a/mysql-test/r/rpl000001.result
+++ b/mysql-test/r/rpl000001.result
@@ -1,17 +1,95 @@
+slave stop;
+reset master;
+reset slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+slave start;
+use test;
+drop table if exists t1,t3;
+create table t1 (word char(20) not null);
+load data infile '../../std_data/words.dat' into table t1;
+load data local infile 'MYSQL_TEST_DIR/std_data/words.dat' into table t1;
+select * from t1;
+word
+Aarhus
+Aaron
+Ababa
+aback
+abaft
+abandon
+abandoned
+abandoning
+abandonment
+abandons
+Aarhus
+Aaron
+Ababa
+aback
+abaft
+abandon
+abandoned
+abandoning
+abandonment
+abandons
+set password for root@"localhost" = password('foo');
+set password for root@"localhost" = password('');
+create table t3(n int);
+insert into t3 values(1),(2);
+use test;
+select * from t3;
n
1
2
+select sum(length(word)) from t1;
sum(length(word))
-71
+141
+drop table t1,t3;
+reset master;
+slave stop;
+reset slave;
+drop table if exists t1,t2;
+create table t1(n int);
+select get_lock("hold_slave",10);
+get_lock("hold_slave",10)
+1
+slave start;
+select release_lock("hold_slave");
+release_lock("hold_slave")
+1
+unlock tables;
+create table t2(id int);
+insert into t2 values(connection_id());
+create temporary table t1_temp(n int);
+insert into t1_temp select get_lock('crash_lock%20C', 1) from t2;
+ update t1 set n = n + get_lock('crash_lock%20C', 2);
+select (@id := id) - id from t2;
(@id := id) - id
0
+kill @id;
+drop table t2;
+Server shutdown in progress
+set sql_slave_skip_counter=1;
+slave start;
+select count(*) from t1;
count(*)
-10
+5000
+drop table t1;
+create table t1 (n int);
+insert into t1 values(3456);
+use mysql;
+insert into user (Host, User, Password)
+VALUES ("10.10.10.%", "blafasel2", password("blafasel2"));
+select select_priv,user from mysql.user where user = 'blafasel2';
select_priv user
N blafasel2
+update user set Select_priv = "Y" where User="blafasel2";
+select select_priv,user from mysql.user where user = 'blafasel2';
select_priv user
Y blafasel2
+use test;
+select n from t1;
n
3456
+select select_priv,user from mysql.user where user = 'blafasel2';
select_priv user
Y blafasel2
+drop table t1;
diff --git a/mysql-test/r/rpl000002.result b/mysql-test/r/rpl000002.result
index a68ef517708..88228321897 100644
--- a/mysql-test/r/rpl000002.result
+++ b/mysql-test/r/rpl000002.result
@@ -1,8 +1,33 @@
+slave stop;
+reset master;
+reset slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+slave start;
+use test;
+drop table if exists t1;
+create table t1 (n int auto_increment primary key);
+set insert_id = 2000;
+insert into t1 values (NULL),(NULL),(NULL);
+use test;
+select * from t1;
n
2000
2001
2002
+show slave hosts;
+Server_id Host Port Rpl_recovery_rank Master_id
+2 127.0.0.1 $SLAVE_MYPORT 2 1
+drop table t1;
+slave stop;
+drop table if exists t2;
+create table t2(id int auto_increment primary key, created datetime);
+set timestamp=12345;
+insert into t2 set created=now();
+select * from t2;
id created
1 1970-01-01 06:25:45
+slave start;
+select * from t2;
id created
1 1970-01-01 06:25:45
+drop table t2;
diff --git a/mysql-test/r/rpl000003.result b/mysql-test/r/rpl000003.result
index f85b057eefa..eb64d1855b1 100644
--- a/mysql-test/r/rpl000003.result
+++ b/mysql-test/r/rpl000003.result
@@ -1,4 +1,16 @@
+slave stop;
+reset master;
+reset slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+slave start;
+drop table if exists t1;
+create table t1(n int primary key);
+insert into t1 values (1),(2),(2);
+Duplicate entry '2' for key 1
+insert into t1 values (3);
+select * from t1;
n
1
2
3
+drop table t1;
diff --git a/mysql-test/r/rpl000004.result b/mysql-test/r/rpl000004.result
index a1c135a142e..e5dee880f73 100644
--- a/mysql-test/r/rpl000004.result
+++ b/mysql-test/r/rpl000004.result
@@ -1,6 +1,34 @@
+slave stop;
+reset master;
+reset slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+slave start;
+use test;
+set SQL_LOG_BIN=0;
+drop table if exists t1;
+create table t1 (word char(20) not null, index(word));
+load data infile '../../std_data/words.dat' into table t1;
+drop table if exists t2;
+create table t2 (word char(20) not null);
+load data infile '../../std_data/words.dat' into table t2;
+create table t3 (word char(20) not null primary key);
+use test;
+drop table if exists t1;
+load table t1 from master;
+drop table if exists t2;
+load table t2 from master;
+drop table if exists t3;
+load table t3 from master;
+check table t1;
Table Op Msg_type Msg_text
test.t1 check status OK
+select count(*) from t2;
count(*)
10
+select count(*) from t3;
count(*)
0
+set SQL_LOG_BIN=1;
+drop table if exists t1,t2,t3;
+create table t1(n int);
+drop table t1;
diff --git a/mysql-test/r/rpl000005.result b/mysql-test/r/rpl000005.result
index 4f1541c75ca..0c91f984db1 100644
--- a/mysql-test/r/rpl000005.result
+++ b/mysql-test/r/rpl000005.result
@@ -1,8 +1,22 @@
+slave stop;
+reset master;
+reset slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+slave start;
+drop table if exists t1;
+CREATE TABLE t1 (name varchar(64), age smallint(3));
+INSERT INTO t1 SET name='Andy', age=31;
+INSERT t1 SET name='Jacob', age=2;
+INSERT into t1 SET name='Caleb', age=1;
+ALTER TABLE t1 ADD id int(8) ZEROFILL AUTO_INCREMENT PRIMARY KEY;
+select * from t1;
name age id
Andy 31 00000001
Jacob 2 00000002
Caleb 1 00000003
+select * from t1;
name age id
Andy 31 00000001
Jacob 2 00000002
Caleb 1 00000003
+drop table t1;
diff --git a/mysql-test/r/rpl000006.result b/mysql-test/r/rpl000006.result
index 56cd7166510..f4e965236af 100644
--- a/mysql-test/r/rpl000006.result
+++ b/mysql-test/r/rpl000006.result
@@ -1,6 +1,30 @@
+slave stop;
+reset master;
+reset slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+slave start;
+set SQL_LOG_BIN=0,timestamp=200006;
+drop table if exists t1;
+create table t1(t timestamp not null,a char(1));
+insert into t1 ( a) values ('F');
+select unix_timestamp(t) from t1;
unix_timestamp(t)
200006
+drop table if exists t1;
+load table t1 from master;
+select unix_timestamp(t) from t1;
unix_timestamp(t)
200006
+set SQL_LOG_BIN=1,timestamp=default;
+drop table t1;
+set SQL_LOG_BIN=0;
+CREATE TABLE t1 (
+a int not null
+) TYPE=MyISAM MAX_ROWS=4000 CHECKSUM=1;
+INSERT INTO t1 VALUES (1);
+load table t1 from master;
+check table t1;
Table Op Msg_type Msg_text
test.t1 check status OK
+drop table t1;
+drop table t1;
diff --git a/mysql-test/r/rpl000007.result b/mysql-test/r/rpl000007.result
index d5b4cdf3bee..7b2b9939228 100644
--- a/mysql-test/r/rpl000007.result
+++ b/mysql-test/r/rpl000007.result
@@ -1,2 +1,21 @@
+slave stop;
+reset master;
+reset slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+slave start;
+use test;
+drop table if exists foo;
+create table foo (n int);
+insert into foo values(4);
+use test;
+drop table if exists foo;
+create table foo (s char(20));
+load data infile '../../std_data/words.dat' into table foo;
+insert into foo values('five');
+drop table if exists bar;
+create table bar (m int);
+insert into bar values(15);
+select foo.n,bar.m from foo,bar;
n m
4 15
+drop table if exists bar,foo;
diff --git a/mysql-test/r/rpl000008.result b/mysql-test/r/rpl000008.result
index 870e8a5510d..5ca156fecf0 100644
--- a/mysql-test/r/rpl000008.result
+++ b/mysql-test/r/rpl000008.result
@@ -1,2 +1,24 @@
+slave stop;
+reset master;
+reset slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+slave start;
+use test;
+drop table if exists foo;
+create table foo (n int);
+insert into foo values(4);
+use test;
+drop table if exists foo;
+create table foo (n int);
+insert into foo values(5);
+drop table if exists bar;
+create table bar (m int);
+insert into bar values(15);
+drop table if exists choo;
+create table choo (k int);
+insert into choo values(55);
+select foo.n,bar.m,choo.k from foo,bar,choo;
n m k
4 15 55
+drop table if exists foo,bar,choo;
+drop table if exists foo,bar,choo;
diff --git a/mysql-test/r/rpl000009.result b/mysql-test/r/rpl000009.result
index d5b4cdf3bee..5246dadc06b 100644
--- a/mysql-test/r/rpl000009.result
+++ b/mysql-test/r/rpl000009.result
@@ -1,2 +1,82 @@
+slave stop;
+reset master;
+reset slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+slave start;
+drop database if exists foo;
+create database foo;
+drop database if exists bar;
+create database bar;
+drop table if exists foo.foo;
+create table foo.foo (n int);
+insert into foo.foo values(4);
+drop table if exists foo.foo;
+create table foo.foo (n int);
+insert into foo.foo values(5);
+drop table if exists bar.bar;
+create table bar.bar (m int);
+insert into bar.bar values(15);
+select foo.foo.n,bar.bar.m from foo.foo,bar.bar;
n m
4 15
+drop database if exists bar;
+drop database if exists foo;
+drop database if exists bar;
+drop database if exists foo;
+set sql_log_bin = 0;
+create database foo;
+create database bar;
+show databases;
+Database
+bar
+foo
+mysql
+test
+create table foo.t1(n int, s char(20));
+create table foo.t2(n int, s text);
+insert into foo.t1 values (1, 'one'), (2, 'two'), (3, 'three');
+insert into foo.t2 values (11, 'eleven'), (12, 'twelve'), (13, 'thirteen');
+create table bar.t1(n int, s char(20));
+create table bar.t2(n int, s text);
+insert into bar.t1 values (1, 'one bar'), (2, 'two bar'), (3, 'three bar');
+insert into bar.t2 values (11, 'eleven bar'), (12, 'twelve bar'),
+(13, 'thirteen bar');
+set sql_log_bin = 1;
+show databases;
+Database
+mysql
+test
+load data from master;
+show databases;
+Database
+bar
+foo
+mysql
+test
+use foo;
+show tables;
+Tables_in_foo
+use bar;
+show tables;
+Tables_in_bar
+t1
+t2
+select * from bar.t1;
+n s
+1 one bar
+2 two bar
+3 three bar
+select * from bar.t2;
+n s
+11 eleven bar
+12 twelve bar
+13 thirteen bar
+insert into bar.t1 values (4, 'four bar');
+select * from bar.t1;
+n s
+1 one bar
+2 two bar
+3 three bar
+4 four bar
+drop database bar;
+drop database foo;
diff --git a/mysql-test/r/rpl000010.result b/mysql-test/r/rpl000010.result
index c52b83d729a..95792a72a6d 100644
--- a/mysql-test/r/rpl000010.result
+++ b/mysql-test/r/rpl000010.result
@@ -1,3 +1,15 @@
+slave stop;
+reset master;
+reset slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+slave start;
+drop table if exists t1;
+drop table if exists t1;
+create table t1 (n int not null auto_increment primary key);
+insert into t1 values(NULL);
+insert into t1 values(2);
+select n from t1;
n
1
2
+drop table t1;
diff --git a/mysql-test/r/rpl000011.result b/mysql-test/r/rpl000011.result
index c52b83d729a..1a46f479677 100644
--- a/mysql-test/r/rpl000011.result
+++ b/mysql-test/r/rpl000011.result
@@ -1,3 +1,17 @@
+slave stop;
+reset master;
+reset slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+slave start;
+use test;
+drop table if exists t1;
+create table t1 (n int);
+insert into t1 values(1);
+slave stop;
+slave start;
+insert into t1 values(2);
+select * from t1;
n
1
2
+drop table t1;
diff --git a/mysql-test/r/rpl000012.result b/mysql-test/r/rpl000012.result
index 9ce7037101e..c7f3ab8f578 100644
--- a/mysql-test/r/rpl000012.result
+++ b/mysql-test/r/rpl000012.result
@@ -1,3 +1,26 @@
+slave stop;
+reset master;
+reset slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+slave start;
+drop table if exists t1,t2,t3;
+create table t2 (n int);
+create temporary table t1 (n int);
+insert into t1 values(1),(2),(3);
+insert into t2 select * from t1;
+drop table if exists test.t3;
+create temporary table test.t3 (n int not null);
+alter table test.t3 add primary key(n);
+flush logs;
+insert into t3 values (100);
+insert into t2 select * from t3;
+drop table if exists test.t3;
+insert into t2 values (101);
+create temporary table t1 (n int);
+insert into t1 values (4),(5);
+insert into t2 select * from t1;
+insert into t2 values(6);
+select * from t2;
n
1
2
@@ -7,5 +30,7 @@ n
4
5
6
+show status like 'Slave_open_temp_tables';
Variable_name Value
Slave_open_temp_tables 0
+drop table if exists t1,t2;
diff --git a/mysql-test/r/rpl000013.result b/mysql-test/r/rpl000013.result
index ec2bd0684f1..5e4b4159e3a 100644
--- a/mysql-test/r/rpl000013.result
+++ b/mysql-test/r/rpl000013.result
@@ -1,3 +1,18 @@
+slave stop;
+reset master;
+reset slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+slave start;
+drop table if exists t2;
+create table t2(n int);
+create temporary table t1 (n int);
+insert into t1 values(1),(2),(3);
+insert into t2 select * from t1;
+create temporary table t1 (n int);
+insert into t1 values (4),(5);
+insert into t2 select * from t1 as t10;
+insert into t2 values(6);
+select * from t2;
n
1
2
@@ -5,5 +20,7 @@ n
4
5
6
+show status like 'Slave_open_temp_tables';
Variable_name Value
Slave_open_temp_tables 0
+drop table if exists t1,t2;
diff --git a/mysql-test/r/rpl000014.result b/mysql-test/r/rpl000014.result
index a47c3c91c1d..7a691119e5c 100644
--- a/mysql-test/r/rpl000014.result
+++ b/mysql-test/r/rpl000014.result
@@ -1,16 +1,39 @@
+slave stop;
+reset master;
+reset slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+slave start;
+show master status;
File Position Binlog_do_db Binlog_ignore_db
-master-bin.001 73
-Master_Host Master_User Master_Port Connect_retry Log_File Pos Slave_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter
-127.0.0.1 root 9999 1 master-bin.001 73 Yes 0 0
-Master_Host Master_User Master_Port Connect_retry Log_File Pos Slave_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter
-127.0.0.1 root 9999 1 master-bin.001 73 No 0 0
-Master_Host Master_User Master_Port Connect_retry Log_File Pos Slave_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter
-127.0.0.1 root 9999 1 master-bin.001 73 Yes 0 0
-Master_Host Master_User Master_Port Connect_retry Log_File Pos Slave_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter
-127.0.0.1 root 9999 1 master-bin.001 173 Yes 0 0
+master-bin.001 79
+show slave status;
+Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter Exec_master_log_pos
+127.0.0.1 root MASTER_PORT 1 master-bin.001 79 slave-relay-bin.002 120 master-bin.001 Yes Yes 0 0 79
+change master to master_log_pos=73;
+slave stop;
+change master to master_log_pos=73;
+show slave status;
+Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter Exec_master_log_pos
+127.0.0.1 root MASTER_PORT 1 master-bin.001 73 slave-relay-bin.001 4 master-bin.001 No No 0 0 73
+slave start;
+show slave status;
+Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter Exec_master_log_pos
+127.0.0.1 root MASTER_PORT 1 master-bin.001 73 slave-relay-bin.001 4 master-bin.001 Yes Yes 0 0 73
+change master to master_log_pos=173;
+show slave status;
+Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter Exec_master_log_pos
+127.0.0.1 root MASTER_PORT 1 master-bin.001 173 slave-relay-bin.001 4 master-bin.001 Yes Yes 0 0 173
+show master status;
File Position Binlog_do_db Binlog_ignore_db
-master-bin.001 73
+master-bin.001 79
+create table if not exists foo(n int);
+drop table if exists foo;
+create table foo (n int);
+insert into foo values (1),(2),(3);
+change master to master_log_pos=79;
+select * from foo;
n
1
2
3
+drop table foo;
diff --git a/mysql-test/r/rpl000015.result b/mysql-test/r/rpl000015.result
index 58487af27f8..03370bc6b0d 100644
--- a/mysql-test/r/rpl000015.result
+++ b/mysql-test/r/rpl000015.result
@@ -1,14 +1,30 @@
+reset master;
+show master status;
File Position Binlog_do_db Binlog_ignore_db
-master-bin.001 73
-Master_Host Master_User Master_Port Connect_retry Log_File Pos Slave_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter
- 0 0 0 No 0 0
-Master_Host Master_User Master_Port Connect_retry Log_File Pos Slave_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter
-127.0.0.1 test 9998 60 4 No 0 0
-Master_Host Master_User Master_Port Connect_retry Log_File Pos Slave_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter
-127.0.0.1 root 9999 60 4 No 0 0
-Master_Host Master_User Master_Port Connect_retry Log_File Pos Slave_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter
-127.0.0.1 root 9999 60 master-bin.001 73 Yes 0 0
+master-bin.001 79
+reset slave;
+show slave status;
+Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter Exec_master_log_pos
+ 0 0 0 0 No No 0 0 0
+change master to master_host='127.0.0.1';
+show slave status;
+Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter Exec_master_log_pos
+127.0.0.1 test MASTER_PORT 60 4 slave-relay-bin.001 4 No No 0 0 0
+change master to master_host='127.0.0.1',master_user='root',
+master_password='',master_port=MASTER_PORT;
+show slave status;
+Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter Exec_master_log_pos
+127.0.0.1 root MASTER_PORT 60 4 slave-relay-bin.001 4 No No 0 0 0
+slave start;
+show slave status;
+Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter Exec_master_log_pos
+127.0.0.1 root MASTER_PORT 60 master-bin.001 79 slave-relay-bin.001 120 master-bin.001 Yes Yes 0 0 79
+drop table if exists t1;
+create table t1 (n int);
+insert into t1 values (10),(45),(90);
+select * from t1;
n
10
45
90
+drop table t1;
diff --git a/mysql-test/r/rpl000016.result b/mysql-test/r/rpl000016.result
index 1390291f1e8..6a91309c29c 100644
--- a/mysql-test/r/rpl000016.result
+++ b/mysql-test/r/rpl000016.result
@@ -1,30 +1,74 @@
-Master_Host Master_User Master_Port Connect_retry Log_File Pos Slave_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter
-127.0.0.1 root 9999 60 master-bin.001 216 Yes 0 0
+slave start;
+Could not initialize master info structure, check permisions on master.info
+slave start;
+Could not initialize master info structure, check permisions on master.info
+change master to master_host='127.0.0.1',master_port=MASTER_PORT,
+master_user='root';
+Could not initialize master info
+reset slave;
+change master to master_host='127.0.0.1',master_port=MASTER_PORT,
+master_user='root';
+reset master;
+slave start;
+drop table if exists t1;
+create table t1 (s text);
+insert into t1 values('Could not break slave'),('Tried hard');
+show slave status;
+Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter Exec_master_log_pos
+127.0.0.1 root MASTER_PORT 60 master-bin.001 234 slave-relay-bin.001 275 master-bin.001 Yes Yes 0 0 234
+select * from t1;
s
Could not break slave
Tried hard
+flush logs;
+drop table if exists t2;
+create table t2(m int not null auto_increment primary key);
+insert into t2 values (34),(67),(123);
+flush logs;
+show master logs;
Log_name
master-bin.001
master-bin.002
master-bin.003
+insert into t2 values(1234);
+set insert_id=1234;
+insert into t2 values(NULL);
+set sql_slave_skip_counter=1;
+slave start;
+purge master logs to 'master-bin.003';
+show master logs;
Log_name
master-bin.003
-Master_Host Master_User Master_Port Connect_retry Log_File Pos Slave_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter
-127.0.0.1 root 9999 60 master-bin.003 206 Yes 0 0
+insert into t2 values (65);
+show slave status;
+Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter Exec_master_log_pos
+127.0.0.1 root MASTER_PORT 60 master-bin.003 155 slave-relay-bin.001 755 master-bin.003 Yes Yes 0 0 155
+select * from t2;
m
34
65
67
123
1234
+drop table if exists t3;
+create table t3 (n int);
+show master logs;
Log_name
master-bin.003
master-bin.004
master-bin.005
master-bin.006
+show master status;
File Position Binlog_do_db Binlog_ignore_db
-master-bin.006 131
-Master_Host Master_User Master_Port Connect_retry Log_File Pos Slave_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter
-127.0.0.1 root 9999 60 master-bin.006 131 Yes 0 0
+master-bin.006 445
+slave stop;
+slave start;
+show slave status;
+Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter Exec_master_log_pos
+127.0.0.1 root MASTER_PORT 60 master-bin.006 445 slave-relay-bin.004 1229 master-bin.006 Yes Yes 0 0 445
+lock tables t3 read;
+select count(*) from t3 where n >= 4;
count(*)
100
+unlock tables;
+drop table if exists t1,t2,t3;
diff --git a/mysql-test/r/rpl000017.result b/mysql-test/r/rpl000017.result
index e4f324047f8..e2c3c089378 100644
--- a/mysql-test/r/rpl000017.result
+++ b/mysql-test/r/rpl000017.result
@@ -1,2 +1,11 @@
+reset master;
+grant file on *.* to replicate@localhost identified by 'aaaaaaaaaaaaaaab';
+grant file on *.* to replicate@127.0.0.1 identified by 'aaaaaaaaaaaaaaab';
+slave start;
+drop table if exists t1;
+create table t1(n int);
+insert into t1 values(24);
+select * from t1;
n
24
+drop table t1;
diff --git a/mysql-test/r/rpl000018.result b/mysql-test/r/rpl000018.result
index 7c89c2ef2b2..ba51406bba0 100644
--- a/mysql-test/r/rpl000018.result
+++ b/mysql-test/r/rpl000018.result
@@ -1,5 +1,13 @@
+reset slave;
+slave start;
+show master logs;
Log_name
master-bin.001
master-bin.002
+drop table if exists t1;
+create table t1(n int);
+insert into t1 values (3351);
+select * from t1;
n
3351
+drop table t1;
diff --git a/mysql-test/r/rpl_compat.result b/mysql-test/r/rpl_compat.result
new file mode 100644
index 00000000000..5e497791771
--- /dev/null
+++ b/mysql-test/r/rpl_compat.result
@@ -0,0 +1,77 @@
+slave stop;
+reset master;
+reset slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+slave start;
+use test;
+drop table if exists t1,t3;
+create table t1 (word char(20) not null);
+load data infile '../../std_data/words.dat' into table t1;
+select * from t1;
+word
+Aarhus
+Aaron
+Ababa
+aback
+abaft
+abandon
+abandoned
+abandoning
+abandonment
+abandons
+set password for root@"localhost" = password('foo');
+set password for root@"localhost" = password('');
+create table t3(n int);
+insert into t3 values(1),(2);
+use test;
+select * from t3;
+n
+1
+2
+select sum(length(word)) from t1;
+sum(length(word))
+71
+drop table t1,t3;
+reset master;
+slave stop;
+reset slave;
+create table t1(n int);
+insert into t1 values (1),(2),(3);
+create table t2(id int);
+insert into t2 values(connection_id());
+create temporary table t1_temp(n int);
+insert into t1_temp select get_lock('crash_lock%20C', 1) from t2;
+ update t1 set n = n + get_lock('crash_lock%20C', 2);
+select (@id := id) - id from t2;
+(@id := id) - id
+0
+kill @id;
+drop table t2;
+Server shutdown in progress
+slave start;
+set sql_slave_skip_counter=1;
+slave start;
+select count(*) from t1;
+count(*)
+3
+drop table t1;
+create table t1 (n int);
+insert into t1 values(3456);
+use mysql;
+insert into user (Host, User, Password)
+VALUES ("10.10.10.%", "blafasel2", password("blafasel2"));
+select select_priv,user from mysql.user where user = 'blafasel2';
+select_priv user
+N blafasel2
+update user set Select_priv = "Y" where User="blafasel2";
+select select_priv,user from mysql.user where user = 'blafasel2';
+select_priv user
+Y blafasel2
+use test;
+select n from t1;
+n
+3456
+select select_priv,user from mysql.user where user = 'blafasel2';
+select_priv user
+Y blafasel2
+drop table t1;
diff --git a/mysql-test/r/rpl_failsafe.result b/mysql-test/r/rpl_failsafe.result
new file mode 100644
index 00000000000..14b749fada9
--- /dev/null
+++ b/mysql-test/r/rpl_failsafe.result
@@ -0,0 +1,33 @@
+slave stop;
+reset master;
+reset slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+slave start;
+show variables like 'rpl_recovery_rank';
+Variable_name Value
+rpl_recovery_rank 1
+show status like 'Rpl_status';
+Variable_name Value
+Rpl_status AUTH_MASTER
+create table t1(n int);
+drop table t1;
+show variables like 'rpl_recovery_rank';
+Variable_name Value
+rpl_recovery_rank 2
+show status like 'Rpl_status';
+Variable_name Value
+Rpl_status ACTIVE_SLAVE
+slave start;
+show variables like 'rpl_recovery_rank';
+Variable_name Value
+rpl_recovery_rank 3
+show status like 'Rpl_status';
+Variable_name Value
+Rpl_status ACTIVE_SLAVE
+slave start;
+show variables like 'rpl_recovery_rank';
+Variable_name Value
+rpl_recovery_rank 4
+show status like 'Rpl_status';
+Variable_name Value
+Rpl_status ACTIVE_SLAVE
diff --git a/mysql-test/r/rpl_get_lock.result b/mysql-test/r/rpl_get_lock.result
index 84749c1a9b1..c86b8f830a5 100644
--- a/mysql-test/r/rpl_get_lock.result
+++ b/mysql-test/r/rpl_get_lock.result
@@ -1,8 +1,20 @@
+slave stop;
+reset master;
+reset slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+slave start;
+create table t1(n int);
+insert into t1 values(get_lock("lock",2));
+select get_lock("lock",2);
get_lock("lock",2)
1
+select release_lock("lock");
release_lock("lock")
1
+select get_lock("lock",3);
get_lock("lock",3)
1
+select * from t1;
n
1
+drop table t1;
diff --git a/mysql-test/r/rpl_log.result b/mysql-test/r/rpl_log.result
new file mode 100644
index 00000000000..e91d17426c8
--- /dev/null
+++ b/mysql-test/r/rpl_log.result
@@ -0,0 +1,98 @@
+slave stop;
+reset master;
+reset slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+slave start;
+slave stop;
+reset master;
+reset slave;
+reset master;
+drop table if exists t1;
+create table t1(n int not null auto_increment primary key);
+insert into t1 values (NULL);
+drop table t1;
+create table t1 (word char(20) not null);
+load data infile '../../std_data/words.dat' into table t1;
+drop table t1;
+show binlog events;
+Log_name Pos Event_type Server_id Orig_log_pos Info
+master-bin.001 4 Start 1 4 Server ver: VERSION, Binlog ver: 3
+master-bin.001 79 Query 1 79 use test; create table t1(n int not null auto_increment primary key)
+master-bin.001 172 Intvar 1 172 INSERT_ID=1
+master-bin.001 200 Query 1 200 use test; insert into t1 values (NULL)
+master-bin.001 263 Query 1 263 use test; drop table t1
+master-bin.001 311 Query 1 311 use test; create table t1 (word char(20) not null)
+master-bin.001 386 Create_file 1 386 db=test;table=t1;file_id=1;block_len=81
+master-bin.001 556 Exec_load 1 556 ;file_id=1
+master-bin.001 579 Query 1 579 use test; drop table t1
+show binlog events from 79 limit 1;
+Log_name Pos Event_type Server_id Orig_log_pos Info
+master-bin.001 79 Query 1 79 use test; create table t1(n int not null auto_increment primary key)
+show binlog events from 79 limit 2;
+Log_name Pos Event_type Server_id Orig_log_pos Info
+master-bin.001 79 Query 1 79 use test; create table t1(n int not null auto_increment primary key)
+master-bin.001 172 Intvar 1 172 INSERT_ID=1
+show binlog events from 79 limit 2,1;
+Log_name Pos Event_type Server_id Orig_log_pos Info
+master-bin.001 200 Query 1 200 use test; insert into t1 values (NULL)
+flush logs;
+create table t1 (n int);
+insert into t1 values (1);
+drop table t1;
+show binlog events;
+Log_name Pos Event_type Server_id Orig_log_pos Info
+master-bin.001 4 Start 1 4 Server ver: VERSION, Binlog ver: 3
+master-bin.001 79 Query 1 79 use test; create table t1(n int not null auto_increment primary key)
+master-bin.001 172 Intvar 1 172 INSERT_ID=1
+master-bin.001 200 Query 1 200 use test; insert into t1 values (NULL)
+master-bin.001 263 Query 1 263 use test; drop table t1
+master-bin.001 311 Query 1 311 use test; create table t1 (word char(20) not null)
+master-bin.001 386 Create_file 1 386 db=test;table=t1;file_id=1;block_len=81
+master-bin.001 556 Exec_load 1 556 ;file_id=1
+master-bin.001 579 Query 1 579 use test; drop table t1
+master-bin.001 627 Rotate 1 627 master-bin.002;pos=4
+master-bin.001 668 Stop 1 668
+show binlog events in 'master-bin.002';
+Log_name Pos Event_type Server_id Orig_log_pos Info
+master-bin.002 4 Query 1 4 use test; create table t1 (n int)
+master-bin.002 62 Query 1 62 use test; insert into t1 values (1)
+master-bin.002 122 Query 1 122 use test; drop table t1
+show master logs;
+Log_name
+master-bin.001
+master-bin.002
+slave start;
+show master logs;
+Log_name
+slave-bin.001
+slave-bin.002
+show binlog events in 'slave-bin.001' from 4;
+show binlog events in 'slave-bin.002' from 4;
+Log_name Pos Event_type Server_id Orig_log_pos Info
+slave-bin.002 4 Slave 2 627 host=127.0.0.1,port=MASTER_PORT,log=master-bin.002,pos=4
+slave-bin.002 57 Query 1 4 use test; create table t1 (n int)
+slave-bin.002 115 Query 1 62 use test; insert into t1 values (1)
+slave-bin.002 175 Query 1 122 use test; drop table t1
+show slave status;
+Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter Exec_master_log_pos
+127.0.0.1 root MASTER_PORT 1 master-bin.002 170 slave-relay-bin.002 916 master-bin.002 Yes Yes 0 0 170
+show new master for slave with master_log_file='master-bin.001' and
+master_log_pos=4 and master_server_id=1;
+Log_name Log_pos
+slave-bin.001 132
+show new master for slave with master_log_file='master-bin.001' and
+master_log_pos=79 and master_server_id=1;
+Log_name Log_pos
+slave-bin.001 225
+show new master for slave with master_log_file='master-bin.001' and
+master_log_pos=311 and master_server_id=1;
+Log_name Log_pos
+slave-bin.001 439
+show new master for slave with master_log_file='master-bin.002' and
+master_log_pos=4 and master_server_id=1;
+Log_name Log_pos
+slave-bin.002 57
+show new master for slave with master_log_file='master-bin.002' and
+master_log_pos=122 and master_server_id=1;
+Log_name Log_pos
+slave-bin.002 223
diff --git a/mysql-test/r/rpl_magic.result b/mysql-test/r/rpl_magic.result
new file mode 100644
index 00000000000..b30d40d04eb
--- /dev/null
+++ b/mysql-test/r/rpl_magic.result
@@ -0,0 +1,36 @@
+slave stop;
+reset master;
+reset slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+slave start;
+drop table if exists t1;
+create table t1 ( n int);
+insert into t1 values (1),(2),(3),(4);
+insert into t1 values(5);
+select * from t1;
+n
+1
+2
+3
+4
+5
+select * from t1;
+n
+1
+2
+3
+4
+select * from t1;
+n
+1
+2
+3
+4
+select * from t1;
+n
+1
+2
+3
+4
+5
+drop table t1;
diff --git a/mysql-test/r/rpl_mystery22.result b/mysql-test/r/rpl_mystery22.result
index f85b057eefa..e798d774380 100644
--- a/mysql-test/r/rpl_mystery22.result
+++ b/mysql-test/r/rpl_mystery22.result
@@ -1,4 +1,23 @@
+drop table if exists t1;
+slave stop;
+reset master;
+reset slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+slave start;
+create table t1(n int auto_increment primary key);
+insert into t1 values (2);
+insert into t1 values(NULL);
+insert into t1 values(NULL);
+delete from t1 where n = 2;
+slave start;
+slave stop;
+create table t2(n int);
+drop table t2;
+insert into t1 values(NULL);
+slave start;
+select * from t1;
n
1
2
3
+drop table t1;
diff --git a/mysql-test/r/rpl_skip_error.result b/mysql-test/r/rpl_skip_error.result
index f85b057eefa..9fe92292178 100644
--- a/mysql-test/r/rpl_skip_error.result
+++ b/mysql-test/r/rpl_skip_error.result
@@ -1,3 +1,14 @@
+slave stop;
+reset master;
+reset slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+slave start;
+drop table if exists t1;
+create table t1 (n int not null primary key);
+insert into t1 values (1);
+insert into t1 values (1);
+insert into t1 values (2),(3);
+select * from t1;
n
1
2
diff --git a/mysql-test/r/rpl_sporadic_master.result b/mysql-test/r/rpl_sporadic_master.result
index ed616c26b67..ca74904889b 100644
--- a/mysql-test/r/rpl_sporadic_master.result
+++ b/mysql-test/r/rpl_sporadic_master.result
@@ -1,3 +1,21 @@
+slave stop;
+reset master;
+reset slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+slave start;
+drop table if exists t1,t2;
+create table t2(n int);
+create table t1(n int not null auto_increment primary key);
+insert into t1 values (NULL),(NULL);
+truncate table t1;
+insert into t1 values (4),(NULL);
+slave stop;
+slave start;
+insert into t1 values (NULL),(NULL);
+flush logs;
+truncate table t1;
+insert into t1 values (10),(NULL),(NULL),(NULL),(NULL),(NULL);
+select * from t1;
n
10
11
@@ -5,3 +23,4 @@ n
13
14
15
+drop table t1,t2;
diff --git a/mysql-test/r/sel000001.result b/mysql-test/r/sel000001.result
index bee97cc7b53..28f6d3d1d5a 100644
--- a/mysql-test/r/sel000001.result
+++ b/mysql-test/r/sel000001.result
@@ -1,2 +1,7 @@
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (s CHAR(20) PRIMARY KEY, id INT);
+INSERT INTO t1 VALUES ('cat', 1), ('mouse', 3), ('dog', 2), ('snake', 77);
+SELECT s, id FROM t1 WHERE s = 'mouse';
s id
mouse 3
+drop table t1;
diff --git a/mysql-test/r/sel000002.result b/mysql-test/r/sel000002.result
index f85b057eefa..b824de8de4a 100644
--- a/mysql-test/r/sel000002.result
+++ b/mysql-test/r/sel000002.result
@@ -1,4 +1,9 @@
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (n INT);
+INSERT INTO t1 VALUES (1), (2), (3);
+SELECT * FROM t1;
n
1
2
3
+drop table t1;
diff --git a/mysql-test/r/sel000003.result b/mysql-test/r/sel000003.result
index 77312414818..c3853832f87 100644
--- a/mysql-test/r/sel000003.result
+++ b/mysql-test/r/sel000003.result
@@ -1,3 +1,8 @@
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (name CHAR(20) NOT NULL PRIMARY KEY, score SMALLINT NOT NULL, KEY(score));
+INSERT INTO t1 VALUES ('Sasha', 20), ('Matt', 20), ('Monty', 10), ('David', 10), ('Tim', 10), ('Jeremy', 10);
+SELECT COUNT(*) as n, score FROM t1 GROUP BY score;
n score
4 10
2 20
+drop table t1;
diff --git a/mysql-test/r/sel000031.result b/mysql-test/r/sel000031.result
index c1caa04a00a..d3f01ab687f 100644
--- a/mysql-test/r/sel000031.result
+++ b/mysql-test/r/sel000031.result
@@ -1,4 +1,12 @@
+drop table if exists t1,t2;
+create table t1 (id int(10) not null unique);
+create table t2 (id int(10) not null primary key,
+val int(10) not null);
+insert into t1 values (1),(2),(4);
+insert into t2 values (1,1),(2,1),(3,1),(4,2);
+select one.id, elt(two.val,'one','two') from t1 one, t2 two where two.id=one.id order by one.id;
id elt(two.val,'one','two')
1 one
2 one
4 two
+drop table t1,t2;
diff --git a/mysql-test/r/sel000032.result b/mysql-test/r/sel000032.result
index c1caa04a00a..4cca245d75b 100644
--- a/mysql-test/r/sel000032.result
+++ b/mysql-test/r/sel000032.result
@@ -1,4 +1,12 @@
+drop table if exists t1,t2;
+create table t1 (id int(10) not null unique);
+create table t2 (id int(10) not null primary key,
+val int(10) not null);
+insert into t1 values (1),(2),(4);
+insert into t2 values (1,1),(2,1),(3,1),(4,2);
+select one.id, elt(two.val,'one','two') from t1 one, t2 two where two.id=one.id;
id elt(two.val,'one','two')
1 one
2 one
4 two
+drop table t1,t2;
diff --git a/mysql-test/r/sel000033.result b/mysql-test/r/sel000033.result
index 689c94082e7..1bfafaf5b27 100644
--- a/mysql-test/r/sel000033.result
+++ b/mysql-test/r/sel000033.result
@@ -1,8 +1,14 @@
+drop table if exists t1;
+create table t1 (id int(10) primary key);
+insert into t1 values (1),(2),(3),(4),(5),(6),(7),(8),(9);
+select id from t1 where id in (2,5,9) ;
id
2
5
9
+select id from t1 where id=2 or id=5 or id=9 ;
id
2
5
9
+drop table t1;
diff --git a/mysql-test/r/sel000100.result b/mysql-test/r/sel000100.result
index e7d8cf0e7ac..f9234815a2b 100644
--- a/mysql-test/r/sel000100.result
+++ b/mysql-test/r/sel000100.result
@@ -1,2 +1,28 @@
+DROP TABLE IF EXISTS t1,t2;
+CREATE TABLE t1 (
+ID int(11) NOT NULL auto_increment,
+NAME varchar(75) DEFAULT '' NOT NULL,
+LINK_ID int(11) DEFAULT '0' NOT NULL,
+PRIMARY KEY (ID),
+KEY NAME (NAME),
+KEY LINK_ID (LINK_ID)
+);
+INSERT INTO t1 (ID, NAME, LINK_ID) VALUES (1,'Mike',0);
+INSERT INTO t1 (ID, NAME, LINK_ID) VALUES (2,'Jack',0);
+INSERT INTO t1 (ID, NAME, LINK_ID) VALUES (3,'Bill',0);
+CREATE TABLE t2 (
+ID int(11) NOT NULL auto_increment,
+NAME varchar(150) DEFAULT '' NOT NULL,
+PRIMARY KEY (ID),
+KEY NAME (NAME)
+);
+SELECT DISTINCT
+t2.id AS key_link_id,
+t2.name AS link
+FROM t1
+LEFT JOIN t2 ON t1.link_id=t2.id
+GROUP BY t1.id
+ORDER BY link;
key_link_id link
NULL NULL
+drop table t1,t2;
diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result
index 413b03130f6..051aeb43b43 100644
--- a/mysql-test/r/select.result
+++ b/mysql-test/r/select.result
@@ -1,13 +1,1237 @@
+use test;
+drop table if exists t1,t2,t3,t4;
+CREATE TABLE t1 (
+Period smallint(4) unsigned zerofill DEFAULT '0000' NOT NULL,
+Varor_period smallint(4) unsigned DEFAULT '0' NOT NULL
+);
+INSERT INTO t1 VALUES (9410,9412);
+select period from t1;
period
9410
+select * from t1;
Period Varor_period
9410 9412
+select t1.* from t1;
Period Varor_period
9410 9412
+CREATE TABLE t2 (
+auto int not null auto_increment,
+fld1 int(6) unsigned zerofill DEFAULT '000000' NOT NULL,
+companynr tinyint(2) unsigned zerofill DEFAULT '00' NOT NULL,
+fld3 char(30) DEFAULT '' NOT NULL,
+fld4 char(35) DEFAULT '' NOT NULL,
+fld5 char(35) DEFAULT '' NOT NULL,
+fld6 char(4) DEFAULT '' NOT NULL,
+UNIQUE fld1 (fld1),
+KEY fld3 (fld3),
+PRIMARY KEY (auto)
+);
+INSERT INTO t2 VALUES (1,000001,00,'Omaha','teethe','neat','');
+INSERT INTO t2 VALUES (2,011401,37,'breaking','dreaded','Steinberg','W');
+INSERT INTO t2 VALUES (3,011402,37,'Romans','scholastics','jarring','');
+INSERT INTO t2 VALUES (4,011403,37,'intercepted','audiology','tinily','');
+INSERT INTO t2 VALUES (5,011501,37,'bewilderingly','wallet','balled','');
+INSERT INTO t2 VALUES (6,011701,37,'astound','parters','persist','W');
+INSERT INTO t2 VALUES (7,011702,37,'admonishing','eschew','attainments','');
+INSERT INTO t2 VALUES (8,011703,37,'sumac','quitter','fanatic','');
+INSERT INTO t2 VALUES (9,012001,37,'flanking','neat','measures','FAS');
+INSERT INTO t2 VALUES (10,012003,37,'combed','Steinberg','rightfulness','');
+INSERT INTO t2 VALUES (11,012004,37,'subjective','jarring','capably','');
+INSERT INTO t2 VALUES (12,012005,37,'scatterbrain','tinily','impulsive','');
+INSERT INTO t2 VALUES (13,012301,37,'Eulerian','balled','starlet','');
+INSERT INTO t2 VALUES (14,012302,36,'dubbed','persist','terminators','');
+INSERT INTO t2 VALUES (15,012303,37,'Kane','attainments','untying','');
+INSERT INTO t2 VALUES (16,012304,37,'overlay','fanatic','announces','FAS');
+INSERT INTO t2 VALUES (17,012305,37,'perturb','measures','featherweight','FAS');
+INSERT INTO t2 VALUES (18,012306,37,'goblins','rightfulness','pessimist','FAS');
+INSERT INTO t2 VALUES (19,012501,37,'annihilates','capably','daughter','');
+INSERT INTO t2 VALUES (20,012602,37,'Wotan','impulsive','decliner','FAS');
+INSERT INTO t2 VALUES (21,012603,37,'snatching','starlet','lawgiver','');
+INSERT INTO t2 VALUES (22,012604,37,'concludes','terminators','stated','');
+INSERT INTO t2 VALUES (23,012605,37,'laterally','untying','readable','');
+INSERT INTO t2 VALUES (24,012606,37,'yelped','announces','attrition','');
+INSERT INTO t2 VALUES (25,012701,37,'grazing','featherweight','cascade','FAS');
+INSERT INTO t2 VALUES (26,012702,37,'Baird','pessimist','motors','FAS');
+INSERT INTO t2 VALUES (27,012703,37,'celery','daughter','interrogate','');
+INSERT INTO t2 VALUES (28,012704,37,'misunderstander','decliner','pests','W');
+INSERT INTO t2 VALUES (29,013601,37,'handgun','lawgiver','stairway','');
+INSERT INTO t2 VALUES (30,013602,37,'foldout','stated','dopers','FAS');
+INSERT INTO t2 VALUES (31,013603,37,'mystic','readable','testicle','W');
+INSERT INTO t2 VALUES (32,013604,37,'succumbed','attrition','Parsifal','W');
+INSERT INTO t2 VALUES (33,013605,37,'Nabisco','cascade','leavings','');
+INSERT INTO t2 VALUES (34,013606,37,'fingerings','motors','postulation','W');
+INSERT INTO t2 VALUES (35,013607,37,'aging','interrogate','squeaking','');
+INSERT INTO t2 VALUES (36,013608,37,'afield','pests','contrasted','');
+INSERT INTO t2 VALUES (37,013609,37,'ammonium','stairway','leftover','');
+INSERT INTO t2 VALUES (38,013610,37,'boat','dopers','whiteners','');
+INSERT INTO t2 VALUES (39,013801,37,'intelligibility','testicle','erases','W');
+INSERT INTO t2 VALUES (40,013802,37,'Augustine','Parsifal','Punjab','W');
+INSERT INTO t2 VALUES (41,013803,37,'teethe','leavings','Merritt','');
+INSERT INTO t2 VALUES (42,013804,37,'dreaded','postulation','Quixotism','');
+INSERT INTO t2 VALUES (43,013901,37,'scholastics','squeaking','sweetish','FAS');
+INSERT INTO t2 VALUES (44,016001,37,'audiology','contrasted','dogging','FAS');
+INSERT INTO t2 VALUES (45,016201,37,'wallet','leftover','scornfully','FAS');
+INSERT INTO t2 VALUES (46,016202,37,'parters','whiteners','bellow','');
+INSERT INTO t2 VALUES (47,016301,37,'eschew','erases','bills','');
+INSERT INTO t2 VALUES (48,016302,37,'quitter','Punjab','cupboard','FAS');
+INSERT INTO t2 VALUES (49,016303,37,'neat','Merritt','sureties','FAS');
+INSERT INTO t2 VALUES (50,016304,37,'Steinberg','Quixotism','puddings','');
+INSERT INTO t2 VALUES (51,018001,37,'jarring','sweetish','tapestry','');
+INSERT INTO t2 VALUES (52,018002,37,'tinily','dogging','fetters','');
+INSERT INTO t2 VALUES (53,018003,37,'balled','scornfully','bivalves','');
+INSERT INTO t2 VALUES (54,018004,37,'persist','bellow','incurring','');
+INSERT INTO t2 VALUES (55,018005,37,'attainments','bills','Adolph','');
+INSERT INTO t2 VALUES (56,018007,37,'fanatic','cupboard','pithed','');
+INSERT INTO t2 VALUES (57,018008,37,'measures','sureties','emergency','');
+INSERT INTO t2 VALUES (58,018009,37,'rightfulness','puddings','Miles','');
+INSERT INTO t2 VALUES (59,018010,37,'capably','tapestry','trimmings','');
+INSERT INTO t2 VALUES (60,018012,37,'impulsive','fetters','tragedies','W');
+INSERT INTO t2 VALUES (61,018013,37,'starlet','bivalves','skulking','W');
+INSERT INTO t2 VALUES (62,018014,37,'terminators','incurring','flint','');
+INSERT INTO t2 VALUES (63,018015,37,'untying','Adolph','flopping','W');
+INSERT INTO t2 VALUES (64,018016,37,'announces','pithed','relaxing','FAS');
+INSERT INTO t2 VALUES (65,018017,37,'featherweight','emergency','offload','FAS');
+INSERT INTO t2 VALUES (66,018018,37,'pessimist','Miles','suites','W');
+INSERT INTO t2 VALUES (67,018019,37,'daughter','trimmings','lists','FAS');
+INSERT INTO t2 VALUES (68,018020,37,'decliner','tragedies','animized','FAS');
+INSERT INTO t2 VALUES (69,018021,37,'lawgiver','skulking','multilayer','W');
+INSERT INTO t2 VALUES (70,018022,37,'stated','flint','standardizes','FAS');
+INSERT INTO t2 VALUES (71,018023,37,'readable','flopping','Judas','');
+INSERT INTO t2 VALUES (72,018024,37,'attrition','relaxing','vacuuming','W');
+INSERT INTO t2 VALUES (73,018025,37,'cascade','offload','dentally','W');
+INSERT INTO t2 VALUES (74,018026,37,'motors','suites','humanness','W');
+INSERT INTO t2 VALUES (75,018027,37,'interrogate','lists','inch','W');
+INSERT INTO t2 VALUES (76,018028,37,'pests','animized','Weissmuller','W');
+INSERT INTO t2 VALUES (77,018029,37,'stairway','multilayer','irresponsibly','W');
+INSERT INTO t2 VALUES (78,018030,37,'dopers','standardizes','luckily','FAS');
+INSERT INTO t2 VALUES (79,018032,37,'testicle','Judas','culled','W');
+INSERT INTO t2 VALUES (80,018033,37,'Parsifal','vacuuming','medical','FAS');
+INSERT INTO t2 VALUES (81,018034,37,'leavings','dentally','bloodbath','FAS');
+INSERT INTO t2 VALUES (82,018035,37,'postulation','humanness','subschema','W');
+INSERT INTO t2 VALUES (83,018036,37,'squeaking','inch','animals','W');
+INSERT INTO t2 VALUES (84,018037,37,'contrasted','Weissmuller','Micronesia','');
+INSERT INTO t2 VALUES (85,018038,37,'leftover','irresponsibly','repetitions','');
+INSERT INTO t2 VALUES (86,018039,37,'whiteners','luckily','Antares','');
+INSERT INTO t2 VALUES (87,018040,37,'erases','culled','ventilate','W');
+INSERT INTO t2 VALUES (88,018041,37,'Punjab','medical','pityingly','');
+INSERT INTO t2 VALUES (89,018042,37,'Merritt','bloodbath','interdependent','');
+INSERT INTO t2 VALUES (90,018043,37,'Quixotism','subschema','Graves','FAS');
+INSERT INTO t2 VALUES (91,018044,37,'sweetish','animals','neonatal','');
+INSERT INTO t2 VALUES (92,018045,37,'dogging','Micronesia','scribbled','FAS');
+INSERT INTO t2 VALUES (93,018046,37,'scornfully','repetitions','chafe','W');
+INSERT INTO t2 VALUES (94,018048,37,'bellow','Antares','honoring','');
+INSERT INTO t2 VALUES (95,018049,37,'bills','ventilate','realtor','');
+INSERT INTO t2 VALUES (96,018050,37,'cupboard','pityingly','elite','');
+INSERT INTO t2 VALUES (97,018051,37,'sureties','interdependent','funereal','');
+INSERT INTO t2 VALUES (98,018052,37,'puddings','Graves','abrogating','');
+INSERT INTO t2 VALUES (99,018053,50,'tapestry','neonatal','sorters','');
+INSERT INTO t2 VALUES (100,018054,37,'fetters','scribbled','Conley','');
+INSERT INTO t2 VALUES (101,018055,37,'bivalves','chafe','lectured','');
+INSERT INTO t2 VALUES (102,018056,37,'incurring','honoring','Abraham','');
+INSERT INTO t2 VALUES (103,018057,37,'Adolph','realtor','Hawaii','W');
+INSERT INTO t2 VALUES (104,018058,37,'pithed','elite','cage','');
+INSERT INTO t2 VALUES (105,018059,36,'emergency','funereal','hushes','');
+INSERT INTO t2 VALUES (106,018060,37,'Miles','abrogating','Simla','');
+INSERT INTO t2 VALUES (107,018061,37,'trimmings','sorters','reporters','');
+INSERT INTO t2 VALUES (108,018101,37,'tragedies','Conley','Dutchman','FAS');
+INSERT INTO t2 VALUES (109,018102,37,'skulking','lectured','descendants','FAS');
+INSERT INTO t2 VALUES (110,018103,37,'flint','Abraham','groupings','FAS');
+INSERT INTO t2 VALUES (111,018104,37,'flopping','Hawaii','dissociate','');
+INSERT INTO t2 VALUES (112,018201,37,'relaxing','cage','coexist','W');
+INSERT INTO t2 VALUES (113,018202,37,'offload','hushes','Beebe','');
+INSERT INTO t2 VALUES (114,018402,37,'suites','Simla','Taoism','');
+INSERT INTO t2 VALUES (115,018403,37,'lists','reporters','Connally','');
+INSERT INTO t2 VALUES (116,018404,37,'animized','Dutchman','fetched','FAS');
+INSERT INTO t2 VALUES (117,018405,37,'multilayer','descendants','checkpoints','FAS');
+INSERT INTO t2 VALUES (118,018406,37,'standardizes','groupings','rusting','');
+INSERT INTO t2 VALUES (119,018409,37,'Judas','dissociate','galling','');
+INSERT INTO t2 VALUES (120,018601,37,'vacuuming','coexist','obliterates','');
+INSERT INTO t2 VALUES (121,018602,37,'dentally','Beebe','traitor','');
+INSERT INTO t2 VALUES (122,018603,37,'humanness','Taoism','resumes','FAS');
+INSERT INTO t2 VALUES (123,018801,37,'inch','Connally','analyzable','FAS');
+INSERT INTO t2 VALUES (124,018802,37,'Weissmuller','fetched','terminator','FAS');
+INSERT INTO t2 VALUES (125,018803,37,'irresponsibly','checkpoints','gritty','FAS');
+INSERT INTO t2 VALUES (126,018804,37,'luckily','rusting','firearm','W');
+INSERT INTO t2 VALUES (127,018805,37,'culled','galling','minima','');
+INSERT INTO t2 VALUES (128,018806,37,'medical','obliterates','Selfridge','');
+INSERT INTO t2 VALUES (129,018807,37,'bloodbath','traitor','disable','');
+INSERT INTO t2 VALUES (130,018808,37,'subschema','resumes','witchcraft','W');
+INSERT INTO t2 VALUES (131,018809,37,'animals','analyzable','betroth','W');
+INSERT INTO t2 VALUES (132,018810,37,'Micronesia','terminator','Manhattanize','');
+INSERT INTO t2 VALUES (133,018811,37,'repetitions','gritty','imprint','');
+INSERT INTO t2 VALUES (134,018812,37,'Antares','firearm','peeked','');
+INSERT INTO t2 VALUES (135,019101,37,'ventilate','minima','swelling','');
+INSERT INTO t2 VALUES (136,019102,37,'pityingly','Selfridge','interrelationships','W');
+INSERT INTO t2 VALUES (137,019103,37,'interdependent','disable','riser','');
+INSERT INTO t2 VALUES (138,019201,37,'Graves','witchcraft','Gandhian','W');
+INSERT INTO t2 VALUES (139,030501,37,'neonatal','betroth','peacock','A');
+INSERT INTO t2 VALUES (140,030502,50,'scribbled','Manhattanize','bee','A');
+INSERT INTO t2 VALUES (141,030503,37,'chafe','imprint','kanji','');
+INSERT INTO t2 VALUES (142,030504,37,'honoring','peeked','dental','');
+INSERT INTO t2 VALUES (143,031901,37,'realtor','swelling','scarf','FAS');
+INSERT INTO t2 VALUES (144,036001,37,'elite','interrelationships','chasm','A');
+INSERT INTO t2 VALUES (145,036002,37,'funereal','riser','insolence','A');
+INSERT INTO t2 VALUES (146,036004,37,'abrogating','Gandhian','syndicate','');
+INSERT INTO t2 VALUES (147,036005,37,'sorters','peacock','alike','');
+INSERT INTO t2 VALUES (148,038001,37,'Conley','bee','imperial','A');
+INSERT INTO t2 VALUES (149,038002,37,'lectured','kanji','convulsion','A');
+INSERT INTO t2 VALUES (150,038003,37,'Abraham','dental','railway','A');
+INSERT INTO t2 VALUES (151,038004,37,'Hawaii','scarf','validate','A');
+INSERT INTO t2 VALUES (152,038005,37,'cage','chasm','normalizes','A');
+INSERT INTO t2 VALUES (153,038006,37,'hushes','insolence','comprehensive','');
+INSERT INTO t2 VALUES (154,038007,37,'Simla','syndicate','chewing','');
+INSERT INTO t2 VALUES (155,038008,37,'reporters','alike','denizen','');
+INSERT INTO t2 VALUES (156,038009,37,'Dutchman','imperial','schemer','');
+INSERT INTO t2 VALUES (157,038010,37,'descendants','convulsion','chronicle','');
+INSERT INTO t2 VALUES (158,038011,37,'groupings','railway','Kline','');
+INSERT INTO t2 VALUES (159,038012,37,'dissociate','validate','Anatole','');
+INSERT INTO t2 VALUES (160,038013,37,'coexist','normalizes','partridges','');
+INSERT INTO t2 VALUES (161,038014,37,'Beebe','comprehensive','brunch','');
+INSERT INTO t2 VALUES (162,038015,37,'Taoism','chewing','recruited','');
+INSERT INTO t2 VALUES (163,038016,37,'Connally','denizen','dimensions','W');
+INSERT INTO t2 VALUES (164,038017,37,'fetched','schemer','Chicana','W');
+INSERT INTO t2 VALUES (165,038018,37,'checkpoints','chronicle','announced','');
+INSERT INTO t2 VALUES (166,038101,37,'rusting','Kline','praised','FAS');
+INSERT INTO t2 VALUES (167,038102,37,'galling','Anatole','employing','');
+INSERT INTO t2 VALUES (168,038103,37,'obliterates','partridges','linear','');
+INSERT INTO t2 VALUES (169,038104,37,'traitor','brunch','quagmire','');
+INSERT INTO t2 VALUES (170,038201,37,'resumes','recruited','western','A');
+INSERT INTO t2 VALUES (171,038202,37,'analyzable','dimensions','relishing','');
+INSERT INTO t2 VALUES (172,038203,37,'terminator','Chicana','serving','A');
+INSERT INTO t2 VALUES (173,038204,37,'gritty','announced','scheduling','');
+INSERT INTO t2 VALUES (174,038205,37,'firearm','praised','lore','');
+INSERT INTO t2 VALUES (175,038206,37,'minima','employing','eventful','');
+INSERT INTO t2 VALUES (176,038208,37,'Selfridge','linear','arteriole','A');
+INSERT INTO t2 VALUES (177,042801,37,'disable','quagmire','disentangle','');
+INSERT INTO t2 VALUES (178,042802,37,'witchcraft','western','cured','A');
+INSERT INTO t2 VALUES (179,046101,37,'betroth','relishing','Fenton','W');
+INSERT INTO t2 VALUES (180,048001,37,'Manhattanize','serving','avoidable','A');
+INSERT INTO t2 VALUES (181,048002,37,'imprint','scheduling','drains','A');
+INSERT INTO t2 VALUES (182,048003,37,'peeked','lore','detectably','FAS');
+INSERT INTO t2 VALUES (183,048004,37,'swelling','eventful','husky','');
+INSERT INTO t2 VALUES (184,048005,37,'interrelationships','arteriole','impelling','');
+INSERT INTO t2 VALUES (185,048006,37,'riser','disentangle','undoes','');
+INSERT INTO t2 VALUES (186,048007,37,'Gandhian','cured','evened','');
+INSERT INTO t2 VALUES (187,048008,37,'peacock','Fenton','squeezes','');
+INSERT INTO t2 VALUES (188,048101,37,'bee','avoidable','destroyer','FAS');
+INSERT INTO t2 VALUES (189,048102,37,'kanji','drains','rudeness','');
+INSERT INTO t2 VALUES (190,048201,37,'dental','detectably','beaner','FAS');
+INSERT INTO t2 VALUES (191,048202,37,'scarf','husky','boorish','');
+INSERT INTO t2 VALUES (192,048203,37,'chasm','impelling','Everhart','');
+INSERT INTO t2 VALUES (193,048204,37,'insolence','undoes','encompass','A');
+INSERT INTO t2 VALUES (194,048205,37,'syndicate','evened','mushrooms','');
+INSERT INTO t2 VALUES (195,048301,37,'alike','squeezes','Alison','A');
+INSERT INTO t2 VALUES (196,048302,37,'imperial','destroyer','externally','FAS');
+INSERT INTO t2 VALUES (197,048303,37,'convulsion','rudeness','pellagra','');
+INSERT INTO t2 VALUES (198,048304,37,'railway','beaner','cult','');
+INSERT INTO t2 VALUES (199,048305,37,'validate','boorish','creek','A');
+INSERT INTO t2 VALUES (200,048401,37,'normalizes','Everhart','Huffman','');
+INSERT INTO t2 VALUES (201,048402,37,'comprehensive','encompass','Majorca','FAS');
+INSERT INTO t2 VALUES (202,048403,37,'chewing','mushrooms','governing','A');
+INSERT INTO t2 VALUES (203,048404,37,'denizen','Alison','gadfly','FAS');
+INSERT INTO t2 VALUES (204,048405,37,'schemer','externally','reassigned','FAS');
+INSERT INTO t2 VALUES (205,048406,37,'chronicle','pellagra','intentness','W');
+INSERT INTO t2 VALUES (206,048407,37,'Kline','cult','craziness','');
+INSERT INTO t2 VALUES (207,048408,37,'Anatole','creek','psychic','');
+INSERT INTO t2 VALUES (208,048409,37,'partridges','Huffman','squabbled','');
+INSERT INTO t2 VALUES (209,048410,37,'brunch','Majorca','burlesque','');
+INSERT INTO t2 VALUES (210,048411,37,'recruited','governing','capped','');
+INSERT INTO t2 VALUES (211,048412,37,'dimensions','gadfly','extracted','A');
+INSERT INTO t2 VALUES (212,048413,37,'Chicana','reassigned','DiMaggio','');
+INSERT INTO t2 VALUES (213,048601,37,'announced','intentness','exclamation','FAS');
+INSERT INTO t2 VALUES (214,048602,37,'praised','craziness','subdirectory','');
+INSERT INTO t2 VALUES (215,048603,37,'employing','psychic','fangs','');
+INSERT INTO t2 VALUES (216,048604,37,'linear','squabbled','buyer','A');
+INSERT INTO t2 VALUES (217,048801,37,'quagmire','burlesque','pithing','A');
+INSERT INTO t2 VALUES (218,050901,37,'western','capped','transistorizing','A');
+INSERT INTO t2 VALUES (219,051201,37,'relishing','extracted','nonbiodegradable','');
+INSERT INTO t2 VALUES (220,056002,37,'serving','DiMaggio','dislocate','');
+INSERT INTO t2 VALUES (221,056003,37,'scheduling','exclamation','monochromatic','FAS');
+INSERT INTO t2 VALUES (222,056004,37,'lore','subdirectory','batting','');
+INSERT INTO t2 VALUES (223,056102,37,'eventful','fangs','postcondition','A');
+INSERT INTO t2 VALUES (224,056203,37,'arteriole','buyer','catalog','FAS');
+INSERT INTO t2 VALUES (225,056204,37,'disentangle','pithing','Remus','');
+INSERT INTO t2 VALUES (226,058003,37,'cured','transistorizing','devices','A');
+INSERT INTO t2 VALUES (227,058004,37,'Fenton','nonbiodegradable','bike','A');
+INSERT INTO t2 VALUES (228,058005,37,'avoidable','dislocate','qualify','');
+INSERT INTO t2 VALUES (229,058006,37,'drains','monochromatic','detained','');
+INSERT INTO t2 VALUES (230,058007,37,'detectably','batting','commended','');
+INSERT INTO t2 VALUES (231,058101,37,'husky','postcondition','civilize','');
+INSERT INTO t2 VALUES (232,058102,37,'impelling','catalog','Elmhurst','');
+INSERT INTO t2 VALUES (233,058103,37,'undoes','Remus','anesthetizing','');
+INSERT INTO t2 VALUES (234,058105,37,'evened','devices','deaf','');
+INSERT INTO t2 VALUES (235,058111,37,'squeezes','bike','Brigham','');
+INSERT INTO t2 VALUES (236,058112,37,'destroyer','qualify','title','');
+INSERT INTO t2 VALUES (237,058113,37,'rudeness','detained','coarse','');
+INSERT INTO t2 VALUES (238,058114,37,'beaner','commended','combinations','');
+INSERT INTO t2 VALUES (239,058115,37,'boorish','civilize','grayness','');
+INSERT INTO t2 VALUES (240,058116,37,'Everhart','Elmhurst','innumerable','FAS');
+INSERT INTO t2 VALUES (241,058117,37,'encompass','anesthetizing','Caroline','A');
+INSERT INTO t2 VALUES (242,058118,37,'mushrooms','deaf','fatty','FAS');
+INSERT INTO t2 VALUES (243,058119,37,'Alison','Brigham','eastbound','');
+INSERT INTO t2 VALUES (244,058120,37,'externally','title','inexperienced','');
+INSERT INTO t2 VALUES (245,058121,37,'pellagra','coarse','hoarder','A');
+INSERT INTO t2 VALUES (246,058122,37,'cult','combinations','scotch','W');
+INSERT INTO t2 VALUES (247,058123,37,'creek','grayness','passport','A');
+INSERT INTO t2 VALUES (248,058124,37,'Huffman','innumerable','strategic','FAS');
+INSERT INTO t2 VALUES (249,058125,37,'Majorca','Caroline','gated','');
+INSERT INTO t2 VALUES (250,058126,37,'governing','fatty','flog','');
+INSERT INTO t2 VALUES (251,058127,37,'gadfly','eastbound','Pipestone','');
+INSERT INTO t2 VALUES (252,058128,37,'reassigned','inexperienced','Dar','');
+INSERT INTO t2 VALUES (253,058201,37,'intentness','hoarder','Corcoran','');
+INSERT INTO t2 VALUES (254,058202,37,'craziness','scotch','flyers','A');
+INSERT INTO t2 VALUES (255,058303,37,'psychic','passport','competitions','W');
+INSERT INTO t2 VALUES (256,058304,37,'squabbled','strategic','suppliers','FAS');
+INSERT INTO t2 VALUES (257,058602,37,'burlesque','gated','skips','');
+INSERT INTO t2 VALUES (258,058603,37,'capped','flog','institutes','');
+INSERT INTO t2 VALUES (259,058604,37,'extracted','Pipestone','troop','A');
+INSERT INTO t2 VALUES (260,058605,37,'DiMaggio','Dar','connective','W');
+INSERT INTO t2 VALUES (261,058606,37,'exclamation','Corcoran','denies','');
+INSERT INTO t2 VALUES (262,058607,37,'subdirectory','flyers','polka','');
+INSERT INTO t2 VALUES (263,060401,36,'fangs','competitions','observations','FAS');
+INSERT INTO t2 VALUES (264,061701,36,'buyer','suppliers','askers','');
+INSERT INTO t2 VALUES (265,066201,36,'pithing','skips','homeless','FAS');
+INSERT INTO t2 VALUES (266,066501,36,'transistorizing','institutes','Anna','');
+INSERT INTO t2 VALUES (267,068001,36,'nonbiodegradable','troop','subdirectories','W');
+INSERT INTO t2 VALUES (268,068002,36,'dislocate','connective','decaying','FAS');
+INSERT INTO t2 VALUES (269,068005,36,'monochromatic','denies','outwitting','W');
+INSERT INTO t2 VALUES (270,068006,36,'batting','polka','Harpy','W');
+INSERT INTO t2 VALUES (271,068007,36,'postcondition','observations','crazed','');
+INSERT INTO t2 VALUES (272,068008,36,'catalog','askers','suffocate','');
+INSERT INTO t2 VALUES (273,068009,36,'Remus','homeless','provers','FAS');
+INSERT INTO t2 VALUES (274,068010,36,'devices','Anna','technically','');
+INSERT INTO t2 VALUES (275,068011,36,'bike','subdirectories','Franklinizations','');
+INSERT INTO t2 VALUES (276,068202,36,'qualify','decaying','considered','');
+INSERT INTO t2 VALUES (277,068302,36,'detained','outwitting','tinnily','');
+INSERT INTO t2 VALUES (278,068303,36,'commended','Harpy','uninterruptedly','');
+INSERT INTO t2 VALUES (279,068401,36,'civilize','crazed','whistled','A');
+INSERT INTO t2 VALUES (280,068501,36,'Elmhurst','suffocate','automate','');
+INSERT INTO t2 VALUES (281,068502,36,'anesthetizing','provers','gutting','W');
+INSERT INTO t2 VALUES (282,068503,36,'deaf','technically','surreptitious','');
+INSERT INTO t2 VALUES (283,068602,36,'Brigham','Franklinizations','Choctaw','');
+INSERT INTO t2 VALUES (284,068603,36,'title','considered','cooks','');
+INSERT INTO t2 VALUES (285,068701,36,'coarse','tinnily','millivolt','FAS');
+INSERT INTO t2 VALUES (286,068702,36,'combinations','uninterruptedly','counterpoise','');
+INSERT INTO t2 VALUES (287,068703,36,'grayness','whistled','Gothicism','');
+INSERT INTO t2 VALUES (288,076001,36,'innumerable','automate','feminine','');
+INSERT INTO t2 VALUES (289,076002,36,'Caroline','gutting','metaphysically','W');
+INSERT INTO t2 VALUES (290,076101,36,'fatty','surreptitious','sanding','A');
+INSERT INTO t2 VALUES (291,076102,36,'eastbound','Choctaw','contributorily','');
+INSERT INTO t2 VALUES (292,076103,36,'inexperienced','cooks','receivers','FAS');
+INSERT INTO t2 VALUES (293,076302,36,'hoarder','millivolt','adjourn','');
+INSERT INTO t2 VALUES (294,076303,36,'scotch','counterpoise','straggled','A');
+INSERT INTO t2 VALUES (295,076304,36,'passport','Gothicism','druggists','');
+INSERT INTO t2 VALUES (296,076305,36,'strategic','feminine','thanking','FAS');
+INSERT INTO t2 VALUES (297,076306,36,'gated','metaphysically','ostrich','');
+INSERT INTO t2 VALUES (298,076307,36,'flog','sanding','hopelessness','FAS');
+INSERT INTO t2 VALUES (299,076402,36,'Pipestone','contributorily','Eurydice','');
+INSERT INTO t2 VALUES (300,076501,36,'Dar','receivers','excitation','W');
+INSERT INTO t2 VALUES (301,076502,36,'Corcoran','adjourn','presumes','FAS');
+INSERT INTO t2 VALUES (302,076701,36,'flyers','straggled','imaginable','FAS');
+INSERT INTO t2 VALUES (303,078001,36,'competitions','druggists','concoct','W');
+INSERT INTO t2 VALUES (304,078002,36,'suppliers','thanking','peering','W');
+INSERT INTO t2 VALUES (305,078003,36,'skips','ostrich','Phelps','FAS');
+INSERT INTO t2 VALUES (306,078004,36,'institutes','hopelessness','ferociousness','FAS');
+INSERT INTO t2 VALUES (307,078005,36,'troop','Eurydice','sentences','');
+INSERT INTO t2 VALUES (308,078006,36,'connective','excitation','unlocks','');
+INSERT INTO t2 VALUES (309,078007,36,'denies','presumes','engrossing','W');
+INSERT INTO t2 VALUES (310,078008,36,'polka','imaginable','Ruth','');
+INSERT INTO t2 VALUES (311,078101,36,'observations','concoct','tying','');
+INSERT INTO t2 VALUES (312,078103,36,'askers','peering','exclaimers','');
+INSERT INTO t2 VALUES (313,078104,36,'homeless','Phelps','synergy','');
+INSERT INTO t2 VALUES (314,078105,36,'Anna','ferociousness','Huey','W');
+INSERT INTO t2 VALUES (315,082101,36,'subdirectories','sentences','merging','');
+INSERT INTO t2 VALUES (316,083401,36,'decaying','unlocks','judges','A');
+INSERT INTO t2 VALUES (317,084001,36,'outwitting','engrossing','Shylock','W');
+INSERT INTO t2 VALUES (318,084002,36,'Harpy','Ruth','Miltonism','');
+INSERT INTO t2 VALUES (319,086001,36,'crazed','tying','hen','W');
+INSERT INTO t2 VALUES (320,086102,36,'suffocate','exclaimers','honeybee','FAS');
+INSERT INTO t2 VALUES (321,086201,36,'provers','synergy','towers','');
+INSERT INTO t2 VALUES (322,088001,36,'technically','Huey','dilutes','W');
+INSERT INTO t2 VALUES (323,088002,36,'Franklinizations','merging','numerals','FAS');
+INSERT INTO t2 VALUES (324,088003,36,'considered','judges','democracy','FAS');
+INSERT INTO t2 VALUES (325,088004,36,'tinnily','Shylock','Ibero-','');
+INSERT INTO t2 VALUES (326,088101,36,'uninterruptedly','Miltonism','invalids','');
+INSERT INTO t2 VALUES (327,088102,36,'whistled','hen','behavior','');
+INSERT INTO t2 VALUES (328,088103,36,'automate','honeybee','accruing','');
+INSERT INTO t2 VALUES (329,088104,36,'gutting','towers','relics','A');
+INSERT INTO t2 VALUES (330,088105,36,'surreptitious','dilutes','rackets','');
+INSERT INTO t2 VALUES (331,088106,36,'Choctaw','numerals','Fischbein','W');
+INSERT INTO t2 VALUES (332,088201,36,'cooks','democracy','phony','W');
+INSERT INTO t2 VALUES (333,088203,36,'millivolt','Ibero-','cross','FAS');
+INSERT INTO t2 VALUES (334,088204,36,'counterpoise','invalids','cleanup','');
+INSERT INTO t2 VALUES (335,088302,37,'Gothicism','behavior','conspirator','');
+INSERT INTO t2 VALUES (336,088303,37,'feminine','accruing','label','FAS');
+INSERT INTO t2 VALUES (337,088305,37,'metaphysically','relics','university','');
+INSERT INTO t2 VALUES (338,088402,37,'sanding','rackets','cleansed','FAS');
+INSERT INTO t2 VALUES (339,088501,36,'contributorily','Fischbein','ballgown','');
+INSERT INTO t2 VALUES (340,088502,36,'receivers','phony','starlet','');
+INSERT INTO t2 VALUES (341,088503,36,'adjourn','cross','aqueous','');
+INSERT INTO t2 VALUES (342,098001,58,'straggled','cleanup','portrayal','A');
+INSERT INTO t2 VALUES (343,098002,58,'druggists','conspirator','despising','W');
+INSERT INTO t2 VALUES (344,098003,58,'thanking','label','distort','W');
+INSERT INTO t2 VALUES (345,098004,58,'ostrich','university','palmed','');
+INSERT INTO t2 VALUES (346,098005,58,'hopelessness','cleansed','faced','');
+INSERT INTO t2 VALUES (347,098006,58,'Eurydice','ballgown','silverware','');
+INSERT INTO t2 VALUES (348,141903,29,'excitation','starlet','assessor','');
+INSERT INTO t2 VALUES (349,098008,58,'presumes','aqueous','spiders','');
+INSERT INTO t2 VALUES (350,098009,58,'imaginable','portrayal','artificially','');
+INSERT INTO t2 VALUES (351,098010,58,'concoct','despising','reminiscence','');
+INSERT INTO t2 VALUES (352,098011,58,'peering','distort','Mexican','');
+INSERT INTO t2 VALUES (353,098012,58,'Phelps','palmed','obnoxious','');
+INSERT INTO t2 VALUES (354,098013,58,'ferociousness','faced','fragile','');
+INSERT INTO t2 VALUES (355,098014,58,'sentences','silverware','apprehensible','');
+INSERT INTO t2 VALUES (356,098015,58,'unlocks','assessor','births','');
+INSERT INTO t2 VALUES (357,098016,58,'engrossing','spiders','garages','');
+INSERT INTO t2 VALUES (358,098017,58,'Ruth','artificially','panty','');
+INSERT INTO t2 VALUES (359,098018,58,'tying','reminiscence','anteater','');
+INSERT INTO t2 VALUES (360,098019,58,'exclaimers','Mexican','displacement','A');
+INSERT INTO t2 VALUES (361,098020,58,'synergy','obnoxious','drovers','A');
+INSERT INTO t2 VALUES (362,098021,58,'Huey','fragile','patenting','A');
+INSERT INTO t2 VALUES (363,098022,58,'merging','apprehensible','far','A');
+INSERT INTO t2 VALUES (364,098023,58,'judges','births','shrieks','');
+INSERT INTO t2 VALUES (365,098024,58,'Shylock','garages','aligning','W');
+INSERT INTO t2 VALUES (366,098025,37,'Miltonism','panty','pragmatism','');
+INSERT INTO t2 VALUES (367,106001,36,'hen','anteater','fevers','W');
+INSERT INTO t2 VALUES (368,108001,36,'honeybee','displacement','reexamines','A');
+INSERT INTO t2 VALUES (369,108002,36,'towers','drovers','occupancies','');
+INSERT INTO t2 VALUES (370,108003,36,'dilutes','patenting','sweats','FAS');
+INSERT INTO t2 VALUES (371,108004,36,'numerals','far','modulators','');
+INSERT INTO t2 VALUES (372,108005,36,'democracy','shrieks','demand','W');
+INSERT INTO t2 VALUES (373,108007,36,'Ibero-','aligning','Madeira','');
+INSERT INTO t2 VALUES (374,108008,36,'invalids','pragmatism','Viennese','W');
+INSERT INTO t2 VALUES (375,108009,36,'behavior','fevers','chillier','W');
+INSERT INTO t2 VALUES (376,108010,36,'accruing','reexamines','wildcats','FAS');
+INSERT INTO t2 VALUES (377,108011,36,'relics','occupancies','gentle','');
+INSERT INTO t2 VALUES (378,108012,36,'rackets','sweats','Angles','W');
+INSERT INTO t2 VALUES (379,108101,36,'Fischbein','modulators','accuracies','');
+INSERT INTO t2 VALUES (380,108102,36,'phony','demand','toggle','');
+INSERT INTO t2 VALUES (381,108103,36,'cross','Madeira','Mendelssohn','W');
+INSERT INTO t2 VALUES (382,108111,50,'cleanup','Viennese','behaviorally','');
+INSERT INTO t2 VALUES (383,108105,36,'conspirator','chillier','Rochford','');
+INSERT INTO t2 VALUES (384,108106,36,'label','wildcats','mirror','W');
+INSERT INTO t2 VALUES (385,108107,36,'university','gentle','Modula','');
+INSERT INTO t2 VALUES (386,108108,50,'cleansed','Angles','clobbering','');
+INSERT INTO t2 VALUES (387,108109,36,'ballgown','accuracies','chronography','');
+INSERT INTO t2 VALUES (388,108110,36,'starlet','toggle','Eskimoizeds','');
+INSERT INTO t2 VALUES (389,108201,36,'aqueous','Mendelssohn','British','W');
+INSERT INTO t2 VALUES (390,108202,36,'portrayal','behaviorally','pitfalls','');
+INSERT INTO t2 VALUES (391,108203,36,'despising','Rochford','verify','W');
+INSERT INTO t2 VALUES (392,108204,36,'distort','mirror','scatter','FAS');
+INSERT INTO t2 VALUES (393,108205,36,'palmed','Modula','Aztecan','');
+INSERT INTO t2 VALUES (394,108301,36,'faced','clobbering','acuity','W');
+INSERT INTO t2 VALUES (395,108302,36,'silverware','chronography','sinking','W');
+INSERT INTO t2 VALUES (396,112101,36,'assessor','Eskimoizeds','beasts','FAS');
+INSERT INTO t2 VALUES (397,112102,36,'spiders','British','Witt','W');
+INSERT INTO t2 VALUES (398,113701,36,'artificially','pitfalls','physicists','FAS');
+INSERT INTO t2 VALUES (399,116001,36,'reminiscence','verify','folksong','A');
+INSERT INTO t2 VALUES (400,116201,36,'Mexican','scatter','strokes','FAS');
+INSERT INTO t2 VALUES (401,116301,36,'obnoxious','Aztecan','crowder','');
+INSERT INTO t2 VALUES (402,116302,36,'fragile','acuity','merry','');
+INSERT INTO t2 VALUES (403,116601,36,'apprehensible','sinking','cadenced','');
+INSERT INTO t2 VALUES (404,116602,36,'births','beasts','alimony','A');
+INSERT INTO t2 VALUES (405,116603,36,'garages','Witt','principled','A');
+INSERT INTO t2 VALUES (406,116701,36,'panty','physicists','golfing','');
+INSERT INTO t2 VALUES (407,116702,36,'anteater','folksong','undiscovered','');
+INSERT INTO t2 VALUES (408,118001,36,'displacement','strokes','irritates','');
+INSERT INTO t2 VALUES (409,118002,36,'drovers','crowder','patriots','A');
+INSERT INTO t2 VALUES (410,118003,36,'patenting','merry','rooms','FAS');
+INSERT INTO t2 VALUES (411,118004,36,'far','cadenced','towering','W');
+INSERT INTO t2 VALUES (412,118005,36,'shrieks','alimony','displease','');
+INSERT INTO t2 VALUES (413,118006,36,'aligning','principled','photosensitive','');
+INSERT INTO t2 VALUES (414,118007,36,'pragmatism','golfing','inking','');
+INSERT INTO t2 VALUES (415,118008,36,'fevers','undiscovered','gainers','');
+INSERT INTO t2 VALUES (416,118101,36,'reexamines','irritates','leaning','A');
+INSERT INTO t2 VALUES (417,118102,36,'occupancies','patriots','hydrant','A');
+INSERT INTO t2 VALUES (418,118103,36,'sweats','rooms','preserve','');
+INSERT INTO t2 VALUES (419,118202,36,'modulators','towering','blinded','A');
+INSERT INTO t2 VALUES (420,118203,36,'demand','displease','interactions','A');
+INSERT INTO t2 VALUES (421,118204,36,'Madeira','photosensitive','Barry','');
+INSERT INTO t2 VALUES (422,118302,36,'Viennese','inking','whiteness','A');
+INSERT INTO t2 VALUES (423,118304,36,'chillier','gainers','pastimes','W');
+INSERT INTO t2 VALUES (424,118305,36,'wildcats','leaning','Edenization','');
+INSERT INTO t2 VALUES (425,118306,36,'gentle','hydrant','Muscat','');
+INSERT INTO t2 VALUES (426,118307,36,'Angles','preserve','assassinated','');
+INSERT INTO t2 VALUES (427,123101,36,'accuracies','blinded','labeled','');
+INSERT INTO t2 VALUES (428,123102,36,'toggle','interactions','glacial','A');
+INSERT INTO t2 VALUES (429,123301,36,'Mendelssohn','Barry','implied','W');
+INSERT INTO t2 VALUES (430,126001,36,'behaviorally','whiteness','bibliographies','W');
+INSERT INTO t2 VALUES (431,126002,36,'Rochford','pastimes','Buchanan','');
+INSERT INTO t2 VALUES (432,126003,36,'mirror','Edenization','forgivably','FAS');
+INSERT INTO t2 VALUES (433,126101,36,'Modula','Muscat','innuendo','A');
+INSERT INTO t2 VALUES (434,126301,36,'clobbering','assassinated','den','FAS');
+INSERT INTO t2 VALUES (435,126302,36,'chronography','labeled','submarines','W');
+INSERT INTO t2 VALUES (436,126402,36,'Eskimoizeds','glacial','mouthful','A');
+INSERT INTO t2 VALUES (437,126601,36,'British','implied','expiring','');
+INSERT INTO t2 VALUES (438,126602,36,'pitfalls','bibliographies','unfulfilled','FAS');
+INSERT INTO t2 VALUES (439,126702,36,'verify','Buchanan','precession','');
+INSERT INTO t2 VALUES (440,128001,36,'scatter','forgivably','nullified','');
+INSERT INTO t2 VALUES (441,128002,36,'Aztecan','innuendo','affects','');
+INSERT INTO t2 VALUES (442,128003,36,'acuity','den','Cynthia','');
+INSERT INTO t2 VALUES (443,128004,36,'sinking','submarines','Chablis','A');
+INSERT INTO t2 VALUES (444,128005,36,'beasts','mouthful','betterments','FAS');
+INSERT INTO t2 VALUES (445,128007,36,'Witt','expiring','advertising','');
+INSERT INTO t2 VALUES (446,128008,36,'physicists','unfulfilled','rubies','A');
+INSERT INTO t2 VALUES (447,128009,36,'folksong','precession','southwest','FAS');
+INSERT INTO t2 VALUES (448,128010,36,'strokes','nullified','superstitious','A');
+INSERT INTO t2 VALUES (449,128011,36,'crowder','affects','tabernacle','W');
+INSERT INTO t2 VALUES (450,128012,36,'merry','Cynthia','silk','A');
+INSERT INTO t2 VALUES (451,128013,36,'cadenced','Chablis','handsomest','A');
+INSERT INTO t2 VALUES (452,128014,36,'alimony','betterments','Persian','A');
+INSERT INTO t2 VALUES (453,128015,36,'principled','advertising','analog','W');
+INSERT INTO t2 VALUES (454,128016,36,'golfing','rubies','complex','W');
+INSERT INTO t2 VALUES (455,128017,36,'undiscovered','southwest','Taoist','');
+INSERT INTO t2 VALUES (456,128018,36,'irritates','superstitious','suspend','');
+INSERT INTO t2 VALUES (457,128019,36,'patriots','tabernacle','relegated','');
+INSERT INTO t2 VALUES (458,128020,36,'rooms','silk','awesome','W');
+INSERT INTO t2 VALUES (459,128021,36,'towering','handsomest','Bruxelles','');
+INSERT INTO t2 VALUES (460,128022,36,'displease','Persian','imprecisely','A');
+INSERT INTO t2 VALUES (461,128023,36,'photosensitive','analog','televise','');
+INSERT INTO t2 VALUES (462,128101,36,'inking','complex','braking','');
+INSERT INTO t2 VALUES (463,128102,36,'gainers','Taoist','true','FAS');
+INSERT INTO t2 VALUES (464,128103,36,'leaning','suspend','disappointing','FAS');
+INSERT INTO t2 VALUES (465,128104,36,'hydrant','relegated','navally','W');
+INSERT INTO t2 VALUES (466,128106,36,'preserve','awesome','circus','');
+INSERT INTO t2 VALUES (467,128107,36,'blinded','Bruxelles','beetles','');
+INSERT INTO t2 VALUES (468,128108,36,'interactions','imprecisely','trumps','');
+INSERT INTO t2 VALUES (469,128202,36,'Barry','televise','fourscore','W');
+INSERT INTO t2 VALUES (470,128203,36,'whiteness','braking','Blackfoots','');
+INSERT INTO t2 VALUES (471,128301,36,'pastimes','true','Grady','');
+INSERT INTO t2 VALUES (472,128302,36,'Edenization','disappointing','quiets','FAS');
+INSERT INTO t2 VALUES (473,128303,36,'Muscat','navally','floundered','FAS');
+INSERT INTO t2 VALUES (474,128304,36,'assassinated','circus','profundity','W');
+INSERT INTO t2 VALUES (475,128305,36,'labeled','beetles','Garrisonian','W');
+INSERT INTO t2 VALUES (476,128307,36,'glacial','trumps','Strauss','');
+INSERT INTO t2 VALUES (477,128401,36,'implied','fourscore','cemented','FAS');
+INSERT INTO t2 VALUES (478,128502,36,'bibliographies','Blackfoots','contrition','A');
+INSERT INTO t2 VALUES (479,128503,36,'Buchanan','Grady','mutations','');
+INSERT INTO t2 VALUES (480,128504,36,'forgivably','quiets','exhibits','W');
+INSERT INTO t2 VALUES (481,128505,36,'innuendo','floundered','tits','');
+INSERT INTO t2 VALUES (482,128601,36,'den','profundity','mate','A');
+INSERT INTO t2 VALUES (483,128603,36,'submarines','Garrisonian','arches','');
+INSERT INTO t2 VALUES (484,128604,36,'mouthful','Strauss','Moll','');
+INSERT INTO t2 VALUES (485,128702,36,'expiring','cemented','ropers','');
+INSERT INTO t2 VALUES (486,128703,36,'unfulfilled','contrition','bombast','');
+INSERT INTO t2 VALUES (487,128704,36,'precession','mutations','difficultly','A');
+INSERT INTO t2 VALUES (488,138001,36,'nullified','exhibits','adsorption','');
+INSERT INTO t2 VALUES (489,138002,36,'affects','tits','definiteness','FAS');
+INSERT INTO t2 VALUES (490,138003,36,'Cynthia','mate','cultivation','A');
+INSERT INTO t2 VALUES (491,138004,36,'Chablis','arches','heals','A');
+INSERT INTO t2 VALUES (492,138005,36,'betterments','Moll','Heusen','W');
+INSERT INTO t2 VALUES (493,138006,36,'advertising','ropers','target','FAS');
+INSERT INTO t2 VALUES (494,138007,36,'rubies','bombast','cited','A');
+INSERT INTO t2 VALUES (495,138008,36,'southwest','difficultly','congresswoman','W');
+INSERT INTO t2 VALUES (496,138009,36,'superstitious','adsorption','Katherine','');
+INSERT INTO t2 VALUES (497,138102,36,'tabernacle','definiteness','titter','A');
+INSERT INTO t2 VALUES (498,138103,36,'silk','cultivation','aspire','A');
+INSERT INTO t2 VALUES (499,138104,36,'handsomest','heals','Mardis','');
+INSERT INTO t2 VALUES (500,138105,36,'Persian','Heusen','Nadia','W');
+INSERT INTO t2 VALUES (501,138201,36,'analog','target','estimating','FAS');
+INSERT INTO t2 VALUES (502,138302,36,'complex','cited','stuck','A');
+INSERT INTO t2 VALUES (503,138303,36,'Taoist','congresswoman','fifteenth','A');
+INSERT INTO t2 VALUES (504,138304,36,'suspend','Katherine','Colombo','');
+INSERT INTO t2 VALUES (505,138401,29,'relegated','titter','survey','A');
+INSERT INTO t2 VALUES (506,140102,29,'awesome','aspire','staffing','');
+INSERT INTO t2 VALUES (507,140103,29,'Bruxelles','Mardis','obtain','');
+INSERT INTO t2 VALUES (508,140104,29,'imprecisely','Nadia','loaded','');
+INSERT INTO t2 VALUES (509,140105,29,'televise','estimating','slaughtered','');
+INSERT INTO t2 VALUES (510,140201,29,'braking','stuck','lights','A');
+INSERT INTO t2 VALUES (511,140701,29,'true','fifteenth','circumference','');
+INSERT INTO t2 VALUES (512,141501,29,'disappointing','Colombo','dull','A');
+INSERT INTO t2 VALUES (513,141502,29,'navally','survey','weekly','A');
+INSERT INTO t2 VALUES (514,141901,29,'circus','staffing','wetness','');
+INSERT INTO t2 VALUES (515,141902,29,'beetles','obtain','visualized','');
+INSERT INTO t2 VALUES (516,142101,29,'trumps','loaded','Tannenbaum','');
+INSERT INTO t2 VALUES (517,142102,29,'fourscore','slaughtered','moribund','');
+INSERT INTO t2 VALUES (518,142103,29,'Blackfoots','lights','demultiplex','');
+INSERT INTO t2 VALUES (519,142701,29,'Grady','circumference','lockings','');
+INSERT INTO t2 VALUES (520,143001,29,'quiets','dull','thugs','FAS');
+INSERT INTO t2 VALUES (521,143501,29,'floundered','weekly','unnerves','');
+INSERT INTO t2 VALUES (522,143502,29,'profundity','wetness','abut','');
+INSERT INTO t2 VALUES (523,148001,29,'Garrisonian','visualized','Chippewa','A');
+INSERT INTO t2 VALUES (524,148002,29,'Strauss','Tannenbaum','stratifications','A');
+INSERT INTO t2 VALUES (525,148003,29,'cemented','moribund','signaled','');
+INSERT INTO t2 VALUES (526,148004,29,'contrition','demultiplex','Italianizes','A');
+INSERT INTO t2 VALUES (527,148005,29,'mutations','lockings','algorithmic','A');
+INSERT INTO t2 VALUES (528,148006,29,'exhibits','thugs','paranoid','FAS');
+INSERT INTO t2 VALUES (529,148007,29,'tits','unnerves','camping','A');
+INSERT INTO t2 VALUES (530,148009,29,'mate','abut','signifying','A');
+INSERT INTO t2 VALUES (531,148010,29,'arches','Chippewa','Patrice','W');
+INSERT INTO t2 VALUES (532,148011,29,'Moll','stratifications','search','A');
+INSERT INTO t2 VALUES (533,148012,29,'ropers','signaled','Angeles','A');
+INSERT INTO t2 VALUES (534,148013,29,'bombast','Italianizes','semblance','');
+INSERT INTO t2 VALUES (535,148023,36,'difficultly','algorithmic','taxed','');
+INSERT INTO t2 VALUES (536,148015,29,'adsorption','paranoid','Beatrice','');
+INSERT INTO t2 VALUES (537,148016,29,'definiteness','camping','retrace','');
+INSERT INTO t2 VALUES (538,148017,29,'cultivation','signifying','lockout','');
+INSERT INTO t2 VALUES (539,148018,29,'heals','Patrice','grammatic','');
+INSERT INTO t2 VALUES (540,148019,29,'Heusen','search','helmsman','');
+INSERT INTO t2 VALUES (541,148020,29,'target','Angeles','uniform','W');
+INSERT INTO t2 VALUES (542,148021,29,'cited','semblance','hamming','');
+INSERT INTO t2 VALUES (543,148022,29,'congresswoman','taxed','disobedience','');
+INSERT INTO t2 VALUES (544,148101,29,'Katherine','Beatrice','captivated','A');
+INSERT INTO t2 VALUES (545,148102,29,'titter','retrace','transferals','A');
+INSERT INTO t2 VALUES (546,148201,29,'aspire','lockout','cartographer','A');
+INSERT INTO t2 VALUES (547,148401,29,'Mardis','grammatic','aims','FAS');
+INSERT INTO t2 VALUES (548,148402,29,'Nadia','helmsman','Pakistani','');
+INSERT INTO t2 VALUES (549,148501,29,'estimating','uniform','burglarized','FAS');
+INSERT INTO t2 VALUES (550,148502,29,'stuck','hamming','saucepans','A');
+INSERT INTO t2 VALUES (551,148503,29,'fifteenth','disobedience','lacerating','A');
+INSERT INTO t2 VALUES (552,148504,29,'Colombo','captivated','corny','');
+INSERT INTO t2 VALUES (553,148601,29,'survey','transferals','megabytes','FAS');
+INSERT INTO t2 VALUES (554,148602,29,'staffing','cartographer','chancellor','');
+INSERT INTO t2 VALUES (555,150701,29,'obtain','aims','bulk','A');
+INSERT INTO t2 VALUES (556,152101,29,'loaded','Pakistani','commits','A');
+INSERT INTO t2 VALUES (557,152102,29,'slaughtered','burglarized','meson','W');
+INSERT INTO t2 VALUES (558,155202,36,'lights','saucepans','deputies','');
+INSERT INTO t2 VALUES (559,155203,29,'circumference','lacerating','northeaster','A');
+INSERT INTO t2 VALUES (560,155204,29,'dull','corny','dipole','');
+INSERT INTO t2 VALUES (561,155205,29,'weekly','megabytes','machining','0');
+INSERT INTO t2 VALUES (562,156001,29,'wetness','chancellor','therefore','');
+INSERT INTO t2 VALUES (563,156002,29,'visualized','bulk','Telefunken','');
+INSERT INTO t2 VALUES (564,156102,29,'Tannenbaum','commits','salvaging','');
+INSERT INTO t2 VALUES (565,156301,29,'moribund','meson','Corinthianizes','A');
+INSERT INTO t2 VALUES (566,156302,29,'demultiplex','deputies','restlessly','A');
+INSERT INTO t2 VALUES (567,156303,29,'lockings','northeaster','bromides','');
+INSERT INTO t2 VALUES (568,156304,29,'thugs','dipole','generalized','A');
+INSERT INTO t2 VALUES (569,156305,29,'unnerves','machining','mishaps','');
+INSERT INTO t2 VALUES (570,156306,29,'abut','therefore','quelling','');
+INSERT INTO t2 VALUES (571,156501,29,'Chippewa','Telefunken','spiritual','A');
+INSERT INTO t2 VALUES (572,158001,29,'stratifications','salvaging','beguiles','FAS');
+INSERT INTO t2 VALUES (573,158002,29,'signaled','Corinthianizes','Trobriand','FAS');
+INSERT INTO t2 VALUES (574,158101,29,'Italianizes','restlessly','fleeing','A');
+INSERT INTO t2 VALUES (575,158102,29,'algorithmic','bromides','Armour','A');
+INSERT INTO t2 VALUES (576,158103,29,'paranoid','generalized','chin','A');
+INSERT INTO t2 VALUES (577,158201,29,'camping','mishaps','provers','A');
+INSERT INTO t2 VALUES (578,158202,29,'signifying','quelling','aeronautic','A');
+INSERT INTO t2 VALUES (579,158203,29,'Patrice','spiritual','voltage','W');
+INSERT INTO t2 VALUES (580,158204,29,'search','beguiles','sash','');
+INSERT INTO t2 VALUES (581,158301,29,'Angeles','Trobriand','anaerobic','A');
+INSERT INTO t2 VALUES (582,158302,29,'semblance','fleeing','simultaneous','A');
+INSERT INTO t2 VALUES (583,158303,29,'taxed','Armour','accumulating','A');
+INSERT INTO t2 VALUES (584,158304,29,'Beatrice','chin','Medusan','A');
+INSERT INTO t2 VALUES (585,158305,29,'retrace','provers','shouted','A');
+INSERT INTO t2 VALUES (586,158306,29,'lockout','aeronautic','freakish','');
+INSERT INTO t2 VALUES (587,158501,29,'grammatic','voltage','index','FAS');
+INSERT INTO t2 VALUES (588,160301,29,'helmsman','sash','commercially','');
+INSERT INTO t2 VALUES (589,166101,50,'uniform','anaerobic','mistiness','A');
+INSERT INTO t2 VALUES (590,166102,50,'hamming','simultaneous','endpoint','');
+INSERT INTO t2 VALUES (591,168001,29,'disobedience','accumulating','straight','A');
+INSERT INTO t2 VALUES (592,168002,29,'captivated','Medusan','flurried','');
+INSERT INTO t2 VALUES (593,168003,29,'transferals','shouted','denotative','A');
+INSERT INTO t2 VALUES (594,168101,29,'cartographer','freakish','coming','FAS');
+INSERT INTO t2 VALUES (595,168102,29,'aims','index','commencements','FAS');
+INSERT INTO t2 VALUES (596,168103,29,'Pakistani','commercially','gentleman','');
+INSERT INTO t2 VALUES (597,168104,29,'burglarized','mistiness','gifted','');
+INSERT INTO t2 VALUES (598,168202,29,'saucepans','endpoint','Shanghais','');
+INSERT INTO t2 VALUES (599,168301,29,'lacerating','straight','sportswriting','A');
+INSERT INTO t2 VALUES (600,168502,29,'corny','flurried','sloping','A');
+INSERT INTO t2 VALUES (601,168503,29,'megabytes','denotative','navies','');
+INSERT INTO t2 VALUES (602,168601,29,'chancellor','coming','leaflet','A');
+INSERT INTO t2 VALUES (603,173001,40,'bulk','commencements','shooter','');
+INSERT INTO t2 VALUES (604,173701,40,'commits','gentleman','Joplin','FAS');
+INSERT INTO t2 VALUES (605,173702,40,'meson','gifted','babies','');
+INSERT INTO t2 VALUES (606,176001,40,'deputies','Shanghais','subdivision','FAS');
+INSERT INTO t2 VALUES (607,176101,40,'northeaster','sportswriting','burstiness','W');
+INSERT INTO t2 VALUES (608,176201,40,'dipole','sloping','belted','FAS');
+INSERT INTO t2 VALUES (609,176401,40,'machining','navies','assails','FAS');
+INSERT INTO t2 VALUES (610,176501,40,'therefore','leaflet','admiring','W');
+INSERT INTO t2 VALUES (611,176601,40,'Telefunken','shooter','swaying','0');
+INSERT INTO t2 VALUES (612,176602,40,'salvaging','Joplin','Goldstine','FAS');
+INSERT INTO t2 VALUES (613,176603,40,'Corinthianizes','babies','fitting','');
+INSERT INTO t2 VALUES (614,178001,40,'restlessly','subdivision','Norwalk','W');
+INSERT INTO t2 VALUES (615,178002,40,'bromides','burstiness','weakening','W');
+INSERT INTO t2 VALUES (616,178003,40,'generalized','belted','analogy','FAS');
+INSERT INTO t2 VALUES (617,178004,40,'mishaps','assails','deludes','');
+INSERT INTO t2 VALUES (618,178005,40,'quelling','admiring','cokes','');
+INSERT INTO t2 VALUES (619,178006,40,'spiritual','swaying','Clayton','');
+INSERT INTO t2 VALUES (620,178007,40,'beguiles','Goldstine','exhausts','');
+INSERT INTO t2 VALUES (621,178008,40,'Trobriand','fitting','causality','');
+INSERT INTO t2 VALUES (622,178101,40,'fleeing','Norwalk','sating','FAS');
+INSERT INTO t2 VALUES (623,178102,40,'Armour','weakening','icon','');
+INSERT INTO t2 VALUES (624,178103,40,'chin','analogy','throttles','');
+INSERT INTO t2 VALUES (625,178201,40,'provers','deludes','communicants','FAS');
+INSERT INTO t2 VALUES (626,178202,40,'aeronautic','cokes','dehydrate','FAS');
+INSERT INTO t2 VALUES (627,178301,40,'voltage','Clayton','priceless','FAS');
+INSERT INTO t2 VALUES (628,178302,40,'sash','exhausts','publicly','');
+INSERT INTO t2 VALUES (629,178401,40,'anaerobic','causality','incidentals','FAS');
+INSERT INTO t2 VALUES (630,178402,40,'simultaneous','sating','commonplace','');
+INSERT INTO t2 VALUES (631,178403,40,'accumulating','icon','mumbles','');
+INSERT INTO t2 VALUES (632,178404,40,'Medusan','throttles','furthermore','W');
+INSERT INTO t2 VALUES (633,178501,40,'shouted','communicants','cautioned','W');
+INSERT INTO t2 VALUES (634,186002,37,'freakish','dehydrate','parametrized','A');
+INSERT INTO t2 VALUES (635,186102,37,'index','priceless','registration','A');
+INSERT INTO t2 VALUES (636,186201,40,'commercially','publicly','sadly','FAS');
+INSERT INTO t2 VALUES (637,186202,40,'mistiness','incidentals','positioning','');
+INSERT INTO t2 VALUES (638,186203,40,'endpoint','commonplace','babysitting','');
+INSERT INTO t2 VALUES (639,186302,37,'straight','mumbles','eternal','A');
+INSERT INTO t2 VALUES (640,188007,37,'flurried','furthermore','hoarder','');
+INSERT INTO t2 VALUES (641,188008,37,'denotative','cautioned','congregates','');
+INSERT INTO t2 VALUES (642,188009,37,'coming','parametrized','rains','');
+INSERT INTO t2 VALUES (643,188010,37,'commencements','registration','workers','W');
+INSERT INTO t2 VALUES (644,188011,37,'gentleman','sadly','sags','A');
+INSERT INTO t2 VALUES (645,188012,37,'gifted','positioning','unplug','W');
+INSERT INTO t2 VALUES (646,188013,37,'Shanghais','babysitting','garage','A');
+INSERT INTO t2 VALUES (647,188014,37,'sportswriting','eternal','boulder','A');
+INSERT INTO t2 VALUES (648,188015,37,'sloping','hoarder','hollowly','A');
+INSERT INTO t2 VALUES (649,188016,37,'navies','congregates','specifics','');
+INSERT INTO t2 VALUES (650,188017,37,'leaflet','rains','Teresa','');
+INSERT INTO t2 VALUES (651,188102,37,'shooter','workers','Winsett','');
+INSERT INTO t2 VALUES (652,188103,37,'Joplin','sags','convenient','A');
+INSERT INTO t2 VALUES (653,188202,37,'babies','unplug','buckboards','FAS');
+INSERT INTO t2 VALUES (654,188301,40,'subdivision','garage','amenities','');
+INSERT INTO t2 VALUES (655,188302,40,'burstiness','boulder','resplendent','FAS');
+INSERT INTO t2 VALUES (656,188303,40,'belted','hollowly','priding','FAS');
+INSERT INTO t2 VALUES (657,188401,37,'assails','specifics','configurations','');
+INSERT INTO t2 VALUES (658,188402,37,'admiring','Teresa','untidiness','A');
+INSERT INTO t2 VALUES (659,188503,37,'swaying','Winsett','Brice','W');
+INSERT INTO t2 VALUES (660,188504,37,'Goldstine','convenient','sews','FAS');
+INSERT INTO t2 VALUES (661,188505,37,'fitting','buckboards','participated','');
+INSERT INTO t2 VALUES (662,190701,37,'Norwalk','amenities','Simon','FAS');
+INSERT INTO t2 VALUES (663,190703,50,'weakening','resplendent','certificates','');
+INSERT INTO t2 VALUES (664,191701,37,'analogy','priding','Fitzpatrick','');
+INSERT INTO t2 VALUES (665,191702,37,'deludes','configurations','Evanston','A');
+INSERT INTO t2 VALUES (666,191703,37,'cokes','untidiness','misted','');
+INSERT INTO t2 VALUES (667,196001,37,'Clayton','Brice','textures','A');
+INSERT INTO t2 VALUES (668,196002,37,'exhausts','sews','save','');
+INSERT INTO t2 VALUES (669,196003,37,'causality','participated','count','');
+INSERT INTO t2 VALUES (670,196101,37,'sating','Simon','rightful','A');
+INSERT INTO t2 VALUES (671,196103,37,'icon','certificates','chaperone','');
+INSERT INTO t2 VALUES (672,196104,37,'throttles','Fitzpatrick','Lizzy','A');
+INSERT INTO t2 VALUES (673,196201,37,'communicants','Evanston','clenched','A');
+INSERT INTO t2 VALUES (674,196202,37,'dehydrate','misted','effortlessly','');
+INSERT INTO t2 VALUES (675,196203,37,'priceless','textures','accessed','');
+INSERT INTO t2 VALUES (676,198001,37,'publicly','save','beaters','A');
+INSERT INTO t2 VALUES (677,198003,37,'incidentals','count','Hornblower','FAS');
+INSERT INTO t2 VALUES (678,198004,37,'commonplace','rightful','vests','A');
+INSERT INTO t2 VALUES (679,198005,37,'mumbles','chaperone','indulgences','FAS');
+INSERT INTO t2 VALUES (680,198006,37,'furthermore','Lizzy','infallibly','A');
+INSERT INTO t2 VALUES (681,198007,37,'cautioned','clenched','unwilling','FAS');
+INSERT INTO t2 VALUES (682,198008,37,'parametrized','effortlessly','excrete','FAS');
+INSERT INTO t2 VALUES (683,198009,37,'registration','accessed','spools','A');
+INSERT INTO t2 VALUES (684,198010,37,'sadly','beaters','crunches','FAS');
+INSERT INTO t2 VALUES (685,198011,37,'positioning','Hornblower','overestimating','FAS');
+INSERT INTO t2 VALUES (686,198012,37,'babysitting','vests','ineffective','');
+INSERT INTO t2 VALUES (687,198013,37,'eternal','indulgences','humiliation','A');
+INSERT INTO t2 VALUES (688,198014,37,'hoarder','infallibly','sophomore','');
+INSERT INTO t2 VALUES (689,198015,37,'congregates','unwilling','star','');
+INSERT INTO t2 VALUES (690,198017,37,'rains','excrete','rifles','');
+INSERT INTO t2 VALUES (691,198018,37,'workers','spools','dialysis','');
+INSERT INTO t2 VALUES (692,198019,37,'sags','crunches','arriving','');
+INSERT INTO t2 VALUES (693,198020,37,'unplug','overestimating','indulge','');
+INSERT INTO t2 VALUES (694,198021,37,'garage','ineffective','clockers','');
+INSERT INTO t2 VALUES (695,198022,37,'boulder','humiliation','languages','');
+INSERT INTO t2 VALUES (696,198023,50,'hollowly','sophomore','Antarctica','A');
+INSERT INTO t2 VALUES (697,198024,37,'specifics','star','percentage','');
+INSERT INTO t2 VALUES (698,198101,37,'Teresa','rifles','ceiling','A');
+INSERT INTO t2 VALUES (699,198103,37,'Winsett','dialysis','specification','');
+INSERT INTO t2 VALUES (700,198105,37,'convenient','arriving','regimented','A');
+INSERT INTO t2 VALUES (701,198106,37,'buckboards','indulge','ciphers','');
+INSERT INTO t2 VALUES (702,198201,37,'amenities','clockers','pictures','A');
+INSERT INTO t2 VALUES (703,198204,37,'resplendent','languages','serpents','A');
+INSERT INTO t2 VALUES (704,198301,53,'priding','Antarctica','allot','A');
+INSERT INTO t2 VALUES (705,198302,53,'configurations','percentage','realized','A');
+INSERT INTO t2 VALUES (706,198303,53,'untidiness','ceiling','mayoral','A');
+INSERT INTO t2 VALUES (707,198304,53,'Brice','specification','opaquely','A');
+INSERT INTO t2 VALUES (708,198401,37,'sews','regimented','hostess','FAS');
+INSERT INTO t2 VALUES (709,198402,37,'participated','ciphers','fiftieth','');
+INSERT INTO t2 VALUES (710,198403,37,'Simon','pictures','incorrectly','');
+INSERT INTO t2 VALUES (711,202101,37,'certificates','serpents','decomposition','FAS');
+INSERT INTO t2 VALUES (712,202301,37,'Fitzpatrick','allot','stranglings','');
+INSERT INTO t2 VALUES (713,202302,37,'Evanston','realized','mixture','FAS');
+INSERT INTO t2 VALUES (714,202303,37,'misted','mayoral','electroencephalography','FAS');
+INSERT INTO t2 VALUES (715,202304,37,'textures','opaquely','similarities','FAS');
+INSERT INTO t2 VALUES (716,202305,37,'save','hostess','charges','W');
+INSERT INTO t2 VALUES (717,202601,37,'count','fiftieth','freest','FAS');
+INSERT INTO t2 VALUES (718,202602,37,'rightful','incorrectly','Greenberg','FAS');
+INSERT INTO t2 VALUES (719,202605,37,'chaperone','decomposition','tinting','');
+INSERT INTO t2 VALUES (720,202606,37,'Lizzy','stranglings','expelled','W');
+INSERT INTO t2 VALUES (721,202607,37,'clenched','mixture','warm','');
+INSERT INTO t2 VALUES (722,202901,37,'effortlessly','electroencephalography','smoothed','');
+INSERT INTO t2 VALUES (723,202902,37,'accessed','similarities','deductions','FAS');
+INSERT INTO t2 VALUES (724,202903,37,'beaters','charges','Romano','W');
+INSERT INTO t2 VALUES (725,202904,37,'Hornblower','freest','bitterroot','');
+INSERT INTO t2 VALUES (726,202907,37,'vests','Greenberg','corset','');
+INSERT INTO t2 VALUES (727,202908,37,'indulgences','tinting','securing','');
+INSERT INTO t2 VALUES (728,203101,37,'infallibly','expelled','environing','FAS');
+INSERT INTO t2 VALUES (729,203103,37,'unwilling','warm','cute','');
+INSERT INTO t2 VALUES (730,203104,37,'excrete','smoothed','Crays','');
+INSERT INTO t2 VALUES (731,203105,37,'spools','deductions','heiress','FAS');
+INSERT INTO t2 VALUES (732,203401,37,'crunches','Romano','inform','FAS');
+INSERT INTO t2 VALUES (733,203402,37,'overestimating','bitterroot','avenge','');
+INSERT INTO t2 VALUES (734,203404,37,'ineffective','corset','universals','');
+INSERT INTO t2 VALUES (735,203901,37,'humiliation','securing','Kinsey','W');
+INSERT INTO t2 VALUES (736,203902,37,'sophomore','environing','ravines','FAS');
+INSERT INTO t2 VALUES (737,203903,37,'star','cute','bestseller','');
+INSERT INTO t2 VALUES (738,203906,37,'rifles','Crays','equilibrium','');
+INSERT INTO t2 VALUES (739,203907,37,'dialysis','heiress','extents','0');
+INSERT INTO t2 VALUES (740,203908,37,'arriving','inform','relatively','');
+INSERT INTO t2 VALUES (741,203909,37,'indulge','avenge','pressure','FAS');
+INSERT INTO t2 VALUES (742,206101,37,'clockers','universals','critiques','FAS');
+INSERT INTO t2 VALUES (743,206201,37,'languages','Kinsey','befouled','');
+INSERT INTO t2 VALUES (744,206202,37,'Antarctica','ravines','rightfully','FAS');
+INSERT INTO t2 VALUES (745,206203,37,'percentage','bestseller','mechanizing','FAS');
+INSERT INTO t2 VALUES (746,206206,37,'ceiling','equilibrium','Latinizes','');
+INSERT INTO t2 VALUES (747,206207,37,'specification','extents','timesharing','');
+INSERT INTO t2 VALUES (748,206208,37,'regimented','relatively','Aden','');
+INSERT INTO t2 VALUES (749,208001,37,'ciphers','pressure','embassies','');
+INSERT INTO t2 VALUES (750,208002,37,'pictures','critiques','males','FAS');
+INSERT INTO t2 VALUES (751,208003,37,'serpents','befouled','shapelessly','FAS');
+INSERT INTO t2 VALUES (752,208004,37,'allot','rightfully','genres','FAS');
+INSERT INTO t2 VALUES (753,208008,37,'realized','mechanizing','mastering','');
+INSERT INTO t2 VALUES (754,208009,37,'mayoral','Latinizes','Newtonian','');
+INSERT INTO t2 VALUES (755,208010,37,'opaquely','timesharing','finishers','FAS');
+INSERT INTO t2 VALUES (756,208011,37,'hostess','Aden','abates','');
+INSERT INTO t2 VALUES (757,208101,37,'fiftieth','embassies','teem','');
+INSERT INTO t2 VALUES (758,208102,37,'incorrectly','males','kiting','FAS');
+INSERT INTO t2 VALUES (759,208103,37,'decomposition','shapelessly','stodgy','FAS');
+INSERT INTO t2 VALUES (760,208104,37,'stranglings','genres','scalps','FAS');
+INSERT INTO t2 VALUES (761,208105,37,'mixture','mastering','feed','FAS');
+INSERT INTO t2 VALUES (762,208110,37,'electroencephalography','Newtonian','guitars','');
+INSERT INTO t2 VALUES (763,208111,37,'similarities','finishers','airships','');
+INSERT INTO t2 VALUES (764,208112,37,'charges','abates','store','');
+INSERT INTO t2 VALUES (765,208113,37,'freest','teem','denounces','');
+INSERT INTO t2 VALUES (766,208201,37,'Greenberg','kiting','Pyle','FAS');
+INSERT INTO t2 VALUES (767,208203,37,'tinting','stodgy','Saxony','');
+INSERT INTO t2 VALUES (768,208301,37,'expelled','scalps','serializations','FAS');
+INSERT INTO t2 VALUES (769,208302,37,'warm','feed','Peruvian','FAS');
+INSERT INTO t2 VALUES (770,208305,37,'smoothed','guitars','taxonomically','FAS');
+INSERT INTO t2 VALUES (771,208401,37,'deductions','airships','kingdom','A');
+INSERT INTO t2 VALUES (772,208402,37,'Romano','store','stint','A');
+INSERT INTO t2 VALUES (773,208403,37,'bitterroot','denounces','Sault','A');
+INSERT INTO t2 VALUES (774,208404,37,'corset','Pyle','faithful','');
+INSERT INTO t2 VALUES (775,208501,37,'securing','Saxony','Ganymede','FAS');
+INSERT INTO t2 VALUES (776,208502,37,'environing','serializations','tidiness','FAS');
+INSERT INTO t2 VALUES (777,208503,37,'cute','Peruvian','gainful','FAS');
+INSERT INTO t2 VALUES (778,208504,37,'Crays','taxonomically','contrary','FAS');
+INSERT INTO t2 VALUES (779,208505,37,'heiress','kingdom','Tipperary','FAS');
+INSERT INTO t2 VALUES (780,210101,37,'inform','stint','tropics','W');
+INSERT INTO t2 VALUES (781,210102,37,'avenge','Sault','theorizers','');
+INSERT INTO t2 VALUES (782,210103,37,'universals','faithful','renew','0');
+INSERT INTO t2 VALUES (783,210104,37,'Kinsey','Ganymede','already','');
+INSERT INTO t2 VALUES (784,210105,37,'ravines','tidiness','terminal','');
+INSERT INTO t2 VALUES (785,210106,37,'bestseller','gainful','Hegelian','');
+INSERT INTO t2 VALUES (786,210107,37,'equilibrium','contrary','hypothesizer','');
+INSERT INTO t2 VALUES (787,210401,37,'extents','Tipperary','warningly','FAS');
+INSERT INTO t2 VALUES (788,213201,37,'relatively','tropics','journalizing','FAS');
+INSERT INTO t2 VALUES (789,213203,37,'pressure','theorizers','nested','');
+INSERT INTO t2 VALUES (790,213204,37,'critiques','renew','Lars','');
+INSERT INTO t2 VALUES (791,213205,37,'befouled','already','saplings','');
+INSERT INTO t2 VALUES (792,213206,37,'rightfully','terminal','foothill','');
+INSERT INTO t2 VALUES (793,213207,37,'mechanizing','Hegelian','labeled','');
+INSERT INTO t2 VALUES (794,216101,37,'Latinizes','hypothesizer','imperiously','FAS');
+INSERT INTO t2 VALUES (795,216103,37,'timesharing','warningly','reporters','FAS');
+INSERT INTO t2 VALUES (796,218001,37,'Aden','journalizing','furnishings','FAS');
+INSERT INTO t2 VALUES (797,218002,37,'embassies','nested','precipitable','FAS');
+INSERT INTO t2 VALUES (798,218003,37,'males','Lars','discounts','FAS');
+INSERT INTO t2 VALUES (799,218004,37,'shapelessly','saplings','excises','FAS');
+INSERT INTO t2 VALUES (800,143503,50,'genres','foothill','Stalin','');
+INSERT INTO t2 VALUES (801,218006,37,'mastering','labeled','despot','FAS');
+INSERT INTO t2 VALUES (802,218007,37,'Newtonian','imperiously','ripeness','FAS');
+INSERT INTO t2 VALUES (803,218008,37,'finishers','reporters','Arabia','');
+INSERT INTO t2 VALUES (804,218009,37,'abates','furnishings','unruly','');
+INSERT INTO t2 VALUES (805,218010,37,'teem','precipitable','mournfulness','');
+INSERT INTO t2 VALUES (806,218011,37,'kiting','discounts','boom','FAS');
+INSERT INTO t2 VALUES (807,218020,37,'stodgy','excises','slaughter','A');
+INSERT INTO t2 VALUES (808,218021,50,'scalps','Stalin','Sabine','');
+INSERT INTO t2 VALUES (809,218022,37,'feed','despot','handy','FAS');
+INSERT INTO t2 VALUES (810,218023,37,'guitars','ripeness','rural','');
+INSERT INTO t2 VALUES (811,218024,37,'airships','Arabia','organizer','');
+INSERT INTO t2 VALUES (812,218101,37,'store','unruly','shipyard','FAS');
+INSERT INTO t2 VALUES (813,218102,37,'denounces','mournfulness','civics','FAS');
+INSERT INTO t2 VALUES (814,218103,37,'Pyle','boom','inaccuracy','FAS');
+INSERT INTO t2 VALUES (815,218201,37,'Saxony','slaughter','rules','FAS');
+INSERT INTO t2 VALUES (816,218202,37,'serializations','Sabine','juveniles','FAS');
+INSERT INTO t2 VALUES (817,218203,37,'Peruvian','handy','comprised','W');
+INSERT INTO t2 VALUES (818,218204,37,'taxonomically','rural','investigations','');
+INSERT INTO t2 VALUES (819,218205,37,'kingdom','organizer','stabilizes','A');
+INSERT INTO t2 VALUES (820,218301,37,'stint','shipyard','seminaries','FAS');
+INSERT INTO t2 VALUES (821,218302,37,'Sault','civics','Hunter','A');
+INSERT INTO t2 VALUES (822,218401,37,'faithful','inaccuracy','sporty','FAS');
+INSERT INTO t2 VALUES (823,218402,37,'Ganymede','rules','test','FAS');
+INSERT INTO t2 VALUES (824,218403,37,'tidiness','juveniles','weasels','');
+INSERT INTO t2 VALUES (825,218404,37,'gainful','comprised','CERN','');
+INSERT INTO t2 VALUES (826,218407,37,'contrary','investigations','tempering','');
+INSERT INTO t2 VALUES (827,218408,37,'Tipperary','stabilizes','afore','FAS');
+INSERT INTO t2 VALUES (828,218409,37,'tropics','seminaries','Galatean','');
+INSERT INTO t2 VALUES (829,218410,37,'theorizers','Hunter','techniques','W');
+INSERT INTO t2 VALUES (830,226001,37,'renew','sporty','error','');
+INSERT INTO t2 VALUES (831,226002,37,'already','test','veranda','');
+INSERT INTO t2 VALUES (832,226003,37,'terminal','weasels','severely','');
+INSERT INTO t2 VALUES (833,226004,37,'Hegelian','CERN','Cassites','FAS');
+INSERT INTO t2 VALUES (834,226005,37,'hypothesizer','tempering','forthcoming','');
+INSERT INTO t2 VALUES (835,226006,37,'warningly','afore','guides','');
+INSERT INTO t2 VALUES (836,226007,37,'journalizing','Galatean','vanish','FAS');
+INSERT INTO t2 VALUES (837,226008,37,'nested','techniques','lied','A');
+INSERT INTO t2 VALUES (838,226203,37,'Lars','error','sawtooth','FAS');
+INSERT INTO t2 VALUES (839,226204,37,'saplings','veranda','fated','FAS');
+INSERT INTO t2 VALUES (840,226205,37,'foothill','severely','gradually','');
+INSERT INTO t2 VALUES (841,226206,37,'labeled','Cassites','widens','');
+INSERT INTO t2 VALUES (842,226207,37,'imperiously','forthcoming','preclude','');
+INSERT INTO t2 VALUES (843,226208,37,'reporters','guides','Jobrel','');
+INSERT INTO t2 VALUES (844,226209,37,'furnishings','vanish','hooker','');
+INSERT INTO t2 VALUES (845,226210,37,'precipitable','lied','rainstorm','');
+INSERT INTO t2 VALUES (846,226211,37,'discounts','sawtooth','disconnects','');
+INSERT INTO t2 VALUES (847,228001,37,'excises','fated','cruelty','');
+INSERT INTO t2 VALUES (848,228004,37,'Stalin','gradually','exponentials','A');
+INSERT INTO t2 VALUES (849,228005,37,'despot','widens','affective','A');
+INSERT INTO t2 VALUES (850,228006,37,'ripeness','preclude','arteries','');
+INSERT INTO t2 VALUES (851,228007,37,'Arabia','Jobrel','Crosby','FAS');
+INSERT INTO t2 VALUES (852,228008,37,'unruly','hooker','acquaint','');
+INSERT INTO t2 VALUES (853,228009,37,'mournfulness','rainstorm','evenhandedly','');
+INSERT INTO t2 VALUES (854,228101,37,'boom','disconnects','percentage','');
+INSERT INTO t2 VALUES (855,228108,37,'slaughter','cruelty','disobedience','');
+INSERT INTO t2 VALUES (856,228109,37,'Sabine','exponentials','humility','');
+INSERT INTO t2 VALUES (857,228110,37,'handy','affective','gleaning','A');
+INSERT INTO t2 VALUES (858,228111,37,'rural','arteries','petted','A');
+INSERT INTO t2 VALUES (859,228112,37,'organizer','Crosby','bloater','A');
+INSERT INTO t2 VALUES (860,228113,37,'shipyard','acquaint','minion','A');
+INSERT INTO t2 VALUES (861,228114,37,'civics','evenhandedly','marginal','A');
+INSERT INTO t2 VALUES (862,228115,37,'inaccuracy','percentage','apiary','A');
+INSERT INTO t2 VALUES (863,228116,37,'rules','disobedience','measures','');
+INSERT INTO t2 VALUES (864,228117,37,'juveniles','humility','precaution','');
+INSERT INTO t2 VALUES (865,228118,37,'comprised','gleaning','repelled','');
+INSERT INTO t2 VALUES (866,228119,37,'investigations','petted','primary','FAS');
+INSERT INTO t2 VALUES (867,228120,37,'stabilizes','bloater','coverings','');
+INSERT INTO t2 VALUES (868,228121,37,'seminaries','minion','Artemia','A');
+INSERT INTO t2 VALUES (869,228122,37,'Hunter','marginal','navigate','');
+INSERT INTO t2 VALUES (870,228201,37,'sporty','apiary','spatial','');
+INSERT INTO t2 VALUES (871,228206,37,'test','measures','Gurkha','');
+INSERT INTO t2 VALUES (872,228207,37,'weasels','precaution','meanwhile','A');
+INSERT INTO t2 VALUES (873,228208,37,'CERN','repelled','Melinda','A');
+INSERT INTO t2 VALUES (874,228209,37,'tempering','primary','Butterfield','');
+INSERT INTO t2 VALUES (875,228210,37,'afore','coverings','Aldrich','A');
+INSERT INTO t2 VALUES (876,228211,37,'Galatean','Artemia','previewing','A');
+INSERT INTO t2 VALUES (877,228212,37,'techniques','navigate','glut','A');
+INSERT INTO t2 VALUES (878,228213,37,'error','spatial','unaffected','');
+INSERT INTO t2 VALUES (879,228214,37,'veranda','Gurkha','inmate','');
+INSERT INTO t2 VALUES (880,228301,37,'severely','meanwhile','mineral','');
+INSERT INTO t2 VALUES (881,228305,37,'Cassites','Melinda','impending','A');
+INSERT INTO t2 VALUES (882,228306,37,'forthcoming','Butterfield','meditation','A');
+INSERT INTO t2 VALUES (883,228307,37,'guides','Aldrich','ideas','');
+INSERT INTO t2 VALUES (884,228308,37,'vanish','previewing','miniaturizes','W');
+INSERT INTO t2 VALUES (885,228309,37,'lied','glut','lewdly','');
+INSERT INTO t2 VALUES (886,228310,37,'sawtooth','unaffected','title','');
+INSERT INTO t2 VALUES (887,228311,37,'fated','inmate','youthfulness','');
+INSERT INTO t2 VALUES (888,228312,37,'gradually','mineral','creak','FAS');
+INSERT INTO t2 VALUES (889,228313,37,'widens','impending','Chippewa','');
+INSERT INTO t2 VALUES (890,228314,37,'preclude','meditation','clamored','');
+INSERT INTO t2 VALUES (891,228401,65,'Jobrel','ideas','freezes','');
+INSERT INTO t2 VALUES (892,228402,65,'hooker','miniaturizes','forgivably','FAS');
+INSERT INTO t2 VALUES (893,228403,65,'rainstorm','lewdly','reduce','FAS');
+INSERT INTO t2 VALUES (894,228404,65,'disconnects','title','McGovern','W');
+INSERT INTO t2 VALUES (895,228405,65,'cruelty','youthfulness','Nazis','W');
+INSERT INTO t2 VALUES (896,228406,65,'exponentials','creak','epistle','W');
+INSERT INTO t2 VALUES (897,228407,65,'affective','Chippewa','socializes','W');
+INSERT INTO t2 VALUES (898,228408,65,'arteries','clamored','conceptions','');
+INSERT INTO t2 VALUES (899,228409,65,'Crosby','freezes','Kevin','');
+INSERT INTO t2 VALUES (900,228410,65,'acquaint','forgivably','uncovering','');
+INSERT INTO t2 VALUES (901,230301,37,'evenhandedly','reduce','chews','FAS');
+INSERT INTO t2 VALUES (902,230302,37,'percentage','McGovern','appendixes','FAS');
+INSERT INTO t2 VALUES (903,230303,37,'disobedience','Nazis','raining','');
+INSERT INTO t2 VALUES (904,018062,37,'humility','epistle','infest','');
+INSERT INTO t2 VALUES (905,230501,37,'gleaning','socializes','compartment','');
+INSERT INTO t2 VALUES (906,230502,37,'petted','conceptions','minting','');
+INSERT INTO t2 VALUES (907,230503,37,'bloater','Kevin','ducks','');
+INSERT INTO t2 VALUES (908,230504,37,'minion','uncovering','roped','A');
+INSERT INTO t2 VALUES (909,230505,37,'marginal','chews','waltz','');
+INSERT INTO t2 VALUES (910,230506,37,'apiary','appendixes','Lillian','');
+INSERT INTO t2 VALUES (911,230507,37,'measures','raining','repressions','A');
+INSERT INTO t2 VALUES (912,230508,37,'precaution','infest','chillingly','');
+INSERT INTO t2 VALUES (913,230509,37,'repelled','compartment','noncritical','');
+INSERT INTO t2 VALUES (914,230901,37,'primary','minting','lithograph','');
+INSERT INTO t2 VALUES (915,230902,37,'coverings','ducks','spongers','');
+INSERT INTO t2 VALUES (916,230903,37,'Artemia','roped','parenthood','');
+INSERT INTO t2 VALUES (917,230904,37,'navigate','waltz','posed','');
+INSERT INTO t2 VALUES (918,230905,37,'spatial','Lillian','instruments','');
+INSERT INTO t2 VALUES (919,230906,37,'Gurkha','repressions','filial','');
+INSERT INTO t2 VALUES (920,230907,37,'meanwhile','chillingly','fixedly','');
+INSERT INTO t2 VALUES (921,230908,37,'Melinda','noncritical','relives','');
+INSERT INTO t2 VALUES (922,230909,37,'Butterfield','lithograph','Pandora','');
+INSERT INTO t2 VALUES (923,230910,37,'Aldrich','spongers','watering','A');
+INSERT INTO t2 VALUES (924,230911,37,'previewing','parenthood','ungrateful','');
+INSERT INTO t2 VALUES (925,230912,37,'glut','posed','secures','');
+INSERT INTO t2 VALUES (926,230913,37,'unaffected','instruments','chastisers','');
+INSERT INTO t2 VALUES (927,230914,37,'inmate','filial','icon','');
+INSERT INTO t2 VALUES (928,231304,37,'mineral','fixedly','reuniting','A');
+INSERT INTO t2 VALUES (929,231305,37,'impending','relives','imagining','A');
+INSERT INTO t2 VALUES (930,231306,37,'meditation','Pandora','abiding','A');
+INSERT INTO t2 VALUES (931,231307,37,'ideas','watering','omnisciently','');
+INSERT INTO t2 VALUES (932,231308,37,'miniaturizes','ungrateful','Britannic','');
+INSERT INTO t2 VALUES (933,231309,37,'lewdly','secures','scholastics','A');
+INSERT INTO t2 VALUES (934,231310,37,'title','chastisers','mechanics','A');
+INSERT INTO t2 VALUES (935,231311,37,'youthfulness','icon','humidly','A');
+INSERT INTO t2 VALUES (936,231312,37,'creak','reuniting','masterpiece','');
+INSERT INTO t2 VALUES (937,231313,37,'Chippewa','imagining','however','');
+INSERT INTO t2 VALUES (938,231314,37,'clamored','abiding','Mendelian','');
+INSERT INTO t2 VALUES (939,231315,37,'freezes','omnisciently','jarred','');
+INSERT INTO t2 VALUES (940,232102,37,'forgivably','Britannic','scolds','');
+INSERT INTO t2 VALUES (941,232103,37,'reduce','scholastics','infatuate','');
+INSERT INTO t2 VALUES (942,232104,37,'McGovern','mechanics','willed','A');
+INSERT INTO t2 VALUES (943,232105,37,'Nazis','humidly','joyfully','');
+INSERT INTO t2 VALUES (944,232106,37,'epistle','masterpiece','Microsoft','');
+INSERT INTO t2 VALUES (945,232107,37,'socializes','however','fibrosities','');
+INSERT INTO t2 VALUES (946,232108,37,'conceptions','Mendelian','Baltimorean','');
+INSERT INTO t2 VALUES (947,232601,37,'Kevin','jarred','equestrian','');
+INSERT INTO t2 VALUES (948,232602,37,'uncovering','scolds','Goodrich','');
+INSERT INTO t2 VALUES (949,232603,37,'chews','infatuate','apish','A');
+INSERT INTO t2 VALUES (950,232605,37,'appendixes','willed','Adlerian','');
+INSERT INTO t2 VALUES (5950,1232605,37,'appendixes','willed','Adlerian','');
+INSERT INTO t2 VALUES (5951,1232606,37,'appendixes','willed','Adlerian','');
+INSERT INTO t2 VALUES (5952,1232607,37,'appendixes','willed','Adlerian','');
+INSERT INTO t2 VALUES (5953,1232608,37,'appendixes','willed','Adlerian','');
+INSERT INTO t2 VALUES (5954,1232609,37,'appendixes','willed','Adlerian','');
+INSERT INTO t2 VALUES (951,232606,37,'raining','joyfully','Tropez','');
+INSERT INTO t2 VALUES (952,232607,37,'infest','Microsoft','nouns','');
+INSERT INTO t2 VALUES (953,232608,37,'compartment','fibrosities','distracting','');
+INSERT INTO t2 VALUES (954,232609,37,'minting','Baltimorean','mutton','');
+INSERT INTO t2 VALUES (955,236104,37,'ducks','equestrian','bridgeable','A');
+INSERT INTO t2 VALUES (956,236105,37,'roped','Goodrich','stickers','A');
+INSERT INTO t2 VALUES (957,236106,37,'waltz','apish','transcontinental','A');
+INSERT INTO t2 VALUES (958,236107,37,'Lillian','Adlerian','amateurish','');
+INSERT INTO t2 VALUES (959,236108,37,'repressions','Tropez','Gandhian','');
+INSERT INTO t2 VALUES (960,236109,37,'chillingly','nouns','stratified','');
+INSERT INTO t2 VALUES (961,236110,37,'noncritical','distracting','chamberlains','');
+INSERT INTO t2 VALUES (962,236111,37,'lithograph','mutton','creditably','');
+INSERT INTO t2 VALUES (963,236112,37,'spongers','bridgeable','philosophic','');
+INSERT INTO t2 VALUES (964,236113,37,'parenthood','stickers','ores','');
+INSERT INTO t2 VALUES (965,238005,37,'posed','transcontinental','Carleton','');
+INSERT INTO t2 VALUES (966,238006,37,'instruments','amateurish','tape','A');
+INSERT INTO t2 VALUES (967,238007,37,'filial','Gandhian','afloat','A');
+INSERT INTO t2 VALUES (968,238008,37,'fixedly','stratified','goodness','A');
+INSERT INTO t2 VALUES (969,238009,37,'relives','chamberlains','welcoming','');
+INSERT INTO t2 VALUES (970,238010,37,'Pandora','creditably','Pinsky','FAS');
+INSERT INTO t2 VALUES (971,238011,37,'watering','philosophic','halting','');
+INSERT INTO t2 VALUES (972,238012,37,'ungrateful','ores','bibliography','');
+INSERT INTO t2 VALUES (973,238013,37,'secures','Carleton','decoding','');
+INSERT INTO t2 VALUES (974,240401,41,'chastisers','tape','variance','A');
+INSERT INTO t2 VALUES (975,240402,41,'icon','afloat','allowed','A');
+INSERT INTO t2 VALUES (976,240901,41,'reuniting','goodness','dire','A');
+INSERT INTO t2 VALUES (977,240902,41,'imagining','welcoming','dub','A');
+INSERT INTO t2 VALUES (978,241801,41,'abiding','Pinsky','poisoning','');
+INSERT INTO t2 VALUES (979,242101,41,'omnisciently','halting','Iraqis','A');
+INSERT INTO t2 VALUES (980,242102,41,'Britannic','bibliography','heaving','');
+INSERT INTO t2 VALUES (981,242201,41,'scholastics','decoding','population','A');
+INSERT INTO t2 VALUES (982,242202,41,'mechanics','variance','bomb','A');
+INSERT INTO t2 VALUES (983,242501,41,'humidly','allowed','Majorca','A');
+INSERT INTO t2 VALUES (984,242502,41,'masterpiece','dire','Gershwins','');
+INSERT INTO t2 VALUES (985,246201,41,'however','dub','explorers','');
+INSERT INTO t2 VALUES (986,246202,41,'Mendelian','poisoning','libretto','A');
+INSERT INTO t2 VALUES (987,246203,41,'jarred','Iraqis','occurred','');
+INSERT INTO t2 VALUES (988,246204,41,'scolds','heaving','Lagos','');
+INSERT INTO t2 VALUES (989,246205,41,'infatuate','population','rats','');
+INSERT INTO t2 VALUES (990,246301,41,'willed','bomb','bankruptcies','A');
+INSERT INTO t2 VALUES (991,246302,41,'joyfully','Majorca','crying','');
+INSERT INTO t2 VALUES (992,248001,41,'Microsoft','Gershwins','unexpected','');
+INSERT INTO t2 VALUES (993,248002,41,'fibrosities','explorers','accessed','A');
+INSERT INTO t2 VALUES (994,248003,41,'Baltimorean','libretto','colorful','A');
+INSERT INTO t2 VALUES (995,248004,41,'equestrian','occurred','versatility','A');
+INSERT INTO t2 VALUES (996,248005,41,'Goodrich','Lagos','cosy','');
+INSERT INTO t2 VALUES (997,248006,41,'apish','rats','Darius','A');
+INSERT INTO t2 VALUES (998,248007,41,'Adlerian','bankruptcies','mastering','A');
+INSERT INTO t2 VALUES (999,248008,41,'Tropez','crying','Asiaticizations','A');
+INSERT INTO t2 VALUES (1000,248009,41,'nouns','unexpected','offerers','A');
+INSERT INTO t2 VALUES (1001,248010,41,'distracting','accessed','uncles','A');
+INSERT INTO t2 VALUES (1002,248011,41,'mutton','colorful','sleepwalk','');
+INSERT INTO t2 VALUES (1003,248012,41,'bridgeable','versatility','Ernestine','');
+INSERT INTO t2 VALUES (1004,248013,41,'stickers','cosy','checksumming','');
+INSERT INTO t2 VALUES (1005,248014,41,'transcontinental','Darius','stopped','');
+INSERT INTO t2 VALUES (1006,248015,41,'amateurish','mastering','sicker','');
+INSERT INTO t2 VALUES (1007,248016,41,'Gandhian','Asiaticizations','Italianization','');
+INSERT INTO t2 VALUES (1008,248017,41,'stratified','offerers','alphabetic','');
+INSERT INTO t2 VALUES (1009,248018,41,'chamberlains','uncles','pharmaceutic','');
+INSERT INTO t2 VALUES (1010,248019,41,'creditably','sleepwalk','creator','');
+INSERT INTO t2 VALUES (1011,248020,41,'philosophic','Ernestine','chess','');
+INSERT INTO t2 VALUES (1012,248021,41,'ores','checksumming','charcoal','');
+INSERT INTO t2 VALUES (1013,248101,41,'Carleton','stopped','Epiphany','A');
+INSERT INTO t2 VALUES (1014,248102,41,'tape','sicker','bulldozes','A');
+INSERT INTO t2 VALUES (1015,248201,41,'afloat','Italianization','Pygmalion','A');
+INSERT INTO t2 VALUES (1016,248202,41,'goodness','alphabetic','caressing','A');
+INSERT INTO t2 VALUES (1017,248203,41,'welcoming','pharmaceutic','Palestine','A');
+INSERT INTO t2 VALUES (1018,248204,41,'Pinsky','creator','regimented','A');
+INSERT INTO t2 VALUES (1019,248205,41,'halting','chess','scars','A');
+INSERT INTO t2 VALUES (1020,248206,41,'bibliography','charcoal','realest','A');
+INSERT INTO t2 VALUES (1021,248207,41,'decoding','Epiphany','diffusing','A');
+INSERT INTO t2 VALUES (1022,248208,41,'variance','bulldozes','clubroom','A');
+INSERT INTO t2 VALUES (1023,248209,41,'allowed','Pygmalion','Blythe','A');
+INSERT INTO t2 VALUES (1024,248210,41,'dire','caressing','ahead','');
+INSERT INTO t2 VALUES (1025,248211,50,'dub','Palestine','reviver','');
+INSERT INTO t2 VALUES (1026,250501,34,'poisoning','regimented','retransmitting','A');
+INSERT INTO t2 VALUES (1027,250502,34,'Iraqis','scars','landslide','');
+INSERT INTO t2 VALUES (1028,250503,34,'heaving','realest','Eiffel','');
+INSERT INTO t2 VALUES (1029,250504,34,'population','diffusing','absentee','');
+INSERT INTO t2 VALUES (1030,250505,34,'bomb','clubroom','aye','');
+INSERT INTO t2 VALUES (1031,250601,34,'Majorca','Blythe','forked','A');
+INSERT INTO t2 VALUES (1032,250602,34,'Gershwins','ahead','Peruvianizes','');
+INSERT INTO t2 VALUES (1033,250603,34,'explorers','reviver','clerked','');
+INSERT INTO t2 VALUES (1034,250604,34,'libretto','retransmitting','tutor','');
+INSERT INTO t2 VALUES (1035,250605,34,'occurred','landslide','boulevard','');
+INSERT INTO t2 VALUES (1036,251001,34,'Lagos','Eiffel','shuttered','');
+INSERT INTO t2 VALUES (1037,251002,34,'rats','absentee','quotes','A');
+INSERT INTO t2 VALUES (1038,251003,34,'bankruptcies','aye','Caltech','');
+INSERT INTO t2 VALUES (1039,251004,34,'crying','forked','Mossberg','');
+INSERT INTO t2 VALUES (1040,251005,34,'unexpected','Peruvianizes','kept','');
+INSERT INTO t2 VALUES (1041,251301,34,'accessed','clerked','roundly','');
+INSERT INTO t2 VALUES (1042,251302,34,'colorful','tutor','features','A');
+INSERT INTO t2 VALUES (1043,251303,34,'versatility','boulevard','imaginable','A');
+INSERT INTO t2 VALUES (1044,251304,34,'cosy','shuttered','controller','');
+INSERT INTO t2 VALUES (1045,251305,34,'Darius','quotes','racial','');
+INSERT INTO t2 VALUES (1046,251401,34,'mastering','Caltech','uprisings','A');
+INSERT INTO t2 VALUES (1047,251402,34,'Asiaticizations','Mossberg','narrowed','A');
+INSERT INTO t2 VALUES (1048,251403,34,'offerers','kept','cannot','A');
+INSERT INTO t2 VALUES (1049,251404,34,'uncles','roundly','vest','');
+INSERT INTO t2 VALUES (1050,251405,34,'sleepwalk','features','famine','');
+INSERT INTO t2 VALUES (1051,251406,34,'Ernestine','imaginable','sugars','');
+INSERT INTO t2 VALUES (1052,251801,34,'checksumming','controller','exterminated','A');
+INSERT INTO t2 VALUES (1053,251802,34,'stopped','racial','belays','');
+INSERT INTO t2 VALUES (1054,252101,34,'sicker','uprisings','Hodges','A');
+INSERT INTO t2 VALUES (1055,252102,34,'Italianization','narrowed','translatable','');
+INSERT INTO t2 VALUES (1056,252301,34,'alphabetic','cannot','duality','A');
+INSERT INTO t2 VALUES (1057,252302,34,'pharmaceutic','vest','recording','A');
+INSERT INTO t2 VALUES (1058,252303,34,'creator','famine','rouses','A');
+INSERT INTO t2 VALUES (1059,252304,34,'chess','sugars','poison','');
+INSERT INTO t2 VALUES (1060,252305,34,'charcoal','exterminated','attitude','');
+INSERT INTO t2 VALUES (1061,252306,34,'Epiphany','belays','dusted','');
+INSERT INTO t2 VALUES (1062,252307,34,'bulldozes','Hodges','encompasses','');
+INSERT INTO t2 VALUES (1063,252308,34,'Pygmalion','translatable','presentation','');
+INSERT INTO t2 VALUES (1064,252309,34,'caressing','duality','Kantian','');
+INSERT INTO t2 VALUES (1065,256001,34,'Palestine','recording','imprecision','A');
+INSERT INTO t2 VALUES (1066,256002,34,'regimented','rouses','saving','');
+INSERT INTO t2 VALUES (1067,256003,34,'scars','poison','maternal','');
+INSERT INTO t2 VALUES (1068,256004,34,'realest','attitude','hewed','');
+INSERT INTO t2 VALUES (1069,256005,34,'diffusing','dusted','kerosene','');
+INSERT INTO t2 VALUES (1070,258001,34,'clubroom','encompasses','Cubans','');
+INSERT INTO t2 VALUES (1071,258002,34,'Blythe','presentation','photographers','');
+INSERT INTO t2 VALUES (1072,258003,34,'ahead','Kantian','nymph','A');
+INSERT INTO t2 VALUES (1073,258004,34,'reviver','imprecision','bedlam','A');
+INSERT INTO t2 VALUES (1074,258005,34,'retransmitting','saving','north','A');
+INSERT INTO t2 VALUES (1075,258006,34,'landslide','maternal','Schoenberg','A');
+INSERT INTO t2 VALUES (1076,258007,34,'Eiffel','hewed','botany','A');
+INSERT INTO t2 VALUES (1077,258008,34,'absentee','kerosene','curs','');
+INSERT INTO t2 VALUES (1078,258009,34,'aye','Cubans','solidification','');
+INSERT INTO t2 VALUES (1079,258010,34,'forked','photographers','inheritresses','');
+INSERT INTO t2 VALUES (1080,258011,34,'Peruvianizes','nymph','stiller','');
+INSERT INTO t2 VALUES (1081,258101,68,'clerked','bedlam','t1','A');
+INSERT INTO t2 VALUES (1082,258102,68,'tutor','north','suite','A');
+INSERT INTO t2 VALUES (1083,258103,34,'boulevard','Schoenberg','ransomer','');
+INSERT INTO t2 VALUES (1084,258104,68,'shuttered','botany','Willy','');
+INSERT INTO t2 VALUES (1085,258105,68,'quotes','curs','Rena','A');
+INSERT INTO t2 VALUES (1086,258106,68,'Caltech','solidification','Seattle','A');
+INSERT INTO t2 VALUES (1087,258107,68,'Mossberg','inheritresses','relaxes','A');
+INSERT INTO t2 VALUES (1088,258108,68,'kept','stiller','exclaim','');
+INSERT INTO t2 VALUES (1089,258109,68,'roundly','t1','implicated','A');
+INSERT INTO t2 VALUES (1090,258110,68,'features','suite','distinguish','');
+INSERT INTO t2 VALUES (1091,258111,68,'imaginable','ransomer','assayed','');
+INSERT INTO t2 VALUES (1092,258112,68,'controller','Willy','homeowner','');
+INSERT INTO t2 VALUES (1093,258113,68,'racial','Rena','and','');
+INSERT INTO t2 VALUES (1094,258201,34,'uprisings','Seattle','stealth','');
+INSERT INTO t2 VALUES (1095,258202,34,'narrowed','relaxes','coinciding','A');
+INSERT INTO t2 VALUES (1096,258203,34,'cannot','exclaim','founder','A');
+INSERT INTO t2 VALUES (1097,258204,34,'vest','implicated','environing','');
+INSERT INTO t2 VALUES (1098,258205,34,'famine','distinguish','jewelry','');
+INSERT INTO t2 VALUES (1099,258301,34,'sugars','assayed','lemons','A');
+INSERT INTO t2 VALUES (1100,258401,34,'exterminated','homeowner','brokenness','A');
+INSERT INTO t2 VALUES (1101,258402,34,'belays','and','bedpost','A');
+INSERT INTO t2 VALUES (1102,258403,34,'Hodges','stealth','assurers','A');
+INSERT INTO t2 VALUES (1103,258404,34,'translatable','coinciding','annoyers','');
+INSERT INTO t2 VALUES (1104,258405,34,'duality','founder','affixed','');
+INSERT INTO t2 VALUES (1105,258406,34,'recording','environing','warbling','');
+INSERT INTO t2 VALUES (1106,258407,34,'rouses','jewelry','seriously','');
+INSERT INTO t2 VALUES (1107,228123,37,'poison','lemons','boasted','');
+INSERT INTO t2 VALUES (1108,250606,34,'attitude','brokenness','Chantilly','');
+INSERT INTO t2 VALUES (1109,208405,37,'dusted','bedpost','Iranizes','');
+INSERT INTO t2 VALUES (1110,212101,37,'encompasses','assurers','violinist','');
+INSERT INTO t2 VALUES (1111,218206,37,'presentation','annoyers','extramarital','');
+INSERT INTO t2 VALUES (1112,150401,37,'Kantian','affixed','spates','');
+INSERT INTO t2 VALUES (1113,248212,41,'imprecision','warbling','cloakroom','');
+INSERT INTO t2 VALUES (1114,128026,00,'saving','seriously','gazer','');
+INSERT INTO t2 VALUES (1115,128024,00,'maternal','boasted','hand','');
+INSERT INTO t2 VALUES (1116,128027,00,'hewed','Chantilly','tucked','');
+INSERT INTO t2 VALUES (1117,128025,00,'kerosene','Iranizes','gems','');
+INSERT INTO t2 VALUES (1118,128109,00,'Cubans','violinist','clinker','');
+INSERT INTO t2 VALUES (1119,128705,00,'photographers','extramarital','refiner','');
+INSERT INTO t2 VALUES (1120,126303,00,'nymph','spates','callus','');
+INSERT INTO t2 VALUES (1121,128308,00,'bedlam','cloakroom','leopards','');
+INSERT INTO t2 VALUES (1122,128204,00,'north','gazer','comfortingly','');
+INSERT INTO t2 VALUES (1123,128205,00,'Schoenberg','hand','generically','');
+INSERT INTO t2 VALUES (1124,128206,00,'botany','tucked','getters','');
+INSERT INTO t2 VALUES (1125,128207,00,'curs','gems','sexually','');
+INSERT INTO t2 VALUES (1126,118205,00,'solidification','clinker','spear','');
+INSERT INTO t2 VALUES (1127,116801,00,'inheritresses','refiner','serums','');
+INSERT INTO t2 VALUES (1128,116803,00,'stiller','callus','Italianization','');
+INSERT INTO t2 VALUES (1129,116804,00,'t1','leopards','attendants','');
+INSERT INTO t2 VALUES (1130,116802,00,'suite','comfortingly','spies','');
+INSERT INTO t2 VALUES (1131,128605,00,'ransomer','generically','Anthony','');
+INSERT INTO t2 VALUES (1132,118308,00,'Willy','getters','planar','');
+INSERT INTO t2 VALUES (1133,113702,00,'Rena','sexually','cupped','');
+INSERT INTO t2 VALUES (1134,113703,00,'Seattle','spear','cleanser','');
+INSERT INTO t2 VALUES (1135,112103,00,'relaxes','serums','commuters','');
+INSERT INTO t2 VALUES (1136,118009,00,'exclaim','Italianization','honeysuckle','');
+INSERT INTO t2 VALUES (5136,1118009,00,'exclaim','Italianization','honeysuckle','');
+INSERT INTO t2 VALUES (1137,138011,00,'implicated','attendants','orphanage','');
+INSERT INTO t2 VALUES (1138,138010,00,'distinguish','spies','skies','');
+INSERT INTO t2 VALUES (1139,138012,00,'assayed','Anthony','crushers','');
+INSERT INTO t2 VALUES (1140,068304,00,'homeowner','planar','Puritan','');
+INSERT INTO t2 VALUES (1141,078009,00,'and','cupped','squeezer','');
+INSERT INTO t2 VALUES (1142,108013,00,'stealth','cleanser','bruises','');
+INSERT INTO t2 VALUES (1143,084004,00,'coinciding','commuters','bonfire','');
+INSERT INTO t2 VALUES (1144,083402,00,'founder','honeysuckle','Colombo','');
+INSERT INTO t2 VALUES (1145,084003,00,'environing','orphanage','nondecreasing','');
+INSERT INTO t2 VALUES (1146,088504,00,'jewelry','skies','innocents','');
+INSERT INTO t2 VALUES (1147,088005,00,'lemons','crushers','masked','');
+INSERT INTO t2 VALUES (1148,088007,00,'brokenness','Puritan','file','');
+INSERT INTO t2 VALUES (1149,088006,00,'bedpost','squeezer','brush','');
+INSERT INTO t2 VALUES (1150,148025,00,'assurers','bruises','mutilate','');
+INSERT INTO t2 VALUES (1151,148024,00,'annoyers','bonfire','mommy','');
+INSERT INTO t2 VALUES (1152,138305,00,'affixed','Colombo','bulkheads','');
+INSERT INTO t2 VALUES (1153,138306,00,'warbling','nondecreasing','undeclared','');
+INSERT INTO t2 VALUES (1154,152701,00,'seriously','innocents','displacements','');
+INSERT INTO t2 VALUES (1155,148505,00,'boasted','masked','nieces','');
+INSERT INTO t2 VALUES (1156,158003,00,'Chantilly','file','coeducation','');
+INSERT INTO t2 VALUES (1157,156201,00,'Iranizes','brush','brassy','');
+INSERT INTO t2 VALUES (1158,156202,00,'violinist','mutilate','authenticator','');
+INSERT INTO t2 VALUES (1159,158307,00,'extramarital','mommy','Washoe','');
+INSERT INTO t2 VALUES (1160,158402,00,'spates','bulkheads','penny','');
+INSERT INTO t2 VALUES (1161,158401,00,'cloakroom','undeclared','Flagler','');
+INSERT INTO t2 VALUES (1162,068013,00,'gazer','displacements','stoned','');
+INSERT INTO t2 VALUES (1163,068012,00,'hand','nieces','cranes','');
+INSERT INTO t2 VALUES (1164,068203,00,'tucked','coeducation','masterful','');
+INSERT INTO t2 VALUES (1165,088205,00,'gems','brassy','biracial','');
+INSERT INTO t2 VALUES (1166,068704,00,'clinker','authenticator','steamships','');
+INSERT INTO t2 VALUES (1167,068604,00,'refiner','Washoe','windmills','');
+INSERT INTO t2 VALUES (1168,158502,00,'callus','penny','exploit','');
+INSERT INTO t2 VALUES (1169,123103,00,'leopards','Flagler','riverfront','');
+INSERT INTO t2 VALUES (1170,148026,00,'comfortingly','stoned','sisterly','');
+INSERT INTO t2 VALUES (1171,123302,00,'generically','cranes','sharpshoot','');
+INSERT INTO t2 VALUES (1172,076503,00,'getters','masterful','mittens','');
+INSERT INTO t2 VALUES (1173,126304,00,'sexually','biracial','interdependency','');
+INSERT INTO t2 VALUES (1174,068306,00,'spear','steamships','policy','');
+INSERT INTO t2 VALUES (1175,143504,00,'serums','windmills','unleashing','');
+INSERT INTO t2 VALUES (1176,160201,00,'Italianization','exploit','pretenders','');
+INSERT INTO t2 VALUES (1177,148028,00,'attendants','riverfront','overstatements','');
+INSERT INTO t2 VALUES (1178,148027,00,'spies','sisterly','birthed','');
+INSERT INTO t2 VALUES (1179,143505,00,'Anthony','sharpshoot','opportunism','');
+INSERT INTO t2 VALUES (1180,108014,00,'planar','mittens','showroom','');
+INSERT INTO t2 VALUES (1181,076104,00,'cupped','interdependency','compromisingly','');
+INSERT INTO t2 VALUES (1182,078106,00,'cleanser','policy','Medicare','');
+INSERT INTO t2 VALUES (1183,126102,00,'commuters','unleashing','corresponds','');
+INSERT INTO t2 VALUES (1184,128029,00,'honeysuckle','pretenders','hardware','');
+INSERT INTO t2 VALUES (1185,128028,00,'orphanage','overstatements','implant','');
+INSERT INTO t2 VALUES (1186,018410,00,'skies','birthed','Alicia','');
+INSERT INTO t2 VALUES (1187,128110,00,'crushers','opportunism','requesting','');
+INSERT INTO t2 VALUES (1188,148506,00,'Puritan','showroom','produced','');
+INSERT INTO t2 VALUES (1189,123303,00,'squeezer','compromisingly','criticizes','');
+INSERT INTO t2 VALUES (1190,123304,00,'bruises','Medicare','backer','');
+INSERT INTO t2 VALUES (1191,068504,00,'bonfire','corresponds','positively','');
+INSERT INTO t2 VALUES (1192,068305,00,'Colombo','hardware','colicky','');
+INSERT INTO t2 VALUES (1193,000000,00,'nondecreasing','implant','thrillingly','');
+select t2.fld3 from t2 where companynr = 58 and fld3 like "%imaginable%";
fld3
imaginable
+select fld3 from t2 where fld3 like "%cultivation" ;
fld3
cultivation
+select t2.fld3,companynr from t2 where companynr = 57+1 order by fld3;
fld3 companynr
concoct 58
druggists 58
@@ -32,6 +1256,7 @@ synergy 58
thanking 58
tying 58
unlocks 58
+select fld3,companynr from t2 where companynr = 58 order by fld3;
fld3 companynr
concoct 58
druggists 58
@@ -56,6 +1281,7 @@ synergy 58
thanking 58
tying 58
unlocks 58
+select fld3 from t2 order by fld3 desc limit 10;
fld3
youthfulness
yelped
@@ -67,49 +1293,71 @@ Winsett
Willy
willed
wildcats
+select fld3 from t2 order by fld3 desc limit 5;
fld3
youthfulness
yelped
Wotan
workers
Witt
+select fld3 from t2 order by fld3 desc limit 5,5;
fld3
witchcraft
Winsett
Willy
willed
wildcats
+select t2.fld3 from t2 where fld3 = 'honeysuckle';
fld3
honeysuckle
+select t2.fld3 from t2 where fld3 LIKE 'honeysuckl_';
fld3
honeysuckle
+select t2.fld3 from t2 where fld3 LIKE 'hon_ysuckl_';
fld3
honeysuckle
+select t2.fld3 from t2 where fld3 LIKE 'honeysuckle%';
fld3
honeysuckle
+select t2.fld3 from t2 where fld3 LIKE 'h%le';
fld3
honeysuckle
+select t2.fld3 from t2 where fld3 LIKE 'honeysuckle_';
fld3
+select t2.fld3 from t2 where fld3 LIKE 'don_t_find_me_please%';
fld3
+explain select t2.fld3 from t2 where fld3 = 'honeysuckle';
table type possible_keys key key_len ref rows Extra
t2 ref fld3 fld3 30 const 1 where used; Using index
+explain select fld3 from t2 ignore index (fld3) where fld3 = 'honeysuckle';
table type possible_keys key key_len ref rows Extra
-t2 index fld3 fld3 30 NULL 1199 where used; Using index
+t2 index NULL fld3 30 NULL 1199 where used; Using index
+explain select fld3 from t2 use index (fld1) where fld3 = 'honeysuckle';
table type possible_keys key key_len ref rows Extra
-t2 index fld3 fld3 30 NULL 1199 where used; Using index
+t2 index NULL fld3 30 NULL 1199 where used; Using index
+explain select fld3 from t2 use index (fld3) where fld3 = 'honeysuckle';
table type possible_keys key key_len ref rows Extra
t2 ref fld3 fld3 30 const 1 where used; Using index
+explain select fld3 from t2 use index (fld1,fld3) where fld3 = 'honeysuckle';
table type possible_keys key key_len ref rows Extra
t2 ref fld3 fld3 30 const 1 where used; Using index
+explain select fld3 from t2 ignore index (fld3,not_used);
+Key column 'not_used' doesn't exist in table
+explain select fld3 from t2 use index (not_used);
+Key column 'not_used' doesn't exist in table
+select t2.fld3 from t2 where fld3 >= 'honeysuckle' and fld3 <= 'honoring' order by fld3;
fld3
honeysuckle
honoring
+explain select t2.fld3 from t2 where fld3 >= 'honeysuckle' and fld3 <= 'honoring' order by fld3;
table type possible_keys key key_len ref rows Extra
t2 range fld3 fld3 30 NULL 2 where used; Using index
+select fld1,fld3 from t2 where fld3="Colombo" or fld3 = "nondecreasing" order by fld3;
fld1 fld3
148504 Colombo
068305 Colombo
000000 nondecreasing
+select fld1,fld3 from t2 where companynr = 37 and fld3 = 'appendixes';
fld1 fld3
232605 appendixes
1232605 appendixes
@@ -117,18 +1365,23 @@ fld1 fld3
1232607 appendixes
1232608 appendixes
1232609 appendixes
+select fld1 from t2 where fld1=250501 or fld1="250502";
fld1
250501
250502
+explain select fld1 from t2 where fld1=250501 or fld1="250502";
table type possible_keys key key_len ref rows Extra
t2 range fld1 fld1 4 NULL 2 where used; Using index
+select fld1 from t2 where fld1=250501 or fld1=250502 or fld1 >= 250505 and fld1 <= 250601 or fld1 between 250501 and 250502;
fld1
250501
250502
250505
250601
+explain select fld1 from t2 where fld1=250501 or fld1=250502 or fld1 >= 250505 and fld1 <= 250601 or fld1 between 250501 and 250502;
table type possible_keys key key_len ref rows Extra
t2 range fld1 fld1 4 NULL 4 where used; Using index
+select fld1,fld3 from t2 where companynr = 37 and fld3 like 'f%';
fld1 fld3
218401 faithful
018007 fanatic
@@ -161,21 +1414,26 @@ fld1 fld3
036002 funereal
226209 furnishings
198006 furthermore
+select fld3 from t2 where fld3 like "L%" and fld3 = "ok";
fld3
+select fld3 from t2 where (fld3 like "C%" and fld3 = "Chantilly");
fld3
Chantilly
+select fld1,fld3 from t2 where fld1 like "25050%";
fld1 fld3
250501 poisoning
250502 Iraqis
250503 heaving
250504 population
250505 bomb
+select fld1,fld3 from t2 where fld1 like "25050_";
fld1 fld3
250501 poisoning
250502 Iraqis
250503 heaving
250504 population
250505 bomb
+select distinct companynr from t2;
companynr
00
37
@@ -189,6 +1447,7 @@ companynr
41
34
68
+select distinct companynr from t2 order by companynr;
companynr
00
29
@@ -202,6 +1461,7 @@ companynr
58
65
68
+select distinct companynr from t2 order by companynr desc;
companynr
68
65
@@ -215,6 +1475,7 @@ companynr
34
29
00
+select distinct t2.fld3,period from t2,t1 where companynr=37 and fld3 like "O%";
fld3 period
obliterates 9410
offload 9410
@@ -222,6 +1483,7 @@ opaquely 9410
organizer 9410
overestimating 9410
overlay 9410
+select distinct fld3 from t2 where companynr = 34 order by fld3;
fld3
absentee
accessed
@@ -293,6 +1555,7 @@ unexpected
uprisings
versatility
vest
+select distinct fld3 from t2 limit 10;
fld3
abates
abiding
@@ -304,6 +1567,7 @@ accessed
accruing
accumulating
accuracies
+select distinct fld3 from t2 having fld3 like "A%" limit 10;
fld3
abates
abiding
@@ -315,6 +1579,7 @@ accessed
accruing
accumulating
accuracies
+select distinct substring(fld3,1,3) from t2 where fld3 like "A%";
substring(fld3,1,3)
aba
abi
@@ -378,6 +1643,7 @@ avo
awe
aye
Azt
+select distinct substring(fld3,1,3) as a from t2 having a like "A%" order by a limit 10;
a
aba
abi
@@ -389,6 +1655,7 @@ acq
acu
Ade
adj
+select distinct substring(fld3,1,3) from t2 where fld3 like "A%" limit 10;
substring(fld3,1,3)
aba
abi
@@ -400,6 +1667,7 @@ acq
acu
Ade
adj
+select distinct substring(fld3,1,3) as a from t2 having a like "A%" limit 10;
a
aba
abi
@@ -411,6 +1679,47 @@ acq
acu
Ade
adj
+create table t3 (
+period int not null,
+name char(32) not null,
+companynr int not null,
+price double(11,0),
+price2 double(11,0),
+key (period),
+key (name)
+);
+INSERT INTO t3 (period,name,companynr,price,price2) VALUES (1001,"Iranizes",37,5987435,234724);
+INSERT INTO t3 (period,name,companynr,price,price2) VALUES (1002,"violinist",37,28357832,8723648);
+INSERT INTO t3 (period,name,companynr,price,price2) VALUES (1003,"extramarital",37,39654943,235872);
+INSERT INTO t3 (period,name,companynr,price,price2) VALUES (1004,"spates",78,726498,72987523);
+INSERT INTO t3 (period,name,companynr,price,price2) VALUES (1005,"cloakroom",78,98439034,823742);
+INSERT INTO t3 (period,name,companynr,price,price2) VALUES (1006,"gazer",101,834598,27348324);
+INSERT INTO t3 (period,name,companynr,price,price2) VALUES (1007,"hand",154,983543950,29837423);
+INSERT INTO t3 (period,name,companynr,price,price2) VALUES (1008,"tucked",311,234298,3275892);
+INSERT INTO t3 (period,name,companynr,price,price2) VALUES (1009,"gems",447,2374834,9872392);
+INSERT INTO t3 (period,name,companynr,price,price2) VALUES (1010,"clinker",512,786542,76234234);
+create temporary table tmp type = myisam select * from t3;
+insert into t3 select * from tmp;
+insert into tmp select * from t3;
+insert into t3 select * from tmp;
+insert into tmp select * from t3;
+insert into t3 select * from tmp;
+insert into tmp select * from t3;
+insert into t3 select * from tmp;
+insert into tmp select * from t3;
+insert into t3 select * from tmp;
+insert into tmp select * from t3;
+insert into t3 select * from tmp;
+insert into tmp select * from t3;
+insert into t3 select * from tmp;
+insert into tmp select * from t3;
+insert into t3 select * from tmp;
+insert into tmp select * from t3;
+insert into t3 select * from tmp;
+alter table t3 add t2nr int not null auto_increment primary key first;
+drop table tmp;
+SET OPTION SQL_BIG_TABLES=1;
+select distinct concat(fld3," ",fld3) as namn from t2,t3 where t2.fld1=t3.t2nr order by namn limit 10;
namn
Abraham Abraham
abrogating abrogating
@@ -422,6 +1731,8 @@ ammonium ammonium
analyzable analyzable
animals animals
animized animized
+SET OPTION SQL_BIG_TABLES=0;
+select distinct concat(fld3," ",fld3) from t2,t3 where t2.fld1=t3.t2nr order by fld3 limit 10;
concat(fld3," ",fld3)
Abraham Abraham
abrogating abrogating
@@ -433,6 +1744,7 @@ ammonium ammonium
analyzable analyzable
animals animals
animized animized
+select distinct fld5 from t2 limit 10;
fld5
neat
Steinberg
@@ -444,6 +1756,7 @@ attainments
fanatic
measures
rightfulness
+select distinct fld3,count(*) from t2 group by companynr,fld3 limit 10;
fld3 count(*)
affixed 1
and 1
@@ -455,6 +1768,8 @@ attendants 1
bedlam 1
bedpost 1
boasted 1
+SET OPTION SQL_BIG_TABLES=1;
+select distinct fld3,count(*) from t2 group by companynr,fld3 limit 10;
fld3 count(*)
affixed 1
and 1
@@ -466,6 +1781,8 @@ attendants 1
bedlam 1
bedpost 1
boasted 1
+SET OPTION SQL_BIG_TABLES=0;
+select distinct fld3,repeat("a",length(fld3)),count(*) from t2 group by companynr,fld3 limit 100,10;
fld3 repeat("a",length(fld3)) count(*)
circus aaaaaa 1
cited aaaaa 1
@@ -477,6 +1794,7 @@ cultivation aaaaaaaaaaa 1
definiteness aaaaaaaaaaaa 1
demultiplex aaaaaaaaaaa 1
disappointing aaaaaaaaaaaaa 1
+select distinct companynr,rtrim(space(512+companynr)) from t3 order by 1,2;
companynr rtrim(space(512+companynr))
37
78
@@ -485,20 +1803,28 @@ companynr rtrim(space(512+companynr))
311
447
512
+select distinct fld3 from t2,t3 where t2.companynr = 34 and t2.fld1=t3.t2nr order by fld3;
fld3
+explain select t3.t2nr,fld3 from t2,t3 where t2.companynr = 34 and t2.fld1=t3.t2nr order by t3.t2nr,fld3;
table type possible_keys key key_len ref rows Extra
t2 ALL fld1 NULL NULL NULL 1199 where used; Using temporary; Using filesort
t3 eq_ref PRIMARY PRIMARY 4 t2.fld1 1 where used; Using index
+select period from t1;
period
9410
+select period from t1 where period=1900;
period
+select fld3,period from t1,t2 where fld1 = 011401 order by period;
fld3 period
breaking 9410
+select fld3,period from t2,t3 where t2.fld1 = 011401 and t2.fld1=t3.t2nr and t3.period=1001;
fld3 period
breaking 1001
+explain select fld3,period from t2,t3 where t2.fld1 = 011401 and t3.t2nr=t2.fld1 and 1001 = t3.period;
table type possible_keys key key_len ref rows Extra
t2 const fld1 fld1 4 const 1
t3 const PRIMARY,period PRIMARY 4 const 1
+select fld3,period from t2,t1 where companynr*10 = 37*10;
fld3 period
breaking 9410
Romans 9410
@@ -1088,6 +2414,7 @@ dusted 9410
encompasses 9410
presentation 9410
Kantian 9410
+select fld3,period,price,price2 from t2,t3 where t2.fld1=t3.t2nr and period >= 1001 and period <= 1002 and t2.companynr = 37 order by fld3,period, price;
fld3 period price price2
admonishing 1002 28357832 8723648
analyzable 1002 28357832 8723648
@@ -1148,11 +2475,32 @@ ventilate 1001 5987435 234724
wallet 1001 5987435 234724
Weissmuller 1002 28357832 8723648
Wotan 1002 28357832 8723648
+select t2.fld1,fld3,period,price,price2 from t2,t3 where t2.fld1>= 18201 and t2.fld1 <= 18811 and t2.fld1=t3.t2nr and period = 1001 and t2.companynr = 37;
fld1 fld3 period price price2
018201 relaxing 1001 5987435 234724
018601 vacuuming 1001 5987435 234724
018801 inch 1001 5987435 234724
018811 repetitions 1001 5987435 234724
+drop table if exists company;
+create table t4 (
+companynr tinyint(2) unsigned zerofill NOT NULL default '00',
+companyname char(30) NOT NULL default '',
+PRIMARY KEY (companynr),
+UNIQUE KEY companyname(companyname)
+) TYPE=MyISAM MAX_ROWS=50 PACK_KEYS=1 COMMENT='companynames';
+INSERT INTO t4 (companynr, companyname) VALUES (29,'company 1');
+INSERT INTO t4 (companynr, companyname) VALUES (34,'company 2');
+INSERT INTO t4 (companynr, companyname) VALUES (36,'company 3');
+INSERT INTO t4 (companynr, companyname) VALUES (37,'company 4');
+INSERT INTO t4 (companynr, companyname) VALUES (40,'company 5');
+INSERT INTO t4 (companynr, companyname) VALUES (41,'company 6');
+INSERT INTO t4 (companynr, companyname) VALUES (53,'company 7');
+INSERT INTO t4 (companynr, companyname) VALUES (58,'company 8');
+INSERT INTO t4 (companynr, companyname) VALUES (65,'company 9');
+INSERT INTO t4 (companynr, companyname) VALUES (68,'company 10');
+INSERT INTO t4 (companynr, companyname) VALUES (50,'company 11');
+INSERT INTO t4 (companynr, companyname) VALUES (00,'Unknown');
+select STRAIGHT_JOIN t2.companynr,companyname from t4,t2 where t2.companynr=t4.companynr group by t2.companynr;
companynr companyname
00 Unknown
29 company 1
@@ -1166,6 +2514,7 @@ companynr companyname
58 company 8
65 company 9
68 company 10
+select SQL_SMALL_RESULT t2.companynr,companyname from t4,t2 where t2.companynr=t4.companynr group by t2.companynr;
companynr companyname
00 Unknown
29 company 1
@@ -1179,8 +2528,10 @@ companynr companyname
58 company 8
65 company 9
68 company 10
+select * from t1,t1 t12;
Period Varor_period Period Varor_period
9410 9412 9410 9412
+select t2.fld1,t22.fld1 from t2,t2 t22 where t2.fld1 >= 250501 and t2.fld1 <= 250505 and t22.fld1 >= 250501 and t22.fld1 <= 250505;
fld1 fld1
250501 250501
250502 250501
@@ -1207,44 +2558,58 @@ fld1 fld1
250503 250505
250504 250505
250505 250505
+select t2.companynr,companyname from t2 left join t4 using (companynr) where t4.companynr is null;
companynr companyname
+explain select t2.companynr,companyname from t2 left join t4 using (companynr) where t4.companynr is null;
table type possible_keys key key_len ref rows Extra
t2 ALL NULL NULL NULL NULL 1199
-t4 eq_ref PRIMARY PRIMARY 1 t2.companynr 1 where used; Not exists
+t4 eq_ref PRIMARY PRIMARY 1 test.t2.companynr 1 where used; Not exists
+explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr is null;
table type possible_keys key key_len ref rows Extra
t4 ALL NULL NULL NULL NULL 12
t2 ALL NULL NULL NULL NULL 1199 where used; Not exists
+select distinct t2.companynr,t4.companynr from t2,t4 where t2.companynr=t4.companynr+1;
companynr companynr
37 36
41 40
+explain select distinct t2.companynr,t4.companynr from t2,t4 where t2.companynr=t4.companynr+1;
table type possible_keys key key_len ref rows Extra
t2 ALL NULL NULL NULL NULL 1199 Using temporary
t4 index NULL PRIMARY 1 NULL 12 where used; Using index
+select t2.fld1,t2.companynr,fld3,period from t3,t2 where t2.fld1 = 38208 and t2.fld1=t3.t2nr and period = 1008 or t2.fld1 = 38008 and t2.fld1 =t3.t2nr and period = 1008;
fld1 companynr fld3 period
038008 37 reporters 1008
038208 37 Selfridge 1008
+select t2.fld1,t2.companynr,fld3,period from t3,t2 where (t2.fld1 = 38208 or t2.fld1 = 38008) and t2.fld1=t3.t2nr and period>=1008 and period<=1009;
fld1 companynr fld3 period
038008 37 reporters 1008
038208 37 Selfridge 1008
+select t2.fld1,t2.companynr,fld3,period from t3,t2 where (t3.t2nr = 38208 or t3.t2nr = 38008) and t2.fld1=t3.t2nr and period>=1008 and period<=1009;
fld1 companynr fld3 period
038008 37 reporters 1008
038208 37 Selfridge 1008
+select period from t1 where (((period > 0) or period < 10000 or (period = 1900)) and (period=1900 and period <= 1901) or (period=1903 and (period=1903)) and period>=1902) or ((period=1904 or period=1905) or (period=1906 or period>1907)) or (period=1908 and period = 1909);
period
9410
+select period from t1 where ((period > 0 and period < 1) or (((period > 0 and period < 100) and (period > 10)) or (period > 10)) or (period > 0 and (period > 5 or period > 6)));
period
9410
+select a.fld1 from t2 as a,t2 b where ((a.fld1 = 250501 and a.fld1=b.fld1) or a.fld1=250502 or a.fld1=250503 or (a.fld1=250505 and a.fld1<=b.fld1 and b.fld1>=a.fld1)) and a.fld1=b.fld1;
fld1
250501
250502
250503
250505
+select fld1 from t2 where fld1 in (250502,98005,98006,250503,250605,250606) and fld1 >=250502 and fld1 not in (250605,250606);
fld1
250502
250503
+select fld1 from t2 where fld1 between 250502 and 250504;
fld1
250502
250503
250504
+select fld3 from t2 where (((fld3 like "_%L%" ) or (fld3 like "%ok%")) and ( fld3 like "L%" or fld3 like "G%")) and fld3 like "L%" ;
fld3
label
labeled
@@ -1255,8 +2620,10 @@ leaflet
lewdly
Lillian
luckily
+select count(*) from t1;
count(*)
1
+select companynr,count(*),sum(fld1) from t2 group by companynr;
companynr count(*) sum(fld1)
00 82 10355753
29 95 14473298
@@ -1270,18 +2637,22 @@ companynr count(*) sum(fld1)
58 23 2254293
65 10 2284055
68 12 3097288
+select companynr,count(*) from t2 group by companynr order by companynr desc limit 5;
companynr count(*)
68 12
65 10
58 23
53 4
50 11
+select count(*),min(fld4),max(fld4),sum(fld1),avg(fld1),std(fld1) from t2 where companynr = 34 and fld4<>"";
count(*) min(fld4) max(fld4) sum(fld1) avg(fld1) std(fld1)
70 absentee vest 17788966 254128.0857 3272.5940
+select companynr,count(*),min(fld4),max(fld4),sum(fld1),avg(fld1),std(fld1) from t2 group by companynr limit 3;
companynr count(*) min(fld4) max(fld4) sum(fld1) avg(fld1) std(fld1)
00 82 Anthony windmills 10355753 126289.6707 115550.9757
29 95 abut wetness 14473298 152350.5053 8368.5480
34 70 absentee vest 17788966 254128.0857 3272.5940
+select companynr,t2nr,count(price),sum(price),min(price),max(price),avg(price) from t3 where companynr = 37 group by companynr,t2nr limit 10;
companynr t2nr count(price) sum(price) min(price) max(price) avg(price)
37 1 1 5987435 5987435 5987435 5987435.0000
37 2 1 28357832 28357832 28357832 28357832.0000
@@ -1293,6 +2664,7 @@ companynr t2nr count(price) sum(price) min(price) max(price) avg(price)
37 22 1 28357832 28357832 28357832 28357832.0000
37 23 1 39654943 39654943 39654943 39654943.0000
37 31 1 5987435 5987435 5987435 5987435.0000
+select /*! SQL_SMALL_RESULT */ companynr,t2nr,count(price),sum(price),min(price),max(price),avg(price) from t3 where companynr = 37 group by companynr,t2nr limit 10;
companynr t2nr count(price) sum(price) min(price) max(price) avg(price)
37 1 1 5987435 5987435 5987435 5987435.0000
37 2 1 28357832 28357832 28357832 28357832.0000
@@ -1304,6 +2676,7 @@ companynr t2nr count(price) sum(price) min(price) max(price) avg(price)
37 22 1 28357832 28357832 28357832 28357832.0000
37 23 1 39654943 39654943 39654943 39654943.0000
37 31 1 5987435 5987435 5987435 5987435.0000
+select companynr,count(price),sum(price),min(price),max(price),avg(price) from t3 group by companynr ;
companynr count(price) sum(price) min(price) max(price) avg(price)
37 12543 309394878010 5987435 39654943 24666736.6667
78 8362 414611089292 726498 98439034 49582766.0000
@@ -1312,6 +2685,7 @@ companynr count(price) sum(price) min(price) max(price) avg(price)
311 4181 979599938 234298 234298 234298.0000
447 4181 9929180954 2374834 2374834 2374834.0000
512 4181 3288532102 786542 786542 786542.0000
+select distinct mod(companynr,10) from t4 group by companynr;
mod(companynr,10)
0
9
@@ -1322,10 +2696,13 @@ mod(companynr,10)
3
8
5
+select distinct 1 from t4 group by companynr;
1
1
+select count(distinct fld1) from t2;
count(distinct fld1)
1199
+select companynr,count(distinct fld1) from t2 group by companynr;
companynr count(distinct fld1)
00 82
29 95
@@ -1339,6 +2716,7 @@ companynr count(distinct fld1)
58 23
65 10
68 12
+select companynr,count(*) from t2 group by companynr;
companynr count(*)
00 82
29 95
@@ -1352,6 +2730,7 @@ companynr count(*)
58 23
65 10
68 12
+select companynr,count(distinct concat(fld1,repeat(65,1000))) from t2 group by companynr;
companynr count(distinct concat(fld1,repeat(65,1000)))
00 82
29 95
@@ -1365,6 +2744,7 @@ companynr count(distinct concat(fld1,repeat(65,1000)))
58 23
65 10
68 12
+select companynr,count(distinct concat(fld1,repeat(65,200))) from t2 group by companynr;
companynr count(distinct concat(fld1,repeat(65,200)))
00 82
29 95
@@ -1378,6 +2758,7 @@ companynr count(distinct concat(fld1,repeat(65,200)))
58 23
65 10
68 12
+select companynr,count(distinct floor(fld1/100)) from t2 group by companynr;
companynr count(distinct floor(fld1/100))
00 47
29 35
@@ -1391,6 +2772,7 @@ companynr count(distinct floor(fld1/100))
58 1
65 1
68 1
+select companynr,count(distinct concat(repeat(65,1000),floor(fld1/100))) from t2 group by companynr;
companynr count(distinct concat(repeat(65,1000),floor(fld1/100)))
00 47
29 35
@@ -1404,16 +2786,22 @@ companynr count(distinct concat(repeat(65,1000),floor(fld1/100)))
58 1
65 1
68 1
+select sum(fld1),fld3 from t2 where fld3="Romans" group by fld1 limit 10;
sum(fld1) fld3
11402 Romans
+select name,count(*) from t3 where name='cloakroom' group by name;
name count(*)
cloakroom 4181
+select name,count(*) from t3 where name='cloakroom' and price>10 group by name;
name count(*)
cloakroom 4181
+select count(*) from t3 where name='cloakroom' and price2=823742;
count(*)
4181
+select name,count(*) from t3 where name='cloakroom' and price2=823742 group by name;
name count(*)
cloakroom 4181
+select name,count(*) from t3 where name >= "extramarital" and price <= 39654943 group by name;
name count(*)
extramarital 4181
gazer 4181
@@ -1422,8 +2810,10 @@ Iranizes 4181
spates 4181
tucked 4181
violinist 4181
+select t2.fld3,count(*) from t2,t3 where t2.fld1=158402 and t3.name=t2.fld3 group by t3.name;
fld3 count(*)
spates 4181
+select companynr|0,companyname from t4 group by 1;
companynr|0 companyname
0 Unknown
29 company 1
@@ -1437,6 +2827,7 @@ companynr|0 companyname
58 company 8
65 company 9
68 company 10
+select t2.companynr,companyname,count(*) from t2,t4 where t2.companynr=t4.companynr group by t2.companynr order by companyname;
companynr companyname count(*)
29 company 1 95
68 company 10 12
@@ -1450,10 +2841,13 @@ companynr companyname count(*)
58 company 8 23
65 company 9 10
00 Unknown 82
+select t2.fld1,count(*) from t2,t3 where t2.fld1=158402 and t3.name=t2.fld3 group by t3.name;
fld1 count(*)
158402 4181
+select sum(Period)/count(*) from t1;
sum(Period)/count(*)
9410.00
+select companynr,count(price) as "count",sum(price) as "sum" ,abs(sum(price)/count(price)-avg(price)) as "diff",(0+count(price))*companynr as func from t3 group by companynr;
companynr count sum diff func
37 12543 309394878010 0.0000 464091
78 8362 414611089292 0.0000 652236
@@ -1462,8 +2856,10 @@ companynr count sum diff func
311 4181 979599938 0.0000 1300291
447 4181 9929180954 0.0000 1868907
512 4181 3288532102 0.0000 2140672
+select companynr,sum(price)/count(price) as avg from t3 group by companynr having avg > 70000000 order by avg;
companynr avg
154 983543950.00
+select companynr,count(*) from t2 group by companynr order by 2 desc;
companynr count(*)
37 588
36 215
@@ -1477,6 +2873,7 @@ companynr count(*)
50 11
65 10
53 4
+select companynr,count(*) from t2 where companynr > 40 group by companynr order by 2 desc;
companynr count(*)
41 52
58 23
@@ -1484,6 +2881,7 @@ companynr count(*)
50 11
65 10
53 4
+select t2.fld4,t2.fld1,count(price),sum(price),min(price),max(price),avg(price) from t3,t2 where t3.companynr = 37 and t2.fld1 = t3.t2nr group by fld1,t2.fld4;
fld4 fld1 count(price) sum(price) min(price) max(price) avg(price)
teethe 000001 1 5987435 5987435 5987435 5987435.0000
dreaded 011401 1 5987435 5987435 5987435 5987435.0000
@@ -1572,6 +2970,7 @@ partridges 038103 1 39654943 39654943 39654943 39654943.0000
recruited 038201 1 5987435 5987435 5987435 5987435.0000
dimensions 038202 1 28357832 28357832 28357832 28357832.0000
Chicana 038203 1 39654943 39654943 39654943 39654943.0000
+select t3.companynr,fld3,sum(price) from t3,t2 where t2.fld1 = t3.t2nr and t3.companynr = 512 group by companynr,fld3;
companynr fld3 sum(price)
512 boat 786542
512 capably 786542
@@ -1583,11 +2982,13 @@ companynr fld3 sum(price)
512 Micronesia 786542
512 Miles 786542
512 skies 786542
+select t2.companynr,count(*),min(fld3),max(fld3),sum(price),avg(price) from t2,t3 where t3.companynr >= 30 and t3.companynr <= 58 and t3.t2nr = t2.fld1 and 1+1=2 group by t2.companynr;
companynr count(*) min(fld3) max(fld3) sum(price) avg(price)
00 1 Omaha Omaha 5987435 5987435.0000
36 1 dubbed dubbed 28357832 28357832.0000
37 83 Abraham Wotan 1908978016 22999735.1325
50 2 scribbled tapestry 68012775 34006387.5000
+select t3.companynr+0,t3.t2nr,fld3,sum(price) from t3,t2 where t2.fld1 = t3.t2nr and t3.companynr = 37 group by 1,t3.t2nr,fld3,fld3,fld3,fld3,fld3 order by fld1;
t3.companynr+0 t2nr fld3 sum(price)
37 1 Omaha 5987435
37 11401 breaking 5987435
@@ -1676,32 +3077,41 @@ t3.companynr+0 t2nr fld3 sum(price)
37 38201 resumes 5987435
37 38202 analyzable 28357832
37 38203 terminator 39654943
+select sum(price) from t3,t2 where t2.fld1 = t3.t2nr and t3.companynr = 512 and t3.t2nr = 38008 and t2.fld1 = 38008 or t2.fld1= t3.t2nr and t3.t2nr = 38008 and t2.fld1 = 38008;
sum(price)
234298
+select t2.fld1,sum(price) from t3,t2 where t2.fld1 = t3.t2nr and t3.companynr = 512 and t3.t2nr = 38008 and t2.fld1 = 38008 or t2.fld1 = t3.t2nr and t3.t2nr = 38008 and t2.fld1 = 38008 or t3.t2nr = t2.fld1 and t2.fld1 = 38008 group by t2.fld1;
fld1 sum(price)
038008 234298
+explain select fld3 from t2 where 1>2 or 2>3;
Comment
Impossible WHERE
+explain select fld3 from t2 where fld1=fld1;
table type possible_keys key key_len ref rows Extra
t2 ALL NULL NULL NULL NULL 1199
+select companynr,fld1 from t2 HAVING fld1=250501 or fld1=250502;
companynr fld1
34 250501
34 250502
+select companynr,fld1 from t2 WHERE fld1>=250501 HAVING fld1<=250502;
companynr fld1
34 250501
34 250502
+select companynr,count(*) as count,sum(fld1) as sum from t2 group by companynr having count > 40 and sum/count >= 120000;
companynr count sum
00 82 10355753
29 95 14473298
34 70 17788966
37 588 83602098
41 52 12816335
+select companynr from t2 group by companynr having count(*) > 40 and sum(fld1)/count(*) >= 120000 ;
companynr
00
29
34
37
41
+select t2.companynr,companyname,count(*) from t2,t4 where t2.companynr=t4.companynr group by companyname having t2.companynr >= 40;
companynr companyname count(*)
68 company 10 12
50 company 11 11
@@ -1710,26 +3120,37 @@ companynr companyname count(*)
53 company 7 4
58 company 8 23
65 company 9 10
+select count(*) from t2;
count(*)
1199
+select count(*) from t2 where fld1 < 098024;
count(*)
387
+select min(fld1) from t2 where fld1>= 098024;
min(fld1)
98024
+select max(fld1) from t2 where fld1>= 098024;
max(fld1)
1232609
+select count(*) from t3 where price2=76234234;
count(*)
4181
+select count(*) from t3 where companynr=512 and price2=76234234;
count(*)
4181
+explain select min(fld1),max(fld1),count(*) from t2;
Comment
Select tables optimized away
+select min(fld1),max(fld1),count(*) from t2;
min(fld1) max(fld1) count(*)
0 1232609 1199
+select min(t2nr),max(t2nr) from t3 where t2nr=2115 and price2=823742;
min(t2nr) max(t2nr)
2115 2115
+select count(*),min(t2nr),max(t2nr) from t3 where name='spates' and companynr=78;
count(*) min(t2nr) max(t2nr)
4181 4 41804
+select t2nr,count(*) from t3 where name='gems' group by t2nr limit 20;
t2nr count(*)
9 1
19 1
@@ -1751,29 +3172,41 @@ t2nr count(*)
179 1
189 1
199 1
+select max(t2nr) from t3 where price=983543950;
max(t2nr)
41807
+select t1.period from t3 = t1 limit 1;
period
1001
+select t1.period from t1 as t1 limit 1;
period
9410
+select t1.period as "Nuvarande period" from t1 as t1 limit 1;
Nuvarande period
9410
+select period as ok_period from t1 limit 1;
ok_period
9410
+select period as ok_period from t1 group by ok_period limit 1;
ok_period
9410
+select 1+1 as summa from t1 group by summa limit 1;
summa
2
+select period as "Nuvarande period" from t1 group by "Nuvarande period" limit 1;
Nuvarande period
9410
+show tables;
Tables_in_test
t1
t2
t3
t4
+show tables from test like "s%";
Tables_in_test (s%)
+show tables from test like "t?";
Tables_in_test (t?)
+show full columns from t2;
Field Type Null Key Default Extra Privileges
auto int(11) PRI NULL auto_increment select,insert,update,references
fld1 int(6) unsigned zerofill UNI 000000 select,insert,update,references
@@ -1782,14 +3215,20 @@ fld3 char(30) MUL select,insert,update,references
fld4 char(35) select,insert,update,references
fld5 char(35) select,insert,update,references
fld6 char(4) select,insert,update,references
+show full columns from t2 from test like 'f%';
Field Type Null Key Default Extra Privileges
fld1 int(6) unsigned zerofill UNI 000000 select,insert,update,references
fld3 char(30) MUL select,insert,update,references
fld4 char(35) select,insert,update,references
fld5 char(35) select,insert,update,references
fld6 char(4) select,insert,update,references
+show full columns from t2 from test like 's%';
Field Type Null Key Default Extra Privileges
-Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Comment
-t2 0 PRIMARY 1 auto A 1199 NULL NULL
-t2 0 fld1 1 fld1 A 1199 NULL NULL
-t2 1 fld3 1 fld3 A NULL NULL NULL
+show keys from t2;
+Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
+t2 0 PRIMARY 1 auto A 1199 NULL NULL BTREE
+t2 0 fld1 1 fld1 A 1199 NULL NULL BTREE
+t2 1 fld3 1 fld3 A NULL NULL NULL BTREE
+DO 1;
+DO benchmark(100,1+1),1,1;
+drop table t4, t3,t2, t1;
diff --git a/mysql-test/r/select_found.result b/mysql-test/r/select_found.result
new file mode 100644
index 00000000000..3a84c3e52da
--- /dev/null
+++ b/mysql-test/r/select_found.result
@@ -0,0 +1,64 @@
+drop table if exists t1;
+create table t1 (a int not null auto_increment, b int not null, primary key(a));
+insert into t1 (b) values (2),(3),(5),(5),(5),(6),(7),(9);
+select SQL_CALC_FOUND_ROWS * from t1;
+a b
+1 2
+2 3
+3 5
+4 5
+5 5
+6 6
+7 7
+8 9
+select found_rows();
+FOUND_ROWS()
+8
+select SQL_CALC_FOUND_ROWS * from t1 limit 1;
+a b
+1 2
+select found_rows();
+FOUND_ROWS()
+8
+select SQL_CALC_FOUND_ROWS * from t1 order by b desc limit 1;
+a b
+8 9
+select found_rows();
+FOUND_ROWS()
+8
+select SQL_CALC_FOUND_ROWS distinct b from t1 limit 1;
+b
+2
+select found_rows();
+FOUND_ROWS()
+6
+select SQL_CALC_FOUND_ROWS b,count(*) as c from t1 group by b order by c desc limit 1;
+b c
+5 3
+select found_rows();
+FOUND_ROWS()
+6
+select SQL_CALC_FOUND_ROWS * from t1 left join t1 as t2 on (t1.b=t2.a) limit 2,1;
+a b a b
+3 5 5 5
+select found_rows();
+FOUND_ROWS()
+8
+drop table t1;
+create table t1 (a int not null primary key);
+insert into t1 values (1),(2),(3),(4),(5);
+select sql_calc_found_rows a from t1 where a in (1,2,3) order by a desc limit 0,2;
+a
+3
+2
+select FOUND_ROWS();
+FOUND_ROWS()
+3
+select sql_calc_found_rows a from t1 where a in (1,2,3) order by a+2 desc limit 0,2;
+a
+3
+2
+select FOUND_ROWS();
+FOUND_ROWS()
+3
+drop table t1;
diff --git a/mysql-test/r/select_safe.result b/mysql-test/r/select_safe.result
index 1111ba00cd9..e225a0e3995 100644
--- a/mysql-test/r/select_safe.result
+++ b/mysql-test/r/select_safe.result
@@ -1,10 +1,39 @@
+drop table if exists t1;
+SET SQL_SAFE_UPDATES=1,SQL_SELECT_LIMIT=4, SQL_MAX_JOIN_SIZE=9;
+create table t1 (a int primary key, b char(20));
+insert into t1 values(1,"test");
+SELECT SQL_BUFFER_RESULT * from t1;
a b
1 test
+update t1 set b="a" where a=1;
+delete from t1 where a=1;
+insert into t1 values(1,"test"),(2,"test2");
+SELECT SQL_BUFFER_RESULT * from t1;
a b
1 test
2 test2
+update t1 set b="a" where a=1;
+select 1 from t1,t1 as t2,t1 as t3,t1 as t4;
1
1
1
1
1
+update t1 set b="a";
+You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column
+update t1 set b="a" where b="test";
+You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column
+delete from t1;
+You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column
+delete from t1 where b="test";
+You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column
+delete from t1 where a+0=1;
+You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column
+select 1 from t1,t1 as t2,t1 as t3,t1 as t4,t1 as t5;
+The SELECT would examine too many records and probably take a very long time. Check your WHERE and use SET OPTION SQL_BIG_SELECTS=1 if the SELECT is ok
+update t1 set b="a" limit 1;
+update t1 set b="a" where b="b" limit 2;
+delete from t1 where b="test" limit 1;
+delete from t1 where a+0=1 limit 2;
+drop table t1;
+SET SQL_SAFE_UPDATES=0,SQL_SELECT_LIMIT=DEFAULT, SQL_MAX_JOIN_SIZE=DEFAULT;
diff --git a/mysql-test/r/show_check.result b/mysql-test/r/show_check.result
index 099ea2fa109..2530e5b09fb 100644
--- a/mysql-test/r/show_check.result
+++ b/mysql-test/r/show_check.result
@@ -1,92 +1,145 @@
-Table Op Msg_type Msg_text
-test.t1 optimize status OK
-Table Op Msg_type Msg_text
-test.t1 check status OK
-test.t2 check error The handler for the table doesn't support check/repair
-Table Op Msg_type Msg_text
-test.t1 repair status OK
-test.t2 repair error The handler for the table doesn't support check/repair
-Table Op Msg_type Msg_text
-test.t2 check error The handler for the table doesn't support check/repair
-test.t1 check status OK
-Table Op Msg_type Msg_text
-test.t2 check error Table 't2' was not locked with LOCK TABLES
-test.t1 check status OK
-Field Type Null Key Default Extra
-a int(11) PRI 0
-b int(11) MUL 0
-c int(11) 0
-Field Type Null Key Default Extra Privileges
-a int(11) PRI 0 select,insert,update,references
-b int(11) MUL 0 select,insert,update,references
-c int(11) 0 select,insert,update,references
-Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Comment
-t1 0 PRIMARY 1 a A 4 NULL NULL
-t1 1 b 1 b A 1 NULL NULL
-t1 1 b 2 c A 4 NULL NULL
+drop table if exists t1,t2;
+create table t1 (a int not null primary key, b int not null,c int not null, key(b,c));
+insert into t1 values (1,2,2),(2,2,3),(3,2,4),(4,2,4);
+check table t1 type=fast;
Table Op Msg_type Msg_text
test.t1 check status Table is already up to date
+check table t1 type=fast;
Table Op Msg_type Msg_text
test.t1 check status Table is already up to date
+check table t1 type=changed;
Table Op Msg_type Msg_text
test.t1 check status OK
+insert into t1 values (5,5,5);
+check table t1 type=changed;
Table Op Msg_type Msg_text
test.t1 check status OK
+check table t1 type=medium;
Table Op Msg_type Msg_text
test.t1 check status OK
+check table t1 type=extended;
Table Op Msg_type Msg_text
test.t1 check status OK
-Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Comment
-t1 0 PRIMARY 1 a A 5 NULL NULL
-t1 1 b 1 b A 1 NULL NULL
-t1 1 b 2 c A 5 NULL NULL
+show index from t1;
+Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
+t1 0 PRIMARY 1 a A 5 NULL NULL BTREE
+t1 1 b 1 b A 1 NULL NULL BTREE
+t1 1 b 2 c A 5 NULL NULL BTREE
+insert into t1 values (5,5,5);
+Duplicate entry '5' for key 1
+optimize table t1;
Table Op Msg_type Msg_text
test.t1 optimize status OK
+optimize table t1;
Table Op Msg_type Msg_text
test.t1 optimize status Table is already up to date
+drop table t1;
+show variables like "wait_timeout%";
Variable_name Value
wait_timeout 28800
+show variables like "this_doesn't_exists%";
Variable_name Value
+show table status from test like "this_doesn't_exists%";
Name Type Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Create_options Comment
+show databases;
Database
mysql
test
+show databases like "test%";
Database (test%)
test
+create table t1 (f1 int not null, f2 int not null, f3 int not null, f4 int not null, primary key(f1,f2,f3,f4));
+insert into t1 values (1,1,1,0),(1,1,2,0),(1,1,3,0),(1,2,1,0),(1,2,2,0),(1,2,3,0),(1,3,1,0),(1,3,2,0),(1,3,3,0),(1,1,1,1),(1,1,2,1),(1,1,3,1),(1,2,1,1),(1,2,2,1),(1,2,3,1),(1,3,1,1),(1,3,2,1),(1,3,3,1);
+analyze table t1;
Table Op Msg_type Msg_text
test.t1 analyze status OK
-Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Comment
-t1 0 PRIMARY 1 f1 A 1 NULL NULL
-t1 0 PRIMARY 2 f2 A 3 NULL NULL
-t1 0 PRIMARY 3 f3 A 9 NULL NULL
-t1 0 PRIMARY 4 f4 A 18 NULL NULL
+show index from t1;
+Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
+t1 0 PRIMARY 1 f1 A 1 NULL NULL BTREE
+t1 0 PRIMARY 2 f2 A 3 NULL NULL BTREE
+t1 0 PRIMARY 3 f3 A 9 NULL NULL BTREE
+t1 0 PRIMARY 4 f4 A 18 NULL NULL BTREE
+repair table t1;
Table Op Msg_type Msg_text
test.t1 repair status OK
-Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Comment
-t1 0 PRIMARY 1 f1 A 1 NULL NULL
-t1 0 PRIMARY 2 f2 A 3 NULL NULL
-t1 0 PRIMARY 3 f3 A 9 NULL NULL
-t1 0 PRIMARY 4 f4 A 18 NULL NULL
+show index from t1;
+Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
+t1 0 PRIMARY 1 f1 A 1 NULL NULL BTREE
+t1 0 PRIMARY 2 f2 A 3 NULL NULL BTREE
+t1 0 PRIMARY 3 f3 A 9 NULL NULL BTREE
+t1 0 PRIMARY 4 f4 A 18 NULL NULL BTREE
+drop table t1;
+create temporary table t1 (a int not null);
+show create table t1;
Table Create Table
t1 CREATE TEMPORARY TABLE `t1` (
`a` int(11) NOT NULL default '0'
) TYPE=MyISAM
+alter table t1 rename t2;
+show create table t2;
Table Create Table
t2 CREATE TEMPORARY TABLE `t2` (
`a` int(11) NOT NULL default '0'
) TYPE=MyISAM
+drop table t2;
+create table t1 (
+test_set set( 'val1', 'val2', 'val3' ) not null default '',
+name char(20) default 'O''Brien'
+ ) comment = 'it\'s a table' ;
+show create table t1 ;
Table Create Table
t1 CREATE TABLE `t1` (
`test_set` set('val1','val2','val3') NOT NULL default '',
`name` char(20) default 'O''Brien'
) TYPE=MyISAM COMMENT='it''s a table'
+drop table t1;
+create table t1 (a int not null, unique aa (a));
+show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` int(11) NOT NULL default '0',
UNIQUE KEY `aa` (`a`)
) TYPE=MyISAM
+drop table t1;
+create table t1 (a int not null, primary key (a));
+show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` int(11) NOT NULL default '0',
PRIMARY KEY (`a`)
) TYPE=MyISAM
+drop table t1;
+flush tables;
+show open tables;
+Database Table In_use Name_locked
+create table t1(n int);
+insert into t1 values (1);
+show open tables;
+Database Table In_use Name_locked
+test t1 0 0
+drop table t1;
+create table t1 (a int not null, b VARCHAR(10), INDEX (b) ) AVG_ROW_LENGTH=10 CHECKSUM=1 COMMENT="test" TYPE=MYISAM MIN_ROWS=10 MAX_ROWS=100 PACK_KEYS=1 DELAY_KEY_WRITE=1 ROW_FORMAT=fixed;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) NOT NULL default '0',
+ `b` char(10) default NULL,
+ KEY `b` (`b`)
+) TYPE=MyISAM MIN_ROWS=10 MAX_ROWS=100 AVG_ROW_LENGTH=10 PACK_KEYS=1 CHECKSUM=1 DELAY_KEY_WRITE=1 ROW_FORMAT=FIXED COMMENT='test'
+alter table t1 MAX_ROWS=200 ROW_FORMAT=dynamic PACK_KEYS=0;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) NOT NULL default '0',
+ `b` varchar(10) default NULL,
+ KEY `b` (`b`)
+) TYPE=MyISAM MIN_ROWS=10 MAX_ROWS=200 AVG_ROW_LENGTH=10 PACK_KEYS=0 CHECKSUM=1 DELAY_KEY_WRITE=1 ROW_FORMAT=DYNAMIC COMMENT='test'
+ALTER TABLE t1 AVG_ROW_LENGTH=0 CHECKSUM=0 COMMENT="" MIN_ROWS=0 MAX_ROWS=0 PACK_KEYS=DEFAULT DELAY_KEY_WRITE=0 ROW_FORMAT=default;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) NOT NULL default '0',
+ `b` varchar(10) default NULL,
+ KEY `b` (`b`)
+) TYPE=MyISAM
+drop table t1;
diff --git a/mysql-test/r/slave-running.result b/mysql-test/r/slave-running.result
index 794d0935ef4..3699390a7d3 100644
--- a/mysql-test/r/slave-running.result
+++ b/mysql-test/r/slave-running.result
@@ -1,2 +1,3 @@
+show status like 'Slave_running';
Variable_name Value
Slave_running ON
diff --git a/mysql-test/r/slave-stopped.result b/mysql-test/r/slave-stopped.result
index 29ab2ac73e4..90b416b7bd7 100644
--- a/mysql-test/r/slave-stopped.result
+++ b/mysql-test/r/slave-stopped.result
@@ -1,2 +1,3 @@
+show status like 'Slave_running';
Variable_name Value
Slave_running OFF
diff --git a/mysql-test/r/status.result b/mysql-test/r/status.result
index 8f3ad3e0d59..3ef6cec32b3 100644
--- a/mysql-test/r/status.result
+++ b/mysql-test/r/status.result
@@ -1,6 +1,19 @@
+flush status;
+show status like 'Table_lock%';
Variable_name Value
Table_locks_immediate 0
Table_locks_waited 0
+SET SQL_LOG_BIN=0;
+drop table if exists t1;
+create table t1(n int) type=myisam;
+insert into t1 values(1);
+lock tables t1 read;
+unlock tables;
+lock tables t1 read;
+update t1 set n = 3;
+unlock tables;
+show status like 'Table_lock%';
Variable_name Value
Table_locks_immediate 3
Table_locks_waited 1
+drop table t1;
diff --git a/mysql-test/r/symlink.result b/mysql-test/r/symlink.result
new file mode 100644
index 00000000000..5626bc0fe11
--- /dev/null
+++ b/mysql-test/r/symlink.result
@@ -0,0 +1,65 @@
+drop table if exists t1,t2,t7,t8,t9;
+create table t1 (a int not null auto_increment, b char(16) not null, primary key (a));
+create table t2 (a int not null auto_increment, b char(16) not null, primary key (a));
+insert into t1 (b) values ("test"),("test1"),("test2"),("test3");
+insert into t2 (b) select b from t1;
+insert into t1 (b) select b from t2;
+insert into t2 (b) select b from t1;
+insert into t1 (b) select b from t2;
+insert into t2 (b) select b from t1;
+insert into t1 (b) select b from t2;
+insert into t2 (b) select b from t1;
+insert into t1 (b) select b from t2;
+insert into t2 (b) select b from t1;
+insert into t1 (b) select b from t2;
+insert into t2 (b) select b from t1;
+insert into t1 (b) select b from t2;
+insert into t2 (b) select b from t1;
+insert into t1 (b) select b from t2;
+insert into t2 (b) select b from t1;
+insert into t1 (b) select b from t2;
+insert into t2 (b) select b from t1;
+insert into t1 (b) select b from t2;
+drop table t2;
+insert into t9 select * from t1;
+check table t9;
+Table Op Msg_type Msg_text
+test.t9 check status OK
+optimize table t9;
+Table Op Msg_type Msg_text
+test.t9 optimize status OK
+repair table t9;
+Table Op Msg_type Msg_text
+test.t9 repair status OK
+alter table t9 add column c int not null;
+show create table t9;
+Table Create Table
+t9 CREATE TABLE `t9` (
+ `a` int(11) NOT NULL auto_increment,
+ `b` char(16) NOT NULL default '',
+ `c` int(11) NOT NULL default '0',
+ PRIMARY KEY (`a`)
+) TYPE=MyISAM
+alter table t9 rename t8, add column d int not null;
+alter table t8 rename t7;
+rename table t7 to t9;
+drop table t1;
+Got one of the listed errors
+Got one of the listed errors
+Got one of the listed errors
+Got one of the listed errors
+Got one of the listed errors
+alter table t9 rename test_mysqltest.t9;
+select count(*) from test_mysqltest.t9;
+count(*)
+16724
+show create table test_mysqltest.t9;
+Table Create Table
+t9 CREATE TABLE `t9` (
+ `a` int(11) NOT NULL auto_increment,
+ `b` char(16) NOT NULL default '',
+ `c` int(11) NOT NULL default '0',
+ `d` int(11) NOT NULL default '0',
+ PRIMARY KEY (`a`)
+) TYPE=MyISAM
+drop database test_mysqltest;
diff --git a/mysql-test/r/tablelock.result b/mysql-test/r/tablelock.result
index 4fbeac979b1..2ffd8f928a9 100644
--- a/mysql-test/r/tablelock.result
+++ b/mysql-test/r/tablelock.result
@@ -1,12 +1,48 @@
+drop table if exists t1,t2;
+create table t1 ( n int auto_increment primary key);
+lock tables t1 write;
+insert into t1 values(NULL);
+unlock tables;
+check table t1;
Table Op Msg_type Msg_text
test.t1 check status OK
+lock tables t1 write, t1 as t0 read;
+insert into t1 values(NULL);
+unlock tables;
+check table t1;
Table Op Msg_type Msg_text
test.t1 check status OK
+lock tables t1 write, t1 as t0 read, t1 as t2 read;
+insert into t1 values(NULL);
+unlock tables;
+check table t1;
Table Op Msg_type Msg_text
test.t1 check status OK
+lock tables t1 write, t1 as t0 write, t1 as t2 read;
+insert into t1 values(NULL);
+unlock tables;
+check table t1;
Table Op Msg_type Msg_text
test.t1 check status OK
+lock tables t1 write, t1 as t0 write, t1 as t2 read, t1 as t3 read;
+insert into t1 values(NULL);
+unlock tables;
+check table t1;
Table Op Msg_type Msg_text
test.t1 check status OK
+lock tables t1 write, t1 as t0 write, t1 as t2 write;
+insert into t1 values(NULL);
+unlock tables;
+check table t1;
Table Op Msg_type Msg_text
test.t1 check status OK
+drop table t1;
+CREATE TABLE t1 (a int);
+CREATE TABLE t2 (a int);
+lock tables t1 write,t1 as b write, t2 write, t2 as c read;
+drop table t1,t2;
+CREATE TABLE t1 (a int);
+CREATE TABLE t2 (a int);
+lock tables t1 write,t1 as b write, t2 write, t2 as c read;
+drop table t2,t1;
+unlock tables;
diff --git a/mysql-test/r/temp_table.result b/mysql-test/r/temp_table.result
index 12e76bba3f7..84a00bfea34 100644
--- a/mysql-test/r/temp_table.result
+++ b/mysql-test/r/temp_table.result
@@ -1,30 +1,74 @@
+drop table if exists t1,t2;
+CREATE TABLE t1 (c int not null, d char (10) not null);
+insert into t1 values(1,""),(2,"a"),(3,"b");
+CREATE TEMPORARY TABLE t1 (a int not null, b char (10) not null);
+insert into t1 values(4,"e"),(5,"f"),(6,"g");
+alter table t1 rename t2;
+select * from t1;
c d
1
2 a
3 b
+select * from t2;
a b
4 e
5 f
6 g
+CREATE TABLE t2 (x int not null, y int not null);
+alter table t2 rename t1;
+select * from t1;
a b
4 e
5 f
6 g
+create TEMPORARY TABLE t2 type=heap select * from t1;
+create TEMPORARY TABLE IF NOT EXISTS t2 (a int) type=heap;
+CREATE TEMPORARY TABLE t1 (a int not null, b char (10) not null);
+Table 't1' already exists
+ALTER TABLE t1 RENAME t2;
+Table 't2' already exists
+select * from t2;
a b
4 e
5 f
6 g
+alter table t2 add primary key (a,b);
+drop table t1,t2;
+select * from t1;
c d
1
2 a
3 b
+drop table t2;
+create temporary table t1 select *,2 as "e" from t1;
+select * from t1;
c d e
1 2
2 a 2
3 b 2
+drop table t1;
+drop table t1;
+drop table if exists t1;
+CREATE TABLE t1 (pkCrash INTEGER PRIMARY KEY,strCrash VARCHAR(255));
+INSERT INTO t1 ( pkCrash, strCrash ) VALUES ( 1, '1');
+SELECT CONCAT_WS(pkCrash, strCrash) FROM t1;
CONCAT_WS(pkCrash, strCrash)
1
+drop table t1;
+create temporary table t1 select 1 as 'x';
+drop table t1;
+CREATE TABLE t1 (x INT);
+INSERT INTO t1 VALUES (1), (2), (3);
+CREATE TEMPORARY TABLE tmp SELECT *, NULL FROM t1;
+drop table t1;
+create temporary table t1 (id int(10) not null unique);
+create temporary table t2 (id int(10) not null primary key,
+val int(10) not null);
+insert into t1 values (1),(2),(4);
+insert into t2 values (1,1),(2,1),(3,1),(4,2);
+select one.id, two.val, elt(two.val,'one','two') from t1 one, t2 two where two.id=one.id order by one.id;
id val elt(two.val,'one','two')
1 1 one
2 1 one
4 2 two
+drop table t1,t2;
diff --git a/mysql-test/r/truncate.result b/mysql-test/r/truncate.result
index 716b38c57c7..79471611638 100644
--- a/mysql-test/r/truncate.result
+++ b/mysql-test/r/truncate.result
@@ -1,4 +1,16 @@
+create table t1 (a integer, b integer,c1 CHAR(10));
+insert into t1 (a) values (1),(2);
+truncate table t1;
+select count(*) from t1;
count(*)
0
+insert into t1 values(1,2,"test");
+select count(*) from t1;
count(*)
1
+delete from t1;
+select * from t1;
+a b c1
+drop table t1;
+select count(*) from t1;
+Table 'test.t1' doesn't exist
diff --git a/mysql-test/r/type_blob.result b/mysql-test/r/type_blob.result
index bc80ba38452..2047eed6227 100644
--- a/mysql-test/r/type_blob.result
+++ b/mysql-test/r/type_blob.result
@@ -1,5 +1,12 @@
+drop table if exists t1,t2,t3,t4,t5,t6,t7;
+create table t1 (nr int(5) not null auto_increment,b blob,str char(10), primary key (nr));
+insert into t1 values (null,"a","A");
+insert into t1 values (null,"bbb","BBB");
+insert into t1 values (null,"ccc","CCC");
+select last_insert_id();
last_insert_id()
3
+select * from t1,t1 as t2;
nr b str nr b str
1 a A 1 a A
2 bbb BBB 1 a A
@@ -10,54 +17,88 @@ nr b str nr b str
1 a A 3 ccc CCC
2 bbb BBB 3 ccc CCC
3 ccc CCC 3 ccc CCC
+drop table t1;
+create table t1 (a text);
+insert into t1 values ('where');
+update t1 set a='Where';
+select * from t1;
a
Where
+drop table t1;
+create table t1 (t text,c char(10),b blob, d char(10) binary);
+insert into t1 values (NULL,NULL,NULL,NULL);
+insert into t1 values ("","","","");
+insert into t1 values ("hello","hello","hello","hello");
+insert into t1 values ("HELLO","HELLO","HELLO","HELLO");
+insert into t1 values ("HELLO MY","HELLO MY","HELLO MY","HELLO MY");
+insert into t1 values ("a","a","a","a");
+insert into t1 values (1,1,1,1);
+insert into t1 values (NULL,NULL,NULL,NULL);
+update t1 set c="",b=null where c="1";
+lock tables t1 READ;
+show full fields from t1;
Field Type Null Key Default Extra Privileges
t text YES NULL select,insert,update,references
c varchar(10) YES NULL select,insert,update,references
b blob YES NULL select,insert,update,references
d varchar(10) binary YES NULL select,insert,update,references
+lock tables t1 WRITE;
+show full fields from t1;
Field Type Null Key Default Extra Privileges
t text YES NULL select,insert,update,references
c varchar(10) YES NULL select,insert,update,references
b blob YES NULL select,insert,update,references
d varchar(10) binary YES NULL select,insert,update,references
+unlock tables;
+select t from t1 where t like "hello";
t
hello
HELLO
+select c from t1 where c like "hello";
c
hello
HELLO
+select b from t1 where b like "hello";
b
hello
+select d from t1 where d like "hello";
d
hello
+select c from t1 having c like "hello";
c
hello
HELLO
+select d from t1 having d like "hello";
d
hello
+select t from t1 where t like "%HELLO%";
t
hello
HELLO
HELLO MY
+select c from t1 where c like "%HELLO%";
c
hello
HELLO
HELLO MY
+select b from t1 where b like "%HELLO%";
b
HELLO
HELLO MY
+select d from t1 where d like "%HELLO%";
d
HELLO
HELLO MY
+select c from t1 having c like "%HELLO%";
c
hello
HELLO
HELLO MY
+select d from t1 having d like "%HELLO%";
d
HELLO
HELLO MY
+select t from t1 order by t;
t
NULL
NULL
@@ -67,6 +108,7 @@ a
hello
HELLO
HELLO MY
+select c from t1 order by c;
c
NULL
NULL
@@ -76,6 +118,7 @@ a
hello
HELLO
HELLO MY
+select b from t1 order by b;
b
NULL
NULL
@@ -85,6 +128,7 @@ HELLO
HELLO MY
a
hello
+select d from t1 order by d;
d
NULL
NULL
@@ -94,6 +138,7 @@ HELLO
HELLO MY
a
hello
+select distinct t from t1;
t
NULL
@@ -101,6 +146,7 @@ hello
HELLO MY
a
1
+select distinct b from t1;
b
NULL
@@ -108,6 +154,7 @@ hello
HELLO
HELLO MY
a
+select distinct t from t1 order by t;
t
NULL
@@ -115,6 +162,7 @@ NULL
a
hello
HELLO MY
+select distinct b from t1 order by b;
b
NULL
@@ -122,6 +170,7 @@ HELLO
HELLO MY
a
hello
+select t from t1 group by t;
t
NULL
@@ -129,6 +178,7 @@ NULL
a
hello
HELLO MY
+select b from t1 group by b;
b
NULL
@@ -136,6 +186,8 @@ HELLO
HELLO MY
a
hello
+set option sql_big_tables=1;
+select distinct t from t1;
t
NULL
@@ -143,6 +195,7 @@ hello
HELLO MY
a
1
+select distinct b from t1;
b
NULL
@@ -150,6 +203,7 @@ hello
HELLO
HELLO MY
a
+select distinct t from t1 order by t;
t
NULL
@@ -157,6 +211,7 @@ NULL
a
hello
HELLO MY
+select distinct b from t1 order by b;
b
NULL
@@ -164,12 +219,14 @@ HELLO
HELLO MY
a
hello
+select distinct c from t1;
c
NULL
hello
HELLO MY
a
+select distinct d from t1;
d
NULL
@@ -178,12 +235,14 @@ HELLO
HELLO MY
a
1
+select distinct c from t1 order by c;
c
NULL
a
hello
HELLO MY
+select distinct d from t1 order by d;
d
NULL
@@ -192,12 +251,14 @@ HELLO
HELLO MY
a
hello
+select c from t1 group by c;
c
NULL
a
hello
HELLO MY
+select d from t1 group by d;
d
NULL
@@ -206,6 +267,8 @@ HELLO
HELLO MY
a
hello
+set option sql_big_tables=0;
+select distinct * from t1;
t c b d
NULL NULL NULL NULL
@@ -214,6 +277,7 @@ HELLO HELLO HELLO HELLO
HELLO MY HELLO MY HELLO MY HELLO MY
a a a a
1 NULL 1
+select t,count(*) from t1 group by t;
t count(*)
NULL 2
1
@@ -221,6 +285,7 @@ NULL 2
a 1
hello 2
HELLO MY 1
+select b,count(*) from t1 group by b;
b count(*)
NULL 3
1
@@ -228,12 +293,14 @@ HELLO 1
HELLO MY 1
a 1
hello 1
+select c,count(*) from t1 group by c;
c count(*)
NULL 2
2
a 1
hello 2
HELLO MY 1
+select d,count(*) from t1 group by d;
d count(*)
NULL 2
1
@@ -242,22 +309,142 @@ HELLO 1
HELLO MY 1
a 1
hello 1
+drop table t1;
+create table t1 (a text, key (a(300)));
+Incorrect sub part key. The used key part isn't a string, the used length is longer than the key part or the table handler doesn't support unique sub keys
+create table t1 (a text, key (a(255)));
+drop table t1;
+CREATE TABLE t1 (
+t1_id bigint(21) DEFAULT '0' NOT NULL auto_increment,
+_field_72 varchar(128) DEFAULT '' NOT NULL,
+_field_95 varchar(32),
+_field_115 tinyint(4) DEFAULT '0' NOT NULL,
+_field_122 tinyint(4) DEFAULT '0' NOT NULL,
+_field_126 tinyint(4),
+_field_134 tinyint(4),
+PRIMARY KEY (t1_id),
+UNIQUE _field_72 (_field_72),
+KEY _field_115 (_field_115),
+KEY _field_122 (_field_122)
+);
+INSERT INTO t1 VALUES (1,'admin','21232f297a57a5a743894a0e4a801fc3',0,1,NULL,NULL);
+INSERT INTO t1 VALUES (2,'hroberts','7415275a8c95952901e42b13a6b78566',0,1,NULL,NULL);
+INSERT INTO t1 VALUES (3,'guest','d41d8cd98f00b204e9800998ecf8427e',1,0,NULL,NULL);
+CREATE TABLE t2 (
+seq_0_id bigint(21) DEFAULT '0' NOT NULL,
+seq_1_id bigint(21) DEFAULT '0' NOT NULL,
+PRIMARY KEY (seq_0_id,seq_1_id)
+);
+INSERT INTO t2 VALUES (1,1);
+INSERT INTO t2 VALUES (2,1);
+INSERT INTO t2 VALUES (2,2);
+CREATE TABLE t3 (
+t3_id bigint(21) DEFAULT '0' NOT NULL auto_increment,
+_field_131 varchar(128),
+_field_133 tinyint(4) DEFAULT '0' NOT NULL,
+_field_135 datetime DEFAULT '0000-00-00 00:00:00' NOT NULL,
+_field_137 tinyint(4),
+_field_139 datetime DEFAULT '0000-00-00 00:00:00' NOT NULL,
+_field_140 blob,
+_field_142 tinyint(4) DEFAULT '0' NOT NULL,
+_field_145 tinyint(4) DEFAULT '0' NOT NULL,
+_field_148 tinyint(4) DEFAULT '0' NOT NULL,
+PRIMARY KEY (t3_id),
+KEY _field_133 (_field_133),
+KEY _field_135 (_field_135),
+KEY _field_139 (_field_139),
+KEY _field_142 (_field_142),
+KEY _field_145 (_field_145),
+KEY _field_148 (_field_148)
+);
+INSERT INTO t3 VALUES (1,'test job 1',0,'0000-00-00 00:00:00',0,'1999-02-25 22:43:32','test\r\njob\r\n1',0,0,0);
+INSERT INTO t3 VALUES (2,'test job 2',0,'0000-00-00 00:00:00',0,'1999-02-26 21:08:04','',0,0,0);
+CREATE TABLE t4 (
+seq_0_id bigint(21) DEFAULT '0' NOT NULL,
+seq_1_id bigint(21) DEFAULT '0' NOT NULL,
+PRIMARY KEY (seq_0_id,seq_1_id)
+);
+INSERT INTO t4 VALUES (1,1);
+INSERT INTO t4 VALUES (2,1);
+CREATE TABLE t5 (
+t5_id bigint(21) DEFAULT '0' NOT NULL auto_increment,
+_field_149 tinyint(4),
+_field_156 varchar(128) DEFAULT '' NOT NULL,
+_field_157 varchar(128) DEFAULT '' NOT NULL,
+_field_158 varchar(128) DEFAULT '' NOT NULL,
+_field_159 varchar(128) DEFAULT '' NOT NULL,
+_field_160 varchar(128) DEFAULT '' NOT NULL,
+_field_161 varchar(128) DEFAULT '' NOT NULL,
+PRIMARY KEY (t5_id),
+KEY _field_156 (_field_156),
+KEY _field_157 (_field_157),
+KEY _field_158 (_field_158),
+KEY _field_159 (_field_159),
+KEY _field_160 (_field_160),
+KEY _field_161 (_field_161)
+);
+INSERT INTO t5 VALUES (1,0,'tomato','','','','','');
+INSERT INTO t5 VALUES (2,0,'cilantro','','','','','');
+CREATE TABLE t6 (
+seq_0_id bigint(21) DEFAULT '0' NOT NULL,
+seq_1_id bigint(21) DEFAULT '0' NOT NULL,
+PRIMARY KEY (seq_0_id,seq_1_id)
+);
+INSERT INTO t6 VALUES (1,1);
+INSERT INTO t6 VALUES (1,2);
+INSERT INTO t6 VALUES (2,2);
+CREATE TABLE t7 (
+t7_id bigint(21) DEFAULT '0' NOT NULL auto_increment,
+_field_143 tinyint(4),
+_field_165 varchar(32),
+_field_166 smallint(6) DEFAULT '0' NOT NULL,
+PRIMARY KEY (t7_id),
+KEY _field_166 (_field_166)
+);
+INSERT INTO t7 VALUES (1,0,'High',1);
+INSERT INTO t7 VALUES (2,0,'Medium',2);
+INSERT INTO t7 VALUES (3,0,'Low',3);
+select replace(t3._field_140, "\r","^M"),t3_id,min(t3._field_131), min(t3._field_135), min(t3._field_139), min(t3._field_137), min(link_alias_142._field_165), min(link_alias_133._field_72), min(t3._field_145), min(link_alias_148._field_156), replace(min(t3._field_140), "\r","^M"),t3.t3_id from t3 left join t4 on t4.seq_0_id = t3.t3_id left join t7 link_alias_142 on t4.seq_1_id = link_alias_142.t7_id left join t6 on t6.seq_0_id = t3.t3_id left join t1 link_alias_133 on t6.seq_1_id = link_alias_133.t1_id left join t2 on t2.seq_0_id = t3.t3_id left join t5 link_alias_148 on t2.seq_1_id = link_alias_148.t5_id where t3.t3_id in (1) group by t3.t3_id order by link_alias_142._field_166, _field_139, link_alias_133._field_72, _field_135, link_alias_148._field_156;
replace(t3._field_140, "\r","^M") t3_id min(t3._field_131) min(t3._field_135) min(t3._field_139) min(t3._field_137) min(link_alias_142._field_165) min(link_alias_133._field_72) min(t3._field_145) min(link_alias_148._field_156) replace(min(t3._field_140), "\r","^M") t3_id
test^M
job^M
1 1 test job 1 0000-00-00 00:00:00 1999-02-25 22:43:32 0 High admin 0 tomato test^M
job^M
1 1
+drop table t1,t2,t3,t4,t5,t6,t7;
+create table t1 (a blob);
+insert into t1 values ("empty"),("");
+select a,reverse(a) from t1;
a reverse(a)
empty ytpme
+drop table t1;
+create table t1 (a blob, key (a(10)));
+insert into t1 values ("bye"),("hello"),("hello"),("hello word");
+select * from t1 where a like "hello%";
a
hello
hello
hello word
+drop table t1;
+CREATE TABLE t1 (
+f1 int(11) DEFAULT '0' NOT NULL,
+f2 varchar(16) DEFAULT '' NOT NULL,
+f5 text,
+KEY index_name (f1,f2,f5(16))
+);
+INSERT INTO t1 VALUES (0,'traktor','1111111111111');
+INSERT INTO t1 VALUES (1,'traktor','1111111111111111111111111');
+select count(*) from t1 where f2='traktor';
count(*)
2
+drop table t1;
+create table t1 (foobar tinyblob not null, boggle smallint not null, key (foobar(32), boggle));
+insert into t1 values ('fish', 10),('bear', 20);
+select foobar, boggle from t1 where foobar = 'fish';
foobar boggle
fish 10
+select foobar, boggle from t1 where foobar = 'fish' and boggle = 10;
foobar boggle
fish 10
+drop table t1;
diff --git a/mysql-test/r/type_date.result b/mysql-test/r/type_date.result
index 9aa6d6fb9b7..642a8a7004d 100644
--- a/mysql-test/r/type_date.result
+++ b/mysql-test/r/type_date.result
@@ -1,20 +1,61 @@
+create table t1 (a char(16), b date, c datetime);
+insert into t1 SET a='test 2000-01-01', b='2000-01-01', c='2000-01-01';
+select * from t1 where c = '2000-01-01';
a b c
test 2000-01-01 2000-01-01 2000-01-01 00:00:00
+select * from t1 where b = '2000-01-01';
a b c
test 2000-01-01 2000-01-01 2000-01-01 00:00:00
+drop table t1;
+drop table if exists t1,t2;
+CREATE TABLE t1 (name char(6),cdate date);
+INSERT INTO t1 VALUES ('name1','1998-01-01');
+INSERT INTO t1 VALUES ('name2','1998-01-01');
+INSERT INTO t1 VALUES ('name1','1998-01-02');
+INSERT INTO t1 VALUES ('name2','1998-01-02');
+CREATE TABLE t2 (cdate date, note char(6));
+INSERT INTO t2 VALUES ('1998-01-01','note01');
+INSERT INTO t2 VALUES ('1998-01-02','note02');
+select name,t1.cdate,note from t1,t2 where t1.cdate=t2.cdate and t1.cdate='1998-01-01';
name cdate note
name1 1998-01-01 note01
name2 1998-01-01 note01
+drop table t1,t2;
+CREATE TABLE t1 ( datum DATE );
+INSERT INTO t1 VALUES ( "2000-1-1" );
+INSERT INTO t1 VALUES ( "2000-1-2" );
+INSERT INTO t1 VALUES ( "2000-1-3" );
+INSERT INTO t1 VALUES ( "2000-1-4" );
+INSERT INTO t1 VALUES ( "2000-1-5" );
+SELECT * FROM t1 WHERE datum BETWEEN "2000-1-2" AND "2000-1-4";
datum
2000-01-02
2000-01-03
2000-01-04
+DROP TABLE t1;
+CREATE TABLE t1 (
+user_id char(10),
+summa int(11),
+rdate date
+);
+INSERT INTO t1 VALUES ('aaa',100,'1998-01-01');
+INSERT INTO t1 VALUES ('aaa',200,'1998-01-03');
+INSERT INTO t1 VALUES ('bbb',50,'1998-01-02');
+INSERT INTO t1 VALUES ('bbb',200,'1998-01-04');
+select max(rdate) as s from t1 where rdate < '1998-01-03' having s> "1998-01-01";
s
1998-01-02
+select max(rdate) as s from t1 having s="1998-01-04";
s
1998-01-04
+select max(rdate+0) as s from t1 having s="19980104";
s
19980104
+drop table t1;
+create table t1 (date date);
+insert into t1 values ("2000-08-10"),("2000-08-11");
+select date_add(date,INTERVAL 1 DAY),date_add(date,INTERVAL 1 SECOND) from t1;
date_add(date,INTERVAL 1 DAY) date_add(date,INTERVAL 1 SECOND)
2000-08-11 2000-08-10 00:00:01
2000-08-12 2000-08-11 00:00:01
+drop table t1;
diff --git a/mysql-test/r/type_datetime.result b/mysql-test/r/type_datetime.result
index 7028b5ffe33..3e13485c872 100644
--- a/mysql-test/r/type_datetime.result
+++ b/mysql-test/r/type_datetime.result
@@ -1,3 +1,7 @@
+drop table if exists t1;
+create table t1 (t datetime);
+insert into t1 values(101),(691231),(700101),(991231),(10000101),(99991231),(101000000),(691231000000),(700101000000),(991231235959),(10000101000000),(99991231235959);
+select * from t1;
t
2000-01-01 00:00:00
2069-12-31 00:00:00
@@ -11,10 +15,15 @@ t
1999-12-31 23:59:59
1000-01-01 00:00:00
9999-12-31 23:59:59
+delete from t1 where t > 0;
+optimize table t1;
Table Op Msg_type Msg_text
test.t1 optimize status OK
+check table t1;
Table Op Msg_type Msg_text
test.t1 check status OK
+insert into t1 values("000101"),("691231"),("700101"),("991231"),("00000101"),("00010101"),("99991231"),("00101000000"),("691231000000"),("700101000000"),("991231235959"),("10000101000000"),("99991231235959");
+select * from t1;
t
2000-01-01 00:00:00
2069-12-31 00:00:00
@@ -29,7 +38,22 @@ t
1999-12-31 23:59:59
1000-01-01 00:00:00
9999-12-31 23:59:59
+drop table t1;
+CREATE TABLE t1 (a timestamp, b date, c time, d datetime);
+insert into t1 (b,c,d) values(now(),curtime(),now());
+select date_format(a,"%Y-%m-%d")=b,right(a,6)=c+0,a=d+0 from t1;
date_format(a,"%Y-%m-%d")=b right(a,6)=c+0 a=d+0
1 1 1
+drop table t1;
+CREATE TABLE t1 (a datetime not null);
+insert into t1 values (0);
+select * from t1 where a is null;
a
0000-00-00 00:00:00
+drop table t1;
+create table t1 (id int, dt datetime);
+insert into t1 values (1,"2001-08-14 00:00:00"),(2,"2001-08-15 00:00:00"),(3,"2001-08-16 00:00:00");
+select * from t1 where dt='2001-08-14 00:00:00' and dt = if(id=1,'2001-08-14 00:00:00','1999-08-15');
+id dt
+1 2001-08-14 00:00:00
+drop table t1;
diff --git a/mysql-test/r/type_decimal.result b/mysql-test/r/type_decimal.result
index 0877424648b..9fee88f4bf8 100644
--- a/mysql-test/r/type_decimal.result
+++ b/mysql-test/r/type_decimal.result
@@ -1,5 +1,152 @@
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (
+id int(11) DEFAULT '0' NOT NULL auto_increment,
+datatype_id int(11) DEFAULT '0' NOT NULL,
+minvalue decimal(20,10) DEFAULT '0.0000000000' NOT NULL,
+maxvalue decimal(20,10) DEFAULT '0.0000000000' NOT NULL,
+valuename varchar(20),
+forecolor int(11),
+backcolor int(11),
+PRIMARY KEY (id),
+UNIQUE datatype_id (datatype_id, minvalue, maxvalue)
+);
+INSERT INTO t1 VALUES ( '1', '4', '0.0000000000', '0.0000000000', 'Ei saja', '0', '16776960');
+INSERT INTO t1 VALUES ( '2', '4', '1.0000000000', '1.0000000000', 'Sajab', '16777215', '255');
+INSERT INTO t1 VALUES ( '3', '1', '2.0000000000', '49.0000000000', '', '0', '16777215');
+INSERT INTO t1 VALUES ( '60', '11', '0.0000000000', '0.0000000000', 'Rikkis', '16777215', '16711680');
+INSERT INTO t1 VALUES ( '4', '12', '1.0000000000', '1.0000000000', 'nork sadu', '65280', '14474460');
+INSERT INTO t1 VALUES ( '5', '12', '2.0000000000', '2.0000000000', 'keskmine sadu', '255', '14474460');
+INSERT INTO t1 VALUES ( '6', '12', '3.0000000000', '3.0000000000', 'tugev sadu', '127', '14474460');
+INSERT INTO t1 VALUES ( '43', '39', '6.0000000000', '6.0000000000', 'lobjakas', '13107327', '16763080');
+INSERT INTO t1 VALUES ( '40', '39', '2.0000000000', '2.0000000000', 'vihm', '8355839', '16777215');
+INSERT INTO t1 VALUES ( '53', '1', '-35.0000000000', '-5.0000000000', '', '0', '16777215');
+INSERT INTO t1 VALUES ( '41', '39', '3.0000000000', '3.0000000000', 'külm vihm', '120', '16763080');
+INSERT INTO t1 VALUES ( '12', '21', '21.0000000000', '21.0000000000', 'Kuiv', '13158600', '16777215');
+INSERT INTO t1 VALUES ( '13', '21', '13.0000000000', '13.0000000000', 'Märg', '5263615', '16777215');
+INSERT INTO t1 VALUES ( '14', '21', '22.0000000000', '22.0000000000', 'Niiske', '9869055', '16777215');
+INSERT INTO t1 VALUES ( '19', '21', '33.0000000000', '33.0000000000', 'Märg', '5263615', '16777215');
+INSERT INTO t1 VALUES ( '15', '21', '23.0000000000', '23.0000000000', 'Märg', '5263615', '16777215');
+INSERT INTO t1 VALUES ( '16', '21', '31.0000000000', '31.0000000000', 'Kuiv', '13158600', '16777215');
+INSERT INTO t1 VALUES ( '17', '21', '12.0000000000', '12.0000000000', 'Niiske', '9869055', '16777215');
+INSERT INTO t1 VALUES ( '18', '21', '32.0000000000', '32.0000000000', 'Niiske', '9869055', '16777215');
+INSERT INTO t1 VALUES ( '20', '21', '331.0000000000', '331.0000000000', 'Härmatise hoiatus!', '14448840', '13158600');
+INSERT INTO t1 VALUES ( '21', '21', '11.0000000000', '11.0000000000', 'Kuiv', '13158600', '16777215');
+INSERT INTO t1 VALUES ( '22', '33', '21.0000000000', '21.0000000000', 'Pilves, kuiv', '8355711', '12632256');
+INSERT INTO t1 VALUES ( '23', '33', '13.0000000000', '13.0000000000', 'Sajab, märg', '0', '8355839');
+INSERT INTO t1 VALUES ( '24', '33', '22.0000000000', '22.0000000000', 'Pilves, niiske', '8355711', '12632319');
+INSERT INTO t1 VALUES ( '29', '33', '33.0000000000', '33.0000000000', 'Selge, märg', '16777215', '8355839');
+INSERT INTO t1 VALUES ( '25', '33', '23.0000000000', '23.0000000000', 'Pilves, märg', '8355711', '8355839');
+INSERT INTO t1 VALUES ( '26', '33', '31.0000000000', '31.0000000000', 'Selge, kuiv', '16777215', '12632256');
+INSERT INTO t1 VALUES ( '27', '33', '12.0000000000', '12.0000000000', 'Sajab, niiske', '0', '12632319');
+INSERT INTO t1 VALUES ( '28', '33', '32.0000000000', '32.0000000000', 'Selge, niiske', '16777215', '12632319');
+INSERT INTO t1 VALUES ( '30', '33', '331.0000000000', '331.0000000000', 'Härmatis! selge,kuiv', '16711680', '12632256');
+INSERT INTO t1 VALUES ( '31', '33', '11.0000000000', '11.0000000000', 'Sajab, kuiv', '0', '12632256');
+INSERT INTO t1 VALUES ( '32', '11', '1.0000000000', '1.0000000000', 'Korras', '16777215', '49152');
+INSERT INTO t1 VALUES ( '33', '21', '335.0000000000', '335.0000000000', 'Härmatis!', '14448840', '11842740');
+INSERT INTO t1 VALUES ( '34', '21', '134.0000000000', '134.0000000000', 'Hoiatus, M+S!', '255', '13158600');
+INSERT INTO t1 VALUES ( '35', '21', '133.0000000000', '133.0000000000', 'Hoiatus, märg!', '5263615', '13158600');
+INSERT INTO t1 VALUES ( '36', '21', '135.0000000000', '135.0000000000', 'Härmatis!', '14448840', '11842740');
+INSERT INTO t1 VALUES ( '37', '21', '334.0000000000', '334.0000000000', 'Härmatise hoiatus!', '14448840', '13158600');
+INSERT INTO t1 VALUES ( '38', '21', '132.0000000000', '132.0000000000', 'Hoiatus, niiske!', '9869055', '13158600');
+INSERT INTO t1 VALUES ( '39', '39', '1.0000000000', '1.0000000000', 'ei saja', '11206570', '16777215');
+INSERT INTO t1 VALUES ( '44', '39', '4.0000000000', '5.0000000000', 'lumi', '16711680', '16763080');
+INSERT INTO t1 VALUES ( '45', '12', '0.0000000000', '0.0000000000', '', '16777215', '14474460');
+INSERT INTO t1 VALUES ( '46', '39', '8.0000000000', '8.0000000000', 'rahe', '9830400', '16763080');
+INSERT INTO t1 VALUES ( '47', '39', '9.0000000000', '9.0000000000', 'tüüp ebaselge', '12582912', '16777215');
+INSERT INTO t1 VALUES ( '48', '39', '7.0000000000', '7.0000000000', 'lumetuisk', '7209070', '16763080');
+INSERT INTO t1 VALUES ( '142', '15', '2.0000000000', '49.0000000000', '', '0', '16777215');
+INSERT INTO t1 VALUES ( '52', '1', '-4.9000000000', '-0.1000000000', '', '0', '15774720');
+INSERT INTO t1 VALUES ( '141', '15', '-4.9000000000', '-0.1000000000', '', '0', '15774720');
+INSERT INTO t1 VALUES ( '55', '8', '0.0000000000', '0.0000000000', '', '0', '16777215');
+INSERT INTO t1 VALUES ( '56', '8', '0.0100000000', '0.1000000000', '', '0', '16770560');
+INSERT INTO t1 VALUES ( '57', '8', '0.1100000000', '25.0000000000', '', '0', '15774720');
+INSERT INTO t1 VALUES ( '58', '2', '90.0000000000', '94.9000000000', '', NULL, '16770560');
+INSERT INTO t1 VALUES ( '59', '6', '0.0000000000', '360.0000000000', '', NULL, '16777215');
+INSERT INTO t1 VALUES ( '61', '21', '38.0000000000', '38.0000000000', 'Niiske', '9869055', '16777215');
+INSERT INTO t1 VALUES ( '62', '38', '500.0000000000', '999.0000000000', '', '0', '16770560');
+INSERT INTO t1 VALUES ( '63', '38', '1000.0000000000', '2000.0000000000', '', '0', '16777215');
+INSERT INTO t1 VALUES ( '64', '17', '0.0000000000', '0.0000000000', '', NULL, '16777215');
+INSERT INTO t1 VALUES ( '65', '17', '0.1000000000', '10.0000000000', '', NULL, '16770560');
+INSERT INTO t1 VALUES ( '67', '21', '412.0000000000', '412.0000000000', 'Niiske', '9869055', '16777215');
+INSERT INTO t1 VALUES ( '68', '21', '413.0000000000', '413.0000000000', 'Märg', '5263615', '16777215');
+INSERT INTO t1 VALUES ( '69', '21', '113.0000000000', '113.0000000000', 'Märg', '5263615', '16777215');
+INSERT INTO t1 VALUES ( '70', '21', '416.0000000000', '416.0000000000', 'Lumine!', '16711680', '11842740');
+INSERT INTO t1 VALUES ( '71', '38', '0.0000000000', '499.0000000000', '', NULL, '16711680');
+INSERT INTO t1 VALUES ( '72', '22', '-49.0000000000', '49.0000000000', '', NULL, '16777215');
+INSERT INTO t1 VALUES ( '73', '13', '0.0000000000', '9.9000000000', '', NULL, '16777215');
+INSERT INTO t1 VALUES ( '74', '13', '10.0000000000', '14.9000000000', '', NULL, '16770560');
+INSERT INTO t1 VALUES ( '75', '7', '0.0000000000', '50.0000000000', '', NULL, '16777215');
+INSERT INTO t1 VALUES ( '76', '18', '0.0000000000', '0.0000000000', '', NULL, '16777215');
+INSERT INTO t1 VALUES ( '77', '18', '0.1000000000', '10.0000000000', '', NULL, '16770560');
+INSERT INTO t1 VALUES ( '78', '19', '300.0000000000', '400.0000000000', '', NULL, '16777215');
+INSERT INTO t1 VALUES ( '79', '19', '0.0000000000', '299.0000000000', '', NULL, '16770560');
+INSERT INTO t1 VALUES ( '80', '23', '0.0000000000', '100.0000000000', '', NULL, '16777215');
+INSERT INTO t1 VALUES ( '81', '24', '0.0000000000', '200.0000000000', '', NULL, '16777215');
+INSERT INTO t1 VALUES ( '82', '26', '0.0000000000', '0.0000000000', '', NULL, '16777215');
+INSERT INTO t1 VALUES ( '83', '26', '0.1000000000', '5.0000000000', '', NULL, '16776960');
+INSERT INTO t1 VALUES ( '84', '21', '422.0000000000', '422.0000000000', 'Niiske', '9869055', '16777215');
+INSERT INTO t1 VALUES ( '85', '21', '411.0000000000', '411.0000000000', 'Saju hoiat.,kuiv!', '16777215', '13158600');
+INSERT INTO t1 VALUES ( '86', '21', '423.0000000000', '423.0000000000', 'Märg', '5263615', '16777215');
+INSERT INTO t1 VALUES ( '144', '16', '-49.0000000000', '-5.0000000000', '', NULL, '16777215');
+INSERT INTO t1 VALUES ( '88', '16', '2.0000000000', '49.0000000000', '', NULL, '16777215');
+INSERT INTO t1 VALUES ( '89', '21', '338.0000000000', '338.0000000000', 'Härm.hoiatus, N+S!', '16744319', '13158600');
+INSERT INTO t1 VALUES ( '90', '21', '332.0000000000', '332.0000000000', 'Härm.hoiat., niiske!', '16744319', '13158600');
+INSERT INTO t1 VALUES ( '91', '21', '114.0000000000', '114.0000000000', 'Hoiatus, M+S!', '255', '13158600');
+INSERT INTO t1 VALUES ( '92', '21', '117.0000000000', '117.0000000000', 'Hoiatus, JÄÄ!', '14448840', '16711680');
+INSERT INTO t1 VALUES ( '93', '21', '116.0000000000', '116.0000000000', 'Lumine!', '16711680', '11842740');
+INSERT INTO t1 VALUES ( '94', '21', '414.0000000000', '414.0000000000', 'Hoiatus, M+S!', '255', '13158600');
+INSERT INTO t1 VALUES ( '95', '21', '325.0000000000', '325.0000000000', 'Härmatis!', '14448840', '11842740');
+INSERT INTO t1 VALUES ( '96', '21', '321.0000000000', '321.0000000000', 'Härmatise hoiatus!', '14448840', '13158600');
+INSERT INTO t1 VALUES ( '97', '21', '328.0000000000', '328.0000000000', 'Härm.hoiatus, N+S!', '16744319', '13158600');
+INSERT INTO t1 VALUES ( '98', '21', '28.0000000000', '28.0000000000', 'Niiske ja sool', '9869055', '16777215');
+INSERT INTO t1 VALUES ( '99', '21', '118.0000000000', '118.0000000000', 'Hoiatus, N+S!', '9869055', '13158600');
+INSERT INTO t1 VALUES ( '100', '21', '418.0000000000', '418.0000000000', 'Hoiatus, N+S!', '9869055', '13158600');
+INSERT INTO t1 VALUES ( '101', '21', '322.0000000000', '322.0000000000', 'Härm.hoiat., niiske!', '16744319', '13158600');
+INSERT INTO t1 VALUES ( '102', '21', '428.0000000000', '428.0000000000', 'Hoiatus, N+S!', '9869055', '13158600');
+INSERT INTO t1 VALUES ( '103', '21', '432.0000000000', '432.0000000000', 'Hoiatus, niiske!', '7895240', '13158600');
+INSERT INTO t1 VALUES ( '104', '21', '421.0000000000', '421.0000000000', 'Saju hoiat.,kuiv!', '16777215', '13158600');
+INSERT INTO t1 VALUES ( '105', '21', '24.0000000000', '24.0000000000', 'Märg ja sool', '255', '16777215');
+INSERT INTO t1 VALUES ( '106', '21', '438.0000000000', '438.0000000000', 'Hoiatus, N+S!', '9869055', '13158600');
+INSERT INTO t1 VALUES ( '107', '21', '112.0000000000', '112.0000000000', 'Hoiatus, niiske!', '9869055', '13158600');
+INSERT INTO t1 VALUES ( '108', '21', '34.0000000000', '34.0000000000', 'Märg ja sool', '255', '16777215');
+INSERT INTO t1 VALUES ( '109', '21', '434.0000000000', '434.0000000000', 'Hoiatus, M+S!', '255', '13158600');
+INSERT INTO t1 VALUES ( '110', '21', '124.0000000000', '124.0000000000', 'Hoiatus, M+S!', '255', '13158600');
+INSERT INTO t1 VALUES ( '111', '21', '424.0000000000', '424.0000000000', 'Hoiatus, M+S!', '255', '13158600');
+INSERT INTO t1 VALUES ( '112', '21', '123.0000000000', '123.0000000000', 'Hoiatus, märg!', '5263615', '13158600');
+INSERT INTO t1 VALUES ( '140', '15', '-49.0000000000', '-5.0000000000', '', '0', '16777215');
+INSERT INTO t1 VALUES ( '114', '21', '18.0000000000', '18.0000000000', 'Niiske ja sool', '9869055', '16777215');
+INSERT INTO t1 VALUES ( '115', '21', '122.0000000000', '122.0000000000', 'Hoiatus, niiske!', '9869055', '13158600');
+INSERT INTO t1 VALUES ( '116', '21', '14.0000000000', '14.0000000000', 'Märg ja sool', '255', '16777215');
+INSERT INTO t1 VALUES ( '117', '21', '311.0000000000', '311.0000000000', 'Härmatise hoiatus!', '14448840', '13158600');
+INSERT INTO t1 VALUES ( '121', '2', '95.0000000000', '100.0000000000', '', NULL, '15774720');
+INSERT INTO t1 VALUES ( '118', '2', '0.0000000000', '89.9000000000', '', NULL, '16777215');
+INSERT INTO t1 VALUES ( '119', '21', '16.0000000000', '16.0000000000', 'Lumine!', '16711680', '11842740');
+INSERT INTO t1 VALUES ( '120', '21', '26.0000000000', '26.0000000000', 'Lumine!', '16711680', '11842740');
+INSERT INTO t1 VALUES ( '122', '13', '15.0000000000', '50.0000000000', '', NULL, '15774720');
+INSERT INTO t1 VALUES ( '123', '5', '0.0000000000', '9.9000000000', '', NULL, '16777215');
+INSERT INTO t1 VALUES ( '124', '5', '10.0000000000', '14.9000000000', '', NULL, '16770560');
+INSERT INTO t1 VALUES ( '125', '5', '15.0000000000', '50.0000000000', '', NULL, '15774720');
+INSERT INTO t1 VALUES ( '126', '21', '128.0000000000', '128.0000000000', 'Hoiatus, N+S!', '9869055', '13158600');
+INSERT INTO t1 VALUES ( '127', '21', '318.0000000000', '318.0000000000', 'Härm.hoiatus, N+S!', '16744319', '13158600');
+INSERT INTO t1 VALUES ( '128', '21', '312.0000000000', '312.0000000000', 'Härm.hoiat., niiske!', '16744319', '13158600');
+INSERT INTO t1 VALUES ( '129', '21', '126.0000000000', '126.0000000000', 'Lumine!', '16711680', '11842740');
+INSERT INTO t1 VALUES ( '130', '21', '324.0000000000', '324.0000000000', 'Härmatise hoiatus!', '14448840', '13158600');
+INSERT INTO t1 VALUES ( '131', '21', '316.0000000000', '316.0000000000', 'Lumine!', '16711680', '11842740');
+INSERT INTO t1 VALUES ( '132', '1', '0.0000000000', '1.9000000000', '', NULL, '16769024');
+INSERT INTO t1 VALUES ( '134', '3', '-50.0000000000', '50.0000000000', '', NULL, '16777215');
+INSERT INTO t1 VALUES ( '135', '8', '26.0000000000', '2000.0000000000', '', '9868950', '15774720');
+INSERT INTO t1 VALUES ( '136', '21', '426.0000000000', '426.0000000000', 'Lumine!', '16711680', '11842740');
+INSERT INTO t1 VALUES ( '137', '21', '127.0000000000', '127.0000000000', 'Hoiatus, JÄÄ!', '14448840', '16711680');
+INSERT INTO t1 VALUES ( '138', '21', '121.0000000000', '121.0000000000', 'Kuiv', '13158600', '16777215');
+INSERT INTO t1 VALUES ( '139', '21', '326.0000000000', '326.0000000000', 'Lumine!', '16711680', '11842740');
+INSERT INTO t1 VALUES ( '143', '16', '-4.9000000000', '-0.1000000000', '', NULL, '15774720');
+INSERT INTO t1 VALUES ( '145', '15', '0.0000000000', '1.9000000000', '', '0', '16769024');
+INSERT INTO t1 VALUES ( '146', '16', '0.0000000000', '1.9000000000', '', '0', '16769024');
+select * from t1 where minvalue<=1 and maxvalue>=-1 and datatype_id=16;
id datatype_id minvalue maxvalue valuename forecolor backcolor
143 16 -4.9000000000 -0.1000000000 NULL 15774720
146 16 0.0000000000 1.9000000000 0 16769024
+select * from t1 where minvalue<=-1 and maxvalue>=-1 and datatype_id=16;
id datatype_id minvalue maxvalue valuename forecolor backcolor
143 16 -4.9000000000 -0.1000000000 NULL 15774720
+drop table t1;
diff --git a/mysql-test/r/type_enum.result b/mysql-test/r/type_enum.result
index de48527edad..355133532bf 100644
--- a/mysql-test/r/type_enum.result
+++ b/mysql-test/r/type_enum.result
@@ -1,3 +1,10 @@
+DROP TABLE if exists t1;
+CREATE TABLE t1 (
+field enum('001001','001004','001010','001018','001019','001020','001021','001027','001028','001029','001030','001031','001100','002003','002004','002005','002007','002008','002009','002012','002013','002014','003002','003003','003004','003005','003006','003007','003008','003009','003010','003011','003012','003013','003014','003015','003016','003017','003018','003019','004002','004003','004005','004006','004007','004008','004010','004012','004014','004016','004017','004020','004021','004022','004023','004024','004025','004026','006002','006004','006006','006010','006011','006012','006013','006014','007001','007002','007003','007004','007005','007006','007007','007008','007009','007010','007011','007012','007013','007014','007015','007016','007017','007018','007019','007020','007021','007022','007023','007024','007025','007026','007027','007028','007029','007030','007031','007032','007033','007034','007035','007036','007037','007038','007039','007040','007043','007044','009001','009002','009004','009005','009006','009007','009008','009009','009010','009011','009012','009013','010002','010003','010004','010005','010006','010007','010008','010009','010010','010011','010012','010013','010015','010016','010017','010018','010019','010020','010021','010022','010023','010024','010025','010026','010027','010028','011001','011002','011003','011004','011006','011012','011013','011014','011015','011016','012017','012018','012019','012023','012027','012028','012029','012030','012031','012032','012033','012034','012035','012036','012037','012038','012039','014001','016002','016003','016004','016007','016010','016011','016016','016019','016020','016021','016022','016023','016024','016026','016027','016028','016029','016030','016031','016032','016033','016034','017002','018001','019002','019004','020001','020003','020004','020005','020006','020007','020008','020009','022001','022002','022003','023001','023002','023003','023004','023005','023006','023007','023008','023010','023011','023012','023017','023019','023020','023021','023025','023026','023027','023028','023029','023030','023031','023032','023033','023034','023035','025001','025003','025004','025005','025006','025007','025008','025009','025010','025011','025012','025013','025014','025015','025016','025017','025018','025019','025020','025021','025022','025023','025024','025025','025026','025027','025028','025029','025030','025031','025032','025033','025034','025035','025036','025037','025038','025039','025040','025041','025042','025043','025044','025045','025046','025047','025048','025049','025050','025051','025052','025053','025054','025055','025056','025057','025058','025059','025060','025061','025062','025063','027001','027002','027011','035008','035012','036001','037001','037003','037004','037005','037006','037007','037008','037009','038004','038005','038006','038007','038009','039001','039002','039003','039004','039005','039006','046001','046002','046003','046004','046005','046007','046008','046009','046010','046011','046012','046013','046014','047001','047002','048001','051001','051002','051003','051004','052001','052002','052005','053015','053016','053019','053020','053023','053024','053026','053028','053029','053033','053034','053036','053037','053038','053039','053041','053042','053043','053045','053046','053047','053048','053051','053052','053054','053055','053056','053057','053068','053069','053070','053073','053074','053075','053086','053094','053095','053096','053097','053098','053099','053100','053101','053102','053103','053104','053105','053107','053122','053123','053124','053125','053127','053128','054001','054002','054003','054004','054005','054006','054007','054009','054010','056001','056002','056003','056004','056005','056006','056009','056010','056011','056016','056017','056018','056019','056020','056021','056022','057001','057002','057003','057004','058002','058003','058004','058005','060001','060003','060004','060005','060006','060007','061002','061003','061004','061005','061006','069006','069007','069010','069011','069012','069013','069014','069015','069016','069017','069018','069020','069021','069022','069023','069024','071002','071003','071004','071005','071006','071008','071011','071013','071020','071021','071022','072001','073001','073002','073003','073004','074001','074002','074003','074004','074005','074006','074007','074008','074009','074010','074011','074012','075001','075007','076101','076102','076103','077001','077002','077003','077004','077006','077007','077008','077009','078005','079002','079003','079004','079005','079006','079007','081001','082006','082007','082011','082013','082014','082015','082016','082017','082021','082022','082023','082024','082025','082026','082027','082028','082029','082030','082031','082032','082033','082034','082035','082036','082037','082038','082039','082040','082041','082042','082043','082044','084001','084002','084003','084004','084005','084007','084008','084009','084011','084013','084014','084016','084017','084027','084031','084032','084033','084035','084036','084037','084038','084039','084040','084041','084042','084043','084044','084045','084046','084047','084048','084049','084050','084051','085001','085002','085003','085004','085005','085006','085007','085009','085011','085012','085013','085014','085015','085016','085017','085018','085019','085020','085021','085022','085023','085028','085029','085030','085031','085033','085034','085035','085036','085037','085038','085040','085041','085042','085043','085044','085045','085046','085047','085048','085063','085064','085065','085068','085070','085071','085073','085082','085083','085086','085088','085089','085090','085091','085092','085093','085094','085095','085096','085097','085098','085099','085100','085101','085102','085103','085104','085105','085106','085107','085108','085109','085110','085111','085112','085113','085115','085119','085120','085121','085122','085123','085124','085125','085126','085127','085128','085129','085130','085132','085133','085134','085135','085136','085137','086001','086002','086003','086004','086005','088001','088003','088005','088006','088007','088008','088009','089001','090001','090002','090003','090004','090005','090006','090007','090008','090009','090010','090013','090015','090016','090017','090018','090019','090022','090027','090028','091001','091002','091005','091008','091009','091010','091011','091012','091013','091014','091015','091016','091017','091018','093001','093003','093098','093100','093102','093104','093141','093142','093146','093151','093153','093167','093168','093176','094001','094002','094004','094005','095004','099001','099002','100001','101001','102002','102003','105001','105002','106001','113001','113002','113003','113004','113005','113006','113007','113008','113009','113010','113011','113012','113013','113014','113015','113016','113017','113018','113019','113020','113021','113022','113023','113024','113025','113026','113027','113028','114001','115001','115002','115003','115004','115005','115006','115007','115008','115009','115010','115011','115012','115013','115014','115015','115016','115017','115018','115020','115021','115022','115023','115025','115026','115027','115028','115029','115030','115031','115032','115033','115034','115035','115036','115039','115040','115041','115042','115043','115044','115045','115046','115047','115048','115049','115050','115051','115052','115053','115054','115055','115056','115057','115059','115060','115061','115062','115063','115064','115065','115066','115067','115068','115069','115070','115071','115072','115073','115075','115076','115081','115082','115085','115086','115087','115088','115095','115096','115097','115098','115099','115101','115102','115103','115104','115105','115106','115108','115109','115110','115111','115112','115113','115114','115115','115116','115117','115118','115119','115120','115121','115122','116001','116002','116003','116004','116005','116006','116007','116008','116009','116010','116011','116012','117001','117002','117003','123001','124010','124014','124015','124019','124024','124025','124026','124027','124028','124029','124030','124031','124032','124033','124035','124036','124037','124038','124039','124040','124041','124042','124043','124044','124045','124046','124047','124048','124049','124050','124051','124052','124053','124054','124055','124056','124057','124058','124059','124060','124061','124062','124063','124064','124065','126001','126002','126003','126004','126005','126006','126007','126008','126009','126010','126011','126012','130001','132001','132002','132003','133001','133008','133009','133010','133011','133012','133013','133014','133015','133016','133017','133018','133019','133020','133021','133022','133023','133024','133025','133027','133028','133029','133030','133031','134001','135001','135002','135003','135004','135005','135006','135007','135008','135009','135010','136001','137009','137010','137011','137012','137013','137014','137015','137016','137017','137018','137019','138001','138002','138003','138004','139001','139003','140001','141001','141002','141003','141006','141007','141008','141009','141011','141012','141014','141015','141016','141017','141018','141019','141020','141021','141022','141023','141024','141025','141026','141027','141028','142001','142002','142003','142004','142005','142006','142007','142008','142010','142011','142012','144001','145001','145002','145003','145004','145005','145006','145007','145008','145009','145010','145011','145012','145013','145014','145015','145016','147001','150003','150005','150009','150013','150014','150015','150016','150017','150020','150021','152001','152002','152003','152004','152005','152006','152007','154001','154002','154003','155001','155002','155003','155004','155005','155006','159001','159002','159003','159004','160001','160002','160003','161001','162001','162002','162003','162004','162007','162010','162011','162012','163001','163002','163003','163005','163010','163011','163014','163015','163016','165001','165002','165003','165004','165005','165006','165007','165008','165009','165010','165011','165012','165013','165014','165015','165016','165017','165018','165019','165020','165021','165022','165023','165024','165025','165026','165027','165028','165029','165030','165031','165032','165033','165034','165035','165036','167001','168001','168002','168003','168004','168005','168007','168008','168009','168010','168011','168012','168013','168014','169001','169002','169003','169007','169008','169009','169010','170001','171001','171002','171003','171004','171005','171006','171007','171008','171009','172001','174001','174002','174003','176001','176002','176003','177001','177002','179001','179002','179003','179004','179005','179006','179007','179008','179009','179010','179011','179012','179013','179014','179015','179016','179017','179018','179019','179020','179021','179022','179023','179024','179025','179026','179027','179028','179029','179030','179031','179032','179033','179034','179035','179036','179037','179038','179039','179040','179041','179042','179043','179044','179045','179046','179047','180001','180010','180012','180013','180014','180015','180016','180017','180018','180019','180020','180021','180022','180023','180024','180025','180026','180027','180028','180030','180031','180032','180033','180034','180035','180036','180037','180038','180039','180041','180042','180043','180044','180045','180046','180047','180048','180049','180050','180051','180052','180053','180054','180055','180056','180057','180058','180059','180060','180061','180062','180063','180064','180065','180066','180067','180068','180069','180070','180071','182001','184001','184002','184005','184006','184007','184008','184009','184010','184011','185001','185003','187001','188001','188002','188003','188004','188005','188006','188007','188008','188009','188010','188011','191001','191002','192002','194001','194002','194003','194004','194005','194006','194007','195001','195002','195003','195004','195005','195006','195007','196001','196002','197001','197002','197003','197004','197005','197006','198001','198003','198004','198005','198006','198007','198008','198009','198010','198011','198012','198013','198014','198015','198016','198017','201001','201002','201005','202001','203001','203002','203003','203017','203018','203019','204001','204002','204003','205001','208001','208002','208003','208004','208005','209001','209002','209003','210001','210002','210003','210004','210005','210006','210007','210008','210009','210010','210011','210012','210013','211017','212001','212002','212003','212004','212005','212006','212007','212008','212009','212010','212011','212012','212013','218001','218003','218004','218006','218007','218008','218009','218011','218015','218016','218017','218018','218019','218020','218021','218022','218023','218024','218025','218026','218027','218028','218029','218030','218031','218032','218033','218034','218035','218036','221001','221002','221003','221004','221005','221006','221007','221008','221009','221010','221011','221012','221013','223001','223002','223003','224001','224002','224003','224006','224007','224008','225001','225002','225003','225004','225005','225006','225007','225008','225009','225010','225011','225012','225013','226001','226002','226003','226004','226005','226006','226007','226008','226009','227001','227002','227003','227004','227005','227006','227007','227008','227009','227010','227011','227012','227013','227014','227015','227016','227017','227018','227019','227020','227021','227022','227023','227024','227025','227026','227027','227028','227029','227030','227031','227032','227033','227034','227035','227036','227037','227038','227039','227040','227041','227042','227043','227044','227045','227046','227047','227048','227049','227050','227051','227052','227053','227054','227055','227056','227057','227058','227059','227060','227061','227062','227063','227064','227065','227066','227067','227068','227069','227070','227071','227072','227073','227074','227075','227076','227077','227078','227079','227080','227081','227082','227083','227084','227085','227086','227087','227088','227089','227090','227091','227092','227093','227094','227095','227096','227097','227098','227099','227100','227101','227102','227103','227104','227105','227106','227107','227108','227109','227110','227111','227112','227113','227114','227115','227116','227117','227118','227119','227120','227122','227123','227124','227125','227126','227127','227128','227129','227130','227131','227132','227133','227134','227135','227136','227137','227138','227139','227140','227141','227142','227143','227144','227145','227146','227147','227148','227149','227150','227151','227152','228001','229001','229002','229003','229004','229005','230001','230002','232001','233001','233002','233003','233004','233005','233006','233007','233008','234001','234002','234003','234004','234005','234006','234007','234008','234009','234010','234011','234012','234013','234014','234015','234016','234017','234018','234019','234020','234021','234022','234023','234024','234025','234026','234027','234028','234029','234030','235001','235002','235003','235004','235005','236001','236002','236003','237001','238002','238003','238004','238005','238006','238007','238008','333013','333014','333015','333016','333017','333018','333019','333020','333021','333022','333023','333024','333025','333030','333031','333032','333033','333034','333035','334001','334002','334003','334004','334005','334006','334007','336004','337001','337002','337003','337004','339001','339002','343001','344001','344002','344003','344004','344005','345001','345002','345003','347001','347002','348001','348002','348003','348004','348005','349001','349002','349003','350001','353001','353002','353003','353004','355001','355002','355003','355004','355005','355006','356001','358001','359001','359002','360001','360002','360003','360004','360005','366001','366002','366003','366004','369001','373001','373002','373003','373004','373005','373006','373007','373008','373009','373010','373011','373012','373013','373014','373015','373016','373017','373018','373019','373020','373021','374001','374002','374003','374004','374005','374006','374007','374008','374009','374010','374011','374012','374013','374014','374015','374016','376001','376002','376003','376004','376005','376006','376007','376008','376009','376010','376011','376012','376013','376016','376017','376018','376019','376020','376021','379003','382001','382002','383001','384001','384002','385001','385002','386001','386002','386003','386004','386005','386006','386007','386008','386009','386010','386011','386012','386013','386014','387001','389001','389002','389003','389004','392001','393001','393002','393003','393004','395001','396001','397001','397002','399001','399002','399003','400001','400002','401001','401002','401003','402001','402002','402003','402004','402005','403001','403002','403003','504001','504002','504004','504005','504006','504007','504008','504009','504010','504011','504012','504013','504014','504017','504018','504019','504021','504022','504023','504024','504025','506001','506002','508001','508002','511001','511002','511003','511004','511005','511006','511007','511008','511009','511010','511011','511012','511013','511014','511017','511018','511020','511021','511022','511024','511028','511029','513001','513002','513003','513004','514001','515001','515002','515003','515007','515008','515009','515010','515011','515012','515013','515014','515015','518001','518002','518003','520001','520002','521001','521002','521003','521004','521005','521006','521007','521008','521009','521010','521011','521012','521013','521014','521015','521016','523001','523002','523003','523004','523005','523006','523007','524001','700001','701001','701002','701003','702001','702002','702003','702004','702005','702006','702007','702008','703001','703002','703003','704001','704002','704003','704004','705001','706001','706002','707001','707002','707003','708001','709001','709002','710001','710002','711001','711002','712001','713001','713002','714001','714002','715001','716001','718001','718002','719001','719002','991001','991002','991003','991004','991005','991006','991007','991008','992001','995001','996001','996002','996003','998001','998002','998003','998004','998005','998006','998007','999001','999002','011017','011018','034001','034002','071010','208006','239001','519001','519003','126013','184012','053071','374017','374018','374019','374020','374021','404001','405002','405001','405003','405007','405006','405005','405004','240011','240010','240009','240008','240007','240006','240005','240004','240003','240002','240001','240012','240013','240014','240015','240016','240017','357001','235006','235007','712002','355008','355007','056023','999999','046015','019005','126014','241003','241002','241001','240018','240020','240019','242001','242002','242003','242004','242005','242006','089002','406001','406002','406003','406004','406005','406006','243001','243002','243003','243004','243005','243006','243007','243008','010030','010029','407001','407006','407005','407004','407003','407002','408001','366005','133032','016035','077010','996004','025064','011019','407007','407008','407009','409001','115123','504026','039007','039009','039008','039010','039011','039012','180072','240021','240023','408002','405008','235008','525001','525002','525003','525004','410001','410002','410003','410004','410005','410006','410007','410008','410009','410010','410011','410012','410013','410014','410015','410016','344006','240031','240030','240029','240028','240027','240026','240025','240024','240034','240033','240032','410017','410018','411001','411002','411003','411004','411005','411006','411007','411008','203020','203021','203022','412001','412002','412003','412004','069025','244001','244002','244009','244008','244007','244006','244005','244004','244003','244015','244014','244013','244012','244011','244010','244016','244017','240042','240041','240040','240039','240038','240037','240036','240035','405009','405010','240043','504034','504033','504032','504031','504030','504029','504028','504027','504042','504041','504040','504039','504038','504037','504036','504035','800001','410019','410020','410021','244018','244019','244020','399004','413001','504043','198018','198019','344007','082045','010031','010032','010033','010034','010035','504044','515016','801002','801003','801004','801005','802001','801001','414001','414002','414003','141029','141030','803001','803002','803003','803004','803005','803006','803007','803008','803009','803010','803011','803012','803013','803014','803015','803016','803017','410022','410023','803018','803019','803020','415002','415001','244021','011020','011023','011022','011021','025065','165037','165038','165039','416001','416002','416003','417001','418001','504045','803022','803021','240022','419001','420001','804010','804009','804008','804007','804006','804005','804004','804003','804002','804001','804020','804019','804018','804017','804016','804015','804014','804013','804012','804011','804024','804021','804023','804022','511019','511016','511015','511032','511031','511030','511027','511026','511025','511033','511023','133034','133033','169011','344008','344009','244022','244026','244025','244030','244023','244024','244027','244028','244029','244031','082046','082047','082048','126015','126016','416004','416005','421001','421002','016037','016036','115124','115125','115126','240049','240048','240047','240046','240045','240044','244032','244033','422001','422002','422003','422004','422005','184013','239002','805001','805002','805003','805004','805005','056024','423001','344010','235009','212014','056025','056026','802002','244034','244035','244036','244037','244038','244039','515017','504046','203015','245002','245001','071023','056027','056028','056029','056030','056031','056032','424001','056034','056033','805006','805007','805008','805009','805010','422008','422007','422006','422010','422009','422011','209004','150022','150023','100002','056035','023036','185004','185005','246001','247001','247002','425001','416006','165042','165041','165040','165043','010040','010039','010038','010037','010036','422012','422013','422014','422015','426000','248001','248002','248003','248004','248005','249001','249002','249003','249004','249005','249006','250007','250001','250002','250003','250004','250005','250006','250008','250009','250010','250011','250012','250013','251001','251002','422016','422017','422018','806001','806002','116013','235010','235011','091026','091027','091028','091029','091019','091020','091021','091022','091023','091024','091025','252001','243009','249007','249008','249009','011024','011025','427001','428002','428001','169012','429001','429002','429003') DEFAULT '001001' NOT NULL,
+KEY field (field)
+);
+INSERT INTO t1 VALUES ('001001'),('001001'),('001001'),('001001'),('001001'),('001001'),('001001'),('001001'),('001001'),('001010'),('001010'),('001010'),('001010'),('001010'),('001018'),('001018'),('001018'),('001018'),('001018'),('001018'),('001020'),('001020'),('001020'),('001020'),('001020'),('001020'),('001020'),('001020'),('001021'),('001021'),('001021'),('001021'),('001021'),('001021'),('001027'),('001027'),('001028'),('001030'),('001030'),('001030'),('001030'),('001031'),('001031'),('001031'),('001031'),('001031'),('001100'),('001100'),('002003'),('002003'),('002003'),('002003'),('002003'),('002003'),('002003'),('002003'),('002003'),('002004'),('002004'),('002004'),('002004'),('002004'),('002004'),('002004'),('002004'),('002004'),('002005'),('002005'),('002005'),('002005'),('002005'),('002005'),('002005'),('002005'),('002007'),('002007'),('002007'),('002007'),('002007'),('002007'),('002007'),('002008'),('002008'),('002008'),('002008'),('002008'),('002008'),('002008'),('002008'),('002009'),('002009'),('002009'),('002009'),('002009'),('002009'),('002009'),('002009'),('002012'),('002012'),('002012'),('002012'),('002012'),('002012'),('002012'),('002013'),('002013'),('002013'),('002013'),('002013'),('002013'),('002013'),('002013'),('002013'),('002014'),('002014'),('002014'),('002014'),('002014'),('002014'),('002014'),('002014'),('003002'),('003002'),('003002'),('003002'),('003002'),('003002'),('003003'),('003003'),('003003'),('003003'),('003003'),('003003'),('003004'),('003004'),('003004'),('003004'),('003004'),('003004'),('003005'),('003005'),('003005'),('003005'),('003005'),('003005'),('003005'),('003005'),('003005'),('003006'),('003006'),('003006'),('003006'),('003006'),('003006'),('003006'),('003006'),('003007'),('003007'),('003007'),('003007'),('003007'),('003008'),('003008'),('003008'),('003008'),('003008'),('003008'),('003009'),('003009'),('003009'),('003009'),('003009'),('003009'),('003009'),('003009'),('003009'),('003010'),('003010'),('003010'),('003010'),('003010'),('003010'),('003010'),('003010'),('003010'),('003011'),('003011'),('003011'),('003011'),('003011'),('003011'),('003011'),('003011'),('003012'),('003012'),('003012'),('003012'),('003012'),('003012'),('003012'),('003012'),('003013'),('003013'),('003013'),('003013'),('003013'),('003013'),('003013'),('003013'),('003014'),('003014'),('003014'),('003014'),('003014'),('003014'),('003014'),('003014'),('003015'),('003015'),('003015'),('003015'),('003015'),('003015'),('003016'),('003016'),('003016'),('003016'),('003016'),('003016'),('003017'),('003017'),('003017'),('003017'),('003017'),('003018'),('003018'),('003018'),('003018'),('003018'),('003019'),('003019'),('004003'),('004005'),('004005'),('004005'),('004005'),('004005'),('004005'),('004006'),('004008'),('004010'),('004012'),('004012'),('004014'),('004014'),('004014'),('004014'),('004014'),('004016'),('004017'),('004017'),('004017'),('004017'),('004017'),('004017'),('004017'),('004017'),('004020'),('004020'),('004020'),('004020'),('004020'),('004020'),('004021'),('004021'),('004021'),('004021'),('004021'),('004021'),('004021'),('004022'),('004023'),('004023'),('004023'),('004023'),('004023'),('004023'),('004023'),('004025'),('004026'),('004026'),('004026'),('004026'),('004026'),('006004'),('006006'),('006010'),('006010'),('006010'),('006010'),('006010'),('006010'),('006010'),('006011'),('006011'),('006011'),('006011'),('006011'),('006011'),('006012'),('006012'),('006012'),('006012'),('006012'),('006012'),('006014'),('006014'),('006014'),('007001'),('007001'),('007002'),('007003'),('007005'),('007007'),('007008'),('007009'),('007011'),('007012'),('007013'),('007015'),('007016'),('007017'),('007018'),('007019'),('007019'),('007020'),('007021'),('007021'),('007022'),('007023'),('007023'),('007025'),('007025'),('007025'),('007027'),('007029'),('007031'),('007031'),('007032'),('007034'),('007034'),('007036'),('007036'),('007036'),('007037'),('007037'),('007038'),('007040'),('007040'),('007040'),('007043'),('009001'),('009001'),('009001'),('009001'),('009001'),('009001'),('009001'),('009002'),('009002'),('009002'),('009002'),('009002'),('009004'),('009004'),('009004'),('009004'),('009005'),('009005'),('009005'),('009005'),('009005'),('009005'),('009005'),('009005'),('009006'),('009006'),('009006'),('009006'),('009007'),('009007'),('009007'),('009007'),('009007'),('009007'),('009008'),('009010'),('009010'),('009010'),('009010'),('009010'),('009010'),('009011'),('009011'),('009011'),('009011'),('009011'),('009012'),('009013'),('009013'),('009013'),('010002'),('010002'),('010002'),('010002'),('010002'),('010002'),('010002'),('010002'),('010003'),('010003'),('010003'),('010003'),('010003'),('010003'),('010003'),('010003'),('010003'),('010004'),('010004'),('010004'),('010004'),('010004'),('010004'),('010004'),('010004'),('010004'),('010005'),('010005'),('010005'),('010005'),('010006'),('010006'),('010006'),('010006'),('010006'),('010006'),('010006'),('010006'),('010006'),('010007'),('010007'),('010007'),('010007'),('010007'),('010007'),('010008'),('010008'),('010008'),('010008'),('010008'),('010008'),('010008'),('010009'),('010009'),('010009'),('010009'),('010009'),('010009'),('010010'),('010010'),('010010'),('010010'),('010010'),('010010'),('010010'),('010011'),('010011'),('010011'),('010011'),('010011'),('010011'),('010011'),('010011'),('010012'),('010012'),('010012'),('010012'),('010012'),('010012'),('010012'),('010013'),('010013'),('010013'),('010013'),('010013'),('010013'),('010015'),('010016'),('010016'),('010016'),('010016'),('010016'),('010016'),('010016'),('010016'),('010017'),('010017'),('010017'),('010017'),('010017'),('010017'),('010018'),('010018'),('010018'),('010018'),('010018'),('010018'),('010018'),('010018'),('010018'),('010019'),('010019'),('010019'),('010019'),('010019'),('010019'),('010020'),('010020'),('010020'),('010021'),('010021'),('010021'),('010021'),('010021'),('010021'),('010022'),('010022'),('010022'),('010022'),('010022'),('010022'),('010022'),('010022'),('010023'),('010023'),('010023'),('010023'),('010023'),('010023'),('010023'),('010023'),('010026'),('010027'),('010028'),('010028'),('011001'),('011001'),('011001'),('011001'),('011001'),('011001'),('011001'),('011002'),('011002'),('011002'),('011002'),('011002'),('011002'),('011002'),('011003'),('011003'),('011003'),('011003'),('011003'),('011003'),('011003'),('011003'),('011004'),('011004'),('011004'),('011004'),('011004'),('011004'),('011004'),('011006'),('011006'),('011006'),('011006'),('011006'),('011006'),('011006'),('011012'),('011012'),('011012'),('011013'),('011013'),('011013'),('011013'),('011013'),('011013'),('011014'),('011014'),('011014'),('011014'),('011015'),('011015'),('011015'),('011015'),('011015'),('011016'),('011016'),('011016'),('011016'),('011016'),('012017'),('012017'),('012027'),('012027'),('012032'),('012034'),('012036'),('012036'),('012037'),('012037'),('012038'),('012039'),('014001'),('014001'),('016016'),('016016'),('016016'),('016019'),('016020'),('016020'),('016020'),('016020'),('016020'),('016020'),('016020'),('016020'),('016021'),('016021'),('016021'),('016021'),('016021'),('016021'),('016021'),('016022'),('016022'),('016022'),('016023'),('016023'),('016023'),('016024'),('016024'),('016024'),('016024'),('016024'),('016024'),('016024'),('016026'),('016026'),('016026'),('016026'),('016026'),('016026'),('016028'),('016028'),('016028'),('016028'),('016028'),('016028'),('016028'),('016029'),('016029'),('016030'),('016031'),('016032'),('016032'),('016032'),('016032'),('016032'),('016032'),('016032'),('016033'),('016033'),('016033'),('016033'),('016033'),('016034'),('016034'),('016034'),('016034'),('016034'),('017002'),('017002'),('017002'),('017002'),('017002'),('018001'),('018001'),('018001'),('018001'),('018001'),('018001'),('018001'),('018001'),('019002'),('019002'),('019002'),('019002'),('019002'),('019002'),('019004'),('019004'),('019004'),('019004'),('019004'),('019004'),('020001'),('020001'),('020001'),('020001'),('020004'),('020006'),('020006'),('020006'),('020006'),('020006'),('020006'),('020008'),('020009'),('020009'),('020009'),('020009'),('020009'),('022001'),('022001'),('022001'),('022001'),('022002'),('022002'),('022002'),('022002'),('022003'),('022003'),('022003'),('022003'),('023001'),('023002'),('023002'),('023002'),('023002'),('023002'),('023002'),('023003'),('023003'),('023003'),('023003'),('023004'),('023004'),('023005'),('023005'),('023006'),('023006'),('023006'),('023006'),('023006'),('023006'),('023007'),('023007'),('023010'),('023010'),('023011'),('023011'),('023017'),('023019'),('023019'),('023019'),('023020'),('023020'),('023025'),('023025'),('023025'),('023026'),('023026'),('023026'),('023027'),('023027'),('023027'),('023028'),('023028'),('023029'),('023029'),('023030'),('023030'),('023032'),('023033'),('023033'),('023033'),('023033'),('023033'),('023033'),('023034'),('023035'),('023035'),('025001'),('025001'),('025001'),('025001'),('025001'),('025001'),('025001'),('025003'),('025003'),('025004'),('025004'),('025005'),('025005'),('025007'),('025007'),('025008'),('025008'),('025009'),('025010'),('025010'),('025010'),('025011'),('025011'),('025012'),('025012'),('025013'),('025013'),('025013'),('025014'),('025015'),('025016'),('025018'),('025018'),('025019'),('025019'),('025020'),('025020'),('025021'),('025022'),('025022'),('025023'),('025023'),('025024'),('025025'),('025025'),('025026'),('025026'),('025027'),('025027'),('025027'),('025028'),('025030'),('025031'),('025033'),('025034'),('025035'),('025037'),('025041'),('025042'),('025043'),('025046'),('025048'),('025048'),('025048'),('025049'),('025049'),('025049'),('025050'),('025050'),('025050'),('025051'),('025051'),('025052'),('025052'),('025052'),('025053'),('025053'),('025054'),('025054'),('025054'),('025054'),('025055'),('025056'),('025056'),('025056'),('025056'),('025056'),('025056'),('025056'),('025056'),('025056'),('025057'),('025057'),('025058'),('025058'),('025060'),('025060'),('025061'),('025062'),('025063'),('027001'),('027002'),('027011'),('036001'),('036001'),('036001'),('036001'),('036001'),('037003'),('037006'),('037007'),('037008'),('037008'),('038009'),('039001'),('039001'),('039001'),('039001'),('039001'),('039001'),('039002'),('039002'),('039002'),('039002'),('039002'),('039003'),('039003'),('039003'),('039003'),('039003'),('039003'),('039004'),('039004'),('039004'),('039004'),('039004'),('039005'),('039005'),('039005'),('039005'),('039005'),('039006'),('039006'),('039006'),('039006'),('046001'),('046001'),('046001'),('046001'),('046001'),('046001'),('046001'),('046001'),('046002'),('046002'),('046002'),('046002'),('046002'),('046002'),('046002'),('046002'),('046003'),('046003'),('046003'),('046003'),('046003'),('046003'),('046003'),('046005'),('046005'),('046005'),('046005'),('046005'),('046005'),('046005'),('046007'),('046007'),('046007'),('046007'),('046007'),('046007'),('046008'),('046008'),('046008'),('046008'),('046008'),('046009'),('046009'),('046009'),('046010'),('046012'),('046012'),('046012'),('046013'),('046014'),('046014'),('046014'),('047001'),('047001'),('047001'),('047001'),('047001'),('047001'),('047001'),('047001'),('047002'),('047002'),('047002'),('047002'),('047002'),('047002'),('047002'),('047002'),('048001'),('048001'),('048001'),('048001'),('048001'),('048001'),('048001'),('048001'),('051003'),('051003'),('051003'),('051003'),('051003'),('051004'),('051004'),('051004'),('051004'),('052001'),('052001'),('052001'),('052001'),('052001'),('052001'),('052001'),('052001'),('052002'),('052002'),('052005'),('052005'),('052005'),('052005'),('052005'),('052005'),('053016'),('053019'),('053019'),('053023'),('053023'),('053023'),('053023'),('053024'),('053024'),('053024'),('053026'),('053026'),('053026'),('053026'),('053028'),('053028'),('053029'),('053029'),('053029'),('053029'),('053033'),('053033'),('053033'),('053045'),('053046'),('053051'),('053051'),('053051'),('053054'),('053054'),('053054'),('053054'),('053057'),('053069'),('053069'),('053097'),('053107'),('053125'),('053125'),('053127'),('054001'),('054001'),('054001'),('054001'),('054001'),('054001'),('054001'),('054002'),('054002'),('054002'),('054002'),('054002'),('054002'),('054003'),('054003'),('054003'),('054003'),('054003'),('054003'),('054003'),('054004'),('054004'),('054004'),('054004'),('054004'),('054004'),('054004'),('054006'),('054006'),('054006'),('054007'),('054007'),('054007'),('054007'),('054007'),('054009'),('054009'),('054009'),('054009'),('054010'),('054010'),('054010'),('054010'),('054010'),('054010'),('054010'),('056001'),('056001'),('056001'),('056001'),('056001'),('056001'),('056001'),('056001'),('056001'),('056002'),('056002'),('056002'),('056002'),('056002'),('056002'),('056002'),('056002'),('056003'),('056003'),('056003'),('056003'),('056003'),('056003'),('056004'),('056004'),('056004'),('056004'),('056004'),('056004'),('056004'),('056005'),('056005'),('056005'),('056005'),('056005'),('056005'),('056005'),('056005'),('056005'),('056006'),('056006'),('056006'),('056006'),('056006'),('056006'),('056006'),('056006'),('056006'),('056009'),('056009'),('056009'),('056011'),('056016'),('056016'),('056016'),('056016'),('056016'),('056016'),('056016'),('056017'),('056017'),('056017'),('056017'),('056017'),('056017'),('056017'),('056017'),('056017'),('056018'),('056018'),('056018'),('056018'),('056018'),('056018'),('056019'),('056019'),('056019'),('056019'),('056019'),('056019'),('056019'),('056019'),('056020'),('056020'),('056020'),('056020'),('056022'),('056022'),('056022'),('056022'),('056022'),('057003'),('057003'),('057004'),('058002'),('058002'),('058002'),('058002'),('058003'),('058003'),('058003'),('058003'),('058004'),('058004'),('058004'),('058005'),('058005'),('058005'),('060001'),('060001'),('060001'),('060001'),('060001'),('060004'),('060004'),('060004'),('060004'),('060004'),('060004'),('060005'),('060005'),('060005'),('060005'),('060005'),('060005'),('060007'),('060007'),('060007'),('060007'),('060007'),('060007'),('060007'),('061004'),('061004'),('061004'),('061004'),('061004'),('061004'),('061006'),('061006'),('061006'),('061006'),('061006'),('061006'),('069006'),('069006'),('069006'),('069006'),('069006'),('069006'),('069006'),('069006'),('069006'),('069007'),('069007'),('069007'),('069007'),('069007'),('069007'),('069007'),('069007'),('069010'),('069010'),('069010'),('069010'),('069010'),('069010'),('069011'),('069012'),('069012'),('069012'),('069012'),('069012'),('069012'),('069012'),('069012'),('069012'),('069012'),('069013'),('069013'),('069013'),('069013'),('069013'),('069013'),('069013'),('069013'),('069013'),('069014'),('069014'),('069014'),('069014'),('069014'),('069014'),('069014'),('069014'),('069014'),('069015'),('069015'),('069015'),('069015'),('069015'),('069015'),('069015'),('069015'),('069015'),('069015'),('069016'),('069016'),('069016'),('069016'),('069016'),('069018'),('069018'),('069018'),('069018'),('069018'),('069018'),('069018'),('069018'),('069018'),('069020'),('069020'),('069020'),('069020'),('069021'),('069023'),('071002'),('071002'),('071002'),('071002'),('071002'),('071003'),('071003'),('071003'),('071003'),('071003'),('071004'),('071004'),('071004'),('071004'),('071004'),('071005'),('071005'),('071005'),('071005'),('071005'),('071005'),('071006'),('071006'),('071006'),('071006'),('071008'),('071008'),('071008'),('071008'),('071008'),('071008'),('071011'),('071011'),('071011'),('071011'),('071011'),('071020'),('071020'),('071020'),('071020'),('071020'),('071021'),('071022'),('071022'),('071022'),('072001'),('072001'),('074001'),('074002'),('074002'),('074002'),('074002'),('074002'),('074002'),('074002'),('074002'),('074003'),('074003'),('074003'),('074003'),('074003'),('074003'),('074003'),('074003'),('074004'),('074004'),('074004'),('074004'),('074004'),('074004'),('074004'),('074004'),('074005'),('074005'),('074005'),('074005'),('074005'),('074005'),('074005'),('074005'),('074006'),('074006'),('074006'),('074006'),('074006'),('074006'),('074006'),('074006'),('074007'),('074007'),('074007'),('074007'),('074007'),('074007'),('074007'),('074007'),('074008'),('074008'),('074008'),('074008'),('074008'),('074008'),('074008'),('074008'),('074009'),('074009'),('074009'),('074009'),('074009'),('074009'),('074009'),('074009'),('074010'),('074010'),('074010'),('074010'),('074010'),('074010'),('074010'),('074010'),('074011'),('074011'),('074011'),('074011'),('074011'),('074011'),('074011'),('074011'),('074012'),('074012'),('074012'),('074012'),('074012'),('074012'),('074012'),('075001'),('075001'),('075001'),('075007'),('075007'),('075007'),('075007'),('076101'),('076101'),('076101'),('076101'),('076102'),('076102'),('076102'),('076103'),('076103'),('076103'),('076103'),('076103'),('077001'),('077001'),('077001'),('077002'),('077002'),('077002'),('077002'),('077002'),('077002'),('077002'),('077003'),('077003'),('077003'),('077003'),('077003'),('077003'),('077003'),('077004'),('077004'),('077004'),('077004'),('077004'),('077004'),('077006'),('077006'),('077008'),('077008'),('077008'),('077008'),('077008'),('077008'),('077008'),('077009'),('077009'),('077009'),('077009'),('077009'),('077009'),('077009'),('078005'),('078005'),('078005'),('079002'),('079002'),('079002'),('079002'),('079002'),('079002'),('079002'),('079003'),('079003'),('079004'),('079004'),('079005'),('079005'),('079005'),('079005'),('079005'),('079005'),('079006'),('079006'),('079006'),('079006'),('079007'),('079007'),('079007'),('079007'),('079007'),('081001'),('081001'),('081001'),('081001'),('081001'),('082011'),('082011'),('082011'),('082011'),('082011'),('082013'),('082013'),('082013'),('082013'),('082013'),('082013'),('082014'),('082014'),('082014'),('082014'),('082014'),('082014'),('082014'),('082015'),('082015'),('082015'),('082015'),('082015'),('082016'),('082016'),('082016'),('082016'),('082016'),('082016'),('082017'),('082017'),('082017'),('082017'),('082017'),('082017'),('082017'),('082021'),('082021'),('082022'),('082022'),('082022'),('082022'),('082022'),('082023'),('082023'),('082023'),('082023'),('082023'),('082024'),('082024'),('082024'),('082024'),('082024'),('082025'),('082025'),('082025'),('082025'),('082025'),('082026'),('082026'),('082026'),('082026'),('082026'),('082027'),('082027'),('082027'),('082027'),('082027'),('082028'),('082028'),('082028'),('082028'),('082029'),('082029'),('082029'),('082029'),('082029'),('082030'),('082030'),('082030'),('082030'),('082031'),('082031'),('082031'),('082031'),('082031'),('082032'),('082032'),('082032'),('082033'),('082033'),('082034'),('082034'),('082034'),('082034'),('082034'),('082034'),('082034'),('082035'),('082035'),('082035'),('082036'),('082036'),('082036'),('082036'),('082037'),('082037'),('082037'),('082038'),('082038'),('082038'),('082038'),('082039'),('082039'),('082039'),('082039'),('082040'),('082040'),('082040'),('082040'),('082040'),('082041'),('082041'),('082041'),('082041'),('082042'),('082042'),('082043'),('082043'),('082043'),('082043'),('082043'),('082044'),('082044'),('082044'),('082044'),('084001'),('084002'),('084002'),('084002'),('084002'),('084003'),('084003'),('084003'),('084003'),('084003'),('084003'),('084003'),('084003'),('084004'),('084004'),('084004'),('084004'),('084004'),('084005'),('084005'),('084005'),('084005'),('084005'),('084007'),('084007'),('084007'),('084007'),('084007'),('084007'),('084008'),('084008'),('084008'),('084008'),('084008'),('084008'),('084009'),('084009'),('084009'),('084009'),('084009'),('084009'),('084011'),('084013'),('084013'),('084013'),('084013'),('084013'),('084014'),('084014'),('084014'),('084016'),('084016'),('084016'),('084016'),('084016'),('084016'),('084016'),('084016'),('084017'),('084017'),('084017'),('084017'),('084017'),('084017'),('084017'),('084017'),('084017'),('084027'),('084027'),('084027'),('084027'),('084027'),('084027'),('084032'),('084032'),('084033'),('084033'),('084033'),('084035'),('084035'),('084035'),('084036'),('084036'),('084036'),('084036'),('084036'),('084036'),('084037'),('084037'),('084038'),('084038'),('084038'),('084038'),('084038'),('084038'),('084039'),('084039'),('084039'),('084039'),('084040'),('084040'),('084040'),('084040'),('084040'),('084041'),('084041'),('084041'),('084041'),('084042'),('084042'),('084043'),('084043'),('084043'),('084043'),('084044'),('084044'),('084044'),('084044'),('084044'),('084045'),('084046'),('084046'),('084046'),('084047'),('084048'),('084048'),('084049'),('084049'),('084050'),('084051'),('084051'),('085001'),('085001'),('085001'),('085001'),('085001'),('085001'),('085002'),('085002'),('085002'),('085002'),('085003'),('085003'),('085003'),('085003'),('085003'),('085003'),('085003'),('085004'),('085004'),('085004'),('085004'),('085004'),('085004'),('085004'),('085005'),('085005'),('085005'),('085005'),('085005'),('085005'),('085006'),('085006'),('085006'),('085006'),('085006'),('085006'),('085006'),('085006'),('085007'),('085007'),('085007'),('085007'),('085007'),('085007'),('085007'),('085009'),('085009'),('085009'),('085009'),('085009'),('085009'),('085011'),('085011'),('085011'),('085011'),('085011'),('085011'),('085011'),('085011'),('085012'),('085012'),('085012'),('085012'),('085012'),('085012'),('085012'),('085014'),('085014'),('085014'),('085014'),('085014'),('085014'),('085014'),('085014'),('085014'),('085015'),('085015'),('085015'),('085015'),('085015'),('085015'),('085015'),('085015'),('085016'),('085016'),('085016'),('085016'),('085016'),('085016'),('085016'),('085016'),('085017'),('085017'),('085017'),('085017'),('085017'),('085018'),('085018'),('085018'),('085018'),('085018'),('085019'),('085019'),('085019'),('085019'),('085019'),('085019'),('085019'),('085019'),('085019'),('085020'),('085020'),('085020'),('085020'),('085020'),('085020'),('085022'),('085022'),('085022'),('085022'),('085022'),('085022'),('085023'),('085023'),('085023'),('085023'),('085023'),('085028'),('085028'),('085028'),('085028'),('085028'),('085028'),('085028'),('085029'),('085029'),('085029'),('085029'),('085029'),('085029'),('085029'),('085030'),('085030'),('085030'),('085030'),('085030'),('085030'),('085030'),('085031'),('085031'),('085031'),('085031'),('085031'),('085031'),('085031'),('085033'),('085034'),('085034'),('085034'),('085034'),('085034'),('085034'),('085034'),('085035'),('085035'),('085035'),('085035'),('085035'),('085035'),('085036'),('085036'),('085036'),('085036'),('085036'),('085036'),('085037'),('085037'),('085037'),('085037'),('085037'),('085037'),('085038'),('085038'),('085038'),('085038'),('085038'),('085038'),('085038'),('085040'),('085040'),('085040'),('085040'),('085040'),('085040'),('085040'),('085040'),('085041'),('085041'),('085041'),('085041'),('085041'),('085041'),('085041'),('085041'),('085042'),('085042'),('085042'),('085042'),('085042'),('085042'),('085042'),('085043'),('085043'),('085043'),('085043'),('085043'),('085043'),('085044'),('085044'),('085044'),('085044'),('085044'),('085044'),('085044'),('085045'),('085045'),('085045'),('085045'),('085045'),('085046'),('085046'),('085046'),('085046'),('085046'),('085046'),('085046'),('085046'),('085047'),('085047'),('085047'),('085047'),('085047'),('085047'),('085047'),('085047'),('085048'),('085048'),('085048'),('085048'),('085048'),('085048'),('085048'),('085063'),('085063'),('085063'),('085063'),('085063'),('085064'),('085064'),('085064'),('085064'),('085064'),('085065'),('085065'),('085068'),('085068'),('085068'),('085068'),('085068'),('085068'),('085071'),('085071'),('085071'),('085071'),('085071'),('085071'),('085073'),('085073'),('085082'),('085082'),('085082'),('085082'),('085082'),('085086'),('085086'),('085086'),('085088'),('085088'),('085088'),('085088'),('085088'),('085088'),('085088'),('085089'),('085089'),('085090'),('085090'),('085090'),('085090'),('085090'),('085090'),('085090'),('085090'),('085091'),('085091'),('085091'),('085091'),('085091'),('085092'),('085092'),('085092'),('085093'),('085093'),('085095'),('085095'),('085095'),('085095'),('085095'),('085096'),('085096'),('085096'),('085096'),('085096'),('085096'),('085097'),('085097'),('085097'),('085097'),('085097'),('085098'),('085098'),('085098'),('085098'),('085098'),('085098'),('085098'),('085099'),('085099'),('085099'),('085099'),('085099'),('085099'),('085099'),('085100'),('085100'),('085100'),('085100'),('085100'),('085100'),('085100'),('085100'),('085100'),('085100'),('085101'),('085101'),('085101'),('085101'),('085101'),('085101'),('085101'),('085101'),('085102'),('085102'),('085103'),('085103'),('085103'),('085104'),('085104'),('085104'),('085104'),('085104'),('085105'),('085105'),('085106'),('085106'),('085106'),('085106'),('085106'),('085106'),('085108'),('085108'),('085109'),('085109'),('085109'),('085109'),('085109'),('085109'),('085109'),('085109'),('085110'),('085110'),('085110'),('085110'),('085110'),('085111'),('085111'),('085111'),('085112'),('085112'),('085112'),('085112'),('085113'),('085113'),('085113'),('085113'),('085113'),('085115'),('085120'),('085121'),('085121'),('085121'),('085121'),('085122'),('085122'),('085122'),('085122'),('085122'),('085122'),('085122'),('085122'),('085123'),('085123'),('085123'),('085123'),('085123'),('085123'),('085123'),('085123'),('085125'),('085125'),('085125'),('085125'),('085125'),('085126'),('085126'),('085126'),('085126'),('085126'),('085127'),('085127'),('085127'),('085127'),('085127'),('085127'),('085127'),('085127'),('085128'),('085128'),('085128'),('085128'),('085128'),('085129'),('085129'),('085129'),('085129'),('085129'),('085130'),('085130'),('085130'),('085130'),('085130'),('085132'),('085132'),('085132'),('085132'),('085132'),('085132'),('085133'),('085133'),('085133'),('085133'),('085133'),('085134'),('085134'),('085134'),('085135'),('085135'),('085135'),('085136'),('085136'),('085136'),('085136'),('085137'),('085137'),('085137'),('085137'),('085137'),('085137'),('085137'),('086002'),('086002'),('086002'),('086002'),('086003'),('086003'),('086003'),('086003'),('086005'),('088001'),('088001'),('088001'),('088001'),('088001'),('088003'),('088003'),('088003'),('088003'),('088003'),('088003'),('088005'),('088005'),('088005'),('088005'),('088005'),('088006'),('088006'),('088006'),('088006'),('088006'),('088007'),('088007'),('088007'),('088008'),('088008'),('088008'),('088008'),('088009'),('088009'),('088009'),('088009'),('088009'),('089001'),('089001'),('089001'),('089001'),('089001'),('089001'),('089001'),('090001'),('090001'),('090001'),('090001'),('090001'),('090001'),('090001'),('090002'),('090002'),('090002'),('090002'),('090002'),('090002'),('090003'),('090003'),('090003'),('090003'),('090003'),('090003'),('090003'),('090004'),('090004'),('090004'),('090004'),('090004'),('090004'),('090004'),('090006'),('090006'),('090006'),('090006'),('090006'),('090006'),('090006'),('090008'),('090008'),('090008'),('090008'),('090008'),('090009'),('090009'),('090009'),('090009'),('090009'),('090010'),('090010'),('090013'),('090013'),('090013'),('090016'),('090016'),('090017'),('090018'),('090022'),('090027'),('091001'),('091001'),('091001'),('091001'),('091001'),('091001'),('091002'),('091002'),('091002'),('091002'),('091002'),('091002'),('091009'),('091009'),('091009'),('091009'),('091009'),('091011'),('091011'),('091011'),('091011'),('091011'),('091011'),('091011'),('091012'),('091012'),('091013'),('091013'),('091013'),('091013'),('091013'),('091013'),('091015'),('091015'),('091015'),('091015'),('091015'),('091015'),('091016'),('091016'),('091016'),('091016'),('091016'),('091017'),('091017'),('091018'),('091018'),('091018'),('091018'),('093003'),('093003'),('093003'),('093003'),('093003'),('093003'),('099001'),('099001'),('099001'),('099001'),('099001'),('099001'),('099001'),('100001'),('100001'),('100001'),('100001'),('106001'),('113005'),('113005'),('113005'),('113006'),('113006'),('113018'),('113019'),('113020'),('115001'),('115001'),('115001'),('115002'),('115002'),('115003'),('115004'),('115004'),('115004'),('115004'),('115005'),('115005'),('115005'),('115006'),('115006'),('115006'),('115007'),('115007'),('115007'),('115007'),('115007'),('115008'),('115008'),('115008'),('115009'),('115010'),('115010'),('115010'),('115010'),('115010'),('115011'),('115011'),('115011'),('115011'),('115012'),('115012'),('115013'),('115013'),('115013'),('115014'),('115014'),('115014'),('115014'),('115015'),('115015'),('115015'),('115016'),('115016'),('115016'),('115016'),('115017'),('115017'),('115017'),('115017'),('115017'),('115018'),('115018'),('115020'),('115020'),('115021'),('115021'),('115022'),('115022'),('115022'),('115023'),('115023'),('115023'),('115023'),('115023'),('115025'),('115025'),('115025'),('115026'),('115026'),('115027'),('115027'),('115027'),('115028'),('115028'),('115028'),('115028'),('115029'),('115029'),('115029'),('115030'),('115030'),('115030'),('115031'),('115031'),('115032'),('115032'),('115032'),('115033'),('115033'),('115033'),('115033'),('115034'),('115034'),('115034'),('115035'),('115035'),('115036'),('115036'),('115036'),('115036'),('115036'),('115039'),('115040'),('115040'),('115040'),('115041'),('115041'),('115041'),('115041'),('115041'),('115042'),('115042'),('115042'),('115042'),('115042'),('115043'),('115043'),('115043'),('115044'),('115044'),('115044'),('115044'),('115046'),('115046'),('115046'),('115047'),('115048'),('115050'),('115050'),('115050'),('115050'),('115050'),('115051'),('115051'),('115051'),('115052'),('115053'),('115053'),('115054'),('115054'),('115054'),('115055'),('115055'),('115055'),('115057'),('115059'),('115059'),('115059'),('115059'),('115060'),('115060'),('115060'),('115060'),('115060'),('115060'),('115061'),('115061'),('115061'),('115062'),('115062'),('115062'),('115062'),('115064'),('115064'),('115064'),('115065'),('115065'),('115065'),('115065'),('115066'),('115066'),('115066'),('115067'),('115067'),('115067'),('115068'),('115068'),('115068'),('115069'),('115069'),('115069'),('115069'),('115069'),('115070'),('115070'),('115070'),('115071'),('115071'),('115071'),('115072'),('115072'),('115072'),('115073'),('115073'),('115075'),('115075'),('115075'),('115076'),('115076'),('115076'),('115076'),('115076'),('115076'),('115081'),('115081'),('115081'),('115082'),('115082'),('115082'),('115085'),('115085'),('115085'),('115085'),('115085'),('115086'),('115086'),('115086'),('115087'),('115087'),('115088'),('115088'),('115088'),('115088'),('115088'),('115095'),('115095'),('115095'),('115096'),('115096'),('115097'),('115097'),('115098'),('115098'),('115099'),('115101'),('115102'),('115102'),('115102'),('115103'),('115103'),('115104'),('115104'),('115104'),('115104'),('115105'),('115105'),('115106'),('115106'),('115106'),('115106'),('115106'),('115108'),('115109'),('115111'),('115111'),('115111'),('115111'),('115112'),('115112'),('115112'),('115112'),('115112'),('115113'),('115113'),('115113'),('115114'),('115114'),('115114'),('115114'),('115114'),('115115'),('115115'),('115115'),('115115'),('115116'),('115117'),('115117'),('115117'),('115118'),('115118'),('115119'),('115119'),('115119'),('115119'),('115120'),('115121'),('115121'),('115122'),('115122'),('116001'),('116003'),('116003'),('116003'),('116003'),('116004'),('116004'),('116005'),('116005'),('116006'),('116006'),('116006'),('116007'),('116007'),('116008'),('116008'),('116009'),('116009'),('116009'),('116010'),('116010'),('116010'),('116010'),('116011'),('116011'),('116011'),('116011'),('116012'),('116012'),('123001'),('123001'),('123001'),('123001'),('123001'),('124065'),('126001'),('126001'),('126001'),('126001'),('126001'),('126001'),('126001'),('126001'),('126002'),('126002'),('126002'),('126002'),('126002'),('126002'),('126002'),('126002'),('126003'),('126003'),('126003'),('126003'),('126003'),('126003'),('126003'),('126003'),('126003'),('126004'),('126004'),('126004'),('126004'),('126004'),('126004'),('126004'),('126004'),('126004'),('126004'),('126005'),('126005'),('126005'),('126005'),('126005'),('126005'),('126005'),('126005'),('126005'),('126006'),('126006'),('126006'),('126006'),('126006'),('126006'),('126006'),('126006'),('126006'),('126007'),('126007'),('126007'),('126007'),('126007'),('126007'),('126007'),('126008'),('126008'),('126008'),('126008'),('126008'),('126008'),('126008'),('126008'),('126009'),('126009'),('126009'),('126009'),('126009'),('126009'),('126009'),('126009'),('126010'),('126010'),('126010'),('126010'),('126010'),('126010'),('126010'),('126010'),('126010'),('126011'),('126011'),('126011'),('126011'),('126011'),('126011'),('126011'),('126012'),('126012'),('126012'),('126012'),('130001'),('130001'),('130001'),('130001'),('132001'),('132001'),('132001'),('132001'),('132001'),('132002'),('132002'),('132002'),('132002'),('132002'),('132002'),('132002'),('133001'),('133001'),('133008'),('133009'),('133010'),('133011'),('133011'),('133011'),('133011'),('133011'),('133011'),('133012'),('133015'),('133015'),('133015'),('133015'),('133016'),('133018'),('133018'),('133018'),('133018'),('133018'),('133019'),('133021'),('133021'),('133022'),('133022'),('133023'),('133023'),('133024'),('133024'),('133024'),('133024'),('133024'),('133024'),('133025'),('133027'),('133027'),('133027'),('133027'),('133027'),('133028'),('133028'),('133028'),('133029'),('133029'),('133029'),('133029'),('133029'),('133029'),('133030'),('133030'),('133031'),('133031'),('133031'),('134001'),('134001'),('134001'),('135001'),('135001'),('135001'),('135001'),('135001'),('135002'),('135002'),('135002'),('135004'),('135010'),('135010'),('135010'),('135010'),('135010'),('135010'),('137010'),('137011'),('137012'),('137014'),('137015'),('137015'),('137016'),('137019'),('139001'),('140001'),('140001'),('140001'),('140001'),('140001'),('140001'),('141001'),('141001'),('141001'),('141001'),('141001'),('141002'),('141002'),('141002'),('141002'),('141002'),('141003'),('141003'),('141003'),('141003'),('141003'),('141003'),('141003'),('141003'),('141006'),('141006'),('141006'),('141006'),('141006'),('141006'),('141006'),('141006'),('141007'),('141007'),('141007'),('141007'),('141007'),('141009'),('141009'),('141009'),('141009'),('141009'),('141011'),('141011'),('141011'),('141011'),('141011'),('141011'),('141012'),('141014'),('141014'),('141014'),('141014'),('141014'),('141014'),('141014'),('141014'),('141015'),('141015'),('141015'),('141015'),('141015'),('141016'),('141016'),('141016'),('141016'),('141016'),('141016'),('141017'),('141017'),('141017'),('141017'),('141017'),('141017'),('141018'),('141018'),('141018'),('141018'),('141019'),('141019'),('141019'),('141019'),('141020'),('141020'),('141020'),('141020'),('141020'),('141020'),('141020'),('141021'),('141021'),('141021'),('141021'),('141021'),('141021'),('141022'),('141022'),('141022'),('141022'),('141022'),('141022'),('141023'),('141023'),('141023'),('141023'),('141023'),('141023'),('141023'),('141024'),('141025'),('141025'),('141025'),('141026'),('141026'),('141026'),('141026'),('141026'),('141026'),('141027'),('141027'),('141027'),('141027'),('141027'),('141028'),('141028'),('145001'),('145001'),('145001'),('145001'),('145001'),('145001'),('145001'),('145001'),('145001'),('145002'),('145002'),('145002'),('145002'),('145002'),('145002'),('145002'),('145002'),('145002'),('145003'),('145003'),('145003'),('145003'),('145003'),('145003'),('145003'),('145003'),('145003'),('145003'),('145004'),('145004'),('145004'),('145004'),('145004'),('145004'),('145004'),('145004'),('145004'),('145005'),('145005'),('145005'),('145005'),('145005'),('145005'),('145005'),('145005'),('145005'),('145006'),('145006'),('145006'),('145006'),('145006'),('145006'),('145006'),('145006'),('145006'),('145008'),('145008'),('145008'),('145008'),('145008'),('145008'),('145008'),('145008'),('145009'),('145009'),('145009'),('145009'),('145009'),('145009'),('145009'),('145011'),('145011'),('145011'),('145011'),('145011'),('145011'),('145011'),('145011'),('145012'),('145012'),('145012'),('145012'),('145012'),('145012'),('145012'),('145012'),('145013'),('145013'),('145013'),('145013'),('145013'),('145013'),('145013'),('150009'),('150013'),('150014'),('150015'),('150015'),('150015'),('150016'),('150016'),('150017'),('150017'),('150017'),('150017'),('150020'),('152001'),('152001'),('152001'),('152002'),('152003'),('152003'),('152003'),('152003'),('152004'),('152005'),('152006'),('152006'),('152006'),('152006'),('152007'),('154001'),('154002'),('154002'),('155001'),('155001'),('155002'),('155003'),('155004'),('155004'),('155006'),('159001'),('159003'),('160001'),('160001'),('160001'),('160001'),('160002'),('160002'),('161001'),('162002'),('162002'),('162003'),('162003'),('162003'),('162003'),('162003'),('162007'),('162012'),('162012'),('162012'),('163001'),('163001'),('163001'),('163011'),('163015'),('163016'),('163016'),('165001'),('165001'),('165001'),('165001'),('165002'),('165002'),('165002'),('165002'),('165003'),('165003'),('165003'),('165004'),('165004'),('165004'),('165005'),('165005'),('165005'),('165006'),('165006'),('165006'),('165006'),('165007'),('165007'),('165007'),('165007'),('165008'),('165008'),('165008'),('165008'),('165009'),('165009'),('165009'),('165009'),('165010'),('165010'),('165010'),('165011'),('165011'),('165012'),('165012'),('165012'),('165013'),('165013'),('165013'),('165014'),('165014'),('165014'),('165015'),('165015'),('165015'),('165015'),('165016'),('165016'),('165016'),('165017'),('165017'),('165017'),('165017'),('165018'),('165018'),('165018'),('165018'),('165019'),('165019'),('165019'),('165019'),('165020'),('165020'),('165020'),('165020'),('165021'),('165021'),('165021'),('165021'),('165022'),('165022'),('165022'),('165023'),('165024'),('165024'),('165024'),('165025'),('165025'),('165025'),('165026'),('165026'),('165026'),('165028'),('165029'),('165030'),('165030'),('165030'),('165031'),('165031'),('165033'),('165033'),('165034'),('165034'),('165034'),('165035'),('165035'),('165035'),('165036'),('165036'),('165036'),('168003'),('168003'),('168004'),('168005'),('168014'),('169001'),('169001'),('169001'),('169001'),('169001'),('169001'),('169001'),('169001'),('169001'),('169001'),('169002'),('169002'),('169002'),('169002'),('169002'),('169002'),('169002'),('169002'),('169002'),('169002'),('169003'),('169003'),('169003'),('169003'),('169007'),('169007'),('169007'),('169007'),('169007'),('169007'),('169007'),('169007'),('169007'),('169007'),('169008'),('169008'),('169008'),('169008'),('169008'),('169008'),('169008'),('169009'),('169009'),('169009'),('169009'),('169010'),('171006'),('171006'),('171007'),('171007'),('171008'),('171008'),('171008'),('171009'),('171009'),('171009'),('172001'),('176001'),('176001'),('176001'),('176001'),('176001'),('176001'),('176001'),('176002'),('176002'),('176002'),('176002'),('176002'),('176003'),('176003'),('176003'),('176003'),('176003'),('176003'),('177001'),('177001'),('177001'),('177001'),('177001'),('177001'),('179007'),('179007'),('179012'),('179012'),('179012'),('179012'),('179012'),('179012'),('179013'),('179013'),('179013'),('179013'),('179013'),('179013'),('179042'),('179044'),('179045'),('180001'),('180013'),('180014'),('180014'),('180015'),('180017'),('180018'),('180020'),('180020'),('180021'),('180021'),('180027'),('180030'),('180033'),('180035'),('180036'),('180037'),('180038'),('180041'),('180042'),('180045'),('180045'),('180047'),('180048'),('180049'),('180050'),('180054'),('180060'),('180066'),('180067'),('180068'),('180070'),('182001'),('184001'),('184002'),('184005'),('184005'),('184005'),('184005'),('184006'),('184006'),('184006'),('184006'),('184008'),('184008'),('184008'),('184008'),('184009'),('184009'),('184009'),('184009'),('184010'),('184010'),('184010'),('184010'),('184011'),('184011'),('184011'),('184011'),('185001'),('185001'),('185001'),('185001'),('185001'),('185001'),('185001'),('185003'),('185003'),('185003'),('185003'),('185003'),('185003'),('185003'),('187001'),('191002'),('191002'),('192002'),('194003'),('197001'),('197001'),('197001'),('197001'),('197001'),('197001'),('197001'),('197002'),('197002'),('197002'),('197002'),('197002'),('197002'),('197002'),('197003'),('197003'),('197003'),('197003'),('197003'),('197003'),('197003'),('197004'),('197004'),('197004'),('197004'),('197004'),('197004'),('197004'),('197005'),('197005'),('197005'),('197005'),('197005'),('197005'),('197006'),('197006'),('197006'),('197006'),('197006'),('198001'),('198001'),('198001'),('198001'),('198001'),('198001'),('198003'),('198003'),('198003'),('198004'),('198004'),('198004'),('198004'),('198004'),('198004'),('198005'),('198005'),('198005'),('198005'),('198005'),('198005'),('198005'),('198006'),('198006'),('198006'),('198006'),('198006'),('198006'),('198007'),('198007'),('198007'),('198007'),('198007'),('198007'),('198007'),('198008'),('198008'),('198008'),('198008'),('198008'),('198008'),('198009'),('198009'),('198009'),('198009'),('198009'),('198009'),('198009'),('198010'),('198010'),('198010'),('198010'),('198010'),('198010'),('198011'),('198012'),('198012'),('198012'),('198012'),('198015'),('198015'),('198016'),('198016'),('198016'),('198016'),('198016'),('198016'),('198017'),('198017'),('198017'),('198017'),('198017'),('198017'),('201001'),('201001'),('201001'),('201001'),('201001'),('201002'),('202001'),('202001'),('203001'),('203001'),('203001'),('203001'),('203001'),('203001'),('203001'),('203002'),('203002'),('203002'),('203002'),('203003'),('203003'),('203003'),('203003'),('203003'),('203017'),('203017'),('203017'),('203017'),('203017'),('203017'),('203017'),('203017'),('203017'),('203018'),('203018'),('203018'),('203018'),('203018'),('203019'),('203019'),('203019'),('203019'),('203019'),('204001'),('204002'),('205001'),('205001'),('205001'),('205001'),('205001'),('205001'),('205001'),('208001'),('208001'),('208002'),('208002'),('208002'),('208003'),('208003'),('208003'),('208004'),('208004'),('208004'),('208004'),('208004'),('208004'),('208004'),('208005'),('208005'),('208005'),('208005'),('208005'),('209001'),('209001'),('209001'),('209001'),('209001'),('209002'),('209002'),('209002'),('209002'),('209002'),('209003'),('209003'),('209003'),('209003'),('209003'),('210001'),('210001'),('210001'),('210001'),('210001'),('210004'),('210004'),('210004'),('210004'),('210004'),('210004'),('210009'),('210010'),('212001'),('212001'),('212002'),('212002'),('212002'),('212002'),('212003'),('212003'),('212003'),('212004'),('212004'),('212004'),('212005'),('212005'),('212005'),('212005'),('212005'),('212006'),('212006'),('212006'),('212007'),('212007'),('212008'),('212008'),('212008'),('212008'),('212009'),('212009'),('212009'),('212009'),('212010'),('212010'),('212010'),('212010'),('212011'),('212011'),('212012'),('212012'),('212013'),('212013'),('212013'),('218001'),('218004'),('218009'),('218011'),('218011'),('218015'),('218020'),('218021'),('218021'),('218022'),('218022'),('218022'),('218023'),('218024'),('218025'),('218026'),('218026'),('218027'),('218028'),('218029'),('218029'),('218029'),('218030'),('218031'),('221001'),('221001'),('221001'),('221001'),('221001'),('221001'),('221002'),('221002'),('221002'),('221002'),('221002'),('221002'),('221003'),('221003'),('221003'),('221003'),('221003'),('221003'),('221004'),('221004'),('221004'),('221004'),('221004'),('221004'),('221005'),('221005'),('221005'),('221005'),('221005'),('221006'),('221006'),('221006'),('221006'),('221006'),('221007'),('221007'),('221007'),('221007'),('221007'),('221007'),('221008'),('221008'),('221008'),('221008'),('221008'),('221008'),('221009'),('221009'),('221009'),('221009'),('221009'),('221009'),('221010'),('221010'),('221010'),('221010'),('221011'),('221011'),('221011'),('221011'),('221012'),('221012'),('221012'),('221012'),('221012'),('221012'),('221013'),('221013'),('221013'),('221013'),('221013'),('221013'),('223003'),('223003'),('224001'),('224001'),('224002'),('224002'),('224003'),('224007'),('224008'),('225001'),('225002'),('225002'),('225002'),('225003'),('225003'),('225003'),('225003'),('225004'),('225004'),('225004'),('225005'),('225005'),('225005'),('225005'),('225005'),('225005'),('225006'),('225006'),('225006'),('225007'),('225007'),('225007'),('225008'),('225008'),('225008'),('225008'),('225008'),('225009'),('225009'),('225009'),('225010'),('225010'),('225010'),('225011'),('225011'),('225011'),('225011'),('225011'),('225012'),('225012'),('225012'),('225012'),('225012'),('225012'),('225013'),('225013'),('226001'),('226002'),('226003'),('226003'),('226005'),('226005'),('226006'),('226007'),('226007'),('226007'),('226007'),('227011'),('227015'),('227015'),('227041'),('227045'),('227052'),('227056'),('227063'),('227064'),('227066'),('227067'),('227069'),('227071'),('227073'),('227085'),('227116'),('227119'),('227131'),('227133'),('227147'),('229005'),('229005'),('229005'),('233003'),('233004'),('235001'),('235001'),('235002'),('235003'),('235003'),('235003'),('235004'),('235005'),('235005'),('235005'),('235005'),('235005'),('235005'),('235005'),('236001'),('236001'),('236001'),('236001'),('236002'),('236003'),('236003'),('236003'),('236003'),('236003'),('236003'),('238002'),('238002'),('238002'),('238002'),('238002'),('238002'),('238003'),('238003'),('238003'),('238003'),('238003'),('238003'),('238004'),('238004'),('238004'),('238004'),('238004'),('238005'),('238005'),('238005'),('238007'),('238007'),('238007'),('238007'),('238007'),('238007'),('238007'),('238008'),('238008'),('238008'),('238008'),('238008'),('238008'),('238008'),('334005'),('334006'),('337001'),('337001'),('337001'),('337002'),('337002'),('337003'),('337003'),('337003'),('337004'),('343001'),('343001'),('344001'),('344002'),('344003'),('344004'),('344005'),('344005'),('345001'),('345001'),('348001'),('348004'),('348005'),('348005'),('349001'),('349001'),('349002'),('349002'),('349002'),('350001'),('353002'),('353002'),('353002'),('353003'),('355001'),('355002'),('355005'),('355006'),('355006'),('356001'),('358001'),('358001'),('358001'),('359001'),('359001'),('359002'),('359002'),('359002'),('359002'),('360001'),('360001'),('360002'),('360002'),('360003'),('360003'),('360004'),('360004'),('360005'),('360005'),('360005'),('366001'),('366002'),('366002'),('366003'),('366004'),('369001'),('369001'),('373001'),('373002'),('373002'),('373003'),('373003'),('373005'),('373007'),('373008'),('373009'),('373009'),('373010'),('373010'),('373010'),('373011'),('373011'),('373011'),('373011'),('373012'),('373012'),('373012'),('373013'),('373013'),('373014'),('373014'),('373015'),('373015'),('373015'),('373015'),('373017'),('373017'),('373017'),('373017'),('373018'),('373021'),('374002'),('374004'),('374006'),('374007'),('374008'),('374009'),('374010'),('374011'),('374012'),('374015'),('374016'),('382001'),('382002'),('382002'),('384001'),('386001'),('386001'),('386001'),('386001'),('386001'),('386001'),('386001'),('386002'),('386002'),('386002'),('386002'),('386002'),('386002'),('386002'),('386003'),('386003'),('386003'),('386003'),('386003'),('386003'),('386003'),('386003'),('386003'),('386004'),('386004'),('386004'),('386004'),('386004'),('386004'),('386004'),('386004'),('386005'),('386005'),('386005'),('386005'),('386005'),('386005'),('386005'),('386006'),('386006'),('386006'),('386006'),('386006'),('386006'),('386007'),('386007'),('386007'),('386007'),('386007'),('386007'),('386007'),('386007'),('386007'),('386008'),('386008'),('386008'),('386008'),('386008'),('386008'),('386008'),('386008'),('386009'),('386009'),('386009'),('386010'),('386010'),('386010'),('386010'),('386010'),('386010'),('386010'),('386010'),('386011'),('386011'),('386011'),('386011'),('386011'),('386011'),('386011'),('386011'),('386011'),('386012'),('386012'),('386012'),('386012'),('386012'),('386012'),('386012'),('386012'),('386012'),('386013'),('386013'),('386013'),('386013'),('386013'),('386013'),('386013'),('386014'),('386014'),('386014'),('386014'),('389001'),('389002'),('389002'),('389003'),('389003'),('389003'),('389003'),('389004'),('389004'),('389004'),('389004'),('392001'),('393001'),('393002'),('393002'),('393003'),('393004'),('395001'),('395001'),('397001'),('397001'),('397001'),('397002'),('399001'),('399001'),('399001'),('399001'),('399001'),('399001'),('399001'),('399002'),('399002'),('399002'),('399002'),('399002'),('399002'),('399002'),('399003'),('400001'),('400001'),('400001'),('400001'),('400002'),('403002'),('504001'),('504001'),('504002'),('504002'),('504002'),('504004'),('504004'),('504005'),('504006'),('504007'),('504007'),('504007'),('504008'),('504008'),('504009'),('504009'),('504009'),('504009'),('504009'),('504010'),('504011'),('504011'),('504012'),('504012'),('504014'),('504014'),('504014'),('504014'),('504014'),('504014'),('504014'),('504014'),('504017'),('504017'),('504021'),('504021'),('504021'),('504021'),('504021'),('504021'),('504021'),('504022'),('504023'),('504023'),('504024'),('504024'),('504025'),('504025'),('506001'),('506001'),('506001'),('506001'),('506001'),('506001'),('506002'),('506002'),('506002'),('506002'),('506002'),('511001'),('511001'),('511001'),('511001'),('511001'),('511001'),('511001'),('511002'),('511002'),('511002'),('511002'),('511002'),('511002'),('511002'),('511003'),('511003'),('511003'),('511003'),('511003'),('511003'),('511004'),('511004'),('511004'),('511004'),('511004'),('511004'),('511004'),('511005'),('511005'),('511005'),('511005'),('511005'),('511005'),('511005'),('511006'),('511006'),('511006'),('511006'),('511006'),('511006'),('511006'),('511007'),('511007'),('511007'),('511007'),('511007'),('511008'),('511008'),('511008'),('511008'),('511008'),('511008'),('511009'),('511009'),('511009'),('511009'),('511009'),('511009'),('511010'),('511010'),('511010'),('511010'),('511010'),('511010'),('511011'),('511011'),('511011'),('511011'),('511011'),('511011'),('511012'),('511012'),('511012'),('511012'),('511012'),('511012'),('511012'),('511013'),('511013'),('511013'),('511013'),('511013'),('511013'),('511013'),('511014'),('511014'),('511014'),('511014'),('511014'),('511017'),('511018'),('511020'),('511021'),('511022'),('511024'),('511028'),('511029'),('511029'),('511029'),('511029'),('511029'),('511029'),('513001'),('513001'),('513001'),('513001'),('513001'),('513001'),('513001'),('513001'),('513002'),('513002'),('513002'),('513002'),('513002'),('513002'),('513003'),('513003'),('513003'),('513003'),('513003'),('513003'),('513003'),('513003'),('513004'),('513004'),('513004'),('515001'),('515001'),('515001'),('515001'),('515001'),('515002'),('515002'),('515003'),('515003'),('515007'),('515007'),('515008'),('515011'),('515011'),('515011'),('515011'),('515011'),('515011'),('515012'),('515012'),('515012'),('515012'),('515013'),('515013'),('515013'),('515013'),('515013'),('515014'),('515014'),('515014'),('515014'),('515014'),('515015'),('515015'),('515015'),('515015'),('515015'),('518001'),('518002'),('521001'),('521002'),('521002'),('521002'),('521003'),('521003'),('521003'),('521003'),('521004'),('521004'),('521004'),('521004'),('521005'),('521005'),('521005'),('521005'),('521006'),('521006'),('521006'),('521009'),('521010'),('521010'),('521010'),('521010'),('521011'),('521011'),('521011'),('521011'),('521012'),('521013'),('521013'),('521015'),('521016'),('521016'),('523001'),('523001'),('523001'),('523001'),('523001'),('523001'),('523001'),('523002'),('523002'),('523002'),('523002'),('523002'),('523002'),('523003'),('523003'),('523003'),('523003'),('523003'),('523003'),('523003'),('523004'),('523004'),('523004'),('523004'),('523004'),('523004'),('523005'),('523005'),('523005'),('523005'),('523005'),('523005'),('523005'),('523005'),('523006'),('523006'),('523006'),('523006'),('523006'),('523006'),('523006'),('523007'),('523007'),('523007'),('523007'),('523007'),('523007'),('523007'),('524001'),('700001'),('701001'),('701002'),('701003'),('702001'),('702002'),('702004'),('702005'),('704001'),('704004'),('705001'),('706001'),('706002'),('707001'),('707002'),('707003'),('708001'),('710001'),('710002'),('711001'),('711002'),('712001'),('714001'),('714002'),('715001'),('719001'),('719002'),('991002'),('991002'),('991002'),('991003'),('991003'),('991003'),('991003'),('991003'),('991003'),('991003'),('991004'),('991004'),('991004'),('991005'),('991005'),('991005'),('991006'),('991007'),('995001'),('995001'),('995001'),('995001'),('995001'),('995001'),('995001'),('995001'),('995001'),('995001'),('995001'),('996001'),('996001'),('996001'),('996001'),('996001'),('996001'),('996001'),('996001'),('996002'),('996002'),('996003'),('996003'),('996003'),('996003'),('996003'),('998001'),('998001'),('998001'),('998001'),('998001'),('998001'),('998001'),('998001'),('998001'),('998001'),('998002'),('998002'),('998002'),('998002'),('998002'),('998002'),('998002'),('998002'),('998002'),('998002'),('998003'),('998003'),('998003'),('998003'),('998003'),('998003'),('998003'),('998003'),('998004'),('998004'),('998005'),('998005'),('998006'),('998007'),('999001'),('999001'),('999001'),('999001'),('999001'),('999001'),('999001'),('999001'),('999001'),('999001'),('999001'),('999002'),('999002'),('011017'),('011017'),('011017'),('011017'),('011017'),('011017'),('011017'),('011018'),('011018'),('011018'),('011018'),('034001'),('034001'),('034002'),('034002'),('071010'),('071010'),('071010'),('519001'),('126013'),('126013'),('126013'),('126013'),('126013'),('184012'),('184012'),('184012'),('404001'),('405002'),('405002'),('405001'),('405003'),('405006'),('240011'),('240011'),('240011'),('240011'),('240011'),('240011'),('240010'),('240010'),('240010'),('240009'),('240009'),('240009'),('240009'),('240008'),('240008'),('240008'),('240007'),('240007'),('240007'),('240007'),('240007'),('240007'),('240005'),('240005'),('240005'),('240005'),('240005'),('240004'),('240004'),('240004'),('240004'),('240004'),('240003'),('240003'),('240003'),('240003'),('240002'),('240002'),('240002'),('240002'),('240002'),('240002'),('240002'),('240001'),('240001'),('240001'),('240001'),('240001'),('240012'),('240012'),('240012'),('240012'),('240012'),('240013'),('240014'),('240015'),('240015'),('240015'),('240015'),('240015'),('240015'),('240015'),('240015'),('240016'),('240016'),('240016'),('240016'),('240016'),('240016'),('240017'),('240017'),('240017'),('357001'),('357001'),('235006'),('235006'),('235007'),('235007'),('235007'),('235007'),('235007'),('056023'),('056023'),('056023'),('056023'),('056023'),('046015'),('019005'),('019005'),('126014'),('126014'),('126014'),('126014'),('126014'),('126014'),('241003'),('241003'),('241003'),('241003'),('241003'),('241003'),('241002'),('241002'),('241002'),('241002'),('241002'),('241002'),('241001'),('241001'),('241001'),('241001'),('241001'),('240020'),('240020'),('240020'),('240020'),('240020'),('240020'),('240019'),('240019'),('240019'),('242001'),('242002'),('242004'),('242005'),('242006'),('089002'),('089002'),('089002'),('089002'),('089002'),('089002'),('406001'),('406002'),('406003'),('406004'),('406004'),('243001'),('243005'),('243006'),('243007'),('243008'),('408001'),('408001'),('408001'),('408001'),('408001'),('366005'),('366005'),('016035'),('016035'),('016035'),('016035'),('077010'),('996004'),('996004'),('996004'),('996004'),('996004'),('996004'),('996004'),('996004'),('025064'),('025064'),('025064'),('025064'),('011019'),('011019'),('011019'),('011019'),('011019'),('115123'),('115123'),('504026'),('039007'),('039009'),('039008'),('039008'),('039010'),('039010'),('039011'),('039012'),('180072'),('240021'),('240021'),('240021'),('240021'),('240021'),('240021'),('240021'),('240023'),('240023'),('240023'),('240023'),('405008'),('405008'),('525002'),('410002'),('410002'),('410004'),('410005'),('410005'),('410006'),('410007'),('410007'),('410008'),('410009'),('410010'),('410011'),('410011'),('410012'),('410012'),('410013'),('410013'),('410014'),('410014'),('410016'),('410016'),('344006'),('240031'),('240031'),('240031'),('240031'),('240030'),('240030'),('240030'),('240030'),('240029'),('240029'),('240029'),('240029'),('240028'),('240028'),('240028'),('240028'),('240027'),('240027'),('240026'),('240026'),('240026'),('240025'),('240025'),('240025'),('240025'),('240024'),('240024'),('240034'),('240034'),('240034'),('240033'),('240033'),('240033'),('240032'),('240032'),('240032'),('240032'),('411001'),('411002'),('203020'),('069025'),('069025'),('069025'),('069025'),('069025'),('069025'),('244001'),('244001'),('244001'),('244001'),('244001'),('244001'),('244001'),('244001'),('244001'),('244001'),('244001'),('244002'),('244002'),('244002'),('244002'),('244002'),('244002'),('244002'),('244002'),('244002'),('244002'),('244002'),('244009'),('244009'),('244009'),('244009'),('244009'),('244009'),('244009'),('244009'),('244009'),('244009'),('244009'),('244008'),('244008'),('244008'),('244008'),('244008'),('244008'),('244008'),('244008'),('244008'),('244008'),('244008'),('244007'),('244007'),('244007'),('244007'),('244007'),('244007'),('244007'),('244007'),('244007'),('244007'),('244007'),('244006'),('244006'),('244006'),('244006'),('244006'),('244006'),('244006'),('244006'),('244006'),('244006'),('244006'),('244004'),('244004'),('244004'),('244004'),('244004'),('244004'),('244004'),('244004'),('244004'),('244004'),('244004'),('244003'),('244003'),('244003'),('244003'),('244003'),('244003'),('244003'),('244003'),('244003'),('244003'),('244003'),('244014'),('244014'),('244014'),('244014'),('244014'),('244014'),('244014'),('244014'),('244013'),('244013'),('244013'),('244013'),('244013'),('244013'),('244013'),('244013'),('244012'),('244012'),('244012'),('244012'),('244012'),('244012'),('244012'),('244012'),('244011'),('244011'),('244011'),('244011'),('244011'),('244011'),('244011'),('244011'),('244016'),('244016'),('244016'),('244016'),('244016'),('244016'),('244016'),('244016'),('244016'),('244016'),('244016'),('244017'),('244017'),('244017'),('244017'),('244017'),('244017'),('244017'),('244017'),('244017'),('240040'),('240037'),('405009'),('405009'),('405009'),('405010'),('405010'),('240043'),('240043'),('504028'),('504040'),('800001'),('410019'),('410019'),('410020'),('410020'),('410020'),('410021'),('410021'),('244018'),('244018'),('244018'),('244018'),('244018'),('244018'),('244018'),('244018'),('244018'),('244018'),('244018'),('244019'),('244019'),('244019'),('244019'),('244019'),('244019'),('244019'),('244019'),('244019'),('244019'),('244019'),('244020'),('244020'),('244020'),('244020'),('244020'),('244020'),('244020'),('244020'),('413001'),('344007'),('082045'),('082045'),('082045'),('082045'),('082045'),('010031'),('010031'),('010031'),('010031'),('010032'),('010032'),('010032'),('010032'),('010033'),('010033'),('010033'),('010033'),('010033'),('010034'),('010034'),('010034'),('010034'),('010035'),('010035'),('010035'),('010035'),('504044'),('515016'),('515016'),('515016'),('515016'),('801002'),('801003'),('801004'),('801005'),('802001'),('801001'),('414001'),('141029'),('803001'),('803002'),('803004'),('803005'),('803006'),('803007'),('803008'),('803009'),('803013'),('803014'),('803015'),('803016'),('803017'),('410022'),('410023'),('410023'),('803019'),('415002'),('415001'),('244021'),('244021'),('244021'),('244021'),('244021'),('244021'),('244021'),('011020'),('011020'),('011020'),('011020'),('011023'),('011023'),('011023'),('011023'),('011022'),('011022'),('011022'),('011022'),('011022'),('011022'),('011021'),('011021'),('011021'),('011021'),('025065'),('025065'),('025065'),('025065'),('165037'),('165037'),('165038'),('165038'),('165038'),('165039'),('416001'),('416001'),('416001'),('416001'),('416001'),('416002'),('416003'),('417001'),('418001'),('504045'),('504045'),('504045'),('803022'),('240022'),('240022'),('240022'),('240022'),('420001'),('420001'),('420001'),('420001'),('804010'),('804005'),('804002'),('804018'),('804013'),('511019'),('511016'),('511015'),('511032'),('511031'),('511030'),('511027'),('511026'),('511025'),('511033'),('511023'),('133034'),('133034'),('133034'),('133033'),('169011'),('169011'),('169011'),('169011'),('169011'),('344008'),('244022'),('244022'),('244022'),('244022'),('244022'),('244022'),('244022'),('244026'),('244026'),('244026'),('244026'),('244026'),('244026'),('244025'),('244025'),('244025'),('244025'),('244025'),('244025'),('244025'),('244025'),('244030'),('244030'),('244030'),('244030'),('244030'),('244030'),('244030'),('244030'),('244023'),('244023'),('244023'),('244023'),('244023'),('244023'),('244024'),('244024'),('244024'),('244024'),('244024'),('244024'),('244024'),('244024'),('244027'),('244027'),('244027'),('244027'),('244027'),('244027'),('244027'),('244027'),('244028'),('244028'),('244028'),('244028'),('244028'),('244028'),('244028'),('244028'),('244029'),('244029'),('244029'),('244029'),('244029'),('244029'),('244029'),('244029'),('244031'),('244031'),('244031'),('244031'),('244031'),('244031'),('244031'),('244031'),('082046'),('082046'),('082046'),('082046'),('082047'),('082047'),('082048'),('082048'),('126015'),('126015'),('126016'),('126016'),('126016'),('126016'),('126016'),('416005'),('421001'),('421001'),('421002'),('016037'),('016037'),('016037'),('016037'),('016036'),('016036'),('016036'),('016036'),('115124'),('115124'),('115126'),('240049'),('240049'),('240048'),('240048'),('240047'),('240047'),('240046'),('240046'),('240045'),('240044'),('244032'),('244033'),('422002'),('422004'),('422004'),('422004'),('422005'),('422005'),('184013'),('184013'),('184013'),('805001'),('805002'),('805003'),('805004'),('805005'),('056024'),('056024'),('056024'),('423001'),('344010'),('235009'),('235009'),('235009'),('235009'),('212014'),('212014'),('056025'),('056025'),('056025'),('056026'),('056026'),('056026'),('056026'),('056026'),('056026'),('244034'),('244034'),('244034'),('244034'),('244034'),('244034'),('244035'),('244035'),('244035'),('244035'),('244035'),('244035'),('244035'),('244036'),('244036'),('244036'),('244036'),('244036'),('244036'),('244036'),('244037'),('244037'),('244037'),('244037'),('244037'),('244037'),('244037'),('244038'),('244038'),('244038'),('244038'),('244038'),('244038'),('244038'),('244039'),('244039'),('244039'),('244039'),('244039'),('244039'),('244039'),('203015'),('245002'),('245002'),('245001'),('245001'),('056029'),('056030'),('056032'),('424001'),('056034'),('056034'),('056034'),('056034'),('056033'),('056033'),('056033'),('805006'),('805007'),('805008'),('805009'),('805010'),('422008'),('422008'),('422007'),('422007'),('422006'),('422006'),('422010'),('422009'),('422009'),('422011'),('422011'),('209004'),('209004'),('150022'),('100002'),('056035'),('056035'),('056035'),('023036'),('023036'),('185005'),('246001'),('246001'),('247001'),('247001'),('247001'),('247001'),('247001'),('247001'),('247001'),('247002'),('247002'),('425001'),('416006'),('416006'),('165042'),('165041'),('165040'),('165043'),('010040'),('010039'),('010038'),('010036'),('248001'),('248002'),('248003'),('248004'),('248005'),('249001'),('249003'),('249004'),('249005'),('250007'),('250001'),('250002'),('250003'),('250004'),('250005'),('250006'),('250008'),('250009'),('250010'),('250011'),('250012'),('250013'),('251001'),('251002'),('806001'),('806002'),('235010'),('243009'),('249007'),('249008'),('249009'),('011024'),('011025'),('429001'),('429001'),('429002'),('429002'),('429003'),('429003');
+select field from t1 group by field;
field
001001
001010
@@ -1614,3 +1621,4 @@ field
429001
429002
429003
+drop table t1;
diff --git a/mysql-test/r/type_float.result b/mysql-test/r/type_float.result
index 30a2f884557..4dbfa1b9f66 100644
--- a/mysql-test/r/type_float.result
+++ b/mysql-test/r/type_float.result
@@ -1,12 +1,21 @@
+SELECT 10,10.0,10.,.1e+2,100.0e-1;
10 10.0 10. .1e+2 100.0e-1
10 10.0 10 10 10
+SELECT 6e-05, -6e-05, --6e-05, -6e-05+1.000000;
6e-05 -6e-05 --6e-05 -6e-05+1.000000
6e-05 -6e-05 6e-05 0.99994
+SELECT 1e1,1.e1,1.0e1,1e+1,1.e+1,1.0e+1,1e-1,1.e-1,1.0e-1;
1e1 1.e1 1.0e1 1e+1 1.e+1 1.0e+1 1e-1 1.e-1 1.0e-1
10 10 10 10 10 10 0.1 0.1 0.1
+drop table if exists t1;
+create table t1 (f1 float(24),f2 float(52));
+show full columns from t1;
Field Type Null Key Default Extra Privileges
f1 float YES NULL select,insert,update,references
f2 double YES NULL select,insert,update,references
+insert into t1 values(10,10),(1e+5,1e+5),(1234567890,1234567890),(1e+10,1e+10),(1e+15,1e+15),(1e+20,1e+20),(1e+50,1e+50),(1e+150,1e+150);
+insert into t1 values(-10,-10),(1e-5,1e-5),(1e-10,1e-10),(1e-15,1e-15),(1e-20,1e-20),(1e-50,1e-50),(1e-150,1e-150);
+select * from t1;
f1 f2
10 10
100000 100000
@@ -23,28 +32,43 @@ f1 f2
1e-20 1e-20
0 1e-50
0 1e-150
+drop table t1;
+create table t1 (datum double);
+insert into t1 values (0.5),(1.0),(1.5),(2.0),(2.5);
+select * from t1;
datum
0.5
1
1.5
2
2.5
+select * from t1 where datum < 1.5;
datum
0.5
1
+select * from t1 where datum > 1.5;
datum
2
2.5
+select * from t1 where datum = 1.5;
datum
1.5
+drop table t1;
+create table t1 (a decimal(7,3) not null, key (a));
+insert into t1 values ("0"),("-0.00"),("-0.01"),("-0.002"),("1");
+select a from t1 order by a;
a
-0.010
-0.002
-0.000
0.000
1.000
+select min(a) from t1;
min(a)
-0.010
+drop table t1;
+create table t1 (f float, f2 float(24), f3 float(6,2), d double, d2 float(53), d3 double(10,3), de decimal, de2 decimal(6), de3 decimal(5,2), n numeric, n2 numeric(8), n3 numeric(5,6));
+show full columns from t1;
Field Type Null Key Default Extra Privileges
f float YES NULL select,insert,update,references
f2 float YES NULL select,insert,update,references
@@ -58,11 +82,20 @@ de3 decimal(5,2) YES NULL select,insert,update,references
n decimal(10,0) YES NULL select,insert,update,references
n2 decimal(8,0) YES NULL select,insert,update,references
n3 decimal(8,6) YES NULL select,insert,update,references
+drop table t1;
+create table t1 (a decimal(7,3) not null, key (a));
+insert into t1 values ("0"),("-0.00"),("-0.01"),("-0.002"),("1");
+select a from t1 order by a;
a
-0.010
-0.002
-0.000
0.000
1.000
+select min(a) from t1;
min(a)
-0.010
+drop table t1;
+create table t1 (f float(54));
+Incorrect column specifier for column 'f'
+drop table if exists t1;
diff --git a/mysql-test/r/type_ranges.result b/mysql-test/r/type_ranges.result
index abb8ef8cb09..fc7cc5255cf 100644
--- a/mysql-test/r/type_ranges.result
+++ b/mysql-test/r/type_ranges.result
@@ -1,3 +1,43 @@
+drop table if exists t1,t2,t3;
+CREATE TABLE t1 (
+auto int(5) unsigned DEFAULT 0 NOT NULL auto_increment,
+string char(10) default "hello",
+tiny tinyint(4) DEFAULT '0' NOT NULL ,
+short smallint(6) DEFAULT '1' NOT NULL ,
+medium mediumint(8) DEFAULT '0' NOT NULL,
+long_int int(11) DEFAULT '0' NOT NULL,
+longlong bigint(13) DEFAULT '0' NOT NULL,
+real_float float(13,1) DEFAULT 0.0 NOT NULL,
+real_double double(16,4),
+utiny tinyint(3) unsigned DEFAULT '0' NOT NULL,
+ushort smallint(5) unsigned zerofill DEFAULT '00000' NOT NULL,
+umedium mediumint(8) unsigned DEFAULT '0' NOT NULL,
+ulong int(11) unsigned DEFAULT '0' NOT NULL,
+ulonglong bigint(13) unsigned DEFAULT '0' NOT NULL,
+time_stamp timestamp,
+date_field date,
+time_field time,
+date_time datetime,
+blob_col blob,
+tinyblob_col tinyblob,
+mediumblob_col mediumblob not null,
+longblob_col longblob not null,
+options enum('one','two','tree') not null,
+flags set('one','two','tree') not null,
+PRIMARY KEY (auto),
+KEY (utiny),
+KEY (tiny),
+KEY (short),
+KEY any_name (medium),
+KEY (longlong),
+KEY (real_float),
+KEY (ushort),
+KEY (umedium),
+KEY (ulong),
+KEY (ulonglong,ulong),
+KEY (options,flags)
+);
+show full fields from t1;
Field Type Null Key Default Extra Privileges
auto int(5) unsigned PRI NULL auto_increment select,insert,update,references
string varchar(10) YES hello select,insert,update,references
@@ -23,21 +63,34 @@ mediumblob_col mediumblob select,insert,update,references
longblob_col longblob select,insert,update,references
options enum('one','two','tree') MUL one select,insert,update,references
flags set('one','two','tree') select,insert,update,references
-Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Comment
-t1 0 PRIMARY 1 auto A 0 NULL NULL
-t1 1 utiny 1 utiny A NULL NULL NULL
-t1 1 tiny 1 tiny A NULL NULL NULL
-t1 1 short 1 short A NULL NULL NULL
-t1 1 any_name 1 medium A NULL NULL NULL
-t1 1 longlong 1 longlong A NULL NULL NULL
-t1 1 real_float 1 real_float A NULL NULL NULL
-t1 1 ushort 1 ushort A NULL NULL NULL
-t1 1 umedium 1 umedium A NULL NULL NULL
-t1 1 ulong 1 ulong A NULL NULL NULL
-t1 1 ulonglong 1 ulonglong A NULL NULL NULL
-t1 1 ulonglong 2 ulong A NULL NULL NULL
-t1 1 options 1 options A NULL NULL NULL
-t1 1 options 2 flags A NULL NULL NULL
+show keys from t1;
+Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
+t1 0 PRIMARY 1 auto A 0 NULL NULL BTREE
+t1 1 utiny 1 utiny A NULL NULL NULL BTREE
+t1 1 tiny 1 tiny A NULL NULL NULL BTREE
+t1 1 short 1 short A NULL NULL NULL BTREE
+t1 1 any_name 1 medium A NULL NULL NULL BTREE
+t1 1 longlong 1 longlong A NULL NULL NULL BTREE
+t1 1 real_float 1 real_float A NULL NULL NULL BTREE
+t1 1 ushort 1 ushort A NULL NULL NULL BTREE
+t1 1 umedium 1 umedium A NULL NULL NULL BTREE
+t1 1 ulong 1 ulong A NULL NULL NULL BTREE
+t1 1 ulonglong 1 ulonglong A NULL NULL NULL BTREE
+t1 1 ulonglong 2 ulong A NULL NULL NULL BTREE
+t1 1 options 1 options A NULL NULL NULL BTREE
+t1 1 options 2 flags A NULL NULL NULL BTREE
+CREATE UNIQUE INDEX test on t1 ( auto ) ;
+CREATE INDEX test2 on t1 ( ulonglong,ulong) ;
+CREATE INDEX test3 on t1 ( medium ) ;
+DROP INDEX test ON t1;
+insert into t1 values (10, 1,1,1,1,1,1,1,1,1,1,1,1,1,NULL,0,0,0,1,1,1,1,'one','one');
+insert into t1 values (NULL,2,2,2,2,2,2,2,2,2,2,2,2,2,NULL,NULL,NULL,NULL,NULL,NULL,2,2,'two','two,one');
+insert into t1 values (0,1/3,3,3,3,3,3,3,3,3,3,3,3,3,NULL,'19970303','10:10:10','19970303 101010','','','','3',3,3);
+insert into t1 values (0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,NULL,19970807,080706,19970403090807,-1,-1,-1,'-1',-1,-1);
+insert into t1 values (0,-4294967295,-4294967295,-4294967295,-4294967295,-4294967295,-4294967295,-4294967295,-4294967295,-4294967295,-4294967295,-4294967295,-4294967295,-4294967295,NULL,0,0,0,-4294967295,-4294967295,-4294967295,'-4294967295',0,"one,two,tree");
+insert into t1 values (0,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,NULL,0,0,0,4294967295,4294967295,4294967295,'4294967295',0,0);
+insert into t1 (tiny) values (1);
+select auto,string,tiny,short,medium,long_int,longlong,real_float,real_double,utiny,ushort,umedium,ulong,ulonglong,mod(floor(time_stamp/1000000),1000000)-mod(curdate(),1000000),date_field,time_field,date_time,blob_col,tinyblob_col,mediumblob_col,longblob_col from t1;
auto string tiny short medium long_int longlong real_float real_double utiny ushort umedium ulong ulonglong mod(floor(time_stamp/1000000),1000000)-mod(curdate(),1000000) date_field time_field date_time blob_col tinyblob_col mediumblob_col longblob_col
10 1 1 1 1 1 1 1.0 1.0000 1 00001 1 1 1 0 0000-00-00 00:00:00 0000-00-00 00:00:00 1 1 1 1
11 2 2 2 2 2 2 2.0 2.0000 2 00002 2 2 2 0 NULL NULL NULL NULL NULL 2 2
@@ -46,6 +99,27 @@ auto string tiny short medium long_int longlong real_float real_double utiny ush
14 -429496729 -128 -32768 -8388608 -2147483648 -4294967295 -4294967296.0 -4294967295.0000 0 00000 0 0 18446744069414584321 0 0000-00-00 00:00:00 0000-00-00 00:00:00 -4294967295 -4294967295 -4294967295 -4294967295
15 4294967295 127 32767 8388607 2147483647 4294967295 4294967296.0 4294967295.0000 255 65535 16777215 4294967295 4294967295 0 0000-00-00 00:00:00 0000-00-00 00:00:00 4294967295 4294967295 4294967295 4294967295
16 hello 1 1 0 0 0 0.0 NULL 0 00000 0 0 0 0 NULL NULL NULL NULL NULL
+ALTER TABLE t1
+add new_field char(10) default "new" not null,
+change blob_col new_blob_col varchar(20),
+change date_field date_field char(10),
+alter column string set default "new default",
+alter short drop default,
+DROP INDEX utiny,
+DROP INDEX ushort,
+DROP PRIMARY KEY,
+DROP FOREIGN KEY any_name,
+ADD INDEX (auto);
+LOCK TABLES t1 WRITE;
+ALTER TABLE t1
+RENAME as t2,
+DROP longblob_col;
+UNLOCK TABLES;
+ALTER TABLE t2 rename as t3;
+LOCK TABLES t3 WRITE ;
+ALTER TABLE t3 rename as t1;
+UNLOCK TABLES;
+select auto,new_field,new_blob_col,date_field from t1 ;
auto new_field new_blob_col date_field
10 new 1 0000-00-00
11 new NULL NULL
@@ -54,6 +128,15 @@ auto new_field new_blob_col date_field
14 new -4294967295 0000-00-00
15 new 4294967295 0000-00-00
16 new NULL NULL
+CREATE TABLE t2 (
+auto int(5) unsigned NOT NULL DEFAULT 0 auto_increment,
+string char(20),
+mediumblob_col mediumblob not null,
+new_field char(2),
+PRIMARY KEY (auto)
+);
+INSERT INTO t2 (string,mediumblob_col,new_field) SELECT string,mediumblob_col,new_field from t1 where auto > 10;
+select * from t2;
auto string mediumblob_col new_field
1 2 2 ne
2 0.33 ne
@@ -61,21 +144,30 @@ auto string mediumblob_col new_field
4 -429496729 -4294967295 ne
5 4294967295 4294967295 ne
6 hello ne
+select distinct flags from t1;
flags
one,two,tree
one
one,two
+select flags from t1 where find_in_set("two",flags)>0;
flags
one,two,tree
one,two,tree
one,two
one,two
+select flags from t1 where find_in_set("unknown",flags)>0;
flags
+select options,flags from t1 where options="ONE" and flags="ONE";
options flags
one one
+select options,flags from t1 where options="one" and flags="one";
options flags
one one
+drop table t2;
+create table t2 select * from t1;
+update t2 set string="changed" where auto=16;
+show full columns from t1;
Field Type Null Key Default Extra Privileges
auto int(5) unsigned MUL NULL auto_increment select,insert,update,references
string varchar(10) YES new defaul select,insert,update,references
@@ -101,6 +193,7 @@ mediumblob_col mediumblob select,insert,update,references
options enum('one','two','tree') MUL one select,insert,update,references
flags set('one','two','tree') select,insert,update,references
new_field varchar(10) new select,insert,update,references
+show full columns from t2;
Field Type Null Key Default Extra Privileges
auto int(5) unsigned 0 select,insert,update,references
string varchar(10) YES new defaul select,insert,update,references
@@ -126,16 +219,22 @@ mediumblob_col mediumblob select,insert,update,references
options enum('one','two','tree') one select,insert,update,references
flags set('one','two','tree') select,insert,update,references
new_field varchar(10) new select,insert,update,references
+select t1.auto,t2.auto from t1,t2 where t1.auto=t2.auto and ((t1.string<>t2.string and (t1.string is not null or t2.string is not null)) or (t1.tiny<>t2.tiny and (t1.tiny is not null or t2.tiny is not null)) or (t1.short<>t2.short and (t1.short is not null or t2.short is not null)) or (t1.medium<>t2.medium and (t1.medium is not null or t2.medium is not null)) or (t1.long_int<>t2.long_int and (t1.long_int is not null or t2.long_int is not null)) or (t1.longlong<>t2.longlong and (t1.longlong is not null or t2.longlong is not null)) or (t1.real_float<>t2.real_float and (t1.real_float is not null or t2.real_float is not null)) or (t1.real_double<>t2.real_double and (t1.real_double is not null or t2.real_double is not null)) or (t1.utiny<>t2.utiny and (t1.utiny is not null or t2.utiny is not null)) or (t1.ushort<>t2.ushort and (t1.ushort is not null or t2.ushort is not null)) or (t1.umedium<>t2.umedium and (t1.umedium is not null or t2.umedium is not null)) or (t1.ulong<>t2.ulong and (t1.ulong is not null or t2.ulong is not null)) or (t1.ulonglong<>t2.ulonglong and (t1.ulonglong is not null or t2.ulonglong is not null)) or (t1.time_stamp<>t2.time_stamp and (t1.time_stamp is not null or t2.time_stamp is not null)) or (t1.date_field<>t2.date_field and (t1.date_field is not null or t2.date_field is not null)) or (t1.time_field<>t2.time_field and (t1.time_field is not null or t2.time_field is not null)) or (t1.date_time<>t2.date_time and (t1.date_time is not null or t2.date_time is not null)) or (t1.new_blob_col<>t2.new_blob_col and (t1.new_blob_col is not null or t2.new_blob_col is not null)) or (t1.tinyblob_col<>t2.tinyblob_col and (t1.tinyblob_col is not null or t2.tinyblob_col is not null)) or (t1.mediumblob_col<>t2.mediumblob_col and (t1.mediumblob_col is not null or t2.mediumblob_col is not null)) or (t1.options<>t2.options and (t1.options is not null or t2.options is not null)) or (t1.flags<>t2.flags and (t1.flags is not null or t2.flags is not null)) or (t1.new_field<>t2.new_field and (t1.new_field is not null or t2.new_field is not null)));
auto auto
16 16
+select t1.auto,t2.auto from t1,t2 where t1.auto=t2.auto and not (t1.string<=>t2.string and t1.tiny<=>t2.tiny and t1.short<=>t2.short and t1.medium<=>t2.medium and t1.long_int<=>t2.long_int and t1.longlong<=>t2.longlong and t1.real_float<=>t2.real_float and t1.real_double<=>t2.real_double and t1.utiny<=>t2.utiny and t1.ushort<=>t2.ushort and t1.umedium<=>t2.umedium and t1.ulong<=>t2.ulong and t1.ulonglong<=>t2.ulonglong and t1.time_stamp<=>t2.time_stamp and t1.date_field<=>t2.date_field and t1.time_field<=>t2.time_field and t1.date_time<=>t2.date_time and t1.new_blob_col<=>t2.new_blob_col and t1.tinyblob_col<=>t2.tinyblob_col and t1.mediumblob_col<=>t2.mediumblob_col and t1.options<=>t2.options and t1.flags<=>t2.flags and t1.new_field<=>t2.new_field);
auto auto
16 16
+drop table t2;
+create table t2 (primary key (auto)) select auto+1 as auto,1 as t1, "a" as t2, repeat("a",256) as t3, binary repeat("b",256) as t4 from t1;
+show full columns from t2;
Field Type Null Key Default Extra Privileges
-auto bigint(17) PRI 0 select,insert,update,references
+auto bigint(17) unsigned PRI 0 select,insert,update,references
t1 bigint(1) 0 select,insert,update,references
t2 char(1) select,insert,update,references
t3 mediumtext select,insert,update,references
t4 mediumblob select,insert,update,references
+select * from t2;
auto t1 t2 t3 t4
11 1 a aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
12 1 a aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
@@ -144,16 +243,39 @@ auto t1 t2 t3 t4
15 1 a aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
16 1 a aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
17 1 a aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
+drop table t1,t2;
+create table t1 (c int);
+insert into t1 values(1),(2);
+create table t2 select * from t1;
+create table t3 select * from t1, t2;
+Duplicate column name 'c'
+create table t3 select t1.c AS c1, t2.c AS c2,1 as "const" from t1, t2;
+show full columns from t3;
Field Type Null Key Default Extra Privileges
c1 int(11) YES NULL select,insert,update,references
c2 int(11) YES NULL select,insert,update,references
const bigint(1) 0 select,insert,update,references
+drop table t1,t2,t3;
+create table t1 ( myfield INT NOT NULL, UNIQUE INDEX (myfield), unique (myfield), index(myfield));
+drop table t1;
+create table t1 ( id integer unsigned not null primary key );
+create table t2 ( id integer unsigned not null primary key );
+insert into t1 values (1), (2);
+insert into t2 values (1);
+select t1.id as id_A, t2.id as id_B from t1 left join t2 using ( id );
id_A id_B
1 1
2 NULL
+create table t3 (id_A integer unsigned not null, id_B integer unsigned null );
+insert into t3 select t1.id as id_A, t2.id as id_B from t1 left join t2 using ( id );
+select * from t3;
id_A id_B
1 1
2 NULL
+drop table t3;
+create table t3 select t1.id as id_A, t2.id as id_B from t1 left join t2 using ( id );
+select * from t3;
id_A id_B
1 1
2 NULL
+drop table t1,t2,t3;
diff --git a/mysql-test/r/type_time.result b/mysql-test/r/type_time.result
index 1a137a89b1e..ff700f456ef 100644
--- a/mysql-test/r/type_time.result
+++ b/mysql-test/r/type_time.result
@@ -1,3 +1,7 @@
+create table t1 (t time);
+insert into t1 values("10:22:33"),("12:34:56.78"),(10),(1234),(123456.78),(1234559.99),("1"),("1:23"),("1:23:45"), ("10.22"), ("-10 1:22:33.45"),("20 10:22:33"),("1999-02-03 20:33:34");
+insert t1 values (30),(1230),("1230"),("12:30"),("12:30:35"),("1 12:30:31.32");
+select * from t1;
t
10:22:33
12:34:56
@@ -18,6 +22,8 @@ t
12:30:00
12:30:35
36:30:31
+insert into t1 values("10.22.22"),(1234567),(123456789),(123456789.10),("10 22:22"),("12.45a");
+select * from t1;
t
10:22:33
12:34:56
@@ -44,6 +50,10 @@ t
838:59:59
262:22:00
00:00:12
+drop table t1;
+create table t1 (t time);
+insert into t1 values ('09:00:00'),('13:00:00'),('19:38:34'), ('13:00:00'),('09:00:00'),('09:00:00'),('13:00:00'),('13:00:00'),('13:00:00'),('09:00:00');
+select t, time_to_sec(t),sec_to_time(time_to_sec(t)) from t1;
t time_to_sec(t) sec_to_time(time_to_sec(t))
09:00:00 32400 09:00:00
13:00:00 46800 13:00:00
@@ -55,6 +65,7 @@ t time_to_sec(t) sec_to_time(time_to_sec(t))
13:00:00 46800 13:00:00
13:00:00 46800 13:00:00
09:00:00 32400 09:00:00
+select sec_to_time(time_to_sec(t)) from t1;
sec_to_time(time_to_sec(t))
09:00:00
13:00:00
@@ -66,3 +77,4 @@ sec_to_time(time_to_sec(t))
13:00:00
13:00:00
09:00:00
+drop table t1;
diff --git a/mysql-test/r/type_timestamp.result b/mysql-test/r/type_timestamp.result
index 8996ca59f7f..ab53d27e8f3 100644
--- a/mysql-test/r/type_timestamp.result
+++ b/mysql-test/r/type_timestamp.result
@@ -1,11 +1,29 @@
+CREATE TABLE t1 ( t timestamp);
+SET TIMESTAMP=1234;
+insert into t1 values(NULL);
+select * from t1;
t
19700101032034
+drop table t1;
+CREATE TABLE t1 (value TEXT NOT NULL, id VARCHAR(32) NOT NULL, stamp timestamp, PRIMARY KEY (id));
+INSERT INTO t1 VALUES ("my value", "myKey","1999-04-02 00:00:00");
+SELECT stamp FROM t1 WHERE id="myKey";
stamp
19990402000000
+UPDATE t1 SET value="my value" WHERE id="myKey";
+SELECT stamp FROM t1 WHERE id="myKey";
stamp
19990402000000
+drop table t1;
+create table t1 (a timestamp);
+insert into t1 values (now());
+select date_format(a,"%Y %y"),year(a),year(now()) from t1;
date_format(a,"%Y %y") year(a) year(now())
1970 70 1970 1970
+drop table t1;
+create table t1 (ix timestamp);
+insert into t1 values (19991101000000),(19990102030405),(19990630232922),(19990601000000),(19990930232922),(19990531232922),(19990501000000),(19991101000000),(19990501000000);
+select * from t1;
ix
19991101000000
19990102030405
@@ -16,6 +34,21 @@ ix
19990501000000
19991101000000
19990501000000
+drop table t1;
+CREATE TABLE t1 (date date, date_time datetime, time_stamp timestamp);
+INSERT INTO t1 VALUES ("1998-12-31","1998-12-31 23:59:59",19981231235959);
+INSERT INTO t1 VALUES ("1999-01-01","1999-01-01 00:00:00",19990101000000);
+INSERT INTO t1 VALUES ("1999-09-09","1999-09-09 23:59:59",19990909235959);
+INSERT INTO t1 VALUES ("2000-01-01","2000-01-01 00:00:00",20000101000000);
+INSERT INTO t1 VALUES ("2000-02-28","2000-02-28 00:00:00",20000228000000);
+INSERT INTO t1 VALUES ("2000-02-29","2000-02-29 00:00:00",20000229000000);
+INSERT INTO t1 VALUES ("2000-03-01","2000-03-01 00:00:00",20000301000000);
+INSERT INTO t1 VALUES ("2000-12-31","2000-12-31 23:59:59",20001231235959);
+INSERT INTO t1 VALUES ("2001-01-01","2001-01-01 00:00:00",20010101000000);
+INSERT INTO t1 VALUES ("2004-12-31","2004-12-31 23:59:59",20041231235959);
+INSERT INTO t1 VALUES ("2005-01-01","2005-01-01 00:00:00",20050101000000);
+INSERT INTO t1 VALUES ("2030-01-01","2030-01-01 00:00:00",20300101000000);
+SELECT * FROM t1;
date date_time time_stamp
1998-12-31 1998-12-31 23:59:59 19981231235959
1999-01-01 1999-01-01 00:00:00 19990101000000
@@ -29,3 +62,4 @@ date date_time time_stamp
2004-12-31 2004-12-31 23:59:59 20041231235959
2005-01-01 2005-01-01 00:00:00 20050101000000
2030-01-01 2030-01-01 00:00:00 20300101000000
+drop table t1;
diff --git a/mysql-test/r/type_uint.result b/mysql-test/r/type_uint.result
index 54fa717e0f8..1acfc700d3a 100644
--- a/mysql-test/r/type_uint.result
+++ b/mysql-test/r/type_uint.result
@@ -1,3 +1,9 @@
+drop table if exists t1;
+create table t1 (this int unsigned);
+insert into t1 values (1);
+insert into t1 values (-1);
+select * from t1;
this
1
0
+drop table t1;
diff --git a/mysql-test/r/type_year.result b/mysql-test/r/type_year.result
index 7dc15a4dd1b..c892d575ca0 100644
--- a/mysql-test/r/type_year.result
+++ b/mysql-test/r/type_year.result
@@ -1,3 +1,6 @@
+create table t1 (y year,y2 year(2));
+insert into t1 values (0,0),(1999,1999),(2000,2000),(2001,2001),(70,70),(69,69);
+select * from t1;
y y2
0000 00
1999 99
@@ -5,6 +8,7 @@ y y2
2001 01
1970 70
2069 69
+select * from t1 order by y;
y y2
0000 00
1970 70
@@ -12,6 +16,7 @@ y y2
2000 00
2001 01
2069 69
+select * from t1 order by y2;
y y2
1970 70
1999 99
@@ -19,3 +24,4 @@ y y2
2000 00
2001 01
2069 69
+drop table t1;
diff --git a/mysql-test/r/union.result b/mysql-test/r/union.result
new file mode 100644
index 00000000000..6a27df648b5
--- /dev/null
+++ b/mysql-test/r/union.result
@@ -0,0 +1,144 @@
+drop table if exists t1,t2,t3;
+CREATE TABLE t1 (a int not null, b char (10) not null);
+insert into t1 values(1,'a'),(2,'b'),(3,'c'),(3,'c');
+CREATE TABLE t2 (a int not null, b char (10) not null);
+insert into t2 values (3,'c'),(4,'d'),(5,'f'),(6,'e');
+select a,b from t1 union select a,b from t2;
+a b
+1 a
+2 b
+3 c
+4 d
+5 f
+6 e
+select a,b from t1 union all select a,b from t2;
+a b
+1 a
+2 b
+3 c
+3 c
+3 c
+4 d
+5 f
+6 e
+select a,b from t1 union all select a,b from t2 order by b;
+a b
+1 a
+2 b
+3 c
+3 c
+3 c
+4 d
+6 e
+5 f
+select a,b from t1 union all select a,b from t2 union select 7,'g';
+a b
+1 a
+2 b
+3 c
+3 c
+3 c
+4 d
+5 f
+6 e
+7 g
+select 0,'#' union select a,b from t1 union all select a,b from t2 union select 7,'gg';
+0 #
+0 #
+1 a
+2 b
+3 c
+3 c
+3 c
+4 d
+5 f
+6 e
+7 g
+select a,b from t1 union select a,b from t1;
+a b
+1 a
+2 b
+3 c
+select 't1',b,count(*) from t1 group by b UNION select 't2',b,count(*) from t2 group by b;
+t1 b count(*)
+t1 a 1
+t1 b 1
+t1 c 2
+t2 c 1
+t2 d 1
+t2 e 1
+t2 f 1
+(select a,b from t1 limit 2) union all (select a,b from t2 order by a) limit 4;
+a b
+1 a
+2 b
+3 c
+4 d
+(select a,b from t1 limit 2) union all (select a,b from t2 order by a limit 1);
+a b
+1 a
+(select a,b from t1 limit 2) union all (select a,b from t2 order by a limit 1) order by b desc;
+a b
+3 c
+2 b
+1 a
+explain select a,b from t1 union all select a,b from t2;
+table type possible_keys key key_len ref rows Extra
+t1 ALL NULL NULL NULL NULL 4
+t2 ALL NULL NULL NULL NULL 4
+select a,b from t1 into outfile 'skr' union select a,b from t2;
+Wrong usage of UNION and INTO
+select a,b from t1 order by a union select a,b from t2;
+Wrong usage of UNION and ORDER BY
+insert into t3 select a from t1 order by a union select a from t2;
+Wrong usage of UNION and ORDER BY
+create table t3 select a,b from t1 union select a from t2;
+The used SELECT statements have a different number of columns
+select a,b from t1 union select a from t2;
+The used SELECT statements have a different number of columns
+select * from t1 union select a from t2;
+The used SELECT statements have a different number of columns
+select a from t1 union select * from t2;
+The used SELECT statements have a different number of columns
+create table t3 select a,b from t1 union all select a,b from t2;
+insert into t3 select a,b from t1 union all select a,b from t2;
+replace into t3 select a,b as c from t1 union all select a,b from t2;
+drop table t1,t2,t3;
+CREATE TABLE t1 (
+`pseudo` char(35) NOT NULL default '',
+`pseudo1` char(35) NOT NULL default '',
+`same` tinyint(1) unsigned NOT NULL default '1',
+PRIMARY KEY (`pseudo1`),
+KEY `pseudo` (`pseudo`)
+) TYPE=MyISAM;
+INSERT INTO t1 (pseudo,pseudo1,same) VALUES ('joce', 'testtt', 1),('joce', 'tsestset', 1),('dekad', 'joce', 1);
+SELECT pseudo FROM t1 WHERE pseudo1='joce' UNION SELECT pseudo FROM t1 WHERE pseudo='joce';
+pseudo
+dekad
+joce
+SELECT pseudo1 FROM t1 WHERE pseudo1='joce' UNION SELECT pseudo1 FROM t1 WHERE pseudo='joce';
+pseudo1
+joce
+testtt
+tsestset
+SELECT * FROM t1 WHERE pseudo1='joce' UNION SELECT * FROM t1 WHERE pseudo='joce' order by pseudo desc,pseudo1 desc;
+pseudo pseudo1 same
+joce tsestset 1
+joce testtt 1
+dekad joce 1
+SELECT pseudo1 FROM t1 WHERE pseudo='joce' UNION SELECT pseudo FROM t1 WHERE pseudo1='joce';
+pseudo1
+testtt
+tsestset
+dekad
+SELECT pseudo1 FROM t1 WHERE pseudo='joce' UNION ALL SELECT pseudo FROM t1 WHERE pseudo1='joce';
+pseudo1
+testtt
+tsestset
+dekad
+SELECT pseudo1 FROM t1 WHERE pseudo='joce' UNION SELECT 1;
+pseudo1
+testtt
+tsestset
+1
+drop table t1;
diff --git a/mysql-test/r/update.result b/mysql-test/r/update.result
index bd34700e5ec..ba5c1c6e28f 100644
--- a/mysql-test/r/update.result
+++ b/mysql-test/r/update.result
@@ -1,3 +1,16 @@
+drop table if exists t1;
+create table t1 (a int auto_increment , primary key (a));
+insert into t1 values (NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL);
+update t1 set a=a+10 where a > 34;
+update t1 set a=a+100 where a > 0;
+update t1 set a=a+100 where a=1 and a=2;
+update t1 set a=b+100 where a=1 and a=2;
+Unknown column 'b' in 'field list'
+update t1 set a=b+100 where c=1 and a=2;
+Unknown column 'c' in 'where clause'
+update t1 set d=a+100 where a=1;
+Unknown column 'd' in 'field list'
+select * from t1;
a
101
102
@@ -35,7 +48,67 @@ a
134
145
146
+drop table t1;
+CREATE TABLE t1
+(
+place_id int (10) unsigned NOT NULL,
+shows int(10) unsigned DEFAULT '0' NOT NULL,
+ishows int(10) unsigned DEFAULT '0' NOT NULL,
+ushows int(10) unsigned DEFAULT '0' NOT NULL,
+clicks int(10) unsigned DEFAULT '0' NOT NULL,
+iclicks int(10) unsigned DEFAULT '0' NOT NULL,
+uclicks int(10) unsigned DEFAULT '0' NOT NULL,
+ts timestamp(14),
+PRIMARY KEY (place_id,ts)
+);
+INSERT INTO t1 (place_id,shows,ishows,ushows,clicks,iclicks,uclicks,ts)
+VALUES (1,0,0,0,0,0,0,20000928174434);
+UPDATE t1 SET shows=shows+1,ishows=ishows+1,ushows=ushows+1,clicks=clicks+1,iclicks=iclicks+1,uclicks=uclicks+1 WHERE place_id=1 AND ts>="2000-09-28 00:00:00";
+select place_id,shows from t1;
place_id shows
1 1
+drop table t1;
+CREATE TABLE t1 (
+lfdnr int(10) unsigned NOT NULL default '0',
+ticket int(10) unsigned NOT NULL default '0',
+client varchar(255) NOT NULL default '',
+replyto varchar(255) NOT NULL default '',
+subject varchar(100) NOT NULL default '',
+timestamp int(10) unsigned NOT NULL default '0',
+tstamp timestamp(14) NOT NULL,
+status int(3) NOT NULL default '0',
+type varchar(15) NOT NULL default '',
+assignment int(10) unsigned NOT NULL default '0',
+fupcount int(4) unsigned NOT NULL default '0',
+parent int(10) unsigned NOT NULL default '0',
+activity int(10) unsigned NOT NULL default '0',
+priority tinyint(1) unsigned NOT NULL default '1',
+cc varchar(255) NOT NULL default '',
+bcc varchar(255) NOT NULL default '',
+body text NOT NULL,
+comment text,
+header text,
+PRIMARY KEY (lfdnr),
+KEY k1 (timestamp),
+KEY k2 (type),
+KEY k3 (parent),
+KEY k4 (assignment),
+KEY ticket (ticket)
+) TYPE=MyISAM;
+INSERT INTO t1 VALUES (773,773,'','','',980257344,20010318180652,0,'Open',10,0,0,0,1,'','','','','');
+alter table t1 change lfdnr lfdnr int(10) unsigned default 0 not null auto_increment;
+update t1 set status=1 where type='Open';
+select status from t1;
status
1
+drop table t1;
+create table t1 (a int not null, b int not null);
+insert into t1 values (1,1),(1,2),(1,3);
+update t1 set b=4 where a=1 order by b asc limit 1;
+update t1 set b=4 where a=1 order by b desc limit 1;
+select * from t1;
+a b
+1 4
+1 2
+1 4
+drop table t1;
diff --git a/mysql-test/r/user_var.result b/mysql-test/r/user_var.result
index e06a113bd29..5c8b4581c5c 100644
--- a/mysql-test/r/user_var.result
+++ b/mysql-test/r/user_var.result
@@ -1,16 +1,32 @@
+set @a := foo;
+You may only use constant expressions with SET
+set @a := connection_id() + 3;
+select @a - connection_id();
@a - connection_id()
3
+drop table if exists t1,t2;
+CREATE TABLE t1 ( i int not null, v int not null,index (i));
+insert into t1 values (1,1),(1,3),(2,1);
+create table t2 (i int not null, unique (i));
+insert into t2 select distinct i from t1;
+select * from t2;
i
1
2
+select distinct t2.i,@vv1:=if(sv1.i,1,0),@vv2:=if(sv2.i,1,0),@vv3:=if(sv3.i,1,0), @vv1+@vv2+@vv3 from t2 left join t1 as sv1 on sv1.i=t2.i and sv1.v=1 left join t1 as sv2 on sv2.i=t2.i and sv2.v=2 left join t1 as sv3 on sv3.i=t2.i and sv3.v=3;
i @vv1:=if(sv1.i,1,0) @vv2:=if(sv2.i,1,0) @vv3:=if(sv3.i,1,0) @vv1+@vv2+@vv3
1 1 0 1 2
2 1 0 0 1
+explain select * from t1 where i=@vv1;
table type possible_keys key key_len ref rows Extra
t1 ref i i 4 const 1 where used
+explain select * from t1 where @vv1:=@vv1+1 and i=@vv1;
table type possible_keys key key_len ref rows Extra
t1 ALL NULL NULL NULL NULL 3 where used
+explain select @vv1:=i from t1 where i=@vv1;
table type possible_keys key key_len ref rows Extra
t1 index NULL i 4 NULL 3 where used; Using index
+explain select * from t1 where i=@vv1;
table type possible_keys key key_len ref rows Extra
t1 ref i i 4 const 1 where used
+drop table t1,t2;
diff --git a/mysql-test/r/varbinary.result b/mysql-test/r/varbinary.result
index 62aeae21970..a63db14b736 100644
--- a/mysql-test/r/varbinary.result
+++ b/mysql-test/r/varbinary.result
@@ -1,6 +1,25 @@
+select 0x41,0x41+0,0x41 | 0x7fffffffffffffff | 0,0xffffffffffffffff | 0 ;
0x41 0x41+0 0x41 | 0x7fffffffffffffff | 0 0xffffffffffffffff | 0
-A 65 9223372036854775807 -1
+A 65 9223372036854775807 18446744073709551615
+select 0x31+1,concat(0x31)+1,-0xf;
0x31+1 concat(0x31)+1 -0xf
50 2 -15
+select x'31',X'ffff'+0;
+x'31' X'ffff'+0
+1 65535
+create table t1 (ID int(8) unsigned zerofill not null auto_increment,UNIQ bigint(21) unsigned zerofill not null,primary key (ID),unique (UNIQ) );
+insert into t1 set UNIQ=0x38afba1d73e6a18a;
+insert into t1 set UNIQ=123;
+explain select * from t1 where UNIQ=0x38afba1d73e6a18a;
table type possible_keys key key_len ref rows Extra
t1 const UNIQ UNIQ 8 const 1
+drop table t1;
+select x'hello';
+You have an error in your SQL syntax near 'x'hello'' at line 1
+select 0xfg;
+Unknown column '0xfg' in 'field list'
+create table t1 select 1 as x, 2 as xx;
+select x,xx from t1;
+x xx
+1 2
+drop table t1;
diff --git a/mysql-test/r/variables.result b/mysql-test/r/variables.result
index ab60d5042b0..e1f21f324ce 100644
--- a/mysql-test/r/variables.result
+++ b/mysql-test/r/variables.result
@@ -1,25 +1,46 @@
+drop table if exists t1;
+set @`test`=1,@TEST=3,@select=2,@t5=1.23456;
+select @test,@`select`,@TEST,@not_used;
@test @`select` @TEST @not_used
1 2 3 NULL
+set @test_int=10,@test_double=1e-10,@test_string="abcdeghi",@test_string2="abcdefghij",@select=NULL;
+select @test_int,@test_double,@test_string,@test_string2,@select;
@test_int @test_double @test_string @test_string2 @select
10 1e-10 abcdeghi abcdefghij NULL
+set @test_int="hello",@test_double="hello",@test_string="hello",@test_string2="hello";
+select @test_int,@test_double,@test_string,@test_string2;
@test_int @test_double @test_string @test_string2
hello hello hello hello
+set @test_int="hellohello",@test_double="hellohello",@test_string="hellohello",@test_string2="hellohello";
+select @test_int,@test_double,@test_string,@test_string2;
@test_int @test_double @test_string @test_string2
hellohello hellohello hellohello hellohello
+set @test_int=null,@test_double=null,@test_string=null,@test_string2=null;
+select @test_int,@test_double,@test_string,@test_string2;
@test_int @test_double @test_string @test_string2
NULL NULL NULL NULL
+select @t1:=(@t2:=1)+@t3:=4,@t1,@t2,@t3;
@t1:=(@t2:=1)+@t3:=4 @t1 @t2 @t3
5 5 1 4
+select @t5;
@t5
1.23456
+CREATE TABLE t1 (c_id INT(4) NOT NULL, c_name CHAR(20), c_country CHAR(3), PRIMARY KEY(c_id));
+INSERT INTO t1 VALUES (1,'Bozo','USA'),(2,'Ronald','USA'),(3,'Kinko','IRE'),(4,'Mr. Floppy','GB');
+SELECT @min_cid:=min(c_id), @max_cid:=max(c_id) from t1;
@min_cid:=min(c_id) @max_cid:=max(c_id)
1 4
+SELECT * FROM t1 WHERE c_id=@min_cid OR c_id=@max_cid;
c_id c_name c_country
1 Bozo USA
4 Mr. Floppy GB
+SELECT * FROM t1 WHERE c_id=@min_cid OR c_id=@max_cid OR c_id=666;
c_id c_name c_country
1 Bozo USA
4 Mr. Floppy GB
+ALTER TABLE t1 DROP PRIMARY KEY;
+select * from t1 where c_id=@min_cid OR c_id=@max_cid;
c_id c_name c_country
1 Bozo USA
4 Mr. Floppy GB
+drop table t1;
diff --git a/mysql-test/r/warnings.result b/mysql-test/r/warnings.result
new file mode 100644
index 00000000000..d77e98cc635
--- /dev/null
+++ b/mysql-test/r/warnings.result
@@ -0,0 +1,9 @@
+create table t1 (a int);
+insert into t1 values (1);
+insert into t1 values ("hej");
+insert into t1 values ("hej"),("då");
+set SQL_WARNINGS=1;
+insert into t1 values ("hej");
+insert into t1 values ("hej"),("då");
+drop table t1;
+set SQL_WARNINGS=0;
diff --git a/mysql-test/resolve-stack b/mysql-test/resolve-stack
new file mode 100755
index 00000000000..cdbe362c752
--- /dev/null
+++ b/mysql-test/resolve-stack
@@ -0,0 +1,8 @@
+#! /bin/sh
+# A shortcut for resolving stacks when debugging when
+# we cannot duplicate the crash in a debugger and have to
+# resort to using stack traces
+
+nm --numeric-sort ../sql/mysqld > var/tmp/mysqld.sym
+echo "Please type or paste the numeric stack trace,Ctrl-C to quit:"
+../extra/resolve_stack_dump -s var/tmp/mysqld.sym
diff --git a/mysql-test/std_data/des_key_file b/mysql-test/std_data/des_key_file
new file mode 100644
index 00000000000..fa53802d449
--- /dev/null
+++ b/mysql-test/std_data/des_key_file
@@ -0,0 +1,4 @@
+5 default_password
+1 password1
+4 password4
+2 password2
diff --git a/mysql-test/std_data/gemini.dat b/mysql-test/std_data/gemini.dat
deleted file mode 100644
index c2e1045f5ac..00000000000
--- a/mysql-test/std_data/gemini.dat
+++ /dev/null
@@ -1,5 +0,0 @@
-65,-1,1
-379,-1,1
-468,-1,1
-469,-1,1
-508,-1,1
diff --git a/mysql-test/std_data/master-bin.001 b/mysql-test/std_data/master-bin.001
index fa30d8e5302..2ec2397acdd 100644
--- a/mysql-test/std_data/master-bin.001
+++ b/mysql-test/std_data/master-bin.001
Binary files differ
diff --git a/mysql-test/t/alter_table.test b/mysql-test/t/alter_table.test
index dbfbd4267d8..22af6663e0a 100644
--- a/mysql-test/t/alter_table.test
+++ b/mysql-test/t/alter_table.test
@@ -10,10 +10,14 @@ col3 varchar (20) not null,
col4 varchar(4) not null,
col5 enum('PENDING', 'ACTIVE', 'DISABLED') not null,
col6 int not null, to_be_deleted int);
+insert into t1 values (2,4,3,5,"PENDING",1,7);
alter table t1
add column col4_5 varchar(20) not null after col4,
-add column col7 varchar(30) not null after col6,
-add column col8 datetime not null, drop column to_be_deleted;
+add column col7 varchar(30) not null after col5,
+add column col8 datetime not null, drop column to_be_deleted,
+change column col2 fourth varchar(30) not null after col3,
+modify column col6 int not null first;
+select * from t1;
drop table t1;
create table t1 (bandID MEDIUMINT UNSIGNED NOT NULL PRIMARY KEY, payoutID SMALLINT UNSIGNED NOT NULL);
@@ -73,6 +77,26 @@ OPTIMIZE TABLE t1;
DROP TABLE t1;
#
+# ALTER TABLE ... ENABLE/DISABLE KEYS
+
+create table t1 (n1 int not null, n2 int, n3 int, n4 float,
+ unique(n1),
+ key (n1, n2, n3, n4),
+ key (n2, n3, n4, n1),
+ key (n3, n4, n1, n2),
+ key (n4, n1, n2, n3) );
+alter table t1 disable keys;
+#let $1=10000;
+let $1=10;
+while ($1)
+{
+ eval insert into t1 values($1,RAND()*1000,RAND()*1000,RAND());
+ dec $1;
+}
+alter table t1 enable keys;
+drop table t1;
+
+#
# Drop and add an auto_increment column
#
@@ -81,4 +105,3 @@ insert into t1 values (null),(null),(null),(null);
alter table t1 drop i,add i int unsigned not null auto_increment, drop primary key, add primary key (i);
select * from t1;
drop table t1;
-
diff --git a/mysql-test/t/analyse.test b/mysql-test/t/analyse.test
index 1b5022f6e4c..3f56b3e47ce 100644
--- a/mysql-test/t/analyse.test
+++ b/mysql-test/t/analyse.test
@@ -2,6 +2,7 @@
# Test of procedure analyse
#
+drop table if exists t1,t2;
create table t1 (i int, j int);
insert into t1 values (1,2), (3,4), (5,6), (7,8);
select * from t1 procedure analyse();
diff --git a/mysql-test/t/auto_increment.test b/mysql-test/t/auto_increment.test
index b9b8c244699..d86466572d8 100644
--- a/mysql-test/t/auto_increment.test
+++ b/mysql-test/t/auto_increment.test
@@ -2,6 +2,7 @@
# Test of auto_increment; The test for BDB tables is in bdb.test
#
+drop table if exists t1;
create table t1 (a int not null auto_increment,b int, primary key (a)) type=myisam auto_increment=3;
insert into t1 values (1,1),(NULL,3),(NULL,4);
delete from t1 where a=4;
@@ -18,20 +19,6 @@ insert into t1 values (NULL,9,9);
select * from t1;
drop table t1;
-create table t1 (a int not null auto_increment,b int, primary key (a)) type=isam;
-insert into t1 values (1,1),(NULL,2),(3,3),(NULL,4);
-delete from t1 where a=4 or a=2;
-insert into t1 values (NULL,4),(NULL,5),(6,6);
-select * from t1;
-delete from t1 where a=6;
-#show table status like "t1";
-replace t1 values (3,1);
-replace t1 values (3,3);
-ALTER TABLE t1 add c int;
-insert into t1 values (NULL,6,6);
-select * from t1;
-drop table t1;
-
create table t1 (
skey tinyint unsigned NOT NULL auto_increment PRIMARY KEY,
sval char(20)
diff --git a/mysql-test/t/backup.test b/mysql-test/t/backup.test
index 71343783d69..ad332cde646 100644
--- a/mysql-test/t/backup.test
+++ b/mysql-test/t/backup.test
@@ -40,9 +40,3 @@ unlock tables;
connection con1;
reap;
drop table t1;
-
-
-
-
-
-
diff --git a/mysql-test/t/bdb-crash.test b/mysql-test/t/bdb-crash.test
index 55e00ad2a5e..cdbc2dbe0e4 100644
--- a/mysql-test/t/bdb-crash.test
+++ b/mysql-test/t/bdb-crash.test
@@ -1,3 +1,4 @@
+-- source include/have_bdb.inc
# test for bug reported by Mark Steele
drop table if exists t1;
diff --git a/mysql-test/t/bdb.test b/mysql-test/t/bdb.test
index 50698bb8df6..0df93b5f220 100644
--- a/mysql-test/t/bdb.test
+++ b/mysql-test/t/bdb.test
@@ -767,3 +767,19 @@ select INFO_NOTE from t1 where STR_DATE = '20010610';
select INFO_NOTE from t1 where STR_DATE < '20010610';
select INFO_NOTE from t1 where STR_DATE > '20010610';
drop table t1;
+
+#
+# Test problem with multi table delete which quickly shows up with bdb tables.
+#
+
+create table t1 (a int not null, b int, primary key (a)) type =bdb;
+create table t2 (a int not null, b int, primary key (a)) type =bdb;
+insert into t1 values (2, 3),(1, 7),(10, 7);
+insert into t2 values (2, 3),(1, 7),(10, 7);
+select * from t1;
+select * from t2;
+delete t1, t2 from t1, t2 where t1.a = t2.a;
+select * from t1;
+select * from t2;
+select * from t2;
+drop table t1,t2;
diff --git a/mysql-test/t/bench_count_distinct.test b/mysql-test/t/bench_count_distinct.test
index 62d456a3cf8..9059428bea4 100644
--- a/mysql-test/t/bench_count_distinct.test
+++ b/mysql-test/t/bench_count_distinct.test
@@ -1,12 +1,13 @@
drop table if exists t1;
create table t1(n int not null, key(n)) delay_key_write = 1;
let $1=100;
+disable_query_log;
while ($1)
{
eval insert into t1 values($1);
eval insert into t1 values($1);
dec $1;
}
-
+enable_query_log;
select count(distinct n) from t1;
drop table t1;
diff --git a/mysql-test/t/bigint.test b/mysql-test/t/bigint.test
index 6470b6f6a30..cec3e1ca45c 100644
--- a/mysql-test/t/bigint.test
+++ b/mysql-test/t/bigint.test
@@ -14,3 +14,26 @@ select * from t1 where a='18446744073709551615';
delete from t1 where a=18446744073709551615;
select * from t1;
drop table t1;
+
+create table t1 ( a int not null default 1, big bigint );
+insert into t1 (big) values (-1),(12345678901234567),(9223372036854775807),(18446744073709551615);
+select min(big),max(big),max(big)-1 from t1;
+select min(big),max(big),max(big)-1 from t1 group by a;
+alter table t1 modify big bigint unsigned not null;
+select min(big),max(big),max(big)-1 from t1;
+select min(big),max(big),max(big)-1 from t1 group by a;
+alter table t1 add key (big);
+select min(big),max(big),max(big)-1 from t1;
+select min(big),max(big),max(big)-1 from t1 group by a;
+alter table t1 modify big bigint not null;
+select min(big),max(big),max(big)-1 from t1;
+select min(big),max(big),max(big)-1 from t1 group by a;
+drop table t1;
+
+select CAST(1-2 AS UNSIGNED);
+select CAST(CAST(1-2 AS UNSIGNED) AS SIGNED INTEGER);
+select CONVERT('-1',UNSIGNED);
+select cast(-5 as unsigned) | 1, cast(-5 as unsigned) & -1;
+select cast(-5 as unsigned) -1, cast(-5 as unsigned) + 1;
+select ~5, cast(~5 as signed);
+select cast(5 as unsigned) -6.0;
diff --git a/mysql-test/t/bulk_replace.test b/mysql-test/t/bulk_replace.test
new file mode 100644
index 00000000000..d366004c16f
--- /dev/null
+++ b/mysql-test/t/bulk_replace.test
@@ -0,0 +1,14 @@
+#
+# this is a test of bulk-insert code
+# as used by REPLACE
+#
+# by Monty
+#
+
+drop table if exists t1;
+CREATE TABLE t1 (a int, unique (a), b int not null, unique(b), c int not null, index(c));
+replace into t1 values (1,1,1),(2,2,2),(3,1,3);
+select * from t1;
+check table t1;
+drop table t1;
+
diff --git a/mysql-test/t/check.test b/mysql-test/t/check.test
index 62af9f92e65..421c98d79e0 100644
--- a/mysql-test/t/check.test
+++ b/mysql-test/t/check.test
@@ -5,14 +5,17 @@ drop table if exists t1;
#add a lot of keys to slow down check
create table t1(n int not null, key(n), key(n), key(n), key(n));
let $1=10000;
+disable_query_log;
while ($1)
{
eval insert into t1 values ($1);
dec $1;
}
+enable_query_log;
send check table t1 type=extended;
connection con2;
insert into t1 values (200000);
connection con1;
reap;
drop table t1;
+
diff --git a/mysql-test/t/count_distinct2-master.opt b/mysql-test/t/count_distinct2-master.opt
new file mode 100644
index 00000000000..d81cc55090d
--- /dev/null
+++ b/mysql-test/t/count_distinct2-master.opt
@@ -0,0 +1 @@
+--set-variable=max_heap_table_size=16384
diff --git a/mysql-test/t/count_distinct2.test b/mysql-test/t/count_distinct2.test
new file mode 100644
index 00000000000..d1bea7614c8
--- /dev/null
+++ b/mysql-test/t/count_distinct2.test
@@ -0,0 +1,79 @@
+drop table if exists t1;
+
+create table t1(n1 int, n2 int, s char(20), vs varchar(20), t text);
+insert into t1 values (1,11, 'one','eleven', 'eleven'),
+ (1,11, 'one','eleven', 'eleven'),
+ (2,11, 'two','eleven', 'eleven'),
+ (2,12, 'two','twevle', 'twelve'),
+ (2,13, 'two','thirteen', 'foo'),
+ (2,13, 'two','thirteen', 'foo'),
+ (2,13, 'two','thirteen', 'bar'),
+ (NULL,13, 'two','thirteen', 'bar'),
+ (2,NULL, 'two','thirteen', 'bar'),
+ (2,13, NULL,'thirteen', 'bar'),
+ (2,13, 'two',NULL, 'bar'),
+ (2,13, 'two','thirteen', NULL);
+
+select distinct n1 from t1;
+select count(distinct n1) from t1;
+
+select distinct n2 from t1;
+select count(distinct n2) from t1;
+
+select distinct s from t1;
+select count(distinct s) from t1;
+
+select distinct vs from t1;
+select count(distinct vs) from t1;
+
+select distinct t from t1;
+select count(distinct t) from t1;
+
+select distinct n1,n2 from t1;
+select count(distinct n1,n2) from t1;
+
+select distinct n1,s from t1;
+select count(distinct n1,s) from t1;
+
+select distinct s,n1,vs from t1;
+select count(distinct s,n1,vs) from t1;
+
+select distinct s,t from t1;
+select count(distinct s,t) from t1;
+
+select count(distinct n1), count(distinct n2) from t1;
+
+select count(distinct n2), n1 from t1 group by n1;
+drop table t1;
+
+# test the conversion from tree to MyISAM
+create table t1 (n int default NULL);
+let $1=5000;
+disable_query_log;
+while ($1)
+{
+ eval insert into t1 values($1);
+ dec $1;
+}
+enable_query_log;
+
+flush status;
+select count(distinct n) from t1;
+show status like 'Created_tmp_disk_tables';
+drop table t1;
+
+#test conversion from heap to MyISAM
+create table t1 (s text);
+let $1=5000;
+disable_query_log;
+while ($1)
+{
+ eval insert into t1 values('$1');
+ dec $1;
+}
+enable_query_log;
+flush status;
+select count(distinct s) from t1;
+show status like 'Created_tmp_disk_tables';
+drop table t1;
+
diff --git a/mysql-test/t/create.test b/mysql-test/t/create.test
index d45d013c9fb..17b098cae89 100644
--- a/mysql-test/t/create.test
+++ b/mysql-test/t/create.test
@@ -25,14 +25,10 @@ drop table if exists t1,t2;
!$1164 create table t1 (a int not null auto_increment,primary key (a)) type=heap;
!$1163 create table t1 (a int not null,b text) type=heap;
!$1171 create table t1 (a int ,primary key(a)) type=heap;
-!$1121 create table t1 (a int,b text, index(a)) type=isam;
-!$1073 create table t1 (a int,b text, index(b)) type=isam;
drop table if exists t1;
-!$1075 create table t1 (ordid int(8) not null auto_increment, ord varchar(50) not null, primary key (ord,ordid)) type=isam;
!$1164 create table t1 (ordid int(8) not null auto_increment, ord varchar(50) not null, primary key (ord,ordid)) type=heap;
!$1171 create table t1 (ordid int(8), primary key (ordid));
-!$1121 create table t1 (ordid int(8), unique (ordid)) type=isam;
-- error 1044,1
create table not_existing_database.test (a int);
@@ -69,3 +65,19 @@ create table t2 (key (b)) select * from t1;
explain select * from t2 where b="world";
select * from t2 where b="world";
drop table t1,t2;
+
+#
+# Test types after CREATE ... SELECT
+#
+
+create table t1(x varchar(50) );
+create table t2 select x from t1 where 1=2;
+describe t1;
+describe t2;
+drop table t2;
+create table t2 select now() as a , curtime() as b, curdate() as c , 1+1 as d , 1.0 + 1 as e , 33333333333333333 + 3 as f;
+describe t2;
+drop table t2;
+create table t2 select CAST("2001-12-29" AS DATE) as d, CAST("20:45:11" AS TIME) as t, CAST("2001-12-29 20:45:11" AS DATETIME) as dt;
+describe t2;
+drop table t1,t2;
diff --git a/mysql-test/t/ctype_latin1_de-master.opt b/mysql-test/t/ctype_latin1_de-master.opt
new file mode 100644
index 00000000000..98accd58c46
--- /dev/null
+++ b/mysql-test/t/ctype_latin1_de-master.opt
@@ -0,0 +1 @@
+--default-character-set=latin1_de
diff --git a/mysql-test/t/ctype_latin1_de.test b/mysql-test/t/ctype_latin1_de.test
new file mode 100644
index 00000000000..d39d7f6e5dd
--- /dev/null
+++ b/mysql-test/t/ctype_latin1_de.test
@@ -0,0 +1,46 @@
+#
+# Test latin_de character set
+#
+drop table if exists t1;
+create table t1 (a char (20) not null, b int not null auto_increment, index (a,b),index(b));
+insert into t1 (a) values ('ä'),('ac'),('ae'),('ad'),('Äc'),('aeb');
+insert into t1 (a) values ('üc'),('uc'),('ue'),('ud'),('Ü'),('ueb'),('uf');
+insert into t1 (a) values ('ö'),('oc'),('Öa'),('oe'),('od'),('Öc'),('oeb');
+insert into t1 (a) values ('s'),('ss'),('ß'),('ßb'),('ssa'),('ssc'),('ßa');
+insert into t1 (a) values ('eä'),('uü'),('öo'),('ää'),('ääa'),('aeae');
+insert into t1 (a) values ('q'),('a'),('u'),('o'),('é'),('É');
+select a,b from t1 order by a,b;
+select a,b from t1 order by upper(a),b;
+select a from t1 order by a desc;
+check table t1;
+select * from t1 where a like "ö%";
+select * from t1 where a like binary "%É%";
+select * from t1 where a like "%Á%";
+select * from t1 where a like "%U%";
+select * from t1 where a like "%ss%";
+drop table t1;
+
+# The following should all be true
+select strcmp('ä','ae'),strcmp('ae','ä'),strcmp('aeq','äq'),strcmp('äq','aeq');
+select strcmp('ss','ß'),strcmp('ß','ss'),strcmp('ßs','sss'),strcmp('ßq','ssq');
+
+# The following should all return -1
+select strcmp('ä','af'),strcmp('a','ä'),strcmp('ää','aeq'),strcmp('ää','aeaeq');
+select strcmp('ss','ßa'),strcmp('ß','ssa'),strcmp('sßa','sssb'),strcmp('s','ß');
+select strcmp('ö','oö'),strcmp('Ü','uü'),strcmp('ö','oeb');
+
+# The following should all return 1
+select strcmp('af','ä'),strcmp('ä','a'),strcmp('aeq','ää'),strcmp('aeaeq','ää');
+select strcmp('ßa','ss'),strcmp('ssa','ß'),strcmp('sssb','sßa'),strcmp('ß','s');
+select strcmp('u','öa'),strcmp('u','ö');
+
+#
+# Some other simple tests with the current character set
+#
+
+create table t1 (a varchar(10), key(a));
+insert into t1 values ("a"),("abc"),("abcd"),("hello"),("test");
+select * from t1 where a like "abc%";
+select * from t1 where a like "test%";
+select * from t1 where a like "te_t";
+drop table t1;
diff --git a/mysql-test/t/dirty-close.test b/mysql-test/t/dirty_close.test
index 3ed22f26d5b..3ed22f26d5b 100644
--- a/mysql-test/t/dirty-close.test
+++ b/mysql-test/t/dirty_close.test
diff --git a/mysql-test/t/drop.test b/mysql-test/t/drop.test
index 2a45fe8253b..c92f2b1f3b9 100644
--- a/mysql-test/t/drop.test
+++ b/mysql-test/t/drop.test
@@ -11,33 +11,33 @@ create table t1(n int);
drop table t1;
select * from t1;
-#now test for a bug in drop database - it is important that the name
-#of the table is the same as the name of the database - in the original
-#code this triggered a bug
-drop database if exists foo;
-create database foo;
-drop database if exists foo;
-create database foo;
-create table foo.foo (n int);
-insert into foo.foo values (4);
-select * from foo.foo;
-drop database if exists foo;
-create database foo;
-drop database foo;
+# now test for a bug in drop database - it is important that the name
+# of the table is the same as the name of the database - in the original
+# code this triggered a bug
+drop database if exists mysqltest;
+create database mysqltest;
+drop database if exists mysqltest;
+create database mysqltest;
+create table mysqltest.mysqltest (n int);
+insert into mysqltest.mysqltest values (4);
+select * from mysqltest.mysqltest;
+drop database if exists mysqltest;
+create database mysqltest;
+drop database mysqltest;
# test drop/create database and FLUSH TABLES WITH READ LOCK
-drop database if exists foo;
+drop database if exists mysqltest;
flush tables with read lock;
---error 1209
-create database foo;
+--error 1209,1223;
+create database mysqltest;
unlock tables;
-create database foo;
+create database mysqltest;
show databases;
flush tables with read lock;
---error 1208
-drop database foo;
+--error 1208,1223;
+drop database mysqltest;
unlock tables;
-drop database foo;
+drop database mysqltest;
show databases;
-
-
+--error 1008
+drop database mysqltest;
diff --git a/mysql-test/t/flush.test b/mysql-test/t/flush.test
index 4491de1f82b..38aa37caa4f 100644
--- a/mysql-test/t/flush.test
+++ b/mysql-test/t/flush.test
@@ -1,3 +1,11 @@
+# This test doesn't work with the embedded version as this code
+# assumes that one query is running while we are doing queries on
+# a second connection.
+# This would work if mysqltest run would be threaded and handle each
+# connection in a separate thread.
+#
+-- source include/not_embedded.inc
+
connect (con1,localhost,root,,);
connect (con2,localhost,root,,);
connection con1;
@@ -7,6 +15,7 @@ drop table if exists t2;
create table t2(n int);
insert into t2 values(3);
let $1=100;
+disable_query_log;
while ($1)
{
connection con1;
@@ -19,7 +28,7 @@ while ($1)
reap;
dec $1;
}
-
+enable_query_log;
connection con1;
select * from t1;
connection con2;
@@ -35,15 +44,15 @@ reap;
#test if drop database will wait until we release the global read lock
connection con1;
-drop database if exists foo;
-create database foo;
-create table foo.t1(n int);
-insert into foo.t1 values (23);
+drop database if exists mysqltest;
+create database mysqltest;
+create table mysqltest.t1(n int);
+insert into mysqltest.t1 values (23);
flush tables with read lock;
connection con2;
-send drop database foo;
+send drop database mysqltest;
connection con1;
-select * from foo.t1;
+select * from mysqltest.t1;
unlock tables;
connection con2;
reap;
@@ -57,3 +66,12 @@ connection con2;
insert into t1 values (345);
select * from t1;
drop table t1;
+
+#
+# Test that QUERY CACHE commands doesn't core dump.
+# (Normally we don't have a cache active at this point)
+#
+
+flush query cache;
+reset query cache;
+show status like "Qcache_queries_in_cache";
diff --git a/mysql-test/t/fulltext.test b/mysql-test/t/fulltext.test
index 83e328ca616..ace51217bba 100644
--- a/mysql-test/t/fulltext.test
+++ b/mysql-test/t/fulltext.test
@@ -5,10 +5,37 @@
drop table if exists t1,t2,t3;
CREATE TABLE t1 (a VARCHAR(200), b TEXT, FULLTEXT (a,b));
-INSERT INTO t1 VALUES('MySQL has now support', 'for full-text search'),('Full-text indexes', 'are called collections'),('Only MyISAM tables','support collections'),('Function MATCH ... AGAINST()','is used to do a search'),('Full-text search in MySQL', 'implements vector space model');
+INSERT INTO t1 VALUES('MySQL has now support', 'for full-text search'),
+ ('Full-text indexes', 'are called collections'),
+ ('Only MyISAM tables','support collections'),
+ ('Function MATCH ... AGAINST()','is used to do a search'),
+ ('Full-text search in MySQL', 'implements vector space model');
+
+# nl search
+
select * from t1 where MATCH(a,b) AGAINST ("collections");
select * from t1 where MATCH(a,b) AGAINST ("indexes");
select * from t1 where MATCH(a,b) AGAINST ("indexes collections");
+
+# boolean search
+
+select * from t1 where MATCH(a,b) AGAINST("support -collections" IN BOOLEAN MODE);
+select * from t1 where MATCH(a,b) AGAINST("support collections" IN BOOLEAN MODE);
+select * from t1 where MATCH(a,b) AGAINST("support +collections" IN BOOLEAN MODE);
+select * from t1 where MATCH(a,b) AGAINST("sear*" IN BOOLEAN MODE);
+select * from t1 where MATCH(a,b) AGAINST("+support +collections" IN BOOLEAN MODE);
+select * from t1 where MATCH(a,b) AGAINST("+search" IN BOOLEAN MODE);
+select * from t1 where MATCH(a,b) AGAINST("+search +(support vector)" IN BOOLEAN MODE);
+select * from t1 where MATCH(a,b) AGAINST("+search -(support vector)" IN BOOLEAN MODE);
+select *, MATCH(a,b) AGAINST("support collections" IN BOOLEAN MODE) as x from t1;
+
+# boolean w/o index:
+
+select * from t1 where MATCH a AGAINST ("search" IN BOOLEAN MODE);
+select * from t1 where MATCH b AGAINST ("sear*" IN BOOLEAN MODE);
+
+#update/delete with fulltext index
+
delete from t1 where a like "MySQL%";
update t1 set a='some test foobar' where MATCH a,b AGAINST ('model');
delete from t1 where MATCH(a,b) AGAINST ("indexes");
@@ -77,14 +104,28 @@ CREATE TABLE t3 (
--error 1210
select * from t2 where MATCH inhalt AGAINST (t2.inhalt);
-
---error 1210
-select * from t2 where MATCH inhalt AGAINST (t2.inhalt);
-
--error 1191
select * from t2 where MATCH ticket AGAINST ('foobar');
-
--error 1210
select * from t2,t3 where MATCH (t2.inhalt,t3.inhalt) AGAINST ('foobar');
drop table t1,t2,t3;
+
+#
+# two more bugtests
+#
+
+CREATE TABLE t1 (
+ id int(11) auto_increment,
+ title varchar(100) default '',
+ PRIMARY KEY (id),
+ KEY ind5 (title),
+ FULLTEXT KEY FT1 (title)
+) TYPE=MyISAM;
+
+insert into t1 (title) values ('this is a test');
+update t1 set title='this is A test' where id=1;
+check table t1;
+update t1 set title='this test once revealed a bug' where id=1;
+select * from t1;
+update t1 set title=NULL where id=1;
diff --git a/mysql-test/t/fulltext_cache.test b/mysql-test/t/fulltext_cache.test
index fc5f0e266b3..0b15e57a97b 100644
--- a/mysql-test/t/fulltext_cache.test
+++ b/mysql-test/t/fulltext_cache.test
@@ -26,10 +26,16 @@ INSERT INTO t2 VALUES (6,2,'um chocolate Snickers');
INSERT INTO t2 VALUES (7,1,'Bife');
INSERT INTO t2 VALUES (8,1,'Pizza de Salmao');
-SELECT t1.q, t2.item, t2.id, MATCH t2.item AGAINST ('sushi') as x FROM t1, t2
-WHERE (t2.id2 = t1.id) ORDER BY x DESC,t2.id;
+SELECT t1.q, t2.item, t2.id, MATCH t2.item AGAINST ('sushi')
+as x FROM t1, t2 WHERE (t2.id2 = t1.id) ORDER BY x DESC,t2.id;
-SELECT t1.q, t2.item, t2.id, MATCH t2.item AGAINST ('sushi') as x FROM t2, t1
-WHERE (t2.id2 = t1.id) ORDER BY x DESC,t2.id;
+SELECT t1.q, t2.item, t2.id, MATCH t2.item AGAINST ('sushi' IN BOOLEAN MODE)
+as x FROM t1, t2 WHERE (t2.id2 = t1.id) ORDER BY x DESC,t2.id;
+
+SELECT t1.q, t2.item, t2.id, MATCH t2.item AGAINST ('sushi')
+as x FROM t2, t1 WHERE (t2.id2 = t1.id) ORDER BY x DESC,t2.id;
+
+SELECT t1.q, t2.item, t2.id, MATCH t2.item AGAINST ('sushi' IN BOOLEAN MODE)
+as x FROM t2, t1 WHERE (t2.id2 = t1.id) ORDER BY x DESC,t2.id;
drop table t1, t2;
diff --git a/mysql-test/t/fulltext_distinct.test b/mysql-test/t/fulltext_distinct.test
new file mode 100644
index 00000000000..86e2f7ca1b4
--- /dev/null
+++ b/mysql-test/t/fulltext_distinct.test
@@ -0,0 +1,41 @@
+#
+# Test of fulltext index
+# bug reported by Tibor Simko <tibor.simko@cern.ch>
+#
+
+DROP TABLE IF EXISTS t1, t2;
+CREATE TABLE t1 (
+ id mediumint unsigned NOT NULL auto_increment,
+ tag char(6) NOT NULL default '',
+ value text NOT NULL default '',
+ PRIMARY KEY (id),
+ KEY kt(tag),
+ KEY kv(value(15)),
+ FULLTEXT KEY kvf(value)
+) TYPE=MyISAM;
+CREATE TABLE t2 (
+ id_t2 mediumint unsigned NOT NULL default '0',
+ id_t1 mediumint unsigned NOT NULL default '0',
+ field_number tinyint unsigned NOT NULL default '0',
+ PRIMARY KEY (id_t2,id_t1,field_number),
+ KEY id_t1(id_t1)
+) TYPE=MyISAM;
+
+INSERT INTO t1 (tag,value) VALUES ('foo123','bar111');
+INSERT INTO t1 (tag,value) VALUES ('foo123','bar222');
+INSERT INTO t1 (tag,value) VALUES ('bar345','baz333 ar');
+
+INSERT INTO t2 VALUES (2231626,64280,0);
+INSERT INTO t2 VALUES (2231626,64281,0);
+INSERT INTO t2 VALUES (12346, 3, 1);
+
+SELECT * FROM t1; SELECT * FROM t2;
+
+SELECT DISTINCT t2.id_t2 FROM t2, t1
+WHERE MATCH (t1.value) AGAINST ('baz333') AND t1.id = t2.id_t1;
+
+SELECT DISTINCT t2.id_t2 FROM t2, t1
+WHERE MATCH (t1.value) AGAINST ('baz333' IN BOOLEAN MODE)
+AND t1.id = t2.id_t1;
+
+DROP TABLE t1, t2;
diff --git a/mysql-test/t/fulltext_left_join.test b/mysql-test/t/fulltext_left_join.test
index d09d577d04b..abb1c8e8473 100644
--- a/mysql-test/t/fulltext_left_join.test
+++ b/mysql-test/t/fulltext_left_join.test
@@ -22,6 +22,8 @@ INSERT INTO t2 VALUES('456', 'lui');
select match(t1.texte,t1.sujet,t1.motsclefs) against('droit')
from t1 left join t2 on t2.id=t1.id;
+select match(t1.texte,t1.sujet,t1.motsclefs) against('droit' IN BOOLEAN MODE)
+ from t1 left join t2 on t2.id=t1.id;
drop table t1, t2;
diff --git a/mysql-test/t/fulltext_order_by.test b/mysql-test/t/fulltext_order_by.test
index 9f35d58e699..d5cb99ef0ee 100644
--- a/mysql-test/t/fulltext_order_by.test
+++ b/mysql-test/t/fulltext_order_by.test
@@ -9,17 +9,24 @@ INSERT INTO t1 (message) VALUES ("Testing"),("table"),("testbug"),
("steve"),("is"),("cool"),("steve is cool");
# basic MATCH
SELECT a, MATCH (message) AGAINST ('steve') FROM t1 WHERE MATCH (message) AGAINST ('steve');
+SELECT a, MATCH (message) AGAINST ('steve' IN BOOLEAN MODE) FROM t1 WHERE MATCH (message) AGAINST ('steve');
+SELECT a, MATCH (message) AGAINST ('steve') FROM t1 WHERE MATCH (message) AGAINST ('steve' IN BOOLEAN MODE);
+SELECT a, MATCH (message) AGAINST ('steve' IN BOOLEAN MODE) FROM t1 WHERE MATCH (message) AGAINST ('steve' IN BOOLEAN MODE);
# MATCH + ORDER BY (with ft-ranges)
SELECT a, MATCH (message) AGAINST ('steve') FROM t1 WHERE MATCH (message) AGAINST ('steve') ORDER BY a;
+SELECT a, MATCH (message) AGAINST ('steve' IN BOOLEAN MODE) FROM t1 WHERE MATCH (message) AGAINST ('steve' IN BOOLEAN MODE) ORDER BY a;
# MATCH + ORDER BY (with normal ranges) + UNIQUE
SELECT a, MATCH (message) AGAINST ('steve') FROM t1 WHERE a in (2,7,4) and MATCH (message) AGAINST ('steve') ORDER BY a DESC;
+SELECT a, MATCH (message) AGAINST ('steve' IN BOOLEAN MODE) FROM t1 WHERE a in (2,7,4) and MATCH (message) AGAINST ('steve' IN BOOLEAN MODE) ORDER BY a DESC;
# MATCH + ORDER BY + UNIQUE (const_table)
SELECT a, MATCH (message) AGAINST ('steve') FROM t1 WHERE a=7 and MATCH (message) AGAINST ('steve') ORDER BY 1;
+SELECT a, MATCH (message) AGAINST ('steve' IN BOOLEAN MODE) FROM t1 WHERE a=7 and MATCH (message) AGAINST ('steve' IN BOOLEAN MODE) ORDER BY 1;
# ORDER BY MATCH
SELECT a, MATCH (message) AGAINST ('steve') as rel FROM t1 ORDER BY rel;
+SELECT a, MATCH (message) AGAINST ('steve' IN BOOLEAN MODE) as rel FROM t1 ORDER BY rel;
drop table t1;
diff --git a/mysql-test/t/fulltext_var.test b/mysql-test/t/fulltext_var.test
new file mode 100644
index 00000000000..71213d1195a
--- /dev/null
+++ b/mysql-test/t/fulltext_var.test
@@ -0,0 +1,5 @@
+#
+# Fulltext configurable parameters
+#
+
+show variables like "ft\_%";
diff --git a/mysql-test/t/func_crypt.test b/mysql-test/t/func_crypt.test
index ddc0816e301..f01504d3691 100644
--- a/mysql-test/t/func_crypt.test
+++ b/mysql-test/t/func_crypt.test
@@ -1,2 +1,3 @@
-
select length(encrypt('foo', 'ff')) <> 0;
+--replace_result $1$aa$4OSUA5cjdx0RUQ08opV27/ aaqPiZY5xR5l.
+select password('test'),length(encrypt('test')),encrypt('test','aa');
diff --git a/mysql-test/t/func_encrypt-master.opt b/mysql-test/t/func_encrypt-master.opt
new file mode 100644
index 00000000000..0b042f52e9a
--- /dev/null
+++ b/mysql-test/t/func_encrypt-master.opt
@@ -0,0 +1 @@
+--des-key-file=$MYSQL_TEST_DIR/std_data/des_key_file
diff --git a/mysql-test/t/func_encrypt.test b/mysql-test/t/func_encrypt.test
new file mode 100644
index 00000000000..3b6acc54ec9
--- /dev/null
+++ b/mysql-test/t/func_encrypt.test
@@ -0,0 +1,67 @@
+-- source include/have_openssl.inc
+
+drop table if exists t1;
+create table t1 (x blob);
+insert into t1 values (des_encrypt('The quick red fox jumped over the lazy brown dog','The quick red fox jumped over the lazy brown dog'));
+insert into t1 values (des_encrypt('a','The quick red fox jumped over the lazy brown dog'));
+insert into t1 values (des_encrypt('The quick red fox jumped over the lazy brown dog','a'));
+insert into t1 values (des_encrypt('ab','The quick red fox jumped over the lazy brown dog'));
+insert into t1 values (des_encrypt('The quick red fox jumped over the lazy brown dog','ab'));
+insert into t1 values (des_encrypt('abc','The quick red fox jumped over the lazy brown dog'));
+insert into t1 values (des_encrypt('The quick red fox jumped over the lazy brown dog','abc'));
+insert into t1 values (des_encrypt('abcd','The quick red fox jumped over the lazy brown dog'));
+insert into t1 values (des_encrypt('The quick red fox jumped over the lazy brown dog','abcd'));
+insert into t1 values (des_encrypt('abcde','The quick red fox jumped over the lazy brown dog'));
+insert into t1 values (des_encrypt('The quick red fox jumped over the lazy brown dog','abcde'));
+insert into t1 values (des_encrypt('abcdef','The quick red fox jumped over the lazy brown dog'));
+insert into t1 values (des_encrypt('The quick red fox jumped over the lazy brown dog','abcdef'));
+insert into t1 values (des_encrypt('abcdefg','The quick red fox jumped over the lazy brown dog'));
+insert into t1 values (des_encrypt('The quick red fox jumped over the lazy brown dog','abcdefg'));
+insert into t1 values (des_encrypt('abcdefgh','The quick red fox jumped over the lazy brown dog'));
+insert into t1 values (des_encrypt('The quick red fox jumped over the lazy brown dog','abcdefgh'));
+insert into t1 values (des_encrypt('abcdefghi','The quick red fox jumped over the lazy brown dog'));
+insert into t1 values (des_encrypt('The quick red fox jumped over the lazy brown dog','abcdefghi'));
+insert into t1 values (des_encrypt('abcdefghij','The quick red fox jumped over the lazy brown dog'));
+insert into t1 values (des_encrypt('The quick red fox jumped over the lazy brown dog','abcdefghij'));
+insert into t1 values (des_encrypt('abcdefghijk','The quick red fox jumped over the lazy brown dog'));
+insert into t1 values (des_encrypt('The quick red fox jumped over the lazy brown dog','abcdefghijk'));
+insert into t1 values (des_encrypt('The quick red fox jumped over the lazy brown dog','sabakala'));
+insert into t1 values (des_encrypt('quick red fox jumped over the lazy brown dog','sabakala'));
+insert into t1 values (des_encrypt('red fox jumped over the lazy brown dog','sabakala'));
+insert into t1 values (des_encrypt('fox jumped over the lazy brown dog','sabakala'));
+insert into t1 values (des_encrypt('jumped over the lazy brown dog','sabakala'));
+insert into t1 values (des_encrypt('over the lazy brown dog','sabakala'));
+insert into t1 values (des_encrypt('the lazy brown dog','sabakala'));
+insert into t1 values (des_encrypt('lazy brown dog','sabakala'));
+insert into t1 values (des_encrypt('brown dog','sabakala'));
+insert into t1 values (des_encrypt('dog','sabakala'));
+insert into t1 values (des_encrypt('dog!','sabakala'));
+insert into t1 values (des_encrypt('dog!!','sabakala'));
+insert into t1 values (des_encrypt('dog!!!','sabakala'));
+insert into t1 values (des_encrypt('dog!!!!','sabakala'));
+insert into t1 values (des_encrypt('dog!!!!!','sabakala'));
+insert into t1 values (des_encrypt('jumped over the lazy brown dog','sabakala'));
+insert into t1 values (des_encrypt('jumped over the lazy brown dog','sabakala'));
+select hex(x), hex(des_decrypt(x,'sabakala')) from t1;
+select des_decrypt(x,'sabakala') as s from t1 having s like '%dog%';
+drop table t1;
+
+#
+# Test default keys
+#
+select hex(des_encrypt("hello")),des_decrypt(des_encrypt("hello"));
+select des_decrypt(des_encrypt("hello",4));
+select des_decrypt(des_encrypt("hello",'test'),'test');
+select hex(des_encrypt("hello")),hex(des_encrypt("hello",5)),hex(des_encrypt("hello",'default_password'));
+select des_decrypt(des_encrypt("hello"),'default_password');
+select des_decrypt(des_encrypt("hello",4),'password4');
+
+# Test flush
+SET @a=des_decrypt(des_encrypt("hello"));
+flush des_key_file;
+select @a = des_decrypt(des_encrypt("hello"));
+
+# Test usage of wrong password
+select hex("hello");
+select hex(des_decrypt(des_encrypt("hello",4),'password2'));
+select hex(des_decrypt(des_encrypt("hello","hidden")));
diff --git a/mysql-test/t/func_like.test b/mysql-test/t/func_like.test
index d160b04176c..e0f1f0db9ce 100644
--- a/mysql-test/t/func_like.test
+++ b/mysql-test/t/func_like.test
@@ -2,9 +2,11 @@
# Test of like
#
+drop table if exists t1;
create table t1 (a varchar(10), key(a));
insert into t1 values ("a"),("abc"),("abcd"),("hello"),("test");
select * from t1 where a like "abc%";
+select * from t1 where a like "ABC%";
select * from t1 where a like "test%";
select * from t1 where a like "te_t";
drop table t1;
diff --git a/mysql-test/t/func_str.test b/mysql-test/t/func_str.test
index b7200b2d144..26272fba03f 100644
--- a/mysql-test/t/func_str.test
+++ b/mysql-test/t/func_str.test
@@ -9,10 +9,11 @@ drop table if exists t1;
select 'hello',"'hello'",'""hello""','''h''e''l''l''o''',"hel""lo",'hel\'lo';
select 'hello' 'monty';
select length('\n\t\r\b\0\_\%\\');
+select bit_length('\n\t\r\b\0\_\%\\');
select concat('monty',' was here ','again'),length('hello'),char(ascii('h'));
select locate('he','hello'),locate('he','hello',2),locate('lo','hello',2) ;
-select instr('hello','he');
-select position('ll' in 'hello'),position('a' in 'hello');
+select instr('hello','HE'), instr('hello',binary 'HE'), instr(binary 'hello','HE');
+select position(binary 'll' in 'hello'),position('a' in binary 'hello');
select left('hello',2),right('hello',2),substring('hello',2,2),mid('hello',1,5) ;
select concat('',left(right(concat('what ',concat('is ','happening')),9),4),'',substring('monty',5,1)) ;
select substring_index('www.tcx.se','.',-2),substring_index('www.tcx.se','.',1);
@@ -35,7 +36,6 @@ select insert('txs',2,1,'hi'),insert('is ',4,0,'a'),insert('txxxxt',2,4,'es');
select replace('aaaa','a','b'),replace('aaaa','aa','b'),replace('aaaa','a','bb'),replace('aaaa','','b'),replace('bbbb','a','c');
select replace(concat(lcase(concat('THIS',' ','IS',' ','A',' ')),ucase('false'),' ','test'),'FALSE','REAL') ;
select soundex(''),soundex('he'),soundex('hello all folks');
-select password('test'),length(encrypt('test')),encrypt('test','aa');
select md5('hello');
select repeat('monty',5),concat('*',space(5),'*');
select reverse('abc'),reverse('abcd');
diff --git a/mysql-test/t/func_system.test b/mysql-test/t/func_system.test
index b0bdbe472dd..052e0530cf6 100644
--- a/mysql-test/t/func_system.test
+++ b/mysql-test/t/func_system.test
@@ -2,5 +2,5 @@
# system functions
#
-select database(),user();
+select database(),user() like "%@%";
select version()>="3.23.29";
diff --git a/mysql-test/t/func_time.test b/mysql-test/t/func_time.test
index ffb0f8bbf1e..a052f5f2d92 100644
--- a/mysql-test/t/func_time.test
+++ b/mysql-test/t/func_time.test
@@ -19,13 +19,23 @@ select month("1997-01-02"),year("98-02-03"),dayofyear("1997-12-31");
select month("2001-02-00"),year("2001-00-00");
select DAYOFYEAR("1997-03-03"), WEEK("1998-03-03"), QUARTER(980303);
select HOUR("1997-03-03 23:03:22"), MINUTE("23:03:22"), SECOND(230322);
+
+# Test of week and yearweek
select week(19980101),week(19970101),week(19980101,1),week(19970101,1);
select week(19981231),week(19971231),week(19981231,1),week(19971231,1);
select week(19950101),week(19950101,1);
select yearweek('1981-12-31',1),yearweek('1982-01-01',1),yearweek('1982-12-31',1),yearweek('1983-01-01',1);
+select yearweek('1987-01-01',1),yearweek('1987-01-01');
+select week("2000-01-01",0) as '2000', week("2001-01-01",0) as '2001', week("2002-01-01",0) as '2002',week("2003-01-01",0) as '2003', week("2004-01-01",0) as '2004', week("2005-01-01",0) as '2005', week("2006-01-01",0) as '2006';
+select week("2000-01-06",0) as '2000', week("2001-01-06",0) as '2001', week("2002-01-06",0) as '2002',week("2003-01-06",0) as '2003', week("2004-01-06",0) as '2004', week("2005-01-06",0) as '2005', week("2006-01-06",0) as '2006';
+select week("2000-01-01",1) as '2000', week("2001-01-01",1) as '2001', week("2002-01-01",1) as '2002',week("2003-01-01",1) as '2003', week("2004-01-01",1) as '2004', week("2005-01-01",1) as '2005', week("2006-01-01",1) as '2006';
+select week("2000-01-06",1) as '2000', week("2001-01-06",1) as '2001', week("2002-01-06",1) as '2002',week("2003-01-06",1) as '2003', week("2004-01-06",1) as '2004', week("2005-01-06",1) as '2005', week("2006-01-06",1) as '2006';
+select yearweek("2000-01-01",0) as '2000', yearweek("2001-01-01",0) as '2001', yearweek("2002-01-01",0) as '2002',yearweek("2003-01-01",0) as '2003', yearweek("2004-01-01",0) as '2004', yearweek("2005-01-01",0) as '2005', yearweek("2006-01-01",0) as '2006';
+select yearweek("2000-01-06",0) as '2000', yearweek("2001-01-06",0) as '2001', yearweek("2002-01-06",0) as '2002',yearweek("2003-01-06",0) as '2003', yearweek("2004-01-06",0) as '2004', yearweek("2005-01-06",0) as '2005', yearweek("2006-01-06",0) as '2006';
+select yearweek("2000-01-01",1) as '2000', yearweek("2001-01-01",1) as '2001', yearweek("2002-01-01",1) as '2002',yearweek("2003-01-01",1) as '2003', yearweek("2004-01-01",1) as '2004', yearweek("2005-01-01",1) as '2005', yearweek("2006-01-01",1) as '2006';
+select yearweek("2000-01-06",1) as '2000', yearweek("2001-01-06",1) as '2001', yearweek("2002-01-06",1) as '2002',yearweek("2003-01-06",1) as '2003', yearweek("2004-01-06",1) as '2004', yearweek("2005-01-06",1) as '2005', yearweek("2006-01-06",1) as '2006';
select date_format('1998-12-31','%x-%v'),date_format('1999-01-01','%x-%v');
select date_format('1999-12-31','%x-%v'),date_format('2000-01-01','%x-%v');
-select yearweek('1987-01-01',1),yearweek('1987-01-01');
select dayname("1962-03-03"),dayname("1962-03-03")+0;
select monthname("1972-03-04"),monthname("1972-03-04")+0;
diff --git a/mysql-test/t/gemini.test b/mysql-test/t/gemini.test
deleted file mode 100644
index 9d4451c3551..00000000000
--- a/mysql-test/t/gemini.test
+++ /dev/null
@@ -1,355 +0,0 @@
--- source include/have_gemini.inc
-
-#
-# Small basic test with ignore
-#
-
-drop table if exists t1;
-create table t1 (id int unsigned not null auto_increment, code tinyint unsigned not null, name char(20) not null, primary key (id), key (code), unique (name)) type=gemini;
-
-insert into t1 (code, name) values (1, 'Tim'), (1, 'Monty'), (2, 'David'), (2, 'Erik'), (3, 'Sasha'), (3, 'Jeremy'), (4, 'Matt');
-select id, code, name from t1 order by id;
-
-update ignore t1 set id = 8, name = 'Sinisa' where id < 3;
-select id, code, name from t1 order by id;
-update ignore t1 set id = id + 10, name = 'Ralph' where id < 4;
-select id, code, name from t1 order by id;
-
-drop table t1;
-
-#
-# A bit bigger test
-#
-
-CREATE TABLE t1 (
- id int(11) NOT NULL auto_increment,
- parent_id int(11) DEFAULT '0' NOT NULL,
- level tinyint(4) DEFAULT '0' NOT NULL,
- PRIMARY KEY (id),
- KEY parent_id (parent_id),
- KEY level (level)
-) type=gemini;
-INSERT INTO t1 VALUES (1,0,0),(3,1,1),(4,1,1),(8,2,2),(9,2,2),(17,3,2),(22,4,2),(24,4,2),(28,5,2),(29,5,2),(30,5,2),(31,6,2),(32,6,2),(33,6,2),(203,7,2),(202,7,2),(20,3,2),(157,0,0),(193,5,2),(40,7,2),(2,1,1),(15,2,2),(6,1,1),(34,6,2),(35,6,2),(16,3,2),(7,1,1),(36,7,2),(18,3,2),(26,5,2),(27,5,2),(183,4,2),(38,7,2),(25,5,2),(37,7,2),(21,4,2),(19,3,2),(5,1,1),(179,5,2);
-update t1 set parent_id=parent_id+100;
-select * from t1 where parent_id=102;
-update t1 set id=id+1000;
-!$1062 update t1 set id=1024 where id=1009;
-select * from t1;
-update ignore t1 set id=id+1; # This will change all rows
-select * from t1;
-update ignore t1 set id=1023 where id=1010;
-select * from t1 where parent_id=102;
-explain select level from t1 where level=1;
-explain select level,id from t1 where level=1;
-explain select level,id,parent_id from t1 where level=1;
-select level,id from t1 where level=1;
-select level,id,parent_id from t1 where level=1;
-drop table t1;
-
-#
-# Test replace
-#
-
-CREATE TABLE t1 (
- gesuchnr int(11) DEFAULT '0' NOT NULL,
- benutzer_id int(11) DEFAULT '0' NOT NULL,
- PRIMARY KEY (gesuchnr,benutzer_id)
-) type=gemini;
-
-replace into t1 (gesuchnr,benutzer_id) values (2,1);
-replace into t1 (gesuchnr,benutzer_id) values (1,1);
-replace into t1 (gesuchnr,benutzer_id) values (1,1);
-select * from t1;
-drop table t1;
-
-#
-# test delete using hidden_primary_key
-#
-
-create table t1 (a int) type=gemini;
-insert into t1 values (1), (2);
-delete from t1 where a = 1;
-select * from t1;
-drop table t1;
-
-#
-# Test auto_increment on sub key
-#
-
-#create table t1 (a char(10) not null, b int not null auto_increment, primary key(a,b)) type=gemini;
-#insert into t1 values ("a",1),("b",2),("a",2),("c",1);
-#insert into t1 values ("a",NULL),("b",NULL),("c",NULL),("e",NULL);
-#insert into t1 (a) values ("a"),("b"),("c"),("d");
-#insert into t1 (a) values ('k'),('d');
-#insert into t1 (a) values ("a");
-#insert into t1 values ("d",last_insert_id());
-#select * from t1;
-#drop table t1;
-
-#
-# Test when reading on part of unique key
-#
-CREATE TABLE t1 (
- user_id int(10) DEFAULT '0' NOT NULL,
- name varchar(100),
- phone varchar(100),
- ref_email varchar(100) DEFAULT '' NOT NULL,
- detail varchar(200),
- PRIMARY KEY (user_id,ref_email)
-)type=gemini;
-
-INSERT INTO t1 VALUES (10292,'sanjeev','29153373','sansh777@hotmail.com','xxx'),(10292,'shirish','2333604','shirish@yahoo.com','ddsds'),(10292,'sonali','323232','sonali@bolly.com','filmstar');
-select * from t1 where user_id=10292;
-INSERT INTO t1 VALUES (10291,'sanjeev','29153373','sansh777@hotmail.com','xxx'),(10293,'shirish','2333604','shirish@yahoo.com','ddsds');
-select * from t1 where user_id=10292;
-select * from t1 where user_id>=10292;
-select * from t1 where user_id>10292;
-select * from t1 where user_id<10292;
-drop table t1;
-
-#
-# Test that keys are created in right order
-# - Needs ANALYZE TABLE to work - MikeF 2/12/01
-#
-#CREATE TABLE t1 (a int not null, b int not null,c int not null,
-#key(a),primary key(a,b), unique(c),key(a),unique(b)) type = gemini;
-#show index from t1;
-#drop table t1;
-
-#
-# Test of ALTER TABLE and gemini tables
-#
-
-#create table t1 (col1 int not null, col2 char(4) not null, primary key(col1));
-#alter table t1 type=gemini;
-#insert into t1 values ('1','1'),('5','2'),('2','3'),('3','4'),('4','4');
-#select * from t1;
-#update t1 set col2='7' where col1='4';
-#select * from t1;
-#alter table t1 add co3 int not null;
-#select * from t1;
-#update t1 set col2='9' where col1='2';
-#select * from t1;
-#drop table t1;
-
-#
-# INSERT INTO gemini tables
-#
-
-create table t1 (a int not null , b int, primary key (a)) type = gemini;
-create table t2 (a int not null , b int, primary key (a)) type = myisam;
-insert into t1 VALUES (1,3) , (2,3), (3,3);
-select * from t1;
-insert into t2 select * from t1;
-select * from t2;
-delete from t1 where b = 3;
-select * from t1;
-insert into t1 select * from t2;
-select * from t1;
-select * from t2;
-drop table t1,t2;
-
-#
-# Search on unique key
-#
-
-CREATE TABLE t1 (
- id int(11) NOT NULL auto_increment,
- ggid varchar(32) binary DEFAULT '' NOT NULL,
- email varchar(64) DEFAULT '' NOT NULL,
- passwd varchar(32) binary DEFAULT '' NOT NULL,
- PRIMARY KEY (id),
- UNIQUE ggid (ggid)
-) TYPE=gemini;
-
-insert into t1 (ggid,passwd) values ('test1','xxx');
-insert into t1 (ggid,passwd) values ('test2','yyy');
-
-select * from t1 where ggid='test1';
-select * from t1 where passwd='xxx';
-select * from t1 where id=2;
-drop table t1;
-
-#
-# ORDER BY on not primary key
-#
-
-#CREATE TABLE t1 (
-# user_name varchar(12),
- #password text,
- #subscribed char(1),
- #user_id int(11) DEFAULT '0' NOT NULL,
- #quota bigint(20),
- #weight double,
- #access_date date,
- #access_time time,
- #approved datetime,
- #dummy_primary_key int(11) NOT NULL auto_increment,
- #PRIMARY KEY (dummy_primary_key)
-#) TYPE=gemini;
-#INSERT INTO t1 VALUES ('user_0','somepassword','N',0,0,0,'2000-09-07','23:06:59','2000-09-07 23:06:59',1);
-#INSERT INTO t1 VALUES ('user_1','somepassword','Y',1,1,1,'2000-09-07','23:06:59','2000-09-07 23:06:59',2);
-#INSERT INTO t1 VALUES ('user_2','somepassword','N',2,2,1.4142135623731,'2000-09-07','23:06:59','2000-09-07 23:06:59',3);
-#INSERT INTO t1 VALUES ('user_3','somepassword','Y',3,3,1.7320508075689,'2000-09-07','23:06:59','2000-09-07 23:06:59',4);
-#INSERT INTO t1 VALUES ('user_4','somepassword','N',4,4,2,'2000-09-07','23:06:59','2000-09-07 23:06:59',5);
-#select user_name, password , subscribed, user_id, quota, weight, access_date, access_time, approved, dummy_primary_key from t1 order by user_name;
-#drop table t1;
-
-#
-# Testing of tables without primary keys
-#
-
-CREATE TABLE t1 (
- id int(11) NOT NULL auto_increment,
- parent_id int(11) DEFAULT '0' NOT NULL,
- level tinyint(4) DEFAULT '0' NOT NULL,
- KEY (id),
- KEY parent_id (parent_id),
- KEY level (level)
-) type=gemini;
-INSERT INTO t1 VALUES (1,0,0),(3,1,1),(4,1,1),(8,2,2),(9,2,2),(17,3,2),(22,4,2),(24,4,2),(28,5,2),(29,5,2),(30,5,2),(31,6,2),(32,6,2),(33,6,2),(203,7,2),(202,7,2),(20,3,2),(157,0,0),(193,5,2),(40,7,2),(2,1,1),(15,2,2),(6,1,1),(34,6,2),(35,6,2),(16,3,2),(7,1,1),(36,7,2),(18,3,2),(26,5,2),(27,5,2),(183,4,2),(38,7,2),(25,5,2),(37,7,2),(21,4,2),(19,3,2),(5,1,1);
-INSERT INTO t1 values (179,5,2);
-update t1 set parent_id=parent_id+100;
-select * from t1 where parent_id=102;
-update t1 set id=id+1000;
-update t1 set id=1024 where id=1009;
-select * from t1;
-update ignore t1 set id=id+1; # This will change all rows
-select * from t1;
-update ignore t1 set id=1023 where id=1010;
-select * from t1 where parent_id=102;
-explain select level from t1 where level=1;
-select level,id from t1 where level=1;
-select level,id,parent_id from t1 where level=1;
-select level,id from t1 where level=1 order by id;
-delete from t1 where level=1;
-select * from t1;
-drop table t1;
-
-#
-# Test of index only reads
-#
-CREATE TABLE t1 (
- sca_code char(6) NOT NULL,
- cat_code char(6) NOT NULL,
- sca_desc varchar(50),
- lan_code char(2) NOT NULL,
- sca_pic varchar(100),
- sca_sdesc varchar(50),
- sca_sch_desc varchar(16),
- PRIMARY KEY (sca_code, cat_code, lan_code)
-) type = gemini ;
-
-INSERT INTO t1 ( sca_code, cat_code, sca_desc, lan_code, sca_pic, sca_sdesc, sca_sch_desc) VALUES ( 'PD', 'J', 'PENDANT', 'EN', NULL, NULL, 'PENDANT'),( 'RI', 'J', 'RING', 'EN', NULL, NULL, 'RING');
-select count(*) from t1 where sca_code = 'PD';
-drop table t1;
-
-#
-# Test of opening table twice
-#
-CREATE TABLE t1 (a int not null, primary key (a)) type=gemini;
-insert into t1 values(1),(2),(3);
-select t1.a from t1 natural join t1 as t2 order by t1.a;
-drop table t1;
-
-#
-# Test rollback
-#
-
-select "test for rollback";
-create table t1 (n int not null primary key) type=gemini;
-set autocommit=0;
-insert into t1 values (4);
-commit;
-insert into t1 values (5);
-rollback;
-select n, "after rollback" from t1;
-insert into t1 values (5);
-commit;
-select n, "after commit" from t1;
-commit;
-insert into t1 values (6);
-!$1062 insert into t1 values (4);
-commit;
-select n, "after commit" from t1;
-set autocommit=1;
-insert into t1 values (7);
-!$1062 insert into t1 values (4);
-select n from t1;
-# nop
-rollback;
-drop table t1;
-
-#
-# Testing transactions
-#
-
-create table t1 ( id int NOT NULL PRIMARY KEY, nom varchar(64)) type=gemini;
-insert into t1 values(1,'first');
-begin;
-insert into t1 values(2,'hamdouni');
-select id as afterbegin_id,nom as afterbegin_nom from t1;
-rollback;
-select id as afterrollback_id,nom as afterrollback_nom from t1;
-set autocommit=0;
-insert into t1 values(3,'mysql');
-select id as afterautocommit0_id,nom as afterautocommit0_nom from t1;
-rollback;
-select id as afterrollback_id,nom as afterrollback_nom from t1;
-set autocommit=1;
-drop table t1;
-
-#
-# Simple not autocommit test
-#
-
-CREATE TABLE t1 (id char(8) not null primary key, val int not null) type=gemini;
-insert into t1 values ('pippo', 12);
-!$1062 insert into t1 values ('pippo', 12); # Gives error
-delete from t1;
-delete from t1 where id = 'pippo';
-select * from t1;
-
-insert into t1 values ('pippo', 12);
-set autocommit=0;
-delete from t1;
-rollback;
-select * from t1;
-delete from t1;
-commit;
-select * from t1;
-drop table t1;
-set autocommit=1;
-
-#
-# The following simple tests failed at some point
-#
-
-CREATE TABLE t1 (ID INTEGER NOT NULL PRIMARY KEY, NAME VARCHAR(64)) TYPE=gemini;
-INSERT INTO t1 VALUES (1, 'Jochen');
-select * from t1;
-drop table t1;
-
-CREATE TABLE t1 ( _userid VARCHAR(60) NOT NULL PRIMARY KEY) TYPE=gemini;
-set autocommit=0;
-INSERT INTO t1 SET _userid='marc@anyware.co.uk';
-COMMIT;
-SELECT * FROM t1;
-SELECT _userid FROM t1 WHERE _userid='marc@anyware.co.uk';
-drop table t1;
-set autocommit=1;
-
-#
-# Test of load data infile
-#
-
-CREATE TABLE if not exists `t1` (
- `f1` int(11) unsigned NOT NULL default '0',
- `f2` tinyint(3) unsigned NOT NULL default '0',
- `f3` tinyint(3) unsigned NOT NULL default '0',
- PRIMARY KEY (`f1`)
-) TYPE=Gemini;
-lock table t1 write;
-load data infile ''../../std_data/gemini.dat' ignore into table t1 fields terminated by ',';
-select f1 from t1;
-drop table t1;
diff --git a/mysql-test/t/grant_cache-master.opt b/mysql-test/t/grant_cache-master.opt
new file mode 100644
index 00000000000..cfdce628e74
--- /dev/null
+++ b/mysql-test/t/grant_cache-master.opt
@@ -0,0 +1 @@
+--set-variable=query_cache_size=1355776
diff --git a/mysql-test/t/grant_cache.test b/mysql-test/t/grant_cache.test
new file mode 100644
index 00000000000..a6c878cc31c
--- /dev/null
+++ b/mysql-test/t/grant_cache.test
@@ -0,0 +1,102 @@
+#
+# Test grants with query cache
+#
+drop table if exists test.t1,mysqltest.t1,mysqltest.t2;
+reset query cache;
+flush status;
+connect (root,localhost,root,,test,0,master.sock);
+connection root;
+create database if not exists mysqltest;
+
+create table mysqltest.t1 (a int,b int,c int);
+create table mysqltest.t2 (a int,b int,c int);
+insert into mysqltest.t1 values (1,1,1),(2,2,2);
+insert into mysqltest.t2 values (3,3,3);
+create table test.t1 (a char (10));
+insert into test.t1 values ("test.t1");
+select * from t1;
+connect (root2,localhost,root,,mysqltest,0,master.sock);
+connection root2;
+# put queries in cache
+select * from t1;
+select a from t1;
+select c from t1;
+select * from t2;
+select * from mysqltest.t1,test.t1;
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_hits%";
+
+# Create the test users
+grant SELECT on mysqltest.* to mysqltest_1@localhost;
+grant SELECT on mysqltest.t1 to mysqltest_2@localhost;
+grant SELECT on test.t1 to mysqltest_2@localhost;
+grant SELECT(a) on mysqltest.t1 to mysqltest_3@localhost;
+
+# The following queries should be fetched from cache
+connect (user1,localhost,mysqltest_1,,mysqltest,0,master.sock);
+connection user1;
+select "user1";
+select * from t1;
+# The pre and end space are intentional
+ select a from t1 ;
+select c from t1;
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_hits";
+show status like "Qcache_not_cached";
+
+# The following queries should be fetched from cache
+connect (user2,localhost,mysqltest_2,,mysqltest,0,master.sock);
+connection user2;
+select "user2";
+select * from t1;
+select a from t1;
+select c from t1;
+select * from mysqltest.t1,test.t1;
+--error 1142
+select * from t2;
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_hits";
+show status like "Qcache_not_cached";
+
+# The following queries should not be fetched from cache
+connect (user3,localhost,mysqltest_3,,mysqltest,0,master.sock);
+connection user3;
+select "user3";
+--error 1143
+select * from t1;
+select a from t1;
+--error 1143
+select c from t1;
+--error 1142
+select * from t2;
+--error 1143
+select mysqltest.t1.c from test.t1,mysqltest.t1;
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_hits";
+show status like "Qcache_not_cached";
+
+# Connect without a database
+connect (user4,localhost,mysqltest_1,,*NO-ONE*,0,master.sock);
+connection user4;
+select "user4";
+--error 1046
+select a from t1;
+# The following query is not cached before (different database)
+select * from mysqltest.t1,test.t1;
+# Cache a query with 'no database'
+select a from mysqltest.t1;
+select a from mysqltest.t1;
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_hits";
+show status like "Qcache_not_cached";
+
+# Cleanup
+
+connection root;
+delete from mysql.user where user in ("mysqltest_1","mysqltest_2","mysqltest_3");
+delete from mysql.db where user in ("mysqltest_1","mysqltest_2","mysqltest_3");
+delete from mysql.tables_priv where user in ("mysqltest_1","mysqltest_2","mysqltest_3");
+delete from mysql.columns_priv where user in ("mysqltest_1","mysqltest_2","mysqltest_3");
+flush privileges;
+drop table test.t1,mysqltest.t1,mysqltest.t2;
+drop database mysqltest;
diff --git a/mysql-test/t/group_by.test b/mysql-test/t/group_by.test
index efa1744feee..17ad9588f1b 100644
--- a/mysql-test/t/group_by.test
+++ b/mysql-test/t/group_by.test
@@ -243,3 +243,43 @@ select sql_big_result spid,sum(userid) from t1 group by spid desc;
explain select sql_big_result score,count(*) from t1 group by score desc;
select sql_big_result score,count(*) from t1 group by score desc;
drop table t1;
+
+#
+# Compare with hash keys
+#
+
+CREATE TABLE t1 (a char(1));
+INSERT INTO t1 VALUES ('A'),('B'),('A'),('B'),('A'),('B'),(NULL),('a'),('b'),(NULL),('A'),('B'),(NULL);
+SELECT a FROM t1 GROUP BY a;
+SELECT a,count(*) FROM t1 GROUP BY a;
+SELECT a FROM t1 GROUP BY binary a;
+SELECT a,count(*) FROM t1 GROUP BY binary a;
+SELECT binary a FROM t1 GROUP BY 1;
+SELECT binary a,count(*) FROM t1 GROUP BY 1;
+# Do the same tests with MyISAM temporary tables
+SET SQL_BIG_TABLES=1;
+SELECT a FROM t1 GROUP BY a;
+SELECT a,count(*) FROM t1 GROUP BY a;
+SELECT a FROM t1 GROUP BY binary a;
+SELECT a,count(*) FROM t1 GROUP BY binary a;
+SELECT binary a FROM t1 GROUP BY 1;
+SELECT binary a,count(*) FROM t1 GROUP BY 1;
+SET SQL_BIG_TABLES=0;
+drop table t1;
+
+#
+# Test of key >= 256 bytes
+#
+
+CREATE TABLE t1 (
+ `a` char(193) default NULL,
+ `b` char(63) default NULL
+);
+INSERT INTO t1 VALUES ('abc','def'),('hij','klm');
+SELECT CONCAT(a, b) FROM t1 GROUP BY 1;
+SELECT CONCAT(a, b),count(*) FROM t1 GROUP BY 1;
+SELECT CONCAT(a, b),count(distinct a) FROM t1 GROUP BY 1;
+SELECT 1 FROM t1 GROUP BY CONCAT(a, b);
+INSERT INTO t1 values ('hij','klm');
+SELECT CONCAT(a, b),count(*) FROM t1 GROUP BY 1;
+DROP TABLE t1;
diff --git a/mysql-test/t/handler.test b/mysql-test/t/handler.test
new file mode 100644
index 00000000000..4f1b11c80ff
--- /dev/null
+++ b/mysql-test/t/handler.test
@@ -0,0 +1,67 @@
+#
+# test of HANDLER ...
+#
+
+drop table if exists t1;
+create table t1 (a int, b char(10), key a(a), key b(a,b));
+insert into t1 values
+(17,"ddd"),(18,"eee"),(19,"fff"),(19,"yyy"),
+(14,"aaa"),(15,"bbb"),(16,"ccc"),(16,"xxx"),
+(20,"ggg"),(21,"hhh"),(22,"iii");
+handler t1 open as t2;
+handler t2 read a first;
+handler t2 read a next;
+handler t2 read a next;
+handler t2 read a prev;
+handler t2 read a last;
+handler t2 read a prev;
+handler t2 read a prev;
+
+handler t2 read a first;
+handler t2 read a prev;
+
+handler t2 read a last;
+handler t2 read a prev;
+handler t2 read a next;
+handler t2 read a next;
+
+handler t2 read a=(15);
+handler t2 read a=(16);
+
+!$1070 handler t2 read a=(19,"fff");
+
+handler t2 read b=(19,"fff");
+handler t2 read b=(19,"yyy");
+handler t2 read b=(19);
+
+!$1109 handler t1 read a last;
+
+handler t2 read a=(11);
+handler t2 read a>=(11);
+
+handler t2 read a=(18);
+handler t2 read a>=(18);
+handler t2 read a>(18);
+handler t2 read a<=(18);
+handler t2 read a<(18);
+
+handler t2 read a first limit 5;
+handler t2 read a next limit 3;
+handler t2 read a prev limit 10;
+
+handler t2 read a>=(16) limit 4;
+handler t2 read a>=(16) limit 2,2;
+handler t2 read a last limit 3;
+
+handler t2 read a=(19);
+handler t2 read a=(19) where b="yyy";
+
+handler t2 read first;
+handler t2 read next;
+alter table t1 type=MyISAM;
+handler t2 read next;
+!$1064 handler t2 read last;
+
+handler t2 close;
+drop table if exists t1;
+
diff --git a/mysql-test/t/heap.test b/mysql-test/t/heap.test
index abb9e1fd1bc..b08e8f6ea36 100644
--- a/mysql-test/t/heap.test
+++ b/mysql-test/t/heap.test
@@ -100,3 +100,25 @@ update t1 set new_col=btn;
explain select * from t1 where btn="a";
explain select * from t1 where btn="a" and new_col="a";
drop table t1;
+
+#
+# Test of NULL keys
+#
+
+CREATE TABLE t1 (
+ a int default NULL,
+ b int default NULL,
+ KEY a (a),
+ UNIQUE b (b)
+) type=heap;
+INSERT INTO t1 VALUES (NULL,99),(99,NULL),(1,1),(2,2),(1,3);
+SELECT * FROM t1 WHERE a=NULL;
+explain SELECT * FROM t1 WHERE a IS NULL;
+SELECT * FROM t1 WHERE a<=>NULL;
+SELECT * FROM t1 WHERE b=NULL;
+explain SELECT * FROM t1 WHERE b IS NULL;
+SELECT * FROM t1 WHERE b<=>NULL;
+
+--error 1062
+INSERT INTO t1 VALUES (1,3);
+DROP TABLE t1;
diff --git a/mysql-test/t/innodb.test b/mysql-test/t/innodb.test
index a962f120d4e..1b7ee99e15a 100644
--- a/mysql-test/t/innodb.test
+++ b/mysql-test/t/innodb.test
@@ -515,6 +515,53 @@ select * from t1;
drop table t1;
#
+# Test DROP DATABASE
+#
+
+create database mysqltest;
+create table mysqltest.t1 (a int not null) type= innodb;
+insert into mysqltest.t1 values(1);
+create table mysqltest.t2 (a int not null) type= myisam;
+insert into mysqltest.t2 values(1);
+create table mysqltest.t3 (a int not null) type= heap;
+insert into mysqltest.t3 values(1);
+commit;
+drop database mysqltest;
+# Don't check error message
+--error 12,12
+show tables from mysqltest;
+
+#
+# Test truncate table with and without auto_commit
+#
+
+set autocommit=0;
+create table t1 (a int not null) type= innodb;
+insert into t1 values(1),(2);
+--error 1192
+truncate table t1;
+commit;
+truncate table t1;
+select * from t1;
+insert into t1 values(1),(2);
+delete from t1;
+select * from t1;
+commit;
+drop table t1;
+set autocommit=1;
+
+create table t1 (a int not null) type= innodb;
+insert into t1 values(1),(2);
+truncate table t1;
+insert into t1 values(1),(2);
+select * from t1;
+truncate table t1;
+insert into t1 values(1),(2);
+delete from t1;
+select * from t1;
+drop table t1;
+
+#
# Test of how ORDER BY works when doing it on the whole table
#
@@ -531,9 +578,63 @@ explain select a,b,c from t1;
drop table t1;
#
-# Check describe
+# Check describe & handler
#
-create table t1 (testint int not null default 1) type=innodb;
+create table t1 (t int not null default 1, key (t)) type=innodb;
desc t1;
+--error 1031
+handler t1 open t1;
+--error 1109
+handler t1 read t first;
+--error 1109
+handler t1 close;
drop table t1;
+
+#
+# Test of multi-table-delete
+#
+
+CREATE TABLE t1 (
+ number bigint(20) NOT NULL default '0',
+ cname char(15) NOT NULL default '',
+ carrier_id smallint(6) NOT NULL default '0',
+ privacy tinyint(4) NOT NULL default '0',
+ last_mod_date timestamp(14) NOT NULL,
+ last_mod_id smallint(6) NOT NULL default '0',
+ last_app_date timestamp(14) NOT NULL,
+ last_app_id smallint(6) default '-1',
+ version smallint(6) NOT NULL default '0',
+ assigned_scps int(11) default '0',
+ status tinyint(4) default '0'
+) TYPE=InnoDB;
+INSERT INTO t1 VALUES (4077711111,'SeanWheeler',90,2,20020111112846,500,00000000000000,-1,2,3,1);
+INSERT INTO t1 VALUES (9197722223,'berry',90,3,20020111112809,500,20020102114532,501,4,10,0);
+INSERT INTO t1 VALUES (650,'San Francisco',0,0,20011227111336,342,00000000000000,-1,1,24,1);
+INSERT INTO t1 VALUES (302467,'Sue\'s Subshop',90,3,20020109113241,500,20020102115111,501,7,24,0);
+INSERT INTO t1 VALUES (6014911113,'SudzCarwash',520,1,20020102115234,500,20020102115259,501,33,32768,0);
+INSERT INTO t1 VALUES (333,'tubs',99,2,20020109113440,501,20020109113440,500,3,10,0);
+CREATE TABLE t2 (
+ number bigint(20) NOT NULL default '0',
+ cname char(15) NOT NULL default '',
+ carrier_id smallint(6) NOT NULL default '0',
+ privacy tinyint(4) NOT NULL default '0',
+ last_mod_date timestamp(14) NOT NULL,
+ last_mod_id smallint(6) NOT NULL default '0',
+ last_app_date timestamp(14) NOT NULL,
+ last_app_id smallint(6) default '-1',
+ version smallint(6) NOT NULL default '0',
+ assigned_scps int(11) default '0',
+ status tinyint(4) default '0'
+) TYPE=InnoDB;
+INSERT INTO t2 VALUES (4077711111,'SeanWheeler',0,2,20020111112853,500,00000000000000,-1,2,3,1);
+INSERT INTO t2 VALUES (9197722223,'berry',90,3,20020111112818,500,20020102114532,501,4,10,0);
+INSERT INTO t2 VALUES (650,'San Francisco',90,0,20020109113158,342,00000000000000,-1,1,24,1);
+INSERT INTO t2 VALUES (333,'tubs',99,2,20020109113453,501,20020109113453,500,3,10,0);
+select * from t1;
+select * from t2;
+delete t1, t2 from t1 left join t2 on t1.number=t2.number where (t1.carrier_id=90 and t1.number=t2.number) or (t2.carrier_id=90 and t1.number=t2.number) or (t1.carrier_id=90 and t2.number is null);
+select * from t1;
+select * from t2;
+select * from t2;
+drop table t1,t2;
diff --git a/mysql-test/t/innodb_cache-master.opt b/mysql-test/t/innodb_cache-master.opt
new file mode 100644
index 00000000000..5f0ebff98f6
--- /dev/null
+++ b/mysql-test/t/innodb_cache-master.opt
@@ -0,0 +1 @@
+--set-variable=query_cache_size=1M
diff --git a/mysql-test/t/innodb_cache.test b/mysql-test/t/innodb_cache.test
new file mode 100644
index 00000000000..0a162a9debe
--- /dev/null
+++ b/mysql-test/t/innodb_cache.test
@@ -0,0 +1,14 @@
+-- source include/have_innodb.inc
+
+#
+# Without auto_commit.
+#
+drop table if exists t1;
+set autocommit=0;
+create table t1 (a int not null) type=innodb;
+insert into t1 values (1),(2),(3);
+select * from t1;
+show status like "Qcache_queries_in_cache";
+drop table t1;
+commit;
+set autocommit=1;
diff --git a/mysql-test/t/insert.test b/mysql-test/t/insert.test
index cf6f41d454d..270b1cd4c79 100644
--- a/mysql-test/t/insert.test
+++ b/mysql-test/t/insert.test
@@ -10,3 +10,15 @@ insert into t1 values (a+3);
insert into t1 values (4),(a+5);
select * from t1;
drop table t1;
+
+#
+# Test of duplicate key values with packed keys
+#
+
+create table t1 (id int not null auto_increment primary key, username varchar(32) not null, unique (username));
+insert into t1 values (0,"mysql");
+insert into t1 values (0,"mysql ab");
+insert into t1 values (0,"mysql a");
+insert into t1 values (0,"r1manic");
+insert into t1 values (0,"r1man");
+drop table t1;
diff --git a/mysql-test/t/insert_select.test b/mysql-test/t/insert_select.test
index 17ecb2d5a1f..42f65858d77 100644
--- a/mysql-test/t/insert_select.test
+++ b/mysql-test/t/insert_select.test
@@ -7,6 +7,64 @@ create table t1 (bandID MEDIUMINT UNSIGNED NOT NULL PRIMARY KEY, payoutID SMALLI
insert into t1 (bandID,payoutID) VALUES (1,6),(2,6),(3,4),(4,9),(5,10),(6,1),(7,12),(8,12);
create table t2 (payoutID SMALLINT UNSIGNED NOT NULL PRIMARY KEY);
insert into t2 (payoutID) SELECT DISTINCT payoutID FROM t1;
+--error 1062
insert into t2 (payoutID) SELECT payoutID+10 FROM t1;
+insert ignore into t2 (payoutID) SELECT payoutID+10 FROM t1;
select * from t2;
drop table t1,t2;
+#
+# bug in bulk insert optimization
+# test case by Fournier Jocelyn <joc@presence-pc.com>
+#
+
+DROP TABLE IF EXISTS crash1,crash2;
+CREATE TABLE `crash1` (
+ `numeropost` bigint(20) unsigned NOT NULL default '0',
+ `icone` tinyint(4) unsigned NOT NULL default '0',
+ `numreponse` bigint(20) unsigned NOT NULL auto_increment,
+ `contenu` text NOT NULL,
+ `pseudo` varchar(50) NOT NULL default '',
+ `date` datetime NOT NULL default '0000-00-00 00:00:00',
+ `ip` bigint(11) NOT NULL default '0',
+ `signature` tinyint(1) unsigned NOT NULL default '0',
+ PRIMARY KEY (`numeropost`,`numreponse`)
+ ,KEY `ip` (`ip`),
+ KEY `date` (`date`),
+ KEY `pseudo` (`pseudo`),
+ KEY `numreponse` (`numreponse`)
+) TYPE=MyISAM;
+
+CREATE TABLE `crash2` (
+ `numeropost` bigint(20) unsigned NOT NULL default '0',
+ `icone` tinyint(4) unsigned NOT NULL default '0',
+ `numreponse` bigint(20) unsigned NOT NULL auto_increment,
+ `contenu` text NOT NULL,
+ `pseudo` varchar(50) NOT NULL default '',
+ `date` datetime NOT NULL default '0000-00-00 00:00:00',
+ `ip` bigint(11) NOT NULL default '0',
+ `signature` tinyint(1) unsigned NOT NULL default '0',
+ PRIMARY KEY (`numeropost`,`numreponse`),
+ KEY `ip` (`ip`),
+ KEY `date` (`date`),
+ KEY `pseudo` (`pseudo`),
+ KEY `numreponse` (`numreponse`)
+) TYPE=MyISAM;
+
+INSERT INTO crash2
+(numeropost,icone,numreponse,contenu,pseudo,date,ip,signature) VALUES
+(9,1,56,'test','joce','2001-07-25 13:50:53'
+,3649052399,0);
+
+
+INSERT INTO crash1 (numeropost,icone,contenu,pseudo,date,signature,ip)
+SELECT 1618,icone,contenu,pseudo,date,signature,ip FROM crash2
+WHERE numeropost=9 ORDER BY numreponse ASC;
+
+show variables like '%bulk%';
+
+INSERT INTO crash1 (numeropost,icone,contenu,pseudo,date,signature,ip)
+SELECT 1718,icone,contenu,pseudo,date,signature,ip FROM crash2
+WHERE numeropost=9 ORDER BY numreponse ASC;
+
+DROP TABLE IF EXISTS crash1,crash2;
+
diff --git a/mysql-test/t/isam.test b/mysql-test/t/isam.test
index 1cf068b42ba..c7308c4b999 100644
--- a/mysql-test/t/isam.test
+++ b/mysql-test/t/isam.test
@@ -1,19 +1,66 @@
+-- source include/have_isam.inc
+
+drop table if exists t1,t2;
+
#
# Test possible problem with rows that are about 65535 bytes long
#
-create table t1 (a tinyint not null auto_increment, b blob not null, primary key (a));
+create table t1 (a tinyint not null auto_increment, b blob not null, primary key (a)) type=isam;
let $1=100;
+disable_query_log;
while ($1)
{
eval insert into t1 (b) values(repeat(char(65+$1),65540-$1));
dec $1;
}
-check table t1;
-repair table t1;
+enable_query_log;
delete from t1 where (a & 1);
-check table t1;
-repair table t1;
-check table t1;
+select sum(length(b)) from t1;
+drop table t1;
+
+#
+# Test of auto_increment; The test for BDB tables is in bdb.test
+#
+
+create table t1 (a int not null auto_increment,b int, primary key (a)) type=isam;
+insert into t1 values (1,1),(NULL,2),(3,3),(NULL,4);
+delete from t1 where a=4 or a=2;
+insert into t1 values (NULL,4),(NULL,5),(6,6);
+select * from t1;
+delete from t1 where a=6;
+#show table status like "t1";
+replace t1 values (3,1);
+replace t1 values (3,3);
+ALTER TABLE t1 add c int;
+insert into t1 values (NULL,6,6);
+select * from t1;
drop table t1;
+
+#
+# Test of some CREATE TABLE's that should fail
+#
+!$1121 create table t1 (a int,b text, index(a)) type=isam;
+!$1073 create table t1 (a int,b text, index(b)) type=isam;
+!$1075 create table t1 (ordid int(8) not null auto_increment, ord varchar(50) not null, primary key (ord,ordid)) type=isam;
+!$1121 create table t1 (ordid int(8), unique (ordid)) type=isam;
+drop table if exists t1;
+
+#
+# Test of some show commands
+#
+
+create table t1 (a int not null primary key, b int not null,c int not null, key(b,c));
+insert into t1 values (1,2,2),(2,2,3),(3,2,4),(4,2,4);
+create table t2 type=isam select * from t1;
+optimize table t1;
+check table t1,t2;
+repair table t1,t2;
+check table t2,t1;
+lock tables t1 write;
+check table t2,t1;
+show columns from t1;
+show full columns from t1;
+show index from t1;
+drop table t1,t2;
diff --git a/mysql-test/t/isolation.test b/mysql-test/t/isolation.test
deleted file mode 100644
index d9750ecb351..00000000000
--- a/mysql-test/t/isolation.test
+++ /dev/null
@@ -1,208 +0,0 @@
-source include/have_gemini.inc
-source include/master-slave.inc;
-connection master;
-drop table if exists t1;
-create table t1 (f1 char(20) not null) type = gemini;
-set autocommit=0;
-
-insert into t1 (f1) values ("test1"), ("bar");
-connection master1;
-!$1030 select * from t1;
-connection master;
-commit;
-
-drop table if exists t1;
-create table t1 (f1 char(20) not null) type = gemini;
-insert into t1 (f1) values ("test2"), ("bar");
-connection master1;
-set transaction isolation level serializable;
-!$-1217 select * from t1;
-connection master;
-commit;
-
-drop table if exists t1;
-create table t1 (f1 char(20) not null) type = gemini;
-insert into t1 (f1) values ("test3"), ("bar");
-connection master1;
-set transaction isolation level read uncommitted;
-select * from t1;
-connection master;
-commit;
-
-drop table if exists t1;
-create table t1 (f1 char(20) not null) type = gemini;
-connection master1;
-set transaction isolation level read committed;
-select * from t1;
-connection master;
-commit;
-
-drop table if exists t1;
-create table t1 (f1 char(20) not null) type = gemini;
-insert into t1 (f1) values ("test4"), ("bar");
-connection master1;
-set transaction isolation level repeatable read;
-select * from t1;
-connection master;
-commit;
-
-drop table if exists t1;
-create table t1 (f1 char(20) not null) type = gemini;
-set transaction isolation level serializable;
-insert into t1 (f1) values ("test5"), ("bar");
-connection master1;
-set transaction isolation level serializable;
-select * from t1;
-connection master;
-commit;
-
-drop table if exists t1;
-create table t1 (f1 char(20) not null) type = gemini;
-set transaction isolation level serializable;
-insert into t1 (f1) values ("test6"), ("bar");
-connection master1;
-set transaction isolation level read uncommitted;
-select * from t1;
-connection master;
-commit;
-
-drop table if exists t1;
-create table t1 (f1 char(20) not null) type = gemini;
-set transaction isolation level serializable;
-insert into t1 (f1) values ("test7"), ("bar");
-connection master1;
-set transaction isolation level read committed;
-select * from t1;
-connection master;
-commit;
-
-drop table if exists t1;
-create table t1 (f1 char(20) not null) type = gemini;
-set transaction isolation level serializable;
-insert into t1 (f1) values ("test8"), ("bar");
-connection master1;
-set transaction isolation level repeatable read;
-select * from t1;
-connection master;
-commit;
-
-drop table if exists t1;
-create table t1 (f1 char(20) not null) type = gemini;
-set transaction isolation level read uncommitted;
-insert into t1 (f1) values ("test9"), ("bar");
-connection master1;
-set transaction isolation level serializable;
-select * from t1;
-connection master;
-commit;
-
-drop table if exists t1;
-create table t1 (f1 char(20) not null) type = gemini;
-set transaction isolation level read uncommitted;
-insert into t1 (f1) values ("test10"), ("bar");
-connection master1;
-set transaction isolation level read uncommitted;
-select * from t1;
-connection master;
-commit;
-
-drop table if exists t1;
-create table t1 (f1 char(20) not null) type = gemini;
-set transaction isolation level read uncommitted;
-insert into t1 (f1) values ("test11"), ("bar");
-connection master1;
-set transaction isolation level read committed;
-select * from t1;
-connection master;
-commit;
-
-drop table if exists t1;
-create table t1 (f1 char(20) not null) type = gemini;
-set transaction isolation level read uncommitted;
-insert into t1 (f1) values ("test12"), ("bar");
-connection master1;
-set transaction isolation level repeatable read;
-select * from t1;
-connection master;
-commit;
-
-drop table if exists t1;
-create table t1 (f1 char(20) not null) type = gemini;
-set transaction isolation level read committed;
-insert into t1 (f1) values ("test13"), ("bar");
-connection master1;
-set transaction isolation level serializable;
-select * from t1;
-connection master;
-commit;
-
-drop table if exists t1;
-create table t1 (f1 char(20) not null) type = gemini;
-set transaction isolation level read committed;
-insert into t1 (f1) values ("test14"), ("bar");
-connection master1;
-set transaction isolation level read uncommitted;
-select * from t1;
-connection master;
-commit;
-
-drop table if exists t1;
-create table t1 (f1 char(20) not null) type = gemini;
-set transaction isolation level read committed;
-insert into t1 (f1) values ("test15"), ("bar");
-connection master1;
-set transaction isolation level read committed;
-select * from t1;
-connection master;
-commit;
-
-drop table if exists t1;
-create table t1 (f1 char(20) not null) type = gemini;
-set transaction isolation level read committed;
-insert into t1 (f1) values ("test16"), ("bar");
-connection master1;
-set transaction isolation level repeatable read;
-select * from t1;
-connection master;
-commit;
-
-drop table if exists t1;
-create table t1 (f1 char(20) not null) type = gemini;
-set transaction isolation level repeatable read;
-insert into t1 (f1) values ("test17"), ("bar");
-connection master1;
-set transaction isolation level serializable;
-select * from t1;
-connection master;
-commit;
-
-drop table if exists t1;
-create table t1 (f1 char(20) not null) type = gemini;
-set transaction isolation level repeatable read;
-insert into t1 (f1) values ("test18"), ("bar");
-connection master1;
-set transaction isolation level read uncommitted;
-select * from t1;
-connection master;
-commit;
-
-drop table if exists t1;
-create table t1 (f1 char(20) not null) type = gemini;
-set transaction isolation level repeatable read;
-insert into t1 (f1) values ("test19"), ("bar");
-connection master1;
-set transaction isolation level read committed;
-select * from t1;
-connection master;
-commit;
-
-drop table if exists t1;
-create table t1 (f1 char(20) not null) type = gemini;
-set transaction isolation level repeatable read;
-insert into t1 (f1) values ("test20"), ("bar");
-connection master1;
-set transaction isolation level repeatable read;
-select * from t1;
-connection master;
-commit;
-drop table t1;
diff --git a/mysql-test/t/join.test b/mysql-test/t/join.test
index 9db520a5edf..3bd78350267 100644
--- a/mysql-test/t/join.test
+++ b/mysql-test/t/join.test
@@ -1,7 +1,6 @@
#
# This failed for lia Perminov
#
-
drop table if exists t1,t2,t3;
create table t1 (id int primary key);
@@ -87,6 +86,7 @@ drop table t1, t2;
create table t1 (a int primary key);
insert into t1 values(1),(2);
select t1.a from t1 as t1 left join t1 as t2 using (a) left join t1 as t3 using (a) left join t1 as t4 using (a) left join t1 as t5 using (a) left join t1 as t6 using (a) left join t1 as t7 using (a) left join t1 as t8 using (a) left join t1 as t9 using (a) left join t1 as t10 using (a) left join t1 as t11 using (a) left join t1 as t12 using (a) left join t1 as t13 using (a) left join t1 as t14 using (a) left join t1 as t15 using (a) left join t1 as t16 using (a) left join t1 as t17 using (a) left join t1 as t18 using (a) left join t1 as t19 using (a) left join t1 as t20 using (a) left join t1 as t21 using (a) left join t1 as t22 using (a) left join t1 as t23 using (a) left join t1 as t24 using (a) left join t1 as t25 using (a) left join t1 as t26 using (a) left join t1 as t27 using (a) left join t1 as t28 using (a) left join t1 as t29 using (a) left join t1 as t30 using (a) left join t1 as t31 using (a);
+--replace_result "31 tables" "XX tables" "63 tables" "XX tables"
--error 1116
select t1.a from t1 as t1 left join t1 as t2 using (a) left join t1 as t3 using (a) left join t1 as t4 using (a) left join t1 as t5 using (a) left join t1 as t6 using (a) left join t1 as t7 using (a) left join t1 as t8 using (a) left join t1 as t9 using (a) left join t1 as t10 using (a) left join t1 as t11 using (a) left join t1 as t12 using (a) left join t1 as t13 using (a) left join t1 as t14 using (a) left join t1 as t15 using (a) left join t1 as t16 using (a) left join t1 as t17 using (a) left join t1 as t18 using (a) left join t1 as t19 using (a) left join t1 as t20 using (a) left join t1 as t21 using (a) left join t1 as t22 using (a) left join t1 as t23 using (a) left join t1 as t24 using (a) left join t1 as t25 using (a) left join t1 as t26 using (a) left join t1 as t27 using (a) left join t1 as t28 using (a) left join t1 as t29 using (a) left join t1 as t30 using (a) left join t1 as t31 using (a) left join t1 as t32 using (a) left join t1 as t33 using (a) left join t1 as t34 using (a) left join t1 as t35 using (a) left join t1 as t36 using (a) left join t1 as t37 using (a) left join t1 as t38 using (a) left join t1 as t39 using (a) left join t1 as t40 using (a) left join t1 as t41 using (a) left join t1 as t42 using (a) left join t1 as t43 using (a) left join t1 as t44 using (a) left join t1 as t45 using (a) left join t1 as t46 using (a) left join t1 as t47 using (a) left join t1 as t48 using (a) left join t1 as t49 using (a) left join t1 as t50 using (a) left join t1 as t51 using (a) left join t1 as t52 using (a) left join t1 as t53 using (a) left join t1 as t54 using (a) left join t1 as t55 using (a) left join t1 as t56 using (a) left join t1 as t57 using (a) left join t1 as t58 using (a) left join t1 as t59 using (a) left join t1 as t60 using (a) left join t1 as t61 using (a) left join t1 as t62 using (a) left join t1 as t63 using (a) left join t1 as t64 using (a) left join t1 as t65 using (a);
drop table t1;
diff --git a/mysql-test/t/key.test b/mysql-test/t/key.test
index a8417fad876..6fc975a1cb3 100644
--- a/mysql-test/t/key.test
+++ b/mysql-test/t/key.test
@@ -160,3 +160,11 @@ SELECT * FROM t1 WHERE a='a' AND b=2;
SELECT * FROM t1 WHERE a='a' AND b in (2);
SELECT * FROM t1 WHERE a='a' AND b in (1,2);
drop table t1;
+
+#
+# Test of create key order
+#
+
+create table t1 (a int not null unique, b int unique, c int, d int not null primary key, key(c), e int not null unique);
+show keys from t1;
+drop table t1;
diff --git a/mysql-test/t/keywords.test b/mysql-test/t/keywords.test
index b9a1f34c715..3bd757aa069 100644
--- a/mysql-test/t/keywords.test
+++ b/mysql-test/t/keywords.test
@@ -8,3 +8,7 @@ insert into t1 values ("12:22:22","97:02:03","1997-01-02");
select * from t1;
select t1.time+0,t1.date+0,t1.timestamp+0,concat(date," ",time) from t1;
drop table t1;
+create table events(binlog int);
+insert into events values(1);
+select events.binlog from events;
+drop table events;
diff --git a/mysql-test/t/kill.test b/mysql-test/t/kill.test
index be6860a3cc3..6bcc43ac916 100644
--- a/mysql-test/t/kill.test
+++ b/mysql-test/t/kill.test
@@ -1,3 +1,11 @@
+# This test doesn't work with the embedded version as this code
+# assumes that one query is running while we are doing queries on
+# a second connection.
+# This would work if mysqltest run would be threaded and handle each
+# connection in a separate thread.
+#
+-- source include/not_embedded.inc
+
connect (con1, localhost, root,,);
connect (con2, localhost, root,,);
diff --git a/mysql-test/t/limit.test b/mysql-test/t/limit.test
index 112761abd87..d4f6ce186cf 100644
--- a/mysql-test/t/limit.test
+++ b/mysql-test/t/limit.test
@@ -28,3 +28,5 @@ delete from t1 limit 0;
update t1 set i=3 limit 0;
select * from t1;
drop table t1;
+
+select 0 limit 0;
diff --git a/mysql-test/t/lock.test b/mysql-test/t/lock.test
index 77354e63252..385713174d2 100644
--- a/mysql-test/t/lock.test
+++ b/mysql-test/t/lock.test
@@ -53,45 +53,3 @@ lock tables t1 write;
check table t2;
unlock tables;
drop table t1,t2;
-
-#test to see if select will get the lock ahead of low priority update
-connect (locker,localhost,root,,);
-connect (reader,localhost,root,,);
-connect (writer,localhost,root,,);
-
-connection locker;
-create table t1(n int);
-insert into t1 values (1);
-lock tables t1 write;
-connection writer;
-send update low_priority t1 set n = 4;
-connection reader;
---sleep 2
-send select n from t1;
-connection locker;
---sleep 2
-unlock tables;
-connection writer;
-reap;
-connection reader;
-reap;
-drop table t1;
-
-connection locker;
-create table t1(n int);
-insert into t1 values (1);
-lock tables t1 read;
-connection writer;
-send update low_priority t1 set n = 4;
-connection reader;
---sleep 2
-send select n from t1;
-connection locker;
---sleep 2
-unlock tables;
-connection writer;
-reap;
-connection reader;
-reap;
-drop table t1;
-
diff --git a/mysql-test/t/lock_multi.test b/mysql-test/t/lock_multi.test
new file mode 100644
index 00000000000..53e9fd3393c
--- /dev/null
+++ b/mysql-test/t/lock_multi.test
@@ -0,0 +1,49 @@
+# This test doesn't work with the embedded version as this code
+# assumes that one query is running while we are doing queries on
+# a second connection.
+# This would work if mysqltest run would be threaded and handle each
+# connection in a separate thread.
+#
+-- source include/not_embedded.inc
+
+#test to see if select will get the lock ahead of low priority update
+
+connect (locker,localhost,root,,);
+connect (reader,localhost,root,,);
+connect (writer,localhost,root,,);
+
+connection locker;
+create table t1(n int);
+insert into t1 values (1);
+lock tables t1 write;
+connection writer;
+send update low_priority t1 set n = 4;
+connection reader;
+--sleep 2
+send select n from t1;
+connection locker;
+--sleep 2
+unlock tables;
+connection writer;
+reap;
+connection reader;
+reap;
+drop table t1;
+
+connection locker;
+create table t1(n int);
+insert into t1 values (1);
+lock tables t1 read;
+connection writer;
+send update low_priority t1 set n = 4;
+connection reader;
+--sleep 2
+send select n from t1;
+connection locker;
+--sleep 2
+unlock tables;
+connection writer;
+reap;
+connection reader;
+reap;
+drop table t1;
diff --git a/mysql-test/t/merge.test b/mysql-test/t/merge.test
index 238dd599664..5bd78769a05 100644
--- a/mysql-test/t/merge.test
+++ b/mysql-test/t/merge.test
@@ -2,7 +2,7 @@
# test of MERGE TABLES
#
-drop table if exists t1,t2,t3;
+drop table if exists t1,t2,t3,t4,t5,t6;
create table t1 (a int not null primary key auto_increment, message char(20));
create table t2 (a int not null primary key auto_increment, message char(20));
INSERT INTO t1 (message) VALUES ("Testing"),("table"),("t1");
@@ -22,7 +22,7 @@ insert into t2 select NULL,message from t1;
insert into t1 select NULL,message from t2;
insert into t2 select NULL,message from t1;
insert into t1 select NULL,message from t2;
-create table t3 (a int not null, b char(20), key(a)) type=MERGE UNION=(t1,t2);
+create table t3 (a int not null, b char(20), key(a)) type=MERGE UNION=(test.t1,test.t2);
explain select * from t3 where a < 10;
explain select * from t3 where a > 10 and a < 20;
select * from t3 where a = 10;
@@ -31,6 +31,14 @@ select * from t3 where a > 10 and a < 20;
explain select a from t3 order by a desc limit 10;
select a from t3 order by a desc limit 10;
select a from t3 order by a desc limit 300,10;
+delete from t3 where a=3;
+select * from t3 where a < 10;
+delete from t3 where a >= 6 and a <= 8;
+select * from t3 where a < 10;
+update t3 set a=3 where a=9;
+select * from t3 where a < 10;
+update t3 set a=6 where a=7;
+select * from t3 where a < 10;
show create table t3;
# The following should give errors
@@ -114,3 +122,49 @@ insert into t2 values (1,1),(2,2),(0,0),(4,4),(5,5),(6,6);
flush tables;
select * from t3 where a=1 order by b limit 2;
drop table t3,t1,t2;
+
+#
+# [phi] testing INSERT_METHOD stuff
+#
+
+drop table if exists t6, t5, t4, t3, t2, t1;
+# first testing of common stuff with new parameters
+create table t1 (a int not null, b int not null, key(a,b));
+create table t2 (a int not null, b int not null, key(a,b));
+create table t3 (a int not null, b int not null, key(a,b)) UNION=(t1,t2) INSERT_METHOD=NO;
+create table t4 (a int not null, b int not null, key(a,b)) TYPE=MERGE UNION=(t1,t2) INSERT_METHOD=NO;
+create table t5 (a int not null, b int not null, key(a,b)) TYPE=MERGE UNION=(t1,t2) INSERT_METHOD=FIRST;
+create table t6 (a int not null, b int not null, key(a,b)) TYPE=MERGE UNION=(t1,t2) INSERT_METHOD=LAST;
+show create table t3;
+show create table t4;
+show create table t5;
+show create table t6;
+insert into t1 values (1,1),(1,2),(1,3),(1,4);
+insert into t2 values (2,1),(2,2),(2,3),(2,4);
+select * from t3 order by b,a limit 3;
+select * from t4 order by b,a limit 3;
+select * from t5 order by b,a limit 3,3;
+select * from t6 order by b,a limit 6,3;
+# now testing inserts and where the data gets written
+insert into t5 values (5,1),(5,2);
+insert into t6 values (6,1),(6,2);
+select * from t1 order by a,b;
+select * from t2 order by a,b;
+select * from t4 order by a,b;
+# preperation for next test
+insert into t3 values (3,1),(3,2),(3,3),(3,4);
+select * from t3 order by a,b;
+# now testing whether options are kept by alter table
+alter table t4 UNION=(t1,t2,t3);
+show create table t4;
+select * from t4 order by a,b;
+# testing switching off insert method and inserts again
+alter table t4 INSERT_METHOD=FIRST;
+show create table t4;
+insert into t4 values (4,1),(4,2);
+select * from t1 order by a,b;
+select * from t2 order by a,b;
+select * from t3 order by a,b;
+select * from t4 order by a,b;
+select * from t5 order by a,b;
+drop table if exists t6, t5, t4, t3, t2, t1;
diff --git a/mysql-test/t/multi_update.test b/mysql-test/t/multi_update.test
new file mode 100644
index 00000000000..11697f794a9
--- /dev/null
+++ b/mysql-test/t/multi_update.test
@@ -0,0 +1,53 @@
+#
+# Only run the test if we are using --big-test, because this test takes a
+# long time
+#
+#-- require r/big_test.require
+#eval select $BIG_TEST as using_big_test;
+
+drop table if exists t1,t2,t3;
+create table t1(id1 int not null auto_increment primary key, t char(12));
+create table t2(id2 int not null, t char(12));
+create table t3(id3 int not null, t char(12), index(id3));
+disable_query_log;
+let $1 = 100;
+while ($1)
+ {
+ let $2 = 5;
+ eval insert into t1(t) values ('$1');
+ while ($2)
+ {
+ eval insert into t2(id2,t) values ($1,'$2');
+ let $3 = 10;
+ while ($3)
+ {
+ eval insert into t3(id3,t) values ($1,'$2');
+ dec $3;
+ }
+ dec $2;
+ }
+ dec $1;
+ }
+enable_query_log;
+update t1,t2,t3 set t1.t="aaa", t2.t="bbb", t3.t="cc" where t1.id1 = t2.id2 and t2.id2 = t3.id3 and t1.id1 > 90;
+delete t1.*, t2.*, t3.* from t1,t2,t3 where t1.id1 = t2.id2 and t2.id2 = t3.id3 and t1.id1 > 95;
+
+check table t1, t2, t3;
+
+select count(*) from t1 where id1 > 95;
+select count(*) from t2 where id2 > 95;
+select count(*) from t3 where id3 > 95;
+
+delete t1, t2, t3 from t1,t2,t3 where t1.id1 = t2.id2 and t2.id2 = t3.id3 and t1.id1 > 5;
+select count(*) from t1 where id1 > 5;
+select count(*) from t2 where id2 > 5;
+select count(*) from t3 where id3 > 5;
+
+delete from t1, t2, t3 using t1,t2,t3 where t1.id1 = t2.id2 and t2.id2 = t3.id3 and t1.id1 > 0;
+
+# These queries will force a scan of the table
+select count(*) from t1 where id1;
+select count(*) from t2 where id2;
+select count(*) from t3 where id3;
+
+drop table t1,t2,t3;
diff --git a/mysql-test/t/myisam.test b/mysql-test/t/myisam.test
index eb1d9a01020..861bc807323 100644
--- a/mysql-test/t/myisam.test
+++ b/mysql-test/t/myisam.test
@@ -24,11 +24,13 @@ drop table t1;
create table t1 (a tinyint not null auto_increment, b blob not null, primary key (a));
let $1=100;
+disable_query_log;
while ($1)
{
eval insert into t1 (b) values(repeat(char(65+$1),65550-$1));
dec $1;
}
+enable_query_log;
check table t1;
repair table t1;
delete from t1 where (a & 1);
diff --git a/mysql-test/t/null.test b/mysql-test/t/null.test
index a010ab38e07..8bd9e806118 100644
--- a/mysql-test/t/null.test
+++ b/mysql-test/t/null.test
@@ -25,7 +25,6 @@ drop table t1;
# Test problem med index on NULL columns and testing with =NULL;
#
-DROP TABLE IF EXISTS t1;
CREATE TABLE t1 (
indexed_field int default NULL,
KEY indexed_field (indexed_field)
diff --git a/mysql-test/t/openssl_1.test b/mysql-test/t/openssl_1.test
new file mode 100644
index 00000000000..8dfd0d8c2f9
--- /dev/null
+++ b/mysql-test/t/openssl_1.test
@@ -0,0 +1,6 @@
+# We test openssl. Result set is optimized to be compiled with --with-openssl but
+# SSL is swithced off in some reason
+-- source include/have_openssl_2.inc
+
+SHOW STATUS LIKE 'SSL%';
+
diff --git a/mysql-test/t/openssl_2.test b/mysql-test/t/openssl_2.test
new file mode 100644
index 00000000000..12f1240f3af
--- /dev/null
+++ b/mysql-test/t/openssl_2.test
@@ -0,0 +1,5 @@
+# We want to test everything with SSL turned on.
+-- source include/have_openssl_2.inc
+
+SHOW STATUS LIKE 'SSL%';
+
diff --git a/mysql-test/t/order_by.test b/mysql-test/t/order_by.test
index 16094206745..baa3fe67f0b 100644
--- a/mysql-test/t/order_by.test
+++ b/mysql-test/t/order_by.test
@@ -206,8 +206,53 @@ ORDER by lastchange_datum DESC LIMIT 2;
drop table t1;
#
-# Test optimizing bug with EQ_REF tables, where some ORDER BY parts where
-# wrongly removed.
+# Test optimization of ORDER BY DESC
+#
+
+create table t1 (a int not null, b int, c varchar(10), key (a, b, c));
+insert into t1 values (1, NULL, NULL), (1, NULL, 'b'), (1, 1, NULL), (1, 1, 'b'), (1, 1, 'b'), (2, 1, 'a'), (2, 1, 'b'), (2, 2, 'a'), (2, 2, 'b'), (2, 3, 'c'),(1,3,'b');
+
+explain select * from t1 where (a = 1 and b is null and c = 'b') or (a > 2) order by a desc;
+select * from t1 where (a = 1 and b is null and c = 'b') or (a > 2) order by a desc;
+explain select * from t1 where a >= 1 and a < 3 order by a desc;
+select * from t1 where a >= 1 and a < 3 order by a desc;
+explain select * from t1 where a = 1 order by a desc, b desc;
+select * from t1 where a = 1 order by a desc, b desc;
+explain select * from t1 where a = 1 and b is null order by a desc, b desc;
+select * from t1 where a = 1 and b is null order by a desc, b desc;
+explain select * from t1 where a >= 1 and a < 3 and b >0 order by a desc,b desc;
+explain select * from t1 where a = 2 and b >0 order by a desc,b desc;
+explain select * from t1 where a = 2 and b is null order by a desc,b desc;
+explain select * from t1 where a = 2 and (b is null or b > 0) order by a
+desc,b desc;
+explain select * from t1 where a = 2 and b > 0 order by a desc,b desc;
+explain select * from t1 where a = 2 and b < 2 order by a desc,b desc;
+
+#
+# Test things when we don't have NULL keys
+#
+
+alter table t1 modify b int not null, modify c varchar(10) not null;
+explain select * from t1 order by a, b, c;
+select * from t1 order by a, b, c;
+explain select * from t1 order by a desc, b desc, c desc;
+select * from t1 order by a desc, b desc, c desc;
+# test multiple ranges, NO_MAX_RANGE and EQ_RANGE
+explain select * from t1 where (a = 1 and b = 1 and c = 'b') or (a > 2) order by a desc;
+select * from t1 where (a = 1 and b = 1 and c = 'b') or (a > 2) order by a desc;
+# test NEAR_MAX, NO_MIN_RANGE
+explain select * from t1 where a < 2 and b <= 1 order by a desc, b desc;
+select * from t1 where a < 2 and b <= 1 order by a desc, b desc;
+select count(*) from t1 where a < 5 and b > 0;
+select * from t1 where a < 5 and b > 0 order by a desc,b desc;
+# test HA_READ_AFTER_KEY (at the end of the file), NEAR_MIN
+explain select * from t1 where a between 1 and 3 and b <= 1 order by a desc, b desc;
+select * from t1 where a between 1 and 3 and b <= 1 order by a desc, b desc;
+# test HA_READ_AFTER_KEY (in the middle of the file)
+explain select * from t1 where a between 0 and 1 order by a desc, b desc;
+select * from t1 where a between 0 and 1 order by a desc, b desc;
+drop table t1;
+
CREATE TABLE t1 (
gid int(10) unsigned NOT NULL auto_increment,
diff --git a/mysql-test/t/order_fill_sortbuf-master.opt b/mysql-test/t/order_fill_sortbuf-master.opt
new file mode 100644
index 00000000000..116494d4588
--- /dev/null
+++ b/mysql-test/t/order_fill_sortbuf-master.opt
@@ -0,0 +1 @@
+--set-variable=sort_buffer=0
diff --git a/mysql-test/t/order_fill_sortbuf.test b/mysql-test/t/order_fill_sortbuf.test
new file mode 100644
index 00000000000..6419f2a93df
--- /dev/null
+++ b/mysql-test/t/order_fill_sortbuf.test
@@ -0,0 +1,21 @@
+#
+# This test does a create-select with ORDER BY, where there is so many
+# rows MySQL needs to use a merge during the sort phase.
+#
+
+drop table if exists t1,t2;
+CREATE TABLE `t1` (
+ `id` int(11) NOT NULL default '0',
+ `id2` int(11) NOT NULL default '0',
+ `id3` int(11) NOT NULL default '0');
+let $1=4000;
+disable_query_log;
+while ($1)
+ {
+ eval insert into t1 (id,id2,id3) values ($1,$1,$1);
+ dec $1;
+ }
+enable_query_log;
+create table t2 select id2 from t1 order by id3;
+select count(*) from t2;
+drop table t1,t2;
diff --git a/mysql-test/t/query_cache-master.opt b/mysql-test/t/query_cache-master.opt
new file mode 100644
index 00000000000..cfdce628e74
--- /dev/null
+++ b/mysql-test/t/query_cache-master.opt
@@ -0,0 +1 @@
+--set-variable=query_cache_size=1355776
diff --git a/mysql-test/t/query_cache.test b/mysql-test/t/query_cache.test
new file mode 100644
index 00000000000..b4d00639587
--- /dev/null
+++ b/mysql-test/t/query_cache.test
@@ -0,0 +1,336 @@
+#
+# Tests with query cache
+#
+
+# Reset query cache variables.
+
+flush query cache; # This crashed in some versions
+flush query cache; # This crashed in some versions
+reset query cache;
+flush status;
+drop table if exists t1,t2,t3,t11,t21, mysqltest.t1;
+
+#
+# First simple test
+#
+
+create table t1 (a int not null);
+insert into t1 values (1),(2),(3);
+select * from t1;
+select * from t1;
+select sql_no_cache * from t1;
+select length(now()) from t1;
+
+# Only check the variables that are independent of the machine and startup
+# options
+
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+
+drop table t1;
+
+show status like "Qcache_queries_in_cache";
+
+#
+# MERGE TABLES with INSERT/UPDATE and DELETE
+#
+create table t1 (a int not null);
+insert into t1 values (1),(2),(3);
+create table t2 (a int not null);
+insert into t2 values (4),(5),(6);
+create table t3 (a int not null) type=MERGE UNION=(t1,t2) INSERT_METHOD=FIRST;
+# insert
+select * from t3;
+select * from t3;
+show status like "Qcache_hits";
+show status like "Qcache_queries_in_cache";
+insert into t2 values (7);
+show status like "Qcache_queries_in_cache";
+select * from t1;
+select * from t1;
+show status like "Qcache_hits";
+show status like "Qcache_queries_in_cache";
+insert into t3 values (8);
+show status like "Qcache_queries_in_cache";
+# update
+select * from t3;
+show status like "Qcache_queries_in_cache";
+update t2 set a=9 where a=7;
+show status like "Qcache_queries_in_cache";
+select * from t1;
+show status like "Qcache_queries_in_cache";
+update t3 set a=10 where a=1;
+show status like "Qcache_queries_in_cache";
+#delete
+select * from t3;
+show status like "Qcache_queries_in_cache";
+delete from t2 where a=9;
+show status like "Qcache_queries_in_cache";
+select * from t1;
+show status like "Qcache_queries_in_cache";
+delete from t3 where a=10;
+show status like "Qcache_queries_in_cache";
+drop table t1, t2, t3;
+#
+# FLUSH QUERY CACHE
+#
+create table t1 (a int not null);
+insert into t1 values (1),(2),(3);
+create table t2 (a int not null);
+insert into t2 values (1),(2),(3);
+select * from t1;
+select * from t2;
+insert into t1 values (4);
+show status like "Qcache_free_blocks";
+flush query cache;
+show status like "Qcache_free_blocks";
+drop table t1, t2;
+# With join results...
+create table t1 (a text not null);
+create table t11 (a text not null);
+create table t2 (a text not null);
+create table t21 (a text not null);
+create table t3 (a text not null);
+insert into t1 values("1111111111111111111111111111111111111111111111111111");
+insert into t2 select * from t1;
+insert into t1 select * from t2;
+insert into t2 select * from t1;
+insert into t1 select * from t2;
+insert into t2 select * from t1;
+insert into t1 select * from t2;
+insert into t2 select * from t1;
+insert into t1 select * from t2;
+insert into t2 select * from t1;
+insert into t1 select * from t2;
+insert into t2 select * from t1;
+insert into t1 select * from t2;
+insert into t2 select * from t1;
+insert into t1 select * from t2;
+insert into t2 select * from t1;
+# t11 and t21 must be over 4Kb (QUERY_CACHE_MIN_RESULT_DATA_SIZE)
+insert into t11 select * from t1;
+insert into t21 select * from t1;
+insert into t1 select * from t2;
+insert into t2 select * from t1;
+insert into t1 select * from t2;
+#results of t3 must be > 0.5Mb
+insert into t3 select * from t1;
+insert into t3 select * from t2;
+insert into t3 select * from t1;
+disable_result_log;
+select * from t11;
+select * from t21;
+enable_result_log;
+show status like "Qcache_total_blocks";
+show status like "Qcache_free_blocks";
+disable_result_log;
+insert into t11 values("");
+select * from t3;
+enable_result_log;
+show status like "Qcache_total_blocks";
+show status like "Qcache_free_blocks";
+flush query cache;
+show status like "Qcache_total_blocks";
+show status like "Qcache_free_blocks";
+drop table t1, t2, t3, t11, t21;
+#
+# SELECT SQL_CACHE ...
+#
+set sql_query_cache_type=demand;
+create table t1 (a int not null);
+insert into t1 values (1),(2),(3);
+select * from t1;
+show status like "Qcache_queries_in_cache";
+select sql_cache * from t1;
+set sql_query_cache_type=2;
+select sql_cache * from t1;
+show status like "Qcache_hits";
+show status like "Qcache_queries_in_cache";
+set sql_query_cache_type=on;
+#
+# RESET QUERY CACHE
+#
+reset query cache;
+show status like "Qcache_queries_in_cache";
+#
+# SELECT SQL_NO_CACHE
+#
+select sql_no_cache * from t1;
+show status like "Qcache_queries_in_cache";
+drop table t1;
+#
+# Check that queries that uses NOW(), LAST_INSERT_ID()... are not cached.
+#
+create table t1 (a text not null);
+select CONNECTION_ID() from t1;
+#GET_LOCK
+#RELEASE_LOCK
+#LOAD_FILE
+select FOUND_ROWS();
+select NOW() from t1;
+select CURDATE() from t1;
+select CURTIME() from t1;
+select DATABASE() from t1;
+select ENCRYPT("test") from t1;
+select LAST_INSERT_ID() from t1;
+select RAND() from t1;
+select UNIX_TIMESTAMP() from t1;
+select USER() from t1;
+select benchmark(1,1) from t1;
+show status like "Qcache_queries_in_cache";
+#
+# Tests when the cache is filled
+#
+create table t2 (a text not null);
+insert into t1 values("1111111111111111111111111111111111111111111111111111");
+insert into t2 select * from t1;
+insert into t1 select * from t2; # 2
+insert into t2 select * from t1; # 3
+insert into t1 select * from t2; # 5
+insert into t2 select * from t1; # 8
+insert into t1 select * from t2; # 13
+insert into t2 select * from t1; # 21
+insert into t1 select * from t2; # 34
+insert into t2 select * from t1; # 55
+insert into t1 select * from t2; # 89
+insert into t2 select * from t1; # 144
+insert into t1 select * from t2; # 233
+insert into t2 select * from t1; # 357
+insert into t1 select * from t2; # 610
+insert into t2 select * from t1; # 987
+insert into t1 select * from t2; # 1597
+insert into t2 select * from t1; # 2584
+insert into t1 select * from t2; # 4181
+
+show status like "Qcache_hits";
+disable_result_log;
+select a as a1, a as a2 from t1;
+select a as a2, a as a3 from t1;
+select a as a3, a as a4 from t1;
+# next query must be out of 1Mb cache
+select a as a1, a as a2 from t1;
+enable_result_log;
+show status like "Qcache_hits";
+show status like "Qcache_queries_in_cache";
+reset query cache;
+#
+# Query bigger then query_cache_limit
+#
+insert into t2 select * from t1;
+insert into t1 select * from t2;
+insert into t2 select * from t1;
+insert into t1 select * from t2;
+insert into t2 select * from t1;
+insert into t1 select * from t2;
+insert into t2 select * from t1;
+insert into t1 select * from t2;
+insert into t2 select * from t1;
+insert into t1 select * from t2;
+disable_result_log;
+select * from t1;
+enable_result_log;
+show status like "Qcache_queries_in_cache";
+drop table t1,t2;
+
+#
+# noncachable ODBC work around (and prepare cache for drop database)
+#
+create database if not exists mysqltest;
+create table mysqltest.t1 (i int not null auto_increment, a int, primary key (i));
+insert into mysqltest.t1 (a) values (1);
+select * from mysqltest.t1 where i is null;
+
+#
+# drop db
+#
+select * from mysqltest.t1;
+show status like "Qcache_queries_in_cache";
+drop database mysqltest;
+show status like "Qcache_queries_in_cache";
+
+#
+# Charset convertion (cp1251_koi8 always present)
+#
+create table t1 (a char(1) not null);
+insert into t1 values("á");
+select * from t1;
+set CHARACTER SET cp1251_koi8;
+select * from t1;
+set CHARACTER SET DEFAULT;
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_hits";
+drop table t1;
+
+# The following tests can't be done as the values differen on 32 and 64 bit
+# machines :(
+#show variables like "query_cache_size";
+#show status like "Qcache_free_memory";
+
+#
+# same tables in different db
+#
+create database if not exists mysqltest;
+create table mysqltest.t1 (i int not null);
+create table t1 (i int not null);
+insert into mysqltest.t1 (i) values (1);
+insert into t1 (i) values (2);
+
+select * from t1;
+use mysqltest;
+select * from t1;
+select * from t1;
+use test;
+select * from t1;
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_hits";
+
+drop database mysqltest;
+drop table t1;
+
+#
+# FOUND_ROWS()
+#
+
+create table t1 (i int not null);
+insert into t1 (i) values (1),(2),(3),(4);
+
+select SQL_CALC_FOUND_ROWS * from t1 limit 2;
+select FOUND_ROWS();
+show status like "Qcache_hits";
+show status like "Qcache_queries_in_cache";
+
+select * from t1 where i=1;
+select FOUND_ROWS();
+show status like "Qcache_hits";
+show status like "Qcache_queries_in_cache";
+
+select SQL_CALC_FOUND_ROWS * from t1 limit 2;
+select FOUND_ROWS();
+show status like "Qcache_hits";
+show status like "Qcache_queries_in_cache";
+
+select * from t1 where i=1;
+select FOUND_ROWS();
+show status like "Qcache_hits";
+show status like "Qcache_queries_in_cache";
+drop table t1;
+
+#
+# Test insert delayed
+#
+
+flush query cache;
+reset query cache;
+
+create table t1 (a int not null);
+insert into t1 values (1),(2),(3);
+select * from t1;
+select * from t1;
+show status like "Qcache_queries_in_cache";
+insert delayed into t1 values (4);
+--sleep 5 # Wait for insert delayed to be executed.
+select a from t1;
+show status like "Qcache_queries_in_cache";
+drop table t1;
+show status like "Qcache_queries_in_cache";
diff --git a/mysql-test/t/rename.test b/mysql-test/t/rename.test
index 2a9cf113a47..ce4651d8de3 100644
--- a/mysql-test/t/rename.test
+++ b/mysql-test/t/rename.test
@@ -12,13 +12,19 @@ select * from t1;
rename table t3 to t4, t2 to t3, t1 to t2, t4 to t1;
rename table t3 to t4, t2 to t3, t1 to t2, t4 to t1;
select * from t1;
+
# The following should give errors
-!$1050 rename table t1 to t2;
-!$1050 rename table t1 to t1;
-!$1050 rename table t3 to t4, t2 to t3, t1 to t2, t4 to t2;
+--error 1050,1050
+rename table t1 to t2;
+--error 1050,1050
+rename table t1 to t1;
+--error 1050,1050
+rename table t3 to t4, t2 to t3, t1 to t2, t4 to t2;
show tables like "t_";
-!$1050 rename table t3 to t1, t2 to t3, t1 to t2, t4 to t1;
-!$1017 rename table t3 to t4, t5 to t3, t1 to t2, t4 to t1;
+--error 1050,1050
+rename table t3 to t1, t2 to t3, t1 to t2, t4 to t1;
+--error 1017,1017
+rename table t3 to t4, t5 to t3, t1 to t2, t4 to t1;
select * from t1;
select * from t2;
diff --git a/mysql-test/t/rpl000001.test b/mysql-test/t/rpl000001.test
index 113a9637dac..a5496d505f0 100644
--- a/mysql-test/t/rpl000001.test
+++ b/mysql-test/t/rpl000001.test
@@ -1,11 +1,15 @@
+eval_result;
source include/master-slave.inc;
connection master;
use test;
drop table if exists t1,t3;
create table t1 (word char(20) not null);
load data infile '../../std_data/words.dat' into table t1;
-set password = password('foo');
-set password = password('');
+--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR
+eval load data local infile '$MYSQL_TEST_DIR/std_data/words.dat' into table t1;
+select * from t1;
+set password for root@"localhost" = password('foo');
+set password for root@"localhost" = password('');
create table t3(n int);
insert into t3 values(1),(2);
save_master_pos;
@@ -24,21 +28,38 @@ sync_with_master;
connection master;
reset master;
connection slave;
+slave stop;
reset slave;
connection master;
drop table if exists t1,t2;
create table t1(n int);
-let $1=10;
+#we want the log to exceed 16K to test deal with the log that is bigger than
+#IO_SIZE
+let $1=5000;
+disable_query_log;
while ($1)
{
- eval insert into t1 values($1);
+ eval insert into t1 values($1+get_lock("hold_slave",10)*0);
dec $1;
}
+enable_query_log;
+
+#try to cause a large relay log lag on the slave
+connection slave;
+select get_lock("hold_slave",10);
+slave start;
+#hope this is long enough for I/O thread to fetch over 16K relay log data
+sleep 1;
+select release_lock("hold_slave");
+unlock tables;
+
+connection master;
create table t2(id int);
insert into t2 values(connection_id());
save_master_pos;
+
connection master1;
#avoid generating result
create temporary table t1_temp(n int);
@@ -57,7 +78,7 @@ reap;
connection slave;
sync_with_master ;
#give the slave a chance to exit
-sleep 0.5;
+wait_for_slave_to_stop;
# The following test can't be done because the result of Pos will differ
# on different computers
diff --git a/mysql-test/t/rpl000002.test b/mysql-test/t/rpl000002.test
index 0c490e6316d..420ae27a337 100644
--- a/mysql-test/t/rpl000002.test
+++ b/mysql-test/t/rpl000002.test
@@ -1,4 +1,5 @@
source include/master-slave.inc;
+eval_result;
connection master;
use test;
drop table if exists t1;
@@ -11,6 +12,7 @@ use test;
sync_with_master;
select * from t1;
connection master;
+show slave hosts;
drop table t1;
save_master_pos;
connection slave;
diff --git a/mysql-test/t/rpl000009.test b/mysql-test/t/rpl000009.test
index 768c6c151b4..208e6f0b037 100644
--- a/mysql-test/t/rpl000009.test
+++ b/mysql-test/t/rpl000009.test
@@ -31,3 +31,56 @@ connection slave;
sync_with_master;
drop database if exists bar;
drop database if exists foo;
+
+#now let's test load data from master
+
+#first create some databases and tables on the master
+connection master;
+set sql_log_bin = 0;
+create database foo;
+create database bar;
+show databases;
+create table foo.t1(n int, s char(20));
+create table foo.t2(n int, s text);
+insert into foo.t1 values (1, 'one'), (2, 'two'), (3, 'three');
+insert into foo.t2 values (11, 'eleven'), (12, 'twelve'), (13, 'thirteen');
+
+create table bar.t1(n int, s char(20));
+create table bar.t2(n int, s text);
+insert into bar.t1 values (1, 'one bar'), (2, 'two bar'), (3, 'three bar');
+insert into bar.t2 values (11, 'eleven bar'), (12, 'twelve bar'),
+ (13, 'thirteen bar');
+set sql_log_bin = 1;
+save_master_pos;
+connection slave;
+sync_with_master;
+
+#this should show that the slave is empty at this point
+show databases;
+load data from master;
+
+#now let's check if we have the right tables and the right data in them
+show databases;
+use foo;
+show tables;
+use bar;
+show tables;
+select * from bar.t1;
+select * from bar.t2;
+
+#now let's see if replication works
+connection master;
+insert into bar.t1 values (4, 'four bar');
+save_master_pos;
+connection slave;
+sync_with_master;
+select * from bar.t1;
+
+#now time for cleanup
+connection master;
+drop database bar;
+drop database foo;
+save_master_pos;
+connection slave;
+sync_with_master;
+
diff --git a/mysql-test/t/rpl000014.test b/mysql-test/t/rpl000014.test
index b501d63b10e..a673a23dde2 100644
--- a/mysql-test/t/rpl000014.test
+++ b/mysql-test/t/rpl000014.test
@@ -4,18 +4,18 @@ show master status;
save_master_pos;
connection slave;
sync_with_master;
---replace_result 9306 9999 3334 9999 3335 9999
+--replace_result 3306 MASTER_PORT 9306 MASTER_PORT 3334 MASTER_PORT 3336 MASTER_PORT
show slave status;
change master to master_log_pos=73;
slave stop;
change master to master_log_pos=73;
---replace_result 9306 9999 3334 9999 3335 9999
+--replace_result 3306 MASTER_PORT 9306 MASTER_PORT 3334 MASTER_PORT 3336 MASTER_PORT
show slave status;
slave start;
---replace_result 9306 9999 3334 9999 3335 9999
+--replace_result 3306 MASTER_PORT 9306 MASTER_PORT 3334 MASTER_PORT 3336 MASTER_PORT
show slave status;
change master to master_log_pos=173;
---replace_result 9306 9999 3334 9999 3335 9999
+--replace_result 3306 MASTER_PORT 9306 MASTER_PORT 3334 MASTER_PORT 3336 MASTER_PORT
show slave status;
connection master;
show master status;
@@ -25,7 +25,7 @@ create table foo (n int);
insert into foo values (1),(2),(3);
save_master_pos;
connection slave;
-change master to master_log_pos=73;
+change master to master_log_pos=79;
sync_with_master;
select * from foo;
connection master;
diff --git a/mysql-test/t/rpl000015.test b/mysql-test/t/rpl000015.test
index 73a10bed7b3..8fd04613ab8 100644
--- a/mysql-test/t/rpl000015.test
+++ b/mysql-test/t/rpl000015.test
@@ -1,22 +1,25 @@
-connect (master,localhost,root,,test,0,mysql-master.sock);
-connect (slave,localhost,root,,test,0, mysql-slave.sock);
+connect (master,localhost,root,,test,0,master.sock);
+connect (slave,localhost,root,,test,0, slave.sock);
connection master;
reset master;
show master status;
save_master_pos;
connection slave;
reset slave;
+--replace_result $MASTER_MYPORT MASTER_PORT
show slave status;
change master to master_host='127.0.0.1';
---replace_result 3306 9998 9306 9999 3334 9999 3335 9999
+# The following needs to be cleaned up when change master is fixed
+--replace_result $MASTER_MYPORT MASTER_PORT 3306 MASTER_PORT 3334 MASTER_PORT
show slave status;
+--replace_result $MASTER_MYPORT MASTER_PORT
eval change master to master_host='127.0.0.1',master_user='root',
master_password='',master_port=$MASTER_MYPORT;
---replace_result 9306 9999 3334 9999 3335 9999
+--replace_result $MASTER_MYPORT MASTER_PORT
show slave status;
slave start;
sync_with_master;
---replace_result 9306 9999 3334 9999 3335 9999
+--replace_result $MASTER_MYPORT MASTER_PORT
show slave status;
connection master;
drop table if exists t1;
@@ -31,4 +34,3 @@ drop table t1;
save_master_pos;
connection slave;
sync_with_master;
-
diff --git a/mysql-test/t/rpl000016-slave.opt b/mysql-test/t/rpl000016-slave.opt
new file mode 100644
index 00000000000..f27601e0d7d
--- /dev/null
+++ b/mysql-test/t/rpl000016-slave.opt
@@ -0,0 +1 @@
+-O max_binlog_size=2048
diff --git a/mysql-test/t/rpl000016-slave.sh b/mysql-test/t/rpl000016-slave.sh
index 62748605af1..9259f593e54 100755
--- a/mysql-test/t/rpl000016-slave.sh
+++ b/mysql-test/t/rpl000016-slave.sh
@@ -1 +1,2 @@
rm -f $MYSQL_TEST_DIR/var/slave-data/master.info
+rm -f $MYSQL_TEST_DIR/var/slave-data/*relay*
diff --git a/mysql-test/t/rpl000016.test b/mysql-test/t/rpl000016.test
index c9b6ccabcd2..7559b2d3515 100644
--- a/mysql-test/t/rpl000016.test
+++ b/mysql-test/t/rpl000016.test
@@ -1,14 +1,16 @@
-connect (master,localhost,root,,test,0,mysql-master.sock);
-connect (slave,localhost,root,,test,0,mysql-slave.sock);
+connect (master,localhost,root,,test,0,master.sock);
+connect (slave,localhost,root,,test,0,slave.sock);
system cat /dev/null > var/slave-data/master.info;
system chmod 000 var/slave-data/master.info;
connection slave;
!slave start;
system chmod 600 var/slave-data/master.info;
!slave start;
+--replace_result 3306 MASTER_PORT 9306 MASTER_PORT 3334 MASTER_PORT 3336 MASTER_PORT
!eval change master to master_host='127.0.0.1',master_port=$MASTER_MYPORT,
master_user='root';
reset slave;
+--replace_result 3306 MASTER_PORT 9306 MASTER_PORT 3334 MASTER_PORT 3336 MASTER_PORT
eval change master to master_host='127.0.0.1',master_port=$MASTER_MYPORT,
master_user='root';
connection master;
@@ -22,7 +24,7 @@ insert into t1 values('Could not break slave'),('Tried hard');
save_master_pos;
connection slave;
sync_with_master;
---replace_result 9306 9999 3334 9999 3335 9999
+--replace_result 3306 MASTER_PORT 9306 MASTER_PORT 3334 MASTER_PORT 3336 MASTER_PORT
show slave status;
select * from t1;
connection master;
@@ -49,8 +51,7 @@ insert into t2 values(NULL);
connection slave;
sync_with_master;
-#the slave may have already stopped, so we ignore the error
-!slave stop;
+wait_for_slave_to_stop;
#restart slave skipping one event
set sql_slave_skip_counter=1;
@@ -69,19 +70,21 @@ insert into t2 values (65);
save_master_pos;
connection slave;
sync_with_master;
---replace_result 9306 9999 3334 9999 3335 9999
+--replace_result 3306 MASTER_PORT 9306 MASTER_PORT 3334 MASTER_PORT 3336 MASTER_PORT
show slave status;
select * from t2;
connection master;
let $1=100;
drop table if exists t3;
create table t3 (n int);
+disable_query_log;
while ($1)
{
#eval means expand $ expressions
eval insert into t3 values($1 + 4);
dec $1;
}
+enable_query_log;
show master logs;
show master status;
save_master_pos;
@@ -89,7 +92,7 @@ connection slave;
slave stop;
slave start;
sync_with_master;
---replace_result 9306 9999 3334 9999 3335 9999
+--replace_result 3306 MASTER_PORT 9306 MASTER_PORT 3334 MASTER_PORT 3336 MASTER_PORT
show slave status;
# because of concurrent insert, the table may not be up to date
# if we do not lock
diff --git a/mysql-test/t/rpl000017-slave.sh b/mysql-test/t/rpl000017-slave.sh
index 0588859c591..066b4880cc1 100755
--- a/mysql-test/t/rpl000017-slave.sh
+++ b/mysql-test/t/rpl000017-slave.sh
@@ -1,3 +1,5 @@
+rm -f $MYSQL_TEST_DIR/var/log/*relay*
+rm -f $MYSQL_TEST_DIR/var/slave-data/relay-log.info
cat > $MYSQL_TEST_DIR/var/slave-data/master.info <<EOF
master-bin.001
4
@@ -6,4 +8,5 @@ replicate
aaaaaaaaaaaaaaabthispartofthepasswordisnotused
$MASTER_MYPORT
1
+0
EOF
diff --git a/mysql-test/t/rpl000017.test b/mysql-test/t/rpl000017.test
index 8e4e61cb9d6..011b6507e49 100644
--- a/mysql-test/t/rpl000017.test
+++ b/mysql-test/t/rpl000017.test
@@ -1,5 +1,5 @@
-connect (master,localhost,root,,test,0,mysql-master.sock);
-connect (slave,localhost,root,,test,0,mysql-slave.sock);
+connect (master,localhost,root,,test,0,master.sock);
+connect (slave,localhost,root,,test,0,slave.sock);
connection master;
reset master;
grant file on *.* to replicate@localhost identified by 'aaaaaaaaaaaaaaab';
diff --git a/mysql-test/t/rpl000018-master.sh b/mysql-test/t/rpl000018-master.sh
deleted file mode 100755
index e570f106ec6..00000000000
--- a/mysql-test/t/rpl000018-master.sh
+++ /dev/null
@@ -1,3 +0,0 @@
-rm -f $MYSQL_TEST_DIR/var/master-data/master-bin.*
-cp $MYSQL_TEST_DIR/std_data/master-bin.001 $MYSQL_TEST_DIR/var/master-data/
-echo ./master-bin.001 > $MYSQL_TEST_DIR/var/master-data/master-bin.index
diff --git a/mysql-test/t/rpl000018.test b/mysql-test/t/rpl000018.test
index 44236323d1d..30d601bb375 100644
--- a/mysql-test/t/rpl000018.test
+++ b/mysql-test/t/rpl000018.test
@@ -1,5 +1,8 @@
-connect (master,localhost,root,,test,0,mysql-master.sock);
-connect (slave,localhost,root,,test,0,mysql-slave.sock);
+require_manager;
+connect (master,localhost,root,,test,0,master.sock);
+connect (slave,localhost,root,,test,0,slave.sock);
+server_stop master;
+server_start master;
connection slave;
reset slave;
slave start;
diff --git a/mysql-test/t/rpl_compat.test b/mysql-test/t/rpl_compat.test
new file mode 100644
index 00000000000..c9455c1e2d2
--- /dev/null
+++ b/mysql-test/t/rpl_compat.test
@@ -0,0 +1,86 @@
+eval_result;
+source include/master-slave.inc;
+connection master;
+require_version 3.23;
+use test;
+drop table if exists t1,t3;
+create table t1 (word char(20) not null);
+load data infile '../../std_data/words.dat' into table t1;
+select * from t1;
+set password for root@"localhost" = password('foo');
+set password for root@"localhost" = password('');
+create table t3(n int);
+insert into t3 values(1),(2);
+save_master_pos;
+connection slave;
+sync_with_master;
+use test;
+select * from t3;
+select sum(length(word)) from t1;
+connection master;
+drop table t1,t3;
+save_master_pos;
+connection slave;
+sync_with_master;
+
+#test handling of aborted connection in the middle of update
+connection master;
+reset master;
+connection slave;
+slave stop;
+reset slave;
+
+connection master;
+create table t1(n int);
+insert into t1 values (1),(2),(3);
+create table t2(id int);
+insert into t2 values(connection_id());
+save_master_pos;
+
+connection master1;
+#avoid generating result
+create temporary table t1_temp(n int);
+insert into t1_temp select get_lock('crash_lock%20C', 1) from t2;
+
+connection master;
+send update t1 set n = n + get_lock('crash_lock%20C', 2);
+connection master1;
+sleep 2;
+select (@id := id) - id from t2;
+kill @id;
+drop table t2;
+connection master;
+--error 1053;
+reap;
+connection slave;
+slave start;
+sync_with_master ;
+#now slave will hit an error
+wait_for_slave_to_stop;
+
+set sql_slave_skip_counter=1;
+slave start;
+select count(*) from t1;
+connection master1;
+drop table t1;
+create table t1 (n int);
+insert into t1 values(3456);
+use mysql;
+insert into user (Host, User, Password)
+ VALUES ("10.10.10.%", "blafasel2", password("blafasel2"));
+select select_priv,user from mysql.user where user = 'blafasel2';
+update user set Select_priv = "Y" where User="blafasel2";
+select select_priv,user from mysql.user where user = 'blafasel2';
+use test;
+save_master_pos;
+connection slave;
+sync_with_master;
+select n from t1;
+select select_priv,user from mysql.user where user = 'blafasel2';
+connection master1;
+drop table t1;
+save_master_pos;
+connection slave;
+sync_with_master;
+
+
diff --git a/mysql-test/t/rpl_failsafe.test b/mysql-test/t/rpl_failsafe.test
new file mode 100644
index 00000000000..866efbce5bf
--- /dev/null
+++ b/mysql-test/t/rpl_failsafe.test
@@ -0,0 +1,24 @@
+require_manager;
+source include/master-slave.inc;
+connect (slave_sec,localhost,root,,test,0,slave.sock-1);
+connect (slave_ter,localhost,root,,test,0,slave.sock-2);
+connection master;
+show variables like 'rpl_recovery_rank';
+show status like 'Rpl_status';
+create table t1(n int);
+drop table t1;
+save_master_pos;
+connection slave;
+sync_with_master;
+show variables like 'rpl_recovery_rank';
+show status like 'Rpl_status';
+connection slave_sec;
+slave start;
+sync_with_master;
+show variables like 'rpl_recovery_rank';
+show status like 'Rpl_status';
+connection slave_ter;
+slave start;
+sync_with_master;
+show variables like 'rpl_recovery_rank';
+show status like 'Rpl_status';
diff --git a/mysql-test/t/rpl_get_lock.test b/mysql-test/t/rpl_get_lock.test
index 3c33103e4c7..3fe45eecf46 100644
--- a/mysql-test/t/rpl_get_lock.test
+++ b/mysql-test/t/rpl_get_lock.test
@@ -6,6 +6,8 @@ dirty_close master;
connection master1;
select get_lock("lock",2);
select release_lock("lock");
+#ignore
+disable_query_log;
let $1=2000;
while ($1)
{
@@ -13,6 +15,7 @@ while ($1)
do release_lock("lock");
dec $1;
}
+enable_query_log;
save_master_pos;
connection slave;
sync_with_master;
diff --git a/mysql-test/t/rpl_log.test b/mysql-test/t/rpl_log.test
new file mode 100644
index 00000000000..3514d435737
--- /dev/null
+++ b/mysql-test/t/rpl_log.test
@@ -0,0 +1,57 @@
+source include/master-slave.inc;
+
+#clean up slave binlogs
+connection slave;
+slave stop;
+reset master;
+reset slave;
+let $VERSION=`select version()`;
+
+connection master;
+reset master;
+drop table if exists t1;
+create table t1(n int not null auto_increment primary key);
+insert into t1 values (NULL);
+drop table t1;
+create table t1 (word char(20) not null);
+load data infile '../../std_data/words.dat' into table t1;
+drop table t1;
+--replace_result $VERSION VERSION
+show binlog events;
+show binlog events from 79 limit 1;
+show binlog events from 79 limit 2;
+show binlog events from 79 limit 2,1;
+flush logs;
+create table t1 (n int);
+insert into t1 values (1);
+drop table t1;
+--replace_result $VERSION VERSION
+show binlog events;
+show binlog events in 'master-bin.002';
+show master logs;
+save_master_pos;
+connection slave;
+slave start;
+sync_with_master;
+show master logs;
+--replace_result 3306 MASTER_PORT 9306 MASTER_PORT 3334 MASTER_PORT 3336 MASTER_PORT $VERSION VERSION
+# We can't compare binlog from slave as the result differ between
+# machines based on where the LOAD DATA file is stored.
+disable_result_log;
+
+show binlog events in 'slave-bin.001' from 4;
+--replace_result 3306 MASTER_PORT 9306 MASTER_PORT 3334 MASTER_PORT 3336 MASTER_PORT $VERSION VERSION
+enable_result_log;
+show binlog events in 'slave-bin.002' from 4;
+--replace_result 3306 MASTER_PORT 9306 MASTER_PORT 3334 MASTER_PORT 3336 MASTER_PORT
+show slave status;
+show new master for slave with master_log_file='master-bin.001' and
+ master_log_pos=4 and master_server_id=1;
+show new master for slave with master_log_file='master-bin.001' and
+ master_log_pos=79 and master_server_id=1;
+show new master for slave with master_log_file='master-bin.001' and
+ master_log_pos=311 and master_server_id=1;
+show new master for slave with master_log_file='master-bin.002' and
+ master_log_pos=4 and master_server_id=1;
+show new master for slave with master_log_file='master-bin.002' and
+ master_log_pos=122 and master_server_id=1;
diff --git a/mysql-test/t/rpl_magic.test b/mysql-test/t/rpl_magic.test
new file mode 100644
index 00000000000..376edc301d7
--- /dev/null
+++ b/mysql-test/t/rpl_magic.test
@@ -0,0 +1,31 @@
+source include/master-slave.inc;
+
+#first, make sure the slave has had enough time to register
+connection master;
+save_master_pos;
+connection slave;
+sync_with_master;
+
+#discover slaves
+connection master;
+rpl_probe;
+
+#turn on master/slave query direction auto-magic
+enable_rpl_parse;
+drop table if exists t1;
+create table t1 ( n int);
+insert into t1 values (1),(2),(3),(4);
+disable_rpl_parse;
+save_master_pos;
+enable_rpl_parse;
+connection slave;
+sync_with_master;
+insert into t1 values(5);
+connection master;
+select * from t1;
+select * from t1;
+disable_rpl_parse;
+select * from t1;
+connection slave;
+select * from t1;
+drop table t1;
diff --git a/mysql-test/t/rpl_mystery22.test b/mysql-test/t/rpl_mystery22.test
index 3a48ef84dc1..e987074697b 100644
--- a/mysql-test/t/rpl_mystery22.test
+++ b/mysql-test/t/rpl_mystery22.test
@@ -1,5 +1,6 @@
# test case to make slave thread get ahead by 22 bytes
+drop table if exists t1;
source include/master-slave.inc;
connection master;
# first, cause a duplicate key problem on the slave
diff --git a/mysql-test/t/rpl_sporadic_master.test b/mysql-test/t/rpl_sporadic_master.test
index c1a47781ddf..0487f868436 100644
--- a/mysql-test/t/rpl_sporadic_master.test
+++ b/mysql-test/t/rpl_sporadic_master.test
@@ -7,7 +7,7 @@ drop table if exists t1,t2;
create table t2(n int);
create table t1(n int not null auto_increment primary key);
insert into t1 values (NULL),(NULL);
-delete from t1;
+truncate table t1;
# We have to use 4 in the following to make this test work with all table types
insert into t1 values (4),(NULL);
save_master_pos;
@@ -18,10 +18,8 @@ slave start;
connection master;
insert into t1 values (NULL),(NULL);
flush logs;
-delete from t1;
-insert into t1 values (10),(NULL);
-insert into t1 values (NULL),(NULL);
-insert into t1 values (NULL),(NULL);
+truncate table t1;
+insert into t1 values (10),(NULL),(NULL),(NULL),(NULL),(NULL);
save_master_pos;
connection slave;
sync_with_master;
diff --git a/mysql-test/t/select.test b/mysql-test/t/select.test
index cdb6ee57e0f..ab4251fe536 100644
--- a/mysql-test/t/select.test
+++ b/mysql-test/t/select.test
@@ -1713,6 +1713,12 @@ show full columns from t2 from test like 's%';
show keys from t2;
#
+# Test of DO
+
+DO 1;
+DO benchmark(100,1+1),1,1;
+
+#
# Drop the test tables
#
diff --git a/mysql-test/t/select_found.test b/mysql-test/t/select_found.test
new file mode 100644
index 00000000000..9b14ab1fcf0
--- /dev/null
+++ b/mysql-test/t/select_found.test
@@ -0,0 +1,32 @@
+#
+# Testing of found_rows()
+#
+
+drop table if exists t1;
+create table t1 (a int not null auto_increment, b int not null, primary key(a));
+insert into t1 (b) values (2),(3),(5),(5),(5),(6),(7),(9);
+select SQL_CALC_FOUND_ROWS * from t1;
+select found_rows();
+select SQL_CALC_FOUND_ROWS * from t1 limit 1;
+select found_rows();
+select SQL_CALC_FOUND_ROWS * from t1 order by b desc limit 1;
+select found_rows();
+select SQL_CALC_FOUND_ROWS distinct b from t1 limit 1;
+select found_rows();
+select SQL_CALC_FOUND_ROWS b,count(*) as c from t1 group by b order by c desc limit 1;
+select found_rows();
+select SQL_CALC_FOUND_ROWS * from t1 left join t1 as t2 on (t1.b=t2.a) limit 2,1;
+select found_rows();
+drop table t1;
+
+#
+# Test SQL_CALC_FOUND_ROWS optimization when used with one table and filesort
+#
+
+create table t1 (a int not null primary key);
+insert into t1 values (1),(2),(3),(4),(5);
+select sql_calc_found_rows a from t1 where a in (1,2,3) order by a desc limit 0,2;
+select FOUND_ROWS();
+select sql_calc_found_rows a from t1 where a in (1,2,3) order by a+2 desc limit 0,2;
+select FOUND_ROWS();
+drop table t1;
diff --git a/mysql-test/t/show_check.test b/mysql-test/t/show_check.test
index 0f07d577c0c..56370b9ca85 100644
--- a/mysql-test/t/show_check.test
+++ b/mysql-test/t/show_check.test
@@ -1,21 +1,8 @@
#
# Test of some show commands
#
-drop table if exists t1,t2;
-create table t1 (a int not null primary key, b int not null,c int not null, key(b,c));
-insert into t1 values (1,2,2),(2,2,3),(3,2,4),(4,2,4);
-create table t2 type=isam select * from t1;
-optimize table t1;
-check table t1,t2;
-repair table t1,t2;
-check table t2,t1;
-lock tables t1 write;
-check table t2,t1;
-show columns from t1;
-show full columns from t1;
-show index from t1;
-drop table t1,t2;
+drop table if exists t1,t2;
create table t1 (a int not null primary key, b int not null,c int not null, key(b,c));
insert into t1 values (1,2,2),(2,2,3),(3,2,4),(4,2,4);
check table t1 type=fast;
@@ -72,3 +59,18 @@ drop table t1;
create table t1 (a int not null, primary key (a));
show create table t1;
drop table t1;
+
+flush tables;
+show open tables;
+create table t1(n int);
+insert into t1 values (1);
+show open tables;
+drop table t1;
+
+create table t1 (a int not null, b VARCHAR(10), INDEX (b) ) AVG_ROW_LENGTH=10 CHECKSUM=1 COMMENT="test" TYPE=MYISAM MIN_ROWS=10 MAX_ROWS=100 PACK_KEYS=1 DELAY_KEY_WRITE=1 ROW_FORMAT=fixed;
+show create table t1;
+alter table t1 MAX_ROWS=200 ROW_FORMAT=dynamic PACK_KEYS=0;
+show create table t1;
+ALTER TABLE t1 AVG_ROW_LENGTH=0 CHECKSUM=0 COMMENT="" MIN_ROWS=0 MAX_ROWS=0 PACK_KEYS=DEFAULT DELAY_KEY_WRITE=0 ROW_FORMAT=default;
+show create table t1;
+drop table t1;
diff --git a/mysql-test/t/status.test b/mysql-test/t/status.test
index 70a7a3ab584..cffca437cf1 100644
--- a/mysql-test/t/status.test
+++ b/mysql-test/t/status.test
@@ -1,3 +1,11 @@
+# This test doesn't work with the embedded version as this code
+# assumes that one query is running while we are doing queries on
+# a second connection.
+# This would work if mysqltest run would be threaded and handle each
+# connection in a separate thread.
+#
+-- source include/not_embedded.inc
+
connect (con1,localhost,root,,);
connect (con2,localhost,root,,);
@@ -6,7 +14,7 @@ show status like 'Table_lock%';
connection con1;
SET SQL_LOG_BIN=0;
drop table if exists t1;
-create table t1(n int);
+create table t1(n int) type=myisam;
insert into t1 values(1);
connection con2;
lock tables t1 read;
diff --git a/mysql-test/t/symlink.test b/mysql-test/t/symlink.test
new file mode 100644
index 00000000000..586761921b8
--- /dev/null
+++ b/mysql-test/t/symlink.test
@@ -0,0 +1,89 @@
+-- require r/have_symlink.require
+disable_query_log;
+show variables like "have_symlink";
+enable_query_log;
+
+#
+# First create little data to play with
+#
+drop table if exists t1,t2,t7,t8,t9;
+create table t1 (a int not null auto_increment, b char(16) not null, primary key (a));
+create table t2 (a int not null auto_increment, b char(16) not null, primary key (a));
+insert into t1 (b) values ("test"),("test1"),("test2"),("test3");
+insert into t2 (b) select b from t1;
+insert into t1 (b) select b from t2;
+insert into t2 (b) select b from t1;
+insert into t1 (b) select b from t2;
+insert into t2 (b) select b from t1;
+insert into t1 (b) select b from t2;
+insert into t2 (b) select b from t1;
+insert into t1 (b) select b from t2;
+insert into t2 (b) select b from t1;
+insert into t1 (b) select b from t2;
+insert into t2 (b) select b from t1;
+insert into t1 (b) select b from t2;
+insert into t2 (b) select b from t1;
+insert into t1 (b) select b from t2;
+insert into t2 (b) select b from t1;
+insert into t1 (b) select b from t2;
+insert into t2 (b) select b from t1;
+insert into t1 (b) select b from t2;
+drop table t2;
+
+#
+# Start the test
+# We use t9 here to not crash with tables generated by the backup test
+#
+
+disable_query_log;
+eval create table t9 (a int not null auto_increment, b char(16) not null, primary key (a)) type=myisam data directory="$MYSQL_TEST_DIR/var/tmp" index directory="$MYSQL_TEST_DIR/var/run";
+enable_query_log;
+
+insert into t9 select * from t1;
+check table t9;
+optimize table t9;
+repair table t9;
+alter table t9 add column c int not null;
+show create table t9;
+
+# Test renames
+alter table t9 rename t8, add column d int not null;
+alter table t8 rename t7;
+rename table t7 to t9;
+# Drop old t1 table, keep t9
+drop table t1;
+
+#
+# Test error handling
+# Note that we are using the above table t9 here!
+#
+
+disable_query_log;
+--error 1103,1103
+create table t1 (a int not null auto_increment, b char(16) not null, primary key (a)) type=myisam data directory="tmp";
+
+# Check that we cannot link over a table from another database.
+
+drop database if exists test_mysqltest;
+create database test_mysqltest;
+
+--error 1,1
+create table test_mysqltest.t9 (a int not null auto_increment, b char(16) not null, primary key (a)) type=myisam index directory="/this-dir-does-not-exist";
+
+--error 1103,1103
+create table test_mysqltest.t9 (a int not null auto_increment, b char(16) not null, primary key (a)) type=myisam index directory="not-hard-path";
+
+--error 1,1
+eval create table test_mysqltest.t9 (a int not null auto_increment, b char(16) not null, primary key (a)) type=myisam index directory="$MYSQL_TEST_DIR/var/run";
+
+--error 1,1
+eval create table test_mysqltest.t9 (a int not null auto_increment, b char(16) not null, primary key (a)) type=myisam data directory="$MYSQL_TEST_DIR/var/tmp";
+enable_query_log;
+
+# Check moving table t9 from default database to test_mysqltest;
+# In this case the symlinks should be removed.
+
+alter table t9 rename test_mysqltest.t9;
+select count(*) from test_mysqltest.t9;
+show create table test_mysqltest.t9;
+drop database test_mysqltest;
diff --git a/mysql-test/t/tablelock.test b/mysql-test/t/tablelock.test
index c32a3f7cd35..fa8c4f03675 100644
--- a/mysql-test/t/tablelock.test
+++ b/mysql-test/t/tablelock.test
@@ -2,6 +2,7 @@
# Test of lock tables
#
+drop table if exists t1,t2;
create table t1 ( n int auto_increment primary key);
lock tables t1 write;
insert into t1 values(NULL);
@@ -36,12 +37,10 @@ drop table t1;
CREATE TABLE t1 (a int);
CREATE TABLE t2 (a int);
lock tables t1 write,t1 as b write, t2 write, t2 as c read;
-drop table t1;
-drop table t2;
+drop table t1,t2;
CREATE TABLE t1 (a int);
CREATE TABLE t2 (a int);
lock tables t1 write,t1 as b write, t2 write, t2 as c read;
-drop table t2;
-drop table t1;
+drop table t2,t1;
unlock tables;
diff --git a/mysql-test/t/truncate.test b/mysql-test/t/truncate.test
index e995517cf1e..2430682a93f 100644
--- a/mysql-test/t/truncate.test
+++ b/mysql-test/t/truncate.test
@@ -2,10 +2,14 @@
# Test of truncate
#
create table t1 (a integer, b integer,c1 CHAR(10));
+insert into t1 (a) values (1),(2);
truncate table t1;
select count(*) from t1;
insert into t1 values(1,2,"test");
select count(*) from t1;
+delete from t1;
+select * from t1;
drop table t1;
# The following should fail
-!$1146 select count(*) from t1;
+--error 1146
+select count(*) from t1;
diff --git a/mysql-test/t/type_datetime.test b/mysql-test/t/type_datetime.test
index 1e7bd11bab1..857937fd90e 100644
--- a/mysql-test/t/type_datetime.test
+++ b/mysql-test/t/type_datetime.test
@@ -30,3 +30,12 @@ CREATE TABLE t1 (a datetime not null);
insert into t1 values (0);
select * from t1 where a is null;
drop table t1;
+
+#
+# Test with bug when propagating DATETIME to integer and WHERE optimization
+#
+
+create table t1 (id int, dt datetime);
+insert into t1 values (1,"2001-08-14 00:00:00"),(2,"2001-08-15 00:00:00"),(3,"2001-08-16 00:00:00");
+select * from t1 where dt='2001-08-14 00:00:00' and dt = if(id=1,'2001-08-14 00:00:00','1999-08-15');
+drop table t1;
diff --git a/mysql-test/t/type_enum.test b/mysql-test/t/type_enum.test
index 0278f53c642..62d83388a67 100644
--- a/mysql-test/t/type_enum.test
+++ b/mysql-test/t/type_enum.test
@@ -2,6 +2,7 @@
# Problem with many enums
#
+DROP TABLE if exists t1;
CREATE TABLE t1 (
field enum('001001','001004','001010','001018','001019','001020','001021','001027','001028','001029','001030','001031','001100','002003','002004','002005','002007','002008','002009','002012','002013','002014','003002','003003','003004','003005','003006','003007','003008','003009','003010','003011','003012','003013','003014','003015','003016','003017','003018','003019','004002','004003','004005','004006','004007','004008','004010','004012','004014','004016','004017','004020','004021','004022','004023','004024','004025','004026','006002','006004','006006','006010','006011','006012','006013','006014','007001','007002','007003','007004','007005','007006','007007','007008','007009','007010','007011','007012','007013','007014','007015','007016','007017','007018','007019','007020','007021','007022','007023','007024','007025','007026','007027','007028','007029','007030','007031','007032','007033','007034','007035','007036','007037','007038','007039','007040','007043','007044','009001','009002','009004','009005','009006','009007','009008','009009','009010','009011','009012','009013','010002','010003','010004','010005','010006','010007','010008','010009','010010','010011','010012','010013','010015','010016','010017','010018','010019','010020','010021','010022','010023','010024','010025','010026','010027','010028','011001','011002','011003','011004','011006','011012','011013','011014','011015','011016','012017','012018','012019','012023','012027','012028','012029','012030','012031','012032','012033','012034','012035','012036','012037','012038','012039','014001','016002','016003','016004','016007','016010','016011','016016','016019','016020','016021','016022','016023','016024','016026','016027','016028','016029','016030','016031','016032','016033','016034','017002','018001','019002','019004','020001','020003','020004','020005','020006','020007','020008','020009','022001','022002','022003','023001','023002','023003','023004','023005','023006','023007','023008','023010','023011','023012','023017','023019','023020','023021','023025','023026','023027','023028','023029','023030','023031','023032','023033','023034','023035','025001','025003','025004','025005','025006','025007','025008','025009','025010','025011','025012','025013','025014','025015','025016','025017','025018','025019','025020','025021','025022','025023','025024','025025','025026','025027','025028','025029','025030','025031','025032','025033','025034','025035','025036','025037','025038','025039','025040','025041','025042','025043','025044','025045','025046','025047','025048','025049','025050','025051','025052','025053','025054','025055','025056','025057','025058','025059','025060','025061','025062','025063','027001','027002','027011','035008','035012','036001','037001','037003','037004','037005','037006','037007','037008','037009','038004','038005','038006','038007','038009','039001','039002','039003','039004','039005','039006','046001','046002','046003','046004','046005','046007','046008','046009','046010','046011','046012','046013','046014','047001','047002','048001','051001','051002','051003','051004','052001','052002','052005','053015','053016','053019','053020','053023','053024','053026','053028','053029','053033','053034','053036','053037','053038','053039','053041','053042','053043','053045','053046','053047','053048','053051','053052','053054','053055','053056','053057','053068','053069','053070','053073','053074','053075','053086','053094','053095','053096','053097','053098','053099','053100','053101','053102','053103','053104','053105','053107','053122','053123','053124','053125','053127','053128','054001','054002','054003','054004','054005','054006','054007','054009','054010','056001','056002','056003','056004','056005','056006','056009','056010','056011','056016','056017','056018','056019','056020','056021','056022','057001','057002','057003','057004','058002','058003','058004','058005','060001','060003','060004','060005','060006','060007','061002','061003','061004','061005','061006','069006','069007','069010','069011','069012','069013','069014','069015','069016','069017','069018','069020','069021','069022','069023','069024','071002','071003','071004','071005','071006','071008','071011','071013','071020','071021','071022','072001','073001','073002','073003','073004','074001','074002','074003','074004','074005','074006','074007','074008','074009','074010','074011','074012','075001','075007','076101','076102','076103','077001','077002','077003','077004','077006','077007','077008','077009','078005','079002','079003','079004','079005','079006','079007','081001','082006','082007','082011','082013','082014','082015','082016','082017','082021','082022','082023','082024','082025','082026','082027','082028','082029','082030','082031','082032','082033','082034','082035','082036','082037','082038','082039','082040','082041','082042','082043','082044','084001','084002','084003','084004','084005','084007','084008','084009','084011','084013','084014','084016','084017','084027','084031','084032','084033','084035','084036','084037','084038','084039','084040','084041','084042','084043','084044','084045','084046','084047','084048','084049','084050','084051','085001','085002','085003','085004','085005','085006','085007','085009','085011','085012','085013','085014','085015','085016','085017','085018','085019','085020','085021','085022','085023','085028','085029','085030','085031','085033','085034','085035','085036','085037','085038','085040','085041','085042','085043','085044','085045','085046','085047','085048','085063','085064','085065','085068','085070','085071','085073','085082','085083','085086','085088','085089','085090','085091','085092','085093','085094','085095','085096','085097','085098','085099','085100','085101','085102','085103','085104','085105','085106','085107','085108','085109','085110','085111','085112','085113','085115','085119','085120','085121','085122','085123','085124','085125','085126','085127','085128','085129','085130','085132','085133','085134','085135','085136','085137','086001','086002','086003','086004','086005','088001','088003','088005','088006','088007','088008','088009','089001','090001','090002','090003','090004','090005','090006','090007','090008','090009','090010','090013','090015','090016','090017','090018','090019','090022','090027','090028','091001','091002','091005','091008','091009','091010','091011','091012','091013','091014','091015','091016','091017','091018','093001','093003','093098','093100','093102','093104','093141','093142','093146','093151','093153','093167','093168','093176','094001','094002','094004','094005','095004','099001','099002','100001','101001','102002','102003','105001','105002','106001','113001','113002','113003','113004','113005','113006','113007','113008','113009','113010','113011','113012','113013','113014','113015','113016','113017','113018','113019','113020','113021','113022','113023','113024','113025','113026','113027','113028','114001','115001','115002','115003','115004','115005','115006','115007','115008','115009','115010','115011','115012','115013','115014','115015','115016','115017','115018','115020','115021','115022','115023','115025','115026','115027','115028','115029','115030','115031','115032','115033','115034','115035','115036','115039','115040','115041','115042','115043','115044','115045','115046','115047','115048','115049','115050','115051','115052','115053','115054','115055','115056','115057','115059','115060','115061','115062','115063','115064','115065','115066','115067','115068','115069','115070','115071','115072','115073','115075','115076','115081','115082','115085','115086','115087','115088','115095','115096','115097','115098','115099','115101','115102','115103','115104','115105','115106','115108','115109','115110','115111','115112','115113','115114','115115','115116','115117','115118','115119','115120','115121','115122','116001','116002','116003','116004','116005','116006','116007','116008','116009','116010','116011','116012','117001','117002','117003','123001','124010','124014','124015','124019','124024','124025','124026','124027','124028','124029','124030','124031','124032','124033','124035','124036','124037','124038','124039','124040','124041','124042','124043','124044','124045','124046','124047','124048','124049','124050','124051','124052','124053','124054','124055','124056','124057','124058','124059','124060','124061','124062','124063','124064','124065','126001','126002','126003','126004','126005','126006','126007','126008','126009','126010','126011','126012','130001','132001','132002','132003','133001','133008','133009','133010','133011','133012','133013','133014','133015','133016','133017','133018','133019','133020','133021','133022','133023','133024','133025','133027','133028','133029','133030','133031','134001','135001','135002','135003','135004','135005','135006','135007','135008','135009','135010','136001','137009','137010','137011','137012','137013','137014','137015','137016','137017','137018','137019','138001','138002','138003','138004','139001','139003','140001','141001','141002','141003','141006','141007','141008','141009','141011','141012','141014','141015','141016','141017','141018','141019','141020','141021','141022','141023','141024','141025','141026','141027','141028','142001','142002','142003','142004','142005','142006','142007','142008','142010','142011','142012','144001','145001','145002','145003','145004','145005','145006','145007','145008','145009','145010','145011','145012','145013','145014','145015','145016','147001','150003','150005','150009','150013','150014','150015','150016','150017','150020','150021','152001','152002','152003','152004','152005','152006','152007','154001','154002','154003','155001','155002','155003','155004','155005','155006','159001','159002','159003','159004','160001','160002','160003','161001','162001','162002','162003','162004','162007','162010','162011','162012','163001','163002','163003','163005','163010','163011','163014','163015','163016','165001','165002','165003','165004','165005','165006','165007','165008','165009','165010','165011','165012','165013','165014','165015','165016','165017','165018','165019','165020','165021','165022','165023','165024','165025','165026','165027','165028','165029','165030','165031','165032','165033','165034','165035','165036','167001','168001','168002','168003','168004','168005','168007','168008','168009','168010','168011','168012','168013','168014','169001','169002','169003','169007','169008','169009','169010','170001','171001','171002','171003','171004','171005','171006','171007','171008','171009','172001','174001','174002','174003','176001','176002','176003','177001','177002','179001','179002','179003','179004','179005','179006','179007','179008','179009','179010','179011','179012','179013','179014','179015','179016','179017','179018','179019','179020','179021','179022','179023','179024','179025','179026','179027','179028','179029','179030','179031','179032','179033','179034','179035','179036','179037','179038','179039','179040','179041','179042','179043','179044','179045','179046','179047','180001','180010','180012','180013','180014','180015','180016','180017','180018','180019','180020','180021','180022','180023','180024','180025','180026','180027','180028','180030','180031','180032','180033','180034','180035','180036','180037','180038','180039','180041','180042','180043','180044','180045','180046','180047','180048','180049','180050','180051','180052','180053','180054','180055','180056','180057','180058','180059','180060','180061','180062','180063','180064','180065','180066','180067','180068','180069','180070','180071','182001','184001','184002','184005','184006','184007','184008','184009','184010','184011','185001','185003','187001','188001','188002','188003','188004','188005','188006','188007','188008','188009','188010','188011','191001','191002','192002','194001','194002','194003','194004','194005','194006','194007','195001','195002','195003','195004','195005','195006','195007','196001','196002','197001','197002','197003','197004','197005','197006','198001','198003','198004','198005','198006','198007','198008','198009','198010','198011','198012','198013','198014','198015','198016','198017','201001','201002','201005','202001','203001','203002','203003','203017','203018','203019','204001','204002','204003','205001','208001','208002','208003','208004','208005','209001','209002','209003','210001','210002','210003','210004','210005','210006','210007','210008','210009','210010','210011','210012','210013','211017','212001','212002','212003','212004','212005','212006','212007','212008','212009','212010','212011','212012','212013','218001','218003','218004','218006','218007','218008','218009','218011','218015','218016','218017','218018','218019','218020','218021','218022','218023','218024','218025','218026','218027','218028','218029','218030','218031','218032','218033','218034','218035','218036','221001','221002','221003','221004','221005','221006','221007','221008','221009','221010','221011','221012','221013','223001','223002','223003','224001','224002','224003','224006','224007','224008','225001','225002','225003','225004','225005','225006','225007','225008','225009','225010','225011','225012','225013','226001','226002','226003','226004','226005','226006','226007','226008','226009','227001','227002','227003','227004','227005','227006','227007','227008','227009','227010','227011','227012','227013','227014','227015','227016','227017','227018','227019','227020','227021','227022','227023','227024','227025','227026','227027','227028','227029','227030','227031','227032','227033','227034','227035','227036','227037','227038','227039','227040','227041','227042','227043','227044','227045','227046','227047','227048','227049','227050','227051','227052','227053','227054','227055','227056','227057','227058','227059','227060','227061','227062','227063','227064','227065','227066','227067','227068','227069','227070','227071','227072','227073','227074','227075','227076','227077','227078','227079','227080','227081','227082','227083','227084','227085','227086','227087','227088','227089','227090','227091','227092','227093','227094','227095','227096','227097','227098','227099','227100','227101','227102','227103','227104','227105','227106','227107','227108','227109','227110','227111','227112','227113','227114','227115','227116','227117','227118','227119','227120','227122','227123','227124','227125','227126','227127','227128','227129','227130','227131','227132','227133','227134','227135','227136','227137','227138','227139','227140','227141','227142','227143','227144','227145','227146','227147','227148','227149','227150','227151','227152','228001','229001','229002','229003','229004','229005','230001','230002','232001','233001','233002','233003','233004','233005','233006','233007','233008','234001','234002','234003','234004','234005','234006','234007','234008','234009','234010','234011','234012','234013','234014','234015','234016','234017','234018','234019','234020','234021','234022','234023','234024','234025','234026','234027','234028','234029','234030','235001','235002','235003','235004','235005','236001','236002','236003','237001','238002','238003','238004','238005','238006','238007','238008','333013','333014','333015','333016','333017','333018','333019','333020','333021','333022','333023','333024','333025','333030','333031','333032','333033','333034','333035','334001','334002','334003','334004','334005','334006','334007','336004','337001','337002','337003','337004','339001','339002','343001','344001','344002','344003','344004','344005','345001','345002','345003','347001','347002','348001','348002','348003','348004','348005','349001','349002','349003','350001','353001','353002','353003','353004','355001','355002','355003','355004','355005','355006','356001','358001','359001','359002','360001','360002','360003','360004','360005','366001','366002','366003','366004','369001','373001','373002','373003','373004','373005','373006','373007','373008','373009','373010','373011','373012','373013','373014','373015','373016','373017','373018','373019','373020','373021','374001','374002','374003','374004','374005','374006','374007','374008','374009','374010','374011','374012','374013','374014','374015','374016','376001','376002','376003','376004','376005','376006','376007','376008','376009','376010','376011','376012','376013','376016','376017','376018','376019','376020','376021','379003','382001','382002','383001','384001','384002','385001','385002','386001','386002','386003','386004','386005','386006','386007','386008','386009','386010','386011','386012','386013','386014','387001','389001','389002','389003','389004','392001','393001','393002','393003','393004','395001','396001','397001','397002','399001','399002','399003','400001','400002','401001','401002','401003','402001','402002','402003','402004','402005','403001','403002','403003','504001','504002','504004','504005','504006','504007','504008','504009','504010','504011','504012','504013','504014','504017','504018','504019','504021','504022','504023','504024','504025','506001','506002','508001','508002','511001','511002','511003','511004','511005','511006','511007','511008','511009','511010','511011','511012','511013','511014','511017','511018','511020','511021','511022','511024','511028','511029','513001','513002','513003','513004','514001','515001','515002','515003','515007','515008','515009','515010','515011','515012','515013','515014','515015','518001','518002','518003','520001','520002','521001','521002','521003','521004','521005','521006','521007','521008','521009','521010','521011','521012','521013','521014','521015','521016','523001','523002','523003','523004','523005','523006','523007','524001','700001','701001','701002','701003','702001','702002','702003','702004','702005','702006','702007','702008','703001','703002','703003','704001','704002','704003','704004','705001','706001','706002','707001','707002','707003','708001','709001','709002','710001','710002','711001','711002','712001','713001','713002','714001','714002','715001','716001','718001','718002','719001','719002','991001','991002','991003','991004','991005','991006','991007','991008','992001','995001','996001','996002','996003','998001','998002','998003','998004','998005','998006','998007','999001','999002','011017','011018','034001','034002','071010','208006','239001','519001','519003','126013','184012','053071','374017','374018','374019','374020','374021','404001','405002','405001','405003','405007','405006','405005','405004','240011','240010','240009','240008','240007','240006','240005','240004','240003','240002','240001','240012','240013','240014','240015','240016','240017','357001','235006','235007','712002','355008','355007','056023','999999','046015','019005','126014','241003','241002','241001','240018','240020','240019','242001','242002','242003','242004','242005','242006','089002','406001','406002','406003','406004','406005','406006','243001','243002','243003','243004','243005','243006','243007','243008','010030','010029','407001','407006','407005','407004','407003','407002','408001','366005','133032','016035','077010','996004','025064','011019','407007','407008','407009','409001','115123','504026','039007','039009','039008','039010','039011','039012','180072','240021','240023','408002','405008','235008','525001','525002','525003','525004','410001','410002','410003','410004','410005','410006','410007','410008','410009','410010','410011','410012','410013','410014','410015','410016','344006','240031','240030','240029','240028','240027','240026','240025','240024','240034','240033','240032','410017','410018','411001','411002','411003','411004','411005','411006','411007','411008','203020','203021','203022','412001','412002','412003','412004','069025','244001','244002','244009','244008','244007','244006','244005','244004','244003','244015','244014','244013','244012','244011','244010','244016','244017','240042','240041','240040','240039','240038','240037','240036','240035','405009','405010','240043','504034','504033','504032','504031','504030','504029','504028','504027','504042','504041','504040','504039','504038','504037','504036','504035','800001','410019','410020','410021','244018','244019','244020','399004','413001','504043','198018','198019','344007','082045','010031','010032','010033','010034','010035','504044','515016','801002','801003','801004','801005','802001','801001','414001','414002','414003','141029','141030','803001','803002','803003','803004','803005','803006','803007','803008','803009','803010','803011','803012','803013','803014','803015','803016','803017','410022','410023','803018','803019','803020','415002','415001','244021','011020','011023','011022','011021','025065','165037','165038','165039','416001','416002','416003','417001','418001','504045','803022','803021','240022','419001','420001','804010','804009','804008','804007','804006','804005','804004','804003','804002','804001','804020','804019','804018','804017','804016','804015','804014','804013','804012','804011','804024','804021','804023','804022','511019','511016','511015','511032','511031','511030','511027','511026','511025','511033','511023','133034','133033','169011','344008','344009','244022','244026','244025','244030','244023','244024','244027','244028','244029','244031','082046','082047','082048','126015','126016','416004','416005','421001','421002','016037','016036','115124','115125','115126','240049','240048','240047','240046','240045','240044','244032','244033','422001','422002','422003','422004','422005','184013','239002','805001','805002','805003','805004','805005','056024','423001','344010','235009','212014','056025','056026','802002','244034','244035','244036','244037','244038','244039','515017','504046','203015','245002','245001','071023','056027','056028','056029','056030','056031','056032','424001','056034','056033','805006','805007','805008','805009','805010','422008','422007','422006','422010','422009','422011','209004','150022','150023','100002','056035','023036','185004','185005','246001','247001','247002','425001','416006','165042','165041','165040','165043','010040','010039','010038','010037','010036','422012','422013','422014','422015','426000','248001','248002','248003','248004','248005','249001','249002','249003','249004','249005','249006','250007','250001','250002','250003','250004','250005','250006','250008','250009','250010','250011','250012','250013','251001','251002','422016','422017','422018','806001','806002','116013','235010','235011','091026','091027','091028','091029','091019','091020','091021','091022','091023','091024','091025','252001','243009','249007','249008','249009','011024','011025','427001','428002','428001','169012','429001','429002','429003') DEFAULT '001001' NOT NULL,
KEY field (field)
diff --git a/mysql-test/t/union.test b/mysql-test/t/union.test
new file mode 100644
index 00000000000..8d98e6e0389
--- /dev/null
+++ b/mysql-test/t/union.test
@@ -0,0 +1,73 @@
+#
+# Test of unions
+#
+
+drop table if exists t1,t2,t3;
+CREATE TABLE t1 (a int not null, b char (10) not null);
+insert into t1 values(1,'a'),(2,'b'),(3,'c'),(3,'c');
+CREATE TABLE t2 (a int not null, b char (10) not null);
+insert into t2 values (3,'c'),(4,'d'),(5,'f'),(6,'e');
+
+select a,b from t1 union select a,b from t2;
+select a,b from t1 union all select a,b from t2;
+select a,b from t1 union all select a,b from t2 order by b;
+select a,b from t1 union all select a,b from t2 union select 7,'g';
+select 0,'#' union select a,b from t1 union all select a,b from t2 union select 7,'gg';
+select a,b from t1 union select a,b from t1;
+select 't1',b,count(*) from t1 group by b UNION select 't2',b,count(*) from t2 group by b;
+
+#test alternate syntax for unions
+(select a,b from t1 limit 2) union all (select a,b from t2 order by a) limit 4;
+(select a,b from t1 limit 2) union all (select a,b from t2 order by a limit 1);
+(select a,b from t1 limit 2) union all (select a,b from t2 order by a limit 1) order by b desc;
+
+# Test some error conditions with UNION
+explain select a,b from t1 union all select a,b from t2;
+
+--error 1221
+select a,b from t1 into outfile 'skr' union select a,b from t2;
+
+--error 1221
+select a,b from t1 order by a union select a,b from t2;
+
+--error 1221
+insert into t3 select a from t1 order by a union select a from t2;
+
+--error 1222
+create table t3 select a,b from t1 union select a from t2;
+
+--error 1222
+select a,b from t1 union select a from t2;
+
+--error 1222
+select * from t1 union select a from t2;
+
+--error 1222
+select a from t1 union select * from t2;
+
+# Test CREATE, INSERT and REPLACE
+create table t3 select a,b from t1 union all select a,b from t2;
+insert into t3 select a,b from t1 union all select a,b from t2;
+replace into t3 select a,b as c from t1 union all select a,b from t2;
+
+drop table t1,t2,t3;
+
+#
+# Test bug reported by joc@presence-pc.com
+#
+
+CREATE TABLE t1 (
+ `pseudo` char(35) NOT NULL default '',
+ `pseudo1` char(35) NOT NULL default '',
+ `same` tinyint(1) unsigned NOT NULL default '1',
+ PRIMARY KEY (`pseudo1`),
+ KEY `pseudo` (`pseudo`)
+) TYPE=MyISAM;
+INSERT INTO t1 (pseudo,pseudo1,same) VALUES ('joce', 'testtt', 1),('joce', 'tsestset', 1),('dekad', 'joce', 1);
+SELECT pseudo FROM t1 WHERE pseudo1='joce' UNION SELECT pseudo FROM t1 WHERE pseudo='joce';
+SELECT pseudo1 FROM t1 WHERE pseudo1='joce' UNION SELECT pseudo1 FROM t1 WHERE pseudo='joce';
+SELECT * FROM t1 WHERE pseudo1='joce' UNION SELECT * FROM t1 WHERE pseudo='joce' order by pseudo desc,pseudo1 desc;
+SELECT pseudo1 FROM t1 WHERE pseudo='joce' UNION SELECT pseudo FROM t1 WHERE pseudo1='joce';
+SELECT pseudo1 FROM t1 WHERE pseudo='joce' UNION ALL SELECT pseudo FROM t1 WHERE pseudo1='joce';
+SELECT pseudo1 FROM t1 WHERE pseudo='joce' UNION SELECT 1;
+drop table t1;
diff --git a/mysql-test/t/update.test b/mysql-test/t/update.test
index 6f446a11521..5cbbd2a350e 100644
--- a/mysql-test/t/update.test
+++ b/mysql-test/t/update.test
@@ -76,3 +76,14 @@ alter table t1 change lfdnr lfdnr int(10) unsigned default 0 not null auto_incre
update t1 set status=1 where type='Open';
select status from t1;
drop table t1;
+
+#
+# Test of ORDER BY
+#
+
+create table t1 (a int not null, b int not null);
+insert into t1 values (1,1),(1,2),(1,3);
+update t1 set b=4 where a=1 order by b asc limit 1;
+update t1 set b=4 where a=1 order by b desc limit 1;
+select * from t1;
+drop table t1;
diff --git a/mysql-test/t/varbinary.test b/mysql-test/t/varbinary.test
index 0ab26f51e65..6d2660271ea 100644
--- a/mysql-test/t/varbinary.test
+++ b/mysql-test/t/varbinary.test
@@ -4,6 +4,7 @@
select 0x41,0x41+0,0x41 | 0x7fffffffffffffff | 0,0xffffffffffffffff | 0 ;
select 0x31+1,concat(0x31)+1,-0xf;
+select x'31',X'ffff'+0;
#
# Test of hex constants in WHERE:
@@ -14,3 +15,18 @@ insert into t1 set UNIQ=0x38afba1d73e6a18a;
insert into t1 set UNIQ=123;
explain select * from t1 where UNIQ=0x38afba1d73e6a18a;
drop table t1;
+
+#
+# Test error conditions
+#
+--error 1064
+select x'hello';
+--error 1054
+select 0xfg;
+
+#
+# Test likely error conditions
+#
+create table t1 select 1 as x, 2 as xx;
+select x,xx from t1;
+drop table t1;
diff --git a/mysql-test/xml/README b/mysql-test/xml/README
deleted file mode 100644
index ee1af30db33..00000000000
--- a/mysql-test/xml/README
+++ /dev/null
@@ -1,74 +0,0 @@
-This directory contains all of the test cases for the MySQL Test Suite
-marked up in XML.
-
-To convert these test cases from XML into 'mysqltest' format, one needs
-an XSL translator installed on their system. At MySQL, we use Sablotron
-(http://www.gingerall.com/). Once installed, conversion happens with a
-command like this:
-
- sabcmd xsl/mysqltest.xsl < tests/sel000001.xml > sel000001.test
-
-The file 'sel000001.test' contains the plain text conversion that is
-to be fed into the 'mysqltest' program.
-
-Below is an example of a test case marked up in XML; illustrating all
-of the XML mark-up currently supported in our 'mysqltest.xsl' stylesheet.
-
-----------------------------------------------------
-<?xml version="1.0" standalone="no"?>
-
-<!-- This file is maintained by matt@mysql.com -->
-
-<test name="sel000001">
-
- <version value="3.22"/>
- <version value="3.23"/>
-
- <description>This test will monkey around trying to kill mysqld.</description>
-
- <connect name="Test_Connect1"
- host="MyHostName"
- user="Matt"
- pass="MattPass"
- db="MyDB"
- port="3306"
- sock="MyDB.sock"
- />
-
- <connection name="Test_Connect1">
- <resultfile name="sel000001.result">
- <sql>SELECT y FROM foo WHERE bar='2'</sql>
- </resultfile>
- <sql>INSERT INTO foo VALUES (y='2') WHERE bar='1'</sql>
- </connection>
-
-</test>
-----------------------------------------------------
-
-
-The converted (mysqltest format) output of this source XML file looks
-like:
-
-
-----------------------------------------------------
-# sel000001
-#
-# Versions
-# --------
-# 3.22
-# 3.23
-#
-# Description
-# -----------
-# This test will monkey around trying to kill mysqld.
-#
-
-
-connect(Test_Connect1, MyHostName, Matt, MattPass, MyDB, 3306, MyDB.sock)
-
-connection Test_Connect1
-INSERT INTO foo VALUES (y='2') WHERE bar='1';
-@sel000001.result SELECT y FROM foo WHERE bar='2';
-----------------------------------------------------
-
-
diff --git a/mysql-test/xml/tests/sel000001.xml b/mysql-test/xml/tests/sel000001.xml
deleted file mode 100644
index 7ce4dae8ee1..00000000000
--- a/mysql-test/xml/tests/sel000001.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" standalone="no"?>
-
-<!-- This file is maintained by matt@mysql.com -->
-
-<test name="sel000001">
-
- <version value="3.22"/>
- <version value="3.23"/>
-
- <description>This test is just a simple select.</description>
- <description>Testing WHERE clause.</description>
-
- <sql>DROP TABLE IF EXISTS t</sql>
- <sql>CREATE TABLE t (s CHAR(20) PRIMARY KEY, id INT)</sql>
- <sql>INSERT INTO t VALUES ('cat', 1), ('mouse', 3), ('dog', 2), ('snake', 77)</sql>
-
- <resultfile name="r/3.23/sel000001.result">
- <sql>SELECT s, id FROM t WHERE s = 'mouse'</sql>
- </resultfile>
-
-</test>
diff --git a/mysql-test/xml/tests/sel000002.xml b/mysql-test/xml/tests/sel000002.xml
deleted file mode 100644
index 902233cbbf0..00000000000
--- a/mysql-test/xml/tests/sel000002.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" standalone="no"?>
-
-<!-- This file is maintained by matt@mysql.com -->
-
-<test name="sel000002">
-
- <version value="3.22"/>
- <version value="3.23"/>
-
- <description>This test is just a simple select.</description>
-
- <sql>DROP TABLE IF EXISTS t</sql>
- <sql>CREATE TABLE t (n INT)</sql>
- <sql>INSERT INTO t VALUES (1), (2), (3)</sql>
-
- <resultfile name="r/3.23/sel000002.result">
- <sql>SELECT * FROM t</sql>
- </resultfile>
-
-</test>
diff --git a/mysql-test/xml/tests/sel000003.xml b/mysql-test/xml/tests/sel000003.xml
deleted file mode 100644
index c9334c972d8..00000000000
--- a/mysql-test/xml/tests/sel000003.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" standalone="no"?>
-
-<!-- This file is maintained by matt@mysql.com -->
-
-<test name="sel000003">
-
- <version value="3.22"/>
- <version value="3.23"/>
-
- <description>This test is just a simple select.</description>
- <description>Testing count() function and GROUP BY clause.</description>
-
- <sql>DROP TABLE IF EXISTS t</sql>
- <sql>CREATE TABLE t (name CHAR(20) NOT NULL PRIMARY KEY, score SMALLINT NOT NULL, KEY(score))</sql>
- <sql>INSERT INTO t VALUES ('Sasha', 20), ('Matt', 20), ('Monty', 10), ('David', 10), ('Tim', 10), ('Jeremy', 10)</sql>
-
- <resultfile name="r/3.23/sel000003.result">
- <sql>SELECT COUNT(*) as n, score FROM t GROUP BY score</sql>
- </resultfile>
-
-</test>
diff --git a/mysql-test/xml/tests/sel000004.xml b/mysql-test/xml/tests/sel000004.xml
deleted file mode 100644
index 9c28c632c32..00000000000
--- a/mysql-test/xml/tests/sel000004.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" standalone="no"?>
-
-<!-- This file is maintained by matt@mysql.com -->
-
-<test name="sel000004">
-
- <version value="3.22"/>
- <version value="3.23"/>
-
- <description>Simple arithmetic.</description>
- <description>Testing MOD(), SIGN(), and arithmetic grouping.</description>
-
- <resultfile name="r/3.23/sel000004.result">
- <sql>SELECT 1+1,1-1,1+1*2,8/5,8%5,MOD(8,5),MOD(8,5)|0,-(1+1)*-2,SIGN(-5)</sql>
- </resultfile>
-
-</test>
diff --git a/mysql-test/xml/tests/sel000005.xml b/mysql-test/xml/tests/sel000005.xml
deleted file mode 100644
index 0bcddb2fbb6..00000000000
--- a/mysql-test/xml/tests/sel000005.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" standalone="no"?>
-
-<!-- This file is maintained by matt@mysql.com -->
-
-<test name="sel000005">
-
- <version value="3.22"/>
- <version value="3.23"/>
-
- <description>Numeric functions.</description>
- <description>Testing FLOOR(), CEILING(), ROUND().</description>
-
- <resultfile name="r/3.23/sel000005.result">
- <sql>SELECT FLOOR(5.5),FLOOR(-5.5),CEILING(5.5),CEILING(-5.5),ROUND(5.5),ROUND(-5.5)</sql>
- </resultfile>
-
-</test>
diff --git a/mysql-test/xml/tests/sel000006.xml b/mysql-test/xml/tests/sel000006.xml
deleted file mode 100644
index 3059f8bb7df..00000000000
--- a/mysql-test/xml/tests/sel000006.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" standalone="no"?>
-
-<!-- This file is maintained by matt@mysql.com -->
-
-<test name="sel000006">
-
- <version value="3.22"/>
- <version value="3.23"/>
-
- <description>Numeric functions.</description>
- <description>Testing ROUND(); hundreths precision.</description>
-
- <resultfile name="r/3.23/sel000006.result">
- <sql>SELECT ROUND(5.64,1),ROUND(5.64,2),ROUND(5.64,-1),ROUND(5.64,-2)</sql>
- </resultfile>
-
-</test>
diff --git a/mysql-test/xml/tests/sel000007.xml b/mysql-test/xml/tests/sel000007.xml
deleted file mode 100644
index 8f8bb7162c3..00000000000
--- a/mysql-test/xml/tests/sel000007.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" standalone="no"?>
-
-<!-- This file is maintained by matt@mysql.com -->
-
-<test name="sel000007">
-
- <version value="3.22"/>
- <version value="3.23"/>
-
- <description>Numeric functions.</description>
- <description>Testing TRUNCATE().</description>
-
- <resultfile name="r/3.23/sel000007.result">
- <sql>SELECT TRUNCATE(52.64,1),TRUNCATE(52.64,2),TRUNCATE(52.64,-1),TRUNCATE(52.64,-2)</sql>
- </resultfile>
-
-</test>
diff --git a/mysql-test/xml/tests/sel000008.xml b/mysql-test/xml/tests/sel000008.xml
deleted file mode 100644
index 70a54a15d5b..00000000000
--- a/mysql-test/xml/tests/sel000008.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" standalone="no"?>
-
-<!-- This file is maintained by matt@mysql.com -->
-
-<test name="sel000008">
-
- <version value="3.22"/>
- <version value="3.23"/>
-
- <description>Numeric functions.</description>
- <description>Testing ABS(), LOG(), LOG10(), EXP(), SQRT(), POW(), RAND(), POWER().</description>
-
- <resultfile name="r/3.23/sel000008.result">
- <sql>SELECT ABS(-10),LOG(EXP(10)),EXP(LOG(SQRT(10))*2),POW(10,LOG10(10)),RAND(999999),RAND(),POWER(2,4)</sql>
- </resultfile>
-
-</test>
diff --git a/mysql-test/xml/tests/sel000009.xml b/mysql-test/xml/tests/sel000009.xml
deleted file mode 100644
index 0c79f032112..00000000000
--- a/mysql-test/xml/tests/sel000009.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" standalone="no"?>
-
-<!-- This file is maintained by matt@mysql.com -->
-
-<test name="sel000009">
-
- <version value="3.22"/>
- <version value="3.23"/>
-
- <description>Numeric functions.</description>
- <description>Testing PI(), SIN(), COS(), TAN(), COT(), ASIN(), ACOS(), ATAN().</description>
-
- <resultfile name="r/3.23/sel000009.result">
- <sql>SELECT PI(),SIN(PI()/2),COS(PI()/2),TAN(PI()),COT(1),ASIN(1),ACOS(0),ATAN(1)</sql>
- </resultfile>
-
-</test>
diff --git a/mysql-test/xml/tests/sel000010.xml b/mysql-test/xml/tests/sel000010.xml
deleted file mode 100644
index 6954fef0750..00000000000
--- a/mysql-test/xml/tests/sel000010.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" standalone="no"?>
-
-<!-- This file is maintained by matt@mysql.com -->
-
-<test name="sel000010">
-
- <version value="3.22"/>
- <version value="3.23"/>
-
- <description>Numeric bitwise comparisons.</description>
- <description>Testing |, &amp;, BIT_COUNT().</description>
-
- <resultfile name="r/3.23/sel000010.result">
- <sql>SELECT 1 | (1+1),5 &amp; 3,BIT_COUNT(7)</sql>
- </resultfile>
-
-</test>
diff --git a/mysql-test/xml/tests/sel000011.xml b/mysql-test/xml/tests/sel000011.xml
deleted file mode 100644
index 5c981b2f85a..00000000000
--- a/mysql-test/xml/tests/sel000011.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" standalone="no"?>
-
-<!-- This file is maintained by matt@mysql.com -->
-
-<test name="sel000011">
-
- <version value="3.22"/>
- <version value="3.23"/>
-
- <description>Numeric bitmoving comparisons.</description>
- <description>Testing &lt;&lt;, >>.</description>
-
- <resultfile name="r/3.23/sel000011.result">
- <sql>SELECT 1 &lt;&lt; 32,1 &lt;&lt; 63, 1 &lt;&lt; 64, 4 >> 2, 4 >> 63, 1&lt;&lt; 63 >> 60</sql>
- </resultfile>
-
-</test>
diff --git a/mysql-test/xml/tests/sel000012.xml b/mysql-test/xml/tests/sel000012.xml
deleted file mode 100644
index 7abcc498164..00000000000
--- a/mysql-test/xml/tests/sel000012.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0" standalone="no"?>
-
-<!-- This file is maintained by matt@mysql.com -->
-
-<test name="sel000012">
-
- <version value="3.22"/>
- <version value="3.23"/>
-
- <description>Numeric floating point.</description>
-
- <resultfile name="r/3.23/sel000012.result">
- <sql>SELECT 10,10.0,10.,.1e+2,100.0e-1</sql>
- </resultfile>
-
-</test>
diff --git a/mysql-test/xml/tests/sel000013.xml b/mysql-test/xml/tests/sel000013.xml
deleted file mode 100644
index fbeca6663fc..00000000000
--- a/mysql-test/xml/tests/sel000013.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0" standalone="no"?>
-
-<!-- This file is maintained by matt@mysql.com -->
-
-<test name="sel000013">
-
- <version value="3.22"/>
- <version value="3.23"/>
-
- <description>Numeric floating point.</description>
-
- <resultfile name="r/3.23/sel000013.result">
- <sql>SELECT 6e-05, -6e-05, --6e-05, -6e-05+1.000000</sql>
- </resultfile>
-
-</test>
diff --git a/mysql-test/xml/tests/sel000014.xml b/mysql-test/xml/tests/sel000014.xml
deleted file mode 100644
index 96a51e671fc..00000000000
--- a/mysql-test/xml/tests/sel000014.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" standalone="no"?>
-
-<!-- This file is maintained by matt@mysql.com -->
-
-<test name="sel000014">
-
- <version value="3.22"/>
- <version value="3.23"/>
-
- <description>Numerics.</description>
- <description>Testing pos/neg and zero padding.</description>
-
- <resultfile name="r/3.23/sel000014.result">
- <sql>SELECT 0,256,00000000000000065536,2147483647,-2147483648,2147483648,+4294967296</sql>
- </resultfile>
-
-</test>
diff --git a/mysql-test/xml/tests/sel000015.xml b/mysql-test/xml/tests/sel000015.xml
deleted file mode 100644
index a339330e6b1..00000000000
--- a/mysql-test/xml/tests/sel000015.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" standalone="no"?>
-
-<!-- This file is maintained by matt@mysql.com -->
-
-<test name="sel000015">
-
- <version value="3.22"/>
- <version value="3.23"/>
-
- <description>Numerics.</description>
- <description>Testing big numbers.</description>
-
- <resultfile name="r/3.23/sel000015.result">
- <sql>SELECT 922337203685477580,92233720368547758000</sql>
- </resultfile>
-
-</test>
diff --git a/mysql-test/xml/tests/sel000016.xml b/mysql-test/xml/tests/sel000016.xml
deleted file mode 100644
index ae971e6576a..00000000000
--- a/mysql-test/xml/tests/sel000016.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" standalone="no"?>
-
-<!-- This file is maintained by matt@mysql.com -->
-
-<test name="sel000016">
-
- <version value="3.22"/>
- <version value="3.23"/>
-
- <description>Numerics.</description>
- <description>Testing big negative numbers.</description>
-
- <resultfile name="r/3.23/sel000016.result">
- <sql>SELECT -922337203685477580,-92233720368547758000</sql>
- </resultfile>
-
-</test>
diff --git a/mysql-test/xml/tests/sel000017.xml b/mysql-test/xml/tests/sel000017.xml
deleted file mode 100644
index 9d06d640ac3..00000000000
--- a/mysql-test/xml/tests/sel000017.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" standalone="no"?>
-
-<!-- This file is maintained by matt@mysql.com -->
-
-<test name="sel000017">
-
- <version value="3.22"/>
- <version value="3.23"/>
-
- <description>Numerics.</description>
- <description>Testing big pos/neg numbers.</description>
-
- <resultfile name="r/3.23/sel000017.result">
- <sql>SELECT 9223372036854775807,-009223372036854775808</sql>
- </resultfile>
-
-</test>
diff --git a/mysql-test/xml/tests/sel000018.xml b/mysql-test/xml/tests/sel000018.xml
deleted file mode 100644
index 909728599fa..00000000000
--- a/mysql-test/xml/tests/sel000018.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" standalone="no"?>
-
-<!-- This file is maintained by matt@mysql.com -->
-
-<test name="sel000018">
-
- <version value="3.22"/>
- <version value="3.23"/>
-
- <description>Numerics.</description>
- <description>Testing big pos/neg numbers.</description>
-
- <resultfile name="r/3.23/sel000018.result">
- <sql>SELECT +9999999999999999999,-9999999999999999999</sql>
- </resultfile>
-
-</test>
diff --git a/mysql-test/xml/tests/sel000019.xml b/mysql-test/xml/tests/sel000019.xml
deleted file mode 100644
index e0286ae2db7..00000000000
--- a/mysql-test/xml/tests/sel000019.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" standalone="no"?>
-
-<!-- This file is maintained by matt@mysql.com -->
-
-<test name="sel000019">
-
- <version value="3.22"/>
- <version value="3.23"/>
-
- <description>Numerics.</description>
- <description>Testing DEGREES(), RADIANS().</description>
-
- <resultfile name="r/3.23/sel000019.result">
- <sql>SELECT DEGREES(PI()),RADIANS(360)</sql>
- </resultfile>
-
-</test>
diff --git a/mysql-test/xml/tests/sel000020.xml b/mysql-test/xml/tests/sel000020.xml
deleted file mode 100644
index 41ad5981cb9..00000000000
--- a/mysql-test/xml/tests/sel000020.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" standalone="no"?>
-
-<!-- This file is maintained by matt@mysql.com -->
-
-<test name="sel000020">
-
- <version value="3.22"/>
- <version value="3.23"/>
-
- <description>Strings.</description>
- <description>Testing string comparisons; STRCMP(), =, >, >=, &lt;=, !=.</description>
-
- <resultfile name="r/3.23/sel000020.result">
- <sql>SELECT 0=0,1>0,1>=1,1&lt;0,1&lt;=0,1!=0,STRCMP("abc","abcd"),STRCMP("b","a"),STRCMP("a","a")</sql>
- </resultfile>
-
-</test>
diff --git a/mysql-test/xml/tests/sel000021.xml b/mysql-test/xml/tests/sel000021.xml
deleted file mode 100644
index ba2e8149abd..00000000000
--- a/mysql-test/xml/tests/sel000021.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" standalone="no"?>
-
-<!-- This file is maintained by matt@mysql.com -->
-
-<test name="sel000021">
-
- <version value="3.22"/>
- <version value="3.23"/>
-
- <description>Strings.</description>
- <description>Testing string comparisons; =, >, >=, &lt;=, &lt;>.</description>
-
- <resultfile name="r/3.23/sel000021.result">
- <sql>SELECT "a"&lt;"b","a"&lt;="b","b">="a","b">"a","a"="A","a"&lt;>"b"</sql>
- </resultfile>
-
-</test>
diff --git a/mysql-test/xml/tests/sel000022.xml b/mysql-test/xml/tests/sel000022.xml
deleted file mode 100644
index 3dca0eb9b7f..00000000000
--- a/mysql-test/xml/tests/sel000022.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" standalone="no"?>
-
-<!-- This file is maintained by matt@mysql.com -->
-
-<test name="sel000022">
-
- <version value="3.22"/>
- <version value="3.23"/>
-
- <description>Strings.</description>
- <description>Testing string comparisons; =, >, &lt;=.</description>
-
- <resultfile name="r/3.23/sel000022.result">
- <sql>SELECT "a "="A", "A "="a", "a " &lt;= "A b"</sql>
- </resultfile>
-
-</test>
diff --git a/mysql-test/xml/tests/sel000023.xml b/mysql-test/xml/tests/sel000023.xml
deleted file mode 100644
index 7cceb4aabca..00000000000
--- a/mysql-test/xml/tests/sel000023.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" standalone="no"?>
-
-<!-- This file is maintained by matt@mysql.com -->
-
-<test name="sel000023">
-
- <version value="3.22"/>
- <version value="3.23"/>
-
- <description>Strings.</description>
- <description>Testing string comparisons; LIKE, NOT LIKE, '%'.</description>
-
- <resultfile name="r/3.23/sel000023.result">
- <sql>SELECT "abc" LIKE "a%", "abc" NOT LIKE "%d%", "a%" LIKE "a\%","abc%" LIKE "a%\%","abcd" LIKE "a%b_%d", "a" LIKE "%%a","abcde" LIKE "a%_e","abc" LIKE "abc%"</sql>
- </resultfile>
-
-</test>
diff --git a/mysql-test/xml/tests/sel000024.xml b/mysql-test/xml/tests/sel000024.xml
deleted file mode 100644
index 5bf9c0be7dc..00000000000
--- a/mysql-test/xml/tests/sel000024.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" standalone="no"?>
-
-<!-- This file is maintained by matt@mysql.com -->
-
-<test name="sel000024">
-
- <version value="3.22"/>
- <version value="3.23"/>
-
- <description>Strings.</description>
- <description>Testing string comparisons; LIKE, '%'.</description>
-
- <resultfile name="r/3.23/sel000024.result">
- <sql>SELECT "a" LIKE "%%b","a" LIKE "%%ab","ab" LIKE "a\%", "ab" LIKE "_", "ab" LIKE "ab_", "abc" LIKE "%_d", "abc" LIKE "abc%d"</sql>
- </resultfile>
-
-</test>
diff --git a/mysql-test/xml/tests/sel000025.xml b/mysql-test/xml/tests/sel000025.xml
deleted file mode 100644
index 4144b65775f..00000000000
--- a/mysql-test/xml/tests/sel000025.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" standalone="no"?>
-
-<!-- This file is maintained by matt@mysql.com -->
-
-<test name="sel000025">
-
- <version value="3.22"/>
- <version value="3.23"/>
-
- <description>Strings.</description>
- <description>Testing string comparisons; LIKE, ESCAPE, '%'.</description>
-
- <resultfile name="r/3.23/sel000025.result">
- <sql>SELECT '?' LIKE '|%', '?' LIKE '|%' ESCAPE '|', '%' LIKE '|%', '%' LIKE '|%' ESCAPE '|', '%' LIKE '%'</sql>
- </resultfile>
-
-</test>
diff --git a/mysql-test/xml/tests/sel000026.xml b/mysql-test/xml/tests/sel000026.xml
deleted file mode 100644
index afaa34009fa..00000000000
--- a/mysql-test/xml/tests/sel000026.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" standalone="no"?>
-
-<!-- This file is maintained by matt@mysql.com -->
-
-<test name="sel000026">
-
- <version value="3.22"/>
- <version value="3.23"/>
-
- <description>Strings.</description>
- <description>Testing string comparisons; LIKE, '%'.</description>
-
- <resultfile name="r/3.23/sel000026.result">
- <sql>SELECT 'abc' LIKE '%c','abcabc' LIKE '%c', "ab" LIKE "", "ab" LIKE "a", "ab" LIKE "ab"</sql>
- </resultfile>
-
-</test>
diff --git a/mysql-test/xml/tests/sel000027.xml b/mysql-test/xml/tests/sel000027.xml
deleted file mode 100644
index 641d5d3a619..00000000000
--- a/mysql-test/xml/tests/sel000027.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" standalone="no"?>
-
-<!-- This file is maintained by matt@mysql.com -->
-
-<test name="sel000027">
-
- <version value="3.22"/>
- <version value="3.23"/>
-
- <description>Strings.</description>
- <description>Testing string comparisons; REGEXP.</description>
-
- <resultfile name="r/3.23/sel000027.result">
- <sql>SELECT "Det här är svenska" REGEXP "h[[:alpha:]]+r", "aba" REGEXP "^(a|b)*$"</sql>
- </resultfile>
-
-</test>
diff --git a/mysql-test/xml/tests/sel000028.xml b/mysql-test/xml/tests/sel000028.xml
deleted file mode 100644
index c8db245c25d..00000000000
--- a/mysql-test/xml/tests/sel000028.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" standalone="no"?>
-
-<!-- This file is maintained by matt@mysql.com -->
-
-<test name="sel000028">
-
- <version value="3.22"/>
- <version value="3.23"/>
-
- <description>Strings.</description>
- <description>Testing string comparisons; REGEXP, CONCAT().</description>
-
- <resultfile name="r/3.23/sel000028.result">
- <sql>SELECT "aba" REGEXP CONCAT("^","a")</sql>
- </resultfile>
-
-</test>
diff --git a/mysql-test/xml/tests/sel000029.xml b/mysql-test/xml/tests/sel000029.xml
deleted file mode 100644
index 84d12a44dc5..00000000000
--- a/mysql-test/xml/tests/sel000029.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" standalone="no"?>
-
-<!-- This file is maintained by matt@mysql.com -->
-
-<test name="sel000029">
-
- <version value="3.22"/>
- <version value="3.23"/>
-
- <description>Strings.</description>
- <description>Testing string comparisons; NOT, AND, OR, !, &amp;&amp;, ||.</description>
-
- <resultfile name="r/3.23/sel000029.result">
- <sql>SELECT !0,NOT 0=1,!(0=0),1 AND 1,1 &amp;&amp; 0,0 OR 1,1 || NULL, 1=1 OR 1=1 AND 1=0</sql>
- </resultfile>
-
-</test>
diff --git a/mysql-test/xml/tests/sel000030.xml b/mysql-test/xml/tests/sel000030.xml
deleted file mode 100644
index 8a8a4d5e0d2..00000000000
--- a/mysql-test/xml/tests/sel000030.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" standalone="no"?>
-
-<!-- This file is maintained by matt@mysql.com -->
-
-<test name="sel000030">
-
- <version value="3.22"/>
- <version value="3.23"/>
-
- <description>Control flow.</description>
- <description>Testing control flow; IF()</description>
-
- <resultfile name="r/3.23/sel000030.result">
- <sql>SELECT IF(0,"ERROR","this"),IF(1,"is","ERROR"),IF(NULL,"ERROR","a"),IF(1,2,3)|0,IF(1,2.0,3.0)+0</sql>
- </resultfile>
-
-</test>
diff --git a/mysql-test/xml/xsl/README b/mysql-test/xml/xsl/README
deleted file mode 100644
index fe11b57cf11..00000000000
--- a/mysql-test/xml/xsl/README
+++ /dev/null
@@ -1,4 +0,0 @@
-XML Stylesheets for converting test cases in XML to other forms.
-
- - mysqltest.xsl -> mysqltest format (text)
-
diff --git a/mysql-test/xml/xsl/mysqltest.xsl b/mysql-test/xml/xsl/mysqltest.xsl
deleted file mode 100644
index 8a1e738e611..00000000000
--- a/mysql-test/xml/xsl/mysqltest.xsl
+++ /dev/null
@@ -1,59 +0,0 @@
-<?xml version="1.0"?>
-<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
-
-<xsl:output method="text"/>
-
-<xsl:template match="/"><xsl:apply-templates /></xsl:template>
-
-<!-- Main Template -->
-
-<xsl:template match="/test"># <xsl:apply-templates select="@name"/>
-#
-# Versions
-# --------<xsl:apply-templates select="version"/>
-#
-# Description
-# -----------<xsl:apply-templates select="description"/>
-#
-
-<xsl:apply-templates select="connect"/>
-
-<xsl:apply-templates select="connection"/>
-
-<xsl:apply-templates select="sql"/>
-
-<xsl:apply-templates select="resultfile"/>
-
-</xsl:template>
-
-<!-- End Main Template -->
-
-
-<xsl:template match="version">
-# <xsl:apply-templates select="@value"/>
-</xsl:template>
-
-<xsl:template match="description">
-# <xsl:apply-templates />
-</xsl:template>
-
-<xsl:template match="connect">
-connect(<xsl:apply-templates select="@name"/>, <xsl:apply-templates select="@host"/>, <xsl:apply-templates select="@user"/>, <xsl:apply-templates select="@pass"/>, <xsl:apply-templates select="@db"/>, <xsl:apply-templates select="@port"/>, <xsl:apply-templates select="@sock"/>)
-</xsl:template>
-
-<xsl:template match="connection">
-<xsl:text>
-connection </xsl:text><xsl:apply-templates select="@name"/>
-<xsl:text>
-</xsl:text>
-<xsl:apply-templates select="sql"/>
-<xsl:apply-templates select="resultfile"/>
-</xsl:template>
-
-<xsl:template match="resultfile">@<xsl:apply-templates select="@name"/><xsl:text> </xsl:text><xsl:apply-templates select="sql"/>
-</xsl:template>
-
-<xsl:template match="sql">
-<xsl:apply-templates />;
-</xsl:template>
-</xsl:stylesheet>
diff --git a/mysys/Makefile.am b/mysys/Makefile.am
index 73cd9768013..287dc357b3d 100644
--- a/mysys/Makefile.am
+++ b/mysys/Makefile.am
@@ -24,7 +24,7 @@ LDADD = libmysys.a ../dbug/libdbug.a \
noinst_HEADERS = mysys_priv.h my_static.h
libmysys_a_SOURCES = my_init.c my_getwd.c mf_getdate.c\
mf_path.c mf_loadpath.c\
- my_open.c my_create.c my_seek.c my_read.c \
+ my_open.c my_create.c my_dup.c my_seek.c my_read.c \
my_pread.c my_write.c \
mf_keycache.c \
mf_iocache.c mf_iocache2.c mf_cache.c mf_tempfile.c \
@@ -35,7 +35,7 @@ libmysys_a_SOURCES = my_init.c my_getwd.c mf_getdate.c\
my_error.c errors.c my_div.c my_messnc.c \
mf_format.c mf_same.c mf_dirname.c mf_fn_ext.c \
my_symlink.c my_symlink2.c \
- mf_pack.c mf_pack2.c mf_unixpath.c mf_stripp.c \
+ mf_pack.c mf_unixpath.c mf_stripp.c \
mf_casecnv.c mf_soundex.c mf_wcomp.c mf_wfile.c \
mf_qsort.c mf_qsort2.c mf_sort.c \
ptr_cmp.c mf_radix.c queues.c \
@@ -44,9 +44,9 @@ libmysys_a_SOURCES = my_init.c my_getwd.c mf_getdate.c\
my_delete.c my_rename.c my_redel.c my_tempnam.c \
my_chsize.c my_lread.c my_lwrite.c my_clock.c \
my_quick.c my_lockmem.c my_static.c \
- getopt.c getopt1.c getvar.c my_mkdir.c \
+ getopt.c getopt1.c my_getopt.c getvar.c my_mkdir.c \
default.c my_compress.c checksum.c raid.cc my_net.c \
- my_vsnprintf.c charset.c my_bitmap.c
+ my_vsnprintf.c charset.c my_bitmap.c my_bit.c md5.c
EXTRA_DIST = thr_alarm.c thr_lock.c my_pthread.c my_thr_init.c \
thr_mutex.c thr_rwlock.c
libmysys_a_LIBADD = @THREAD_LOBJECTS@
@@ -96,6 +96,10 @@ test_vsnprintf: my_vsnprintf.c $(LIBRARIES)
$(CP) $(srcdir)/my_vsnprintf.c test_vsnprintf.c
$(LINK) $(FLAGS) -DMAIN ./test_vsnprintf.c $(LDADD) $(LIBS)
$(RM) -f test_vsnprintf.*
+test_io_cache: mf_iocache.c $(LIBRARIES)
+ $(CP) $(srcdir)/mf_iocache.c test_io_cache.c
+ $(LINK) $(FLAGS) -DMAIN ./test_io_cache.c $(LDADD) $(LIBS)
+ $(RM) -f test_io_cache.*
test_dir: test_dir.c $(LIBRARIES)
$(LINK) $(FLAGS) -DMAIN $(srcdir)/test_dir.c $(LDADD) $(LIBS)
diff --git a/mysys/array.c b/mysys/array.c
index 17e5ded322b..408747366d3 100644
--- a/mysys/array.c
+++ b/mysys/array.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/* Handling of arrays that can grow dynamicly. */
diff --git a/mysys/charset.c b/mysys/charset.c
index f778afb4144..93e8b697904 100644
--- a/mysys/charset.c
+++ b/mysys/charset.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include "mysys_priv.h"
#include "mysys_err.h"
@@ -44,13 +43,6 @@ struct simpleconfig_buf_st {
char *p;
};
-/* Defined in strings/ctype.c */
-
-CHARSET_INFO *find_compiled_charset(uint cs_number);
-uint compiled_charset_number(const char *name);
-const char *compiled_charset_name(uint charset_number);
-
-
static uint num_from_csname(CS_ID **cs, const char *name)
{
CS_ID **c;
@@ -110,7 +102,7 @@ char *get_charsets_dir(char *buf)
strxmov(buf, DEFAULT_CHARSET_HOME, "/", sharedir, "/", CHARSET_DIR,
NullS);
}
- convert_dirname(buf);
+ convert_dirname(buf,buf,NullS);
DBUG_PRINT("info",("charsets dir='%s'", buf));
DBUG_RETURN(strend(buf));
}
@@ -203,6 +195,7 @@ static my_bool init_available_charsets(myf myflags)
void free_charsets(void)
{
delete_dynamic(&cs_info_table);
+ charset_initialized=0;
}
@@ -264,22 +257,22 @@ static my_bool read_charset_file(uint cs_number, CHARSET_INFO *set,
uint get_charset_number(const char *charset_name)
{
- my_bool error;
- error = init_available_charsets(MYF(0)); /* If it isn't initialized */
- if (error)
- return compiled_charset_number(charset_name);
- else
- return num_from_csname(available_charsets, charset_name);
+ uint number=compiled_charset_number(charset_name);
+ if (number)
+ return number;
+ if (init_available_charsets(MYF(0))) /* If it isn't initialized */
+ return 0;
+ return num_from_csname(available_charsets, charset_name);
}
const char *get_charset_name(uint charset_number)
{
- my_bool error;
- error = init_available_charsets(MYF(0)); /* If it isn't initialized */
- if (error)
- return compiled_charset_name(charset_number);
- else
- return name_from_csnum(available_charsets, charset_number);
+ const char *name=compiled_charset_name(charset_number);
+ if (*name != '?')
+ return name;
+ if (init_available_charsets(MYF(0))) /* If it isn't initialized */
+ return "?";
+ return name_from_csnum(available_charsets, charset_number);
}
@@ -293,8 +286,8 @@ static CHARSET_INFO *find_charset(CHARSET_INFO **table, uint cs_number,
return NULL;
}
-static CHARSET_INFO *find_charset_by_name(CHARSET_INFO **table, const char *name,
- size_t tablesz)
+static CHARSET_INFO *find_charset_by_name(CHARSET_INFO **table,
+ const char *name, size_t tablesz)
{
uint i;
for (i = 0; i < tablesz; ++i)
@@ -303,7 +296,7 @@ static CHARSET_INFO *find_charset_by_name(CHARSET_INFO **table, const char *name
return NULL;
}
-static CHARSET_INFO *add_charset(uint cs_number, const char *cs_name)
+static CHARSET_INFO *add_charset(uint cs_number, const char *cs_name, myf flags)
{
CHARSET_INFO tmp_cs,*cs;
uchar tmp_ctype[CTYPE_TABLE_SIZE];
@@ -318,11 +311,11 @@ static CHARSET_INFO *add_charset(uint cs_number, const char *cs_name)
cs->to_lower=tmp_to_lower;
cs->to_upper=tmp_to_upper;
cs->sort_order=tmp_sort_order;
- if (read_charset_file(cs_number, cs, MYF(MY_WME)))
+ if (read_charset_file(cs_number, cs, flags))
return NULL;
cs = (CHARSET_INFO*) my_once_alloc(sizeof(CHARSET_INFO),
- MYF(MY_WME));
+ MYF(MY_WME));
*cs=tmp_cs;
cs->name = (char *) my_once_alloc((uint) strlen(cs_name)+1, MYF(MY_WME));
cs->ctype = (uchar*) my_once_alloc(CTYPE_TABLE_SIZE, MYF(MY_WME));
@@ -340,7 +333,7 @@ static CHARSET_INFO *add_charset(uint cs_number, const char *cs_name)
return cs;
}
-static CHARSET_INFO *get_internal_charset(uint cs_number)
+static CHARSET_INFO *get_internal_charset(uint cs_number, myf flags)
{
CHARSET_INFO *cs;
/*
@@ -351,13 +344,13 @@ static CHARSET_INFO *get_internal_charset(uint cs_number)
if (!(cs = find_charset((CHARSET_INFO**) cs_info_table.buffer, cs_number,
cs_info_table.elements)))
if (!(cs = find_compiled_charset(cs_number)))
- cs=add_charset(cs_number, get_charset_name(cs_number));
+ cs=add_charset(cs_number, get_charset_name(cs_number), flags);
pthread_mutex_unlock(&THR_LOCK_charset);
return cs;
}
-static CHARSET_INFO *get_internal_charset_by_name(const char *name)
+static CHARSET_INFO *get_internal_charset_by_name(const char *name, myf flags)
{
CHARSET_INFO *cs;
/*
@@ -368,7 +361,7 @@ static CHARSET_INFO *get_internal_charset_by_name(const char *name)
if (!(cs = find_charset_by_name((CHARSET_INFO**) cs_info_table.buffer, name,
cs_info_table.elements)))
if (!(cs = find_compiled_charset_by_name(name)))
- cs=add_charset(get_charset_number(name), name);
+ cs=add_charset(get_charset_number(name), name, flags);
pthread_mutex_unlock(&THR_LOCK_charset);
return cs;
}
@@ -378,7 +371,7 @@ CHARSET_INFO *get_charset(uint cs_number, myf flags)
{
CHARSET_INFO *cs;
(void) init_available_charsets(MYF(0)); /* If it isn't initialized */
- cs=get_internal_charset(cs_number);
+ cs=get_internal_charset(cs_number, flags);
if (!cs && (flags & MY_WME))
{
@@ -410,7 +403,7 @@ CHARSET_INFO *get_charset_by_name(const char *cs_name, myf flags)
{
CHARSET_INFO *cs;
(void) init_available_charsets(MYF(0)); /* If it isn't initialized */
- cs=get_internal_charset_by_name(cs_name);
+ cs=get_internal_charset_by_name(cs_name, flags);
if (!cs && (flags & MY_WME))
{
diff --git a/mysys/checksum.c b/mysys/checksum.c
index 00861853945..e09de7d5969 100644
--- a/mysys/checksum.c
+++ b/mysys/checksum.c
@@ -1,23 +1,22 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/* Calculate a long checksum for a memoryblock. Used to verify pack_isam */
-#include <global.h>
+#include <my_global.h>
#include "my_sys.h"
ulong checksum(const byte *mem, uint count)
diff --git a/mysys/default.c b/mysys/default.c
index e2e80f36a68..d3c1b3815eb 100644
--- a/mysys/default.c
+++ b/mysys/default.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/****************************************************************************
** Add all options from files named "group".cnf from the default_directories
@@ -95,6 +94,7 @@ void load_defaults(const char *conf_file, const char **groups,
res[0]= **argv; /* Copy program name */
for (i=2 ; i < (uint) *argc ; i++)
res[i-1]=argv[0][i];
+ res[i-1]=0; /* End pointer */
(*argc)--;
*argv=res;
*(MEM_ROOT*) ptr= alloc; /* Save alloc root for free */
@@ -231,11 +231,10 @@ static my_bool search_default_file(DYNAMIC_ARRAY *args, MEM_ROOT *alloc,
return 0; /* Ignore wrong paths */
if (dir)
{
- strmov(name,dir);
- convert_dirname(name);
+ end=convert_dirname(name, dir, NullS);
if (dir[0] == FN_HOMELIB) /* Add . to filenames in home */
- strcat(name,".");
- strxmov(strend(name),config_file,ext,NullS);
+ *end++='.';
+ strxmov(end,config_file,ext,NullS);
}
else
{
@@ -369,16 +368,18 @@ void print_defaults(const char *conf_file, const char **groups)
#endif
for (dirs=default_directories ; *dirs; dirs++)
{
+ const char *pos;
+ char *end;
if (**dirs)
- strmov(name,*dirs);
+ pos= *dirs;
else if (defaults_extra_file)
- strmov(name,defaults_extra_file);
+ pos= defaults_extra_file;
else
continue;
- convert_dirname(name);
+ end=convert_dirname(name, pos, NullS);
if (name[0] == FN_HOMELIB) /* Add . to filenames in home */
- strcat(name,".");
- strxmov(strend(name),conf_file,default_ext," ",NullS);
+ *end++='.';
+ strxmov(end,conf_file,default_ext," ",NullS);
fputs(name,stdout);
}
puts("");
@@ -395,4 +396,3 @@ void print_defaults(const char *conf_file, const char **groups)
--defaults-file=# Only read default options from the given file #\n\
--defaults-extra-file=# Read this file after the global files are read");
}
-
diff --git a/mysys/errors.c b/mysys/errors.c
index 77e52c2f0b3..8a120e0e869 100644
--- a/mysys/errors.c
+++ b/mysys/errors.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include "mysys_priv.h"
#include "mysys_err.h"
diff --git a/mysys/getopt.c b/mysys/getopt.c
index 774cf3b82f4..7b96e10c85c 100644
--- a/mysys/getopt.c
+++ b/mysys/getopt.c
@@ -27,7 +27,7 @@ You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If
not, write to the Free Software Foundation, Inc., 675 Mass Ave,
Cambridge, MA 02139, USA. */
-
+
/* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>.
Ditto for AIX 3.2 and <stdlib.h>. */
#ifndef _NO_PROTO
@@ -46,7 +46,7 @@ Cambridge, MA 02139, USA. */
#endif
#endif
-#include <global.h> /* Changes for mysys */
+#include <my_global.h> /* Changes for mysys */
#include <m_string.h>
/* Comment out all this code if we are using the GNU C Library, and are not
diff --git a/mysys/getopt1.c b/mysys/getopt1.c
index bff76d6e5b2..15f3c8f544b 100644
--- a/mysys/getopt1.c
+++ b/mysys/getopt1.c
@@ -24,7 +24,7 @@ Cambridge, MA 02139, USA. */
#include <config.h>
#endif
-#include <global.h>
+#include <my_global.h>
#include "getopt.h"
#if (!defined (__STDC__) || !__STDC__) && !defined(MSDOS) && !defined(OS2)
diff --git a/mysys/getvar.c b/mysys/getvar.c
index 90ab599244d..bb470423c57 100644
--- a/mysys/getvar.c
+++ b/mysys/getvar.c
@@ -1,26 +1,25 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/* Allow use of the -O variable= option to set long variables */
#include "mysys_priv.h"
#include <m_string.h>
#include <m_ctype.h>
-
+#include <my_getopt.h>
/* set all changeable variables */
void set_all_changeable_vars(CHANGEABLE_VAR *vars)
diff --git a/mysys/hash.c b/mysys/hash.c
index e37bea3846c..0b326ebc508 100644
--- a/mysys/hash.c
+++ b/mysys/hash.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/* The hash functions used for saveing keys */
/* One of key_length or key_length_offset must be given */
@@ -148,9 +147,7 @@ static uint calc_hashnr_caseup(const byte *key,uint length)
*
* The magic is in the interesting relationship between the special prime
* 16777619 (2^24 + 403) and 2^32 and 2^8.
- *
- * This hash produces the fewest collisions of any function that we've seen so
- * far, and works well on both numbers and strings.
+ * This works well on both numbers and strings.
*/
uint calc_hashnr(const byte *key, uint len)
@@ -517,8 +514,8 @@ my_bool hash_update(HASH *hash,byte *record,byte *old_key,uint old_key_length)
/* Search after record with key */
idx=hash_mask((*hash->calc_hashnr)(old_key,(old_key_length ?
- old_key_length :
- hash->key_length)),
+ old_key_length :
+ hash->key_length)),
blength,records);
new_index=hash_mask(rec_hashnr(hash,record),blength,records);
if (idx == new_index)
@@ -578,6 +575,18 @@ byte *hash_element(HASH *hash,uint idx)
}
+/*
+ Replace old row with new row. This should only be used when key
+ isn't changed
+*/
+
+void hash_replace(HASH *hash, uint idx, byte *new_row)
+{
+ if (idx != NO_RECORD) /* Safety */
+ dynamic_element(&hash->array,idx,HASH_LINK*)->data=new_row;
+}
+
+
#ifndef DBUG_OFF
my_bool hash_check(HASH *hash)
diff --git a/mysys/list.c b/mysys/list.c
index c9c863d4cc2..ac9e1b979a0 100644
--- a/mysys/list.c
+++ b/mysys/list.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/*
Code for handling dubble-linked lists in C
diff --git a/mysys/make-conf.c b/mysys/make-conf.c
index 9db766574e2..404299e1726 100644
--- a/mysys/make-conf.c
+++ b/mysys/make-conf.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/* make-conf.c
* make a charset .conf file out of a ctype-charset.c file.
@@ -34,7 +33,7 @@
#define CH_INCLUDE STRINGIZE(CH_SRC)
/* aaaah, that's better */
-#include <my_global.h>
+#include <my_my_global.h>
#include CH_INCLUDE
#include <stdio.h>
diff --git a/sql/md5.c b/mysys/md5.c
index 4c2e80107b8..5de95288141 100644
--- a/sql/md5.c
+++ b/mysys/md5.c
@@ -1,3 +1,19 @@
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
/* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
*/
@@ -28,7 +44,7 @@ documentation and/or software.
Replace of MD5_memset and MD5_memcpy with memset & memcpy
*/
-#include <global.h>
+#include <my_global.h>
#include <m_string.h>
#include "md5.h"
@@ -108,7 +124,7 @@ Rotation is separate from addition to prevent recomputation.
/* MD5 initialization. Begins an MD5 operation, writing a new context.
*/
-void MD5Init (MD5_CTX *context) /* context */
+void my_MD5Init (my_MD5_CTX *context) /* context */
{
context->count[0] = context->count[1] = 0;
/* Load magic initialization constants.
@@ -123,8 +139,9 @@ void MD5Init (MD5_CTX *context) /* context */
operation, processing another message block, and updating the
context.
*/
-void MD5Update (
-MD5_CTX *context, /* context */
+
+void my_MD5Update (
+my_MD5_CTX *context, /* context */
unsigned char *input, /* input block */
unsigned int inputLen) /* length of input block */
{
@@ -164,9 +181,10 @@ unsigned int inputLen) /* length of input block */
/* MD5 finalization. Ends an MD5 message-digest operation, writing the
the message digest and zeroizing the context.
*/
-void MD5Final (
+
+void my_MD5Final (
unsigned char digest[16], /* message digest */
-MD5_CTX *context) /* context */
+my_MD5_CTX *context) /* context */
{
unsigned char bits[8];
unsigned int idx, padLen;
@@ -178,10 +196,10 @@ MD5_CTX *context) /* context */
*/
idx = (unsigned int)((context->count[0] >> 3) & 0x3f);
padLen = (idx < 56) ? (56 - idx) : (120 - idx);
- MD5Update (context, PADDING, padLen);
+ my_MD5Update (context, PADDING, padLen);
/* Append length (before padding) */
- MD5Update (context, bits, 8);
+ my_MD5Update (context, bits, 8);
/* Store state in digest */
Encode (digest, context->state, 16);
diff --git a/mysys/mf_brkhant.c b/mysys/mf_brkhant.c
index debf5d9a712..4180bd6df66 100644
--- a/mysys/mf_brkhant.c
+++ b/mysys/mf_brkhant.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/* Dont let the user break when you are doing something important */
/* Remembers if it got 'SIGINT' and executes it on allow_break */
diff --git a/mysys/mf_cache.c b/mysys/mf_cache.c
index 85b6b19b328..2c5d8658625 100644
--- a/mysys/mf_cache.c
+++ b/mysys/mf_cache.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+/* Copyright (C) 2000 MySQL AB
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
- This library is distributed in the hope that it will be useful,
+ 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
- Library General Public License for more details.
+ 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 Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/* Open a temporary file and cache it with io_cache. Delete it on close */
diff --git a/mysys/mf_casecnv.c b/mysys/mf_casecnv.c
index 125f54b2594..0302688ad1f 100644
--- a/mysys/mf_casecnv.c
+++ b/mysys/mf_casecnv.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/*
Functions to convert to lover_case and to upper_case in scandinavia.
@@ -25,7 +24,9 @@
#include "mysys_priv.h"
#include <m_ctype.h>
+#ifndef SCO
#include <m_string.h>
+#endif
/* string to uppercase */
@@ -35,7 +36,7 @@ void caseup_str(my_string str)
if (use_mb(default_charset_info))
{
register uint32 l;
- register char *end=str+(uint) strlen(str);
+ register char *end=str+strlen(str);
while (*str)
{
if ((l=my_ismbchar(default_charset_info, str,end))) str+=l;
@@ -56,7 +57,7 @@ void casedn_str(my_string str)
if (use_mb(default_charset_info))
{
register uint32 l;
- register char *end=str+(uint) strlen(str);
+ register char *end=str+strlen(str);
while (*str)
{
if ((l=my_ismbchar(default_charset_info, str,end))) str+=l;
@@ -155,7 +156,7 @@ int my_strcasecmp(const char *s, const char *t)
if (use_mb(default_charset_info))
{
register uint32 l;
- register const char *end=s+(uint) strlen(s);
+ register const char *end=s+strlen(s);
while (s<end)
{
if ((l=my_ismbchar(default_charset_info, s,end)))
diff --git a/mysys/mf_dirname.c b/mysys/mf_dirname.c
index 399082a238b..6523abcdb12 100644
--- a/mysys/mf_dirname.c
+++ b/mysys/mf_dirname.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include "mysys_priv.h"
#include <m_string.h>
@@ -50,57 +49,70 @@ uint dirname_part(my_string to, const char *name)
DBUG_PRINT("enter",("'%s'",name));
length=dirname_length(name);
- (void) strmake(to,(char*) name,min(length,FN_REFLEN-2));
- convert_dirname(to); /* Convert chars */
+ convert_dirname(to, name, name+length);
DBUG_RETURN(length);
} /* dirname */
- /* convert dirname to use under this system */
- /* If MSDOS converts '/' to '\' */
- /* If VMS converts '<' to '[' and '>' to ']' */
- /* Adds a '/' to end if there isn't one and the last isn't a dev_char */
- /* ARGSUSED */
+ /*
+ Convert directory name to use under this system
+ If MSDOS converts '/' to '\'
+ If VMS converts '<' to '[' and '>' to ']'
+ Adds a FN_LIBCHAR to end if the result string if there isn't one
+ and the last isn't dev_char.
+ Copies data from 'from' until ASCII(0) for until from == from_end
+ If you want to use the whole 'from' string, just send NullS as the
+ last argument.
+ If the result string is larger than FN_REFLEN -1, then it's cut.
+
+ Returns pointer to end \0
+ */
#ifndef FN_DEVCHAR
#define FN_DEVCHAR '\0' /* For easier code */
#endif
-char *convert_dirname(my_string to)
+char *convert_dirname(char *to, const char *from, const char *from_end)
{
- reg1 char *pos;
-#ifdef FN_UPPER_CASE
- caseup_str(to);
-#endif
-#ifdef FN_LOWER_CASE
- casedn_str(to);
-#endif
-#if FN_LIBCHAR != '/'
- {
- pos=to-1; /* Change from '/' */
- while ((pos=strchr(pos+1,'/')) != 0)
- *pos=FN_LIBCHAR;
- }
-#endif
-#ifdef FN_C_BEFORE_DIR_2
+ char *to_org=to;
+
+ /* We use -2 here, becasue we need place for the last FN_LIBCHAR */
+ if (!from_end || (from_end - from) > FN_REFLEN-2)
+ from_end=from+FN_REFLEN -2;
+
+#if FN_LIBCHAR != '/' || defined(FN_C_BEFORE_DIR_2)
{
- for (pos=to ; *pos ; pos++)
+ for (; *from && from != from_end; from++)
{
- if (*pos == FN_C_BEFORE_DIR_2)
- *pos=FN_C_BEFORE_DIR;
- if (*pos == FN_C_AFTER_DIR_2)
- *pos=FN_C_AFTER_DIR;
+ if (*from == '/')
+ *to++= FN_LIBCHAR;
+#ifdef FN_C_BEFORE_DIR_2
+ else if (*from == FN_C_BEFORE_DIR_2)
+ *to++= FN_C_BEFORE_DIR;
+ else if (*from == FN_C_AFTER_DIR_2)
+ *to++= FN_C_AFTER_DIR;
+#endif
+ else
+ *to++= *from;
}
+ *to=0;
}
#else
- { /* Append FN_LIBCHAR if not there */
- pos=strend(to);
- if (pos != to && (pos[-1] != FN_LIBCHAR && pos[-1] != FN_DEVCHAR))
- {
- *pos++=FN_LIBCHAR;
- *pos=0;
- }
+ /* This is ok even if to == from, becasue we need to cut the string */
+ to= strmake(to, from, (uint) (from_end-from));
+#endif
+
+ /* Add FN_LIBCHAR to the end of directory path */
+ if (to != to_org && (to[-1] != FN_LIBCHAR && to[-1] != FN_DEVCHAR))
+ {
+ *to++=FN_LIBCHAR;
+ *to=0;
}
+#ifdef FN_UPPER_CASE
+ caseup_str(to_org);
+#endif
+#ifdef FN_LOWER_CASE
+ casedn_str(to_org);
#endif
- return pos; /* Pointer to end of dir */
+ return to; /* Pointer to end of dir */
} /* convert_dirname */
diff --git a/mysys/mf_fn_ext.c b/mysys/mf_fn_ext.c
index 6a9b9d18341..fb3fd8870aa 100644
--- a/mysys/mf_fn_ext.c
+++ b/mysys/mf_fn_ext.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/* Returnerar en pekare till filnamnets extension. */
diff --git a/mysys/mf_format.c b/mysys/mf_format.c
index 7dac46cf0d0..ab1904da162 100644
--- a/mysys/mf_format.c
+++ b/mysys/mf_format.c
@@ -1,94 +1,84 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include "mysys_priv.h"
#include <m_string.h>
-#ifdef HAVE_REALPATH
-#include <sys/param.h>
-#include <sys/stat.h>
-#endif
- /* format a filename with replace of library and extension */
- /* params to and name may be identicall */
- /* function doesn't change name if name != to */
- /* Flag may be: 1 replace filenames library with 'dsk' */
- /* 2 replace extension with 'form' */
- /* 4 Unpack filename (replace ~ with home) */
- /* 8 Pack filename as short as possibly */
- /* 16 Resolve symbolic links for filename */
- /* 32 Resolve filename to full path */
- /* 64 Return NULL if too long path */
+ /*
+ Formats a filename with possible replace of directory of extension
+ Function can handle the case where 'to' == 'name'
+ For a description of the flag values, consult my_sys.h
+ The arguments should be in unix format.
+ */
-#ifdef SCO
-#define BUFF_LEN 4097
-#else
-#ifdef MAXPATHLEN
-#define BUFF_LEN MAXPATHLEN
-#else
-#define BUFF_LEN FN_LEN
-#endif
-#endif
-my_string fn_format(my_string to, const char *name, const char *dsk,
- const char *form, int flag)
+my_string fn_format(my_string to, const char *name, const char *dir,
+ const char *extension, uint flag)
{
reg1 uint length;
- char dev[FN_REFLEN], buff[BUFF_LEN], *pos, *startpos;
+ char dev[FN_REFLEN], buff[FN_REFLEN], *pos, *startpos;
const char *ext;
DBUG_ENTER("fn_format");
- DBUG_PRINT("enter",("name: %s dsk: %s form: %s flag: %d",
- name,dsk,form,flag));
+ DBUG_PRINT("enter",("name: %s dir: %s extension: %s flag: %d",
+ name,dir,extension,flag));
- /* Kopiera & skippa enheten */
+ /* Copy and skip directory */
name+=(length=dirname_part(dev,(startpos=(my_string) name)));
- if (length == 0 || flag & 1)
+ if (length == 0 || (flag & MY_REPLACE_DIR))
{
- (void) strmake(dev,dsk, sizeof(dev) - 2);
- /* Use given directory */
- convert_dirname(dev); /* Fix to this OS */
+ /* Use given directory */
+ convert_dirname(dev,dir,NullS); /* Fix to this OS */
}
- if (flag & 8)
+ else if ((flag & MY_RELATIVE_PATH) && !test_if_hard_path(name))
+ {
+ /* Put 'dir' before the given path */
+ strmake(buff,dev,sizeof(buff)-1);
+ pos=convert_dirname(dev,dir,NullS);
+ strmake(pos,buff,sizeof(buff)-1- (int) (pos-dev));
+ }
+
+ if (flag & MY_PACK_FILENAME)
pack_dirname(dev,dev); /* Put in ./.. and ~/.. */
- if (flag & 4)
+ if (flag & MY_UNPACK_FILENAME)
(void) unpack_dirname(dev,dev); /* Replace ~/.. with dir */
- if ((pos=(char*)strchr(name,FN_EXTCHAR)) != NullS)
+ if ((pos= (char*) strchr(name,FN_EXTCHAR)) != NullS)
{
- if ((flag & 2) == 0) /* Skall vi byta extension ? */
+ if ((flag & MY_REPLACE_EXT) == 0) /* If we should keep old ext */
{
- length=strlength(name); /* Old extension */
+ length=strlength(name); /* Use old extension */
ext = "";
}
else
{
length=(uint) (pos-(char*) name); /* Change extension */
- ext= form;
+ ext= extension;
}
}
else
{
- length=strlength(name); /* Har ingen ext- tag nya */
- ext=form;
+ length=strlength(name); /* No ext, use the now one */
+ ext=extension;
}
if (strlen(dev)+length+strlen(ext) >= FN_REFLEN || length >= FN_LEN )
- { /* To long path, return original */
+ {
+ /* To long path, return original or NULL */
uint tmp_length;
- if (flag & 64)
- return 0;
+ if (flag & MY_SAFE_PATH)
+ return NullS;
tmp_length=strlength(startpos);
DBUG_PRINT("error",("dev: '%s' ext: '%s' length: %d",dev,ext,length));
(void) strmake(to,startpos,min(tmp_length,FN_REFLEN-1));
@@ -109,18 +99,18 @@ my_string fn_format(my_string to, const char *name, const char *dsk,
#endif
(void) strmov(pos,ext); /* Don't convert extension */
}
- /* Purify gives a lot of UMR errors when using realpath */
-#if defined(HAVE_REALPATH) && !defined(HAVE_purify) && !defined(HAVE_BROKEN_REALPATH)
- if (flag & 16)
+ /*
+ If MY_RETURN_REAL_PATH and MY_RESOLVE_SYMLINK is given, only do
+ realpath if the file is a symbolic link
+ */
+ if (flag & MY_RETURN_REAL_PATH)
+ (void) my_realpath(to, to, MYF(flag & MY_RESOLVE_SYMLINKS ?
+ MY_RESOLVE_LINK: 0));
+ else if (flag & MY_RESOLVE_SYMLINKS)
{
- struct stat stat_buff;
- if (flag & 32 || (!lstat(to,&stat_buff) && S_ISLNK(stat_buff.st_mode)))
- {
- if (realpath(to,buff))
- strmake(to,buff,FN_REFLEN-1);
- }
+ strmov(buff,to);
+ (void) my_readlink(to, buff, MYF(0));
}
-#endif
DBUG_RETURN (to);
} /* fn_format */
diff --git a/mysys/mf_getdate.c b/mysys/mf_getdate.c
index f01d1d7633a..189d43e782a 100644
--- a/mysys/mf_getdate.c
+++ b/mysys/mf_getdate.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/* Get date in a printable form: yyyy-mm-dd hh:mm:ss */
diff --git a/mysys/mf_iocache.c b/mysys/mf_iocache.c
index 0d1c227c2b2..872757f77c5 100644
--- a/mysys/mf_iocache.c
+++ b/mysys/mf_iocache.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/*
Cashing of files with only does (sequential) read or writes of fixed-
@@ -23,12 +22,30 @@
Possibly use of asyncronic io.
macros for read and writes for faster io.
Used instead of FILE when reading or writing whole files.
- This will make mf_rec_cache obsolete.
+ This code makes mf_rec_cache obsolete (currently only used by ISAM)
One can change info->pos_in_file to a higher value to skip bytes in file if
- also info->rc_pos is set to info->rc_end.
+ also info->read_pos is set to info->read_end.
If called through open_cached_file(), then the temporary file will
only be created if a write exeeds the file buffer or if one calls
- flush_io_cache().
+ flush_io_cache().
+
+ If one uses SEQ_READ_APPEND, then two buffers are allocated, one for
+ reading and another for writing. Reads are first done from disk and
+ then done from the write buffer. This is an efficient way to read
+ from a log file when one is writing to it at the same time.
+ For this to work, the file has to be opened in append mode!
+ Note that when one uses SEQ_READ_APPEND, one MUST write using
+ my_b_append ! This is needed because we need to lock the mutex
+ every time we access the write buffer.
+
+TODO:
+ When one SEQ_READ_APPEND and we are reading and writing at the same time,
+ each time the write buffer gets full and it's written to disk, we will
+ always do a disk read to read a part of the buffer from disk to the
+ read buffer.
+ This should be fixed so that when we do a flush_io_cache() and
+ we have been reading the write buffer, we should transfer the rest of the
+ write buffer to the read buffer before we start to reuse it.
*/
#define MAP_TO_USE_RAID
@@ -36,10 +53,54 @@
#include <m_string.h>
#ifdef HAVE_AIOWAIT
#include "mysys_err.h"
-#include <errno.h>
static void my_aiowait(my_aio_result *result);
#endif
+#include <assert.h>
+#include <errno.h>
+
+#ifdef THREAD
+#define lock_append_buffer(info) \
+ pthread_mutex_lock(&(info)->append_buffer_lock)
+#define unlock_append_buffer(info) \
+ pthread_mutex_unlock(&(info)->append_buffer_lock)
+#else
+#define lock_append_buffer(info)
+#define unlock_append_buffer(info)
+#endif
+
+static void
+init_functions(IO_CACHE* info, enum cache_type type)
+{
+ switch (type) {
+ case READ_NET:
+ /* must be initialized by the caller. The problem is that
+ _my_b_net_read has to be defined in sql directory because of
+ the dependency on THD, and therefore cannot be visible to
+ programs that link against mysys but know nothing about THD, such
+ as myisamchk
+ */
+ break;
+ case SEQ_READ_APPEND:
+ info->read_function = _my_b_seq_read;
+ info->write_function = 0; /* Force a core if used */
+ break;
+ default:
+ info->read_function = _my_b_read;
+ info->write_function = _my_b_write;
+ }
+ /* Ensure that my_b_tell() and my_b_bytes_in_cache works */
+ if (type == WRITE_CACHE)
+ {
+ info->current_pos= &info->write_pos;
+ info->current_end= &info->write_end;
+ }
+ else
+ {
+ info->current_pos= &info->read_pos;
+ info->current_end= &info->read_end;
+ }
+}
/*
** if cachesize == 0 then use default cachesize (from s-file)
@@ -52,70 +113,95 @@ int init_io_cache(IO_CACHE *info, File file, uint cachesize,
pbool use_async_io, myf cache_myflags)
{
uint min_cache;
+ my_off_t end_of_file= ~(my_off_t) 0;
DBUG_ENTER("init_io_cache");
DBUG_PRINT("enter",("type: %d pos: %ld",(int) type, (ulong) seek_offset));
- info->file=file;
+ info->file= file;
+ info->type=type;
+ info->pos_in_file= seek_offset;
+ info->pre_close = info->pre_read = info->post_read = 0;
+ info->arg = 0;
+ info->init_count++; /* we assume the user had set it to 0 prior to
+ first call */
+ info->alloced_buffer = 0;
+ info->buffer=0;
+ info->seek_not_done= test(file >= 0);
+
if (!cachesize)
if (! (cachesize= my_default_record_cache_size))
DBUG_RETURN(1); /* No cache requested */
min_cache=use_async_io ? IO_SIZE*4 : IO_SIZE*2;
- if (type == READ_CACHE)
+ if (type == READ_CACHE || type == SEQ_READ_APPEND)
{ /* Assume file isn't growing */
- if (cache_myflags & MY_DONT_CHECK_FILESIZE)
- {
- cache_myflags &= ~MY_DONT_CHECK_FILESIZE;
- }
- else
+ if (!(cache_myflags & MY_DONT_CHECK_FILESIZE))
{
- my_off_t file_pos,end_of_file;
- if ((file_pos=my_tell(file,MYF(0)) == MY_FILEPOS_ERROR))
- DBUG_RETURN(1);
+ /* Calculate end of file to not allocate to big buffers */
end_of_file=my_seek(file,0L,MY_SEEK_END,MYF(0));
if (end_of_file < seek_offset)
end_of_file=seek_offset;
- VOID(my_seek(file,file_pos,MY_SEEK_SET,MYF(0)));
+ /* Trim cache size if the file is very small */
if ((my_off_t) cachesize > end_of_file-seek_offset+IO_SIZE*2-1)
{
cachesize=(uint) (end_of_file-seek_offset)+IO_SIZE*2-1;
- use_async_io=0; /* No nead to use async */
+ use_async_io=0; /* No need to use async */
}
}
}
-
- for (;;)
+ cache_myflags &= ~MY_DONT_CHECK_FILESIZE;
+ if (type != READ_NET && type != WRITE_NET)
{
- cachesize=(uint) ((ulong) (cachesize + min_cache-1) &
- (ulong) ~(min_cache-1));
- if (cachesize < min_cache)
- cachesize = min_cache;
- if ((info->buffer=
- (byte*) my_malloc(cachesize,
- MYF((cache_myflags & ~ MY_WME) |
- (cachesize == min_cache ? MY_WME : 0)))) != 0)
- break; /* Enough memory found */
- if (cachesize == min_cache)
- DBUG_RETURN(2); /* Can't alloc cache */
- cachesize= (uint) ((long) cachesize*3/4); /* Try with less memory */
- }
- info->pos_in_file=seek_offset;
+ /* Retry allocating memory in smaller blocks until we get one */
+ for (;;)
+ {
+ uint buffer_block;
+ cachesize=(uint) ((ulong) (cachesize + min_cache-1) &
+ (ulong) ~(min_cache-1));
+ if (cachesize < min_cache)
+ cachesize = min_cache;
+ buffer_block = cachesize;
+ if (type == SEQ_READ_APPEND)
+ buffer_block *= 2;
+ if ((info->buffer=
+ (byte*) my_malloc(buffer_block,
+ MYF((cache_myflags & ~ MY_WME) |
+ (cachesize == min_cache ? MY_WME : 0)))) != 0)
+ {
+ info->write_buffer=info->buffer;
+ if (type == SEQ_READ_APPEND)
+ info->write_buffer = info->buffer + cachesize;
+ info->alloced_buffer=1;
+ break; /* Enough memory found */
+ }
+ if (cachesize == min_cache)
+ DBUG_RETURN(2); /* Can't alloc cache */
+ cachesize= (uint) ((long) cachesize*3/4); /* Try with less memory */
+ }
+ }
+
+ DBUG_PRINT("info",("init_io_cache: cachesize = %u",cachesize));
info->read_length=info->buffer_length=cachesize;
- info->seek_not_done= test(file >= 0); /* Seek not done */
info->myflags=cache_myflags & ~(MY_NABP | MY_FNABP);
- info->rc_request_pos=info->rc_pos=info->buffer;
-
- if (type == READ_CACHE)
- {
- info->rc_end=info->buffer; /* Nothing in cache */
- }
- else /* type == WRITE_CACHE */
+ info->request_pos= info->read_pos= info->write_pos = info->buffer;
+ if (type == SEQ_READ_APPEND)
{
- info->rc_end=info->buffer+info->buffer_length- (seek_offset & (IO_SIZE-1));
+ info->append_read_pos = info->write_pos = info->write_buffer;
+ info->write_end = info->write_buffer + info->buffer_length;
+#ifdef THREAD
+ pthread_mutex_init(&info->append_buffer_lock,MY_MUTEX_INIT_FAST);
+#endif
}
- info->end_of_file=MY_FILEPOS_ERROR; /* May be changed by user */
- info->type=type;
+
+ if (type == WRITE_CACHE)
+ info->write_end=
+ info->buffer+info->buffer_length- (seek_offset & (IO_SIZE-1));
+ else
+ info->read_end=info->buffer; /* Nothing in cache */
+
+ /* End_of_file may be changed by user later */
+ info->end_of_file= end_of_file;
info->error=0;
- info->read_function=_my_b_read;
+ init_functions(info,type);
#ifdef HAVE_AIOWAIT
if (use_async_io && ! my_disable_async_io)
{
@@ -156,8 +242,13 @@ static void my_aiowait(my_aio_result *result)
}
#endif
- /* Use this to reset cache to start or other type */
- /* Some simple optimizing is done when reinit in current buffer */
+
+/*
+ Use this to reset cache to re-start reading or to change the type
+ between READ_CACHE <-> WRITE_CACHE
+ If we are doing a reinit of a cache where we have the start of the file
+ in the cache, we are reusing this memory without flushing it to disk.
+*/
my_bool reinit_io_cache(IO_CACHE *info, enum cache_type type,
my_off_t seek_offset,
@@ -165,47 +256,71 @@ my_bool reinit_io_cache(IO_CACHE *info, enum cache_type type,
pbool clear_cache)
{
DBUG_ENTER("reinit_io_cache");
+ DBUG_PRINT("enter",("type: %d seek_offset: %lu clear_cache: %d",
+ type, (ulong) seek_offset, (int) clear_cache));
- info->seek_not_done= test(info->file >= 0); /* Seek not done */
+ /* One can't do reinit with the following types */
+ DBUG_ASSERT(type != READ_NET && info->type != READ_NET &&
+ type != WRITE_NET && info->type != WRITE_NET &&
+ type != SEQ_READ_APPEND && info->type != SEQ_READ_APPEND);
+
+ /* If the whole file is in memory, avoid flushing to disk */
if (! clear_cache &&
seek_offset >= info->pos_in_file &&
- seek_offset <= info->pos_in_file +
- (uint) (info->rc_end - info->rc_request_pos))
- { /* use current buffer */
+ seek_offset <= my_b_tell(info))
+ {
+ /* Reuse current buffer without flushing it to disk */
+ byte *pos;
if (info->type == WRITE_CACHE && type == READ_CACHE)
{
- info->rc_end=info->rc_pos;
+ info->read_end=info->write_pos;
info->end_of_file=my_b_tell(info);
}
- else if (info->type == READ_CACHE && type == WRITE_CACHE)
- info->rc_end=info->buffer+info->buffer_length;
- info->rc_pos=info->rc_request_pos+(seek_offset-info->pos_in_file);
+ else if (type == WRITE_CACHE)
+ {
+ if (info->type == READ_CACHE)
+ info->write_end=info->write_buffer+info->buffer_length;
+ info->end_of_file = ~(my_off_t) 0;
+ }
+ pos=info->request_pos+(seek_offset-info->pos_in_file);
+ if (type == WRITE_CACHE)
+ info->write_pos=pos;
+ else
+ info->read_pos= pos;
#ifdef HAVE_AIOWAIT
my_aiowait(&info->aio_result); /* Wait for outstanding req */
#endif
}
else
{
+ /*
+ If we change from WRITE_CACHE to READ_CACHE, assume that everything
+ after the current positions should be ignored
+ */
if (info->type == WRITE_CACHE && type == READ_CACHE)
info->end_of_file=my_b_tell(info);
- if (flush_io_cache(info))
+ /* flush cache if we want to reuse it */
+ if (!clear_cache && flush_io_cache(info))
DBUG_RETURN(1);
info->pos_in_file=seek_offset;
- info->rc_request_pos=info->rc_pos=info->buffer;
+ /* Better to do always do a seek */
+ info->seek_not_done=1;
+ info->request_pos=info->read_pos=info->write_pos=info->buffer;
if (type == READ_CACHE)
{
- info->rc_end=info->buffer; /* Nothing in cache */
+ info->read_end=info->buffer; /* Nothing in cache */
}
else
{
- info->rc_end=info->buffer+info->buffer_length-
- (seek_offset & (IO_SIZE-1));
- info->end_of_file=MY_FILEPOS_ERROR; /* May be changed by user */
+ info->write_end=(info->buffer + info->buffer_length -
+ (seek_offset & (IO_SIZE-1)));
+ info->end_of_file= ~(my_off_t) 0;
}
}
info->type=type;
info->error=0;
- info->read_function=_my_b_read;
+ init_functions(info,type);
+
#ifdef HAVE_AIOWAIT
if (use_async_io && ! my_disable_async_io &&
((ulong) info->buffer_length <
@@ -217,23 +332,34 @@ my_bool reinit_io_cache(IO_CACHE *info, enum cache_type type,
info->inited=0;
#endif
DBUG_RETURN(0);
-} /* init_io_cache */
+} /* reinit_io_cache */
- /* Read buffered. Returns 1 if can't read requested characters */
- /* Returns 0 if record read */
+/*
+ Read buffered. Returns 1 if can't read requested characters
+ This function is only called from the my_b_read() macro
+ when there isn't enough characters in the buffer to
+ satisfy the request.
+ Returns 0 we succeeded in reading all data
+*/
int _my_b_read(register IO_CACHE *info, byte *Buffer, uint Count)
{
uint length,diff_length,left_length;
my_off_t max_length, pos_in_file;
+ DBUG_ENTER("_my_b_read");
- memcpy(Buffer,info->rc_pos,
- (size_t) (left_length=(uint) (info->rc_end-info->rc_pos)));
- Buffer+=left_length;
- Count-=left_length;
- pos_in_file=info->pos_in_file+(uint) (info->rc_end - info->buffer);
+ if ((left_length=(uint) (info->read_end-info->read_pos)))
+ {
+ DBUG_ASSERT(Count >= left_length); /* User is not using my_b_read() */
+ memcpy(Buffer,info->read_pos, (size_t) (left_length));
+ Buffer+=left_length;
+ Count-=left_length;
+ }
+
+ /* pos_in_file always point on where info->buffer was read */
+ pos_in_file=info->pos_in_file+(uint) (info->read_end - info->buffer);
if (info->seek_not_done)
{ /* File touched, do seek */
VOID(my_seek(info->file,pos_in_file,MY_SEEK_SET,MYF(0)));
@@ -246,7 +372,7 @@ int _my_b_read(register IO_CACHE *info, byte *Buffer, uint Count)
if (info->end_of_file == pos_in_file)
{ /* End of file */
info->error=(int) left_length;
- return 1;
+ DBUG_RETURN(1);
}
length=(Count & (uint) ~(IO_SIZE-1))-diff_length;
if ((read_length=my_read(info->file,Buffer,(uint) length,info->myflags))
@@ -254,7 +380,7 @@ int _my_b_read(register IO_CACHE *info, byte *Buffer, uint Count)
{
info->error= read_length == (uint) -1 ? -1 :
(int) (read_length+left_length);
- return 1;
+ DBUG_RETURN(1);
}
Count-=length;
Buffer+=length;
@@ -262,16 +388,17 @@ int _my_b_read(register IO_CACHE *info, byte *Buffer, uint Count)
left_length+=length;
diff_length=0;
}
- max_length=info->end_of_file - pos_in_file;
- if (max_length > info->read_length-diff_length)
- max_length=info->read_length-diff_length;
+ max_length=info->read_length-diff_length;
+ if (info->type != READ_FIFO &&
+ max_length > (info->end_of_file - pos_in_file))
+ max_length = info->end_of_file - pos_in_file;
if (!max_length)
{
if (Count)
{
info->error= left_length; /* We only got this many char */
- return 1;
+ DBUG_RETURN(1);
}
length=0; /* Didn't read any chars */
}
@@ -282,13 +409,160 @@ int _my_b_read(register IO_CACHE *info, byte *Buffer, uint Count)
if (length != (uint) -1)
memcpy(Buffer,info->buffer,(size_t) length);
info->error= length == (uint) -1 ? -1 : (int) (length+left_length);
- return 1;
+ info->read_pos=info->read_end=info->buffer;
+ DBUG_RETURN(1);
}
- info->rc_pos=info->buffer+Count;
- info->rc_end=info->buffer+length;
+ info->read_pos=info->buffer+Count;
+ info->read_end=info->buffer+length;
+ info->pos_in_file=pos_in_file;
+ memcpy(Buffer,info->buffer,(size_t) Count);
+ DBUG_RETURN(0);
+}
+
+/*
+ Do sequential read from the SEQ_READ_APPEND cache
+ we do this in three stages:
+ - first read from info->buffer
+ - then if there are still data to read, try the file descriptor
+ - afterwards, if there are still data to read, try append buffer
+*/
+
+int _my_b_seq_read(register IO_CACHE *info, byte *Buffer, uint Count)
+{
+ uint length,diff_length,left_length,save_count;
+ my_off_t max_length, pos_in_file;
+ save_count=Count;
+
+ /* first, read the regular buffer */
+ if ((left_length=(uint) (info->read_end-info->read_pos)))
+ {
+ DBUG_ASSERT(Count > left_length); /* User is not using my_b_read() */
+ memcpy(Buffer,info->read_pos, (size_t) (left_length));
+ Buffer+=left_length;
+ Count-=left_length;
+ }
+ lock_append_buffer(info);
+
+ /* pos_in_file always point on where info->buffer was read */
+ if ((pos_in_file=info->pos_in_file+(uint) (info->read_end - info->buffer)) >=
+ info->end_of_file)
+ goto read_append_buffer;
+
+ /*
+ With read-append cache we must always do a seek before we read,
+ because the write could have moved the file pointer astray
+ */
+ VOID(my_seek(info->file,pos_in_file,MY_SEEK_SET,MYF(0)));
+ info->seek_not_done=0;
+
+ diff_length=(uint) (pos_in_file & (IO_SIZE-1));
+
+ /* now the second stage begins - read from file descriptor */
+ if (Count >= (uint) (IO_SIZE+(IO_SIZE-diff_length)))
+ { /* Fill first intern buffer */
+ uint read_length;
+
+ length=(Count & (uint) ~(IO_SIZE-1))-diff_length;
+ if ((read_length=my_read(info->file,Buffer,(uint) length,info->myflags)) ==
+ (uint)-1)
+ {
+ info->error= -1;
+ unlock_append_buffer(info);
+ return 1;
+ }
+ Count-=read_length;
+ Buffer+=read_length;
+ pos_in_file+=read_length;
+
+ if (read_length != (uint) length)
+ {
+ /*
+ We only got part of data; Read the rest of the data from the
+ write buffer
+ */
+ goto read_append_buffer;
+ }
+ left_length+=length;
+ diff_length=0;
+ }
+
+ max_length=info->read_length-diff_length;
+ if (max_length > (info->end_of_file - pos_in_file))
+ max_length = info->end_of_file - pos_in_file;
+ if (!max_length)
+ {
+ if (Count)
+ goto read_append_buffer;
+ length=0; /* Didn't read any more chars */
+ }
+ else
+ {
+ length=my_read(info->file,info->buffer,(uint) max_length,
+ info->myflags);
+ if (length == (uint) -1)
+ {
+ info->error= -1;
+ unlock_append_buffer(info);
+ return 1;
+ }
+ if (length < Count)
+ {
+ memcpy(Buffer,info->buffer,(size_t) length);
+ Count -= length;
+ Buffer += length;
+
+ /*
+ added the line below to make
+ DBUG_ASSERT(pos_in_file==info->end_of_file) pass.
+ otherwise this does not appear to be needed
+ */
+ pos_in_file += length;
+ goto read_append_buffer;
+ }
+ }
+ unlock_append_buffer(info);
+ info->read_pos=info->buffer+Count;
+ info->read_end=info->buffer+length;
info->pos_in_file=pos_in_file;
memcpy(Buffer,info->buffer,(size_t) Count);
return 0;
+
+read_append_buffer:
+
+ /*
+ Read data from the current write buffer.
+ Count should never be == 0 here (The code will work even if count is 0)
+ */
+
+ {
+ /* First copy the data to Count */
+ uint len_in_buff = (uint) (info->write_pos - info->append_read_pos);
+ uint copy_len;
+ uint transfer_len;
+
+ DBUG_ASSERT(info->append_read_pos <= info->write_pos);
+ /*
+ TODO: figure out if the assert below is needed or correct.
+ */
+ DBUG_ASSERT(pos_in_file == info->end_of_file);
+ copy_len=min(Count, len_in_buff);
+ memcpy(Buffer, info->append_read_pos, copy_len);
+ info->append_read_pos += copy_len;
+ Count -= copy_len;
+ if (Count)
+ info->error = save_count - Count;
+
+ /* Fill read buffer with data from write buffer */
+ memcpy(info->buffer, info->append_read_pos,
+ (size_t) (transfer_len=len_in_buff - copy_len));
+ info->read_pos= info->buffer;
+ info->read_end= info->buffer+transfer_len;
+ info->append_read_pos=info->write_pos;
+ info->pos_in_file=pos_in_file+copy_len;
+ info->end_of_file+=len_in_buff;
+ }
+ unlock_append_buffer(info);
+ return Count ? 1 : 0;
}
@@ -301,8 +575,8 @@ int _my_b_async_read(register IO_CACHE *info, byte *Buffer, uint Count)
my_off_t next_pos_in_file;
byte *read_buffer;
- memcpy(Buffer,info->rc_pos,
- (size_t) (left_length=(uint) (info->rc_end-info->rc_pos)));
+ memcpy(Buffer,info->read_pos,
+ (size_t) (left_length=(uint) (info->read_end-info->read_pos)));
Buffer+=left_length;
org_Count=Count;
Count-=left_length;
@@ -329,13 +603,13 @@ int _my_b_async_read(register IO_CACHE *info, byte *Buffer, uint Count)
(int) (read_length+left_length));
return(1);
}
- info->pos_in_file+=(uint) (info->rc_end - info->rc_request_pos);
+ info->pos_in_file+=(uint) (info->read_end - info->request_pos);
- if (info->rc_request_pos != info->buffer)
- info->rc_request_pos=info->buffer;
+ if (info->request_pos != info->buffer)
+ info->request_pos=info->buffer;
else
- info->rc_request_pos=info->buffer+info->read_length;
- info->rc_pos=info->rc_request_pos;
+ info->request_pos=info->buffer+info->read_length;
+ info->read_pos=info->request_pos;
next_pos_in_file=info->aio_read_pos+read_length;
/* Check if pos_in_file is changed
@@ -352,8 +626,8 @@ int _my_b_async_read(register IO_CACHE *info, byte *Buffer, uint Count)
{
my_off_t offset= (info->pos_in_file - info->aio_read_pos);
info->pos_in_file=info->aio_read_pos; /* Whe are here */
- info->rc_pos=info->rc_request_pos+offset;
- read_length-=offset; /* Bytes left from rc_pos */
+ info->read_pos=info->request_pos+offset;
+ read_length-=offset; /* Bytes left from read_pos */
}
}
#ifndef DBUG_OFF
@@ -365,16 +639,16 @@ int _my_b_async_read(register IO_CACHE *info, byte *Buffer, uint Count)
#endif
/* Copy found bytes to buffer */
length=min(Count,read_length);
- memcpy(Buffer,info->rc_pos,(size_t) length);
+ memcpy(Buffer,info->read_pos,(size_t) length);
Buffer+=length;
Count-=length;
left_length+=length;
- info->rc_end=info->rc_pos+read_length;
- info->rc_pos+=length;
+ info->read_end=info->rc_pos+read_length;
+ info->read_pos+=length;
}
else
next_pos_in_file=(info->pos_in_file+ (uint)
- (info->rc_end - info->rc_request_pos));
+ (info->read_end - info->request_pos));
/* If reading large blocks, or first read or read with skipp */
if (Count)
@@ -388,13 +662,13 @@ int _my_b_async_read(register IO_CACHE *info, byte *Buffer, uint Count)
read_length=IO_SIZE*2- (uint) (next_pos_in_file & (IO_SIZE-1));
if (Count < read_length)
{ /* Small block, read to cache */
- if ((read_length=my_read(info->file,info->rc_request_pos,
+ if ((read_length=my_read(info->file,info->request_pos,
read_length, info->myflags)) == (uint) -1)
return info->error= -1;
use_length=min(Count,read_length);
- memcpy(Buffer,info->rc_request_pos,(size_t) use_length);
- info->rc_pos=info->rc_request_pos+Count;
- info->rc_end=info->rc_request_pos+read_length;
+ memcpy(Buffer,info->request_pos,(size_t) use_length);
+ info->read_pos=info->request_pos+Count;
+ info->read_end=info->request_pos+read_length;
info->pos_in_file=next_pos_in_file; /* Start of block in cache */
next_pos_in_file+=read_length;
@@ -415,7 +689,7 @@ int _my_b_async_read(register IO_CACHE *info, byte *Buffer, uint Count)
info->error= read_length == (uint) -1 ? -1 : read_length+left_length;
return 1;
}
- info->rc_pos=info->rc_end=info->rc_request_pos;
+ info->read_pos=info->read_end=info->request_pos;
info->pos_in_file=(next_pos_in_file+=Count);
}
}
@@ -426,7 +700,7 @@ int _my_b_async_read(register IO_CACHE *info, byte *Buffer, uint Count)
if (max_length > (my_off_t) info->read_length - diff_length)
max_length= (my_off_t) info->read_length - diff_length;
- if (info->rc_request_pos != info->buffer)
+ if (info->request_pos != info->buffer)
read_buffer=info->buffer;
else
read_buffer=info->buffer+info->read_length;
@@ -443,13 +717,13 @@ int _my_b_async_read(register IO_CACHE *info, byte *Buffer, uint Count)
my_errno=errno;
DBUG_PRINT("error",("got error: %d, aio_result: %d from aioread, async skipped",
errno, info->aio_result.result.aio_errno));
- if (info->rc_request_pos != info->buffer)
+ if (info->request_pos != info->buffer)
{
- bmove(info->buffer,info->rc_request_pos,
- (uint) (info->rc_end - info->rc_pos));
- info->rc_request_pos=info->buffer;
- info->rc_pos-=info->read_length;
- info->rc_end-=info->read_length;
+ bmove(info->buffer,info->request_pos,
+ (uint) (info->read_end - info->read_pos));
+ info->request_pos=info->buffer;
+ info->read_pos-=info->read_length;
+ info->read_end-=info->read_length;
}
info->read_length=info->buffer_length; /* Use hole buffer */
info->read_function=_my_b_read; /* Use normal IO_READ next */
@@ -467,8 +741,13 @@ int _my_b_async_read(register IO_CACHE *info, byte *Buffer, uint Count)
int _my_b_get(IO_CACHE *info)
{
byte buff;
+ IO_CACHE_CALLBACK pre_read,post_read;
+ if ((pre_read = info->pre_read))
+ (*pre_read)(info);
if ((*(info)->read_function)(info,&buff,1))
return my_b_EOF;
+ if ((post_read = info->post_read))
+ (*post_read)(info);
return (int) (uchar) buff;
}
@@ -478,11 +757,17 @@ int _my_b_write(register IO_CACHE *info, const byte *Buffer, uint Count)
{
uint rest_length,length;
- rest_length=(uint) (info->rc_end - info->rc_pos);
- memcpy(info->rc_pos,Buffer,(size_t) rest_length);
+ if (info->pos_in_file+info->buffer_length > info->end_of_file)
+ {
+ my_errno=errno=EFBIG;
+ return info->error = -1;
+ }
+
+ rest_length=(uint) (info->write_end - info->write_pos);
+ memcpy(info->write_pos,Buffer,(size_t) rest_length);
Buffer+=rest_length;
Count-=rest_length;
- info->rc_pos+=rest_length;
+ info->write_pos+=rest_length;
if (flush_io_cache(info))
return 1;
if (Count >= IO_SIZE)
@@ -499,8 +784,52 @@ int _my_b_write(register IO_CACHE *info, const byte *Buffer, uint Count)
Buffer+=length;
info->pos_in_file+=length;
}
- memcpy(info->rc_pos,Buffer,(size_t) Count);
- info->rc_pos+=Count;
+ memcpy(info->write_pos,Buffer,(size_t) Count);
+ info->write_pos+=Count;
+ return 0;
+}
+
+
+/*
+ Append a block to the write buffer.
+ This is done with the buffer locked to ensure that we don't read from
+ the write buffer before we are ready with it.
+*/
+
+int my_b_append(register IO_CACHE *info, const byte *Buffer, uint Count)
+{
+ uint rest_length,length;
+
+ lock_append_buffer(info);
+ rest_length=(uint) (info->write_end - info->write_pos);
+ if (Count <= rest_length)
+ goto end;
+ memcpy(info->write_pos,Buffer,(size_t) rest_length);
+ Buffer+=rest_length;
+ Count-=rest_length;
+ info->write_pos+=rest_length;
+ if (_flush_io_cache(info,0))
+ {
+ unlock_append_buffer(info);
+ return 1;
+ }
+ if (Count >= IO_SIZE)
+ { /* Fill first intern buffer */
+ length=Count & (uint) ~(IO_SIZE-1);
+ if (my_write(info->file,Buffer,(uint) length,info->myflags | MY_NABP))
+ {
+ unlock_append_buffer(info);
+ return info->error= -1;
+ }
+ Count-=length;
+ Buffer+=length;
+ info->end_of_file+=length;
+ }
+
+end:
+ memcpy(info->write_pos,Buffer,(size_t) Count);
+ info->write_pos+=Count;
+ unlock_append_buffer(info);
return 0;
}
@@ -530,10 +859,13 @@ int my_block_write(register IO_CACHE *info, const byte *Buffer, uint Count,
Buffer+=length;
pos+= length;
Count-= length;
+#ifndef HAVE_PREAD
+ info->seek_not_done=1;
+#endif
}
/* Check if we want to write inside the used part of the buffer.*/
- length= (uint) (info->rc_end - info->buffer);
+ length= (uint) (info->write_end - info->buffer);
if (pos < info->pos_in_file + length)
{
uint offset= (uint) (pos - info->pos_in_file);
@@ -544,8 +876,8 @@ int my_block_write(register IO_CACHE *info, const byte *Buffer, uint Count,
Buffer+=length;
Count-= length;
/* Fix length of buffer if the new data was larger */
- if (info->buffer+length > info->rc_pos)
- info->rc_pos=info->buffer+length;
+ if (info->buffer+length > info->write_pos)
+ info->write_pos=info->buffer+length;
if (!Count)
return (error);
}
@@ -555,46 +887,89 @@ int my_block_write(register IO_CACHE *info, const byte *Buffer, uint Count,
return error;
}
+
/* Flush write cache */
-int flush_io_cache(IO_CACHE *info)
+#ifdef THREAD
+#define LOCK_APPEND_BUFFER if (need_append_buffer_lock) \
+ lock_append_buffer(info);
+#define UNLOCK_APPEND_BUFFER if (need_append_buffer_lock) \
+ unlock_append_buffer(info);
+#else
+#define LOCK_APPEND_BUFFER
+#define UNLOCK_APPEND_BUFFER
+#endif
+
+
+int _flush_io_cache(IO_CACHE *info, int need_append_buffer_lock)
{
uint length;
+ my_bool append_cache;
+ my_off_t pos_in_file;
DBUG_ENTER("flush_io_cache");
- if (info->type == WRITE_CACHE)
+ if (!(append_cache = (info->type == SEQ_READ_APPEND)))
+ need_append_buffer_lock=0;
+
+ if (info->type == WRITE_CACHE || append_cache)
{
if (info->file == -1)
{
if (real_open_cached_file(info))
DBUG_RETURN((info->error= -1));
}
- if (info->rc_pos != info->buffer)
+ LOCK_APPEND_BUFFER;
+
+ if ((length=(uint) (info->write_pos - info->write_buffer)))
{
- length=(uint) (info->rc_pos - info->buffer);
- if (info->seek_not_done)
+ pos_in_file=info->pos_in_file;
+ /* if we have append cache, we always open the file with
+ O_APPEND which moves the pos to EOF automatically on every write
+ */
+ if (!append_cache && info->seek_not_done)
{ /* File touched, do seek */
- if (my_seek(info->file,info->pos_in_file,MY_SEEK_SET,MYF(0)) ==
+ if (my_seek(info->file,pos_in_file,MY_SEEK_SET,MYF(0)) ==
MY_FILEPOS_ERROR)
+ {
+ UNLOCK_APPEND_BUFFER;
DBUG_RETURN((info->error= -1));
- info->seek_not_done=0;
+ }
+ if (!append_cache)
+ info->seek_not_done=0;
}
- info->rc_pos=info->buffer;
- info->pos_in_file+=length;
- info->rc_end=(info->buffer+info->buffer_length-
- (info->pos_in_file & (IO_SIZE-1)));
- if (my_write(info->file,info->buffer,length,info->myflags | MY_NABP))
- DBUG_RETURN((info->error= -1));
- DBUG_RETURN(0);
+ if (!append_cache)
+ info->pos_in_file+=length;
+ info->write_end= (info->write_buffer+info->buffer_length-
+ ((pos_in_file+length) & (IO_SIZE-1)));
+
+ if (my_write(info->file,info->write_buffer,length,
+ info->myflags | MY_NABP))
+ info->error= -1;
+ else
+ info->error= 0;
+ if (!append_cache)
+ {
+ set_if_bigger(info->end_of_file,(pos_in_file+length));
+ }
+ else
+ {
+ info->end_of_file+=(info->write_pos-info->append_read_pos);
+ DBUG_ASSERT(info->end_of_file == my_tell(info->file,MYF(0)));
+ }
+
+ info->append_read_pos=info->write_pos=info->write_buffer;
+ UNLOCK_APPEND_BUFFER;
+ DBUG_RETURN(info->error);
}
}
#ifdef HAVE_AIOWAIT
- else
+ else if (info->type != READ_NET)
{
- my_aiowait(&info->aio_result); /* Wait for outstanding req */
+ my_aiowait(&info->aio_result); /* Wait for outstanding req */
info->inited=0;
}
#endif
+ UNLOCK_APPEND_BUFFER;
DBUG_RETURN(0);
}
@@ -602,13 +977,118 @@ int flush_io_cache(IO_CACHE *info)
int end_io_cache(IO_CACHE *info)
{
int error=0;
+ IO_CACHE_CALLBACK pre_close;
DBUG_ENTER("end_io_cache");
- if (info->buffer)
+
+ if ((pre_close=info->pre_close))
+ (*pre_close)(info);
+ if (info->alloced_buffer)
{
+ info->alloced_buffer=0;
if (info->file != -1) /* File doesn't exist */
error=flush_io_cache(info);
my_free((gptr) info->buffer,MYF(MY_WME));
- info->buffer=info->rc_pos=(byte*) 0;
+ info->buffer=info->read_pos=(byte*) 0;
+ }
+ if (info->type == SEQ_READ_APPEND)
+ {
+ /* Destroy allocated mutex */
+ info->type=0;
+#ifdef THREAD
+ pthread_mutex_destroy(&info->append_buffer_lock);
+#endif
}
DBUG_RETURN(error);
} /* end_io_cache */
+
+
+/**********************************************************************
+ Testing of MF_IOCACHE
+**********************************************************************/
+
+#ifdef MAIN
+
+#include <my_dir.h>
+
+void die(const char* fmt, ...)
+{
+ va_list va_args;
+ va_start(va_args,fmt);
+ fprintf(stderr,"Error:");
+ vfprintf(stderr, fmt,va_args);
+ fprintf(stderr,", errno=%d\n", errno);
+ exit(1);
+}
+
+int open_file(const char* fname, IO_CACHE* info, int cache_size)
+{
+ int fd;
+ if ((fd=my_open(fname,O_CREAT | O_RDWR,MYF(MY_WME))) < 0)
+ die("Could not open %s", fname);
+ if (init_io_cache(info, fd, cache_size, SEQ_READ_APPEND, 0,0,MYF(MY_WME)))
+ die("failed in init_io_cache()");
+ return fd;
+}
+
+void close_file(IO_CACHE* info)
+{
+ end_io_cache(info);
+ my_close(info->file, MYF(MY_WME));
+}
+
+int main(int argc, char** argv)
+{
+ IO_CACHE sra_cache; /* SEQ_READ_APPEND */
+ MY_STAT status;
+ const char* fname="/tmp/iocache.test";
+ int cache_size=16384;
+ char llstr_buf[22];
+ int max_block,total_bytes=0;
+ int i,num_loops=100,error=0;
+ char *p;
+ char* block, *block_end;
+ MY_INIT(argv[0]);
+ max_block = cache_size*3;
+ if (!(block=(char*)my_malloc(max_block,MYF(MY_WME))))
+ die("Not enough memory to allocate test block");
+ block_end = block + max_block;
+ for (p = block,i=0; p < block_end;i++)
+ {
+ *p++ = (char)i;
+ }
+ if (my_stat(fname,&status, MYF(0)) &&
+ my_delete(fname,MYF(MY_WME)))
+ {
+ die("Delete of %s failed, aborting", fname);
+ }
+ open_file(fname,&sra_cache, cache_size);
+ for (i = 0; i < num_loops; i++)
+ {
+ char buf[4];
+ int block_size = abs(rand() % max_block);
+ int4store(buf, block_size);
+ if (my_b_append(&sra_cache,buf,4) ||
+ my_b_append(&sra_cache, block, block_size))
+ die("write failed");
+ total_bytes += 4+block_size;
+ }
+ close_file(&sra_cache);
+ my_free(block,MYF(MY_WME));
+ if (!my_stat(fname,&status,MYF(MY_WME)))
+ die("%s failed to stat, but I had just closed it,\
+ wonder how that happened");
+ printf("Final size of %s is %s, wrote %d bytes\n",fname,
+ llstr(status.st_size,llstr_buf),
+ total_bytes);
+ my_delete(fname, MYF(MY_WME));
+ /* check correctness of tests */
+ if (total_bytes != status.st_size)
+ {
+ fprintf(stderr,"Not the same number of bytes acutally in file as bytes \
+supposedly written\n");
+ error=1;
+ }
+ exit(error);
+ return 0;
+}
+#endif
diff --git a/mysys/mf_iocache2.c b/mysys/mf_iocache2.c
index 3e9cc74e0a2..127bf20e8fe 100644
--- a/mysys/mf_iocache2.c
+++ b/mysys/mf_iocache2.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/*
More functions to be used with IO_CACHE files
@@ -24,58 +23,114 @@
#include <m_string.h>
#include <stdarg.h>
#include <m_ctype.h>
+#include <assert.h>
+
+my_off_t my_b_append_tell(IO_CACHE* info)
+{
+ /* prevent optimizer from putting res in a register when debugging
+ we need this to be able to see the value of res when the assert fails
+ */
+ dbug_volatile my_off_t res;
+/* we need to lock the append buffer mutex to keep flush_io_cache()
+ from messing with the variables that we need in order to provide the
+ answer to the question.
+*/
+#ifdef THREAD
+ pthread_mutex_lock(&info->append_buffer_lock);
+#endif
+ /* save the value of my_tell in res so we can see it when studying
+ coredump
+ */
+#ifndef DBUG_OFF
+ /* make sure EOF is where we think it is. Note that we cannot just use
+ my_tell() because we have a reader thread that could have left the
+ file offset in a non-EOF location
+ */
+ {
+ volatile my_off_t save_pos;
+ save_pos = my_tell(info->file,MYF(0));
+ my_seek(info->file,(my_off_t)0,MY_SEEK_END,MYF(0));
+ DBUG_ASSERT(info->end_of_file - (info->append_read_pos-info->write_buffer)
+ == (res=my_tell(info->file,MYF(0))));
+ my_seek(info->file,save_pos,MY_SEEK_SET,MYF(0));
+ }
+#endif
+ res = info->end_of_file + (info->write_pos-info->append_read_pos);
+#ifdef THREAD
+ pthread_mutex_unlock(&info->append_buffer_lock);
+#endif
+ return res;
+}
/*
-** Fix that next read will be made at certain position
-** For write cache, make next write happen at a certain position
+ Make next read happen at the given position
+ For write cache, make next write happen at the given position
*/
void my_b_seek(IO_CACHE *info,my_off_t pos)
{
- my_off_t offset = (pos - info->pos_in_file);
+ my_off_t offset;
DBUG_ENTER("my_b_seek");
DBUG_PRINT("enter",("pos: %lu", (ulong) pos));
- if (info->type == READ_CACHE)
+ /*
+ TODO: verify that it is OK to do seek in the non-append
+ area in SEQ_READ_APPEND cache
+ */
+ /* TODO:
+ a) see if this always works
+ b) see if there is a better way to make it work
+ */
+ if (info->type == SEQ_READ_APPEND)
+ flush_io_cache(info);
+
+ offset=(pos - info->pos_in_file);
+
+ if (info->type == READ_CACHE || info->type == SEQ_READ_APPEND)
{
- if ((ulonglong) offset < (ulonglong) (info->rc_end - info->buffer))
+ /* TODO: explain why this works if pos < info->pos_in_file */
+ if ((ulonglong) offset < (ulonglong) (info->read_end - info->buffer))
{
/* The read is in the current buffer; Reuse it */
- info->rc_pos = info->buffer + offset;
+ info->read_pos = info->buffer + offset;
DBUG_VOID_RETURN;
}
else
{
/* Force a new read on next my_b_read */
- info->rc_pos=info->rc_end=info->buffer;
+ info->read_pos=info->read_end=info->buffer;
}
}
else if (info->type == WRITE_CACHE)
{
/* If write is in current buffer, reuse it */
if ((ulonglong) offset <
- (ulonglong) (info->rc_end - info->buffer))
+ (ulonglong) (info->write_end - info->write_buffer))
{
- info->rc_pos = info->buffer + offset;
+ info->write_pos = info->write_buffer + offset;
DBUG_VOID_RETURN;
}
flush_io_cache(info);
- info->rc_end=(info->buffer+info->buffer_length-(pos & (IO_SIZE-1)));
+ /* Correct buffer end so that we write in increments of IO_SIZE */
+ info->write_end=(info->write_buffer+info->buffer_length-
+ (pos & (IO_SIZE-1)));
}
info->pos_in_file=pos;
info->seek_not_done=1;
}
+
/*
-** Fill buffer. Note that this assumes that you have already used
-** all characters in the CACHE, independent of the rc_pos value!
-** return: 0 on error or EOF (info->error = -1 on error)
-** number of characters
+ Fill buffer. Note that this assumes that you have already used
+ all characters in the CACHE, independent of the read_pos value!
+ return: 0 on error or EOF (info->error = -1 on error)
+ number of characters
*/
uint my_b_fill(IO_CACHE *info)
{
- my_off_t pos_in_file=info->pos_in_file+(uint) (info->rc_end - info->buffer);
+ my_off_t pos_in_file=(info->pos_in_file+
+ (uint) (info->read_end - info->buffer));
my_off_t max_length;
uint diff_length,length;
if (info->seek_not_done)
@@ -103,16 +158,18 @@ uint my_b_fill(IO_CACHE *info)
info->error= -1;
return 0;
}
- info->rc_pos=info->buffer;
- info->rc_end=info->buffer+length;
+ info->read_pos=info->buffer;
+ info->read_end=info->buffer+length;
info->pos_in_file=pos_in_file;
return length;
}
+
/*
-** Read a string ended by '\n' into a buffer of 'max_length' size.
-** Returns number of characters read, 0 on error.
-** last byte is set to '\0'
+ Read a string ended by '\n' into a buffer of 'max_length' size.
+ Returns number of characters read, 0 on error.
+ last byte is set to '\0'
+ If buffer is full then to[max_length-1] will be set to \0.
*/
uint my_b_gets(IO_CACHE *info, char *to, uint max_length)
@@ -129,11 +186,11 @@ uint my_b_gets(IO_CACHE *info, char *to, uint max_length)
char *pos,*end;
if (length > max_length)
length=max_length;
- for (pos=info->rc_pos,end=pos+length ; pos < end ;)
+ for (pos=info->read_pos,end=pos+length ; pos < end ;)
{
if ((*to++ = *pos++) == '\n')
{
- info->rc_pos=pos;
+ info->read_pos=pos;
*to='\0';
return (uint) (to-start);
}
@@ -141,7 +198,7 @@ uint my_b_gets(IO_CACHE *info, char *to, uint max_length)
if (!(max_length-=length))
{
/* Found enough charcters; Return found string */
- info->rc_pos=pos;
+ info->read_pos=pos;
*to='\0';
return (uint) (to-start);
}
@@ -150,6 +207,7 @@ uint my_b_gets(IO_CACHE *info, char *to, uint max_length)
}
}
+
/*
Simple printf version. Supports '%s', '%d', '%u', "%ld" and "%lu"
Used for logging in MySQL
diff --git a/mysys/mf_keycache.c b/mysys/mf_keycache.c
index 5b8ec96b4d1..2ddf13bfa1f 100644
--- a/mysys/mf_keycache.c
+++ b/mysys/mf_keycache.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 functions is handle keyblock cacheing for NISAM, MISAM and PISAM
@@ -53,7 +52,6 @@ typedef struct sec_link {
} SEC_LINK;
-static uint find_next_bigger_power(uint value);
static SEC_LINK *find_key_block(int file,my_off_t filepos,int *error);
/* static variables in this file */
@@ -61,9 +59,11 @@ static SEC_LINK *_my_block_root,**_my_hash_root,
*_my_used_first,*_my_used_last;
static int _my_disk_blocks;
static uint _my_disk_blocks_used, _my_hash_blocks;
+static uint key_cache_shift;
ulong _my_blocks_used,_my_blocks_changed;
ulong _my_cache_w_requests,_my_cache_write,_my_cache_r_requests,
_my_cache_read;
+uint key_cache_block_size=DEFAULT_KEYCACHE_BLOCK_SIZE;
static byte HUGE_PTR *_my_block_mem;
static SEC_LINK *changed_blocks[CHANGED_BLOCKS_HASH];
static SEC_LINK *file_blocks[CHANGED_BLOCKS_HASH];
@@ -92,12 +92,16 @@ int init_key_cache(ulong use_mem,
{
key_cache_inited=TRUE;
_my_disk_blocks= -1;
+ key_cache_shift=my_bit_log2(key_cache_block_size);
+ DBUG_PRINT("info",("key_cache_block_size: %u key_cache_shift: %u",
+ key_cache_block_size, key_cache_shift));
#ifndef DBUG_OFF
_my_printed=0;
#endif
}
- blocks= (uint) (use_mem/(sizeof(SEC_LINK)+sizeof(SEC_LINK*)*5/4+KEYCACHE_BLOCK_SIZE));
+ blocks= (uint) (use_mem/(sizeof(SEC_LINK)+sizeof(SEC_LINK*)*5/4+
+ key_cache_block_size));
/* No use to have very few blocks */
if (blocks >= 8 && _my_disk_blocks < 0)
{
@@ -107,13 +111,15 @@ int init_key_cache(ulong use_mem,
#endif
for (;;)
{
- if ((_my_hash_blocks=find_next_bigger_power((uint) blocks)) < blocks*5/4)
- _my_hash_blocks<<=1;
+ /* Set my_hash_blocks to the next bigger 2 power */
+ _my_hash_blocks=(uint) 1 << (my_bit_log2(blocks*5/4)+1);
while ((length=(uint) blocks*sizeof(SEC_LINK)+
- sizeof(SEC_LINK*)*_my_hash_blocks)+(ulong) blocks*KEYCACHE_BLOCK_SIZE >
+ sizeof(SEC_LINK*)*_my_hash_blocks)+
+ ((ulong) blocks << key_cache_shift) >
use_mem)
blocks--;
- if ((_my_block_mem=my_malloc_lock((ulong) blocks * KEYCACHE_BLOCK_SIZE,MYF(0))))
+ if ((_my_block_mem=my_malloc_lock((ulong) blocks << key_cache_shift,
+ MYF(0))))
{
if ((_my_block_root=(SEC_LINK*) my_malloc((uint) length,MYF(0))) != 0)
break;
@@ -162,6 +168,7 @@ void end_key_cache(void)
}
}
key_cache_inited=0;
+ _my_hash_blocks=_my_blocks_used=0;
DBUG_PRINT("status",
("used: %d changed: %d w_requests: %ld writes: %ld r_requests: %ld reads: %ld",
_my_blocks_used,_my_blocks_changed,_my_cache_w_requests,
@@ -170,17 +177,6 @@ void end_key_cache(void)
} /* end_key_cache */
-static uint find_next_bigger_power(uint value)
-{
- uint old_value=1;
- while (value)
- {
- old_value=value;
- value&= value-1;
- }
- return (old_value << 1);
-}
-
static inline void link_into_file_blocks(SEC_LINK *next, int file)
{
reg1 SEC_LINK **ptr= &file_blocks[(uint) file & CHANGED_BLOCKS_MASK];
@@ -243,7 +239,7 @@ static void test_key_cache(const char *where, my_bool lock);
/*
** read a key_buffer
- ** filepos must point at a even KEYCACHE_BLOCK_SIZE block
+ ** filepos must point at a even key_cache_block_size block
** if return_buffer is set then the intern buffer is returned if
** it can be used
** Returns adress to where data is read
@@ -255,9 +251,12 @@ byte *key_cache_read(File file, my_off_t filepos, byte *buff, uint length,
{
reg1 SEC_LINK *next;
int error=0;
+ DBUG_ENTER("key_cache_read");
+ DBUG_PRINT("enter", ("file %u, filepos %lu, length %u",
+ (uint) file, (ulong) filepos, length));
#ifndef THREAD
- if (block_length > KEYCACHE_BLOCK_SIZE)
+ if (block_length > key_cache_block_size)
return_buffer=0;
#endif
if (_my_disk_blocks > 0)
@@ -268,18 +267,19 @@ byte *key_cache_read(File file, my_off_t filepos, byte *buff, uint length,
do
{
_my_cache_r_requests++;
- read_length= length > KEYCACHE_BLOCK_SIZE ? KEYCACHE_BLOCK_SIZE : length;
+ read_length= (length > key_cache_block_size ? key_cache_block_size :
+ length);
if (!(next=find_key_block(file,filepos,&error)))
{
pthread_mutex_unlock(&THR_LOCK_keycache);
- return (byte*) 0; /* Got a fatal error */
+ DBUG_RETURN ((byte*) 0); /* Got a fatal error */
}
if (error)
{ /* Didn't find it in cache */
if (my_pread(file,next->buffer,read_length,filepos,MYF(MY_NABP)))
{
pthread_mutex_unlock(&THR_LOCK_keycache);
- return((byte*) 0);
+ DBUG_RETURN((byte*) 0);
}
_my_cache_read++;
}
@@ -287,7 +287,7 @@ byte *key_cache_read(File file, my_off_t filepos, byte *buff, uint length,
if (return_buffer)
{
pthread_mutex_unlock(&THR_LOCK_keycache);
- return (next->buffer);
+ DBUG_RETURN (next->buffer);
}
#endif
if (! (read_length & 511))
@@ -298,19 +298,19 @@ byte *key_cache_read(File file, my_off_t filepos, byte *buff, uint length,
filepos+=read_length;
} while ((length-= read_length));
pthread_mutex_unlock(&THR_LOCK_keycache);
- return(start);
+ DBUG_RETURN(start);
}
_my_cache_r_requests++;
_my_cache_read++;
if (my_pread(file,(byte*) buff,length,filepos,MYF(MY_NABP)))
error=1;
- return (error ? (byte*) 0 : buff);
+ DBUG_RETURN(error ? (byte*) 0 : buff);
} /* key_cache_read */
/* write a key_buffer */
/* We don't have to use pwrite because of write locking */
- /* buff must point at a even KEYCACHE_BLOCK_SIZE block */
+ /* buff must point at a even key_cache_block_size block */
int key_cache_write(File file, my_off_t filepos, byte *buff, uint length,
uint block_length __attribute__((unused)),
@@ -318,12 +318,15 @@ int key_cache_write(File file, my_off_t filepos, byte *buff, uint length,
{
reg1 SEC_LINK *next;
int error=0;
+ DBUG_ENTER("key_cache_write");
+ DBUG_PRINT("enter", ("file %u, filepos %lu, length %u",
+ (uint) file, (ulong) filepos, length));
if (!dont_write)
{ /* Forced write of buffer */
_my_cache_write++;
if (my_pwrite(file,buff,length,filepos,MYF(MY_NABP | MY_WAIT_IF_FULL)))
- return(1);
+ DBUG_RETURN(1);
}
#if !defined(DBUG_OFF) && defined(EXTRA_DEBUG)
@@ -336,7 +339,7 @@ int key_cache_write(File file, my_off_t filepos, byte *buff, uint length,
_my_cache_w_requests++;
do
{
- read_length= length > KEYCACHE_BLOCK_SIZE ? KEYCACHE_BLOCK_SIZE : length;
+ read_length= length > key_cache_block_size ? key_cache_block_size : length;
if (!(next=find_key_block(file,filepos,&error)))
goto end; /* Fatal error */
if (!dont_write) /* If we wrote buff at start */
@@ -369,7 +372,7 @@ end:
#if !defined(DBUG_OFF) && defined(EXTRA_DEBUG)
DBUG_EXECUTE("check_keycache",test_key_cache("end of key_cache_write",1););
#endif
- return(error);
+ DBUG_RETURN(error);
} /* key_cache_write */
@@ -379,13 +382,16 @@ end:
static SEC_LINK *find_key_block(int file, my_off_t filepos, int *error)
{
reg1 SEC_LINK *next,**start;
+ DBUG_ENTER("find_key_block");
+ DBUG_PRINT("enter", ("file %u, filepos %lu",
+ (uint) file, (ulong) filepos));
#if !defined(DBUG_OFF) && defined(EXTRA_DEBUG)
DBUG_EXECUTE("check_keycache2",test_key_cache("start of find_key_block",0););
#endif
*error=0;
- next= *(start= &_my_hash_root[((ulong) (filepos/KEYCACHE_BLOCK_SIZE)+(ulong) file) &
+ next= *(start= &_my_hash_root[((ulong) (filepos >> key_cache_shift)+(ulong) file) &
(_my_hash_blocks-1)]);
while (next && (next->diskpos != filepos || next->file != file))
next= next->next_hash;
@@ -411,7 +417,8 @@ static SEC_LINK *find_key_block(int file, my_off_t filepos, int *error)
{ /* There are unused blocks */
next= &_my_block_root[_my_blocks_used++]; /* Link in hash-chain */
next->buffer=ADD_TO_PTR(_my_block_mem,
- (ulong) _my_disk_blocks_used*KEYCACHE_BLOCK_SIZE,byte*);
+ ((ulong) _my_disk_blocks_used << key_cache_shift),
+ byte*);
/* link first in file_blocks */
next->changed=0;
link_into_file_blocks(next,file);
@@ -426,7 +433,8 @@ static SEC_LINK *find_key_block(int file, my_off_t filepos, int *error)
next= _my_used_first;
if (next->changed)
{
- if (my_pwrite(next->file,next->buffer,KEYCACHE_BLOCK_SIZE,next->diskpos,
+ if (my_pwrite(next->file,next->buffer,key_cache_block_size,
+ next->diskpos,
MYF(MY_NABP | MY_WAIT_IF_FULL)))
{
*error=1;
@@ -461,7 +469,7 @@ static SEC_LINK *find_key_block(int file, my_off_t filepos, int *error)
#if !defined(DBUG_OFF) && defined(EXTRA_DEBUG)
DBUG_EXECUTE("check_keycache2",test_key_cache("end of find_key_block",0););
#endif
- return next;
+ DBUG_RETURN(next);
} /* find_key_block */
@@ -505,7 +513,8 @@ static int flush_cached_blocks(File file, SEC_LINK **cache, uint count)
qsort((byte*) cache, count, sizeof(*cache), (qsort_cmp) cmp_sec_link);
for ( ; count-- ; cache++)
{
- if (my_pwrite(file,(*cache)->buffer,KEYCACHE_BLOCK_SIZE,(*cache)->diskpos,
+ if (my_pwrite(file,(*cache)->buffer,key_cache_block_size,
+ (*cache)->diskpos,
MYF(MY_NABP | MY_WAIT_IF_FULL)))
{
if (!last_errno)
@@ -646,7 +655,7 @@ static void test_key_cache(const char *where, my_bool lock)
i,(ulong) pos,(ulong) prev,(ulong) pos->prev_hash));
}
- if (((pos->diskpos/KEYCACHE_BLOCK_SIZE)+pos->file) % _my_hash_blocks != i)
+ if (((pos->diskpos >> key_cache_shift)+pos->file) % _my_hash_blocks != i)
{
DBUG_PRINT("error",("hash: %d pos: %lx : Wrong disk_buffer %ld",
i,(ulong) pos,(ulong) pos->diskpos));
diff --git a/mysys/mf_loadpath.c b/mysys/mf_loadpath.c
index 641528b8b5d..68d6e3ceda3 100644
--- a/mysys/mf_loadpath.c
+++ b/mysys/mf_loadpath.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include "mysys_priv.h"
#include <m_string.h>
diff --git a/mysys/mf_pack.c b/mysys/mf_pack.c
index b442af7e9e5..8fba14f626b 100644
--- a/mysys/mf_pack.c
+++ b/mysys/mf_pack.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include "mysys_priv.h"
#include <m_string.h>
@@ -40,6 +39,7 @@ void pack_dirname(my_string to, const char *from)
char buff[FN_REFLEN];
DBUG_ENTER("pack_dirname");
+ LINT_INIT(buff_length);
(void) intern_filename(to,from); /* Change to intern name */
#ifdef FN_DEVCHAR
@@ -49,7 +49,6 @@ void pack_dirname(my_string to, const char *from)
#endif
start=to;
- LINT_INIT(buff_length);
if (!(cwd_err= my_getwd(buff,FN_REFLEN,MYF(0))))
{
buff_length= (uint) strlen(buff);
@@ -218,7 +217,7 @@ uint cleanup_dirname(register my_string to, const char *from)
to the directory. This will be used if the directory name
doesn't exists
*/
-
+
my_bool my_use_symdir=0; /* Set this if you want to use symdirs */
@@ -459,8 +458,7 @@ my_string intern_filename(my_string to, const char *from)
my_string pos,from_pos,to_pos,end_pos;
char buff[FN_REFLEN];
- (void) strmov(buff,from);
- convert_dirname(buff); /* change '<>' to '[]' */
+ convert_dirname(buff,from,NullS); /* change '<>' to '[]' */
from_pos=buff;
if ((pos=strrchr(from_pos,FN_DEVCHAR))) /* Skipp device part */
{
diff --git a/mysys/mf_pack2.c b/mysys/mf_pack2.c
deleted file mode 100644
index 1cda7797457..00000000000
--- a/mysys/mf_pack2.c
+++ /dev/null
@@ -1,53 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
-
-#include "mysys_priv.h"
-#include <m_string.h>
-
- /* Pack a filename for output on screen */
- /* Changes long paths to .../ */
- /* Removes pathname and extension */
- /* If not possibly to pack returns '?' in to and returns 1*/
-
-int pack_filename(my_string to, const char *name, size_s max_length)
- /* to may be name */
-
-{
- int i;
- char buff[FN_REFLEN];
-
- if (strlen(fn_format(to,name,"","",0)) <= max_length)
- return 0;
- if (strlen(fn_format(to,name,"","",8)) <= max_length)
- return 0;
- if (strlen(fn_format(buff,name,".../","",1)) <= max_length)
- {
- VOID(strmov(to,buff));
- return 0;
- }
- for (i= 0 ; i < 3 ; i++)
- {
- if (strlen(fn_format(buff,to,"","", i == 0 ? 2 : i == 1 ? 1 : 3 ))
- <= max_length)
- {
- VOID(strmov(to,buff));
- return 0;
- }
- }
- to[0]='?'; to[1]=0; /* Can't pack filename */
- return 1;
-} /* pack_filename */
diff --git a/mysys/mf_path.c b/mysys/mf_path.c
index 9a88b938e2c..23eadd2acce 100644
--- a/mysys/mf_path.c
+++ b/mysys/mf_path.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include "mysys_priv.h"
#include <m_string.h>
diff --git a/mysys/mf_qsort.c b/mysys/mf_qsort.c
index 64e70990696..9cc937f6e8b 100644
--- a/mysys/mf_qsort.c
+++ b/mysys/mf_qsort.c
@@ -1,249 +1,217 @@
-/* Copyright (C) 1991, 1992, 1996, 1997 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
- Written by Douglas C. Schmidt (schmidt@ics.uci.edu).
+/* Copyright (C) 2000 MySQL AB
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public License as
- published by the Free Software Foundation; either version 2 of the
- License, or (at your option) any later version.
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
- The GNU C Library is distributed in the hope that it will be useful,
+ 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
- Library General Public License for more details.
+ 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 Library General Public
- License along with the GNU C Library; see the file COPYING.LIB. If not,
- write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
+ 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 */
/*
- Modifications by monty:
- - Uses mysys include files
- - Small fixes to make the it a bit faster
- - Can be compiled with a cmp function that takes one extra argument.
+ qsort implementation optimized for comparison of pointers
+ Inspired by the qsort implementations by Douglas C. Schmidt,
+ and Bentley & McIlroy's "Engineering a Sort Function".
*/
+
#include "mysys_priv.h"
+#ifndef SCO
#include <m_string.h>
+#endif
-/* Envoke the comparison function, returns either 0, < 0, or > 0. */
+/* We need to use qsort with 2 different compare functions */
#ifdef QSORT_EXTRA_CMP_ARGUMENT
#define CMP(A,B) ((*cmp)(cmp_argument,(A),(B)))
#else
#define CMP(A,B) ((*cmp)((A),(B)))
#endif
-/* Byte-wise swap two items of size SIZE. */
-#define SWAP(a, b, size) \
- do \
- { \
- register size_t __size = (size); \
- register char *__a = (a), *__b = (b); \
- do \
- { \
- char __tmp = *__a; \
- *__a++ = *__b; \
- *__b++ = __tmp; \
- } while (--__size > 0); \
- } while (0)
-
-/* Discontinue quicksort algorithm when partition gets below this size.
- This particular magic number was chosen to work best on a Sun 4/260. */
-#define MAX_THRESH 8
-
-/* Stack node declarations used to store unfulfilled partition obligations. */
-typedef struct _qsort_stack_node
- {
- char *lo;
- char *hi;
- } stack_node;
-
-/* The next 4 #defines implement a very fast in-line stack abstraction. */
-#define STACK_SIZE (8 * sizeof(unsigned long int))
-#define PUSH(LOW,HIGH) do {top->lo = LOW;top++->hi = HIGH;} while (0)
-#define POP(LOW,HIGH) do {LOW = (--top)->lo;HIGH = top->hi;} while (0)
-#define STACK_NOT_EMPTY (stack < top)
-
-/* Order size using quicksort. This implementation incorporates
- four optimizations discussed in Sedgewick:
-
- 1. Non-recursive, using an explicit stack of pointer that store the
- next array partition to sort. To save time, this maximum amount
- of space required to store an array of MAX_INT is allocated on the
- stack. Assuming a 32-bit integer, this needs only 32 *
- sizeof (stack_node) == 136 bits. Pretty cheap, actually.
+#define SWAP(A, B, size,swap_ptrs) \
+do { \
+ if (swap_ptrs) \
+ { \
+ reg1 char **a = (char**) (A), **b = (char**) (B); \
+ char *tmp = *a; *a++ = *b; *b++ = tmp; \
+ } \
+ else \
+ { \
+ reg1 char *a = (A), *b = (B); \
+ reg3 char *end= a+size; \
+ do \
+ { \
+ char tmp = *a; *a++ = *b; *b++ = tmp; \
+ } while (a < end); \
+ } \
+} while (0)
+
+/* Put the median in the middle argument */
+#define MEDIAN(low, mid, high) \
+{ \
+ if (CMP(high,low) < 0) \
+ SWAP(high, low, size, ptr_cmp); \
+ if (CMP(mid, low) < 0) \
+ SWAP(mid, low, size, ptr_cmp); \
+ else if (CMP(high, mid) < 0) \
+ SWAP(mid, high, size, ptr_cmp); \
+}
- 2. Chose the pivot element using a median-of-three decision tree.
- This reduces the probability of selecting a bad pivot value and
- eliminates certain extraneous comparisons.
+/* The following node is used to store ranges to avoid recursive calls */
- 3. Only quicksorts TOTAL_ELEMS / MAX_THRESH partitions, leaving
- insertion sort to order the MAX_THRESH items within each partition.
- This is a big win, since insertion sort is faster for small, mostly
- sorted array segments.
+typedef struct st_stack
+{
+ char *low,*high;
+} stack_node;
- 4. The larger of the two sub-partitions is always pushed onto the
- stack first, with the algorithm then concentrating on the
- smaller partition. This *guarantees* no more than log (n)
- stack size is needed (actually O(1) in this case)! */
+#define PUSH(LOW,HIGH) {stack_ptr->low = LOW; stack_ptr++->high = HIGH;}
+#define POP(LOW,HIGH) {LOW = (--stack_ptr)->low; HIGH = stack_ptr->high;}
+/* The following stack size is enough for ulong ~0 elements */
+#define STACK_SIZE (8 * sizeof(unsigned long int))
+#define THRESHOLD_FOR_INSERT_SORT 10
#if defined(QSORT_TYPE_IS_VOID)
#define SORT_RETURN return
#else
#define SORT_RETURN return 0
#endif
+/****************************************************************************
+** 'standard' quicksort with the following extensions:
+**
+** Can be compiled with the qsort2_cmp compare function
+** Store ranges on stack to avoid recursion
+** Use insert sort on small ranges
+** Optimize for sorting of pointers (used often by MySQL)
+** Use median comparison to find partition element
+*****************************************************************************/
+
#ifdef QSORT_EXTRA_CMP_ARGUMENT
-qsort_t qsort2(void *base_ptr, size_t total_elems, size_t size, qsort2_cmp cmp,
+qsort_t qsort2(void *base_ptr, size_t count, size_t size, qsort2_cmp cmp,
void *cmp_argument)
#else
-qsort_t qsort(void *base_ptr, size_t total_elems, size_t size, qsort_cmp cmp)
+qsort_t qsort(void *base_ptr, size_t count, size_t size, qsort_cmp cmp)
#endif
{
- /* Allocating SIZE bytes for a pivot buffer facilitates a better
- algorithm below since we can do comparisons directly on the pivot.
- */
- size_t max_thresh = (size_t) (MAX_THRESH * size);
- if (total_elems <= 1)
- SORT_RETURN; /* Crashes on MSDOS if continues */
-
- if (total_elems > MAX_THRESH)
- {
- char *lo = (char*) base_ptr;
- char *hi = &lo[size * (total_elems - 1)];
- stack_node stack[STACK_SIZE]; /* Largest size needed for 32-bit int!!! */
- stack_node *top = stack + 1;
- char *pivot = (char *) my_alloca ((int) size);
+ char *low, *high, *pivot;
+ stack_node stack[STACK_SIZE], *stack_ptr;
+ my_bool ptr_cmp;
+ /* Handle the simple case first */
+ /* This will also make the rest of the code simpler */
+ if (count <= 1)
+ SORT_RETURN;
+
+ low = (char*) base_ptr;
+ high = low+ size * (count - 1);
+ stack_ptr = stack + 1;
#ifdef HAVE_purify
- stack[0].lo=stack[0].hi=0;
+ /* The first element in the stack will be accessed for the last POP */
+ stack[0].low=stack[0].high=0;
#endif
+ pivot = (char *) my_alloca((int) size);
+ ptr_cmp= size == sizeof(char*) && !((low - (char*) 0)& (sizeof(char*)-1));
- do
+ /* The following loop sorts elements between high and low */
+ do
+ {
+ char *low_ptr, *high_ptr, *mid;
+
+ count=((size_t) (high - low) / size)+1;
+ /* If count is small, then an insert sort is faster than qsort */
+ if (count < THRESHOLD_FOR_INSERT_SORT)
{
- char *left_ptr,*right_ptr;
-
- /* Select median value from among LO, MID, and HI. Rearrange
- LO and HI so the three values are sorted. This lowers the
- probability of picking a pathological pivot value and
- skips a comparison for both the LEFT_PTR and RIGHT_PTR. */
-
- char *mid = lo + size * (((ulong) (hi - lo) / (ulong) size) >> 1);
-
- if (CMP(hi,lo) < 0)
- SWAP (hi, lo, size);
- if (CMP (mid, lo) < 0)
- SWAP (mid, lo, size);
- else if (CMP (hi, mid) < 0)
- SWAP (mid, hi, size);
- memcpy (pivot, mid, size);
-
- left_ptr = lo + size;
- right_ptr = hi - size;
-
- /* Here's the famous ``collapse the walls'' section of quicksort.
- Gotta like those tight inner loops! They are the main reason
- that this algorithm runs much faster than others. */
- do
+ for (low_ptr = low + size; low_ptr <= high; low_ptr += size)
{
- while (CMP (left_ptr, pivot) < 0)
- left_ptr += size;
-
- while (CMP (pivot, right_ptr) < 0)
- right_ptr -= size;
-
- if (left_ptr < right_ptr)
- {
- SWAP (left_ptr, right_ptr, size);
- left_ptr += size;
- right_ptr -= size;
- }
- else if (left_ptr == right_ptr)
- {
- left_ptr += size;
- right_ptr -= size;
- break;
- }
- else
- break; /* left_ptr > right_ptr */
+ char *ptr;
+ for (ptr = low_ptr; ptr > low && CMP(ptr - size, ptr) > 0;
+ ptr -= size)
+ SWAP(ptr, ptr - size, size, ptr_cmp);
}
- while (left_ptr <= right_ptr);
+ POP(low, high);
+ continue;
+ }
+ /* Try to find a good middle element */
+ mid= low + size * (count >> 1);
+ if (count > 40) /* Must be bigger than 24 */
+ {
+ size_t step = size* (count / 8);
+ MEDIAN(low, low + step, low+step*2);
+ MEDIAN(mid - step, mid, mid+step);
+ MEDIAN(high - 2 * step, high-step, high);
+ /* Put best median in 'mid' */
+ MEDIAN(low+step, mid, high-step);
+ low_ptr = low;
+ high_ptr = high;
+ }
+ else
+ {
+ MEDIAN(low, mid, high);
+ /* The low and high argument are already in sorted against 'pivot' */
+ low_ptr = low + size;
+ high_ptr = high - size;
+ }
+ memcpy(pivot, mid, size);
- /* Set up pointers for next iteration. First determine whether
- left and right partitions are below the threshold size. If so,
- ignore one or both. Otherwise, push the larger partition's
- bounds on the stack and continue sorting the smaller one. */
+ do
+ {
+ while (CMP(low_ptr, pivot) < 0)
+ low_ptr += size;
+ while (CMP(pivot, high_ptr) < 0)
+ high_ptr -= size;
- if ((size_t) (right_ptr - lo) <= max_thresh)
+ if (low_ptr < high_ptr)
{
- if ((size_t) (hi - left_ptr) <= max_thresh)
- POP (lo, hi); /* Ignore both small partitions. */
- else
- lo = left_ptr; /* Ignore small left part. */
+ SWAP(low_ptr, high_ptr, size, ptr_cmp);
+ low_ptr += size;
+ high_ptr -= size;
}
- else if ((size_t) (hi - left_ptr) <= max_thresh)
- hi = right_ptr; /* Ignore small right partition. */
- else if ((right_ptr - lo) > (hi - left_ptr))
- {
- PUSH (lo, right_ptr); /* Push larger left part */
- lo = left_ptr;
- }
- else
+ else
{
- PUSH (left_ptr, hi); /* Push larger right part */
- hi = right_ptr;
+ if (low_ptr == high_ptr)
+ {
+ low_ptr += size;
+ high_ptr -= size;
+ }
+ break;
}
- } while (STACK_NOT_EMPTY);
- my_afree(pivot);
- }
-
- /* Once the BASE_PTR array is partially sorted by quicksort the rest
- is completely sorted using insertion sort, since this is efficient
- for partitions below MAX_THRESH size. BASE_PTR points to the beginning
- of the array to sort, and END_PTR points at the very last element in
- the array (*not* one beyond it!). */
-
- {
- char *end_ptr = (char*) base_ptr + size * (total_elems - 1);
- char *tmp_ptr = (char*) base_ptr;
- char *thresh = min (end_ptr, (char*) base_ptr + max_thresh);
- register char *run_ptr;
-
- /* Find smallest element in first threshold and place it at the
- array's beginning. This is the smallest array element,
- and the operation speeds up insertion sort's inner loop. */
-
- for (run_ptr = tmp_ptr + size; run_ptr <= thresh; run_ptr += size)
- if (CMP (run_ptr, tmp_ptr) < 0)
- tmp_ptr = run_ptr;
-
- if (tmp_ptr != (char*) base_ptr)
- SWAP (tmp_ptr, (char*) base_ptr, size);
+ }
+ while (low_ptr <= high_ptr);
- /* Insertion sort, running from left-hand-side up to right-hand-side. */
+ /*
+ Prepare for next iteration.
+ Skip partitions of size 1 as these doesn't have to be sorted
+ Push the larger partition and sort the smaller one first.
+ This ensures that the stack is keept small.
+ */
- for (run_ptr = (char*) base_ptr + size;
- (run_ptr += size) <= end_ptr; )
+ if ((int) (high_ptr - low) <= 0)
{
- if (CMP (run_ptr, (tmp_ptr = run_ptr-size)) < 0)
+ if ((int) (high - low_ptr) <= 0)
{
- char *trav;
- while (CMP (run_ptr, tmp_ptr -= size) < 0) ;
- tmp_ptr += size;
-
- /* Shift down all smaller elements, put found element in 'run_ptr' */
- for (trav = run_ptr + size; --trav >= run_ptr;)
- {
- char c = *trav;
- char *hi, *lo;
-
- for (hi = lo = trav; (lo -= size) >= tmp_ptr; hi = lo)
- *hi = *lo;
- *hi = c;
- }
+ POP(low, high); /* Nothing more to sort */
}
+ else
+ low = low_ptr; /* Ignore small left part. */
+ }
+ else if ((int) (high - low_ptr) <= 0)
+ high = high_ptr; /* Ignore small right part. */
+ else if ((high_ptr - low) > (high - low_ptr))
+ {
+ PUSH(low, high_ptr); /* Push larger left part */
+ low = low_ptr;
+ }
+ else
+ {
+ PUSH(low_ptr, high); /* Push larger right part */
+ high = high_ptr;
}
- }
+ } while (stack_ptr > stack);
+ my_afree(pivot);
SORT_RETURN;
}
diff --git a/mysys/mf_qsort2.c b/mysys/mf_qsort2.c
index 7b1ca4e39ab..160bb6df817 100644
--- a/mysys/mf_qsort2.c
+++ b/mysys/mf_qsort2.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/* qsort that sends one extra argument to the compare subrutine */
diff --git a/mysys/mf_radix.c b/mysys/mf_radix.c
index 99aa4d0b073..7ee96b966b9 100644
--- a/mysys/mf_radix.c
+++ b/mysys/mf_radix.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/*
Radixsort for pointers to fixed length strings.
diff --git a/mysys/mf_same.c b/mysys/mf_same.c
index c1a5cae11cb..efd6e7b2ca4 100644
--- a/mysys/mf_same.c
+++ b/mysys/mf_same.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/* Kopierar biblioteksstrukturen och extensionen fr}n ett filnamn */
diff --git a/mysys/mf_sleep.c b/mysys/mf_sleep.c
index f33a904cf5a..49db465e7c5 100644
--- a/mysys/mf_sleep.c
+++ b/mysys/mf_sleep.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/* Wait a given time (On systems that dont have sleep !!; MSDOS) */
diff --git a/mysys/mf_sort.c b/mysys/mf_sort.c
index 754a1deb1a7..0dc6c78a589 100644
--- a/mysys/mf_sort.c
+++ b/mysys/mf_sort.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/* Sort of string pointers in string-order with radix or qsort */
@@ -25,7 +24,7 @@ void my_string_ptr_sort(void *base, uint items, size_s size)
#if INT_MAX > 65536L
uchar **ptr=0;
- if (size <= 20 && items >= 1000 &&
+ if (size <= 20 && items >= 1000 && items < 100000 &&
(ptr= (uchar**) my_malloc(items*sizeof(char*),MYF(0))))
{
radixsort_for_str_ptr((uchar**) base,items,size,ptr);
diff --git a/mysys/mf_soundex.c b/mysys/mf_soundex.c
index 827385a1466..4f7aa7da601 100644
--- a/mysys/mf_soundex.c
+++ b/mysys/mf_soundex.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/****************************************************************
* SOUNDEX ALGORITHM in C *
diff --git a/mysys/mf_stripp.c b/mysys/mf_stripp.c
index 6ebdce4cff6..d2fd171ec8c 100644
--- a/mysys/mf_stripp.c
+++ b/mysys/mf_stripp.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/* T|mmer en str{ng p{ slut_space */
diff --git a/mysys/mf_tempfile.c b/mysys/mf_tempfile.c
index 465311088c1..86e43e5b6fc 100644
--- a/mysys/mf_tempfile.c
+++ b/mysys/mf_tempfile.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include "mysys_priv.h"
#include <m_string.h>
@@ -90,9 +89,10 @@ File create_temp_file(char *to, const char *dir, const char *prefix,
uint pfx_len;
File org_file;
- pfx_len=(strmov(strnmov(prefix_buff,
- prefix ? prefix : "tmp.",
- sizeof(prefix_buff)-7),"XXXXXX") - prefix_buff);
+ pfx_len= (uint) (strmov(strnmov(prefix_buff,
+ prefix ? prefix : "tmp.",
+ sizeof(prefix_buff)-7),"XXXXXX") -
+ prefix_buff);
if (!dir && ! (dir =getenv("TMPDIR")))
dir=P_tmpdir;
if (strlen(dir)+ pfx_len > FN_REFLEN-2)
@@ -100,8 +100,7 @@ File create_temp_file(char *to, const char *dir, const char *prefix,
errno=my_errno= ENAMETOOLONG;
return 1;
}
- strmov(to,dir);
- strmov(convert_dirname(to),prefix_buff);
+ strmov(convert_dirname(to,dir,NullS),prefix_buff);
org_file=mkstemp(to);
file=my_register_filename(org_file, to, FILE_BY_MKSTEMP,
EE_CANTCREATEFILE, MyFlags);
@@ -178,7 +177,7 @@ File create_temp_file(char *to, const char *dir, const char *prefix,
if (end_pos != to && end_pos[-1] != FN_LIBCHAR)
*end_pos++=FN_LIBCHAR;
end_pos=strmov(end_pos,pfx);
-
+
for (length=0 ; length < 8 && uniq ; length++)
{
*end_pos++= _dig_vec[(int) (uniq & 31)];
diff --git a/mysys/mf_unixpath.c b/mysys/mf_unixpath.c
index 6ae29f99136..9efc3e5d9b8 100644
--- a/mysys/mf_unixpath.c
+++ b/mysys/mf_unixpath.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include "mysys_priv.h"
#include <m_string.h>
diff --git a/mysys/mf_util.c b/mysys/mf_util.c
index 12af323680e..132c83b4623 100644
--- a/mysys/mf_util.c
+++ b/mysys/mf_util.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/* Utilities with are missing on some systems */
diff --git a/mysys/mf_wcomp.c b/mysys/mf_wcomp.c
index 5f1ab9b813e..bdcfb0501d8 100644
--- a/mysys/mf_wcomp.c
+++ b/mysys/mf_wcomp.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/* Funktions for comparing with wild-cards */
diff --git a/mysys/mf_wfile.c b/mysys/mf_wfile.c
index 87d1392250a..e9e12c72755 100644
--- a/mysys/mf_wfile.c
+++ b/mysys/mf_wfile.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/* Functions for finding files with wildcards */
diff --git a/mysys/mulalloc.c b/mysys/mulalloc.c
index 8a7ee312aa9..a2960aec4b5 100644
--- a/mysys/mulalloc.c
+++ b/mysys/mulalloc.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/* Malloc many pointers at the same time */
/* format myFlags,ptr,length,ptr,length ... until null ptr */
diff --git a/mysys/my_alarm.c b/mysys/my_alarm.c
index aab01ad77f4..70daf4a9dd0 100644
--- a/mysys/my_alarm.c
+++ b/mysys/my_alarm.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/* Function to set a varible when we got a alarm */
/* Used by my_lock samt functions in m_alarm.h */
diff --git a/mysys/my_alloc.c b/mysys/my_alloc.c
index db482454e69..789e64526a3 100644
--- a/mysys/my_alloc.c
+++ b/mysys/my_alloc.c
@@ -1,27 +1,29 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/* Routines to handle mallocing of results which will be freed the same time */
-#include <global.h>
+#include <my_global.h>
#include <my_sys.h>
#include <m_string.h>
+#undef EXTRA_DEBUG
+#define EXTRA_DEBUG
-void init_alloc_root(MEM_ROOT *mem_root, uint block_size, uint pre_alloc_size)
+void init_alloc_root(MEM_ROOT *mem_root, uint block_size,
+ uint pre_alloc_size __attribute__((unused)))
{
mem_root->free=mem_root->used=0;
mem_root->min_malloc=32;
@@ -55,6 +57,7 @@ gptr alloc_root(MEM_ROOT *mem_root,unsigned int Size)
return((gptr) 0); /* purecov: inspected */
}
next->next=mem_root->used;
+ next->size= Size;
mem_root->used=next;
return (gptr) (((char*) next)+ALIGN_SIZE(sizeof(USED_MEM)));
#else
@@ -100,7 +103,34 @@ gptr alloc_root(MEM_ROOT *mem_root,unsigned int Size)
#endif
}
- /* deallocate everything used by alloc_root */
+/* Mark all data in blocks free for reusage */
+
+static inline void mark_blocks_free(MEM_ROOT* root)
+{
+ reg1 USED_MEM *next;
+ reg2 USED_MEM **last;
+
+ /* iterate through (partially) free blocks, mark them free */
+ last= &root->free;
+ for (next= root->free; next; next= *(last= &next->next))
+ next->left= next->size - ALIGN_SIZE(sizeof(USED_MEM));
+
+ /* Combine the free and the used list */
+ *last= next=root->used;
+
+ /* now go through the used blocks and mark them free */
+ for (; next; next= next->next)
+ next->left= next->size - ALIGN_SIZE(sizeof(USED_MEM));
+
+ /* Now everything is set; Indicate that nothing is used anymore */
+ root->used= 0;
+}
+
+
+/*
+ Deallocate everything used by alloc_root or just move
+ used blocks to free list if called with MY_USED_TO_FREE
+*/
void free_root(MEM_ROOT *root, myf MyFlags)
{
@@ -109,18 +139,23 @@ void free_root(MEM_ROOT *root, myf MyFlags)
if (!root)
DBUG_VOID_RETURN; /* purecov: inspected */
+ if (MyFlags & MY_MARK_BLOCKS_FREE)
+ {
+ mark_blocks_free(root);
+ DBUG_VOID_RETURN;
+ }
if (!(MyFlags & MY_KEEP_PREALLOC))
root->pre_alloc=0;
- for ( next=root->used; next ;)
+ for (next=root->used; next ;)
{
old=next; next= next->next ;
if (old != root->pre_alloc)
my_free((gptr) old,MYF(0));
}
- for (next= root->free ; next ; )
+ for (next=root->free ; next ;)
{
- old=next; next= next->next ;
+ old=next; next= next->next;
if (old != root->pre_alloc)
my_free((gptr) old,MYF(0));
}
@@ -134,13 +169,45 @@ void free_root(MEM_ROOT *root, myf MyFlags)
DBUG_VOID_RETURN;
}
+/*
+ Find block that contains an object and set the pre_alloc to it
+*/
+
+void set_prealloc_root(MEM_ROOT *root, char *ptr)
+{
+ USED_MEM *next;
+ for (next=root->used; next ; next=next->next)
+ {
+ if ((char*) next <= ptr && (char*) next + next->size > ptr)
+ {
+ root->pre_alloc=next;
+ return;
+ }
+ }
+ for (next=root->free ; next ; next=next->next)
+ {
+ if ((char*) next <= ptr && (char*) next + next->size > ptr)
+ {
+ root->pre_alloc=next;
+ return;
+ }
+ }
+}
+
char *strdup_root(MEM_ROOT *root,const char *str)
{
- uint len= (uint) strlen(str)+1;
+ return strmake_root(root, str, strlen(str));
+}
+
+char *strmake_root(MEM_ROOT *root,const char *str, uint len)
+{
char *pos;
- if ((pos=alloc_root(root,len)))
+ if ((pos=alloc_root(root,len+1)))
+ {
memcpy(pos,str,len);
+ pos[len]=0;
+ }
return pos;
}
diff --git a/mysys/my_append.c b/mysys/my_append.c
index 0d3296fb278..2e08b4b4c05 100644
--- a/mysys/my_append.c
+++ b/mysys/my_append.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
#define USES_TYPES /* sys/types is included */
#include "mysys_priv.h"
diff --git a/mysys/my_bit.c b/mysys/my_bit.c
new file mode 100644
index 00000000000..0ff487afe03
--- /dev/null
+++ b/mysys/my_bit.c
@@ -0,0 +1,31 @@
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+/* Some useful bit functions */
+
+#include "mysys_priv.h"
+
+/*
+ Find smallest X in 2^X >= value
+ This can be used to divide a number with value by doing a shift instead
+*/
+
+uint my_bit_log2(ulong value)
+{
+ uint bit;
+ for (bit=0 ; value > 1 ; value>>=1, bit++) ;
+ return bit;
+}
diff --git a/mysys/my_bitmap.c b/mysys/my_bitmap.c
index a18fcba0b60..8834dda98e1 100644
--- a/mysys/my_bitmap.c
+++ b/mysys/my_bitmap.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/*
Handling of uchar arrays as large bitmaps.
@@ -26,7 +25,6 @@
#include "mysys_priv.h"
#include <my_bitmap.h>
#include <assert.h>
-#include <string.h>
#include <m_string.h>
inline void bitmap_lock(MY_BITMAP* map)
@@ -50,7 +48,7 @@ my_bool bitmap_init(MY_BITMAP *map, uint bitmap_size, my_bool thread_safe)
if (!(map->bitmap=(uchar*) my_malloc((bitmap_size+7)/8,
MYF(MY_WME | MY_ZEROFILL))))
return 1;
- dbug_assert(bitmap_size != ~(uint) 0);
+ DBUG_ASSERT(bitmap_size != ~(uint) 0);
#ifdef THREAD
if ((map->thread_safe = thread_safe))
pthread_mutex_init(&map->mutex, MY_MUTEX_INIT_FAST);
@@ -123,6 +121,7 @@ void bitmap_clear_bit(MY_BITMAP *map, uint bitmap_bit)
}
}
+
void bitmap_set_all(MY_BITMAP* map)
{
bitmap_lock(map);
diff --git a/mysys/my_chsize.c b/mysys/my_chsize.c
index 2c07e8d136f..aeab9e47ee2 100644
--- a/mysys/my_chsize.c
+++ b/mysys/my_chsize.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include "mysys_priv.h"
#include "mysys_err.h"
diff --git a/mysys/my_clock.c b/mysys/my_clock.c
index e7d1758fa2e..e49b2f85b66 100644
--- a/mysys/my_clock.c
+++ b/mysys/my_clock.c
@@ -1,22 +1,21 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
#define USES_TYPES
-#include "global.h"
+#include "my_global.h"
#if !defined(_MSC_VER) && !defined(__BORLANDC__) && !defined(OS2)
#include "mysys_priv.h"
diff --git a/mysys/my_compress.c b/mysys/my_compress.c
index f97d28c25ea..1e46584d525 100644
--- a/mysys/my_compress.c
+++ b/mysys/my_compress.c
@@ -1,26 +1,27 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
-/* Written by Sinisa Milivojevic <sinisa@coresinc.com> */
+/* Written by Sinisa Milivojevic <sinisa@mysql.com> */
-#include <global.h>
+#include <my_global.h>
#ifdef HAVE_COMPRESS
#include <my_sys.h>
+#ifndef SCO
#include <m_string.h>
+#endif
#include <zlib.h>
/*
diff --git a/mysys/my_copy.c b/mysys/my_copy.c
index 9b02d84d063..253608c5306 100644
--- a/mysys/my_copy.c
+++ b/mysys/my_copy.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
#define USES_TYPES /* sys/types is included */
#include "mysys_priv.h"
diff --git a/mysys/my_create.c b/mysys/my_create.c
index 5a10b0fd8b5..5fa97a9ca78 100644
--- a/mysys/my_create.c
+++ b/mysys/my_create.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
#define USES_TYPES
#include "mysys_priv.h"
diff --git a/mysys/my_delete.c b/mysys/my_delete.c
index 77d5f311418..5670f03da64 100644
--- a/mysys/my_delete.c
+++ b/mysys/my_delete.c
@@ -1,22 +1,20 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
-#include "mysys_priv.h"
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+#include "mysys_priv.h"
#include "mysys_err.h"
int my_delete(const char *name, myf MyFlags)
diff --git a/mysys/my_div.c b/mysys/my_div.c
index 24794679376..e47589a087c 100644
--- a/mysys/my_div.c
+++ b/mysys/my_div.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include "mysys_priv.h"
diff --git a/mysys/my_dup.c b/mysys/my_dup.c
new file mode 100644
index 00000000000..df298780e3e
--- /dev/null
+++ b/mysys/my_dup.c
@@ -0,0 +1,39 @@
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#define USES_TYPES
+#include "mysys_priv.h"
+#include "mysys_err.h"
+#include <my_dir.h>
+#include <errno.h>
+#if defined(MSDOS) || defined(__WIN__) || defined(__EMX__)
+#include <share.h>
+#endif
+
+ /* Open a file */
+
+File my_dup(File file, myf MyFlags)
+{
+ File fd;
+ const char *filename;
+ DBUG_ENTER("my_dup");
+ DBUG_PRINT("my",("file: %d MyFlags: %d", MyFlags));
+ fd = dup(file);
+ filename= (((int) file < MY_NFILE) ?
+ my_file_info[(int) file].name : "Unknown");
+ DBUG_RETURN(my_register_filename(fd, filename, FILE_BY_DUP,
+ EE_FILENOTFOUND, MyFlags));
+} /* my_open */
diff --git a/mysys/my_error.c b/mysys/my_error.c
index 4aa946aa6c3..61f8c16aba5 100644
--- a/mysys/my_error.c
+++ b/mysys/my_error.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include "mysys_priv.h"
#include "mysys_err.h"
diff --git a/mysys/my_fopen.c b/mysys/my_fopen.c
index e1575b0af48..d3b0b90f9c5 100644
--- a/mysys/my_fopen.c
+++ b/mysys/my_fopen.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include "mysys_priv.h"
#include "my_static.h"
diff --git a/mysys/my_fstream.c b/mysys/my_fstream.c
index d93caadbcdc..94f3aaf3464 100644
--- a/mysys/my_fstream.c
+++ b/mysys/my_fstream.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/* USE_MY_STREAM isn't set because we can't thrust my_fclose! */
@@ -147,7 +146,8 @@ uint my_fwrite(FILE *stream, const byte *Buffer, uint Count, myf MyFlags)
/* Seek to position in file */
/* ARGSUSED */
-my_off_t my_fseek(FILE *stream, my_off_t pos, int whence, myf MyFlags)
+my_off_t my_fseek(FILE *stream, my_off_t pos, int whence,
+ myf MyFlags __attribute__((unused)))
{
DBUG_ENTER("my_fseek");
DBUG_PRINT("my",("stream: %lx pos: %lu whence: %d MyFlags: %d",
@@ -160,7 +160,7 @@ my_off_t my_fseek(FILE *stream, my_off_t pos, int whence, myf MyFlags)
/* Tell current position of file */
/* ARGSUSED */
-my_off_t my_ftell(FILE *stream, myf MyFlags)
+my_off_t my_ftell(FILE *stream, myf MyFlags __attribute__((unused)))
{
off_t pos;
DBUG_ENTER("my_ftell");
diff --git a/mysys/my_getopt.c b/mysys/my_getopt.c
new file mode 100644
index 00000000000..a28d3dd4e3c
--- /dev/null
+++ b/mysys/my_getopt.c
@@ -0,0 +1,578 @@
+/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <my_config.h>
+#include <my_global.h>
+#include <m_string.h>
+#include <stdlib.h>
+#include <my_getopt.h>
+#include <assert.h>
+
+static int findopt (char *optpat, uint length,
+ const struct my_option **opt_res,
+ char **ffname);
+static my_bool compare_strings (register const char *s, register const char *t,
+ uint length);
+static longlong getopt_ll (char *arg, const struct my_option *optp, int *err);
+static void init_variables(const struct my_option *options);
+
+
+#define DISABLE_OPTION_COUNT 2
+
+static const char *special_opt_prefix[]=
+{"skip", "disable", "enable", "maximum", 0};
+
+
+/* Return error values from handle_options */
+
+#define ERR_UNKNOWN_OPTION 1
+#define ERR_AMBIGUOUS_OPTION 2
+#define ERR_NO_ARGUMENT_ALLOWED 3
+#define ERR_ARGUMENT_REQUIRED 4
+#define ERR_VAR_PREFIX_NOT_UNIQUE 5
+#define ERR_UNKNOWN_VARIABLE 6
+#define ERR_MUST_BE_VARIABLE 7
+#define ERR_UNKNOWN_SUFFIX 8
+#define ERR_NO_PTR_TO_VARIABLE 9
+
+
+/*
+ function: handle_options
+
+ Sort options; put options first, until special end of options (--), or
+ until end of argv. Parse options; check that the given option matches with
+ one of the options in struct 'my_option', return error in case of ambiguous
+ or unknown option. Check that option was given an argument if it requires
+ one. Call function 'get_one_option()' once for each option.
+*/
+
+int handle_options(int *argc, char ***argv,
+ const struct my_option *longopts,
+ my_bool (*get_one_option)(int,
+ const struct my_option *,
+ char *))
+{
+ uint opt_found, argvpos= 0, length, spec_len, i;
+ int err;
+ my_bool end_of_options= 0, must_be_var, set_maximum_value, special_used;
+ char *progname= *(*argv), **pos, *optend, *prev_found;
+ const struct my_option *optp;
+
+ LINT_INIT(opt_found);
+ (*argc)--; /* Skip the program name */
+ (*argv)++; /* --- || ---- */
+ init_variables(longopts);
+ for (pos= *argv; *pos; pos++)
+ {
+ char *cur_arg= *pos;
+ if (cur_arg[0] == '-' && cur_arg[1] && !end_of_options) /* must be opt */
+ {
+ char *argument= 0;
+ must_be_var= 0;
+ set_maximum_value= 0;
+ special_used= 0;
+
+ cur_arg++; /* skip '-' */
+ if (*cur_arg == 'O')
+ {
+ must_be_var= 1;
+
+ if (!(*++cur_arg)) /* If not -Ovar=# */
+ {
+ /* the argument must be in next argv */
+ if (!*++pos)
+ {
+ fprintf(stderr, "%s: Option '-O' requires an argument\n",
+ progname);
+ return ERR_ARGUMENT_REQUIRED;
+ }
+ cur_arg= *pos;
+ (*argc)--;
+ }
+ }
+ else if (*cur_arg == '-') /* check for long option, or --set-variable */
+ {
+ if (!compare_strings(cur_arg, "-set-variable", 13))
+ {
+ must_be_var= 1;
+ if (cur_arg[13] == '=')
+ {
+ cur_arg+= 14;
+ if (!*cur_arg)
+ {
+ fprintf(stderr,
+ "%s: Option '--set-variable' requires an argument\n",
+ progname);
+ return ERR_ARGUMENT_REQUIRED;
+ }
+ }
+ else if (cur_arg[14]) /* garbage, or another option. break out */
+ must_be_var= 0;
+ else
+ {
+ /* the argument must be in next argv */
+ if (!*++pos)
+ {
+ fprintf(stderr,
+ "%s: Option '--set-variable' requires an argument\n",
+ progname);
+ return ERR_ARGUMENT_REQUIRED;
+ }
+ cur_arg= *pos;
+ (*argc)--;
+ }
+ }
+ else if (!must_be_var)
+ {
+ if (!*++cur_arg) /* skip the double dash */
+ {
+ /* '--' means end of options, look no further */
+ end_of_options= 1;
+ (*argc)--;
+ continue;
+ }
+ }
+ optend= strcend(cur_arg, '=');
+ length= optend - cur_arg;
+ if (*optend == '=')
+ optend++;
+ else
+ optend=0;
+
+ /*
+ Find first the right option. Return error in case of an ambiguous,
+ or unknown option
+ */
+ optp= longopts;
+ if (!(opt_found= findopt(cur_arg, length, &optp, &prev_found)))
+ {
+ /*
+ Didn't find any matching option. Let's see if someone called
+ option with a special option prefix
+ */
+ if (!must_be_var)
+ {
+ if (optend)
+ must_be_var= 1;
+ for (i= 0; special_opt_prefix[i]; i++)
+ {
+ spec_len= strlen(special_opt_prefix[i]);
+ if (!compare_strings(special_opt_prefix[i], cur_arg, spec_len) &&
+ cur_arg[spec_len] == '-')
+ {
+ /*
+ We were called with a special prefix, we can reuse opt_found
+ */
+ special_used= 1;
+ cur_arg += (spec_len + 1);
+ if ((opt_found= findopt(cur_arg, length - (spec_len + 1),
+ &optp, &prev_found)))
+ {
+ if (opt_found > 1)
+ {
+ fprintf(stderr,
+ "%s: ambiguous option '--%s-%s' (--%s-%s)\n",
+ progname, special_opt_prefix[i], cur_arg,
+ special_opt_prefix[i], prev_found);
+ return ERR_AMBIGUOUS_OPTION;
+ }
+ if (i < DISABLE_OPTION_COUNT)
+ optend= (char*) "0";
+ else if (!compare_strings(special_opt_prefix[i],"enable",6))
+ optend= (char*) "1";
+ else if (!compare_strings(special_opt_prefix[i],"maximum",7))
+ {
+ set_maximum_value= 1;
+ must_be_var= 1;
+ }
+ break; /* break from the inner loop, main loop continues */
+ }
+ }
+ }
+ }
+ if (!opt_found)
+ {
+ if (must_be_var)
+ {
+ fprintf(stderr,
+ "%s: unknown variable '%s'\n", progname, cur_arg);
+ return ERR_UNKNOWN_VARIABLE;
+ }
+ else
+ {
+ fprintf(stderr,
+ "%s: unknown option '--%s'\n", progname, cur_arg);
+ return ERR_UNKNOWN_OPTION;
+ }
+ }
+ }
+ if (opt_found > 1)
+ {
+ if (must_be_var)
+ {
+ fprintf(stderr, "%s: variable prefix '%s' is not unique\n",
+ progname, cur_arg);
+ return ERR_VAR_PREFIX_NOT_UNIQUE;
+ }
+ else
+ {
+ fprintf(stderr, "%s: ambiguous option '--%s' (%s, %s)\n",
+ progname, cur_arg, prev_found, optp->name);
+ return ERR_AMBIGUOUS_OPTION;
+ }
+ }
+ if (must_be_var && !optp->value)
+ {
+ fprintf(stderr, "%s: the argument '%s' is not an variable\n",
+ progname, *pos);
+ return ERR_MUST_BE_VARIABLE;
+ }
+ if (optp->arg_type == NO_ARG && optend && !special_used)
+ {
+ fprintf(stderr, "%s: option '--%s' cannot take an argument\n",
+ progname, optp->name);
+ return ERR_NO_ARGUMENT_ALLOWED;
+ }
+ else if (optp->arg_type == REQUIRED_ARG && !optend)
+ {
+ /* Check if there are more arguments after this one */
+ if (!*++pos)
+ {
+ fprintf(stderr, "%s: option '--%s' requires an argument\n",
+ progname, optp->name);
+ return ERR_ARGUMENT_REQUIRED;
+ }
+ argument= *pos;
+ (*argc)--;
+ }
+ else
+ argument= optend;
+ }
+ else /* must be short option */
+ {
+ for (optend= cur_arg; *optend; optend++, opt_found= 0)
+ {
+ for (optp= longopts; optp->id; optp++)
+ {
+ if (optp->id == (int) (uchar) *optend)
+ {
+ /* Option recognized. Find next what to do with it */
+ opt_found= 1;
+ if (optp->arg_type == REQUIRED_ARG || optp->arg_type == OPT_ARG)
+ {
+ if (*(optend + 1))
+ {
+ // The rest of the option is option argument
+ argument= optend + 1;
+ // This is in effect a jump out of the outer loop
+ optend= (char*) " ";
+ }
+ else if (optp->arg_type == REQUIRED_ARG)
+ {
+ /* Check if there are more arguments after this one */
+ if (!*++pos)
+ {
+ fprintf(stderr, "%s: option '-%c' requires an argument\n",
+ progname, optp->id);
+ return ERR_ARGUMENT_REQUIRED;
+ }
+ argument= *pos;
+ (*argc)--;
+ /* the other loop will break, because *optend + 1 == 0 */
+ }
+ }
+ get_one_option(optp->id, optp, argument);
+ break;
+ }
+ }
+ if (!opt_found)
+ {
+ fprintf(stderr,
+ "%s: unknown option '-%c'\n", progname, *cur_arg);
+ return ERR_UNKNOWN_OPTION;
+ }
+ }
+ (*argc)--; /* option handled (short), decrease argument count */
+ continue;
+ }
+ if (optp->value)
+ {
+ gptr *result_pos= (set_maximum_value) ?
+ optp->u_max_value : optp->value;
+ if (!result_pos)
+ {
+ fprintf(stderr,
+ "%s: Can't set a value for %s\n", progname, optp->name);
+ return ERR_NO_PTR_TO_VARIABLE;
+ }
+ if (optp->var_type == GET_LONG)
+ *((long*) result_pos)= (long) getopt_ll(argument, optp, &err);
+ else if (optp->var_type == GET_LL)
+ *((longlong*) result_pos)= getopt_ll(argument, optp, &err);
+ else if (optp->var_type == GET_STR)
+ *((char**) result_pos)= argument;
+ if (err)
+ return ERR_UNKNOWN_SUFFIX;
+ }
+ else
+ get_one_option(optp->id, optp, argument);
+
+ (*argc)--; /* option handled (short or long), decrease argument count */
+ }
+ else /* non-option found */
+ (*argv)[argvpos++]= cur_arg;
+ }
+ return 0;
+}
+
+
+/*
+ function: findopt
+
+ Arguments: opt_pattern, length of opt_pattern, opt_struct, first found
+ name (ffname)
+
+ Go through all options in the my_option struct. Return number
+ of options found that match the pattern and in the argument
+ list the option found, if any. In case of ambiguous option, store
+ the name in ffname argument
+*/
+
+static int findopt (char *optpat, uint length,
+ const struct my_option **opt_res,
+ char **ffname)
+{
+ int count;
+ struct my_option *opt= (struct my_option *) *opt_res;
+
+ for (count= 0; opt->name; opt++)
+ {
+ if (!compare_strings(opt->name, optpat, length)) /* match found */
+ {
+ (*opt_res)= opt;
+ if (!count)
+ *ffname= (char *) opt->name; /* we only need to know one prev */
+ if (length == strlen(opt->name)) /* exact match */
+ return 1;
+ count++;
+ }
+ }
+ return count;
+}
+
+
+/*
+ function: compare_strings
+
+ Works like strncmp, other than 1.) considers '-' and '_' the same.
+ 2.) Returns -1 if strings differ, 0 if they are equal
+*/
+
+static my_bool compare_strings(register const char *s, register const char *t,
+ uint length)
+{
+ char const *end= s + length;
+ for (;s != end ; s++, t++)
+ {
+ if ((*s != '-' ? *s : '_') != (*t != '-' ? *t : '_'))
+ return 1;
+ }
+ return 0;
+}
+
+
+/*
+ function: getopt_ll
+
+ Evaluates and returns the value that user gave as an argument
+ to a variable. Recognizes (case insensitive) K as KILO, M as MEGA
+ and G as GIGA bytes. Some values must be in certain blocks, as
+ defined in the given my_option struct, this function will check
+ that those values are honored.
+ In case of an error, set error value in *err.
+*/
+
+static longlong getopt_ll (char *arg, const struct my_option *optp, int *err)
+{
+ char *endchar;
+ longlong num;
+
+ *err= 0;
+ num= strtoll(arg, &endchar, 10);
+ if (*endchar == 'k' || *endchar == 'K')
+ num*= 1024L;
+ else if (*endchar == 'm' || *endchar == 'M')
+ num*= 1024L * 1024L;
+ else if (*endchar == 'g' || *endchar == 'G')
+ num*= 1024L * 1024L * 1024L;
+ else if (*endchar)
+ {
+ fprintf(stderr,
+ "Unknown suffix '%c' used for variable '%s' (value '%s')\n",
+ *endchar, optp->name, arg);
+ *err= 1;
+ }
+ if (num < (longlong) optp->min_value)
+ num= (longlong) optp->min_value;
+ else if (num > 0 && (ulonglong) num > (ulonglong) (ulong) optp->max_value
+ && optp->max_value) // if max value is not set -> no upper limit
+ num= (longlong) (ulong) optp->max_value;
+ num= ((num - (longlong) optp->sub_size) / (optp->block_size ?
+ (ulonglong) optp->block_size :
+ 1L));
+ return (longlong) (num * (optp->block_size ? (ulonglong) optp->block_size :
+ 1L));
+}
+
+
+/*
+ function: init_variables
+
+ initialize all variables to their default values
+*/
+
+static void init_variables(const struct my_option *options)
+{
+ for (; options->name; options++)
+ {
+ if (options->value)
+ {
+ if (options->var_type == GET_LONG)
+ *((long*) options->u_max_value)= *((long*) options->value)=
+ options->def_value;
+ else if (options->var_type == GET_LL)
+ *((longlong*) options->u_max_value)= *((longlong*) options->value)=
+ options->def_value;
+ }
+ }
+}
+
+
+/*
+ function: my_print_options
+
+ Print help for all options and variables.
+*/
+
+void my_print_help(const struct my_option *options)
+{
+ uint col, name_space= 22, comment_space= 57;
+ const char *line_end;
+ const struct my_option *optp;
+
+ for (optp= options; optp->id; optp++)
+ {
+ if (optp->id < 256)
+ {
+ printf(" -%c, ", optp->id);
+ col= 6;
+ }
+ else
+ {
+ printf(" ");
+ col= 2;
+ }
+ printf("--%s", optp->name);
+ col+= 2 + strlen(optp->name);
+ if (optp->var_type == GET_STR)
+ {
+ printf("=name ");
+ col+= 6;
+ }
+ else if (optp->var_type == GET_NO_ARG)
+ {
+ putchar(' ');
+ col++;
+ }
+ else
+ {
+ printf("=# ");
+ col+= 3;
+ }
+ if (col > name_space)
+ {
+ putchar('\n');
+ col= 0;
+ }
+ for (; col < name_space; col++)
+ putchar(' ');
+ if (optp->comment && *optp->comment)
+ {
+ const char *comment= optp->comment, *end= strend(comment);
+
+ while ((uint) (end - comment) > comment_space)
+ {
+ for (line_end= comment + comment_space; *line_end != ' '; line_end--);
+ for (; comment != line_end; comment++)
+ putchar(*comment);
+ comment++; // skip the space, as a newline will take it's place now
+ putchar('\n');
+ for (col= 0; col < name_space; col++)
+ putchar(' ');
+ }
+ printf("%s", comment);
+ }
+ putchar('\n');
+ }
+}
+
+
+/*
+ function: my_print_options
+
+ Print variables.
+*/
+
+void my_print_variables(const struct my_option *options)
+{
+ uint name_space= 34, length;
+ char buff[255];
+ const struct my_option *optp;
+
+ printf("Variables (--variable-name=value) Default value\n");
+ printf("--------------------------------- -------------\n");
+ for (optp= options; optp->id; optp++)
+ {
+ if (optp->value)
+ {
+ printf("%s", optp->name);
+ length= strlen(optp->name);
+ for (; length < name_space; length++)
+ putchar(' ');
+ if (optp->var_type == GET_STR)
+ {
+ if (!optp->def_value && !*((char**) optp->value))
+ printf("(No default value)\n");
+ else
+ printf("%s\n", *((char**) optp->value));
+ }
+ else if (optp->var_type == GET_LONG)
+ {
+ if (!optp->def_value && !*((long*) optp->value))
+ printf("(No default value)\n");
+ else
+ printf("%lu\n", *((long*) optp->value));
+ }
+ else
+ {
+ if (!optp->def_value && !*((longlong*) optp->value))
+ printf("(No default value)\n");
+ else
+ printf("%s\n", llstr(*((longlong*) optp->value), buff));
+ }
+ }
+ }
+}
diff --git a/mysys/my_getwd.c b/mysys/my_getwd.c
index 6bdea813fe4..22c6a4dbc2b 100644
--- a/mysys/my_getwd.c
+++ b/mysys/my_getwd.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/* my_setwd() and my_getwd() works with intern_filenames !! */
diff --git a/mysys/my_init.c b/mysys/my_init.c
index 3bc87fd179d..c4e6132aa9c 100644
--- a/mysys/my_init.c
+++ b/mysys/my_init.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include "mysys_priv.h"
#include "my_static.h"
@@ -45,9 +44,8 @@ static my_bool win32_init_tcp_ip();
#else
#define my_win_init()
#endif
-static my_bool my_init_done=0;
-
+my_bool my_init_done=0;
static ulong atoi_octal(const char *str)
{
@@ -169,6 +167,7 @@ Voluntary context switches %ld, Involuntary context switches %ld\n",
pthread_mutex_destroy(&THR_LOCK_malloc);
pthread_mutex_destroy(&THR_LOCK_open);
DBUG_POP(); /* Must be done before my_thread_end */
+ my_once_free();
my_thread_end();
my_thread_global_end();
#endif
diff --git a/mysys/my_lib.c b/mysys/my_lib.c
index f9774d8a4aa..a06120894c5 100644
--- a/mysys/my_lib.c
+++ b/mysys/my_lib.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/* TODO: check for overun of memory for names. */
/* Convert MSDOS-TIME to standar time_t */
@@ -112,6 +111,10 @@ MY_DIR *my_dir(const char *path, myf MyFlags)
dirp = opendir(directory_file_name(tmp_path,(my_string) path));
size = STARTSIZE;
+#if defined(__amiga__)
+ if ((dirp->dd_fd) < 0) /* Directory doesn't exists */
+ goto error;
+#endif
if (dirp == NULL || ! (buffer = (char *) my_malloc(size, MyFlags)))
goto error;
@@ -183,7 +186,7 @@ MY_DIR *my_dir(const char *path, myf MyFlags)
my_errno=errno;
if (dirp)
(void) closedir(dirp);
- if (MyFlags & (MY_FAE+MY_WME))
+ if (MyFlags & (MY_FAE | MY_WME))
my_error(EE_DIR,MYF(ME_BELL+ME_WAITTANG),path,my_errno);
DBUG_RETURN((MY_DIR *) NULL);
} /* my_dir */
@@ -580,13 +583,15 @@ error:
** Note that MY_STAT is assumed to be same as struct stat
****************************************************************************/
-int my_fstat(int Filedes, MY_STAT *stat_area, myf MyFlags )
+int my_fstat(int Filedes, MY_STAT *stat_area,
+ myf MyFlags __attribute__((unused)))
{
DBUG_ENTER("my_fstat");
DBUG_PRINT("my",("fd: %d MyFlags: %d",Filedes,MyFlags));
DBUG_RETURN(fstat(Filedes, (struct stat *) stat_area));
}
+
MY_STAT *my_stat(const char *path, MY_STAT *stat_area, myf my_flags)
{
int m_used;
@@ -611,4 +616,3 @@ error:
}
DBUG_RETURN((MY_STAT *) NULL);
} /* my_stat */
-
diff --git a/mysys/my_lock.c b/mysys/my_lock.c
index c002f447f59..44ac53677ba 100644
--- a/mysys/my_lock.c
+++ b/mysys/my_lock.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include "mysys_priv.h"
#include "mysys_err.h"
diff --git a/mysys/my_lockmem.c b/mysys/my_lockmem.c
index 9c77c885797..6712c387a71 100644
--- a/mysys/my_lockmem.c
+++ b/mysys/my_lockmem.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/* Alloc a block of locked memory */
diff --git a/mysys/my_lread.c b/mysys/my_lread.c
index 94ed258151e..601d772b844 100644
--- a/mysys/my_lread.c
+++ b/mysys/my_lread.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include "mysys_priv.h"
#include "mysys_err.h"
diff --git a/mysys/my_lwrite.c b/mysys/my_lwrite.c
index 734916173ce..e1a3decd053 100644
--- a/mysys/my_lwrite.c
+++ b/mysys/my_lwrite.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include "mysys_priv.h"
#include "mysys_err.h"
diff --git a/mysys/my_malloc.c b/mysys/my_malloc.c
index c2df22ec7ec..1e7cdd3a3b5 100644
--- a/mysys/my_malloc.c
+++ b/mysys/my_malloc.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#ifdef SAFEMALLOC /* We don't need SAFEMALLOC here */
#undef SAFEMALLOC
diff --git a/mysys/my_messnc.c b/mysys/my_messnc.c
index 0dd3be5ba98..6bb88443109 100644
--- a/mysys/my_messnc.c
+++ b/mysys/my_messnc.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include "mysys_priv.h"
diff --git a/mysys/my_mkdir.c b/mysys/my_mkdir.c
index 3685312132c..ba1f4c1f2d8 100644
--- a/mysys/my_mkdir.c
+++ b/mysys/my_mkdir.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include "mysys_priv.h"
#include "mysys_err.h"
diff --git a/mysys/my_net.c b/mysys/my_net.c
index 1c91f7ff802..a4a842ac15e 100644
--- a/mysys/my_net.c
+++ b/mysys/my_net.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/* thread safe version of some common functions */
diff --git a/mysys/my_once.c b/mysys/my_once.c
index 0b8b5addc16..3358112551f 100644
--- a/mysys/my_once.c
+++ b/mysys/my_once.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/* Not MT-SAFE */
diff --git a/mysys/my_open.c b/mysys/my_open.c
index 748113528a1..a0a802b8a2e 100644
--- a/mysys/my_open.c
+++ b/mysys/my_open.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
#define USES_TYPES
#include "mysys_priv.h"
diff --git a/mysys/my_pread.c b/mysys/my_pread.c
index 5c7d0be5854..661ef48ab3e 100644
--- a/mysys/my_pread.c
+++ b/mysys/my_pread.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include "mysys_priv.h"
#include "mysys_err.h"
diff --git a/mysys/my_pthread.c b/mysys/my_pthread.c
index 8bdbc0f7fd8..37c18a32451 100644
--- a/mysys/my_pthread.c
+++ b/mysys/my_pthread.c
@@ -1,22 +1,22 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/* Functions to get threads more portable */
+#define DONT_REMAP_PTHREAD_FUNCTIONS
#include "mysys_priv.h"
#ifdef THREAD
#include <signal.h>
@@ -424,7 +424,7 @@ struct hostent *my_gethostbyname_r(const char *name,
int buflen, int *h_errnop)
{
struct hostent *hp;
- dbug_assert((size_t) buflen >= sizeof(*result));
+ DBUG_ASSERT((size_t) buflen >= sizeof(*result));
if (gethostbyname_r(name,result, buffer, (size_t) buflen, &hp, h_errnop))
return 0;
return hp;
@@ -436,7 +436,7 @@ struct hostent *my_gethostbyname_r(const char *name,
struct hostent *result, char *buffer,
int buflen, int *h_errnop)
{
- dbug_assert(buflen >= sizeof(struct hostent_data));
+ DBUG_ASSERT(buflen >= sizeof(struct hostent_data));
if (gethostbyname_r(name,result,(struct hostent_data *) buffer) == -1)
{
*h_errnop= errno;
@@ -452,7 +452,7 @@ struct hostent *my_gethostbyname_r(const char *name,
int buflen, int *h_errnop)
{
struct hostent *hp;
- dbug_assert(buflen >= sizeof(struct hostent_data));
+ DBUG_ASSERT(buflen >= sizeof(struct hostent_data));
hp= gethostbyname_r(name,result,(struct hostent_data *) buffer);
*h_errnop= errno;
return hp;
@@ -461,6 +461,41 @@ struct hostent *my_gethostbyname_r(const char *name,
#endif /* GLIBC2_STYLE_GETHOSTBYNAME_R */
#endif
+/*****************************************************************************
+ Patches for HPUX
+ We need these because the pthread_mutex.. code returns -1 on error,
+ instead of the error code.
+
+ Note that currently we only remap pthread_ functions used by MySQL.
+ If we are depending on the value for some other pthread_xxx functions,
+ this has to be added here.
+*****************************************************************************/
+
+#ifdef HPUX
+
+int my_pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex,
+ struct timespec *abstime)
+{
+ int error=pthread_cond_timedwait(cond, mutex, abstime);
+ if (error == -1) /* Safety if the lib is fixed */
+ error=errno;
+ if (error == EAGAIN) /* Correct errno to Posix */
+ error=ETIMEDOUT;
+ return error;
+}
+
+
+int my_pthread_mutex_trylock(pthread_mutex_t *mutex)
+{
+ int error=pthread_mutex_trylock(mutex);
+ if (error == 1) /* Safety if the lib is fixed */
+ return 0; /* Mutex was locked */
+ if (error == -1) /* Safety if the lib is fixed */
+ error=errno;
+ return error;
+}
+
+#endif
/* Some help functions */
diff --git a/mysys/my_quick.c b/mysys/my_quick.c
index 6151d5037ae..44ed3fc0b2c 100644
--- a/mysys/my_quick.c
+++ b/mysys/my_quick.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/* Quicker interface to read & write. Used with my_nosys.h */
diff --git a/mysys/my_read.c b/mysys/my_read.c
index b317630f4bd..0c8962e91a9 100644
--- a/mysys/my_read.c
+++ b/mysys/my_read.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include "mysys_priv.h"
#include "mysys_err.h"
@@ -28,10 +27,11 @@ uint my_read(File Filedes, byte *Buffer, uint Count, myf MyFlags)
/* Max number of bytes returnd */
/* Flags on what to do on error */
{
- uint readbytes;
+ uint readbytes,save_count;
DBUG_ENTER("my_read");
DBUG_PRINT("my",("Fd: %d Buffer: %lx Count: %u MyFlags: %d",
Filedes, Buffer, Count, MyFlags));
+ save_count=Count;
for (;;)
{
@@ -54,12 +54,21 @@ uint my_read(File Filedes, byte *Buffer, uint Count, myf MyFlags)
my_error(EE_EOFERR, MYF(ME_BELL+ME_WAITTANG),
my_filename(Filedes),my_errno);
}
- if ((int) readbytes == -1 || (MyFlags & (MY_FNABP | MY_NABP)))
+ if ((int) readbytes == -1 ||
+ ((MyFlags & (MY_FNABP | MY_NABP)) && !(MyFlags & MY_FULL_IO)))
DBUG_RETURN(MY_FILE_ERROR); /* Return with error */
+ if (readbytes > 0 && (MyFlags & MY_FULL_IO))
+ {
+ Buffer+=readbytes;
+ Count-=readbytes;
+ continue;
+ }
}
if (MyFlags & (MY_NABP | MY_FNABP))
readbytes=0; /* Ok on read */
+ else if (MyFlags & MY_FULL_IO)
+ readbytes=save_count;
break;
}
DBUG_RETURN(readbytes);
diff --git a/mysys/my_realloc.c b/mysys/my_realloc.c
index 7ab75d47619..49d96c2eb4f 100644
--- a/mysys/my_realloc.c
+++ b/mysys/my_realloc.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#ifdef SAFEMALLOC /* We don't need SAFEMALLOC here */
#undef SAFEMALLOC
diff --git a/mysys/my_redel.c b/mysys/my_redel.c
index 16ec77394d2..8474dab0d13 100644
--- a/mysys/my_redel.c
+++ b/mysys/my_redel.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
#define USES_TYPES /* sys/types is included */
#include "mysys_priv.h"
diff --git a/mysys/my_rename.c b/mysys/my_rename.c
index ea895ffcf76..fde45eba456 100644
--- a/mysys/my_rename.c
+++ b/mysys/my_rename.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
#define USES_TYPES
#include "mysys_priv.h"
diff --git a/mysys/my_seek.c b/mysys/my_seek.c
index 7c4da4f6010..177a5cee953 100644
--- a/mysys/my_seek.c
+++ b/mysys/my_seek.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include "mysys_priv.h"
@@ -26,7 +25,8 @@ my_off_t my_seek(File fd, my_off_t pos, int whence,
reg1 os_off_t newpos;
DBUG_ENTER("my_seek");
DBUG_PRINT("my",("Fd: %d Hpos: %lu Pos: %lu Whence: %d MyFlags: %d",
- fd, ((ulonglong) pos) >> 32, (ulong) pos, whence, MyFlags));
+ fd, (ulong) (((ulonglong) pos) >> 32), (ulong) pos,
+ whence, MyFlags));
newpos=lseek(fd, pos, whence);
if (newpos == (os_off_t) -1)
{
@@ -34,6 +34,10 @@ my_off_t my_seek(File fd, my_off_t pos, int whence,
DBUG_PRINT("error",("lseek: %lu, errno: %d",newpos,errno));
DBUG_RETURN(MY_FILEPOS_ERROR);
}
+ if ((my_off_t) newpos != pos)
+ {
+ DBUG_PRINT("exit",("pos: %lu", (ulong) newpos));
+ }
DBUG_RETURN((my_off_t) newpos);
} /* my_seek */
@@ -53,6 +57,6 @@ my_off_t my_tell(File fd, myf MyFlags __attribute__((unused)))
#endif
if (pos == (os_off_t) -1)
my_errno=errno;
- DBUG_PRINT("exit",("pos: %lu",pos));
+ DBUG_PRINT("exit",("pos: %lu", (ulong) pos));
DBUG_RETURN((my_off_t) pos);
} /* my_tell */
diff --git a/mysys/my_static.c b/mysys/my_static.c
index 00061893cdc..1eb6220f185 100644
--- a/mysys/my_static.c
+++ b/mysys/my_static.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/*
Static variables for mysys library. All definied here for easy making of
@@ -83,6 +82,13 @@ struct remember *pRememberRoot = NULL;
int volatile my_have_got_alarm=0; /* declare variable to reset */
ulong my_time_to_wait_for_lock=2; /* In seconds */
+ /*
+ We need to have this define here as otherwise linking will fail
+ on OSF1 when compiling --without-raid --with-debug
+ */
+
+const char *raid_type_string[]={"none","striped"};
+
/* from errors.c */
#ifdef SHARED_LIBRARY
char * NEAR globerrs[GLOBERRS]; /* my_error_messages is here */
diff --git a/mysys/my_static.h b/mysys/my_static.h
index e9d1a30b786..4f944938b8d 100644
--- a/mysys/my_static.h
+++ b/mysys/my_static.h
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/*
Static variables for mysys library. All definied here for easy making of
diff --git a/mysys/my_symlink.c b/mysys/my_symlink.c
index 65d165fc026..5cc22b6bfbc 100644
--- a/mysys/my_symlink.c
+++ b/mysys/my_symlink.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include "mysys_priv.h"
#include "mysys_err.h"
diff --git a/mysys/my_symlink2.c b/mysys/my_symlink2.c
index f1e90abaa9b..68b034bec5c 100644
--- a/mysys/my_symlink2.c
+++ b/mysys/my_symlink2.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/*
Advanced symlink handling.
@@ -23,6 +22,7 @@
*/
#include "mysys_priv.h"
+#include "mysys_err.h"
#include <m_string.h>
File my_create_with_symlink(const char *linkname, const char *filename,
@@ -30,11 +30,27 @@ File my_create_with_symlink(const char *linkname, const char *filename,
{
File file;
int tmp_errno;
+ /* Test if we should create a link */
+ int create_link=(linkname && strcmp(linkname,filename));
DBUG_ENTER("my_create_with_symlink");
+
+ if (!(MyFlags & MY_DELETE_OLD))
+ {
+ if (!access(filename,F_OK))
+ {
+ my_error(EE_CANTCREATEFILE, MYF(0), filename, EEXIST);
+ DBUG_RETURN(-1);
+ }
+ if (create_link && !access(linkname,F_OK))
+ {
+ my_error(EE_CANTCREATEFILE, MYF(0), linkname, EEXIST);
+ DBUG_RETURN(-1);
+ }
+ }
+
if ((file=my_create(filename, createflags, access_flags, MyFlags)) >= 0)
{
- /* Test if we should create a link */
- if (linkname && strcmp(linkname,filename))
+ if (create_link)
{
/* Delete old link/file */
if (MyFlags & MY_DELETE_OLD)
diff --git a/mysys/my_tempnam.c b/mysys/my_tempnam.c
index fdaf018af0d..da0692b46c5 100644
--- a/mysys/my_tempnam.c
+++ b/mysys/my_tempnam.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+/* Copyright (C) 2000 MySQL AB
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
- This library is distributed in the hope that it will be useful,
+ 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
- Library General Public License for more details.
+ 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 Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 function is only used by some old ISAM code.
diff --git a/mysys/my_thr_init.c b/mysys/my_thr_init.c
index e1f9e23912e..b4d98feeeb6 100644
--- a/mysys/my_thr_init.c
+++ b/mysys/my_thr_init.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/*
** Functions to handle initializating and allocationg of all mysys & debug
diff --git a/mysys/my_vsnprintf.c b/mysys/my_vsnprintf.c
index ab8edec4d7b..0fe6eff24a6 100644
--- a/mysys/my_vsnprintf.c
+++ b/mysys/my_vsnprintf.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include "mysys_priv.h"
#include "mysys_err.h"
@@ -94,7 +93,7 @@ static void my_printf(const char * fmt, ...)
int main()
{
-
+
my_printf("Hello\n");
my_printf("Hello int, %d\n", 1);
my_printf("Hello string '%s'\n", "I am a string");
@@ -109,4 +108,3 @@ int main()
return 0;
}
#endif
-
diff --git a/mysys/my_wincond.c b/mysys/my_wincond.c
index 0c5b01f90d8..8c497e8f250 100644
--- a/mysys/my_wincond.c
+++ b/mysys/my_wincond.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/*****************************************************************************
** The following is a simple implementation of posix conditions
diff --git a/mysys/my_winsem.c b/mysys/my_winsem.c
new file mode 100644
index 00000000000..268a05a0b21
--- /dev/null
+++ b/mysys/my_winsem.c
@@ -0,0 +1,406 @@
+/*
+ * -------------------------------------------------------------
+ *
+ * Module: my_semaphore.c (Original: semaphore.c from pthreads library)
+ *
+ * Purpose:
+ * Semaphores aren't actually part of the PThreads standard.
+ * They are defined by the POSIX Standard:
+ *
+ * POSIX 1003.1b-1993 (POSIX.1b)
+ *
+ * -------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright (C) 1998
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA
+ */
+
+/*
+ NEED_SEM is not used in MySQL and should only be needed under
+ Windows CE.
+
+ The big changes compared to the original version was to not allocate
+ any additional memory in sem_init() but to instead store everthing
+ we need in sem_t.
+
+ TODO:
+ To get HAVE_CREATESEMAPHORE we have to define the struct
+ in my_semaphore.h
+*/
+
+#include "mysys_priv.h"
+#ifdef __WIN__
+#include "my_semaphore.h"
+#include <errno.h>
+
+/*
+ DOCPUBLIC
+ This function initializes an unnamed semaphore. the
+ initial value of the semaphore is 'value'
+
+ PARAMETERS
+ sem Pointer to an instance of sem_t
+
+ pshared If zero, this semaphore may only be shared between
+ threads in the same process.
+ If nonzero, the semaphore can be shared between
+ processes
+
+ value Initial value of the semaphore counter
+
+ RESULTS
+ 0 Successfully created semaphore,
+ -1 Failed, error in errno
+
+ ERRNO
+ EINVAL 'sem' is not a valid semaphore,
+ ENOSPC A required resource has been exhausted,
+ ENOSYS Semaphores are not supported,
+ EPERM The process lacks appropriate privilege
+
+*/
+
+int
+sem_init (sem_t *sem, int pshared, unsigned int value)
+{
+ int result = 0;
+
+ if (pshared != 0)
+ {
+ /*
+ We don't support creating a semaphore that can be shared between
+ processes
+ */
+ result = EPERM;
+ }
+ else
+ {
+#ifndef HAVE_CREATESEMAPHORE
+ sem->value = value;
+ sem->event = CreateEvent(NULL,
+ FALSE, /* manual reset */
+ FALSE, /* initial state */
+ NULL);
+ if (!sem->event)
+ result = ENOSPC;
+ else
+ {
+ if (value)
+ SetEvent(sem->event);
+ InitializeCriticalSection(&sem->sem_lock_cs);
+ }
+#else /* HAVE_CREATESEMAPHORE */
+ *sem = CreateSemaphore (NULL, /* Always NULL */
+ value, /* Initial value */
+ 0x7FFFFFFFL, /* Maximum value */
+ NULL); /* Name */
+ if (!*sem)
+ result = ENOSPC;
+#endif /* HAVE_CREATESEMAPHORE */
+ }
+ if (result != 0)
+ {
+ errno = result;
+ return -1;
+ }
+ return 0;
+} /* sem_init */
+
+
+/*
+ DOCPUBLIC
+ This function destroys an unnamed semaphore.
+
+ PARAMETERS
+ sem Pointer to an instance of sem_t
+
+ RESULTS
+ 0 Successfully destroyed semaphore,
+ -1 Failed, error in errno
+ ERRNO
+ EINVAL 'sem' is not a valid semaphore,
+ ENOSYS Semaphores are not supported,
+ EBUSY Threads (or processes) are currently blocked on 'sem'
+*/
+
+int
+sem_destroy (sem_t * sem)
+{
+ int result = 0;
+
+#ifdef EXTRA_DEBUG
+ if (sem == NULL || *sem == NULL)
+ {
+ errno=EINVAL;
+ return;
+ }
+#endif /* EXTRA_DEBUG */
+
+#ifndef HAVE_CREATESEMAPHORE
+ if (! CloseHandle(sem->event))
+ result = EINVAL;
+ else
+ DeleteCriticalSection(&sem->sem_lock_cs);
+#else /* HAVE_CREATESEMAPHORE */
+ if (!CloseHandle(*sem))
+ result = EINVAL;
+#endif /* HAVE_CREATESEMAPHORE */
+ if (result)
+ {
+ errno = result;
+ return -1;
+ }
+ *sem=0; /* Safety */
+ return 0;
+} /* sem_destroy */
+
+
+/*
+ DOCPUBLIC
+ This function tries to wait on a semaphore. If the
+ semaphore value is greater than zero, it decreases
+ its value by one. If the semaphore value is zero, then
+ this function returns immediately with the error EAGAIN
+
+ PARAMETERS
+ sem Pointer to an instance of sem_t
+
+ RESULTS
+ 0 Successfully decreased semaphore,
+ -1 Failed, error in errno
+
+ ERRNO
+ EAGAIN The semaphore was already locked,
+ EINVAL 'sem' is not a valid semaphore,
+ ENOSYS Semaphores are not supported,
+ EINTR The function was interrupted by a signal,
+ EDEADLK A deadlock condition was detected.
+*/
+
+int
+sem_trywait(sem_t * sem)
+{
+#ifndef HAVE_CREATESEMAPHORE
+ /* not yet implemented! */
+ int errno = EINVAL;
+ return -1;
+#else /* HAVE_CREATESEMAPHORE */
+#ifdef EXTRA_DEBUG
+ if (sem == NULL || *sem == NULL)
+ {
+ errno=EINVAL;
+ return -1;
+ }
+#endif /* EXTRA_DEBUG */
+ if (WaitForSingleObject (*sem, 0) == WAIT_TIMEOUT)
+ {
+ errno= EAGAIN;
+ return -1;
+ }
+ return 0;
+#endif /* HAVE_CREATESEMAPHORE */
+
+} /* sem_trywait */
+
+
+#ifndef HAVE_CREATESEMAPHORE
+
+static void
+ptw32_decrease_semaphore(sem_t * sem)
+{
+ EnterCriticalSection(&sem->sem_lock_cs);
+ DBUG_ASSERT(sem->value != 0);
+ sem->value--;
+ if (sem->value != 0)
+ SetEvent(sem->event);
+ LeaveCriticalSection(&sem->sem_lock_cs);
+}
+
+static BOOL
+ptw32_increase_semaphore(sem_t * sem, unsigned int n)
+{
+ BOOL result=FALSE;
+
+ EnterCriticalSection(&sem->sem_lock_cs);
+ if (sem->value + n > sem->value)
+ {
+ sem->value += n;
+ SetEvent(sem->event);
+ result = TRUE;
+ }
+ LeaveCriticalSection(&sem->sem_lock_cs);
+ return result;
+}
+
+#endif /* HAVE_CREATESEMAPHORE */
+
+
+/*
+ ------------------------------------------------------
+ DOCPUBLIC
+ This function waits on a semaphore. If the
+ semaphore value is greater than zero, it decreases
+ its value by one. If the semaphore value is zero, then
+ the calling thread (or process) is blocked until it can
+ successfully decrease the value or until interrupted by
+ a signal.
+
+ PARAMETERS
+ sem Pointer to an instance of sem_t
+
+ RESULTS
+ 0 Successfully decreased semaphore,
+ -1 Failed, error in errno
+
+ ERRNO
+ EINVAL 'Sem' is not a valid semaphore,
+ ENOSYS Semaphores are not supported,
+ EINTR The function was interrupted by a signal,
+ EDEADLK A deadlock condition was detected.
+*/
+
+int
+sem_wait(sem_t *sem)
+{
+ int result;
+
+#ifdef EXTRA_DEBUG
+ if (sem == NULL || *sem == NULL)
+ {
+ errno=EINVAL;
+ return -1;
+ }
+#endif /* EXTRA_DEBUG */
+
+#ifndef HAVE_CREATESEMAPHORE
+ result=WaitForSingleObject(sem->event, INFINITE);
+#else
+ result=WaitForSingleObject(*sem, INFINITE);
+#endif
+ if (result == WAIT_FAILED || result == WAIT_ABANDONED_0)
+ result = EINVAL;
+ else if (result == WAIT_TIMEOUT)
+ result = ETIMEDOUT;
+ else
+ result=0;
+ if (result)
+ {
+ errno = result;
+ return -1;
+ }
+#ifndef HAVE_CREATESEMAPHORE
+ ptw32_decrease_semaphore(sem);
+#endif /* HAVE_CREATESEMAPHORE */
+ return 0;
+}
+
+
+/*
+ ------------------------------------------------------
+ DOCPUBLIC
+ This function posts a wakeup to a semaphore. If there
+ are waiting threads (or processes), one is awakened;
+ otherwise, the semaphore value is incremented by one.
+
+ PARAMETERS
+ sem Pointer to an instance of sem_t
+
+ RESULTS
+ 0 Successfully posted semaphore,
+ -1 Failed, error in errno
+
+ ERRNO
+ EINVAL 'sem' is not a valid semaphore,
+ ENOSYS Semaphores are not supported,
+
+*/
+
+int
+sem_post (sem_t * sem)
+{
+#ifdef EXTRA_DEBUG
+ if (sem == NULL || *sem == NULL)
+ {
+ errno=EINVAL;
+ return -1;
+ }
+#endif /* EXTRA_DEBUG */
+
+#ifndef HAVE_CREATESEMAPHORE
+ if (! ptw32_increase_semaphore(sem, 1))
+#else /* HAVE_CREATESEMAPHORE */
+ if (! ReleaseSemaphore(*sem, 1, 0))
+#endif /* HAVE_CREATESEMAPHORE */
+ {
+ errno=EINVAL;
+ return -1;
+ }
+ return 0;
+}
+
+
+/*
+ ------------------------------------------------------
+ DOCPUBLIC
+ This function posts multiple wakeups to a semaphore. If there
+ are waiting threads (or processes), n <= count are awakened;
+ the semaphore value is incremented by count - n.
+
+ PARAMETERS
+ sem Pointer to an instance of sem_t
+ count Counter, must be greater than zero.
+
+ RESULTS
+ 0 Successfully posted semaphore,
+ -1 Failed, error in errno
+
+ ERRNO
+ EINVAL 'sem' is not a valid semaphore or count is less
+ than or equal to zero.
+*/
+
+int
+sem_post_multiple (sem_t * sem, int count )
+{
+#ifdef EXTRA_DEBUG
+ if (sem == NULL || *sem == NULL || count <= 0)
+ {
+ errno=EINVAL;
+ return -1;
+ }
+#endif /* EXTRA_DEBUG */
+#ifndef HAVE_CREATESEMAPHORE
+ if (! ptw32_increase_semaphore (sem, count))
+#else /* HAVE_CREATESEMAPHORE */
+ if (! ReleaseSemaphore(*sem, count, 0))
+#endif /* HAVE_CREATESEMAPHORE */
+ {
+ errno = EINVAL;
+ return -1;
+ }
+ return 0;
+}
+
+int
+sem_getvalue (sem_t *sem, int *sval)
+{
+ errno = ENOSYS;
+ return -1;
+} /* sem_getvalue */
+
+#endif /* __WIN__ */
diff --git a/mysys/my_winthread.c b/mysys/my_winthread.c
index a77167c23e4..eebc07df180 100644
--- a/mysys/my_winthread.c
+++ b/mysys/my_winthread.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/*****************************************************************************
** Simulation of posix threads calls for WIN95 and NT
diff --git a/mysys/my_write.c b/mysys/my_write.c
index 5d5a48a3dda..61fd6097e28 100644
--- a/mysys/my_write.c
+++ b/mysys/my_write.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include "mysys_priv.h"
#include "mysys_err.h"
diff --git a/mysys/mysys_priv.h b/mysys/mysys_priv.h
index 20fda270658..ba16e8820fe 100644
--- a/mysys/mysys_priv.h
+++ b/mysys/mysys_priv.h
@@ -1,21 +1,20 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-#include <global.h>
+#include <my_global.h>
#include <my_sys.h>
#ifdef USE_SYSTEM_WRAPPERS
diff --git a/mysys/ptr_cmp.c b/mysys/ptr_cmp.c
index 65b2c51aafd..5fc7ccab4fa 100644
--- a/mysys/ptr_cmp.c
+++ b/mysys/ptr_cmp.c
@@ -1,27 +1,23 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/*
get_ptr_compare(len) returns a pointer to a optimal byte-compare function
for a array of stringpointer where all strings have size len.
The bytes are compare as unsigned chars.
- Because the size is saved in a static variable.
- When using threads the program must have called my_init and the thread
- my_init_thread()
*/
#include "mysys_priv.h"
diff --git a/mysys/queues.c b/mysys/queues.c
index 1c7a1a4a618..50ef3944a3f 100644
--- a/mysys/queues.c
+++ b/mysys/queues.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/*
Code for generell handling of priority Queues.
@@ -124,7 +123,6 @@ byte *queue_remove(register QUEUE *queue, uint idx)
}
}
-
/* Fix when element on top has been replaced */
#ifndef queue_replaced
@@ -166,3 +164,22 @@ void _downheap(register QUEUE *queue, uint idx)
}
queue->root[idx]=element;
}
+
+
+static int queue_fix_cmp(QUEUE *queue, void **a, void **b)
+{
+ return queue->compare(queue->first_cmp_arg,
+ (char*) (*a)+queue->offset_to_key,
+ (char*) (*b)+queue->offset_to_key);
+}
+
+/* Fix heap when every element was changed
+ actually, it can be done in linear time,
+ not in n*log(n), but some code (myisam/ft_boolean_search.c)
+ requires a strict order here, not just a queue property
+*/
+void queue_fix(QUEUE *queue)
+{
+ qsort2(queue->root+1,queue->elements, sizeof(void *),
+ (qsort2_cmp)queue_fix_cmp, queue);
+}
diff --git a/mysys/raid.cc b/mysys/raid.cc
index 48aa5cdb134..72d3b2074be 100644
--- a/mysys/raid.cc
+++ b/mysys/raid.cc
@@ -1,75 +1,74 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
-
-/* --------------------------------------------------------*
-*
-* RAID support for MySQL. Raid 0 (stiping) only implemented yet.
-*
-* Why RAID? Why it must be in MySQL?
-*
-* This is because then you can:
-* 1. Have bigger tables than your OS limit. In time of writing this
-* we are hitting to 2GB limit under linux/ext2
-* 2. You can get more speed from IO bottleneck by putting
-* Raid dirs on different physical disks.
-* 3. Getting more fault tolerance (not implemented yet)
-*
-* Why not to use RAID:
-*
-* 1. You are losing some processor power to calculate things,
-* do more syscalls and interrupts.
-*
-* Functionality is supplied by two classes: RaidFd and RaidName.
-* RaidFd supports funtionality over file descriptors like
-* open/create/write/seek/close. RaidName supports functionality
-* like rename/delete where we have no relations to filedescriptors.
-* RaidName can be prorably unchanged for different Raid levels. RaidFd
-* have to be virtual I think ;).
-* You can speed up some calls in MySQL code by skipping RAID code.
-* For example LOAD DATA INFILE never needs to read RAID-ed files.
-* This can be done adding proper "#undef my_read" or similar undef-s
-* in your code. Check out the raid.h!
-*
-* Some explanation about _seek_vector[]
-* This is seek cache. RAID seeks too much and we cacheing this. We
-* fool it and just storing new position in file to _seek_vector.
-* When there is no seeks to do, we are putting RAID_SEEK_DONE into it.
-* Any other value requires seeking to that position.
-*
-* TODO:
-*
-*
-* - Implement other fancy things like RAID 1 (mirroring) and RAID 5.
-* Should not to be very complex.
-*
-* - Optimize big blob writes by resorting write buffers and writing
-* big chunks at once instead of doing many syscalls. - after thinking I
-* found this is useless. This is because same thing one can do with just
-* increasing RAID_CHUNKSIZE. Monty, what do you think? tonu.
-*
-* - If needed, then implement missing syscalls. One known to miss is stat();
-*
-* - Make and use a thread safe dynamic_array buffer. The used one
-* will not work if needs to be extended at the same time someone is
-* accessing it.
-*
-*
-* tonu@mysql.com & monty@mysql.com
-* --------------------------------------------------------*/
+ 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 */
+
+/*
+
+ RAID support for MySQL. Raid 0 (stiping) only implemented yet.
+
+ Why RAID? Why it must be in MySQL?
+
+ This is because then you can:
+ 1. Have bigger tables than your OS limit. In time of writing this
+ we are hitting to 2GB limit under linux/ext2
+ 2. You can get more speed from IO bottleneck by putting
+ Raid dirs on different physical disks.
+ 3. Getting more fault tolerance (not implemented yet)
+
+ Why not to use RAID:
+
+ 1. You are losing some processor power to calculate things,
+ do more syscalls and interrupts.
+
+ Functionality is supplied by two classes: RaidFd and RaidName.
+ RaidFd supports funtionality over file descriptors like
+ open/create/write/seek/close. RaidName supports functionality
+ like rename/delete where we have no relations to filedescriptors.
+ RaidName can be prorably unchanged for different Raid levels. RaidFd
+ have to be virtual I think ;).
+ You can speed up some calls in MySQL code by skipping RAID code.
+ For example LOAD DATA INFILE never needs to read RAID-ed files.
+ This can be done adding proper "#undef my_read" or similar undef-s
+ in your code. Check out the raid.h!
+
+ Some explanation about _seek_vector[]
+ This is seek cache. RAID seeks too much and we cacheing this. We
+ fool it and just storing new position in file to _seek_vector.
+ When there is no seeks to do, we are putting RAID_SEEK_DONE into it.
+ Any other value requires seeking to that position.
+
+ TODO:
+
+
+ - Implement other fancy things like RAID 1 (mirroring) and RAID 5.
+ Should not to be very complex.
+
+ - Optimize big blob writes by resorting write buffers and writing
+ big chunks at once instead of doing many syscalls. - after thinking I
+ found this is useless. This is because same thing one can do with just
+ increasing RAID_CHUNKSIZE. Monty, what do you think? tonu.
+
+ - If needed, then implement missing syscalls. One known to miss is stat();
+
+ - Make and use a thread safe dynamic_array buffer. The used one
+ will not work if needs to be extended at the same time someone is
+ accessing it.
+
+
+ tonu@mysql.com & monty@mysql.com
+*/
#ifdef __GNUC__
#pragma implementation // gcc: Class implementation
@@ -80,16 +79,6 @@
#include <m_string.h>
#include <assert.h>
-const char *raid_type_string[]={"none","striped"};
-
-
-extern "C" {
- const char *my_raid_type(int raid_type)
- {
- return raid_type_string[raid_type];
- }
-}
-
#if defined(USE_RAID) && !defined(MYSQL_CLIENT)
#define RAID_SEEK_DONE ~(off_t) 0
@@ -420,8 +409,8 @@ IsRaid(File fd)
RaidFd::
RaidFd(uint raid_type, uint raid_chunks, ulong raid_chunksize)
:_raid_type(raid_type), _raid_chunks(raid_chunks),
- _raid_chunksize(raid_chunksize), _position(0), _fd_vector(0),
- _size(RAID_SIZE_UNKNOWN)
+ _raid_chunksize(raid_chunksize), _position(0), _size(RAID_SIZE_UNKNOWN),
+ _fd_vector(0)
{
DBUG_ENTER("RaidFd::RaidFd");
DBUG_PRINT("enter",("RaidFd_type: %u Disks: %u Chunksize: %d",
diff --git a/mysys/safemalloc.c b/mysys/safemalloc.c
index 34fcfff756c..d8c089c2ff0 100644
--- a/mysys/safemalloc.c
+++ b/mysys/safemalloc.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 posting refers to an article entitled "oops, corrupted memory
diff --git a/mysys/string.c b/mysys/string.c
index 96a503c1179..ea747bc9847 100644
--- a/mysys/string.c
+++ b/mysys/string.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/*
Code for handling strings with can grow dynamicly.
@@ -51,7 +50,7 @@ my_bool init_dynamic_string(DYNAMIC_STRING *str, const char *init_str,
my_bool dynstr_set(DYNAMIC_STRING *str, const char *init_str)
{
- uint length;
+ uint length=0;
DBUG_ENTER("dynstr_set");
if (init_str && (length= (uint) strlen(init_str)+1) > str->max_length)
diff --git a/mysys/test_charset.c b/mysys/test_charset.c
index 6a5183d2cd3..15e46f3ff82 100644
--- a/mysys/test_charset.c
+++ b/mysys/test_charset.c
@@ -1,21 +1,20 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
-
-#include <global.h>
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <my_global.h>
#include <m_ctype.h>
#include <my_sys.h>
#include <mysql_version.h>
diff --git a/mysys/test_dir.c b/mysys/test_dir.c
index fafdde137b6..f3d220e942f 100644
--- a/mysys/test_dir.c
+++ b/mysys/test_dir.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/* TODO: Test all functions */
diff --git a/mysys/test_fn.c b/mysys/test_fn.c
index 224b899ebe1..5a0546392ab 100644
--- a/mysys/test_fn.c
+++ b/mysys/test_fn.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include "mysys_priv.h"
diff --git a/mysys/testhash.c b/mysys/testhash.c
index a8fbf800595..461f1d8be5e 100644
--- a/mysys/testhash.c
+++ b/mysys/testhash.c
@@ -1,23 +1,22 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/* Test av hash libarary: stor test */
-#include <global.h>
+#include <my_global.h>
#include <my_sys.h>
#include <hash.h>
#include <m_string.h>
diff --git a/mysys/thr_alarm.c b/mysys/thr_alarm.c
index f51f27b7f51..f5f26e6d87b 100644
--- a/mysys/thr_alarm.c
+++ b/mysys/thr_alarm.c
@@ -1,21 +1,20 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
-
-#include <global.h>
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <my_global.h>
#if defined(THREAD) && !defined(DONT_USE_THR_ALARM)
#include <errno.h>
diff --git a/mysys/thr_lock.c b/mysys/thr_lock.c
index aa50877072d..0288c7c1cbe 100644
--- a/mysys/thr_lock.c
+++ b/mysys/thr_lock.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/*
Read and write locks for Posix threads. All tread must acquire
diff --git a/mysys/thr_mutex.c b/mysys/thr_mutex.c
index fa7ae4f1e82..4493c54069f 100644
--- a/mysys/thr_mutex.c
+++ b/mysys/thr_mutex.c
@@ -1,23 +1,22 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 makes a wrapper for mutex handling to make it easier to debug mutex */
-#include <global.h>
+#include <my_global.h>
#if defined(HAVE_LINUXTHREADS) && !defined (__USE_UNIX98)
#define __USE_UNIX98 /* To get rw locks under Linux */
#endif
@@ -70,7 +69,8 @@ int safe_mutex_lock(safe_mutex_t *mp,const char *file, uint line)
}
if (mp->count++)
{
- fprintf(stderr,"safe_mutex: Error in thread libray: Got mutex at %s, line %d more than 1 time\n", file,line);
+ fprintf(stderr,"safe_mutex: Error in thread libray: Got mutex at %s, \
+line %d more than 1 time\n", file,line);
fflush(stderr);
abort();
}
@@ -108,7 +108,7 @@ int safe_mutex_unlock(safe_mutex_t *mp,const char *file, uint line)
error=pthread_mutex_unlock(&mp->mutex);
if (error)
{
- fprintf(stderr,"safe_mutex: Got error: %d when trying to unlock mutex at %s, line %d\n", error, file, line);
+ fprintf(stderr,"safe_mutex: Got error: %d (%d) when trying to unlock mutex at %s, line %d\n", error, errno, file, line);
fflush(stderr);
abort();
}
@@ -149,7 +149,7 @@ int safe_cond_wait(pthread_cond_t *cond, safe_mutex_t *mp, const char *file,
pthread_mutex_lock(&mp->global);
if (error)
{
- fprintf(stderr,"safe_mutex: Got error: %d when doing a safe_mutex_wait at %s, line %d\n", error, file, line);
+ fprintf(stderr,"safe_mutex: Got error: %d (%d) when doing a safe_mutex_wait at %s, line %d\n", error, errno, file, line);
fflush(stderr);
abort();
}
@@ -187,15 +187,15 @@ int safe_cond_timedwait(pthread_cond_t *cond, safe_mutex_t *mp,
#ifdef EXTRA_DEBUG
if (error && (error != EINTR && error != ETIMEDOUT))
{
- fprintf(stderr,"safe_mutex: Got error: %d when doing a safe_mutex_timedwait at %s, line %d\n", error, file, line);
+ fprintf(stderr,"safe_mutex: Got error: %d (%d) when doing a safe_mutex_timedwait at %s, line %d\n", error, errno, file, line);
}
#endif
pthread_mutex_lock(&mp->global);
if (mp->count++)
{
fprintf(stderr,
- "safe_mutex: Count was %d in thread %lx when locking mutex at %s, line %d (error: %d)\n",
- mp->count-1, my_thread_id(), file, line, error);
+ "safe_mutex: Count was %d in thread %lx when locking mutex at %s, line %d (error: %d (%d))\n",
+ mp->count-1, my_thread_id(), file, line, error, error);
fflush(stderr);
abort();
}
diff --git a/mysys/thr_rwlock.c b/mysys/thr_rwlock.c
index 866948a1c23..4e2cf3554b7 100644
--- a/mysys/thr_rwlock.c
+++ b/mysys/thr_rwlock.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/* Synchronization - readers / writer thread locks */
diff --git a/mysys/tree.c b/mysys/tree.c
index cd05a17fd72..2ac2c88fd66 100644
--- a/mysys/tree.c
+++ b/mysys/tree.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/*
Code for handling red-black (balanced) binary trees.
@@ -62,28 +61,35 @@ static void rb_delete_fixup(TREE *tree,TREE_ELEMENT ***parent);
/* The actuall code for handling binary trees */
-void init_tree(TREE *tree, uint default_alloc_size, int size,
- qsort_cmp compare, my_bool with_delete,
- void (*free_element) (void *))
+#ifndef DBUG_OFF
+static int test_rb_tree(TREE_ELEMENT *element);
+#endif
+
+void init_tree(TREE *tree, uint default_alloc_size, uint memory_limit,
+ int size, qsort_cmp2 compare, my_bool with_delete,
+ tree_element_free free_element, void *custom_arg)
{
DBUG_ENTER("init_tree");
DBUG_PRINT("enter",("tree: %lx size: %d",tree,size));
- if (!default_alloc_size)
- default_alloc_size= DEFAULT_ALLOC_SIZE;
+ if (!default_alloc_size)
+ default_alloc_size= DEFAULT_ALLOC_SIZE;
bzero((gptr) &tree->null_element,sizeof(tree->null_element));
tree->root= &tree->null_element;
tree->compare=compare;
tree->size_of_element=size > 0 ? (uint) size : 0;
+ tree->memory_limit=memory_limit;
tree->free=free_element;
+ tree->allocated=0;
tree->elements_in_tree=0;
+ tree->custom_arg = custom_arg;
tree->null_element.colour=BLACK;
tree->null_element.left=tree->null_element.right=0;
if (!free_element && size >= 0 &&
((uint) size <= sizeof(void*) || ((uint) size & (sizeof(void*)-1))))
{
tree->offset_to_key=sizeof(TREE_ELEMENT); /* Put key after element */
- /* Fix allocation size so that we don't loose any memory */
+ /* Fix allocation size so that we don't lose any memory */
default_alloc_size/=(sizeof(TREE_ELEMENT)+size);
if (!default_alloc_size)
default_alloc_size=1;
@@ -102,9 +108,9 @@ void init_tree(TREE *tree, uint default_alloc_size, int size,
DBUG_VOID_RETURN;
}
-void delete_tree(TREE *tree)
+static void free_tree(TREE *tree, myf free_flags)
{
- DBUG_ENTER("delete_tree");
+ DBUG_ENTER("free_tree");
DBUG_PRINT("enter",("tree: %lx",tree));
if (tree->root) /* If initialized */
@@ -114,24 +120,43 @@ void delete_tree(TREE *tree)
else
{
if (tree->free)
+ {
+ if (tree->memory_limit)
+ (*tree->free)(NULL, free_init, tree->custom_arg);
delete_tree_element(tree,tree->root);
- free_root(&tree->mem_root,MYF(0));
+ if (tree->memory_limit)
+ (*tree->free)(NULL, free_end, tree->custom_arg);
+ }
+ free_root(&tree->mem_root, free_flags);
}
}
tree->root= &tree->null_element;
tree->elements_in_tree=0;
+ tree->allocated=0;
DBUG_VOID_RETURN;
}
+void delete_tree(TREE* tree)
+{
+ free_tree(tree, MYF(0)); /* my_free() mem_root if applicable */
+}
+
+void reset_tree(TREE* tree)
+{
+ free_tree(tree, MYF(MY_MARK_BLOCKS_FREE));
+ /* do not my_free() mem_root if applicable, just mark blocks as free */
+}
+
+
static void delete_tree_element(TREE *tree, TREE_ELEMENT *element)
{
if (element != &tree->null_element)
{
delete_tree_element(tree,element->left);
- delete_tree_element(tree,element->right);
if (tree->free)
- (*tree->free)(ELEMENT_KEY(tree,element));
+ (*tree->free)(ELEMENT_KEY(tree,element), free_free, tree->custom_arg);
+ delete_tree_element(tree,element->right);
if (tree->with_delete)
my_free((char*) element,MYF(0));
}
@@ -152,7 +177,8 @@ TREE_ELEMENT *tree_insert(TREE *tree, void *key, uint key_size)
for (;;)
{
if (element == &tree->null_element ||
- (cmp=(*tree->compare)(ELEMENT_KEY(tree,element),key)) == 0)
+ (cmp=(*tree->compare)(tree->custom_arg,
+ ELEMENT_KEY(tree,element),key)) == 0)
break;
if (cmp < 0)
{
@@ -165,13 +191,22 @@ TREE_ELEMENT *tree_insert(TREE *tree, void *key, uint key_size)
}
if (element == &tree->null_element)
{
+ uint alloc_size=sizeof(TREE_ELEMENT)+key_size+tree->size_of_element;
+ tree->allocated+=alloc_size;
+
+ if (tree->memory_limit && tree->elements_in_tree
+ && tree->allocated > tree->memory_limit)
+ {
+ reset_tree(tree);
+ return tree_insert(tree, key, key_size);
+ }
+
key_size+=tree->size_of_element;
if (tree->with_delete)
- element=(TREE_ELEMENT *) my_malloc(sizeof(TREE_ELEMENT)+key_size,
- MYF(MY_WME));
+ element=(TREE_ELEMENT *) my_malloc(alloc_size, MYF(MY_WME));
else
element=(TREE_ELEMENT *)
- alloc_root(&tree->mem_root,sizeof(TREE_ELEMENT)+key_size);
+ alloc_root(&tree->mem_root,alloc_size);
if (!element)
return(NULL);
**parent=element;
@@ -195,6 +230,7 @@ TREE_ELEMENT *tree_insert(TREE *tree, void *key, uint key_size)
}
else
element->count++;
+ DBUG_EXECUTE("check_tree", test_rb_tree(tree->root););
return element;
}
@@ -212,7 +248,8 @@ int tree_delete(TREE *tree, void *key)
{
if (element == &tree->null_element)
return 1; /* Was not in tree */
- if ((cmp=(*tree->compare)(ELEMENT_KEY(tree,element),key)) == 0)
+ if ((cmp=(*tree->compare)(tree->custom_arg,
+ ELEMENT_KEY(tree,element),key)) == 0)
break;
if (cmp < 0)
{
@@ -252,7 +289,7 @@ int tree_delete(TREE *tree, void *key)
if (remove_colour == BLACK)
rb_delete_fixup(tree,parent);
if (tree->free)
- (*tree->free)(ELEMENT_KEY(tree,element));
+ (*tree->free)(ELEMENT_KEY(tree,element), free_free, tree->custom_arg);
my_free((gptr) element,MYF(0));
tree->elements_in_tree--;
return 0;
@@ -268,7 +305,8 @@ void *tree_search(TREE *tree, void *key)
{
if (element == &tree->null_element)
return (void*) 0;
- if ((cmp=(*tree->compare)(ELEMENT_KEY(tree,element),key)) == 0)
+ if ((cmp=(*tree->compare)(tree->custom_arg,
+ ELEMENT_KEY(tree,element),key)) == 0)
return ELEMENT_KEY(tree,element);
if (cmp < 0)
element=element->right;
@@ -484,8 +522,7 @@ static void rb_delete_fixup(TREE *tree, TREE_ELEMENT ***parent)
x->colour=BLACK;
}
-
-#ifdef TESTING_TREES
+#ifndef DBUG_OFF
/* Test that the proporties for a red-black tree holds */
@@ -511,5 +548,4 @@ static int test_rb_tree(TREE_ELEMENT *element)
}
return -1;
}
-
#endif
diff --git a/mysys/typelib.c b/mysys/typelib.c
index b18959442ae..e2c8eade5c8 100644
--- a/mysys/typelib.c
+++ b/mysys/typelib.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/* Functions to handle typelib */
@@ -84,7 +83,8 @@ int find_type(my_string x, TYPELIB *typelib, uint full_name)
/* Get name of type nr 'nr' */
/* Warning first type is 1, 0 = empty field */
-void make_type(register my_string to, register uint nr, register TYPELIB *typelib)
+void make_type(register my_string to, register uint nr,
+ register TYPELIB *typelib)
{
DBUG_ENTER("make_type");
if (!nr)
diff --git a/pstack/Makefile.am b/pstack/Makefile.am
new file mode 100644
index 00000000000..863a52f4488
--- /dev/null
+++ b/pstack/Makefile.am
@@ -0,0 +1,36 @@
+# Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+#
+# As pstack doesn't work on all configurations, we have to use
+# the USE_PSTACK hack to get all files into distribution
+#
+
+SUBDIRS = aout
+INCLUDES = -I$(srcdir)/../include -I../include
+noinst_HEADERS = bucomm.h debug.h ieee.h budbg.h demangle.h \
+ linuxthreads.h pstack.h pstacktrace.h
+SRC= bucomm.c filemode.c linuxthreads.c rddbg.c \
+ debug.c ieee.c pstack.c stabs.c
+EXTRA_DIST= $(SRC)
+
+if COMPILE_PSTACK
+pkglib_LIBRARIES = libpstack.a
+libpstack_a_SOURCES = bucomm.c filemode.c linuxthreads.c rddbg.c debug.c ieee.c pstack.c stabs.c
+endif
+
+# Don't update the files from bitkeeper
+%::SCCS/s.%
diff --git a/pstack/aout/Makefile.am b/pstack/aout/Makefile.am
new file mode 100644
index 00000000000..0b02cb7b643
--- /dev/null
+++ b/pstack/aout/Makefile.am
@@ -0,0 +1 @@
+noinst_HEADERS = aout64.h stab.def stab_gnu.h
diff --git a/pstack/aout/aout64.h b/pstack/aout/aout64.h
new file mode 100644
index 00000000000..76f1140b682
--- /dev/null
+++ b/pstack/aout/aout64.h
@@ -0,0 +1,475 @@
+/* `a.out' object-file definitions, including extensions to 64-bit fields */
+
+#ifndef __A_OUT_64_H__
+#define __A_OUT_64_H__
+
+/* This is the layout on disk of the 32-bit or 64-bit exec header. */
+
+#ifndef external_exec
+struct external_exec
+{
+ bfd_byte e_info[4]; /* magic number and stuff */
+ bfd_byte e_text[BYTES_IN_WORD]; /* length of text section in bytes */
+ bfd_byte e_data[BYTES_IN_WORD]; /* length of data section in bytes */
+ bfd_byte e_bss[BYTES_IN_WORD]; /* length of bss area in bytes */
+ bfd_byte e_syms[BYTES_IN_WORD]; /* length of symbol table in bytes */
+ bfd_byte e_entry[BYTES_IN_WORD]; /* start address */
+ bfd_byte e_trsize[BYTES_IN_WORD]; /* length of text relocation info */
+ bfd_byte e_drsize[BYTES_IN_WORD]; /* length of data relocation info */
+};
+
+#define EXEC_BYTES_SIZE (4 + BYTES_IN_WORD * 7)
+
+/* Magic numbers for a.out files */
+
+#if ARCH_SIZE==64
+#define OMAGIC 0x1001 /* Code indicating object file */
+#define ZMAGIC 0x1002 /* Code indicating demand-paged executable. */
+#define NMAGIC 0x1003 /* Code indicating pure executable. */
+
+/* There is no 64-bit QMAGIC as far as I know. */
+
+#define N_BADMAG(x) (N_MAGIC(x) != OMAGIC \
+ && N_MAGIC(x) != NMAGIC \
+ && N_MAGIC(x) != ZMAGIC)
+#else
+#define OMAGIC 0407 /* ...object file or impure executable. */
+#define NMAGIC 0410 /* Code indicating pure executable. */
+#define ZMAGIC 0413 /* Code indicating demand-paged executable. */
+#define BMAGIC 0415 /* Used by a b.out object. */
+
+/* This indicates a demand-paged executable with the header in the text.
+ It is used by 386BSD (and variants) and Linux, at least. */
+#ifndef QMAGIC
+#define QMAGIC 0314
+#endif
+# ifndef N_BADMAG
+# define N_BADMAG(x) (N_MAGIC(x) != OMAGIC \
+ && N_MAGIC(x) != NMAGIC \
+ && N_MAGIC(x) != ZMAGIC \
+ && N_MAGIC(x) != QMAGIC)
+# endif /* N_BADMAG */
+#endif
+
+#endif
+
+#ifdef QMAGIC
+#define N_IS_QMAGIC(x) (N_MAGIC (x) == QMAGIC)
+#else
+#define N_IS_QMAGIC(x) (0)
+#endif
+
+/* The difference between TARGET_PAGE_SIZE and N_SEGSIZE is that TARGET_PAGE_SIZE is
+ the finest granularity at which you can page something, thus it
+ controls the padding (if any) before the text segment of a ZMAGIC
+ file. N_SEGSIZE is the resolution at which things can be marked as
+ read-only versus read/write, so it controls the padding between the
+ text segment and the data segment (in memory; on disk the padding
+ between them is TARGET_PAGE_SIZE). TARGET_PAGE_SIZE and N_SEGSIZE are the same
+ for most machines, but different for sun3. */
+
+/* By default, segment size is constant. But some machines override this
+ to be a function of the a.out header (e.g. machine type). */
+
+#ifndef N_SEGSIZE
+#define N_SEGSIZE(x) SEGMENT_SIZE
+#endif
+
+/* Virtual memory address of the text section.
+ This is getting very complicated. A good reason to discard a.out format
+ for something that specifies these fields explicitly. But til then...
+
+ * OMAGIC and NMAGIC files:
+ (object files: text for "relocatable addr 0" right after the header)
+ start at 0, offset is EXEC_BYTES_SIZE, size as stated.
+ * The text address, offset, and size of ZMAGIC files depend
+ on the entry point of the file:
+ * entry point below TEXT_START_ADDR:
+ (hack for SunOS shared libraries)
+ start at 0, offset is 0, size as stated.
+ * If N_HEADER_IN_TEXT(x) is true (which defaults to being the
+ case when the entry point is EXEC_BYTES_SIZE or further into a page):
+ no padding is needed; text can start after exec header. Sun
+ considers the text segment of such files to include the exec header;
+ for BFD's purposes, we don't, which makes more work for us.
+ start at TEXT_START_ADDR + EXEC_BYTES_SIZE, offset is EXEC_BYTES_SIZE,
+ size as stated minus EXEC_BYTES_SIZE.
+ * If N_HEADER_IN_TEXT(x) is false (which defaults to being the case when
+ the entry point is less than EXEC_BYTES_SIZE into a page (e.g. page
+ aligned)): (padding is needed so that text can start at a page boundary)
+ start at TEXT_START_ADDR, offset TARGET_PAGE_SIZE, size as stated.
+
+ Specific configurations may want to hardwire N_HEADER_IN_TEXT,
+ for efficiency or to allow people to play games with the entry point.
+ In that case, you would #define N_HEADER_IN_TEXT(x) as 1 for sunos,
+ and as 0 for most other hosts (Sony News, Vax Ultrix, etc).
+ (Do this in the appropriate bfd target file.)
+ (The default is a heuristic that will break if people try changing
+ the entry point, perhaps with the ld -e flag.)
+
+ * QMAGIC is always like a ZMAGIC for which N_HEADER_IN_TEXT is true,
+ and for which the starting address is TARGET_PAGE_SIZE (or should this be
+ SEGMENT_SIZE?) (TEXT_START_ADDR only applies to ZMAGIC, not to QMAGIC).
+ */
+
+/* This macro is only relevant for ZMAGIC files; QMAGIC always has the header
+ in the text. */
+#ifndef N_HEADER_IN_TEXT
+#define N_HEADER_IN_TEXT(x) (((x).a_entry & (TARGET_PAGE_SIZE-1)) >= EXEC_BYTES_SIZE)
+#endif
+
+/* Sun shared libraries, not linux. This macro is only relevant for ZMAGIC
+ files. */
+#ifndef N_SHARED_LIB
+#define N_SHARED_LIB(x) ((x).a_entry < TEXT_START_ADDR)
+#endif
+
+/* Returning 0 not TEXT_START_ADDR for OMAGIC and NMAGIC is based on
+ the assumption that we are dealing with a .o file, not an
+ executable. This is necessary for OMAGIC (but means we don't work
+ right on the output from ld -N); more questionable for NMAGIC. */
+
+#ifndef N_TXTADDR
+#define N_TXTADDR(x) \
+ (/* The address of a QMAGIC file is always one page in, */ \
+ /* with the header in the text. */ \
+ N_IS_QMAGIC (x) ? TARGET_PAGE_SIZE + EXEC_BYTES_SIZE : \
+ N_MAGIC(x) != ZMAGIC ? 0 : /* object file or NMAGIC */\
+ N_SHARED_LIB(x) ? 0 : \
+ N_HEADER_IN_TEXT(x) ? \
+ TEXT_START_ADDR + EXEC_BYTES_SIZE : /* no padding */\
+ TEXT_START_ADDR /* a page of padding */\
+ )
+#endif
+
+/* If N_HEADER_IN_TEXT is not true for ZMAGIC, there is some padding
+ to make the text segment start at a certain boundary. For most
+ systems, this boundary is TARGET_PAGE_SIZE. But for Linux, in the
+ time-honored tradition of crazy ZMAGIC hacks, it is 1024 which is
+ not what TARGET_PAGE_SIZE needs to be for QMAGIC. */
+
+#ifndef ZMAGIC_DISK_BLOCK_SIZE
+#define ZMAGIC_DISK_BLOCK_SIZE TARGET_PAGE_SIZE
+#endif
+
+#define N_DISK_BLOCK_SIZE(x) \
+ (N_MAGIC(x) == ZMAGIC ? ZMAGIC_DISK_BLOCK_SIZE : TARGET_PAGE_SIZE)
+
+/* Offset in an a.out of the start of the text section. */
+#ifndef N_TXTOFF
+#define N_TXTOFF(x) \
+ (/* For {O,N,Q}MAGIC, no padding. */ \
+ N_MAGIC(x) != ZMAGIC ? EXEC_BYTES_SIZE : \
+ N_SHARED_LIB(x) ? 0 : \
+ N_HEADER_IN_TEXT(x) ? \
+ EXEC_BYTES_SIZE : /* no padding */\
+ ZMAGIC_DISK_BLOCK_SIZE /* a page of padding */\
+ )
+#endif
+/* Size of the text section. It's always as stated, except that we
+ offset it to `undo' the adjustment to N_TXTADDR and N_TXTOFF
+ for ZMAGIC files that nominally include the exec header
+ as part of the first page of text. (BFD doesn't consider the
+ exec header to be part of the text segment.) */
+#ifndef N_TXTSIZE
+#define N_TXTSIZE(x) \
+ (/* For QMAGIC, we don't consider the header part of the text section. */\
+ N_IS_QMAGIC (x) ? (x).a_text - EXEC_BYTES_SIZE : \
+ (N_MAGIC(x) != ZMAGIC || N_SHARED_LIB(x)) ? (x).a_text : \
+ N_HEADER_IN_TEXT(x) ? \
+ (x).a_text - EXEC_BYTES_SIZE: /* no padding */\
+ (x).a_text /* a page of padding */\
+ )
+#endif
+/* The address of the data segment in virtual memory.
+ It is the text segment address, plus text segment size, rounded
+ up to a N_SEGSIZE boundary for pure or pageable files. */
+#ifndef N_DATADDR
+#define N_DATADDR(x) \
+ (N_MAGIC(x)==OMAGIC? (N_TXTADDR(x)+N_TXTSIZE(x)) \
+ : (N_SEGSIZE(x) + ((N_TXTADDR(x)+N_TXTSIZE(x)-1) & ~(N_SEGSIZE(x)-1))))
+#endif
+/* The address of the BSS segment -- immediately after the data segment. */
+
+#define N_BSSADDR(x) (N_DATADDR(x) + (x).a_data)
+
+/* Offsets of the various portions of the file after the text segment. */
+
+/* For {Q,Z}MAGIC, there is padding to make the data segment start on
+ a page boundary. Most of the time the a_text field (and thus
+ N_TXTSIZE) already contains this padding. It is possible that for
+ BSDI and/or 386BSD it sometimes doesn't contain the padding, and
+ perhaps we should be adding it here. But this seems kind of
+ questionable and probably should be BSDI/386BSD-specific if we do
+ do it.
+
+ For NMAGIC (at least for hp300 BSD, probably others), there is
+ padding in memory only, not on disk, so we must *not* ever pad here
+ for NMAGIC. */
+
+#ifndef N_DATOFF
+#define N_DATOFF(x) \
+ (N_TXTOFF(x) + N_TXTSIZE(x))
+#endif
+
+#ifndef N_TRELOFF
+#define N_TRELOFF(x) ( N_DATOFF(x) + (x).a_data )
+#endif
+#ifndef N_DRELOFF
+#define N_DRELOFF(x) ( N_TRELOFF(x) + (x).a_trsize )
+#endif
+#ifndef N_SYMOFF
+#define N_SYMOFF(x) ( N_DRELOFF(x) + (x).a_drsize )
+#endif
+#ifndef N_STROFF
+#define N_STROFF(x) ( N_SYMOFF(x) + (x).a_syms )
+#endif
+
+/* Symbols */
+#ifndef external_nlist
+struct external_nlist {
+ bfd_byte e_strx[BYTES_IN_WORD]; /* index into string table of name */
+ bfd_byte e_type[1]; /* type of symbol */
+ bfd_byte e_other[1]; /* misc info (usually empty) */
+ bfd_byte e_desc[2]; /* description field */
+ bfd_byte e_value[BYTES_IN_WORD]; /* value of symbol */
+};
+#define EXTERNAL_NLIST_SIZE (BYTES_IN_WORD+4+BYTES_IN_WORD)
+#endif
+
+struct internal_nlist {
+ unsigned long n_strx; /* index into string table of name */
+ unsigned char n_type; /* type of symbol */
+ unsigned char n_other; /* misc info (usually empty) */
+ unsigned short n_desc; /* description field */
+ bfd_vma n_value; /* value of symbol */
+};
+
+/* The n_type field is the symbol type, containing: */
+
+#define N_UNDF 0 /* Undefined symbol */
+#define N_ABS 2 /* Absolute symbol -- defined at particular addr */
+#define N_TEXT 4 /* Text sym -- defined at offset in text seg */
+#define N_DATA 6 /* Data sym -- defined at offset in data seg */
+#define N_BSS 8 /* BSS sym -- defined at offset in zero'd seg */
+#define N_COMM 0x12 /* Common symbol (visible after shared lib dynlink) */
+#define N_FN 0x1f /* File name of .o file */
+#define N_FN_SEQ 0x0C /* N_FN from Sequent compilers (sigh) */
+/* Note: N_EXT can only be usefully OR-ed with N_UNDF, N_ABS, N_TEXT,
+ N_DATA, or N_BSS. When the low-order bit of other types is set,
+ (e.g. N_WARNING versus N_FN), they are two different types. */
+#define N_EXT 1 /* External symbol (as opposed to local-to-this-file) */
+#define N_TYPE 0x1e
+#define N_STAB 0xe0 /* If any of these bits are on, it's a debug symbol */
+
+#define N_INDR 0x0a
+
+/* The following symbols refer to set elements.
+ All the N_SET[ATDB] symbols with the same name form one set.
+ Space is allocated for the set in the text section, and each set
+ elements value is stored into one word of the space.
+ The first word of the space is the length of the set (number of elements).
+
+ The address of the set is made into an N_SETV symbol
+ whose name is the same as the name of the set.
+ This symbol acts like a N_DATA global symbol
+ in that it can satisfy undefined external references. */
+
+/* These appear as input to LD, in a .o file. */
+#define N_SETA 0x14 /* Absolute set element symbol */
+#define N_SETT 0x16 /* Text set element symbol */
+#define N_SETD 0x18 /* Data set element symbol */
+#define N_SETB 0x1A /* Bss set element symbol */
+
+/* This is output from LD. */
+#define N_SETV 0x1C /* Pointer to set vector in data area. */
+
+/* Warning symbol. The text gives a warning message, the next symbol
+ in the table will be undefined. When the symbol is referenced, the
+ message is printed. */
+
+#define N_WARNING 0x1e
+
+/* Weak symbols. These are a GNU extension to the a.out format. The
+ semantics are those of ELF weak symbols. Weak symbols are always
+ externally visible. The N_WEAK? values are squeezed into the
+ available slots. The value of a N_WEAKU symbol is 0. The values
+ of the other types are the definitions. */
+#define N_WEAKU 0x0d /* Weak undefined symbol. */
+#define N_WEAKA 0x0e /* Weak absolute symbol. */
+#define N_WEAKT 0x0f /* Weak text symbol. */
+#define N_WEAKD 0x10 /* Weak data symbol. */
+#define N_WEAKB 0x11 /* Weak bss symbol. */
+
+/* Relocations
+
+ There are two types of relocation flavours for a.out systems,
+ standard and extended. The standard form is used on systems where the
+ instruction has room for all the bits of an offset to the operand, whilst
+ the extended form is used when an address operand has to be split over n
+ instructions. Eg, on the 68k, each move instruction can reference
+ the target with a displacement of 16 or 32 bits. On the sparc, move
+ instructions use an offset of 14 bits, so the offset is stored in
+ the reloc field, and the data in the section is ignored.
+*/
+
+/* This structure describes a single relocation to be performed.
+ The text-relocation section of the file is a vector of these structures,
+ all of which apply to the text section.
+ Likewise, the data-relocation section applies to the data section. */
+
+struct reloc_std_external {
+ bfd_byte r_address[BYTES_IN_WORD]; /* offset of of data to relocate */
+ bfd_byte r_index[3]; /* symbol table index of symbol */
+ bfd_byte r_type[1]; /* relocation type */
+};
+
+#define RELOC_STD_BITS_PCREL_BIG ((unsigned int) 0x80)
+#define RELOC_STD_BITS_PCREL_LITTLE ((unsigned int) 0x01)
+
+#define RELOC_STD_BITS_LENGTH_BIG ((unsigned int) 0x60)
+#define RELOC_STD_BITS_LENGTH_SH_BIG 5
+#define RELOC_STD_BITS_LENGTH_LITTLE ((unsigned int) 0x06)
+#define RELOC_STD_BITS_LENGTH_SH_LITTLE 1
+
+#define RELOC_STD_BITS_EXTERN_BIG ((unsigned int) 0x10)
+#define RELOC_STD_BITS_EXTERN_LITTLE ((unsigned int) 0x08)
+
+#define RELOC_STD_BITS_BASEREL_BIG ((unsigned int) 0x08)
+#define RELOC_STD_BITS_BASEREL_LITTLE ((unsigned int) 0x10)
+
+#define RELOC_STD_BITS_JMPTABLE_BIG ((unsigned int) 0x04)
+#define RELOC_STD_BITS_JMPTABLE_LITTLE ((unsigned int) 0x20)
+
+#define RELOC_STD_BITS_RELATIVE_BIG ((unsigned int) 0x02)
+#define RELOC_STD_BITS_RELATIVE_LITTLE ((unsigned int) 0x40)
+
+#define RELOC_STD_SIZE (BYTES_IN_WORD + 3 + 1) /* Bytes per relocation entry */
+
+struct reloc_std_internal
+{
+ bfd_vma r_address; /* Address (within segment) to be relocated. */
+ /* The meaning of r_symbolnum depends on r_extern. */
+ unsigned int r_symbolnum:24;
+ /* Nonzero means value is a pc-relative offset
+ and it should be relocated for changes in its own address
+ as well as for changes in the symbol or section specified. */
+ unsigned int r_pcrel:1;
+ /* Length (as exponent of 2) of the field to be relocated.
+ Thus, a value of 2 indicates 1<<2 bytes. */
+ unsigned int r_length:2;
+ /* 1 => relocate with value of symbol.
+ r_symbolnum is the index of the symbol
+ in files the symbol table.
+ 0 => relocate with the address of a segment.
+ r_symbolnum is N_TEXT, N_DATA, N_BSS or N_ABS
+ (the N_EXT bit may be set also, but signifies nothing). */
+ unsigned int r_extern:1;
+ /* The next three bits are for SunOS shared libraries, and seem to
+ be undocumented. */
+ unsigned int r_baserel:1; /* Linkage table relative */
+ unsigned int r_jmptable:1; /* pc-relative to jump table */
+ unsigned int r_relative:1; /* "relative relocation" */
+ /* unused */
+ unsigned int r_pad:1; /* Padding -- set to zero */
+};
+
+
+/* EXTENDED RELOCS */
+
+struct reloc_ext_external {
+ bfd_byte r_address[BYTES_IN_WORD]; /* offset of of data to relocate */
+ bfd_byte r_index[3]; /* symbol table index of symbol */
+ bfd_byte r_type[1]; /* relocation type */
+ bfd_byte r_addend[BYTES_IN_WORD]; /* datum addend */
+};
+
+#define RELOC_EXT_BITS_EXTERN_BIG ((unsigned int) 0x80)
+#define RELOC_EXT_BITS_EXTERN_LITTLE ((unsigned int) 0x01)
+
+#define RELOC_EXT_BITS_TYPE_BIG ((unsigned int) 0x1F)
+#define RELOC_EXT_BITS_TYPE_SH_BIG 0
+#define RELOC_EXT_BITS_TYPE_LITTLE ((unsigned int) 0xF8)
+#define RELOC_EXT_BITS_TYPE_SH_LITTLE 3
+
+/* Bytes per relocation entry */
+#define RELOC_EXT_SIZE (BYTES_IN_WORD + 3 + 1 + BYTES_IN_WORD)
+
+enum reloc_type
+{
+ /* simple relocations */
+ RELOC_8, /* data[0:7] = addend + sv */
+ RELOC_16, /* data[0:15] = addend + sv */
+ RELOC_32, /* data[0:31] = addend + sv */
+ /* pc-rel displacement */
+ RELOC_DISP8, /* data[0:7] = addend - pc + sv */
+ RELOC_DISP16, /* data[0:15] = addend - pc + sv */
+ RELOC_DISP32, /* data[0:31] = addend - pc + sv */
+ /* Special */
+ RELOC_WDISP30, /* data[0:29] = (addend + sv - pc)>>2 */
+ RELOC_WDISP22, /* data[0:21] = (addend + sv - pc)>>2 */
+ RELOC_HI22, /* data[0:21] = (addend + sv)>>10 */
+ RELOC_22, /* data[0:21] = (addend + sv) */
+ RELOC_13, /* data[0:12] = (addend + sv) */
+ RELOC_LO10, /* data[0:9] = (addend + sv) */
+ RELOC_SFA_BASE,
+ RELOC_SFA_OFF13,
+ /* P.I.C. (base-relative) */
+ RELOC_BASE10, /* Not sure - maybe we can do this the */
+ RELOC_BASE13, /* right way now */
+ RELOC_BASE22,
+ /* for some sort of pc-rel P.I.C. (?) */
+ RELOC_PC10,
+ RELOC_PC22,
+ /* P.I.C. jump table */
+ RELOC_JMP_TBL,
+ /* reputedly for shared libraries somehow */
+ RELOC_SEGOFF16,
+ RELOC_GLOB_DAT,
+ RELOC_JMP_SLOT,
+ RELOC_RELATIVE,
+
+ RELOC_11,
+ RELOC_WDISP2_14,
+ RELOC_WDISP19,
+ RELOC_HHI22, /* data[0:21] = (addend + sv) >> 42 */
+ RELOC_HLO10, /* data[0:9] = (addend + sv) >> 32 */
+
+ /* 29K relocation types */
+ RELOC_JUMPTARG,
+ RELOC_CONST,
+ RELOC_CONSTH,
+
+ /* All the new ones I can think of, for sparc v9 */
+
+ RELOC_64, /* data[0:63] = addend + sv */
+ RELOC_DISP64, /* data[0:63] = addend - pc + sv */
+ RELOC_WDISP21, /* data[0:20] = (addend + sv - pc)>>2 */
+ RELOC_DISP21, /* data[0:20] = addend - pc + sv */
+ RELOC_DISP14, /* data[0:13] = addend - pc + sv */
+ /* Q .
+ What are the other ones,
+ Since this is a clean slate, can we throw away the ones we dont
+ understand ? Should we sort the values ? What about using a
+ microcode format like the 68k ?
+ */
+ NO_RELOC
+ };
+
+
+struct reloc_internal {
+ bfd_vma r_address; /* offset of of data to relocate */
+ long r_index; /* symbol table index of symbol */
+ enum reloc_type r_type; /* relocation type */
+ bfd_vma r_addend; /* datum addend */
+};
+
+/* Q.
+ Should the length of the string table be 4 bytes or 8 bytes ?
+
+ Q.
+ What about archive indexes ?
+
+ */
+
+#endif /* __A_OUT_64_H__ */
diff --git a/pstack/aout/stab.def b/pstack/aout/stab.def
new file mode 100644
index 00000000000..3c6b456d3a9
--- /dev/null
+++ b/pstack/aout/stab.def
@@ -0,0 +1,264 @@
+/* Table of DBX symbol codes for the GNU system.
+ Copyright (C) 1988, 91, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* New stab from Solaris 2. This uses an n_type of 0, which in a.out files
+ overlaps the N_UNDF used for ordinary symbols. In ELF files, the
+ debug information is in a different file section, so there is no conflict.
+ This symbol's n_value gives the size of the string section associated
+ with this file. The symbol's n_strx (relative to the just-updated
+ string section start address) gives the name of the source file,
+ e.g. "foo.c", without any path information. The symbol's n_desc gives
+ the count of upcoming symbols associated with this file (not including
+ this one). */
+/* __define_stab (N_UNDF, 0x00, "UNDF") */
+
+/* Global variable. Only the name is significant.
+ To find the address, look in the corresponding external symbol. */
+__define_stab (N_GSYM, 0x20, "GSYM")
+
+/* Function name for BSD Fortran. Only the name is significant.
+ To find the address, look in the corresponding external symbol. */
+__define_stab (N_FNAME, 0x22, "FNAME")
+
+/* Function name or text-segment variable for C. Value is its address.
+ Desc is supposedly starting line number, but GCC doesn't set it
+ and DBX seems not to miss it. */
+__define_stab (N_FUN, 0x24, "FUN")
+
+/* Data-segment variable with internal linkage. Value is its address.
+ "Static Sym". */
+__define_stab (N_STSYM, 0x26, "STSYM")
+
+/* BSS-segment variable with internal linkage. Value is its address. */
+__define_stab (N_LCSYM, 0x28, "LCSYM")
+
+/* Name of main routine. Only the name is significant. */
+__define_stab (N_MAIN, 0x2a, "MAIN")
+
+/* Solaris2: Read-only data symbols. */
+__define_stab (N_ROSYM, 0x2c, "ROSYM")
+
+/* Global symbol in Pascal.
+ Supposedly the value is its line number; I'm skeptical. */
+__define_stab (N_PC, 0x30, "PC")
+
+/* Number of symbols: 0, files,,funcs,lines according to Ultrix V4.0. */
+__define_stab (N_NSYMS, 0x32, "NSYMS")
+
+/* "No DST map for sym: name, ,0,type,ignored" according to Ultrix V4.0. */
+__define_stab (N_NOMAP, 0x34, "NOMAP")
+
+/* New stab from Solaris 2. Like N_SO, but for the object file. Two in
+ a row provide the build directory and the relative path of the .o from it.
+ Solaris2 uses this to avoid putting the stabs info into the linked
+ executable; this stab goes into the ".stab.index" section, and the debugger
+ reads the real stabs directly from the .o files instead. */
+__define_stab (N_OBJ, 0x38, "OBJ")
+
+/* New stab from Solaris 2. Options for the debugger, related to the
+ source language for this module. E.g. whether to use ANSI
+ integral promotions or traditional integral promotions. */
+__define_stab (N_OPT, 0x3c, "OPT")
+
+/* Register variable. Value is number of register. */
+__define_stab (N_RSYM, 0x40, "RSYM")
+
+/* Modula-2 compilation unit. Can someone say what info it contains? */
+__define_stab (N_M2C, 0x42, "M2C")
+
+/* Line number in text segment. Desc is the line number;
+ value is corresponding address. On Solaris2, the line number is
+ relative to the start of the current function. */
+__define_stab (N_SLINE, 0x44, "SLINE")
+
+/* Similar, for data segment. */
+__define_stab (N_DSLINE, 0x46, "DSLINE")
+
+/* Similar, for bss segment. */
+__define_stab (N_BSLINE, 0x48, "BSLINE")
+
+/* Sun's source-code browser stabs. ?? Don't know what the fields are.
+ Supposedly the field is "path to associated .cb file". THIS VALUE
+ OVERLAPS WITH N_BSLINE! */
+__define_stab_duplicate (N_BROWS, 0x48, "BROWS")
+
+/* GNU Modula-2 definition module dependency. Value is the modification time
+ of the definition file. Other is non-zero if it is imported with the
+ GNU M2 keyword %INITIALIZE. Perhaps N_M2C can be used if there
+ are enough empty fields? */
+__define_stab(N_DEFD, 0x4a, "DEFD")
+
+/* New in Solaris2. Function start/body/end line numbers. */
+__define_stab(N_FLINE, 0x4C, "FLINE")
+
+/* THE FOLLOWING TWO STAB VALUES CONFLICT. Happily, one is for Modula-2
+ and one is for C++. Still,... */
+/* GNU C++ exception variable. Name is variable name. */
+__define_stab (N_EHDECL, 0x50, "EHDECL")
+/* Modula2 info "for imc": name,,0,0,0 according to Ultrix V4.0. */
+__define_stab_duplicate (N_MOD2, 0x50, "MOD2")
+
+/* GNU C++ `catch' clause. Value is its address. Desc is nonzero if
+ this entry is immediately followed by a CAUGHT stab saying what exception
+ was caught. Multiple CAUGHT stabs means that multiple exceptions
+ can be caught here. If Desc is 0, it means all exceptions are caught
+ here. */
+__define_stab (N_CATCH, 0x54, "CATCH")
+
+/* Structure or union element. Value is offset in the structure. */
+__define_stab (N_SSYM, 0x60, "SSYM")
+
+/* Solaris2: Last stab emitted for module. */
+__define_stab (N_ENDM, 0x62, "ENDM")
+
+/* Name of main source file.
+ Value is starting text address of the compilation.
+ If multiple N_SO's appear, the first to contain a trailing / is the
+ compilation directory. The first to not contain a trailing / is the
+ source file name, relative to the compilation directory. Others (perhaps
+ resulting from cfront) are ignored.
+ On Solaris2, value is undefined, but desc is a source-language code. */
+
+__define_stab (N_SO, 0x64, "SO")
+
+/* Automatic variable in the stack. Value is offset from frame pointer.
+ Also used for type descriptions. */
+__define_stab (N_LSYM, 0x80, "LSYM")
+
+/* Beginning of an include file. Only Sun uses this.
+ In an object file, only the name is significant.
+ The Sun linker puts data into some of the other fields. */
+__define_stab (N_BINCL, 0x82, "BINCL")
+
+/* Name of sub-source file (#include file).
+ Value is starting text address of the compilation. */
+__define_stab (N_SOL, 0x84, "SOL")
+
+/* Parameter variable. Value is offset from argument pointer.
+ (On most machines the argument pointer is the same as the frame pointer. */
+__define_stab (N_PSYM, 0xa0, "PSYM")
+
+/* End of an include file. No name.
+ This and N_BINCL act as brackets around the file's output.
+ In an object file, there is no significant data in this entry.
+ The Sun linker puts data into some of the fields. */
+__define_stab (N_EINCL, 0xa2, "EINCL")
+
+/* Alternate entry point. Value is its address. */
+__define_stab (N_ENTRY, 0xa4, "ENTRY")
+
+/* Beginning of lexical block.
+ The desc is the nesting level in lexical blocks.
+ The value is the address of the start of the text for the block.
+ The variables declared inside the block *precede* the N_LBRAC symbol.
+ On Solaris2, the value is relative to the start of the current function. */
+__define_stab (N_LBRAC, 0xc0, "LBRAC")
+
+/* Place holder for deleted include file. Replaces a N_BINCL and everything
+ up to the corresponding N_EINCL. The Sun linker generates these when
+ it finds multiple identical copies of the symbols from an include file.
+ This appears only in output from the Sun linker. */
+__define_stab (N_EXCL, 0xc2, "EXCL")
+
+/* Modula-2 scope information. Can someone say what info it contains? */
+__define_stab (N_SCOPE, 0xc4, "SCOPE")
+
+/* End of a lexical block. Desc matches the N_LBRAC's desc.
+ The value is the address of the end of the text for the block.
+ On Solaris2, the value is relative to the start of the current function. */
+__define_stab (N_RBRAC, 0xe0, "RBRAC")
+
+/* Begin named common block. Only the name is significant. */
+__define_stab (N_BCOMM, 0xe2, "BCOMM")
+
+/* End named common block. Only the name is significant
+ (and it should match the N_BCOMM). */
+__define_stab (N_ECOMM, 0xe4, "ECOMM")
+
+/* Member of a common block; value is offset within the common block.
+ This should occur within a BCOMM/ECOMM pair. */
+__define_stab (N_ECOML, 0xe8, "ECOML")
+
+/* Solaris2: Pascal "with" statement: type,,0,0,offset */
+__define_stab (N_WITH, 0xea, "WITH")
+
+/* These STAB's are used on Gould systems for Non-Base register symbols
+ or something like that. FIXME. I have assigned the values at random
+ since I don't have a Gould here. Fixups from Gould folk welcome... */
+__define_stab (N_NBTEXT, 0xF0, "NBTEXT")
+__define_stab (N_NBDATA, 0xF2, "NBDATA")
+__define_stab (N_NBBSS, 0xF4, "NBBSS")
+__define_stab (N_NBSTS, 0xF6, "NBSTS")
+__define_stab (N_NBLCS, 0xF8, "NBLCS")
+
+/* Second symbol entry containing a length-value for the preceding entry.
+ The value is the length. */
+__define_stab (N_LENG, 0xfe, "LENG")
+
+/* The above information, in matrix format.
+
+ STAB MATRIX
+ _________________________________________________
+ | 00 - 1F are not dbx stab symbols |
+ | In most cases, the low bit is the EXTernal bit|
+
+ | 00 UNDEF | 02 ABS | 04 TEXT | 06 DATA |
+ | 01 |EXT | 03 |EXT | 05 |EXT | 07 |EXT |
+
+ | 08 BSS | 0A INDR | 0C FN_SEQ | 0E WEAKA |
+ | 09 |EXT | 0B | 0D WEAKU | 0F WEAKT |
+
+ | 10 WEAKD | 12 COMM | 14 SETA | 16 SETT |
+ | 11 WEAKB | 13 | 15 | 17 |
+
+ | 18 SETD | 1A SETB | 1C SETV | 1E WARNING|
+ | 19 | 1B | 1D | 1F FN |
+
+ |_______________________________________________|
+ | Debug entries with bit 01 set are unused. |
+ | 20 GSYM | 22 FNAME | 24 FUN | 26 STSYM |
+ | 28 LCSYM | 2A MAIN | 2C ROSYM | 2E |
+ | 30 PC | 32 NSYMS | 34 NOMAP | 36 |
+ | 38 OBJ | 3A | 3C OPT | 3E |
+ | 40 RSYM | 42 M2C | 44 SLINE | 46 DSLINE |
+ | 48 BSLINE*| 4A DEFD | 4C FLINE | 4E |
+ | 50 EHDECL*| 52 | 54 CATCH | 56 |
+ | 58 | 5A | 5C | 5E |
+ | 60 SSYM | 62 ENDM | 64 SO | 66 |
+ | 68 | 6A | 6C | 6E |
+ | 70 | 72 | 74 | 76 |
+ | 78 | 7A | 7C | 7E |
+ | 80 LSYM | 82 BINCL | 84 SOL | 86 |
+ | 88 | 8A | 8C | 8E |
+ | 90 | 92 | 94 | 96 |
+ | 98 | 9A | 9C | 9E |
+ | A0 PSYM | A2 EINCL | A4 ENTRY | A6 |
+ | A8 | AA | AC | AE |
+ | B0 | B2 | B4 | B6 |
+ | B8 | BA | BC | BE |
+ | C0 LBRAC | C2 EXCL | C4 SCOPE | C6 |
+ | C8 | CA | CC | CE |
+ | D0 | D2 | D4 | D6 |
+ | D8 | DA | DC | DE |
+ | E0 RBRAC | E2 BCOMM | E4 ECOMM | E6 |
+ | E8 ECOML | EA WITH | EC | EE |
+ | F0 | F2 | F4 | F6 |
+ | F8 | FA | FC | FE LENG |
+ +-----------------------------------------------+
+ * 50 EHDECL is also MOD2.
+ * 48 BSLINE is also BROWS.
+ */
diff --git a/pstack/aout/stab_gnu.h b/pstack/aout/stab_gnu.h
new file mode 100644
index 00000000000..7d18e14a263
--- /dev/null
+++ b/pstack/aout/stab_gnu.h
@@ -0,0 +1,37 @@
+#ifndef __GNU_STAB__
+
+/* Indicate the GNU stab.h is in use. */
+
+#define __GNU_STAB__
+
+#define __define_stab(NAME, CODE, STRING) NAME=CODE,
+#define __define_stab_duplicate(NAME, CODE, STRING) NAME=CODE,
+
+enum __stab_debug_code
+{
+#include "aout/stab.def"
+LAST_UNUSED_STAB_CODE
+};
+
+#undef __define_stab
+
+/* Definitions of "desc" field for N_SO stabs in Solaris2. */
+
+#define N_SO_AS 1
+#define N_SO_C 2
+#define N_SO_ANSI_C 3
+#define N_SO_CC 4 /* C++ */
+#define N_SO_FORTRAN 5
+#define N_SO_PASCAL 6
+
+/* Solaris2: Floating point type values in basic types. */
+
+#define NF_NONE 0
+#define NF_SINGLE 1 /* IEEE 32-bit */
+#define NF_DOUBLE 2 /* IEEE 64-bit */
+#define NF_COMPLEX 3 /* Fortran complex */
+#define NF_COMPLEX16 4 /* Fortran double complex */
+#define NF_COMPLEX32 5 /* Fortran complex*16 */
+#define NF_LDOUBLE 6 /* Long double (whatever that is) */
+
+#endif /* __GNU_STAB_ */
diff --git a/pstack/bucomm.c b/pstack/bucomm.c
new file mode 100644
index 00000000000..d3231e71747
--- /dev/null
+++ b/pstack/bucomm.c
@@ -0,0 +1,238 @@
+/* bucomm.c -- Bin Utils COMmon code.
+ Copyright (C) 1991, 92, 93, 94, 95, 1997 Free Software Foundation, Inc.
+
+ This file is part of GNU Binutils.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+/* We might put this in a library someday so it could be dynamically
+ loaded, but for now it's not necessary. */
+
+#include <bfd.h>
+#include <libiberty.h>
+#include "bucomm.h"
+
+#include <sys/stat.h>
+#include <time.h> /* ctime, maybe time_t */
+
+#ifdef ANSI_PROTOTYPES
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+/* Error reporting */
+
+char *program_name;
+
+void
+bfd_nonfatal (string)
+ CONST char *string;
+{
+ CONST char *errmsg = bfd_errmsg (bfd_get_error ());
+
+ if (string)
+ fprintf (stderr, "%s: %s: %s\n", program_name, string, errmsg);
+ else
+ fprintf (stderr, "%s: %s\n", program_name, errmsg);
+}
+
+void
+bfd_fatal (string)
+ CONST char *string;
+{
+ bfd_nonfatal (string);
+ xexit (1);
+}
+
+#ifdef ANSI_PROTOTYPES
+void
+fatal (const char *format, ...)
+{
+ va_list args;
+
+ fprintf (stderr, "%s: ", program_name);
+ va_start (args, format);
+ vfprintf (stderr, format, args);
+ va_end (args);
+ putc ('\n', stderr);
+ xexit (1);
+}
+#else
+void
+fatal (va_alist)
+ va_dcl
+{
+ char *Format;
+ va_list args;
+
+ fprintf (stderr, "%s: ", program_name);
+ va_start (args);
+ Format = va_arg (args, char *);
+ vfprintf (stderr, Format, args);
+ va_end (args);
+ putc ('\n', stderr);
+ xexit (1);
+}
+#endif
+
+/* Set the default BFD target based on the configured target. Doing
+ this permits the binutils to be configured for a particular target,
+ and linked against a shared BFD library which was configured for a
+ different target. */
+
+#define TARGET "elf32-i386" /* FIXME: hard-coded! */
+void
+set_default_bfd_target ()
+{
+ /* The macro TARGET is defined by Makefile. */
+ const char *target = TARGET;
+
+ if (! bfd_set_default_target (target))
+ {
+ char *errmsg;
+
+ errmsg = (char *) xmalloc (100 + strlen (target));
+ sprintf (errmsg, "can't set BFD default target to `%s'", target);
+ bfd_fatal (errmsg);
+ }
+}
+
+/* After a false return from bfd_check_format_matches with
+ bfd_get_error () == bfd_error_file_ambiguously_recognized, print
+ the possible matching targets. */
+
+void
+list_matching_formats (p)
+ char **p;
+{
+ fprintf(stderr, "%s: Matching formats:", program_name);
+ while (*p)
+ fprintf(stderr, " %s", *p++);
+ fprintf(stderr, "\n");
+}
+
+/* List the supported targets. */
+
+void
+list_supported_targets (name, f)
+ const char *name;
+ FILE *f;
+{
+ extern bfd_target *bfd_target_vector[];
+ int t;
+
+ if (name == NULL)
+ fprintf (f, "Supported targets:");
+ else
+ fprintf (f, "%s: supported targets:", name);
+ for (t = 0; bfd_target_vector[t] != NULL; t++)
+ fprintf (f, " %s", bfd_target_vector[t]->name);
+ fprintf (f, "\n");
+}
+
+/* Display the archive header for an element as if it were an ls -l listing:
+
+ Mode User\tGroup\tSize\tDate Name */
+
+void
+print_arelt_descr (file, abfd, verbose)
+ FILE *file;
+ bfd *abfd;
+ boolean verbose;
+{
+ struct stat buf;
+
+ if (verbose)
+ {
+ if (bfd_stat_arch_elt (abfd, &buf) == 0)
+ {
+ char modebuf[11];
+ char timebuf[40];
+ time_t when = buf.st_mtime;
+ CONST char *ctime_result = (CONST char *) ctime (&when);
+
+ /* POSIX format: skip weekday and seconds from ctime output. */
+ sprintf (timebuf, "%.12s %.4s", ctime_result + 4, ctime_result + 20);
+
+ mode_string (buf.st_mode, modebuf);
+ modebuf[10] = '\0';
+ /* POSIX 1003.2/D11 says to skip first character (entry type). */
+ fprintf (file, "%s %ld/%ld %6ld %s ", modebuf + 1,
+ (long) buf.st_uid, (long) buf.st_gid,
+ (long) buf.st_size, timebuf);
+ }
+ }
+
+ fprintf (file, "%s\n", bfd_get_filename (abfd));
+}
+
+/* Return the name of a temporary file in the same directory as FILENAME. */
+
+char *
+make_tempname (filename)
+ char *filename;
+{
+ static char template[] = "stXXXXXX";
+ char *tmpname;
+ char *slash = strrchr (filename, '/');
+
+#if defined (__DJGPP__) || defined (__GO32__) || defined (_WIN32)
+ if (slash == NULL)
+ slash = strrchr (filename, '\\');
+#endif
+
+ if (slash != (char *) NULL)
+ {
+ char c;
+
+ c = *slash;
+ *slash = 0;
+ tmpname = xmalloc (strlen (filename) + sizeof (template) + 1);
+ strcpy (tmpname, filename);
+ strcat (tmpname, "/");
+ strcat (tmpname, template);
+ mkstemp (tmpname);
+ *slash = c;
+ }
+ else
+ {
+ tmpname = xmalloc (sizeof (template));
+ strcpy (tmpname, template);
+ mkstemp (tmpname);
+ }
+ return tmpname;
+}
+
+/* Parse a string into a VMA, with a fatal error if it can't be
+ parsed. */
+
+bfd_vma
+parse_vma (s, arg)
+ const char *s;
+ const char *arg;
+{
+ bfd_vma ret;
+ const char *end;
+
+ ret = bfd_scan_vma (s, &end, 0);
+ if (*end != '\0')
+ {
+ fprintf (stderr, "%s: %s: bad number: %s\n", program_name, arg, s);
+ exit (1);
+ }
+ return ret;
+}
diff --git a/pstack/bucomm.h b/pstack/bucomm.h
new file mode 100644
index 00000000000..7712a70f5a2
--- /dev/null
+++ b/pstack/bucomm.h
@@ -0,0 +1,85 @@
+/* bucomm.h -- binutils common include file.
+ Copyright (C) 1992, 93, 94, 95, 96, 1997 Free Software Foundation, Inc.
+
+This file is part of GNU Binutils.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef _BUCOMM_H
+#define _BUCOMM_H
+
+#include "ansidecl.h"
+#include <stdio.h>
+#include <sys/types.h>
+
+#include <errno.h>
+#include <unistd.h>
+
+#include <string.h>
+
+#include <stdlib.h>
+
+#include <fcntl.h>
+
+#ifdef __GNUC__
+# undef alloca
+# define alloca __builtin_alloca
+#else
+# if HAVE_ALLOCA_H
+# include <alloca.h>
+# else
+# ifndef alloca /* predefined by HP cc +Olibcalls */
+# if !defined (__STDC__) && !defined (__hpux)
+char *alloca ();
+# else
+void *alloca ();
+# endif /* __STDC__, __hpux */
+# endif /* alloca */
+# endif /* HAVE_ALLOCA_H */
+#endif
+
+/* bucomm.c */
+void bfd_nonfatal PARAMS ((CONST char *));
+
+void bfd_fatal PARAMS ((CONST char *));
+
+void fatal PARAMS ((CONST char *, ...));
+
+void set_default_bfd_target PARAMS ((void));
+
+void list_matching_formats PARAMS ((char **p));
+
+void list_supported_targets PARAMS ((const char *, FILE *));
+
+void print_arelt_descr PARAMS ((FILE *file, bfd *abfd, boolean verbose));
+
+char *make_tempname PARAMS ((char *));
+
+bfd_vma parse_vma PARAMS ((const char *, const char *));
+
+extern char *program_name;
+
+/* filemode.c */
+void mode_string PARAMS ((unsigned long mode, char *buf));
+
+/* version.c */
+extern void print_version PARAMS ((const char *));
+
+/* libiberty */
+PTR xmalloc PARAMS ((size_t));
+
+PTR xrealloc PARAMS ((PTR, size_t));
+
+#endif /* _BUCOMM_H */
diff --git a/pstack/budbg.h b/pstack/budbg.h
new file mode 100644
index 00000000000..d8ee8895e76
--- /dev/null
+++ b/pstack/budbg.h
@@ -0,0 +1,58 @@
+/* budbg.c -- Interfaces to the generic debugging information routines.
+ Copyright (C) 1995, 1996 Free Software Foundation, Inc.
+ Written by Ian Lance Taylor <ian@cygnus.com>.
+
+ This file is part of GNU Binutils.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+#ifndef BUDBG_H
+#define BUDBG_H
+
+#include <stdio.h>
+
+/* Routine used to read generic debugging information. */
+
+extern PTR read_debugging_info PARAMS ((bfd *, asymbol **, long));
+
+/* Routine used to print generic debugging information. */
+
+extern boolean print_debugging_info PARAMS ((FILE *, PTR));
+
+/* Routines used to read and write stabs information. */
+
+extern PTR start_stab PARAMS ((PTR, bfd *, boolean, asymbol **, long));
+
+extern boolean finish_stab PARAMS ((PTR, PTR));
+
+extern boolean parse_stab PARAMS ((PTR, PTR, int, int, bfd_vma, const char *));
+
+extern boolean write_stabs_in_sections_debugging_info
+ PARAMS ((bfd *, PTR, bfd_byte **, bfd_size_type *, bfd_byte **,
+ bfd_size_type *));
+
+/* Routines used to read and write IEEE debugging information. */
+
+extern boolean parse_ieee
+ PARAMS ((PTR, bfd *, const bfd_byte *, bfd_size_type));
+
+extern boolean write_ieee_debugging_info PARAMS ((bfd *, PTR));
+
+/* Routine used to read COFF debugging information. */
+
+extern boolean parse_coff PARAMS ((bfd *, asymbol **, long, PTR));
+
+#endif
diff --git a/pstack/debug.c b/pstack/debug.c
new file mode 100644
index 00000000000..73412ae3f03
--- /dev/null
+++ b/pstack/debug.c
@@ -0,0 +1,3509 @@
+/* debug.c -- Handle generic debugging information.
+ Copyright (C) 1995, 1996 Free Software Foundation, Inc.
+ Written by Ian Lance Taylor <ian@cygnus.com>.
+
+ This file is part of GNU Binutils.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+/* This file implements a generic debugging format. We may eventually
+ have readers which convert different formats into this generic
+ format, and writers which write it out. The initial impetus for
+ this was writing a convertor from stabs to HP IEEE-695 debugging
+ format. */
+
+#include <stdio.h>
+#include <assert.h>
+
+#include <bfd.h>
+#include "bucomm.h"
+#include <libiberty.h>
+#include "debug.h"
+
+/* Global information we keep for debugging. A pointer to this
+ structure is the debugging handle passed to all the routines. */
+
+struct debug_handle
+{
+ /* A linked list of compilation units. */
+ struct debug_unit *units;
+ /* The current compilation unit. */
+ struct debug_unit *current_unit;
+ /* The current source file. */
+ struct debug_file *current_file;
+ /* The current function. */
+ struct debug_function *current_function;
+ /* The current block. */
+ struct debug_block *current_block;
+ /* The current line number information for the current unit. */
+ struct debug_lineno *current_lineno;
+ /* Mark. This is used by debug_write. */
+ unsigned int mark;
+ /* A struct/class ID used by debug_write. */
+ unsigned int class_id;
+ /* The base for class_id for this call to debug_write. */
+ unsigned int base_id;
+ /* The current line number in debug_write. */
+ struct debug_lineno *current_write_lineno;
+ unsigned int current_write_lineno_index;
+ /* A list of classes which have assigned ID's during debug_write.
+ This is linked through the next_id field of debug_class_type. */
+ struct debug_class_id *id_list;
+ /* A list used to avoid recursion during debug_type_samep. */
+ struct debug_type_compare_list *compare_list;
+};
+
+/* Information we keep for a single compilation unit. */
+
+struct debug_unit
+{
+ /* The next compilation unit. */
+ struct debug_unit *next;
+ /* A list of files included in this compilation unit. The first
+ file is always the main one, and that is where the main file name
+ is stored. */
+ struct debug_file *files;
+ /* Line number information for this compilation unit. This is not
+ stored by function, because assembler code may have line number
+ information without function information. */
+ struct debug_lineno *linenos;
+};
+
+/* Information kept for a single source file. */
+
+struct debug_file
+{
+ /* The next source file in this compilation unit. */
+ struct debug_file *next;
+ /* The name of the source file. */
+ const char *filename;
+ /* Global functions, variables, types, etc. */
+ struct debug_namespace *globals;
+};
+
+/* A type. */
+
+struct debug_type
+{
+ /* Kind of type. */
+ enum debug_type_kind kind;
+ /* Size of type (0 if not known). */
+ unsigned int size;
+ /* Type which is a pointer to this type. */
+ debug_type pointer;
+ /* Tagged union with additional information about the type. */
+ union
+ {
+ /* DEBUG_KIND_INDIRECT. */
+ struct debug_indirect_type *kindirect;
+ /* DEBUG_KIND_INT. */
+ /* Whether the integer is unsigned. */
+ boolean kint;
+ /* DEBUG_KIND_STRUCT, DEBUG_KIND_UNION, DEBUG_KIND_CLASS,
+ DEBUG_KIND_UNION_CLASS. */
+ struct debug_class_type *kclass;
+ /* DEBUG_KIND_ENUM. */
+ struct debug_enum_type *kenum;
+ /* DEBUG_KIND_POINTER. */
+ struct debug_type *kpointer;
+ /* DEBUG_KIND_FUNCTION. */
+ struct debug_function_type *kfunction;
+ /* DEBUG_KIND_REFERENCE. */
+ struct debug_type *kreference;
+ /* DEBUG_KIND_RANGE. */
+ struct debug_range_type *krange;
+ /* DEBUG_KIND_ARRAY. */
+ struct debug_array_type *karray;
+ /* DEBUG_KIND_SET. */
+ struct debug_set_type *kset;
+ /* DEBUG_KIND_OFFSET. */
+ struct debug_offset_type *koffset;
+ /* DEBUG_KIND_METHOD. */
+ struct debug_method_type *kmethod;
+ /* DEBUG_KIND_CONST. */
+ struct debug_type *kconst;
+ /* DEBUG_KIND_VOLATILE. */
+ struct debug_type *kvolatile;
+ /* DEBUG_KIND_NAMED, DEBUG_KIND_TAGGED. */
+ struct debug_named_type *knamed;
+ } u;
+};
+
+/* Information kept for an indirect type. */
+
+struct debug_indirect_type
+{
+ /* Slot where the final type will appear. */
+ debug_type *slot;
+ /* Tag. */
+ const char *tag;
+};
+
+/* Information kept for a struct, union, or class. */
+
+struct debug_class_type
+{
+ /* NULL terminated array of fields. */
+ debug_field *fields;
+ /* A mark field which indicates whether the struct has already been
+ printed. */
+ unsigned int mark;
+ /* This is used to uniquely identify unnamed structs when printing. */
+ unsigned int id;
+ /* The remaining fields are only used for DEBUG_KIND_CLASS and
+ DEBUG_KIND_UNION_CLASS. */
+ /* NULL terminated array of base classes. */
+ debug_baseclass *baseclasses;
+ /* NULL terminated array of methods. */
+ debug_method *methods;
+ /* The type of the class providing the virtual function table for
+ this class. This may point to the type itself. */
+ debug_type vptrbase;
+};
+
+/* Information kept for an enum. */
+
+struct debug_enum_type
+{
+ /* NULL terminated array of names. */
+ const char **names;
+ /* Array of corresponding values. */
+ bfd_signed_vma *values;
+};
+
+/* Information kept for a function. FIXME: We should be able to
+ record the parameter types. */
+
+struct debug_function_type
+{
+ /* Return type. */
+ debug_type return_type;
+ /* NULL terminated array of argument types. */
+ debug_type *arg_types;
+ /* Whether the function takes a variable number of arguments. */
+ boolean varargs;
+};
+
+/* Information kept for a range. */
+
+struct debug_range_type
+{
+ /* Range base type. */
+ debug_type type;
+ /* Lower bound. */
+ bfd_signed_vma lower;
+ /* Upper bound. */
+ bfd_signed_vma upper;
+};
+
+/* Information kept for an array. */
+
+struct debug_array_type
+{
+ /* Element type. */
+ debug_type element_type;
+ /* Range type. */
+ debug_type range_type;
+ /* Lower bound. */
+ bfd_signed_vma lower;
+ /* Upper bound. */
+ bfd_signed_vma upper;
+ /* Whether this array is really a string. */
+ boolean stringp;
+};
+
+/* Information kept for a set. */
+
+struct debug_set_type
+{
+ /* Base type. */
+ debug_type type;
+ /* Whether this set is really a bitstring. */
+ boolean bitstringp;
+};
+
+/* Information kept for an offset type (a based pointer). */
+
+struct debug_offset_type
+{
+ /* The type the pointer is an offset from. */
+ debug_type base_type;
+ /* The type the pointer points to. */
+ debug_type target_type;
+};
+
+/* Information kept for a method type. */
+
+struct debug_method_type
+{
+ /* The return type. */
+ debug_type return_type;
+ /* The object type which this method is for. */
+ debug_type domain_type;
+ /* A NULL terminated array of argument types. */
+ debug_type *arg_types;
+ /* Whether the method takes a variable number of arguments. */
+ boolean varargs;
+};
+
+/* Information kept for a named type. */
+
+struct debug_named_type
+{
+ /* Name. */
+ struct debug_name *name;
+ /* Real type. */
+ debug_type type;
+};
+
+/* A field in a struct or union. */
+
+struct debug_field
+{
+ /* Name of the field. */
+ const char *name;
+ /* Type of the field. */
+ struct debug_type *type;
+ /* Visibility of the field. */
+ enum debug_visibility visibility;
+ /* Whether this is a static member. */
+ boolean static_member;
+ union
+ {
+ /* If static_member is false. */
+ struct
+ {
+ /* Bit position of the field in the struct. */
+ unsigned int bitpos;
+ /* Size of the field in bits. */
+ unsigned int bitsize;
+ } f;
+ /* If static_member is true. */
+ struct
+ {
+ const char *physname;
+ } s;
+ } u;
+};
+
+/* A base class for an object. */
+
+struct debug_baseclass
+{
+ /* Type of the base class. */
+ struct debug_type *type;
+ /* Bit position of the base class in the object. */
+ unsigned int bitpos;
+ /* Whether the base class is virtual. */
+ boolean virtual;
+ /* Visibility of the base class. */
+ enum debug_visibility visibility;
+};
+
+/* A method of an object. */
+
+struct debug_method
+{
+ /* The name of the method. */
+ const char *name;
+ /* A NULL terminated array of different types of variants. */
+ struct debug_method_variant **variants;
+};
+
+/* The variants of a method function of an object. These indicate
+ which method to run. */
+
+struct debug_method_variant
+{
+ /* The physical name of the function. */
+ const char *physname;
+ /* The type of the function. */
+ struct debug_type *type;
+ /* The visibility of the function. */
+ enum debug_visibility visibility;
+ /* Whether the function is const. */
+ boolean constp;
+ /* Whether the function is volatile. */
+ boolean volatilep;
+ /* The offset to the function in the virtual function table. */
+ bfd_vma voffset;
+ /* If voffset is VOFFSET_STATIC_METHOD, this is a static method. */
+#define VOFFSET_STATIC_METHOD ((bfd_vma) -1)
+ /* Context of a virtual method function. */
+ struct debug_type *context;
+};
+
+/* A variable. This is the information we keep for a variable object.
+ This has no name; a name is associated with a variable in a
+ debug_name structure. */
+
+struct debug_variable
+{
+ /* Kind of variable. */
+ enum debug_var_kind kind;
+ /* Type. */
+ debug_type type;
+ /* Value. The interpretation of the value depends upon kind. */
+ bfd_vma val;
+};
+
+/* A function. This has no name; a name is associated with a function
+ in a debug_name structure. */
+
+struct debug_function
+{
+ /* Return type. */
+ debug_type return_type;
+ /* Parameter information. */
+ struct debug_parameter *parameters;
+ /* Block information. The first structure on the list is the main
+ block of the function, and describes function local variables. */
+ struct debug_block *blocks;
+};
+
+/* A function parameter. */
+
+struct debug_parameter
+{
+ /* Next parameter. */
+ struct debug_parameter *next;
+ /* Name. */
+ const char *name;
+ /* Type. */
+ debug_type type;
+ /* Kind. */
+ enum debug_parm_kind kind;
+ /* Value (meaning depends upon kind). */
+ bfd_vma val;
+};
+
+/* A typed constant. */
+
+struct debug_typed_constant
+{
+ /* Type. */
+ debug_type type;
+ /* Value. FIXME: We may eventually need to support non-integral
+ values. */
+ bfd_vma val;
+};
+
+/* Information about a block within a function. */
+
+struct debug_block
+{
+ /* Next block with the same parent. */
+ struct debug_block *next;
+ /* Parent block. */
+ struct debug_block *parent;
+ /* List of child blocks. */
+ struct debug_block *children;
+ /* Start address of the block. */
+ bfd_vma start;
+ /* End address of the block. */
+ bfd_vma end;
+ /* Local variables. */
+ struct debug_namespace *locals;
+};
+
+/* Line number information we keep for a compilation unit. FIXME:
+ This structure is easy to create, but can be very space
+ inefficient. */
+
+struct debug_lineno
+{
+ /* More line number information for this block. */
+ struct debug_lineno *next;
+ /* Source file. */
+ struct debug_file *file;
+ /* Line numbers, terminated by a -1 or the end of the array. */
+#define DEBUG_LINENO_COUNT 10
+ unsigned long linenos[DEBUG_LINENO_COUNT];
+ /* Addresses for the line numbers. */
+ bfd_vma addrs[DEBUG_LINENO_COUNT];
+};
+
+/* A namespace. This is a mapping from names to objects. FIXME: This
+ should be implemented as a hash table. */
+
+struct debug_namespace
+{
+ /* List of items in this namespace. */
+ struct debug_name *list;
+ /* Pointer to where the next item in this namespace should go. */
+ struct debug_name **tail;
+};
+
+/* Kinds of objects that appear in a namespace. */
+
+enum debug_object_kind
+{
+ /* A type. */
+ DEBUG_OBJECT_TYPE,
+ /* A tagged type (really a different sort of namespace). */
+ DEBUG_OBJECT_TAG,
+ /* A variable. */
+ DEBUG_OBJECT_VARIABLE,
+ /* A function. */
+ DEBUG_OBJECT_FUNCTION,
+ /* An integer constant. */
+ DEBUG_OBJECT_INT_CONSTANT,
+ /* A floating point constant. */
+ DEBUG_OBJECT_FLOAT_CONSTANT,
+ /* A typed constant. */
+ DEBUG_OBJECT_TYPED_CONSTANT
+};
+
+/* Linkage of an object that appears in a namespace. */
+
+enum debug_object_linkage
+{
+ /* Local variable. */
+ DEBUG_LINKAGE_AUTOMATIC,
+ /* Static--either file static or function static, depending upon the
+ namespace is. */
+ DEBUG_LINKAGE_STATIC,
+ /* Global. */
+ DEBUG_LINKAGE_GLOBAL,
+ /* No linkage. */
+ DEBUG_LINKAGE_NONE
+};
+
+/* A name in a namespace. */
+
+struct debug_name
+{
+ /* Next name in this namespace. */
+ struct debug_name *next;
+ /* Name. */
+ const char *name;
+ /* Mark. This is used by debug_write. */
+ unsigned int mark;
+ /* Kind of object. */
+ enum debug_object_kind kind;
+ /* Linkage of object. */
+ enum debug_object_linkage linkage;
+ /* Tagged union with additional information about the object. */
+ union
+ {
+ /* DEBUG_OBJECT_TYPE. */
+ struct debug_type *type;
+ /* DEBUG_OBJECT_TAG. */
+ struct debug_type *tag;
+ /* DEBUG_OBJECT_VARIABLE. */
+ struct debug_variable *variable;
+ /* DEBUG_OBJECT_FUNCTION. */
+ struct debug_function *function;
+ /* DEBUG_OBJECT_INT_CONSTANT. */
+ bfd_vma int_constant;
+ /* DEBUG_OBJECT_FLOAT_CONSTANT. */
+ double float_constant;
+ /* DEBUG_OBJECT_TYPED_CONSTANT. */
+ struct debug_typed_constant *typed_constant;
+ } u;
+};
+
+/* During debug_write, a linked list of these structures is used to
+ keep track of ID numbers that have been assigned to classes. */
+
+struct debug_class_id
+{
+ /* Next ID number. */
+ struct debug_class_id *next;
+ /* The type with the ID. */
+ struct debug_type *type;
+ /* The tag; NULL if no tag. */
+ const char *tag;
+};
+
+/* During debug_type_samep, a linked list of these structures is kept
+ on the stack to avoid infinite recursion. */
+
+struct debug_type_compare_list
+{
+ /* Next type on list. */
+ struct debug_type_compare_list *next;
+ /* The types we are comparing. */
+ struct debug_type *t1;
+ struct debug_type *t2;
+};
+
+/* Local functions. */
+
+static void debug_error PARAMS ((const char *));
+static struct debug_name *debug_add_to_namespace
+ PARAMS ((struct debug_handle *, struct debug_namespace **, const char *,
+ enum debug_object_kind, enum debug_object_linkage));
+static struct debug_name *debug_add_to_current_namespace
+ PARAMS ((struct debug_handle *, const char *, enum debug_object_kind,
+ enum debug_object_linkage));
+static struct debug_type *debug_make_type
+ PARAMS ((struct debug_handle *, enum debug_type_kind, unsigned int));
+static struct debug_type *debug_get_real_type PARAMS ((PTR, debug_type));
+static boolean debug_write_name
+ PARAMS ((struct debug_handle *, const struct debug_write_fns *, PTR,
+ struct debug_name *));
+static boolean debug_write_type
+ PARAMS ((struct debug_handle *, const struct debug_write_fns *, PTR,
+ struct debug_type *, struct debug_name *));
+static boolean debug_write_class_type
+ PARAMS ((struct debug_handle *, const struct debug_write_fns *, PTR,
+ struct debug_type *, const char *));
+static boolean debug_write_function
+ PARAMS ((struct debug_handle *, const struct debug_write_fns *, PTR,
+ const char *, enum debug_object_linkage, struct debug_function *));
+static boolean debug_write_block
+ PARAMS ((struct debug_handle *, const struct debug_write_fns *, PTR,
+ struct debug_block *));
+static boolean debug_write_linenos
+ PARAMS ((struct debug_handle *, const struct debug_write_fns *, PTR,
+ bfd_vma));
+static boolean debug_set_class_id
+ PARAMS ((struct debug_handle *, const char *, struct debug_type *));
+static boolean debug_type_samep
+ PARAMS ((struct debug_handle *, struct debug_type *, struct debug_type *));
+static boolean debug_class_type_samep
+ PARAMS ((struct debug_handle *, struct debug_type *, struct debug_type *));
+
+/* Issue an error message. */
+
+static void
+debug_error (message)
+ const char *message;
+{
+ fprintf (stderr, "%s\n", message);
+}
+
+/* Add an object to a namespace. */
+
+static struct debug_name *
+debug_add_to_namespace (info, nsp, name, kind, linkage)
+ struct debug_handle *info;
+ struct debug_namespace **nsp;
+ const char *name;
+ enum debug_object_kind kind;
+ enum debug_object_linkage linkage;
+{
+ struct debug_name *n;
+ struct debug_namespace *ns;
+
+ n = (struct debug_name *) xmalloc (sizeof *n);
+ memset (n, 0, sizeof *n);
+
+ n->name = name;
+ n->kind = kind;
+ n->linkage = linkage;
+
+ ns = *nsp;
+ if (ns == NULL)
+ {
+ ns = (struct debug_namespace *) xmalloc (sizeof *ns);
+ memset (ns, 0, sizeof *ns);
+
+ ns->tail = &ns->list;
+
+ *nsp = ns;
+ }
+
+ *ns->tail = n;
+ ns->tail = &n->next;
+
+ return n;
+}
+
+/* Add an object to the current namespace. */
+
+static struct debug_name *
+debug_add_to_current_namespace (info, name, kind, linkage)
+ struct debug_handle *info;
+ const char *name;
+ enum debug_object_kind kind;
+ enum debug_object_linkage linkage;
+{
+ struct debug_namespace **nsp;
+
+ if (info->current_unit == NULL
+ || info->current_file == NULL)
+ {
+ debug_error ("debug_add_to_current_namespace: no current file");
+ return NULL;
+ }
+
+ if (info->current_block != NULL)
+ nsp = &info->current_block->locals;
+ else
+ nsp = &info->current_file->globals;
+
+ return debug_add_to_namespace (info, nsp, name, kind, linkage);
+}
+
+/* Return a handle for debugging information. */
+
+PTR
+debug_init ()
+{
+ struct debug_handle *ret;
+
+ ret = (struct debug_handle *) xmalloc (sizeof *ret);
+ memset (ret, 0, sizeof *ret);
+ return (PTR) ret;
+}
+
+/* Set the source filename. This implicitly starts a new compilation
+ unit. */
+
+boolean
+debug_set_filename (handle, name)
+ PTR handle;
+ const char *name;
+{
+ struct debug_handle *info = (struct debug_handle *) handle;
+ struct debug_file *nfile;
+ struct debug_unit *nunit;
+
+ if (name == NULL)
+ name = "";
+
+ nfile = (struct debug_file *) xmalloc (sizeof *nfile);
+ memset (nfile, 0, sizeof *nfile);
+
+ nfile->filename = name;
+
+ nunit = (struct debug_unit *) xmalloc (sizeof *nunit);
+ memset (nunit, 0, sizeof *nunit);
+
+ nunit->files = nfile;
+ info->current_file = nfile;
+
+ if (info->current_unit != NULL)
+ info->current_unit->next = nunit;
+ else
+ {
+ assert (info->units == NULL);
+ info->units = nunit;
+ }
+
+ info->current_unit = nunit;
+
+ info->current_function = NULL;
+ info->current_block = NULL;
+ info->current_lineno = NULL;
+
+ return true;
+}
+
+/* Change source files to the given file name. This is used for
+ include files in a single compilation unit. */
+
+boolean
+debug_start_source (handle, name)
+ PTR handle;
+ const char *name;
+{
+ struct debug_handle *info = (struct debug_handle *) handle;
+ struct debug_file *f, **pf;
+
+ if (name == NULL)
+ name = "";
+
+ if (info->current_unit == NULL)
+ {
+ debug_error ("debug_start_source: no debug_set_filename call");
+ return false;
+ }
+
+ for (f = info->current_unit->files; f != NULL; f = f->next)
+ {
+ if (f->filename[0] == name[0]
+ && f->filename[1] == name[1]
+ && strcmp (f->filename, name) == 0)
+ {
+ info->current_file = f;
+ return true;
+ }
+ }
+
+ f = (struct debug_file *) xmalloc (sizeof *f);
+ memset (f, 0, sizeof *f);
+
+ f->filename = name;
+
+ for (pf = &info->current_file->next;
+ *pf != NULL;
+ pf = &(*pf)->next)
+ ;
+ *pf = f;
+
+ info->current_file = f;
+
+ return true;
+}
+
+/* Record a function definition. This implicitly starts a function
+ block. The debug_type argument is the type of the return value.
+ The boolean indicates whether the function is globally visible.
+ The bfd_vma is the address of the start of the function. Currently
+ the parameter types are specified by calls to
+ debug_record_parameter. FIXME: There is no way to specify nested
+ functions. */
+
+boolean
+debug_record_function (handle, name, return_type, global, addr)
+ PTR handle;
+ const char *name;
+ debug_type return_type;
+ boolean global;
+ bfd_vma addr;
+{
+ struct debug_handle *info = (struct debug_handle *) handle;
+ struct debug_function *f;
+ struct debug_block *b;
+ struct debug_name *n;
+
+ if (name == NULL)
+ name = "";
+ if (return_type == NULL)
+ return false;
+
+ if (info->current_unit == NULL)
+ {
+ debug_error ("debug_record_function: no debug_set_filename call");
+ return false;
+ }
+
+ f = (struct debug_function *) xmalloc (sizeof *f);
+ memset (f, 0, sizeof *f);
+
+ f->return_type = return_type;
+
+ b = (struct debug_block *) xmalloc (sizeof *b);
+ memset (b, 0, sizeof *b);
+
+ b->start = addr;
+ b->end = (bfd_vma) -1;
+
+ f->blocks = b;
+
+ info->current_function = f;
+ info->current_block = b;
+
+ /* FIXME: If we could handle nested functions, this would be the
+ place: we would want to use a different namespace. */
+ n = debug_add_to_namespace (info,
+ &info->current_file->globals,
+ name,
+ DEBUG_OBJECT_FUNCTION,
+ (global
+ ? DEBUG_LINKAGE_GLOBAL
+ : DEBUG_LINKAGE_STATIC));
+ if (n == NULL)
+ return false;
+
+ n->u.function = f;
+
+ return true;
+}
+
+/* Record a parameter for the current function. */
+
+boolean
+debug_record_parameter (handle, name, type, kind, val)
+ PTR handle;
+ const char *name;
+ debug_type type;
+ enum debug_parm_kind kind;
+ bfd_vma val;
+{
+ struct debug_handle *info = (struct debug_handle *) handle;
+ struct debug_parameter *p, **pp;
+
+ if (name == NULL || type == NULL)
+ return false;
+
+ if (info->current_unit == NULL
+ || info->current_function == NULL)
+ {
+ debug_error ("debug_record_parameter: no current function");
+ return false;
+ }
+
+ p = (struct debug_parameter *) xmalloc (sizeof *p);
+ memset (p, 0, sizeof *p);
+
+ p->name = name;
+ p->type = type;
+ p->kind = kind;
+ p->val = val;
+
+ for (pp = &info->current_function->parameters;
+ *pp != NULL;
+ pp = &(*pp)->next)
+ ;
+ *pp = p;
+
+ return true;
+}
+
+/* End a function. FIXME: This should handle function nesting. */
+
+boolean
+debug_end_function (handle, addr)
+ PTR handle;
+ bfd_vma addr;
+{
+ struct debug_handle *info = (struct debug_handle *) handle;
+
+ if (info->current_unit == NULL
+ || info->current_block == NULL
+ || info->current_function == NULL)
+ {
+ debug_error ("debug_end_function: no current function");
+ return false;
+ }
+
+ if (info->current_block->parent != NULL)
+ {
+ debug_error ("debug_end_function: some blocks were not closed");
+ return false;
+ }
+
+ info->current_block->end = addr;
+
+ info->current_function = NULL;
+ info->current_block = NULL;
+
+ return true;
+}
+
+/* Start a block in a function. All local information will be
+ recorded in this block, until the matching call to debug_end_block.
+ debug_start_block and debug_end_block may be nested. The bfd_vma
+ argument is the address at which this block starts. */
+
+boolean
+debug_start_block (handle, addr)
+ PTR handle;
+ bfd_vma addr;
+{
+ struct debug_handle *info = (struct debug_handle *) handle;
+ struct debug_block *b, **pb;
+
+ /* We must always have a current block: debug_record_function sets
+ one up. */
+ if (info->current_unit == NULL
+ || info->current_block == NULL)
+ {
+ debug_error ("debug_start_block: no current block");
+ return false;
+ }
+
+ b = (struct debug_block *) xmalloc (sizeof *b);
+ memset (b, 0, sizeof *b);
+
+ b->parent = info->current_block;
+ b->start = addr;
+ b->end = (bfd_vma) -1;
+
+ /* This new block is a child of the current block. */
+ for (pb = &info->current_block->children;
+ *pb != NULL;
+ pb = &(*pb)->next)
+ ;
+ *pb = b;
+
+ info->current_block = b;
+
+ return true;
+}
+
+/* Finish a block in a function. This matches the call to
+ debug_start_block. The argument is the address at which this block
+ ends. */
+
+boolean
+debug_end_block (handle, addr)
+ PTR handle;
+ bfd_vma addr;
+{
+ struct debug_handle *info = (struct debug_handle *) handle;
+ struct debug_block *parent;
+
+ if (info->current_unit == NULL
+ || info->current_block == NULL)
+ {
+ debug_error ("debug_end_block: no current block");
+ return false;
+ }
+
+ parent = info->current_block->parent;
+ if (parent == NULL)
+ {
+ debug_error ("debug_end_block: attempt to close top level block");
+ return false;
+ }
+
+ info->current_block->end = addr;
+
+ info->current_block = parent;
+
+ return true;
+}
+
+/* Associate a line number in the current source file and function
+ with a given address. */
+
+boolean
+debug_record_line (handle, lineno, addr)
+ PTR handle;
+ unsigned long lineno;
+ bfd_vma addr;
+{
+ struct debug_handle *info = (struct debug_handle *) handle;
+ struct debug_lineno *l;
+ unsigned int i;
+
+ if (info->current_unit == NULL)
+ {
+ debug_error ("debug_record_line: no current unit");
+ return false;
+ }
+
+ l = info->current_lineno;
+ if (l != NULL && l->file == info->current_file)
+ {
+ for (i = 0; i < DEBUG_LINENO_COUNT; i++)
+ {
+ if (l->linenos[i] == (unsigned long) -1)
+ {
+ l->linenos[i] = lineno;
+ l->addrs[i] = addr;
+ return true;
+ }
+ }
+ }
+
+ /* If we get here, then either 1) there is no current_lineno
+ structure, which means this is the first line number in this
+ compilation unit, 2) the current_lineno structure is for a
+ different file, or 3) the current_lineno structure is full.
+ Regardless, we want to allocate a new debug_lineno structure, put
+ it in the right place, and make it the new current_lineno
+ structure. */
+
+ l = (struct debug_lineno *) xmalloc (sizeof *l);
+ memset (l, 0, sizeof *l);
+
+ l->file = info->current_file;
+ l->linenos[0] = lineno;
+ l->addrs[0] = addr;
+ for (i = 1; i < DEBUG_LINENO_COUNT; i++)
+ l->linenos[i] = (unsigned long) -1;
+
+ if (info->current_lineno != NULL)
+ info->current_lineno->next = l;
+ else
+ info->current_unit->linenos = l;
+
+ info->current_lineno = l;
+
+ return true;
+}
+
+/* Start a named common block. This is a block of variables that may
+ move in memory. */
+
+boolean
+debug_start_common_block (handle, name)
+ PTR handle;
+ const char *name;
+{
+ /* FIXME */
+ debug_error ("debug_start_common_block: not implemented");
+ return false;
+}
+
+/* End a named common block. */
+
+boolean
+debug_end_common_block (handle, name)
+ PTR handle;
+ const char *name;
+{
+ /* FIXME */
+ debug_error ("debug_end_common_block: not implemented");
+ return false;
+}
+
+/* Record a named integer constant. */
+
+boolean
+debug_record_int_const (handle, name, val)
+ PTR handle;
+ const char *name;
+ bfd_vma val;
+{
+ struct debug_handle *info = (struct debug_handle *) handle;
+ struct debug_name *n;
+
+ if (name == NULL)
+ return false;
+
+ n = debug_add_to_current_namespace (info, name, DEBUG_OBJECT_INT_CONSTANT,
+ DEBUG_LINKAGE_NONE);
+ if (n == NULL)
+ return false;
+
+ n->u.int_constant = val;
+
+ return true;
+}
+
+/* Record a named floating point constant. */
+
+boolean
+debug_record_float_const (handle, name, val)
+ PTR handle;
+ const char *name;
+ double val;
+{
+ struct debug_handle *info = (struct debug_handle *) handle;
+ struct debug_name *n;
+
+ if (name == NULL)
+ return false;
+
+ n = debug_add_to_current_namespace (info, name, DEBUG_OBJECT_FLOAT_CONSTANT,
+ DEBUG_LINKAGE_NONE);
+ if (n == NULL)
+ return false;
+
+ n->u.float_constant = val;
+
+ return true;
+}
+
+/* Record a typed constant with an integral value. */
+
+boolean
+debug_record_typed_const (handle, name, type, val)
+ PTR handle;
+ const char *name;
+ debug_type type;
+ bfd_vma val;
+{
+ struct debug_handle *info = (struct debug_handle *) handle;
+ struct debug_name *n;
+ struct debug_typed_constant *tc;
+
+ if (name == NULL || type == NULL)
+ return false;
+
+ n = debug_add_to_current_namespace (info, name, DEBUG_OBJECT_TYPED_CONSTANT,
+ DEBUG_LINKAGE_NONE);
+ if (n == NULL)
+ return false;
+
+ tc = (struct debug_typed_constant *) xmalloc (sizeof *tc);
+ memset (tc, 0, sizeof *tc);
+
+ tc->type = type;
+ tc->val = val;
+
+ n->u.typed_constant = tc;
+
+ return true;
+}
+
+/* Record a label. */
+
+boolean
+debug_record_label (handle, name, type, addr)
+ PTR handle;
+ const char *name;
+ debug_type type;
+ bfd_vma addr;
+{
+ /* FIXME. */
+ debug_error ("debug_record_label not implemented");
+ return false;
+}
+
+/* Record a variable. */
+
+boolean
+debug_record_variable (handle, name, type, kind, val)
+ PTR handle;
+ const char *name;
+ debug_type type;
+ enum debug_var_kind kind;
+ bfd_vma val;
+{
+ struct debug_handle *info = (struct debug_handle *) handle;
+ struct debug_namespace **nsp;
+ enum debug_object_linkage linkage;
+ struct debug_name *n;
+ struct debug_variable *v;
+
+ if (name == NULL || type == NULL)
+ return false;
+
+ if (info->current_unit == NULL
+ || info->current_file == NULL)
+ {
+ debug_error ("debug_record_variable: no current file");
+ return false;
+ }
+
+ if (kind == DEBUG_GLOBAL || kind == DEBUG_STATIC)
+ {
+ nsp = &info->current_file->globals;
+ if (kind == DEBUG_GLOBAL)
+ linkage = DEBUG_LINKAGE_GLOBAL;
+ else
+ linkage = DEBUG_LINKAGE_STATIC;
+ }
+ else
+ {
+ if (info->current_block == NULL)
+ {
+ debug_error ("debug_record_variable: no current block");
+ return false;
+ }
+ nsp = &info->current_block->locals;
+ linkage = DEBUG_LINKAGE_AUTOMATIC;
+ }
+
+ n = debug_add_to_namespace (info, nsp, name, DEBUG_OBJECT_VARIABLE, linkage);
+ if (n == NULL)
+ return false;
+
+ v = (struct debug_variable *) xmalloc (sizeof *v);
+ memset (v, 0, sizeof *v);
+
+ v->kind = kind;
+ v->type = type;
+ v->val = val;
+
+ n->u.variable = v;
+
+ return true;
+}
+
+/* Make a type with a given kind and size. */
+
+/*ARGSUSED*/
+static struct debug_type *
+debug_make_type (info, kind, size)
+ struct debug_handle *info;
+ enum debug_type_kind kind;
+ unsigned int size;
+{
+ struct debug_type *t;
+
+ t = (struct debug_type *) xmalloc (sizeof *t);
+ memset (t, 0, sizeof *t);
+
+ t->kind = kind;
+ t->size = size;
+
+ return t;
+}
+
+/* Make an indirect type which may be used as a placeholder for a type
+ which is referenced before it is defined. */
+
+debug_type
+debug_make_indirect_type (handle, slot, tag)
+ PTR handle;
+ debug_type *slot;
+ const char *tag;
+{
+ struct debug_handle *info = (struct debug_handle *) handle;
+ struct debug_type *t;
+ struct debug_indirect_type *i;
+
+ t = debug_make_type (info, DEBUG_KIND_INDIRECT, 0);
+ if (t == NULL)
+ return DEBUG_TYPE_NULL;
+
+ i = (struct debug_indirect_type *) xmalloc (sizeof *i);
+ memset (i, 0, sizeof *i);
+
+ i->slot = slot;
+ i->tag = tag;
+
+ t->u.kindirect = i;
+
+ return t;
+}
+
+/* Make a void type. There is only one of these. */
+
+debug_type
+debug_make_void_type (handle)
+ PTR handle;
+{
+ struct debug_handle *info = (struct debug_handle *) handle;
+
+ return debug_make_type (info, DEBUG_KIND_VOID, 0);
+}
+
+/* Make an integer type of a given size. The boolean argument is true
+ if the integer is unsigned. */
+
+debug_type
+debug_make_int_type (handle, size, unsignedp)
+ PTR handle;
+ unsigned int size;
+ boolean unsignedp;
+{
+ struct debug_handle *info = (struct debug_handle *) handle;
+ struct debug_type *t;
+
+ t = debug_make_type (info, DEBUG_KIND_INT, size);
+ if (t == NULL)
+ return DEBUG_TYPE_NULL;
+
+ t->u.kint = unsignedp;
+
+ return t;
+}
+
+/* Make a floating point type of a given size. FIXME: On some
+ platforms, like an Alpha, you probably need to be able to specify
+ the format. */
+
+debug_type
+debug_make_float_type (handle, size)
+ PTR handle;
+ unsigned int size;
+{
+ struct debug_handle *info = (struct debug_handle *) handle;
+
+ return debug_make_type (info, DEBUG_KIND_FLOAT, size);
+}
+
+/* Make a boolean type of a given size. */
+
+debug_type
+debug_make_bool_type (handle, size)
+ PTR handle;
+ unsigned int size;
+{
+ struct debug_handle *info = (struct debug_handle *) handle;
+
+ return debug_make_type (info, DEBUG_KIND_BOOL, size);
+}
+
+/* Make a complex type of a given size. */
+
+debug_type
+debug_make_complex_type (handle, size)
+ PTR handle;
+ unsigned int size;
+{
+ struct debug_handle *info = (struct debug_handle *) handle;
+
+ return debug_make_type (info, DEBUG_KIND_COMPLEX, size);
+}
+
+/* Make a structure type. The second argument is true for a struct,
+ false for a union. The third argument is the size of the struct.
+ The fourth argument is a NULL terminated array of fields. */
+
+debug_type
+debug_make_struct_type (handle, structp, size, fields)
+ PTR handle;
+ boolean structp;
+ bfd_vma size;
+ debug_field *fields;
+{
+ struct debug_handle *info = (struct debug_handle *) handle;
+ struct debug_type *t;
+ struct debug_class_type *c;
+
+ t = debug_make_type (info,
+ structp ? DEBUG_KIND_STRUCT : DEBUG_KIND_UNION,
+ size);
+ if (t == NULL)
+ return DEBUG_TYPE_NULL;
+
+ c = (struct debug_class_type *) xmalloc (sizeof *c);
+ memset (c, 0, sizeof *c);
+
+ c->fields = fields;
+
+ t->u.kclass = c;
+
+ return t;
+}
+
+/* Make an object type. The first three arguments after the handle
+ are the same as for debug_make_struct_type. The next arguments are
+ a NULL terminated array of base classes, a NULL terminated array of
+ methods, the type of the object holding the virtual function table
+ if it is not this object, and a boolean which is true if this
+ object has its own virtual function table. */
+
+debug_type
+debug_make_object_type (handle, structp, size, fields, baseclasses,
+ methods, vptrbase, ownvptr)
+ PTR handle;
+ boolean structp;
+ bfd_vma size;
+ debug_field *fields;
+ debug_baseclass *baseclasses;
+ debug_method *methods;
+ debug_type vptrbase;
+ boolean ownvptr;
+{
+ struct debug_handle *info = (struct debug_handle *) handle;
+ struct debug_type *t;
+ struct debug_class_type *c;
+
+ t = debug_make_type (info,
+ structp ? DEBUG_KIND_CLASS : DEBUG_KIND_UNION_CLASS,
+ size);
+ if (t == NULL)
+ return DEBUG_TYPE_NULL;
+
+ c = (struct debug_class_type *) xmalloc (sizeof *c);
+ memset (c, 0, sizeof *c);
+
+ c->fields = fields;
+ c->baseclasses = baseclasses;
+ c->methods = methods;
+ if (ownvptr)
+ c->vptrbase = t;
+ else
+ c->vptrbase = vptrbase;
+
+ t->u.kclass = c;
+
+ return t;
+}
+
+/* Make an enumeration type. The arguments are a null terminated
+ array of strings, and an array of corresponding values. */
+
+debug_type
+debug_make_enum_type (handle, names, values)
+ PTR handle;
+ const char **names;
+ bfd_signed_vma *values;
+{
+ struct debug_handle *info = (struct debug_handle *) handle;
+ struct debug_type *t;
+ struct debug_enum_type *e;
+
+ t = debug_make_type (info, DEBUG_KIND_ENUM, 0);
+ if (t == NULL)
+ return DEBUG_TYPE_NULL;
+
+ e = (struct debug_enum_type *) xmalloc (sizeof *e);
+ memset (e, 0, sizeof *e);
+
+ e->names = names;
+ e->values = values;
+
+ t->u.kenum = e;
+
+ return t;
+}
+
+/* Make a pointer to a given type. */
+
+debug_type
+debug_make_pointer_type (handle, type)
+ PTR handle;
+ debug_type type;
+{
+ struct debug_handle *info = (struct debug_handle *) handle;
+ struct debug_type *t;
+
+ if (type == NULL)
+ return DEBUG_TYPE_NULL;
+
+ if (type->pointer != DEBUG_TYPE_NULL)
+ return type->pointer;
+
+ t = debug_make_type (info, DEBUG_KIND_POINTER, 0);
+ if (t == NULL)
+ return DEBUG_TYPE_NULL;
+
+ t->u.kpointer = type;
+
+ type->pointer = t;
+
+ return t;
+}
+
+/* Make a function returning a given type. FIXME: We should be able
+ to record the parameter types. */
+
+debug_type
+debug_make_function_type (handle, type, arg_types, varargs)
+ PTR handle;
+ debug_type type;
+ debug_type *arg_types;
+ boolean varargs;
+{
+ struct debug_handle *info = (struct debug_handle *) handle;
+ struct debug_type *t;
+ struct debug_function_type *f;
+
+ if (type == NULL)
+ return DEBUG_TYPE_NULL;
+
+ t = debug_make_type (info, DEBUG_KIND_FUNCTION, 0);
+ if (t == NULL)
+ return DEBUG_TYPE_NULL;
+
+ f = (struct debug_function_type *) xmalloc (sizeof *f);
+ memset (f, 0, sizeof *f);
+
+ f->return_type = type;
+ f->arg_types = arg_types;
+ f->varargs = varargs;
+
+ t->u.kfunction = f;
+
+ return t;
+}
+
+/* Make a reference to a given type. */
+
+debug_type
+debug_make_reference_type (handle, type)
+ PTR handle;
+ debug_type type;
+{
+ struct debug_handle *info = (struct debug_handle *) handle;
+ struct debug_type *t;
+
+ if (type == NULL)
+ return DEBUG_TYPE_NULL;
+
+ t = debug_make_type (info, DEBUG_KIND_REFERENCE, 0);
+ if (t == NULL)
+ return DEBUG_TYPE_NULL;
+
+ t->u.kreference = type;
+
+ return t;
+}
+
+/* Make a range of a given type from a lower to an upper bound. */
+
+debug_type
+debug_make_range_type (handle, type, lower, upper)
+ PTR handle;
+ debug_type type;
+ bfd_signed_vma lower;
+ bfd_signed_vma upper;
+{
+ struct debug_handle *info = (struct debug_handle *) handle;
+ struct debug_type *t;
+ struct debug_range_type *r;
+
+ if (type == NULL)
+ return DEBUG_TYPE_NULL;
+
+ t = debug_make_type (info, DEBUG_KIND_RANGE, 0);
+ if (t == NULL)
+ return DEBUG_TYPE_NULL;
+
+ r = (struct debug_range_type *) xmalloc (sizeof *r);
+ memset (r, 0, sizeof *r);
+
+ r->type = type;
+ r->lower = lower;
+ r->upper = upper;
+
+ t->u.krange = r;
+
+ return t;
+}
+
+/* Make an array type. The second argument is the type of an element
+ of the array. The third argument is the type of a range of the
+ array. The fourth and fifth argument are the lower and upper
+ bounds, respectively. The sixth argument is true if this array is
+ actually a string, as in C. */
+
+debug_type
+debug_make_array_type (handle, element_type, range_type, lower, upper,
+ stringp)
+ PTR handle;
+ debug_type element_type;
+ debug_type range_type;
+ bfd_signed_vma lower;
+ bfd_signed_vma upper;
+ boolean stringp;
+{
+ struct debug_handle *info = (struct debug_handle *) handle;
+ struct debug_type *t;
+ struct debug_array_type *a;
+
+ if (element_type == NULL || range_type == NULL)
+ return DEBUG_TYPE_NULL;
+
+ t = debug_make_type (info, DEBUG_KIND_ARRAY, 0);
+ if (t == NULL)
+ return DEBUG_TYPE_NULL;
+
+ a = (struct debug_array_type *) xmalloc (sizeof *a);
+ memset (a, 0, sizeof *a);
+
+ a->element_type = element_type;
+ a->range_type = range_type;
+ a->lower = lower;
+ a->upper = upper;
+ a->stringp = stringp;
+
+ t->u.karray = a;
+
+ return t;
+}
+
+/* Make a set of a given type. For example, a Pascal set type. The
+ boolean argument is true if this set is actually a bitstring, as in
+ CHILL. */
+
+debug_type
+debug_make_set_type (handle, type, bitstringp)
+ PTR handle;
+ debug_type type;
+ boolean bitstringp;
+{
+ struct debug_handle *info = (struct debug_handle *) handle;
+ struct debug_type *t;
+ struct debug_set_type *s;
+
+ if (type == NULL)
+ return DEBUG_TYPE_NULL;
+
+ t = debug_make_type (info, DEBUG_KIND_SET, 0);
+ if (t == NULL)
+ return DEBUG_TYPE_NULL;
+
+ s = (struct debug_set_type *) xmalloc (sizeof *s);
+ memset (s, 0, sizeof *s);
+
+ s->type = type;
+ s->bitstringp = bitstringp;
+
+ t->u.kset = s;
+
+ return t;
+}
+
+/* Make a type for a pointer which is relative to an object. The
+ second argument is the type of the object to which the pointer is
+ relative. The third argument is the type that the pointer points
+ to. */
+
+debug_type
+debug_make_offset_type (handle, base_type, target_type)
+ PTR handle;
+ debug_type base_type;
+ debug_type target_type;
+{
+ struct debug_handle *info = (struct debug_handle *) handle;
+ struct debug_type *t;
+ struct debug_offset_type *o;
+
+ if (base_type == NULL || target_type == NULL)
+ return DEBUG_TYPE_NULL;
+
+ t = debug_make_type (info, DEBUG_KIND_OFFSET, 0);
+ if (t == NULL)
+ return DEBUG_TYPE_NULL;
+
+ o = (struct debug_offset_type *) xmalloc (sizeof *o);
+ memset (o, 0, sizeof *o);
+
+ o->base_type = base_type;
+ o->target_type = target_type;
+
+ t->u.koffset = o;
+
+ return t;
+}
+
+/* Make a type for a method function. The second argument is the
+ return type, the third argument is the domain, and the fourth
+ argument is a NULL terminated array of argument types. */
+
+debug_type
+debug_make_method_type (handle, return_type, domain_type, arg_types, varargs)
+ PTR handle;
+ debug_type return_type;
+ debug_type domain_type;
+ debug_type *arg_types;
+ boolean varargs;
+{
+ struct debug_handle *info = (struct debug_handle *) handle;
+ struct debug_type *t;
+ struct debug_method_type *m;
+
+ if (return_type == NULL)
+ return DEBUG_TYPE_NULL;
+
+ t = debug_make_type (info, DEBUG_KIND_METHOD, 0);
+ if (t == NULL)
+ return DEBUG_TYPE_NULL;
+
+ m = (struct debug_method_type *) xmalloc (sizeof *m);
+ memset (m, 0, sizeof *m);
+
+ m->return_type = return_type;
+ m->domain_type = domain_type;
+ m->arg_types = arg_types;
+ m->varargs = varargs;
+
+ t->u.kmethod = m;
+
+ return t;
+}
+
+/* Make a const qualified version of a given type. */
+
+debug_type
+debug_make_const_type (handle, type)
+ PTR handle;
+ debug_type type;
+{
+ struct debug_handle *info = (struct debug_handle *) handle;
+ struct debug_type *t;
+
+ if (type == NULL)
+ return DEBUG_TYPE_NULL;
+
+ t = debug_make_type (info, DEBUG_KIND_CONST, 0);
+ if (t == NULL)
+ return DEBUG_TYPE_NULL;
+
+ t->u.kconst = type;
+
+ return t;
+}
+
+/* Make a volatile qualified version of a given type. */
+
+debug_type
+debug_make_volatile_type (handle, type)
+ PTR handle;
+ debug_type type;
+{
+ struct debug_handle *info = (struct debug_handle *) handle;
+ struct debug_type *t;
+
+ if (type == NULL)
+ return DEBUG_TYPE_NULL;
+
+ t = debug_make_type (info, DEBUG_KIND_VOLATILE, 0);
+ if (t == NULL)
+ return DEBUG_TYPE_NULL;
+
+ t->u.kvolatile = type;
+
+ return t;
+}
+
+/* Make an undefined tagged type. For example, a struct which has
+ been mentioned, but not defined. */
+
+debug_type
+debug_make_undefined_tagged_type (handle, name, kind)
+ PTR handle;
+ const char *name;
+ enum debug_type_kind kind;
+{
+ struct debug_handle *info = (struct debug_handle *) handle;
+ struct debug_type *t;
+
+ if (name == NULL)
+ return DEBUG_TYPE_NULL;
+
+ switch (kind)
+ {
+ case DEBUG_KIND_STRUCT:
+ case DEBUG_KIND_UNION:
+ case DEBUG_KIND_CLASS:
+ case DEBUG_KIND_UNION_CLASS:
+ case DEBUG_KIND_ENUM:
+ break;
+
+ default:
+ debug_error ("debug_make_undefined_type: unsupported kind");
+ return DEBUG_TYPE_NULL;
+ }
+
+ t = debug_make_type (info, kind, 0);
+ if (t == NULL)
+ return DEBUG_TYPE_NULL;
+
+ return debug_tag_type (handle, name, t);
+}
+
+/* Make a base class for an object. The second argument is the base
+ class type. The third argument is the bit position of this base
+ class in the object (always 0 unless doing multiple inheritance).
+ The fourth argument is whether this is a virtual class. The fifth
+ argument is the visibility of the base class. */
+
+/*ARGSUSED*/
+debug_baseclass
+debug_make_baseclass (handle, type, bitpos, virtual, visibility)
+ PTR handle;
+ debug_type type;
+ bfd_vma bitpos;
+ boolean virtual;
+ enum debug_visibility visibility;
+{
+ struct debug_baseclass *b;
+
+ b = (struct debug_baseclass *) xmalloc (sizeof *b);
+ memset (b, 0, sizeof *b);
+
+ b->type = type;
+ b->bitpos = bitpos;
+ b->virtual = virtual;
+ b->visibility = visibility;
+
+ return b;
+}
+
+/* Make a field for a struct. The second argument is the name. The
+ third argument is the type of the field. The fourth argument is
+ the bit position of the field. The fifth argument is the size of
+ the field (it may be zero). The sixth argument is the visibility
+ of the field. */
+
+/*ARGSUSED*/
+debug_field
+debug_make_field (handle, name, type, bitpos, bitsize, visibility)
+ PTR handle;
+ const char *name;
+ debug_type type;
+ bfd_vma bitpos;
+ bfd_vma bitsize;
+ enum debug_visibility visibility;
+{
+ struct debug_field *f;
+
+ f = (struct debug_field *) xmalloc (sizeof *f);
+ memset (f, 0, sizeof *f);
+
+ f->name = name;
+ f->type = type;
+ f->static_member = false;
+ f->u.f.bitpos = bitpos;
+ f->u.f.bitsize = bitsize;
+ f->visibility = visibility;
+
+ return f;
+}
+
+/* Make a static member of an object. The second argument is the
+ name. The third argument is the type of the member. The fourth
+ argument is the physical name of the member (i.e., the name as a
+ global variable). The fifth argument is the visibility of the
+ member. */
+
+/*ARGSUSED*/
+debug_field
+debug_make_static_member (handle, name, type, physname, visibility)
+ PTR handle;
+ const char *name;
+ debug_type type;
+ const char *physname;
+ enum debug_visibility visibility;
+{
+ struct debug_field *f;
+
+ f = (struct debug_field *) xmalloc (sizeof *f);
+ memset (f, 0, sizeof *f);
+
+ f->name = name;
+ f->type = type;
+ f->static_member = true;
+ f->u.s.physname = physname;
+ f->visibility = visibility;
+
+ return f;
+}
+
+/* Make a method. The second argument is the name, and the third
+ argument is a NULL terminated array of method variants. */
+
+/*ARGSUSED*/
+debug_method
+debug_make_method (handle, name, variants)
+ PTR handle;
+ const char *name;
+ debug_method_variant *variants;
+{
+ struct debug_method *m;
+
+ m = (struct debug_method *) xmalloc (sizeof *m);
+ memset (m, 0, sizeof *m);
+
+ m->name = name;
+ m->variants = variants;
+
+ return m;
+}
+
+/* Make a method argument. The second argument is the real name of
+ the function. The third argument is the type of the function. The
+ fourth argument is the visibility. The fifth argument is whether
+ this is a const function. The sixth argument is whether this is a
+ volatile function. The seventh argument is the offset in the
+ virtual function table, if any. The eighth argument is the virtual
+ function context. FIXME: Are the const and volatile arguments
+ necessary? Could we just use debug_make_const_type? */
+
+/*ARGSUSED*/
+debug_method_variant
+debug_make_method_variant (handle, physname, type, visibility, constp,
+ volatilep, voffset, context)
+ PTR handle;
+ const char *physname;
+ debug_type type;
+ enum debug_visibility visibility;
+ boolean constp;
+ boolean volatilep;
+ bfd_vma voffset;
+ debug_type context;
+{
+ struct debug_method_variant *m;
+
+ m = (struct debug_method_variant *) xmalloc (sizeof *m);
+ memset (m, 0, sizeof *m);
+
+ m->physname = physname;
+ m->type = type;
+ m->visibility = visibility;
+ m->constp = constp;
+ m->volatilep = volatilep;
+ m->voffset = voffset;
+ m->context = context;
+
+ return m;
+}
+
+/* Make a static method argument. The arguments are the same as for
+ debug_make_method_variant, except that the last two are omitted
+ since a static method can not also be virtual. */
+
+debug_method_variant
+debug_make_static_method_variant (handle, physname, type, visibility,
+ constp, volatilep)
+ PTR handle;
+ const char *physname;
+ debug_type type;
+ enum debug_visibility visibility;
+ boolean constp;
+ boolean volatilep;
+{
+ struct debug_method_variant *m;
+
+ m = (struct debug_method_variant *) xmalloc (sizeof *m);
+ memset (m, 0, sizeof *m);
+
+ m->physname = physname;
+ m->type = type;
+ m->visibility = visibility;
+ m->constp = constp;
+ m->volatilep = volatilep;
+ m->voffset = VOFFSET_STATIC_METHOD;
+
+ return m;
+}
+
+/* Name a type. */
+
+debug_type
+debug_name_type (handle, name, type)
+ PTR handle;
+ const char *name;
+ debug_type type;
+{
+ struct debug_handle *info = (struct debug_handle *) handle;
+ struct debug_type *t;
+ struct debug_named_type *n;
+ struct debug_name *nm;
+
+ if (name == NULL || type == NULL)
+ return DEBUG_TYPE_NULL;
+
+ if (info->current_unit == NULL
+ || info->current_file == NULL)
+ {
+ debug_error ("debug_name_type: no current file");
+ return DEBUG_TYPE_NULL;
+ /* return false; */
+ }
+
+ t = debug_make_type (info, DEBUG_KIND_NAMED, 0);
+ if (t == NULL)
+ return DEBUG_TYPE_NULL;
+
+ n = (struct debug_named_type *) xmalloc (sizeof *n);
+ memset (n, 0, sizeof *n);
+
+ n->type = type;
+
+ t->u.knamed = n;
+
+ /* We always add the name to the global namespace. This is probably
+ wrong in some cases, but it seems to be right for stabs. FIXME. */
+
+ nm = debug_add_to_namespace (info, &info->current_file->globals, name,
+ DEBUG_OBJECT_TYPE, DEBUG_LINKAGE_NONE);
+ if (nm == NULL)
+ return DEBUG_TYPE_NULL;
+
+ nm->u.type = t;
+
+ n->name = nm;
+
+ return t;
+}
+
+/* Tag a type. */
+
+debug_type
+debug_tag_type (handle, name, type)
+ PTR handle;
+ const char *name;
+ debug_type type;
+{
+ struct debug_handle *info = (struct debug_handle *) handle;
+ struct debug_type *t;
+ struct debug_named_type *n;
+ struct debug_name *nm;
+
+ if (name == NULL || type == NULL)
+ return DEBUG_TYPE_NULL;
+
+ if (info->current_file == NULL)
+ {
+ debug_error ("debug_tag_type: no current file");
+ return DEBUG_TYPE_NULL;
+ }
+
+ if (type->kind == DEBUG_KIND_TAGGED)
+ {
+ if (strcmp (type->u.knamed->name->name, name) == 0)
+ return type;
+ debug_error ("debug_tag_type: extra tag attempted");
+ return DEBUG_TYPE_NULL;
+ }
+
+ t = debug_make_type (info, DEBUG_KIND_TAGGED, 0);
+ if (t == NULL)
+ return DEBUG_TYPE_NULL;
+
+ n = (struct debug_named_type *) xmalloc (sizeof *n);
+ memset (n, 0, sizeof *n);
+
+ n->type = type;
+
+ t->u.knamed = n;
+
+ /* We keep a global namespace of tags for each compilation unit. I
+ don't know if that is the right thing to do. */
+
+ nm = debug_add_to_namespace (info, &info->current_file->globals, name,
+ DEBUG_OBJECT_TAG, DEBUG_LINKAGE_NONE);
+ if (nm == NULL)
+ return DEBUG_TYPE_NULL;
+
+ nm->u.tag = t;
+
+ n->name = nm;
+
+ return t;
+}
+
+/* Record the size of a given type. */
+
+/*ARGSUSED*/
+boolean
+debug_record_type_size (handle, type, size)
+ PTR handle;
+ debug_type type;
+ unsigned int size;
+{
+#if 0
+ if (type->size != 0 && type->size != size)
+ fprintf (stderr, "Warning: changing type size from %d to %d\n",
+ type->size, size);
+#endif
+
+ type->size = size;
+
+ return true;
+}
+
+/* Find a named type. */
+
+debug_type
+debug_find_named_type (handle, name)
+ PTR handle;
+ const char *name;
+{
+ struct debug_handle *info = (struct debug_handle *) handle;
+ struct debug_block *b;
+ struct debug_file *f;
+
+ /* We only search the current compilation unit. I don't know if
+ this is right or not. */
+
+ if (info->current_unit == NULL)
+ {
+ debug_error ("debug_find_named_type: no current compilation unit");
+ return DEBUG_TYPE_NULL;
+ }
+
+ for (b = info->current_block; b != NULL; b = b->parent)
+ {
+ if (b->locals != NULL)
+ {
+ struct debug_name *n;
+
+ for (n = b->locals->list; n != NULL; n = n->next)
+ {
+ if (n->kind == DEBUG_OBJECT_TYPE
+ && n->name[0] == name[0]
+ && strcmp (n->name, name) == 0)
+ return n->u.type;
+ }
+ }
+ }
+
+ for (f = info->current_unit->files; f != NULL; f = f->next)
+ {
+ if (f->globals != NULL)
+ {
+ struct debug_name *n;
+
+ for (n = f->globals->list; n != NULL; n = n->next)
+ {
+ if (n->kind == DEBUG_OBJECT_TYPE
+ && n->name[0] == name[0]
+ && strcmp (n->name, name) == 0)
+ return n->u.type;
+ }
+ }
+ }
+
+ return DEBUG_TYPE_NULL;
+}
+
+/* Find a tagged type. */
+
+debug_type
+debug_find_tagged_type (handle, name, kind)
+ PTR handle;
+ const char *name;
+ enum debug_type_kind kind;
+{
+ struct debug_handle *info = (struct debug_handle *) handle;
+ struct debug_unit *u;
+
+ /* We search the globals of all the compilation units. I don't know
+ if this is correct or not. It would be easy to change. */
+
+ for (u = info->units; u != NULL; u = u->next)
+ {
+ struct debug_file *f;
+
+ for (f = u->files; f != NULL; f = f->next)
+ {
+ struct debug_name *n;
+
+ if (f->globals != NULL)
+ {
+ for (n = f->globals->list; n != NULL; n = n->next)
+ {
+ if (n->kind == DEBUG_OBJECT_TAG
+ && (kind == DEBUG_KIND_ILLEGAL
+ || n->u.tag->kind == kind)
+ && n->name[0] == name[0]
+ && strcmp (n->name, name) == 0)
+ return n->u.tag;
+ }
+ }
+ }
+ }
+
+ return DEBUG_TYPE_NULL;
+}
+
+/* Get a base type. */
+
+static struct debug_type *
+debug_get_real_type (handle, type)
+ PTR handle;
+ debug_type type;
+{
+ switch (type->kind)
+ {
+ default:
+ return type;
+ case DEBUG_KIND_INDIRECT:
+ if (*type->u.kindirect->slot != NULL)
+ return debug_get_real_type (handle, *type->u.kindirect->slot);
+ return type;
+ case DEBUG_KIND_NAMED:
+ case DEBUG_KIND_TAGGED:
+ return debug_get_real_type (handle, type->u.knamed->type);
+ }
+ /*NOTREACHED*/
+}
+
+/* Get the kind of a type. */
+
+enum debug_type_kind
+debug_get_type_kind (handle, type)
+ PTR handle;
+ debug_type type;
+{
+ if (type == NULL)
+ return DEBUG_KIND_ILLEGAL;
+ type = debug_get_real_type (handle, type);
+ return type->kind;
+}
+
+/* Get the name of a type. */
+
+const char *
+debug_get_type_name (handle, type)
+ PTR handle;
+ debug_type type;
+{
+ if (type->kind == DEBUG_KIND_INDIRECT)
+ {
+ if (*type->u.kindirect->slot != NULL)
+ return debug_get_type_name (handle, *type->u.kindirect->slot);
+ return type->u.kindirect->tag;
+ }
+ if (type->kind == DEBUG_KIND_NAMED
+ || type->kind == DEBUG_KIND_TAGGED)
+ return type->u.knamed->name->name;
+ return NULL;
+}
+
+/* Get the size of a type. */
+
+bfd_vma
+debug_get_type_size (handle, type)
+ PTR handle;
+ debug_type type;
+{
+ if (type == NULL)
+ return 0;
+
+ /* We don't call debug_get_real_type, because somebody might have
+ called debug_record_type_size on a named or indirect type. */
+
+ if (type->size != 0)
+ return type->size;
+
+ switch (type->kind)
+ {
+ default:
+ return 0;
+ case DEBUG_KIND_INDIRECT:
+ if (*type->u.kindirect->slot != NULL)
+ return debug_get_type_size (handle, *type->u.kindirect->slot);
+ return 0;
+ case DEBUG_KIND_NAMED:
+ case DEBUG_KIND_TAGGED:
+ return debug_get_type_size (handle, type->u.knamed->type);
+ }
+ /*NOTREACHED*/
+}
+
+/* Get the return type of a function or method type. */
+
+debug_type
+debug_get_return_type (handle, type)
+ PTR handle;
+ debug_type type;
+{
+ if (type == NULL)
+ return DEBUG_TYPE_NULL;
+ type = debug_get_real_type (handle, type);
+ switch (type->kind)
+ {
+ default:
+ return DEBUG_TYPE_NULL;
+ case DEBUG_KIND_FUNCTION:
+ return type->u.kfunction->return_type;
+ case DEBUG_KIND_METHOD:
+ return type->u.kmethod->return_type;
+ }
+ /*NOTREACHED*/
+}
+
+/* Get the parameter types of a function or method type (except that
+ we don't currently store the parameter types of a function). */
+
+const debug_type *
+debug_get_parameter_types (handle, type, pvarargs)
+ PTR handle;
+ debug_type type;
+ boolean *pvarargs;
+{
+ if (type == NULL)
+ return NULL;
+ type = debug_get_real_type (handle, type);
+ switch (type->kind)
+ {
+ default:
+ return NULL;
+ case DEBUG_KIND_FUNCTION:
+ *pvarargs = type->u.kfunction->varargs;
+ return type->u.kfunction->arg_types;
+ case DEBUG_KIND_METHOD:
+ *pvarargs = type->u.kmethod->varargs;
+ return type->u.kmethod->arg_types;
+ }
+ /*NOTREACHED*/
+}
+
+/* Get the target type of a type. */
+
+debug_type
+debug_get_target_type (handle, type)
+ PTR handle;
+ debug_type type;
+{
+ if (type == NULL)
+ return NULL;
+ type = debug_get_real_type (handle, type);
+ switch (type->kind)
+ {
+ default:
+ return NULL;
+ case DEBUG_KIND_POINTER:
+ return type->u.kpointer;
+ case DEBUG_KIND_REFERENCE:
+ return type->u.kreference;
+ case DEBUG_KIND_CONST:
+ return type->u.kconst;
+ case DEBUG_KIND_VOLATILE:
+ return type->u.kvolatile;
+ }
+ /*NOTREACHED*/
+}
+
+/* Get the NULL terminated array of fields for a struct, union, or
+ class. */
+
+const debug_field *
+debug_get_fields (handle, type)
+ PTR handle;
+ debug_type type;
+{
+ if (type == NULL)
+ return NULL;
+ type = debug_get_real_type (handle, type);
+ switch (type->kind)
+ {
+ default:
+ return NULL;
+ case DEBUG_KIND_STRUCT:
+ case DEBUG_KIND_UNION:
+ case DEBUG_KIND_CLASS:
+ case DEBUG_KIND_UNION_CLASS:
+ return type->u.kclass->fields;
+ }
+ /*NOTREACHED*/
+}
+
+/* Get the type of a field. */
+
+/*ARGSUSED*/
+debug_type
+debug_get_field_type (handle, field)
+ PTR handle;
+ debug_field field;
+{
+ if (field == NULL)
+ return NULL;
+ return field->type;
+}
+
+/* Get the name of a field. */
+
+/*ARGSUSED*/
+const char *
+debug_get_field_name (handle, field)
+ PTR handle;
+ debug_field field;
+{
+ if (field == NULL)
+ return NULL;
+ return field->name;
+}
+
+/* Get the bit position of a field. */
+
+/*ARGSUSED*/
+bfd_vma
+debug_get_field_bitpos (handle, field)
+ PTR handle;
+ debug_field field;
+{
+ if (field == NULL || field->static_member)
+ return (bfd_vma) -1;
+ return field->u.f.bitpos;
+}
+
+/* Get the bit size of a field. */
+
+/*ARGSUSED*/
+bfd_vma
+debug_get_field_bitsize (handle, field)
+ PTR handle;
+ debug_field field;
+{
+ if (field == NULL || field->static_member)
+ return (bfd_vma) -1;
+ return field->u.f.bitsize;
+}
+
+/* Get the visibility of a field. */
+
+/*ARGSUSED*/
+enum debug_visibility
+debug_get_field_visibility (handle, field)
+ PTR handle;
+ debug_field field;
+{
+ if (field == NULL)
+ return DEBUG_VISIBILITY_IGNORE;
+ return field->visibility;
+}
+
+/* Get the physical name of a field. */
+
+const char *
+debug_get_field_physname (handle, field)
+ PTR handle;
+ debug_field field;
+{
+ if (field == NULL || ! field->static_member)
+ return NULL;
+ return field->u.s.physname;
+}
+
+/* Write out the debugging information. This is given a handle to
+ debugging information, and a set of function pointers to call. */
+
+boolean
+debug_write (handle, fns, fhandle)
+ PTR handle;
+ const struct debug_write_fns *fns;
+ PTR fhandle;
+{
+ struct debug_handle *info = (struct debug_handle *) handle;
+ struct debug_unit *u;
+
+ /* We use a mark to tell whether we have already written out a
+ particular name. We use an integer, so that we don't have to
+ clear the mark fields if we happen to write out the same
+ information more than once. */
+ ++info->mark;
+
+ /* The base_id field holds an ID value which will never be used, so
+ that we can tell whether we have assigned an ID during this call
+ to debug_write. */
+ info->base_id = info->class_id;
+
+ /* We keep a linked list of classes for which was have assigned ID's
+ during this call to debug_write. */
+ info->id_list = NULL;
+
+ for (u = info->units; u != NULL; u = u->next)
+ {
+ struct debug_file *f;
+ boolean first_file;
+
+ info->current_write_lineno = u->linenos;
+ info->current_write_lineno_index = 0;
+
+ if (! (*fns->start_compilation_unit) (fhandle, u->files->filename))
+ return false;
+
+ first_file = true;
+ for (f = u->files; f != NULL; f = f->next)
+ {
+ struct debug_name *n;
+
+ if (first_file)
+ first_file = false;
+ else
+ {
+ if (! (*fns->start_source) (fhandle, f->filename))
+ return false;
+ }
+
+ if (f->globals != NULL)
+ {
+ for (n = f->globals->list; n != NULL; n = n->next)
+ {
+ if (! debug_write_name (info, fns, fhandle, n))
+ return false;
+ }
+ }
+ }
+
+ /* Output any line number information which hasn't already been
+ handled. */
+ if (! debug_write_linenos (info, fns, fhandle, (bfd_vma) -1))
+ return false;
+ }
+
+ return true;
+}
+
+/* Write out an element in a namespace. */
+
+static boolean
+debug_write_name (info, fns, fhandle, n)
+ struct debug_handle *info;
+ const struct debug_write_fns *fns;
+ PTR fhandle;
+ struct debug_name *n;
+{
+ switch (n->kind)
+ {
+ case DEBUG_OBJECT_TYPE:
+ if (! debug_write_type (info, fns, fhandle, n->u.type, n)
+ || ! (*fns->typdef) (fhandle, n->name))
+ return false;
+ return true;
+ case DEBUG_OBJECT_TAG:
+ if (! debug_write_type (info, fns, fhandle, n->u.tag, n))
+ return false;
+ return (*fns->tag) (fhandle, n->name);
+ case DEBUG_OBJECT_VARIABLE:
+ if (! debug_write_type (info, fns, fhandle, n->u.variable->type,
+ (struct debug_name *) NULL))
+ return false;
+ return (*fns->variable) (fhandle, n->name, n->u.variable->kind,
+ n->u.variable->val);
+ case DEBUG_OBJECT_FUNCTION:
+ return debug_write_function (info, fns, fhandle, n->name,
+ n->linkage, n->u.function);
+ case DEBUG_OBJECT_INT_CONSTANT:
+ return (*fns->int_constant) (fhandle, n->name, n->u.int_constant);
+ case DEBUG_OBJECT_FLOAT_CONSTANT:
+ return (*fns->float_constant) (fhandle, n->name, n->u.float_constant);
+ case DEBUG_OBJECT_TYPED_CONSTANT:
+ if (! debug_write_type (info, fns, fhandle, n->u.typed_constant->type,
+ (struct debug_name *) NULL))
+ return false;
+ return (*fns->typed_constant) (fhandle, n->name,
+ n->u.typed_constant->val);
+ default:
+ abort ();
+ return false;
+ }
+ /*NOTREACHED*/
+}
+
+/* Write out a type. If the type is DEBUG_KIND_NAMED or
+ DEBUG_KIND_TAGGED, then the name argument is the name for which we
+ are about to call typedef or tag. If the type is anything else,
+ then the name argument is a tag from a DEBUG_KIND_TAGGED type which
+ points to this one. */
+
+static boolean
+debug_write_type (info, fns, fhandle, type, name)
+ struct debug_handle *info;
+ const struct debug_write_fns *fns;
+ PTR fhandle;
+ struct debug_type *type;
+ struct debug_name *name;
+{
+ unsigned int i;
+ int is;
+ const char *tag;
+
+ /* If we have a name for this type, just output it. We only output
+ typedef names after they have been defined. We output type tags
+ whenever we are not actually defining them. */
+ if ((type->kind == DEBUG_KIND_NAMED
+ || type->kind == DEBUG_KIND_TAGGED)
+ && (type->u.knamed->name->mark == info->mark
+ || (type->kind == DEBUG_KIND_TAGGED
+ && type->u.knamed->name != name)))
+ {
+ if (type->kind == DEBUG_KIND_NAMED)
+ return (*fns->typedef_type) (fhandle, type->u.knamed->name->name);
+ else
+ {
+ struct debug_type *real;
+ unsigned int id;
+
+ real = debug_get_real_type ((PTR) info, type);
+ id = 0;
+ if ((real->kind == DEBUG_KIND_STRUCT
+ || real->kind == DEBUG_KIND_UNION
+ || real->kind == DEBUG_KIND_CLASS
+ || real->kind == DEBUG_KIND_UNION_CLASS)
+ && real->u.kclass != NULL)
+ {
+ if (real->u.kclass->id <= info->base_id)
+ {
+ if (! debug_set_class_id (info,
+ type->u.knamed->name->name,
+ real))
+ return false;
+ }
+ id = real->u.kclass->id;
+ }
+
+ return (*fns->tag_type) (fhandle, type->u.knamed->name->name, id,
+ real->kind);
+ }
+ }
+
+ /* Mark the name after we have already looked for a known name, so
+ that we don't just define a type in terms of itself. We need to
+ mark the name here so that a struct containing a pointer to
+ itself will work. */
+ if (name != NULL)
+ name->mark = info->mark;
+
+ tag = NULL;
+ if (name != NULL
+ && type->kind != DEBUG_KIND_NAMED
+ && type->kind != DEBUG_KIND_TAGGED)
+ {
+ assert (name->kind == DEBUG_OBJECT_TAG);
+ tag = name->name;
+ }
+
+ switch (type->kind)
+ {
+ case DEBUG_KIND_ILLEGAL:
+ debug_error ("debug_write_type: illegal type encountered");
+ return false;
+ case DEBUG_KIND_INDIRECT:
+ if (*type->u.kindirect->slot == DEBUG_TYPE_NULL)
+ return (*fns->empty_type) (fhandle);
+ return debug_write_type (info, fns, fhandle, *type->u.kindirect->slot,
+ name);
+ case DEBUG_KIND_VOID:
+ return (*fns->void_type) (fhandle);
+ case DEBUG_KIND_INT:
+ return (*fns->int_type) (fhandle, type->size, type->u.kint);
+ case DEBUG_KIND_FLOAT:
+ return (*fns->float_type) (fhandle, type->size);
+ case DEBUG_KIND_COMPLEX:
+ return (*fns->complex_type) (fhandle, type->size);
+ case DEBUG_KIND_BOOL:
+ return (*fns->bool_type) (fhandle, type->size);
+ case DEBUG_KIND_STRUCT:
+ case DEBUG_KIND_UNION:
+ if (type->u.kclass != NULL)
+ {
+ if (type->u.kclass->id <= info->base_id)
+ {
+ if (! debug_set_class_id (info, tag, type))
+ return false;
+ }
+
+ if (info->mark == type->u.kclass->mark)
+ {
+ /* We are currently outputting this struct, or we have
+ already output it. I don't know if this can happen,
+ but it can happen for a class. */
+ assert (type->u.kclass->id > info->base_id);
+ return (*fns->tag_type) (fhandle, tag, type->u.kclass->id,
+ type->kind);
+ }
+ type->u.kclass->mark = info->mark;
+ }
+
+ if (! (*fns->start_struct_type) (fhandle, tag,
+ (type->u.kclass != NULL
+ ? type->u.kclass->id
+ : 0),
+ type->kind == DEBUG_KIND_STRUCT,
+ type->size))
+ return false;
+ if (type->u.kclass != NULL
+ && type->u.kclass->fields != NULL)
+ {
+ for (i = 0; type->u.kclass->fields[i] != NULL; i++)
+ {
+ struct debug_field *f;
+
+ f = type->u.kclass->fields[i];
+ if (! debug_write_type (info, fns, fhandle, f->type,
+ (struct debug_name *) NULL)
+ || ! (*fns->struct_field) (fhandle, f->name, f->u.f.bitpos,
+ f->u.f.bitsize, f->visibility))
+ return false;
+ }
+ }
+ return (*fns->end_struct_type) (fhandle);
+ case DEBUG_KIND_CLASS:
+ case DEBUG_KIND_UNION_CLASS:
+ return debug_write_class_type (info, fns, fhandle, type, tag);
+ case DEBUG_KIND_ENUM:
+ if (type->u.kenum == NULL)
+ return (*fns->enum_type) (fhandle, tag, (const char **) NULL,
+ (bfd_signed_vma *) NULL);
+ return (*fns->enum_type) (fhandle, tag, type->u.kenum->names,
+ type->u.kenum->values);
+ case DEBUG_KIND_POINTER:
+ if (! debug_write_type (info, fns, fhandle, type->u.kpointer,
+ (struct debug_name *) NULL))
+ return false;
+ return (*fns->pointer_type) (fhandle);
+ case DEBUG_KIND_FUNCTION:
+ if (! debug_write_type (info, fns, fhandle,
+ type->u.kfunction->return_type,
+ (struct debug_name *) NULL))
+ return false;
+ if (type->u.kfunction->arg_types == NULL)
+ is = -1;
+ else
+ {
+ for (is = 0; type->u.kfunction->arg_types[is] != NULL; is++)
+ if (! debug_write_type (info, fns, fhandle,
+ type->u.kfunction->arg_types[is],
+ (struct debug_name *) NULL))
+ return false;
+ }
+ return (*fns->function_type) (fhandle, is,
+ type->u.kfunction->varargs);
+ case DEBUG_KIND_REFERENCE:
+ if (! debug_write_type (info, fns, fhandle, type->u.kreference,
+ (struct debug_name *) NULL))
+ return false;
+ return (*fns->reference_type) (fhandle);
+ case DEBUG_KIND_RANGE:
+ if (! debug_write_type (info, fns, fhandle, type->u.krange->type,
+ (struct debug_name *) NULL))
+ return false;
+ return (*fns->range_type) (fhandle, type->u.krange->lower,
+ type->u.krange->upper);
+ case DEBUG_KIND_ARRAY:
+ if (! debug_write_type (info, fns, fhandle, type->u.karray->element_type,
+ (struct debug_name *) NULL)
+ || ! debug_write_type (info, fns, fhandle,
+ type->u.karray->range_type,
+ (struct debug_name *) NULL))
+ return false;
+ return (*fns->array_type) (fhandle, type->u.karray->lower,
+ type->u.karray->upper,
+ type->u.karray->stringp);
+ case DEBUG_KIND_SET:
+ if (! debug_write_type (info, fns, fhandle, type->u.kset->type,
+ (struct debug_name *) NULL))
+ return false;
+ return (*fns->set_type) (fhandle, type->u.kset->bitstringp);
+ case DEBUG_KIND_OFFSET:
+ if (! debug_write_type (info, fns, fhandle, type->u.koffset->base_type,
+ (struct debug_name *) NULL)
+ || ! debug_write_type (info, fns, fhandle,
+ type->u.koffset->target_type,
+ (struct debug_name *) NULL))
+ return false;
+ return (*fns->offset_type) (fhandle);
+ case DEBUG_KIND_METHOD:
+ if (! debug_write_type (info, fns, fhandle,
+ type->u.kmethod->return_type,
+ (struct debug_name *) NULL))
+ return false;
+ if (type->u.kmethod->arg_types == NULL)
+ is = -1;
+ else
+ {
+ for (is = 0; type->u.kmethod->arg_types[is] != NULL; is++)
+ if (! debug_write_type (info, fns, fhandle,
+ type->u.kmethod->arg_types[is],
+ (struct debug_name *) NULL))
+ return false;
+ }
+ if (type->u.kmethod->domain_type != NULL)
+ {
+ if (! debug_write_type (info, fns, fhandle,
+ type->u.kmethod->domain_type,
+ (struct debug_name *) NULL))
+ return false;
+ }
+ return (*fns->method_type) (fhandle,
+ type->u.kmethod->domain_type != NULL,
+ is,
+ type->u.kmethod->varargs);
+ case DEBUG_KIND_CONST:
+ if (! debug_write_type (info, fns, fhandle, type->u.kconst,
+ (struct debug_name *) NULL))
+ return false;
+ return (*fns->const_type) (fhandle);
+ case DEBUG_KIND_VOLATILE:
+ if (! debug_write_type (info, fns, fhandle, type->u.kvolatile,
+ (struct debug_name *) NULL))
+ return false;
+ return (*fns->volatile_type) (fhandle);
+ case DEBUG_KIND_NAMED:
+ return debug_write_type (info, fns, fhandle, type->u.knamed->type,
+ (struct debug_name *) NULL);
+ case DEBUG_KIND_TAGGED:
+ return debug_write_type (info, fns, fhandle, type->u.knamed->type,
+ type->u.knamed->name);
+ default:
+ abort ();
+ return false;
+ }
+}
+
+/* Write out a class type. */
+
+static boolean
+debug_write_class_type (info, fns, fhandle, type, tag)
+ struct debug_handle *info;
+ const struct debug_write_fns *fns;
+ PTR fhandle;
+ struct debug_type *type;
+ const char *tag;
+{
+ unsigned int i;
+ unsigned int id;
+ struct debug_type *vptrbase;
+
+ if (type->u.kclass == NULL)
+ {
+ id = 0;
+ vptrbase = NULL;
+ }
+ else
+ {
+ if (type->u.kclass->id <= info->base_id)
+ {
+ if (! debug_set_class_id (info, tag, type))
+ return false;
+ }
+
+ if (info->mark == type->u.kclass->mark)
+ {
+ /* We are currently outputting this class, or we have
+ already output it. This can happen when there are
+ methods for an anonymous class. */
+ assert (type->u.kclass->id > info->base_id);
+ return (*fns->tag_type) (fhandle, tag, type->u.kclass->id,
+ type->kind);
+ }
+ type->u.kclass->mark = info->mark;
+ id = type->u.kclass->id;
+
+ vptrbase = type->u.kclass->vptrbase;
+ if (vptrbase != NULL && vptrbase != type)
+ {
+ if (! debug_write_type (info, fns, fhandle, vptrbase,
+ (struct debug_name *) NULL))
+ return false;
+ }
+ }
+
+ if (! (*fns->start_class_type) (fhandle, tag, id,
+ type->kind == DEBUG_KIND_CLASS,
+ type->size,
+ vptrbase != NULL,
+ vptrbase == type))
+ return false;
+
+ if (type->u.kclass != NULL)
+ {
+ if (type->u.kclass->fields != NULL)
+ {
+ for (i = 0; type->u.kclass->fields[i] != NULL; i++)
+ {
+ struct debug_field *f;
+
+ f = type->u.kclass->fields[i];
+ if (! debug_write_type (info, fns, fhandle, f->type,
+ (struct debug_name *) NULL))
+ return false;
+ if (f->static_member)
+ {
+ if (! (*fns->class_static_member) (fhandle, f->name,
+ f->u.s.physname,
+ f->visibility))
+ return false;
+ }
+ else
+ {
+ if (! (*fns->struct_field) (fhandle, f->name, f->u.f.bitpos,
+ f->u.f.bitsize, f->visibility))
+ return false;
+ }
+ }
+ }
+
+ if (type->u.kclass->baseclasses != NULL)
+ {
+ for (i = 0; type->u.kclass->baseclasses[i] != NULL; i++)
+ {
+ struct debug_baseclass *b;
+
+ b = type->u.kclass->baseclasses[i];
+ if (! debug_write_type (info, fns, fhandle, b->type,
+ (struct debug_name *) NULL))
+ return false;
+ if (! (*fns->class_baseclass) (fhandle, b->bitpos, b->virtual,
+ b->visibility))
+ return false;
+ }
+ }
+
+ if (type->u.kclass->methods != NULL)
+ {
+ for (i = 0; type->u.kclass->methods[i] != NULL; i++)
+ {
+ struct debug_method *m;
+ unsigned int j;
+
+ m = type->u.kclass->methods[i];
+ if (! (*fns->class_start_method) (fhandle, m->name))
+ return false;
+ for (j = 0; m->variants[j] != NULL; j++)
+ {
+ struct debug_method_variant *v;
+
+ v = m->variants[j];
+ if (v->context != NULL)
+ {
+ if (! debug_write_type (info, fns, fhandle, v->context,
+ (struct debug_name *) NULL))
+ return false;
+ }
+ if (! debug_write_type (info, fns, fhandle, v->type,
+ (struct debug_name *) NULL))
+ return false;
+ if (v->voffset != VOFFSET_STATIC_METHOD)
+ {
+ if (! (*fns->class_method_variant) (fhandle, v->physname,
+ v->visibility,
+ v->constp,
+ v->volatilep,
+ v->voffset,
+ v->context != NULL))
+ return false;
+ }
+ else
+ {
+ if (! (*fns->class_static_method_variant) (fhandle,
+ v->physname,
+ v->visibility,
+ v->constp,
+ v->volatilep))
+ return false;
+ }
+ }
+ if (! (*fns->class_end_method) (fhandle))
+ return false;
+ }
+ }
+ }
+
+ return (*fns->end_class_type) (fhandle);
+}
+
+/* Write out information for a function. */
+
+static boolean
+debug_write_function (info, fns, fhandle, name, linkage, function)
+ struct debug_handle *info;
+ const struct debug_write_fns *fns;
+ PTR fhandle;
+ const char *name;
+ enum debug_object_linkage linkage;
+ struct debug_function *function;
+{
+ struct debug_parameter *p;
+ struct debug_block *b;
+
+ if (! debug_write_linenos (info, fns, fhandle, function->blocks->start))
+ return false;
+
+ if (! debug_write_type (info, fns, fhandle, function->return_type,
+ (struct debug_name *) NULL))
+ return false;
+
+ if (! (*fns->start_function) (fhandle, name,
+ linkage == DEBUG_LINKAGE_GLOBAL))
+ return false;
+
+ for (p = function->parameters; p != NULL; p = p->next)
+ {
+ if (! debug_write_type (info, fns, fhandle, p->type,
+ (struct debug_name *) NULL)
+ || ! (*fns->function_parameter) (fhandle, p->name, p->kind, p->val))
+ return false;
+ }
+
+ for (b = function->blocks; b != NULL; b = b->next)
+ {
+ if (! debug_write_block (info, fns, fhandle, b))
+ return false;
+ }
+
+ return (*fns->end_function) (fhandle);
+}
+
+/* Write out information for a block. */
+
+static boolean
+debug_write_block (info, fns, fhandle, block)
+ struct debug_handle *info;
+ const struct debug_write_fns *fns;
+ PTR fhandle;
+ struct debug_block *block;
+{
+ struct debug_name *n;
+ struct debug_block *b;
+
+ if (! debug_write_linenos (info, fns, fhandle, block->start))
+ return false;
+
+ /* I can't see any point to writing out a block with no local
+ variables, so we don't bother, except for the top level block. */
+ if (block->locals != NULL || block->parent == NULL)
+ {
+ if (! (*fns->start_block) (fhandle, block->start))
+ return false;
+ }
+
+ if (block->locals != NULL)
+ {
+ for (n = block->locals->list; n != NULL; n = n->next)
+ {
+ if (! debug_write_name (info, fns, fhandle, n))
+ return false;
+ }
+ }
+
+ for (b = block->children; b != NULL; b = b->next)
+ {
+ if (! debug_write_block (info, fns, fhandle, b))
+ return false;
+ }
+
+ if (! debug_write_linenos (info, fns, fhandle, block->end))
+ return false;
+
+ if (block->locals != NULL || block->parent == NULL)
+ {
+ if (! (*fns->end_block) (fhandle, block->end))
+ return false;
+ }
+
+ return true;
+}
+
+/* Write out line number information up to ADDRESS. */
+
+static boolean
+debug_write_linenos (info, fns, fhandle, address)
+ struct debug_handle *info;
+ const struct debug_write_fns *fns;
+ PTR fhandle;
+ bfd_vma address;
+{
+ while (info->current_write_lineno != NULL)
+ {
+ struct debug_lineno *l;
+
+ l = info->current_write_lineno;
+
+ while (info->current_write_lineno_index < DEBUG_LINENO_COUNT)
+ {
+ if (l->linenos[info->current_write_lineno_index]
+ == (unsigned long) -1)
+ break;
+
+ if (l->addrs[info->current_write_lineno_index] >= address)
+ return true;
+
+ if (! (*fns->lineno) (fhandle, l->file->filename,
+ l->linenos[info->current_write_lineno_index],
+ l->addrs[info->current_write_lineno_index]))
+ return false;
+
+ ++info->current_write_lineno_index;
+ }
+
+ info->current_write_lineno = l->next;
+ info->current_write_lineno_index = 0;
+ }
+
+ return true;
+}
+
+/* Get the ID number for a class. If during the same call to
+ debug_write we find a struct with the same definition with the same
+ name, we use the same ID. This type of things happens because the
+ same struct will be defined by multiple compilation units. */
+
+static boolean
+debug_set_class_id (info, tag, type)
+ struct debug_handle *info;
+ const char *tag;
+ struct debug_type *type;
+{
+ struct debug_class_type *c;
+ struct debug_class_id *l;
+
+ assert (type->kind == DEBUG_KIND_STRUCT
+ || type->kind == DEBUG_KIND_UNION
+ || type->kind == DEBUG_KIND_CLASS
+ || type->kind == DEBUG_KIND_UNION_CLASS);
+
+ c = type->u.kclass;
+
+ if (c->id > info->base_id)
+ return true;
+
+ for (l = info->id_list; l != NULL; l = l->next)
+ {
+ if (l->type->kind != type->kind)
+ continue;
+
+ if (tag == NULL)
+ {
+ if (l->tag != NULL)
+ continue;
+ }
+ else
+ {
+ if (l->tag == NULL
+ || l->tag[0] != tag[0]
+ || strcmp (l->tag, tag) != 0)
+ continue;
+ }
+
+ if (debug_type_samep (info, l->type, type))
+ {
+ c->id = l->type->u.kclass->id;
+ return true;
+ }
+ }
+
+ /* There are no identical types. Use a new ID, and add it to the
+ list. */
+ ++info->class_id;
+ c->id = info->class_id;
+
+ l = (struct debug_class_id *) xmalloc (sizeof *l);
+ memset (l, 0, sizeof *l);
+
+ l->type = type;
+ l->tag = tag;
+
+ l->next = info->id_list;
+ info->id_list = l;
+
+ return true;
+}
+
+/* See if two types are the same. At this point, we don't care about
+ tags and the like. */
+
+static boolean
+debug_type_samep (info, t1, t2)
+ struct debug_handle *info;
+ struct debug_type *t1;
+ struct debug_type *t2;
+{
+ struct debug_type_compare_list *l;
+ struct debug_type_compare_list top;
+ boolean ret;
+
+ if (t1 == NULL)
+ return t2 == NULL;
+ if (t2 == NULL)
+ return false;
+
+ while (t1->kind == DEBUG_KIND_INDIRECT)
+ {
+ t1 = *t1->u.kindirect->slot;
+ if (t1 == NULL)
+ return false;
+ }
+ while (t2->kind == DEBUG_KIND_INDIRECT)
+ {
+ t2 = *t2->u.kindirect->slot;
+ if (t2 == NULL)
+ return false;
+ }
+
+ if (t1 == t2)
+ return true;
+
+ /* As a special case, permit a typedef to match a tag, since C++
+ debugging output will sometimes add a typedef where C debugging
+ output will not. */
+ if (t1->kind == DEBUG_KIND_NAMED
+ && t2->kind == DEBUG_KIND_TAGGED)
+ return debug_type_samep (info, t1->u.knamed->type, t2);
+ else if (t1->kind == DEBUG_KIND_TAGGED
+ && t2->kind == DEBUG_KIND_NAMED)
+ return debug_type_samep (info, t1, t2->u.knamed->type);
+
+ if (t1->kind != t2->kind
+ || t1->size != t2->size)
+ return false;
+
+ /* Get rid of the trivial cases first. */
+ switch (t1->kind)
+ {
+ default:
+ break;
+ case DEBUG_KIND_VOID:
+ case DEBUG_KIND_FLOAT:
+ case DEBUG_KIND_COMPLEX:
+ case DEBUG_KIND_BOOL:
+ return true;
+ case DEBUG_KIND_INT:
+ return t1->u.kint == t2->u.kint;
+ }
+
+ /* We have to avoid an infinite recursion. We do this by keeping a
+ list of types which we are comparing. We just keep the list on
+ the stack. If we encounter a pair of types we are currently
+ comparing, we just assume that they are equal. */
+ for (l = info->compare_list; l != NULL; l = l->next)
+ {
+ if (l->t1 == t1 && l->t2 == t2)
+ return true;
+ }
+
+ top.t1 = t1;
+ top.t2 = t2;
+ top.next = info->compare_list;
+ info->compare_list = &top;
+
+ switch (t1->kind)
+ {
+ default:
+ abort ();
+ ret = false;
+ break;
+
+ case DEBUG_KIND_STRUCT:
+ case DEBUG_KIND_UNION:
+ case DEBUG_KIND_CLASS:
+ case DEBUG_KIND_UNION_CLASS:
+ if (t1->u.kclass == NULL)
+ ret = t2->u.kclass == NULL;
+ else if (t2->u.kclass == NULL)
+ ret = false;
+ else if (t1->u.kclass->id > info->base_id
+ && t1->u.kclass->id == t2->u.kclass->id)
+ ret = true;
+ else
+ ret = debug_class_type_samep (info, t1, t2);
+ break;
+
+ case DEBUG_KIND_ENUM:
+ if (t1->u.kenum == NULL)
+ ret = t2->u.kenum == NULL;
+ else if (t2->u.kenum == NULL)
+ ret = false;
+ else
+ {
+ const char **pn1, **pn2;
+ bfd_signed_vma *pv1, *pv2;
+
+ pn1 = t1->u.kenum->names;
+ pn2 = t2->u.kenum->names;
+ pv1 = t1->u.kenum->values;
+ pv2 = t2->u.kenum->values;
+ while (*pn1 != NULL && *pn2 != NULL)
+ {
+ if (**pn1 != **pn2
+ || *pv1 != *pv2
+ || strcmp (*pn1, *pn2) != 0)
+ break;
+ ++pn1;
+ ++pn2;
+ ++pv1;
+ ++pv2;
+ }
+ ret = *pn1 == NULL && *pn2 == NULL;
+ }
+ break;
+
+ case DEBUG_KIND_POINTER:
+ ret = debug_type_samep (info, t1->u.kpointer, t2->u.kpointer);
+ break;
+
+ case DEBUG_KIND_FUNCTION:
+ if (t1->u.kfunction->varargs != t2->u.kfunction->varargs
+ || ! debug_type_samep (info, t1->u.kfunction->return_type,
+ t2->u.kfunction->return_type)
+ || ((t1->u.kfunction->arg_types == NULL)
+ != (t2->u.kfunction->arg_types == NULL)))
+ ret = false;
+ else if (t1->u.kfunction->arg_types == NULL)
+ ret = true;
+ else
+ {
+ struct debug_type **a1, **a2;
+
+ a1 = t1->u.kfunction->arg_types;
+ a2 = t2->u.kfunction->arg_types;
+ while (*a1 != NULL && *a2 != NULL)
+ if (! debug_type_samep (info, *a1, *a2))
+ break;
+ ret = *a1 == NULL && *a2 == NULL;
+ }
+ break;
+
+ case DEBUG_KIND_REFERENCE:
+ ret = debug_type_samep (info, t1->u.kreference, t2->u.kreference);
+ break;
+
+ case DEBUG_KIND_RANGE:
+ ret = (t1->u.krange->lower == t2->u.krange->lower
+ && t1->u.krange->upper == t2->u.krange->upper
+ && debug_type_samep (info, t1->u.krange->type,
+ t2->u.krange->type));
+
+ case DEBUG_KIND_ARRAY:
+ ret = (t1->u.karray->lower == t2->u.karray->lower
+ && t1->u.karray->upper == t2->u.karray->upper
+ && t1->u.karray->stringp == t2->u.karray->stringp
+ && debug_type_samep (info, t1->u.karray->element_type,
+ t2->u.karray->element_type));
+ break;
+
+ case DEBUG_KIND_SET:
+ ret = (t1->u.kset->bitstringp == t2->u.kset->bitstringp
+ && debug_type_samep (info, t1->u.kset->type, t2->u.kset->type));
+ break;
+
+ case DEBUG_KIND_OFFSET:
+ ret = (debug_type_samep (info, t1->u.koffset->base_type,
+ t2->u.koffset->base_type)
+ && debug_type_samep (info, t1->u.koffset->target_type,
+ t2->u.koffset->target_type));
+ break;
+
+ case DEBUG_KIND_METHOD:
+ if (t1->u.kmethod->varargs != t2->u.kmethod->varargs
+ || ! debug_type_samep (info, t1->u.kmethod->return_type,
+ t2->u.kmethod->return_type)
+ || ! debug_type_samep (info, t1->u.kmethod->domain_type,
+ t2->u.kmethod->domain_type)
+ || ((t1->u.kmethod->arg_types == NULL)
+ != (t2->u.kmethod->arg_types == NULL)))
+ ret = false;
+ else if (t1->u.kmethod->arg_types == NULL)
+ ret = true;
+ else
+ {
+ struct debug_type **a1, **a2;
+
+ a1 = t1->u.kmethod->arg_types;
+ a2 = t2->u.kmethod->arg_types;
+ while (*a1 != NULL && *a2 != NULL)
+ if (! debug_type_samep (info, *a1, *a2))
+ break;
+ ret = *a1 == NULL && *a2 == NULL;
+ }
+ break;
+
+ case DEBUG_KIND_CONST:
+ ret = debug_type_samep (info, t1->u.kconst, t2->u.kconst);
+ break;
+
+ case DEBUG_KIND_VOLATILE:
+ ret = debug_type_samep (info, t1->u.kvolatile, t2->u.kvolatile);
+ break;
+
+ case DEBUG_KIND_NAMED:
+ case DEBUG_KIND_TAGGED:
+ ret = (strcmp (t1->u.knamed->name->name, t2->u.knamed->name->name) == 0
+ && debug_type_samep (info, t1->u.knamed->type,
+ t2->u.knamed->type));
+ break;
+ }
+
+ info->compare_list = top.next;
+
+ return ret;
+}
+
+/* See if two classes are the same. This is a subroutine of
+ debug_type_samep. */
+
+static boolean
+debug_class_type_samep (info, t1, t2)
+ struct debug_handle *info;
+ struct debug_type *t1;
+ struct debug_type *t2;
+{
+ struct debug_class_type *c1, *c2;
+
+ c1 = t1->u.kclass;
+ c2 = t2->u.kclass;
+
+ if ((c1->fields == NULL) != (c2->fields == NULL)
+ || (c1->baseclasses == NULL) != (c2->baseclasses == NULL)
+ || (c1->methods == NULL) != (c2->methods == NULL)
+ || (c1->vptrbase == NULL) != (c2->vptrbase == NULL))
+ return false;
+
+ if (c1->fields != NULL)
+ {
+ struct debug_field **pf1, **pf2;
+
+ for (pf1 = c1->fields, pf2 = c2->fields;
+ *pf1 != NULL && *pf2 != NULL;
+ pf1++, pf2++)
+ {
+ struct debug_field *f1, *f2;
+
+ f1 = *pf1;
+ f2 = *pf2;
+ if (f1->name[0] != f2->name[0]
+ || f1->visibility != f2->visibility
+ || f1->static_member != f2->static_member)
+ return false;
+ if (f1->static_member)
+ {
+ if (strcmp (f1->u.s.physname, f2->u.s.physname) != 0)
+ return false;
+ }
+ else
+ {
+ if (f1->u.f.bitpos != f2->u.f.bitpos
+ || f1->u.f.bitsize != f2->u.f.bitsize)
+ return false;
+ }
+ /* We do the checks which require function calls last. We
+ don't require that the types of fields have the same
+ names, since that sometimes fails in the presence of
+ typedefs and we really don't care. */
+ if (strcmp (f1->name, f2->name) != 0
+ || ! debug_type_samep (info,
+ debug_get_real_type ((PTR) info,
+ f1->type),
+ debug_get_real_type ((PTR) info,
+ f2->type)))
+ return false;
+ }
+ if (*pf1 != NULL || *pf2 != NULL)
+ return false;
+ }
+
+ if (c1->vptrbase != NULL)
+ {
+ if (! debug_type_samep (info, c1->vptrbase, c2->vptrbase))
+ return false;
+ }
+
+ if (c1->baseclasses != NULL)
+ {
+ struct debug_baseclass **pb1, **pb2;
+
+ for (pb1 = c1->baseclasses, pb2 = c2->baseclasses;
+ *pb1 != NULL && *pb2 != NULL;
+ ++pb1, ++pb2)
+ {
+ struct debug_baseclass *b1, *b2;
+
+ b1 = *pb1;
+ b2 = *pb2;
+ if (b1->bitpos != b2->bitpos
+ || b1->virtual != b2->virtual
+ || b1->visibility != b2->visibility
+ || ! debug_type_samep (info, b1->type, b2->type))
+ return false;
+ }
+ if (*pb1 != NULL || *pb2 != NULL)
+ return false;
+ }
+
+ if (c1->methods != NULL)
+ {
+ struct debug_method **pm1, **pm2;
+
+ for (pm1 = c1->methods, pm2 = c2->methods;
+ *pm1 != NULL && *pm2 != NULL;
+ ++pm1, ++pm2)
+ {
+ struct debug_method *m1, *m2;
+
+ m1 = *pm1;
+ m2 = *pm2;
+ if (m1->name[0] != m2->name[0]
+ || strcmp (m1->name, m2->name) != 0
+ || (m1->variants == NULL) != (m2->variants == NULL))
+ return false;
+ if (m1->variants == NULL)
+ {
+ struct debug_method_variant **pv1, **pv2;
+
+ for (pv1 = m1->variants, pv2 = m2->variants;
+ *pv1 != NULL && *pv2 != NULL;
+ ++pv1, ++pv2)
+ {
+ struct debug_method_variant *v1, *v2;
+
+ v1 = *pv1;
+ v2 = *pv2;
+ if (v1->physname[0] != v2->physname[0]
+ || v1->visibility != v2->visibility
+ || v1->constp != v2->constp
+ || v1->volatilep != v2->volatilep
+ || v1->voffset != v2->voffset
+ || (v1->context == NULL) != (v2->context == NULL)
+ || strcmp (v1->physname, v2->physname) != 0
+ || ! debug_type_samep (info, v1->type, v2->type))
+ return false;
+ if (v1->context != NULL)
+ {
+ if (! debug_type_samep (info, v1->context,
+ v2->context))
+ return false;
+ }
+ }
+ if (*pv1 != NULL || *pv2 != NULL)
+ return false;
+ }
+ }
+ if (*pm1 != NULL || *pm2 != NULL)
+ return false;
+ }
+
+ return true;
+}
diff --git a/pstack/debug.h b/pstack/debug.h
new file mode 100644
index 00000000000..a4d3d8306cd
--- /dev/null
+++ b/pstack/debug.h
@@ -0,0 +1,798 @@
+/* debug.h -- Describe generic debugging information.
+ Copyright (C) 1995, 1996 Free Software Foundation, Inc.
+ Written by Ian Lance Taylor <ian@cygnus.com>.
+
+ This file is part of GNU Binutils.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+#ifndef DEBUG_H
+#define DEBUG_H
+
+/* This header file describes a generic debugging information format.
+ We may eventually have readers which convert different formats into
+ this generic format, and writers which write it out. The initial
+ impetus for this was writing a convertor from stabs to HP IEEE-695
+ debugging format. */
+
+/* Different kinds of types. */
+
+enum debug_type_kind
+{
+ /* Not used. */
+ DEBUG_KIND_ILLEGAL,
+ /* Indirect via a pointer. */
+ DEBUG_KIND_INDIRECT,
+ /* Void. */
+ DEBUG_KIND_VOID,
+ /* Integer. */
+ DEBUG_KIND_INT,
+ /* Floating point. */
+ DEBUG_KIND_FLOAT,
+ /* Complex. */
+ DEBUG_KIND_COMPLEX,
+ /* Boolean. */
+ DEBUG_KIND_BOOL,
+ /* Struct. */
+ DEBUG_KIND_STRUCT,
+ /* Union. */
+ DEBUG_KIND_UNION,
+ /* Class. */
+ DEBUG_KIND_CLASS,
+ /* Union class (can this really happen?). */
+ DEBUG_KIND_UNION_CLASS,
+ /* Enumeration type. */
+ DEBUG_KIND_ENUM,
+ /* Pointer. */
+ DEBUG_KIND_POINTER,
+ /* Function. */
+ DEBUG_KIND_FUNCTION,
+ /* Reference. */
+ DEBUG_KIND_REFERENCE,
+ /* Range. */
+ DEBUG_KIND_RANGE,
+ /* Array. */
+ DEBUG_KIND_ARRAY,
+ /* Set. */
+ DEBUG_KIND_SET,
+ /* Based pointer. */
+ DEBUG_KIND_OFFSET,
+ /* Method. */
+ DEBUG_KIND_METHOD,
+ /* Const qualified type. */
+ DEBUG_KIND_CONST,
+ /* Volatile qualified type. */
+ DEBUG_KIND_VOLATILE,
+ /* Named type. */
+ DEBUG_KIND_NAMED,
+ /* Tagged type. */
+ DEBUG_KIND_TAGGED
+};
+
+/* Different kinds of variables. */
+
+enum debug_var_kind
+{
+ /* Not used. */
+ DEBUG_VAR_ILLEGAL,
+ /* A global variable. */
+ DEBUG_GLOBAL,
+ /* A static variable. */
+ DEBUG_STATIC,
+ /* A local static variable. */
+ DEBUG_LOCAL_STATIC,
+ /* A local variable. */
+ DEBUG_LOCAL,
+ /* A register variable. */
+ DEBUG_REGISTER
+};
+
+/* Different kinds of function parameters. */
+
+enum debug_parm_kind
+{
+ /* Not used. */
+ DEBUG_PARM_ILLEGAL,
+ /* A stack based parameter. */
+ DEBUG_PARM_STACK,
+ /* A register parameter. */
+ DEBUG_PARM_REG,
+ /* A stack based reference parameter. */
+ DEBUG_PARM_REFERENCE,
+ /* A register reference parameter. */
+ DEBUG_PARM_REF_REG
+};
+
+/* Different kinds of visibility. */
+
+enum debug_visibility
+{
+ /* A public field (e.g., a field in a C struct). */
+ DEBUG_VISIBILITY_PUBLIC,
+ /* A protected field. */
+ DEBUG_VISIBILITY_PROTECTED,
+ /* A private field. */
+ DEBUG_VISIBILITY_PRIVATE,
+ /* A field which should be ignored. */
+ DEBUG_VISIBILITY_IGNORE
+};
+
+/* A type. */
+
+typedef struct debug_type *debug_type;
+
+#define DEBUG_TYPE_NULL ((debug_type) NULL)
+
+/* A field in a struct or union. */
+
+typedef struct debug_field *debug_field;
+
+#define DEBUG_FIELD_NULL ((debug_field) NULL)
+
+/* A base class for an object. */
+
+typedef struct debug_baseclass *debug_baseclass;
+
+#define DEBUG_BASECLASS_NULL ((debug_baseclass) NULL)
+
+/* A method of an object. */
+
+typedef struct debug_method *debug_method;
+
+#define DEBUG_METHOD_NULL ((debug_method) NULL)
+
+/* The arguments to a method function of an object. These indicate
+ which method to run. */
+
+typedef struct debug_method_variant *debug_method_variant;
+
+#define DEBUG_METHOD_VARIANT_NULL ((debug_method_variant) NULL)
+
+/* This structure is passed to debug_write. It holds function
+ pointers that debug_write will call based on the accumulated
+ debugging information. */
+
+struct debug_write_fns
+{
+ /* This is called at the start of each new compilation unit with the
+ name of the main file in the new unit. */
+ boolean (*start_compilation_unit) PARAMS ((PTR, const char *));
+
+ /* This is called at the start of each source file within a
+ compilation unit, before outputting any global information for
+ that file. The argument is the name of the file. */
+ boolean (*start_source) PARAMS ((PTR, const char *));
+
+ /* Each writer must keep a stack of types. */
+
+ /* Push an empty type onto the type stack. This type can appear if
+ there is a reference to a type which is never defined. */
+ boolean (*empty_type) PARAMS ((PTR));
+
+ /* Push a void type onto the type stack. */
+ boolean (*void_type) PARAMS ((PTR));
+
+ /* Push an integer type onto the type stack, given the size and
+ whether it is unsigned. */
+ boolean (*int_type) PARAMS ((PTR, unsigned int, boolean));
+
+ /* Push a floating type onto the type stack, given the size. */
+ boolean (*float_type) PARAMS ((PTR, unsigned int));
+
+ /* Push a complex type onto the type stack, given the size. */
+ boolean (*complex_type) PARAMS ((PTR, unsigned int));
+
+ /* Push a boolean type onto the type stack, given the size. */
+ boolean (*bool_type) PARAMS ((PTR, unsigned int));
+
+ /* Push an enum type onto the type stack, given the tag, a NULL
+ terminated array of names and the associated values. If there is
+ no tag, the tag argument will be NULL. If this is an undefined
+ enum, the names and values arguments will be NULL. */
+ boolean (*enum_type) PARAMS ((PTR, const char *, const char **,
+ bfd_signed_vma *));
+
+ /* Pop the top type on the type stack, and push a pointer to that
+ type onto the type stack. */
+ boolean (*pointer_type) PARAMS ((PTR));
+
+ /* Push a function type onto the type stack. The second argument
+ indicates the number of argument types that have been pushed onto
+ the stack. If the number of argument types is passed as -1, then
+ the argument types of the function are unknown, and no types have
+ been pushed onto the stack. The third argument is true if the
+ function takes a variable number of arguments. The return type
+ of the function is pushed onto the type stack below the argument
+ types, if any. */
+ boolean (*function_type) PARAMS ((PTR, int, boolean));
+
+ /* Pop the top type on the type stack, and push a reference to that
+ type onto the type stack. */
+ boolean (*reference_type) PARAMS ((PTR));
+
+ /* Pop the top type on the type stack, and push a range of that type
+ with the given lower and upper bounds onto the type stack. */
+ boolean (*range_type) PARAMS ((PTR, bfd_signed_vma, bfd_signed_vma));
+
+ /* Push an array type onto the type stack. The top type on the type
+ stack is the range, and the next type on the type stack is the
+ element type. These should be popped before the array type is
+ pushed. The arguments are the lower bound, the upper bound, and
+ whether the array is a string. */
+ boolean (*array_type) PARAMS ((PTR, bfd_signed_vma, bfd_signed_vma,
+ boolean));
+
+ /* Pop the top type on the type stack, and push a set of that type
+ onto the type stack. The argument indicates whether this set is
+ a bitstring. */
+ boolean (*set_type) PARAMS ((PTR, boolean));
+
+ /* Push an offset type onto the type stack. The top type on the
+ type stack is the target type, and the next type on the type
+ stack is the base type. These should be popped before the offset
+ type is pushed. */
+ boolean (*offset_type) PARAMS ((PTR));
+
+ /* Push a method type onto the type stack. If the second argument
+ is true, the top type on the stack is the class to which the
+ method belongs; otherwise, the class must be determined by the
+ class to which the method is attached. The third argument is the
+ number of argument types; these are pushed onto the type stack in
+ reverse order (the first type popped is the last argument to the
+ method). A value of -1 for the third argument means that no
+ argument information is available. The fourth argument is true
+ if the function takes a variable number of arguments. The next
+ type on the type stack below the domain and the argument types is
+ the return type of the method. All these types must be popped,
+ and then the method type must be pushed. */
+ boolean (*method_type) PARAMS ((PTR, boolean, int, boolean));
+
+ /* Pop the top type off the type stack, and push a const qualified
+ version of that type onto the type stack. */
+ boolean (*const_type) PARAMS ((PTR));
+
+ /* Pop the top type off the type stack, and push a volatile
+ qualified version of that type onto the type stack. */
+ boolean (*volatile_type) PARAMS ((PTR));
+
+ /* Start building a struct. This is followed by calls to the
+ struct_field function, and finished by a call to the
+ end_struct_type function. The second argument is the tag; this
+ will be NULL if there isn't one. If the second argument is NULL,
+ the third argument is a constant identifying this struct for use
+ with tag_type. The fourth argument is true for a struct, false
+ for a union. The fifth argument is the size. If this is an
+ undefined struct or union, the size will be 0 and struct_field
+ will not be called before end_struct_type is called. */
+ boolean (*start_struct_type) PARAMS ((PTR, const char *, unsigned int,
+ boolean, unsigned int));
+
+ /* Add a field to the struct type currently being built. The type
+ of the field should be popped off the type stack. The arguments
+ are the name, the bit position, the bit size (may be zero if the
+ field is not packed), and the visibility. */
+ boolean (*struct_field) PARAMS ((PTR, const char *, bfd_vma, bfd_vma,
+ enum debug_visibility));
+
+ /* Finish building a struct, and push it onto the type stack. */
+ boolean (*end_struct_type) PARAMS ((PTR));
+
+ /* Start building a class. This is followed by calls to several
+ functions: struct_field, class_static_member, class_baseclass,
+ class_start_method, class_method_variant,
+ class_static_method_variant, and class_end_method. The class is
+ finished by a call to end_class_type. The first five arguments
+ are the same as for start_struct_type. The sixth argument is
+ true if there is a virtual function table; if there is, the
+ seventh argument is true if the virtual function table can be
+ found in the type itself, and is false if the type of the object
+ holding the virtual function table should be popped from the type
+ stack. */
+ boolean (*start_class_type) PARAMS ((PTR, const char *, unsigned int,
+ boolean, unsigned int, boolean,
+ boolean));
+
+ /* Add a static member to the class currently being built. The
+ arguments are the field name, the physical name, and the
+ visibility. The type must be popped off the type stack. */
+ boolean (*class_static_member) PARAMS ((PTR, const char *, const char *,
+ enum debug_visibility));
+
+ /* Add a baseclass to the class currently being built. The type of
+ the baseclass must be popped off the type stack. The arguments
+ are the bit position, whether the class is virtual, and the
+ visibility. */
+ boolean (*class_baseclass) PARAMS ((PTR, bfd_vma, boolean,
+ enum debug_visibility));
+
+ /* Start adding a method to the class currently being built. This
+ is followed by calls to class_method_variant and
+ class_static_method_variant to describe different variants of the
+ method which take different arguments. The method is finished
+ with a call to class_end_method. The argument is the method
+ name. */
+ boolean (*class_start_method) PARAMS ((PTR, const char *));
+
+ /* Describe a variant to the class method currently being built.
+ The type of the variant must be popped off the type stack. The
+ second argument is the physical name of the function. The
+ following arguments are the visibility, whether the variant is
+ const, whether the variant is volatile, the offset in the virtual
+ function table, and whether the context is on the type stack
+ (below the variant type). */
+ boolean (*class_method_variant) PARAMS ((PTR, const char *,
+ enum debug_visibility,
+ boolean, boolean,
+ bfd_vma, boolean));
+
+ /* Describe a static variant to the class method currently being
+ built. The arguments are the same as for class_method_variant,
+ except that the last two arguments are omitted. The type of the
+ variant must be popped off the type stack. */
+ boolean (*class_static_method_variant) PARAMS ((PTR, const char *,
+ enum debug_visibility,
+ boolean, boolean));
+
+ /* Finish describing a class method. */
+ boolean (*class_end_method) PARAMS ((PTR));
+
+ /* Finish describing a class, and push it onto the type stack. */
+ boolean (*end_class_type) PARAMS ((PTR));
+
+ /* Push a type on the stack which was given a name by an earlier
+ call to typdef. */
+ boolean (*typedef_type) PARAMS ((PTR, const char *));
+
+ /* Push a tagged type on the stack which was defined earlier. If
+ the second argument is not NULL, the type was defined by a call
+ to tag. If the second argument is NULL, the type was defined by
+ a call to start_struct_type or start_class_type with a tag of
+ NULL and the number of the third argument. Either way, the
+ fourth argument is the tag kind. Note that this may be called
+ for a struct (class) being defined, in between the call to
+ start_struct_type (start_class_type) and the call to
+ end_struct_type (end_class_type). */
+ boolean (*tag_type) PARAMS ((PTR, const char *, unsigned int,
+ enum debug_type_kind));
+
+ /* Pop the type stack, and typedef it to the given name. */
+ boolean (*typdef) PARAMS ((PTR, const char *));
+
+ /* Pop the type stack, and declare it as a tagged struct or union or
+ enum or whatever. The tag passed down here is redundant, since
+ was also passed when enum_type, start_struct_type, or
+ start_class_type was called. */
+ boolean (*tag) PARAMS ((PTR, const char *));
+
+ /* This is called to record a named integer constant. */
+ boolean (*int_constant) PARAMS ((PTR, const char *, bfd_vma));
+
+ /* This is called to record a named floating point constant. */
+ boolean (*float_constant) PARAMS ((PTR, const char *, double));
+
+ /* This is called to record a typed integer constant. The type is
+ popped off the type stack. */
+ boolean (*typed_constant) PARAMS ((PTR, const char *, bfd_vma));
+
+ /* This is called to record a variable. The type is popped off the
+ type stack. */
+ boolean (*variable) PARAMS ((PTR, const char *, enum debug_var_kind,
+ bfd_vma));
+
+ /* Start writing out a function. The return type must be popped off
+ the stack. The boolean is true if the function is global. This
+ is followed by calls to function_parameter, followed by block
+ information. */
+ boolean (*start_function) PARAMS ((PTR, const char *, boolean));
+
+ /* Record a function parameter for the current function. The type
+ must be popped off the stack. */
+ boolean (*function_parameter) PARAMS ((PTR, const char *,
+ enum debug_parm_kind, bfd_vma));
+
+ /* Start writing out a block. There is at least one top level block
+ per function. Blocks may be nested. The argument is the
+ starting address of the block. */
+ boolean (*start_block) PARAMS ((PTR, bfd_vma));
+
+ /* Finish writing out a block. The argument is the ending address
+ of the block. */
+ boolean (*end_block) PARAMS ((PTR, bfd_vma));
+
+ /* Finish writing out a function. */
+ boolean (*end_function) PARAMS ((PTR));
+
+ /* Record line number information for the current compilation unit. */
+ boolean (*lineno) PARAMS ((PTR, const char *, unsigned long, bfd_vma));
+};
+
+/* Exported functions. */
+
+/* The first argument to most of these functions is a handle. This
+ handle is returned by the debug_init function. The purpose of the
+ handle is to permit the debugging routines to not use static
+ variables, and hence to be reentrant. This would be useful for a
+ program which wanted to handle two executables simultaneously. */
+
+/* Return a debugging handle. */
+
+extern PTR debug_init PARAMS ((void));
+
+/* Set the source filename. This implicitly starts a new compilation
+ unit. */
+
+extern boolean debug_set_filename PARAMS ((PTR, const char *));
+
+/* Change source files to the given file name. This is used for
+ include files in a single compilation unit. */
+
+extern boolean debug_start_source PARAMS ((PTR, const char *));
+
+/* Record a function definition. This implicitly starts a function
+ block. The debug_type argument is the type of the return value.
+ The boolean indicates whether the function is globally visible.
+ The bfd_vma is the address of the start of the function. Currently
+ the parameter types are specified by calls to
+ debug_record_parameter. */
+
+extern boolean debug_record_function
+ PARAMS ((PTR, const char *, debug_type, boolean, bfd_vma));
+
+/* Record a parameter for the current function. */
+
+extern boolean debug_record_parameter
+ PARAMS ((PTR, const char *, debug_type, enum debug_parm_kind, bfd_vma));
+
+/* End a function definition. The argument is the address where the
+ function ends. */
+
+extern boolean debug_end_function PARAMS ((PTR, bfd_vma));
+
+/* Start a block in a function. All local information will be
+ recorded in this block, until the matching call to debug_end_block.
+ debug_start_block and debug_end_block may be nested. The argument
+ is the address at which this block starts. */
+
+extern boolean debug_start_block PARAMS ((PTR, bfd_vma));
+
+/* Finish a block in a function. This matches the call to
+ debug_start_block. The argument is the address at which this block
+ ends. */
+
+extern boolean debug_end_block PARAMS ((PTR, bfd_vma));
+
+/* Associate a line number in the current source file with a given
+ address. */
+
+extern boolean debug_record_line PARAMS ((PTR, unsigned long, bfd_vma));
+
+/* Start a named common block. This is a block of variables that may
+ move in memory. */
+
+extern boolean debug_start_common_block PARAMS ((PTR, const char *));
+
+/* End a named common block. */
+
+extern boolean debug_end_common_block PARAMS ((PTR, const char *));
+
+/* Record a named integer constant. */
+
+extern boolean debug_record_int_const PARAMS ((PTR, const char *, bfd_vma));
+
+/* Record a named floating point constant. */
+
+extern boolean debug_record_float_const PARAMS ((PTR, const char *, double));
+
+/* Record a typed constant with an integral value. */
+
+extern boolean debug_record_typed_const
+ PARAMS ((PTR, const char *, debug_type, bfd_vma));
+
+/* Record a label. */
+
+extern boolean debug_record_label
+ PARAMS ((PTR, const char *, debug_type, bfd_vma));
+
+/* Record a variable. */
+
+extern boolean debug_record_variable
+ PARAMS ((PTR, const char *, debug_type, enum debug_var_kind, bfd_vma));
+
+/* Make an indirect type. The first argument is a pointer to the
+ location where the real type will be placed. The second argument
+ is the type tag, if there is one; this may be NULL; the only
+ purpose of this argument is so that debug_get_type_name can return
+ something useful. This function may be used when a type is
+ referenced before it is defined. */
+
+extern debug_type debug_make_indirect_type
+ PARAMS ((PTR, debug_type *, const char *));
+
+/* Make a void type. */
+
+extern debug_type debug_make_void_type PARAMS ((PTR));
+
+/* Make an integer type of a given size. The boolean argument is true
+ if the integer is unsigned. */
+
+extern debug_type debug_make_int_type PARAMS ((PTR, unsigned int, boolean));
+
+/* Make a floating point type of a given size. FIXME: On some
+ platforms, like an Alpha, you probably need to be able to specify
+ the format. */
+
+extern debug_type debug_make_float_type PARAMS ((PTR, unsigned int));
+
+/* Make a boolean type of a given size. */
+
+extern debug_type debug_make_bool_type PARAMS ((PTR, unsigned int));
+
+/* Make a complex type of a given size. */
+
+extern debug_type debug_make_complex_type PARAMS ((PTR, unsigned int));
+
+/* Make a structure type. The second argument is true for a struct,
+ false for a union. The third argument is the size of the struct.
+ The fourth argument is a NULL terminated array of fields. */
+
+extern debug_type debug_make_struct_type
+ PARAMS ((PTR, boolean, bfd_vma, debug_field *));
+
+/* Make an object type. The first three arguments after the handle
+ are the same as for debug_make_struct_type. The next arguments are
+ a NULL terminated array of base classes, a NULL terminated array of
+ methods, the type of the object holding the virtual function table
+ if it is not this object, and a boolean which is true if this
+ object has its own virtual function table. */
+
+extern debug_type debug_make_object_type
+ PARAMS ((PTR, boolean, bfd_vma, debug_field *, debug_baseclass *,
+ debug_method *, debug_type, boolean));
+
+/* Make an enumeration type. The arguments are a null terminated
+ array of strings, and an array of corresponding values. */
+
+extern debug_type debug_make_enum_type
+ PARAMS ((PTR, const char **, bfd_signed_vma *));
+
+/* Make a pointer to a given type. */
+
+extern debug_type debug_make_pointer_type
+ PARAMS ((PTR, debug_type));
+
+/* Make a function type. The second argument is the return type. The
+ third argument is a NULL terminated array of argument types. The
+ fourth argument is true if the function takes a variable number of
+ arguments. If the third argument is NULL, then the argument types
+ are unknown. */
+
+extern debug_type debug_make_function_type
+ PARAMS ((PTR, debug_type, debug_type *, boolean));
+
+/* Make a reference to a given type. */
+
+extern debug_type debug_make_reference_type PARAMS ((PTR, debug_type));
+
+/* Make a range of a given type from a lower to an upper bound. */
+
+extern debug_type debug_make_range_type
+ PARAMS ((PTR, debug_type, bfd_signed_vma, bfd_signed_vma));
+
+/* Make an array type. The second argument is the type of an element
+ of the array. The third argument is the type of a range of the
+ array. The fourth and fifth argument are the lower and upper
+ bounds, respectively (if the bounds are not known, lower should be
+ 0 and upper should be -1). The sixth argument is true if this
+ array is actually a string, as in C. */
+
+extern debug_type debug_make_array_type
+ PARAMS ((PTR, debug_type, debug_type, bfd_signed_vma, bfd_signed_vma,
+ boolean));
+
+/* Make a set of a given type. For example, a Pascal set type. The
+ boolean argument is true if this set is actually a bitstring, as in
+ CHILL. */
+
+extern debug_type debug_make_set_type PARAMS ((PTR, debug_type, boolean));
+
+/* Make a type for a pointer which is relative to an object. The
+ second argument is the type of the object to which the pointer is
+ relative. The third argument is the type that the pointer points
+ to. */
+
+extern debug_type debug_make_offset_type
+ PARAMS ((PTR, debug_type, debug_type));
+
+/* Make a type for a method function. The second argument is the
+ return type. The third argument is the domain. The fourth
+ argument is a NULL terminated array of argument types. The fifth
+ argument is true if the function takes a variable number of
+ arguments, in which case the array of argument types indicates the
+ types of the first arguments. The domain and the argument array
+ may be NULL, in which case this is a stub method and that
+ information is not available. Stabs debugging uses this, and gets
+ the argument types from the mangled name. */
+
+extern debug_type debug_make_method_type
+ PARAMS ((PTR, debug_type, debug_type, debug_type *, boolean));
+
+/* Make a const qualified version of a given type. */
+
+extern debug_type debug_make_const_type PARAMS ((PTR, debug_type));
+
+/* Make a volatile qualified version of a given type. */
+
+extern debug_type debug_make_volatile_type PARAMS ((PTR, debug_type));
+
+/* Make an undefined tagged type. For example, a struct which has
+ been mentioned, but not defined. */
+
+extern debug_type debug_make_undefined_tagged_type
+ PARAMS ((PTR, const char *, enum debug_type_kind));
+
+/* Make a base class for an object. The second argument is the base
+ class type. The third argument is the bit position of this base
+ class in the object. The fourth argument is whether this is a
+ virtual class. The fifth argument is the visibility of the base
+ class. */
+
+extern debug_baseclass debug_make_baseclass
+ PARAMS ((PTR, debug_type, bfd_vma, boolean, enum debug_visibility));
+
+/* Make a field for a struct. The second argument is the name. The
+ third argument is the type of the field. The fourth argument is
+ the bit position of the field. The fifth argument is the size of
+ the field (it may be zero). The sixth argument is the visibility
+ of the field. */
+
+extern debug_field debug_make_field
+ PARAMS ((PTR, const char *, debug_type, bfd_vma, bfd_vma,
+ enum debug_visibility));
+
+/* Make a static member of an object. The second argument is the
+ name. The third argument is the type of the member. The fourth
+ argument is the physical name of the member (i.e., the name as a
+ global variable). The fifth argument is the visibility of the
+ member. */
+
+extern debug_field debug_make_static_member
+ PARAMS ((PTR, const char *, debug_type, const char *,
+ enum debug_visibility));
+
+/* Make a method. The second argument is the name, and the third
+ argument is a NULL terminated array of method variants. Each
+ method variant is a method with this name but with different
+ argument types. */
+
+extern debug_method debug_make_method
+ PARAMS ((PTR, const char *, debug_method_variant *));
+
+/* Make a method variant. The second argument is the physical name of
+ the function. The third argument is the type of the function,
+ probably constructed by debug_make_method_type. The fourth
+ argument is the visibility. The fifth argument is whether this is
+ a const function. The sixth argument is whether this is a volatile
+ function. The seventh argument is the index in the virtual
+ function table, if any. The eighth argument is the virtual
+ function context. */
+
+extern debug_method_variant debug_make_method_variant
+ PARAMS ((PTR, const char *, debug_type, enum debug_visibility, boolean,
+ boolean, bfd_vma, debug_type));
+
+/* Make a static method argument. The arguments are the same as for
+ debug_make_method_variant, except that the last two are omitted
+ since a static method can not also be virtual. */
+
+extern debug_method_variant debug_make_static_method_variant
+ PARAMS ((PTR, const char *, debug_type, enum debug_visibility, boolean,
+ boolean));
+
+/* Name a type. This returns a new type with an attached name. */
+
+extern debug_type debug_name_type PARAMS ((PTR, const char *, debug_type));
+
+/* Give a tag to a type, such as a struct or union. This returns a
+ new type with an attached tag. */
+
+extern debug_type debug_tag_type PARAMS ((PTR, const char *, debug_type));
+
+/* Record the size of a given type. */
+
+extern boolean debug_record_type_size PARAMS ((PTR, debug_type, unsigned int));
+
+/* Find a named type. */
+
+extern debug_type debug_find_named_type PARAMS ((PTR, const char *));
+
+/* Find a tagged type. */
+
+extern debug_type debug_find_tagged_type
+ PARAMS ((PTR, const char *, enum debug_type_kind));
+
+/* Get the kind of a type. */
+
+extern enum debug_type_kind debug_get_type_kind PARAMS ((PTR, debug_type));
+
+/* Get the name of a type. */
+
+extern const char *debug_get_type_name PARAMS ((PTR, debug_type));
+
+/* Get the size of a type. */
+
+extern bfd_vma debug_get_type_size PARAMS ((PTR, debug_type));
+
+/* Get the return type of a function or method type. */
+
+extern debug_type debug_get_return_type PARAMS ((PTR, debug_type));
+
+/* Get the NULL terminated array of parameter types for a function or
+ method type (actually, parameter types are not currently stored for
+ function types). This may be used to determine whether a method
+ type is a stub method or not. The last argument points to a
+ boolean which is set to true if the function takes a variable
+ number of arguments. */
+
+extern const debug_type *debug_get_parameter_types PARAMS ((PTR,
+ debug_type,
+ boolean *));
+
+/* Get the target type of a pointer or reference or const or volatile
+ type. */
+
+extern debug_type debug_get_target_type PARAMS ((PTR, debug_type));
+
+/* Get the NULL terminated array of fields for a struct, union, or
+ class. */
+
+extern const debug_field *debug_get_fields PARAMS ((PTR, debug_type));
+
+/* Get the type of a field. */
+
+extern debug_type debug_get_field_type PARAMS ((PTR, debug_field));
+
+/* Get the name of a field. */
+
+extern const char *debug_get_field_name PARAMS ((PTR, debug_field));
+
+/* Get the bit position of a field within the containing structure.
+ If the field is a static member, this will return (bfd_vma) -1. */
+
+extern bfd_vma debug_get_field_bitpos PARAMS ((PTR, debug_field));
+
+/* Get the bit size of a field. If the field is a static member, this
+ will return (bfd_vma) -1. */
+
+extern bfd_vma debug_get_field_bitsize PARAMS ((PTR, debug_field));
+
+/* Get the visibility of a field. */
+
+extern enum debug_visibility debug_get_field_visibility
+ PARAMS ((PTR, debug_field));
+
+/* Get the physical name of a field, if it is a static member. If the
+ field is not a static member, this will return NULL. */
+
+extern const char *debug_get_field_physname PARAMS ((PTR, debug_field));
+
+/* Write out the recorded debugging information. This takes a set of
+ function pointers which are called to do the actual writing. The
+ first PTR is the debugging handle. The second PTR is a handle
+ which is passed to the functions. */
+
+extern boolean debug_write PARAMS ((PTR, const struct debug_write_fns *, PTR));
+
+#endif /* DEBUG_H */
diff --git a/pstack/demangle.h b/pstack/demangle.h
new file mode 100644
index 00000000000..a961436ca77
--- /dev/null
+++ b/pstack/demangle.h
@@ -0,0 +1,90 @@
+/* Defs for interface to demanglers.
+ Copyright 1992, 1995, 1996 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+
+#if !defined (DEMANGLE_H)
+#define DEMANGLE_H
+
+#ifdef IN_GCC
+#include "gansidecl.h"
+#define PARAMS(ARGS) PROTO(ARGS)
+#else /* ! IN_GCC */
+#include <ansidecl.h>
+#endif /* IN_GCC */
+
+/* Options passed to cplus_demangle (in 2nd parameter). */
+
+#define DMGL_NO_OPTS 0 /* For readability... */
+#define DMGL_PARAMS (1 << 0) /* Include function args */
+#define DMGL_ANSI (1 << 1) /* Include const, volatile, etc */
+#define DMGL_JAVA (1 << 2) /* Demangle as Java rather than C++. */
+
+#define DMGL_AUTO (1 << 8)
+#define DMGL_GNU (1 << 9)
+#define DMGL_LUCID (1 << 10)
+#define DMGL_ARM (1 << 11)
+/* If none of these are set, use 'current_demangling_style' as the default. */
+#define DMGL_STYLE_MASK (DMGL_AUTO|DMGL_GNU|DMGL_LUCID|DMGL_ARM)
+
+/* Enumeration of possible demangling styles.
+
+ Lucid and ARM styles are still kept logically distinct, even though
+ they now both behave identically. The resulting style is actual the
+ union of both. I.E. either style recognizes both "__pt__" and "__rf__"
+ for operator "->", even though the first is lucid style and the second
+ is ARM style. (FIXME?) */
+
+extern enum demangling_styles
+{
+ unknown_demangling = 0,
+ auto_demangling = DMGL_AUTO,
+ gnu_demangling = DMGL_GNU,
+ lucid_demangling = DMGL_LUCID,
+ arm_demangling = DMGL_ARM
+} current_demangling_style;
+
+/* Define string names for the various demangling styles. */
+
+#define AUTO_DEMANGLING_STYLE_STRING "auto"
+#define GNU_DEMANGLING_STYLE_STRING "gnu"
+#define LUCID_DEMANGLING_STYLE_STRING "lucid"
+#define ARM_DEMANGLING_STYLE_STRING "arm"
+
+/* Some macros to test what demangling style is active. */
+
+#define CURRENT_DEMANGLING_STYLE current_demangling_style
+#define AUTO_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_AUTO)
+#define GNU_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_GNU)
+#define LUCID_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_LUCID)
+#define ARM_DEMANGLING (CURRENT_DEMANGLING_STYLE & DMGL_ARM)
+
+extern char *
+cplus_demangle PARAMS ((const char *mangled, int options));
+
+extern int
+cplus_demangle_opname PARAMS ((const char *opname, char *result, int options));
+
+extern const char *
+cplus_mangle_opname PARAMS ((const char *opname, int options));
+
+/* Note: This sets global state. FIXME if you care about multi-threading. */
+
+extern void
+set_cplus_marker_for_demangling PARAMS ((int ch));
+
+#endif /* DEMANGLE_H */
diff --git a/pstack/filemode.c b/pstack/filemode.c
new file mode 100644
index 00000000000..58b52ba7489
--- /dev/null
+++ b/pstack/filemode.c
@@ -0,0 +1,266 @@
+/* filemode.c -- make a string describing file modes
+ Copyright (C) 1985, 90, 91, 94, 95, 1997 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+#include "bfd.h"
+#include "bucomm.h"
+
+static char ftypelet PARAMS ((unsigned long));
+static void setst PARAMS ((unsigned long, char *));
+
+/* filemodestring - fill in string STR with an ls-style ASCII
+ representation of the st_mode field of file stats block STATP.
+ 10 characters are stored in STR; no terminating null is added.
+ The characters stored in STR are:
+
+ 0 File type. 'd' for directory, 'c' for character
+ special, 'b' for block special, 'm' for multiplex,
+ 'l' for symbolic link, 's' for socket, 'p' for fifo,
+ '-' for any other file type
+
+ 1 'r' if the owner may read, '-' otherwise.
+
+ 2 'w' if the owner may write, '-' otherwise.
+
+ 3 'x' if the owner may execute, 's' if the file is
+ set-user-id, '-' otherwise.
+ 'S' if the file is set-user-id, but the execute
+ bit isn't set.
+
+ 4 'r' if group members may read, '-' otherwise.
+
+ 5 'w' if group members may write, '-' otherwise.
+
+ 6 'x' if group members may execute, 's' if the file is
+ set-group-id, '-' otherwise.
+ 'S' if it is set-group-id but not executable.
+
+ 7 'r' if any user may read, '-' otherwise.
+
+ 8 'w' if any user may write, '-' otherwise.
+
+ 9 'x' if any user may execute, 't' if the file is "sticky"
+ (will be retained in swap space after execution), '-'
+ otherwise.
+ 'T' if the file is sticky but not executable. */
+
+#if 0
+
+/* This is not used; only mode_string is used. */
+
+void
+filemodestring (statp, str)
+ struct stat *statp;
+ char *str;
+{
+ mode_string ((unsigned long) statp->st_mode, str);
+}
+
+#endif
+
+/* Get definitions for the file permission bits. */
+
+#ifndef S_IRWXU
+#define S_IRWXU 0700
+#endif
+#ifndef S_IRUSR
+#define S_IRUSR 0400
+#endif
+#ifndef S_IWUSR
+#define S_IWUSR 0200
+#endif
+#ifndef S_IXUSR
+#define S_IXUSR 0100
+#endif
+
+#ifndef S_IRWXG
+#define S_IRWXG 0070
+#endif
+#ifndef S_IRGRP
+#define S_IRGRP 0040
+#endif
+#ifndef S_IWGRP
+#define S_IWGRP 0020
+#endif
+#ifndef S_IXGRP
+#define S_IXGRP 0010
+#endif
+
+#ifndef S_IRWXO
+#define S_IRWXO 0007
+#endif
+#ifndef S_IROTH
+#define S_IROTH 0004
+#endif
+#ifndef S_IWOTH
+#define S_IWOTH 0002
+#endif
+#ifndef S_IXOTH
+#define S_IXOTH 0001
+#endif
+
+/* Like filemodestring, but only the relevant part of the `struct stat'
+ is given as an argument. */
+
+void
+mode_string (mode, str)
+ unsigned long mode;
+ char *str;
+{
+ str[0] = ftypelet ((unsigned long) mode);
+ str[1] = (mode & S_IRUSR) != 0 ? 'r' : '-';
+ str[2] = (mode & S_IWUSR) != 0 ? 'w' : '-';
+ str[3] = (mode & S_IXUSR) != 0 ? 'x' : '-';
+ str[4] = (mode & S_IRGRP) != 0 ? 'r' : '-';
+ str[5] = (mode & S_IWGRP) != 0 ? 'w' : '-';
+ str[6] = (mode & S_IXGRP) != 0 ? 'x' : '-';
+ str[7] = (mode & S_IROTH) != 0 ? 'r' : '-';
+ str[8] = (mode & S_IWOTH) != 0 ? 'w' : '-';
+ str[9] = (mode & S_IXOTH) != 0 ? 'x' : '-';
+ setst ((unsigned long) mode, str);
+}
+
+/* Return a character indicating the type of file described by
+ file mode BITS:
+ 'd' for directories
+ 'b' for block special files
+ 'c' for character special files
+ 'm' for multiplexor files
+ 'l' for symbolic links
+ 's' for sockets
+ 'p' for fifos
+ '-' for any other file type. */
+
+#ifndef S_ISDIR
+#ifdef S_IFDIR
+#define S_ISDIR(i) (((i) & S_IFMT) == S_IFDIR)
+#else /* ! defined (S_IFDIR) */
+#define S_ISDIR(i) (((i) & 0170000) == 040000)
+#endif /* ! defined (S_IFDIR) */
+#endif /* ! defined (S_ISDIR) */
+
+#ifndef S_ISBLK
+#ifdef S_IFBLK
+#define S_ISBLK(i) (((i) & S_IFMT) == S_IFBLK)
+#else /* ! defined (S_IFBLK) */
+#define S_ISBLK(i) 0
+#endif /* ! defined (S_IFBLK) */
+#endif /* ! defined (S_ISBLK) */
+
+#ifndef S_ISCHR
+#ifdef S_IFCHR
+#define S_ISCHR(i) (((i) & S_IFMT) == S_IFCHR)
+#else /* ! defined (S_IFCHR) */
+#define S_ISCHR(i) 0
+#endif /* ! defined (S_IFCHR) */
+#endif /* ! defined (S_ISCHR) */
+
+#ifndef S_ISFIFO
+#ifdef S_IFIFO
+#define S_ISFIFO(i) (((i) & S_IFMT) == S_IFIFO)
+#else /* ! defined (S_IFIFO) */
+#define S_ISFIFO(i) 0
+#endif /* ! defined (S_IFIFO) */
+#endif /* ! defined (S_ISFIFO) */
+
+#ifndef S_ISSOCK
+#ifdef S_IFSOCK
+#define S_ISSOCK(i) (((i) & S_IFMT) == S_IFSOCK)
+#else /* ! defined (S_IFSOCK) */
+#define S_ISSOCK(i) 0
+#endif /* ! defined (S_IFSOCK) */
+#endif /* ! defined (S_ISSOCK) */
+
+#ifndef S_ISLNK
+#ifdef S_IFLNK
+#define S_ISLNK(i) (((i) & S_IFMT) == S_IFLNK)
+#else /* ! defined (S_IFLNK) */
+#define S_ISLNK(i) 0
+#endif /* ! defined (S_IFLNK) */
+#endif /* ! defined (S_ISLNK) */
+
+static char
+ftypelet (bits)
+ unsigned long bits;
+{
+ if (S_ISDIR (bits))
+ return 'd';
+ if (S_ISLNK (bits))
+ return 'l';
+ if (S_ISBLK (bits))
+ return 'b';
+ if (S_ISCHR (bits))
+ return 'c';
+ if (S_ISSOCK (bits))
+ return 's';
+ if (S_ISFIFO (bits))
+ return 'p';
+
+#ifdef S_IFMT
+#ifdef S_IFMPC
+ if ((bits & S_IFMT) == S_IFMPC
+ || (bits & S_IFMT) == S_IFMPB)
+ return 'm';
+#endif
+#ifdef S_IFNWK
+ if ((bits & S_IFMT) == S_IFNWK)
+ return 'n';
+#endif
+#endif
+
+ return '-';
+}
+
+/* Set the 's' and 't' flags in file attributes string CHARS,
+ according to the file mode BITS. */
+
+static void
+setst (bits, chars)
+ unsigned long bits;
+ char *chars;
+{
+#ifdef S_ISUID
+ if (bits & S_ISUID)
+ {
+ if (chars[3] != 'x')
+ /* Set-uid, but not executable by owner. */
+ chars[3] = 'S';
+ else
+ chars[3] = 's';
+ }
+#endif
+#ifdef S_ISGID
+ if (bits & S_ISGID)
+ {
+ if (chars[6] != 'x')
+ /* Set-gid, but not executable by group. */
+ chars[6] = 'S';
+ else
+ chars[6] = 's';
+ }
+#endif
+#ifdef S_ISVTX
+ if (bits & S_ISVTX)
+ {
+ if (chars[9] != 'x')
+ /* Sticky, but not executable by others. */
+ chars[9] = 'T';
+ else
+ chars[9] = 't';
+ }
+#endif
+}
diff --git a/pstack/ieee.c b/pstack/ieee.c
new file mode 100644
index 00000000000..8084656a5ef
--- /dev/null
+++ b/pstack/ieee.c
@@ -0,0 +1,7602 @@
+/* ieee.c -- Read and write IEEE-695 debugging information.
+ Copyright (C) 1996 Free Software Foundation, Inc.
+ Written by Ian Lance Taylor <ian@cygnus.com>.
+
+ This file is part of GNU Binutils.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+/* This file reads and writes IEEE-695 debugging information. */
+
+#include <stdio.h>
+#include <assert.h>
+
+#include <bfd.h>
+#include "ieee.h"
+#include "bucomm.h"
+#include <libiberty.h>
+#include "debug.h"
+#include "budbg.h"
+
+/* This structure holds an entry on the block stack. */
+
+struct ieee_block
+{
+ /* The kind of block. */
+ int kind;
+ /* The source file name, for a BB5 block. */
+ const char *filename;
+ /* The index of the function type, for a BB4 or BB6 block. */
+ unsigned int fnindx;
+ /* True if this function is being skipped. */
+ boolean skip;
+};
+
+/* This structure is the block stack. */
+
+#define BLOCKSTACK_SIZE (16)
+
+struct ieee_blockstack
+{
+ /* The stack pointer. */
+ struct ieee_block *bsp;
+ /* The stack. */
+ struct ieee_block stack[BLOCKSTACK_SIZE];
+};
+
+/* This structure holds information for a variable. */
+
+struct ieee_var
+{
+ /* Start of name. */
+ const char *name;
+ /* Length of name. */
+ unsigned long namlen;
+ /* Type. */
+ debug_type type;
+ /* Slot if we make an indirect type. */
+ debug_type *pslot;
+ /* Kind of variable or function. */
+ enum
+ {
+ IEEE_UNKNOWN,
+ IEEE_EXTERNAL,
+ IEEE_GLOBAL,
+ IEEE_STATIC,
+ IEEE_LOCAL,
+ IEEE_FUNCTION
+ } kind;
+};
+
+/* This structure holds all the variables. */
+
+struct ieee_vars
+{
+ /* Number of slots allocated. */
+ unsigned int alloc;
+ /* Variables. */
+ struct ieee_var *vars;
+};
+
+/* This structure holds information for a type. We need this because
+ we don't want to represent bitfields as real types. */
+
+struct ieee_type
+{
+ /* Type. */
+ debug_type type;
+ /* Slot if this is type is referenced before it is defined. */
+ debug_type *pslot;
+ /* Slots for arguments if we make indirect types for them. */
+ debug_type *arg_slots;
+ /* If this is a bitfield, this is the size in bits. If this is not
+ a bitfield, this is zero. */
+ unsigned long bitsize;
+};
+
+/* This structure holds all the type information. */
+
+struct ieee_types
+{
+ /* Number of slots allocated. */
+ unsigned int alloc;
+ /* Types. */
+ struct ieee_type *types;
+ /* Builtin types. */
+#define BUILTIN_TYPE_COUNT (60)
+ debug_type builtins[BUILTIN_TYPE_COUNT];
+};
+
+/* This structure holds a linked last of structs with their tag names,
+ so that we can convert them to C++ classes if necessary. */
+
+struct ieee_tag
+{
+ /* Next tag. */
+ struct ieee_tag *next;
+ /* This tag name. */
+ const char *name;
+ /* The type of the tag. */
+ debug_type type;
+ /* The tagged type is an indirect type pointing at this slot. */
+ debug_type slot;
+ /* This is an array of slots used when a field type is converted
+ into a indirect type, in case it needs to be later converted into
+ a reference type. */
+ debug_type *fslots;
+};
+
+/* This structure holds the information we pass around to the parsing
+ functions. */
+
+struct ieee_info
+{
+ /* The debugging handle. */
+ PTR dhandle;
+ /* The BFD. */
+ bfd *abfd;
+ /* The start of the bytes to be parsed. */
+ const bfd_byte *bytes;
+ /* The end of the bytes to be parsed. */
+ const bfd_byte *pend;
+ /* The block stack. */
+ struct ieee_blockstack blockstack;
+ /* Whether we have seen a BB1 or BB2. */
+ boolean saw_filename;
+ /* The variables. */
+ struct ieee_vars vars;
+ /* The global variables, after a global typedef block. */
+ struct ieee_vars *global_vars;
+ /* The types. */
+ struct ieee_types types;
+ /* The global types, after a global typedef block. */
+ struct ieee_types *global_types;
+ /* The list of tagged structs. */
+ struct ieee_tag *tags;
+};
+
+/* Basic builtin types, not including the pointers. */
+
+enum builtin_types
+{
+ builtin_unknown = 0,
+ builtin_void = 1,
+ builtin_signed_char = 2,
+ builtin_unsigned_char = 3,
+ builtin_signed_short_int = 4,
+ builtin_unsigned_short_int = 5,
+ builtin_signed_long = 6,
+ builtin_unsigned_long = 7,
+ builtin_signed_long_long = 8,
+ builtin_unsigned_long_long = 9,
+ builtin_float = 10,
+ builtin_double = 11,
+ builtin_long_double = 12,
+ builtin_long_long_double = 13,
+ builtin_quoted_string = 14,
+ builtin_instruction_address = 15,
+ builtin_int = 16,
+ builtin_unsigned = 17,
+ builtin_unsigned_int = 18,
+ builtin_char = 19,
+ builtin_long = 20,
+ builtin_short = 21,
+ builtin_unsigned_short = 22,
+ builtin_short_int = 23,
+ builtin_signed_short = 24,
+ builtin_bcd_float = 25
+};
+
+/* These are the values found in the derivation flags of a 'b'
+ component record of a 'T' type extension record in a C++ pmisc
+ record. These are bitmasks. */
+
+/* Set for a private base class, clear for a public base class.
+ Protected base classes are not supported. */
+#define BASEFLAGS_PRIVATE (0x1)
+/* Set for a virtual base class. */
+#define BASEFLAGS_VIRTUAL (0x2)
+/* Set for a friend class, clear for a base class. */
+#define BASEFLAGS_FRIEND (0x10)
+
+/* These are the values found in the specs flags of a 'd', 'm', or 'v'
+ component record of a 'T' type extension record in a C++ pmisc
+ record. The same flags are used for a 'M' record in a C++ pmisc
+ record. */
+
+/* The lower two bits hold visibility information. */
+#define CXXFLAGS_VISIBILITY (0x3)
+/* This value in the lower two bits indicates a public member. */
+#define CXXFLAGS_VISIBILITY_PUBLIC (0x0)
+/* This value in the lower two bits indicates a private member. */
+#define CXXFLAGS_VISIBILITY_PRIVATE (0x1)
+/* This value in the lower two bits indicates a protected member. */
+#define CXXFLAGS_VISIBILITY_PROTECTED (0x2)
+/* Set for a static member. */
+#define CXXFLAGS_STATIC (0x4)
+/* Set for a virtual override. */
+#define CXXFLAGS_OVERRIDE (0x8)
+/* Set for a friend function. */
+#define CXXFLAGS_FRIEND (0x10)
+/* Set for a const function. */
+#define CXXFLAGS_CONST (0x20)
+/* Set for a volatile function. */
+#define CXXFLAGS_VOLATILE (0x40)
+/* Set for an overloaded function. */
+#define CXXFLAGS_OVERLOADED (0x80)
+/* Set for an operator function. */
+#define CXXFLAGS_OPERATOR (0x100)
+/* Set for a constructor or destructor. */
+#define CXXFLAGS_CTORDTOR (0x400)
+/* Set for a constructor. */
+#define CXXFLAGS_CTOR (0x200)
+/* Set for an inline function. */
+#define CXXFLAGS_INLINE (0x800)
+
+/* Local functions. */
+
+static void ieee_error
+ PARAMS ((struct ieee_info *, const bfd_byte *, const char *));
+static void ieee_eof PARAMS ((struct ieee_info *));
+static char *savestring PARAMS ((const char *, unsigned long));
+static boolean ieee_read_number
+ PARAMS ((struct ieee_info *, const bfd_byte **, bfd_vma *));
+static boolean ieee_read_optional_number
+ PARAMS ((struct ieee_info *, const bfd_byte **, bfd_vma *, boolean *));
+static boolean ieee_read_id
+ PARAMS ((struct ieee_info *, const bfd_byte **, const char **,
+ unsigned long *));
+static boolean ieee_read_optional_id
+ PARAMS ((struct ieee_info *, const bfd_byte **, const char **,
+ unsigned long *, boolean *));
+static boolean ieee_read_expression
+ PARAMS ((struct ieee_info *, const bfd_byte **, bfd_vma *));
+static debug_type ieee_builtin_type
+ PARAMS ((struct ieee_info *, const bfd_byte *, unsigned int));
+static boolean ieee_alloc_type
+ PARAMS ((struct ieee_info *, unsigned int, boolean));
+static boolean ieee_read_type_index
+ PARAMS ((struct ieee_info *, const bfd_byte **, debug_type *));
+static int ieee_regno_to_genreg PARAMS ((bfd *, int));
+static int ieee_genreg_to_regno PARAMS ((bfd *, int));
+static boolean parse_ieee_bb PARAMS ((struct ieee_info *, const bfd_byte **));
+static boolean parse_ieee_be PARAMS ((struct ieee_info *, const bfd_byte **));
+static boolean parse_ieee_nn PARAMS ((struct ieee_info *, const bfd_byte **));
+static boolean parse_ieee_ty PARAMS ((struct ieee_info *, const bfd_byte **));
+static boolean parse_ieee_atn PARAMS ((struct ieee_info *, const bfd_byte **));
+static boolean ieee_read_cxx_misc
+ PARAMS ((struct ieee_info *, const bfd_byte **, unsigned long));
+static boolean ieee_read_cxx_class
+ PARAMS ((struct ieee_info *, const bfd_byte **, unsigned long));
+static boolean ieee_read_cxx_defaults
+ PARAMS ((struct ieee_info *, const bfd_byte **, unsigned long));
+static boolean ieee_read_reference
+ PARAMS ((struct ieee_info *, const bfd_byte **));
+static boolean ieee_require_asn
+ PARAMS ((struct ieee_info *, const bfd_byte **, bfd_vma *));
+static boolean ieee_require_atn65
+ PARAMS ((struct ieee_info *, const bfd_byte **, const char **,
+ unsigned long *));
+
+/* Report an error in the IEEE debugging information. */
+
+static void
+ieee_error (info, p, s)
+ struct ieee_info *info;
+ const bfd_byte *p;
+ const char *s;
+{
+ if (p != NULL)
+ fprintf (stderr, "%s: 0x%lx: %s (0x%x)\n", bfd_get_filename (info->abfd),
+ (unsigned long) (p - info->bytes), s, *p);
+ else
+ fprintf (stderr, "%s: %s\n", bfd_get_filename (info->abfd), s);
+}
+
+/* Report an unexpected EOF in the IEEE debugging information. */
+
+static void
+ieee_eof (info)
+ struct ieee_info *info;
+{
+ ieee_error (info, (const bfd_byte *) NULL,
+ "unexpected end of debugging information");
+}
+
+/* Save a string in memory. */
+
+static char *
+savestring (start, len)
+ const char *start;
+ unsigned long len;
+{
+ char *ret;
+
+ ret = (char *) xmalloc (len + 1);
+ memcpy (ret, start, len);
+ ret[len] = '\0';
+ return ret;
+}
+
+/* Read a number which must be present in an IEEE file. */
+
+static boolean
+ieee_read_number (info, pp, pv)
+ struct ieee_info *info;
+ const bfd_byte **pp;
+ bfd_vma *pv;
+{
+ return ieee_read_optional_number (info, pp, pv, (boolean *) NULL);
+}
+
+/* Read a number in an IEEE file. If ppresent is not NULL, the number
+ need not be there. */
+
+static boolean
+ieee_read_optional_number (info, pp, pv, ppresent)
+ struct ieee_info *info;
+ const bfd_byte **pp;
+ bfd_vma *pv;
+ boolean *ppresent;
+{
+ ieee_record_enum_type b;
+
+ if (*pp >= info->pend)
+ {
+ if (ppresent != NULL)
+ {
+ *ppresent = false;
+ return true;
+ }
+ ieee_eof (info);
+ return false;
+ }
+
+ b = (ieee_record_enum_type) **pp;
+ ++*pp;
+
+ if (b <= ieee_number_end_enum)
+ {
+ *pv = (bfd_vma) b;
+ if (ppresent != NULL)
+ *ppresent = true;
+ return true;
+ }
+
+ if (b >= ieee_number_repeat_start_enum && b <= ieee_number_repeat_end_enum)
+ {
+ unsigned int i;
+
+ i = (int) b - (int) ieee_number_repeat_start_enum;
+ if (*pp + i - 1 >= info->pend)
+ {
+ ieee_eof (info);
+ return false;
+ }
+
+ *pv = 0;
+ for (; i > 0; i--)
+ {
+ *pv <<= 8;
+ *pv += **pp;
+ ++*pp;
+ }
+
+ if (ppresent != NULL)
+ *ppresent = true;
+
+ return true;
+ }
+
+ if (ppresent != NULL)
+ {
+ --*pp;
+ *ppresent = false;
+ return true;
+ }
+
+ ieee_error (info, *pp - 1, "invalid number");
+ return false;
+}
+
+/* Read a required string from an IEEE file. */
+
+static boolean
+ieee_read_id (info, pp, pname, pnamlen)
+ struct ieee_info *info;
+ const bfd_byte **pp;
+ const char **pname;
+ unsigned long *pnamlen;
+{
+ return ieee_read_optional_id (info, pp, pname, pnamlen, (boolean *) NULL);
+}
+
+/* Read a string from an IEEE file. If ppresent is not NULL, the
+ string is optional. */
+
+static boolean
+ieee_read_optional_id (info, pp, pname, pnamlen, ppresent)
+ struct ieee_info *info;
+ const bfd_byte **pp;
+ const char **pname;
+ unsigned long *pnamlen;
+ boolean *ppresent;
+{
+ bfd_byte b;
+ unsigned long len;
+
+ if (*pp >= info->pend)
+ {
+ ieee_eof (info);
+ return false;
+ }
+
+ b = **pp;
+ ++*pp;
+
+ if (b <= 0x7f)
+ len = b;
+ else if ((ieee_record_enum_type) b == ieee_extension_length_1_enum)
+ {
+ len = **pp;
+ ++*pp;
+ }
+ else if ((ieee_record_enum_type) b == ieee_extension_length_2_enum)
+ {
+ len = (**pp << 8) + (*pp)[1];
+ *pp += 2;
+ }
+ else
+ {
+ if (ppresent != NULL)
+ {
+ --*pp;
+ *ppresent = false;
+ return true;
+ }
+ ieee_error (info, *pp - 1, "invalid string length");
+ return false;
+ }
+
+ if ((unsigned long) (info->pend - *pp) < len)
+ {
+ ieee_eof (info);
+ return false;
+ }
+
+ *pname = (const char *) *pp;
+ *pnamlen = len;
+ *pp += len;
+
+ if (ppresent != NULL)
+ *ppresent = true;
+
+ return true;
+}
+
+/* Read an expression from an IEEE file. Since this code is only used
+ to parse debugging information, I haven't bothered to write a full
+ blown IEEE expression parser. I've only thrown in the things I've
+ seen in debugging information. This can be easily extended if
+ necessary. */
+
+static boolean
+ieee_read_expression (info, pp, pv)
+ struct ieee_info *info;
+ const bfd_byte **pp;
+ bfd_vma *pv;
+{
+ const bfd_byte *expr_start;
+#define EXPR_STACK_SIZE (10)
+ bfd_vma expr_stack[EXPR_STACK_SIZE];
+ bfd_vma *esp;
+
+ expr_start = *pp;
+
+ esp = expr_stack;
+
+ while (1)
+ {
+ const bfd_byte *start;
+ bfd_vma val;
+ boolean present;
+ ieee_record_enum_type c;
+
+ start = *pp;
+
+ if (! ieee_read_optional_number (info, pp, &val, &present))
+ return false;
+
+ if (present)
+ {
+ if (esp - expr_stack >= EXPR_STACK_SIZE)
+ {
+ ieee_error (info, start, "expression stack overflow");
+ return false;
+ }
+ *esp++ = val;
+ continue;
+ }
+
+ c = (ieee_record_enum_type) **pp;
+
+ if (c >= ieee_module_beginning_enum)
+ break;
+
+ ++*pp;
+
+ if (c == ieee_comma)
+ break;
+
+ switch (c)
+ {
+ default:
+ ieee_error (info, start, "unsupported IEEE expression operator");
+ break;
+
+ case ieee_variable_R_enum:
+ {
+ bfd_vma indx;
+ asection *s;
+
+ if (! ieee_read_number (info, pp, &indx))
+ return false;
+ for (s = info->abfd->sections; s != NULL; s = s->next)
+ if ((bfd_vma) s->target_index == indx)
+ break;
+ if (s == NULL)
+ {
+ ieee_error (info, start, "unknown section");
+ return false;
+ }
+
+ if (esp - expr_stack >= EXPR_STACK_SIZE)
+ {
+ ieee_error (info, start, "expression stack overflow");
+ return false;
+ }
+
+ *esp++ = bfd_get_section_vma (info->abfd, s);
+ }
+ break;
+
+ case ieee_function_plus_enum:
+ case ieee_function_minus_enum:
+ {
+ bfd_vma v1, v2;
+
+ if (esp - expr_stack < 2)
+ {
+ ieee_error (info, start, "expression stack underflow");
+ return false;
+ }
+
+ v1 = *--esp;
+ v2 = *--esp;
+ *esp++ = v1 + v2;
+ }
+ break;
+ }
+ }
+
+ if (esp - 1 != expr_stack)
+ {
+ ieee_error (info, expr_start, "expression stack mismatch");
+ return false;
+ }
+
+ *pv = *--esp;
+
+ return true;
+}
+
+/* Return an IEEE builtin type. */
+
+static debug_type
+ieee_builtin_type (info, p, indx)
+ struct ieee_info *info;
+ const bfd_byte *p;
+ unsigned int indx;
+{
+ PTR dhandle;
+ debug_type type;
+ const char *name;
+
+ if (indx < BUILTIN_TYPE_COUNT
+ && info->types.builtins[indx] != DEBUG_TYPE_NULL)
+ return info->types.builtins[indx];
+
+ dhandle = info->dhandle;
+
+ if (indx >= 32 && indx < 64)
+ {
+ type = debug_make_pointer_type (dhandle,
+ ieee_builtin_type (info, p, indx - 32));
+ assert (indx < BUILTIN_TYPE_COUNT);
+ info->types.builtins[indx] = type;
+ return type;
+ }
+
+ switch ((enum builtin_types) indx)
+ {
+ default:
+ ieee_error (info, p, "unknown builtin type");
+ return NULL;
+
+ case builtin_unknown:
+ type = debug_make_void_type (dhandle);
+ name = NULL;
+ break;
+
+ case builtin_void:
+ type = debug_make_void_type (dhandle);
+ name = "void";
+ break;
+
+ case builtin_signed_char:
+ type = debug_make_int_type (dhandle, 1, false);
+ name = "signed char";
+ break;
+
+ case builtin_unsigned_char:
+ type = debug_make_int_type (dhandle, 1, true);
+ name = "unsigned char";
+ break;
+
+ case builtin_signed_short_int:
+ type = debug_make_int_type (dhandle, 2, false);
+ name = "signed short int";
+ break;
+
+ case builtin_unsigned_short_int:
+ type = debug_make_int_type (dhandle, 2, true);
+ name = "unsigned short int";
+ break;
+
+ case builtin_signed_long:
+ type = debug_make_int_type (dhandle, 4, false);
+ name = "signed long";
+ break;
+
+ case builtin_unsigned_long:
+ type = debug_make_int_type (dhandle, 4, true);
+ name = "unsigned long";
+ break;
+
+ case builtin_signed_long_long:
+ type = debug_make_int_type (dhandle, 8, false);
+ name = "signed long long";
+ break;
+
+ case builtin_unsigned_long_long:
+ type = debug_make_int_type (dhandle, 8, true);
+ name = "unsigned long long";
+ break;
+
+ case builtin_float:
+ type = debug_make_float_type (dhandle, 4);
+ name = "float";
+ break;
+
+ case builtin_double:
+ type = debug_make_float_type (dhandle, 8);
+ name = "double";
+ break;
+
+ case builtin_long_double:
+ /* FIXME: The size for this type should depend upon the
+ processor. */
+ type = debug_make_float_type (dhandle, 12);
+ name = "long double";
+ break;
+
+ case builtin_long_long_double:
+ type = debug_make_float_type (dhandle, 16);
+ name = "long long double";
+ break;
+
+ case builtin_quoted_string:
+ type = debug_make_array_type (dhandle,
+ ieee_builtin_type (info, p,
+ ((unsigned int)
+ builtin_char)),
+ ieee_builtin_type (info, p,
+ ((unsigned int)
+ builtin_int)),
+ 0, -1, true);
+ name = "QUOTED STRING";
+ break;
+
+ case builtin_instruction_address:
+ /* FIXME: This should be a code address. */
+ type = debug_make_int_type (dhandle, 4, true);
+ name = "instruction address";
+ break;
+
+ case builtin_int:
+ /* FIXME: The size for this type should depend upon the
+ processor. */
+ type = debug_make_int_type (dhandle, 4, false);
+ name = "int";
+ break;
+
+ case builtin_unsigned:
+ /* FIXME: The size for this type should depend upon the
+ processor. */
+ type = debug_make_int_type (dhandle, 4, true);
+ name = "unsigned";
+ break;
+
+ case builtin_unsigned_int:
+ /* FIXME: The size for this type should depend upon the
+ processor. */
+ type = debug_make_int_type (dhandle, 4, true);
+ name = "unsigned int";
+ break;
+
+ case builtin_char:
+ type = debug_make_int_type (dhandle, 1, false);
+ name = "char";
+ break;
+
+ case builtin_long:
+ type = debug_make_int_type (dhandle, 4, false);
+ name = "long";
+ break;
+
+ case builtin_short:
+ type = debug_make_int_type (dhandle, 2, false);
+ name = "short";
+ break;
+
+ case builtin_unsigned_short:
+ type = debug_make_int_type (dhandle, 2, true);
+ name = "unsigned short";
+ break;
+
+ case builtin_short_int:
+ type = debug_make_int_type (dhandle, 2, false);
+ name = "short int";
+ break;
+
+ case builtin_signed_short:
+ type = debug_make_int_type (dhandle, 2, false);
+ name = "signed short";
+ break;
+
+ case builtin_bcd_float:
+ ieee_error (info, p, "BCD float type not supported");
+ return DEBUG_TYPE_NULL;
+ }
+
+ if (name != NULL)
+ type = debug_name_type (dhandle, name, type);
+
+ assert (indx < BUILTIN_TYPE_COUNT);
+
+ info->types.builtins[indx] = type;
+
+ return type;
+}
+
+/* Allocate more space in the type table. If ref is true, this is a
+ reference to the type; if it is not already defined, we should set
+ up an indirect type. */
+
+static boolean
+ieee_alloc_type (info, indx, ref)
+ struct ieee_info *info;
+ unsigned int indx;
+ boolean ref;
+{
+ unsigned int nalloc;
+ register struct ieee_type *t;
+ struct ieee_type *tend;
+
+ if (indx >= info->types.alloc)
+ {
+ nalloc = info->types.alloc;
+ if (nalloc == 0)
+ nalloc = 4;
+ while (indx >= nalloc)
+ nalloc *= 2;
+
+ info->types.types = ((struct ieee_type *)
+ xrealloc (info->types.types,
+ nalloc * sizeof *info->types.types));
+
+ memset (info->types.types + info->types.alloc, 0,
+ (nalloc - info->types.alloc) * sizeof *info->types.types);
+
+ tend = info->types.types + nalloc;
+ for (t = info->types.types + info->types.alloc; t < tend; t++)
+ t->type = DEBUG_TYPE_NULL;
+
+ info->types.alloc = nalloc;
+ }
+
+ if (ref)
+ {
+ t = info->types.types + indx;
+ if (t->type == NULL)
+ {
+ t->pslot = (debug_type *) xmalloc (sizeof *t->pslot);
+ *t->pslot = DEBUG_TYPE_NULL;
+ t->type = debug_make_indirect_type (info->dhandle, t->pslot,
+ (const char *) NULL);
+ if (t->type == NULL)
+ return false;
+ }
+ }
+
+ return true;
+}
+
+/* Read a type index and return the corresponding type. */
+
+static boolean
+ieee_read_type_index (info, pp, ptype)
+ struct ieee_info *info;
+ const bfd_byte **pp;
+ debug_type *ptype;
+{
+ const bfd_byte *start;
+ bfd_vma indx;
+
+ start = *pp;
+
+ if (! ieee_read_number (info, pp, &indx))
+ return false;
+
+ if (indx < 256)
+ {
+ *ptype = ieee_builtin_type (info, start, indx);
+ if (*ptype == NULL)
+ return false;
+ return true;
+ }
+
+ indx -= 256;
+ if (! ieee_alloc_type (info, indx, true))
+ return false;
+
+ *ptype = info->types.types[indx].type;
+
+ return true;
+}
+
+/* Parse IEEE debugging information for a file. This is passed the
+ bytes which compose the Debug Information Part of an IEEE file. */
+
+boolean
+parse_ieee (dhandle, abfd, bytes, len)
+ PTR dhandle;
+ bfd *abfd;
+ const bfd_byte *bytes;
+ bfd_size_type len;
+{
+ struct ieee_info info;
+ unsigned int i;
+ const bfd_byte *p, *pend;
+
+ info.dhandle = dhandle;
+ info.abfd = abfd;
+ info.bytes = bytes;
+ info.pend = bytes + len;
+ info.blockstack.bsp = info.blockstack.stack;
+ info.saw_filename = false;
+ info.vars.alloc = 0;
+ info.vars.vars = NULL;
+ info.types.alloc = 0;
+ info.types.types = NULL;
+ info.tags = NULL;
+ for (i = 0; i < BUILTIN_TYPE_COUNT; i++)
+ info.types.builtins[i] = DEBUG_TYPE_NULL;
+
+ p = bytes;
+ pend = info.pend;
+ while (p < pend)
+ {
+ const bfd_byte *record_start;
+ ieee_record_enum_type c;
+
+ record_start = p;
+
+ c = (ieee_record_enum_type) *p++;
+
+ if (c == ieee_at_record_enum)
+ c = (ieee_record_enum_type) (((unsigned int) c << 8) | *p++);
+
+ if (c <= ieee_number_repeat_end_enum)
+ {
+ ieee_error (&info, record_start, "unexpected number");
+ return false;
+ }
+
+ switch (c)
+ {
+ default:
+ ieee_error (&info, record_start, "unexpected record type");
+ return false;
+
+ case ieee_bb_record_enum:
+ if (! parse_ieee_bb (&info, &p))
+ return false;
+ break;
+
+ case ieee_be_record_enum:
+ if (! parse_ieee_be (&info, &p))
+ return false;
+ break;
+
+ case ieee_nn_record:
+ if (! parse_ieee_nn (&info, &p))
+ return false;
+ break;
+
+ case ieee_ty_record_enum:
+ if (! parse_ieee_ty (&info, &p))
+ return false;
+ break;
+
+ case ieee_atn_record_enum:
+ if (! parse_ieee_atn (&info, &p))
+ return false;
+ break;
+ }
+ }
+
+ if (info.blockstack.bsp != info.blockstack.stack)
+ {
+ ieee_error (&info, (const bfd_byte *) NULL,
+ "blocks left on stack at end");
+ return false;
+ }
+
+ return true;
+}
+
+/* Handle an IEEE BB record. */
+
+static boolean
+parse_ieee_bb (info, pp)
+ struct ieee_info *info;
+ const bfd_byte **pp;
+{
+ const bfd_byte *block_start;
+ bfd_byte b;
+ bfd_vma size;
+ const char *name;
+ unsigned long namlen;
+ char *namcopy = NULL;
+ unsigned int fnindx;
+ boolean skip;
+
+ block_start = *pp;
+
+ b = **pp;
+ ++*pp;
+
+ if (! ieee_read_number (info, pp, &size)
+ || ! ieee_read_id (info, pp, &name, &namlen))
+ return false;
+
+ fnindx = (unsigned int) -1;
+ skip = false;
+
+ switch (b)
+ {
+ case 1:
+ /* BB1: Type definitions local to a module. */
+ namcopy = savestring (name, namlen);
+ if (namcopy == NULL)
+ return false;
+ if (! debug_set_filename (info->dhandle, namcopy))
+ return false;
+ info->saw_filename = true;
+
+ /* Discard any variables or types we may have seen before. */
+ if (info->vars.vars != NULL)
+ free (info->vars.vars);
+ info->vars.vars = NULL;
+ info->vars.alloc = 0;
+ if (info->types.types != NULL)
+ free (info->types.types);
+ info->types.types = NULL;
+ info->types.alloc = 0;
+
+ /* Initialize the types to the global types. */
+ if (info->global_types != NULL)
+ {
+ info->types.alloc = info->global_types->alloc;
+ info->types.types = ((struct ieee_type *)
+ xmalloc (info->types.alloc
+ * sizeof (*info->types.types)));
+ memcpy (info->types.types, info->global_types->types,
+ info->types.alloc * sizeof (*info->types.types));
+ }
+
+ break;
+
+ case 2:
+ /* BB2: Global type definitions. The name is supposed to be
+ empty, but we don't check. */
+ if (! debug_set_filename (info->dhandle, "*global*"))
+ return false;
+ info->saw_filename = true;
+ break;
+
+ case 3:
+ /* BB3: High level module block begin. We don't have to do
+ anything here. The name is supposed to be the same as for
+ the BB1, but we don't check. */
+ break;
+
+ case 4:
+ /* BB4: Global function. */
+ {
+ bfd_vma stackspace, typindx, offset;
+ debug_type return_type;
+
+ if (! ieee_read_number (info, pp, &stackspace)
+ || ! ieee_read_number (info, pp, &typindx)
+ || ! ieee_read_expression (info, pp, &offset))
+ return false;
+
+ /* We have no way to record the stack space. FIXME. */
+
+ if (typindx < 256)
+ {
+ return_type = ieee_builtin_type (info, block_start, typindx);
+ if (return_type == DEBUG_TYPE_NULL)
+ return false;
+ }
+ else
+ {
+ typindx -= 256;
+ if (! ieee_alloc_type (info, typindx, true))
+ return false;
+ fnindx = typindx;
+ return_type = info->types.types[typindx].type;
+ if (debug_get_type_kind (info->dhandle, return_type)
+ == DEBUG_KIND_FUNCTION)
+ return_type = debug_get_return_type (info->dhandle,
+ return_type);
+ }
+
+ namcopy = savestring (name, namlen);
+ if (namcopy == NULL)
+ return false;
+ if (! debug_record_function (info->dhandle, namcopy, return_type,
+ true, offset))
+ return false;
+ }
+ break;
+
+ case 5:
+ /* BB5: File name for source line numbers. */
+ {
+ unsigned int i;
+
+ /* We ignore the date and time. FIXME. */
+ for (i = 0; i < 6; i++)
+ {
+ bfd_vma ignore;
+ boolean present;
+
+ if (! ieee_read_optional_number (info, pp, &ignore, &present))
+ return false;
+ if (! present)
+ break;
+ }
+
+ namcopy = savestring (name, namlen);
+ if (namcopy == NULL)
+ return false;
+ if (! debug_start_source (info->dhandle, namcopy))
+ return false;
+ }
+ break;
+
+ case 6:
+ /* BB6: Local function or block. */
+ {
+ bfd_vma stackspace, typindx, offset;
+
+ if (! ieee_read_number (info, pp, &stackspace)
+ || ! ieee_read_number (info, pp, &typindx)
+ || ! ieee_read_expression (info, pp, &offset))
+ return false;
+
+ /* We have no way to record the stack space. FIXME. */
+
+ if (namlen == 0)
+ {
+ if (! debug_start_block (info->dhandle, offset))
+ return false;
+ /* Change b to indicate that this is a block
+ rather than a function. */
+ b = 0x86;
+ }
+ else
+ {
+ /* The MRI C++ compiler will output a fake function named
+ __XRYCPP to hold C++ debugging information. We skip
+ that function. This is not crucial, but it makes
+ converting from IEEE to other debug formats work
+ better. */
+ if (strncmp (name, "__XRYCPP", namlen) == 0)
+ skip = true;
+ else
+ {
+ debug_type return_type;
+
+ if (typindx < 256)
+ {
+ return_type = ieee_builtin_type (info, block_start,
+ typindx);
+ if (return_type == NULL)
+ return false;
+ }
+ else
+ {
+ typindx -= 256;
+ if (! ieee_alloc_type (info, typindx, true))
+ return false;
+ fnindx = typindx;
+ return_type = info->types.types[typindx].type;
+ if (debug_get_type_kind (info->dhandle, return_type)
+ == DEBUG_KIND_FUNCTION)
+ return_type = debug_get_return_type (info->dhandle,
+ return_type);
+ }
+
+ namcopy = savestring (name, namlen);
+ if (namcopy == NULL)
+ return false;
+ if (! debug_record_function (info->dhandle, namcopy,
+ return_type, false, offset))
+ return false;
+ }
+ }
+ }
+ break;
+
+ case 10:
+ /* BB10: Assembler module scope. In the normal case, we
+ completely ignore all this information. FIXME. */
+ {
+ const char *inam, *vstr;
+ unsigned long inamlen, vstrlen;
+ bfd_vma tool_type;
+ boolean present;
+ unsigned int i;
+
+ if (! info->saw_filename)
+ {
+ namcopy = savestring (name, namlen);
+ if (namcopy == NULL)
+ return false;
+ if (! debug_set_filename (info->dhandle, namcopy))
+ return false;
+ info->saw_filename = true;
+ }
+
+ if (! ieee_read_id (info, pp, &inam, &inamlen)
+ || ! ieee_read_number (info, pp, &tool_type)
+ || ! ieee_read_optional_id (info, pp, &vstr, &vstrlen, &present))
+ return false;
+ for (i = 0; i < 6; i++)
+ {
+ bfd_vma ignore;
+
+ if (! ieee_read_optional_number (info, pp, &ignore, &present))
+ return false;
+ if (! present)
+ break;
+ }
+ }
+ break;
+
+ case 11:
+ /* BB11: Module section. We completely ignore all this
+ information. FIXME. */
+ {
+ bfd_vma sectype, secindx, offset, map;
+ boolean present;
+
+ if (! ieee_read_number (info, pp, &sectype)
+ || ! ieee_read_number (info, pp, &secindx)
+ || ! ieee_read_expression (info, pp, &offset)
+ || ! ieee_read_optional_number (info, pp, &map, &present))
+ return false;
+ }
+ break;
+
+ default:
+ ieee_error (info, block_start, "unknown BB type");
+ return false;
+ }
+
+
+ /* Push this block on the block stack. */
+
+ if (info->blockstack.bsp >= info->blockstack.stack + BLOCKSTACK_SIZE)
+ {
+ ieee_error (info, (const bfd_byte *) NULL, "stack overflow");
+ return false;
+ }
+
+ info->blockstack.bsp->kind = b;
+ if (b == 5)
+ info->blockstack.bsp->filename = namcopy;
+ info->blockstack.bsp->fnindx = fnindx;
+ info->blockstack.bsp->skip = skip;
+ ++info->blockstack.bsp;
+
+ return true;
+}
+
+/* Handle an IEEE BE record. */
+
+static boolean
+parse_ieee_be (info, pp)
+ struct ieee_info *info;
+ const bfd_byte **pp;
+{
+ bfd_vma offset;
+
+ if (info->blockstack.bsp <= info->blockstack.stack)
+ {
+ ieee_error (info, *pp, "stack underflow");
+ return false;
+ }
+ --info->blockstack.bsp;
+
+ switch (info->blockstack.bsp->kind)
+ {
+ case 2:
+ /* When we end the global typedefs block, we copy out the the
+ contents of info->vars. This is because the variable indices
+ may be reused in the local blocks. However, we need to
+ preserve them so that we can locate a function returning a
+ reference variable whose type is named in the global typedef
+ block. */
+ info->global_vars = ((struct ieee_vars *)
+ xmalloc (sizeof *info->global_vars));
+ info->global_vars->alloc = info->vars.alloc;
+ info->global_vars->vars = ((struct ieee_var *)
+ xmalloc (info->vars.alloc
+ * sizeof (*info->vars.vars)));
+ memcpy (info->global_vars->vars, info->vars.vars,
+ info->vars.alloc * sizeof (*info->vars.vars));
+
+ /* We also copy out the non builtin parts of info->types, since
+ the types are discarded when we start a new block. */
+ info->global_types = ((struct ieee_types *)
+ xmalloc (sizeof *info->global_types));
+ info->global_types->alloc = info->types.alloc;
+ info->global_types->types = ((struct ieee_type *)
+ xmalloc (info->types.alloc
+ * sizeof (*info->types.types)));
+ memcpy (info->global_types->types, info->types.types,
+ info->types.alloc * sizeof (*info->types.types));
+ memset (info->global_types->builtins, 0,
+ sizeof (info->global_types->builtins));
+
+ break;
+
+ case 4:
+ case 6:
+ if (! ieee_read_expression (info, pp, &offset))
+ return false;
+ if (! info->blockstack.bsp->skip)
+ {
+ if (! debug_end_function (info->dhandle, offset + 1))
+ return false;
+ }
+ break;
+
+ case 0x86:
+ /* This is BE6 when BB6 started a block rather than a local
+ function. */
+ if (! ieee_read_expression (info, pp, &offset))
+ return false;
+ if (! debug_end_block (info->dhandle, offset + 1))
+ return false;
+ break;
+
+ case 5:
+ /* When we end a BB5, we look up the stack for the last BB5, if
+ there is one, so that we can call debug_start_source. */
+ if (info->blockstack.bsp > info->blockstack.stack)
+ {
+ struct ieee_block *bl;
+
+ bl = info->blockstack.bsp;
+ do
+ {
+ --bl;
+ if (bl->kind == 5)
+ {
+ if (! debug_start_source (info->dhandle, bl->filename))
+ return false;
+ break;
+ }
+ }
+ while (bl != info->blockstack.stack);
+ }
+ break;
+
+ case 11:
+ if (! ieee_read_expression (info, pp, &offset))
+ return false;
+ /* We just ignore the module size. FIXME. */
+ break;
+
+ default:
+ /* Other block types do not have any trailing information. */
+ break;
+ }
+
+ return true;
+}
+
+/* Parse an NN record. */
+
+static boolean
+parse_ieee_nn (info, pp)
+ struct ieee_info *info;
+ const bfd_byte **pp;
+{
+ const bfd_byte *nn_start;
+ bfd_vma varindx;
+ const char *name;
+ unsigned long namlen;
+
+ nn_start = *pp;
+
+ if (! ieee_read_number (info, pp, &varindx)
+ || ! ieee_read_id (info, pp, &name, &namlen))
+ return false;
+
+ if (varindx < 32)
+ {
+ ieee_error (info, nn_start, "illegal variable index");
+ return false;
+ }
+ varindx -= 32;
+
+ if (varindx >= info->vars.alloc)
+ {
+ unsigned int alloc;
+
+ alloc = info->vars.alloc;
+ if (alloc == 0)
+ alloc = 4;
+ while (varindx >= alloc)
+ alloc *= 2;
+ info->vars.vars = ((struct ieee_var *)
+ xrealloc (info->vars.vars,
+ alloc * sizeof *info->vars.vars));
+ memset (info->vars.vars + info->vars.alloc, 0,
+ (alloc - info->vars.alloc) * sizeof *info->vars.vars);
+ info->vars.alloc = alloc;
+ }
+
+ info->vars.vars[varindx].name = name;
+ info->vars.vars[varindx].namlen = namlen;
+
+ return true;
+}
+
+/* Parse a TY record. */
+
+static boolean
+parse_ieee_ty (info, pp)
+ struct ieee_info *info;
+ const bfd_byte **pp;
+{
+ const bfd_byte *ty_start, *ty_var_start, *ty_code_start;
+ bfd_vma typeindx, varindx, tc;
+ PTR dhandle;
+ boolean tag, typdef;
+ debug_type *arg_slots;
+ unsigned long type_bitsize;
+ debug_type type;
+
+ ty_start = *pp;
+
+ if (! ieee_read_number (info, pp, &typeindx))
+ return false;
+
+ if (typeindx < 256)
+ {
+ ieee_error (info, ty_start, "illegal type index");
+ return false;
+ }
+
+ typeindx -= 256;
+ if (! ieee_alloc_type (info, typeindx, false))
+ return false;
+
+ if (**pp != 0xce)
+ {
+ ieee_error (info, *pp, "unknown TY code");
+ return false;
+ }
+ ++*pp;
+
+ ty_var_start = *pp;
+
+ if (! ieee_read_number (info, pp, &varindx))
+ return false;
+
+ if (varindx < 32)
+ {
+ ieee_error (info, ty_var_start, "illegal variable index");
+ return false;
+ }
+ varindx -= 32;
+
+ if (varindx >= info->vars.alloc || info->vars.vars[varindx].name == NULL)
+ {
+ ieee_error (info, ty_var_start, "undefined variable in TY");
+ return false;
+ }
+
+ ty_code_start = *pp;
+
+ if (! ieee_read_number (info, pp, &tc))
+ return false;
+
+ dhandle = info->dhandle;
+
+ tag = false;
+ typdef = false;
+ arg_slots = NULL;
+ type_bitsize = 0;
+ switch (tc)
+ {
+ default:
+ ieee_error (info, ty_code_start, "unknown TY code");
+ return false;
+
+ case '!':
+ /* Unknown type, with size. We treat it as int. FIXME. */
+ {
+ bfd_vma size;
+
+ if (! ieee_read_number (info, pp, &size))
+ return false;
+ type = debug_make_int_type (dhandle, size, false);
+ }
+ break;
+
+ case 'A': /* Array. */
+ case 'a': /* FORTRAN array in column/row order. FIXME: Not
+ distinguished from normal array. */
+ {
+ debug_type ele_type;
+ bfd_vma lower, upper;
+
+ if (! ieee_read_type_index (info, pp, &ele_type)
+ || ! ieee_read_number (info, pp, &lower)
+ || ! ieee_read_number (info, pp, &upper))
+ return false;
+ type = debug_make_array_type (dhandle, ele_type,
+ ieee_builtin_type (info, ty_code_start,
+ ((unsigned int)
+ builtin_int)),
+ (bfd_signed_vma) lower,
+ (bfd_signed_vma) upper,
+ false);
+ }
+ break;
+
+ case 'E':
+ /* Simple enumeration. */
+ {
+ bfd_vma size;
+ unsigned int alloc;
+ const char **names;
+ unsigned int c;
+ bfd_signed_vma *vals;
+ unsigned int i;
+
+ if (! ieee_read_number (info, pp, &size))
+ return false;
+ /* FIXME: we ignore the enumeration size. */
+
+ alloc = 10;
+ names = (const char **) xmalloc (alloc * sizeof *names);
+ memset (names, 0, alloc * sizeof *names);
+ c = 0;
+ while (1)
+ {
+ const char *name;
+ unsigned long namlen;
+ boolean present;
+
+ if (! ieee_read_optional_id (info, pp, &name, &namlen, &present))
+ return false;
+ if (! present)
+ break;
+
+ if (c + 1 >= alloc)
+ {
+ alloc += 10;
+ names = ((const char **)
+ xrealloc (names, alloc * sizeof *names));
+ }
+
+ names[c] = savestring (name, namlen);
+ if (names[c] == NULL)
+ return false;
+ ++c;
+ }
+
+ names[c] = NULL;
+
+ vals = (bfd_signed_vma *) xmalloc (c * sizeof *vals);
+ for (i = 0; i < c; i++)
+ vals[i] = i;
+
+ type = debug_make_enum_type (dhandle, names, vals);
+ tag = true;
+ }
+ break;
+
+ case 'G':
+ /* Struct with bit fields. */
+ {
+ bfd_vma size;
+ unsigned int alloc;
+ debug_field *fields;
+ unsigned int c;
+
+ if (! ieee_read_number (info, pp, &size))
+ return false;
+
+ alloc = 10;
+ fields = (debug_field *) xmalloc (alloc * sizeof *fields);
+ c = 0;
+ while (1)
+ {
+ const char *name;
+ unsigned long namlen;
+ boolean present;
+ debug_type ftype;
+ bfd_vma bitpos, bitsize;
+
+ if (! ieee_read_optional_id (info, pp, &name, &namlen, &present))
+ return false;
+ if (! present)
+ break;
+ if (! ieee_read_type_index (info, pp, &ftype)
+ || ! ieee_read_number (info, pp, &bitpos)
+ || ! ieee_read_number (info, pp, &bitsize))
+ return false;
+
+ if (c + 1 >= alloc)
+ {
+ alloc += 10;
+ fields = ((debug_field *)
+ xrealloc (fields, alloc * sizeof *fields));
+ }
+
+ fields[c] = debug_make_field (dhandle, savestring (name, namlen),
+ ftype, bitpos, bitsize,
+ DEBUG_VISIBILITY_PUBLIC);
+ if (fields[c] == NULL)
+ return false;
+ ++c;
+ }
+
+ fields[c] = NULL;
+
+ type = debug_make_struct_type (dhandle, true, size, fields);
+ tag = true;
+ }
+ break;
+
+ case 'N':
+ /* Enumeration. */
+ {
+ unsigned int alloc;
+ const char **names;
+ bfd_signed_vma *vals;
+ unsigned int c;
+
+ alloc = 10;
+ names = (const char **) xmalloc (alloc * sizeof *names);
+ vals = (bfd_signed_vma *) xmalloc (alloc * sizeof *names);
+ c = 0;
+ while (1)
+ {
+ const char *name;
+ unsigned long namlen;
+ boolean present;
+ bfd_vma val;
+
+ if (! ieee_read_optional_id (info, pp, &name, &namlen, &present))
+ return false;
+ if (! present)
+ break;
+ if (! ieee_read_number (info, pp, &val))
+ return false;
+
+ /* If the length of the name is zero, then the value is
+ actually the size of the enum. We ignore this
+ information. FIXME. */
+ if (namlen == 0)
+ continue;
+
+ if (c + 1 >= alloc)
+ {
+ alloc += 10;
+ names = ((const char **)
+ xrealloc (names, alloc * sizeof *names));
+ vals = ((bfd_signed_vma *)
+ xrealloc (vals, alloc * sizeof *vals));
+ }
+
+ names[c] = savestring (name, namlen);
+ if (names[c] == NULL)
+ return false;
+ vals[c] = (bfd_signed_vma) val;
+ ++c;
+ }
+
+ names[c] = NULL;
+
+ type = debug_make_enum_type (dhandle, names, vals);
+ tag = true;
+ }
+ break;
+
+ case 'O': /* Small pointer. We don't distinguish small and large
+ pointers. FIXME. */
+ case 'P': /* Large pointer. */
+ {
+ debug_type t;
+
+ if (! ieee_read_type_index (info, pp, &t))
+ return false;
+ type = debug_make_pointer_type (dhandle, t);
+ }
+ break;
+
+ case 'R':
+ /* Range. */
+ {
+ bfd_vma low, high, signedp, size;
+
+ if (! ieee_read_number (info, pp, &low)
+ || ! ieee_read_number (info, pp, &high)
+ || ! ieee_read_number (info, pp, &signedp)
+ || ! ieee_read_number (info, pp, &size))
+ return false;
+
+ type = debug_make_range_type (dhandle,
+ debug_make_int_type (dhandle, size,
+ ! signedp),
+ (bfd_signed_vma) low,
+ (bfd_signed_vma) high);
+ }
+ break;
+
+ case 'S': /* Struct. */
+ case 'U': /* Union. */
+ {
+ bfd_vma size;
+ unsigned int alloc;
+ debug_field *fields;
+ unsigned int c;
+
+ if (! ieee_read_number (info, pp, &size))
+ return false;
+
+ alloc = 10;
+ fields = (debug_field *) xmalloc (alloc * sizeof *fields);
+ c = 0;
+ while (1)
+ {
+ const char *name;
+ unsigned long namlen;
+ boolean present;
+ bfd_vma tindx;
+ bfd_vma offset;
+ debug_type ftype;
+ bfd_vma bitsize;
+
+ if (! ieee_read_optional_id (info, pp, &name, &namlen, &present))
+ return false;
+ if (! present)
+ break;
+ if (! ieee_read_number (info, pp, &tindx)
+ || ! ieee_read_number (info, pp, &offset))
+ return false;
+
+ if (tindx < 256)
+ {
+ ftype = ieee_builtin_type (info, ty_code_start, tindx);
+ bitsize = 0;
+ offset *= 8;
+ }
+ else
+ {
+ struct ieee_type *t;
+
+ tindx -= 256;
+ if (! ieee_alloc_type (info, tindx, true))
+ return false;
+ t = info->types.types + tindx;
+ ftype = t->type;
+ bitsize = t->bitsize;
+ if (bitsize == 0)
+ offset *= 8;
+ }
+
+ if (c + 1 >= alloc)
+ {
+ alloc += 10;
+ fields = ((debug_field *)
+ xrealloc (fields, alloc * sizeof *fields));
+ }
+
+ fields[c] = debug_make_field (dhandle, savestring (name, namlen),
+ ftype, offset, bitsize,
+ DEBUG_VISIBILITY_PUBLIC);
+ if (fields[c] == NULL)
+ return false;
+ ++c;
+ }
+
+ fields[c] = NULL;
+
+ type = debug_make_struct_type (dhandle, tc == 'S', size, fields);
+ tag = true;
+ }
+ break;
+
+ case 'T':
+ /* Typedef. */
+ if (! ieee_read_type_index (info, pp, &type))
+ return false;
+ typdef = true;
+ break;
+
+ case 'X':
+ /* Procedure. FIXME: This is an extern declaration, which we
+ have no way of representing. */
+ {
+ bfd_vma attr;
+ debug_type rtype;
+ bfd_vma nargs;
+ boolean present;
+ struct ieee_var *pv;
+
+ /* FIXME: We ignore the attribute and the argument names. */
+
+ if (! ieee_read_number (info, pp, &attr)
+ || ! ieee_read_type_index (info, pp, &rtype)
+ || ! ieee_read_number (info, pp, &nargs))
+ return false;
+ do
+ {
+ const char *name;
+ unsigned long namlen;
+
+ if (! ieee_read_optional_id (info, pp, &name, &namlen, &present))
+ return false;
+ }
+ while (present);
+
+ pv = info->vars.vars + varindx;
+ pv->kind = IEEE_EXTERNAL;
+ if (pv->namlen > 0
+ && debug_get_type_kind (dhandle, rtype) == DEBUG_KIND_POINTER)
+ {
+ /* Set up the return type as an indirect type pointing to
+ the variable slot, so that we can change it to a
+ reference later if appropriate. */
+ pv->pslot = (debug_type *) xmalloc (sizeof *pv->pslot);
+ *pv->pslot = rtype;
+ rtype = debug_make_indirect_type (dhandle, pv->pslot,
+ (const char *) NULL);
+ }
+
+ type = debug_make_function_type (dhandle, rtype, (debug_type *) NULL,
+ false);
+ }
+ break;
+
+ case 'V':
+ /* Void. This is not documented, but the MRI compiler emits it. */
+ type = debug_make_void_type (dhandle);
+ break;
+
+ case 'Z':
+ /* Array with 0 lower bound. */
+ {
+ debug_type etype;
+ bfd_vma high;
+
+ if (! ieee_read_type_index (info, pp, &etype)
+ || ! ieee_read_number (info, pp, &high))
+ return false;
+
+ type = debug_make_array_type (dhandle, etype,
+ ieee_builtin_type (info, ty_code_start,
+ ((unsigned int)
+ builtin_int)),
+ 0, (bfd_signed_vma) high, false);
+ }
+ break;
+
+ case 'c': /* Complex. */
+ case 'd': /* Double complex. */
+ {
+ const char *name;
+ unsigned long namlen;
+
+ /* FIXME: I don't know what the name means. */
+
+ if (! ieee_read_id (info, pp, &name, &namlen))
+ return false;
+
+ type = debug_make_complex_type (dhandle, tc == 'c' ? 4 : 8);
+ }
+ break;
+
+ case 'f':
+ /* Pascal file name. FIXME. */
+ ieee_error (info, ty_code_start, "Pascal file name not supported");
+ return false;
+
+ case 'g':
+ /* Bitfield type. */
+ {
+ bfd_vma signedp, bitsize, dummy;
+ const bfd_byte *hold;
+ boolean present;
+
+ if (! ieee_read_number (info, pp, &signedp)
+ || ! ieee_read_number (info, pp, &bitsize))
+ return false;
+
+ /* I think the documentation says that there is a type index,
+ but some actual files do not have one. */
+ hold = *pp;
+ if (! ieee_read_optional_number (info, pp, &dummy, &present))
+ return false;
+ if (! present)
+ {
+ /* FIXME: This is just a guess. */
+ type = debug_make_int_type (dhandle, 4,
+ signedp ? false : true);
+ }
+ else
+ {
+ *pp = hold;
+ if (! ieee_read_type_index (info, pp, &type))
+ return false;
+ }
+ type_bitsize = bitsize;
+ }
+ break;
+
+ case 'n':
+ /* Qualifier. */
+ {
+ bfd_vma kind;
+ debug_type t;
+
+ if (! ieee_read_number (info, pp, &kind)
+ || ! ieee_read_type_index (info, pp, &t))
+ return false;
+
+ switch (kind)
+ {
+ default:
+ ieee_error (info, ty_start, "unsupported qualifer");
+ return false;
+
+ case 1:
+ type = debug_make_const_type (dhandle, t);
+ break;
+
+ case 2:
+ type = debug_make_volatile_type (dhandle, t);
+ break;
+ }
+ }
+ break;
+
+ case 's':
+ /* Set. */
+ {
+ bfd_vma size;
+ debug_type etype;
+
+ if (! ieee_read_number (info, pp, &size)
+ || ! ieee_read_type_index (info, pp, &etype))
+ return false;
+
+ /* FIXME: We ignore the size. */
+
+ type = debug_make_set_type (dhandle, etype, false);
+ }
+ break;
+
+ case 'x':
+ /* Procedure with compiler dependencies. */
+ {
+ struct ieee_var *pv;
+ bfd_vma attr, frame_type, push_mask, nargs, level, father;
+ debug_type rtype;
+ debug_type *arg_types;
+ boolean varargs;
+ boolean present;
+
+ /* FIXME: We ignore some of this information. */
+
+ pv = info->vars.vars + varindx;
+
+ if (! ieee_read_number (info, pp, &attr)
+ || ! ieee_read_number (info, pp, &frame_type)
+ || ! ieee_read_number (info, pp, &push_mask)
+ || ! ieee_read_type_index (info, pp, &rtype)
+ || ! ieee_read_number (info, pp, &nargs))
+ return false;
+ if (nargs == (bfd_vma) -1)
+ {
+ arg_types = NULL;
+ varargs = false;
+ }
+ else
+ {
+ unsigned int i;
+
+ arg_types = ((debug_type *)
+ xmalloc ((nargs + 1) * sizeof *arg_types));
+ for (i = 0; i < nargs; i++)
+ if (! ieee_read_type_index (info, pp, arg_types + i))
+ return false;
+
+ /* If the last type is pointer to void, this is really a
+ varargs function. */
+ varargs = false;
+ if (nargs > 0)
+ {
+ debug_type last;
+
+ last = arg_types[nargs - 1];
+ if (debug_get_type_kind (dhandle, last) == DEBUG_KIND_POINTER
+ && (debug_get_type_kind (dhandle,
+ debug_get_target_type (dhandle,
+ last))
+ == DEBUG_KIND_VOID))
+ {
+ --nargs;
+ varargs = true;
+ }
+ }
+
+ /* If there are any pointer arguments, turn them into
+ indirect types in case we later need to convert them to
+ reference types. */
+ for (i = 0; i < nargs; i++)
+ {
+ if (debug_get_type_kind (dhandle, arg_types[i])
+ == DEBUG_KIND_POINTER)
+ {
+ if (arg_slots == NULL)
+ {
+ arg_slots = ((debug_type *)
+ xmalloc (nargs * sizeof *arg_slots));
+ memset (arg_slots, 0, nargs * sizeof *arg_slots);
+ }
+ arg_slots[i] = arg_types[i];
+ arg_types[i] =
+ debug_make_indirect_type (dhandle,
+ arg_slots + i,
+ (const char *) NULL);
+ }
+ }
+
+ arg_types[nargs] = DEBUG_TYPE_NULL;
+ }
+ if (! ieee_read_number (info, pp, &level)
+ || ! ieee_read_optional_number (info, pp, &father, &present))
+ return false;
+
+ /* We can't distinguish between a global function and a static
+ function. */
+ pv->kind = IEEE_FUNCTION;
+
+ if (pv->namlen > 0
+ && debug_get_type_kind (dhandle, rtype) == DEBUG_KIND_POINTER)
+ {
+ /* Set up the return type as an indirect type pointing to
+ the variable slot, so that we can change it to a
+ reference later if appropriate. */
+ pv->pslot = (debug_type *) xmalloc (sizeof *pv->pslot);
+ *pv->pslot = rtype;
+ rtype = debug_make_indirect_type (dhandle, pv->pslot,
+ (const char *) NULL);
+ }
+
+ type = debug_make_function_type (dhandle, rtype, arg_types, varargs);
+ }
+ break;
+ }
+
+ /* Record the type in the table. */
+
+ if (type == DEBUG_TYPE_NULL)
+ return false;
+
+ info->vars.vars[varindx].type = type;
+
+ if ((tag || typdef)
+ && info->vars.vars[varindx].namlen > 0)
+ {
+ const char *name;
+
+ name = savestring (info->vars.vars[varindx].name,
+ info->vars.vars[varindx].namlen);
+ if (typdef)
+ type = debug_name_type (dhandle, name, type);
+ else if (tc == 'E' || tc == 'N')
+ type = debug_tag_type (dhandle, name, type);
+ else
+ {
+ struct ieee_tag *it;
+
+ /* We must allocate all struct tags as indirect types, so
+ that if we later see a definition of the tag as a C++
+ record we can update the indirect slot and automatically
+ change all the existing references. */
+ it = (struct ieee_tag *) xmalloc (sizeof *it);
+ memset (it, 0, sizeof *it);
+ it->next = info->tags;
+ info->tags = it;
+ it->name = name;
+ it->slot = type;
+
+ type = debug_make_indirect_type (dhandle, &it->slot, name);
+ type = debug_tag_type (dhandle, name, type);
+
+ it->type = type;
+ }
+ if (type == NULL)
+ return false;
+ }
+
+ info->types.types[typeindx].type = type;
+ info->types.types[typeindx].arg_slots = arg_slots;
+ info->types.types[typeindx].bitsize = type_bitsize;
+
+ /* We may have already allocated type as an indirect type pointing
+ to slot. It does no harm to replace the indirect type with the
+ real type. Filling in slot as well handles the indirect types
+ which are already hanging around. */
+ if (info->types.types[typeindx].pslot != NULL)
+ *info->types.types[typeindx].pslot = type;
+
+ return true;
+}
+
+/* Parse an ATN record. */
+
+static boolean
+parse_ieee_atn (info, pp)
+ struct ieee_info *info;
+ const bfd_byte **pp;
+{
+ const bfd_byte *atn_start, *atn_code_start;
+ bfd_vma varindx;
+ struct ieee_var *pvar;
+ debug_type type;
+ bfd_vma atn_code;
+ PTR dhandle;
+ bfd_vma v, v2, v3, v4, v5;
+ const char *name;
+ unsigned long namlen;
+ char *namcopy;
+ boolean present;
+ int blocktype;
+
+ atn_start = *pp;
+
+ if (! ieee_read_number (info, pp, &varindx)
+ || ! ieee_read_type_index (info, pp, &type))
+ return false;
+
+ atn_code_start = *pp;
+
+ if (! ieee_read_number (info, pp, &atn_code))
+ return false;
+
+ if (varindx == 0)
+ {
+ pvar = NULL;
+ name = "";
+ namlen = 0;
+ }
+ else if (varindx < 32)
+ {
+ ieee_error (info, atn_start, "illegal variable index");
+ return false;
+ }
+ else
+ {
+ varindx -= 32;
+ if (varindx >= info->vars.alloc
+ || info->vars.vars[varindx].name == NULL)
+ {
+ /* The MRI compiler or linker sometimes omits the NN record
+ for a pmisc record. */
+ if (atn_code == 62)
+ {
+ if (varindx >= info->vars.alloc)
+ {
+ unsigned int alloc;
+
+ alloc = info->vars.alloc;
+ if (alloc == 0)
+ alloc = 4;
+ while (varindx >= alloc)
+ alloc *= 2;
+ info->vars.vars = ((struct ieee_var *)
+ xrealloc (info->vars.vars,
+ (alloc
+ * sizeof *info->vars.vars)));
+ memset (info->vars.vars + info->vars.alloc, 0,
+ ((alloc - info->vars.alloc)
+ * sizeof *info->vars.vars));
+ info->vars.alloc = alloc;
+ }
+
+ pvar = info->vars.vars + varindx;
+ pvar->name = "";
+ pvar->namlen = 0;
+ }
+ else
+ {
+ ieee_error (info, atn_start, "undefined variable in ATN");
+ return false;
+ }
+ }
+
+ pvar = info->vars.vars + varindx;
+
+ pvar->type = type;
+
+ name = pvar->name;
+ namlen = pvar->namlen;
+ }
+
+ dhandle = info->dhandle;
+
+ /* If we are going to call debug_record_variable with a pointer
+ type, change the type to an indirect type so that we can later
+ change it to a reference type if we encounter a C++ pmisc 'R'
+ record. */
+ if (pvar != NULL
+ && type != DEBUG_TYPE_NULL
+ && debug_get_type_kind (dhandle, type) == DEBUG_KIND_POINTER)
+ {
+ switch (atn_code)
+ {
+ case 1:
+ case 2:
+ case 3:
+ case 5:
+ case 8:
+ case 10:
+ pvar->pslot = (debug_type *) xmalloc (sizeof *pvar->pslot);
+ *pvar->pslot = type;
+ type = debug_make_indirect_type (dhandle, pvar->pslot,
+ (const char *) NULL);
+ pvar->type = type;
+ break;
+ }
+ }
+
+ switch (atn_code)
+ {
+ default:
+ ieee_error (info, atn_code_start, "unknown ATN type");
+ return false;
+
+ case 1:
+ /* Automatic variable. */
+ if (! ieee_read_number (info, pp, &v))
+ return false;
+ namcopy = savestring (name, namlen);
+ if (type == NULL)
+ type = debug_make_void_type (dhandle);
+ if (pvar != NULL)
+ pvar->kind = IEEE_LOCAL;
+ return debug_record_variable (dhandle, namcopy, type, DEBUG_LOCAL, v);
+
+ case 2:
+ /* Register variable. */
+ if (! ieee_read_number (info, pp, &v))
+ return false;
+ namcopy = savestring (name, namlen);
+ if (type == NULL)
+ type = debug_make_void_type (dhandle);
+ if (pvar != NULL)
+ pvar->kind = IEEE_LOCAL;
+ return debug_record_variable (dhandle, namcopy, type, DEBUG_REGISTER,
+ ieee_regno_to_genreg (info->abfd, v));
+
+ case 3:
+ /* Static variable. */
+ if (! ieee_require_asn (info, pp, &v))
+ return false;
+ namcopy = savestring (name, namlen);
+ if (type == NULL)
+ type = debug_make_void_type (dhandle);
+ if (info->blockstack.bsp <= info->blockstack.stack)
+ blocktype = 0;
+ else
+ blocktype = info->blockstack.bsp[-1].kind;
+ if (pvar != NULL)
+ {
+ if (blocktype == 4 || blocktype == 6)
+ pvar->kind = IEEE_LOCAL;
+ else
+ pvar->kind = IEEE_STATIC;
+ }
+ return debug_record_variable (dhandle, namcopy, type,
+ (blocktype == 4 || blocktype == 6
+ ? DEBUG_LOCAL_STATIC
+ : DEBUG_STATIC),
+ v);
+
+ case 4:
+ /* External function. We don't currently record these. FIXME. */
+ if (pvar != NULL)
+ pvar->kind = IEEE_EXTERNAL;
+ return true;
+
+ case 5:
+ /* External variable. We don't currently record these. FIXME. */
+ if (pvar != NULL)
+ pvar->kind = IEEE_EXTERNAL;
+ return true;
+
+ case 7:
+ if (! ieee_read_number (info, pp, &v)
+ || ! ieee_read_number (info, pp, &v2)
+ || ! ieee_read_optional_number (info, pp, &v3, &present))
+ return false;
+ if (present)
+ {
+ if (! ieee_read_optional_number (info, pp, &v4, &present))
+ return false;
+ }
+
+ /* We just ignore the two optional fields in v3 and v4, since
+ they are not defined. */
+
+ if (! ieee_require_asn (info, pp, &v3))
+ return false;
+
+ /* We have no way to record the column number. FIXME. */
+
+ return debug_record_line (dhandle, v, v3);
+
+ case 8:
+ /* Global variable. */
+ if (! ieee_require_asn (info, pp, &v))
+ return false;
+ namcopy = savestring (name, namlen);
+ if (type == NULL)
+ type = debug_make_void_type (dhandle);
+ if (pvar != NULL)
+ pvar->kind = IEEE_GLOBAL;
+ return debug_record_variable (dhandle, namcopy, type, DEBUG_GLOBAL, v);
+
+ case 9:
+ /* Variable lifetime information. */
+ if (! ieee_read_number (info, pp, &v))
+ return false;
+
+ /* We have no way to record this information. FIXME. */
+ return true;
+
+ case 10:
+ /* Locked register. The spec says that there are two required
+ fields, but at least on occasion the MRI compiler only emits
+ one. */
+ if (! ieee_read_number (info, pp, &v)
+ || ! ieee_read_optional_number (info, pp, &v2, &present))
+ return false;
+
+ /* I think this means a variable that is both in a register and
+ a frame slot. We ignore the frame slot. FIXME. */
+
+ namcopy = savestring (name, namlen);
+ if (type == NULL)
+ type = debug_make_void_type (dhandle);
+ if (pvar != NULL)
+ pvar->kind = IEEE_LOCAL;
+ return debug_record_variable (dhandle, namcopy, type, DEBUG_REGISTER, v);
+
+ case 11:
+ /* Reserved for FORTRAN common. */
+ ieee_error (info, atn_code_start, "unsupported ATN11");
+
+ /* Return true to keep going. */
+ return true;
+
+ case 12:
+ /* Based variable. */
+ v3 = 0;
+ v4 = 0x80;
+ v5 = 0;
+ if (! ieee_read_number (info, pp, &v)
+ || ! ieee_read_number (info, pp, &v2)
+ || ! ieee_read_optional_number (info, pp, &v3, &present))
+ return false;
+ if (present)
+ {
+ if (! ieee_read_optional_number (info, pp, &v4, &present))
+ return false;
+ if (present)
+ {
+ if (! ieee_read_optional_number (info, pp, &v5, &present))
+ return false;
+ }
+ }
+
+ /* We have no way to record this information. FIXME. */
+
+ ieee_error (info, atn_code_start, "unsupported ATN12");
+
+ /* Return true to keep going. */
+ return true;
+
+ case 16:
+ /* Constant. The description of this that I have is ambiguous,
+ so I'm not going to try to implement it. */
+ if (! ieee_read_number (info, pp, &v)
+ || ! ieee_read_optional_number (info, pp, &v2, &present))
+ return false;
+ if (present)
+ {
+ if (! ieee_read_optional_number (info, pp, &v2, &present))
+ return false;
+ if (present)
+ {
+ if (! ieee_read_optional_id (info, pp, &name, &namlen, &present))
+ return false;
+ }
+ }
+
+ if ((ieee_record_enum_type) **pp == ieee_e2_first_byte_enum)
+ {
+ if (! ieee_require_asn (info, pp, &v3))
+ return false;
+ }
+
+ return true;
+
+ case 19:
+ /* Static variable from assembler. */
+ v2 = 0;
+ if (! ieee_read_number (info, pp, &v)
+ || ! ieee_read_optional_number (info, pp, &v2, &present)
+ || ! ieee_require_asn (info, pp, &v3))
+ return false;
+ namcopy = savestring (name, namlen);
+ /* We don't really handle this correctly. FIXME. */
+ return debug_record_variable (dhandle, namcopy,
+ debug_make_void_type (dhandle),
+ v2 != 0 ? DEBUG_GLOBAL : DEBUG_STATIC,
+ v3);
+
+ case 62:
+ /* Procedure miscellaneous information. */
+ case 63:
+ /* Variable miscellaneous information. */
+ case 64:
+ /* Module miscellaneous information. */
+ if (! ieee_read_number (info, pp, &v)
+ || ! ieee_read_number (info, pp, &v2)
+ || ! ieee_read_optional_id (info, pp, &name, &namlen, &present))
+ return false;
+
+ if (atn_code == 62 && v == 80)
+ {
+ if (present)
+ {
+ ieee_error (info, atn_code_start,
+ "unexpected string in C++ misc");
+ return false;
+ }
+ return ieee_read_cxx_misc (info, pp, v2);
+ }
+
+ /* We just ignore all of this stuff. FIXME. */
+
+ for (; v2 > 0; --v2)
+ {
+ switch ((ieee_record_enum_type) **pp)
+ {
+ default:
+ ieee_error (info, *pp, "bad misc record");
+ return false;
+
+ case ieee_at_record_enum:
+ if (! ieee_require_atn65 (info, pp, &name, &namlen))
+ return false;
+ break;
+
+ case ieee_e2_first_byte_enum:
+ if (! ieee_require_asn (info, pp, &v3))
+ return false;
+ break;
+ }
+ }
+
+ return true;
+ }
+
+ /*NOTREACHED*/
+}
+
+/* Handle C++ debugging miscellaneous records. This is called for
+ procedure miscellaneous records of type 80. */
+
+static boolean
+ieee_read_cxx_misc (info, pp, count)
+ struct ieee_info *info;
+ const bfd_byte **pp;
+ unsigned long count;
+{
+ const bfd_byte *start;
+ bfd_vma category;
+
+ start = *pp;
+
+ /* Get the category of C++ misc record. */
+ if (! ieee_require_asn (info, pp, &category))
+ return false;
+ --count;
+
+ switch (category)
+ {
+ default:
+ ieee_error (info, start, "unrecognized C++ misc record");
+ return false;
+
+ case 'T':
+ if (! ieee_read_cxx_class (info, pp, count))
+ return false;
+ break;
+
+ case 'M':
+ {
+ bfd_vma flags;
+ const char *name;
+ unsigned long namlen;
+
+ /* The IEEE spec indicates that the 'M' record only has a
+ flags field. The MRI compiler also emits the name of the
+ function. */
+
+ if (! ieee_require_asn (info, pp, &flags))
+ return false;
+ if (*pp < info->pend
+ && (ieee_record_enum_type) **pp == ieee_at_record_enum)
+ {
+ if (! ieee_require_atn65 (info, pp, &name, &namlen))
+ return false;
+ }
+
+ /* This is emitted for method functions, but I don't think we
+ care very much. It might help if it told us useful
+ information like the class with which this function is
+ associated, but it doesn't, so it isn't helpful. */
+ }
+ break;
+
+ case 'B':
+ if (! ieee_read_cxx_defaults (info, pp, count))
+ return false;
+ break;
+
+ case 'z':
+ {
+ const char *name, *mangled, *class;
+ unsigned long namlen, mangledlen, classlen;
+ bfd_vma control;
+
+ /* Pointer to member. */
+
+ if (! ieee_require_atn65 (info, pp, &name, &namlen)
+ || ! ieee_require_atn65 (info, pp, &mangled, &mangledlen)
+ || ! ieee_require_atn65 (info, pp, &class, &classlen)
+ || ! ieee_require_asn (info, pp, &control))
+ return false;
+
+ /* FIXME: We should now track down name and change its type. */
+ }
+ break;
+
+ case 'R':
+ if (! ieee_read_reference (info, pp))
+ return false;
+ break;
+ }
+
+ return true;
+}
+
+/* Read a C++ class definition. This is a pmisc type 80 record of
+ category 'T'. */
+
+static boolean
+ieee_read_cxx_class (info, pp, count)
+ struct ieee_info *info;
+ const bfd_byte **pp;
+ unsigned long count;
+{
+ const bfd_byte *start;
+ bfd_vma class;
+ const char *tag;
+ unsigned long taglen;
+ struct ieee_tag *it;
+ PTR dhandle;
+ debug_field *fields;
+ unsigned int field_count, field_alloc;
+ debug_baseclass *baseclasses;
+ unsigned int baseclasses_count, baseclasses_alloc;
+ const debug_field *structfields;
+ struct ieee_method
+ {
+ const char *name;
+ unsigned long namlen;
+ debug_method_variant *variants;
+ unsigned count;
+ unsigned int alloc;
+ } *methods;
+ unsigned int methods_count, methods_alloc;
+ debug_type vptrbase;
+ boolean ownvptr;
+ debug_method *dmethods;
+
+ start = *pp;
+
+ if (! ieee_require_asn (info, pp, &class))
+ return false;
+ --count;
+
+ if (! ieee_require_atn65 (info, pp, &tag, &taglen))
+ return false;
+ --count;
+
+ /* Find the C struct with this name. */
+ for (it = info->tags; it != NULL; it = it->next)
+ if (it->name[0] == tag[0]
+ && strncmp (it->name, tag, taglen) == 0
+ && strlen (it->name) == taglen)
+ break;
+ if (it == NULL)
+ {
+ ieee_error (info, start, "undefined C++ object");
+ return false;
+ }
+
+ dhandle = info->dhandle;
+
+ fields = NULL;
+ field_count = 0;
+ field_alloc = 0;
+ baseclasses = NULL;
+ baseclasses_count = 0;
+ baseclasses_alloc = 0;
+ methods = NULL;
+ methods_count = 0;
+ methods_alloc = 0;
+ vptrbase = DEBUG_TYPE_NULL;
+ ownvptr = false;
+
+ structfields = debug_get_fields (dhandle, it->type);
+
+ while (count > 0)
+ {
+ bfd_vma id;
+ const bfd_byte *spec_start;
+
+ spec_start = *pp;
+
+ if (! ieee_require_asn (info, pp, &id))
+ return false;
+ --count;
+
+ switch (id)
+ {
+ default:
+ ieee_error (info, spec_start, "unrecognized C++ object spec");
+ return false;
+
+ case 'b':
+ {
+ bfd_vma flags, cinline;
+ const char *basename, *fieldname;
+ unsigned long baselen, fieldlen;
+ char *basecopy;
+ debug_type basetype;
+ bfd_vma bitpos;
+ boolean virtualp;
+ enum debug_visibility visibility;
+ debug_baseclass baseclass;
+
+ /* This represents a base or friend class. */
+
+ if (! ieee_require_asn (info, pp, &flags)
+ || ! ieee_require_atn65 (info, pp, &basename, &baselen)
+ || ! ieee_require_asn (info, pp, &cinline)
+ || ! ieee_require_atn65 (info, pp, &fieldname, &fieldlen))
+ return false;
+ count -= 4;
+
+ /* We have no way of recording friend information, so we
+ just ignore it. */
+ if ((flags & BASEFLAGS_FRIEND) != 0)
+ break;
+
+ /* I assume that either all of the members of the
+ baseclass are included in the object, starting at the
+ beginning of the object, or that none of them are
+ included. */
+
+ if ((fieldlen == 0) == (cinline == 0))
+ {
+ ieee_error (info, start, "unsupported C++ object type");
+ return false;
+ }
+
+ basecopy = savestring (basename, baselen);
+ basetype = debug_find_tagged_type (dhandle, basecopy,
+ DEBUG_KIND_ILLEGAL);
+ free (basecopy);
+ if (basetype == DEBUG_TYPE_NULL)
+ {
+ ieee_error (info, start, "C++ base class not defined");
+ return false;
+ }
+
+ if (fieldlen == 0)
+ bitpos = 0;
+ else
+ {
+ const debug_field *pf;
+
+ if (structfields == NULL)
+ {
+ ieee_error (info, start, "C++ object has no fields");
+ return false;
+ }
+
+ for (pf = structfields; *pf != DEBUG_FIELD_NULL; pf++)
+ {
+ const char *fname;
+
+ fname = debug_get_field_name (dhandle, *pf);
+ if (fname == NULL)
+ return false;
+ if (fname[0] == fieldname[0]
+ && strncmp (fname, fieldname, fieldlen) == 0
+ && strlen (fname) == fieldlen)
+ break;
+ }
+ if (*pf == DEBUG_FIELD_NULL)
+ {
+ ieee_error (info, start,
+ "C++ base class not found in container");
+ return false;
+ }
+
+ bitpos = debug_get_field_bitpos (dhandle, *pf);
+ }
+
+ if ((flags & BASEFLAGS_VIRTUAL) != 0)
+ virtualp = true;
+ else
+ virtualp = false;
+ if ((flags & BASEFLAGS_PRIVATE) != 0)
+ visibility = DEBUG_VISIBILITY_PRIVATE;
+ else
+ visibility = DEBUG_VISIBILITY_PUBLIC;
+
+ baseclass = debug_make_baseclass (dhandle, basetype, bitpos,
+ virtualp, visibility);
+ if (baseclass == DEBUG_BASECLASS_NULL)
+ return false;
+
+ if (baseclasses_count + 1 >= baseclasses_alloc)
+ {
+ baseclasses_alloc += 10;
+ baseclasses = ((debug_baseclass *)
+ xrealloc (baseclasses,
+ (baseclasses_alloc
+ * sizeof *baseclasses)));
+ }
+
+ baseclasses[baseclasses_count] = baseclass;
+ ++baseclasses_count;
+ baseclasses[baseclasses_count] = DEBUG_BASECLASS_NULL;
+ }
+ break;
+
+ case 'd':
+ {
+ bfd_vma flags;
+ const char *fieldname, *mangledname;
+ unsigned long fieldlen, mangledlen;
+ char *fieldcopy;
+ boolean staticp;
+ debug_type ftype;
+ const debug_field *pf = NULL;
+ enum debug_visibility visibility;
+ debug_field field;
+
+ /* This represents a data member. */
+
+ if (! ieee_require_asn (info, pp, &flags)
+ || ! ieee_require_atn65 (info, pp, &fieldname, &fieldlen)
+ || ! ieee_require_atn65 (info, pp, &mangledname, &mangledlen))
+ return false;
+ count -= 3;
+
+ fieldcopy = savestring (fieldname, fieldlen);
+
+ staticp = (flags & CXXFLAGS_STATIC) != 0 ? true : false;
+
+ if (staticp)
+ {
+ struct ieee_var *pv, *pvend;
+
+ /* See if we can find a definition for this variable. */
+ pv = info->vars.vars;
+ pvend = pv + info->vars.alloc;
+ for (; pv < pvend; pv++)
+ if (pv->namlen == mangledlen
+ && strncmp (pv->name, mangledname, mangledlen) == 0)
+ break;
+ if (pv < pvend)
+ ftype = pv->type;
+ else
+ {
+ /* This can happen if the variable is never used. */
+ ftype = ieee_builtin_type (info, start,
+ (unsigned int) builtin_void);
+ }
+ }
+ else
+ {
+ unsigned int findx;
+
+ if (structfields == NULL)
+ {
+ ieee_error (info, start, "C++ object has no fields");
+ return false;
+ }
+
+ for (pf = structfields, findx = 0;
+ *pf != DEBUG_FIELD_NULL;
+ pf++, findx++)
+ {
+ const char *fname;
+
+ fname = debug_get_field_name (dhandle, *pf);
+ if (fname == NULL)
+ return false;
+ if (fname[0] == mangledname[0]
+ && strncmp (fname, mangledname, mangledlen) == 0
+ && strlen (fname) == mangledlen)
+ break;
+ }
+ if (*pf == DEBUG_FIELD_NULL)
+ {
+ ieee_error (info, start,
+ "C++ data member not found in container");
+ return false;
+ }
+
+ ftype = debug_get_field_type (dhandle, *pf);
+
+ if (debug_get_type_kind (dhandle, ftype) == DEBUG_KIND_POINTER)
+ {
+ /* We might need to convert this field into a
+ reference type later on, so make it an indirect
+ type. */
+ if (it->fslots == NULL)
+ {
+ unsigned int fcnt;
+ const debug_field *pfcnt;
+
+ fcnt = 0;
+ for (pfcnt = structfields;
+ *pfcnt != DEBUG_FIELD_NULL;
+ pfcnt++)
+ ++fcnt;
+ it->fslots = ((debug_type *)
+ xmalloc (fcnt * sizeof *it->fslots));
+ memset (it->fslots, 0,
+ fcnt * sizeof *it->fslots);
+ }
+
+ if (ftype == DEBUG_TYPE_NULL)
+ return false;
+ it->fslots[findx] = ftype;
+ ftype = debug_make_indirect_type (dhandle,
+ it->fslots + findx,
+ (const char *) NULL);
+ }
+ }
+ if (ftype == DEBUG_TYPE_NULL)
+ return false;
+
+ switch (flags & CXXFLAGS_VISIBILITY)
+ {
+ default:
+ ieee_error (info, start, "unknown C++ visibility");
+ return false;
+
+ case CXXFLAGS_VISIBILITY_PUBLIC:
+ visibility = DEBUG_VISIBILITY_PUBLIC;
+ break;
+
+ case CXXFLAGS_VISIBILITY_PRIVATE:
+ visibility = DEBUG_VISIBILITY_PRIVATE;
+ break;
+
+ case CXXFLAGS_VISIBILITY_PROTECTED:
+ visibility = DEBUG_VISIBILITY_PROTECTED;
+ break;
+ }
+
+ if (staticp)
+ {
+ char *mangledcopy;
+
+ mangledcopy = savestring (mangledname, mangledlen);
+
+ field = debug_make_static_member (dhandle, fieldcopy,
+ ftype, mangledcopy,
+ visibility);
+ }
+ else
+ {
+ bfd_vma bitpos, bitsize;
+
+ bitpos = debug_get_field_bitpos (dhandle, *pf);
+ bitsize = debug_get_field_bitsize (dhandle, *pf);
+ if (bitpos == (bfd_vma) -1 || bitsize == (bfd_vma) -1)
+ {
+ ieee_error (info, start, "bad C++ field bit pos or size");
+ return false;
+ }
+ field = debug_make_field (dhandle, fieldcopy, ftype, bitpos,
+ bitsize, visibility);
+ }
+
+ if (field == DEBUG_FIELD_NULL)
+ return false;
+
+ if (field_count + 1 >= field_alloc)
+ {
+ field_alloc += 10;
+ fields = ((debug_field *)
+ xrealloc (fields, field_alloc * sizeof *fields));
+ }
+
+ fields[field_count] = field;
+ ++field_count;
+ fields[field_count] = DEBUG_FIELD_NULL;
+ }
+ break;
+
+ case 'm':
+ case 'v':
+ {
+ bfd_vma flags, voffset, control;
+ const char *name, *mangled;
+ unsigned long namlen, mangledlen;
+ struct ieee_var *pv, *pvend;
+ debug_type type;
+ enum debug_visibility visibility;
+ boolean constp, volatilep;
+ char *mangledcopy;
+ debug_method_variant mv;
+ struct ieee_method *meth;
+ unsigned int im;
+
+ if (! ieee_require_asn (info, pp, &flags)
+ || ! ieee_require_atn65 (info, pp, &name, &namlen)
+ || ! ieee_require_atn65 (info, pp, &mangled, &mangledlen))
+ return false;
+ count -= 3;
+ if (id != 'v')
+ voffset = 0;
+ else
+ {
+ if (! ieee_require_asn (info, pp, &voffset))
+ return false;
+ --count;
+ }
+ if (! ieee_require_asn (info, pp, &control))
+ return false;
+ --count;
+
+ /* We just ignore the control information. */
+
+ /* We have no way to represent friend information, so we
+ just ignore it. */
+ if ((flags & CXXFLAGS_FRIEND) != 0)
+ break;
+
+ /* We should already have seen a type for the function. */
+ pv = info->vars.vars;
+ pvend = pv + info->vars.alloc;
+ for (; pv < pvend; pv++)
+ if (pv->namlen == mangledlen
+ && strncmp (pv->name, mangled, mangledlen) == 0)
+ break;
+
+ if (pv >= pvend)
+ {
+ /* We won't have type information for this function if
+ it is not included in this file. We don't try to
+ handle this case. FIXME. */
+ type = (debug_make_function_type
+ (dhandle,
+ ieee_builtin_type (info, start,
+ (unsigned int) builtin_void),
+ (debug_type *) NULL,
+ false));
+ }
+ else
+ {
+ debug_type return_type;
+ const debug_type *arg_types;
+ boolean varargs;
+
+ if (debug_get_type_kind (dhandle, pv->type)
+ != DEBUG_KIND_FUNCTION)
+ {
+ ieee_error (info, start,
+ "bad type for C++ method function");
+ return false;
+ }
+
+ return_type = debug_get_return_type (dhandle, pv->type);
+ arg_types = debug_get_parameter_types (dhandle, pv->type,
+ &varargs);
+ if (return_type == DEBUG_TYPE_NULL || arg_types == NULL)
+ {
+ ieee_error (info, start,
+ "no type information for C++ method function");
+ return false;
+ }
+
+ type = debug_make_method_type (dhandle, return_type, it->type,
+ (debug_type *) arg_types,
+ varargs);
+ }
+ if (type == DEBUG_TYPE_NULL)
+ return false;
+
+ switch (flags & CXXFLAGS_VISIBILITY)
+ {
+ default:
+ ieee_error (info, start, "unknown C++ visibility");
+ return false;
+
+ case CXXFLAGS_VISIBILITY_PUBLIC:
+ visibility = DEBUG_VISIBILITY_PUBLIC;
+ break;
+
+ case CXXFLAGS_VISIBILITY_PRIVATE:
+ visibility = DEBUG_VISIBILITY_PRIVATE;
+ break;
+
+ case CXXFLAGS_VISIBILITY_PROTECTED:
+ visibility = DEBUG_VISIBILITY_PROTECTED;
+ break;
+ }
+
+ constp = (flags & CXXFLAGS_CONST) != 0 ? true : false;
+ volatilep = (flags & CXXFLAGS_VOLATILE) != 0 ? true : false;
+
+ mangledcopy = savestring (mangled, mangledlen);
+
+ if ((flags & CXXFLAGS_STATIC) != 0)
+ {
+ if (id == 'v')
+ {
+ ieee_error (info, start, "C++ static virtual method");
+ return false;
+ }
+ mv = debug_make_static_method_variant (dhandle, mangledcopy,
+ type, visibility,
+ constp, volatilep);
+ }
+ else
+ {
+ debug_type vcontext;
+
+ if (id != 'v')
+ vcontext = DEBUG_TYPE_NULL;
+ else
+ {
+ /* FIXME: How can we calculate this correctly? */
+ vcontext = it->type;
+ }
+ mv = debug_make_method_variant (dhandle, mangledcopy, type,
+ visibility, constp,
+ volatilep, voffset,
+ vcontext);
+ }
+ if (mv == DEBUG_METHOD_VARIANT_NULL)
+ return false;
+
+ for (meth = methods, im = 0; im < methods_count; meth++, im++)
+ if (meth->namlen == namlen
+ && strncmp (meth->name, name, namlen) == 0)
+ break;
+ if (im >= methods_count)
+ {
+ if (methods_count >= methods_alloc)
+ {
+ methods_alloc += 10;
+ methods = ((struct ieee_method *)
+ xrealloc (methods,
+ methods_alloc * sizeof *methods));
+ }
+ methods[methods_count].name = name;
+ methods[methods_count].namlen = namlen;
+ methods[methods_count].variants = NULL;
+ methods[methods_count].count = 0;
+ methods[methods_count].alloc = 0;
+ meth = methods + methods_count;
+ ++methods_count;
+ }
+
+ if (meth->count + 1 >= meth->alloc)
+ {
+ meth->alloc += 10;
+ meth->variants = ((debug_method_variant *)
+ xrealloc (meth->variants,
+ (meth->alloc
+ * sizeof *meth->variants)));
+ }
+
+ meth->variants[meth->count] = mv;
+ ++meth->count;
+ meth->variants[meth->count] = DEBUG_METHOD_VARIANT_NULL;
+ }
+ break;
+
+ case 'o':
+ {
+ bfd_vma spec;
+
+ /* We have no way to store this information, so we just
+ ignore it. */
+ if (! ieee_require_asn (info, pp, &spec))
+ return false;
+ --count;
+ if ((spec & 4) != 0)
+ {
+ const char *filename;
+ unsigned long filenamlen;
+ bfd_vma lineno;
+
+ if (! ieee_require_atn65 (info, pp, &filename, &filenamlen)
+ || ! ieee_require_asn (info, pp, &lineno))
+ return false;
+ count -= 2;
+ }
+ else if ((spec & 8) != 0)
+ {
+ const char *mangled;
+ unsigned long mangledlen;
+
+ if (! ieee_require_atn65 (info, pp, &mangled, &mangledlen))
+ return false;
+ --count;
+ }
+ else
+ {
+ ieee_error (info, start,
+ "unrecognized C++ object overhead spec");
+ return false;
+ }
+ }
+ break;
+
+ case 'z':
+ {
+ const char *vname, *basename;
+ unsigned long vnamelen, baselen;
+ bfd_vma vsize, control;
+
+ /* A virtual table pointer. */
+
+ if (! ieee_require_atn65 (info, pp, &vname, &vnamelen)
+ || ! ieee_require_asn (info, pp, &vsize)
+ || ! ieee_require_atn65 (info, pp, &basename, &baselen)
+ || ! ieee_require_asn (info, pp, &control))
+ return false;
+ count -= 4;
+
+ /* We just ignore the control number. We don't care what
+ the virtual table name is. We have no way to store the
+ virtual table size, and I don't think we care anyhow. */
+
+ /* FIXME: We can't handle multiple virtual table pointers. */
+
+ if (baselen == 0)
+ ownvptr = true;
+ else
+ {
+ char *basecopy;
+
+ basecopy = savestring (basename, baselen);
+ vptrbase = debug_find_tagged_type (dhandle, basecopy,
+ DEBUG_KIND_ILLEGAL);
+ free (basecopy);
+ if (vptrbase == DEBUG_TYPE_NULL)
+ {
+ ieee_error (info, start, "undefined C++ vtable");
+ return false;
+ }
+ }
+ }
+ break;
+ }
+ }
+
+ /* Now that we have seen all the method variants, we can call
+ debug_make_method for each one. */
+
+ if (methods_count == 0)
+ dmethods = NULL;
+ else
+ {
+ unsigned int i;
+
+ dmethods = ((debug_method *)
+ xmalloc ((methods_count + 1) * sizeof *dmethods));
+ for (i = 0; i < methods_count; i++)
+ {
+ char *namcopy;
+
+ namcopy = savestring (methods[i].name, methods[i].namlen);
+ dmethods[i] = debug_make_method (dhandle, namcopy,
+ methods[i].variants);
+ if (dmethods[i] == DEBUG_METHOD_NULL)
+ return false;
+ }
+ dmethods[i] = DEBUG_METHOD_NULL;
+ free (methods);
+ }
+
+ /* The struct type was created as an indirect type pointing at
+ it->slot. We update it->slot to automatically update all
+ references to this struct. */
+ it->slot = debug_make_object_type (dhandle,
+ class != 'u',
+ debug_get_type_size (dhandle,
+ it->slot),
+ fields, baseclasses, dmethods,
+ vptrbase, ownvptr);
+ if (it->slot == DEBUG_TYPE_NULL)
+ return false;
+
+ return true;
+}
+
+/* Read C++ default argument value and reference type information. */
+
+static boolean
+ieee_read_cxx_defaults (info, pp, count)
+ struct ieee_info *info;
+ const bfd_byte **pp;
+ unsigned long count;
+{
+ const bfd_byte *start;
+ const char *fnname;
+ unsigned long fnlen;
+ bfd_vma defcount;
+
+ start = *pp;
+
+ /* Giving the function name before the argument count is an addendum
+ to the spec. The function name is demangled, though, so this
+ record must always refer to the current function. */
+
+ if (info->blockstack.bsp <= info->blockstack.stack
+ || info->blockstack.bsp[-1].fnindx == (unsigned int) -1)
+ {
+ ieee_error (info, start, "C++ default values not in a function");
+ return false;
+ }
+
+ if (! ieee_require_atn65 (info, pp, &fnname, &fnlen)
+ || ! ieee_require_asn (info, pp, &defcount))
+ return false;
+ count -= 2;
+
+ while (defcount-- > 0)
+ {
+ bfd_vma type, val;
+ const char *strval;
+ unsigned long strvallen;
+
+ if (! ieee_require_asn (info, pp, &type))
+ return false;
+ --count;
+
+ switch (type)
+ {
+ case 0:
+ case 4:
+ break;
+
+ case 1:
+ case 2:
+ if (! ieee_require_asn (info, pp, &val))
+ return false;
+ --count;
+ break;
+
+ case 3:
+ case 7:
+ if (! ieee_require_atn65 (info, pp, &strval, &strvallen))
+ return false;
+ --count;
+ break;
+
+ default:
+ ieee_error (info, start, "unrecognized C++ default type");
+ return false;
+ }
+
+ /* We have no way to record the default argument values, so we
+ just ignore them. FIXME. */
+ }
+
+ /* Any remaining arguments are indices of parameters that are really
+ reference type. */
+ if (count > 0)
+ {
+ PTR dhandle;
+ debug_type *arg_slots;
+
+ dhandle = info->dhandle;
+ arg_slots = info->types.types[info->blockstack.bsp[-1].fnindx].arg_slots;
+ while (count-- > 0)
+ {
+ bfd_vma indx;
+ debug_type target;
+
+ if (! ieee_require_asn (info, pp, &indx))
+ return false;
+ /* The index is 1 based. */
+ --indx;
+ if (arg_slots == NULL
+ || arg_slots[indx] == DEBUG_TYPE_NULL
+ || (debug_get_type_kind (dhandle, arg_slots[indx])
+ != DEBUG_KIND_POINTER))
+ {
+ ieee_error (info, start, "reference parameter is not a pointer");
+ return false;
+ }
+
+ target = debug_get_target_type (dhandle, arg_slots[indx]);
+ arg_slots[indx] = debug_make_reference_type (dhandle, target);
+ if (arg_slots[indx] == DEBUG_TYPE_NULL)
+ return false;
+ }
+ }
+
+ return true;
+}
+
+/* Read a C++ reference definition. */
+
+static boolean
+ieee_read_reference (info, pp)
+ struct ieee_info *info;
+ const bfd_byte **pp;
+{
+ const bfd_byte *start;
+ bfd_vma flags;
+ const char *class, *name;
+ unsigned long classlen, namlen;
+ debug_type *pslot;
+ debug_type target;
+
+ start = *pp;
+
+ if (! ieee_require_asn (info, pp, &flags))
+ return false;
+
+ /* Giving the class name before the member name is in an addendum to
+ the spec. */
+ if (flags == 3)
+ {
+ if (! ieee_require_atn65 (info, pp, &class, &classlen))
+ return false;
+ }
+
+ if (! ieee_require_atn65 (info, pp, &name, &namlen))
+ return false;
+
+ pslot = NULL;
+ if (flags != 3)
+ {
+ int pass;
+
+ /* We search from the last variable indices to the first in
+ hopes of finding local variables correctly. We search the
+ local variables on the first pass, and the global variables
+ on the second. FIXME: This probably won't work in all cases.
+ On the other hand, I don't know what will. */
+ for (pass = 0; pass < 2; pass++)
+ {
+ struct ieee_vars *vars;
+ int i;
+ struct ieee_var *pv = NULL;
+
+ if (pass == 0)
+ vars = &info->vars;
+ else
+ {
+ vars = info->global_vars;
+ if (vars == NULL)
+ break;
+ }
+
+ for (i = (int) vars->alloc - 1; i >= 0; i--)
+ {
+ boolean found;
+
+ pv = vars->vars + i;
+
+ if (pv->pslot == NULL
+ || pv->namlen != namlen
+ || strncmp (pv->name, name, namlen) != 0)
+ continue;
+
+ found = false;
+ switch (flags)
+ {
+ default:
+ ieee_error (info, start,
+ "unrecognized C++ reference type");
+ return false;
+
+ case 0:
+ /* Global variable or function. */
+ if (pv->kind == IEEE_GLOBAL
+ || pv->kind == IEEE_EXTERNAL
+ || pv->kind == IEEE_FUNCTION)
+ found = true;
+ break;
+
+ case 1:
+ /* Global static variable or function. */
+ if (pv->kind == IEEE_STATIC
+ || pv->kind == IEEE_FUNCTION)
+ found = true;
+ break;
+
+ case 2:
+ /* Local variable. */
+ if (pv->kind == IEEE_LOCAL)
+ found = true;
+ break;
+ }
+
+ if (found)
+ break;
+ }
+
+ if (i >= 0)
+ {
+ pslot = pv->pslot;
+ break;
+ }
+ }
+ }
+ else
+ {
+ struct ieee_tag *it;
+
+ for (it = info->tags; it != NULL; it = it->next)
+ {
+ if (it->name[0] == class[0]
+ && strncmp (it->name, class, classlen) == 0
+ && strlen (it->name) == classlen)
+ {
+ if (it->fslots != NULL)
+ {
+ const debug_field *pf;
+ unsigned int findx;
+
+ pf = debug_get_fields (info->dhandle, it->type);
+ if (pf == NULL)
+ {
+ ieee_error (info, start,
+ "C++ reference in class with no fields");
+ return false;
+ }
+
+ for (findx = 0; *pf != DEBUG_FIELD_NULL; pf++, findx++)
+ {
+ const char *fname;
+
+ fname = debug_get_field_name (info->dhandle, *pf);
+ if (fname == NULL)
+ return false;
+ if (strncmp (fname, name, namlen) == 0
+ && strlen (fname) == namlen)
+ {
+ pslot = it->fslots + findx;
+ break;
+ }
+ }
+ }
+
+ break;
+ }
+ }
+ }
+
+ if (pslot == NULL)
+ {
+ ieee_error (info, start, "C++ reference not found");
+ return false;
+ }
+
+ /* We allocated the type of the object as an indirect type pointing
+ to *pslot, which we can now update to be a reference type. */
+ if (debug_get_type_kind (info->dhandle, *pslot) != DEBUG_KIND_POINTER)
+ {
+ ieee_error (info, start, "C++ reference is not pointer");
+ return false;
+ }
+
+ target = debug_get_target_type (info->dhandle, *pslot);
+ *pslot = debug_make_reference_type (info->dhandle, target);
+ if (*pslot == DEBUG_TYPE_NULL)
+ return false;
+
+ return true;
+}
+
+/* Require an ASN record. */
+
+static boolean
+ieee_require_asn (info, pp, pv)
+ struct ieee_info *info;
+ const bfd_byte **pp;
+ bfd_vma *pv;
+{
+ const bfd_byte *start;
+ ieee_record_enum_type c;
+ bfd_vma varindx;
+
+ start = *pp;
+
+ c = (ieee_record_enum_type) **pp;
+ if (c != ieee_e2_first_byte_enum)
+ {
+ ieee_error (info, start, "missing required ASN");
+ return false;
+ }
+ ++*pp;
+
+ c = (ieee_record_enum_type) (((unsigned int) c << 8) | **pp);
+ if (c != ieee_asn_record_enum)
+ {
+ ieee_error (info, start, "missing required ASN");
+ return false;
+ }
+ ++*pp;
+
+ /* Just ignore the variable index. */
+ if (! ieee_read_number (info, pp, &varindx))
+ return false;
+
+ return ieee_read_expression (info, pp, pv);
+}
+
+/* Require an ATN65 record. */
+
+static boolean
+ieee_require_atn65 (info, pp, pname, pnamlen)
+ struct ieee_info *info;
+ const bfd_byte **pp;
+ const char **pname;
+ unsigned long *pnamlen;
+{
+ const bfd_byte *start;
+ ieee_record_enum_type c;
+ bfd_vma name_indx, type_indx, atn_code;
+
+ start = *pp;
+
+ c = (ieee_record_enum_type) **pp;
+ if (c != ieee_at_record_enum)
+ {
+ ieee_error (info, start, "missing required ATN65");
+ return false;
+ }
+ ++*pp;
+
+ c = (ieee_record_enum_type) (((unsigned int) c << 8) | **pp);
+ if (c != ieee_atn_record_enum)
+ {
+ ieee_error (info, start, "missing required ATN65");
+ return false;
+ }
+ ++*pp;
+
+ if (! ieee_read_number (info, pp, &name_indx)
+ || ! ieee_read_number (info, pp, &type_indx)
+ || ! ieee_read_number (info, pp, &atn_code))
+ return false;
+
+ /* Just ignore name_indx. */
+
+ if (type_indx != 0 || atn_code != 65)
+ {
+ ieee_error (info, start, "bad ATN65 record");
+ return false;
+ }
+
+ return ieee_read_id (info, pp, pname, pnamlen);
+}
+
+/* Convert a register number in IEEE debugging information into a
+ generic register number. */
+
+static int
+ieee_regno_to_genreg (abfd, r)
+ bfd *abfd;
+ int r;
+{
+ switch (bfd_get_arch (abfd))
+ {
+ case bfd_arch_m68k:
+ /* For some reasons stabs adds 2 to the floating point register
+ numbers. */
+ if (r >= 16)
+ r += 2;
+ break;
+
+ case bfd_arch_i960:
+ /* Stabs uses 0 to 15 for r0 to r15, 16 to 31 for g0 to g15, and
+ 32 to 35 for fp0 to fp3. */
+ --r;
+ break;
+
+ default:
+ break;
+ }
+
+ return r;
+}
+
+/* Convert a generic register number to an IEEE specific one. */
+
+static int
+ieee_genreg_to_regno (abfd, r)
+ bfd *abfd;
+ int r;
+{
+ switch (bfd_get_arch (abfd))
+ {
+ case bfd_arch_m68k:
+ /* For some reason stabs add 2 to the floating point register
+ numbers. */
+ if (r >= 18)
+ r -= 2;
+ break;
+
+ case bfd_arch_i960:
+ /* Stabs uses 0 to 15 for r0 to r15, 16 to 31 for g0 to g15, and
+ 32 to 35 for fp0 to fp3. */
+ ++r;
+ break;
+
+ default:
+ break;
+ }
+
+ return r;
+}
+
+/* These routines build IEEE debugging information out of the generic
+ debugging information. */
+
+/* We build the IEEE debugging information byte by byte. Rather than
+ waste time copying data around, we use a linked list of buffers to
+ hold the data. */
+
+#define IEEE_BUFSIZE (490)
+
+struct ieee_buf
+{
+ /* Next buffer. */
+ struct ieee_buf *next;
+ /* Number of data bytes in this buffer. */
+ unsigned int c;
+ /* Bytes. */
+ bfd_byte buf[IEEE_BUFSIZE];
+};
+
+/* A list of buffers. */
+
+struct ieee_buflist
+{
+ /* Head of list. */
+ struct ieee_buf *head;
+ /* Tail--last buffer on list. */
+ struct ieee_buf *tail;
+};
+
+/* In order to generate the BB11 blocks required by the HP emulator,
+ we keep track of ranges of addresses which correspond to a given
+ compilation unit. */
+
+struct ieee_range
+{
+ /* Next range. */
+ struct ieee_range *next;
+ /* Low address. */
+ bfd_vma low;
+ /* High address. */
+ bfd_vma high;
+};
+
+/* This structure holds information for a class on the type stack. */
+
+struct ieee_type_class
+{
+ /* The name index in the debugging information. */
+ unsigned int indx;
+ /* The pmisc records for the class. */
+ struct ieee_buflist pmiscbuf;
+ /* The number of pmisc records. */
+ unsigned int pmisccount;
+ /* The name of the class holding the virtual table, if not this
+ class. */
+ const char *vclass;
+ /* Whether this class holds its own virtual table. */
+ boolean ownvptr;
+ /* The largest virtual table offset seen so far. */
+ bfd_vma voffset;
+ /* The current method. */
+ const char *method;
+ /* Additional pmisc records used to record fields of reference type. */
+ struct ieee_buflist refs;
+};
+
+/* This is how we store types for the writing routines. Most types
+ are simply represented by a type index. */
+
+struct ieee_write_type
+{
+ /* Type index. */
+ unsigned int indx;
+ /* The size of the type, if known. */
+ unsigned int size;
+ /* The name of the type, if any. */
+ const char *name;
+ /* If this is a function or method type, we build the type here, and
+ only add it to the output buffers if we need it. */
+ struct ieee_buflist fndef;
+ /* If this is a struct, this is where the struct definition is
+ built. */
+ struct ieee_buflist strdef;
+ /* If this is a class, this is where the class information is built. */
+ struct ieee_type_class *classdef;
+ /* Whether the type is unsigned. */
+ unsigned int unsignedp : 1;
+ /* Whether this is a reference type. */
+ unsigned int referencep : 1;
+ /* Whether this is in the local type block. */
+ unsigned int localp : 1;
+ /* Whether this is a duplicate struct definition which we are
+ ignoring. */
+ unsigned int ignorep : 1;
+};
+
+/* This is the type stack used by the debug writing routines. FIXME:
+ We could generate more efficient output if we remembered when we
+ have output a particular type before. */
+
+struct ieee_type_stack
+{
+ /* Next entry on stack. */
+ struct ieee_type_stack *next;
+ /* Type information. */
+ struct ieee_write_type type;
+};
+
+/* This is a list of associations between a name and some types.
+ These are used for typedefs and tags. */
+
+struct ieee_name_type
+{
+ /* Next type for this name. */
+ struct ieee_name_type *next;
+ /* ID number. For a typedef, this is the index of the type to which
+ this name is typedefed. */
+ unsigned int id;
+ /* Type. */
+ struct ieee_write_type type;
+ /* If this is a tag which has not yet been defined, this is the
+ kind. If the tag has been defined, this is DEBUG_KIND_ILLEGAL. */
+ enum debug_type_kind kind;
+};
+
+/* We use a hash table to associate names and types. */
+
+struct ieee_name_type_hash_table
+{
+ struct bfd_hash_table root;
+};
+
+struct ieee_name_type_hash_entry
+{
+ struct bfd_hash_entry root;
+ /* Information for this name. */
+ struct ieee_name_type *types;
+};
+
+/* This is a list of enums. */
+
+struct ieee_defined_enum
+{
+ /* Next enum. */
+ struct ieee_defined_enum *next;
+ /* Type index. */
+ unsigned int indx;
+ /* Whether this enum has been defined. */
+ boolean defined;
+ /* Tag. */
+ const char *tag;
+ /* Names. */
+ const char **names;
+ /* Values. */
+ bfd_signed_vma *vals;
+};
+
+/* We keep a list of modified versions of types, so that we don't
+ output them more than once. */
+
+struct ieee_modified_type
+{
+ /* Pointer to this type. */
+ unsigned int pointer;
+ /* Function with unknown arguments returning this type. */
+ unsigned int function;
+ /* Const version of this type. */
+ unsigned int const_qualified;
+ /* Volatile version of this type. */
+ unsigned int volatile_qualified;
+ /* List of arrays of this type of various bounds. */
+ struct ieee_modified_array_type *arrays;
+};
+
+/* A list of arrays bounds. */
+
+struct ieee_modified_array_type
+{
+ /* Next array bounds. */
+ struct ieee_modified_array_type *next;
+ /* Type index with these bounds. */
+ unsigned int indx;
+ /* Low bound. */
+ bfd_signed_vma low;
+ /* High bound. */
+ bfd_signed_vma high;
+};
+
+/* This is a list of pending function parameter information. We don't
+ output them until we see the first block. */
+
+struct ieee_pending_parm
+{
+ /* Next pending parameter. */
+ struct ieee_pending_parm *next;
+ /* Name. */
+ const char *name;
+ /* Type index. */
+ unsigned int type;
+ /* Whether the type is a reference. */
+ boolean referencep;
+ /* Kind. */
+ enum debug_parm_kind kind;
+ /* Value. */
+ bfd_vma val;
+};
+
+/* This is the handle passed down by debug_write. */
+
+struct ieee_handle
+{
+ /* BFD we are writing to. */
+ bfd *abfd;
+ /* Whether we got an error in a subroutine called via traverse or
+ map_over_sections. */
+ boolean error;
+ /* Current data buffer list. */
+ struct ieee_buflist *current;
+ /* Current data buffer. */
+ struct ieee_buf *curbuf;
+ /* Filename of current compilation unit. */
+ const char *filename;
+ /* Module name of current compilation unit. */
+ const char *modname;
+ /* List of buffer for global types. */
+ struct ieee_buflist global_types;
+ /* List of finished data buffers. */
+ struct ieee_buflist data;
+ /* List of buffers for typedefs in the current compilation unit. */
+ struct ieee_buflist types;
+ /* List of buffers for variables and functions in the current
+ compilation unit. */
+ struct ieee_buflist vars;
+ /* List of buffers for C++ class definitions in the current
+ compilation unit. */
+ struct ieee_buflist cxx;
+ /* List of buffers for line numbers in the current compilation unit. */
+ struct ieee_buflist linenos;
+ /* Ranges for the current compilation unit. */
+ struct ieee_range *ranges;
+ /* Ranges for all debugging information. */
+ struct ieee_range *global_ranges;
+ /* Nested pending ranges. */
+ struct ieee_range *pending_ranges;
+ /* Type stack. */
+ struct ieee_type_stack *type_stack;
+ /* Next unallocated type index. */
+ unsigned int type_indx;
+ /* Next unallocated name index. */
+ unsigned int name_indx;
+ /* Typedefs. */
+ struct ieee_name_type_hash_table typedefs;
+ /* Tags. */
+ struct ieee_name_type_hash_table tags;
+ /* Enums. */
+ struct ieee_defined_enum *enums;
+ /* Modified versions of types. */
+ struct ieee_modified_type *modified;
+ /* Number of entries allocated in modified. */
+ unsigned int modified_alloc;
+ /* 4 byte complex type. */
+ unsigned int complex_float_index;
+ /* 8 byte complex type. */
+ unsigned int complex_double_index;
+ /* The depth of block nesting. This is 0 outside a function, and 1
+ just after start_function is called. */
+ unsigned int block_depth;
+ /* The name of the current function. */
+ const char *fnname;
+ /* List of buffers for the type of the function we are currently
+ writing out. */
+ struct ieee_buflist fntype;
+ /* List of buffers for the parameters of the function we are
+ currently writing out. */
+ struct ieee_buflist fnargs;
+ /* Number of arguments written to fnargs. */
+ unsigned int fnargcount;
+ /* Pending function parameters. */
+ struct ieee_pending_parm *pending_parms;
+ /* Current line number filename. */
+ const char *lineno_filename;
+ /* Line number name index. */
+ unsigned int lineno_name_indx;
+ /* Filename of pending line number. */
+ const char *pending_lineno_filename;
+ /* Pending line number. */
+ unsigned long pending_lineno;
+ /* Address of pending line number. */
+ bfd_vma pending_lineno_addr;
+ /* Highest address seen at end of procedure. */
+ bfd_vma highaddr;
+};
+
+static boolean ieee_init_buffer
+ PARAMS ((struct ieee_handle *, struct ieee_buflist *));
+static boolean ieee_change_buffer
+ PARAMS ((struct ieee_handle *, struct ieee_buflist *));
+static boolean ieee_append_buffer
+ PARAMS ((struct ieee_handle *, struct ieee_buflist *,
+ struct ieee_buflist *));
+static boolean ieee_real_write_byte PARAMS ((struct ieee_handle *, int));
+static boolean ieee_write_2bytes PARAMS ((struct ieee_handle *, int));
+static boolean ieee_write_number PARAMS ((struct ieee_handle *, bfd_vma));
+static boolean ieee_write_id PARAMS ((struct ieee_handle *, const char *));
+static boolean ieee_write_asn
+ PARAMS ((struct ieee_handle *, unsigned int, bfd_vma));
+static boolean ieee_write_atn65
+ PARAMS ((struct ieee_handle *, unsigned int, const char *));
+static boolean ieee_push_type
+ PARAMS ((struct ieee_handle *, unsigned int, unsigned int, boolean,
+ boolean));
+static unsigned int ieee_pop_type PARAMS ((struct ieee_handle *));
+static void ieee_pop_unused_type PARAMS ((struct ieee_handle *));
+static unsigned int ieee_pop_type_used
+ PARAMS ((struct ieee_handle *, boolean));
+static boolean ieee_add_range
+ PARAMS ((struct ieee_handle *, boolean, bfd_vma, bfd_vma));
+static boolean ieee_start_range PARAMS ((struct ieee_handle *, bfd_vma));
+static boolean ieee_end_range PARAMS ((struct ieee_handle *, bfd_vma));
+static boolean ieee_define_type
+ PARAMS ((struct ieee_handle *, unsigned int, boolean, boolean));
+static boolean ieee_define_named_type
+ PARAMS ((struct ieee_handle *, const char *, unsigned int, unsigned int,
+ boolean, boolean, struct ieee_buflist *));
+static struct ieee_modified_type *ieee_get_modified_info
+ PARAMS ((struct ieee_handle *, unsigned int));
+static struct bfd_hash_entry *ieee_name_type_newfunc
+ PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));
+static boolean ieee_write_undefined_tag
+ PARAMS ((struct ieee_name_type_hash_entry *, PTR));
+static boolean ieee_finish_compilation_unit PARAMS ((struct ieee_handle *));
+static void ieee_add_bb11_blocks PARAMS ((bfd *, asection *, PTR));
+static boolean ieee_add_bb11
+ PARAMS ((struct ieee_handle *, asection *, bfd_vma, bfd_vma));
+static boolean ieee_output_pending_parms PARAMS ((struct ieee_handle *));
+static unsigned int ieee_vis_to_flags PARAMS ((enum debug_visibility));
+static boolean ieee_class_method_var
+ PARAMS ((struct ieee_handle *, const char *, enum debug_visibility, boolean,
+ boolean, boolean, bfd_vma, boolean));
+
+static boolean ieee_start_compilation_unit PARAMS ((PTR, const char *));
+static boolean ieee_start_source PARAMS ((PTR, const char *));
+static boolean ieee_empty_type PARAMS ((PTR));
+static boolean ieee_void_type PARAMS ((PTR));
+static boolean ieee_int_type PARAMS ((PTR, unsigned int, boolean));
+static boolean ieee_float_type PARAMS ((PTR, unsigned int));
+static boolean ieee_complex_type PARAMS ((PTR, unsigned int));
+static boolean ieee_bool_type PARAMS ((PTR, unsigned int));
+static boolean ieee_enum_type
+ PARAMS ((PTR, const char *, const char **, bfd_signed_vma *));
+static boolean ieee_pointer_type PARAMS ((PTR));
+static boolean ieee_function_type PARAMS ((PTR, int, boolean));
+static boolean ieee_reference_type PARAMS ((PTR));
+static boolean ieee_range_type PARAMS ((PTR, bfd_signed_vma, bfd_signed_vma));
+static boolean ieee_array_type
+ PARAMS ((PTR, bfd_signed_vma, bfd_signed_vma, boolean));
+static boolean ieee_set_type PARAMS ((PTR, boolean));
+static boolean ieee_offset_type PARAMS ((PTR));
+static boolean ieee_method_type PARAMS ((PTR, boolean, int, boolean));
+static boolean ieee_const_type PARAMS ((PTR));
+static boolean ieee_volatile_type PARAMS ((PTR));
+static boolean ieee_start_struct_type
+ PARAMS ((PTR, const char *, unsigned int, boolean, unsigned int));
+static boolean ieee_struct_field
+ PARAMS ((PTR, const char *, bfd_vma, bfd_vma, enum debug_visibility));
+static boolean ieee_end_struct_type PARAMS ((PTR));
+static boolean ieee_start_class_type
+ PARAMS ((PTR, const char *, unsigned int, boolean, unsigned int, boolean,
+ boolean));
+static boolean ieee_class_static_member
+ PARAMS ((PTR, const char *, const char *, enum debug_visibility));
+static boolean ieee_class_baseclass
+ PARAMS ((PTR, bfd_vma, boolean, enum debug_visibility));
+static boolean ieee_class_start_method PARAMS ((PTR, const char *));
+static boolean ieee_class_method_variant
+ PARAMS ((PTR, const char *, enum debug_visibility, boolean, boolean,
+ bfd_vma, boolean));
+static boolean ieee_class_static_method_variant
+ PARAMS ((PTR, const char *, enum debug_visibility, boolean, boolean));
+static boolean ieee_class_end_method PARAMS ((PTR));
+static boolean ieee_end_class_type PARAMS ((PTR));
+static boolean ieee_typedef_type PARAMS ((PTR, const char *));
+static boolean ieee_tag_type
+ PARAMS ((PTR, const char *, unsigned int, enum debug_type_kind));
+static boolean ieee_typdef PARAMS ((PTR, const char *));
+static boolean ieee_tag PARAMS ((PTR, const char *));
+static boolean ieee_int_constant PARAMS ((PTR, const char *, bfd_vma));
+static boolean ieee_float_constant PARAMS ((PTR, const char *, double));
+static boolean ieee_typed_constant PARAMS ((PTR, const char *, bfd_vma));
+static boolean ieee_variable
+ PARAMS ((PTR, const char *, enum debug_var_kind, bfd_vma));
+static boolean ieee_start_function PARAMS ((PTR, const char *, boolean));
+static boolean ieee_function_parameter
+ PARAMS ((PTR, const char *, enum debug_parm_kind, bfd_vma));
+static boolean ieee_start_block PARAMS ((PTR, bfd_vma));
+static boolean ieee_end_block PARAMS ((PTR, bfd_vma));
+static boolean ieee_end_function PARAMS ((PTR));
+static boolean ieee_lineno
+ PARAMS ((PTR, const char *, unsigned long, bfd_vma));
+
+static const struct debug_write_fns ieee_fns =
+{
+ ieee_start_compilation_unit,
+ ieee_start_source,
+ ieee_empty_type,
+ ieee_void_type,
+ ieee_int_type,
+ ieee_float_type,
+ ieee_complex_type,
+ ieee_bool_type,
+ ieee_enum_type,
+ ieee_pointer_type,
+ ieee_function_type,
+ ieee_reference_type,
+ ieee_range_type,
+ ieee_array_type,
+ ieee_set_type,
+ ieee_offset_type,
+ ieee_method_type,
+ ieee_const_type,
+ ieee_volatile_type,
+ ieee_start_struct_type,
+ ieee_struct_field,
+ ieee_end_struct_type,
+ ieee_start_class_type,
+ ieee_class_static_member,
+ ieee_class_baseclass,
+ ieee_class_start_method,
+ ieee_class_method_variant,
+ ieee_class_static_method_variant,
+ ieee_class_end_method,
+ ieee_end_class_type,
+ ieee_typedef_type,
+ ieee_tag_type,
+ ieee_typdef,
+ ieee_tag,
+ ieee_int_constant,
+ ieee_float_constant,
+ ieee_typed_constant,
+ ieee_variable,
+ ieee_start_function,
+ ieee_function_parameter,
+ ieee_start_block,
+ ieee_end_block,
+ ieee_end_function,
+ ieee_lineno
+};
+
+/* Initialize a buffer to be empty. */
+
+/*ARGSUSED*/
+static boolean
+ieee_init_buffer (info, buflist)
+ struct ieee_handle *info;
+ struct ieee_buflist *buflist;
+{
+ buflist->head = NULL;
+ buflist->tail = NULL;
+ return true;
+}
+
+/* See whether a buffer list has any data. */
+
+#define ieee_buffer_emptyp(buflist) ((buflist)->head == NULL)
+
+/* Change the current buffer to a specified buffer chain. */
+
+static boolean
+ieee_change_buffer (info, buflist)
+ struct ieee_handle *info;
+ struct ieee_buflist *buflist;
+{
+ if (buflist->head == NULL)
+ {
+ struct ieee_buf *buf;
+
+ buf = (struct ieee_buf *) xmalloc (sizeof *buf);
+ buf->next = NULL;
+ buf->c = 0;
+ buflist->head = buf;
+ buflist->tail = buf;
+ }
+
+ info->current = buflist;
+ info->curbuf = buflist->tail;
+
+ return true;
+}
+
+/* Append a buffer chain. */
+
+/*ARGSUSED*/
+static boolean
+ieee_append_buffer (info, mainbuf, newbuf)
+ struct ieee_handle *info;
+ struct ieee_buflist *mainbuf;
+ struct ieee_buflist *newbuf;
+{
+ if (newbuf->head != NULL)
+ {
+ if (mainbuf->head == NULL)
+ mainbuf->head = newbuf->head;
+ else
+ mainbuf->tail->next = newbuf->head;
+ mainbuf->tail = newbuf->tail;
+ }
+ return true;
+}
+
+/* Write a byte into the buffer. We use a macro for speed and a
+ function for the complex cases. */
+
+#define ieee_write_byte(info, b) \
+ ((info)->curbuf->c < IEEE_BUFSIZE \
+ ? ((info)->curbuf->buf[(info)->curbuf->c++] = (b), true) \
+ : ieee_real_write_byte ((info), (b)))
+
+static boolean
+ieee_real_write_byte (info, b)
+ struct ieee_handle *info;
+ int b;
+{
+ if (info->curbuf->c >= IEEE_BUFSIZE)
+ {
+ struct ieee_buf *n;
+
+ n = (struct ieee_buf *) xmalloc (sizeof *n);
+ n->next = NULL;
+ n->c = 0;
+ if (info->current->head == NULL)
+ info->current->head = n;
+ else
+ info->current->tail->next = n;
+ info->current->tail = n;
+ info->curbuf = n;
+ }
+
+ info->curbuf->buf[info->curbuf->c] = b;
+ ++info->curbuf->c;
+
+ return true;
+}
+
+/* Write out two bytes. */
+
+static boolean
+ieee_write_2bytes (info, i)
+ struct ieee_handle *info;
+ int i;
+{
+ return (ieee_write_byte (info, i >> 8)
+ && ieee_write_byte (info, i & 0xff));
+}
+
+/* Write out an integer. */
+
+static boolean
+ieee_write_number (info, v)
+ struct ieee_handle *info;
+ bfd_vma v;
+{
+ bfd_vma t;
+ bfd_byte ab[20];
+ bfd_byte *p;
+ unsigned int c;
+
+ if (v <= (bfd_vma) ieee_number_end_enum)
+ return ieee_write_byte (info, (int) v);
+
+ t = v;
+ p = ab + sizeof ab;
+ while (t != 0)
+ {
+ *--p = t & 0xff;
+ t >>= 8;
+ }
+ c = (ab + 20) - p;
+
+ if (c > (unsigned int) (ieee_number_repeat_end_enum
+ - ieee_number_repeat_start_enum))
+ {
+ fprintf (stderr, "IEEE numeric overflow: 0x");
+ fprintf_vma (stderr, v);
+ fprintf (stderr, "\n");
+ return false;
+ }
+
+ if (! ieee_write_byte (info, (int) ieee_number_repeat_start_enum + c))
+ return false;
+ for (; c > 0; --c, ++p)
+ {
+ if (! ieee_write_byte (info, *p))
+ return false;
+ }
+
+ return true;
+}
+
+/* Write out a string. */
+
+static boolean
+ieee_write_id (info, s)
+ struct ieee_handle *info;
+ const char *s;
+{
+ unsigned int len;
+
+ len = strlen (s);
+ if (len <= 0x7f)
+ {
+ if (! ieee_write_byte (info, len))
+ return false;
+ }
+ else if (len <= 0xff)
+ {
+ if (! ieee_write_byte (info, (int) ieee_extension_length_1_enum)
+ || ! ieee_write_byte (info, len))
+ return false;
+ }
+ else if (len <= 0xffff)
+ {
+ if (! ieee_write_byte (info, (int) ieee_extension_length_2_enum)
+ || ! ieee_write_2bytes (info, len))
+ return false;
+ }
+ else
+ {
+ fprintf (stderr, "IEEE string length overflow: %u\n", len);
+ return false;
+ }
+
+ for (; *s != '\0'; s++)
+ if (! ieee_write_byte (info, *s))
+ return false;
+
+ return true;
+}
+
+/* Write out an ASN record. */
+
+static boolean
+ieee_write_asn (info, indx, val)
+ struct ieee_handle *info;
+ unsigned int indx;
+ bfd_vma val;
+{
+ return (ieee_write_2bytes (info, (int) ieee_asn_record_enum)
+ && ieee_write_number (info, indx)
+ && ieee_write_number (info, val));
+}
+
+/* Write out an ATN65 record. */
+
+static boolean
+ieee_write_atn65 (info, indx, s)
+ struct ieee_handle *info;
+ unsigned int indx;
+ const char *s;
+{
+ return (ieee_write_2bytes (info, (int) ieee_atn_record_enum)
+ && ieee_write_number (info, indx)
+ && ieee_write_number (info, 0)
+ && ieee_write_number (info, 65)
+ && ieee_write_id (info, s));
+}
+
+/* Push a type index onto the type stack. */
+
+static boolean
+ieee_push_type (info, indx, size, unsignedp, localp)
+ struct ieee_handle *info;
+ unsigned int indx;
+ unsigned int size;
+ boolean unsignedp;
+ boolean localp;
+{
+ struct ieee_type_stack *ts;
+
+ ts = (struct ieee_type_stack *) xmalloc (sizeof *ts);
+ memset (ts, 0, sizeof *ts);
+
+ ts->type.indx = indx;
+ ts->type.size = size;
+ ts->type.unsignedp = unsignedp;
+ ts->type.localp = localp;
+
+ ts->next = info->type_stack;
+ info->type_stack = ts;
+
+ return true;
+}
+
+/* Pop a type index off the type stack. */
+
+static unsigned int
+ieee_pop_type (info)
+ struct ieee_handle *info;
+{
+ return ieee_pop_type_used (info, true);
+}
+
+/* Pop an unused type index off the type stack. */
+
+static void
+ieee_pop_unused_type (info)
+ struct ieee_handle *info;
+{
+ (void) ieee_pop_type_used (info, false);
+}
+
+/* Pop a used or unused type index off the type stack. */
+
+static unsigned int
+ieee_pop_type_used (info, used)
+ struct ieee_handle *info;
+ boolean used;
+{
+ struct ieee_type_stack *ts;
+ unsigned int ret;
+
+ ts = info->type_stack;
+ assert (ts != NULL);
+
+ /* If this is a function type, and we need it, we need to append the
+ actual definition to the typedef block now. */
+ if (used && ! ieee_buffer_emptyp (&ts->type.fndef))
+ {
+ struct ieee_buflist *buflist;
+
+ if (ts->type.localp)
+ {
+ /* Make sure we have started the types block. */
+ if (ieee_buffer_emptyp (&info->types))
+ {
+ if (! ieee_change_buffer (info, &info->types)
+ || ! ieee_write_byte (info, (int) ieee_bb_record_enum)
+ || ! ieee_write_byte (info, 1)
+ || ! ieee_write_number (info, 0)
+ || ! ieee_write_id (info, info->modname))
+ return false;
+ }
+ buflist = &info->types;
+ }
+ else
+ {
+ /* Make sure we started the global type block. */
+ if (ieee_buffer_emptyp (&info->global_types))
+ {
+ if (! ieee_change_buffer (info, &info->global_types)
+ || ! ieee_write_byte (info, (int) ieee_bb_record_enum)
+ || ! ieee_write_byte (info, 2)
+ || ! ieee_write_number (info, 0)
+ || ! ieee_write_id (info, ""))
+ return false;
+ }
+ buflist = &info->global_types;
+ }
+
+ if (! ieee_append_buffer (info, buflist, &ts->type.fndef))
+ return false;
+ }
+
+ ret = ts->type.indx;
+ info->type_stack = ts->next;
+ free (ts);
+ return ret;
+}
+
+/* Add a range of bytes included in the current compilation unit. */
+
+static boolean
+ieee_add_range (info, global, low, high)
+ struct ieee_handle *info;
+ boolean global;
+ bfd_vma low;
+ bfd_vma high;
+{
+ struct ieee_range **plist, *r, **pr;
+
+ if (low == (bfd_vma) -1 || high == (bfd_vma) -1 || low == high)
+ return true;
+
+ if (global)
+ plist = &info->global_ranges;
+ else
+ plist = &info->ranges;
+
+ for (r = *plist; r != NULL; r = r->next)
+ {
+ if (high >= r->low && low <= r->high)
+ {
+ /* The new range overlaps r. */
+ if (low < r->low)
+ r->low = low;
+ if (high > r->high)
+ r->high = high;
+ pr = &r->next;
+ while (*pr != NULL && (*pr)->low <= r->high)
+ {
+ struct ieee_range *n;
+
+ if ((*pr)->high > r->high)
+ r->high = (*pr)->high;
+ n = (*pr)->next;
+ free (*pr);
+ *pr = n;
+ }
+ return true;
+ }
+ }
+
+ r = (struct ieee_range *) xmalloc (sizeof *r);
+ memset (r, 0, sizeof *r);
+
+ r->low = low;
+ r->high = high;
+
+ /* Store the ranges sorted by address. */
+ for (pr = plist; *pr != NULL; pr = &(*pr)->next)
+ if ((*pr)->low > high)
+ break;
+ r->next = *pr;
+ *pr = r;
+
+ return true;
+}
+
+/* Start a new range for which we only have the low address. */
+
+static boolean
+ieee_start_range (info, low)
+ struct ieee_handle *info;
+ bfd_vma low;
+{
+ struct ieee_range *r;
+
+ r = (struct ieee_range *) xmalloc (sizeof *r);
+ memset (r, 0, sizeof *r);
+ r->low = low;
+ r->next = info->pending_ranges;
+ info->pending_ranges = r;
+ return true;
+}
+
+/* Finish a range started by ieee_start_range. */
+
+static boolean
+ieee_end_range (info, high)
+ struct ieee_handle *info;
+ bfd_vma high;
+{
+ struct ieee_range *r;
+ bfd_vma low;
+
+ assert (info->pending_ranges != NULL);
+ r = info->pending_ranges;
+ low = r->low;
+ info->pending_ranges = r->next;
+ free (r);
+ return ieee_add_range (info, false, low, high);
+}
+
+/* Start defining a type. */
+
+static boolean
+ieee_define_type (info, size, unsignedp, localp)
+ struct ieee_handle *info;
+ unsigned int size;
+ boolean unsignedp;
+ boolean localp;
+{
+ return ieee_define_named_type (info, (const char *) NULL,
+ (unsigned int) -1, size, unsignedp,
+ localp, (struct ieee_buflist *) NULL);
+}
+
+/* Start defining a named type. */
+
+static boolean
+ieee_define_named_type (info, name, indx, size, unsignedp, localp, buflist)
+ struct ieee_handle *info;
+ const char *name;
+ unsigned int indx;
+ unsigned int size;
+ boolean unsignedp;
+ boolean localp;
+ struct ieee_buflist *buflist;
+{
+ unsigned int type_indx;
+ unsigned int name_indx;
+
+ if (indx != (unsigned int) -1)
+ type_indx = indx;
+ else
+ {
+ type_indx = info->type_indx;
+ ++info->type_indx;
+ }
+
+ name_indx = info->name_indx;
+ ++info->name_indx;
+
+ if (name == NULL)
+ name = "";
+
+ /* If we were given a buffer, use it; otherwise, use either the
+ local or the global type information, and make sure that the type
+ block is started. */
+ if (buflist != NULL)
+ {
+ if (! ieee_change_buffer (info, buflist))
+ return false;
+ }
+ else if (localp)
+ {
+ if (! ieee_buffer_emptyp (&info->types))
+ {
+ if (! ieee_change_buffer (info, &info->types))
+ return false;
+ }
+ else
+ {
+ if (! ieee_change_buffer (info, &info->types)
+ || ! ieee_write_byte (info, (int) ieee_bb_record_enum)
+ || ! ieee_write_byte (info, 1)
+ || ! ieee_write_number (info, 0)
+ || ! ieee_write_id (info, info->modname))
+ return false;
+ }
+ }
+ else
+ {
+ if (! ieee_buffer_emptyp (&info->global_types))
+ {
+ if (! ieee_change_buffer (info, &info->global_types))
+ return false;
+ }
+ else
+ {
+ if (! ieee_change_buffer (info, &info->global_types)
+ || ! ieee_write_byte (info, (int) ieee_bb_record_enum)
+ || ! ieee_write_byte (info, 2)
+ || ! ieee_write_number (info, 0)
+ || ! ieee_write_id (info, ""))
+ return false;
+ }
+ }
+
+ /* Push the new type on the type stack, write out an NN record, and
+ write out the start of a TY record. The caller will then finish
+ the TY record. */
+ if (! ieee_push_type (info, type_indx, size, unsignedp, localp))
+ return false;
+
+ return (ieee_write_byte (info, (int) ieee_nn_record)
+ && ieee_write_number (info, name_indx)
+ && ieee_write_id (info, name)
+ && ieee_write_byte (info, (int) ieee_ty_record_enum)
+ && ieee_write_number (info, type_indx)
+ && ieee_write_byte (info, 0xce)
+ && ieee_write_number (info, name_indx));
+}
+
+/* Get an entry to the list of modified versions of a type. */
+
+static struct ieee_modified_type *
+ieee_get_modified_info (info, indx)
+ struct ieee_handle *info;
+ unsigned int indx;
+{
+ if (indx >= info->modified_alloc)
+ {
+ unsigned int nalloc;
+
+ nalloc = info->modified_alloc;
+ if (nalloc == 0)
+ nalloc = 16;
+ while (indx >= nalloc)
+ nalloc *= 2;
+ info->modified = ((struct ieee_modified_type *)
+ xrealloc (info->modified,
+ nalloc * sizeof *info->modified));
+ memset (info->modified + info->modified_alloc, 0,
+ (nalloc - info->modified_alloc) * sizeof *info->modified);
+ info->modified_alloc = nalloc;
+ }
+
+ return info->modified + indx;
+}
+
+/* Routines for the hash table mapping names to types. */
+
+/* Initialize an entry in the hash table. */
+
+static struct bfd_hash_entry *
+ieee_name_type_newfunc (entry, table, string)
+ struct bfd_hash_entry *entry;
+ struct bfd_hash_table *table;
+ const char *string;
+{
+ struct ieee_name_type_hash_entry *ret =
+ (struct ieee_name_type_hash_entry *) entry;
+
+ /* Allocate the structure if it has not already been allocated by a
+ subclass. */
+ if (ret == NULL)
+ ret = ((struct ieee_name_type_hash_entry *)
+ bfd_hash_allocate (table, sizeof *ret));
+ if (ret == NULL)
+ return NULL;
+
+ /* Call the allocation method of the superclass. */
+ ret = ((struct ieee_name_type_hash_entry *)
+ bfd_hash_newfunc ((struct bfd_hash_entry *) ret, table, string));
+ if (ret)
+ {
+ /* Set local fields. */
+ ret->types = NULL;
+ }
+
+ return (struct bfd_hash_entry *) ret;
+}
+
+/* Look up an entry in the hash table. */
+
+#define ieee_name_type_hash_lookup(table, string, create, copy) \
+ ((struct ieee_name_type_hash_entry *) \
+ bfd_hash_lookup (&(table)->root, (string), (create), (copy)))
+
+/* Traverse the hash table. */
+
+#define ieee_name_type_hash_traverse(table, func, info) \
+ (bfd_hash_traverse \
+ (&(table)->root, \
+ (boolean (*) PARAMS ((struct bfd_hash_entry *, PTR))) (func), \
+ (info)))
+
+/* The general routine to write out IEEE debugging information. */
+
+boolean
+write_ieee_debugging_info (abfd, dhandle)
+ bfd *abfd;
+ PTR dhandle;
+{
+ struct ieee_handle info;
+ asection *s;
+ const char *err;
+ struct ieee_buf *b;
+
+ memset (&info, 0, sizeof info);
+ info.abfd = abfd;
+ info.type_indx = 256;
+ info.name_indx = 32;
+
+ if (! bfd_hash_table_init (&info.typedefs.root, ieee_name_type_newfunc)
+ || ! bfd_hash_table_init (&info.tags.root, ieee_name_type_newfunc))
+ return false;
+
+ if (! ieee_init_buffer (&info, &info.global_types)
+ || ! ieee_init_buffer (&info, &info.data)
+ || ! ieee_init_buffer (&info, &info.types)
+ || ! ieee_init_buffer (&info, &info.vars)
+ || ! ieee_init_buffer (&info, &info.cxx)
+ || ! ieee_init_buffer (&info, &info.linenos)
+ || ! ieee_init_buffer (&info, &info.fntype)
+ || ! ieee_init_buffer (&info, &info.fnargs))
+ return false;
+
+ if (! debug_write (dhandle, &ieee_fns, (PTR) &info))
+ return false;
+
+ if (info.filename != NULL)
+ {
+ if (! ieee_finish_compilation_unit (&info))
+ return false;
+ }
+
+ /* Put any undefined tags in the global typedef information. */
+ info.error = false;
+ ieee_name_type_hash_traverse (&info.tags,
+ ieee_write_undefined_tag,
+ (PTR) &info);
+ if (info.error)
+ return false;
+
+ /* Prepend the global typedef information to the other data. */
+ if (! ieee_buffer_emptyp (&info.global_types))
+ {
+ /* The HP debugger seems to have a bug in which it ignores the
+ last entry in the global types, so we add a dummy entry. */
+ if (! ieee_change_buffer (&info, &info.global_types)
+ || ! ieee_write_byte (&info, (int) ieee_nn_record)
+ || ! ieee_write_number (&info, info.name_indx)
+ || ! ieee_write_id (&info, "")
+ || ! ieee_write_byte (&info, (int) ieee_ty_record_enum)
+ || ! ieee_write_number (&info, info.type_indx)
+ || ! ieee_write_byte (&info, 0xce)
+ || ! ieee_write_number (&info, info.name_indx)
+ || ! ieee_write_number (&info, 'P')
+ || ! ieee_write_number (&info, (int) builtin_void + 32)
+ || ! ieee_write_byte (&info, (int) ieee_be_record_enum))
+ return false;
+
+ if (! ieee_append_buffer (&info, &info.global_types, &info.data))
+ return false;
+ info.data = info.global_types;
+ }
+
+ /* Make sure that we have declare BB11 blocks for each range in the
+ file. They are added to info->vars. */
+ info.error = false;
+ if (! ieee_init_buffer (&info, &info.vars))
+ return false;
+ bfd_map_over_sections (abfd, ieee_add_bb11_blocks, (PTR) &info);
+ if (info.error)
+ return false;
+ if (! ieee_buffer_emptyp (&info.vars))
+ {
+ if (! ieee_change_buffer (&info, &info.vars)
+ || ! ieee_write_byte (&info, (int) ieee_be_record_enum))
+ return false;
+
+ if (! ieee_append_buffer (&info, &info.data, &info.vars))
+ return false;
+ }
+
+ /* Now all the data is in info.data. Write it out to the BFD. We
+ normally would need to worry about whether all the other sections
+ are set up yet, but the IEEE backend will handle this particular
+ case correctly regardless. */
+ if (ieee_buffer_emptyp (&info.data))
+ {
+ /* There is no debugging information. */
+ return true;
+ }
+ err = NULL;
+ s = bfd_make_section (abfd, ".debug");
+ if (s == NULL)
+ err = "bfd_make_section";
+ if (err == NULL)
+ {
+ if (! bfd_set_section_flags (abfd, s, SEC_DEBUGGING | SEC_HAS_CONTENTS))
+ err = "bfd_set_section_flags";
+ }
+ if (err == NULL)
+ {
+ bfd_size_type size;
+
+ size = 0;
+ for (b = info.data.head; b != NULL; b = b->next)
+ size += b->c;
+ if (! bfd_set_section_size (abfd, s, size))
+ err = "bfd_set_section_size";
+ }
+ if (err == NULL)
+ {
+ file_ptr offset;
+
+ offset = 0;
+ for (b = info.data.head; b != NULL; b = b->next)
+ {
+ if (! bfd_set_section_contents (abfd, s, b->buf, offset, b->c))
+ {
+ err = "bfd_set_section_contents";
+ break;
+ }
+ offset += b->c;
+ }
+ }
+
+ if (err != NULL)
+ {
+ fprintf (stderr, "%s: %s: %s\n", bfd_get_filename (abfd), err,
+ bfd_errmsg (bfd_get_error ()));
+ return false;
+ }
+
+ bfd_hash_table_free (&info.typedefs.root);
+ bfd_hash_table_free (&info.tags.root);
+
+ return true;
+}
+
+/* Write out information for an undefined tag. This is called via
+ ieee_name_type_hash_traverse. */
+
+static boolean
+ieee_write_undefined_tag (h, p)
+ struct ieee_name_type_hash_entry *h;
+ PTR p;
+{
+ struct ieee_handle *info = (struct ieee_handle *) p;
+ struct ieee_name_type *nt;
+
+ for (nt = h->types; nt != NULL; nt = nt->next)
+ {
+ unsigned int name_indx;
+ char code;
+
+ if (nt->kind == DEBUG_KIND_ILLEGAL)
+ continue;
+
+ if (ieee_buffer_emptyp (&info->global_types))
+ {
+ if (! ieee_change_buffer (info, &info->global_types)
+ || ! ieee_write_byte (info, (int) ieee_bb_record_enum)
+ || ! ieee_write_byte (info, 2)
+ || ! ieee_write_number (info, 0)
+ || ! ieee_write_id (info, ""))
+ {
+ info->error = true;
+ return false;
+ }
+ }
+ else
+ {
+ if (! ieee_change_buffer (info, &info->global_types))
+ {
+ info->error = true;
+ return false;
+ }
+ }
+
+ name_indx = info->name_indx;
+ ++info->name_indx;
+ if (! ieee_write_byte (info, (int) ieee_nn_record)
+ || ! ieee_write_number (info, name_indx)
+ || ! ieee_write_id (info, nt->type.name)
+ || ! ieee_write_byte (info, (int) ieee_ty_record_enum)
+ || ! ieee_write_number (info, nt->type.indx)
+ || ! ieee_write_byte (info, 0xce)
+ || ! ieee_write_number (info, name_indx))
+ {
+ info->error = true;
+ return false;
+ }
+
+ switch (nt->kind)
+ {
+ default:
+ abort ();
+ info->error = true;
+ return false;
+ case DEBUG_KIND_STRUCT:
+ case DEBUG_KIND_CLASS:
+ code = 'S';
+ break;
+ case DEBUG_KIND_UNION:
+ case DEBUG_KIND_UNION_CLASS:
+ code = 'U';
+ break;
+ case DEBUG_KIND_ENUM:
+ code = 'E';
+ break;
+ }
+ if (! ieee_write_number (info, code)
+ || ! ieee_write_number (info, 0))
+ {
+ info->error = true;
+ return false;
+ }
+ }
+
+ return true;
+}
+
+/* Start writing out information for a compilation unit. */
+
+static boolean
+ieee_start_compilation_unit (p, filename)
+ PTR p;
+ const char *filename;
+{
+ struct ieee_handle *info = (struct ieee_handle *) p;
+ const char *modname;
+ char *c, *s;
+ unsigned int nindx;
+
+ if (info->filename != NULL)
+ {
+ if (! ieee_finish_compilation_unit (info))
+ return false;
+ }
+
+ info->filename = filename;
+ modname = strrchr (filename, '/');
+ if (modname != NULL)
+ ++modname;
+ else
+ {
+ modname = strrchr (filename, '\\');
+ if (modname != NULL)
+ ++modname;
+ else
+ modname = filename;
+ }
+ c = xstrdup (modname);
+ s = strrchr (c, '.');
+ if (s != NULL)
+ *s = '\0';
+ info->modname = c;
+
+ if (! ieee_init_buffer (info, &info->types)
+ || ! ieee_init_buffer (info, &info->vars)
+ || ! ieee_init_buffer (info, &info->cxx)
+ || ! ieee_init_buffer (info, &info->linenos))
+ return false;
+ info->ranges = NULL;
+
+ /* Always include a BB1 and a BB3 block. That is what the output of
+ the MRI linker seems to look like. */
+ if (! ieee_change_buffer (info, &info->types)
+ || ! ieee_write_byte (info, (int) ieee_bb_record_enum)
+ || ! ieee_write_byte (info, 1)
+ || ! ieee_write_number (info, 0)
+ || ! ieee_write_id (info, info->modname))
+ return false;
+
+ nindx = info->name_indx;
+ ++info->name_indx;
+ if (! ieee_change_buffer (info, &info->vars)
+ || ! ieee_write_byte (info, (int) ieee_bb_record_enum)
+ || ! ieee_write_byte (info, 3)
+ || ! ieee_write_number (info, 0)
+ || ! ieee_write_id (info, info->modname))
+ return false;
+
+ return true;
+}
+
+/* Finish up a compilation unit. */
+
+static boolean
+ieee_finish_compilation_unit (info)
+ struct ieee_handle *info;
+{
+ struct ieee_range *r;
+
+ if (! ieee_buffer_emptyp (&info->types))
+ {
+ if (! ieee_change_buffer (info, &info->types)
+ || ! ieee_write_byte (info, (int) ieee_be_record_enum))
+ return false;
+ }
+
+ if (! ieee_buffer_emptyp (&info->cxx))
+ {
+ /* Append any C++ information to the global function and
+ variable information. */
+ assert (! ieee_buffer_emptyp (&info->vars));
+ if (! ieee_change_buffer (info, &info->vars))
+ return false;
+
+ /* We put the pmisc records in a dummy procedure, just as the
+ MRI compiler does. */
+ if (! ieee_write_byte (info, (int) ieee_bb_record_enum)
+ || ! ieee_write_byte (info, 6)
+ || ! ieee_write_number (info, 0)
+ || ! ieee_write_id (info, "__XRYCPP")
+ || ! ieee_write_number (info, 0)
+ || ! ieee_write_number (info, 0)
+ || ! ieee_write_number (info, info->highaddr - 1)
+ || ! ieee_append_buffer (info, &info->vars, &info->cxx)
+ || ! ieee_change_buffer (info, &info->vars)
+ || ! ieee_write_byte (info, (int) ieee_be_record_enum)
+ || ! ieee_write_number (info, info->highaddr - 1))
+ return false;
+ }
+
+ if (! ieee_buffer_emptyp (&info->vars))
+ {
+ if (! ieee_change_buffer (info, &info->vars)
+ || ! ieee_write_byte (info, (int) ieee_be_record_enum))
+ return false;
+ }
+
+ if (info->pending_lineno_filename != NULL)
+ {
+ /* Force out the pending line number. */
+ if (! ieee_lineno ((PTR) info, (const char *) NULL, 0, (bfd_vma) -1))
+ return false;
+ }
+ if (! ieee_buffer_emptyp (&info->linenos))
+ {
+ if (! ieee_change_buffer (info, &info->linenos)
+ || ! ieee_write_byte (info, (int) ieee_be_record_enum))
+ return false;
+ if (strcmp (info->filename, info->lineno_filename) != 0)
+ {
+ /* We were not in the main file. We just closed the
+ included line number block, and now we must close the
+ main line number block. */
+ if (! ieee_write_byte (info, (int) ieee_be_record_enum))
+ return false;
+ }
+ }
+
+ if (! ieee_append_buffer (info, &info->data, &info->types)
+ || ! ieee_append_buffer (info, &info->data, &info->vars)
+ || ! ieee_append_buffer (info, &info->data, &info->linenos))
+ return false;
+
+ /* Build BB10/BB11 blocks based on the ranges we recorded. */
+ if (! ieee_change_buffer (info, &info->data))
+ return false;
+
+ if (! ieee_write_byte (info, (int) ieee_bb_record_enum)
+ || ! ieee_write_byte (info, 10)
+ || ! ieee_write_number (info, 0)
+ || ! ieee_write_id (info, info->modname)
+ || ! ieee_write_id (info, "")
+ || ! ieee_write_number (info, 0)
+ || ! ieee_write_id (info, "GNU objcopy"))
+ return false;
+
+ for (r = info->ranges; r != NULL; r = r->next)
+ {
+ bfd_vma low, high;
+ asection *s;
+ int kind;
+
+ low = r->low;
+ high = r->high;
+
+ /* Find the section corresponding to this range. */
+ for (s = info->abfd->sections; s != NULL; s = s->next)
+ {
+ if (bfd_get_section_vma (info->abfd, s) <= low
+ && high <= (bfd_get_section_vma (info->abfd, s)
+ + bfd_section_size (info->abfd, s)))
+ break;
+ }
+
+ if (s == NULL)
+ {
+ /* Just ignore this range. */
+ continue;
+ }
+
+ /* Coalesce ranges if it seems reasonable. */
+ while (r->next != NULL
+ && high + 0x1000 >= r->next->low
+ && (r->next->high
+ <= (bfd_get_section_vma (info->abfd, s)
+ + bfd_section_size (info->abfd, s))))
+ {
+ r = r->next;
+ high = r->high;
+ }
+
+ if ((s->flags & SEC_CODE) != 0)
+ kind = 1;
+ else if ((s->flags & SEC_READONLY) != 0)
+ kind = 3;
+ else
+ kind = 2;
+
+ if (! ieee_write_byte (info, (int) ieee_bb_record_enum)
+ || ! ieee_write_byte (info, 11)
+ || ! ieee_write_number (info, 0)
+ || ! ieee_write_id (info, "")
+ || ! ieee_write_number (info, kind)
+ || ! ieee_write_number (info, s->index + IEEE_SECTION_NUMBER_BASE)
+ || ! ieee_write_number (info, low)
+ || ! ieee_write_byte (info, (int) ieee_be_record_enum)
+ || ! ieee_write_number (info, high - low))
+ return false;
+
+ /* Add this range to the list of global ranges. */
+ if (! ieee_add_range (info, true, low, high))
+ return false;
+ }
+
+ if (! ieee_write_byte (info, (int) ieee_be_record_enum))
+ return false;
+
+ return true;
+}
+
+/* Add BB11 blocks describing each range that we have not already
+ described. */
+
+static void
+ieee_add_bb11_blocks (abfd, sec, data)
+ bfd *abfd;
+ asection *sec;
+ PTR data;
+{
+ struct ieee_handle *info = (struct ieee_handle *) data;
+ bfd_vma low, high;
+ struct ieee_range *r;
+
+ low = bfd_get_section_vma (abfd, sec);
+ high = low + bfd_section_size (abfd, sec);
+
+ /* Find the first range at or after this section. The ranges are
+ sorted by address. */
+ for (r = info->global_ranges; r != NULL; r = r->next)
+ if (r->high > low)
+ break;
+
+ while (low < high)
+ {
+ if (r == NULL || r->low >= high)
+ {
+ if (! ieee_add_bb11 (info, sec, low, high))
+ info->error = true;
+ return;
+ }
+
+ if (low < r->low
+ && r->low - low > 0x100)
+ {
+ if (! ieee_add_bb11 (info, sec, low, r->low))
+ {
+ info->error = true;
+ return;
+ }
+ }
+ low = r->high;
+
+ r = r->next;
+ }
+}
+
+/* Add a single BB11 block for a range. We add it to info->vars. */
+
+static boolean
+ieee_add_bb11 (info, sec, low, high)
+ struct ieee_handle *info;
+ asection *sec;
+ bfd_vma low;
+ bfd_vma high;
+{
+ int kind;
+
+ if (! ieee_buffer_emptyp (&info->vars))
+ {
+ if (! ieee_change_buffer (info, &info->vars))
+ return false;
+ }
+ else
+ {
+ const char *filename, *modname;
+ char *c, *s;
+
+ /* Start the enclosing BB10 block. */
+ filename = bfd_get_filename (info->abfd);
+ modname = strrchr (filename, '/');
+ if (modname != NULL)
+ ++modname;
+ else
+ {
+ modname = strrchr (filename, '\\');
+ if (modname != NULL)
+ ++modname;
+ else
+ modname = filename;
+ }
+ c = xstrdup (modname);
+ s = strrchr (c, '.');
+ if (s != NULL)
+ *s = '\0';
+
+ if (! ieee_change_buffer (info, &info->vars)
+ || ! ieee_write_byte (info, (int) ieee_bb_record_enum)
+ || ! ieee_write_byte (info, 10)
+ || ! ieee_write_number (info, 0)
+ || ! ieee_write_id (info, c)
+ || ! ieee_write_id (info, "")
+ || ! ieee_write_number (info, 0)
+ || ! ieee_write_id (info, "GNU objcopy"))
+ return false;
+
+ free (c);
+ }
+
+ if ((sec->flags & SEC_CODE) != 0)
+ kind = 1;
+ else if ((sec->flags & SEC_READONLY) != 0)
+ kind = 3;
+ else
+ kind = 2;
+
+ if (! ieee_write_byte (info, (int) ieee_bb_record_enum)
+ || ! ieee_write_byte (info, 11)
+ || ! ieee_write_number (info, 0)
+ || ! ieee_write_id (info, "")
+ || ! ieee_write_number (info, kind)
+ || ! ieee_write_number (info, sec->index + IEEE_SECTION_NUMBER_BASE)
+ || ! ieee_write_number (info, low)
+ || ! ieee_write_byte (info, (int) ieee_be_record_enum)
+ || ! ieee_write_number (info, high - low))
+ return false;
+
+ return true;
+}
+
+/* Start recording information from a particular source file. This is
+ used to record which file defined which types, variables, etc. It
+ is not used for line numbers, since the lineno entry point passes
+ down the file name anyhow. IEEE debugging information doesn't seem
+ to store this information anywhere. */
+
+/*ARGSUSED*/
+static boolean
+ieee_start_source (p, filename)
+ PTR p;
+ const char *filename;
+{
+ return true;
+}
+
+/* Make an empty type. */
+
+static boolean
+ieee_empty_type (p)
+ PTR p;
+{
+ struct ieee_handle *info = (struct ieee_handle *) p;
+
+ return ieee_push_type (info, (int) builtin_unknown, 0, false, false);
+}
+
+/* Make a void type. */
+
+static boolean
+ieee_void_type (p)
+ PTR p;
+{
+ struct ieee_handle *info = (struct ieee_handle *) p;
+
+ return ieee_push_type (info, (int) builtin_void, 0, false, false);
+}
+
+/* Make an integer type. */
+
+static boolean
+ieee_int_type (p, size, unsignedp)
+ PTR p;
+ unsigned int size;
+ boolean unsignedp;
+{
+ struct ieee_handle *info = (struct ieee_handle *) p;
+ unsigned int indx;
+
+ switch (size)
+ {
+ case 1:
+ indx = (int) builtin_signed_char;
+ break;
+ case 2:
+ indx = (int) builtin_signed_short_int;
+ break;
+ case 4:
+ indx = (int) builtin_signed_long;
+ break;
+ case 8:
+ indx = (int) builtin_signed_long_long;
+ break;
+ default:
+ fprintf (stderr, "IEEE unsupported integer type size %u\n", size);
+ return false;
+ }
+
+ if (unsignedp)
+ ++indx;
+
+ return ieee_push_type (info, indx, size, unsignedp, false);
+}
+
+/* Make a floating point type. */
+
+static boolean
+ieee_float_type (p, size)
+ PTR p;
+ unsigned int size;
+{
+ struct ieee_handle *info = (struct ieee_handle *) p;
+ unsigned int indx;
+
+ switch (size)
+ {
+ case 4:
+ indx = (int) builtin_float;
+ break;
+ case 8:
+ indx = (int) builtin_double;
+ break;
+ case 12:
+ /* FIXME: This size really depends upon the processor. */
+ indx = (int) builtin_long_double;
+ break;
+ case 16:
+ indx = (int) builtin_long_long_double;
+ break;
+ default:
+ fprintf (stderr, "IEEE unsupported float type size %u\n", size);
+ return false;
+ }
+
+ return ieee_push_type (info, indx, size, false, false);
+}
+
+/* Make a complex type. */
+
+static boolean
+ieee_complex_type (p, size)
+ PTR p;
+ unsigned int size;
+{
+ struct ieee_handle *info = (struct ieee_handle *) p;
+ char code;
+
+ switch (size)
+ {
+ case 4:
+ if (info->complex_float_index != 0)
+ return ieee_push_type (info, info->complex_float_index, size * 2,
+ false, false);
+ code = 'c';
+ break;
+ case 12:
+ case 16:
+ /* These cases can be output by gcc -gstabs. Outputting the
+ wrong type is better than crashing. */
+ case 8:
+ if (info->complex_double_index != 0)
+ return ieee_push_type (info, info->complex_double_index, size * 2,
+ false, false);
+ code = 'd';
+ break;
+ default:
+ fprintf (stderr, "IEEE unsupported complex type size %u\n", size);
+ return false;
+ }
+
+ /* FIXME: I don't know what the string is for. */
+ if (! ieee_define_type (info, size * 2, false, false)
+ || ! ieee_write_number (info, code)
+ || ! ieee_write_id (info, ""))
+ return false;
+
+ if (size == 4)
+ info->complex_float_index = info->type_stack->type.indx;
+ else
+ info->complex_double_index = info->type_stack->type.indx;
+
+ return true;
+}
+
+/* Make a boolean type. IEEE doesn't support these, so we just make
+ an integer type instead. */
+
+static boolean
+ieee_bool_type (p, size)
+ PTR p;
+ unsigned int size;
+{
+ return ieee_int_type (p, size, true);
+}
+
+/* Make an enumeration. */
+
+static boolean
+ieee_enum_type (p, tag, names, vals)
+ PTR p;
+ const char *tag;
+ const char **names;
+ bfd_signed_vma *vals;
+{
+ struct ieee_handle *info = (struct ieee_handle *) p;
+ struct ieee_defined_enum *e;
+ boolean localp, simple;
+ unsigned int indx;
+ int i = 0;
+
+ localp = false;
+ indx = (unsigned int) -1;
+ for (e = info->enums; e != NULL; e = e->next)
+ {
+ if (tag == NULL)
+ {
+ if (e->tag != NULL)
+ continue;
+ }
+ else
+ {
+ if (e->tag == NULL
+ || tag[0] != e->tag[0]
+ || strcmp (tag, e->tag) != 0)
+ continue;
+ }
+
+ if (! e->defined)
+ {
+ /* This enum tag has been seen but not defined. */
+ indx = e->indx;
+ break;
+ }
+
+ if (names != NULL && e->names != NULL)
+ {
+ for (i = 0; names[i] != NULL && e->names[i] != NULL; i++)
+ {
+ if (names[i][0] != e->names[i][0]
+ || vals[i] != e->vals[i]
+ || strcmp (names[i], e->names[i]) != 0)
+ break;
+ }
+ }
+
+ if ((names == NULL && e->names == NULL)
+ || (names != NULL
+ && e->names != NULL
+ && names[i] == NULL
+ && e->names[i] == NULL))
+ {
+ /* We've seen this enum before. */
+ return ieee_push_type (info, e->indx, 0, true, false);
+ }
+
+ if (tag != NULL)
+ {
+ /* We've already seen an enum of the same name, so we must make
+ sure to output this one locally. */
+ localp = true;
+ break;
+ }
+ }
+
+ /* If this is a simple enumeration, in which the values start at 0
+ and always increment by 1, we can use type E. Otherwise we must
+ use type N. */
+
+ simple = true;
+ if (names != NULL)
+ {
+ for (i = 0; names[i] != NULL; i++)
+ {
+ if (vals[i] != i)
+ {
+ simple = false;
+ break;
+ }
+ }
+ }
+
+ if (! ieee_define_named_type (info, tag, indx, 0, true, localp,
+ (struct ieee_buflist *) NULL)
+ || ! ieee_write_number (info, simple ? 'E' : 'N'))
+ return false;
+ if (simple)
+ {
+ /* FIXME: This is supposed to be the enumeration size, but we
+ don't store that. */
+ if (! ieee_write_number (info, 4))
+ return false;
+ }
+ if (names != NULL)
+ {
+ for (i = 0; names[i] != NULL; i++)
+ {
+ if (! ieee_write_id (info, names[i]))
+ return false;
+ if (! simple)
+ {
+ if (! ieee_write_number (info, vals[i]))
+ return false;
+ }
+ }
+ }
+
+ if (! localp)
+ {
+ if (indx == (unsigned int) -1)
+ {
+ e = (struct ieee_defined_enum *) xmalloc (sizeof *e);
+ memset (e, 0, sizeof *e);
+ e->indx = info->type_stack->type.indx;
+ e->tag = tag;
+
+ e->next = info->enums;
+ info->enums = e;
+ }
+
+ e->names = names;
+ e->vals = vals;
+ e->defined = true;
+ }
+
+ return true;
+}
+
+/* Make a pointer type. */
+
+static boolean
+ieee_pointer_type (p)
+ PTR p;
+{
+ struct ieee_handle *info = (struct ieee_handle *) p;
+ boolean localp;
+ unsigned int indx;
+ struct ieee_modified_type *m = NULL;
+
+ localp = info->type_stack->type.localp;
+ indx = ieee_pop_type (info);
+
+ /* A pointer to a simple builtin type can be obtained by adding 32.
+ FIXME: Will this be a short pointer, and will that matter? */
+ if (indx < 32)
+ return ieee_push_type (info, indx + 32, 0, true, false);
+
+ if (! localp)
+ {
+ m = ieee_get_modified_info (p, indx);
+ if (m == NULL)
+ return false;
+
+ /* FIXME: The size should depend upon the architecture. */
+ if (m->pointer > 0)
+ return ieee_push_type (info, m->pointer, 4, true, false);
+ }
+
+ if (! ieee_define_type (info, 4, true, localp)
+ || ! ieee_write_number (info, 'P')
+ || ! ieee_write_number (info, indx))
+ return false;
+
+ if (! localp)
+ m->pointer = info->type_stack->type.indx;
+
+ return true;
+}
+
+/* Make a function type. This will be called for a method, but we
+ don't want to actually add it to the type table in that case. We
+ handle this by defining the type in a private buffer, and only
+ adding that buffer to the typedef block if we are going to use it. */
+
+static boolean
+ieee_function_type (p, argcount, varargs)
+ PTR p;
+ int argcount;
+ boolean varargs;
+{
+ struct ieee_handle *info = (struct ieee_handle *) p;
+ boolean localp;
+ unsigned int *args = NULL;
+ int i;
+ unsigned int retindx;
+ struct ieee_buflist fndef;
+ struct ieee_modified_type *m;
+
+ localp = false;
+
+ if (argcount > 0)
+ {
+ args = (unsigned int *) xmalloc (argcount * sizeof *args);
+ for (i = argcount - 1; i >= 0; i--)
+ {
+ if (info->type_stack->type.localp)
+ localp = true;
+ args[i] = ieee_pop_type (info);
+ }
+ }
+ else if (argcount < 0)
+ varargs = false;
+
+ if (info->type_stack->type.localp)
+ localp = true;
+ retindx = ieee_pop_type (info);
+
+ m = NULL;
+ if (argcount < 0 && ! localp)
+ {
+ m = ieee_get_modified_info (p, retindx);
+ if (m == NULL)
+ return false;
+
+ if (m->function > 0)
+ return ieee_push_type (info, m->function, 0, true, false);
+ }
+
+ /* An attribute of 0x41 means that the frame and push mask are
+ unknown. */
+ if (! ieee_init_buffer (info, &fndef)
+ || ! ieee_define_named_type (info, (const char *) NULL,
+ (unsigned int) -1, 0, true, localp,
+ &fndef)
+ || ! ieee_write_number (info, 'x')
+ || ! ieee_write_number (info, 0x41)
+ || ! ieee_write_number (info, 0)
+ || ! ieee_write_number (info, 0)
+ || ! ieee_write_number (info, retindx)
+ || ! ieee_write_number (info, (bfd_vma) argcount + (varargs ? 1 : 0)))
+ return false;
+ if (argcount > 0)
+ {
+ for (i = 0; i < argcount; i++)
+ if (! ieee_write_number (info, args[i]))
+ return false;
+ free (args);
+ }
+ if (varargs)
+ {
+ /* A varargs function is represented by writing out the last
+ argument as type void *, although this makes little sense. */
+ if (! ieee_write_number (info, (bfd_vma) builtin_void + 32))
+ return false;
+ }
+
+ if (! ieee_write_number (info, 0))
+ return false;
+
+ /* We wrote the information into fndef, in case we don't need it.
+ It will be appended to info->types by ieee_pop_type. */
+ info->type_stack->type.fndef = fndef;
+
+ if (m != NULL)
+ m->function = info->type_stack->type.indx;
+
+ return true;
+}
+
+/* Make a reference type. */
+
+static boolean
+ieee_reference_type (p)
+ PTR p;
+{
+ struct ieee_handle *info = (struct ieee_handle *) p;
+
+ /* IEEE appears to record a normal pointer type, and then use a
+ pmisc record to indicate that it is really a reference. */
+
+ if (! ieee_pointer_type (p))
+ return false;
+ info->type_stack->type.referencep = true;
+ return true;
+}
+
+/* Make a range type. */
+
+static boolean
+ieee_range_type (p, low, high)
+ PTR p;
+ bfd_signed_vma low;
+ bfd_signed_vma high;
+{
+ struct ieee_handle *info = (struct ieee_handle *) p;
+ unsigned int size;
+ boolean unsignedp, localp;
+
+ size = info->type_stack->type.size;
+ unsignedp = info->type_stack->type.unsignedp;
+ localp = info->type_stack->type.localp;
+ ieee_pop_unused_type (info);
+ return (ieee_define_type (info, size, unsignedp, localp)
+ && ieee_write_number (info, 'R')
+ && ieee_write_number (info, (bfd_vma) low)
+ && ieee_write_number (info, (bfd_vma) high)
+ && ieee_write_number (info, unsignedp ? 0 : 1)
+ && ieee_write_number (info, size));
+}
+
+/* Make an array type. */
+
+/*ARGSUSED*/
+static boolean
+ieee_array_type (p, low, high, stringp)
+ PTR p;
+ bfd_signed_vma low;
+ bfd_signed_vma high;
+ boolean stringp;
+{
+ struct ieee_handle *info = (struct ieee_handle *) p;
+ unsigned int eleindx;
+ boolean localp;
+ unsigned int size;
+ struct ieee_modified_type *m = NULL;
+ struct ieee_modified_array_type *a;
+
+ /* IEEE does not store the range, so we just ignore it. */
+ ieee_pop_unused_type (info);
+ localp = info->type_stack->type.localp;
+ size = info->type_stack->type.size;
+ eleindx = ieee_pop_type (info);
+
+ /* If we don't know the range, treat the size as exactly one
+ element. */
+ if (low < high)
+ size *= (high - low) + 1;
+
+ if (! localp)
+ {
+ m = ieee_get_modified_info (info, eleindx);
+ if (m == NULL)
+ return false;
+
+ for (a = m->arrays; a != NULL; a = a->next)
+ {
+ if (a->low == low && a->high == high)
+ return ieee_push_type (info, a->indx, size, false, false);
+ }
+ }
+
+ if (! ieee_define_type (info, size, false, localp)
+ || ! ieee_write_number (info, low == 0 ? 'Z' : 'C')
+ || ! ieee_write_number (info, eleindx))
+ return false;
+ if (low != 0)
+ {
+ if (! ieee_write_number (info, low))
+ return false;
+ }
+
+ if (! ieee_write_number (info, high + 1))
+ return false;
+
+ if (! localp)
+ {
+ a = (struct ieee_modified_array_type *) xmalloc (sizeof *a);
+ memset (a, 0, sizeof *a);
+
+ a->indx = info->type_stack->type.indx;
+ a->low = low;
+ a->high = high;
+
+ a->next = m->arrays;
+ m->arrays = a;
+ }
+
+ return true;
+}
+
+/* Make a set type. */
+
+static boolean
+ieee_set_type (p, bitstringp)
+ PTR p;
+ boolean bitstringp;
+{
+ struct ieee_handle *info = (struct ieee_handle *) p;
+ boolean localp;
+ unsigned int eleindx;
+
+ localp = info->type_stack->type.localp;
+ eleindx = ieee_pop_type (info);
+
+ /* FIXME: We don't know the size, so we just use 4. */
+
+ return (ieee_define_type (info, 0, true, localp)
+ && ieee_write_number (info, 's')
+ && ieee_write_number (info, 4)
+ && ieee_write_number (info, eleindx));
+}
+
+/* Make an offset type. */
+
+static boolean
+ieee_offset_type (p)
+ PTR p;
+{
+ struct ieee_handle *info = (struct ieee_handle *) p;
+ unsigned int targetindx, baseindx;
+
+ targetindx = ieee_pop_type (info);
+ baseindx = ieee_pop_type (info);
+
+ /* FIXME: The MRI C++ compiler does not appear to generate any
+ useful type information about an offset type. It just records a
+ pointer to member as an integer. The MRI/HP IEEE spec does
+ describe a pmisc record which can be used for a pointer to
+ member. Unfortunately, it does not describe the target type,
+ which seems pretty important. I'm going to punt this for now. */
+
+ return ieee_int_type (p, 4, true);
+}
+
+/* Make a method type. */
+
+static boolean
+ieee_method_type (p, domain, argcount, varargs)
+ PTR p;
+ boolean domain;
+ int argcount;
+ boolean varargs;
+{
+ struct ieee_handle *info = (struct ieee_handle *) p;
+
+ /* FIXME: The MRI/HP IEEE spec defines a pmisc record to use for a
+ method, but the definition is incomplete. We just output an 'x'
+ type. */
+
+ if (domain)
+ ieee_pop_unused_type (info);
+
+ return ieee_function_type (p, argcount, varargs);
+}
+
+/* Make a const qualified type. */
+
+static boolean
+ieee_const_type (p)
+ PTR p;
+{
+ struct ieee_handle *info = (struct ieee_handle *) p;
+ unsigned int size;
+ boolean unsignedp, localp;
+ unsigned int indx;
+ struct ieee_modified_type *m = NULL;
+
+ size = info->type_stack->type.size;
+ unsignedp = info->type_stack->type.unsignedp;
+ localp = info->type_stack->type.localp;
+ indx = ieee_pop_type (info);
+
+ if (! localp)
+ {
+ m = ieee_get_modified_info (info, indx);
+ if (m == NULL)
+ return false;
+
+ if (m->const_qualified > 0)
+ return ieee_push_type (info, m->const_qualified, size, unsignedp,
+ false);
+ }
+
+ if (! ieee_define_type (info, size, unsignedp, localp)
+ || ! ieee_write_number (info, 'n')
+ || ! ieee_write_number (info, 1)
+ || ! ieee_write_number (info, indx))
+ return false;
+
+ if (! localp)
+ m->const_qualified = info->type_stack->type.indx;
+
+ return true;
+}
+
+/* Make a volatile qualified type. */
+
+static boolean
+ieee_volatile_type (p)
+ PTR p;
+{
+ struct ieee_handle *info = (struct ieee_handle *) p;
+ unsigned int size;
+ boolean unsignedp, localp;
+ unsigned int indx;
+ struct ieee_modified_type *m = NULL;
+
+ size = info->type_stack->type.size;
+ unsignedp = info->type_stack->type.unsignedp;
+ localp = info->type_stack->type.localp;
+ indx = ieee_pop_type (info);
+
+ if (! localp)
+ {
+ m = ieee_get_modified_info (info, indx);
+ if (m == NULL)
+ return false;
+
+ if (m->volatile_qualified > 0)
+ return ieee_push_type (info, m->volatile_qualified, size, unsignedp,
+ false);
+ }
+
+ if (! ieee_define_type (info, size, unsignedp, localp)
+ || ! ieee_write_number (info, 'n')
+ || ! ieee_write_number (info, 2)
+ || ! ieee_write_number (info, indx))
+ return false;
+
+ if (! localp)
+ m->volatile_qualified = info->type_stack->type.indx;
+
+ return true;
+}
+
+/* Convert an enum debug_visibility into a CXXFLAGS value. */
+
+static unsigned int
+ieee_vis_to_flags (visibility)
+ enum debug_visibility visibility;
+{
+ switch (visibility)
+ {
+ default:
+ abort ();
+ case DEBUG_VISIBILITY_PUBLIC:
+ return CXXFLAGS_VISIBILITY_PUBLIC;
+ case DEBUG_VISIBILITY_PRIVATE:
+ return CXXFLAGS_VISIBILITY_PRIVATE;
+ case DEBUG_VISIBILITY_PROTECTED:
+ return CXXFLAGS_VISIBILITY_PROTECTED;
+ }
+ /*NOTREACHED*/
+}
+
+/* Start defining a struct type. We build it in the strdef field on
+ the stack, to avoid confusing type definitions required by the
+ fields with the struct type itself. */
+
+static boolean
+ieee_start_struct_type (p, tag, id, structp, size)
+ PTR p;
+ const char *tag;
+ unsigned int id;
+ boolean structp;
+ unsigned int size;
+{
+ struct ieee_handle *info = (struct ieee_handle *) p;
+ boolean localp, ignorep;
+ boolean copy;
+ char ab[20];
+ const char *look;
+ struct ieee_name_type_hash_entry *h;
+ struct ieee_name_type *nt, *ntlook;
+ struct ieee_buflist strdef;
+
+ localp = false;
+ ignorep = false;
+
+ /* We need to create a tag for internal use even if we don't want
+ one for external use. This will let us refer to an anonymous
+ struct. */
+ if (tag != NULL)
+ {
+ look = tag;
+ copy = false;
+ }
+ else
+ {
+ sprintf (ab, "__anon%u", id);
+ look = ab;
+ copy = true;
+ }
+
+ /* If we already have references to the tag, we must use the
+ existing type index. */
+ h = ieee_name_type_hash_lookup (&info->tags, look, true, copy);
+ if (h == NULL)
+ return false;
+
+ nt = NULL;
+ for (ntlook = h->types; ntlook != NULL; ntlook = ntlook->next)
+ {
+ if (ntlook->id == id)
+ nt = ntlook;
+ else if (! ntlook->type.localp)
+ {
+ /* We are creating a duplicate definition of a globally
+ defined tag. Force it to be local to avoid
+ confusion. */
+ localp = true;
+ }
+ }
+
+ if (nt != NULL)
+ {
+ assert (localp == nt->type.localp);
+ if (nt->kind == DEBUG_KIND_ILLEGAL && ! localp)
+ {
+ /* We've already seen a global definition of the type.
+ Ignore this new definition. */
+ ignorep = true;
+ }
+ }
+ else
+ {
+ nt = (struct ieee_name_type *) xmalloc (sizeof *nt);
+ memset (nt, 0, sizeof *nt);
+ nt->id = id;
+ nt->type.name = h->root.string;
+ nt->next = h->types;
+ h->types = nt;
+ nt->type.indx = info->type_indx;
+ ++info->type_indx;
+ }
+
+ nt->kind = DEBUG_KIND_ILLEGAL;
+
+ if (! ieee_init_buffer (info, &strdef)
+ || ! ieee_define_named_type (info, tag, nt->type.indx, size, true,
+ localp, &strdef)
+ || ! ieee_write_number (info, structp ? 'S' : 'U')
+ || ! ieee_write_number (info, size))
+ return false;
+
+ if (! ignorep)
+ {
+ const char *hold;
+
+ /* We never want nt->type.name to be NULL. We want the rest of
+ the type to be the object set up on the type stack; it will
+ have a NULL name if tag is NULL. */
+ hold = nt->type.name;
+ nt->type = info->type_stack->type;
+ nt->type.name = hold;
+ }
+
+ info->type_stack->type.name = tag;
+ info->type_stack->type.strdef = strdef;
+ info->type_stack->type.ignorep = ignorep;
+
+ return true;
+}
+
+/* Add a field to a struct. */
+
+static boolean
+ieee_struct_field (p, name, bitpos, bitsize, visibility)
+ PTR p;
+ const char *name;
+ bfd_vma bitpos;
+ bfd_vma bitsize;
+ enum debug_visibility visibility;
+{
+ struct ieee_handle *info = (struct ieee_handle *) p;
+ unsigned int size;
+ boolean unsignedp;
+ boolean referencep;
+ boolean localp;
+ unsigned int indx;
+ bfd_vma offset;
+
+ assert (info->type_stack != NULL
+ && info->type_stack->next != NULL
+ && ! ieee_buffer_emptyp (&info->type_stack->next->type.strdef));
+
+ /* If we are ignoring this struct definition, just pop and ignore
+ the type. */
+ if (info->type_stack->next->type.ignorep)
+ {
+ ieee_pop_unused_type (info);
+ return true;
+ }
+
+ size = info->type_stack->type.size;
+ unsignedp = info->type_stack->type.unsignedp;
+ referencep = info->type_stack->type.referencep;
+ localp = info->type_stack->type.localp;
+ indx = ieee_pop_type (info);
+
+ if (localp)
+ info->type_stack->type.localp = true;
+
+ if (info->type_stack->type.classdef != NULL)
+ {
+ unsigned int flags;
+ unsigned int nindx;
+
+ /* This is a class. We must add a description of this field to
+ the class records we are building. */
+
+ flags = ieee_vis_to_flags (visibility);
+ nindx = info->type_stack->type.classdef->indx;
+ if (! ieee_change_buffer (info,
+ &info->type_stack->type.classdef->pmiscbuf)
+ || ! ieee_write_asn (info, nindx, 'd')
+ || ! ieee_write_asn (info, nindx, flags)
+ || ! ieee_write_atn65 (info, nindx, name)
+ || ! ieee_write_atn65 (info, nindx, name))
+ return false;
+ info->type_stack->type.classdef->pmisccount += 4;
+
+ if (referencep)
+ {
+ unsigned int nindx;
+
+ /* We need to output a record recording that this field is
+ really of reference type. We put this on the refs field
+ of classdef, so that it can be appended to the C++
+ records after the class is defined. */
+
+ nindx = info->name_indx;
+ ++info->name_indx;
+
+ if (! ieee_change_buffer (info,
+ &info->type_stack->type.classdef->refs)
+ || ! ieee_write_byte (info, (int) ieee_nn_record)
+ || ! ieee_write_number (info, nindx)
+ || ! ieee_write_id (info, "")
+ || ! ieee_write_2bytes (info, (int) ieee_atn_record_enum)
+ || ! ieee_write_number (info, nindx)
+ || ! ieee_write_number (info, 0)
+ || ! ieee_write_number (info, 62)
+ || ! ieee_write_number (info, 80)
+ || ! ieee_write_number (info, 4)
+ || ! ieee_write_asn (info, nindx, 'R')
+ || ! ieee_write_asn (info, nindx, 3)
+ || ! ieee_write_atn65 (info, nindx, info->type_stack->type.name)
+ || ! ieee_write_atn65 (info, nindx, name))
+ return false;
+ }
+ }
+
+ /* If the bitsize doesn't match the expected size, we need to output
+ a bitfield type. */
+ if (size == 0 || bitsize == 0 || bitsize == size * 8)
+ offset = bitpos / 8;
+ else
+ {
+ if (! ieee_define_type (info, 0, unsignedp,
+ info->type_stack->type.localp)
+ || ! ieee_write_number (info, 'g')
+ || ! ieee_write_number (info, unsignedp ? 0 : 1)
+ || ! ieee_write_number (info, bitsize)
+ || ! ieee_write_number (info, indx))
+ return false;
+ indx = ieee_pop_type (info);
+ offset = bitpos;
+ }
+
+ /* Switch to the struct we are building in order to output this
+ field definition. */
+ return (ieee_change_buffer (info, &info->type_stack->type.strdef)
+ && ieee_write_id (info, name)
+ && ieee_write_number (info, indx)
+ && ieee_write_number (info, offset));
+}
+
+/* Finish up a struct type. */
+
+static boolean
+ieee_end_struct_type (p)
+ PTR p;
+{
+ struct ieee_handle *info = (struct ieee_handle *) p;
+ struct ieee_buflist *pb;
+
+ assert (info->type_stack != NULL
+ && ! ieee_buffer_emptyp (&info->type_stack->type.strdef));
+
+ /* If we were ignoring this struct definition because it was a
+ duplicate defintion, just through away whatever bytes we have
+ accumulated. Leave the type on the stack. */
+ if (info->type_stack->type.ignorep)
+ return true;
+
+ /* If this is not a duplicate definition of this tag, then localp
+ will be false, and we can put it in the global type block.
+ FIXME: We should avoid outputting duplicate definitions which are
+ the same. */
+ if (! info->type_stack->type.localp)
+ {
+ /* Make sure we have started the global type block. */
+ if (ieee_buffer_emptyp (&info->global_types))
+ {
+ if (! ieee_change_buffer (info, &info->global_types)
+ || ! ieee_write_byte (info, (int) ieee_bb_record_enum)
+ || ! ieee_write_byte (info, 2)
+ || ! ieee_write_number (info, 0)
+ || ! ieee_write_id (info, ""))
+ return false;
+ }
+ pb = &info->global_types;
+ }
+ else
+ {
+ /* Make sure we have started the types block. */
+ if (ieee_buffer_emptyp (&info->types))
+ {
+ if (! ieee_change_buffer (info, &info->types)
+ || ! ieee_write_byte (info, (int) ieee_bb_record_enum)
+ || ! ieee_write_byte (info, 1)
+ || ! ieee_write_number (info, 0)
+ || ! ieee_write_id (info, info->modname))
+ return false;
+ }
+ pb = &info->types;
+ }
+
+ /* Append the struct definition to the types. */
+ if (! ieee_append_buffer (info, pb, &info->type_stack->type.strdef)
+ || ! ieee_init_buffer (info, &info->type_stack->type.strdef))
+ return false;
+
+ /* Leave the struct on the type stack. */
+
+ return true;
+}
+
+/* Start a class type. */
+
+static boolean
+ieee_start_class_type (p, tag, id, structp, size, vptr, ownvptr)
+ PTR p;
+ const char *tag;
+ unsigned int id;
+ boolean structp;
+ unsigned int size;
+ boolean vptr;
+ boolean ownvptr;
+{
+ struct ieee_handle *info = (struct ieee_handle *) p;
+ const char *vclass;
+ struct ieee_buflist pmiscbuf;
+ unsigned int indx;
+ struct ieee_type_class *classdef;
+
+ /* A C++ class is output as a C++ struct along with a set of pmisc
+ records describing the class. */
+
+ /* We need to have a name so that we can associate the struct and
+ the class. */
+ if (tag == NULL)
+ {
+ char *t;
+
+ t = (char *) xmalloc (20);
+ sprintf (t, "__anon%u", id);
+ tag = t;
+ }
+
+ /* We can't write out the virtual table information until we have
+ finished the class, because we don't know the virtual table size.
+ We get the size from the largest voffset we see. */
+ vclass = NULL;
+ if (vptr && ! ownvptr)
+ {
+ vclass = info->type_stack->type.name;
+ assert (vclass != NULL);
+ /* We don't call ieee_pop_unused_type, since the class should
+ get defined. */
+ (void) ieee_pop_type (info);
+ }
+
+ if (! ieee_start_struct_type (p, tag, id, structp, size))
+ return false;
+
+ indx = info->name_indx;
+ ++info->name_indx;
+
+ /* We write out pmisc records into the classdef field. We will
+ write out the pmisc start after we know the number of records we
+ need. */
+ if (! ieee_init_buffer (info, &pmiscbuf)
+ || ! ieee_change_buffer (info, &pmiscbuf)
+ || ! ieee_write_asn (info, indx, 'T')
+ || ! ieee_write_asn (info, indx, structp ? 'o' : 'u')
+ || ! ieee_write_atn65 (info, indx, tag))
+ return false;
+
+ classdef = (struct ieee_type_class *) xmalloc (sizeof *classdef);
+ memset (classdef, 0, sizeof *classdef);
+
+ classdef->indx = indx;
+ classdef->pmiscbuf = pmiscbuf;
+ classdef->pmisccount = 3;
+ classdef->vclass = vclass;
+ classdef->ownvptr = ownvptr;
+
+ info->type_stack->type.classdef = classdef;
+
+ return true;
+}
+
+/* Add a static member to a class. */
+
+static boolean
+ieee_class_static_member (p, name, physname, visibility)
+ PTR p;
+ const char *name;
+ const char *physname;
+ enum debug_visibility visibility;
+{
+ struct ieee_handle *info = (struct ieee_handle *) p;
+ unsigned int flags;
+ unsigned int nindx;
+
+ /* We don't care about the type. Hopefully there will be a call to
+ ieee_variable declaring the physical name and the type, since
+ that is where an IEEE consumer must get the type. */
+ ieee_pop_unused_type (info);
+
+ assert (info->type_stack != NULL
+ && info->type_stack->type.classdef != NULL);
+
+ flags = ieee_vis_to_flags (visibility);
+ flags |= CXXFLAGS_STATIC;
+
+ nindx = info->type_stack->type.classdef->indx;
+
+ if (! ieee_change_buffer (info, &info->type_stack->type.classdef->pmiscbuf)
+ || ! ieee_write_asn (info, nindx, 'd')
+ || ! ieee_write_asn (info, nindx, flags)
+ || ! ieee_write_atn65 (info, nindx, name)
+ || ! ieee_write_atn65 (info, nindx, physname))
+ return false;
+ info->type_stack->type.classdef->pmisccount += 4;
+
+ return true;
+}
+
+/* Add a base class to a class. */
+
+static boolean
+ieee_class_baseclass (p, bitpos, virtual, visibility)
+ PTR p;
+ bfd_vma bitpos;
+ boolean virtual;
+ enum debug_visibility visibility;
+{
+ struct ieee_handle *info = (struct ieee_handle *) p;
+ const char *bname;
+ boolean localp;
+ unsigned int bindx;
+ char *fname;
+ unsigned int flags;
+ unsigned int nindx;
+
+ assert (info->type_stack != NULL
+ && info->type_stack->type.name != NULL
+ && info->type_stack->next != NULL
+ && info->type_stack->next->type.classdef != NULL
+ && ! ieee_buffer_emptyp (&info->type_stack->next->type.strdef));
+
+ bname = info->type_stack->type.name;
+ localp = info->type_stack->type.localp;
+ bindx = ieee_pop_type (info);
+
+ /* We are currently defining both a struct and a class. We must
+ write out a field definition in the struct which holds the base
+ class. The stabs debugging reader will create a field named
+ _vb$CLASS for a virtual base class, so we just use that. FIXME:
+ we should not depend upon a detail of stabs debugging. */
+ if (virtual)
+ {
+ fname = (char *) xmalloc (strlen (bname) + sizeof "_vb$");
+ sprintf (fname, "_vb$%s", bname);
+ flags = BASEFLAGS_VIRTUAL;
+ }
+ else
+ {
+ if (localp)
+ info->type_stack->type.localp = true;
+
+ fname = (char *) xmalloc (strlen (bname) + sizeof "_b$");
+ sprintf (fname, "_b$%s", bname);
+
+ if (! ieee_change_buffer (info, &info->type_stack->type.strdef)
+ || ! ieee_write_id (info, fname)
+ || ! ieee_write_number (info, bindx)
+ || ! ieee_write_number (info, bitpos / 8))
+ return false;
+ flags = 0;
+ }
+
+ if (visibility == DEBUG_VISIBILITY_PRIVATE)
+ flags |= BASEFLAGS_PRIVATE;
+
+ nindx = info->type_stack->type.classdef->indx;
+
+ if (! ieee_change_buffer (info, &info->type_stack->type.classdef->pmiscbuf)
+ || ! ieee_write_asn (info, nindx, 'b')
+ || ! ieee_write_asn (info, nindx, flags)
+ || ! ieee_write_atn65 (info, nindx, bname)
+ || ! ieee_write_asn (info, nindx, 0)
+ || ! ieee_write_atn65 (info, nindx, fname))
+ return false;
+ info->type_stack->type.classdef->pmisccount += 5;
+
+ free (fname);
+
+ return true;
+}
+
+/* Start building a method for a class. */
+
+static boolean
+ieee_class_start_method (p, name)
+ PTR p;
+ const char *name;
+{
+ struct ieee_handle *info = (struct ieee_handle *) p;
+
+ assert (info->type_stack != NULL
+ && info->type_stack->type.classdef != NULL
+ && info->type_stack->type.classdef->method == NULL);
+
+ info->type_stack->type.classdef->method = name;
+
+ return true;
+}
+
+/* Define a new method variant, either static or not. */
+
+static boolean
+ieee_class_method_var (info, physname, visibility, staticp, constp,
+ volatilep, voffset, context)
+ struct ieee_handle *info;
+ const char *physname;
+ enum debug_visibility visibility;
+ boolean staticp;
+ boolean constp;
+ boolean volatilep;
+ bfd_vma voffset;
+ boolean context;
+{
+ unsigned int flags;
+ unsigned int nindx;
+ boolean virtual;
+
+ /* We don't need the type of the method. An IEEE consumer which
+ wants the type must track down the function by the physical name
+ and get the type from that. */
+ ieee_pop_unused_type (info);
+
+ /* We don't use the context. FIXME: We probably ought to use it to
+ adjust the voffset somehow, but I don't really know how. */
+ if (context)
+ ieee_pop_unused_type (info);
+
+ assert (info->type_stack != NULL
+ && info->type_stack->type.classdef != NULL
+ && info->type_stack->type.classdef->method != NULL);
+
+ flags = ieee_vis_to_flags (visibility);
+
+ /* FIXME: We never set CXXFLAGS_OVERRIDE, CXXFLAGS_OPERATOR,
+ CXXFLAGS_CTORDTOR, CXXFLAGS_CTOR, or CXXFLAGS_INLINE. */
+
+ if (staticp)
+ flags |= CXXFLAGS_STATIC;
+ if (constp)
+ flags |= CXXFLAGS_CONST;
+ if (volatilep)
+ flags |= CXXFLAGS_VOLATILE;
+
+ nindx = info->type_stack->type.classdef->indx;
+
+ virtual = context || voffset > 0;
+
+ if (! ieee_change_buffer (info,
+ &info->type_stack->type.classdef->pmiscbuf)
+ || ! ieee_write_asn (info, nindx, virtual ? 'v' : 'm')
+ || ! ieee_write_asn (info, nindx, flags)
+ || ! ieee_write_atn65 (info, nindx,
+ info->type_stack->type.classdef->method)
+ || ! ieee_write_atn65 (info, nindx, physname))
+ return false;
+
+ if (virtual)
+ {
+ if (voffset > info->type_stack->type.classdef->voffset)
+ info->type_stack->type.classdef->voffset = voffset;
+ if (! ieee_write_asn (info, nindx, voffset))
+ return false;
+ ++info->type_stack->type.classdef->pmisccount;
+ }
+
+ if (! ieee_write_asn (info, nindx, 0))
+ return false;
+
+ info->type_stack->type.classdef->pmisccount += 5;
+
+ return true;
+}
+
+/* Define a new method variant. */
+
+static boolean
+ieee_class_method_variant (p, physname, visibility, constp, volatilep,
+ voffset, context)
+ PTR p;
+ const char *physname;
+ enum debug_visibility visibility;
+ boolean constp;
+ boolean volatilep;
+ bfd_vma voffset;
+ boolean context;
+{
+ struct ieee_handle *info = (struct ieee_handle *) p;
+
+ return ieee_class_method_var (info, physname, visibility, false, constp,
+ volatilep, voffset, context);
+}
+
+/* Define a new static method variant. */
+
+static boolean
+ieee_class_static_method_variant (p, physname, visibility, constp, volatilep)
+ PTR p;
+ const char *physname;
+ enum debug_visibility visibility;
+ boolean constp;
+ boolean volatilep;
+{
+ struct ieee_handle *info = (struct ieee_handle *) p;
+
+ return ieee_class_method_var (info, physname, visibility, true, constp,
+ volatilep, 0, false);
+}
+
+/* Finish up a method. */
+
+static boolean
+ieee_class_end_method (p)
+ PTR p;
+{
+ struct ieee_handle *info = (struct ieee_handle *) p;
+
+ assert (info->type_stack != NULL
+ && info->type_stack->type.classdef != NULL
+ && info->type_stack->type.classdef->method != NULL);
+
+ info->type_stack->type.classdef->method = NULL;
+
+ return true;
+}
+
+/* Finish up a class. */
+
+static boolean
+ieee_end_class_type (p)
+ PTR p;
+{
+ struct ieee_handle *info = (struct ieee_handle *) p;
+ unsigned int nindx;
+
+ assert (info->type_stack != NULL
+ && info->type_stack->type.classdef != NULL);
+
+ /* If we were ignoring this class definition because it was a
+ duplicate definition, just through away whatever bytes we have
+ accumulated. Leave the type on the stack. */
+ if (info->type_stack->type.ignorep)
+ return true;
+
+ nindx = info->type_stack->type.classdef->indx;
+
+ /* If we have a virtual table, we can write out the information now. */
+ if (info->type_stack->type.classdef->vclass != NULL
+ || info->type_stack->type.classdef->ownvptr)
+ {
+ if (! ieee_change_buffer (info,
+ &info->type_stack->type.classdef->pmiscbuf)
+ || ! ieee_write_asn (info, nindx, 'z')
+ || ! ieee_write_atn65 (info, nindx, "")
+ || ! ieee_write_asn (info, nindx,
+ info->type_stack->type.classdef->voffset))
+ return false;
+ if (info->type_stack->type.classdef->ownvptr)
+ {
+ if (! ieee_write_atn65 (info, nindx, ""))
+ return false;
+ }
+ else
+ {
+ if (! ieee_write_atn65 (info, nindx,
+ info->type_stack->type.classdef->vclass))
+ return false;
+ }
+ if (! ieee_write_asn (info, nindx, 0))
+ return false;
+ info->type_stack->type.classdef->pmisccount += 5;
+ }
+
+ /* Now that we know the number of pmisc records, we can write out
+ the atn62 which starts the pmisc records, and append them to the
+ C++ buffers. */
+
+ if (! ieee_change_buffer (info, &info->cxx)
+ || ! ieee_write_byte (info, (int) ieee_nn_record)
+ || ! ieee_write_number (info, nindx)
+ || ! ieee_write_id (info, "")
+ || ! ieee_write_2bytes (info, (int) ieee_atn_record_enum)
+ || ! ieee_write_number (info, nindx)
+ || ! ieee_write_number (info, 0)
+ || ! ieee_write_number (info, 62)
+ || ! ieee_write_number (info, 80)
+ || ! ieee_write_number (info,
+ info->type_stack->type.classdef->pmisccount))
+ return false;
+
+ if (! ieee_append_buffer (info, &info->cxx,
+ &info->type_stack->type.classdef->pmiscbuf))
+ return false;
+ if (! ieee_buffer_emptyp (&info->type_stack->type.classdef->refs))
+ {
+ if (! ieee_append_buffer (info, &info->cxx,
+ &info->type_stack->type.classdef->refs))
+ return false;
+ }
+
+ return ieee_end_struct_type (p);
+}
+
+/* Push a previously seen typedef onto the type stack. */
+
+static boolean
+ieee_typedef_type (p, name)
+ PTR p;
+ const char *name;
+{
+ struct ieee_handle *info = (struct ieee_handle *) p;
+ struct ieee_name_type_hash_entry *h;
+ struct ieee_name_type *nt;
+
+ h = ieee_name_type_hash_lookup (&info->typedefs, name, false, false);
+
+ /* h should never be NULL, since that would imply that the generic
+ debugging code has asked for a typedef which it has not yet
+ defined. */
+ assert (h != NULL);
+
+ /* We always use the most recently defined type for this name, which
+ will be the first one on the list. */
+
+ nt = h->types;
+ if (! ieee_push_type (info, nt->type.indx, nt->type.size,
+ nt->type.unsignedp, nt->type.localp))
+ return false;
+
+ /* Copy over any other type information we may have. */
+ info->type_stack->type = nt->type;
+
+ return true;
+}
+
+/* Push a tagged type onto the type stack. */
+
+static boolean
+ieee_tag_type (p, name, id, kind)
+ PTR p;
+ const char *name;
+ unsigned int id;
+ enum debug_type_kind kind;
+{
+ struct ieee_handle *info = (struct ieee_handle *) p;
+ boolean localp;
+ boolean copy;
+ char ab[20];
+ struct ieee_name_type_hash_entry *h;
+ struct ieee_name_type *nt;
+
+ if (kind == DEBUG_KIND_ENUM)
+ {
+ struct ieee_defined_enum *e;
+
+ if (name == NULL)
+ abort ();
+ for (e = info->enums; e != NULL; e = e->next)
+ if (e->tag != NULL && strcmp (e->tag, name) == 0)
+ return ieee_push_type (info, e->indx, 0, true, false);
+
+ e = (struct ieee_defined_enum *) xmalloc (sizeof *e);
+ memset (e, 0, sizeof *e);
+
+ e->indx = info->type_indx;
+ ++info->type_indx;
+ e->tag = name;
+ e->defined = false;
+
+ e->next = info->enums;
+ info->enums = e;
+
+ return ieee_push_type (info, e->indx, 0, true, false);
+ }
+
+ localp = false;
+
+ copy = false;
+ if (name == NULL)
+ {
+ sprintf (ab, "__anon%u", id);
+ name = ab;
+ copy = true;
+ }
+
+ h = ieee_name_type_hash_lookup (&info->tags, name, true, copy);
+ if (h == NULL)
+ return false;
+
+ for (nt = h->types; nt != NULL; nt = nt->next)
+ {
+ if (nt->id == id)
+ {
+ if (! ieee_push_type (info, nt->type.indx, nt->type.size,
+ nt->type.unsignedp, nt->type.localp))
+ return false;
+ /* Copy over any other type information we may have. */
+ info->type_stack->type = nt->type;
+ return true;
+ }
+
+ if (! nt->type.localp)
+ {
+ /* This is a duplicate of a global type, so it must be
+ local. */
+ localp = true;
+ }
+ }
+
+ nt = (struct ieee_name_type *) xmalloc (sizeof *nt);
+ memset (nt, 0, sizeof *nt);
+
+ nt->id = id;
+ nt->type.name = h->root.string;
+ nt->type.indx = info->type_indx;
+ nt->type.localp = localp;
+ ++info->type_indx;
+ nt->kind = kind;
+
+ nt->next = h->types;
+ h->types = nt;
+
+ if (! ieee_push_type (info, nt->type.indx, 0, false, localp))
+ return false;
+
+ info->type_stack->type.name = h->root.string;
+
+ return true;
+}
+
+/* Output a typedef. */
+
+static boolean
+ieee_typdef (p, name)
+ PTR p;
+ const char *name;
+{
+ struct ieee_handle *info = (struct ieee_handle *) p;
+ struct ieee_write_type type;
+ unsigned int indx;
+ boolean found;
+ boolean localp;
+ struct ieee_name_type_hash_entry *h;
+ struct ieee_name_type *nt;
+
+ type = info->type_stack->type;
+ indx = type.indx;
+
+ /* If this is a simple builtin type using a builtin name, we don't
+ want to output the typedef itself. We also want to change the
+ type index to correspond to the name being used. We recognize
+ names used in stabs debugging output even if they don't exactly
+ correspond to the names used for the IEEE builtin types. */
+ found = false;
+ if (indx <= (unsigned int) builtin_bcd_float)
+ {
+ switch ((enum builtin_types) indx)
+ {
+ default:
+ break;
+
+ case builtin_void:
+ if (strcmp (name, "void") == 0)
+ found = true;
+ break;
+
+ case builtin_signed_char:
+ case builtin_char:
+ if (strcmp (name, "signed char") == 0)
+ {
+ indx = (unsigned int) builtin_signed_char;
+ found = true;
+ }
+ else if (strcmp (name, "char") == 0)
+ {
+ indx = (unsigned int) builtin_char;
+ found = true;
+ }
+ break;
+
+ case builtin_unsigned_char:
+ if (strcmp (name, "unsigned char") == 0)
+ found = true;
+ break;
+
+ case builtin_signed_short_int:
+ case builtin_short:
+ case builtin_short_int:
+ case builtin_signed_short:
+ if (strcmp (name, "signed short int") == 0)
+ {
+ indx = (unsigned int) builtin_signed_short_int;
+ found = true;
+ }
+ else if (strcmp (name, "short") == 0)
+ {
+ indx = (unsigned int) builtin_short;
+ found = true;
+ }
+ else if (strcmp (name, "short int") == 0)
+ {
+ indx = (unsigned int) builtin_short_int;
+ found = true;
+ }
+ else if (strcmp (name, "signed short") == 0)
+ {
+ indx = (unsigned int) builtin_signed_short;
+ found = true;
+ }
+ break;
+
+ case builtin_unsigned_short_int:
+ case builtin_unsigned_short:
+ if (strcmp (name, "unsigned short int") == 0
+ || strcmp (name, "short unsigned int") == 0)
+ {
+ indx = builtin_unsigned_short_int;
+ found = true;
+ }
+ else if (strcmp (name, "unsigned short") == 0)
+ {
+ indx = builtin_unsigned_short;
+ found = true;
+ }
+ break;
+
+ case builtin_signed_long:
+ case builtin_int: /* FIXME: Size depends upon architecture. */
+ case builtin_long:
+ if (strcmp (name, "signed long") == 0)
+ {
+ indx = builtin_signed_long;
+ found = true;
+ }
+ else if (strcmp (name, "int") == 0)
+ {
+ indx = builtin_int;
+ found = true;
+ }
+ else if (strcmp (name, "long") == 0
+ || strcmp (name, "long int") == 0)
+ {
+ indx = builtin_long;
+ found = true;
+ }
+ break;
+
+ case builtin_unsigned_long:
+ case builtin_unsigned: /* FIXME: Size depends upon architecture. */
+ case builtin_unsigned_int: /* FIXME: Like builtin_unsigned. */
+ if (strcmp (name, "unsigned long") == 0
+ || strcmp (name, "long unsigned int") == 0)
+ {
+ indx = builtin_unsigned_long;
+ found = true;
+ }
+ else if (strcmp (name, "unsigned") == 0)
+ {
+ indx = builtin_unsigned;
+ found = true;
+ }
+ else if (strcmp (name, "unsigned int") == 0)
+ {
+ indx = builtin_unsigned_int;
+ found = true;
+ }
+ break;
+
+ case builtin_signed_long_long:
+ if (strcmp (name, "signed long long") == 0
+ || strcmp (name, "long long int") == 0)
+ found = true;
+ break;
+
+ case builtin_unsigned_long_long:
+ if (strcmp (name, "unsigned long long") == 0
+ || strcmp (name, "long long unsigned int") == 0)
+ found = true;
+ break;
+
+ case builtin_float:
+ if (strcmp (name, "float") == 0)
+ found = true;
+ break;
+
+ case builtin_double:
+ if (strcmp (name, "double") == 0)
+ found = true;
+ break;
+
+ case builtin_long_double:
+ if (strcmp (name, "long double") == 0)
+ found = true;
+ break;
+
+ case builtin_long_long_double:
+ if (strcmp (name, "long long double") == 0)
+ found = true;
+ break;
+ }
+
+ if (found)
+ type.indx = indx;
+ }
+
+ h = ieee_name_type_hash_lookup (&info->typedefs, name, true, false);
+ if (h == NULL)
+ return false;
+
+ /* See if we have already defined this type with this name. */
+ localp = type.localp;
+ for (nt = h->types; nt != NULL; nt = nt->next)
+ {
+ if (nt->id == indx)
+ {
+ /* If this is a global definition, then we don't need to
+ do anything here. */
+ if (! nt->type.localp)
+ {
+ ieee_pop_unused_type (info);
+ return true;
+ }
+ }
+ else
+ {
+ /* This is a duplicate definition, so make this one local. */
+ localp = true;
+ }
+ }
+
+ /* We need to add a new typedef for this type. */
+
+ nt = (struct ieee_name_type *) xmalloc (sizeof *nt);
+ memset (nt, 0, sizeof *nt);
+ nt->id = indx;
+ nt->type = type;
+ nt->type.name = name;
+ nt->type.localp = localp;
+ nt->kind = DEBUG_KIND_ILLEGAL;
+
+ nt->next = h->types;
+ h->types = nt;
+
+ if (found)
+ {
+ /* This is one of the builtin typedefs, so we don't need to
+ actually define it. */
+ ieee_pop_unused_type (info);
+ return true;
+ }
+
+ indx = ieee_pop_type (info);
+
+ if (! ieee_define_named_type (info, name, (unsigned int) -1, type.size,
+ type.unsignedp, localp,
+ (struct ieee_buflist *) NULL)
+ || ! ieee_write_number (info, 'T')
+ || ! ieee_write_number (info, indx))
+ return false;
+
+ /* Remove the type we just added to the type stack. This should not
+ be ieee_pop_unused_type, since the type is used, we just don't
+ need it now. */
+ (void) ieee_pop_type (info);
+
+ return true;
+}
+
+/* Output a tag for a type. We don't have to do anything here. */
+
+static boolean
+ieee_tag (p, name)
+ PTR p;
+ const char *name;
+{
+ struct ieee_handle *info = (struct ieee_handle *) p;
+
+ /* This should not be ieee_pop_unused_type, since we want the type
+ to be defined. */
+ (void) ieee_pop_type (info);
+ return true;
+}
+
+/* Output an integer constant. */
+
+static boolean
+ieee_int_constant (p, name, val)
+ PTR p;
+ const char *name;
+ bfd_vma val;
+{
+ /* FIXME. */
+ return true;
+}
+
+/* Output a floating point constant. */
+
+static boolean
+ieee_float_constant (p, name, val)
+ PTR p;
+ const char *name;
+ double val;
+{
+ /* FIXME. */
+ return true;
+}
+
+/* Output a typed constant. */
+
+static boolean
+ieee_typed_constant (p, name, val)
+ PTR p;
+ const char *name;
+ bfd_vma val;
+{
+ struct ieee_handle *info = (struct ieee_handle *) p;
+
+ /* FIXME. */
+ ieee_pop_unused_type (info);
+ return true;
+}
+
+/* Output a variable. */
+
+static boolean
+ieee_variable (p, name, kind, val)
+ PTR p;
+ const char *name;
+ enum debug_var_kind kind;
+ bfd_vma val;
+{
+ struct ieee_handle *info = (struct ieee_handle *) p;
+ unsigned int name_indx;
+ unsigned int size;
+ boolean referencep;
+ unsigned int type_indx;
+ boolean asn;
+ int refflag;
+
+ size = info->type_stack->type.size;
+ referencep = info->type_stack->type.referencep;
+ type_indx = ieee_pop_type (info);
+
+ assert (! ieee_buffer_emptyp (&info->vars));
+ if (! ieee_change_buffer (info, &info->vars))
+ return false;
+
+ name_indx = info->name_indx;
+ ++info->name_indx;
+
+ /* Write out an NN and an ATN record for this variable. */
+ if (! ieee_write_byte (info, (int) ieee_nn_record)
+ || ! ieee_write_number (info, name_indx)
+ || ! ieee_write_id (info, name)
+ || ! ieee_write_2bytes (info, (int) ieee_atn_record_enum)
+ || ! ieee_write_number (info, name_indx)
+ || ! ieee_write_number (info, type_indx))
+ return false;
+ switch (kind)
+ {
+ default:
+ abort ();
+ return false;
+ case DEBUG_GLOBAL:
+ if (! ieee_write_number (info, 8)
+ || ! ieee_add_range (info, false, val, val + size))
+ return false;
+ refflag = 0;
+ asn = true;
+ break;
+ case DEBUG_STATIC:
+ if (! ieee_write_number (info, 3)
+ || ! ieee_add_range (info, false, val, val + size))
+ return false;
+ refflag = 1;
+ asn = true;
+ break;
+ case DEBUG_LOCAL_STATIC:
+ if (! ieee_write_number (info, 3)
+ || ! ieee_add_range (info, false, val, val + size))
+ return false;
+ refflag = 2;
+ asn = true;
+ break;
+ case DEBUG_LOCAL:
+ if (! ieee_write_number (info, 1)
+ || ! ieee_write_number (info, val))
+ return false;
+ refflag = 2;
+ asn = false;
+ break;
+ case DEBUG_REGISTER:
+ if (! ieee_write_number (info, 2)
+ || ! ieee_write_number (info,
+ ieee_genreg_to_regno (info->abfd, val)))
+ return false;
+ refflag = 2;
+ asn = false;
+ break;
+ }
+
+ if (asn)
+ {
+ if (! ieee_write_asn (info, name_indx, val))
+ return false;
+ }
+
+ /* If this is really a reference type, then we just output it with
+ pointer type, and must now output a C++ record indicating that it
+ is really reference type. */
+ if (referencep)
+ {
+ unsigned int nindx;
+
+ nindx = info->name_indx;
+ ++info->name_indx;
+
+ /* If this is a global variable, we want to output the misc
+ record in the C++ misc record block. Otherwise, we want to
+ output it just after the variable definition, which is where
+ the current buffer is. */
+ if (refflag != 2)
+ {
+ if (! ieee_change_buffer (info, &info->cxx))
+ return false;
+ }
+
+ if (! ieee_write_byte (info, (int) ieee_nn_record)
+ || ! ieee_write_number (info, nindx)
+ || ! ieee_write_id (info, "")
+ || ! ieee_write_2bytes (info, (int) ieee_atn_record_enum)
+ || ! ieee_write_number (info, nindx)
+ || ! ieee_write_number (info, 0)
+ || ! ieee_write_number (info, 62)
+ || ! ieee_write_number (info, 80)
+ || ! ieee_write_number (info, 3)
+ || ! ieee_write_asn (info, nindx, 'R')
+ || ! ieee_write_asn (info, nindx, refflag)
+ || ! ieee_write_atn65 (info, nindx, name))
+ return false;
+ }
+
+ return true;
+}
+
+/* Start outputting information for a function. */
+
+static boolean
+ieee_start_function (p, name, global)
+ PTR p;
+ const char *name;
+ boolean global;
+{
+ struct ieee_handle *info = (struct ieee_handle *) p;
+ boolean referencep;
+ unsigned int retindx, typeindx;
+
+ referencep = info->type_stack->type.referencep;
+ retindx = ieee_pop_type (info);
+
+ /* Besides recording a BB4 or BB6 block, we record the type of the
+ function in the BB1 typedef block. We can't write out the full
+ type until we have seen all the parameters, so we accumulate it
+ in info->fntype and info->fnargs. */
+ if (! ieee_buffer_emptyp (&info->fntype))
+ {
+ /* FIXME: This might happen someday if we support nested
+ functions. */
+ abort ();
+ }
+
+ info->fnname = name;
+
+ /* An attribute of 0x40 means that the push mask is unknown. */
+ if (! ieee_define_named_type (info, name, (unsigned int) -1, 0, false, true,
+ &info->fntype)
+ || ! ieee_write_number (info, 'x')
+ || ! ieee_write_number (info, 0x40)
+ || ! ieee_write_number (info, 0)
+ || ! ieee_write_number (info, 0)
+ || ! ieee_write_number (info, retindx))
+ return false;
+
+ typeindx = ieee_pop_type (info);
+
+ if (! ieee_init_buffer (info, &info->fnargs))
+ return false;
+ info->fnargcount = 0;
+
+ /* If the function return value is actually a reference type, we
+ must add a record indicating that. */
+ if (referencep)
+ {
+ unsigned int nindx;
+
+ nindx = info->name_indx;
+ ++info->name_indx;
+ if (! ieee_change_buffer (info, &info->cxx)
+ || ! ieee_write_byte (info, (int) ieee_nn_record)
+ || ! ieee_write_number (info, nindx)
+ || ! ieee_write_id (info, "")
+ || ! ieee_write_2bytes (info, (int) ieee_atn_record_enum)
+ || ! ieee_write_number (info, nindx)
+ || ! ieee_write_number (info, 0)
+ || ! ieee_write_number (info, 62)
+ || ! ieee_write_number (info, 80)
+ || ! ieee_write_number (info, 3)
+ || ! ieee_write_asn (info, nindx, 'R')
+ || ! ieee_write_asn (info, nindx, global ? 0 : 1)
+ || ! ieee_write_atn65 (info, nindx, name))
+ return false;
+ }
+
+ assert (! ieee_buffer_emptyp (&info->vars));
+ if (! ieee_change_buffer (info, &info->vars))
+ return false;
+
+ /* The address is written out as the first block. */
+
+ ++info->block_depth;
+
+ return (ieee_write_byte (info, (int) ieee_bb_record_enum)
+ && ieee_write_byte (info, global ? 4 : 6)
+ && ieee_write_number (info, 0)
+ && ieee_write_id (info, name)
+ && ieee_write_number (info, 0)
+ && ieee_write_number (info, typeindx));
+}
+
+/* Add a function parameter. This will normally be called before the
+ first block, so we postpone them until we see the block. */
+
+static boolean
+ieee_function_parameter (p, name, kind, val)
+ PTR p;
+ const char *name;
+ enum debug_parm_kind kind;
+ bfd_vma val;
+{
+ struct ieee_handle *info = (struct ieee_handle *) p;
+ struct ieee_pending_parm *m, **pm;
+
+ assert (info->block_depth == 1);
+
+ m = (struct ieee_pending_parm *) xmalloc (sizeof *m);
+ memset (m, 0, sizeof *m);
+
+ m->next = NULL;
+ m->name = name;
+ m->referencep = info->type_stack->type.referencep;
+ m->type = ieee_pop_type (info);
+ m->kind = kind;
+ m->val = val;
+
+ for (pm = &info->pending_parms; *pm != NULL; pm = &(*pm)->next)
+ ;
+ *pm = m;
+
+ /* Add the type to the fnargs list. */
+ if (! ieee_change_buffer (info, &info->fnargs)
+ || ! ieee_write_number (info, m->type))
+ return false;
+ ++info->fnargcount;
+
+ return true;
+}
+
+/* Output pending function parameters. */
+
+static boolean
+ieee_output_pending_parms (info)
+ struct ieee_handle *info;
+{
+ struct ieee_pending_parm *m;
+ unsigned int refcount;
+
+ refcount = 0;
+ for (m = info->pending_parms; m != NULL; m = m->next)
+ {
+ enum debug_var_kind vkind;
+
+ switch (m->kind)
+ {
+ default:
+ abort ();
+ return false;
+ case DEBUG_PARM_STACK:
+ case DEBUG_PARM_REFERENCE:
+ vkind = DEBUG_LOCAL;
+ break;
+ case DEBUG_PARM_REG:
+ case DEBUG_PARM_REF_REG:
+ vkind = DEBUG_REGISTER;
+ break;
+ }
+
+ if (! ieee_push_type (info, m->type, 0, false, false))
+ return false;
+ info->type_stack->type.referencep = m->referencep;
+ if (m->referencep)
+ ++refcount;
+ if (! ieee_variable ((PTR) info, m->name, vkind, m->val))
+ return false;
+ }
+
+ /* If there are any reference parameters, we need to output a
+ miscellaneous record indicating them. */
+ if (refcount > 0)
+ {
+ unsigned int nindx, varindx;
+
+ /* FIXME: The MRI compiler outputs the demangled function name
+ here, but we are outputting the mangled name. */
+ nindx = info->name_indx;
+ ++info->name_indx;
+ if (! ieee_change_buffer (info, &info->vars)
+ || ! ieee_write_byte (info, (int) ieee_nn_record)
+ || ! ieee_write_number (info, nindx)
+ || ! ieee_write_id (info, "")
+ || ! ieee_write_2bytes (info, (int) ieee_atn_record_enum)
+ || ! ieee_write_number (info, nindx)
+ || ! ieee_write_number (info, 0)
+ || ! ieee_write_number (info, 62)
+ || ! ieee_write_number (info, 80)
+ || ! ieee_write_number (info, refcount + 3)
+ || ! ieee_write_asn (info, nindx, 'B')
+ || ! ieee_write_atn65 (info, nindx, info->fnname)
+ || ! ieee_write_asn (info, nindx, 0))
+ return false;
+ for (m = info->pending_parms, varindx = 1;
+ m != NULL;
+ m = m->next, varindx++)
+ {
+ if (m->referencep)
+ {
+ if (! ieee_write_asn (info, nindx, varindx))
+ return false;
+ }
+ }
+ }
+
+ m = info->pending_parms;
+ while (m != NULL)
+ {
+ struct ieee_pending_parm *next;
+
+ next = m->next;
+ free (m);
+ m = next;
+ }
+
+ info->pending_parms = NULL;
+
+ return true;
+}
+
+/* Start a block. If this is the first block, we output the address
+ to finish the BB4 or BB6, and then output the function parameters. */
+
+static boolean
+ieee_start_block (p, addr)
+ PTR p;
+ bfd_vma addr;
+{
+ struct ieee_handle *info = (struct ieee_handle *) p;
+
+ if (! ieee_change_buffer (info, &info->vars))
+ return false;
+
+ if (info->block_depth == 1)
+ {
+ if (! ieee_write_number (info, addr)
+ || ! ieee_output_pending_parms (info))
+ return false;
+ }
+ else
+ {
+ if (! ieee_write_byte (info, (int) ieee_bb_record_enum)
+ || ! ieee_write_byte (info, 6)
+ || ! ieee_write_number (info, 0)
+ || ! ieee_write_id (info, "")
+ || ! ieee_write_number (info, 0)
+ || ! ieee_write_number (info, 0)
+ || ! ieee_write_number (info, addr))
+ return false;
+ }
+
+ if (! ieee_start_range (info, addr))
+ return false;
+
+ ++info->block_depth;
+
+ return true;
+}
+
+/* End a block. */
+
+static boolean
+ieee_end_block (p, addr)
+ PTR p;
+ bfd_vma addr;
+{
+ struct ieee_handle *info = (struct ieee_handle *) p;
+
+ /* The address we are given is the end of the block, but IEEE seems
+ to want to the address of the last byte in the block, so we
+ subtract one. */
+ if (! ieee_change_buffer (info, &info->vars)
+ || ! ieee_write_byte (info, (int) ieee_be_record_enum)
+ || ! ieee_write_number (info, addr - 1))
+ return false;
+
+ if (! ieee_end_range (info, addr))
+ return false;
+
+ --info->block_depth;
+
+ if (addr > info->highaddr)
+ info->highaddr = addr;
+
+ return true;
+}
+
+/* End a function. */
+
+static boolean
+ieee_end_function (p)
+ PTR p;
+{
+ struct ieee_handle *info = (struct ieee_handle *) p;
+
+ assert (info->block_depth == 1);
+
+ --info->block_depth;
+
+ /* Now we can finish up fntype, and add it to the typdef section.
+ At this point, fntype is the 'x' type up to the argument count,
+ and fnargs is the argument types. We must add the argument
+ count, and we must add the level. FIXME: We don't record varargs
+ functions correctly. In fact, stabs debugging does not give us
+ enough information to do so. */
+ if (! ieee_change_buffer (info, &info->fntype)
+ || ! ieee_write_number (info, info->fnargcount)
+ || ! ieee_change_buffer (info, &info->fnargs)
+ || ! ieee_write_number (info, 0))
+ return false;
+
+ /* Make sure the typdef block has been started. */
+ if (ieee_buffer_emptyp (&info->types))
+ {
+ if (! ieee_change_buffer (info, &info->types)
+ || ! ieee_write_byte (info, (int) ieee_bb_record_enum)
+ || ! ieee_write_byte (info, 1)
+ || ! ieee_write_number (info, 0)
+ || ! ieee_write_id (info, info->modname))
+ return false;
+ }
+
+ if (! ieee_append_buffer (info, &info->types, &info->fntype)
+ || ! ieee_append_buffer (info, &info->types, &info->fnargs))
+ return false;
+
+ info->fnname = NULL;
+ if (! ieee_init_buffer (info, &info->fntype)
+ || ! ieee_init_buffer (info, &info->fnargs))
+ return false;
+ info->fnargcount = 0;
+
+ return true;
+}
+
+/* Record line number information. */
+
+static boolean
+ieee_lineno (p, filename, lineno, addr)
+ PTR p;
+ const char *filename;
+ unsigned long lineno;
+ bfd_vma addr;
+{
+ struct ieee_handle *info = (struct ieee_handle *) p;
+
+ assert (info->filename != NULL);
+
+ /* The HP simulator seems to get confused when more than one line is
+ listed for the same address, at least if they are in different
+ files. We handle this by always listing the last line for a
+ given address, since that seems to be the one that gdb uses. */
+ if (info->pending_lineno_filename != NULL
+ && addr != info->pending_lineno_addr)
+ {
+ /* Make sure we have a line number block. */
+ if (! ieee_buffer_emptyp (&info->linenos))
+ {
+ if (! ieee_change_buffer (info, &info->linenos))
+ return false;
+ }
+ else
+ {
+ info->lineno_name_indx = info->name_indx;
+ ++info->name_indx;
+ if (! ieee_change_buffer (info, &info->linenos)
+ || ! ieee_write_byte (info, (int) ieee_bb_record_enum)
+ || ! ieee_write_byte (info, 5)
+ || ! ieee_write_number (info, 0)
+ || ! ieee_write_id (info, info->filename)
+ || ! ieee_write_byte (info, (int) ieee_nn_record)
+ || ! ieee_write_number (info, info->lineno_name_indx)
+ || ! ieee_write_id (info, ""))
+ return false;
+ info->lineno_filename = info->filename;
+ }
+
+ if (strcmp (info->pending_lineno_filename, info->lineno_filename) != 0)
+ {
+ if (strcmp (info->filename, info->lineno_filename) != 0)
+ {
+ /* We were not in the main file. Close the block for the
+ included file. */
+ if (! ieee_write_byte (info, (int) ieee_be_record_enum))
+ return false;
+ if (strcmp (info->filename, info->pending_lineno_filename) == 0)
+ {
+ /* We need a new NN record, and we aren't about to
+ output one. */
+ info->lineno_name_indx = info->name_indx;
+ ++info->name_indx;
+ if (! ieee_write_byte (info, (int) ieee_nn_record)
+ || ! ieee_write_number (info, info->lineno_name_indx)
+ || ! ieee_write_id (info, ""))
+ return false;
+ }
+ }
+ if (strcmp (info->filename, info->pending_lineno_filename) != 0)
+ {
+ /* We are not changing to the main file. Open a block for
+ the new included file. */
+ info->lineno_name_indx = info->name_indx;
+ ++info->name_indx;
+ if (! ieee_write_byte (info, (int) ieee_bb_record_enum)
+ || ! ieee_write_byte (info, 5)
+ || ! ieee_write_number (info, 0)
+ || ! ieee_write_id (info, info->pending_lineno_filename)
+ || ! ieee_write_byte (info, (int) ieee_nn_record)
+ || ! ieee_write_number (info, info->lineno_name_indx)
+ || ! ieee_write_id (info, ""))
+ return false;
+ }
+ info->lineno_filename = info->pending_lineno_filename;
+ }
+
+ if (! ieee_write_2bytes (info, (int) ieee_atn_record_enum)
+ || ! ieee_write_number (info, info->lineno_name_indx)
+ || ! ieee_write_number (info, 0)
+ || ! ieee_write_number (info, 7)
+ || ! ieee_write_number (info, info->pending_lineno)
+ || ! ieee_write_number (info, 0)
+ || ! ieee_write_asn (info, info->lineno_name_indx,
+ info->pending_lineno_addr))
+ return false;
+ }
+
+ info->pending_lineno_filename = filename;
+ info->pending_lineno = lineno;
+ info->pending_lineno_addr = addr;
+
+ return true;
+}
diff --git a/pstack/ieee.h b/pstack/ieee.h
new file mode 100644
index 00000000000..56634b2819a
--- /dev/null
+++ b/pstack/ieee.h
@@ -0,0 +1,138 @@
+/* IEEE Standard 695-1980 "Universal Format for Object Modules" header file
+ Contributed by Cygnus Support. */
+
+#define N_W_VARIABLES 8
+#define Module_Beginning 0xe0
+
+typedef struct ieee_module {
+ char *processor;
+ char *module_name;
+} ieee_module_begin_type;
+
+#define Address_Descriptor 0xec
+typedef struct ieee_address {
+bfd_vma number_of_bits_mau;
+ bfd_vma number_of_maus_in_address;
+
+ unsigned char byte_order;
+#define IEEE_LITTLE 0xcc
+#define IEEE_BIG 0xcd
+} ieee_address_descriptor_type;
+
+typedef union ieee_w_variable {
+ file_ptr offset[N_W_VARIABLES];
+ struct {
+ file_ptr extension_record;
+ file_ptr environmental_record;
+ file_ptr section_part;
+ file_ptr external_part;
+ file_ptr debug_information_part;
+ file_ptr data_part;
+ file_ptr trailer_part;
+ file_ptr me_record;
+ } r;
+} ieee_w_variable_type;
+
+
+
+
+
+typedef enum ieee_record
+{
+ ieee_number_start_enum = 0x00,
+ ieee_number_end_enum=0x7f,
+ ieee_number_repeat_start_enum = 0x80,
+ ieee_number_repeat_end_enum = 0x88,
+ ieee_number_repeat_4_enum = 0x84,
+ ieee_number_repeat_3_enum = 0x83,
+ ieee_number_repeat_2_enum = 0x82,
+ ieee_number_repeat_1_enum = 0x81,
+ ieee_module_beginning_enum = 0xe0,
+ ieee_module_end_enum = 0xe1,
+ ieee_extension_length_1_enum = 0xde,
+ ieee_extension_length_2_enum = 0xdf,
+ ieee_section_type_enum = 0xe6,
+ ieee_section_alignment_enum = 0xe7,
+ ieee_external_symbol_enum = 0xe8,
+ ieee_comma = 0x90,
+ ieee_external_reference_enum = 0xe9,
+ ieee_set_current_section_enum = 0xe5,
+ ieee_address_descriptor_enum = 0xec,
+ ieee_load_constant_bytes_enum = 0xed,
+ ieee_load_with_relocation_enum = 0xe4,
+
+ ieee_variable_A_enum = 0xc1,
+ ieee_variable_B_enum = 0xc2,
+ ieee_variable_C_enum = 0xc3,
+ ieee_variable_D_enum = 0xc4,
+ ieee_variable_E_enum = 0xc5,
+ ieee_variable_F_enum = 0xc6,
+ ieee_variable_G_enum = 0xc7,
+ ieee_variable_H_enum = 0xc8,
+ ieee_variable_I_enum = 0xc9,
+ ieee_variable_J_enum = 0xca,
+ ieee_variable_K_enum = 0xcb,
+ ieee_variable_L_enum = 0xcc,
+ ieee_variable_M_enum = 0xcd,
+ ieee_variable_N_enum = 0xce,
+ ieee_variable_O_enum = 0xcf,
+ ieee_variable_P_enum = 0xd0,
+ ieee_variable_Q_enum = 0xd1,
+ ieee_variable_R_enum = 0xd2,
+ ieee_variable_S_enum = 0xd3,
+ ieee_variable_T_enum = 0xd4,
+ ieee_variable_U_enum = 0xd5,
+ ieee_variable_V_enum = 0xd6,
+ ieee_variable_W_enum = 0xd7,
+ ieee_variable_X_enum = 0xd8,
+ ieee_variable_Y_enum = 0xd9,
+ ieee_variable_Z_enum = 0xda,
+ ieee_function_plus_enum = 0xa5,
+ ieee_function_minus_enum = 0xa6,
+ ieee_function_signed_open_b_enum = 0xba,
+ ieee_function_signed_close_b_enum = 0xbb,
+
+ ieee_function_unsigned_open_b_enum = 0xbc,
+ ieee_function_unsigned_close_b_enum = 0xbd,
+
+ ieee_function_either_open_b_enum = 0xbe,
+ ieee_function_either_close_b_enum = 0xbf,
+ ieee_record_seperator_enum = 0xdb,
+
+ ieee_e2_first_byte_enum = 0xe2,
+ ieee_section_size_enum = 0xe2d3,
+ ieee_physical_region_size_enum = 0xe2c1,
+ ieee_region_base_address_enum = 0xe2c2,
+ ieee_mau_size_enum = 0xe2c6,
+ ieee_m_value_enum = 0xe2cd,
+ ieee_section_base_address_enum = 0xe2cc,
+ ieee_asn_record_enum = 0xe2ce,
+ ieee_section_offset_enum = 0xe2d2,
+ ieee_value_starting_address_enum = 0xe2c7,
+ ieee_assign_value_to_variable_enum = 0xe2d7,
+ ieee_set_current_pc_enum = 0xe2d0,
+ ieee_value_record_enum = 0xe2c9,
+ ieee_nn_record = 0xf0,
+ ieee_at_record_enum = 0xf1,
+ ieee_ty_record_enum = 0xf2,
+ ieee_attribute_record_enum = 0xf1c9,
+ ieee_atn_record_enum = 0xf1ce,
+ ieee_external_reference_info_record_enum = 0xf1d8,
+ ieee_weak_external_reference_enum= 0xf4,
+ ieee_repeat_data_enum = 0xf7,
+ ieee_bb_record_enum = 0xf8,
+ ieee_be_record_enum = 0xf9
+} ieee_record_enum_type;
+
+
+typedef struct ieee_section {
+ unsigned int section_index;
+ unsigned int section_type;
+ char *section_name;
+ unsigned int parent_section_index;
+ unsigned int sibling_section_index;
+ unsigned int context_index;
+} ieee_section_type;
+#define IEEE_REFERENCE_BASE 11
+#define IEEE_PUBLIC_BASE 32
+#define IEEE_SECTION_NUMBER_BASE 1
diff --git a/pstack/libiberty.h b/pstack/libiberty.h
new file mode 100644
index 00000000000..ca0043d31c6
--- /dev/null
+++ b/pstack/libiberty.h
@@ -0,0 +1,180 @@
+/* Function declarations for libiberty.
+ Written by Cygnus Support, 1994.
+
+ The libiberty library provides a number of functions which are
+ missing on some operating systems. We do not declare those here,
+ to avoid conflicts with the system header files on operating
+ systems that do support those functions. In this file we only
+ declare those functions which are specific to libiberty. */
+
+#ifndef LIBIBERTY_H
+#define LIBIBERTY_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "ansidecl.h"
+
+/* Build an argument vector from a string. Allocates memory using
+ malloc. Use freeargv to free the vector. */
+
+extern char **buildargv PARAMS ((char *));
+
+/* Free a vector returned by buildargv. */
+
+extern void freeargv PARAMS ((char **));
+
+/* Duplicate an argument vector. Allocates memory using malloc. Use
+ freeargv to free the vector. */
+
+extern char **dupargv PARAMS ((char **));
+
+
+/* Return the last component of a path name. Note that we can't use a
+ prototype here because the parameter is declared inconsistently
+ across different systems, sometimes as "char *" and sometimes as
+ "const char *" */
+
+#if defined (__GNU_LIBRARY__ ) || defined (__linux__) || defined (__FreeBSD__)
+extern char *basename PARAMS ((const char *));
+#else
+extern char *basename ();
+#endif
+
+/* Concatenate an arbitrary number of strings, up to (char *) NULL.
+ Allocates memory using xmalloc. */
+
+extern char *concat PARAMS ((const char *, ...));
+
+/* Check whether two file descriptors refer to the same file. */
+
+extern int fdmatch PARAMS ((int fd1, int fd2));
+
+/* Get the amount of time the process has run, in microseconds. */
+
+extern long get_run_time PARAMS ((void));
+
+/* Choose a temporary directory to use for scratch files. */
+
+extern char *choose_temp_base PARAMS ((void));
+
+/* Allocate memory filled with spaces. Allocates using malloc. */
+
+extern const char *spaces PARAMS ((int count));
+
+/* Return the maximum error number for which strerror will return a
+ string. */
+
+extern int errno_max PARAMS ((void));
+
+/* Return the name of an errno value (e.g., strerrno (EINVAL) returns
+ "EINVAL"). */
+
+extern const char *strerrno PARAMS ((int));
+
+/* Given the name of an errno value, return the value. */
+
+extern int strtoerrno PARAMS ((const char *));
+
+/* ANSI's strerror(), but more robust. */
+
+extern char *xstrerror PARAMS ((int));
+
+/* Return the maximum signal number for which strsignal will return a
+ string. */
+
+extern int signo_max PARAMS ((void));
+
+/* Return a signal message string for a signal number
+ (e.g., strsignal (SIGHUP) returns something like "Hangup"). */
+/* This is commented out as it can conflict with one in system headers.
+ We still document its existence though. */
+
+/*extern const char *strsignal PARAMS ((int));*/
+
+/* Return the name of a signal number (e.g., strsigno (SIGHUP) returns
+ "SIGHUP"). */
+
+extern const char *strsigno PARAMS ((int));
+
+/* Given the name of a signal, return its number. */
+
+extern int strtosigno PARAMS ((const char *));
+
+/* Register a function to be run by xexit. Returns 0 on success. */
+
+extern int xatexit PARAMS ((void (*fn) (void)));
+
+/* Exit, calling all the functions registered with xatexit. */
+
+#ifndef __GNUC__
+extern void xexit PARAMS ((int status));
+#else
+void xexit PARAMS ((int status)) __attribute__ ((noreturn));
+#endif
+
+/* Set the program name used by xmalloc. */
+
+extern void xmalloc_set_program_name PARAMS ((const char *));
+
+/* Allocate memory without fail. If malloc fails, this will print a
+ message to stderr (using the name set by xmalloc_set_program_name,
+ if any) and then call xexit. */
+
+#ifdef ANSI_PROTOTYPES
+/* Get a definition for size_t. */
+#include <stddef.h>
+#endif
+extern PTR xmalloc PARAMS ((size_t));
+
+/* Reallocate memory without fail. This works like xmalloc.
+
+ FIXME: We do not declare the parameter types for the same reason as
+ xmalloc. */
+
+extern PTR xrealloc PARAMS ((PTR, size_t));
+
+/* Allocate memory without fail and set it to zero. This works like
+ xmalloc. */
+
+extern PTR xcalloc PARAMS ((size_t, size_t));
+
+/* Copy a string into a memory buffer without fail. */
+
+extern char *xstrdup PARAMS ((const char *));
+
+/* hex character manipulation routines */
+
+#define _hex_array_size 256
+#define _hex_bad 99
+extern char _hex_value[_hex_array_size];
+extern void hex_init PARAMS ((void));
+#define hex_p(c) (hex_value (c) != _hex_bad)
+/* If you change this, note well: Some code relies on side effects in
+ the argument being performed exactly once. */
+#define hex_value(c) (_hex_value[(unsigned char) (c)])
+
+/* Definitions used by the pexecute routine. */
+
+#define PEXECUTE_FIRST 1
+#define PEXECUTE_LAST 2
+#define PEXECUTE_ONE (PEXECUTE_FIRST + PEXECUTE_LAST)
+#define PEXECUTE_SEARCH 4
+#define PEXECUTE_VERBOSE 8
+
+/* Execute a program. */
+
+extern int pexecute PARAMS ((const char *, char * const *, const char *,
+ const char *, char **, char **, int));
+
+/* Wait for pexecute to finish. */
+
+extern int pwait PARAMS ((int, int *, int));
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* ! defined (LIBIBERTY_H) */
diff --git a/pstack/linuxthreads.c b/pstack/linuxthreads.c
new file mode 100644
index 00000000000..8624bd21782
--- /dev/null
+++ b/pstack/linuxthreads.c
@@ -0,0 +1,90 @@
+/* $Header$ */
+
+/*
+ * LinuxThreads specific stuff.
+ */
+
+#include <sys/types.h>
+
+#include <assert.h>
+#include <limits.h> /* PTHREAD_THREADS_MAX */
+#include <pthread.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <signal.h>
+#include <sched.h>
+
+#include "linuxthreads.h"
+
+#define AT_INT(intval) *((int32_t*)(intval))
+
+/*
+ * Internal LinuxThreads variables.
+ * Official interface exposed to GDB.
+ */
+#if 1
+extern volatile int __pthread_threads_debug;
+extern volatile char __pthread_handles;
+extern char __pthread_initial_thread;
+/*extern volatile Elf32_Sym* __pthread_manager_thread;*/
+extern const int __pthread_sizeof_handle;
+extern const int __pthread_offsetof_descr;
+extern const int __pthread_offsetof_pid;
+extern volatile int __pthread_handles_num;
+#endif /* 0 */
+
+/*
+ * Notify others.
+ */
+int
+linuxthreads_notify_others( const int signotify)
+{
+ const pid_t mypid = getpid();
+ //const pthread_t mytid = pthread_self();
+ int i;
+ int threadcount = 0;
+ int threads[PTHREAD_THREADS_MAX];
+ int pid;
+
+ TRACE_FPRINTF((stderr, "theadcount:%d\n", __pthread_handles_num));
+ if (__pthread_handles_num==2) {
+ /* no threads beside the initial thread */
+ return 0;
+ }
+ /*assert(maxthreads>=3);
+ assert(maxthreads>=__pthread_handles_num+2);*/
+
+ // take the initial thread with us
+ pid = AT_INT(&__pthread_initial_thread + __pthread_offsetof_pid);
+ if (pid!=mypid && pid!=0)
+ threads[threadcount++] = pid;
+ // don't know why, but always handles[0]==handles[1]
+ for (i=1; i<__pthread_handles_num; ++i) {
+ const int descr = AT_INT(&__pthread_handles+i*__pthread_sizeof_handle+__pthread_offsetof_descr);
+ assert(descr!=0);
+ pid = AT_INT(descr+__pthread_offsetof_pid);
+ if (pid!=mypid && pid!=0)
+ threads[threadcount++] = pid;
+ }
+ /* TRACE_FPRINTF((stderr, "Stopping threads...")); */
+ //for (i=0; i<threadcount; ++i) {
+ // /* TRACE_FPRINTF((stderr, "%d ", threads[i])); */
+ // fflush(stdout);
+ // kill(threads[i], SIGSTOP); /* Tell thread to stop */
+ //}
+ /* TRACE_FPRINTF((stderr, " done!\n")); */
+ for (i=0; i<threadcount; ++i) {
+ TRACE_FPRINTF((stderr, "--- NOTIFYING %d\n", threads[i]));
+ kill(threads[i], signotify); /* Tell to print stack trace */
+ /* TRACE_FPRINTF((stderr, "--- WAITING FOR %d\n", threads[i])); */
+ /*pause(); Wait for confirmation. */
+ }
+ for (i=0; i<threadcount; ++i)
+ sched_yield();
+ for (i=0; i<threadcount; ++i) {
+ TRACE_FPRINTF((stderr, "--- KILLING %d\n", threads[i]));
+ kill(threads[i], SIGKILL); /* Tell thread die :) */
+ }
+ return __pthread_handles_num;
+}
+
diff --git a/pstack/linuxthreads.h b/pstack/linuxthreads.h
new file mode 100644
index 00000000000..f5eb0f652d8
--- /dev/null
+++ b/pstack/linuxthreads.h
@@ -0,0 +1,28 @@
+/* $Header$ */
+
+/*
+ * LinuxThreads specific stuff.
+ */
+
+#ifndef pstack_linuxthreads_h_
+#define pstack_linuxthreads_h_
+
+#include <pthread.h>
+#include "pstacktrace.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Tell other threads to dump stacks...
+ */
+int
+linuxthreads_notify_others( const int signotify);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* pstack_linuxthreads_h_ */
+
diff --git a/pstack/pstack.c b/pstack/pstack.c
new file mode 100644
index 00000000000..48280d4aedb
--- /dev/null
+++ b/pstack/pstack.c
@@ -0,0 +1,2745 @@
+/*
+ pstack.c -- asynchronous stack trace of a running process
+ Copyright (c) 1999 Ross Thompson
+ Author: Ross Thompson <ross@whatsis.com>
+ Critical bug fix: Tim Waugh
+*/
+
+/*
+ This file is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+/* RESTRICTIONS:
+
+ pstack currently works only on Linux, only on an x86 machine running
+ 32 bit ELF binaries (64 bit not supported). Also, for symbolic
+ information, you need to use a GNU compiler to generate your
+ program, and you can't strip symbols from the binaries. For thread
+ information to be dumped, you have to use the debug-aware version
+ of libpthread.so. (To check, run 'nm' on your libpthread.so, and
+ make sure that the symbol "__pthread_threads_debug" is defined.)
+
+ The details of pulling stuff out of ELF files and running through
+ program images is very platform specific, and I don't want to
+ try to support modes or machine types I can't test in or on.
+ If someone wants to generalize this to other architectures, I would
+ be happy to help and coordinate the activity. Please send me whatever
+ changes you make to support these machines, so that I can own the
+ central font of all truth (at least as regards this program).
+
+ Thanks
+*/
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <sys/ptrace.h>
+#include <asm/ptrace.h>
+
+#include <assert.h>
+#include <fcntl.h>
+#include <link.h>
+#include <malloc.h>
+#include <string.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <signal.h>
+#include <pthread.h>
+#include <limits.h> /* PTHREAD_THREADS_MAX */
+
+
+#include <bfd.h>
+
+#include "libiberty.h"
+
+#include "pstack.h" /* just one function */
+#include "budbg.h" /* binutils stuff related to debugging symbols. */
+#include "bucomm.h" /* some common stuff */
+#include "debug.h" /* and more binutils stuff... */
+#include "budbg.h"
+#include "linuxthreads.h" /* LinuxThreads specific stuff... */
+
+
+/*
+ * fprintf for file descriptors :) NOTE: we have to use fixed-size buffer :)(
+ * due to malloc's unavalaibility.
+ */
+int
+fdprintf( int fd,
+ const char* fmt,...)
+{
+ char xbuf[2048];// FIXME: enough?
+ va_list ap;
+ int r;
+ if (fd<0)
+ return -1;
+ va_start(ap, fmt);
+ r = vsnprintf(xbuf, sizeof(xbuf), fmt, ap);
+ va_end(ap);
+ return write(fd, xbuf, r);
+}
+
+int
+fdputc( char c,
+ int fd)
+{
+ if (fd<0)
+ return -1;
+ return write(fd, &c, sizeof(c));
+}
+
+int
+fdputs( const char* s,
+ int fd)
+{
+ if (fd<0)
+ return -1;
+ return write(fd, s, strlen(s));
+}
+
+/*
+ * Use this function to open log file.
+ * Flags: truncate on opening.
+ */
+static const char* path_format = "stack-trace-on-segv-%d.txt";
+static int
+open_log_file( const pthread_t tid,
+ const pid_t pid)
+{
+ char fname[PATH_MAX];
+ int r;
+ snprintf(fname, sizeof(fname), path_format, tid, pid);
+ r = open(fname, O_WRONLY|O_CREAT|O_TRUNC,
+ S_IRUSR|S_IWUSR);
+ if (r<0)
+ perror("open");
+ return r;
+}
+/*
+ * Add additional debugging information for functions.
+ */
+
+/*
+ * Lineno
+ */
+typedef struct {
+ int lineno;
+ bfd_vma addr;
+} debug_lineno_t;
+
+/*
+ * Block - a {} pair.
+ */
+typedef struct debug_block_st {
+ bfd_vma begin_addr; /* where did it start */
+ bfd_vma end_addr; /* where did it end */
+ struct debug_block_st* parent;
+ struct debug_block_st* childs;
+ int childs_count;
+} debug_block_t;
+
+/*
+ * Function parameter.
+ */
+typedef struct {
+ bfd_vma offset; /* Offset in the stack */
+ const char* name; /* And name. */
+} debug_parameter_t;
+
+/*
+ * Extra information about functions.
+ */
+typedef struct {
+ asymbol* symbol; /* mangled function name, addr */
+ debug_lineno_t* lines;
+ int lines_count;
+ int max_lines_count;
+ const char* name;
+ const char* filename;/* a file name it occured in... */
+ debug_block_t* block; /* each function has a block, or not, you know */
+ debug_parameter_t* argv; /* argument types. */
+ int argc;
+ int max_argc;
+} debug_function_t;
+
+/* This is the structure we use as a handle for these routines. */
+struct pr_handle
+{
+ /* File to print information to. */
+ FILE *f;
+ /* Current indentation level. */
+ unsigned int indent;
+ /* Type stack. */
+ struct pr_stack *stack;
+ /* Parameter number we are about to output. */
+ int parameter;
+ debug_block_t* block; /* current block */
+ debug_function_t* function; /* current function */
+ debug_function_t* functions; /* all functions */
+ int functions_size; /* current size */
+ int functions_maxsize; /* maximum size */
+};
+
+/* The type stack. */
+
+struct pr_stack
+{
+ /* Next element on the stack. */
+ struct pr_stack *next;
+ /* This element. */
+ char *type;
+ /* Current visibility of fields if this is a class. */
+ enum debug_visibility visibility;
+ /* Name of the current method we are handling. */
+ const char *method;
+};
+
+static void indent PARAMS ((struct pr_handle *));
+static boolean push_type PARAMS ((struct pr_handle *, const char *));
+static boolean prepend_type PARAMS ((struct pr_handle *, const char *));
+static boolean append_type PARAMS ((struct pr_handle *, const char *));
+static boolean substitute_type PARAMS ((struct pr_handle *, const char *));
+static boolean indent_type PARAMS ((struct pr_handle *));
+static char *pop_type PARAMS ((struct pr_handle *));
+static void print_vma PARAMS ((bfd_vma, char *, boolean, boolean));
+static boolean pr_fix_visibility
+ PARAMS ((struct pr_handle *, enum debug_visibility));
+
+static boolean pr_start_compilation_unit PARAMS ((PTR, const char *));
+static boolean pr_start_source PARAMS ((PTR, const char *));
+static boolean pr_empty_type PARAMS ((PTR));
+static boolean pr_void_type PARAMS ((PTR));
+static boolean pr_int_type PARAMS ((PTR, unsigned int, boolean));
+static boolean pr_float_type PARAMS ((PTR, unsigned int));
+static boolean pr_complex_type PARAMS ((PTR, unsigned int));
+static boolean pr_bool_type PARAMS ((PTR, unsigned int));
+static boolean pr_enum_type
+ PARAMS ((PTR, const char *, const char **, bfd_signed_vma *));
+static boolean pr_pointer_type PARAMS ((PTR));
+static boolean pr_function_type PARAMS ((PTR, int, boolean));
+static boolean pr_reference_type PARAMS ((PTR));
+static boolean pr_range_type PARAMS ((PTR, bfd_signed_vma, bfd_signed_vma));
+static boolean pr_array_type
+ PARAMS ((PTR, bfd_signed_vma, bfd_signed_vma, boolean));
+static boolean pr_set_type PARAMS ((PTR, boolean));
+static boolean pr_offset_type PARAMS ((PTR));
+static boolean pr_method_type PARAMS ((PTR, boolean, int, boolean));
+static boolean pr_const_type PARAMS ((PTR));
+static boolean pr_volatile_type PARAMS ((PTR));
+static boolean pr_start_struct_type
+ PARAMS ((PTR, const char *, unsigned int, boolean, unsigned int));
+static boolean pr_struct_field
+ PARAMS ((PTR, const char *, bfd_vma, bfd_vma, enum debug_visibility));
+static boolean pr_end_struct_type PARAMS ((PTR));
+static boolean pr_start_class_type
+ PARAMS ((PTR, const char *, unsigned int, boolean, unsigned int, boolean,
+ boolean));
+static boolean pr_class_static_member
+ PARAMS ((PTR, const char *, const char *, enum debug_visibility));
+static boolean pr_class_baseclass
+ PARAMS ((PTR, bfd_vma, boolean, enum debug_visibility));
+static boolean pr_class_start_method PARAMS ((PTR, const char *));
+static boolean pr_class_method_variant
+ PARAMS ((PTR, const char *, enum debug_visibility, boolean, boolean,
+ bfd_vma, boolean));
+static boolean pr_class_static_method_variant
+ PARAMS ((PTR, const char *, enum debug_visibility, boolean, boolean));
+static boolean pr_class_end_method PARAMS ((PTR));
+static boolean pr_end_class_type PARAMS ((PTR));
+static boolean pr_typedef_type PARAMS ((PTR, const char *));
+static boolean pr_tag_type
+ PARAMS ((PTR, const char *, unsigned int, enum debug_type_kind));
+static boolean pr_typdef PARAMS ((PTR, const char *));
+static boolean pr_tag PARAMS ((PTR, const char *));
+static boolean pr_int_constant PARAMS ((PTR, const char *, bfd_vma));
+static boolean pr_float_constant PARAMS ((PTR, const char *, double));
+static boolean pr_typed_constant PARAMS ((PTR, const char *, bfd_vma));
+static boolean pr_variable
+ PARAMS ((PTR, const char *, enum debug_var_kind, bfd_vma));
+static boolean pr_start_function PARAMS ((PTR, const char *, boolean));
+static boolean pr_function_parameter
+ PARAMS ((PTR, const char *, enum debug_parm_kind, bfd_vma));
+static boolean pr_start_block PARAMS ((PTR, bfd_vma));
+static boolean pr_end_block PARAMS ((PTR, bfd_vma));
+static boolean pr_end_function PARAMS ((PTR));
+static boolean pr_lineno PARAMS ((PTR, const char *, unsigned long, bfd_vma));
+
+static const struct debug_write_fns pr_fns =
+{
+ pr_start_compilation_unit,
+ pr_start_source,
+ pr_empty_type,
+ pr_void_type,
+ pr_int_type,
+ pr_float_type,
+ pr_complex_type,
+ pr_bool_type,
+ pr_enum_type,
+ pr_pointer_type,
+ pr_function_type,
+ pr_reference_type,
+ pr_range_type,
+ pr_array_type,
+ pr_set_type,
+ pr_offset_type,
+ pr_method_type,
+ pr_const_type,
+ pr_volatile_type,
+ pr_start_struct_type,
+ pr_struct_field,
+ pr_end_struct_type,
+ pr_start_class_type,
+ pr_class_static_member,
+ pr_class_baseclass,
+ pr_class_start_method,
+ pr_class_method_variant,
+ pr_class_static_method_variant,
+ pr_class_end_method,
+ pr_end_class_type,
+ pr_typedef_type,
+ pr_tag_type,
+ pr_typdef,
+ pr_tag,
+ pr_int_constant,
+ pr_float_constant,
+ pr_typed_constant,
+ pr_variable,
+ pr_start_function,
+ pr_function_parameter,
+ pr_start_block,
+ pr_end_block,
+ pr_end_function,
+ pr_lineno
+};
+
+
+/* Indent to the current indentation level. */
+
+static void
+indent (info)
+ struct pr_handle *info;
+{
+ unsigned int i;
+
+ for (i = 0; i < info->indent; i++)
+ TRACE_PUTC ((' ', info->f));
+}
+
+/* Push a type on the type stack. */
+
+static boolean
+push_type (info, type)
+ struct pr_handle *info;
+ const char *type;
+{
+ struct pr_stack *n;
+
+ if (type == NULL)
+ return false;
+
+ n = (struct pr_stack *) xmalloc (sizeof *n);
+ memset (n, 0, sizeof *n);
+
+ n->type = xstrdup (type);
+ n->visibility = DEBUG_VISIBILITY_IGNORE;
+ n->method = NULL;
+ n->next = info->stack;
+ info->stack = n;
+
+ return true;
+}
+
+/* Prepend a string onto the type on the top of the type stack. */
+
+static boolean
+prepend_type (info, s)
+ struct pr_handle *info;
+ const char *s;
+{
+ char *n;
+
+ assert (info->stack != NULL);
+
+ n = (char *) xmalloc (strlen (s) + strlen (info->stack->type) + 1);
+ sprintf (n, "%s%s", s, info->stack->type);
+ free (info->stack->type);
+ info->stack->type = n;
+
+ return true;
+}
+
+/* Append a string to the type on the top of the type stack. */
+
+static boolean
+append_type (info, s)
+ struct pr_handle *info;
+ const char *s;
+{
+ unsigned int len;
+
+ if (s == NULL)
+ return false;
+
+ assert (info->stack != NULL);
+
+ len = strlen (info->stack->type);
+ info->stack->type = (char *) xrealloc (info->stack->type,
+ len + strlen (s) + 1);
+ strcpy (info->stack->type + len, s);
+
+ return true;
+}
+
+/* We use an underscore to indicate where the name should go in a type
+ string. This function substitutes a string for the underscore. If
+ there is no underscore, the name follows the type. */
+
+static boolean
+substitute_type (info, s)
+ struct pr_handle *info;
+ const char *s;
+{
+ char *u;
+
+ assert (info->stack != NULL);
+
+ u = strchr (info->stack->type, '|');
+ if (u != NULL)
+ {
+ char *n;
+
+ n = (char *) xmalloc (strlen (info->stack->type) + strlen (s));
+
+ memcpy (n, info->stack->type, u - info->stack->type);
+ strcpy (n + (u - info->stack->type), s);
+ strcat (n, u + 1);
+
+ free (info->stack->type);
+ info->stack->type = n;
+
+ return true;
+ }
+
+ if (strchr (s, '|') != NULL
+ && (strchr (info->stack->type, '{') != NULL
+ || strchr (info->stack->type, '(') != NULL))
+ {
+ if (! prepend_type (info, "(")
+ || ! append_type (info, ")"))
+ return false;
+ }
+
+ if (*s == '\0')
+ return true;
+
+ return (append_type (info, " ")
+ && append_type (info, s));
+}
+
+/* Indent the type at the top of the stack by appending spaces. */
+
+static boolean
+indent_type (info)
+ struct pr_handle *info;
+{
+ unsigned int i;
+
+ for (i = 0; i < info->indent; i++)
+ {
+ if (! append_type (info, " "))
+ return false;
+ }
+
+ return true;
+}
+
+/* Pop a type from the type stack. */
+
+static char *
+pop_type (info)
+ struct pr_handle *info;
+{
+ struct pr_stack *o;
+ char *ret;
+
+ assert (info->stack != NULL);
+
+ o = info->stack;
+ info->stack = o->next;
+ ret = o->type;
+ free (o);
+
+ return ret;
+}
+
+/* Print a VMA value into a string. */
+
+static void
+print_vma (vma, buf, unsignedp, hexp)
+ bfd_vma vma;
+ char *buf;
+ boolean unsignedp;
+ boolean hexp;
+{
+ if (sizeof (vma) <= sizeof (unsigned long))
+ {
+ if (hexp)
+ sprintf (buf, "0x%lx", (unsigned long) vma);
+ else if (unsignedp)
+ sprintf (buf, "%lu", (unsigned long) vma);
+ else
+ sprintf (buf, "%ld", (long) vma);
+ }
+ else
+ {
+ buf[0] = '0';
+ buf[1] = 'x';
+ sprintf_vma (buf + 2, vma);
+ }
+}
+
+/* Start a new compilation unit. */
+
+static boolean
+pr_start_compilation_unit (p, filename)
+ PTR p;
+ const char *filename;
+{
+ struct pr_handle *info = (struct pr_handle *) p;
+
+ assert (info->indent == 0);
+/*
+ TRACE_FPRINTF( (info->f, "%s:\n", filename));
+*/
+ return true;
+}
+
+/* Start a source file within a compilation unit. */
+
+static boolean
+pr_start_source (p, filename)
+ PTR p;
+ const char *filename;
+{
+ struct pr_handle *info = (struct pr_handle *) p;
+
+ assert (info->indent == 0);
+/*
+ TRACE_FPRINTF( (info->f, " %s:\n", filename));
+*/
+ return true;
+}
+
+/* Push an empty type onto the type stack. */
+
+static boolean
+pr_empty_type (p)
+ PTR p;
+{
+ struct pr_handle *info = (struct pr_handle *) p;
+
+ return push_type (info, "<undefined>");
+}
+
+/* Push a void type onto the type stack. */
+
+static boolean
+pr_void_type (p)
+ PTR p;
+{
+ struct pr_handle *info = (struct pr_handle *) p;
+
+ return push_type (info, "void");
+}
+
+/* Push an integer type onto the type stack. */
+
+static boolean
+pr_int_type (p, size, unsignedp)
+ PTR p;
+ unsigned int size;
+ boolean unsignedp;
+{
+ struct pr_handle *info = (struct pr_handle *) p;
+ char ab[10];
+
+ sprintf (ab, "%sint%d", unsignedp ? "u" : "", size * 8);
+ return push_type (info, ab);
+}
+
+/* Push a floating type onto the type stack. */
+
+static boolean
+pr_float_type (p, size)
+ PTR p;
+ unsigned int size;
+{
+ struct pr_handle *info = (struct pr_handle *) p;
+ char ab[10];
+
+ if (size == 4)
+ return push_type (info, "float");
+ else if (size == 8)
+ return push_type (info, "double");
+
+ sprintf (ab, "float%d", size * 8);
+ return push_type (info, ab);
+}
+
+/* Push a complex type onto the type stack. */
+
+static boolean
+pr_complex_type (p, size)
+ PTR p;
+ unsigned int size;
+{
+ struct pr_handle *info = (struct pr_handle *) p;
+
+ if (! pr_float_type (p, size))
+ return false;
+
+ return prepend_type (info, "complex ");
+}
+
+/* Push a boolean type onto the type stack. */
+
+static boolean
+pr_bool_type (p, size)
+ PTR p;
+ unsigned int size;
+{
+ struct pr_handle *info = (struct pr_handle *) p;
+ char ab[10];
+
+ sprintf (ab, "bool%d", size * 8);
+
+ return push_type (info, ab);
+}
+
+/* Push an enum type onto the type stack. */
+
+static boolean
+pr_enum_type (p, tag, names, values)
+ PTR p;
+ const char *tag;
+ const char **names;
+ bfd_signed_vma *values;
+{
+ struct pr_handle *info = (struct pr_handle *) p;
+ unsigned int i;
+ bfd_signed_vma val;
+
+ if (! push_type (info, "enum "))
+ return false;
+ if (tag != NULL)
+ {
+ if (! append_type (info, tag)
+ || ! append_type (info, " "))
+ return false;
+ }
+ if (! append_type (info, "{ "))
+ return false;
+
+ if (names == NULL)
+ {
+ if (! append_type (info, "/* undefined */"))
+ return false;
+ }
+ else
+ {
+ val = 0;
+ for (i = 0; names[i] != NULL; i++)
+ {
+ if (i > 0)
+ {
+ if (! append_type (info, ", "))
+ return false;
+ }
+
+ if (! append_type (info, names[i]))
+ return false;
+
+ if (values[i] != val)
+ {
+ char ab[20];
+
+ print_vma (values[i], ab, false, false);
+ if (! append_type (info, " = ")
+ || ! append_type (info, ab))
+ return false;
+ val = values[i];
+ }
+
+ ++val;
+ }
+ }
+
+ return append_type (info, " }");
+}
+
+/* Turn the top type on the stack into a pointer. */
+
+static boolean
+pr_pointer_type (p)
+ PTR p;
+{
+ struct pr_handle *info = (struct pr_handle *) p;
+ char *s;
+
+ assert (info->stack != NULL);
+
+ s = strchr (info->stack->type, '|');
+ if (s != NULL && s[1] == '[')
+ return substitute_type (info, "(*|)");
+ return substitute_type (info, "*|");
+}
+
+/* Turn the top type on the stack into a function returning that type. */
+
+static boolean
+pr_function_type (p, argcount, varargs)
+ PTR p;
+ int argcount;
+ boolean varargs;
+{
+ struct pr_handle *info = (struct pr_handle *) p;
+ char **arg_types;
+ unsigned int len;
+ char *s;
+
+ assert (info->stack != NULL);
+
+ len = 10;
+
+ if (argcount <= 0)
+ {
+ arg_types = NULL;
+ len += 15;
+ }
+ else
+ {
+ int i;
+
+ arg_types = (char **) xmalloc (argcount * sizeof *arg_types);
+ for (i = argcount - 1; i >= 0; i--)
+ {
+ if (! substitute_type (info, ""))
+ return false;
+ arg_types[i] = pop_type (info);
+ if (arg_types[i] == NULL)
+ return false;
+ len += strlen (arg_types[i]) + 2;
+ }
+ if (varargs)
+ len += 5;
+ }
+
+ /* Now the return type is on the top of the stack. */
+
+ s = (char *) xmalloc (len);
+ strcpy (s, "(|) (");
+
+ if (argcount < 0)
+ {
+#if 0
+ /* Turn off unknown arguments. */
+ strcat (s, "/* unknown */");
+#endif
+ }
+ else
+ {
+ int i;
+
+ for (i = 0; i < argcount; i++)
+ {
+ if (i > 0)
+ strcat (s, ", ");
+ strcat (s, arg_types[i]);
+ }
+ if (varargs)
+ {
+ if (i > 0)
+ strcat (s, ", ");
+ strcat (s, "...");
+ }
+ if (argcount > 0)
+ free (arg_types);
+ }
+
+ strcat (s, ")");
+
+ if (! substitute_type (info, s))
+ return false;
+
+ free (s);
+
+ return true;
+}
+
+/* Turn the top type on the stack into a reference to that type. */
+
+static boolean
+pr_reference_type (p)
+ PTR p;
+{
+ struct pr_handle *info = (struct pr_handle *) p;
+
+ assert (info->stack != NULL);
+
+ return substitute_type (info, "&|");
+}
+
+/* Make a range type. */
+
+static boolean
+pr_range_type (p, lower, upper)
+ PTR p;
+ bfd_signed_vma lower;
+ bfd_signed_vma upper;
+{
+ struct pr_handle *info = (struct pr_handle *) p;
+ char abl[20], abu[20];
+
+ assert (info->stack != NULL);
+
+ if (! substitute_type (info, ""))
+ return false;
+
+ print_vma (lower, abl, false, false);
+ print_vma (upper, abu, false, false);
+
+ return (prepend_type (info, "range (")
+ && append_type (info, "):")
+ && append_type (info, abl)
+ && append_type (info, ":")
+ && append_type (info, abu));
+}
+
+/* Make an array type. */
+
+/*ARGSUSED*/
+static boolean
+pr_array_type (p, lower, upper, stringp)
+ PTR p;
+ bfd_signed_vma lower;
+ bfd_signed_vma upper;
+ boolean stringp;
+{
+ struct pr_handle *info = (struct pr_handle *) p;
+ char *range_type;
+ char abl[20], abu[20], ab[50];
+
+ range_type = pop_type (info);
+ if (range_type == NULL)
+ return false;
+
+ if (lower == 0)
+ {
+ if (upper == -1)
+ sprintf (ab, "|[]");
+ else
+ {
+ print_vma (upper + 1, abu, false, false);
+ sprintf (ab, "|[%s]", abu);
+ }
+ }
+ else
+ {
+ print_vma (lower, abl, false, false);
+ print_vma (upper, abu, false, false);
+ sprintf (ab, "|[%s:%s]", abl, abu);
+ }
+
+ if (! substitute_type (info, ab))
+ return false;
+
+ if (strcmp (range_type, "int") != 0)
+ {
+ if (! append_type (info, ":")
+ || ! append_type (info, range_type))
+ return false;
+ }
+
+ if (stringp)
+ {
+ if (! append_type (info, " /* string */"))
+ return false;
+ }
+
+ return true;
+}
+
+/* Make a set type. */
+
+/*ARGSUSED*/
+static boolean
+pr_set_type (p, bitstringp)
+ PTR p;
+ boolean bitstringp;
+{
+ struct pr_handle *info = (struct pr_handle *) p;
+
+ if (! substitute_type (info, ""))
+ return false;
+
+ if (! prepend_type (info, "set { ")
+ || ! append_type (info, " }"))
+ return false;
+
+ if (bitstringp)
+ {
+ if (! append_type (info, "/* bitstring */"))
+ return false;
+ }
+
+ return true;
+}
+
+/* Make an offset type. */
+
+static boolean
+pr_offset_type (p)
+ PTR p;
+{
+ struct pr_handle *info = (struct pr_handle *) p;
+ char *t;
+
+ if (! substitute_type (info, ""))
+ return false;
+
+ t = pop_type (info);
+ if (t == NULL)
+ return false;
+
+ return (substitute_type (info, "")
+ && prepend_type (info, " ")
+ && prepend_type (info, t)
+ && append_type (info, "::|"));
+}
+
+/* Make a method type. */
+
+static boolean
+pr_method_type (p, domain, argcount, varargs)
+ PTR p;
+ boolean domain;
+ int argcount;
+ boolean varargs;
+{
+ struct pr_handle *info = (struct pr_handle *) p;
+ unsigned int len;
+ char *domain_type;
+ char **arg_types;
+ char *s;
+
+ len = 10;
+
+ if (! domain)
+ domain_type = NULL;
+ else
+ {
+ if (! substitute_type (info, ""))
+ return false;
+ domain_type = pop_type (info);
+ if (domain_type == NULL)
+ return false;
+ if (strncmp (domain_type, "class ", sizeof "class " - 1) == 0
+ && strchr (domain_type + sizeof "class " - 1, ' ') == NULL)
+ domain_type += sizeof "class " - 1;
+ else if (strncmp (domain_type, "union class ",
+ sizeof "union class ") == 0
+ && (strchr (domain_type + sizeof "union class " - 1, ' ')
+ == NULL))
+ domain_type += sizeof "union class " - 1;
+ len += strlen (domain_type);
+ }
+
+ if (argcount <= 0)
+ {
+ arg_types = NULL;
+ len += 15;
+ }
+ else
+ {
+ int i;
+
+ arg_types = (char **) xmalloc (argcount * sizeof *arg_types);
+ for (i = argcount - 1; i >= 0; i--)
+ {
+ if (! substitute_type (info, ""))
+ return false;
+ arg_types[i] = pop_type (info);
+ if (arg_types[i] == NULL)
+ return false;
+ len += strlen (arg_types[i]) + 2;
+ }
+ if (varargs)
+ len += 5;
+ }
+
+ /* Now the return type is on the top of the stack. */
+
+ s = (char *) xmalloc (len);
+ if (! domain)
+ *s = '\0';
+ else
+ strcpy (s, domain_type);
+ strcat (s, "::| (");
+
+ if (argcount < 0)
+ strcat (s, "/* unknown */");
+ else
+ {
+ int i;
+
+ for (i = 0; i < argcount; i++)
+ {
+ if (i > 0)
+ strcat (s, ", ");
+ strcat (s, arg_types[i]);
+ }
+ if (varargs)
+ {
+ if (i > 0)
+ strcat (s, ", ");
+ strcat (s, "...");
+ }
+ if (argcount > 0)
+ free (arg_types);
+ }
+
+ strcat (s, ")");
+
+ if (! substitute_type (info, s))
+ return false;
+
+ free (s);
+
+ return true;
+}
+
+/* Make a const qualified type. */
+
+static boolean
+pr_const_type (p)
+ PTR p;
+{
+ struct pr_handle *info = (struct pr_handle *) p;
+
+ return substitute_type (info, "const |");
+}
+
+/* Make a volatile qualified type. */
+
+static boolean
+pr_volatile_type (p)
+ PTR p;
+{
+ struct pr_handle *info = (struct pr_handle *) p;
+
+ return substitute_type (info, "volatile |");
+}
+
+/* Start accumulating a struct type. */
+
+static boolean
+pr_start_struct_type (p, tag, id, structp, size)
+ PTR p;
+ const char *tag;
+ unsigned int id;
+ boolean structp;
+ unsigned int size;
+{
+ struct pr_handle *info = (struct pr_handle *) p;
+
+ info->indent += 2;
+
+ if (! push_type (info, structp ? "struct " : "union "))
+ return false;
+ if (tag != NULL)
+ {
+ if (! append_type (info, tag))
+ return false;
+ }
+ else
+ {
+ char idbuf[20];
+
+ sprintf (idbuf, "%%anon%u", id);
+ if (! append_type (info, idbuf))
+ return false;
+ }
+
+ if (! append_type (info, " {"))
+ return false;
+ if (size != 0 || tag != NULL)
+ {
+ char ab[30];
+
+ if (! append_type (info, " /*"))
+ return false;
+
+ if (size != 0)
+ {
+ sprintf (ab, " size %u", size);
+ if (! append_type (info, ab))
+ return false;
+ }
+ if (tag != NULL)
+ {
+ sprintf (ab, " id %u", id);
+ if (! append_type (info, ab))
+ return false;
+ }
+ if (! append_type (info, " */"))
+ return false;
+ }
+ if (! append_type (info, "\n"))
+ return false;
+
+ info->stack->visibility = DEBUG_VISIBILITY_PUBLIC;
+
+ return indent_type (info);
+}
+
+/* Output the visibility of a field in a struct. */
+
+static boolean
+pr_fix_visibility (info, visibility)
+ struct pr_handle *info;
+ enum debug_visibility visibility;
+{
+ const char *s;
+ char *t;
+ unsigned int len;
+
+ assert (info->stack != NULL);
+
+ if (info->stack->visibility == visibility)
+ return true;
+
+ assert (info->stack->visibility != DEBUG_VISIBILITY_IGNORE);
+
+ switch (visibility)
+ {
+ case DEBUG_VISIBILITY_PUBLIC:
+ s = "public";
+ break;
+ case DEBUG_VISIBILITY_PRIVATE:
+ s = "private";
+ break;
+ case DEBUG_VISIBILITY_PROTECTED:
+ s = "protected";
+ break;
+ case DEBUG_VISIBILITY_IGNORE:
+ s = "/* ignore */";
+ break;
+ default:
+ abort ();
+ return false;
+ }
+
+ /* Trim off a trailing space in the struct string, to make the
+ output look a bit better, then stick on the visibility string. */
+
+ t = info->stack->type;
+ len = strlen (t);
+ assert (t[len - 1] == ' ');
+ t[len - 1] = '\0';
+
+ if (! append_type (info, s)
+ || ! append_type (info, ":\n")
+ || ! indent_type (info))
+ return false;
+
+ info->stack->visibility = visibility;
+
+ return true;
+}
+
+/* Add a field to a struct type. */
+
+static boolean
+pr_struct_field (p, name, bitpos, bitsize, visibility)
+ PTR p;
+ const char *name;
+ bfd_vma bitpos;
+ bfd_vma bitsize;
+ enum debug_visibility visibility;
+{
+ struct pr_handle *info = (struct pr_handle *) p;
+ char ab[20];
+ char *t;
+
+ if (! substitute_type (info, name))
+ return false;
+
+ if (! append_type (info, "; /* "))
+ return false;
+
+ if (bitsize != 0)
+ {
+ print_vma (bitsize, ab, true, false);
+ if (! append_type (info, "bitsize ")
+ || ! append_type (info, ab)
+ || ! append_type (info, ", "))
+ return false;
+ }
+
+ print_vma (bitpos, ab, true, false);
+ if (! append_type (info, "bitpos ")
+ || ! append_type (info, ab)
+ || ! append_type (info, " */\n")
+ || ! indent_type (info))
+ return false;
+
+ t = pop_type (info);
+ if (t == NULL)
+ return false;
+
+ if (! pr_fix_visibility (info, visibility))
+ return false;
+
+ return append_type (info, t);
+}
+
+/* Finish a struct type. */
+
+static boolean
+pr_end_struct_type (p)
+ PTR p;
+{
+ struct pr_handle *info = (struct pr_handle *) p;
+ char *s;
+
+ assert (info->stack != NULL);
+ assert (info->indent >= 2);
+
+ info->indent -= 2;
+
+ /* Change the trailing indentation to have a close brace. */
+ s = info->stack->type + strlen (info->stack->type) - 2;
+ assert (s[0] == ' ' && s[1] == ' ' && s[2] == '\0');
+
+ *s++ = '}';
+ *s = '\0';
+
+ return true;
+}
+
+/* Start a class type. */
+
+static boolean
+pr_start_class_type (p, tag, id, structp, size, vptr, ownvptr)
+ PTR p;
+ const char *tag;
+ unsigned int id;
+ boolean structp;
+ unsigned int size;
+ boolean vptr;
+ boolean ownvptr;
+{
+ struct pr_handle *info = (struct pr_handle *) p;
+ char *tv = NULL;
+
+ info->indent += 2;
+
+ if (vptr && ! ownvptr)
+ {
+ tv = pop_type (info);
+ if (tv == NULL)
+ return false;
+ }
+
+ if (! push_type (info, structp ? "class " : "union class "))
+ return false;
+ if (tag != NULL)
+ {
+ if (! append_type (info, tag))
+ return false;
+ }
+ else
+ {
+ char idbuf[20];
+
+ sprintf (idbuf, "%%anon%u", id);
+ if (! append_type (info, idbuf))
+ return false;
+ }
+
+ if (! append_type (info, " {"))
+ return false;
+ if (size != 0 || vptr || ownvptr || tag != NULL)
+ {
+ if (! append_type (info, " /*"))
+ return false;
+
+ if (size != 0)
+ {
+ char ab[20];
+
+ sprintf (ab, "%u", size);
+ if (! append_type (info, " size ")
+ || ! append_type (info, ab))
+ return false;
+ }
+
+ if (vptr)
+ {
+ if (! append_type (info, " vtable "))
+ return false;
+ if (ownvptr)
+ {
+ if (! append_type (info, "self "))
+ return false;
+ }
+ else
+ {
+ if (! append_type (info, tv)
+ || ! append_type (info, " "))
+ return false;
+ }
+ }
+
+ if (tag != NULL)
+ {
+ char ab[30];
+
+ sprintf (ab, " id %u", id);
+ if (! append_type (info, ab))
+ return false;
+ }
+
+ if (! append_type (info, " */"))
+ return false;
+ }
+
+ info->stack->visibility = DEBUG_VISIBILITY_PRIVATE;
+
+ return (append_type (info, "\n")
+ && indent_type (info));
+}
+
+/* Add a static member to a class. */
+
+static boolean
+pr_class_static_member (p, name, physname, visibility)
+ PTR p;
+ const char *name;
+ const char *physname;
+ enum debug_visibility visibility;
+{
+ struct pr_handle *info = (struct pr_handle *) p;
+ char *t;
+
+ if (! substitute_type (info, name))
+ return false;
+
+ if (! prepend_type (info, "static ")
+ || ! append_type (info, "; /* ")
+ || ! append_type (info, physname)
+ || ! append_type (info, " */\n")
+ || ! indent_type (info))
+ return false;
+
+ t = pop_type (info);
+ if (t == NULL)
+ return false;
+
+ if (! pr_fix_visibility (info, visibility))
+ return false;
+
+ return append_type (info, t);
+}
+
+/* Add a base class to a class. */
+
+static boolean
+pr_class_baseclass (p, bitpos, virtual, visibility)
+ PTR p;
+ bfd_vma bitpos;
+ boolean virtual;
+ enum debug_visibility visibility;
+{
+ struct pr_handle *info = (struct pr_handle *) p;
+ char *t;
+ const char *prefix;
+ char ab[20];
+ char *s, *l, *n;
+
+ assert (info->stack != NULL && info->stack->next != NULL);
+
+ if (! substitute_type (info, ""))
+ return false;
+
+ t = pop_type (info);
+ if (t == NULL)
+ return false;
+
+ if (strncmp (t, "class ", sizeof "class " - 1) == 0)
+ t += sizeof "class " - 1;
+
+ /* Push it back on to take advantage of the prepend_type and
+ append_type routines. */
+ if (! push_type (info, t))
+ return false;
+
+ if (virtual)
+ {
+ if (! prepend_type (info, "virtual "))
+ return false;
+ }
+
+ switch (visibility)
+ {
+ case DEBUG_VISIBILITY_PUBLIC:
+ prefix = "public ";
+ break;
+ case DEBUG_VISIBILITY_PROTECTED:
+ prefix = "protected ";
+ break;
+ case DEBUG_VISIBILITY_PRIVATE:
+ prefix = "private ";
+ break;
+ default:
+ prefix = "/* unknown visibility */ ";
+ break;
+ }
+
+ if (! prepend_type (info, prefix))
+ return false;
+
+ if (bitpos != 0)
+ {
+ print_vma (bitpos, ab, true, false);
+ if (! append_type (info, " /* bitpos ")
+ || ! append_type (info, ab)
+ || ! append_type (info, " */"))
+ return false;
+ }
+
+ /* Now the top of the stack is something like "public A / * bitpos
+ 10 * /". The next element on the stack is something like "class
+ xx { / * size 8 * /\n...". We want to substitute the top of the
+ stack in before the {. */
+ s = strchr (info->stack->next->type, '{');
+ assert (s != NULL);
+ --s;
+
+ /* If there is already a ':', then we already have a baseclass, and
+ we must append this one after a comma. */
+ for (l = info->stack->next->type; l != s; l++)
+ if (*l == ':')
+ break;
+ if (! prepend_type (info, l == s ? " : " : ", "))
+ return false;
+
+ t = pop_type (info);
+ if (t == NULL)
+ return false;
+
+ n = (char *) xmalloc (strlen (info->stack->type) + strlen (t) + 1);
+ memcpy (n, info->stack->type, s - info->stack->type);
+ strcpy (n + (s - info->stack->type), t);
+ strcat (n, s);
+
+ free (info->stack->type);
+ info->stack->type = n;
+
+ free (t);
+
+ return true;
+}
+
+/* Start adding a method to a class. */
+
+static boolean
+pr_class_start_method (p, name)
+ PTR p;
+ const char *name;
+{
+ struct pr_handle *info = (struct pr_handle *) p;
+
+ assert (info->stack != NULL);
+ info->stack->method = name;
+ return true;
+}
+
+/* Add a variant to a method. */
+
+static boolean
+pr_class_method_variant (p, physname, visibility, constp, volatilep, voffset,
+ context)
+ PTR p;
+ const char *physname;
+ enum debug_visibility visibility;
+ boolean constp;
+ boolean volatilep;
+ bfd_vma voffset;
+ boolean context;
+{
+ struct pr_handle *info = (struct pr_handle *) p;
+ char *method_type;
+ char *context_type;
+
+ assert (info->stack != NULL);
+ assert (info->stack->next != NULL);
+
+ /* Put the const and volatile qualifiers on the type. */
+ if (volatilep)
+ {
+ if (! append_type (info, " volatile"))
+ return false;
+ }
+ if (constp)
+ {
+ if (! append_type (info, " const"))
+ return false;
+ }
+
+ /* Stick the name of the method into its type. */
+ if (! substitute_type (info,
+ (context
+ ? info->stack->next->next->method
+ : info->stack->next->method)))
+ return false;
+
+ /* Get the type. */
+ method_type = pop_type (info);
+ if (method_type == NULL)
+ return false;
+
+ /* Pull off the context type if there is one. */
+ if (! context)
+ context_type = NULL;
+ else
+ {
+ context_type = pop_type (info);
+ if (context_type == NULL)
+ return false;
+ }
+
+ /* Now the top of the stack is the class. */
+
+ if (! pr_fix_visibility (info, visibility))
+ return false;
+
+ if (! append_type (info, method_type)
+ || ! append_type (info, " /* ")
+ || ! append_type (info, physname)
+ || ! append_type (info, " "))
+ return false;
+ if (context || voffset != 0)
+ {
+ char ab[20];
+
+ if (context)
+ {
+ if (! append_type (info, "context ")
+ || ! append_type (info, context_type)
+ || ! append_type (info, " "))
+ return false;
+ }
+ print_vma (voffset, ab, true, false);
+ if (! append_type (info, "voffset ")
+ || ! append_type (info, ab))
+ return false;
+ }
+
+ return (append_type (info, " */;\n")
+ && indent_type (info));
+}
+
+/* Add a static variant to a method. */
+
+static boolean
+pr_class_static_method_variant (p, physname, visibility, constp, volatilep)
+ PTR p;
+ const char *physname;
+ enum debug_visibility visibility;
+ boolean constp;
+ boolean volatilep;
+{
+ struct pr_handle *info = (struct pr_handle *) p;
+ char *method_type;
+
+ assert (info->stack != NULL);
+ assert (info->stack->next != NULL);
+ assert (info->stack->next->method != NULL);
+
+ /* Put the const and volatile qualifiers on the type. */
+ if (volatilep)
+ {
+ if (! append_type (info, " volatile"))
+ return false;
+ }
+ if (constp)
+ {
+ if (! append_type (info, " const"))
+ return false;
+ }
+
+ /* Mark it as static. */
+ if (! prepend_type (info, "static "))
+ return false;
+
+ /* Stick the name of the method into its type. */
+ if (! substitute_type (info, info->stack->next->method))
+ return false;
+
+ /* Get the type. */
+ method_type = pop_type (info);
+ if (method_type == NULL)
+ return false;
+
+ /* Now the top of the stack is the class. */
+
+ if (! pr_fix_visibility (info, visibility))
+ return false;
+
+ return (append_type (info, method_type)
+ && append_type (info, " /* ")
+ && append_type (info, physname)
+ && append_type (info, " */;\n")
+ && indent_type (info));
+}
+
+/* Finish up a method. */
+
+static boolean
+pr_class_end_method (p)
+ PTR p;
+{
+ struct pr_handle *info = (struct pr_handle *) p;
+
+ info->stack->method = NULL;
+ return true;
+}
+
+/* Finish up a class. */
+
+static boolean
+pr_end_class_type (p)
+ PTR p;
+{
+ return pr_end_struct_type (p);
+}
+
+/* Push a type on the stack using a typedef name. */
+
+static boolean
+pr_typedef_type (p, name)
+ PTR p;
+ const char *name;
+{
+ struct pr_handle *info = (struct pr_handle *) p;
+
+ return push_type (info, name);
+}
+
+/* Push a type on the stack using a tag name. */
+
+static boolean
+pr_tag_type (p, name, id, kind)
+ PTR p;
+ const char *name;
+ unsigned int id;
+ enum debug_type_kind kind;
+{
+ struct pr_handle *info = (struct pr_handle *) p;
+ const char *t, *tag;
+ char idbuf[20];
+
+ switch (kind)
+ {
+ case DEBUG_KIND_STRUCT:
+ t = "struct ";
+ break;
+ case DEBUG_KIND_UNION:
+ t = "union ";
+ break;
+ case DEBUG_KIND_ENUM:
+ t = "enum ";
+ break;
+ case DEBUG_KIND_CLASS:
+ t = "class ";
+ break;
+ case DEBUG_KIND_UNION_CLASS:
+ t = "union class ";
+ break;
+ default:
+ abort ();
+ return false;
+ }
+
+ if (! push_type (info, t))
+ return false;
+ if (name != NULL)
+ tag = name;
+ else
+ {
+ sprintf (idbuf, "%%anon%u", id);
+ tag = idbuf;
+ }
+
+ if (! append_type (info, tag))
+ return false;
+ if (name != NULL && kind != DEBUG_KIND_ENUM)
+ {
+ sprintf (idbuf, " /* id %u */", id);
+ if (! append_type (info, idbuf))
+ return false;
+ }
+
+ return true;
+}
+
+/* Output a typedef. */
+
+static boolean
+pr_typdef (p, name)
+ PTR p;
+ const char *name;
+{
+ struct pr_handle *info = (struct pr_handle *) p;
+ char *s;
+
+ if (! substitute_type (info, name))
+ return false;
+
+ s = pop_type (info);
+ if (s == NULL)
+ return false;
+/*
+ indent (info);
+ TRACE_FPRINTF( (info->f, "typedef %s;\n", s));
+*/
+ free (s);
+
+ return true;
+}
+
+/* Output a tag. The tag should already be in the string on the
+ stack, so all we have to do here is print it out. */
+
+/*ARGSUSED*/
+static boolean
+pr_tag (p, name)
+ PTR p;
+ const char *name;
+{
+ struct pr_handle *info = (struct pr_handle *) p;
+ char *t;
+
+ t = pop_type (info);
+ if (t == NULL)
+ return false;
+/*
+ indent (info);
+ TRACE_FPRINTF( (info->f, "%s;\n", t));
+*/
+ free (t);
+
+ return true;
+}
+
+/* Output an integer constant. */
+
+static boolean
+pr_int_constant (p, name, val)
+ PTR p;
+ const char *name;
+ bfd_vma val;
+{
+/*
+ struct pr_handle *info = (struct pr_handle *) p;
+ char ab[20];
+ indent (info);
+ print_vma (val, ab, false, false);
+ TRACE_FPRINTF( (info->f, "const int %s = %s;\n", name, ab));
+ */
+ return true;
+}
+
+/* Output a floating point constant. */
+
+static boolean
+pr_float_constant (p, name, val)
+ PTR p;
+ const char *name;
+ double val;
+{
+/*
+ struct pr_handle *info = (struct pr_handle *) p;
+ indent (info);
+ TRACE_FPRINTF( (info->f, "const double %s = %g;\n", name, val));
+ */
+ return true;
+}
+
+/* Output a typed constant. */
+
+static boolean
+pr_typed_constant (p, name, val)
+ PTR p;
+ const char *name;
+ bfd_vma val;
+{
+ struct pr_handle *info = (struct pr_handle *) p;
+ char *t;
+
+ t = pop_type (info);
+ if (t == NULL)
+ return false;
+/*
+ char ab[20];
+ indent (info);
+ print_vma (val, ab, false, false);
+ TRACE_FPRINTF( (info->f, "const %s %s = %s;\n", t, name, ab));
+*/
+ free (t);
+
+ return true;
+}
+
+/* Output a variable. */
+
+static boolean
+pr_variable (p, name, kind, val)
+ PTR p;
+ const char *name;
+ enum debug_var_kind kind;
+ bfd_vma val;
+{
+ struct pr_handle *info = (struct pr_handle *) p;
+ char *t;
+ char ab[20];
+ (void)ab;
+
+ if (! substitute_type (info, name))
+ return false;
+
+ t = pop_type (info);
+ if (t == NULL)
+ return false;
+
+#if 0
+ indent (info);
+ switch (kind)
+ {
+ case DEBUG_STATIC:
+ case DEBUG_LOCAL_STATIC:
+ TRACE_FPRINTF( (info->f, "static "));
+ break;
+ case DEBUG_REGISTER:
+ TRACE_FPRINTF( (info->f, "register "));
+ break;
+ default:
+ break;
+ }
+ print_vma (val, ab, true, true);
+ TRACE_FPRINTF( (info->f, "%s /* %s */;\n", t, ab));
+#else /* 0 */
+#if 0
+ if (kind==DEBUG_STATIC || kind==DEBUG_LOCAL_STATIC) {
+ print_vma (val, ab, true, true);
+ TRACE_FPRINTF( (info->f, "STATIC_VAR: %s /* %s */;\n", t, ab));
+ }
+#endif /* 0 */
+#endif /* !0 */
+
+ free (t);
+
+ return true;
+}
+
+/* Start outputting a function. */
+
+static boolean
+pr_start_function (p, name, global)
+ PTR p;
+ const char *name;
+ boolean global;
+{
+ struct pr_handle *info = (struct pr_handle *) p;
+ char *t;
+
+ if (! substitute_type (info, name))
+ return false;
+
+ t = pop_type (info);
+ if (t == NULL)
+ return false;
+
+#if 0
+ indent (info);
+ if (! global)
+ TRACE_FPRINTF( (info->f, "static "));
+ TRACE_FPRINTF( (info->f, "%s (", t));
+ info->parameter = 1;
+#else /* 0 */
+ if (info->functions_size==info->functions_maxsize) {
+ info->functions_maxsize *= 2;
+ info->functions = xrealloc(info->functions,
+ info->functions_maxsize*sizeof(debug_function_t));
+ assert(info->functions!=0);
+ }
+ /* info->functions[info->functions_size] = xmalloc(sizeof(debug_function_t)); */
+ info->function = &info->functions[info->functions_size];
+ ++info->functions_size;
+ info->function->symbol = NULL;
+ info->function->lines = NULL;
+ info->function->lines_count = 0;
+ info->function->max_lines_count = 0;
+ info->function->name = t;
+ info->function->filename = NULL;
+ info->function->block = NULL;
+ info->function->argv = NULL;
+ info->function->argc = 0;
+ info->function->max_argc = 0;
+#endif /* !0 */
+ return true;
+}
+
+/* Output a function parameter. */
+
+static boolean
+pr_function_parameter (p, name, kind, val)
+ PTR p;
+ const char *name;
+ enum debug_parm_kind kind;
+ bfd_vma val;
+{
+ struct pr_handle *info = (struct pr_handle *) p;
+ debug_function_t* f = info->function;
+ char *t;
+ char ab[20];
+ (void)ab;
+
+ if (kind == DEBUG_PARM_REFERENCE
+ || kind == DEBUG_PARM_REF_REG)
+ {
+ if (! pr_reference_type (p))
+ return false;
+ }
+
+ if (! substitute_type (info, name))
+ return false;
+
+ t = pop_type (info);
+ if (t == NULL)
+ return false;
+
+#if 0
+ if (info->parameter != 1)
+ TRACE_FPRINTF( (info->f, ", "));
+
+ if (kind == DEBUG_PARM_REG || kind == DEBUG_PARM_REF_REG)
+ TRACE_FPRINTF( (info->f, "register "));
+
+ print_vma (val, ab, true, true);
+ TRACE_FPRINTF( (info->f, "%s /* %s */", t, ab));
+ free (t);
+ ++info->parameter;
+#else /* 0 */
+ assert(f!=NULL);
+ if (f->argv==NULL) {
+ f->max_argc = 7; /* rarely anyone has more than that many args... */
+ f->argv = xmalloc(sizeof(debug_parameter_t)*f->max_argc);
+ } else if (f->argc==f->max_argc) {
+ f->max_argc *= 2;
+ f->argv = realloc(f->argv,sizeof(debug_parameter_t)*f->max_argc);
+ }
+ f->argv[f->argc].offset = val;
+ f->argv[f->argc].name = t;
+ ++f->argc;
+#endif /* !0 */
+ return true;
+}
+
+/* Start writing out a block. */
+
+static boolean
+pr_start_block (p, addr)
+ PTR p;
+ bfd_vma addr;
+{
+ struct pr_handle *info = (struct pr_handle *) p;
+ char ab[20];
+ debug_block_t* block = 0;
+ (void)ab;
+#if 0
+ if (info->parameter > 0)
+ {
+ TRACE_FPRINTF( (info->f, ")\n"));
+ info->parameter = 0;
+ }
+ indent (info);
+ print_vma (addr, ab, true, true);
+ TRACE_FPRINTF( (info->f, "{ /* %s */\n", ab));
+ info->indent += 2;
+#else
+ if (info->block) {
+ if (info->block->childs_count==0)
+ info->block->childs = xmalloc(sizeof(debug_block_t));
+ else
+ info->block->childs = xrealloc(info->block->childs,
+ info->block->childs_count*sizeof(debug_block_t));
+ block = &info->block->childs[info->block->childs_count];
+ } else {
+ block = xmalloc(sizeof(debug_block_t));
+ info->function->block = block;
+ }
+ block->begin_addr = addr;
+ block->end_addr = 0;
+ block->parent = info->block;
+ block->childs = NULL;
+ block->childs_count = 0;
+ info->block = block;
+#endif
+ return true;
+}
+
+/* Write out line number information. */
+
+static boolean
+pr_lineno (p, filename, lineno, addr)
+ PTR p;
+ const char *filename;
+ unsigned long lineno;
+ bfd_vma addr;
+{
+ struct pr_handle *info = (struct pr_handle *) p;
+ char ab[20];
+ debug_function_t* f = info->function;
+ (void)ab;
+
+#if 0
+ indent (info);
+ print_vma (addr, ab, true, true);
+ TRACE_FPRINTF( (info->f, "/* file %s line %lu addr %s */\n", filename, lineno, ab));
+#else /* 0 */
+ if (f==NULL) /* FIXME: skips junk silently. */
+ return true;
+ /* assert(f!=NULL); */
+ if (f->filename==NULL) {
+ f->filename = filename;
+ assert(f->lines==0);
+ f->max_lines_count = 4;
+ f->lines = xmalloc(sizeof(debug_lineno_t)*f->max_lines_count);
+ }
+ if (f->lines_count==f->max_lines_count) {
+ f->max_lines_count *= 2;
+ f->lines = xrealloc(f->lines, sizeof(debug_lineno_t)*f->max_lines_count);
+ }
+ f->lines[f->lines_count].lineno = lineno;
+ f->lines[f->lines_count].addr = addr;
+ ++f->lines_count;
+#endif /* !0 */
+
+ return true;
+}
+
+/* Finish writing out a block. */
+
+static boolean
+pr_end_block (p, addr)
+ PTR p;
+ bfd_vma addr;
+{
+ struct pr_handle *info = (struct pr_handle *) p;
+
+#if 0
+ char ab[20];
+
+ info->indent -= 2;
+ indent (info);
+ print_vma (addr, ab, true, true);
+ TRACE_FPRINTF( (info->f, "} /* %s */\n", ab));
+#else /* 0 */
+ assert(info->block!=0);
+ info->block->end_addr = addr;
+ info->block = info->block->parent;
+#endif /* !0 */
+
+ return true;
+}
+
+/* Finish writing out a function. */
+
+/*ARGSUSED*/
+static boolean
+pr_end_function (p)
+ PTR p;
+{
+ struct pr_handle *info = (struct pr_handle *) p;
+ assert(info->block==0);
+ info->function = NULL;
+ return true;
+}
+
+/* third parameter to segv_action. */
+/* Got it after a bit of head scratching and stack dumping. */
+typedef struct {
+ u_int32_t foo1; /* +0x00 */
+ u_int32_t foo2;
+ u_int32_t foo3;
+ u_int32_t foo4; /* usually 2 */
+ u_int32_t foo5; /* +0x10 */
+ u_int32_t xgs; /* always zero */
+ u_int32_t xfs; /* always zero */
+ u_int32_t xes; /* always es=ds=ss */
+ u_int32_t xds; /* +0x20 */
+ u_int32_t edi;
+ u_int32_t esi;
+ u_int32_t ebp;
+ u_int32_t esp; /* +0x30 */
+ u_int32_t ebx;
+ u_int32_t edx;
+ u_int32_t ecx;
+ u_int32_t eax; /* +0x40 */
+ u_int32_t foo11; /* usually 0xe */
+ u_int32_t foo12; /* usually 0x6 */
+ u_int32_t eip; /* instruction pointer */
+ u_int32_t xcs; /* +0x50 */
+ u_int32_t foo21; /* usually 0x2 */
+ u_int32_t foo22; /* second stack pointer?! Probably. */
+ u_int32_t xss;
+ u_int32_t foo31; /* +0x60 */ /* usually 0x0 */
+ u_int32_t foo32; /* usually 0x2 */
+ u_int32_t fault_addr; /* Address which caused a fault */
+ u_int32_t foo41; /* usually 0x2 */
+} signal_regs_t;
+
+signal_regs_t* ptrace_regs = 0; /* Tells my_ptrace to "ptrace" current process" */
+/*
+ * my_ptrace: small wrapper around ptrace.
+ * Act as normal ptrace if ptrace_regs==0.
+ * Read data from current process if ptrace_regs!=0.
+ */
+static int
+my_ptrace( int request,
+ int pid,
+ int addr,
+ int data)
+{
+ if (ptrace_regs==0)
+ return ptrace(request, pid, addr, data);
+ /* we are tracing ourselves! */
+ switch (request) {
+ case PTRACE_ATTACH: return 0;
+ case PTRACE_CONT: return 0;
+ case PTRACE_DETACH: return 0;
+ case PTRACE_PEEKUSER:
+ switch (addr / 4) {
+ case EIP: return ptrace_regs->eip;
+ case EBP: return ptrace_regs->ebp;
+ default: assert(0);
+ }
+ case PTRACE_PEEKTEXT: /* FALLTHROUGH */
+ case PTRACE_PEEKDATA: return *(int*)(addr);
+ default: assert(0);
+ }
+ errno = 1; /* what to do here? */
+ return 1; /* failed?! */
+}
+
+#define MAXARGS 6
+
+/*
+ * To minimize the number of parameters.
+ */
+typedef struct {
+ asymbol** syms; /* Sorted! */
+ int symcount;
+ debug_function_t** functions;
+ int functions_size;
+} symbol_data_t;
+
+/*
+ * Perform a search. A binary search for a symbol.
+ */
+static void
+decode_symbol( symbol_data_t* symbol_data,
+ const unsigned long addr,
+ char* buf,
+ const int bufsize)
+{
+ asymbol** syms = symbol_data->syms;
+ const int symcount = symbol_data->symcount;
+ int bottom = 0;
+ int top = symcount - 1;
+ int i;
+ if (symcount==0) {
+ sprintf(buf, "????");
+ return;
+ }
+ while (top>bottom+1) {
+ i = (top+bottom) / 2;
+ if (bfd_asymbol_value(syms[i])==addr) {
+ sprintf(buf, "%s", syms[i]->name);
+ return;
+ } else if (bfd_asymbol_value(syms[i]) > addr)
+ top = i;
+ else
+ bottom = i;
+ }
+ i = bottom;
+ if (addr<bfd_asymbol_value(syms[i]) || addr>(syms[i]->section->vma+syms[i]->section->_cooked_size))
+ sprintf(buf, "????");
+ else
+ sprintf(buf, "%s + 0x%lx", syms[i]->name, addr-bfd_asymbol_value(syms[i]));
+}
+
+/*
+ * 1. Perform a binary search for an debug_function_t.
+ * 2. Fill buf/bufsize with name, parameters and lineno, if found
+ * Or with '????' otherwise.
+ */
+static debug_function_t*
+find_debug_function_t( symbol_data_t* symbol_data,
+ const pid_t pid,
+ const unsigned long fp, /* frame pointer */
+ const unsigned long addr,
+ char* buf, /* string buffer */
+ const int bufsize)/* FIXME: not used! */
+{
+ debug_function_t** syms = symbol_data->functions;
+ debug_function_t* f = NULL;
+ debug_block_t* block = NULL;
+ debug_lineno_t* lineno = NULL;
+ const int symcount = symbol_data->functions_size;
+ int bottom = 0;
+ int top = symcount - 1;
+ int i;
+ char* bufptr = buf;
+
+ if (symcount==0) {
+ sprintf(buf, "????");
+ return NULL;
+ }
+ while (top>bottom+1) {
+ i = (top+bottom) / 2;
+ if (syms[i]->block->begin_addr==addr) {
+ f = syms[i];
+ break;
+ } else if (syms[i]->block->begin_addr > addr)
+ top = i;
+ else
+ if (syms[i]->block->end_addr >= addr) {
+ f = syms[i];
+ break;
+ } else
+ bottom = i;
+ }
+ i = bottom;
+ if (f!=0)
+ block = f->block;
+ else {
+ block = syms[i]->block;
+ if (block->begin_addr>=addr && block->end_addr<=addr)
+ f = syms[i];
+ }
+ if (f==0)
+ sprintf(buf, "????");
+ else {
+ /*
+ * Do the backtrace the GDB way...
+ */
+ unsigned long arg;
+ /* assert(f->lines_count>0); */
+ if (f->lines_count>0) {
+ lineno = &f->lines[f->lines_count-1];
+ for (i=1; i<f->lines_count; ++i)
+ if (f->lines[i].addr>addr) {
+ lineno = &f->lines[i-1];
+ break;
+ }
+ }
+ bufptr[0] = 0;
+ bufptr += sprintf(bufptr, "%s+0x%lx (", f->name, addr-block->begin_addr);
+ for (i=0; i<f->argc; ++i) {
+ bufptr += sprintf(bufptr, "%s = ", f->argv[i].name);
+ /* FIXME: better parameter printing */
+ errno = 0;
+ arg = my_ptrace(PTRACE_PEEKDATA, pid, fp+f->argv[i].offset, 0);
+ assert(errno==0);
+ bufptr += sprintf(bufptr, "0x%x", arg);
+ if (i!=f->argc-1)
+ bufptr += sprintf(bufptr, ", ");
+ }
+ if (lineno!=0)
+ bufptr += sprintf(bufptr, ") at %s:%d", f->filename, lineno->lineno);
+ }
+ return f;
+}
+
+/*
+ * Advance through the stacks and display frames as needed.
+ */
+static int
+my_crawl( int pid,
+ symbol_data_t* symbol_data,
+ int fout)
+{
+ unsigned long pc = 0;
+ unsigned long fp = 0;
+ unsigned long nextfp;
+ unsigned long nargs;
+ unsigned long i;
+ unsigned long arg;
+ char buf[8096]; // FIXME: enough?
+ debug_function_t* f = 0;
+
+ errno = 0;
+
+ pc = my_ptrace(PTRACE_PEEKUSER, pid, EIP * 4, 0);
+ if (!errno)
+ fp = my_ptrace(PTRACE_PEEKUSER, pid, EBP * 4, 0);
+
+ if (!errno) {
+#if 1
+ f = find_debug_function_t(symbol_data, pid, fp, pc, buf, sizeof(buf));
+ fdprintf(fout,"0x%08lx: %s", pc, buf);
+ for ( ; !errno && fp; ) {
+ nextfp = my_ptrace(PTRACE_PEEKDATA, pid, fp, 0);
+ if (errno)
+ break;
+
+ if (f==0) {
+ nargs = (nextfp - fp - 8) / 4;
+ if (nargs > MAXARGS)
+ nargs = MAXARGS;
+ if (nargs > 0) {
+ fdputs(" (", fout);
+ for (i = 1; i <= nargs; i++) {
+ arg = my_ptrace(PTRACE_PEEKDATA, pid, fp + 4 * (i + 1), 0);
+ if (errno)
+ break;
+ fdprintf(fout,"%lx", arg);
+ if (i < nargs)
+ fdputs(", ", fout);
+ }
+ fdputc(')', fout);
+ nargs = nextfp - fp - 8 - (4 * nargs);
+ if (!errno && nargs > 0)
+ fdprintf(fout," + %lx\n", nargs);
+ else
+ fdputc('\n', fout);
+ } else
+ fdputc('\n', fout);
+ } else
+ fdputc('\n', fout);
+
+ if (errno || !nextfp)
+ break;
+ pc = my_ptrace(PTRACE_PEEKDATA, pid, fp + 4, 0);
+ fp = nextfp;
+ if (errno)
+ break;
+ f = find_debug_function_t(symbol_data, pid, fp, pc, buf, sizeof(buf));
+ fdprintf(fout,"0x%08lx: %s", pc, buf);
+ }
+#else /* 1 */
+ decode_symbol(symbol_data, pc, buf, sizeof(buf));
+ fdprintf(fout,"0x%08lx: %s", pc, buf);
+ for ( ; !errno && fp; ) {
+ nextfp = my_ptrace(PTRACE_PEEKDATA, pid, fp, 0);
+ if (errno)
+ break;
+
+ nargs = (nextfp - fp - 8) / 4;
+ if (nargs > MAXARGS)
+ nargs = MAXARGS;
+ if (nargs > 0) {
+ fputs(" (", fout);
+ for (i = 1; i <= nargs; i++) {
+ arg = my_ptrace(PTRACE_PEEKDATA, pid, fp + 4 * (i + 1), 0);
+ if (errno)
+ break;
+ fdprintf(fout,"%lx", arg);
+ if (i < nargs)
+ fputs(", ", fout);
+ }
+ fdputc(')', fout);
+ nargs = nextfp - fp - 8 - (4 * nargs);
+ if (!errno && nargs > 0)
+ fdprintf(fout," + %lx\n", nargs);
+ else
+ fdputc('\n', fout);
+ } else
+ fdputc('\n', fout);
+
+ if (errno || !nextfp)
+ break;
+ pc = my_ptrace(PTRACE_PEEKDATA, pid, fp + 4, 0);
+ fp = nextfp;
+ if (errno)
+ break;
+ decode_symbol(symbol_data, pc, buf, sizeof(buf));
+ fdprintf(fout,"0x%08lx: %s", pc, buf);
+ }
+#endif /* !1 */
+ }
+ if (errno)
+ perror("my_crawl");
+ return errno;
+}
+
+/* layout from /usr/src/linux/arch/i386/kernel/process.c */
+static void
+show_regs( signal_regs_t* regs,
+ int fd)
+{
+ /* long cr0 = 0L, cr2 = 0L, cr3 = 0L; */
+
+ fdprintf(fd,"\n");
+ fdprintf(fd,"FAULT ADDR: %08x\n", regs->fault_addr);
+ fdprintf(fd,"EIP: %04x:[<%08x>]",0xffff & regs->xcs,regs->eip);
+ if (regs->xcs & 3)
+ fdprintf(fd," ESP: %04x:%08x",0xffff & regs->xss,regs->esp);
+ /*fdprintf(fd," EFLAGS: %08lx\n",regs->eflags); */
+ fdprintf(fd, "\n");
+ fdprintf(fd,"EAX: %08x EBX: %08x ECX: %08x EDX: %08x\n",
+ regs->eax,regs->ebx,regs->ecx,regs->edx);
+ fdprintf(fd,"ESI: %08x EDI: %08x EBP: %08x",
+ regs->esi, regs->edi, regs->ebp);
+ fdprintf(fd," DS: %04x ES: %04x\n",
+ 0xffff & regs->xds,0xffff & regs->xes);
+ /*
+ __asm__("movl %%cr0, %0": "=r" (cr0));
+ __asm__("movl %%cr2, %0": "=r" (cr2));
+ __asm__("movl %%cr3, %0": "=r" (cr3));
+ fprintf(stderr,"CR0: %08lx CR2: %08lx CR3: %08lx\n", cr0, cr2, cr3); */
+}
+
+/*
+ * Load a BFD for an executable based on PID. Return 0 on failure.
+ */
+static bfd*
+load_bfd( const int pid)
+{
+ char filename[512];
+ bfd* abfd = 0;
+
+ /* Get the contents from procfs. */
+#if 1
+ sprintf(filename, "/proc/%d/exe", pid);
+#else
+ sprintf(filename, "crashing");
+#endif
+
+ if ((abfd = bfd_openr (filename, 0))== NULL)
+ bfd_nonfatal (filename);
+ else {
+ char** matching;
+ assert(bfd_check_format(abfd, bfd_archive)!=true);
+
+ /*
+ * There is no indication in BFD documentation that it should be done.
+ * God knows why...
+ */
+ if (!bfd_check_format_matches (abfd, bfd_object, &matching)) {
+ bfd_nonfatal (bfd_get_filename (abfd));
+ if (bfd_get_error () == bfd_error_file_ambiguously_recognized) {
+ list_matching_formats (matching);
+ free (matching);
+ }
+ }
+ }
+ return abfd;
+}
+
+/*
+ * Those are for qsort. We need only function addresses, so all the others don't count.
+ */
+/*
+ * Compare two BFD::asymbol-s.
+ */
+static int
+compare_symbols(const void* ap,
+ const void* bp)
+{
+ const asymbol *a = *(const asymbol **)ap;
+ const asymbol *b = *(const asymbol **)bp;
+ if (bfd_asymbol_value (a) > bfd_asymbol_value (b))
+ return 1;
+ else if (bfd_asymbol_value (a) < bfd_asymbol_value (b))
+ return -1;
+ return 0;
+}
+
+/*
+ * Compare two debug_asymbol_t-s.
+ */
+static int
+compare_debug_function_t(const void* ap,
+ const void* bp)
+{
+ const debug_function_t *a = *(const debug_function_t **)ap;
+ const debug_function_t *b = *(const debug_function_t **)bp;
+ assert(a->block!=0);
+ assert(b->block!=0);
+ {
+ const bfd_vma addr1 = a->block->begin_addr;
+ const bfd_vma addr2 = b->block->begin_addr;
+ if (addr1 > addr2)
+ return 1;
+ else if (addr2 > addr1)
+ return -1;
+ }
+ return 0;
+}
+
+/*
+ * Filter out (in place) symbols that are useless for stack tracing.
+ * COUNT is the number of elements in SYMBOLS.
+ * Return the number of useful symbols.
+ */
+
+static long
+remove_useless_symbols( asymbol** symbols,
+ long count)
+{
+ asymbol** in_ptr = symbols;
+ asymbol** out_ptr = symbols;
+
+ while (--count >= 0) {
+ asymbol *sym = *in_ptr++;
+
+ if (sym->name == NULL || sym->name[0] == '\0' || sym->value==0)
+ continue;
+ if (sym->flags & (BSF_DEBUGGING))
+ continue;
+ if (bfd_is_und_section (sym->section) || bfd_is_com_section (sym->section))
+ continue;
+ *out_ptr++ = sym;
+ }
+ return out_ptr - symbols;
+}
+
+/*
+ * Debugging information.
+ */
+static bfd* abfd = 0;
+static PTR dhandle = 0;
+static asymbol** syms = 0;
+static long symcount = 0;
+static asymbol** sorted_syms = 0;
+static long sorted_symcount = 0;
+static debug_function_t** functions = 0;
+static int functions_size = 0;
+static int sigreport = SIGUSR1;
+static pthread_t segv_tid; /* What thread did SEGV? */
+static pid_t segv_pid;
+
+/*
+ * We'll get here after a SIGSEGV. But you can install it on other signals, too :)
+ * Because we are in the middle of the SIGSEGV, we are on our own. We can't do
+ * any malloc(), any fopen(), nothing. The last is actually a sin. We event can't
+ * fprintf(stderr,...)!!!
+ */
+static void
+segv_action(int signo, siginfo_t* siginfo, void* ptr)
+{
+ symbol_data_t symbol_data;
+ int fd = -1;
+
+ segv_pid = getpid();
+ segv_tid = pthread_self();
+ fd = open_log_file(segv_tid, segv_pid);
+ /* signal(SIGSEGV, SIG_DFL); */
+ ptrace_regs = (signal_regs_t*)ptr;
+ assert(ptrace_regs!=0);
+
+ /* Show user how guilty we are. */
+ fdprintf(fd,"--------- SEGV in PROCESS %d, THREAD %d ---------------\n", segv_pid, pthread_self());
+ show_regs(ptrace_regs, fd);
+
+ /* Some form of stack trace, too. */
+ fdprintf(fd, "STACK TRACE:\n");
+
+ symbol_data.syms = sorted_syms;
+ symbol_data.symcount = sorted_symcount;
+ symbol_data.functions = functions;
+ symbol_data.functions_size = functions_size;
+ my_crawl(segv_pid, &symbol_data, fd);
+ //fflush(stdout);
+ close(fd);
+ linuxthreads_notify_others(sigreport);
+}
+
+
+static void
+report_action(int signo, siginfo_t* siginfo, void* ptr)
+{
+ const int pid = getpid();
+ pthread_t tid = pthread_self();
+ symbol_data_t symbol_data;
+ int fd;
+ if (pthread_equal(tid, segv_tid)) {
+ /* We have already printed our stack trace... */
+ return;
+ }
+
+ fd = open_log_file(tid, pid);
+ fdprintf(fd, "REPORT: CURRENT PROCESS:%d, THREAD:%d\n", getpid(), pthread_self());
+ /* signal(SIGSEGV, SIG_DFL); */
+ ptrace_regs = (signal_regs_t*)ptr;
+ assert(ptrace_regs!=0);
+
+ /* Show user how guilty we are. */
+ fdprintf(fd,"--------- STACK TRACE FOR PROCESS %d, THREAD %d ---------------\n", pid, pthread_self());
+ show_regs(ptrace_regs, fd);
+
+ /* Some form of stack trace, too. */
+ fdprintf(fd, "STACK TRACE:\n");
+
+ symbol_data.syms = sorted_syms;
+ symbol_data.symcount = sorted_symcount;
+ symbol_data.functions = functions;
+ symbol_data.functions_size = functions_size;
+ my_crawl(pid, &symbol_data, fd);
+ //fflush(stdout);
+ close(fd);
+ /* Tell segv_thread to proceed after pause(). */
+ /*pthread_kill(segv_tid, sigreport);
+ kill(segv_pid, sigreport);
+ pthread_cancel(tid); */
+}
+
+/*
+ * Main library routine. Just call it on your program.
+ */
+int
+pstack_install_segv_action( const char* path_format_)
+{
+ const int pid = getpid();
+ struct sigaction act;
+
+ /* Store what we have to for later usage. */
+ path_format = path_format_;
+
+ /* We need a signal action for SIGSEGV and sigreport ! */
+ sigreport = SIGUSR1;
+ act.sa_handler = 0;
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = SA_SIGINFO|SA_ONESHOT; /* Just one SIGSEGV. */
+ act.sa_sigaction = segv_action;
+ act.sa_restorer = NULL;
+ if (sigaction(SIGSEGV, &act, NULL)!=0) {
+ perror("sigaction");
+ return 1;
+ }
+ act.sa_sigaction = report_action;
+ act.sa_flags = SA_SIGINFO; /* But many sigreports. */
+ if (sigaction(sigreport, &act, NULL)!=0) {
+ perror("sigaction");
+ return 1;
+ }
+
+ /* And a little setup for libiberty. */
+ program_name = "crashing";
+ xmalloc_set_program_name (program_name);
+
+ /* Umm, and initialize BFD, too */
+ bfd_init();
+#if 0
+ list_supported_targets(0, stdout);
+ set_default_bfd_target();
+#endif /* 0 */
+
+ if ((abfd = load_bfd(pid))==0)
+ fprintf(stderr, "BFD load failed..\n");
+ else {
+ long storage_needed = bfd_get_symtab_upper_bound (abfd);
+ long i;
+ (void)i;
+
+ if (storage_needed < 0)
+ fprintf(stderr, "Symbol table size estimation failure.\n");
+ else if (storage_needed > 0) {
+ syms = (asymbol **) xmalloc (storage_needed);
+ symcount = bfd_canonicalize_symtab (abfd, syms);
+
+ TRACE_FPRINTF((stderr, "TOTAL: %ld SYMBOLS.\n", symcount));
+ /* We need debugging info, too! */
+ if (symcount==0 || (dhandle = read_debugging_info (abfd, syms, symcount))==0)
+ fprintf(stderr, "NO DEBUGGING INFORMATION FOUND.\n");
+
+ /* We make a copy of syms to sort. We don't want to sort syms
+ because that will screw up the relocs. */
+ sorted_syms = (asymbol **) xmalloc (symcount * sizeof (asymbol *));
+ memcpy (sorted_syms, syms, symcount * sizeof (asymbol *));
+
+#if 0
+ for (i=0; i<symcount; ++i)
+ if (syms[i]->name!=0 && strlen(syms[i]->name)>0 && syms[i]->value!=0)
+ printf("%08lx T %s\n", syms[i]->section->vma + syms[i]->value, syms[i]->name);
+#endif
+ sorted_symcount = remove_useless_symbols (sorted_syms, symcount);
+ TRACE_FPRINTF((stderr, "SORTED: %ld SYMBOLS.\n", sorted_symcount));
+
+ /* Sort the symbols into section and symbol order */
+ qsort (sorted_syms, sorted_symcount, sizeof (asymbol *), compare_symbols);
+#if 0
+ for (i=0; i<sorted_symcount; ++i)
+ if (sorted_syms[i]->name!=0 && strlen(sorted_syms[i]->name)>0 && sorted_syms[i]->value!=0)
+ printf("%08lx T %s\n", sorted_syms[i]->section->vma + sorted_syms[i]->value, sorted_syms[i]->name);
+#endif
+ /* We have symbols, we need debugging info somehow sorted out. */
+ if (dhandle==0) {
+ fprintf(stderr, "STACK TRACE WILL BE UNCOMFORTABLE.\n");
+ } else {
+ /* Start collecting the debugging information.... */
+ struct pr_handle info;
+
+ info.f = stdout;
+ info.indent = 0;
+ info.stack = NULL;
+ info.parameter = 0;
+ info.block = NULL;
+ info.function = NULL;
+ info.functions_size = 0;
+ info.functions_maxsize = 1000;
+ info.functions = (debug_function_t*)xmalloc(sizeof(debug_function_t)*info.functions_maxsize);
+ debug_write (dhandle, &pr_fns, (PTR) &info);
+ TRACE_FPRINTF((stdout, "\n%d DEBUG SYMBOLS\n", info.functions_size));
+ assert(info.functions_size!=0);
+ functions = xmalloc(sizeof(debug_function_t*)*info.functions_size);
+ functions_size = info.functions_size;
+ for (i=0; i<functions_size; ++i)
+ functions[i] = &info.functions[i];
+ /* Sort the symbols into section and symbol order */
+ qsort (functions, functions_size, sizeof(debug_function_t*),
+ compare_debug_function_t);
+#if 0
+ for (i=0; i<info.functions_size; ++i)
+ fprintf(stdout, "%08lx T %s\n", info.functions[i].block->begin_addr, info.functions[i].name);
+#endif
+ fflush(stdout);
+ }
+ } else /* storage_needed == 0 */
+ fprintf(stderr, "NO SYMBOLS FOUND.\n");
+ }
+ return 0;
+}
+
+/*********************************************************************/
+/*********************************************************************/
+/*********************************************************************/
diff --git a/pstack/pstack.h b/pstack/pstack.h
new file mode 100644
index 00000000000..4c4fad7e754
--- /dev/null
+++ b/pstack/pstack.h
@@ -0,0 +1,22 @@
+/* $Header$ */
+
+#ifndef pstack_pstack_h_
+#define pstack_pstack_h_
+
+#include "pstacktrace.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Install the stack-trace-on-SEGV handler....
+ */
+extern int
+pstack_install_segv_action( const char* path_format);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* pstack_pstack_h_ */
+
diff --git a/pstack/pstacktrace.h b/pstack/pstacktrace.h
new file mode 100644
index 00000000000..c884bcb9f87
--- /dev/null
+++ b/pstack/pstacktrace.h
@@ -0,0 +1,24 @@
+/* $Header$ */
+
+/*
+ * Debugging macros.
+ */
+
+#ifndef pstacktrace_h_
+#define pstacktrace_h_
+
+#define PSTACK_DEBUG 1
+#undef PSTACK_DEBUG
+
+#ifdef PSTACK_DEBUG
+# define TRACE_PUTC(a) putc a
+# define TRACE_FPUTS(a) fputs a
+# define TRACE_FPRINTF(a) fprintf a
+#else /* PSTACK_DEBUG */
+# define TRACE_PUTC(a) (void)0
+# define TRACE_FPUTS(a) (void)0
+# define TRACE_FPRINTF(a) (void)0
+#endif /* !PSTACK_DEBUG */
+
+#endif /* pstacktrace_h_ */
+
diff --git a/pstack/rddbg.c b/pstack/rddbg.c
new file mode 100644
index 00000000000..be3dfc21c57
--- /dev/null
+++ b/pstack/rddbg.c
@@ -0,0 +1,462 @@
+/* rddbg.c -- Read debugging information into a generic form.
+ Copyright (C) 1995, 96, 1997 Free Software Foundation, Inc.
+ Written by Ian Lance Taylor <ian@cygnus.com>.
+
+ This file is part of GNU Binutils.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+/* This file reads debugging information into a generic form. This
+ file knows how to dig the debugging information out of an object
+ file. */
+
+#include <bfd.h>
+#include "bucomm.h"
+#include <libiberty.h>
+#include "debug.h"
+#include "budbg.h"
+
+static boolean read_section_stabs_debugging_info
+ PARAMS ((bfd *, asymbol **, long, PTR, boolean *));
+static boolean read_symbol_stabs_debugging_info
+ PARAMS ((bfd *, asymbol **, long, PTR, boolean *));
+static boolean read_ieee_debugging_info PARAMS ((bfd *, PTR, boolean *));
+static void save_stab PARAMS ((int, int, bfd_vma, const char *));
+static void stab_context PARAMS ((void));
+static void free_saved_stabs PARAMS ((void));
+
+/* Read debugging information from a BFD. Returns a generic debugging
+ pointer. */
+
+PTR
+read_debugging_info (abfd, syms, symcount)
+ bfd *abfd;
+ asymbol **syms;
+ long symcount;
+{
+ PTR dhandle;
+ boolean found;
+
+ dhandle = debug_init ();
+ if (dhandle == NULL)
+ return NULL;
+
+ if (! read_section_stabs_debugging_info (abfd, syms, symcount, dhandle,
+ &found))
+ return NULL;
+
+ if (bfd_get_flavour (abfd) == bfd_target_aout_flavour)
+ {
+ if (! read_symbol_stabs_debugging_info (abfd, syms, symcount, dhandle,
+ &found))
+ return NULL;
+ }
+
+ if (bfd_get_flavour (abfd) == bfd_target_ieee_flavour)
+ {
+ if (! read_ieee_debugging_info (abfd, dhandle, &found))
+ return NULL;
+ }
+
+ /* Try reading the COFF symbols if we didn't find any stabs in COFF
+ sections. */
+ if (! found
+ && bfd_get_flavour (abfd) == bfd_target_coff_flavour
+ && symcount > 0)
+ {
+#if 0
+/*
+ * JZ: Do we need coff?
+ */
+ if (! parse_coff (abfd, syms, symcount, dhandle))
+#else
+ fprintf (stderr, "%s: COFF support temporarily disabled\n",
+ bfd_get_filename (abfd));
+ return NULL;
+#endif
+ return NULL;
+ found = true;
+ }
+
+ if (! found)
+ {
+ fprintf (stderr, "%s: no recognized debugging information\n",
+ bfd_get_filename (abfd));
+ return NULL;
+ }
+
+ return dhandle;
+}
+
+/* Read stabs in sections debugging information from a BFD. */
+
+static boolean
+read_section_stabs_debugging_info (abfd, syms, symcount, dhandle, pfound)
+ bfd *abfd;
+ asymbol **syms;
+ long symcount;
+ PTR dhandle;
+ boolean *pfound;
+{
+ static struct
+ {
+ const char *secname;
+ const char *strsecname;
+ } names[] = { { ".stab", ".stabstr" } };
+ unsigned int i;
+ PTR shandle;
+
+ *pfound = false;
+ shandle = NULL;
+
+ for (i = 0; i < sizeof names / sizeof names[0]; i++)
+ {
+ asection *sec, *strsec;
+
+ sec = bfd_get_section_by_name (abfd, names[i].secname);
+ strsec = bfd_get_section_by_name (abfd, names[i].strsecname);
+ if (sec != NULL && strsec != NULL)
+ {
+ bfd_size_type stabsize, strsize;
+ bfd_byte *stabs, *strings;
+ bfd_byte *stab;
+ bfd_size_type stroff, next_stroff;
+
+ stabsize = bfd_section_size (abfd, sec);
+ stabs = (bfd_byte *) xmalloc (stabsize);
+ if (! bfd_get_section_contents (abfd, sec, stabs, 0, stabsize))
+ {
+ fprintf (stderr, "%s: %s: %s\n",
+ bfd_get_filename (abfd), names[i].secname,
+ bfd_errmsg (bfd_get_error ()));
+ return false;
+ }
+
+ strsize = bfd_section_size (abfd, strsec);
+ strings = (bfd_byte *) xmalloc (strsize);
+ if (! bfd_get_section_contents (abfd, strsec, strings, 0, strsize))
+ {
+ fprintf (stderr, "%s: %s: %s\n",
+ bfd_get_filename (abfd), names[i].strsecname,
+ bfd_errmsg (bfd_get_error ()));
+ return false;
+ }
+
+ if (shandle == NULL)
+ {
+ shandle = start_stab (dhandle, abfd, true, syms, symcount);
+ if (shandle == NULL)
+ return false;
+ }
+
+ *pfound = true;
+
+ stroff = 0;
+ next_stroff = 0;
+ for (stab = stabs; stab < stabs + stabsize; stab += 12)
+ {
+ bfd_size_type strx;
+ int type;
+ int other;
+ int desc;
+ bfd_vma value;
+
+ /* This code presumes 32 bit values. */
+
+ strx = bfd_get_32 (abfd, stab);
+ type = bfd_get_8 (abfd, stab + 4);
+ other = bfd_get_8 (abfd, stab + 5);
+ desc = bfd_get_16 (abfd, stab + 6);
+ value = bfd_get_32 (abfd, stab + 8);
+
+ if (type == 0)
+ {
+ /* Special type 0 stabs indicate the offset to the
+ next string table. */
+ stroff = next_stroff;
+ next_stroff += value;
+ }
+ else
+ {
+ char *f, *s;
+
+ f = NULL;
+ s = (char *) strings + stroff + strx;
+ while (s[strlen (s) - 1] == '\\'
+ && stab + 12 < stabs + stabsize)
+ {
+ char *p;
+
+ stab += 12;
+ p = s + strlen (s) - 1;
+ *p = '\0';
+ s = concat (s,
+ ((char *) strings
+ + stroff
+ + bfd_get_32 (abfd, stab)),
+ (const char *) NULL);
+
+ /* We have to restore the backslash, because, if
+ the linker is hashing stabs strings, we may
+ see the same string more than once. */
+ *p = '\\';
+
+ if (f != NULL)
+ free (f);
+ f = s;
+ }
+
+ save_stab (type, desc, value, s);
+
+ if (! parse_stab (dhandle, shandle, type, desc, value, s))
+ {
+#if 0
+/*
+ * JZ: skip the junk.
+ */
+ stab_context ();
+ free_saved_stabs ();
+ return false;
+#endif
+ }
+
+ /* Don't free f, since I think the stabs code
+ expects strings to hang around. This should be
+ straightened out. FIXME. */
+ }
+ }
+
+ free_saved_stabs ();
+ free (stabs);
+
+ /* Don't free strings, since I think the stabs code expects
+ the strings to hang around. This should be straightened
+ out. FIXME. */
+ }
+ }
+
+ if (shandle != NULL)
+ {
+ if (! finish_stab (dhandle, shandle))
+ return false;
+ }
+
+ return true;
+}
+
+/* Read stabs in the symbol table. */
+
+static boolean
+read_symbol_stabs_debugging_info (abfd, syms, symcount, dhandle, pfound)
+ bfd *abfd;
+ asymbol **syms;
+ long symcount;
+ PTR dhandle;
+ boolean *pfound;
+{
+ PTR shandle;
+ asymbol **ps, **symend;
+
+ shandle = NULL;
+ symend = syms + symcount;
+ for (ps = syms; ps < symend; ps++)
+ {
+ symbol_info i;
+
+ bfd_get_symbol_info (abfd, *ps, &i);
+
+ if (i.type == '-')
+ {
+ const char *s;
+ char *f;
+
+ if (shandle == NULL)
+ {
+ shandle = start_stab (dhandle, abfd, false, syms, symcount);
+ if (shandle == NULL)
+ return false;
+ }
+
+ *pfound = true;
+
+ s = i.name;
+ f = NULL;
+ while (s[strlen (s) - 1] == '\\'
+ && ps + 1 < symend)
+ {
+ char *sc, *n;
+
+ ++ps;
+ sc = xstrdup (s);
+ sc[strlen (sc) - 1] = '\0';
+ n = concat (sc, bfd_asymbol_name (*ps), (const char *) NULL);
+ free (sc);
+ if (f != NULL)
+ free (f);
+ f = n;
+ s = n;
+ }
+
+ save_stab (i.stab_type, i.stab_desc, i.value, s);
+
+ if (! parse_stab (dhandle, shandle, i.stab_type, i.stab_desc,
+ i.value, s))
+ {
+ stab_context ();
+ free_saved_stabs ();
+ return false;
+ }
+
+ /* Don't free f, since I think the stabs code expects
+ strings to hang around. This should be straightened out.
+ FIXME. */
+ }
+ }
+
+ free_saved_stabs ();
+
+ if (shandle != NULL)
+ {
+ if (! finish_stab (dhandle, shandle))
+ return false;
+ }
+
+ return true;
+}
+
+/* Read IEEE debugging information. */
+
+static boolean
+read_ieee_debugging_info (abfd, dhandle, pfound)
+ bfd *abfd;
+ PTR dhandle;
+ boolean *pfound;
+{
+ asection *dsec;
+ bfd_size_type size;
+ bfd_byte *contents;
+
+ /* The BFD backend puts the debugging information into a section
+ named .debug. */
+
+ dsec = bfd_get_section_by_name (abfd, ".debug");
+ if (dsec == NULL)
+ return true;
+
+ size = bfd_section_size (abfd, dsec);
+ contents = (bfd_byte *) xmalloc (size);
+ if (! bfd_get_section_contents (abfd, dsec, contents, 0, size))
+ return false;
+
+ if (! parse_ieee (dhandle, abfd, contents, size))
+ return false;
+
+ free (contents);
+
+ *pfound = true;
+
+ return true;
+}
+
+/* Record stabs strings, so that we can give some context for errors. */
+
+#define SAVE_STABS_COUNT (16)
+
+struct saved_stab
+{
+ int type;
+ int desc;
+ bfd_vma value;
+ char *string;
+};
+
+static struct saved_stab saved_stabs[SAVE_STABS_COUNT];
+static int saved_stabs_index;
+
+/* Save a stabs string. */
+
+static void
+save_stab (type, desc, value, string)
+ int type;
+ int desc;
+ bfd_vma value;
+ const char *string;
+{
+ if (saved_stabs[saved_stabs_index].string != NULL)
+ free (saved_stabs[saved_stabs_index].string);
+ saved_stabs[saved_stabs_index].type = type;
+ saved_stabs[saved_stabs_index].desc = desc;
+ saved_stabs[saved_stabs_index].value = value;
+ saved_stabs[saved_stabs_index].string = xstrdup (string);
+ saved_stabs_index = (saved_stabs_index + 1) % SAVE_STABS_COUNT;
+}
+
+/* Provide context for an error. */
+
+static void
+stab_context ()
+{
+ int i;
+
+ fprintf (stderr, "Last stabs entries before error:\n");
+ fprintf (stderr, "n_type n_desc n_value string\n");
+
+ i = saved_stabs_index;
+ do
+ {
+ struct saved_stab *stabp;
+
+ stabp = saved_stabs + i;
+ if (stabp->string != NULL)
+ {
+ const char *s;
+
+ s = bfd_get_stab_name (stabp->type);
+ if (s != NULL)
+ fprintf (stderr, "%-6s", s);
+ else if (stabp->type == 0)
+ fprintf (stderr, "HdrSym");
+ else
+ fprintf (stderr, "%-6d", stabp->type);
+ fprintf (stderr, " %-6d ", stabp->desc);
+ fprintf_vma (stderr, stabp->value);
+ if (stabp->type != 0)
+ fprintf (stderr, " %s", stabp->string);
+ fprintf (stderr, "\n");
+ }
+ i = (i + 1) % SAVE_STABS_COUNT;
+ }
+ while (i != saved_stabs_index);
+}
+
+/* Free the saved stab strings. */
+
+static void
+free_saved_stabs ()
+{
+ int i;
+
+ for (i = 0; i < SAVE_STABS_COUNT; i++)
+ {
+ if (saved_stabs[i].string != NULL)
+ {
+ free (saved_stabs[i].string);
+ saved_stabs[i].string = NULL;
+ }
+ }
+
+ saved_stabs_index = 0;
+}
diff --git a/pstack/stabs.c b/pstack/stabs.c
new file mode 100644
index 00000000000..076231d19cb
--- /dev/null
+++ b/pstack/stabs.c
@@ -0,0 +1,5082 @@
+/* stabs.c -- Parse stabs debugging information
+ Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
+ Written by Ian Lance Taylor <ian@cygnus.com>.
+
+ This file is part of GNU Binutils.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+/* This file contains code which parses stabs debugging information.
+ The organization of this code is based on the gdb stabs reading
+ code. The job it does is somewhat different, because it is not
+ trying to identify the correct address for anything. */
+
+#include <stdio.h>
+#include <ctype.h>
+
+#include <bfd.h>
+#include "bucomm.h"
+#include <libiberty.h>
+#include "demangle.h"
+#include "debug.h"
+#include "budbg.h"
+
+/* Meaningless definition needs by aout64.h. FIXME. */
+#define BYTES_IN_WORD 4
+
+#include "aout/aout64.h"
+#include "aout/stab_gnu.h"
+
+/* The number of predefined XCOFF types. */
+
+#define XCOFF_TYPE_COUNT 34
+
+/* This structure is used as a handle so that the stab parsing doesn't
+ need to use any static variables. */
+
+struct stab_handle
+{
+ /* The BFD. */
+ bfd *abfd;
+ /* True if this is stabs in sections. */
+ boolean sections;
+ /* The symbol table. */
+ asymbol **syms;
+ /* The number of symbols. */
+ long symcount;
+ /* The accumulated file name string. */
+ char *so_string;
+ /* The value of the last N_SO symbol. */
+ bfd_vma so_value;
+ /* The value of the start of the file, so that we can handle file
+ relative N_LBRAC and N_RBRAC symbols. */
+ bfd_vma file_start_offset;
+ /* The offset of the start of the function, so that we can handle
+ function relative N_LBRAC and N_RBRAC symbols. */
+ bfd_vma function_start_offset;
+ /* The version number of gcc which compiled the current compilation
+ unit, 0 if not compiled by gcc. */
+ int gcc_compiled;
+ /* Whether an N_OPT symbol was seen that was not generated by gcc,
+ so that we can detect the SunPRO compiler. */
+ boolean n_opt_found;
+ /* The main file name. */
+ char *main_filename;
+ /* A stack of unfinished N_BINCL files. */
+ struct bincl_file *bincl_stack;
+ /* A list of finished N_BINCL files. */
+ struct bincl_file *bincl_list;
+ /* Whether we are inside a function or not. */
+ boolean within_function;
+ /* The address of the end of the function, used if we have seen an
+ N_FUN symbol while in a function. This is -1 if we have not seen
+ an N_FUN (the normal case). */
+ bfd_vma function_end;
+ /* The depth of block nesting. */
+ int block_depth;
+ /* List of pending variable definitions. */
+ struct stab_pending_var *pending;
+ /* Number of files for which we have types. */
+ unsigned int files;
+ /* Lists of types per file. */
+ struct stab_types **file_types;
+ /* Predefined XCOFF types. */
+ debug_type xcoff_types[XCOFF_TYPE_COUNT];
+ /* Undefined tags. */
+ struct stab_tag *tags;
+};
+
+/* A list of these structures is used to hold pending variable
+ definitions seen before the N_LBRAC of a block. */
+
+struct stab_pending_var
+{
+ /* Next pending variable definition. */
+ struct stab_pending_var *next;
+ /* Name. */
+ const char *name;
+ /* Type. */
+ debug_type type;
+ /* Kind. */
+ enum debug_var_kind kind;
+ /* Value. */
+ bfd_vma val;
+};
+
+/* A list of these structures is used to hold the types for a single
+ file. */
+
+struct stab_types
+{
+ /* Next set of slots for this file. */
+ struct stab_types *next;
+ /* Types indexed by type number. */
+#define STAB_TYPES_SLOTS (16)
+ debug_type types[STAB_TYPES_SLOTS];
+};
+
+/* We keep a list of undefined tags that we encounter, so that we can
+ fill them in if the tag is later defined. */
+
+struct stab_tag
+{
+ /* Next undefined tag. */
+ struct stab_tag *next;
+ /* Tag name. */
+ const char *name;
+ /* Type kind. */
+ enum debug_type_kind kind;
+ /* Slot to hold real type when we discover it. If we don't, we fill
+ in an undefined tag type. */
+ debug_type slot;
+ /* Indirect type we have created to point at slot. */
+ debug_type type;
+};
+
+static char *savestring PARAMS ((const char *, int));
+static bfd_vma parse_number PARAMS ((const char **, boolean *));
+static void bad_stab PARAMS ((const char *));
+static void warn_stab PARAMS ((const char *, const char *));
+static boolean parse_stab_string
+ PARAMS ((PTR, struct stab_handle *, int, int, bfd_vma, const char *));
+static debug_type parse_stab_type
+ PARAMS ((PTR, struct stab_handle *, const char *, const char **,
+ debug_type **));
+static boolean parse_stab_type_number
+ PARAMS ((const char **, int *));
+static debug_type parse_stab_range_type
+ PARAMS ((PTR, struct stab_handle *, const char *, const char **,
+ const int *));
+static debug_type parse_stab_sun_builtin_type PARAMS ((PTR, const char **));
+static debug_type parse_stab_sun_floating_type
+ PARAMS ((PTR, const char **));
+static debug_type parse_stab_enum_type PARAMS ((PTR, const char **));
+static debug_type parse_stab_struct_type
+ PARAMS ((PTR, struct stab_handle *, const char *, const char **, boolean,
+ const int *));
+static boolean parse_stab_baseclasses
+ PARAMS ((PTR, struct stab_handle *, const char **, debug_baseclass **));
+static boolean parse_stab_struct_fields
+ PARAMS ((PTR, struct stab_handle *, const char **, debug_field **,
+ boolean *));
+static boolean parse_stab_cpp_abbrev
+ PARAMS ((PTR, struct stab_handle *, const char **, debug_field *));
+static boolean parse_stab_one_struct_field
+ PARAMS ((PTR, struct stab_handle *, const char **, const char *,
+ debug_field *, boolean *));
+static boolean parse_stab_members
+ PARAMS ((PTR, struct stab_handle *, const char *, const char **,
+ const int *, debug_method **));
+static debug_type parse_stab_argtypes
+ PARAMS ((PTR, struct stab_handle *, debug_type, const char *, const char *,
+ debug_type, const char *, boolean, boolean, const char **));
+static boolean parse_stab_tilde_field
+ PARAMS ((PTR, struct stab_handle *, const char **, const int *,
+ debug_type *, boolean *));
+static debug_type parse_stab_array_type
+ PARAMS ((PTR, struct stab_handle *, const char **, boolean));
+static void push_bincl PARAMS ((struct stab_handle *, const char *, bfd_vma));
+static const char *pop_bincl PARAMS ((struct stab_handle *));
+static boolean find_excl
+ PARAMS ((struct stab_handle *, const char *, bfd_vma));
+static boolean stab_record_variable
+ PARAMS ((PTR, struct stab_handle *, const char *, debug_type,
+ enum debug_var_kind, bfd_vma));
+static boolean stab_emit_pending_vars PARAMS ((PTR, struct stab_handle *));
+static debug_type *stab_find_slot
+ PARAMS ((struct stab_handle *, const int *));
+static debug_type stab_find_type
+ PARAMS ((PTR, struct stab_handle *, const int *));
+static boolean stab_record_type
+ PARAMS ((PTR, struct stab_handle *, const int *, debug_type));
+static debug_type stab_xcoff_builtin_type
+ PARAMS ((PTR, struct stab_handle *, int));
+static debug_type stab_find_tagged_type
+ PARAMS ((PTR, struct stab_handle *, const char *, int,
+ enum debug_type_kind));
+static debug_type *stab_demangle_argtypes
+ PARAMS ((PTR, struct stab_handle *, const char *, boolean *));
+
+/* Save a string in memory. */
+
+static char *
+savestring (start, len)
+ const char *start;
+ int len;
+{
+ char *ret;
+
+ ret = (char *) xmalloc (len + 1);
+ memcpy (ret, start, len);
+ ret[len] = '\0';
+ return ret;
+}
+
+/* Read a number from a string. */
+
+static bfd_vma
+parse_number (pp, poverflow)
+ const char **pp;
+ boolean *poverflow;
+{
+ unsigned long ul;
+ const char *orig;
+
+ if (poverflow != NULL)
+ *poverflow = false;
+
+ orig = *pp;
+
+ errno = 0;
+ ul = strtoul (*pp, (char **) pp, 0);
+ if (ul + 1 != 0 || errno == 0)
+ return (bfd_vma) ul;
+
+ /* Note that even though strtoul overflowed, it should have set *pp
+ to the end of the number, which is where we want it. */
+
+ if (sizeof (bfd_vma) > sizeof (unsigned long))
+ {
+ const char *p;
+ boolean neg;
+ int base;
+ bfd_vma over, lastdig;
+ boolean overflow;
+ bfd_vma v;
+
+ /* Our own version of strtoul, for a bfd_vma. */
+
+ p = orig;
+
+ neg = false;
+ if (*p == '+')
+ ++p;
+ else if (*p == '-')
+ {
+ neg = true;
+ ++p;
+ }
+
+ base = 10;
+ if (*p == '0')
+ {
+ if (p[1] == 'x' || p[1] == 'X')
+ {
+ base = 16;
+ p += 2;
+ }
+ else
+ {
+ base = 8;
+ ++p;
+ }
+ }
+
+ over = ((bfd_vma) (bfd_signed_vma) -1) / (bfd_vma) base;
+ lastdig = ((bfd_vma) (bfd_signed_vma) -1) % (bfd_vma) base;
+
+ overflow = false;
+ v = 0;
+ while (1)
+ {
+ int d;
+
+ d = *p++;
+ if (isdigit ((unsigned char) d))
+ d -= '0';
+ else if (isupper ((unsigned char) d))
+ d -= 'A';
+ else if (islower ((unsigned char) d))
+ d -= 'a';
+ else
+ break;
+
+ if (d >= base)
+ break;
+
+ if (v > over || (v == over && (bfd_vma) d > lastdig))
+ {
+ overflow = true;
+ break;
+ }
+ }
+
+ if (! overflow)
+ {
+ if (neg)
+ v = - v;
+ return v;
+ }
+ }
+
+ /* If we get here, the number is too large to represent in a
+ bfd_vma. */
+
+ if (poverflow != NULL)
+ *poverflow = true;
+ else
+ warn_stab (orig, "numeric overflow");
+
+ return 0;
+}
+
+/* Give an error for a bad stab string. */
+
+static void
+bad_stab (p)
+ const char *p;
+{
+ fprintf (stderr, "Bad stab: %s\n", p);
+}
+
+/* Warn about something in a stab string. */
+
+static void
+warn_stab (p, err)
+ const char *p;
+ const char *err;
+{
+ fprintf (stderr, "Warning: %s: %s\n", err, p);
+}
+
+/* Create a handle to parse stabs symbols with. */
+
+/*ARGSUSED*/
+PTR
+start_stab (dhandle, abfd, sections, syms, symcount)
+ PTR dhandle;
+ bfd *abfd;
+ boolean sections;
+ asymbol **syms;
+ long symcount;
+{
+ struct stab_handle *ret;
+
+ ret = (struct stab_handle *) xmalloc (sizeof *ret);
+ memset (ret, 0, sizeof *ret);
+ ret->abfd = abfd;
+ ret->sections = sections;
+ ret->syms = syms;
+ ret->symcount = symcount;
+ ret->files = 1;
+ ret->file_types = (struct stab_types **) xmalloc (sizeof *ret->file_types);
+ ret->file_types[0] = NULL;
+ ret->function_end = (bfd_vma) -1;
+ return (PTR) ret;
+}
+
+/* When we have processed all the stabs information, we need to go
+ through and fill in all the undefined tags. */
+
+boolean
+finish_stab (dhandle, handle)
+ PTR dhandle;
+ PTR handle;
+{
+ struct stab_handle *info = (struct stab_handle *) handle;
+ struct stab_tag *st;
+
+ if (info->within_function)
+ {
+ if (! stab_emit_pending_vars (dhandle, info)
+ || ! debug_end_function (dhandle, info->function_end))
+ return false;
+ info->within_function = false;
+ info->function_end = (bfd_vma) -1;
+ }
+
+ for (st = info->tags; st != NULL; st = st->next)
+ {
+ enum debug_type_kind kind;
+
+ kind = st->kind;
+ if (kind == DEBUG_KIND_ILLEGAL)
+ kind = DEBUG_KIND_STRUCT;
+ st->slot = debug_make_undefined_tagged_type (dhandle, st->name, kind);
+ if (st->slot == DEBUG_TYPE_NULL)
+ return false;
+ }
+
+ return true;
+}
+
+/* Handle a single stabs symbol. */
+
+boolean
+parse_stab (dhandle, handle, type, desc, value, string)
+ PTR dhandle;
+ PTR handle;
+ int type;
+ int desc;
+ bfd_vma value;
+ const char *string;
+{
+ struct stab_handle *info = (struct stab_handle *) handle;
+
+ /* gcc will emit two N_SO strings per compilation unit, one for the
+ directory name and one for the file name. We just collect N_SO
+ strings as we see them, and start the new compilation unit when
+ we see a non N_SO symbol. */
+ if (info->so_string != NULL
+ && (type != N_SO || *string == '\0' || value != info->so_value))
+ {
+ if (! debug_set_filename (dhandle, info->so_string))
+ return false;
+ info->main_filename = info->so_string;
+
+ info->gcc_compiled = 0;
+ info->n_opt_found = false;
+
+ /* Generally, for stabs in the symbol table, the N_LBRAC and
+ N_RBRAC symbols are relative to the N_SO symbol value. */
+ if (! info->sections)
+ info->file_start_offset = info->so_value;
+
+ /* We need to reset the mapping from type numbers to types. We
+ can't free the old mapping, because of the use of
+ debug_make_indirect_type. */
+ info->files = 1;
+ info->file_types = ((struct stab_types **)
+ xmalloc (sizeof *info->file_types));
+ info->file_types[0] = NULL;
+
+ info->so_string = NULL;
+
+ /* Now process whatever type we just got. */
+ }
+
+ switch (type)
+ {
+ case N_FN:
+ case N_FN_SEQ:
+ break;
+
+ case N_LBRAC:
+ /* Ignore extra outermost context from SunPRO cc and acc. */
+ if (info->n_opt_found && desc == 1)
+ break;
+
+ if (! info->within_function)
+ {
+ fprintf (stderr, "N_LBRAC not within function\n");
+ return false;
+ }
+
+ /* Start an inner lexical block. */
+ if (! debug_start_block (dhandle,
+ (value
+ + info->file_start_offset
+ + info->function_start_offset)))
+ return false;
+
+ /* Emit any pending variable definitions. */
+ if (! stab_emit_pending_vars (dhandle, info))
+ return false;
+
+ ++info->block_depth;
+ break;
+
+ case N_RBRAC:
+ /* Ignore extra outermost context from SunPRO cc and acc. */
+ if (info->n_opt_found && desc == 1)
+ break;
+
+ /* We shouldn't have any pending variable definitions here, but,
+ if we do, we probably need to emit them before closing the
+ block. */
+ if (! stab_emit_pending_vars (dhandle, info))
+ return false;
+
+ /* End an inner lexical block. */
+ if (! debug_end_block (dhandle,
+ (value
+ + info->file_start_offset
+ + info->function_start_offset)))
+ return false;
+
+ --info->block_depth;
+ if (info->block_depth < 0)
+ {
+ fprintf (stderr, "Too many N_RBRACs\n");
+ return false;
+ }
+ break;
+
+ case N_SO:
+ /* This always ends a function. */
+ if (info->within_function)
+ {
+ bfd_vma endval;
+
+ endval = value;
+ if (*string != '\0'
+ && info->function_end != (bfd_vma) -1
+ && info->function_end < endval)
+ endval = info->function_end;
+ if (! stab_emit_pending_vars (dhandle, info)
+ || ! debug_end_function (dhandle, endval))
+ return false;
+ info->within_function = false;
+ info->function_end = (bfd_vma) -1;
+ }
+
+ /* An empty string is emitted by gcc at the end of a compilation
+ unit. */
+ if (*string == '\0')
+ return true;
+
+ /* Just accumulate strings until we see a non N_SO symbol. If
+ the string starts with '/', we discard the previously
+ accumulated strings. */
+ if (info->so_string == NULL)
+ info->so_string = xstrdup (string);
+ else
+ {
+ char *f;
+
+ f = info->so_string;
+ if (*string == '/')
+ info->so_string = xstrdup (string);
+ else
+ info->so_string = concat (info->so_string, string,
+ (const char *) NULL);
+ free (f);
+ }
+
+ info->so_value = value;
+
+ break;
+
+ case N_SOL:
+ /* Start an include file. */
+ if (! debug_start_source (dhandle, string))
+ return false;
+ break;
+
+ case N_BINCL:
+ /* Start an include file which may be replaced. */
+ push_bincl (info, string, value);
+ if (! debug_start_source (dhandle, string))
+ return false;
+ break;
+
+ case N_EINCL:
+ /* End an N_BINCL include. */
+ if (! debug_start_source (dhandle, pop_bincl (info)))
+ return false;
+ break;
+
+ case N_EXCL:
+ /* This is a duplicate of a header file named by N_BINCL which
+ was eliminated by the linker. */
+ if (! find_excl (info, string, value))
+ return false;
+ break;
+
+ case N_SLINE:
+ if (! debug_record_line (dhandle, desc,
+ value + info->function_start_offset))
+ return false;
+ break;
+
+ case N_BCOMM:
+ if (! debug_start_common_block (dhandle, string))
+ return false;
+ break;
+
+ case N_ECOMM:
+ if (! debug_end_common_block (dhandle, string))
+ return false;
+ break;
+
+ case N_FUN:
+ if (*string == '\0')
+ {
+ if (info->within_function)
+ {
+ /* This always marks the end of a function; we don't
+ need to worry about info->function_end. */
+ if (info->sections)
+ value += info->function_start_offset;
+ if (! stab_emit_pending_vars (dhandle, info)
+ || ! debug_end_function (dhandle, value))
+ return false;
+ info->within_function = false;
+ info->function_end = (bfd_vma) -1;
+ }
+ break;
+ }
+
+ /* A const static symbol in the .text section will have an N_FUN
+ entry. We need to use these to mark the end of the function,
+ in case we are looking at gcc output before it was changed to
+ always emit an empty N_FUN. We can't call debug_end_function
+ here, because it might be a local static symbol. */
+ if (info->within_function
+ && (info->function_end == (bfd_vma) -1
+ || value < info->function_end))
+ info->function_end = value;
+
+ /* Fall through. */
+ /* FIXME: gdb checks the string for N_STSYM, N_LCSYM or N_ROSYM
+ symbols, and if it does not start with :S, gdb relocates the
+ value to the start of the section. gcc always seems to use
+ :S, so we don't worry about this. */
+ /* Fall through. */
+ default:
+ {
+ const char *colon;
+
+ colon = strchr (string, ':');
+ if (colon != NULL
+ && (colon[1] == 'f' || colon[1] == 'F'))
+ {
+ if (info->within_function)
+ {
+ bfd_vma endval;
+
+ endval = value;
+ if (info->function_end != (bfd_vma) -1
+ && info->function_end < endval)
+ endval = info->function_end;
+ if (! stab_emit_pending_vars (dhandle, info)
+ || ! debug_end_function (dhandle, endval))
+ return false;
+ info->function_end = (bfd_vma) -1;
+ }
+ /* For stabs in sections, line numbers and block addresses
+ are offsets from the start of the function. */
+ if (info->sections)
+ info->function_start_offset = value;
+ info->within_function = true;
+ }
+
+ if (! parse_stab_string (dhandle, info, type, desc, value, string))
+ return false;
+ }
+ break;
+
+ case N_OPT:
+ if (string != NULL && strcmp (string, "gcc2_compiled.") == 0)
+ info->gcc_compiled = 2;
+ else if (string != NULL && strcmp (string, "gcc_compiled.") == 0)
+ info->gcc_compiled = 1;
+ else
+ info->n_opt_found = true;
+ break;
+
+ case N_OBJ:
+ case N_ENDM:
+ case N_MAIN:
+ break;
+ }
+
+ return true;
+}
+
+/* Parse the stabs string. */
+
+static boolean
+parse_stab_string (dhandle, info, stabtype, desc, value, string)
+ PTR dhandle;
+ struct stab_handle *info;
+ int stabtype;
+ int desc;
+ bfd_vma value;
+ const char *string;
+{
+ const char *p;
+ char *name;
+ int type;
+ debug_type dtype;
+ boolean synonym;
+ unsigned int lineno;
+ debug_type *slot;
+
+ p = strchr (string, ':');
+ if (p == NULL)
+ return true;
+
+ while (p[1] == ':')
+ {
+ p += 2;
+ p = strchr (p, ':');
+ if (p == NULL)
+ {
+ bad_stab (string);
+ return false;
+ }
+ }
+
+ /* GCC 2.x puts the line number in desc. SunOS apparently puts in
+ the number of bytes occupied by a type or object, which we
+ ignore. */
+ if (info->gcc_compiled >= 2)
+ lineno = desc;
+ else
+ lineno = 0;
+
+ /* FIXME: Sometimes the special C++ names start with '.'. */
+ name = NULL;
+ if (string[0] == '$')
+ {
+ switch (string[1])
+ {
+ case 't':
+ name = "this";
+ break;
+ case 'v':
+ /* Was: name = "vptr"; */
+ break;
+ case 'e':
+ name = "eh_throw";
+ break;
+ case '_':
+ /* This was an anonymous type that was never fixed up. */
+ break;
+ case 'X':
+ /* SunPRO (3.0 at least) static variable encoding. */
+ break;
+ default:
+ warn_stab (string, "unknown C++ encoded name");
+ break;
+ }
+ }
+
+ if (name == NULL)
+ {
+ if (p == string || (string[0] == ' ' && p == string + 1))
+ name = NULL;
+ else
+ name = savestring (string, p - string);
+ }
+
+ ++p;
+ if (isdigit ((unsigned char) *p) || *p == '(' || *p == '-')
+ type = 'l';
+ else
+ type = *p++;
+
+ switch (type)
+ {
+ case 'c':
+ /* c is a special case, not followed by a type-number.
+ SYMBOL:c=iVALUE for an integer constant symbol.
+ SYMBOL:c=rVALUE for a floating constant symbol.
+ SYMBOL:c=eTYPE,INTVALUE for an enum constant symbol.
+ e.g. "b:c=e6,0" for "const b = blob1"
+ (where type 6 is defined by "blobs:t6=eblob1:0,blob2:1,;"). */
+ if (*p != '=')
+ {
+ bad_stab (string);
+ return false;
+ }
+ ++p;
+ switch (*p++)
+ {
+ case 'r':
+ /* Floating point constant. */
+ if (! debug_record_float_const (dhandle, name, atof (p)))
+ return false;
+ break;
+ case 'i':
+ /* Integer constant. */
+ /* Defining integer constants this way is kind of silly,
+ since 'e' constants allows the compiler to give not only
+ the value, but the type as well. C has at least int,
+ long, unsigned int, and long long as constant types;
+ other languages probably should have at least unsigned as
+ well as signed constants. */
+ if (! debug_record_int_const (dhandle, name, atoi (p)))
+ return false;
+ break;
+ case 'e':
+ /* SYMBOL:c=eTYPE,INTVALUE for a constant symbol whose value
+ can be represented as integral.
+ e.g. "b:c=e6,0" for "const b = blob1"
+ (where type 6 is defined by "blobs:t6=eblob1:0,blob2:1,;"). */
+ dtype = parse_stab_type (dhandle, info, (const char *) NULL,
+ &p, (debug_type **) NULL);
+ if (dtype == DEBUG_TYPE_NULL)
+ return false;
+ if (*p != ',')
+ {
+ bad_stab (string);
+ return false;
+ }
+ if (! debug_record_typed_const (dhandle, name, dtype, atoi (p)))
+ return false;
+ break;
+ default:
+ bad_stab (string);
+ return false;
+ }
+
+ break;
+
+ case 'C':
+ /* The name of a caught exception. */
+ dtype = parse_stab_type (dhandle, info, (const char *) NULL,
+ &p, (debug_type **) NULL);
+ if (dtype == DEBUG_TYPE_NULL)
+ return false;
+ if (! debug_record_label (dhandle, name, dtype, value))
+ return false;
+ break;
+
+ case 'f':
+ case 'F':
+ /* A function definition. */
+ dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
+ (debug_type **) NULL);
+ if (dtype == DEBUG_TYPE_NULL)
+ return false;
+ if (! debug_record_function (dhandle, name, dtype, type == 'F', value))
+ return false;
+
+ /* Sun acc puts declared types of arguments here. We don't care
+ about their actual types (FIXME -- we should remember the whole
+ function prototype), but the list may define some new types
+ that we have to remember, so we must scan it now. */
+ while (*p == ';')
+ {
+ ++p;
+ if (parse_stab_type (dhandle, info, (const char *) NULL, &p,
+ (debug_type **) NULL)
+ == DEBUG_TYPE_NULL)
+ return false;
+ }
+
+ break;
+
+ case 'G':
+ {
+ char leading;
+ long c;
+ asymbol **ps;
+
+ /* A global symbol. The value must be extracted from the
+ symbol table. */
+ dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
+ (debug_type **) NULL);
+ if (dtype == DEBUG_TYPE_NULL)
+ return false;
+ leading = bfd_get_symbol_leading_char (info->abfd);
+ for (c = info->symcount, ps = info->syms; c > 0; --c, ++ps)
+ {
+ const char *n;
+
+ n = bfd_asymbol_name (*ps);
+ if (leading != '\0' && *n == leading)
+ ++n;
+ if (*n == *name && strcmp (n, name) == 0)
+ break;
+ }
+ if (c > 0)
+ value = bfd_asymbol_value (*ps);
+ if (! stab_record_variable (dhandle, info, name, dtype, DEBUG_GLOBAL,
+ value))
+ return false;
+ }
+ break;
+
+ /* This case is faked by a conditional above, when there is no
+ code letter in the dbx data. Dbx data never actually
+ contains 'l'. */
+ case 'l':
+ case 's':
+ dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
+ (debug_type **) NULL);
+ if (dtype == DEBUG_TYPE_NULL)
+ return false;
+ if (! stab_record_variable (dhandle, info, name, dtype, DEBUG_LOCAL,
+ value))
+ return false;
+ break;
+
+ case 'p':
+ /* A function parameter. */
+ if (*p != 'F')
+ dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
+ (debug_type **) NULL);
+ else
+ {
+ /* pF is a two-letter code that means a function parameter in
+ Fortran. The type-number specifies the type of the return
+ value. Translate it into a pointer-to-function type. */
+ ++p;
+ dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
+ (debug_type **) NULL);
+ if (dtype != DEBUG_TYPE_NULL)
+ {
+ debug_type ftype;
+
+ ftype = debug_make_function_type (dhandle, dtype,
+ (debug_type *) NULL, false);
+ dtype = debug_make_pointer_type (dhandle, ftype);
+ }
+ }
+ if (dtype == DEBUG_TYPE_NULL)
+ return false;
+ if (! debug_record_parameter (dhandle, name, dtype, DEBUG_PARM_STACK,
+ value))
+ return false;
+
+ /* FIXME: At this point gdb considers rearranging the parameter
+ address on a big endian machine if it is smaller than an int.
+ We have no way to do that, since we don't really know much
+ about the target. */
+
+ break;
+
+ case 'P':
+ if (stabtype == N_FUN)
+ {
+ /* Prototype of a function referenced by this file. */
+ while (*p == ';')
+ {
+ ++p;
+ if (parse_stab_type (dhandle, info, (const char *) NULL, &p,
+ (debug_type **) NULL)
+ == DEBUG_TYPE_NULL)
+ return false;
+ }
+ break;
+ }
+ /* Fall through. */
+ case 'R':
+ /* Parameter which is in a register. */
+ dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
+ (debug_type **) NULL);
+ if (dtype == DEBUG_TYPE_NULL)
+ return false;
+ if (! debug_record_parameter (dhandle, name, dtype, DEBUG_PARM_REG,
+ value))
+ return false;
+ break;
+
+ case 'r':
+ /* Register variable (either global or local). */
+ dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
+ (debug_type **) NULL);
+ if (dtype == DEBUG_TYPE_NULL)
+ return false;
+ if (! stab_record_variable (dhandle, info, name, dtype, DEBUG_REGISTER,
+ value))
+ return false;
+
+ /* FIXME: At this point gdb checks to combine pairs of 'p' and
+ 'r' stabs into a single 'P' stab. */
+
+ break;
+
+ case 'S':
+ /* Static symbol at top level of file */
+ dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
+ (debug_type **) NULL);
+ if (dtype == DEBUG_TYPE_NULL)
+ return false;
+ if (! stab_record_variable (dhandle, info, name, dtype, DEBUG_STATIC,
+ value))
+ return false;
+ break;
+
+ case 't':
+ /* A typedef. */
+ dtype = parse_stab_type (dhandle, info, name, &p, &slot);
+ if (dtype == DEBUG_TYPE_NULL)
+ return false;
+ if (name == NULL)
+ {
+ /* A nameless type. Nothing to do. */
+ return true;
+ }
+
+ dtype = debug_name_type (dhandle, name, dtype);
+ if (dtype == DEBUG_TYPE_NULL)
+ return false;
+
+ if (slot != NULL)
+ *slot = dtype;
+
+ break;
+
+ case 'T':
+ /* Struct, union, or enum tag. For GNU C++, this can be be followed
+ by 't' which means we are typedef'ing it as well. */
+ if (*p != 't')
+ {
+ synonym = false;
+ /* FIXME: gdb sets synonym to true if the current language
+ is C++. */
+ }
+ else
+ {
+ synonym = true;
+ ++p;
+ }
+
+ dtype = parse_stab_type (dhandle, info, name, &p, &slot);
+ if (dtype == DEBUG_TYPE_NULL)
+ return false;
+ if (name == NULL)
+ return true;
+
+ dtype = debug_tag_type (dhandle, name, dtype);
+ if (dtype == DEBUG_TYPE_NULL)
+ return false;
+ if (slot != NULL)
+ *slot = dtype;
+
+ /* See if we have a cross reference to this tag which we can now
+ fill in. */
+ {
+ register struct stab_tag **pst;
+
+ for (pst = &info->tags; *pst != NULL; pst = &(*pst)->next)
+ {
+ if ((*pst)->name[0] == name[0]
+ && strcmp ((*pst)->name, name) == 0)
+ {
+ (*pst)->slot = dtype;
+ *pst = (*pst)->next;
+ break;
+ }
+ }
+ }
+
+ if (synonym)
+ {
+ dtype = debug_name_type (dhandle, name, dtype);
+ if (dtype == DEBUG_TYPE_NULL)
+ return false;
+
+ if (slot != NULL)
+ *slot = dtype;
+ }
+
+ break;
+
+ case 'V':
+ /* Static symbol of local scope */
+ dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
+ (debug_type **) NULL);
+ if (dtype == DEBUG_TYPE_NULL)
+ return false;
+ /* FIXME: gdb checks os9k_stabs here. */
+ if (! stab_record_variable (dhandle, info, name, dtype,
+ DEBUG_LOCAL_STATIC, value))
+ return false;
+ break;
+
+ case 'v':
+ /* Reference parameter. */
+ dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
+ (debug_type **) NULL);
+ if (dtype == DEBUG_TYPE_NULL)
+ return false;
+ if (! debug_record_parameter (dhandle, name, dtype, DEBUG_PARM_REFERENCE,
+ value))
+ return false;
+ break;
+
+ case 'a':
+ /* Reference parameter which is in a register. */
+ dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
+ (debug_type **) NULL);
+ if (dtype == DEBUG_TYPE_NULL)
+ return false;
+ if (! debug_record_parameter (dhandle, name, dtype, DEBUG_PARM_REF_REG,
+ value))
+ return false;
+ break;
+
+ case 'X':
+ /* This is used by Sun FORTRAN for "function result value".
+ Sun claims ("dbx and dbxtool interfaces", 2nd ed)
+ that Pascal uses it too, but when I tried it Pascal used
+ "x:3" (local symbol) instead. */
+ dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
+ (debug_type **) NULL);
+ if (dtype == DEBUG_TYPE_NULL)
+ return false;
+ if (! stab_record_variable (dhandle, info, name, dtype, DEBUG_LOCAL,
+ value))
+ return false;
+ break;
+
+ default:
+ bad_stab (string);
+ return false;
+ }
+
+ /* FIXME: gdb converts structure values to structure pointers in a
+ couple of cases, depending upon the target. */
+
+ return true;
+}
+
+/* Parse a stabs type. The typename argument is non-NULL if this is a
+ typedef or a tag definition. The pp argument points to the stab
+ string, and is updated. The slotp argument points to a place to
+ store the slot used if the type is being defined. */
+
+static debug_type
+parse_stab_type (dhandle, info, typename, pp, slotp)
+ PTR dhandle;
+ struct stab_handle *info;
+ const char *typename;
+ const char **pp;
+ debug_type **slotp;
+{
+ const char *orig;
+ int typenums[2];
+ int size;
+ boolean stringp;
+ int descriptor;
+ debug_type dtype;
+
+ if (slotp != NULL)
+ *slotp = NULL;
+
+ orig = *pp;
+
+ size = -1;
+ stringp = false;
+
+ /* Read type number if present. The type number may be omitted.
+ for instance in a two-dimensional array declared with type
+ "ar1;1;10;ar1;1;10;4". */
+ if (! isdigit ((unsigned char) **pp) && **pp != '(' && **pp != '-')
+ {
+ /* 'typenums=' not present, type is anonymous. Read and return
+ the definition, but don't put it in the type vector. */
+ typenums[0] = typenums[1] = -1;
+ }
+ else
+ {
+ if (! parse_stab_type_number (pp, typenums))
+ return DEBUG_TYPE_NULL;
+
+ if (**pp != '=')
+ {
+ /* Type is not being defined here. Either it already
+ exists, or this is a forward reference to it. */
+ return stab_find_type (dhandle, info, typenums);
+ }
+
+ /* Only set the slot if the type is being defined. This means
+ that the mapping from type numbers to types will only record
+ the name of the typedef which defines a type. If we don't do
+ this, then something like
+ typedef int foo;
+ int i;
+ will record that i is of type foo. Unfortunately, stabs
+ information is ambiguous about variable types. For this code,
+ typedef int foo;
+ int i;
+ foo j;
+ the stabs information records both i and j as having the same
+ type. This could be fixed by patching the compiler. */
+ if (slotp != NULL && typenums[0] >= 0 && typenums[1] >= 0)
+ *slotp = stab_find_slot (info, typenums);
+
+ /* Type is being defined here. */
+ /* Skip the '='. */
+ ++*pp;
+
+ while (**pp == '@')
+ {
+ const char *p = *pp + 1;
+ const char *attr;
+
+ if (isdigit ((unsigned char) *p) || *p == '(' || *p == '-')
+ {
+ /* Member type. */
+ break;
+ }
+
+ /* Type attributes. */
+ attr = p;
+
+ for (; *p != ';'; ++p)
+ {
+ if (*p == '\0')
+ {
+ bad_stab (orig);
+ return DEBUG_TYPE_NULL;
+ }
+ }
+ *pp = p + 1;
+
+ switch (*attr)
+ {
+ case 's':
+ size = atoi (attr + 1);
+ if (size <= 0)
+ size = -1;
+ break;
+
+ case 'S':
+ stringp = true;
+ break;
+
+ default:
+ /* Ignore unrecognized type attributes, so future
+ compilers can invent new ones. */
+ break;
+ }
+ }
+ }
+
+ descriptor = **pp;
+ ++*pp;
+
+ switch (descriptor)
+ {
+ case 'x':
+ {
+ enum debug_type_kind code;
+ const char *q1, *q2, *p;
+
+ /* A cross reference to another type. */
+
+ switch (**pp)
+ {
+ case 's':
+ code = DEBUG_KIND_STRUCT;
+ break;
+ case 'u':
+ code = DEBUG_KIND_UNION;
+ break;
+ case 'e':
+ code = DEBUG_KIND_ENUM;
+ break;
+ default:
+ /* Complain and keep going, so compilers can invent new
+ cross-reference types. */
+ warn_stab (orig, "unrecognized cross reference type");
+ code = DEBUG_KIND_STRUCT;
+ break;
+ }
+ ++*pp;
+
+ q1 = strchr (*pp, '<');
+ p = strchr (*pp, ':');
+ if (p == NULL)
+ {
+ bad_stab (orig);
+ return DEBUG_TYPE_NULL;
+ }
+ while (q1 != NULL && p > q1 && p[1] == ':')
+ {
+ q2 = strchr (q1, '>');
+ if (q2 == NULL || q2 < p)
+ break;
+ p += 2;
+ p = strchr (p, ':');
+ if (p == NULL)
+ {
+ bad_stab (orig);
+ return DEBUG_TYPE_NULL;
+ }
+ }
+
+ dtype = stab_find_tagged_type (dhandle, info, *pp, p - *pp, code);
+
+ *pp = p + 1;
+ }
+ break;
+
+ case '-':
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ case '(':
+ {
+ const char *hold;
+ int xtypenums[2];
+
+ /* This type is defined as another type. */
+
+ (*pp)--;
+ hold = *pp;
+
+ /* Peek ahead at the number to detect void. */
+ if (! parse_stab_type_number (pp, xtypenums))
+ return DEBUG_TYPE_NULL;
+
+ if (typenums[0] == xtypenums[0] && typenums[1] == xtypenums[1])
+ {
+ /* This type is being defined as itself, which means that
+ it is void. */
+ dtype = debug_make_void_type (dhandle);
+ }
+ else
+ {
+ *pp = hold;
+
+ /* Go back to the number and have parse_stab_type get it.
+ This means that we can deal with something like
+ t(1,2)=(3,4)=... which the Lucid compiler uses. */
+ dtype = parse_stab_type (dhandle, info, (const char *) NULL,
+ pp, (debug_type **) NULL);
+ if (dtype == DEBUG_TYPE_NULL)
+ return DEBUG_TYPE_NULL;
+ }
+
+ if (typenums[0] != -1)
+ {
+ if (! stab_record_type (dhandle, info, typenums, dtype))
+ return DEBUG_TYPE_NULL;
+ }
+
+ break;
+ }
+
+ case '*':
+ dtype = debug_make_pointer_type (dhandle,
+ parse_stab_type (dhandle, info,
+ (const char *) NULL,
+ pp,
+ (debug_type **) NULL));
+ break;
+
+ case '&':
+ /* Reference to another type. */
+ dtype = (debug_make_reference_type
+ (dhandle,
+ parse_stab_type (dhandle, info, (const char *) NULL, pp,
+ (debug_type **) NULL)));
+ break;
+
+ case 'f':
+ /* Function returning another type. */
+ /* FIXME: gdb checks os9k_stabs here. */
+ dtype = (debug_make_function_type
+ (dhandle,
+ parse_stab_type (dhandle, info, (const char *) NULL, pp,
+ (debug_type **) NULL),
+ (debug_type *) NULL, false));
+ break;
+
+ case 'k':
+ /* Const qualifier on some type (Sun). */
+ /* FIXME: gdb accepts 'c' here if os9k_stabs. */
+ dtype = debug_make_const_type (dhandle,
+ parse_stab_type (dhandle, info,
+ (const char *) NULL,
+ pp,
+ (debug_type **) NULL));
+ break;
+
+ case 'B':
+ /* Volatile qual on some type (Sun). */
+ /* FIXME: gdb accepts 'i' here if os9k_stabs. */
+ dtype = (debug_make_volatile_type
+ (dhandle,
+ parse_stab_type (dhandle, info, (const char *) NULL, pp,
+ (debug_type **) NULL)));
+ break;
+
+ case '@':
+ /* Offset (class & variable) type. This is used for a pointer
+ relative to an object. */
+ {
+ debug_type domain;
+ debug_type memtype;
+
+ /* Member type. */
+
+ domain = parse_stab_type (dhandle, info, (const char *) NULL, pp,
+ (debug_type **) NULL);
+ if (domain == DEBUG_TYPE_NULL)
+ return DEBUG_TYPE_NULL;
+
+ if (**pp != ',')
+ {
+ bad_stab (orig);
+ return DEBUG_TYPE_NULL;
+ }
+ ++*pp;
+
+ memtype = parse_stab_type (dhandle, info, (const char *) NULL, pp,
+ (debug_type **) NULL);
+ if (memtype == DEBUG_TYPE_NULL)
+ return DEBUG_TYPE_NULL;
+
+ dtype = debug_make_offset_type (dhandle, domain, memtype);
+ }
+ break;
+
+ case '#':
+ /* Method (class & fn) type. */
+ if (**pp == '#')
+ {
+ debug_type return_type;
+
+ ++*pp;
+ return_type = parse_stab_type (dhandle, info, (const char *) NULL,
+ pp, (debug_type **) NULL);
+ if (return_type == DEBUG_TYPE_NULL)
+ return DEBUG_TYPE_NULL;
+ if (**pp != ';')
+ {
+ bad_stab (orig);
+ return DEBUG_TYPE_NULL;
+ }
+ ++*pp;
+ dtype = debug_make_method_type (dhandle, return_type,
+ DEBUG_TYPE_NULL,
+ (debug_type *) NULL, false);
+ }
+ else
+ {
+ debug_type domain;
+ debug_type return_type;
+ debug_type *args;
+ unsigned int n;
+ unsigned int alloc;
+ boolean varargs;
+
+ domain = parse_stab_type (dhandle, info, (const char *) NULL,
+ pp, (debug_type **) NULL);
+ if (domain == DEBUG_TYPE_NULL)
+ return DEBUG_TYPE_NULL;
+
+ if (**pp != ',')
+ {
+ bad_stab (orig);
+ return DEBUG_TYPE_NULL;
+ }
+ ++*pp;
+
+ return_type = parse_stab_type (dhandle, info, (const char *) NULL,
+ pp, (debug_type **) NULL);
+ if (return_type == DEBUG_TYPE_NULL)
+ return DEBUG_TYPE_NULL;
+
+ alloc = 10;
+ args = (debug_type *) xmalloc (alloc * sizeof *args);
+ n = 0;
+ while (**pp != ';')
+ {
+ if (**pp != ',')
+ {
+ bad_stab (orig);
+ return DEBUG_TYPE_NULL;
+ }
+ ++*pp;
+
+ if (n + 1 >= alloc)
+ {
+ alloc += 10;
+ args = ((debug_type *)
+ xrealloc ((PTR) args, alloc * sizeof *args));
+ }
+
+ args[n] = parse_stab_type (dhandle, info, (const char *) NULL,
+ pp, (debug_type **) NULL);
+ if (args[n] == DEBUG_TYPE_NULL)
+ return DEBUG_TYPE_NULL;
+ ++n;
+ }
+ ++*pp;
+
+ /* If the last type is not void, then this function takes a
+ variable number of arguments. Otherwise, we must strip
+ the void type. */
+ if (n == 0
+ || debug_get_type_kind (dhandle, args[n - 1]) != DEBUG_KIND_VOID)
+ varargs = true;
+ else
+ {
+ --n;
+ varargs = false;
+ }
+
+ args[n] = DEBUG_TYPE_NULL;
+
+ dtype = debug_make_method_type (dhandle, return_type, domain, args,
+ varargs);
+ }
+ break;
+
+ case 'r':
+ /* Range type. */
+ dtype = parse_stab_range_type (dhandle, info, typename, pp, typenums);
+ break;
+
+ case 'b':
+ /* FIXME: gdb checks os9k_stabs here. */
+ /* Sun ACC builtin int type. */
+ dtype = parse_stab_sun_builtin_type (dhandle, pp);
+ break;
+
+ case 'R':
+ /* Sun ACC builtin float type. */
+ dtype = parse_stab_sun_floating_type (dhandle, pp);
+ break;
+
+ case 'e':
+ /* Enumeration type. */
+ dtype = parse_stab_enum_type (dhandle, pp);
+ break;
+
+ case 's':
+ case 'u':
+ /* Struct or union type. */
+ dtype = parse_stab_struct_type (dhandle, info, typename, pp,
+ descriptor == 's', typenums);
+ break;
+
+ case 'a':
+ /* Array type. */
+ if (**pp != 'r')
+ {
+ bad_stab (orig);
+ return DEBUG_TYPE_NULL;
+ }
+ ++*pp;
+
+ dtype = parse_stab_array_type (dhandle, info, pp, stringp);
+ break;
+
+ case 'S':
+ dtype = debug_make_set_type (dhandle,
+ parse_stab_type (dhandle, info,
+ (const char *) NULL,
+ pp,
+ (debug_type **) NULL),
+ stringp);
+ break;
+
+ default:
+ bad_stab (orig);
+ return DEBUG_TYPE_NULL;
+ }
+
+ if (dtype == DEBUG_TYPE_NULL)
+ return DEBUG_TYPE_NULL;
+
+ if (typenums[0] != -1)
+ {
+ if (! stab_record_type (dhandle, info, typenums, dtype))
+ return DEBUG_TYPE_NULL;
+ }
+
+ if (size != -1)
+ {
+ if (! debug_record_type_size (dhandle, dtype, (unsigned int) size))
+ return DEBUG_TYPE_NULL;
+ }
+
+ return dtype;
+}
+
+/* Read a number by which a type is referred to in dbx data, or
+ perhaps read a pair (FILENUM, TYPENUM) in parentheses. Just a
+ single number N is equivalent to (0,N). Return the two numbers by
+ storing them in the vector TYPENUMS. */
+
+static boolean
+parse_stab_type_number (pp, typenums)
+ const char **pp;
+ int *typenums;
+{
+ const char *orig;
+
+ orig = *pp;
+
+ if (**pp != '(')
+ {
+ typenums[0] = 0;
+ typenums[1] = (int) parse_number (pp, (boolean *) NULL);
+ }
+ else
+ {
+ ++*pp;
+ typenums[0] = (int) parse_number (pp, (boolean *) NULL);
+ if (**pp != ',')
+ {
+ bad_stab (orig);
+ return false;
+ }
+ ++*pp;
+ typenums[1] = (int) parse_number (pp, (boolean *) NULL);
+ if (**pp != ')')
+ {
+ bad_stab (orig);
+ return false;
+ }
+ ++*pp;
+ }
+
+ return true;
+}
+
+/* Parse a range type. */
+
+static debug_type
+parse_stab_range_type (dhandle, info, typename, pp, typenums)
+ PTR dhandle;
+ struct stab_handle *info;
+ const char *typename;
+ const char **pp;
+ const int *typenums;
+{
+ const char *orig;
+ int rangenums[2];
+ boolean self_subrange;
+ debug_type index_type;
+ const char *s2, *s3;
+ bfd_signed_vma n2, n3;
+ boolean ov2, ov3;
+
+ orig = *pp;
+
+ index_type = DEBUG_TYPE_NULL;
+
+ /* First comes a type we are a subrange of.
+ In C it is usually 0, 1 or the type being defined. */
+ if (! parse_stab_type_number (pp, rangenums))
+ return DEBUG_TYPE_NULL;
+
+ self_subrange = (rangenums[0] == typenums[0]
+ && rangenums[1] == typenums[1]);
+
+ if (**pp == '=')
+ {
+ *pp = orig;
+ index_type = parse_stab_type (dhandle, info, (const char *) NULL,
+ pp, (debug_type **) NULL);
+ if (index_type == DEBUG_TYPE_NULL)
+ return DEBUG_TYPE_NULL;
+ }
+
+ if (**pp == ';')
+ ++*pp;
+
+ /* The remaining two operands are usually lower and upper bounds of
+ the range. But in some special cases they mean something else. */
+ s2 = *pp;
+ n2 = parse_number (pp, &ov2);
+ if (**pp != ';')
+ {
+ bad_stab (orig);
+ return DEBUG_TYPE_NULL;
+ }
+ ++*pp;
+
+ s3 = *pp;
+ n3 = parse_number (pp, &ov3);
+ if (**pp != ';')
+ {
+ bad_stab (orig);
+ return DEBUG_TYPE_NULL;
+ }
+ ++*pp;
+
+ if (ov2 || ov3)
+ {
+ /* gcc will emit range stabs for long long types. Handle this
+ as a special case. FIXME: This needs to be more general. */
+#define LLLOW "01000000000000000000000;"
+#define LLHIGH "0777777777777777777777;"
+#define ULLHIGH "01777777777777777777777;"
+ if (index_type == DEBUG_TYPE_NULL)
+ {
+ if (strncmp (s2, LLLOW, sizeof LLLOW - 1) == 0
+ && strncmp (s3, LLHIGH, sizeof LLHIGH - 1) == 0)
+ return debug_make_int_type (dhandle, 8, false);
+ if (! ov2
+ && n2 == 0
+ && strncmp (s3, ULLHIGH, sizeof ULLHIGH - 1) == 0)
+ return debug_make_int_type (dhandle, 8, true);
+ }
+
+ warn_stab (orig, "numeric overflow");
+ }
+
+ if (index_type == DEBUG_TYPE_NULL)
+ {
+ /* A type defined as a subrange of itself, with both bounds 0,
+ is void. */
+ if (self_subrange && n2 == 0 && n3 == 0)
+ return debug_make_void_type (dhandle);
+
+ /* A type defined as a subrange of itself, with n2 positive and
+ n3 zero, is a complex type, and n2 is the number of bytes. */
+ if (self_subrange && n3 == 0 && n2 > 0)
+ return debug_make_complex_type (dhandle, n2);
+
+ /* If n3 is zero and n2 is positive, this is a floating point
+ type, and n2 is the number of bytes. */
+ if (n3 == 0 && n2 > 0)
+ return debug_make_float_type (dhandle, n2);
+
+ /* If the upper bound is -1, this is an unsigned int. */
+ if (n2 == 0 && n3 == -1)
+ {
+ /* When gcc is used with -gstabs, but not -gstabs+, it will emit
+ long long int:t6=r1;0;-1;
+ long long unsigned int:t7=r1;0;-1;
+ We hack here to handle this reasonably. */
+ if (typename != NULL)
+ {
+ if (strcmp (typename, "long long int") == 0)
+ return debug_make_int_type (dhandle, 8, false);
+ else if (strcmp (typename, "long long unsigned int") == 0)
+ return debug_make_int_type (dhandle, 8, true);
+ }
+ /* FIXME: The size here really depends upon the target. */
+ return debug_make_int_type (dhandle, 4, true);
+ }
+
+ /* A range of 0 to 127 is char. */
+ if (self_subrange && n2 == 0 && n3 == 127)
+ return debug_make_int_type (dhandle, 1, false);
+
+ /* FIXME: gdb checks for the language CHILL here. */
+
+ if (n2 == 0)
+ {
+ if (n3 < 0)
+ return debug_make_int_type (dhandle, - n3, true);
+ else if (n3 == 0xff)
+ return debug_make_int_type (dhandle, 1, true);
+ else if (n3 == 0xffff)
+ return debug_make_int_type (dhandle, 2, true);
+ /* -1 is used for the upper bound of (4 byte) "unsigned int"
+ and "unsigned long", and we already checked for that, so
+ don't need to test for it here. */
+ }
+ else if (n3 == 0
+ && n2 < 0
+ && (self_subrange || n2 == -8))
+ return debug_make_int_type (dhandle, - n2, true);
+ else if (n2 == - n3 - 1)
+ {
+ if (n3 == 0x7f)
+ return debug_make_int_type (dhandle, 1, false);
+ else if (n3 == 0x7fff)
+ return debug_make_int_type (dhandle, 2, false);
+ else if (n3 == 0x7fffffff)
+ return debug_make_int_type (dhandle, 4, false);
+ }
+ }
+
+ /* At this point I don't have the faintest idea how to deal with a
+ self_subrange type; I'm going to assume that this is used as an
+ idiom, and that all of them are special cases. So . . . */
+ if (self_subrange)
+ {
+ bad_stab (orig);
+ return DEBUG_TYPE_NULL;
+ }
+
+ index_type = stab_find_type (dhandle, info, rangenums);
+ if (index_type == DEBUG_TYPE_NULL)
+ {
+ /* Does this actually ever happen? Is that why we are worrying
+ about dealing with it rather than just calling error_type? */
+ warn_stab (orig, "missing index type");
+ index_type = debug_make_int_type (dhandle, 4, false);
+ }
+
+ return debug_make_range_type (dhandle, index_type, n2, n3);
+}
+
+/* Sun's ACC uses a somewhat saner method for specifying the builtin
+ typedefs in every file (for int, long, etc):
+
+ type = b <signed> <width>; <offset>; <nbits>
+ signed = u or s. Possible c in addition to u or s (for char?).
+ offset = offset from high order bit to start bit of type.
+ width is # bytes in object of this type, nbits is # bits in type.
+
+ The width/offset stuff appears to be for small objects stored in
+ larger ones (e.g. `shorts' in `int' registers). We ignore it for now,
+ FIXME. */
+
+static debug_type
+parse_stab_sun_builtin_type (dhandle, pp)
+ PTR dhandle;
+ const char **pp;
+{
+ const char *orig;
+ boolean unsignedp;
+ bfd_vma bits;
+
+ orig = *pp;
+
+ switch (**pp)
+ {
+ case 's':
+ unsignedp = false;
+ break;
+ case 'u':
+ unsignedp = true;
+ break;
+ default:
+ bad_stab (orig);
+ return DEBUG_TYPE_NULL;
+ }
+ ++*pp;
+
+ /* For some odd reason, all forms of char put a c here. This is strange
+ because no other type has this honor. We can safely ignore this because
+ we actually determine 'char'acterness by the number of bits specified in
+ the descriptor. */
+ if (**pp == 'c')
+ ++*pp;
+
+ /* The first number appears to be the number of bytes occupied
+ by this type, except that unsigned short is 4 instead of 2.
+ Since this information is redundant with the third number,
+ we will ignore it. */
+ (void) parse_number (pp, (boolean *) NULL);
+ if (**pp != ';')
+ {
+ bad_stab (orig);
+ return DEBUG_TYPE_NULL;
+ }
+ ++*pp;
+
+ /* The second number is always 0, so ignore it too. */
+ (void) parse_number (pp, (boolean *) NULL);
+ if (**pp != ';')
+ {
+ bad_stab (orig);
+ return DEBUG_TYPE_NULL;
+ }
+ ++*pp;
+
+ /* The third number is the number of bits for this type. */
+ bits = parse_number (pp, (boolean *) NULL);
+
+ /* The type *should* end with a semicolon. If it are embedded
+ in a larger type the semicolon may be the only way to know where
+ the type ends. If this type is at the end of the stabstring we
+ can deal with the omitted semicolon (but we don't have to like
+ it). Don't bother to complain(), Sun's compiler omits the semicolon
+ for "void". */
+ if (**pp == ';')
+ ++*pp;
+
+ if (bits == 0)
+ return debug_make_void_type (dhandle);
+
+ return debug_make_int_type (dhandle, bits / 8, unsignedp);
+}
+
+/* Parse a builtin floating type generated by the Sun compiler. */
+
+static debug_type
+parse_stab_sun_floating_type (dhandle, pp)
+ PTR dhandle;
+ const char **pp;
+{
+ const char *orig;
+ bfd_vma details;
+ bfd_vma bytes;
+
+ orig = *pp;
+
+ /* The first number has more details about the type, for example
+ FN_COMPLEX. */
+ details = parse_number (pp, (boolean *) NULL);
+ if (**pp != ';')
+ {
+ bad_stab (orig);
+ return DEBUG_TYPE_NULL;
+ }
+
+ /* The second number is the number of bytes occupied by this type */
+ bytes = parse_number (pp, (boolean *) NULL);
+ if (**pp != ';')
+ {
+ bad_stab (orig);
+ return DEBUG_TYPE_NULL;
+ }
+
+ if (details == NF_COMPLEX
+ || details == NF_COMPLEX16
+ || details == NF_COMPLEX32)
+ return debug_make_complex_type (dhandle, bytes);
+
+ return debug_make_float_type (dhandle, bytes);
+}
+
+/* Handle an enum type. */
+
+static debug_type
+parse_stab_enum_type (dhandle, pp)
+ PTR dhandle;
+ const char **pp;
+{
+ const char *orig;
+ const char **names;
+ bfd_signed_vma *values;
+ unsigned int n;
+ unsigned int alloc;
+
+ orig = *pp;
+
+ /* FIXME: gdb checks os9k_stabs here. */
+
+ /* The aix4 compiler emits an extra field before the enum members;
+ my guess is it's a type of some sort. Just ignore it. */
+ if (**pp == '-')
+ {
+ while (**pp != ':')
+ ++*pp;
+ ++*pp;
+ }
+
+ /* Read the value-names and their values.
+ The input syntax is NAME:VALUE,NAME:VALUE, and so on.
+ A semicolon or comma instead of a NAME means the end. */
+ alloc = 10;
+ names = (const char **) xmalloc (alloc * sizeof *names);
+ values = (bfd_signed_vma *) xmalloc (alloc * sizeof *values);
+ n = 0;
+ while (**pp != '\0' && **pp != ';' && **pp != ',')
+ {
+ const char *p;
+ char *name;
+ bfd_signed_vma val;
+
+ p = *pp;
+ while (*p != ':')
+ ++p;
+
+ name = savestring (*pp, p - *pp);
+
+ *pp = p + 1;
+ val = (bfd_signed_vma) parse_number (pp, (boolean *) NULL);
+ if (**pp != ',')
+ {
+ bad_stab (orig);
+ return DEBUG_TYPE_NULL;
+ }
+ ++*pp;
+
+ if (n + 1 >= alloc)
+ {
+ alloc += 10;
+ names = ((const char **)
+ xrealloc ((PTR) names, alloc * sizeof *names));
+ values = ((bfd_signed_vma *)
+ xrealloc ((PTR) values, alloc * sizeof *values));
+ }
+
+ names[n] = name;
+ values[n] = val;
+ ++n;
+ }
+
+ names[n] = NULL;
+ values[n] = 0;
+
+ if (**pp == ';')
+ ++*pp;
+
+ return debug_make_enum_type (dhandle, names, values);
+}
+
+/* Read the description of a structure (or union type) and return an object
+ describing the type.
+
+ PP points to a character pointer that points to the next unconsumed token
+ in the the stabs string. For example, given stabs "A:T4=s4a:1,0,32;;",
+ *PP will point to "4a:1,0,32;;". */
+
+static debug_type
+parse_stab_struct_type (dhandle, info, tagname, pp, structp, typenums)
+ PTR dhandle;
+ struct stab_handle *info;
+ const char *tagname;
+ const char **pp;
+ boolean structp;
+ const int *typenums;
+{
+ const char *orig;
+ bfd_vma size;
+ debug_baseclass *baseclasses;
+ debug_field *fields;
+ boolean statics;
+ debug_method *methods;
+ debug_type vptrbase;
+ boolean ownvptr;
+
+ orig = *pp;
+
+ /* Get the size. */
+ size = parse_number (pp, (boolean *) NULL);
+
+ /* Get the other information. */
+ if (! parse_stab_baseclasses (dhandle, info, pp, &baseclasses)
+ || ! parse_stab_struct_fields (dhandle, info, pp, &fields, &statics)
+ || ! parse_stab_members (dhandle, info, tagname, pp, typenums, &methods)
+ || ! parse_stab_tilde_field (dhandle, info, pp, typenums, &vptrbase,
+ &ownvptr))
+ return DEBUG_TYPE_NULL;
+
+ if (! statics
+ && baseclasses == NULL
+ && methods == NULL
+ && vptrbase == DEBUG_TYPE_NULL
+ && ! ownvptr)
+ return debug_make_struct_type (dhandle, structp, size, fields);
+
+ return debug_make_object_type (dhandle, structp, size, fields, baseclasses,
+ methods, vptrbase, ownvptr);
+}
+
+/* The stabs for C++ derived classes contain baseclass information which
+ is marked by a '!' character after the total size. This function is
+ called when we encounter the baseclass marker, and slurps up all the
+ baseclass information.
+
+ Immediately following the '!' marker is the number of base classes that
+ the class is derived from, followed by information for each base class.
+ For each base class, there are two visibility specifiers, a bit offset
+ to the base class information within the derived class, a reference to
+ the type for the base class, and a terminating semicolon.
+
+ A typical example, with two base classes, would be "!2,020,19;0264,21;".
+ ^^ ^ ^ ^ ^ ^ ^
+ Baseclass information marker __________________|| | | | | | |
+ Number of baseclasses __________________________| | | | | | |
+ Visibility specifiers (2) ________________________| | | | | |
+ Offset in bits from start of class _________________| | | | |
+ Type number for base class ___________________________| | | |
+ Visibility specifiers (2) _______________________________| | |
+ Offset in bits from start of class ________________________| |
+ Type number of base class ____________________________________|
+
+ Return true for success, false for failure. */
+
+static boolean
+parse_stab_baseclasses (dhandle, info, pp, retp)
+ PTR dhandle;
+ struct stab_handle *info;
+ const char **pp;
+ debug_baseclass **retp;
+{
+ const char *orig;
+ unsigned int c, i;
+ debug_baseclass *classes;
+
+ *retp = NULL;
+
+ orig = *pp;
+
+ if (**pp != '!')
+ {
+ /* No base classes. */
+ return true;
+ }
+ ++*pp;
+
+ c = (unsigned int) parse_number (pp, (boolean *) NULL);
+
+ if (**pp != ',')
+ {
+ bad_stab (orig);
+ return false;
+ }
+ ++*pp;
+
+ classes = (debug_baseclass *) xmalloc ((c + 1) * sizeof (**retp));
+
+ for (i = 0; i < c; i++)
+ {
+ boolean virtual;
+ enum debug_visibility visibility;
+ bfd_vma bitpos;
+ debug_type type;
+
+ switch (**pp)
+ {
+ case '0':
+ virtual = false;
+ break;
+ case '1':
+ virtual = true;
+ break;
+ default:
+ warn_stab (orig, "unknown virtual character for baseclass");
+ virtual = false;
+ break;
+ }
+ ++*pp;
+
+ switch (**pp)
+ {
+ case '0':
+ visibility = DEBUG_VISIBILITY_PRIVATE;
+ break;
+ case '1':
+ visibility = DEBUG_VISIBILITY_PROTECTED;
+ break;
+ case '2':
+ visibility = DEBUG_VISIBILITY_PUBLIC;
+ break;
+ default:
+ warn_stab (orig, "unknown visibility character for baseclass");
+ visibility = DEBUG_VISIBILITY_PUBLIC;
+ break;
+ }
+ ++*pp;
+
+ /* The remaining value is the bit offset of the portion of the
+ object corresponding to this baseclass. Always zero in the
+ absence of multiple inheritance. */
+ bitpos = parse_number (pp, (boolean *) NULL);
+ if (**pp != ',')
+ {
+ bad_stab (orig);
+ return false;
+ }
+ ++*pp;
+
+ type = parse_stab_type (dhandle, info, (const char *) NULL, pp,
+ (debug_type **) NULL);
+ if (type == DEBUG_TYPE_NULL)
+ return false;
+
+ classes[i] = debug_make_baseclass (dhandle, type, bitpos, virtual,
+ visibility);
+ if (classes[i] == DEBUG_BASECLASS_NULL)
+ return false;
+
+ if (**pp != ';')
+ return false;
+ ++*pp;
+ }
+
+ classes[i] = DEBUG_BASECLASS_NULL;
+
+ *retp = classes;
+
+ return true;
+}
+
+/* Read struct or class data fields. They have the form:
+
+ NAME : [VISIBILITY] TYPENUM , BITPOS , BITSIZE ;
+
+ At the end, we see a semicolon instead of a field.
+
+ In C++, this may wind up being NAME:?TYPENUM:PHYSNAME; for
+ a static field.
+
+ The optional VISIBILITY is one of:
+
+ '/0' (VISIBILITY_PRIVATE)
+ '/1' (VISIBILITY_PROTECTED)
+ '/2' (VISIBILITY_PUBLIC)
+ '/9' (VISIBILITY_IGNORE)
+
+ or nothing, for C style fields with public visibility.
+
+ Returns 1 for success, 0 for failure. */
+
+static boolean
+parse_stab_struct_fields (dhandle, info, pp, retp, staticsp)
+ PTR dhandle;
+ struct stab_handle *info;
+ const char **pp;
+ debug_field **retp;
+ boolean *staticsp;
+{
+ const char *orig;
+ const char *p;
+ debug_field *fields;
+ unsigned int c;
+ unsigned int alloc;
+
+ *retp = NULL;
+ *staticsp = false;
+
+ orig = *pp;
+
+ c = 0;
+ alloc = 10;
+ fields = (debug_field *) xmalloc (alloc * sizeof *fields);
+ while (**pp != ';')
+ {
+ /* FIXME: gdb checks os9k_stabs here. */
+
+ p = *pp;
+
+ /* Add 1 to c to leave room for NULL pointer at end. */
+ if (c + 1 >= alloc)
+ {
+ alloc += 10;
+ fields = ((debug_field *)
+ xrealloc ((PTR) fields, alloc * sizeof *fields));
+ }
+
+ /* If it starts with CPLUS_MARKER it is a special abbreviation,
+ unless the CPLUS_MARKER is followed by an underscore, in
+ which case it is just the name of an anonymous type, which we
+ should handle like any other type name. We accept either '$'
+ or '.', because a field name can never contain one of these
+ characters except as a CPLUS_MARKER. */
+
+ if ((*p == '$' || *p == '.') && p[1] != '_')
+ {
+ ++*pp;
+ if (! parse_stab_cpp_abbrev (dhandle, info, pp, fields + c))
+ return false;
+ ++c;
+ continue;
+ }
+
+ /* Look for the ':' that separates the field name from the field
+ values. Data members are delimited by a single ':', while member
+ functions are delimited by a pair of ':'s. When we hit the member
+ functions (if any), terminate scan loop and return. */
+
+ p = strchr (p, ':');
+ if (p == NULL)
+ {
+ bad_stab (orig);
+ return false;
+ }
+
+ if (p[1] == ':')
+ break;
+
+ if (! parse_stab_one_struct_field (dhandle, info, pp, p, fields + c,
+ staticsp))
+ return false;
+
+ ++c;
+ }
+
+ fields[c] = DEBUG_FIELD_NULL;
+
+ *retp = fields;
+
+ return true;
+}
+
+/* Special GNU C++ name. */
+
+static boolean
+parse_stab_cpp_abbrev (dhandle, info, pp, retp)
+ PTR dhandle;
+ struct stab_handle *info;
+ const char **pp;
+ debug_field *retp;
+{
+ const char *orig;
+ int cpp_abbrev;
+ debug_type context;
+ const char *name;
+ const char *typename;
+ debug_type type;
+ bfd_vma bitpos;
+
+ *retp = DEBUG_FIELD_NULL;
+
+ orig = *pp;
+
+ if (**pp != 'v')
+ {
+ bad_stab (*pp);
+ return false;
+ }
+ ++*pp;
+
+ cpp_abbrev = **pp;
+ ++*pp;
+
+ /* At this point, *pp points to something like "22:23=*22...", where
+ the type number before the ':' is the "context" and everything
+ after is a regular type definition. Lookup the type, find it's
+ name, and construct the field name. */
+
+ context = parse_stab_type (dhandle, info, (const char *) NULL, pp,
+ (debug_type **) NULL);
+ if (context == DEBUG_TYPE_NULL)
+ return false;
+
+ switch (cpp_abbrev)
+ {
+ case 'f':
+ /* $vf -- a virtual function table pointer. */
+ name = "_vptr$";
+ break;
+ case 'b':
+ /* $vb -- a virtual bsomethingorother */
+ typename = debug_get_type_name (dhandle, context);
+ if (typename == NULL)
+ {
+ warn_stab (orig, "unnamed $vb type");
+ typename = "FOO";
+ }
+ name = concat ("_vb$", typename, (const char *) NULL);
+ break;
+ default:
+ warn_stab (orig, "unrecognized C++ abbreviation");
+ name = "INVALID_CPLUSPLUS_ABBREV";
+ break;
+ }
+
+ if (**pp != ':')
+ {
+ bad_stab (orig);
+ return false;
+ }
+ ++*pp;
+
+ type = parse_stab_type (dhandle, info, (const char *) NULL, pp,
+ (debug_type **) NULL);
+ if (**pp != ',')
+ {
+ bad_stab (orig);
+ return false;
+ }
+ ++*pp;
+
+ bitpos = parse_number (pp, (boolean *) NULL);
+ if (**pp != ';')
+ {
+ bad_stab (orig);
+ return false;
+ }
+ ++*pp;
+
+ *retp = debug_make_field (dhandle, name, type, bitpos, 0,
+ DEBUG_VISIBILITY_PRIVATE);
+ if (*retp == DEBUG_FIELD_NULL)
+ return false;
+
+ return true;
+}
+
+/* Parse a single field in a struct or union. */
+
+static boolean
+parse_stab_one_struct_field (dhandle, info, pp, p, retp, staticsp)
+ PTR dhandle;
+ struct stab_handle *info;
+ const char **pp;
+ const char *p;
+ debug_field *retp;
+ boolean *staticsp;
+{
+ const char *orig;
+ char *name;
+ enum debug_visibility visibility;
+ debug_type type;
+ bfd_vma bitpos;
+ bfd_vma bitsize;
+
+ orig = *pp;
+
+ /* FIXME: gdb checks ARM_DEMANGLING here. */
+
+ name = savestring (*pp, p - *pp);
+
+ *pp = p + 1;
+
+ if (**pp != '/')
+ visibility = DEBUG_VISIBILITY_PUBLIC;
+ else
+ {
+ ++*pp;
+ switch (**pp)
+ {
+ case '0':
+ visibility = DEBUG_VISIBILITY_PRIVATE;
+ break;
+ case '1':
+ visibility = DEBUG_VISIBILITY_PROTECTED;
+ break;
+ case '2':
+ visibility = DEBUG_VISIBILITY_PUBLIC;
+ break;
+ default:
+ warn_stab (orig, "unknown visibility character for field");
+ visibility = DEBUG_VISIBILITY_PUBLIC;
+ break;
+ }
+ ++*pp;
+ }
+
+ type = parse_stab_type (dhandle, info, (const char *) NULL, pp,
+ (debug_type **) NULL);
+ if (type == DEBUG_TYPE_NULL)
+ return false;
+
+ if (**pp == ':')
+ {
+ char *varname;
+
+ /* This is a static class member. */
+ ++*pp;
+ p = strchr (*pp, ';');
+ if (p == NULL)
+ {
+ bad_stab (orig);
+ return false;
+ }
+
+ varname = savestring (*pp, p - *pp);
+
+ *pp = p + 1;
+
+ *retp = debug_make_static_member (dhandle, name, type, varname,
+ visibility);
+ *staticsp = true;
+
+ return true;
+ }
+
+ if (**pp != ',')
+ {
+ bad_stab (orig);
+ return false;
+ }
+ ++*pp;
+
+ bitpos = parse_number (pp, (boolean *) NULL);
+ if (**pp != ',')
+ {
+ bad_stab (orig);
+ return false;
+ }
+ ++*pp;
+
+ bitsize = parse_number (pp, (boolean *) NULL);
+ if (**pp != ';')
+ {
+ bad_stab (orig);
+ return false;
+ }
+ ++*pp;
+
+ if (bitpos == 0 && bitsize == 0)
+ {
+ /* This can happen in two cases: (1) at least for gcc 2.4.5 or
+ so, it is a field which has been optimized out. The correct
+ stab for this case is to use VISIBILITY_IGNORE, but that is a
+ recent invention. (2) It is a 0-size array. For example
+ union { int num; char str[0]; } foo. Printing "<no value>"
+ for str in "p foo" is OK, since foo.str (and thus foo.str[3])
+ will continue to work, and a 0-size array as a whole doesn't
+ have any contents to print.
+
+ I suspect this probably could also happen with gcc -gstabs
+ (not -gstabs+) for static fields, and perhaps other C++
+ extensions. Hopefully few people use -gstabs with gdb, since
+ it is intended for dbx compatibility. */
+ visibility = DEBUG_VISIBILITY_IGNORE;
+ }
+
+ /* FIXME: gdb does some stuff here to mark fields as unpacked. */
+
+ *retp = debug_make_field (dhandle, name, type, bitpos, bitsize, visibility);
+
+ return true;
+}
+
+/* Read member function stabs info for C++ classes. The form of each member
+ function data is:
+
+ NAME :: TYPENUM[=type definition] ARGS : PHYSNAME ;
+
+ An example with two member functions is:
+
+ afunc1::20=##15;:i;2A.;afunc2::20:i;2A.;
+
+ For the case of overloaded operators, the format is op$::*.funcs, where
+ $ is the CPLUS_MARKER (usually '$'), `*' holds the place for an operator
+ name (such as `+=') and `.' marks the end of the operator name. */
+
+static boolean
+parse_stab_members (dhandle, info, tagname, pp, typenums, retp)
+ PTR dhandle;
+ struct stab_handle *info;
+ const char *tagname;
+ const char **pp;
+ const int *typenums;
+ debug_method **retp;
+{
+ const char *orig;
+ debug_method *methods;
+ unsigned int c;
+ unsigned int alloc;
+
+ *retp = NULL;
+
+ orig = *pp;
+
+ alloc = 0;
+ methods = NULL;
+ c = 0;
+
+ while (**pp != ';')
+ {
+ const char *p;
+ char *name;
+ debug_method_variant *variants;
+ unsigned int cvars;
+ unsigned int allocvars;
+ debug_type look_ahead_type;
+
+ p = strchr (*pp, ':');
+ if (p == NULL || p[1] != ':')
+ break;
+
+ /* FIXME: Some systems use something other than '$' here. */
+ if ((*pp)[0] != 'o' || (*pp)[1] != 'p' || (*pp)[2] != '$')
+ {
+ name = savestring (*pp, p - *pp);
+ *pp = p + 2;
+ }
+ else
+ {
+ /* This is a completely wierd case. In order to stuff in the
+ names that might contain colons (the usual name delimiter),
+ Mike Tiemann defined a different name format which is
+ signalled if the identifier is "op$". In that case, the
+ format is "op$::XXXX." where XXXX is the name. This is
+ used for names like "+" or "=". YUUUUUUUK! FIXME! */
+ *pp = p + 2;
+ for (p = *pp; *p != '.' && *p != '\0'; p++)
+ ;
+ if (*p != '.')
+ {
+ bad_stab (orig);
+ return false;
+ }
+ name = savestring (*pp, p - *pp);
+ *pp = p + 1;
+ }
+
+ allocvars = 10;
+ variants = ((debug_method_variant *)
+ xmalloc (allocvars * sizeof *variants));
+ cvars = 0;
+
+ look_ahead_type = DEBUG_TYPE_NULL;
+
+ do
+ {
+ debug_type type;
+ boolean stub;
+ char *argtypes;
+ enum debug_visibility visibility;
+ boolean constp, volatilep, staticp;
+ bfd_vma voffset;
+ debug_type context;
+ const char *physname;
+ boolean varargs;
+
+ if (look_ahead_type != DEBUG_TYPE_NULL)
+ {
+ /* g++ version 1 kludge */
+ type = look_ahead_type;
+ look_ahead_type = DEBUG_TYPE_NULL;
+ }
+ else
+ {
+ type = parse_stab_type (dhandle, info, (const char *) NULL, pp,
+ (debug_type **) NULL);
+ if (type == DEBUG_TYPE_NULL)
+ return false;
+ if (**pp != ':')
+ {
+ bad_stab (orig);
+ return false;
+ }
+ }
+
+ ++*pp;
+ p = strchr (*pp, ';');
+ if (p == NULL)
+ {
+ bad_stab (orig);
+ return false;
+ }
+
+ stub = false;
+ if (debug_get_type_kind (dhandle, type) == DEBUG_KIND_METHOD
+ && debug_get_parameter_types (dhandle, type, &varargs) == NULL)
+ stub = true;
+
+ argtypes = savestring (*pp, p - *pp);
+ *pp = p + 1;
+
+ switch (**pp)
+ {
+ case '0':
+ visibility = DEBUG_VISIBILITY_PRIVATE;
+ break;
+ case '1':
+ visibility = DEBUG_VISIBILITY_PROTECTED;
+ break;
+ default:
+ visibility = DEBUG_VISIBILITY_PUBLIC;
+ break;
+ }
+ ++*pp;
+
+ constp = false;
+ volatilep = false;
+ switch (**pp)
+ {
+ case 'A':
+ /* Normal function. */
+ ++*pp;
+ break;
+ case 'B':
+ /* const member function. */
+ constp = true;
+ ++*pp;
+ break;
+ case 'C':
+ /* volatile member function. */
+ volatilep = true;
+ ++*pp;
+ break;
+ case 'D':
+ /* const volatile member function. */
+ constp = true;
+ volatilep = true;
+ ++*pp;
+ break;
+ case '*':
+ case '?':
+ case '.':
+ /* File compiled with g++ version 1; no information. */
+ break;
+ default:
+ warn_stab (orig, "const/volatile indicator missing");
+ break;
+ }
+
+ staticp = false;
+ switch (**pp)
+ {
+ case '*':
+ /* virtual member function, followed by index. The sign
+ bit is supposedly set to distinguish
+ pointers-to-methods from virtual function indicies. */
+ ++*pp;
+ voffset = parse_number (pp, (boolean *) NULL);
+ if (**pp != ';')
+ {
+ bad_stab (orig);
+ return false;
+ }
+ ++*pp;
+ voffset &= 0x7fffffff;
+
+ if (**pp == ';' || *pp == '\0')
+ {
+ /* Must be g++ version 1. */
+ context = DEBUG_TYPE_NULL;
+ }
+ else
+ {
+ /* Figure out from whence this virtual function
+ came. It may belong to virtual function table of
+ one of its baseclasses. */
+ look_ahead_type = parse_stab_type (dhandle, info,
+ (const char *) NULL,
+ pp,
+ (debug_type **) NULL);
+ if (**pp == ':')
+ {
+ /* g++ version 1 overloaded methods. */
+ context = DEBUG_TYPE_NULL;
+ }
+ else
+ {
+ context = look_ahead_type;
+ look_ahead_type = DEBUG_TYPE_NULL;
+ if (**pp != ';')
+ {
+ bad_stab (orig);
+ return false;
+ }
+ ++*pp;
+ }
+ }
+ break;
+
+ case '?':
+ /* static member function. */
+ ++*pp;
+ staticp = true;
+ voffset = 0;
+ context = DEBUG_TYPE_NULL;
+ if (strncmp (argtypes, name, strlen (name)) != 0)
+ stub = true;
+ break;
+
+ default:
+ warn_stab (orig, "member function type missing");
+ voffset = 0;
+ context = DEBUG_TYPE_NULL;
+ break;
+
+ case '.':
+ ++*pp;
+ voffset = 0;
+ context = DEBUG_TYPE_NULL;
+ break;
+ }
+
+ /* If the type is not a stub, then the argtypes string is
+ the physical name of the function. Otherwise the
+ argtypes string is the mangled form of the argument
+ types, and the full type and the physical name must be
+ extracted from them. */
+ if (! stub)
+ physname = argtypes;
+ else
+ {
+ debug_type class_type, return_type;
+
+ class_type = stab_find_type (dhandle, info, typenums);
+ if (class_type == DEBUG_TYPE_NULL)
+ return false;
+ return_type = debug_get_return_type (dhandle, type);
+ if (return_type == DEBUG_TYPE_NULL)
+ {
+ bad_stab (orig);
+ return false;
+ }
+ type = parse_stab_argtypes (dhandle, info, class_type, name,
+ tagname, return_type, argtypes,
+ constp, volatilep, &physname);
+ if (type == DEBUG_TYPE_NULL)
+ return false;
+ }
+
+ if (cvars + 1 >= allocvars)
+ {
+ allocvars += 10;
+ variants = ((debug_method_variant *)
+ xrealloc ((PTR) variants,
+ allocvars * sizeof *variants));
+ }
+
+ if (! staticp)
+ variants[cvars] = debug_make_method_variant (dhandle, physname,
+ type, visibility,
+ constp, volatilep,
+ voffset, context);
+ else
+ variants[cvars] = debug_make_static_method_variant (dhandle,
+ physname,
+ type,
+ visibility,
+ constp,
+ volatilep);
+ if (variants[cvars] == DEBUG_METHOD_VARIANT_NULL)
+ return false;
+
+ ++cvars;
+ }
+ while (**pp != ';' && **pp != '\0');
+
+ variants[cvars] = DEBUG_METHOD_VARIANT_NULL;
+
+ if (**pp != '\0')
+ ++*pp;
+
+ if (c + 1 >= alloc)
+ {
+ alloc += 10;
+ methods = ((debug_method *)
+ xrealloc ((PTR) methods, alloc * sizeof *methods));
+ }
+
+ methods[c] = debug_make_method (dhandle, name, variants);
+
+ ++c;
+ }
+
+ if (methods != NULL)
+ methods[c] = DEBUG_METHOD_NULL;
+
+ *retp = methods;
+
+ return true;
+}
+
+/* Parse a string representing argument types for a method. Stabs
+ tries to save space by packing argument types into a mangled
+ string. This string should give us enough information to extract
+ both argument types and the physical name of the function, given
+ the tag name. */
+
+static debug_type
+parse_stab_argtypes (dhandle, info, class_type, fieldname, tagname,
+ return_type, argtypes, constp, volatilep, pphysname)
+ PTR dhandle;
+ struct stab_handle *info;
+ debug_type class_type;
+ const char *fieldname;
+ const char *tagname;
+ debug_type return_type;
+ const char *argtypes;
+ boolean constp;
+ boolean volatilep;
+ const char **pphysname;
+{
+ boolean is_full_physname_constructor;
+ boolean is_constructor;
+ boolean is_destructor;
+ debug_type *args;
+ boolean varargs;
+
+ /* Constructors are sometimes handled specially. */
+ is_full_physname_constructor = ((argtypes[0] == '_'
+ && argtypes[1] == '_'
+ && (isdigit ((unsigned char) argtypes[2])
+ || argtypes[2] == 'Q'
+ || argtypes[2] == 't'))
+ || strncmp (argtypes, "__ct", 4) == 0);
+
+ is_constructor = (is_full_physname_constructor
+ || (tagname != NULL
+ && strcmp (fieldname, tagname) == 0));
+ is_destructor = ((argtypes[0] == '_'
+ && (argtypes[1] == '$' || argtypes[1] == '.')
+ && argtypes[2] == '_')
+ || strncmp (argtypes, "__dt", 4) == 0);
+
+ if (is_destructor || is_full_physname_constructor)
+ *pphysname = argtypes;
+ else
+ {
+ unsigned int len;
+ const char *const_prefix;
+ const char *volatile_prefix;
+ char buf[20];
+ unsigned int mangled_name_len;
+ char *physname;
+
+ len = tagname == NULL ? 0 : strlen (tagname);
+ const_prefix = constp ? "C" : "";
+ volatile_prefix = volatilep ? "V" : "";
+
+ if (len == 0)
+ sprintf (buf, "__%s%s", const_prefix, volatile_prefix);
+ else if (tagname != NULL && strchr (tagname, '<') != NULL)
+ {
+ /* Template methods are fully mangled. */
+ sprintf (buf, "__%s%s", const_prefix, volatile_prefix);
+ tagname = NULL;
+ len = 0;
+ }
+ else
+ sprintf (buf, "__%s%s%d", const_prefix, volatile_prefix, len);
+
+ mangled_name_len = ((is_constructor ? 0 : strlen (fieldname))
+ + strlen (buf)
+ + len
+ + strlen (argtypes)
+ + 1);
+
+ if (fieldname[0] == 'o'
+ && fieldname[1] == 'p'
+ && (fieldname[2] == '$' || fieldname[2] == '.'))
+ {
+ const char *opname;
+
+ opname = cplus_mangle_opname (fieldname + 3, 0);
+ if (opname == NULL)
+ {
+ fprintf (stderr, "No mangling for \"%s\"\n", fieldname);
+ return DEBUG_TYPE_NULL;
+ }
+ mangled_name_len += strlen (opname);
+ physname = (char *) xmalloc (mangled_name_len);
+ strncpy (physname, fieldname, 3);
+ strcpy (physname + 3, opname);
+ }
+ else
+ {
+ physname = (char *) xmalloc (mangled_name_len);
+ if (is_constructor)
+ physname[0] = '\0';
+ else
+ strcpy (physname, fieldname);
+ }
+
+ strcat (physname, buf);
+ if (tagname != NULL)
+ strcat (physname, tagname);
+ strcat (physname, argtypes);
+
+ *pphysname = physname;
+ }
+
+ if (*argtypes == '\0' || is_destructor)
+ {
+ args = (debug_type *) xmalloc (sizeof *args);
+ *args = NULL;
+ return debug_make_method_type (dhandle, return_type, class_type, args,
+ false);
+ }
+
+ args = stab_demangle_argtypes (dhandle, info, *pphysname, &varargs);
+ if (args == NULL)
+ return DEBUG_TYPE_NULL;
+
+ return debug_make_method_type (dhandle, return_type, class_type, args,
+ varargs);
+}
+
+/* The tail end of stabs for C++ classes that contain a virtual function
+ pointer contains a tilde, a %, and a type number.
+ The type number refers to the base class (possibly this class itself) which
+ contains the vtable pointer for the current class.
+
+ This function is called when we have parsed all the method declarations,
+ so we can look for the vptr base class info. */
+
+static boolean
+parse_stab_tilde_field (dhandle, info, pp, typenums, retvptrbase, retownvptr)
+ PTR dhandle;
+ struct stab_handle *info;
+ const char **pp;
+ const int *typenums;
+ debug_type *retvptrbase;
+ boolean *retownvptr;
+{
+ const char *orig;
+ const char *hold;
+ int vtypenums[2];
+
+ *retvptrbase = DEBUG_TYPE_NULL;
+ *retownvptr = false;
+
+ orig = *pp;
+
+ /* If we are positioned at a ';', then skip it. */
+ if (**pp == ';')
+ ++*pp;
+
+ if (**pp != '~')
+ return true;
+
+ ++*pp;
+
+ if (**pp == '=' || **pp == '+' || **pp == '-')
+ {
+ /* Obsolete flags that used to indicate the presence of
+ constructors and/or destructors. */
+ ++*pp;
+ }
+
+ if (**pp != '%')
+ return true;
+
+ ++*pp;
+
+ hold = *pp;
+
+ /* The next number is the type number of the base class (possibly
+ our own class) which supplies the vtable for this class. */
+ if (! parse_stab_type_number (pp, vtypenums))
+ return false;
+
+ if (vtypenums[0] == typenums[0]
+ && vtypenums[1] == typenums[1])
+ *retownvptr = true;
+ else
+ {
+ debug_type vtype;
+ const char *p;
+
+ *pp = hold;
+
+ vtype = parse_stab_type (dhandle, info, (const char *) NULL, pp,
+ (debug_type **) NULL);
+ for (p = *pp; *p != ';' && *p != '\0'; p++)
+ ;
+ if (*p != ';')
+ {
+ bad_stab (orig);
+ return false;
+ }
+
+ *retvptrbase = vtype;
+
+ *pp = p + 1;
+ }
+
+ return true;
+}
+
+/* Read a definition of an array type. */
+
+static debug_type
+parse_stab_array_type (dhandle, info, pp, stringp)
+ PTR dhandle;
+ struct stab_handle *info;
+ const char **pp;
+ boolean stringp;
+{
+ const char *orig;
+ const char *p;
+ int typenums[2];
+ debug_type index_type;
+ boolean adjustable;
+ bfd_signed_vma lower, upper;
+ debug_type element_type;
+
+ /* Format of an array type:
+ "ar<index type>;lower;upper;<array_contents_type>".
+ OS9000: "arlower,upper;<array_contents_type>".
+
+ Fortran adjustable arrays use Adigits or Tdigits for lower or upper;
+ for these, produce a type like float[][]. */
+
+ orig = *pp;
+
+ /* FIXME: gdb checks os9k_stabs here. */
+
+ /* If the index type is type 0, we take it as int. */
+ p = *pp;
+ if (! parse_stab_type_number (&p, typenums))
+ return DEBUG_TYPE_NULL;
+ if (typenums[0] == 0 && typenums[1] == 0 && **pp != '=')
+ {
+ index_type = debug_find_named_type (dhandle, "int");
+ if (index_type == DEBUG_TYPE_NULL)
+ {
+ index_type = debug_make_int_type (dhandle, 4, false);
+ if (index_type == DEBUG_TYPE_NULL)
+ return DEBUG_TYPE_NULL;
+ }
+ *pp = p;
+ }
+ else
+ {
+ index_type = parse_stab_type (dhandle, info, (const char *) NULL, pp,
+ (debug_type **) NULL);
+ }
+
+ if (**pp != ';')
+ {
+ bad_stab (orig);
+ return DEBUG_TYPE_NULL;
+ }
+ ++*pp;
+
+ adjustable = false;
+
+ if (! isdigit ((unsigned char) **pp) && **pp != '-')
+ {
+ ++*pp;
+ adjustable = true;
+ }
+
+ lower = (bfd_signed_vma) parse_number (pp, (boolean *) NULL);
+ if (**pp != ';')
+ {
+ bad_stab (orig);
+ return DEBUG_TYPE_NULL;
+ }
+ ++*pp;
+
+ if (! isdigit ((unsigned char) **pp) && **pp != '-')
+ {
+ ++*pp;
+ adjustable = true;
+ }
+
+ upper = (bfd_signed_vma) parse_number (pp, (boolean *) NULL);
+ if (**pp != ';')
+ {
+ bad_stab (orig);
+ return DEBUG_TYPE_NULL;
+ }
+ ++*pp;
+
+ element_type = parse_stab_type (dhandle, info, (const char *) NULL, pp,
+ (debug_type **) NULL);
+ if (element_type == DEBUG_TYPE_NULL)
+ return DEBUG_TYPE_NULL;
+
+ if (adjustable)
+ {
+ lower = 0;
+ upper = -1;
+ }
+
+ return debug_make_array_type (dhandle, element_type, index_type, lower,
+ upper, stringp);
+}
+
+/* This struct holds information about files we have seen using
+ N_BINCL. */
+
+struct bincl_file
+{
+ /* The next N_BINCL file. */
+ struct bincl_file *next;
+ /* The next N_BINCL on the stack. */
+ struct bincl_file *next_stack;
+ /* The file name. */
+ const char *name;
+ /* The hash value. */
+ bfd_vma hash;
+ /* The file index. */
+ unsigned int file;
+ /* The list of types defined in this file. */
+ struct stab_types *file_types;
+};
+
+/* Start a new N_BINCL file, pushing it onto the stack. */
+
+static void
+push_bincl (info, name, hash)
+ struct stab_handle *info;
+ const char *name;
+ bfd_vma hash;
+{
+ struct bincl_file *n;
+
+ n = (struct bincl_file *) xmalloc (sizeof *n);
+ n->next = info->bincl_list;
+ n->next_stack = info->bincl_stack;
+ n->name = name;
+ n->hash = hash;
+ n->file = info->files;
+ n->file_types = NULL;
+ info->bincl_list = n;
+ info->bincl_stack = n;
+
+ ++info->files;
+ info->file_types = ((struct stab_types **)
+ xrealloc ((PTR) info->file_types,
+ (info->files
+ * sizeof *info->file_types)));
+ info->file_types[n->file] = NULL;
+}
+
+/* Finish an N_BINCL file, at an N_EINCL, popping the name off the
+ stack. */
+
+static const char *
+pop_bincl (info)
+ struct stab_handle *info;
+{
+ struct bincl_file *o;
+
+ o = info->bincl_stack;
+ if (o == NULL)
+ return info->main_filename;
+ info->bincl_stack = o->next_stack;
+
+ o->file_types = info->file_types[o->file];
+
+ if (info->bincl_stack == NULL)
+ return info->main_filename;
+ return info->bincl_stack->name;
+}
+
+/* Handle an N_EXCL: get the types from the corresponding N_BINCL. */
+
+static boolean
+find_excl (info, name, hash)
+ struct stab_handle *info;
+ const char *name;
+ bfd_vma hash;
+{
+ struct bincl_file *l;
+
+ ++info->files;
+ info->file_types = ((struct stab_types **)
+ xrealloc ((PTR) info->file_types,
+ (info->files
+ * sizeof *info->file_types)));
+
+ for (l = info->bincl_list; l != NULL; l = l->next)
+ if (l->hash == hash && strcmp (l->name, name) == 0)
+ break;
+ if (l == NULL)
+ {
+ warn_stab (name, "Undefined N_EXCL");
+ info->file_types[info->files - 1] = NULL;
+ return true;
+ }
+
+ info->file_types[info->files - 1] = l->file_types;
+
+ return true;
+}
+
+/* Handle a variable definition. gcc emits variable definitions for a
+ block before the N_LBRAC, so we must hold onto them until we see
+ it. The SunPRO compiler emits variable definitions after the
+ N_LBRAC, so we can call debug_record_variable immediately. */
+
+static boolean
+stab_record_variable (dhandle, info, name, type, kind, val)
+ PTR dhandle;
+ struct stab_handle *info;
+ const char *name;
+ debug_type type;
+ enum debug_var_kind kind;
+ bfd_vma val;
+{
+ struct stab_pending_var *v;
+
+ if ((kind == DEBUG_GLOBAL || kind == DEBUG_STATIC)
+ || ! info->within_function
+ || (info->gcc_compiled == 0 && info->n_opt_found))
+ return debug_record_variable (dhandle, name, type, kind, val);
+
+ v = (struct stab_pending_var *) xmalloc (sizeof *v);
+ memset (v, 0, sizeof *v);
+
+ v->next = info->pending;
+ v->name = name;
+ v->type = type;
+ v->kind = kind;
+ v->val = val;
+ info->pending = v;
+
+ return true;
+}
+
+/* Emit pending variable definitions. This is called after we see the
+ N_LBRAC that starts the block. */
+
+static boolean
+stab_emit_pending_vars (dhandle, info)
+ PTR dhandle;
+ struct stab_handle *info;
+{
+ struct stab_pending_var *v;
+
+ v = info->pending;
+ while (v != NULL)
+ {
+ struct stab_pending_var *next;
+
+ if (! debug_record_variable (dhandle, v->name, v->type, v->kind, v->val))
+ return false;
+
+ next = v->next;
+ free (v);
+ v = next;
+ }
+
+ info->pending = NULL;
+
+ return true;
+}
+
+/* Find the slot for a type in the database. */
+
+static debug_type *
+stab_find_slot (info, typenums)
+ struct stab_handle *info;
+ const int *typenums;
+{
+ int filenum;
+ int index;
+ struct stab_types **ps;
+
+ filenum = typenums[0];
+ index = typenums[1];
+
+ if (filenum < 0 || (unsigned int) filenum >= info->files)
+ {
+ fprintf (stderr, "Type file number %d out of range\n", filenum);
+ return NULL;
+ }
+ if (index < 0)
+ {
+ fprintf (stderr, "Type index number %d out of range\n", index);
+ return NULL;
+ }
+
+ ps = info->file_types + filenum;
+
+ while (index >= STAB_TYPES_SLOTS)
+ {
+ if (*ps == NULL)
+ {
+ *ps = (struct stab_types *) xmalloc (sizeof **ps);
+ memset (*ps, 0, sizeof **ps);
+ }
+ ps = &(*ps)->next;
+ index -= STAB_TYPES_SLOTS;
+ }
+ if (*ps == NULL)
+ {
+ *ps = (struct stab_types *) xmalloc (sizeof **ps);
+ memset (*ps, 0, sizeof **ps);
+ }
+
+ return (*ps)->types + index;
+}
+
+/* Find a type given a type number. If the type has not been
+ allocated yet, create an indirect type. */
+
+static debug_type
+stab_find_type (dhandle, info, typenums)
+ PTR dhandle;
+ struct stab_handle *info;
+ const int *typenums;
+{
+ debug_type *slot;
+
+ if (typenums[0] == 0 && typenums[1] < 0)
+ {
+ /* A negative type number indicates an XCOFF builtin type. */
+ return stab_xcoff_builtin_type (dhandle, info, typenums[1]);
+ }
+
+ slot = stab_find_slot (info, typenums);
+ if (slot == NULL)
+ return DEBUG_TYPE_NULL;
+
+ if (*slot == DEBUG_TYPE_NULL)
+ return debug_make_indirect_type (dhandle, slot, (const char *) NULL);
+
+ return *slot;
+}
+
+/* Record that a given type number refers to a given type. */
+
+static boolean
+stab_record_type (dhandle, info, typenums, type)
+ PTR dhandle;
+ struct stab_handle *info;
+ const int *typenums;
+ debug_type type;
+{
+ debug_type *slot;
+
+ slot = stab_find_slot (info, typenums);
+ if (slot == NULL)
+ return false;
+
+ /* gdb appears to ignore type redefinitions, so we do as well. */
+
+ *slot = type;
+
+ return true;
+}
+
+/* Return an XCOFF builtin type. */
+
+static debug_type
+stab_xcoff_builtin_type (dhandle, info, typenum)
+ PTR dhandle;
+ struct stab_handle *info;
+ int typenum;
+{
+ debug_type rettype;
+ const char *name;
+
+ if (typenum >= 0 || typenum < -XCOFF_TYPE_COUNT)
+ {
+ fprintf (stderr, "Unrecognized XCOFF type %d\n", typenum);
+ return DEBUG_TYPE_NULL;
+ }
+ if (info->xcoff_types[-typenum] != NULL)
+ return info->xcoff_types[-typenum];
+
+ switch (-typenum)
+ {
+ case 1:
+ /* The size of this and all the other types are fixed, defined
+ by the debugging format. */
+ name = "int";
+ rettype = debug_make_int_type (dhandle, 4, false);
+ break;
+ case 2:
+ name = "char";
+ rettype = debug_make_int_type (dhandle, 1, false);
+ break;
+ case 3:
+ name = "short";
+ rettype = debug_make_int_type (dhandle, 2, false);
+ break;
+ case 4:
+ name = "long";
+ rettype = debug_make_int_type (dhandle, 4, false);
+ break;
+ case 5:
+ name = "unsigned char";
+ rettype = debug_make_int_type (dhandle, 1, true);
+ break;
+ case 6:
+ name = "signed char";
+ rettype = debug_make_int_type (dhandle, 1, false);
+ break;
+ case 7:
+ name = "unsigned short";
+ rettype = debug_make_int_type (dhandle, 2, true);
+ break;
+ case 8:
+ name = "unsigned int";
+ rettype = debug_make_int_type (dhandle, 4, true);
+ break;
+ case 9:
+ name = "unsigned";
+ rettype = debug_make_int_type (dhandle, 4, true);
+ case 10:
+ name = "unsigned long";
+ rettype = debug_make_int_type (dhandle, 4, true);
+ break;
+ case 11:
+ name = "void";
+ rettype = debug_make_void_type (dhandle);
+ break;
+ case 12:
+ /* IEEE single precision (32 bit). */
+ name = "float";
+ rettype = debug_make_float_type (dhandle, 4);
+ break;
+ case 13:
+ /* IEEE double precision (64 bit). */
+ name = "double";
+ rettype = debug_make_float_type (dhandle, 8);
+ break;
+ case 14:
+ /* This is an IEEE double on the RS/6000, and different machines
+ with different sizes for "long double" should use different
+ negative type numbers. See stabs.texinfo. */
+ name = "long double";
+ rettype = debug_make_float_type (dhandle, 8);
+ break;
+ case 15:
+ name = "integer";
+ rettype = debug_make_int_type (dhandle, 4, false);
+ break;
+ case 16:
+ name = "boolean";
+ rettype = debug_make_bool_type (dhandle, 4);
+ break;
+ case 17:
+ name = "short real";
+ rettype = debug_make_float_type (dhandle, 4);
+ break;
+ case 18:
+ name = "real";
+ rettype = debug_make_float_type (dhandle, 8);
+ break;
+ case 19:
+ /* FIXME */
+ name = "stringptr";
+ rettype = NULL;
+ break;
+ case 20:
+ /* FIXME */
+ name = "character";
+ rettype = debug_make_int_type (dhandle, 1, true);
+ break;
+ case 21:
+ name = "logical*1";
+ rettype = debug_make_bool_type (dhandle, 1);
+ break;
+ case 22:
+ name = "logical*2";
+ rettype = debug_make_bool_type (dhandle, 2);
+ break;
+ case 23:
+ name = "logical*4";
+ rettype = debug_make_bool_type (dhandle, 4);
+ break;
+ case 24:
+ name = "logical";
+ rettype = debug_make_bool_type (dhandle, 4);
+ break;
+ case 25:
+ /* Complex type consisting of two IEEE single precision values. */
+ name = "complex";
+ rettype = debug_make_complex_type (dhandle, 8);
+ break;
+ case 26:
+ /* Complex type consisting of two IEEE double precision values. */
+ name = "double complex";
+ rettype = debug_make_complex_type (dhandle, 16);
+ break;
+ case 27:
+ name = "integer*1";
+ rettype = debug_make_int_type (dhandle, 1, false);
+ break;
+ case 28:
+ name = "integer*2";
+ rettype = debug_make_int_type (dhandle, 2, false);
+ break;
+ case 29:
+ name = "integer*4";
+ rettype = debug_make_int_type (dhandle, 4, false);
+ break;
+ case 30:
+ /* FIXME */
+ name = "wchar";
+ rettype = debug_make_int_type (dhandle, 2, false);
+ break;
+ case 31:
+ name = "long long";
+ rettype = debug_make_int_type (dhandle, 8, false);
+ break;
+ case 32:
+ name = "unsigned long long";
+ rettype = debug_make_int_type (dhandle, 8, true);
+ break;
+ case 33:
+ name = "logical*8";
+ rettype = debug_make_bool_type (dhandle, 8);
+ break;
+ case 34:
+ name = "integer*8";
+ rettype = debug_make_int_type (dhandle, 8, false);
+ break;
+ default:
+ abort ();
+ }
+
+ rettype = debug_name_type (dhandle, name, rettype);
+
+ info->xcoff_types[-typenum] = rettype;
+
+ return rettype;
+}
+
+/* Find or create a tagged type. */
+
+static debug_type
+stab_find_tagged_type (dhandle, info, p, len, kind)
+ PTR dhandle;
+ struct stab_handle *info;
+ const char *p;
+ int len;
+ enum debug_type_kind kind;
+{
+ char *name;
+ debug_type dtype;
+ struct stab_tag *st;
+
+ name = savestring (p, len);
+
+ /* We pass DEBUG_KIND_ILLEGAL because we want all tags in the same
+ namespace. This is right for C, and I don't know how to handle
+ other languages. FIXME. */
+ dtype = debug_find_tagged_type (dhandle, name, DEBUG_KIND_ILLEGAL);
+ if (dtype != DEBUG_TYPE_NULL)
+ {
+ free (name);
+ return dtype;
+ }
+
+ /* We need to allocate an entry on the undefined tag list. */
+ for (st = info->tags; st != NULL; st = st->next)
+ {
+ if (st->name[0] == name[0]
+ && strcmp (st->name, name) == 0)
+ {
+ if (st->kind == DEBUG_KIND_ILLEGAL)
+ st->kind = kind;
+ free (name);
+ break;
+ }
+ }
+ if (st == NULL)
+ {
+ st = (struct stab_tag *) xmalloc (sizeof *st);
+ memset (st, 0, sizeof *st);
+
+ st->next = info->tags;
+ st->name = name;
+ st->kind = kind;
+ st->slot = DEBUG_TYPE_NULL;
+ st->type = debug_make_indirect_type (dhandle, &st->slot, name);
+ info->tags = st;
+ }
+
+ return st->type;
+}
+
+/* In order to get the correct argument types for a stubbed method, we
+ need to extract the argument types from a C++ mangled string.
+ Since the argument types can refer back to the return type, this
+ means that we must demangle the entire physical name. In gdb this
+ is done by calling cplus_demangle and running the results back
+ through the C++ expression parser. Since we have no expression
+ parser, we must duplicate much of the work of cplus_demangle here.
+
+ We assume that GNU style demangling is used, since this is only
+ done for method stubs, and only g++ should output that form of
+ debugging information. */
+
+/* This structure is used to hold a pointer to type information which
+ demangling a string. */
+
+struct stab_demangle_typestring
+{
+ /* The start of the type. This is not null terminated. */
+ const char *typestring;
+ /* The length of the type. */
+ unsigned int len;
+};
+
+/* This structure is used to hold information while demangling a
+ string. */
+
+struct stab_demangle_info
+{
+ /* The debugging information handle. */
+ PTR dhandle;
+ /* The stab information handle. */
+ struct stab_handle *info;
+ /* The array of arguments we are building. */
+ debug_type *args;
+ /* Whether the method takes a variable number of arguments. */
+ boolean varargs;
+ /* The array of types we have remembered. */
+ struct stab_demangle_typestring *typestrings;
+ /* The number of typestrings. */
+ unsigned int typestring_count;
+ /* The number of typestring slots we have allocated. */
+ unsigned int typestring_alloc;
+};
+
+static void stab_bad_demangle PARAMS ((const char *));
+static unsigned int stab_demangle_count PARAMS ((const char **));
+static boolean stab_demangle_get_count
+ PARAMS ((const char **, unsigned int *));
+static boolean stab_demangle_prefix
+ PARAMS ((struct stab_demangle_info *, const char **));
+static boolean stab_demangle_function_name
+ PARAMS ((struct stab_demangle_info *, const char **, const char *));
+static boolean stab_demangle_signature
+ PARAMS ((struct stab_demangle_info *, const char **));
+static boolean stab_demangle_qualified
+ PARAMS ((struct stab_demangle_info *, const char **, debug_type *));
+static boolean stab_demangle_template
+ PARAMS ((struct stab_demangle_info *, const char **));
+static boolean stab_demangle_class
+ PARAMS ((struct stab_demangle_info *, const char **, const char **));
+static boolean stab_demangle_args
+ PARAMS ((struct stab_demangle_info *, const char **, debug_type **,
+ boolean *));
+static boolean stab_demangle_arg
+ PARAMS ((struct stab_demangle_info *, const char **, debug_type **,
+ unsigned int *, unsigned int *));
+static boolean stab_demangle_type
+ PARAMS ((struct stab_demangle_info *, const char **, debug_type *));
+static boolean stab_demangle_fund_type
+ PARAMS ((struct stab_demangle_info *, const char **, debug_type *));
+static boolean stab_demangle_remember_type
+ PARAMS ((struct stab_demangle_info *, const char *, int));
+
+/* Warn about a bad demangling. */
+
+static void
+stab_bad_demangle (s)
+ const char *s;
+{
+ fprintf (stderr, "bad mangled name `%s'\n", s);
+}
+
+/* Get a count from a stab string. */
+
+static unsigned int
+stab_demangle_count (pp)
+ const char **pp;
+{
+ unsigned int count;
+
+ count = 0;
+ while (isdigit ((unsigned char) **pp))
+ {
+ count *= 10;
+ count += **pp - '0';
+ ++*pp;
+ }
+ return count;
+}
+
+/* Require a count in a string. The count may be multiple digits, in
+ which case it must end in an underscore. */
+
+static boolean
+stab_demangle_get_count (pp, pi)
+ const char **pp;
+ unsigned int *pi;
+{
+ if (! isdigit ((unsigned char) **pp))
+ return false;
+
+ *pi = **pp - '0';
+ ++*pp;
+ if (isdigit ((unsigned char) **pp))
+ {
+ unsigned int count;
+ const char *p;
+
+ count = *pi;
+ p = *pp;
+ do
+ {
+ count *= 10;
+ count += *p - '0';
+ ++p;
+ }
+ while (isdigit ((unsigned char) *p));
+ if (*p == '_')
+ {
+ *pp = p + 1;
+ *pi = count;
+ }
+ }
+
+ return true;
+}
+
+/* This function demangles a physical name, returning a NULL
+ terminated array of argument types. */
+
+static debug_type *
+stab_demangle_argtypes (dhandle, info, physname, pvarargs)
+ PTR dhandle;
+ struct stab_handle *info;
+ const char *physname;
+ boolean *pvarargs;
+{
+ struct stab_demangle_info minfo;
+
+ minfo.dhandle = dhandle;
+ minfo.info = info;
+ minfo.args = NULL;
+ minfo.varargs = false;
+ minfo.typestring_alloc = 10;
+ minfo.typestrings = ((struct stab_demangle_typestring *)
+ xmalloc (minfo.typestring_alloc
+ * sizeof *minfo.typestrings));
+ minfo.typestring_count = 0;
+
+ /* cplus_demangle checks for special GNU mangled forms, but we can't
+ see any of them in mangled method argument types. */
+
+ if (! stab_demangle_prefix (&minfo, &physname))
+ goto error_return;
+
+ if (*physname != '\0')
+ {
+ if (! stab_demangle_signature (&minfo, &physname))
+ goto error_return;
+ }
+
+ free (minfo.typestrings);
+ minfo.typestrings = NULL;
+
+ if (minfo.args == NULL)
+ fprintf (stderr, "no argument types in mangled string\n");
+
+ *pvarargs = minfo.varargs;
+ return minfo.args;
+
+ error_return:
+ if (minfo.typestrings != NULL)
+ free (minfo.typestrings);
+ return NULL;
+}
+
+/* Demangle the prefix of the mangled name. */
+
+static boolean
+stab_demangle_prefix (minfo, pp)
+ struct stab_demangle_info *minfo;
+ const char **pp;
+{
+ const char *scan;
+ unsigned int i;
+
+ /* cplus_demangle checks for global constructors and destructors,
+ but we can't see them in mangled argument types. */
+
+ /* Look for `__'. */
+ scan = *pp;
+ do
+ {
+ scan = strchr (scan, '_');
+ }
+ while (scan != NULL && *++scan != '_');
+
+ if (scan == NULL)
+ {
+ stab_bad_demangle (*pp);
+ return false;
+ }
+
+ --scan;
+
+ /* We found `__'; move ahead to the last contiguous `__' pair. */
+ i = strspn (scan, "_");
+ if (i > 2)
+ scan += i - 2;
+
+ if (scan == *pp
+ && (isdigit ((unsigned char) scan[2])
+ || scan[2] == 'Q'
+ || scan[2] == 't'))
+ {
+ /* This is a GNU style constructor name. */
+ *pp = scan + 2;
+ return true;
+ }
+ else if (scan == *pp
+ && ! isdigit ((unsigned char) scan[2])
+ && scan[2] != 't')
+ {
+ /* Look for the `__' that separates the prefix from the
+ signature. */
+ while (*scan == '_')
+ ++scan;
+ scan = strstr (scan, "__");
+ if (scan == NULL || scan[2] == '\0')
+ {
+ stab_bad_demangle (*pp);
+ return false;
+ }
+
+ return stab_demangle_function_name (minfo, pp, scan);
+ }
+ else if (scan[2] != '\0')
+ {
+ /* The name doesn't start with `__', but it does contain `__'. */
+ return stab_demangle_function_name (minfo, pp, scan);
+ }
+ else
+ {
+ stab_bad_demangle (*pp);
+ return false;
+ }
+ /*NOTREACHED*/
+}
+
+/* Demangle a function name prefix. The scan argument points to the
+ double underscore which separates the function name from the
+ signature. */
+
+static boolean
+stab_demangle_function_name (minfo, pp, scan)
+ struct stab_demangle_info *minfo;
+ const char **pp;
+ const char *scan;
+{
+ const char *name;
+
+ /* The string from *pp to scan is the name of the function. We
+ don't care about the name, since we just looking for argument
+ types. However, for conversion operators, the name may include a
+ type which we must remember in order to handle backreferences. */
+
+ name = *pp;
+ *pp = scan + 2;
+
+ if (*pp - name >= 5
+ && strncmp (name, "type", 4) == 0
+ && (name[4] == '$' || name[4] == '.'))
+ {
+ const char *tem;
+
+ /* This is a type conversion operator. */
+ tem = name + 5;
+ if (! stab_demangle_type (minfo, &tem, (debug_type *) NULL))
+ return false;
+ }
+ else if (name[0] == '_'
+ && name[1] == '_'
+ && name[2] == 'o'
+ && name[3] == 'p')
+ {
+ const char *tem;
+
+ /* This is a type conversion operator. */
+ tem = name + 4;
+ if (! stab_demangle_type (minfo, &tem, (debug_type *) NULL))
+ return false;
+ }
+
+ return true;
+}
+
+/* Demangle the signature. This is where the argument types are
+ found. */
+
+static boolean
+stab_demangle_signature (minfo, pp)
+ struct stab_demangle_info *minfo;
+ const char **pp;
+{
+ const char *orig;
+ boolean expect_func, func_done;
+ const char *hold;
+
+ orig = *pp;
+
+ expect_func = false;
+ func_done = false;
+ hold = NULL;
+
+ while (**pp != '\0')
+ {
+ switch (**pp)
+ {
+ case 'Q':
+ hold = *pp;
+ if (! stab_demangle_qualified (minfo, pp, (debug_type *) NULL)
+ || ! stab_demangle_remember_type (minfo, hold, *pp - hold))
+ return false;
+ expect_func = true;
+ hold = NULL;
+ break;
+
+ case 'S':
+ /* Static member function. FIXME: Can this happen? */
+ if (hold == NULL)
+ hold = *pp;
+ ++*pp;
+ break;
+
+ case 'C':
+ /* Const member function. */
+ if (hold == NULL)
+ hold = *pp;
+ ++*pp;
+ break;
+
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ if (hold == NULL)
+ hold = *pp;
+ if (! stab_demangle_class (minfo, pp, (const char **) NULL)
+ || ! stab_demangle_remember_type (minfo, hold, *pp - hold))
+ return false;
+ expect_func = true;
+ hold = NULL;
+ break;
+
+ case 'F':
+ /* Function. I don't know if this actually happens with g++
+ output. */
+ hold = NULL;
+ func_done = true;
+ ++*pp;
+ if (! stab_demangle_args (minfo, pp, &minfo->args, &minfo->varargs))
+ return false;
+ break;
+
+ case 't':
+ /* Template. */
+ if (hold == NULL)
+ hold = *pp;
+ if (! stab_demangle_template (minfo, pp)
+ || ! stab_demangle_remember_type (minfo, hold, *pp - hold))
+ return false;
+ hold = NULL;
+ expect_func = true;
+ break;
+
+ case '_':
+ /* At the outermost level, we cannot have a return type
+ specified, so if we run into another '_' at this point we
+ are dealing with a mangled name that is either bogus, or
+ has been mangled by some algorithm we don't know how to
+ deal with. So just reject the entire demangling. */
+ stab_bad_demangle (orig);
+ return false;
+
+ default:
+ /* Assume we have stumbled onto the first outermost function
+ argument token, and start processing args. */
+ func_done = true;
+ if (! stab_demangle_args (minfo, pp, &minfo->args, &minfo->varargs))
+ return false;
+ break;
+ }
+
+ if (expect_func)
+ {
+ func_done = true;
+ if (! stab_demangle_args (minfo, pp, &minfo->args, &minfo->varargs))
+ return false;
+ }
+ }
+
+ if (! func_done)
+ {
+ /* With GNU style demangling, bar__3foo is 'foo::bar(void)', and
+ bar__3fooi is 'foo::bar(int)'. We get here when we find the
+ first case, and need to ensure that the '(void)' gets added
+ to the current declp. */
+ if (! stab_demangle_args (minfo, pp, &minfo->args, &minfo->varargs))
+ return false;
+ }
+
+ return true;
+}
+
+/* Demangle a qualified name, such as "Q25Outer5Inner" which is the
+ mangled form of "Outer::Inner". */
+
+static boolean
+stab_demangle_qualified (minfo, pp, ptype)
+ struct stab_demangle_info *minfo;
+ const char **pp;
+ debug_type *ptype;
+{
+ const char *orig;
+ const char *p;
+ unsigned int qualifiers;
+ debug_type context;
+
+ orig = *pp;
+
+ switch ((*pp)[1])
+ {
+ case '_':
+ /* GNU mangled name with more than 9 classes. The count is
+ preceded by an underscore (to distinguish it from the <= 9
+ case) and followed by an underscore. */
+ p = *pp + 2;
+ if (! isdigit ((unsigned char) *p) || *p == '0')
+ {
+ stab_bad_demangle (orig);
+ return false;
+ }
+ qualifiers = atoi (p);
+ while (isdigit ((unsigned char) *p))
+ ++p;
+ if (*p != '_')
+ {
+ stab_bad_demangle (orig);
+ return false;
+ }
+ *pp = p + 1;
+ break;
+
+ case '1': case '2': case '3': case '4': case '5':
+ case '6': case '7': case '8': case '9':
+ qualifiers = (*pp)[1] - '0';
+ /* Skip an optional underscore after the count. */
+ if ((*pp)[2] == '_')
+ ++*pp;
+ *pp += 2;
+ break;
+
+ case '0':
+ default:
+ stab_bad_demangle (orig);
+ return false;
+ }
+
+ context = DEBUG_TYPE_NULL;
+
+ /* Pick off the names. */
+ while (qualifiers-- > 0)
+ {
+ if (**pp == '_')
+ ++*pp;
+ if (**pp == 't')
+ {
+ /* FIXME: I don't know how to handle the ptype != NULL case
+ here. */
+ if (! stab_demangle_template (minfo, pp))
+ return false;
+ }
+ else
+ {
+ unsigned int len;
+
+ len = stab_demangle_count (pp);
+ if (strlen (*pp) < len)
+ {
+ stab_bad_demangle (orig);
+ return false;
+ }
+
+ if (ptype != NULL)
+ {
+ const debug_field *fields;
+
+ fields = NULL;
+ if (context != DEBUG_TYPE_NULL)
+ fields = debug_get_fields (minfo->dhandle, context);
+
+ context = DEBUG_TYPE_NULL;
+
+ if (fields != NULL)
+ {
+ char *name;
+
+ /* Try to find the type by looking through the
+ fields of context until we find a field with the
+ same type. This ought to work for a class
+ defined within a class, but it won't work for,
+ e.g., an enum defined within a class. stabs does
+ not give us enough information to figure out the
+ latter case. */
+
+ name = savestring (*pp, len);
+
+ for (; *fields != DEBUG_FIELD_NULL; fields++)
+ {
+ debug_type ft;
+ const char *dn;
+
+ ft = debug_get_field_type (minfo->dhandle, *fields);
+ if (ft == NULL)
+ return false;
+ dn = debug_get_type_name (minfo->dhandle, ft);
+ if (dn != NULL && strcmp (dn, name) == 0)
+ {
+ context = ft;
+ break;
+ }
+ }
+
+ free (name);
+ }
+
+ if (context == DEBUG_TYPE_NULL)
+ {
+ /* We have to fall back on finding the type by name.
+ If there are more types to come, then this must
+ be a class. Otherwise, it could be anything. */
+
+ if (qualifiers == 0)
+ {
+ char *name;
+
+ name = savestring (*pp, len);
+ context = debug_find_named_type (minfo->dhandle,
+ name);
+ free (name);
+ }
+
+ if (context == DEBUG_TYPE_NULL)
+ {
+ context = stab_find_tagged_type (minfo->dhandle,
+ minfo->info,
+ *pp, len,
+ (qualifiers == 0
+ ? DEBUG_KIND_ILLEGAL
+ : DEBUG_KIND_CLASS));
+ if (context == DEBUG_TYPE_NULL)
+ return false;
+ }
+ }
+ }
+
+ *pp += len;
+ }
+ }
+
+ if (ptype != NULL)
+ *ptype = context;
+
+ return true;
+}
+
+/* Demangle a template. */
+
+static boolean
+stab_demangle_template (minfo, pp)
+ struct stab_demangle_info *minfo;
+ const char **pp;
+{
+ const char *orig;
+ unsigned int r, i;
+
+ orig = *pp;
+
+ ++*pp;
+
+ /* Skip the template name. */
+ r = stab_demangle_count (pp);
+ if (r == 0 || strlen (*pp) < r)
+ {
+ stab_bad_demangle (orig);
+ return false;
+ }
+ *pp += r;
+
+ /* Get the size of the parameter list. */
+ if (stab_demangle_get_count (pp, &r) == 0)
+ {
+ stab_bad_demangle (orig);
+ return false;
+ }
+
+ for (i = 0; i < r; i++)
+ {
+ if (**pp == 'Z')
+ {
+ /* This is a type parameter. */
+ ++*pp;
+ if (! stab_demangle_type (minfo, pp, (debug_type *) NULL))
+ return false;
+ }
+ else
+ {
+ const char *old_p;
+ boolean pointerp, realp, integralp, charp, boolp;
+ boolean done;
+
+ old_p = *pp;
+ pointerp = false;
+ realp = false;
+ integralp = false;
+ charp = false;
+ boolp = false;
+ done = false;
+
+ /* This is a value parameter. */
+
+ if (! stab_demangle_type (minfo, pp, (debug_type *) NULL))
+ return false;
+
+ while (*old_p != '\0' && ! done)
+ {
+ switch (*old_p)
+ {
+ case 'P':
+ case 'p':
+ case 'R':
+ pointerp = true;
+ done = true;
+ break;
+ case 'C': /* Const. */
+ case 'S': /* Signed. */
+ case 'U': /* Unsigned. */
+ case 'V': /* Volatile. */
+ case 'F': /* Function. */
+ case 'M': /* Member function. */
+ case 'O': /* ??? */
+ ++old_p;
+ break;
+ case 'Q': /* Qualified name. */
+ integralp = true;
+ done = true;
+ break;
+ case 'T': /* Remembered type. */
+ abort ();
+ case 'v': /* Void. */
+ abort ();
+ case 'x': /* Long long. */
+ case 'l': /* Long. */
+ case 'i': /* Int. */
+ case 's': /* Short. */
+ case 'w': /* Wchar_t. */
+ integralp = true;
+ done = true;
+ break;
+ case 'b': /* Bool. */
+ boolp = true;
+ done = true;
+ break;
+ case 'c': /* Char. */
+ charp = true;
+ done = true;
+ break;
+ case 'r': /* Long double. */
+ case 'd': /* Double. */
+ case 'f': /* Float. */
+ realp = true;
+ done = true;
+ break;
+ default:
+ /* Assume it's a user defined integral type. */
+ integralp = true;
+ done = true;
+ break;
+ }
+ }
+
+ if (integralp)
+ {
+ if (**pp == 'm')
+ ++*pp;
+ while (isdigit ((unsigned char) **pp))
+ ++*pp;
+ }
+ else if (charp)
+ {
+ unsigned int val;
+
+ if (**pp == 'm')
+ ++*pp;
+ val = stab_demangle_count (pp);
+ if (val == 0)
+ {
+ stab_bad_demangle (orig);
+ return false;
+ }
+ }
+ else if (boolp)
+ {
+ unsigned int val;
+
+ val = stab_demangle_count (pp);
+ if (val != 0 && val != 1)
+ {
+ stab_bad_demangle (orig);
+ return false;
+ }
+ }
+ else if (realp)
+ {
+ if (**pp == 'm')
+ ++*pp;
+ while (isdigit ((unsigned char) **pp))
+ ++*pp;
+ if (**pp == '.')
+ {
+ ++*pp;
+ while (isdigit ((unsigned char) **pp))
+ ++*pp;
+ }
+ if (**pp == 'e')
+ {
+ ++*pp;
+ while (isdigit ((unsigned char) **pp))
+ ++*pp;
+ }
+ }
+ else if (pointerp)
+ {
+ unsigned int len;
+
+ if (! stab_demangle_get_count (pp, &len))
+ {
+ stab_bad_demangle (orig);
+ return false;
+ }
+ *pp += len;
+ }
+ }
+ }
+
+ return true;
+}
+
+/* Demangle a class name. */
+
+static boolean
+stab_demangle_class (minfo, pp, pstart)
+ struct stab_demangle_info *minfo;
+ const char **pp;
+ const char **pstart;
+{
+ const char *orig;
+ unsigned int n;
+
+ orig = *pp;
+
+ n = stab_demangle_count (pp);
+ if (strlen (*pp) < n)
+ {
+ stab_bad_demangle (orig);
+ return false;
+ }
+
+ if (pstart != NULL)
+ *pstart = *pp;
+
+ *pp += n;
+
+ return true;
+}
+
+/* Demangle function arguments. If the pargs argument is not NULL, it
+ is set to a NULL terminated array holding the arguments. */
+
+static boolean
+stab_demangle_args (minfo, pp, pargs, pvarargs)
+ struct stab_demangle_info *minfo;
+ const char **pp;
+ debug_type **pargs;
+ boolean *pvarargs;
+{
+ const char *orig;
+ unsigned int alloc, count;
+
+ orig = *pp;
+
+ alloc = 10;
+ if (pargs != NULL)
+ {
+ *pargs = (debug_type *) xmalloc (alloc * sizeof **pargs);
+ *pvarargs = false;
+ }
+ count = 0;
+
+ while (**pp != '_' && **pp != '\0' && **pp != 'e')
+ {
+ if (**pp == 'N' || **pp == 'T')
+ {
+ char temptype;
+ unsigned int r, t;
+
+ temptype = **pp;
+ ++*pp;
+
+ if (temptype == 'T')
+ r = 1;
+ else
+ {
+ if (! stab_demangle_get_count (pp, &r))
+ {
+ stab_bad_demangle (orig);
+ return false;
+ }
+ }
+
+ if (! stab_demangle_get_count (pp, &t))
+ {
+ stab_bad_demangle (orig);
+ return false;
+ }
+
+ if (t >= minfo->typestring_count)
+ {
+ stab_bad_demangle (orig);
+ return false;
+ }
+ while (r-- > 0)
+ {
+ const char *tem;
+
+ tem = minfo->typestrings[t].typestring;
+ if (! stab_demangle_arg (minfo, &tem, pargs, &count, &alloc))
+ return false;
+ }
+ }
+ else
+ {
+ if (! stab_demangle_arg (minfo, pp, pargs, &count, &alloc))
+ return false;
+ }
+ }
+
+ if (pargs != NULL)
+ (*pargs)[count] = DEBUG_TYPE_NULL;
+
+ if (**pp == 'e')
+ {
+ if (pargs != NULL)
+ *pvarargs = true;
+ ++*pp;
+ }
+
+ return true;
+}
+
+/* Demangle a single argument. */
+
+static boolean
+stab_demangle_arg (minfo, pp, pargs, pcount, palloc)
+ struct stab_demangle_info *minfo;
+ const char **pp;
+ debug_type **pargs;
+ unsigned int *pcount;
+ unsigned int *palloc;
+{
+ const char *start;
+ debug_type type;
+
+ start = *pp;
+ if (! stab_demangle_type (minfo, pp,
+ pargs == NULL ? (debug_type *) NULL : &type)
+ || ! stab_demangle_remember_type (minfo, start, *pp - start))
+ return false;
+
+ if (pargs != NULL)
+ {
+ if (type == DEBUG_TYPE_NULL)
+ return false;
+
+ if (*pcount + 1 >= *palloc)
+ {
+ *palloc += 10;
+ *pargs = ((debug_type *)
+ xrealloc (*pargs, *palloc * sizeof **pargs));
+ }
+ (*pargs)[*pcount] = type;
+ ++*pcount;
+ }
+
+ return true;
+}
+
+/* Demangle a type. If the ptype argument is not NULL, *ptype is set
+ to the newly allocated type. */
+
+static boolean
+stab_demangle_type (minfo, pp, ptype)
+ struct stab_demangle_info *minfo;
+ const char **pp;
+ debug_type *ptype;
+{
+ const char *orig;
+
+ orig = *pp;
+
+ switch (**pp)
+ {
+ case 'P':
+ case 'p':
+ /* A pointer type. */
+ ++*pp;
+ if (! stab_demangle_type (minfo, pp, ptype))
+ return false;
+ if (ptype != NULL)
+ *ptype = debug_make_pointer_type (minfo->dhandle, *ptype);
+ break;
+
+ case 'R':
+ /* A reference type. */
+ ++*pp;
+ if (! stab_demangle_type (minfo, pp, ptype))
+ return false;
+ if (ptype != NULL)
+ *ptype = debug_make_reference_type (minfo->dhandle, *ptype);
+ break;
+
+ case 'A':
+ /* An array. */
+ {
+ unsigned long high;
+
+ ++*pp;
+ high = 0;
+ while (**pp != '\0' && **pp != '_')
+ {
+ if (! isdigit ((unsigned char) **pp))
+ {
+ stab_bad_demangle (orig);
+ return false;
+ }
+ high *= 10;
+ high += **pp - '0';
+ ++*pp;
+ }
+ if (**pp != '_')
+ {
+ stab_bad_demangle (orig);
+ return false;
+ }
+ ++*pp;
+
+ if (! stab_demangle_type (minfo, pp, ptype))
+ return false;
+ if (ptype != NULL)
+ {
+ debug_type int_type;
+
+ int_type = debug_find_named_type (minfo->dhandle, "int");
+ if (int_type == NULL)
+ int_type = debug_make_int_type (minfo->dhandle, 4, false);
+ *ptype = debug_make_array_type (minfo->dhandle, *ptype, int_type,
+ 0, high, false);
+ }
+ }
+ break;
+
+ case 'T':
+ /* A back reference to a remembered type. */
+ {
+ unsigned int i;
+ const char *p;
+
+ ++*pp;
+ if (! stab_demangle_get_count (pp, &i))
+ {
+ stab_bad_demangle (orig);
+ return false;
+ }
+ if (i >= minfo->typestring_count)
+ {
+ stab_bad_demangle (orig);
+ return false;
+ }
+ p = minfo->typestrings[i].typestring;
+ if (! stab_demangle_type (minfo, &p, ptype))
+ return false;
+ }
+ break;
+
+ case 'F':
+ /* A function. */
+ {
+ debug_type *args;
+ boolean varargs;
+
+ ++*pp;
+ if (! stab_demangle_args (minfo, pp,
+ (ptype == NULL
+ ? (debug_type **) NULL
+ : &args),
+ (ptype == NULL
+ ? (boolean *) NULL
+ : &varargs)))
+ return false;
+ if (**pp != '_')
+ {
+ /* cplus_demangle will accept a function without a return
+ type, but I don't know when that will happen, or what
+ to do if it does. */
+ stab_bad_demangle (orig);
+ return false;
+ }
+ ++*pp;
+ if (! stab_demangle_type (minfo, pp, ptype))
+ return false;
+ if (ptype != NULL)
+ *ptype = debug_make_function_type (minfo->dhandle, *ptype, args,
+ varargs);
+
+ }
+ break;
+
+ case 'M':
+ case 'O':
+ {
+ boolean memberp, constp, volatilep;
+ debug_type *args;
+ boolean varargs;
+ unsigned int n;
+ const char *name;
+
+ memberp = **pp == 'M';
+ constp = false;
+ volatilep = false;
+ args = NULL;
+ varargs = false;
+
+ ++*pp;
+ if (! isdigit ((unsigned char) **pp))
+ {
+ stab_bad_demangle (orig);
+ return false;
+ }
+ n = stab_demangle_count (pp);
+ if (strlen (*pp) < n)
+ {
+ stab_bad_demangle (orig);
+ return false;
+ }
+ name = *pp;
+ *pp += n;
+
+ if (memberp)
+ {
+ if (**pp == 'C')
+ {
+ constp = true;
+ ++*pp;
+ }
+ else if (**pp == 'V')
+ {
+ volatilep = true;
+ ++*pp;
+ }
+ if (**pp != 'F')
+ {
+ stab_bad_demangle (orig);
+ return false;
+ }
+ ++*pp;
+ if (! stab_demangle_args (minfo, pp,
+ (ptype == NULL
+ ? (debug_type **) NULL
+ : &args),
+ (ptype == NULL
+ ? (boolean *) NULL
+ : &varargs)))
+ return false;
+ }
+
+ if (**pp != '_')
+ {
+ stab_bad_demangle (orig);
+ return false;
+ }
+ ++*pp;
+
+ if (! stab_demangle_type (minfo, pp, ptype))
+ return false;
+
+ if (ptype != NULL)
+ {
+ debug_type class_type;
+
+ class_type = stab_find_tagged_type (minfo->dhandle, minfo->info,
+ name, (int) n,
+ DEBUG_KIND_CLASS);
+ if (class_type == DEBUG_TYPE_NULL)
+ return false;
+
+ if (! memberp)
+ *ptype = debug_make_offset_type (minfo->dhandle, class_type,
+ *ptype);
+ else
+ {
+ /* FIXME: We have no way to record constp or
+ volatilep. */
+ *ptype = debug_make_method_type (minfo->dhandle, *ptype,
+ class_type, args, varargs);
+ }
+ }
+ }
+ break;
+
+ case 'G':
+ ++*pp;
+ if (! stab_demangle_type (minfo, pp, ptype))
+ return false;
+ break;
+
+ case 'C':
+ ++*pp;
+ if (! stab_demangle_type (minfo, pp, ptype))
+ return false;
+ if (ptype != NULL)
+ *ptype = debug_make_const_type (minfo->dhandle, *ptype);
+ break;
+
+ case 'Q':
+ {
+ const char *hold;
+
+ hold = *pp;
+ if (! stab_demangle_qualified (minfo, pp, ptype))
+ return false;
+ }
+ break;
+
+ default:
+ if (! stab_demangle_fund_type (minfo, pp, ptype))
+ return false;
+ break;
+ }
+
+ return true;
+}
+
+/* Demangle a fundamental type. If the ptype argument is not NULL,
+ *ptype is set to the newly allocated type. */
+
+static boolean
+stab_demangle_fund_type (minfo, pp, ptype)
+ struct stab_demangle_info *minfo;
+ const char **pp;
+ debug_type *ptype;
+{
+ const char *orig;
+ boolean constp, volatilep, unsignedp, signedp;
+ boolean done;
+
+ orig = *pp;
+
+ constp = false;
+ volatilep = false;
+ unsignedp = false;
+ signedp = false;
+
+ done = false;
+ while (! done)
+ {
+ switch (**pp)
+ {
+ case 'C':
+ constp = true;
+ ++*pp;
+ break;
+
+ case 'U':
+ unsignedp = true;
+ ++*pp;
+ break;
+
+ case 'S':
+ signedp = true;
+ ++*pp;
+ break;
+
+ case 'V':
+ volatilep = true;
+ ++*pp;
+ break;
+
+ default:
+ done = true;
+ break;
+ }
+ }
+
+ switch (**pp)
+ {
+ case '\0':
+ case '_':
+ /* cplus_demangle permits this, but I don't know what it means. */
+ stab_bad_demangle (orig);
+ break;
+
+ case 'v': /* void */
+ if (ptype != NULL)
+ {
+ *ptype = debug_find_named_type (minfo->dhandle, "void");
+ if (*ptype == DEBUG_TYPE_NULL)
+ *ptype = debug_make_void_type (minfo->dhandle);
+ }
+ ++*pp;
+ break;
+
+ case 'x': /* long long */
+ if (ptype != NULL)
+ {
+ *ptype = debug_find_named_type (minfo->dhandle,
+ (unsignedp
+ ? "long long unsigned int"
+ : "long long int"));
+ if (*ptype == DEBUG_TYPE_NULL)
+ *ptype = debug_make_int_type (minfo->dhandle, 8, unsignedp);
+ }
+ ++*pp;
+ break;
+
+ case 'l': /* long */
+ if (ptype != NULL)
+ {
+ *ptype = debug_find_named_type (minfo->dhandle,
+ (unsignedp
+ ? "long unsigned int"
+ : "long int"));
+ if (*ptype == DEBUG_TYPE_NULL)
+ *ptype = debug_make_int_type (minfo->dhandle, 4, unsignedp);
+ }
+ ++*pp;
+ break;
+
+ case 'i': /* int */
+ if (ptype != NULL)
+ {
+ *ptype = debug_find_named_type (minfo->dhandle,
+ (unsignedp
+ ? "unsigned int"
+ : "int"));
+ if (*ptype == DEBUG_TYPE_NULL)
+ *ptype = debug_make_int_type (minfo->dhandle, 4, unsignedp);
+ }
+ ++*pp;
+ break;
+
+ case 's': /* short */
+ if (ptype != NULL)
+ {
+ *ptype = debug_find_named_type (minfo->dhandle,
+ (unsignedp
+ ? "short unsigned int"
+ : "short int"));
+ if (*ptype == DEBUG_TYPE_NULL)
+ *ptype = debug_make_int_type (minfo->dhandle, 2, unsignedp);
+ }
+ ++*pp;
+ break;
+
+ case 'b': /* bool */
+ if (ptype != NULL)
+ {
+ *ptype = debug_find_named_type (minfo->dhandle, "bool");
+ if (*ptype == DEBUG_TYPE_NULL)
+ *ptype = debug_make_bool_type (minfo->dhandle, 4);
+ }
+ ++*pp;
+ break;
+
+ case 'c': /* char */
+ if (ptype != NULL)
+ {
+ *ptype = debug_find_named_type (minfo->dhandle,
+ (unsignedp
+ ? "unsigned char"
+ : (signedp
+ ? "signed char"
+ : "char")));
+ if (*ptype == DEBUG_TYPE_NULL)
+ *ptype = debug_make_int_type (minfo->dhandle, 1, unsignedp);
+ }
+ ++*pp;
+ break;
+
+ case 'w': /* wchar_t */
+ if (ptype != NULL)
+ {
+ *ptype = debug_find_named_type (minfo->dhandle, "__wchar_t");
+ if (*ptype == DEBUG_TYPE_NULL)
+ *ptype = debug_make_int_type (minfo->dhandle, 2, true);
+ }
+ ++*pp;
+ break;
+
+ case 'r': /* long double */
+ if (ptype != NULL)
+ {
+ *ptype = debug_find_named_type (minfo->dhandle, "long double");
+ if (*ptype == DEBUG_TYPE_NULL)
+ *ptype = debug_make_float_type (minfo->dhandle, 8);
+ }
+ ++*pp;
+ break;
+
+ case 'd': /* double */
+ if (ptype != NULL)
+ {
+ *ptype = debug_find_named_type (minfo->dhandle, "double");
+ if (*ptype == DEBUG_TYPE_NULL)
+ *ptype = debug_make_float_type (minfo->dhandle, 8);
+ }
+ ++*pp;
+ break;
+
+ case 'f': /* float */
+ if (ptype != NULL)
+ {
+ *ptype = debug_find_named_type (minfo->dhandle, "float");
+ if (*ptype == DEBUG_TYPE_NULL)
+ *ptype = debug_make_float_type (minfo->dhandle, 4);
+ }
+ ++*pp;
+ break;
+
+ case 'G':
+ ++*pp;
+ if (! isdigit ((unsigned char) **pp))
+ {
+ stab_bad_demangle (orig);
+ return false;
+ }
+ /* Fall through. */
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ {
+ const char *hold;
+
+ if (! stab_demangle_class (minfo, pp, &hold))
+ return false;
+ if (ptype != NULL)
+ {
+ char *name;
+
+ name = savestring (hold, *pp - hold);
+ *ptype = debug_find_named_type (minfo->dhandle, name);
+ if (*ptype == DEBUG_TYPE_NULL)
+ {
+ /* FIXME: It is probably incorrect to assume that
+ undefined types are tagged types. */
+ *ptype = stab_find_tagged_type (minfo->dhandle, minfo->info,
+ hold, *pp - hold,
+ DEBUG_KIND_ILLEGAL);
+ }
+ free (name);
+ }
+ }
+ break;
+
+ case 't':
+ if (! stab_demangle_template (minfo, pp))
+ return false;
+ if (ptype != NULL)
+ {
+ debug_type t;
+
+ /* FIXME: I really don't know how a template should be
+ represented in the current type system. Perhaps the
+ template should be demangled into a string, and the type
+ should be represented as a named type. However, I don't
+ know what the base type of the named type should be. */
+ t = debug_make_void_type (minfo->dhandle);
+ t = debug_make_pointer_type (minfo->dhandle, t);
+ t = debug_name_type (minfo->dhandle, "TEMPLATE", t);
+ *ptype = t;
+ }
+ break;
+
+ default:
+ stab_bad_demangle (orig);
+ return false;
+ }
+
+ if (ptype != NULL)
+ {
+ if (constp)
+ *ptype = debug_make_const_type (minfo->dhandle, *ptype);
+ if (volatilep)
+ *ptype = debug_make_volatile_type (minfo->dhandle, *ptype);
+ }
+
+ return true;
+}
+
+/* Remember a type string in a demangled string. */
+
+static boolean
+stab_demangle_remember_type (minfo, p, len)
+ struct stab_demangle_info *minfo;
+ const char *p;
+ int len;
+{
+ if (minfo->typestring_count >= minfo->typestring_alloc)
+ {
+ minfo->typestring_alloc += 10;
+ minfo->typestrings = ((struct stab_demangle_typestring *)
+ xrealloc (minfo->typestrings,
+ (minfo->typestring_alloc
+ * sizeof *minfo->typestrings)));
+ }
+
+ minfo->typestrings[minfo->typestring_count].typestring = p;
+ minfo->typestrings[minfo->typestring_count].len = (unsigned int) len;
+ ++minfo->typestring_count;
+
+ return true;
+}
diff --git a/readline/bind.c b/readline/bind.c
index 57383239098..f122bdf4860 100644
--- a/readline/bind.c
+++ b/readline/bind.c
@@ -108,7 +108,7 @@ Keymap rl_binding_keymap;
/* Forward declarations */
void rl_set_keymap_from_edit_mode ();
-static int _rl_read_init_file ();
+static int _rl_read_init_file (const char *filename, int include_level);
static int glean_key_from_name ();
static int substring_member_of_array ();
@@ -570,10 +570,7 @@ rl_named_function (string)
type of the object pointed to. One of ISFUNC (function), ISKMAP (keymap),
or ISMACR (macro). */
Function *
-rl_function_of_keyseq (keyseq, map, type)
- char *keyseq;
- Keymap map;
- int *type;
+rl_function_of_keyseq (const char *keyseq, Keymap map, int *type)
{
register int i;
@@ -629,7 +626,7 @@ rl_function_of_keyseq (keyseq, map, type)
static char *last_readline_init_file = (char *)NULL;
/* The file we're currently reading key bindings from. */
-static char *current_readline_init_file;
+static const char *current_readline_init_file;
static int current_readline_init_include_level;
static int current_readline_init_lineno;
@@ -685,8 +682,8 @@ _rl_read_file (filename, sizep)
/* Re-read the current keybindings file. */
int
-rl_re_read_init_file (count, ignore)
- int count, ignore;
+rl_re_read_init_file (int count __attribute__((unused)),
+ int ignore __attribute__((unused)))
{
int r;
r = rl_read_init_file ((char *)NULL);
@@ -702,8 +699,7 @@ rl_re_read_init_file (count, ignore)
If the file existed and could be opened and read, 0 is returned,
otherwise errno is returned. */
int
-rl_read_init_file (filename)
- char *filename;
+rl_read_init_file (const char *filename)
{
/* Default the filename. */
if (filename == 0)
@@ -722,9 +718,7 @@ rl_read_init_file (filename)
}
static int
-_rl_read_init_file (filename, include_level)
- char *filename;
- int include_level;
+_rl_read_init_file (const char *filename, int include_level)
{
register int i;
char *buffer, *openname, *line, *end;
@@ -739,7 +733,7 @@ _rl_read_init_file (filename, include_level)
if (buffer == 0)
return (errno);
-
+
if (include_level == 0 && filename != last_readline_init_file)
{
FREE (last_readline_init_file);
@@ -797,7 +791,7 @@ _rl_init_file_error (msg)
/* Conditionals. */
/* Calling programs set this to have their argv[0]. */
-char *rl_readline_name = "other";
+const char *rl_readline_name = "other";
/* Stack of previous values of parsing_conditionalized_out. */
static unsigned char *if_stack = (unsigned char *)NULL;
@@ -881,7 +875,7 @@ parser_if (args)
/* Invert the current parser state if there is anything on the stack. */
static int
parser_else (args)
- char *args;
+char *args __attribute__((unused));
{
register int i;
@@ -906,7 +900,7 @@ parser_else (args)
_rl_parsing_conditionalized_out from the stack. */
static int
parser_endif (args)
- char *args;
+char *args __attribute__((unused));
{
if (if_stack_depth)
_rl_parsing_conditionalized_out = if_stack[--if_stack_depth];
@@ -919,7 +913,8 @@ static int
parser_include (args)
char *args;
{
- char *old_init_file, *e;
+ const char *old_init_file;
+ char *e;
int old_line_number, old_include_level, r;
if (_rl_parsing_conditionalized_out)
@@ -940,10 +935,10 @@ parser_include (args)
return r;
}
-
+
/* Associate textual names with actual functions. */
static struct {
- char *name;
+ const char *name;
Function *function;
} parser_directives [] = {
{ "if", parser_if },
@@ -1233,7 +1228,7 @@ rl_parse_and_bind (string)
false. */
static struct {
- char *name;
+ const char *name;
int *value;
} boolean_varlist [] = {
#if defined (PAREN_MATCHING)
@@ -1375,7 +1370,7 @@ rl_variable_bind (name, value)
_rl_isearch_terminators[end] = '\0';
free (v);
}
-
+
/* For the time being, unknown variable names are simply ignored. */
return 0;
}
@@ -1384,7 +1379,7 @@ rl_variable_bind (name, value)
For example, `Space' returns ' '. */
typedef struct {
- char *name;
+ const char *name;
int value;
} assoc_list;
@@ -1418,7 +1413,7 @@ glean_key_from_name (name)
/* Auxiliary functions to manage keymaps. */
static struct {
- char *name;
+ const char *name;
Keymap map;
} keymap_names[] = {
{ "emacs", emacs_standard_keymap },
@@ -1446,7 +1441,7 @@ rl_get_keymap_by_name (name)
return ((Keymap) NULL);
}
-char *
+const char *
rl_get_keymap_name (map)
Keymap map;
{
@@ -1456,7 +1451,7 @@ rl_get_keymap_name (map)
return (keymap_names[i].name);
return ((char *)NULL);
}
-
+
void
rl_set_keymap (map)
Keymap map;
@@ -1482,7 +1477,7 @@ rl_set_keymap_from_edit_mode ()
#endif /* VI_MODE */
}
-char *
+const char *
rl_get_keymap_name_from_edit_mode ()
{
if (rl_editing_mode == emacs_mode)
@@ -1675,7 +1670,7 @@ rl_invoking_keyseqs_in_map (function, map)
keyname[0] = (char) key;
keyname[1] = '\0';
}
-
+
strcat (keyname, seqs[i]);
free (seqs[i]);
@@ -1780,8 +1775,8 @@ rl_function_dumper (print_readably)
rl_outstream. If an explicit argument is given, then print
the output in such a way that it can be read back in. */
int
-rl_dump_functions (count, key)
- int count, key;
+rl_dump_functions (int count __attribute__((unused)),
+ int key __attribute__((unused)))
{
if (rl_dispatching)
fprintf (rl_outstream, "\r\n");
@@ -1865,8 +1860,8 @@ rl_macro_dumper (print_readably)
}
int
-rl_dump_macros (count, key)
- int count, key;
+rl_dump_macros (int count __attribute__((unused)),
+ int key __attribute__((unused)))
{
if (rl_dispatching)
fprintf (rl_outstream, "\r\n");
@@ -1880,7 +1875,7 @@ rl_variable_dumper (print_readably)
int print_readably;
{
int i;
- char *kname;
+ const char *kname;
for (i = 0; boolean_varlist[i].name; i++)
{
@@ -1955,8 +1950,8 @@ rl_variable_dumper (print_readably)
rl_outstream. If an explicit argument is given, then print
the output in such a way that it can be read back in. */
int
-rl_dump_variables (count, key)
- int count, key;
+rl_dump_variables (int count __attribute__((unused)),
+ int key __attribute__((unused)))
{
if (rl_dispatching)
fprintf (rl_outstream, "\r\n");
diff --git a/readline/callback.c b/readline/callback.c
index 6915be483a4..200f3cc37f9 100644
--- a/readline/callback.c
+++ b/readline/callback.c
@@ -29,6 +29,7 @@
#if defined (READLINE_CALLBACKS)
+#include <stdlib.h>
#include <sys/types.h>
#include <stdio.h>
diff --git a/readline/complete.c b/readline/complete.c
index ade317ff578..8810ca06d5f 100644
--- a/readline/complete.c
+++ b/readline/complete.c
@@ -95,7 +95,7 @@ extern int rl_display_fixed;
VFunction *rl_completion_display_matches_hook = (VFunction *)NULL;
/* Forward declarations for functions defined and used in this file. */
-char *filename_completion_function ();
+char *filename_completion_function (const char *text, int state);
char **completion_matches ();
#if defined (VISIBLE_STATS)
@@ -186,15 +186,15 @@ int rl_completion_query_items = 100;
/* The basic list of characters that signal a break between words for the
completer routine. The contents of this variable is what breaks words
in the shell, i.e. " \t\n\"\\'`@$><=" */
-char *rl_basic_word_break_characters = " \t\n\"\\'`@$><=;|&{(";
+const char *rl_basic_word_break_characters = " \t\n\"\\'`@$><=;|&{(";
/* List of basic quoting characters. */
-char *rl_basic_quote_characters = "\"'";
+const char *rl_basic_quote_characters = "\"'";
/* The list of characters that signal a break between words for
rl_complete_internal. The default list is the contents of
rl_basic_word_break_characters. */
-char *rl_completer_word_break_characters = (char *)NULL;
+const char *rl_completer_word_break_characters = (char *)NULL;
/* List of characters which can be used to quote a substring of the line.
Completion occurs on the entire substring, and within the substring
@@ -241,7 +241,7 @@ Function *rl_ignore_some_completions_function = (Function *)NULL;
and a pointer to the quoting character to be used, which the function can
reset if desired. */
CPFunction *rl_filename_quoting_function = rl_quote_filename;
-
+
/* Function to call to remove quoting characters from a filename. Called
before completion is attempted, so the embedded quotes do not interfere
with matching names in the file system. Readline doesn't do anything
@@ -291,14 +291,14 @@ rl_complete (ignore, invoking_key)
/* List the possible completions. See description of rl_complete (). */
int
rl_possible_completions (ignore, invoking_key)
- int ignore, invoking_key;
+ int ignore __attribute__((unused)), invoking_key __attribute__((unused));
{
return (rl_complete_internal ('?'));
}
int
rl_insert_completions (ignore, invoking_key)
- int ignore, invoking_key;
+ int ignore __attribute__((unused)), invoking_key __attribute__((unused));
{
return (rl_complete_internal ('*'));
}
@@ -513,7 +513,7 @@ print_filename (to_print, full_pathname)
static char *
rl_quote_filename (s, rtype, qcp)
char *s;
- int rtype;
+ int rtype __attribute__((unused));
char *qcp;
{
char *r;
@@ -1010,7 +1010,7 @@ display_matches (matches)
(*rl_completion_display_matches_hook) (matches, len, max);
return;
}
-
+
/* If there are many items, then ask the user if she really wants to
see them all. */
if (len >= rl_completion_query_items)
@@ -1356,9 +1356,7 @@ rl_complete_internal (what_to_do)
when there are no more matches.
*/
char **
-completion_matches (text, entry_function)
- char *text;
- CPFunction *entry_function;
+completion_matches (const char *text, CPFunction *entry_function)
{
/* Number of slots in match_list. */
int match_list_size;
@@ -1403,9 +1401,7 @@ completion_matches (text, entry_function)
TEXT contains a partial username preceded by a random
character (usually `~'). */
char *
-username_completion_function (text, state)
- char *text;
- int state;
+username_completion_function (const char *text, int state)
{
#if defined (__GO32__) || defined (__WIN__) || defined (__OPENNT)
return (char *)NULL;
@@ -1460,9 +1456,7 @@ username_completion_function (text, state)
because of all the pathnames that must be followed when looking up the
completion for a command. */
char *
-filename_completion_function (text, state)
- char *text;
- int state;
+filename_completion_function (const char *text, int state)
{
static DIR *directory = (DIR *)NULL;
static char *filename = (char *)NULL;
@@ -1639,8 +1633,7 @@ filename_completion_function (text, state)
hit the end of the match list, we restore the original unmatched text,
ring the bell, and reset the counter to zero. */
int
-rl_menu_complete (count, ignore)
- int count, ignore;
+rl_menu_complete (int count, int ignore __attribute__((unused)))
{
Function *our_func;
int matching_filenames, found_quote;
diff --git a/readline/display.c b/readline/display.c
index 25aba64ca67..e21af1f472d 100644
--- a/readline/display.c
+++ b/readline/display.c
@@ -79,9 +79,9 @@ extern int _rl_output_character_function ();
#endif
extern int _rl_backspace ();
-extern char *term_clreol, *term_clrpag;
-extern char *term_im, *term_ic, *term_ei, *term_DC;
-extern char *term_up, *term_dc, *term_cr, *term_IC;
+extern const char *term_clreol, *term_clrpag;
+extern const char *term_im, *term_ic, *term_ei, *term_DC;
+extern const char *term_up, *term_dc, *term_cr, *term_IC;
extern int screenheight, screenwidth, screenchars;
extern int terminal_can_insert, _rl_term_autowrap;
@@ -141,7 +141,7 @@ int _rl_suppress_redisplay = 0;
/* The stuff that gets printed out before the actual text of the line.
This is usually pointing to rl_prompt. */
-char *rl_display_prompt = (char *)NULL;
+const char *rl_display_prompt = (char *)NULL;
/* Pseudo-global variables declared here. */
/* The visible cursor position. If you print some text, adjust this. */
@@ -218,7 +218,7 @@ expand_prompt (pmt, lp, lip)
l = strlen (pmt);
r = ret = xmalloc (l + 1);
-
+
for (rl = ignoring = last = 0, p = pmt; p && *p; p++)
{
/* This code strips the invisible character string markers
@@ -315,7 +315,7 @@ rl_redisplay ()
register char *line;
int c_pos, inv_botlin, lb_botlin, lb_linenum;
int newlines, lpos, temp;
- char *prompt_this_line;
+ const char *prompt_this_line;
if (!readline_echoing_p)
return;
@@ -831,7 +831,7 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
if (old[0] && new[0])
old[0] = new[0];
}
-
+
/* Find first difference. */
for (ofd = old, nfd = new;
(ofd - old < omax) && *ofd && (*ofd == *nfd);
@@ -1229,8 +1229,7 @@ rl_message (va_alist)
}
#else /* !USE_VARARGS */
int
-rl_message (format, arg1, arg2)
- char *format;
+rl_message (char *format, void *arg1, void *arg2)
{
sprintf (msg_buf, format, arg1, arg2);
rl_display_prompt = msg_buf;
@@ -1512,7 +1511,8 @@ cr ()
void
_rl_redisplay_after_sigwinch ()
{
- char *t, *oldp, *oldl, *oldlprefix;
+ char *t, *oldl, *oldlprefix;
+ const char *oldp;
/* Clear the current line and put the cursor at column 0. Make sure
the right thing happens if we have wrapped to a new screen line. */
diff --git a/readline/funmap.c b/readline/funmap.c
index f6b86286fe0..472119bd80a 100644
--- a/readline/funmap.c
+++ b/readline/funmap.c
@@ -180,16 +180,14 @@ static FUNMAP default_funmap[] = {
};
int
-rl_add_funmap_entry (name, function)
- char *name;
- Function *function;
+rl_add_funmap_entry (const char *name, Function *function)
{
if (funmap_entry + 2 >= funmap_size)
{
funmap_size += 64;
funmap = (FUNMAP **)xrealloc (funmap, funmap_size * sizeof (FUNMAP *));
}
-
+
funmap[funmap_entry] = (FUNMAP *)xmalloc (sizeof (FUNMAP));
funmap[funmap_entry]->name = name;
funmap[funmap_entry]->function = function;
@@ -236,7 +234,7 @@ rl_funmap_names ()
result = (char **)xrealloc (result, result_size * sizeof (char *));
}
- result[result_index] = funmap[result_index]->name;
+ result[result_index] = (char*) funmap[result_index]->name;
result[result_index + 1] = (char *)NULL;
}
@@ -245,10 +243,10 @@ rl_funmap_names ()
}
/* Things that mean `Control'. */
-char *possible_control_prefixes[] = {
+const char *possible_control_prefixes[] = {
"Control-", "C-", "CTRL-", (char *)NULL
};
-char *possible_meta_prefixes[] = {
+const char *possible_meta_prefixes[] = {
"Meta", "M-", (char *)NULL
};
diff --git a/readline/histexpand.c b/readline/histexpand.c
index 30c6131801d..f78838ef2ba 100644
--- a/readline/histexpand.c
+++ b/readline/histexpand.c
@@ -87,7 +87,7 @@ char history_comment_char = '\0';
/* The list of characters which inhibit the expansion of text if found
immediately following history_expansion_char. */
-char *history_no_expand_chars = " \t\n\r=";
+const char *history_no_expand_chars = " \t\n\r=";
/* If set to a non-zero value, single quotes inhibit history expansion.
The default is 0. */
@@ -249,7 +249,7 @@ get_history_event (string, caller_index, delimiting_quote)
{
entry = current_history ();
history_offset = history_length;
-
+
/* If this was a substring search, then remember the
string that we matched for word substitution. */
if (substring_okay)
@@ -342,7 +342,8 @@ hist_error(s, start, current, errtype)
char *s;
int start, current, errtype;
{
- char *temp, *emsg;
+ char *temp;
+ const char *emsg;
int ll, elen;
ll = current - start;
@@ -514,7 +515,7 @@ history_expand_internal (string, start, end_index_ptr, ret_string, current_line)
quoted_search_delimiter = string[i - 1];
event = get_history_event (string, &i, quoted_search_delimiter);
}
-
+
if (event == 0)
{
*ret_string = hist_error (string, start, i, EVENT_NOT_FOUND);
@@ -825,7 +826,7 @@ history_expand (hstring, output)
*output = savestring (hstring);
return (0);
}
-
+
/* Prepare the buffer for printing error messages. */
result = xmalloc (result_len = 256);
result[0] = '\0';
@@ -904,7 +905,7 @@ history_expand (hstring, output)
i++;
}
}
-
+
if (string[i] != history_expansion_char)
{
free (result);
@@ -1239,7 +1240,7 @@ history_tokenize_internal (string, wind, indp)
return (result);
start = i;
-
+
if (member (string[i], "()\n"))
{
i++;
diff --git a/readline/histfile.c b/readline/histfile.c
index 3325b7fc1f7..1da45b00b58 100644
--- a/readline/histfile.c
+++ b/readline/histfile.c
@@ -84,14 +84,15 @@ static char *
history_filename (filename)
char *filename;
{
- char *return_val, *home;
+ char *return_val;
+ const char *home;
int home_len;
return_val = filename ? savestring (filename) : (char *)NULL;
if (return_val)
return (return_val);
-
+
home = get_env_value ("HOME");
if (home == 0)
@@ -130,11 +131,10 @@ read_history_range (filename, from, to)
char *filename;
int from, to;
{
- register int line_start, line_end;
char *input, *buffer;
int file, current_line;
struct stat finfo;
- size_t file_size;
+ size_t line_start, line_end, file_size;
buffer = (char *)NULL;
input = history_filename (filename);
diff --git a/readline/history.c b/readline/history.c
index d56ffacc6a0..804ffddcd89 100644
--- a/readline/history.c
+++ b/readline/history.c
@@ -161,7 +161,7 @@ history_set_pos (pos)
history_offset = pos;
return (1);
}
-
+
/* Return the current history array. The caller has to be carefull, since this
is the actual array of data, and could be bashed or made corrupt easily.
The array is terminated with a NULL pointer. */
diff --git a/readline/history.h b/readline/history.h
index 8ecce726779..88bf471bb62 100644
--- a/readline/history.h
+++ b/readline/history.h
@@ -116,7 +116,7 @@ extern HIST_ENTRY **history_list __P((void));
/* Returns the number which says what history element we are now
looking at. */
extern int where_history __P((void));
-
+
/* Return the history entry at the current position, as determined by
history_offset. If there is no entry there, return a NULL pointer. */
HIST_ENTRY *current_history __P((void));
@@ -232,8 +232,8 @@ extern int max_input_history;
extern char history_expansion_char;
extern char history_subst_char;
extern char history_comment_char;
-extern char *history_no_expand_chars;
-extern char *history_search_delimiter_chars;
+extern const char *history_no_expand_chars;
+extern const char *history_search_delimiter_chars;
extern int history_quotes_inhibit_expansion;
/* If set, this function is called to decide whether or not a particular
diff --git a/readline/histsearch.c b/readline/histsearch.c
index 7e98e950acb..eb17e9332e8 100644
--- a/readline/histsearch.c
+++ b/readline/histsearch.c
@@ -52,7 +52,7 @@ extern int history_offset;
/* The list of alternate characters that can delimit a history search
string. */
-char *history_search_delimiter_chars = (char *)NULL;
+const char *history_search_delimiter_chars = (char *)NULL;
/* Search the history for STRING, starting at history_offset.
If DIRECTION < 0, then the search is through previous entries, else
diff --git a/readline/input.c b/readline/input.c
index e23af552494..ea1342969b0 100644
--- a/readline/input.c
+++ b/readline/input.c
@@ -311,7 +311,7 @@ _rl_input_available ()
void
_rl_insert_typein (c)
int c;
-{
+{
int key, t, i;
char *string;
diff --git a/readline/isearch.c b/readline/isearch.c
index ae8dce520f0..a4a294b6b20 100644
--- a/readline/isearch.c
+++ b/readline/isearch.c
@@ -97,7 +97,8 @@ rl_forward_search_history (sign, key)
static void
rl_display_search (search_string, reverse_p, where)
char *search_string;
- int reverse_p, where;
+ int reverse_p;
+ int where __attribute__((unused));
{
char *message;
int msglen, searchlen;
@@ -144,8 +145,7 @@ rl_display_search (search_string, reverse_p, where)
DIRECTION is which direction to search; >= 0 means forward, < 0 means
backwards. */
static int
-rl_search_history (direction, invoking_key)
- int direction, invoking_key;
+rl_search_history (int direction, int invoking_key __attribute__((unused)))
{
/* The string that the user types in to search for. */
char *search_string;
diff --git a/readline/kill.c b/readline/kill.c
index 0b4714fafa8..78387e138c2 100644
--- a/readline/kill.c
+++ b/readline/kill.c
@@ -82,8 +82,7 @@ static int rl_kill_ring_length;
/* How to say that you only want to save a certain amount
of kill material. */
int
-rl_set_retained_kills (num)
- int num;
+rl_set_retained_kills (int num __attribute__((unused)))
{
return 0;
}
@@ -285,8 +284,8 @@ rl_backward_kill_line (direction, ignore)
/* Kill the whole line, no matter where point is. */
int
-rl_kill_full_line (count, ignore)
- int count, ignore;
+rl_kill_full_line (int count __attribute__((unused)),
+ int ignore __attribute__((unused)))
{
rl_begin_undo_group ();
rl_point = 0;
@@ -302,8 +301,7 @@ rl_kill_full_line (count, ignore)
/* This does what C-w does in Unix. We can't prevent people from
using behaviour that they expect. */
int
-rl_unix_word_rubout (count, key)
- int count, key;
+rl_unix_word_rubout (int count, int key __attribute__((unused)))
{
int orig_point;
@@ -336,8 +334,8 @@ rl_unix_word_rubout (count, key)
into the line at all, and if you aren't, then you know what you are
doing. */
int
-rl_unix_line_discard (count, key)
- int count, key;
+rl_unix_line_discard (int count __attribute__((unused)),
+ int key __attribute__((unused)))
{
if (rl_point == 0)
ding ();
@@ -374,16 +372,16 @@ region_kill_internal (delete)
/* Copy the text in the region to the kill ring. */
int
-rl_copy_region_to_kill (count, ignore)
- int count, ignore;
+rl_copy_region_to_kill (int count __attribute__((unused)),
+ int key __attribute__((unused)))
{
return (region_kill_internal (0));
}
/* Kill the text between the point and mark. */
int
-rl_kill_region (count, ignore)
- int count, ignore;
+rl_kill_region (int count __attribute__((unused)),
+ int key __attribute__((unused)))
{
int r;
@@ -442,11 +440,11 @@ rl_copy_backward_word (count, key)
return (_rl_copy_word_as_kill (count, -1));
}
-
+
/* Yank back the last killed text. This ignores arguments. */
int
-rl_yank (count, ignore)
- int count, ignore;
+rl_yank (int count __attribute__((unused)),
+ int key __attribute__((unused)))
{
if (rl_kill_ring == 0)
{
@@ -464,8 +462,8 @@ rl_yank (count, ignore)
delete that text from the line, rotate the index down, and
yank back some other text. */
int
-rl_yank_pop (count, key)
- int count, key;
+rl_yank_pop (int count __attribute__((unused)),
+ int key __attribute__((unused)))
{
int l, n;
@@ -592,7 +590,7 @@ rl_yank_last_arg (count, key)
if (history_skip < 0)
history_skip = 0;
}
-
+
if (explicit_arg_p)
retval = rl_yank_nth_arg_internal (count_passed, key, history_skip);
else
diff --git a/readline/macro.c b/readline/macro.c
index f3c442b41c3..b4d7835c631 100644
--- a/readline/macro.c
+++ b/readline/macro.c
@@ -90,7 +90,7 @@ static int current_macro_index;
It is a linked list of string/index for each saved macro. */
struct saved_macro {
struct saved_macro *next;
- char *string;
+ const char *string;
int sindex;
};
@@ -100,11 +100,10 @@ static struct saved_macro *macro_list = (struct saved_macro *)NULL;
/* Set up to read subsequent input from STRING.
STRING is free ()'ed when we are done with it. */
void
-_rl_with_macro_input (string)
- char *string;
+_rl_with_macro_input (const char *string)
{
_rl_push_executing_macro ();
- _rl_executing_macro = string;
+ _rl_executing_macro = (char*) string;
executing_macro_index = 0;
}
@@ -155,7 +154,7 @@ _rl_pop_executing_macro ()
if (macro_list)
{
macro = macro_list;
- _rl_executing_macro = macro_list->string;
+ _rl_executing_macro = (char*) macro_list->string;
executing_macro_index = macro_list->sindex;
macro_list = macro_list->next;
free (macro);
@@ -206,8 +205,8 @@ _rl_kill_kbd_macro ()
definition to the end of the existing macro, and start by
re-executing the existing macro. */
int
-rl_start_kbd_macro (ignore1, ignore2)
- int ignore1, ignore2;
+rl_start_kbd_macro (int count __attribute__((unused)),
+ int key __attribute__((unused)))
{
if (_rl_defining_kbd_macro)
{
@@ -231,8 +230,7 @@ rl_start_kbd_macro (ignore1, ignore2)
A numeric argument says to execute the macro right now,
that many times, counting the definition as the first time. */
int
-rl_end_kbd_macro (count, ignore)
- int count, ignore;
+rl_end_kbd_macro (int count, int ignore __attribute__((unused)))
{
if (_rl_defining_kbd_macro == 0)
{
@@ -251,8 +249,7 @@ rl_end_kbd_macro (count, ignore)
/* Execute the most recently defined keyboard macro.
COUNT says how many times to execute it. */
int
-rl_call_last_kbd_macro (count, ignore)
- int count, ignore;
+rl_call_last_kbd_macro (int count, int key __attribute__((unused)))
{
if (current_macro == 0)
_rl_abort_internal ();
diff --git a/readline/readline.c b/readline/readline.c
index 622811fc11e..1da73250773 100644
--- a/readline/readline.c
+++ b/readline/readline.c
@@ -129,8 +129,8 @@ extern int _rl_suppress_redisplay;
extern char *rl_display_prompt;
/* Variables imported from complete.c. */
-extern char *rl_completer_word_break_characters;
-extern char *rl_basic_word_break_characters;
+extern const char *rl_completer_word_break_characters;
+extern const char *rl_basic_word_break_characters;
extern int rl_completion_query_items;
extern int rl_complete_with_tilde_expansion;
@@ -181,7 +181,7 @@ extern char *xmalloc (), *xrealloc ();
/* */
/* **************************************************************** */
-char *rl_library_version = RL_LIBRARY_VERSION;
+const char *rl_library_version = RL_LIBRARY_VERSION;
/* A pointer to the keymap that is currently in use.
By default, it is the standard emacs keymap. */
@@ -280,7 +280,7 @@ int _rl_mark_modified_lines = 0;
/* The style of `bell' notification preferred. This can be set to NO_BELL,
AUDIBLE_BELL, or VISIBLE_BELL. */
int _rl_bell_preference = AUDIBLE_BELL;
-
+
/* String inserted into the line by rl_insert_comment (). */
char *_rl_comment_begin;
@@ -755,7 +755,7 @@ readline_initialize_everything ()
/* Decide whether we should automatically go into eight-bit mode. */
_rl_init_eightbit ();
-
+
/* Read in the init file. */
rl_read_init_file ((char *)NULL);
@@ -914,7 +914,7 @@ rl_digit_loop ()
/* Add the current digit to the argument in progress. */
int
rl_digit_argument (ignore, key)
- int ignore, key;
+ int ignore __attribute__((unused)), key;
{
rl_pending_input = key;
return (rl_digit_loop ());
@@ -944,7 +944,7 @@ _rl_init_argument ()
dispatch on it. If the key is the abort character then abort. */
int
rl_universal_argument (count, key)
- int count, key;
+ int count __attribute__((unused)), key __attribute__((unused));
{
rl_numeric_arg *= 4;
return (rl_digit_loop ());
@@ -960,8 +960,7 @@ rl_universal_argument (count, key)
way that you should do insertion. rl_insert () calls this
function. */
int
-rl_insert_text (string)
- char *string;
+rl_insert_text (const char *string)
{
register int i, l = strlen (string);
@@ -1147,7 +1146,7 @@ rl_backward (count, key)
/* Move to the beginning of the line. */
int
rl_beg_of_line (count, key)
- int count, key;
+ int count __attribute__((unused)), key __attribute__((unused));
{
rl_point = 0;
return 0;
@@ -1156,7 +1155,7 @@ rl_beg_of_line (count, key)
/* Move to the end of the line. */
int
rl_end_of_line (count, key)
- int count, key;
+ int count __attribute__((unused)), key __attribute__((unused));
{
rl_point = rl_end;
return 0;
@@ -1253,7 +1252,7 @@ rl_backward_word (count, key)
/* Clear the current line. Numeric argument to C-l does this. */
int
rl_refresh_line (ignore1, ignore2)
- int ignore1, ignore2;
+ int ignore1 __attribute__((unused)), ignore2 __attribute__((unused));
{
int curr_line, nleft;
@@ -1313,7 +1312,7 @@ rl_clear_screen (count, key)
int
rl_arrow_keys (count, c)
- int count, c;
+ int count, c __attribute__((unused));
{
int ch;
@@ -1417,7 +1416,7 @@ rl_insert (count, c)
/* Insert the next typed character verbatim. */
int
rl_quoted_insert (count, key)
- int count, key;
+ int count, key __attribute__((unused));
{
int c;
@@ -1428,7 +1427,7 @@ rl_quoted_insert (count, key)
/* Insert a tab character. */
int
rl_tab_insert (count, key)
- int count, key;
+ int count, key __attribute__((unused));
{
return (rl_insert (count, '\t'));
}
@@ -1438,7 +1437,7 @@ rl_tab_insert (count, key)
meaning in the future. */
int
rl_newline (count, key)
- int count, key;
+ int count __attribute__((unused)), key __attribute__((unused));
{
rl_done = 1;
@@ -1466,7 +1465,7 @@ rl_newline (count, key)
is special cased. */
int
rl_do_lowercase_version (ignore1, ignore2)
- int ignore1, ignore2;
+ int ignore1 __attribute__((unused)), ignore2 __attribute__((unused));
{
return 0;
}
@@ -1548,12 +1547,12 @@ rl_rubout_or_delete (count, key)
return (rl_rubout (count, key));
else
return (rl_delete (count, key));
-}
+}
/* Delete all spaces and tabs around point. */
int
rl_delete_horizontal_space (count, ignore)
- int count, ignore;
+ int count __attribute__((unused)), ignore __attribute__((unused));
{
int start = rl_point;
@@ -1594,7 +1593,7 @@ rl_delete_or_show_completions (count, key)
A K*rn shell style function. */
int
rl_insert_comment (count, key)
- int count, key;
+ int count __attribute__((unused)), key;
{
rl_beg_of_line (1, key);
rl_insert_text (_rl_comment_begin ? _rl_comment_begin
@@ -1620,7 +1619,7 @@ static int rl_change_case ();
/* Uppercase the word at point. */
int
rl_upcase_word (count, key)
- int count, key;
+ int count, key __attribute__((unused));
{
return (rl_change_case (count, UpCase));
}
@@ -1628,7 +1627,7 @@ rl_upcase_word (count, key)
/* Lowercase the word at point. */
int
rl_downcase_word (count, key)
- int count, key;
+ int count, key __attribute__((unused));
{
return (rl_change_case (count, DownCase));
}
@@ -1636,7 +1635,7 @@ rl_downcase_word (count, key)
/* Upcase the first letter, downcase the rest. */
int
rl_capitalize_word (count, key)
- int count, key;
+ int count, key __attribute__((unused));
{
return (rl_change_case (count, CapCase));
}
@@ -1760,7 +1759,7 @@ rl_transpose_words (count, key)
then transpose the characters before point. */
int
rl_transpose_chars (count, key)
- int count, key;
+ int count, key __attribute__((unused));
{
char dummy[2];
@@ -1853,14 +1852,14 @@ _rl_char_search (count, fdir, bdir)
int
rl_char_search (count, key)
- int count, key;
+ int count, key __attribute__((unused));
{
return (_rl_char_search (count, FFIND, BFIND));
}
int
rl_backward_char_search (count, key)
- int count, key;
+ int count, key __attribute__((unused));
{
return (_rl_char_search (count, BFIND, FFIND));
}
@@ -1965,7 +1964,7 @@ maybe_save_line ()
/* Meta-< goes to the start of the history. */
int
rl_beginning_of_history (count, key)
- int count, key;
+ int count __attribute__((unused)), key;
{
return (rl_get_previous_history (1 + where_history (), key));
}
@@ -1973,7 +1972,7 @@ rl_beginning_of_history (count, key)
/* Meta-> goes to the end of the history. (The current line). */
int
rl_end_of_history (count, key)
- int count, key;
+ int count __attribute__((unused)), key __attribute__((unused));
{
maybe_replace_line ();
using_history ();
@@ -2105,7 +2104,7 @@ _rl_set_mark_at_pos (position)
/* A bindable command to set the mark. */
int
rl_set_mark (count, key)
- int count, key;
+ int count, key __attribute__((unused));
{
return (_rl_set_mark_at_pos (rl_explicit_arg ? count : rl_point));
}
@@ -2113,7 +2112,7 @@ rl_set_mark (count, key)
/* Exchange the position of mark and point. */
int
rl_exchange_point_and_mark (count, key)
- int count, key;
+ int count __attribute__((unused)), key __attribute__((unused));
{
if (rl_mark > rl_end)
rl_mark = -1;
@@ -2137,7 +2136,7 @@ rl_exchange_point_and_mark (count, key)
/* How to toggle back and forth between editing modes. */
int
rl_vi_editing_mode (count, key)
- int count, key;
+ int count __attribute__((unused)), key;
{
#if defined (VI_MODE)
rl_editing_mode = vi_mode;
@@ -2148,7 +2147,7 @@ rl_vi_editing_mode (count, key)
int
rl_emacs_editing_mode (count, key)
- int count, key;
+ int count __attribute__((unused)), key __attribute__((unused));
{
rl_editing_mode = emacs_mode;
_rl_keymap = emacs_standard_keymap;
diff --git a/readline/readline.h b/readline/readline.h
index dba1a0fdde9..7804d31efb1 100644
--- a/readline/readline.h
+++ b/readline/readline.h
@@ -60,7 +60,7 @@ extern UNDO_LIST *rl_undo_list;
/* The data structure for mapping textual names to code addresses. */
typedef struct _funmap {
- char *name;
+ const char *name;
Function *function;
} FUNMAP;
@@ -286,17 +286,17 @@ extern int rl_translate_keyseq __P((char *, char *, int *));
extern char *rl_untranslate_keyseq __P((int));
extern Function *rl_named_function __P((char *));
-extern Function *rl_function_of_keyseq __P((char *, Keymap, int *));
+extern Function *rl_function_of_keyseq __P((const char *, Keymap, int *));
extern void rl_list_funmap_names __P((void));
extern char **rl_invoking_keyseqs_in_map __P((Function *, Keymap));
extern char **rl_invoking_keyseqs __P((Function *));
-
+
extern void rl_function_dumper __P((int));
extern void rl_macro_dumper __P((int));
extern void rl_variable_dumper __P((int));
-extern int rl_read_init_file __P((char *));
+extern int rl_read_init_file __P((const char *));
extern int rl_parse_and_bind __P((char *));
/* Functions for manipulating keymaps. */
@@ -306,14 +306,14 @@ extern Keymap rl_make_keymap __P((void));
extern void rl_discard_keymap __P((Keymap));
extern Keymap rl_get_keymap_by_name __P((char *));
-extern char *rl_get_keymap_name __P((Keymap));
+extern const char *rl_get_keymap_name __P((Keymap));
extern void rl_set_keymap __P((Keymap));
extern Keymap rl_get_keymap __P((void));
extern void rl_set_keymap_from_edit_mode __P((void));
-extern char *rl_get_keymap_name_from_edit_mode __P((void));
+extern const char *rl_get_keymap_name_from_edit_mode __P((void));
/* Functions for manipulating the funmap, which maps command names to functions. */
-extern int rl_add_funmap_entry __P((char *, Function *));
+extern int rl_add_funmap_entry __P((const char *, Function *));
extern void rl_initialize_funmap __P((void));
extern char **rl_funmap_names __P((void));
@@ -351,7 +351,7 @@ extern void rl_save_prompt __P((void));
extern void rl_restore_prompt __P((void));
/* Modifying text. */
-extern int rl_insert_text __P((char *));
+extern int rl_insert_text __P((const char *));
extern int rl_delete_text __P((int, int));
extern int rl_kill_text __P((int, int));
extern char *rl_copy_text __P((int, int));
@@ -380,7 +380,7 @@ extern int rl_clear_signals __P((void));
extern void rl_cleanup_after_signal __P((void));
extern void rl_reset_after_signal __P((void));
extern void rl_free_line_state __P((void));
-
+
/* Undocumented. */
extern int rl_expand_prompt __P((char *));
@@ -392,9 +392,9 @@ extern int maybe_replace_line __P((void));
extern int rl_complete_internal __P((int));
extern void rl_display_match_list __P((char **, int, int));
-extern char **completion_matches __P((char *, CPFunction *));
-extern char *username_completion_function __P((char *, int));
-extern char *filename_completion_function __P((char *, int));
+extern char **completion_matches __P((const char *, CPFunction *));
+extern char *username_completion_function __P((const char *, int));
+extern char *filename_completion_function __P((const char *, int));
/* **************************************************************** */
/* */
@@ -403,11 +403,11 @@ extern char *filename_completion_function __P((char *, int));
/* **************************************************************** */
/* The version of this incarnation of the readline library. */
-extern char *rl_library_version;
+extern const char *rl_library_version;
/* The name of the calling program. You should initialize this to
whatever was in argv[0]. It is used when parsing conditionals. */
-extern char *rl_readline_name;
+extern const char *rl_readline_name;
/* The prompt readline uses. This is set from the argument to
readline (), and should not be assigned to directly. */
@@ -448,7 +448,7 @@ extern Function *rl_startup_hook;
readline_internal_setup () returns and readline_internal starts
reading input characters. */
extern Function *rl_pre_input_hook;
-
+
/* The address of a function to call periodically while Readline is
awaiting character input, or NULL, for no event handling. */
extern Function *rl_event_hook;
@@ -506,12 +506,12 @@ extern CPPFunction *rl_attempted_completion_function;
/* The basic list of characters that signal a break between words for the
completer routine. The initial contents of this variable is what
breaks words in the shell, i.e. "n\"\\'`@$>". */
-extern char *rl_basic_word_break_characters;
+extern const char *rl_basic_word_break_characters;
/* The list of characters that signal a break between words for
rl_complete_internal. The default list is the contents of
rl_basic_word_break_characters. */
-extern char *rl_completer_word_break_characters;
+extern const char *rl_completer_word_break_characters;
/* List of characters which can be used to quote a substring of the line.
Completion occurs on the entire substring, and within the substring
@@ -520,7 +520,7 @@ extern char *rl_completer_word_break_characters;
extern char *rl_completer_quote_characters;
/* List of quote characters which cause a word break. */
-extern char *rl_basic_quote_characters;
+extern const char *rl_basic_quote_characters;
/* List of characters that need to be quoted in filenames by the completer. */
extern char *rl_filename_quote_characters;
@@ -599,7 +599,7 @@ extern int rl_ignore_completion_duplicates;
/* If this is non-zero, completion is (temporarily) inhibited, and the
completion character will be inserted as any other. */
extern int rl_inhibit_completion;
-
+
/* Definitions available for use by readline clients. */
#define RL_PROMPT_START_IGNORE '\001'
#define RL_PROMPT_END_IGNORE '\002'
diff --git a/readline/rlstdc.h b/readline/rlstdc.h
index d2c5f874d7a..f79cf89fe76 100644
--- a/readline/rlstdc.h
+++ b/readline/rlstdc.h
@@ -76,4 +76,8 @@
#endif /* !__STDC__ */
+#if !defined(__attribute__) && (defined(__cplusplus) || !defined(__GNUC__) || __GNUC__ == 2 && __GNUC_MINOR__ < 8)
+#define __attribute__(A)
+#endif
+
#endif /* !_RL_STDC_H_ */
diff --git a/readline/rltty.c b/readline/rltty.c
index b4d0cf127d5..f87c1c9747f 100644
--- a/readline/rltty.c
+++ b/readline/rltty.c
@@ -368,12 +368,15 @@ static TIOTYPE otio;
# define OUTPUT_BEING_FLUSHED(tp) 0
#endif
+#if defined (_AIX) || (defined (FLUSHO) && defined (_AIX41))
static void
rltty_warning (msg)
char *msg;
{
fprintf (stderr, "readline: warning: %s\n", msg);
}
+#endif
+
#if defined (_AIX)
void
@@ -604,8 +607,8 @@ rl_deprep_terminal ()
/* **************************************************************** */
int
-rl_restart_output (count, key)
- int count, key;
+rl_restart_output (int count __attribute__((unused)),
+ int key __attribute__((unused)))
{
int fildes = fileno (rl_outstream);
#if defined (TIOCSTART)
@@ -637,8 +640,8 @@ rl_restart_output (count, key)
}
int
-rl_stop_output (count, key)
- int count, key;
+rl_stop_output (int count __attribute__((unused)),
+ int key __attribute__((unused)))
{
int fildes = fileno (rl_instream);
diff --git a/readline/search.c b/readline/search.c
index f198e7409e5..0179d8da2f1 100644
--- a/readline/search.c
+++ b/readline/search.c
@@ -247,8 +247,7 @@ noninc_search (dir, pchar)
/* Search forward through the history list for a string. If the vi-mode
code calls this, KEY will be `?'. */
int
-rl_noninc_forward_search (count, key)
- int count, key;
+rl_noninc_forward_search (int count __attribute__((unused)), int key)
{
noninc_search (1, (key == '?') ? '?' : 0);
return 0;
@@ -257,8 +256,7 @@ rl_noninc_forward_search (count, key)
/* Reverse search the history list for a string. If the vi-mode code
calls this, KEY will be `/'. */
int
-rl_noninc_reverse_search (count, key)
- int count, key;
+rl_noninc_reverse_search (int count __attribute__((unused)), int key)
{
noninc_search (-1, (key == '/') ? '/' : 0);
return 0;
@@ -267,8 +265,8 @@ rl_noninc_reverse_search (count, key)
/* Search forward through the history list for the last string searched
for. If there is no saved search string, abort. */
int
-rl_noninc_forward_search_again (count, key)
- int count, key;
+rl_noninc_forward_search_again (int count __attribute__((unused)),
+ int key __attribute__((unused)))
{
if (!noninc_search_string)
{
@@ -282,8 +280,8 @@ rl_noninc_forward_search_again (count, key)
/* Reverse search in the history list for the last string searched
for. If there is no saved search string, abort. */
int
-rl_noninc_reverse_search_again (count, key)
- int count, key;
+rl_noninc_reverse_search_again (int count __attribute__((unused)),
+ int key __attribute__((unused)))
{
if (!noninc_search_string)
{
@@ -352,8 +350,7 @@ rl_history_search_internal (count, direction)
from the start of the line to rl_point. This is a non-incremental
search. */
int
-rl_history_search_forward (count, ignore)
- int count, ignore;
+rl_history_search_forward (int count, int ignore __attribute__((unused)))
{
if (count == 0)
return (0);
@@ -366,8 +363,7 @@ rl_history_search_forward (count, ignore)
from the start of the line to rl_point. This is a non-incremental
search. */
int
-rl_history_search_backward (count, ignore)
- int count, ignore;
+rl_history_search_backward (int count, int ignore __attribute__((unused)))
{
if (count == 0)
return (0);
diff --git a/readline/shell.c b/readline/shell.c
index 4d9e0064d3f..becd66e0f9a 100644
--- a/readline/shell.c
+++ b/readline/shell.c
@@ -26,6 +26,7 @@
# include <config.h>
#endif
+#include <stdio.h>
#include <sys/types.h>
#if defined (HAVE_UNISTD_H)
diff --git a/readline/terminal.c b/readline/terminal.c
index 6e94bdc4011..1d2fead7768 100644
--- a/readline/terminal.c
+++ b/readline/terminal.c
@@ -99,8 +99,8 @@ char PC, *BC, *UP;
#endif /* __linux__ */
/* Some strings to control terminal actions. These are output by tputs (). */
-char *term_goto, *term_clreol, *term_cr, *term_clrpag, *term_backspace;
-char *term_pc;
+char *term_goto, *term_clreol, *term_clrpag, *term_backspace;
+char *term_cr, *term_pc;
/* Non-zero if we determine that the terminal can do character insertion. */
int terminal_can_insert = 0;
@@ -245,8 +245,8 @@ rl_resize_terminal ()
}
struct _tc_string {
- char *tc_var;
- char **tc_value;
+ const char *tc_var;
+ char **tc_value;
};
/* This should be kept sorted, just in case we decide to change the
@@ -291,7 +291,7 @@ get_term_capabilities (bp)
{
register int i;
- for (i = 0; i < NUM_TC_STRINGS; i++)
+ for (i = 0; i < (int) NUM_TC_STRINGS; i++)
*(tc_strings[i].tc_value) = tgetstr (tc_strings[i].tc_var, bp);
tcap_initialized = 1;
}
@@ -304,7 +304,7 @@ _rl_init_terminal_io (terminal_name)
screenwidth = ScreenCols ();
screenheight = ScreenRows ();
screenchars = screenwidth * screenheight;
- term_cr = "\r";
+ term_cr = (char*) "\r";
term_im = term_ei = term_ic = term_IC = (char *)NULL;
term_up = term_dc = term_DC = visible_bell = (char *)NULL;
@@ -322,7 +322,8 @@ _rl_init_terminal_io (terminal_name)
return;
#else /* !__GO32__ */
- char *term, *buffer;
+ const char *term;
+ char *buffer;
int tty;
Keymap xkeymap;
@@ -347,7 +348,7 @@ _rl_init_terminal_io (terminal_name)
screenwidth = 79;
screenheight = 24;
screenchars = 79 * 24;
- term_cr = "\r";
+ term_cr = (char*) "\r";
term_im = term_ei = term_ic = term_IC = (char *)NULL;
term_up = term_dc = term_DC = visible_bell = (char *)NULL;
term_ku = term_kd = term_kl = term_kr = (char *)NULL;
@@ -367,7 +368,7 @@ _rl_init_terminal_io (terminal_name)
UP = term_up;
if (!term_cr)
- term_cr = "\r";
+ term_cr = (char*) "\r";
tty = rl_instream ? fileno (rl_instream) : 0;
@@ -427,7 +428,7 @@ rl_get_termcap (cap)
if (tcap_initialized == 0)
return ((char *)NULL);
- for (i = 0; i < NUM_TC_STRINGS; i++)
+ for (i = 0; i < (int) NUM_TC_STRINGS; i++)
{
if (tc_strings[i].tc_var[0] == cap[0] && strcmp (tc_strings[i].tc_var, cap) == 0)
return *(tc_strings[i].tc_value);
diff --git a/readline/tilde.c b/readline/tilde.c
index 65a1e2f3902..05c9ed741ed 100644
--- a/readline/tilde.c
+++ b/readline/tilde.c
@@ -82,13 +82,13 @@ extern char *get_env_value ();
/* The default value of tilde_additional_prefixes. This is set to
whitespace preceding a tilde so that simple programs which do not
perform any word separation get desired behaviour. */
-static char *default_prefixes[] =
+static const char *default_prefixes[] =
{ " ~", "\t~", (char *)NULL };
/* The default value of tilde_additional_suffixes. This is set to
whitespace or newline so that simple programs which do not
perform any word separation get desired behaviour. */
-static char *default_suffixes[] =
+static const char *default_suffixes[] =
{ " ", "\n", (char *)NULL };
/* If non-null, this contains the address of a function that the application
@@ -106,12 +106,12 @@ CPFunction *tilde_expansion_failure_hook = (CPFunction *)NULL;
/* When non-null, this is a NULL terminated array of strings which
are duplicates for a tilde prefix. Bash uses this to expand
`=~' and `:~'. */
-char **tilde_additional_prefixes = default_prefixes;
+const char ** tilde_additional_prefixes = default_prefixes;
/* When non-null, this is a NULL terminated array of strings which match
the end of a username, instead of just "/". Bash sets this to
`:' and `=~'. */
-char **tilde_additional_suffixes = default_suffixes;
+const char **tilde_additional_suffixes = default_suffixes;
/* Find the start of a tilde expansion in STRING, and return the index of
the tilde which starts the expansion. Place the length of the text
@@ -122,7 +122,7 @@ tilde_find_prefix (string, len)
int *len;
{
register int i, j, string_len;
- register char **prefixes = tilde_additional_prefixes;
+ register const char **prefixes = tilde_additional_prefixes;
string_len = strlen (string);
*len = 0;
@@ -154,7 +154,7 @@ tilde_find_suffix (string)
char *string;
{
register int i, j, string_len;
- register char **suffixes;
+ register const char **suffixes;
suffixes = tilde_additional_suffixes;
string_len = strlen (string);
diff --git a/readline/tilde.h b/readline/tilde.h
index 634b95449aa..45eea1b66e5 100644
--- a/readline/tilde.h
+++ b/readline/tilde.h
@@ -48,12 +48,12 @@ extern CPFunction *tilde_expansion_failure_hook;
/* When non-null, this is a NULL terminated array of strings which
are duplicates for a tilde prefix. Bash uses this to expand
`=~' and `:~'. */
-extern char **tilde_additional_prefixes;
+extern const char **tilde_additional_prefixes;
/* When non-null, this is a NULL terminated array of strings which match
the end of a username, instead of just "/". Bash sets this to
`:' and `=~'. */
-extern char **tilde_additional_suffixes;
+extern const char **tilde_additional_suffixes;
/* Return a new string which is the result of tilde expanding STRING. */
extern char *tilde_expand ();
diff --git a/readline/undo.c b/readline/undo.c
index 68710b667ed..c8f4892b774 100644
--- a/readline/undo.c
+++ b/readline/undo.c
@@ -174,7 +174,7 @@ _rl_fix_last_undo_of_type (type, start, end)
for (rl = rl_undo_list; rl; rl = rl->next)
{
- if (rl->what == type)
+ if ((int) rl->what == type)
{
rl->start = start;
rl->end = end;
@@ -225,8 +225,8 @@ rl_modifying (start, end)
/* Revert the current line to its previous state. */
int
-rl_revert_line (count, key)
- int count, key;
+rl_revert_line (int count __attribute__((unused)),
+ int key __attribute__((unused)))
{
if (!rl_undo_list)
ding ();
@@ -240,8 +240,7 @@ rl_revert_line (count, key)
/* Do some undoing of things that were done. */
int
-rl_undo_command (count, key)
- int count, key;
+rl_undo_command (int count, int key __attribute__((unused)))
{
if (count < 0)
return 0; /* Nothing to do. */
diff --git a/readline/util.c b/readline/util.c
index 1dc3b664f1c..bcd8f3bc5b2 100644
--- a/readline/util.c
+++ b/readline/util.c
@@ -81,7 +81,7 @@ extern char *xmalloc (), *xrealloc ();
in words, or 1 if it is. */
int _rl_allow_pathname_alphabetic_chars = 0;
-static char *pathname_alphabetic_chars = "/-_=~.#$";
+static const char *pathname_alphabetic_chars = "/-_=~.#$";
int
alphabetic (c)
@@ -113,15 +113,15 @@ _rl_abort_internal ()
}
int
-rl_abort (count, key)
- int count, key;
+rl_abort (int count __attribute__((unused)),
+ int key __attribute__((unused)))
{
return (_rl_abort_internal ());
}
int
-rl_tty_status (count, key)
- int count, key;
+rl_tty_status (int count __attribute__((unused)),
+ int key __attribute__((unused)))
{
#if defined (TIOCSTAT)
ioctl (1, TIOCSTAT, (char *)0);
@@ -170,8 +170,8 @@ rl_extend_line_buffer (len)
/* A function for simple tilde expansion. */
int
-rl_tilde_expand (ignore, key)
- int ignore, key;
+rl_tilde_expand (int ignore __attribute__((unused)),
+ int key __attribute__((unused)))
{
register int start, end;
char *homedir, *temp;
diff --git a/readline/vi_mode.c b/readline/vi_mode.c
index 2a4f11d28a4..5f97ef2a4c4 100644
--- a/readline/vi_mode.c
+++ b/readline/vi_mode.c
@@ -98,7 +98,7 @@ extern int rl_vi_check ();
static int _rl_vi_doing_insert;
/* Command keys which do movement for xxx_to commands. */
-static char *vi_motion = " hl^$0ftFt;,%wbeWBE|";
+static const char *vi_motion = " hl^$0ftFt;,%wbeWBE|";
/* Keymap used for vi replace characters. Created dynamically since
rarely used. */
@@ -126,7 +126,7 @@ static int _rl_vi_last_key_before_insert;
static int vi_redoing;
/* Text modification commands. These are the `redoable' commands. */
-static char *vi_textmod = "_*\\AaIiCcDdPpYyRrSsXx~";
+static const char *vi_textmod = "_*\\AaIiCcDdPpYyRrSsXx~";
/* Arrays for the saved marks. */
static int vi_mark_chars[27];
@@ -136,7 +136,7 @@ static int rl_digit_loop1 ();
void
_rl_vi_initialize_line ()
{
- register int i;
+ register uint i;
for (i = 0; i < (int) sizeof (vi_mark_chars) / sizeof (int); i++)
vi_mark_chars[i] = -1;
@@ -183,7 +183,7 @@ _rl_vi_stuff_insert (count)
puts you back into insert mode. */
int
rl_vi_redo (count, c)
- int count, c;
+ int count, c __attribute__((unused));
{
if (!rl_explicit_arg)
{
@@ -215,11 +215,11 @@ rl_vi_undo (count, key)
{
return (rl_undo_command (count, key));
}
-
+
/* Yank the nth arg from the previous line into this line at point. */
int
-rl_vi_yank_arg (count, key)
- int count, key;
+rl_vi_yank_arg (count, key)
+ int count, key __attribute__((unused));
{
/* Readline thinks that the first word on a line is the 0th, while vi
thinks the first word on a line is the 1st. Compensate. */
@@ -300,7 +300,7 @@ rl_vi_search (count, key)
/* Completion, from vi's point of view. */
int
rl_vi_complete (ignore, key)
- int ignore, key;
+ int ignore __attribute__((unused)), key;
{
if ((rl_point < rl_end) && (!whitespace (rl_line_buffer[rl_point])))
{
@@ -329,7 +329,7 @@ rl_vi_complete (ignore, key)
/* Tilde expansion for vi mode. */
int
rl_vi_tilde_expand (ignore, key)
- int ignore, key;
+ int ignore __attribute__((unused)), key;
{
rl_tilde_expand (0, key);
_rl_vi_set_last (key, 1, rl_arg_sign); /* XXX */
@@ -401,7 +401,7 @@ rl_vi_end_word (count, key)
/* Move forward a word the way that 'W' does. */
int
rl_vi_fWord (count, ignore)
- int count, ignore;
+ int count, ignore __attribute__((unused));
{
while (count-- && rl_point < (rl_end - 1))
{
@@ -418,7 +418,7 @@ rl_vi_fWord (count, ignore)
int
rl_vi_bWord (count, ignore)
- int count, ignore;
+ int count, ignore __attribute__((unused));
{
while (count-- && rl_point > 0)
{
@@ -442,7 +442,7 @@ rl_vi_bWord (count, ignore)
int
rl_vi_eWord (count, ignore)
- int count, ignore;
+ int count, ignore __attribute__((unused));
{
while (count-- && rl_point < (rl_end - 1))
{
@@ -472,7 +472,7 @@ rl_vi_eWord (count, ignore)
int
rl_vi_fword (count, ignore)
- int count, ignore;
+ int count, ignore __attribute__((unused));
{
while (count-- && rl_point < (rl_end - 1))
{
@@ -498,7 +498,7 @@ rl_vi_fword (count, ignore)
int
rl_vi_bword (count, ignore)
- int count, ignore;
+ int count, ignore __attribute__((unused));
{
while (count-- && rl_point > 0)
{
@@ -537,7 +537,7 @@ rl_vi_bword (count, ignore)
int
rl_vi_eword (count, ignore)
- int count, ignore;
+ int count, ignore __attribute__((unused));
{
while (count-- && rl_point < rl_end - 1)
{
@@ -562,7 +562,7 @@ rl_vi_eword (count, ignore)
int
rl_vi_insert_beg (count, key)
- int count, key;
+ int count __attribute__((unused)), key;
{
rl_beg_of_line (1, key);
rl_vi_insertion_mode (1, key);
@@ -571,7 +571,7 @@ rl_vi_insert_beg (count, key)
int
rl_vi_append_mode (count, key)
- int count, key;
+ int count __attribute__((unused)), key;
{
if (rl_point < rl_end)
rl_point++;
@@ -581,7 +581,7 @@ rl_vi_append_mode (count, key)
int
rl_vi_append_eol (count, key)
- int count, key;
+ int count __attribute__((unused)), key;
{
rl_end_of_line (1, key);
rl_vi_append_mode (1, key);
@@ -591,7 +591,7 @@ rl_vi_append_eol (count, key)
/* What to do in the case of C-d. */
int
rl_vi_eof_maybe (count, c)
- int count, c;
+ int count __attribute__((unused)), c __attribute__((unused));
{
return (rl_newline (1, '\n'));
}
@@ -602,7 +602,7 @@ rl_vi_eof_maybe (count, c)
switching keymaps. */
int
rl_vi_insertion_mode (count, key)
- int count, key;
+ int count __attribute__((unused)), key;
{
_rl_keymap = vi_insertion_keymap;
_rl_vi_last_key_before_insert = key;
@@ -633,7 +633,7 @@ _rl_vi_save_insert (up)
strncpy (vi_insert_buffer, rl_line_buffer + start, len - 1);
vi_insert_buffer[len-1] = '\0';
}
-
+
void
_rl_vi_done_inserting ()
{
@@ -664,7 +664,7 @@ _rl_vi_done_inserting ()
int
rl_vi_movement_mode (count, key)
- int count, key;
+ int count __attribute__((unused)), key;
{
if (rl_point > 0)
rl_backward (1, key);
@@ -686,7 +686,7 @@ rl_vi_arg_digit (count, c)
int
rl_vi_change_case (count, ignore)
- int count, ignore;
+ int count, ignore __attribute__((unused));
{
char c = 0;
@@ -724,7 +724,7 @@ rl_vi_change_case (count, ignore)
int
rl_vi_put (count, key)
- int count, key;
+ int count __attribute__((unused)), key;
{
if (!_rl_uppercase_p (key) && (rl_point + 1 <= rl_end))
rl_point++;
@@ -881,7 +881,7 @@ rl_digit_loop1 ()
int
rl_vi_delete_to (count, key)
- int count, key;
+ int count __attribute__((unused)), key;
{
int c;
@@ -961,7 +961,7 @@ rl_vi_change_to (count, key)
int
rl_vi_yank_to (count, key)
- int count, key;
+ int count __attribute__((unused)), key;
{
int c, save = rl_point;
@@ -1006,7 +1006,7 @@ rl_vi_delete (count, key)
end = rl_end;
rl_kill_text (rl_point, end);
-
+
if (rl_point > 0 && rl_point == rl_end)
rl_backward (1, key);
return (0);
@@ -1014,7 +1014,7 @@ rl_vi_delete (count, key)
int
rl_vi_back_to_indent (count, key)
- int count, key;
+ int count __attribute__((unused)), key;
{
rl_beg_of_line (1, key);
while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point]))
@@ -1024,7 +1024,7 @@ rl_vi_back_to_indent (count, key)
int
rl_vi_first_print (count, key)
- int count, key;
+ int count __attribute__((unused)), key;
{
return (rl_vi_back_to_indent (1, key));
}
@@ -1071,7 +1071,7 @@ rl_vi_char_search (count, key)
/* Match brackets */
int
rl_vi_match (ignore, key)
- int ignore, key;
+ int ignore __attribute__((unused)), key;
{
int count = 1, brack, pos;
@@ -1152,7 +1152,7 @@ rl_vi_bracktype (c)
int
rl_vi_change_char (count, key)
- int count, key;
+ int count, key __attribute__((unused));
{
int c;
@@ -1278,7 +1278,7 @@ rl_vi_overstrike_delete (count, key)
int
rl_vi_replace (count, key)
- int count, key;
+ int count __attribute__((unused)), key __attribute__((unused));
{
int i;
@@ -1339,7 +1339,7 @@ rl_vi_possible_completions()
/* Functions to save and restore marks. */
int
rl_vi_set_mark (count, key)
- int count, key;
+ int count __attribute__((unused)), key __attribute__((unused));
{
int ch;
@@ -1356,7 +1356,7 @@ rl_vi_set_mark (count, key)
int
rl_vi_goto_mark (count, key)
- int count, key;
+ int count __attribute__((unused)), key __attribute__((unused));
{
int ch;
diff --git a/regex/cclass.h b/regex/cclass.h
index 7d9a7ccc7c2..e0f752f38b8 100644
--- a/regex/cclass.h
+++ b/regex/cclass.h
@@ -15,7 +15,7 @@
#define CCLASS_LAST 12
extern struct cclass {
- char *name;
- char *chars;
- char *multis;
+ const char *name;
+ const char *chars;
+ const char *multis;
} cclasses[];
diff --git a/regex/cname.h b/regex/cname.h
index 2b6a1a8496f..06865f3e102 100644
--- a/regex/cname.h
+++ b/regex/cname.h
@@ -1,7 +1,7 @@
/* character-name table */
static struct cname {
- char *name;
- char code;
+ const char *name;
+ const char code;
} cnames[] = {
{"NUL", '\0'},
{"SOH", '\001'},
diff --git a/regex/debug.c b/regex/debug.c
index 8c6fd14a209..35279941d48 100644
--- a/regex/debug.c
+++ b/regex/debug.c
@@ -1,4 +1,4 @@
-#include <global.h>
+#include <my_global.h>
#include <m_ctype.h>
#include <m_string.h>
#include <sys/types.h>
diff --git a/regex/main.c b/regex/main.c
index 4b607f401ca..7844a4d8384 100644
--- a/regex/main.c
+++ b/regex/main.c
@@ -1,4 +1,4 @@
-#include <global.h>
+#include <my_global.h>
#include <m_string.h>
#include <sys/types.h>
#include <regex.h>
@@ -133,9 +133,9 @@ FILE *in;
int i;
char erbuf[100];
size_t ne;
- char *badpat = "invalid regular expression";
+ const char *badpat = "invalid regular expression";
# define SHORT 10
- char *bpname = "REG_BADPAT";
+ const char *bpname = "REG_BADPAT";
regex_t re;
while (fgets(inbuf, sizeof(inbuf), in) != NULL) {
@@ -152,7 +152,7 @@ FILE *in;
}
for (i = 0; i < nf; i++)
if (strcmp(f[i], "\"\"") == 0)
- f[i] = "";
+ f[i] = (char*) "";
if (nf <= 3)
f[3] = NULL;
if (nf <= 4)
@@ -217,7 +217,7 @@ int opts; /* may not match f1 */
char erbuf[100];
int err;
int len;
- char *type = (opts & REG_EXTENDED) ? "ERE" : "BRE";
+ const char *type = (opts & REG_EXTENDED) ? "ERE" : "BRE";
register int i;
char *grump;
char f0copy[1000];
@@ -291,7 +291,7 @@ int opts; /* may not match f1 */
nshould = split(f4, should+1, NSHOULD-1, ",");
if (nshould == 0) {
nshould = 1;
- should[1] = "";
+ should[1] = (char*) "";
}
for (i = 1; i < NSUBS; i++) {
grump = check(f2, subs[i], should[i]);
@@ -317,7 +317,7 @@ char *s;
{
register char *p;
register int o = (type == 'c') ? copts : eopts;
- register char *legal = (type == 'c') ? "bisnmp" : "^$#tl";
+ register const char *legal = (type == 'c') ? "bisnmp" : "^$#tl";
for (p = s; *p != '\0'; p++)
if (strchr(legal, *p) != NULL)
@@ -417,7 +417,7 @@ char *should;
should = NULL;
if (should != NULL && should[0] == '@') {
at = should + 1;
- should = "";
+ should = (char*) "";
}
/* check rm_so and rm_eo for consistency */
@@ -434,7 +434,7 @@ char *should;
if (sub.rm_so == -1 && should == NULL)
return(NULL);
if (sub.rm_so == -1)
- return("did not match");
+ return((char*) "did not match");
/* check for in range */
if ((int) sub.rm_eo > (int) strlen(str)) {
diff --git a/regex/regcomp.c b/regex/regcomp.c
index 048f45ca71c..6f8221a706d 100644
--- a/regex/regcomp.c
+++ b/regex/regcomp.c
@@ -1,4 +1,4 @@
-#include <global.h>
+#include <my_global.h>
#include <m_string.h>
#include <m_ctype.h>
#include <regex.h>
@@ -219,7 +219,7 @@ int stop; /* character this ERE should end at */
conc = HERE();
while (MORE() && (c = PEEK()) != '|' && c != stop)
p_ere_exp(p);
- if(REQUIRE(HERE() != conc, REG_EMPTY)); /* require nonempty */
+ if(REQUIRE(HERE() != conc, REG_EMPTY)) {}/* require nonempty */
if (!EAT('|'))
break; /* NOTE BREAK OUT */
@@ -266,11 +266,11 @@ register struct parse *p;
pos = HERE();
switch (c) {
case '(':
- if(REQUIRE(MORE(), REG_EPAREN));
+ if(REQUIRE(MORE(), REG_EPAREN)) {}
p->g->nsub++;
subno = (sopno) p->g->nsub;
if (subno < NPAREN)
- p->pbegin[subno] = HERE();
+ p->pbegin[subno] = HERE();
EMIT(OLPAREN, subno);
if (!SEE(')'))
p_ere(p, ')');
@@ -279,7 +279,7 @@ register struct parse *p;
assert(p->pend[subno] != 0);
}
EMIT(ORPAREN, subno);
- if(MUSTEAT(')', REG_EPAREN));
+ if(MUSTEAT(')', REG_EPAREN)) {}
break;
#ifndef POSIX_MISTAKE
case ')': /* happens only if no current unmatched ( */
@@ -322,12 +322,12 @@ register struct parse *p;
p_bracket(p);
break;
case '\\':
- if(REQUIRE(MORE(), REG_EESCAPE));
+ if(REQUIRE(MORE(), REG_EESCAPE)) {}
c = GETNEXT();
ordinary(p, c);
break;
case '{': /* okay as ordinary except if digit follows */
- if(REQUIRE(!MORE() || !isdigit(PEEK()), REG_BADRPT));
+ if(REQUIRE(!MORE() || !isdigit(PEEK()), REG_BADRPT)) {}
/* FALLTHROUGH */
default:
ordinary(p, c);
@@ -343,7 +343,7 @@ register struct parse *p;
return; /* no repetition, we're done */
NEXT();
- if(REQUIRE(!wascaret, REG_BADRPT));
+ if(REQUIRE(!wascaret, REG_BADRPT)) {}
switch (c) {
case '*': /* implemented as +? */
/* this case does not require the (y|) trick, noKLUDGE */
@@ -370,7 +370,7 @@ register struct parse *p;
if (EAT(',')) {
if (isdigit(PEEK())) {
count2 = p_count(p);
- if(REQUIRE(count <= count2, REG_BADBR));
+ if(REQUIRE(count <= count2, REG_BADBR)) {}
} else /* single number with comma */
count2 = RE_INFINITY;
} else /* just a single number */
@@ -379,7 +379,7 @@ register struct parse *p;
if (!EAT('}')) { /* error heuristics */
while (MORE() && PEEK() != '}')
NEXT();
- if(REQUIRE(MORE(), REG_EBRACE));
+ if(REQUIRE(MORE(), REG_EBRACE)) {}
SETERROR(REG_BADBR);
}
break;
@@ -402,7 +402,7 @@ static void
p_str(p)
register struct parse *p;
{
- if(REQUIRE(MORE(), REG_EMPTY));
+ if(REQUIRE(MORE(), REG_EMPTY)) {}
while (MORE())
ordinary(p, GETNEXT());
}
@@ -445,7 +445,7 @@ register int end2; /* second terminating character */
p->g->neol++;
}
- if(REQUIRE(HERE() != start, REG_EMPTY)); /* require nonempty */
+ if(REQUIRE(HERE() != start, REG_EMPTY)) {} /* require nonempty */
}
/*
@@ -470,7 +470,7 @@ int starordinary; /* is a leading * an ordinary character? */
assert(MORE()); /* caller should have ensured this */
c = GETNEXT();
if (c == '\\') {
- if(REQUIRE(MORE(), REG_EESCAPE));
+ if(REQUIRE(MORE(), REG_EESCAPE)) {}
c = BACKSL | (unsigned char)GETNEXT();
}
switch (c) {
@@ -500,7 +500,7 @@ int starordinary; /* is a leading * an ordinary character? */
assert(p->pend[subno] != 0);
}
EMIT(ORPAREN, subno);
- if(REQUIRE(EATTWO('\\', ')'), REG_EPAREN));
+ if(REQUIRE(EATTWO('\\', ')'), REG_EPAREN)) {}
break;
case BACKSL|')': /* should not get here -- must be user */
case BACKSL|'}':
@@ -530,7 +530,7 @@ int starordinary; /* is a leading * an ordinary character? */
p->g->backrefs = 1;
break;
case '*':
- if(REQUIRE(starordinary, REG_BADRPT));
+ if(REQUIRE(starordinary, REG_BADRPT)) {}
/* FALLTHROUGH */
default:
ordinary(p, c &~ BACKSL);
@@ -548,7 +548,7 @@ int starordinary; /* is a leading * an ordinary character? */
if (EAT(',')) {
if (MORE() && isdigit(PEEK())) {
count2 = p_count(p);
- if(REQUIRE(count <= count2, REG_BADBR));
+ if(REQUIRE(count <= count2, REG_BADBR)) {}
} else /* single number with comma */
count2 = RE_INFINITY;
} else /* just a single number */
@@ -557,7 +557,7 @@ int starordinary; /* is a leading * an ordinary character? */
if (!EATTWO('\\', '}')) { /* error heuristics */
while (MORE() && !SEETWO('\\', '}'))
NEXT();
- if(REQUIRE(MORE(), REG_EBRACE));
+ if(REQUIRE(MORE(), REG_EBRACE)) {}
SETERROR(REG_BADBR);
}
} else if (c == (unsigned char)'$') /* $ (but not \$) ends it */
@@ -582,7 +582,7 @@ register struct parse *p;
ndigits++;
}
- if(REQUIRE(ndigits > 0 && count <= DUPMAX, REG_BADBR));
+ if(REQUIRE(ndigits > 0 && count <= DUPMAX, REG_BADBR)) {}
return(count);
}
@@ -622,7 +622,7 @@ register struct parse *p;
p_b_term(p, cs);
if (EAT('-'))
CHadd(cs, '-');
- if(MUSTEAT(']', REG_EBRACK));
+ if(MUSTEAT(']', REG_EBRACK)) {}
if (p->error != 0) /* don't mess things up further */
return;
@@ -693,21 +693,21 @@ register cset *cs;
switch (c) {
case ':': /* character class */
NEXT2();
- if(REQUIRE(MORE(), REG_EBRACK));
+ if(REQUIRE(MORE(), REG_EBRACK)) {}
c = PEEK();
- if(REQUIRE(c != '-' && c != ']', REG_ECTYPE));
+ if(REQUIRE(c != '-' && c != ']', REG_ECTYPE)) {}
p_b_cclass(p, cs);
- if(REQUIRE(MORE(), REG_EBRACK));
- if(REQUIRE(EATTWO(':', ']'), REG_ECTYPE));
+ if(REQUIRE(MORE(), REG_EBRACK)) {}
+ if(REQUIRE(EATTWO(':', ']'), REG_ECTYPE)) {}
break;
case '=': /* equivalence class */
NEXT2();
- if(REQUIRE(MORE(), REG_EBRACK));
+ if(REQUIRE(MORE(), REG_EBRACK)) {}
c = PEEK();
- if(REQUIRE(c != '-' && c != ']', REG_ECOLLATE));
+ if(REQUIRE(c != '-' && c != ']', REG_ECOLLATE)) {}
p_b_eclass(p, cs);
- if(REQUIRE(MORE(), REG_EBRACK));
- if(REQUIRE(EATTWO('=', ']'), REG_ECOLLATE));
+ if(REQUIRE(MORE(), REG_EBRACK)) {}
+ if(REQUIRE(EATTWO('=', ']'), REG_ECOLLATE)) {}
break;
default: /* symbol, ordinary character, or range */
/* xxx revision needed for multichar stuff */
@@ -722,7 +722,7 @@ register cset *cs;
} else
finish = start;
/* xxx what about signed chars here... */
- if(REQUIRE(start <= finish, REG_ERANGE));
+ if(REQUIRE(start <= finish, REG_ERANGE)) {}
for (i = start; i <= finish; i++)
CHadd(cs, i);
break;
@@ -756,10 +756,10 @@ register cset *cs;
return;
}
- u = cp->chars;
+ u = (char*) cp->chars;
while ((c = *u++) != '\0')
CHadd(cs, c);
- for (u = cp->multis; *u != '\0'; u += strlen(u) + 1)
+ for (u = (char*) cp->multis; *u != '\0'; u += strlen(u) + 1)
MCadd(p, cs, u);
}
@@ -790,13 +790,13 @@ register struct parse *p;
{
register char value;
- if(REQUIRE(MORE(), REG_EBRACK));
+ if(REQUIRE(MORE(), REG_EBRACK)) {}
if (!EATTWO('[', '.'))
return(GETNEXT());
/* collating symbol */
value = p_b_coll_elem(p, '.');
- if(REQUIRE(EATTWO('.', ']'), REG_ECOLLATE));
+ if(REQUIRE(EATTWO('.', ']'), REG_ECOLLATE)) {}
return(value);
}
@@ -1189,6 +1189,7 @@ register char *cp;
cs->multis[cs->smultis - 1] = '\0';
}
+#ifdef NOT_USED
/*
- mcsub - subtract a collating element from a cset
== static void mcsub(register cset *cs, register char *cp);
@@ -1246,6 +1247,7 @@ register char *cp;
return(p);
return(NULL);
}
+#endif
/*
- mcinvert - invert the list of collating elements in a cset
@@ -1256,8 +1258,8 @@ register char *cp;
*/
static void
mcinvert(p, cs)
-register struct parse *p;
-register cset *cs;
+ register struct parse *p __attribute__((unused));
+ register cset *cs __attribute__((unused));
{
assert(cs->multis == NULL); /* xxx */
}
@@ -1271,8 +1273,8 @@ register cset *cs;
*/
static void
mccase(p, cs)
-register struct parse *p;
-register cset *cs;
+register struct parse *p __attribute__((unused));
+register cset *cs __attribute__((unused));
{
assert(cs->multis == NULL); /* xxx */
}
diff --git a/regex/regcomp.ih b/regex/regcomp.ih
index 0776e7185cd..4ae45bbf4a9 100644
--- a/regex/regcomp.ih
+++ b/regex/regcomp.ih
@@ -28,9 +28,11 @@ static int freezeset(register struct parse *p, register cset *cs);
static int firstch(register struct parse *p, register cset *cs);
static int nch(register struct parse *p, register cset *cs);
static void mcadd(register struct parse *p, register cset *cs, register char *cp);
+#ifdef NOT_USED
static void mcsub(register cset *cs, register char *cp);
static int mcin(register cset *cs, register char *cp);
static char *mcfind(register cset *cs, register char *cp);
+#endif
static void mcinvert(register struct parse *p, register cset *cs);
static void mccase(register struct parse *p, register cset *cs);
static int isinsets(register struct re_guts *g, int c);
diff --git a/regex/regerror.c b/regex/regerror.c
index a356912564a..0a7b7c8da2c 100644
--- a/regex/regerror.c
+++ b/regex/regerror.c
@@ -1,4 +1,4 @@
-#include <global.h>
+#include <my_global.h>
#include <m_string.h>
#include <m_ctype.h>
#include <regex.h>
@@ -28,8 +28,8 @@
*/
static struct rerr {
int code;
- char *name;
- char *explain;
+ const char *name;
+ const char *explain;
} rerrs[] = {
{REG_NOMATCH, "REG_NOMATCH", "regexec() failed to match"},
{REG_BADPAT, "REG_BADPAT", "invalid regular expression"},
@@ -83,7 +83,7 @@ size_t errbuf_size;
assert(strlen(convbuf) < sizeof(convbuf));
s = convbuf;
} else
- s = r->explain;
+ s = (char*) r->explain;
}
len = strlen(s) + 1;
@@ -113,7 +113,7 @@ char *localbuf;
if (strcmp(r->name, preg->re_endp) == 0)
break;
if (r->code == 0)
- return("0");
+ return((char*) "0");
sprintf(localbuf, "%d", r->code);
return(localbuf);
diff --git a/regex/regexec.c b/regex/regexec.c
index 853bd7aa263..7f2704f8214 100644
--- a/regex/regexec.c
+++ b/regex/regexec.c
@@ -5,7 +5,7 @@
* macros that code uses. This lets the same code operate on two different
* representations for state sets.
*/
-#include <global.h>
+#include <my_global.h>
#include <m_string.h>
#include <m_ctype.h>
#include <regex.h>
diff --git a/regex/regexp.c b/regex/regexp.c
index 706208a6b25..8ddf90f2943 100644
--- a/regex/regexp.c
+++ b/regex/regexp.c
@@ -58,7 +58,7 @@
*/
/* Headers */
-#include "global.h"
+#include "my_global.h"
#include <ctype.h>
#include "regexp.h"
#ifdef __WIN__
diff --git a/regex/regfree.c b/regex/regfree.c
index a0dd8087a45..6ab50735075 100644
--- a/regex/regfree.c
+++ b/regex/regfree.c
@@ -1,4 +1,4 @@
-#include <global.h>
+#include <my_global.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
diff --git a/regex/reginit.c b/regex/reginit.c
index b5815e7d01c..18647c386fc 100644
--- a/regex/reginit.c
+++ b/regex/reginit.c
@@ -1,6 +1,6 @@
/* Init cclasses array from ctypes */
-#include <global.h>
+#include <my_global.h>
#include <m_ctype.h>
#include <m_string.h>
#include "cclass.h"
@@ -63,7 +63,7 @@ void regex_end()
{
int i;
for (i=0; i < CCLASS_LAST ; i++)
- free(cclasses[i].chars);
+ free((char*) cclasses[i].chars);
regex_inited=0;
}
}
diff --git a/regex/split.c b/regex/split.c
index 188bdb775b9..bd2a53c01e3 100644
--- a/regex/split.c
+++ b/regex/split.c
@@ -27,7 +27,7 @@ char *sep; /* "" white, "c" single char, "ab" [ab]+ */
continue;
p--;
trimtrail = 1;
- sep = " \t"; /* note, code below knows this is 2 long */
+ sep = (char*) " \t"; /* note, code below knows this is 2 long */
sepc = ' ';
} else
trimtrail = 0;
diff --git a/scripts/Makefile.am b/scripts/Makefile.am
index 18957b6422d..1c3b8083347 100644
--- a/scripts/Makefile.am
+++ b/scripts/Makefile.am
@@ -20,6 +20,7 @@ bin_SCRIPTS = @server_scripts@ \
msql2mysql \
mysql_config \
mysql_fix_privilege_tables \
+ mysql_fix_extensions \
mysql_setpermission \
mysql_zap \
mysqlaccess \
@@ -28,12 +29,14 @@ bin_SCRIPTS = @server_scripts@ \
mysql_find_rows \
mysqlhotcopy \
mysqldumpslow \
+ mysql_explain_log \
mysqld_multi
EXTRA_SCRIPTS = make_binary_distribution.sh \
msql2mysql.sh \
mysql_config.sh \
mysql_fix_privilege_tables.sh \
+ mysql_fix_extensions.sh \
mysql_install_db.sh \
mysql_setpermission.sh \
mysql_zap.sh \
@@ -43,8 +46,9 @@ EXTRA_SCRIPTS = make_binary_distribution.sh \
mysql_find_rows.sh \
mysqlhotcopy.sh \
mysqldumpslow.sh \
+ mysql_explain_log.sh \
mysqld_multi.sh \
- safe_mysqld.sh
+ mysqld_safe.sh
EXTRA_DIST = $(EXTRA_SCRIPTS) \
mysqlaccess.conf \
@@ -59,6 +63,7 @@ CLEANFILES = @server_scripts@ \
msql2mysql \
mysql_config \
mysql_fix_privilege_tables \
+ mysql_fix_extensions \
mysql_setpermission \
mysql_zap \
mysqlaccess \
@@ -95,6 +100,8 @@ SUFFIXES = .sh
-e 's!@''CXXFLAGS''@!@SAVE_CXXFLAGS@!'\
-e 's!@''LDFLAGS''@!@SAVE_LDFLAGS@!'\
-e 's!@''CLIENT_LIBS''@!@CLIENT_LIBS@!' \
+ -e 's!@''LIBS''@!@LIBS@!' \
+ -e 's!@''innodb_system_libs''@!@innodb_system_libs@!' \
-e 's!@''VERSION''@!@VERSION@!' \
-e 's!@''MYSQL_SERVER_SUFFIX''@!@MYSQL_SERVER_SUFFIX@!' \
-e 's!@''COMPILATION_COMMENT''@!@COMPILATION_COMMENT@!' \
diff --git a/scripts/explain_log.sh b/scripts/explain_log.sh
new file mode 100644
index 00000000000..c4a4ef21568
--- /dev/null
+++ b/scripts/explain_log.sh
@@ -0,0 +1,383 @@
+#!@PERL@ -w
+use strict;
+use DBI;
+
+use Getopt::Long;
+$Getopt::Long::ignorecase=0;
+
+print "explain_log provided by http://www.mobile.de\n";
+print "=========== ================================\n";
+
+my $Param={};
+
+$Param->{host}='';
+$Param->{user}='';
+$Param->{password}='';
+$Param->{PrintError}=0;
+
+if (!GetOptions ('date|d:i' => \$Param->{ViewDate},
+ 'host|h:s' => \$Param->{host},
+ 'user|u:s' => \$Param->{user},
+ 'password|p:s' => \$Param->{password},
+ 'printerror|e:s' => \$Param->{PrintError},
+ )) {
+ ShowOptions();
+}
+else {
+ $Param->{UpdateCount} = 0;
+ $Param->{SelectCount} = 0;
+ $Param->{IdxUseCount} = 0;
+ $Param->{LineCount} = 0;
+
+ $Param->{Init} = 0;
+ $Param->{Field} = 0;
+ $Param->{Refresh} = 0;
+ $Param->{QueryCount} = 0;
+ $Param->{Statistics} =0;
+
+ $Param->{Query} = undef;
+ $Param->{ALL} = undef ;
+ $Param->{Comment} = undef ;
+
+ @{$Param->{Rows}} = (qw|possible_keys key type|);
+
+ if ($Param->{ViewDate}) {
+ $Param->{View} = 0;
+ }
+ else {
+ $Param->{View} = 1;
+ }
+
+ #print "Date=$Param->{ViewDate}, host=$Param->{host}, user=$Param->{user}, password=$Param->{password}\n";
+
+ $Param->{dbh}=DBI->connect("DBI:mysql:host=$Param->{host}",$Param->{user},$Param->{password},{PrintError=>0});
+ if (DBI::err()) {
+ print "Error: " . DBI::errstr() . "\n";
+ }
+ else {
+ $Param->{Start} = time;
+ while(<STDIN>) {
+ $Param->{LineCount} ++ ;
+
+ if ($Param->{ViewDate} ) {
+ if (m/^(\d{6})\s+\d{1,2}:\d\d:\d\d\s.*$/) { # get date
+ #print "# $1 #\n";
+ if ($1 == $Param->{ViewDate}) {
+ $Param->{View} = 1;
+ }
+ else {
+ $Param->{View} = 0;
+ }
+ }
+ }
+ if ($Param->{View} ) {
+ #print "->>>$_";
+
+ if (m/^(\d{6}\s+\d{1,2}:\d\d:\d\d\s+|\s+)(\d+)\s+Connect.+\s+on\s+(.*)$/i) { # get connection ID($2) and database($3)
+ #print "C-$1--$2--$3------\n";
+ RunQuery($Param);
+ if (defined $3) {
+ $Param->{CID}->{$2} = $3 ;
+ #print "DB:$Param->{CID}->{$2} .. $2 .. $3 \n";
+ }
+ }
+
+ elsif (m/^(\d{6}\s+\d{1,2}:\d\d:\d\d\s+|\s+)(\d+)\s+Connect.+$/i) { # get connection ID($2) and database($3)
+ #print "\n <<<<<<<<<<<<<<<<<<----------------------------<<<<<<<<<<<<<<<< \n";
+ #print "Connect \n";
+ RunQuery($Param);
+ }
+ elsif (m/^(\d{6}\s+\d{1,2}:\d\d:\d\d\s+|\s+)(\d+)\s+Change user .*\s+on\s+(.*)$/i) { # get connection ID($2) and database($3)
+ #print "C-$1--$2--$3------\n";
+ RunQuery($Param);
+ if (defined $3) {
+ $Param->{CID}->{$2} = $3 ;
+ #print "DB:$Param->{CID}->{$2} .. $2 .. $3 \n";
+ }
+ }
+
+ elsif (m/^(\d{6}\s+\d{1,2}:\d\d:\d\d\s+|\s+)(\d+)\s+Quit\s+$/i) { # remove connection ID($2) and querystring
+ #print "Q-$1--$2--------\n";
+ RunQuery($Param);
+ delete $Param->{CID}->{$2} ;
+ }
+
+ elsif (m/^(\d{6}\s+\d{1,2}:\d\d:\d\d\s+|\s+)(\d+)\s+Query\s+(select.+)$/i) { # get connection ID($2) and querystring
+ #print "S1-$1--$2--$3------\n";
+ RunQuery($Param);
+ unless ($Param->{CID}->{$2}) {
+ #print "Error: No Database for Handle: $2 found\n";
+ }
+ else {
+ $Param->{DB}=$Param->{CID}->{$2};
+
+ my $s = "$3";
+ $s =~ s/from\s/from $Param->{DB}./i;
+ $Param->{Query}="EXPLAIN $s";
+
+ #$s =~ m/from\s+(\w+[.]\w+)/i;
+ #$Param->{tab} =$1;
+ #print "-- $Param->{tab} -- $s --\n";
+ }
+ }
+
+ elsif (m/^(\d{6}\s+\d{1,2}:\d\d:\d\d\s+|\s+)(\d+)\s+Query\s+(update.+)$/i) { # get connection ID($2) and querystring
+ #print "S2--$1--$2--$3------\n";
+ RunQuery($Param);
+ unless ($Param->{CID}->{$2}) {
+ #print "Error: No Database for Handle: $2 found\n";
+ }
+ else {
+ $Param->{DB}=$Param->{CID}->{$2};
+
+ my $ud = $3;
+ $ud =~ m/^update\s+(\w+).+(where.+)$/i;
+ $Param->{Query} ="EXPLAIN SELECT * FROM $1 $2";
+ $Param->{Query} =~ s/from\s/from $Param->{DB}./i;
+
+ #$Param->{Query} =~ m/from\s+(\w+[.]\w+)/i;
+ #$Param->{tab} =$1;
+ }
+ }
+
+ elsif (m/^(\d{6}\s+\d{1,2}:\d\d:\d\d\s+|\s+)(\d+)\s+Statistics\s+(.*)$/i) { # get connection ID($2) and info?
+ $Param->{Statistics} ++;
+ #print "Statistics--$1--$2--$3------\n";
+ RunQuery($Param);
+ }
+ elsif (m/^(\d{6}\s+\d{1,2}:\d\d:\d\d\s+|\s+)(\d+)\s+Query\s+(.+)$/i) { # get connection ID($2)
+ $Param->{QueryCount} ++;
+ #print "Query-NULL $3\n";
+ RunQuery($Param);
+ }
+ elsif (m/^(\d{6}\s+\d{1,2}:\d\d:\d\d\s+|\s+)(\d+)\s+Refresh\s+(.+)$/i) { # get connection ID($2)
+ $Param->{Refresh} ++;
+ #print "Refresh\n";
+ RunQuery($Param);
+ }
+ elsif (m/^(\d{6}\s+\d{1,2}:\d\d:\d\d\s+|\s+)(\d+)\s+Init\s+(.+)$/i) { # get connection ID($2)
+ $Param->{Init} ++;
+ #print "Init $3\n";
+ RunQuery($Param);
+ }
+ elsif (m/^(\d{6}\s+\d{1,2}:\d\d:\d\d\s+|\s+)(\d+)\s+Field\s+(.+)$/i) { # get connection ID($2)
+ $Param->{Field} ++;
+ #print "Field $3\n";
+ RunQuery($Param);
+ }
+
+ elsif (m/^\s+(.+)$/ ) { # command could be some lines ...
+ #print "multi-lined ($1)\n";
+ my ($A)=$1;
+ chomp $A;
+ $Param->{Query} .= " $1";
+ #print "multi-lined ($1)<<$Param->{Query}>>\n";
+ }
+
+
+ }
+
+ }
+
+ $Param->{dbh}->disconnect();
+
+ if (1 == 0) {
+ print "\nunclosed handles----------------------------------------\n";
+ my $count=0;
+ foreach (sort keys %{$Param->{CID}}) {
+ print "$count | $_ : $Param->{CID}->{$_} \n";
+ $count ++;
+ }
+ }
+
+ print "\nIndex usage ------------------------------------\n";
+ foreach my $t (sort keys %{$Param->{Data}}) {
+ print "\nTable\t$t: ---\n";
+ foreach my $k (sort keys %{$Param->{Data}->{$t}}) {
+ print " count\t$k:\n";
+ my %h = %{$Param->{Data}->{$t}->{$k}};
+ foreach (sort {$h{$a} <=> $h{$b}} keys %h) {
+ print " $Param->{Data}->{$t}->{$k}->{$_}\t$_\n";
+ }
+ }
+ }
+
+ $Param->{AllCount}=0;
+ print "\nQueries causing table scans -------------------\n\n";
+ foreach (@{$Param->{ALL}}) {
+ $Param->{AllCount} ++;
+ print "$_\n";
+ }
+ print "Sum: $Param->{AllCount} table scans\n";
+
+ print "\nSummary ---------------------------------------\n\n";
+ print "Select: \t$Param->{SelectCount} queries\n";
+ print "Update: \t$Param->{UpdateCount} queries\n";
+ print "\n";
+
+ print "Init: \t$Param->{Init} times\n";
+ print "Field: \t$Param->{Field} times\n";
+ print "Refresh: \t$Param->{Refresh} times\n";
+ print "Query: \t$Param->{QueryCount} times\n";
+ print "Statistics:\t$Param->{Statistics} times\n";
+ print "\n";
+
+ print "Logfile: \t$Param->{LineCount} lines\n";
+ print "Started: \t".localtime($Param->{Start})."\n";
+ print "Finished: \t".localtime(time)."\n";
+
+ }
+}
+
+
+###########################################################################
+#
+#
+#
+sub RunQuery {
+ my $Param = shift ;
+
+ if (defined $Param->{Query}) {
+ if (defined $Param->{DB} ) {
+
+ $Param->{Query} =~ m/from\s+(\w+[.]\w+|\w+)/i;
+ $Param->{tab} =$1;
+ #print "||$Param->{tab} -- $Param->{Query}\n";
+
+ my $sth=$Param->{dbh}->prepare("USE $Param->{DB}");
+ if (DBI::err()) {
+ if ($Param->{PrintError}) {print "Error: ".DBI::errstr()."\n";}
+ }
+ else {
+ $sth->execute();
+ if (DBI::err()) {
+ if ($Param->{PrintError}) {print "Error: ".DBI::errstr()."\n";}
+ }
+ else {
+ $sth->finish();
+
+ $sth=$Param->{dbh}->prepare($Param->{Query});
+ if (DBI::err()) {
+ if ($Param->{PrintError}) {print "Error: ".DBI::errstr()."\n";}
+ }
+ else {
+ #print "$Param->{Query}\n";
+ $sth->execute();
+ if (DBI::err()) {
+ if ($Param->{PrintError}) {print "[$Param->{LineCount}]<<$Param->{Query}>>\n";}
+ if ($Param->{PrintError}) {print "Error: ".DBI::errstr()."\n";}
+ }
+ else {
+ my $row = undef;
+ while ($row = $sth->fetchrow_hashref()) {
+ $Param->{SelectCount} ++;
+
+ if (defined $row->{Comment}) {
+ push (@{$Param->{Comment}}, "$row->{Comment}; $_; $Param->{DB}; $Param->{Query}");
+ }
+ foreach (@{$Param->{Rows}}) {
+ if (defined $row->{$_}) {
+ #if (($_ eq 'type' ) and ($row->{$_} eq 'ALL')) {
+ if ($row->{type} eq 'ALL') {
+ push (@{$Param->{ALL}}, "$Param->{Query}");
+ #print ">> $row->{$_} $_ $Param->{DB} $Param->{Query}\n";
+ }
+ $Param->{IdxUseCount} ++;
+ $Param->{Data}->{$Param->{tab}}->{$_}->{$row->{$_}} ++;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ $sth->finish();
+ }
+ $Param->{Query} = undef ;
+ }
+}
+
+###########################################################################
+#
+#
+#
+sub ShowOptions {
+ print <<EOF;
+Usage: $0 [OPTIONS] < LOGFILE
+
+--date=YYMMDD select only entrys of date
+-d=YYMMDD
+--host=HOSTNAME db-host to ask
+-h=HOSTNAME
+--user=USERNAME db-user
+-u=USERNAME
+--password=PASSWORD password of db-user
+-p=PASSWORD
+
+Read logfile from STDIN an try to EXPLAIN all SELECT statements. All UPDATE statements are rewritten to an EXPLAIN SELECT statement. The results of the EXPLAIN statement are collected and counted. All results with type=ALL are collected in an separete list. Results are printed to STDOUT.
+
+EOF
+}
+
+1;
+
+__END__
+
+=pod
+
+=head1 NAME
+
+explain_log.pl
+
+Feed a mysqld general logfile (created with mysqld --log) back into mysql
+and collect statistics about index usage with EXPLAIN.
+
+=head1 DISCUSSION
+
+To optimize your indices, you have to know which ones are actually
+used and what kind of queries are causing table scans. Especially
+if you are generating your queries dynamically and you have a huge
+amount of queries going on, this isn't easy.
+
+Use this tool to take a look at the effects of your real life queries.
+Then add indices to avoid table scans and remove those which aren't used.
+
+=head1 USAGE
+
+explain_log.pl [--date=YYMMDD] --host=dbhost] [--user=dbuser] [--password=dbpw] < logfile
+
+--date=YYMMDD select only entrys of date
+
+-d=YYMMDD
+
+--host=HOSTNAME db-host to ask
+
+-h=HOSTNAME
+
+--user=USERNAME db-user
+
+-u=USERNAME
+
+--password=PASSWORD password of db-user
+
+-p=PASSWORD
+
+=head1 EXAMPLE
+
+explain_log.pl --host=localhost --user=foo --password=bar < /var/lib/mysql/mobile.log
+
+=head1 AUTHOR
+
+ Stefan Nitz
+ Jan Willamowius <jan@mobile.de>, http://www.mobile.de
+
+=head1 RECRUITING
+
+If you are looking for a MySQL or Perl job, take a look at http://www.mobile.de
+and send me an email with your resume (you must be speaking German!).
+
+=head1 SEE ALSO
+
+mysql documentation
+
+=cut
diff --git a/scripts/make_binary_distribution.sh b/scripts/make_binary_distribution.sh
index 99eb9e42967..44dc9d44322 100644
--- a/scripts/make_binary_distribution.sh
+++ b/scripts/make_binary_distribution.sh
@@ -66,9 +66,12 @@ for i in extra/comp_err extra/replace extra/perror extra/resolveip \
myisam/myisampack sql/mysqld client/mysqlbinlog \
client/mysql sql/mysqld client/mysqlshow client/mysqlcheck \
client/mysqladmin client/mysqldump client/mysqlimport client/mysqltest \
+ client/mysqlmanagerc client/mysqlmanager-pwgen tools/mysqlmanager \
client/.libs/mysql client/.libs/mysqlshow client/.libs/mysqladmin \
client/.libs/mysqldump client/.libs/mysqlimport client/.libs/mysqltest \
- client/.libs/mysqlcheck client/.libs/mysqlbinlog
+ client/.libs/mysqlcheck client/.libs/mysqlbinlog \
+ client/.libs/mysqlmanagerc client/.libs/mysqlmanager-pwgen \
+ tools/.libs/mysqlmanager
do
if [ -f $i ]
then
@@ -88,7 +91,7 @@ do
fi
done
-for i in libmysql/.libs/libmysqlclient.a libmysql/.libs/libmysqlclient.so* libmysql/libmysqlclient.* libmysql_r/.libs/libmysqlclient_r.a libmysql_r/.libs/libmysqlclient_r.so* libmysql_r/libmysqlclient_r.* mysys/libmysys.a strings/libmystrings.a dbug/libdbug.a $BASE/lib
+for i in libmysql/.libs/libmysqlclient.a libmysql/.libs/libmysqlclient.so* libmysql/libmysqlclient.* libmysql_r/.libs/libmysqlclient_r.a libmysql_r/.libs/libmysqlclient_r.so* libmysql_r/libmysqlclient_r.* mysys/libmysys.a strings/libmystrings.a dbug/libdbug.a libmysqld/.libs/libmysqld.a libmysqld/.libs/libmysqld.so* libmysqld/libmysqld.a
do
if [ -f $i ]
then
@@ -118,7 +121,7 @@ rm -f $BASE/bin/Makefile* $BASE/bin/*.in $BASE/bin/*.sh $BASE/bin/mysql_install_
$BASE/bin/replace \@localstatedir\@ ./data \@bindir\@ ./bin \@scriptdir\@ ./bin \@libexecdir\@ ./bin \@sbindir\@ ./bin \@prefix\@ . \@HOSTNAME\@ @HOSTNAME@ < $SOURCE/scripts/mysql_install_db.sh > $BASE/scripts/mysql_install_db
$BASE/bin/replace \@prefix\@ /usr/local/mysql \@bindir\@ ./bin \@MYSQLD_USER\@ root \@localstatedir\@ /usr/local/mysql/data < $SOURCE/support-files/mysql.server.sh > $BASE/support-files/mysql.server
-$BASE/bin/replace /my/gnu/bin/hostname /bin/hostname -- $BASE/bin/safe_mysqld
+$BASE/bin/replace /my/gnu/bin/hostname /bin/hostname -- $BASE/bin/mysqld_safe
mv $BASE/support-files/binary-configure $BASE/configure
chmod a+x $BASE/bin/* $BASE/scripts/* $BASE/support-files/mysql-* $BASE/configure
diff --git a/scripts/mysql_config.sh b/scripts/mysql_config.sh
index 9320efdd2a1..6a31db9a2b3 100644
--- a/scripts/mysql_config.sh
+++ b/scripts/mysql_config.sh
@@ -87,16 +87,18 @@ client_libs='@CLIENT_LIBS@'
libs="$ldflags -L'$pkglibdir' -lmysqlclient $client_libs"
libs=`echo $libs | sed -e 's; +;;'`
cflags="-I'$pkgincludedir'"
+embedded_libs="$ldflags -L'$pkglibdir' -lmysqld @LIBS@ @innodb_system_libs@"
usage () {
cat <<EOF
Usage: $0 [OPTIONS]
Options:
- --cflags [$cflags]
- --libs [$libs]
- --socket [$socket]
- --port [$port]
- --version [$version]
+ --cflags [$cflags]
+ --libs [$libs]
+ --socket [$socket]
+ --port [$port]
+ --version [$version]
+ --libmysqld-libs [$embedded_libs]
EOF
exit 1
}
@@ -110,6 +112,7 @@ while test $# -gt 0; do
--socket) echo "$socket" ;;
--port) echo "$port" ;;
--version) echo "$version" ;;
+ --embedded-libs | --embedded | libmysqld-libs) echo "$embedded_libs" ;;
*) usage ;;
esac
diff --git a/scripts/mysql_explain_log.sh b/scripts/mysql_explain_log.sh
new file mode 100644
index 00000000000..d7f6bb97b40
--- /dev/null
+++ b/scripts/mysql_explain_log.sh
@@ -0,0 +1,383 @@
+#!@PERL@ -w
+use strict;
+use DBI;
+
+use Getopt::Long;
+$Getopt::Long::ignorecase=0;
+
+print "explain_log provided by http://www.mobile.de\n";
+print "=========== ================================\n";
+
+my $Param={};
+
+$Param->{host}='';
+$Param->{user}='';
+$Param->{password}='';
+$Param->{PrintError}=0;
+
+if (!GetOptions ('date|d:i' => \$Param->{ViewDate},
+ 'host|h:s' => \$Param->{host},
+ 'user|u:s' => \$Param->{user},
+ 'password|p:s' => \$Param->{password},
+ 'printerror|e:s' => \$Param->{PrintError},
+ )) {
+ ShowOptions();
+}
+else {
+ $Param->{UpdateCount} = 0;
+ $Param->{SelectCount} = 0;
+ $Param->{IdxUseCount} = 0;
+ $Param->{LineCount} = 0;
+
+ $Param->{Init} = 0;
+ $Param->{Field} = 0;
+ $Param->{Refresh} = 0;
+ $Param->{QueryCount} = 0;
+ $Param->{Statistics} =0;
+
+ $Param->{Query} = undef;
+ $Param->{ALL} = undef ;
+ $Param->{Comment} = undef ;
+
+ @{$Param->{Rows}} = (qw|possible_keys key type|);
+
+ if ($Param->{ViewDate}) {
+ $Param->{View} = 0;
+ }
+ else {
+ $Param->{View} = 1;
+ }
+
+ #print "Date=$Param->{ViewDate}, host=$Param->{host}, user=$Param->{user}, password=$Param->{password}\n";
+
+ $Param->{dbh}=DBI->connect("DBI:mysql:host=$Param->{host}",$Param->{user},$Param->{password},{PrintError=>0});
+ if (DBI::err()) {
+ print "Error: " . DBI::errstr() . "\n";
+ }
+ else {
+ $Param->{Start} = time;
+ while(<STDIN>) {
+ $Param->{LineCount} ++ ;
+
+ if ($Param->{ViewDate} ) {
+ if (m/^(\d{6})\s+\d{1,2}:\d\d:\d\d\s.*$/) { # get date
+ #print "# $1 #\n";
+ if ($1 == $Param->{ViewDate}) {
+ $Param->{View} = 1;
+ }
+ else {
+ $Param->{View} = 0;
+ }
+ }
+ }
+ if ($Param->{View} ) {
+ #print "->>>$_";
+
+ if (m/^(\d{6}\s+\d{1,2}:\d\d:\d\d\s+|\s+)(\d+)\s+Connect.+\s+on\s+(.*)$/i) { # get connection ID($2) and database($3)
+ #print "C-$1--$2--$3------\n";
+ RunQuery($Param);
+ if (defined $3) {
+ $Param->{CID}->{$2} = $3 ;
+ #print "DB:$Param->{CID}->{$2} .. $2 .. $3 \n";
+ }
+ }
+
+ elsif (m/^(\d{6}\s+\d{1,2}:\d\d:\d\d\s+|\s+)(\d+)\s+Connect.+$/i) { # get connection ID($2) and database($3)
+ #print "\n <<<<<<<<<<<<<<<<<<----------------------------<<<<<<<<<<<<<<<< \n";
+ #print "Connect \n";
+ RunQuery($Param);
+ }
+ elsif (m/^(\d{6}\s+\d{1,2}:\d\d:\d\d\s+|\s+)(\d+)\s+Change user .*\s+on\s+(.*)$/i) { # get connection ID($2) and database($3)
+ #print "C-$1--$2--$3------\n";
+ RunQuery($Param);
+ if (defined $3) {
+ $Param->{CID}->{$2} = $3 ;
+ #print "DB:$Param->{CID}->{$2} .. $2 .. $3 \n";
+ }
+ }
+
+ elsif (m/^(\d{6}\s+\d{1,2}:\d\d:\d\d\s+|\s+)(\d+)\s+Quit\s+$/i) { # remove connection ID($2) and querystring
+ #print "Q-$1--$2--------\n";
+ RunQuery($Param);
+ delete $Param->{CID}->{$2} ;
+ }
+
+ elsif (m/^(\d{6}\s+\d{1,2}:\d\d:\d\d\s+|\s+)(\d+)\s+Query\s+(select.+)$/i) { # get connection ID($2) and querystring
+ #print "S1-$1--$2--$3------\n";
+ RunQuery($Param);
+ unless ($Param->{CID}->{$2}) {
+ #print "Error: No Database for Handle: $2 found\n";
+ }
+ else {
+ $Param->{DB}=$Param->{CID}->{$2};
+
+ my $s = "$3";
+ $s =~ s/from\s/from $Param->{DB}./i;
+ $Param->{Query}="EXPLAIN $s";
+
+ #$s =~ m/from\s+(\w+[.]\w+)/i;
+ #$Param->{tab} =$1;
+ #print "-- $Param->{tab} -- $s --\n";
+ }
+ }
+
+ elsif (m/^(\d{6}\s+\d{1,2}:\d\d:\d\d\s+|\s+)(\d+)\s+Query\s+(update.+)$/i) { # get connection ID($2) and querystring
+ #print "S2--$1--$2--$3------\n";
+ RunQuery($Param);
+ unless ($Param->{CID}->{$2}) {
+ #print "Error: No Database for Handle: $2 found\n";
+ }
+ else {
+ $Param->{DB}=$Param->{CID}->{$2};
+
+ my $ud = $3;
+ $ud =~ m/^update\s+(\w+).+(where.+)$/i;
+ $Param->{Query} ="EXPLAIN SELECT * FROM $1 $2";
+ $Param->{Query} =~ s/from\s/from $Param->{DB}./i;
+
+ #$Param->{Query} =~ m/from\s+(\w+[.]\w+)/i;
+ #$Param->{tab} =$1;
+ }
+ }
+
+ elsif (m/^(\d{6}\s+\d{1,2}:\d\d:\d\d\s+|\s+)(\d+)\s+Statistics\s+(.*)$/i) { # get connection ID($2) and info?
+ $Param->{Statistics} ++;
+ #print "Statistics--$1--$2--$3------\n";
+ RunQuery($Param);
+ }
+ elsif (m/^(\d{6}\s+\d{1,2}:\d\d:\d\d\s+|\s+)(\d+)\s+Query\s+(.+)$/i) { # get connection ID($2)
+ $Param->{QueryCount} ++;
+ #print "Query-NULL $3\n";
+ RunQuery($Param);
+ }
+ elsif (m/^(\d{6}\s+\d{1,2}:\d\d:\d\d\s+|\s+)(\d+)\s+Refresh\s+(.+)$/i) { # get connection ID($2)
+ $Param->{Refresh} ++;
+ #print "Refresh\n";
+ RunQuery($Param);
+ }
+ elsif (m/^(\d{6}\s+\d{1,2}:\d\d:\d\d\s+|\s+)(\d+)\s+Init\s+(.+)$/i) { # get connection ID($2)
+ $Param->{Init} ++;
+ #print "Init $3\n";
+ RunQuery($Param);
+ }
+ elsif (m/^(\d{6}\s+\d{1,2}:\d\d:\d\d\s+|\s+)(\d+)\s+Field\s+(.+)$/i) { # get connection ID($2)
+ $Param->{Field} ++;
+ #print "Field $3\n";
+ RunQuery($Param);
+ }
+
+ elsif (m/^\s+(.+)$/ ) { # command could be some lines ...
+ #print "multi-lined ($1)\n";
+ my ($A)=$1;
+ chomp $A;
+ $Param->{Query} .= " $1";
+ #print "multi-lined ($1)<<$Param->{Query}>>\n";
+ }
+
+
+ }
+
+ }
+
+ $Param->{dbh}->disconnect();
+
+ if (1 == 0) {
+ print "\nunclosed handles----------------------------------------\n";
+ my $count=0;
+ foreach (sort keys %{$Param->{CID}}) {
+ print "$count | $_ : $Param->{CID}->{$_} \n";
+ $count ++;
+ }
+ }
+
+ print "\nIndex usage ------------------------------------\n";
+ foreach my $t (sort keys %{$Param->{Data}}) {
+ print "\nTable\t$t: ---\n";
+ foreach my $k (sort keys %{$Param->{Data}->{$t}}) {
+ print " count\t$k:\n";
+ my %h = %{$Param->{Data}->{$t}->{$k}};
+ foreach (sort {$h{$a} <=> $h{$b}} keys %h) {
+ print " $Param->{Data}->{$t}->{$k}->{$_}\t$_\n";
+ }
+ }
+ }
+
+ $Param->{AllCount}=0;
+ print "\nQueries causing table scans -------------------\n\n";
+ foreach (@{$Param->{ALL}}) {
+ $Param->{AllCount} ++;
+ print "$_\n";
+ }
+ print "Sum: $Param->{AllCount} table scans\n";
+
+ print "\nSummary ---------------------------------------\n\n";
+ print "Select: \t$Param->{SelectCount} queries\n";
+ print "Update: \t$Param->{UpdateCount} queries\n";
+ print "\n";
+
+ print "Init: \t$Param->{Init} times\n";
+ print "Field: \t$Param->{Field} times\n";
+ print "Refresh: \t$Param->{Refresh} times\n";
+ print "Query: \t$Param->{QueryCount} times\n";
+ print "Statistics:\t$Param->{Statistics} times\n";
+ print "\n";
+
+ print "Logfile: \t$Param->{LineCount} lines\n";
+ print "Started: \t".localtime($Param->{Start})."\n";
+ print "Finished: \t".localtime(time)."\n";
+
+ }
+}
+
+
+###########################################################################
+#
+#
+#
+sub RunQuery {
+ my $Param = shift ;
+
+ if (defined $Param->{Query}) {
+ if (defined $Param->{DB} ) {
+
+ $Param->{Query} =~ m/from\s+(\w+[.]\w+|\w+)/i;
+ $Param->{tab} =$1;
+ #print "||$Param->{tab} -- $Param->{Query}\n";
+
+ my $sth=$Param->{dbh}->prepare("USE $Param->{DB}");
+ if (DBI::err()) {
+ if ($Param->{PrintError}) {print "Error: ".DBI::errstr()."\n";}
+ }
+ else {
+ $sth->execute();
+ if (DBI::err()) {
+ if ($Param->{PrintError}) {print "Error: ".DBI::errstr()."\n";}
+ }
+ else {
+ $sth->finish();
+
+ $sth=$Param->{dbh}->prepare($Param->{Query});
+ if (DBI::err()) {
+ if ($Param->{PrintError}) {print "Error: ".DBI::errstr()."\n";}
+ }
+ else {
+ #print "$Param->{Query}\n";
+ $sth->execute();
+ if (DBI::err()) {
+ if ($Param->{PrintError}) {print "[$Param->{LineCount}]<<$Param->{Query}>>\n";}
+ if ($Param->{PrintError}) {print "Error: ".DBI::errstr()."\n";}
+ }
+ else {
+ my $row = undef;
+ while ($row = $sth->fetchrow_hashref()) {
+ $Param->{SelectCount} ++;
+
+ if (defined $row->{Comment}) {
+ push (@{$Param->{Comment}}, "$row->{Comment}; $_; $Param->{DB}; $Param->{Query}");
+ }
+ foreach (@{$Param->{Rows}}) {
+ if (defined $row->{$_}) {
+ #if (($_ eq 'type' ) and ($row->{$_} eq 'ALL')) {
+ if ($row->{type} eq 'ALL') {
+ push (@{$Param->{ALL}}, "$row->{$_} $_ $Param->{DB} $Param->{Query}");
+ #print ">> $row->{$_} $_ $Param->{DB} $Param->{Query}\n";
+ }
+ $Param->{IdxUseCount} ++;
+ $Param->{Data}->{$Param->{tab}}->{$_}->{$row->{$_}} ++;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ $sth->finish();
+ }
+ $Param->{Query} = undef ;
+ }
+}
+
+###########################################################################
+#
+#
+#
+sub ShowOptions {
+ print <<EOF;
+Usage: $0 [OPTIONS] < LOGFILE
+
+--date=YYMMDD select only entrys of date
+-d=YYMMDD
+--host=HOSTNAME db-host to ask
+-h=HOSTNAME
+--user=USERNAME db-user
+-u=USERNAME
+--password=PASSWORD password of db-user
+-p=PASSWORD
+
+Read logfile from STDIN an try to EXPLAIN all SELECT statements. All UPDATE statements are rewritten to an EXPLAIN SELECT statement. The results of the EXPLAIN statement are collected and counted. All results with type=ALL are collected in an separete list. Results are printed to STDOUT.
+
+EOF
+}
+
+1;
+
+__END__
+
+=pod
+
+=head1 NAME
+
+explain_log.pl
+
+Feed a mysqld general logfile (created with mysqld --log) back into mysql
+and collect statistics about index usage with EXPLAIN.
+
+=head1 DISCUSSION
+
+To optimize your indices, you have to know which ones are actually
+used and what kind of queries are causing table scans. Especially
+if you are generating your queries dynamically and you have a huge
+amount of queries going on, this isn't easy.
+
+Use this tool to take a look at the effects of your real life queries.
+Then add indices to avoid table scans and remove those which aren't used.
+
+=head1 USAGE
+
+explain_log.pl [--date=YYMMDD] --host=dbhost] [--user=dbuser] [--password=dbpw] < logfile
+
+--date=YYMMDD select only entrys of date
+
+-d=YYMMDD
+
+--host=HOSTNAME db-host to ask
+
+-h=HOSTNAME
+
+--user=USERNAME db-user
+
+-u=USERNAME
+
+--password=PASSWORD password of db-user
+
+-p=PASSWORD
+
+=head1 EXAMPLE
+
+explain_log.pl --host=localhost --user=foo --password=bar < /var/lib/mysql/mobile.log
+
+=head1 AUTHOR
+
+ Stefan Nitz
+ Jan Willamowius <jan@mobile.de>, http://www.mobile.de
+
+=head1 RECRUITING
+
+If you are looking for a MySQL or Perl job, take a look at http://www.mobile.de
+and send me an email with your resume (you must be speaking German!).
+
+=head1 SEE ALSO
+
+mysql documentation
+
+=cut
diff --git a/scripts/mysql_fix_extensions.sh b/scripts/mysql_fix_extensions.sh
new file mode 100644
index 00000000000..fbc72406f5e
--- /dev/null
+++ b/scripts/mysql_fix_extensions.sh
@@ -0,0 +1,16 @@
+#!@PERL@
+# This is a utility for MySQL. It is not needed by any standard part
+# of MySQL.
+
+# Usage: mysql_fix_extentions datadir
+# does not work with RAID, with InnoDB or BDB tables
+# makes .frm lowercase and .MYI/MYD/ISM/ISD uppercase
+# useful when datafiles are copied from windows
+
+die "Usage: $0 datadir\n" unless -d $ARGV[0];
+
+for $a (<$ARGV[0]/*/*.*>) { $_=$a;
+ s/\.frm$/.frm/i;
+ s/\.(is[md]|my[id])$/\U$&/i;
+ rename ($a, $_) || warn "Cannot rename $a => $_ : $!";
+}
diff --git a/scripts/mysql_fix_privilege_tables.sh b/scripts/mysql_fix_privilege_tables.sh
index 86312fdab52..7226840b475 100644
--- a/scripts/mysql_fix_privilege_tables.sh
+++ b/scripts/mysql_fix_privilege_tables.sh
@@ -56,6 +56,13 @@ END_OF_DATA
echo ""
fi
+echo "Adding columns needed by GRANT .. REQUIRE (openssl)"
+echo "You can ignore any Duplicate column errors"
+@bindir@/mysql --user=root --password="$root_password" --host="$host" mysql <<END_OF_DATA
+ALTER TABLE user ADD ssl_type enum('NONE','ANY','X509', 'SPECIFIED') DEFAULT 'NONE' NOT NULL, ADD ssl_cipher BLOB NOT NULL, ADD x509_issuer BLOB NOT NULL, ADD x509_subject BLOB NOT NULL
+END_OF_DATA
+echo ""
+
#
# Create tables_priv and columns_priv if they don't exists
#
@@ -96,6 +103,7 @@ echo "You can ignore any errors from this"
@bindir@/mysql -f --user=root --password="$root_password" --host="$host" mysql <<END_OF_DATA
ALTER TABLE columns_priv change Type Column_priv set('Select','Insert','Update','References') DEFAULT '' NOT NULL;
END_OF_DATA
+echo ""
#
# Add the new 'type' column to the func table.
@@ -107,3 +115,14 @@ echo "You can ignore any Duplicate column errors"
@bindir@/mysql --user=root --password=$root_password mysql <<EOF
alter table func add type enum ('function','aggregate') NOT NULL;
EOF
+echo ""
+
+echo "Converting all privilege tables to MyISAM format"
+@bindir@/mysql -f --user=root --password="$root_password" --host="$host" mysql <<END_OF_DATA
+ALTER TABLE user type=MyISAM;
+ALTER TABLE db type=MyISAM;
+ALTER TABLE host type=MyISAM;
+ALTER TABLE func type=MyISAM;
+ALTER TABLE columns_priv type=MyISAM;
+ALTER TABLE tables_priv type=MyISAM;
+END_OF_DATA
diff --git a/scripts/mysql_install_db.sh b/scripts/mysql_install_db.sh
index f7324668bd2..473b182de25 100644
--- a/scripts/mysql_install_db.sh
+++ b/scripts/mysql_install_db.sh
@@ -224,18 +224,25 @@ then
c_u="$c_u References_priv enum('N','Y') DEFAULT 'N' NOT NULL,"
c_u="$c_u Index_priv enum('N','Y') DEFAULT 'N' NOT NULL,"
c_u="$c_u Alter_priv enum('N','Y') DEFAULT 'N' NOT NULL,"
+ c_u="$c_u ssl_type enum('NONE','ANY','X509', 'SPECIFIED') DEFAULT 'NONE' NOT NULL,"
+ c_u="$c_u ssl_cipher BLOB NOT NULL,"
+ c_u="$c_u x509_issuer BLOB NOT NULL,"
+ c_u="$c_u x509_subject BLOB NOT NULL,"
+ c_u="$c_u max_questions int(11) unsigned DEFAULT 0 NOT NULL,"
+ c_u="$c_u max_updates int(11) unsigned DEFAULT 0 NOT NULL,"
+ c_u="$c_u max_connections int(11) unsigned DEFAULT 0 NOT NULL,"
c_u="$c_u PRIMARY KEY Host (Host,User)"
c_u="$c_u )"
c_u="$c_u comment='Users and global privileges';"
- i_u="INSERT INTO user VALUES ('localhost','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y');
- INSERT INTO user VALUES ('$hostname','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y');
+ i_u="INSERT INTO user VALUES ('localhost','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','NONE','','','',0,0,0);
+ INSERT INTO user VALUES ('$hostname','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','NONE','','','',0,0,0);
- REPLACE INTO user VALUES ('localhost','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y');
- REPLACE INTO user VALUES ('$hostname','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y');
+ REPLACE INTO user VALUES ('localhost','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','NONE','','','',0,0,0);
+ REPLACE INTO user VALUES ('$hostname','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','NONE','','','',0,0,0);
- INSERT INTO user VALUES ('localhost','','','N','N','N','N','N','N','N','N','N','N','N','N','N','N');
- INSERT INTO user VALUES ('$hostname','','','N','N','N','N','N','N','N','N','N','N','N','N','N','N');"
+ INSERT INTO user VALUES ('localhost','','','N','N','N','N','N','N','N','N','N','N','N','N','N','N','NONE','','','',0,0,0);
+ INSERT INTO user VALUES ('$hostname','','','N','N','N','N','N','N','N','N','N','N','N','N','N','N','NONE','','','',0,0,0);"
fi
if test ! -f $mdata/func.frm
@@ -290,7 +297,7 @@ fi
echo "Installing all prepared tables"
if eval "$execdir/mysqld $defaults --bootstrap --skip-grant-tables \
- --basedir=$basedir --datadir=$ldata --skip-innodb --skip-gemini --skip-bdb $args" << END_OF_DATA
+ --basedir=$basedir --datadir=$ldata --skip-innodb --skip-bdb $args" << END_OF_DATA
use mysql;
$c_d
$i_d
@@ -317,8 +324,8 @@ then
fi
echo "PLEASE REMEMBER TO SET A PASSWORD FOR THE MySQL root USER !"
echo "This is done with:"
- echo "$bindir/mysqladmin -u root -p password 'new-password'"
- echo "$bindir/mysqladmin -u root -h $hostname -p password 'new-password'"
+ echo "$bindir/mysqladmin -u root password 'new-password'"
+ echo "$bindir/mysqladmin -u root -h $hostname password 'new-password'"
echo "See the manual for more instructions."
#
# Print message about upgrading unless we have created a new db table.
@@ -333,7 +340,7 @@ then
if test "$IN_RPM" -eq 0
then
echo "You can start the MySQL daemon with:"
- echo "cd @prefix@ ; $bindir/safe_mysqld &"
+ echo "cd @prefix@ ; $bindir/mysqld_safe &"
echo
echo "You can test the MySQL daemon with the benchmarks in the 'sql-bench' directory:"
echo "cd sql-bench ; run-all-tests"
diff --git a/scripts/mysql_new_fix_privilege_tables.sh b/scripts/mysql_new_fix_privilege_tables.sh
new file mode 100644
index 00000000000..ce10ed0b412
--- /dev/null
+++ b/scripts/mysql_new_fix_privilege_tables.sh
@@ -0,0 +1,25 @@
+#!/bin/sh
+
+echo "This scripts updates the mysql.user, mysql.db, mysql.host and the"
+echo "mysql.func table to MySQL 3.22.14 and above."
+echo ""
+echo "This is needed if you want to use the new GRANT functions,"
+echo "CREATE AGGREAGATE FUNCTION or want to use the more secure passwords in 3.23"
+echo ""
+echo "If you get Access denied errors, you should run this script again"
+echo "and give the MySQL root user password as a argument!"
+
+root_password="$1"
+host="localhost"
+
+# Fix old password format, add File_priv and func table
+echo ""
+echo "If your tables are already up to date or partially up to date you will"
+echo "get some warnings about 'Duplicated column name'. You can safely ignore these!"
+
+# Add fields that can be used to limit number of questions and connections
+# for some users.
+
+@bindir@/mysql -f --user=root --password="$root_password" --host="$host" mysql <<END_OF_DATA
+alter table user add max_questions int(11) NOT NULL, add max_updates int(11) unsigned NOT NULL, add max_connections int(11) unsigned NOT NULL;
+END_OF_DATA
diff --git a/scripts/mysqld_multi.sh b/scripts/mysqld_multi.sh
index 1adaa458271..656894f0e37 100644
--- a/scripts/mysqld_multi.sh
+++ b/scripts/mysqld_multi.sh
@@ -457,12 +457,12 @@ sub example
# directory, that you have (just change the socket, -S=...)
# See more detailed information from chapter:
# '6 The MySQL Access Privilege System' from the MySQL manual.
-# 2.pid-file is very important, if you are using safe_mysqld to start mysqld
-# (e.g. --mysqld=safe_mysqld) Every mysqld should have it's own pid-file.
-# The advantage using safe_mysqld instead of mysqld directly here is, that
-# safe_mysqld 'guards' every mysqld process and will restart it, if mysqld
+# 2.pid-file is very important, if you are using mysqld_safe to start mysqld
+# (e.g. --mysqld=mysqld_safe) Every mysqld should have it's own pid-file.
+# The advantage using mysqld_safe instead of mysqld directly here is, that
+# mysqld_safe 'guards' every mysqld process and will restart it, if mysqld
# process fails due to signal kill -9, or similar. (Like segmentation fault,
-# which MySQL should never do, of course ;) Please note that safe_mysqld
+# which MySQL should never do, of course ;) Please note that mysqld_safe
# script may require that you start it from a certain place. This means that
# you may have to CD to a certain directory, before you start the
# mysqld_multi. If you have problems starting, please see the script.
@@ -497,7 +497,7 @@ sub example
# give you extra performance in a threaded system!
#
[mysqld_multi]
-mysqld = @bindir@/safe_mysqld
+mysqld = @bindir@/mysqld_safe
mysqladmin = @bindir@/mysqladmin
user = multi_admin
password = multipass
@@ -591,9 +591,9 @@ Options:
Using: $opt_log
--mysqladmin=... mysqladmin binary to be used for a server shutdown.
Using: $mysqladmin
---mysqld=... mysqld binary to be used. Note that you can give safe_mysqld
+--mysqld=... mysqld binary to be used. Note that you can give mysqld_safe
to this option also. The options are passed to mysqld. Just
- make sure you have mysqld in your PATH or fix safe_mysqld.
+ make sure you have mysqld in your PATH or fix mysqld_safe.
Using: $mysqld
--no-log Print to stdout instead of the log file. By default the log
file is turned on.
diff --git a/scripts/safe_mysqld-watch.sh b/scripts/mysqld_safe-watch.sh
index 30f95fd7a86..c59b3b2614d 100644
--- a/scripts/safe_mysqld-watch.sh
+++ b/scripts/mysqld_safe-watch.sh
@@ -8,7 +8,7 @@
# binary installation that has other paths than you are using.
#
# mysql.server works by first doing a cd to the base directory and from there
-# executing safe_mysqld
+# executing mysqld_safe
# Check if we are starting this relative (for the binary release)
if test -f ./data/mysql/db.frm -a -f ./share/mysql/english/errmsg.sys -a \
diff --git a/scripts/safe_mysqld.sh b/scripts/mysqld_safe.sh
index e7418819604..5504d929ede 100644
--- a/scripts/safe_mysqld.sh
+++ b/scripts/mysqld_safe.sh
@@ -8,7 +8,7 @@
# binary installation that has other paths than you are using.
#
# mysql.server works by first doing a cd to the base directory and from there
-# executing safe_mysqld
+# executing mysqld_safe
trap '' 1 2 3 15 # we shouldn't let anyone kill us
@@ -23,32 +23,37 @@ parse_arguments() {
# We only need to pass arguments through to the server if we don't
# handle them here. So, we collect unrecognized options (passed on
# the command line) into the args variable.
- pick_args=$1; shift
+ pick_args=
+ if test "$1" = PICK-ARGS-FROM-ARGV
+ then
+ pick_args=1
+ shift
+ fi
for arg do
case "$arg" in
# these get passed explicitly to mysqld
- --basedir=*) MY_BASEDIR_VERSION=`echo "$arg" | sed -e "s;--[^=]*=;;"` ;;
- --datadir=*) DATADIR=`echo "$arg" | sed -e "s;--[^=]*=;;"` ;;
- --pid-file=*) pid_file=`echo "$arg" | sed -e "s;--[^=]*=;;"` ;;
+ --basedir=*) MY_BASEDIR_VERSION=`echo "$arg" | sed -e "s;--basedir=;;"` ;;
+ --datadir=*) DATADIR=`echo "$arg" | sed -e "s;--datadir=;;"` ;;
+ --pid-file=*) pid_file=`echo "$arg" | sed -e "s;--pid-file=;;"` ;;
--user=*) user=`echo "$arg" | sed -e "s;--[^=]*=;;"` ; SET_USER=1 ;;
- # these two might have been set in a [safe_mysqld] section of my.cnf
- # they get passed via environment variables to safe_mysqld
- --socket=*) MYSQL_UNIX_PORT=`echo "$arg" | sed -e "s;--[^=]*=;;"` ;;
- --port=*) MYSQL_TCP_PORT=`echo "$arg" | sed -e "s;--[^=]*=;;"` ;;
+ # these two might have been set in a [mysqld_safe] section of my.cnf
+ # they get passed via environment variables to mysqld_safe
+ --socket=*) MYSQL_UNIX_PORT=`echo "$arg" | sed -e "s;--socket=;;"` ;;
+ --port=*) MYSQL_TCP_PORT=`echo "$arg" | sed -e "s;--port=;;"` ;;
- # safe_mysqld-specific options
- --ledir=*) ledir=`echo "$arg" | sed -e "s;--[^=]*=;;"` ;;
- --err-log=*) err_log=`echo "$arg" | sed -e "s;--[^=]*=;;"` ;;
+ # mysqld_safe-specific options - must be set in my.cnf ([mysqld_safe])!
+ --ledir=*) ledir=`echo "$arg" | sed -e "s;--ledir=;;"` ;;
+ --err-log=*) err_log=`echo "$arg" | sed -e "s;--err-log=;;"` ;;
# QQ The --open-files should be removed
- --open-files=*) open_files=`echo "$arg" | sed -e "s;--[^=]*=;;"` ;;
- --open-files-limit=*) open_files=`echo "$arg" | sed -e "s;--[^=]*=;;"` ;;
- --core-file-size=*) core_file_size=`echo "$arg" | sed -e "s;--[^=]*=;;"` ;;
- --timezone=*) TZ=`echo "$arg" | sed -e "s;--[^=]*=;;"` ; export TZ; ;;
- --mysqld=*) MYSQLD=`echo "$arg" | sed -e "s;--[^=]*=;;"` ;;
+ --open-files=*) open_files=`echo "$arg" | sed -e "s;--open-files=;;"` ;;
+ --open-files-limit=*) open_files=`echo "$arg" | sed -e "s;--open-files-limit=;;"` ;;
+ --core-file-size=*) core_file_size=`echo "$arg" | sed -e "s;--core_file_size=;;"` ;;
+ --timezone=*) TZ=`echo "$arg" | sed -e "s;--timezone=;;"` ; export TZ; ;;
+ --mysqld=*) MYSQLD=`echo "$arg" | sed -e "s;--mysqld=;;"` ;;
--mysqld-version=*)
- tmp=`echo "$arg" | sed -e "s;--[^=]*=;;"`
+ tmp=`echo "$arg" | sed -e "s;--mysqld-version=;;"`
if test -n "$tmp"
then
MYSQLD="mysqld-$tmp"
@@ -57,7 +62,7 @@ parse_arguments() {
fi
;;
*)
- if test $pick_args -eq 1
+ if test -n "$pick_args"
then
# This sed command makes sure that any special chars are quoted,
# so the arg gets passed exactly to the server.
@@ -110,7 +115,7 @@ pid_file=
err_log=
SET_USER=0
-# Get first arguments from the my.cnf file, groups [mysqld] and [safe_mysqld]
+# Get first arguments from the my.cnf file, groups [mysqld] and [mysqld_safe]
# and then merge with the command line arguments
if test -x ./bin/my_print_defaults
then
@@ -126,15 +131,15 @@ else
fi
args=
-parse_arguments 0 `$print_defaults $defaults mysqld server safe_mysqld`
-parse_arguments 1 "$@"
+parse_arguments `$print_defaults $defaults mysqld server mysqld_safe safe_mysqld`
+parse_arguments PICK-ARGS-FROM-ARGV "$@"
if test ! -x $ledir/$MYSQLD
then
echo "The file $ledir/$MYSQLD doesn't exist or is not executable"
echo "Please do a cd to the mysql installation directory and restart"
echo "this script from there as follows:"
- echo "./bin/safe_mysqld".
+ echo "./bin/mysqld_safe".
exit 1
fi
@@ -154,15 +159,48 @@ export MYSQL_TCP_PORT
NOHUP_NICENESS="nohup"
-if test -w /
+
+# Using nice with no args to get the niceness level is GNU-specific.
+# This check could be extended for other operating systems (e.g.,
+# BSD could use "nohup sh -c 'ps -o nice -p $$' | tail -1").
+# But, it also seems that GNU nohup is the only one which messes
+# with the priority, so this is okay.
+if nohup nice > /dev/null 2>&1
then
- NOHUP_NICENESS=`nohup nice 2>&1`
- if test $? -eq 0 && test x"$NOHUP_NICENESS" != x0 && nice --1 echo foo > /dev/null 2>&1
- then
- NOHUP_NICENESS="nice --$NOHUP_NICENESS nohup"
- else
- NOHUP_NICENESS="nohup"
- fi
+ normal_niceness=`nice`
+ nohup_niceness=`nohup nice`
+
+ numeric_nice_values=1
+ for val in $normal_niceness $nohup_niceness
+ do
+ case "$val" in
+ -[0-9] | -[0-9][0-9] | -[0-9][0-9][0-9] | \
+ [0-9] | [0-9][0-9] | [0-9][0-9][0-9] )
+ ;;
+ * )
+ numeric_nice_values=0 ;;
+ esac
+ done
+
+ if test $numeric_nice_values -eq 1
+ then
+ nice_value_diff=`expr $nohup_niceness - $normal_niceness`
+ if test $? -eq 0 && test $nice_value_diff -gt 0 && \
+ nice --$nice_value_diff echo testing > /dev/null 2>&1
+ then
+ # nohup increases the priority (bad), and we are permitted
+ # to lower the priority
+ NOHUP_NICENESS="nice --$nice_value_diff nohup"
+ fi
+ fi
+else
+ if nohup echo testing > /dev/null 2>&1
+ then
+ :
+ else
+ # nohup doesn't work on this system
+ NOHUP_NICENESS=""
+ fi
fi
USER_OPTION=""
diff --git a/scripts/mysqlhotcopy.sh b/scripts/mysqlhotcopy.sh
index caf2615fe7a..063ff8be750 100644
--- a/scripts/mysqlhotcopy.sh
+++ b/scripts/mysqlhotcopy.sh
@@ -307,7 +307,7 @@ foreach my $rdb ( @db_desc ) {
$rdb->{files} = [ @db_files ];
$rdb->{index} = [ @index_files ];
- my @hc_tables = map { "$db.$_" } @dbh_tables;
+ my @hc_tables = map { "`$db.$_`" } @dbh_tables;
$rdb->{tables} = [ @hc_tables ];
$rdb->{raid_dirs} = [ get_raid_dirs( $rdb->{files} ) ];
diff --git a/sql-bench/Comments/interbase b/sql-bench/Comments/interbase
new file mode 100644
index 00000000000..addaf74b63f
--- /dev/null
+++ b/sql-bench/Comments/interbase
@@ -0,0 +1,18 @@
+Running crash-me on Interbase:
+I
+- got opensource version of interbase 6.0.1
+ (both mode, classic and superserver),
+- set up DBD::InterBase from cpan,
+- created database "test" and set sql_dialect for that database to 3
+- executed crash-me for both interbase's models (classic and superserver).
+
+There were some problems during the execution:
+1) Sometimes client side got SIGSEGV , At that moment server side
+ writes
+ gds__alloc: non-positive size allocation request
+ to log file.
+ This problem has both models. I am not shure if it's interbase or
+ DBD:InterBase problem (though DBD::InterBase made all nesessary
+ tests during the installation without any problem)
+
+2) In "superserver" mode ibserver several times died (and ibguard restarted it)
diff --git a/sql-bench/Makefile.am b/sql-bench/Makefile.am
index 80806f35418..4bfa9868428 100644
--- a/sql-bench/Makefile.am
+++ b/sql-bench/Makefile.am
@@ -21,16 +21,18 @@ benchdir_root= $(prefix)
benchdir = $(benchdir_root)/sql-bench
bench_SCRIPTS = test-ATIS test-connect test-create test-insert \
test-big-tables test-select test-wisconsin \
- test-alter-table graph-compare-results \
+ test-alter-table test-transactions \
+ graph-compare-results \
bench-init.pl compare-results run-all-tests \
- server-cfg crash-me copy-db
+ server-cfg crash-me copy-db bench-count-distinct
CLEANFILES = $(bench_SCRIPTS)
EXTRA_SCRIPTS = test-ATIS.sh test-connect.sh test-create.sh \
test-insert.sh test-big-tables.sh test-select.sh \
test-alter-table.sh test-wisconsin.sh \
+ test-transactions.sh \
bench-init.pl.sh compare-results.sh server-cfg.sh \
run-all-tests.sh crash-me.sh copy-db.sh \
- graph-compare-results.sh
+ bench-count-distinct.sh graph-compare-results.sh
EXTRA_DIST = $(EXTRA_SCRIPTS)
dist-hook:
diff --git a/sql-bench/as3ap.sh b/sql-bench/as3ap.sh
new file mode 100644
index 00000000000..ed796249ebb
--- /dev/null
+++ b/sql-bench/as3ap.sh
@@ -0,0 +1,636 @@
+#!@PERL@
+# Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the Free
+# Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+# MA 02111-1307, USA
+#
+# AS3AP single-user benchmark.
+#
+
+##################### Standard benchmark inits ##############################
+
+use DBI;
+use Benchmark;
+
+chomp($pwd = `pwd`); $pwd = "." if ($pwd eq '');
+require "$pwd/bench-init.pl" || die "Can't read Configuration file: $!\n";
+
+$opt_loop_count=1;
+
+#Create tables
+
+$dbh = $server->connect();
+
+#Create Table
+$sth = $dbh->do("drop table uniques");
+$sth = $dbh->do("drop table updates");
+$sth = $dbh->do("drop table hundred");
+$sth = $dbh->do("drop table tenpct");
+$sth = $dbh->do("drop table tiny");
+
+#Temporary table
+$sth = $dbh->do("drop table saveupdates");
+
+@fields=("col_key int not null",
+ "col_int int not null",
+ "col_signed int not null",
+ "col_float float not null",
+ "col_double float not null",
+ "col_decim numeric(18,2) not null",
+ "col_date char(20) not null",
+ "col_code char(10) not null",
+ "col_name char(20) not null",
+ "col_address varchar(80) not null");
+
+do_many($dbh,$server->create("uniques",\@fields,[]));
+do_many($dbh,$server->create("updates",\@fields,[]));
+do_many($dbh,$server->create("hundred",\@fields,[]));
+do_many($dbh,$server->create("tenpct",\@fields,[]));
+do_many($dbh,$server->create("tiny",["col_key int not null"],[]));
+
+print "Start AS3AP benchmark\n\n";
+
+$start_time=new Benchmark;
+
+print "Load DATA\n";
+#Load DATA
+
+@table_names=("uniques","updates","hundred","tenpct","tiny");
+
+$loop_time=new Benchmark;
+
+if ($opt_fast && $server->{'limits'}->{'load_data_infile'})
+{
+ for ($ti = 0; $ti <= $#table_names; $ti++)
+ {
+ my $table_name = $table_names[$ti];
+ my $file = "$pwd/Data/AS3AP/${table_name}\.new";
+ print "$table_name - $file\n" if ($opt_debug);
+ $row_count += $server->insert_file($table_name,$file,$dbh);
+ }
+}
+else
+{
+ for ($ti = 0; $ti <= $#table_names; $ti++)
+ {
+ my $table_name = $table_names[$ti];
+ print "$table_name - $file\n" if ($opt_debug);
+ my $insert_start = "insert into $table_name values (";
+ open(DATA, "$pwd/Data/AS3AP/${table_name}\.new") || die "Can't open text file: $pwd/Data/AS3AP/${table_name}\.new\n";
+ while(<DATA>)
+ {
+ chomp;
+ next unless ( $_ =~ /\w/ ); # skip blank lines
+ $command = $insert_start."$_".")";
+ $command =~ $server->fix_to_insert($command);
+ print "$command\n" if ($opt_debug);
+ $sth = $dbh->do($command) or die "Got error: $DBI::errstr when executing '$command'\n";
+ $row_count++;
+ }
+ close(DATA);
+ }
+}
+
+$end_time=new Benchmark;
+print "Time for Load Data - " . "($row_count): " .
+timestr(timediff($end_time, $loop_time),"all") . "\n\n";
+
+
+print "Create Index\n";
+
+test_command("create_idx_uniques_key_bt",
+ "time for create_idx_uniques_key_bt",
+ "create unique index uniques_key_bt on uniques (col_key)",$dbh,$opt_loop_count);
+
+test_command("create_idx_updates_key_bt",
+ "time for create_idx_updates_key_bt",
+ "create unique index updates_key_bt on updates (col_key)",$dbh,$opt_loop_count);
+
+test_command("create_idx_hundred_key_bt",
+ "time for create_idx_hundred_key_bt",
+ "create unique index hundred_key_bt on hundred (col_key)",
+ $dbh,$opt_loop_count);
+
+test_command("create_idx_tenpct_key_bt",
+ "time for create_idx_tenpct_key_bt",
+ "create unique index tenpct_key_bt on tenpct (col_key)",$dbh,$opt_loop_count);
+
+test_command("create_idx_tenpct_key_code_bt",
+ "time for create_idx_tenpct_key_code_bt",
+ "create index tenpct_key_code_bt on tenpct (col_key,col_code)",
+ $dbh,$opt_loop_count);
+
+test_command("create_idx_tiny_key_bt",
+ "time for create_idx_tiny_key_bt",
+ "create index tiny_key_bt on tiny (col_key)",$dbh,$opt_loop_count);
+
+test_command("create_idx_tenpct_int_bt",
+ "time for create_idx_tenpct_int_bt",
+ "create index tenpct_int_bt on tenpct (col_int)",$dbh,$opt_loop_count);
+
+test_command("create_idx_tenpct_signed_bt",
+ "time for create_idx_tenpct_signed_bt",
+ "create index tenpct_signed_bt on tenpct (col_signed)",$dbh,$opt_loop_count);
+
+test_command("create_idx_uniques_code_h",
+ "time for create_idx_uniques_code_h",
+ "create index uniques_code_h on uniques (col_code)",$dbh,$opt_loop_count);
+
+test_command("create_idx_tenpct_double_bt",
+ "time for create_idx_tenpct_double_bt",
+ "create index tenpct_double_bt on tenpct (col_double)",$dbh,$opt_loop_count);
+
+
+test_command("create_idx_updates_decim_bt",
+ "time for create_idx_updates_decim_bt",
+ "create index updates_decim_bt on updates (col_decim)",$dbh,$opt_loop_count);
+
+test_command("create_idx_tenpct_float_bt",
+ "time for create_idx_tenpct_float_bt",
+ "create index tenpct_float_bt on tenpct (col_float)",$dbh,$opt_loop_count);
+
+test_command("create_idx_updates_int_bt",
+ "time for create_idx_updates_int_bt",
+ "create index updates_int_bt on updates (col_int)",$dbh,$opt_loop_count);
+
+test_command("create_idx_tenpct_decim_bt",
+ "time for create_idx_tenpct_decim_bt",
+ "create index tenpct_decim_bt on tenpct (col_decim)",$dbh,$opt_loop_count);
+
+test_command("create_idx_hundred_code_h",
+ "time for create_idx_hundred_code_h",
+ "create index hundred_code_h on hundred (col_code)",$dbh,$opt_loop_count);
+
+test_command("create_idx_tenpct_name_h",
+ "time for create_idx_tenpct_name_h",
+ "create index tenpct_name_h on tenpct (col_name)",$dbh,$opt_loop_count);
+
+test_command("create_idx_updates_code_h",
+ "time for create_idx_updates_code_h",
+ "create index updates_code_h on updates (col_code)",$dbh,$opt_loop_count);
+
+test_command("create_idx_tenpct_code_h",
+ "time for create_idx_tenpct_code_h",
+ "create index tenpct_code_h on tenpct (col_code)",$dbh,$opt_loop_count);
+
+test_command("create_idx_updates_double_bt",
+ "time for create_idx_updates_double_bt",
+ "create index updates_double_bt on updates (col_double)",$dbh,$opt_loop_count);
+
+test_command("create_idx_hundred_foreign",
+ "time for create_idx_hundred_foreign",
+ "alter table hundred add constraint fk_hundred_updates foreign key (col_signed)
+ references updates (col_key)",$dbh,$opt_loop_count);
+
+test_query("sel_1_cl",
+ "Time to sel_1_cl",
+ "select col_key, col_int, col_signed, col_code, col_double, col_name
+ from updates where col_key = 1000",$dbh,$opt_loop_count);
+
+test_query("join_3_cl",
+ "Time to join_3_cl",
+ "select uniques.col_signed, uniques.col_date,
+ hundred.col_signed, hundred.col_date,
+ tenpct.col_signed, tenpct.col_date
+ from uniques, hundred, tenpct
+ where uniques.col_key = hundred.col_key
+ and uniques.col_key = tenpct.col_key
+ and uniques.col_key = 1000",$dbh,$opt_loop_count);
+
+test_query("sel_100_ncl",
+ "Time to sel_100_ncl",
+ "select col_key, col_int, col_signed, col_code,col_double, col_name
+ from updates where col_int <= 100",$dbh,$opt_loop_count);
+
+test_query("table_scan",
+ "Time to table_scan",
+ "select * from uniques where col_int = 1",$dbh,$opt_loop_count);
+
+test_query("agg_func",
+ "Time for agg_func",
+ "select min(col_key) from hundred group by col_name",$dbh,$opt_loop_count);
+
+test_query("agg_scal",
+ "Time for agg_scal",
+ "select min(col_key) from uniques",$dbh,$opt_loop_count);
+
+test_query("sel_100_cl",
+ "Time for sel_100_cl",
+ "select col_key, col_int, col_signed, col_code,
+ col_double, col_name
+ from updates where col_key <= 100",$dbh,$opt_loop_count);
+
+test_query("join_3_ncl",
+ "Time for join_3_ncl",
+ "select uniques.col_signed, uniques.col_date,
+ hundred.col_signed, hundred.col_date,
+ tenpct.col_signed, tenpct.col_date
+ from uniques, hundred, tenpct
+ where uniques.col_code = hundred.col_code
+ and uniques.col_code = tenpct.col_code
+ and uniques.col_code = 'BENCHMARKS'",$dbh,$opt_loop_count);
+
+test_query("sel_10pct_ncl",
+ "Time for sel_10pct_ncl",
+ "select col_key, col_int, col_signed, col_code,
+ col_double, col_name
+ from tenpct
+ where col_name = 'THE+ASAP+BENCHMARKS+'",$dbh,$opt_loop_count);
+
+if ($limits->{'subqueries'}){
+ test_query("agg_simple_report",
+ "Time for agg_simple_report",
+ "select avg(updates.col_decim)
+ from updates
+ where updates.col_key in
+ (select updates.col_key
+ from updates, hundred
+ where hundred.col_key = updates.col_key
+ and updates.col_decim > 980000000)",$dbh,$opt_loop_count);
+}else{
+ print "agg_simple_report - Failed\n\n";
+}
+
+test_query("agg_info_retrieval",
+ "Time for agg_info_retrieval",
+ "select count(col_key)
+ from tenpct
+ where col_name = 'THE+ASAP+BENCHMARKS'
+ and col_int <= 100000000
+ and col_signed between 1 and 99999999
+ and not (col_float between -450000000 and 450000000)
+ and col_double > 600000000
+ and col_decim < -600000000",$dbh,$opt_loop_count);
+
+if ($limits->{'views'}){
+ test_query("agg_create_view",
+ "Time for agg_create_view",
+ "create view
+ reportview(col_key,col_signed,col_date,col_decim,
+ col_name,col_code,col_int) as
+ select updates.col_key, updates.col_signed,
+ updates.col_date, updates.col_decim,
+ hundred.col_name, hundred.col_code,
+ hundred.col_int
+ from updates, hundred
+ where updates.col_key = hundred.col_key",$dbh,$opt_loop_count);
+
+ test_query("agg_subtotal_report",
+ "Time for agg_subtotal_report",
+ "select avg(col_signed), min(col_signed), max(col_signed),
+ max(col_date), min(col_date),
+ count(distinct col_name), count(col_name),
+ col_code, col_int
+ from reportview
+ where col_decim >980000000
+ group by col_code, col_int",$dbh,$opt_loop_count);
+
+
+ test_query("agg_total_report",
+ "Time for agg_total_report",
+ "select avg(col_signed), min(col_signed), max(col_signed),
+ max(col_date), min(col_date),
+ count(distinct col_name), count(col_name),
+ count(col_code), count(col_int)
+ from reportview
+ where col_decim >980000000",$dbh,$opt_loop_count);
+}else{
+ print "agg_create_view - Failed\n\n";
+ print "agg_subtotal_report - Failed\n\n";
+ print "agg_total_report - Failed\n\n";
+}
+
+#fix from here
+test_query("join_2_cl",
+ "Time for join_2_cl",
+ "select uniques.col_signed, uniques.col_name,
+ hundred.col_signed, hundred.col_name
+ from uniques, hundred
+ where uniques.col_key = hundred.col_key
+ and uniques.col_key =1000"
+ ,$dbh,$opt_loop_count);
+
+test_query("join_2",
+ "Time for join_2",
+ "select uniques.col_signed, uniques.col_name,
+ hundred.col_signed, hundred.col_name
+ from uniques, hundred
+ where uniques.col_address = hundred.col_address
+ and uniques.col_address = 'SILICON VALLEY'"
+ ,$dbh,$opt_loop_count);
+
+test_query("sel_variable_select_low",
+ "Time for sel_variable_select_low",
+ "select col_key, col_int, col_signed, col_code,
+ col_double, col_name
+ from tenpct
+ where col_signed < -500000000"
+ ,$dbh,$opt_loop_count);
+
+test_query("sel_variable_select_high",
+ "Time for sel_variable_select_high",
+ "select col_key, col_int, col_signed, col_code,
+ col_double, col_name
+ from tenpct
+ where col_signed < -250000000"
+ ,$dbh,$opt_loop_count);
+
+test_query("join_4_cl",
+ "Time for join_4_cl",
+ "select uniques.col_date, hundred.col_date,
+ tenpct.col_date, updates.col_date
+ from uniques, hundred, tenpct, updates
+ where uniques.col_key = hundred.col_key
+ and uniques.col_key = tenpct.col_key
+ and uniques.col_key = updates.col_key
+ and uniques.col_key = 1000"
+ ,$dbh,$opt_loop_count);
+
+test_query("proj_100",
+ "Time for proj_100",
+ "select distinct col_address, col_signed from hundred"
+ ,$dbh,$opt_loop_count);
+
+test_query("join_4_ncl",
+ "Time for join_4_ncl",
+ "select uniques.col_date, hundred.col_date,
+ tenpct.col_date, updates.col_date
+ from uniques, hundred, tenpct, updates
+ where uniques.col_code = hundred.col_code
+ and uniques.col_code = tenpct.col_code
+ and uniques.col_code = updates.col_code
+ and uniques.col_code = 'BENCHMARKS'"
+ ,$dbh,$opt_loop_count);
+
+test_query("proj_10pct",
+ "Time for proj_10pct",
+ "select distinct col_signed from tenpct"
+ ,$dbh,$opt_loop_count);
+
+test_query("sel_1_ncl",
+ "Time for sel_1_ncl",
+ "select col_key, col_int, col_signed, col_code,
+ col_double, col_name
+ from updates where col_code = 'BENCHMARKS'"
+ ,$dbh,$opt_loop_count);
+
+test_query("join_2_ncl",
+ "Time for join_2_ncl",
+ "select uniques.col_signed, uniques.col_name,
+ hundred.col_signed, hundred.col_name
+ from uniques, hundred
+ where uniques.col_code = hundred.col_code
+ and uniques.col_code = 'BENCHMARKS'"
+ ,$dbh,$opt_loop_count);
+
+if ($limits->{'foreign_key'}){
+ do_many($dbh,$server->create("integrity_temp",\@fields,[]));
+
+ test_query("integrity_test_1",
+ "Time for integrity_test",
+ "insert into integrity_temp select *
+ from hundred where col_int=0",$dbh,$opt_loop_count);
+
+ test_query("integrity_test_2",
+ "Time for integrity_test",
+ "update hundred set col_signed = '-500000000'
+ where col_int = 0",$dbh,$opt_loop_count);
+
+ test_query("integrity_test_3",
+ "Time for integrity_test",
+ "update hundred set col_signed = '-500000000'
+ where col_int = 0",$dbh,$opt_loop_count);
+
+
+}else{
+ print "integrity_test - Failed\n\n";
+}
+
+push @drop_seq_command,$server->drop_index("updates","updates_int_bt");
+push @drop_seq_command,$server->drop_index("updates","updates_double_bt");
+push @drop_seq_command,$server->drop_index("updates","updates_decim_bt");
+push @drop_seq_command,$server->drop_index("updates","updates_code_h");
+
+test_many_command("Drop updates keys",
+ "Time for drop_updates_keys",
+ \@drop_seq_command,$dbh,$opt_loop_count);
+
+do_many($dbh,$server->create("saveupdates",\@fields,[]));
+
+test_command("bulk_save",
+ "Time for bulk_save",
+ "insert into saveupdates select *
+ from updates where col_key between 5000 and 5999"
+ ,$dbh,$opt_loop_count);
+
+test_command("bulk_modify",
+ "Time for bulk_modify",
+ "update updates
+ set col_key = col_key - 100000
+ where col_key between 5000 and 5999"
+ ,$dbh,$opt_loop_count);
+
+safe_command("upd_append_duplicate",
+ "Time for upd_append_duplicate",
+ "insert into updates
+ values (6000, 0, 60000, 39997.90,
+ 50005.00, 50005.00,
+ '11/10/1985', 'CONTROLLER',
+ 'ALICE IN WONDERLAND',
+ 'UNIVERSITY OF ILLINOIS AT CHICAGO')"
+ ,$dbh,$opt_loop_count);
+
+test_command("upd_remove_duplicate",
+ "Time for upd_remove_duplicate",
+ "delete from updates where col_key = 6000 and col_int = 0"
+ ,$dbh,$opt_loop_count);
+
+test_command("upd_app_t_mid",
+ "Time for upd_app_t_mid",
+ "insert into updates
+ values (5005, 5005, 50005, 50005.00, 50005.00,
+ 50005.00, '1/1/1988', 'CONTROLLER',
+ 'ALICE IN WONDERLAND',
+ 'UNIVERSITY OF ILLINOIS AT CHICAGO')"
+ ,$dbh,$opt_loop_count);
+
+test_command("upd_mod_t_mid",
+ "Time for upd_mod_t_mid",
+ "update updates set col_key = '-5000'
+ where col_key = 5005"
+ ,$dbh,$opt_loop_count);
+
+test_command("upd_del_t_mid",
+ "Time for upd_del_t_mid",
+ "delete from updates
+ where (col_key='5005') or (col_key='-5000')"
+ ,$dbh,$opt_loop_count);
+
+test_command("upd_app_t_end",
+ "Time for upd_app_t_end",
+ "delete from updates
+ where (col_key='5005') or (col_key='-5000')"
+ ,$dbh,$opt_loop_count);
+
+test_command("upd_mod_t_end",
+ "Time for upd_mod_t_end",
+ "update updates
+ set col_key = -1000
+ where col_key = 1000000001"
+ ,$dbh,$opt_loop_count);
+
+test_command("upd_del_t_end",
+ "Time for upd_del_t_end",
+ "delete from updates where col_key = -1000"
+ ,$dbh,$opt_loop_count);
+
+test_command("create_idx_updates_code_h",
+ "time for create_idx_updates_code_h",
+ "create index updates_code_h on updates (col_code)",
+ $dbh,$opt_loop_count);
+
+test_command("upd_app_t_mid",
+ "Time for upd_app_t_mid",
+ "insert into updates
+ values (5005, 5005, 50005, 50005.00, 50005.00,
+ 50005.00, '1/1/1988', 'CONTROLLER',
+ 'ALICE IN WONDERLAND',
+ 'UNIVERSITY OF ILLINOIS AT CHICAGO')"
+ ,$dbh,$opt_loop_count);
+
+test_command("upd_mod_t_cod",
+ "Time for upd_mod_t_cod",
+ "update updates
+ set col_code = 'SQL+GROUPS'
+ where col_key = 5005"
+ ,$dbh,$opt_loop_count);
+
+test_command("upd_del_t_mid",
+ "Time for upd_del_t_mid",
+ "delete from updates
+ where (col_key='5005') or (col_key='-5000')"
+ ,$dbh,$opt_loop_count);
+
+test_command("create_idx_updates_int_bt",
+ "time for create_idx_updates_int_bt",
+ "create index updates_int_bt on updates (col_int)",
+ $dbh,$opt_loop_count);
+
+test_command("upd_app_t_mid",
+ "Time for upd_app_t_mid",
+ "insert into updates
+ values (5005, 5005, 50005, 50005.00, 50005.00,
+ 50005.00, '1/1/1988', 'CONTROLLER',
+ 'ALICE IN WONDERLAND',
+ 'UNIVERSITY OF ILLINOIS AT CHICAGO')"
+ ,$dbh,$opt_loop_count);
+
+test_command("upd_mod_t_int",
+ "Time for upd_mod_t_int",
+ "update updates set col_int = 50015 where col_key = 5005"
+ ,$dbh,$opt_loop_count);
+
+test_command("upd_del_t_mid",
+ "Time for upd_del_t_mid",
+ "delete from updates
+ where (col_key='5005') or (col_key='-5000')"
+ ,$dbh,$opt_loop_count);
+
+test_command("bulk_append",
+ "Time for bulk_append",
+ "insert into updates select * from saveupdates"
+ ,$dbh,$opt_loop_count);
+
+test_command("bulk_delete",
+ "Time for bulk_delete",
+ "delete from updates where col_key < 0"
+ ,$dbh,$opt_loop_count);
+
+################################ END ###################################
+####
+#### End of the test...Finally print time used to execute the
+#### whole test.
+
+$dbh->disconnect;
+
+end_benchmark($start_time);
+
+############################ HELP FUNCTIONS ##############################
+
+sub test_query
+{
+ my($test_text,$result_text,$query,$dbh,$count)=@_;
+ my($i,$loop_time,$end_time);
+
+ print $test_text . "\n";
+ $loop_time=new Benchmark;
+ for ($i=0 ; $i < $count ; $i++)
+ {
+ defined(fetch_all_rows($dbh,$query)) or warn $DBI::errstr;
+ }
+ $end_time=new Benchmark;
+ print $result_text . "($count): " .
+ timestr(timediff($end_time, $loop_time),"all") . "\n\n";
+}
+
+
+sub test_command
+{
+ my($test_text,$result_text,$query,$dbh,$count)=@_;
+ my($i,$loop_time,$end_time);
+
+ print $test_text . "\n";
+ $loop_time=new Benchmark;
+ for ($i=0 ; $i < $count ; $i++)
+ {
+ $dbh->do($query) or die $DBI::errstr;
+ }
+ $end_time=new Benchmark;
+ print $result_text . "($count): " .
+ timestr(timediff($end_time, $loop_time),"all") . "\n\n";
+}
+
+sub safe_command
+{
+ my($test_text,$result_text,$query,$dbh,$count)=@_;
+ my($i,$loop_time,$end_time);
+
+ print $test_text . "\n";
+ $loop_time=new Benchmark;
+ for ($i=0 ; $i < $count ; $i++)
+ {
+ safe_do_many($dbh,$query);
+ }
+ $end_time=new Benchmark;
+ print $result_text . "($count): " .
+ timestr(timediff($end_time, $loop_time),"all") . "\n\n";
+}
+
+sub test_many_command
+{
+ my($test_text,$result_text,$query,$dbh,$count)=@_;
+ my($i,$loop_time,$end_time);
+
+ $loop_time=new Benchmark;
+ for ($i=0 ; $i < $count ; $i++)
+ {
+ safe_do_many($dbh, @$query);
+ }
+ $end_time=new Benchmark;
+ print $result_text . "($count): " .
+ timestr(timediff($end_time, $loop_time),"all") . "\n\n";
+}
+
+
diff --git a/sql-bench/bench-count-distinct.sh b/sql-bench/bench-count-distinct.sh
new file mode 100644
index 00000000000..1359a864ac1
--- /dev/null
+++ b/sql-bench/bench-count-distinct.sh
@@ -0,0 +1,258 @@
+#!@PERL@
+# Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the Free
+# Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+# MA 02111-1307, USA
+#
+# Test of selecting on keys that consist of many parts
+#
+##################### Standard benchmark inits ##############################
+
+use DBI;
+use Getopt::Long;
+use Benchmark;
+
+$opt_loop_count=10000;
+$opt_medium_loop_count=200;
+$opt_small_loop_count=10;
+$opt_regions=6;
+$opt_groups=100;
+
+chomp($pwd = `pwd`); $pwd = "." if ($pwd eq '');
+require "$pwd/bench-init.pl" || die "Can't read Configuration file: $!\n";
+
+$columns=min($limits->{'max_columns'},500,($limits->{'query_size'}-50)/24,
+ $limits->{'max_conditions'}/2-3);
+
+if ($opt_small_test)
+{
+ $opt_loop_count/=10;
+ $opt_medium_loop_count/=10;
+ $opt_small_loop_count/=10;
+ $opt_groups/=10;
+}
+
+print "Testing the speed of selecting on keys that consist of many parts\n";
+print "The test-table has $opt_loop_count rows and the test is done with $columns ranges.\n\n";
+
+####
+#### Connect and start timeing
+####
+
+$dbh = $server->connect();
+$start_time=new Benchmark;
+
+####
+#### Create needed tables
+####
+
+goto select_test if ($opt_skip_create);
+
+print "Creating table\n";
+$dbh->do("drop table bench1" . $server->{'drop_attr'});
+
+do_many($dbh,$server->create("bench1",
+ ["region char(1) NOT NULL",
+ "idn integer(6) NOT NULL",
+ "rev_idn integer(6) NOT NULL",
+ "grp integer(6) NOT NULL"],
+ ["primary key (region,idn)",
+ "unique (region,rev_idn)",
+ "unique (region,grp,idn)"]));
+if ($opt_lock_tables)
+{
+ do_query($dbh,"LOCK TABLES bench1 WRITE");
+}
+
+if ($opt_fast && defined($server->{vacuum}))
+{
+ $server->vacuum(1,\$dbh);
+}
+
+####
+#### Insert $opt_loop_count records with
+#### region: "A" -> "E"
+#### idn: 0 -> count
+#### rev_idn: count -> 0,
+#### grp: distributed values 0 - > count/100
+####
+
+print "Inserting $opt_loop_count rows\n";
+
+$loop_time=new Benchmark;
+$query="insert into bench1 values (";
+$half_done=$opt_loop_count/2;
+for ($id=0,$rev_id=$opt_loop_count-1 ; $id < $opt_loop_count ; $id++,$rev_id--)
+{
+ $grp=$id*3 % $opt_groups;
+ $region=chr(65+$id%$opt_regions);
+ do_query($dbh,"$query'$region',$id,$rev_id,$grp)");
+ if ($id == $half_done)
+ { # Test with different insert
+ $query="insert into bench1 (region,idn,rev_idn,grp) values (";
+ }
+}
+
+$end_time=new Benchmark;
+print "Time to insert ($opt_loop_count): " .
+ timestr(timediff($end_time, $loop_time),"all") . "\n\n";
+
+if ($opt_lock_tables)
+{
+ do_query($dbh,"UNLOCK TABLES");
+}
+
+if ($opt_fast && defined($server->{vacuum}))
+{
+ $server->vacuum(0,\$dbh,"bench1");
+}
+
+if ($opt_lock_tables)
+{
+ do_query($dbh,"LOCK TABLES bench1 WRITE");
+}
+
+####
+#### Do some selects on the table
+####
+
+select_test:
+
+
+
+if ($limits->{'group_distinct_functions'})
+{
+ print "Testing count(distinct) on the table\n";
+ $loop_time=new Benchmark;
+ $rows=$estimated=$count=0;
+ for ($i=0 ; $i < $opt_medium_loop_count ; $i++)
+ {
+ $count++;
+ $rows+=fetch_all_rows($dbh,"select count(distinct region) from bench1");
+ $end_time=new Benchmark;
+ last if ($estimated=predict_query_time($loop_time,$end_time,\$count,$i+1,
+ $opt_medium_loop_count));
+ }
+ print_time($estimated);
+ print " for count_distinct_key_prefix ($count:$rows): " .
+ timestr(timediff($end_time, $loop_time),"all") . "\n";
+
+ $loop_time=new Benchmark;
+ $rows=$estimated=$count=0;
+ for ($i=0 ; $i < $opt_medium_loop_count ; $i++)
+ {
+ $count++;
+ $rows+=fetch_all_rows($dbh,"select count(distinct grp) from bench1");
+ $end_time=new Benchmark;
+ last if ($estimated=predict_query_time($loop_time,$end_time,\$count,$i+1,
+ $opt_medium_loop_count));
+ }
+ print_time($estimated);
+ print " for count_distinct ($count:$rows): " .
+ timestr(timediff($end_time, $loop_time),"all") . "\n";
+
+ $loop_time=new Benchmark;
+ $rows=$estimated=$count=0;
+ for ($i=0 ; $i < $opt_medium_loop_count ; $i++)
+ {
+ $count++;
+ $rows+=fetch_all_rows($dbh,"select count(distinct grp),count(distinct rev_idn) from bench1");
+ $end_time=new Benchmark;
+ last if ($estimated=predict_query_time($loop_time,$end_time,\$count,$i+1,
+ $opt_medium_loop_count));
+ }
+ print_time($estimated);
+ print " for count_distinct_2 ($count:$rows): " .
+ timestr(timediff($end_time, $loop_time),"all") . "\n";
+
+ $loop_time=new Benchmark;
+ $rows=$estimated=$count=0;
+ for ($i=0 ; $i < $opt_medium_loop_count ; $i++)
+ {
+ $count++;
+ $rows+=fetch_all_rows($dbh,"select region,count(distinct idn) from bench1 group by region");
+ $end_time=new Benchmark;
+ last if ($estimated=predict_query_time($loop_time,$end_time,\$count,$i+1,
+ $opt_medium_loop_count));
+ }
+ print_time($estimated);
+ print " for count_distinct_group_on_key ($count:$rows): " .
+ timestr(timediff($end_time, $loop_time),"all") . "\n";
+
+ $loop_time=new Benchmark;
+ $rows=$estimated=$count=0;
+ for ($i=0 ; $i < $opt_medium_loop_count ; $i++)
+ {
+ $count++;
+ $rows+=fetch_all_rows($dbh,"select grp,count(distinct idn) from bench1 group by grp");
+ $end_time=new Benchmark;
+ last if ($estimated=predict_query_time($loop_time,$end_time,\$count,$i+1,
+ $opt_medium_loop_count));
+ }
+ print_time($estimated);
+ print " for count_distinct_group_on_key_parts ($count:$rows): " .
+ timestr(timediff($end_time, $loop_time),"all") . "\n";
+
+ $loop_time=new Benchmark;
+ $rows=$estimated=$count=0;
+ for ($i=0 ; $i < $opt_medium_loop_count ; $i++)
+ {
+ $count++;
+ $rows+=fetch_all_rows($dbh,"select grp,count(distinct rev_idn) from bench1 group by grp");
+ $end_time=new Benchmark;
+ last if ($estimated=predict_query_time($loop_time,$end_time,\$count,$i+1,
+ $opt_medium_loop_count));
+ }
+ print_time($estimated);
+ print " for count_distinct_group ($count:$rows): " .
+ timestr(timediff($end_time, $loop_time),"all") . "\n";
+
+ $loop_time=new Benchmark;
+ $rows=$estimated=$count=0;
+ $test_count=$opt_medium_loop_count/10;
+ for ($i=0 ; $i < $test_count ; $i++)
+ {
+ $count++;
+ $rows+=fetch_all_rows($dbh,"select idn,count(distinct region) from bench1 group by idn");
+ $end_time=new Benchmark;
+ last if ($estimated=predict_query_time($loop_time,$end_time,\$count,$i+1,
+ $test_count));
+ }
+ print_time($estimated);
+ print " for count_distinct_big ($count:$rows): " .
+ timestr(timediff($end_time, $loop_time),"all") . "\n";
+}
+
+####
+#### End of benchmark
+####
+
+if ($opt_lock_tables)
+{
+ do_query($dbh,"UNLOCK TABLES");
+}
+if (!$opt_skip_delete)
+{
+ do_query($dbh,"drop table bench1" . $server->{'drop_attr'});
+}
+
+if ($opt_fast && defined($server->{vacuum}))
+{
+ $server->vacuum(0,\$dbh);
+}
+
+$dbh->disconnect; # close connection
+
+end_benchmark($start_time);
diff --git a/sql-bench/bench-init.pl.sh b/sql-bench/bench-init.pl.sh
index 204d15d7ab3..4e7e1c29504 100644
--- a/sql-bench/bench-init.pl.sh
+++ b/sql-bench/bench-init.pl.sh
@@ -38,24 +38,28 @@ require "$pwd/server-cfg" || die "Can't read Configuration file: $!\n";
$|=1; # Output data immediately
-$opt_skip_test=$opt_skip_create=$opt_skip_delete=$opt_verbose=$opt_fast_insert=$opt_lock_tables=$opt_debug=$opt_skip_delete=$opt_fast=$opt_force=$opt_log=$opt_use_old_results=$opt_help=$opt_odbc=$opt_small_test=$opt_small_tables=$opt_samll_key_tables=$opt_stage=$opt_old_headers=$opt_die_on_errors=$opt_tcpip=0;
+$opt_skip_test=$opt_skip_create=$opt_skip_delete=$opt_verbose=$opt_fast_insert=$opt_lock_tables=$opt_debug=$opt_skip_delete=$opt_fast=$opt_force=$opt_log=$opt_use_old_results=$opt_help=$opt_odbc=$opt_small_test=$opt_small_tables=$opt_samll_key_tables=$opt_stage=$opt_old_headers=$opt_die_on_errors=$opt_tcpip=$opt_random=0;
$opt_cmp=$opt_user=$opt_password="";
$opt_server="mysql"; $opt_dir="output";
$opt_host="localhost";$opt_database="test";
$opt_machine=""; $opt_suffix="";
$opt_create_options=undef;
+$opt_optimization="None";
+$opt_hw="";
+$opt_threads=5;
$opt_time_limit=10*60; # Don't wait more than 10 min for some tests
$log_prog_args=join(" ", skip_arguments(\@ARGV,"comments","cmp","server",
"user", "host", "database", "password",
"use-old-results","skip-test",
+ "optimization","hw",
"machine", "dir", "suffix", "log"));
-GetOptions("skip-test=s","comments=s","cmp=s","server=s","user=s","host=s","database=s","password=s","loop-count=i","row-count=i","skip-create","skip-delete","verbose","fast-insert","lock-tables","debug","fast","force","field-count=i","regions=i","groups=i","time-limit=i","log","use-old-results","machine=s","dir=s","suffix=s","help","odbc","small-test","small-tables","small-key-tables","stage=i","old-headers","die-on-errors","create-options=s","hires","tcpip","silent") || usage();
+GetOptions("skip-test=s","comments=s","cmp=s","server=s","user=s","host=s","database=s","password=s","loop-count=i","row-count=i","skip-create","skip-delete","verbose","fast-insert","lock-tables","debug","fast","force","field-count=i","regions=i","groups=i","time-limit=i","log","use-old-results","machine=s","dir=s","suffix=s","help","odbc","small-test","small-tables","small-key-tables","stage=i","threads=i","random","old-headers","die-on-errors","create-options=s","hires","tcpip","silent","optimization=s","hw=s","socket=s") || usage();
usage() if ($opt_help);
$server=get_server($opt_server,$opt_host,$opt_database,$opt_odbc,
- machine_part());
+ machine_part(), $opt_socket);
$limits=merge_limits($server,$opt_cmp);
$date=date();
@estimated=(0.0,0.0,0.0); # For estimated time support
@@ -515,6 +519,10 @@ All benchmarks takes the following options:
--password='password'
Password for the current user.
+--socket='socket'
+ If the database supports connecting through a Unix socket,
+ use this socket to connect
+
--regions
This is a test specific option that is only used when debugging a test.
This usually means how AND levels should be tested.
@@ -553,6 +561,13 @@ All benchmarks takes the following options:
different server options without overwritten old files.
When using --fast the suffix is automaticly set to '_fast'.
+--random
+ Inform test suite that we are generate random inital values for sequence of
+ test executions. It should be used for imitation of real conditions.
+
+--threads=# (Default 5)
+ Number of threads for multi-user benchmarks.
+
--tcpip
Inform test suite that we are using TCP/IP to connect to the server. In
this case we can\t do many new connections in a row as we in this case may
@@ -572,6 +587,13 @@ All benchmarks takes the following options:
--verbose
This is a test specific option that is only used when debugging a test.
Print more information about what is going on.
+
+--optimization='some comments'
+ Add coments about optimization of DBMS, which was done before the test.
+
+--hw='some comments'
+ Add coments about hardware used for this test.
+
EOF
exit(0);
}
diff --git a/sql-bench/crash-me.sh b/sql-bench/crash-me.sh
index f6985adc5c0..9572143ae53 100644
--- a/sql-bench/crash-me.sh
+++ b/sql-bench/crash-me.sh
@@ -143,7 +143,15 @@ $longreadlen=16000000; # For retrieval buffer
#
use sigtrap; # Must be removed with perl5.005_2 on Win98
$SIG{PIPE} = 'IGNORE';
-$SIG{SEGV} = sub {warn('SEGFAULT')};
+$problem_counter=0;
+$SIG{SEGV} = sub {
+ $problem_counter +=1;
+ if ($problem_counter >= 100) {
+ die("Too many problems, try to restart");
+ } else {
+ warn('SEGFAULT');
+ };
+};
$dbh=safe_connect();
#
@@ -252,6 +260,8 @@ report("Functions",'functions',"select 1+1 $end_query");
report("Group functions",'group_functions',"select count(*) from crash_me");
report("Group functions with distinct",'group_distinct_functions',
"select count(distinct a) from crash_me");
+report("Group functions with several distinct",'group_many_distinct_functions',
+ "select count(distinct a), count(distinct b) from crash_me");
report("Group by",'group_by',"select a from crash_me group by a");
report("Group by position",'group_by_position',
"select a from crash_me group by 1");
@@ -1438,6 +1448,14 @@ if (!report("case independent table names","table_name_case",
safe_query("drop table crash_q $drop_attr");
}
+if (!report("case independent field names","field_name_case",
+ "create table crash_q (q integer)",
+ "insert into crash_q(Q) values (1)",
+ "drop table crash_q $drop_attr"))
+{
+ safe_query("drop table crash_q $drop_attr");
+}
+
if (!report("drop table if exists","drop_if_exists",
"create table crash_q (q integer)",
"drop table if exists crash_q $drop_attr"))
@@ -2450,6 +2468,7 @@ sub report
print "$prompt: ";
if (!defined($limits{$limit}))
{
+ save_config_data($limit,"incompleted",$prompt);
save_config_data($limit,safe_query(\@queries) ? "yes" : "no",$prompt);
}
print "$limits{$limit}\n";
@@ -2462,6 +2481,7 @@ sub report_fail
print "$prompt: ";
if (!defined($limits{$limit}))
{
+ save_config_data($limit,"incompleted",$prompt);
save_config_data($limit,safe_query(\@queries) ? "no" : "yes",$prompt);
}
print "$limits{$limit}\n";
@@ -2478,6 +2498,7 @@ sub report_one
print "$prompt: ";
if (!defined($limits{$limit}))
{
+ save_config_data($limit,"incompleted",$prompt);
$result="no";
foreach $query (@$queries)
{
@@ -2503,6 +2524,7 @@ sub report_result
print "$prompt: ";
if (!defined($limits{$limit}))
{
+ save_config_data($limit,"incompleted",$prompt);
$error=safe_query_result($query,"1",2);
save_config_data($limit,$error ? "not supported" : $last_result,$prompt);
}
@@ -2515,6 +2537,7 @@ sub report_trans
my ($limit,$queries,$check,$clear)=@_;
if (!defined($limits{$limit}))
{
+ save_config_data($limit,"incompleted",$prompt);
eval {undef($dbh->{AutoCommit})};
if (!$@)
{
@@ -2524,21 +2547,21 @@ sub report_trans
if ($rc) {
$dbh->{AutoCommit} = 1;
if (safe_query_result($check,"","")) {
- save_config_data($limit,"yes",$prompt);
+ save_config_data($limit,"yes",$limit);
}
safe_query($clear);
} else {
$dbh->{AutoCommit} = 1;
- save_config_data($limit,"error",$prompt);
+ save_config_data($limit,"error",$limit);
}
} else {
- save_config_data($limit,"error",$prompt);
+ save_config_data($limit,"error",$limit);
}
$dbh->{AutoCommit} = 1;
}
else
{
- save_config_data($limit,"no",$prompt);
+ save_config_data($limit,"no",$limit);
}
safe_query($clear);
}
@@ -2556,9 +2579,11 @@ sub check_and_report
print "$prompt: " if (!defined($skip_prompt));
if (!defined($limits{$limit}))
{
+ save_config_data($limit,"incompleted",$prompt);
$tmp=1-safe_query(\@$pre);
$tmp=safe_query_result($query,$answer,$string_type) if (!$tmp);
safe_query(\@$post);
+ delete $limits{$limit};
if ($function == 3) # Report error as 'no'.
{
$function=0;
@@ -2587,8 +2612,10 @@ sub try_and_report
my ($tmp,$test,$type);
print "$prompt: ";
+
if (!defined($limits{$limit}))
{
+ save_config_data($limit,"incompleted",$prompt);
$type="no"; # Not supported
foreach $test (@tests)
{
@@ -2699,7 +2726,7 @@ sub safe_query_result
elsif ($result_type == 5) # Result should have given prefix
{
$result= -1 if (length($row->[0]) < length($answer) &&
- substring($row->[0],1,length($answer)) ne $answer);
+ substr($row->[0],1,length($answer)) ne $answer);
}
elsif ($result_type == 6) # Exact match but ignore errors
{
@@ -2760,6 +2787,8 @@ sub find_limit()
print "$end (cache)\n";
return $end;
}
+ save_config_data($limit,"incompleted",$prompt);
+
if (defined($query->{'init'}) && !defined($end=$limits{'restart'}{'tohigh'}))
{
if (!safe_query($query->{'init'}))
diff --git a/sql-bench/limits/db2.cfg b/sql-bench/limits/db2.cfg
index 31280fbe643..5b2c0e172e7 100644
--- a/sql-bench/limits/db2.cfg
+++ b/sql-bench/limits/db2.cfg
@@ -1,34 +1,68 @@
-#This file is automaticly generated by crash-me 1.19a
+#This file is automaticly generated by crash-me 1.57
NEG=yes # update of column= -column
+Need_cast_for_null=no # Need to cast NULL for arithmetic
alter_add_col=yes # Alter table add column
+alter_add_constraint=yes # Alter table add constraint
+alter_add_foreign_key=yes # Alter table add foreign key
+alter_add_multi_col=no # Alter table add many columns
+alter_add_primary_key=with constraint # Alter table add primary key
+alter_add_unique=no # Alter table add unique
+alter_alter_col=no # Alter table alter column default
alter_change_col=no # Alter table change column
alter_drop_col=no # Alter table drop column
+alter_drop_constraint=yes # Alter table drop constraint
+alter_drop_foreign_key=with drop constraint # Alter table drop foreign key
+alter_drop_primary_key=drop primary key # Alter table drop primary key
+alter_drop_unique=no # Alter table drop unique
alter_modify_col=no # Alter table modify column
alter_rename_table=no # Alter table rename table
atomic_updates=yes # atomic updates
atomic_updates_with_rollback=yes # atomic_updates_with_rollback
-binary_items=no # binary items (0x41)
-case_insensitive_strings=no # case insensitive compare
-char_is_space_filled=no # char are space filled
+automatic_rowid=no # Automatic row id
+binary_numbers=no # binary numbers (0b1001)
+binary_strings=no # binary strings (b'0110')
+case_insensitive_strings=no # Case insensitive compare
+char_is_space_filled=yes # char are space filled
column_alias=yes # Column alias
+columns_in_group_by=+64 # number of columns in group by
+columns_in_order_by=+64 # number of columns in order by
comment_#=no # # as comment
-comment_--=yes # -- as comment
+comment_--=yes # -- as comment (ANSI)
comment_/**/=no # /* */ as comment
+comment_//=no # // as comment
compute=no # Compute
-connections=125 # Simultaneous connections
+connections=40 # Simultaneous connections (installation default)
+constraint_check=yes # Column constraints
+constraint_check_table=yes # Table constraints
+constraint_null=no # NULL constraint (SyBase style)
crash_me_safe=no # crash me safe
-crash_me_version=1.19a # crash me version
+crash_me_version=1.57 # crash me version
create_default=yes # default value for column
+create_default_func=no # default value function for column
+create_if_not_exists=no # create table if not exists
create_index=yes # create index
+create_schema=no # Create SCHEMA
+create_table_select=no # create table from select
cross_join=no # cross join (same as from a,b)
date_as_string=no # String functions on date columns
+date_infinity=no # Supports 'infinity dates
+date_last=no # Supports 9999-12-31 dates
+date_one=no # Supports 0001-01-01 dates
date_with_YY=no # Supports YY-MM-DD dates
date_zero=no # Supports 0000-00-00 dates
+domains=no # Domains (ANSI SQL)
+dont_require_cast_to_float=yes # No need to cast from integer to float
double_quotes=yes # Double '' as ' in strings
+drop_if_exists=no # drop table if exists
drop_index=yes # drop index
+drop_requires_cascade=no # drop table require cascade/restrict
+drop_restrict=no # drop table with cascade/restrict
+end_colon=yes # allows end ';'
except=yes # except
except_all=yes # except all
+except_all_incompat=no # except all (incompatible lists)
+except_incompat=no # except (incompatible lists)
float_int_expr=yes # mixing of integer and float in expression
foreign_key=yes # foreign keys
foreign_key_syntax=yes # foreign key syntax
@@ -41,6 +75,8 @@ func_extra_<>=no # Function <> in SELECT
func_extra_==no # Function =
func_extra_add_months=no # Function ADD_MONTHS
func_extra_and_or=no # Function AND and OR in SELECT
+func_extra_ascii_char=no # Function ASCII_CHAR
+func_extra_ascii_code=no # Function ASCII_CODE
func_extra_atn2=no # Function ATN2
func_extra_auto_num2string=no # Function automatic num->string convert
func_extra_auto_string2num=no # Function automatic string->num convert
@@ -72,6 +108,7 @@ func_extra_in_num=no # Function IN on numbers in SELECT
func_extra_in_str=no # Function IN on strings in SELECT
func_extra_initcap=no # Function INITCAP
func_extra_instr=no # Function LOCATE as INSTR
+func_extra_instr_oracle=no # Function INSTR (Oracle syntax)
func_extra_instrb=no # Function INSTRB
func_extra_interval=no # Function INTERVAL
func_extra_last_day=no # Function LAST_DAY
@@ -84,16 +121,15 @@ func_extra_ln=yes # Function LN
func_extra_log(m_n)=no # Function LOG(m,n)
func_extra_logn=no # Function LOGN
func_extra_lpad=no # Function LPAD
-func_extra_max_num=no # Function MAX on numbers
func_extra_mdy=no # Function MDY
func_extra_mid=no # Function SUBSTRING as MID
-func_extra_min_num=no # Function MIN on numbers
func_extra_months_between=no # Function MONTHS_BETWEEN
func_extra_not=no # Function NOT in SELECT
func_extra_not_between=no # Function NOT BETWEEN in SELECT
func_extra_not_like=no # Function NOT LIKE in SELECT
func_extra_odbc_convert=no # Function ODBC CONVERT
func_extra_password=no # Function PASSWORD
+func_extra_paste=no # Function PASTE
func_extra_patindex=no # Function PATINDEX
func_extra_period_add=no # Function PERIOD_ADD
func_extra_period_diff=no # Function PERIOD_DIFF
@@ -112,6 +148,8 @@ func_extra_strcmp=no # Function STRCMP
func_extra_stuff=no # Function STUFF
func_extra_substrb=no # Function SUBSTRB
func_extra_substring_index=no # Function SUBSTRING_INDEX
+func_extra_sysdate=no # Function SYSDATE
+func_extra_tail=no # Function TAIL
func_extra_tanh=no # Function TANH
func_extra_time_to_sec=no # Function TIME_TO_SEC
func_extra_to_days=no # Function TO_DAYS
@@ -126,6 +164,7 @@ func_extra_version=no # Function VERSION
func_extra_weekday=no # Function WEEKDAY
func_extra_|=no # Function | (bitwise or)
func_extra_||=no # Function OR as '||'
+func_extra_~*=no # Function ~* (case insensitive compare)
func_odbc_abs=yes # Function ABS
func_odbc_acos=yes # Function ACOS
func_odbc_ascii=yes # Function ASCII
@@ -133,31 +172,30 @@ func_odbc_asin=yes # Function ASIN
func_odbc_atan=yes # Function ATAN
func_odbc_atan2=error # Function ATAN2
func_odbc_ceiling=yes # Function CEILING
-func_odbc_char=error # Function CHAR
+func_odbc_char=yes # Function CHAR
func_odbc_concat=yes # Function CONCAT(2 arg)
func_odbc_cos=yes # Function COS
func_odbc_cot=yes # Function COT
-func_odbc_curdate=no # Function CURDATE
-func_odbc_curtime=no # Function CURTIME
-func_odbc_database=no # Function DATABASE
-func_odbc_dayname=no # Function DAYNAME
-func_odbc_dayofmonth=no # Function DAYOFMONTH
-func_odbc_dayofweek=no # Function DAYOFWEEK
-func_odbc_dayofyear=no # Function DAYOFYEAR
+func_odbc_curdate=yes # Function CURDATE
+func_odbc_curtime=yes # Function CURTIME
+func_odbc_database=yes # Function DATABASE
+func_odbc_dayname=yes # Function DAYNAME
+func_odbc_dayofmonth=yes # Function DAYOFMONTH
+func_odbc_dayofweek=yes # Function DAYOFWEEK
+func_odbc_dayofyear=yes # Function DAYOFYEAR
func_odbc_degrees=yes # Function DEGREES
func_odbc_difference=yes # Function DIFFERENCE()
func_odbc_exp=yes # Function EXP
-func_odbc_extract=no # Function EXTRACT
func_odbc_floor=yes # Function FLOOR
func_odbc_fn_left=yes # Function ODBC syntax LEFT & RIGHT
func_odbc_hour=yes # Function HOUR
-func_odbc_hour_time=no # Function ANSI HOUR
-func_odbc_ifnull=no # Function IFNULL
+func_odbc_hour_time=yes # Function ANSI HOUR
+func_odbc_ifnull=yes # Function IFNULL
func_odbc_insert=yes # Function INSERT
func_odbc_lcase=yes # Function LCASE
func_odbc_left=yes # Function LEFT
func_odbc_length=yes # Function REAL LENGTH
-func_odbc_length_without_space=error # Function ODBC LENGTH
+func_odbc_length_without_space=yes # Function ODBC LENGTH
func_odbc_locate_2=yes # Function LOCATE(2 arg)
func_odbc_locate_3=yes # Function LOCATE(3 arg)
func_odbc_log=yes # Function LOG
@@ -165,12 +203,12 @@ func_odbc_log10=yes # Function LOG10
func_odbc_ltrim=yes # Function LTRIM
func_odbc_minute=yes # Function MINUTE
func_odbc_mod=yes # Function MOD
-func_odbc_month=no # Function MONTH
-func_odbc_monthname=no # Function MONTHNAME
-func_odbc_now=no # Function NOW
-func_odbc_pi=no # Function PI
+func_odbc_month=yes # Function MONTH
+func_odbc_monthname=yes # Function MONTHNAME
+func_odbc_now=yes # Function NOW
+func_odbc_pi=yes # Function PI
func_odbc_power=yes # Function POWER
-func_odbc_quarter=no # Function QUARTER
+func_odbc_quarter=yes # Function QUARTER
func_odbc_radians=yes # Function RADIANS
func_odbc_rand=yes # Function RAND
func_odbc_repeat=yes # Function REPEAT
@@ -184,38 +222,43 @@ func_odbc_sin=yes # Function SIN
func_odbc_soundex=yes # Function SOUNDEX
func_odbc_space=yes # Function SPACE
func_odbc_sqrt=yes # Function SQRT
-func_odbc_substring=no # Function ODBC SUBSTRING
+func_odbc_substring=yes # Function ODBC SUBSTRING
func_odbc_tan=yes # Function TAN
func_odbc_timestampadd=no # Function TIMESTAMPADD
func_odbc_timestampdiff=no # Function TIMESTAMPDIFF
func_odbc_truncate=yes # Function TRUNCATE
-func_odbc_ucase=no # Function UCASE
-func_odbc_user=yes # Function USER
-func_odbc_user()=no # Function USER()
-func_odbc_week=no # Function WEEK
-func_odbc_year=no # Function YEAR
+func_odbc_ucase=yes # Function UCASE
+func_odbc_user()=yes # Function USER()
+func_odbc_week=yes # Function WEEK
+func_odbc_year=yes # Function YEAR
func_sql_+=yes # Function +, -, * and /
func_sql_bit_length=no # Function BIT_LENGTH
-func_sql_case=yes # Function CASE
func_sql_cast=yes # Function CAST
func_sql_char_length=no # Function CHAR_LENGTH
+func_sql_char_length(constant)=no # Function CHAR_LENGTH(constant)
func_sql_character_length=no # Function CHARACTER_LENGTH
+func_sql_coalesce=no # Function COALESCE
func_sql_concat_as_||=yes # Function concatenation with ||
func_sql_current_date=no # Function CURRENT_DATE
-func_sql_current_date()=no # Function CURRENT_DATE()
func_sql_current_time=no # Function CURRENT_TIME
-func_sql_current_time()=no # Function CURRENT_TIME()
func_sql_current_timestamp=no # Function CURRENT_TIMESTAMP
-func_sql_current_timestamp()=no # Function CURRENT_TIMESTAMP()
-func_sql_lower=no # Function LOWER
+func_sql_current_user=no # Function CURRENT_USER
+func_sql_extract_sql=no # Function EXTRACT
+func_sql_localtime=no # Function LOCALTIME
+func_sql_localtimestamp=no # Function LOCALTIMESTAMP
+func_sql_lower=yes # Function LOWER
+func_sql_nullif_num=yes # Function NULLIF with numbers
+func_sql_nullif_string=yes # Function NULLIF with strings
func_sql_octet_length=no # Function OCTET_LENGTH
func_sql_position=no # Function POSITION
+func_sql_searched_case=yes # Function searched CASE
func_sql_session_user=no # Function SESSION_USER
+func_sql_simple_case=yes # Function simple CASE
func_sql_substring=no # Function ANSI SQL SUBSTRING
-func_extra_sysdate=no # Function SYSDATE
func_sql_system_user=no # Function SYSTEM_USER
func_sql_trim=no # Function TRIM
-func_sql_upper=no # Function UPPER
+func_sql_upper=yes # Function UPPER
+func_sql_user=yes # Function USER
func_where_between=yes # Function BETWEEN
func_where_eq_all=yes # Function = ALL
func_where_eq_any=yes # Function = ANY
@@ -235,36 +278,49 @@ func_where_unique=no # Function UNIQUE
functions=yes # Functions
group_by=yes # Group by
group_by_alias=no # Group by alias
-group_by_null=yes # Test nulls in group by
+group_by_null=yes # Group on column with null values
group_by_position=no # Group by position
group_distinct_functions=yes # Group functions with distinct
group_func_extra_bit_and=no # Group function BIT_AND
group_func_extra_bit_or=no # Group function BIT_OR
+group_func_extra_count_distinct_list=no # Group function COUNT(DISTINCT expr,expr,...)
group_func_extra_std=no # Group function STD
group_func_extra_stddev=yes # Group function STDDEV
group_func_extra_variance=yes # Group function VARIANCE
+group_func_sql_any=no # Group function ANY
group_func_sql_avg=yes # Group function AVG
group_func_sql_count_*=yes # Group function COUNT (*)
group_func_sql_count_column=yes # Group function COUNT column name
-group_func_sql_count_distinct=yes # Group function COUNT DISTINCT column name
+group_func_sql_count_distinct=yes # Group function COUNT(DISTINCT expr)
+group_func_sql_every=no # Group function EVERY
group_func_sql_max=yes # Group function MAX on numbers
group_func_sql_max_str=yes # Group function MAX on strings
group_func_sql_min=yes # Group function MIN on numbers
group_func_sql_min_str=yes # Group function MIN on strings
+group_func_sql_some=no # Group function SOME
group_func_sql_sum=yes # Group function SUM
group_functions=yes # Group functions
+group_on_unused=yes # Group on unused column
+has_true_false=no # TRUE and FALSE
having=yes # Having
having_with_alias=no # Having on alias
having_with_group=yes # Having with group function
-ignore_end_space=yes # ignore end space in compare
+hex_numbers=no # hex numbers (0x41)
+hex_strings=yes # hex strings (x'1ace')
+ignore_end_space=yes # Ignore end space in compare
index_in_create=no # index in create table
index_namespace=no # different namespace for index
index_parts=no # index on column part (extension)
+inner_join=yes # inner join
insert_empty_string=yes # insert empty string
+insert_multi_value=yes # INSERT with Value lists
insert_select=yes # insert INTO ... SELECT ...
+insert_with_set=no # INSERT with set syntax
intersect=yes # intersect
intersect_all=yes # intersect all
-join_tables=+64 # tables in join
+intersect_all_incompat=no # intersect all (incompatible lists)
+intersect_incompat=no # intersect (incompatible lists)
+join_tables=10 # tables in join
left_outer_join=yes # left outer join
left_outer_join_using=no # left outer join using
like_with_column=no # column LIKE column
@@ -273,150 +329,194 @@ lock_tables=yes # lock table
logical_value=not supported # Value of logical operation (1=1)
max_big_expressions=1 # big expressions
max_char_size=254 # max char() size
-max_column_name=18 # column name length
+max_column_name=30 # column name length
max_columns=500 # Columns in table
-max_conditions=418 # OR and AND in WHERE
-max_expressions=9820 # simple expressions
+max_conditions=2082 # OR and AND in WHERE
+max_expressions=9543 # simple expressions
max_index=+64 # max index
-max_index_length=255 # index length
+max_index_length=1024 # index length
max_index_name=18 # index name length
max_index_part_length=254 # max index part length
-max_index_parts=15 # index parts
-max_index_varchar_part_length=251 # index varchar part length
+max_index_parts=16 # index parts
+max_index_varchar_part_length=255 # index varchar part length
max_row_length=4005 # max table row length (without blobs)
max_row_length_with_null=3989 # table row length with nulls (without blobs)
-max_select_alias_name=18 # select alias name length
+max_select_alias_name=30 # select alias name length
max_stack_expression=1363 # stacked expressions
-max_table_alias_name=18 # table alias name length
-max_table_name=18 # table name length
+max_table_alias_name=128 # table alias name length
+max_table_name=128 # table name length
max_unique_index=+64 # unique indexes
max_varchar_size=4000 # max varchar() size
minus=no # minus
+minus_incompat=no # minus (incompatible lists)
minus_neg=no # Calculate 1--1
multi_drop=no # many tables to drop table
multi_strings=no # Multiple line strings
multi_table_delete=no # DELETE FROM table1,table2...
multi_table_update=no # Update with many tables
natural_join=no # natural join
+natural_join_incompat=no # natural join (incompatible lists)
natural_left_outer_join=no # natural left outer join
no_primary_key=yes # Tables without primary key
null_concat_expr=no # Is 'a' || NULL = NULL
null_in_index=yes # null in index
-null_in_unique=no # null in unique
+null_in_unique=no # null in unique index
null_num_expr=no # Is 1+NULL = NULL
+nulls_in_unique=no # null combination in unique index
odbc_left_outer_join=yes # left outer join odbc style
-operating_system=Windows NT Version 4.0 # crash-me tested on
+operating_system=Linux 2.4.4-64GB-SMP i686 # crash-me tested on
order_by=yes # Order by
order_by_alias=yes # Order by alias
+order_by_function=yes # Order by function
order_by_position=yes # Order by position
+order_by_remember_desc=no # Order by DESC is remembered
+order_on_unused=yes # Order by on unused column
primary_key_in_create=yes # primary key in create table
-query_size=19662 # query size
+psm_functions=no # PSM functions (ANSI SQL)
+psm_modules=no # PSM modules (ANSI SQL)
+psm_procedures=no # PSM procedures (ANSI SQL)
+psm_trigger=no # Triggers (ANSI SQL)
+query_size=65535 # query size
+quote_ident_with_"=yes # " as identifier quote (ANSI SQL)
+quote_ident_with_[=no # [] as identifier quote
+quote_ident_with_`=no # ` as identifier quote
quote_with_"=no # Allows ' and " as string markers
-recursive_subqueries=22 # recursive subqueries
+recursive_subqueries=8 # recursive subqueries
remember_end_space=no # Remembers end space in char()
remember_end_space_varchar=yes # Remembers end space in varchar()
+rename_table=yes # rename table
repeat_string_size=4000 # return string size from function
right_outer_join=yes # right outer join
+rowid=no # Type for row id
select_constants=yes # Select constants
-select_string_size=4000 # constant string size in SELECT
+select_limit=no # LIMIT number of rows
+select_limit2=no # SELECT with LIMIT #,#
+select_string_size=32672 # constant string size in SELECT
select_table_update=yes # Update with sub select
select_without_from=no # SELECT without FROM
-server_version=IBM DB2 5 # server version
+server_version=IBM DB2 7.2 # server version
simple_joins=yes # ANSI SQL simple joins
+storage_of_float=truncate # Storage of float values
subqueries=yes # subqueries
table_alias=yes # Table alias
+table_name_case=yes # case independent table names
table_wildcard=yes # Select table_name.*
-transactions=yes # transactions
+temporary_table=no # temporary tables
+transactions=yes # constant string size in where
+truncate_table=no # truncate
type_extra_abstime=no # Type abstime
type_extra_bfile=no # Type bfile
type_extra_blob=no # Type blob
type_extra_bool=no # Type bool
type_extra_box=no # Type box
type_extra_byte=no # Type byte
-type_extra_char(1_arg)_binary=no # Type char(1 arg) binary
-type_extra_char16=no # Type char16
-type_extra_char2=no # Type char2
-type_extra_char4=no # Type char4
-type_extra_char8=no # Type char8
+type_extra_char(1_arg)_binary=no # Type char(1 arg) binary
+type_extra_cidr=no # Type cidr
type_extra_circle=no # Type circle
type_extra_clob=no # Type clob
type_extra_datetime=no # Type datetime
-type_extra_enum(1_arg)=no # Type enum(1 arg)
-type_sql_float(1_arg)=yes # Type float(1 arg)
+type_extra_double=yes # Type double
+type_extra_enum(1_arg)=no # Type enum(1 arg)
+type_extra_float(2_arg)=no # Type float(2 arg)
type_extra_float4=no # Type float4
type_extra_float8=no # Type float8
type_extra_image=no # Type image
-type_extra_int(1_arg)_zerofill=no # Type int(1 arg) zerofill
+type_extra_inet=no # Type inet
+type_extra_int(1_arg)_zerofill=no # Type int(1 arg) zerofill
type_extra_int1=no # Type int1
type_extra_int2=no # Type int2
type_extra_int3=no # Type int3
type_extra_int4=no # Type int4
type_extra_int8=no # Type int8
type_extra_int_auto_increment=no # Type int not null auto_increment
+type_extra_int_identity=no # Type int not null identity
+type_extra_int_unsigned=no # Type int unsigned
+type_extra_interval=no # Type interval
type_extra_line=no # Type line
type_extra_long=no # Type long
type_extra_long_raw=no # Type long raw
type_extra_long_varbinary=no # Type long varbinary
-type_extra_long_varchar(1_arg)=no # Type long varchar(1 arg)
+type_extra_long_varchar(1_arg)=no # Type long varchar(1 arg)
type_extra_lseg=no # Type lseg
+type_extra_macaddr=no # Type macaddr
type_extra_mediumint=no # Type mediumint
type_extra_mediumtext=no # Type mediumtext
type_extra_middleint=no # Type middleint
type_extra_mlslabel=no # Type mlslabel
type_extra_money=no # Type money
-type_sql_nchar(1_arg)=no # Type nchar(1 arg)
type_extra_nclob=no # Type nclob
type_extra_number=no # Type number
-type_extra_number(1_arg)=no # Type number(1 arg)
-type_extra_nvarchar(2_arg)=no # Type nvarchar(2 arg)
+type_extra_number(1_arg)=no # Type number(1 arg)
+type_extra_number(2_arg)=no # Type number(2 arg)
type_extra_nvarchar2(1_arg)=no # Type nvarchar2(1 arg)
type_extra_path=no # Type path
type_extra_point=no # Type point
type_extra_polygon=no # Type polygon
-type_extra_raw(1_arg)=no # Type raw(1 arg)
+type_extra_raw(1_arg)=no # Type raw(1 arg)
type_extra_reltime=no # Type reltime
type_extra_rowid=no # Type rowid
type_extra_serial=no # Type serial
-type_extra_set(1_arg)=no # Type set(1 arg)
+type_extra_set(1_arg)=no # Type set(1 arg)
type_extra_smalldatetime=no # Type smalldatetime
type_extra_smallfloat=no # Type smallfloat
type_extra_smallmoney=no # Type smallmoney
type_extra_text=no # Type text
-type_extra_text(1_arg)=no # Type text(1 arg)
+type_extra_text(1_arg)=no # Type text(1 arg)
type_extra_timespan=no # Type timespan
+type_extra_uint=no # Type uint
type_extra_varchar2(1_arg)=no # Type varchar2(1 arg)
type_extra_year=no # Type year
-type_odbc_bigint=no # Type bigint
-type_odbc_binary(1_arg)=no # Type binary(1 arg)
+type_odbc_bigint=yes # Type bigint
+type_odbc_binary(1_arg)=no # Type binary(1 arg)
type_odbc_datetime=no # Type datetime
-type_sql_smallint=yes # Type smallint
type_odbc_tinyint=no # Type tinyint
type_odbc_varbinary(1_arg)=no # Type varbinary(1 arg)
type_sql_bit=no # Type bit
type_sql_bit(1_arg)=no # Type bit(1 arg)
type_sql_bit_varying(1_arg)=no # Type bit varying(1 arg)
-type_sql_char(1_arg)=yes # Type char(1 arg)
-type_sql_char_varying(1_arg)=yes # Type char varying(1 arg)
+type_sql_boolean=no # Type boolean
+type_sql_char(1_arg)=yes # Type char(1 arg)
+type_sql_char_varying(1_arg)=yes # Type char varying(1 arg)
type_sql_character(1_arg)=yes # Type character(1 arg)
type_sql_character_varying(1_arg)=yes # Type character varying(1 arg)
type_sql_date=yes # Type date
type_sql_dec(2_arg)=yes # Type dec(2 arg)
-type_sql_decimal(2_arg)=yes # Type decimal(2 arg)
-type_extra_double=yes # Type double
+type_sql_decimal(2_arg)=yes # Type decimal(2 arg)
type_sql_double_precision=yes # Type double precision
type_sql_float=yes # Type float
-type_extra_float(2_arg)=no # Type float(1 arg)
+type_sql_float(1_arg)=yes # Type float(1 arg)
type_sql_int=yes # Type int
type_sql_integer=yes # Type integer
+type_sql_interval_day=no # Type interval day
+type_sql_interval_day_to_hour=no # Type interval day to hour
+type_sql_interval_day_to_minute=no # Type interval day to minute
+type_sql_interval_day_to_second=no # Type interval day to second
+type_sql_interval_hour=no # Type interval hour
+type_sql_interval_hour_to_minute=no # Type interval hour to minute
+type_sql_interval_hour_to_second=no # Type interval hour to second
+type_sql_interval_minute=no # Type interval minute
+type_sql_interval_minute_to_second=no # Type interval minute to second
+type_sql_interval_month=no # Type interval month
+type_sql_interval_second=no # Type interval second
type_sql_interval_year=no # Type interval year
-type_sql_numeric(2_arg)=yes # Type numeric(2 arg)
+type_sql_interval_year_to_month=no # Type interval year to month
+type_sql_national_char_varying(1_arg)=no # Type national char varying(1 arg)
+type_sql_national_character(1_arg)=no # Type national character(1 arg)
+type_sql_national_character_varying(1_arg)=no # Type national character varying(1 arg)
+type_sql_nchar(1_arg)=no # Type nchar(1 arg)
+type_sql_nchar_varying(1_arg)=no # Type nchar varying(1 arg)
+type_sql_numeric(2_arg)=yes # Type numeric(2 arg)
type_sql_real=yes # Type real
+type_sql_smallint=yes # Type smallint
type_sql_time=yes # Type time
type_sql_timestamp=yes # Type timestamp
-type_sql_varchar(1_arg)=yes # Type varchar(1 arg)
+type_sql_timestamp_with_time_zone=no # Type timestamp with time zone
+type_sql_varchar(1_arg)=yes # Type varchar(1 arg)
union=yes # union
union_all=yes # union all
+union_all_incompat=yes # union all (incompatible lists)
+union_incompat=yes # union (incompatible lists)
unique_in_create=yes # unique in create table
unique_null_in_create=no # unique null in create
views=yes # views
-where_string_size=4000 # constant string size in where
+where_string_size=32672 # constant string size in where
diff --git a/sql-bench/limits/interbase-dialect1.cfg b/sql-bench/limits/interbase-dialect1.cfg
new file mode 100644
index 00000000000..046627be513
--- /dev/null
+++ b/sql-bench/limits/interbase-dialect1.cfg
@@ -0,0 +1,514 @@
+#This file is automaticly generated by crash-me 1.57
+
+NEG=no # update of column= -column
+Need_cast_for_null=no # Need to cast NULL for arithmetic
+alter_add_col=yes # Alter table add column
+alter_add_constraint=yes # Alter table add constraint
+alter_add_foreign_key=yes # Alter table add foreign key
+alter_add_multi_col=with add # Alter table add many columns
+alter_add_primary_key=with constraint # Alter table add primary key
+alter_add_unique=no # Alter table add unique
+alter_alter_col=no # Alter table alter column default
+alter_change_col=no # Alter table change column
+alter_drop_col=no # Alter table drop column
+alter_drop_constraint=yes # Alter table drop constraint
+alter_drop_foreign_key=with drop constraint # Alter table drop foreign key
+alter_drop_primary_key=no # Alter table drop primary key
+alter_drop_unique=no # Alter table drop unique
+alter_modify_col=no # Alter table modify column
+alter_rename_table=no # Alter table rename table
+atomic_updates=no # atomic updates
+automatic_rowid=no # Automatic row id
+binary_numbers=yes # binary numbers (0b1001)
+binary_strings=no # binary strings (b'0110')
+case_insensitive_strings=no # Case insensitive compare
+char_is_space_filled=yes # char are space filled
+column_alias=yes # Column alias
+columns_in_order_by=37 # number of columns in order by
+comment_#=no # # as comment
+comment_--=no # -- as comment (ANSI)
+comment_/**/=yes # /* */ as comment
+comment_//=no # // as comment
+compute=no # Compute
+connections=1000 # Simultaneous connections (installation default)
+constraint_check=no # Column constraints
+constraint_check_table=no # Table constraints
+constraint_null=no # NULL constraint (SyBase style)
+crash_me_safe=yes # crash me safe
+crash_me_version=1.57 # crash me version
+create_default=yes # default value for column
+create_default_func=no # default value function for column
+create_if_not_exists=no # create table if not exists
+create_index=yes # create index
+create_schema=no # Create SCHEMA
+create_table_select=no # create table from select
+cross_join=no # cross join (same as from a,b)
+date_infinity=no # Supports 'infinity dates
+date_last=no # Supports 9999-12-31 dates
+date_one=no # Supports 0001-01-01 dates
+date_with_YY=no # Supports YY-MM-DD dates
+date_zero=no # Supports 0000-00-00 dates
+domains=no # Domains (ANSI SQL)
+double_quotes=yes # Double '' as ' in strings
+drop_if_exists=no # drop table if exists
+drop_index=yes # drop index
+drop_requires_cascade=no # drop table require cascade/restrict
+drop_restrict=no # drop table with cascade/restrict
+end_colon=yes # allows end ';'
+except=no # except
+except_all=no # except all
+except_all_incompat=no # except all (incompatible lists)
+except_incompat=no # except (incompatible lists)
+float_int_expr=yes # mixing of integer and float in expression
+foreign_key_syntax=no # foreign key syntax
+full_outer_join=yes # full outer join
+func_extra_!=no # Function NOT as '!' in SELECT
+func_extra_%=no # Function MOD as %
+func_extra_&=no # Function & (bitwise and)
+func_extra_&&=no # Function AND as '&&'
+func_extra_<>=no # Function <> in SELECT
+func_extra_==no # Function =
+func_extra_add_months=no # Function ADD_MONTHS
+func_extra_and_or=no # Function AND and OR in SELECT
+func_extra_ascii_char=no # Function ASCII_CHAR
+func_extra_ascii_code=no # Function ASCII_CODE
+func_extra_atn2=no # Function ATN2
+func_extra_auto_num2string=no # Function automatic num->string convert
+func_extra_auto_string2num=no # Function automatic string->num convert
+func_extra_between=no # Function BETWEEN in SELECT
+func_extra_binary_shifts=no # Function << and >> (bitwise shifts)
+func_extra_bit_count=no # Function BIT_COUNT
+func_extra_ceil=no # Function CEIL
+func_extra_charindex=no # Function CHARINDEX
+func_extra_chr=no # Function CHR
+func_extra_concat_as_+=no # Function concatenation with +
+func_extra_concat_list=no # Function CONCAT(list)
+func_extra_convert=no # Function CONVERT
+func_extra_cosh=no # Function COSH
+func_extra_date_format=no # Function DATE_FORMAT
+func_extra_dateadd=no # Function DATEADD
+func_extra_datediff=no # Function DATEDIFF
+func_extra_datename=no # Function DATENAME
+func_extra_datepart=no # Function DATEPART
+func_extra_elt=no # Function ELT
+func_extra_encrypt=no # Function ENCRYPT
+func_extra_field=no # Function FIELD
+func_extra_format=no # Function FORMAT
+func_extra_from_days=no # Function FROM_DAYS
+func_extra_from_unixtime=no # Function FROM_UNIXTIME
+func_extra_getdate=no # Function GETDATE
+func_extra_greatest=no # Function GREATEST
+func_extra_if=no # Function IF
+func_extra_in_num=no # Function IN on numbers in SELECT
+func_extra_in_str=no # Function IN on strings in SELECT
+func_extra_initcap=no # Function INITCAP
+func_extra_instr=no # Function LOCATE as INSTR
+func_extra_instr_oracle=no # Function INSTR (Oracle syntax)
+func_extra_instrb=no # Function INSTRB
+func_extra_interval=no # Function INTERVAL
+func_extra_last_day=no # Function LAST_DAY
+func_extra_last_insert_id=no # Function LAST_INSERT_ID
+func_extra_least=no # Function LEAST
+func_extra_lengthb=no # Function LENGTHB
+func_extra_like=no # Function LIKE in SELECT
+func_extra_like_escape=no # Function LIKE ESCAPE in SELECT
+func_extra_ln=no # Function LN
+func_extra_log(m_n)=no # Function LOG(m,n)
+func_extra_logn=no # Function LOGN
+func_extra_lpad=no # Function LPAD
+func_extra_mdy=no # Function MDY
+func_extra_mid=no # Function SUBSTRING as MID
+func_extra_months_between=no # Function MONTHS_BETWEEN
+func_extra_not=no # Function NOT in SELECT
+func_extra_not_between=no # Function NOT BETWEEN in SELECT
+func_extra_not_like=no # Function NOT LIKE in SELECT
+func_extra_odbc_convert=no # Function ODBC CONVERT
+func_extra_password=no # Function PASSWORD
+func_extra_paste=no # Function PASTE
+func_extra_patindex=no # Function PATINDEX
+func_extra_period_add=no # Function PERIOD_ADD
+func_extra_period_diff=no # Function PERIOD_DIFF
+func_extra_pow=no # Function POW
+func_extra_range=no # Function RANGE
+func_extra_regexp=no # Function REGEXP in SELECT
+func_extra_replicate=no # Function REPLICATE
+func_extra_reverse=no # Function REVERSE
+func_extra_root=no # Function ROOT
+func_extra_round1=no # Function ROUND(1 arg)
+func_extra_rpad=no # Function RPAD
+func_extra_sec_to_time=no # Function SEC_TO_TIME
+func_extra_sinh=no # Function SINH
+func_extra_str=no # Function STR
+func_extra_strcmp=no # Function STRCMP
+func_extra_stuff=no # Function STUFF
+func_extra_substrb=no # Function SUBSTRB
+func_extra_substring_index=no # Function SUBSTRING_INDEX
+func_extra_sysdate=no # Function SYSDATE
+func_extra_tail=no # Function TAIL
+func_extra_tanh=no # Function TANH
+func_extra_time_to_sec=no # Function TIME_TO_SEC
+func_extra_to_days=no # Function TO_DAYS
+func_extra_translate=no # Function TRANSLATE
+func_extra_trim_many_char=no # Function TRIM; Many char extension
+func_extra_trim_substring=no # Function TRIM; Substring extension
+func_extra_trunc=no # Function TRUNC
+func_extra_uid=no # Function UID
+func_extra_unix_timestamp=no # Function UNIX_TIMESTAMP
+func_extra_userenv=no # Function USERENV
+func_extra_version=no # Function VERSION
+func_extra_weekday=no # Function WEEKDAY
+func_extra_|=no # Function | (bitwise or)
+func_extra_||=no # Function OR as '||'
+func_extra_~*=no # Function ~* (case insensitive compare)
+func_odbc_abs=no # Function ABS
+func_odbc_acos=no # Function ACOS
+func_odbc_ascii=no # Function ASCII
+func_odbc_asin=no # Function ASIN
+func_odbc_atan=no # Function ATAN
+func_odbc_atan2=no # Function ATAN2
+func_odbc_ceiling=no # Function CEILING
+func_odbc_char=no # Function CHAR
+func_odbc_concat=no # Function CONCAT(2 arg)
+func_odbc_cos=no # Function COS
+func_odbc_cot=no # Function COT
+func_odbc_curdate=no # Function CURDATE
+func_odbc_curtime=no # Function CURTIME
+func_odbc_database=no # Function DATABASE
+func_odbc_dayname=no # Function DAYNAME
+func_odbc_dayofmonth=no # Function DAYOFMONTH
+func_odbc_dayofweek=no # Function DAYOFWEEK
+func_odbc_dayofyear=no # Function DAYOFYEAR
+func_odbc_degrees=no # Function DEGREES
+func_odbc_difference=no # Function DIFFERENCE()
+func_odbc_exp=no # Function EXP
+func_odbc_floor=no # Function FLOOR
+func_odbc_fn_left=no # Function ODBC syntax LEFT & RIGHT
+func_odbc_hour=no # Function HOUR
+func_odbc_hour_time=no # Function ANSI HOUR
+func_odbc_ifnull=no # Function IFNULL
+func_odbc_insert=no # Function INSERT
+func_odbc_lcase=no # Function LCASE
+func_odbc_left=no # Function LEFT
+func_odbc_length=no # Function REAL LENGTH
+func_odbc_length_without_space=no # Function ODBC LENGTH
+func_odbc_locate_2=no # Function LOCATE(2 arg)
+func_odbc_locate_3=no # Function LOCATE(3 arg)
+func_odbc_log=no # Function LOG
+func_odbc_log10=no # Function LOG10
+func_odbc_ltrim=no # Function LTRIM
+func_odbc_minute=no # Function MINUTE
+func_odbc_mod=no # Function MOD
+func_odbc_month=no # Function MONTH
+func_odbc_monthname=no # Function MONTHNAME
+func_odbc_now=no # Function NOW
+func_odbc_pi=no # Function PI
+func_odbc_power=no # Function POWER
+func_odbc_quarter=no # Function QUARTER
+func_odbc_radians=no # Function RADIANS
+func_odbc_rand=no # Function RAND
+func_odbc_repeat=no # Function REPEAT
+func_odbc_replace=no # Function REPLACE
+func_odbc_right=no # Function RIGHT
+func_odbc_round=no # Function ROUND(2 arg)
+func_odbc_rtrim=no # Function RTRIM
+func_odbc_second=no # Function SECOND
+func_odbc_sign=no # Function SIGN
+func_odbc_sin=no # Function SIN
+func_odbc_soundex=no # Function SOUNDEX
+func_odbc_space=no # Function SPACE
+func_odbc_sqrt=no # Function SQRT
+func_odbc_substring=no # Function ODBC SUBSTRING
+func_odbc_tan=no # Function TAN
+func_odbc_timestampadd=no # Function TIMESTAMPADD
+func_odbc_timestampdiff=no # Function TIMESTAMPDIFF
+func_odbc_truncate=no # Function TRUNCATE
+func_odbc_ucase=no # Function UCASE
+func_odbc_user()=no # Function USER()
+func_odbc_week=no # Function WEEK
+func_odbc_year=no # Function YEAR
+func_sql_+=yes # Function +, -, * and /
+func_sql_bit_length=no # Function BIT_LENGTH
+func_sql_cast=yes # Function CAST
+func_sql_char_length=no # Function CHAR_LENGTH
+func_sql_char_length(constant)=no # Function CHAR_LENGTH(constant)
+func_sql_character_length=no # Function CHARACTER_LENGTH
+func_sql_coalesce=no # Function COALESCE
+func_sql_concat_as_||=yes # Function concatenation with ||
+func_sql_current_date=no # Function CURRENT_DATE
+func_sql_current_time=no # Function CURRENT_TIME
+func_sql_current_timestamp=yes # Function CURRENT_TIMESTAMP
+func_sql_current_user=no # Function CURRENT_USER
+func_sql_extract_sql=yes # Function EXTRACT
+func_sql_localtime=no # Function LOCALTIME
+func_sql_localtimestamp=no # Function LOCALTIMESTAMP
+func_sql_lower=no # Function LOWER
+func_sql_nullif_num=no # Function NULLIF with numbers
+func_sql_nullif_string=no # Function NULLIF with strings
+func_sql_octet_length=no # Function OCTET_LENGTH
+func_sql_position=no # Function POSITION
+func_sql_searched_case=no # Function searched CASE
+func_sql_session_user=no # Function SESSION_USER
+func_sql_simple_case=no # Function simple CASE
+func_sql_substring=no # Function ANSI SQL SUBSTRING
+func_sql_system_user=no # Function SYSTEM_USER
+func_sql_trim=no # Function TRIM
+func_sql_upper=yes # Function UPPER
+func_sql_user=yes # Function USER
+func_where_between=yes # Function BETWEEN
+func_where_eq_all=yes # Function = ALL
+func_where_eq_any=yes # Function = ANY
+func_where_eq_some=yes # Function = SOME
+func_where_exists=yes # Function EXISTS
+func_where_in_num=yes # Function IN on numbers
+func_where_like=yes # Function LIKE
+func_where_like_escape=yes # Function LIKE ESCAPE
+func_where_match=no # Function MATCH
+func_where_match_unique=no # Function MATCH UNIQUE
+func_where_matches=no # Function MATCHES
+func_where_not_between=yes # Function NOT BETWEEN
+func_where_not_exists=yes # Function NOT EXISTS
+func_where_not_like=yes # Function NOT LIKE
+func_where_not_unique=no # Function NOT UNIQUE
+func_where_unique=no # Function UNIQUE
+functions=yes # Functions
+group_by=yes # Group by
+group_by_alias=no # Group by alias
+group_by_null=yes # Group on column with null values
+group_by_position=no # Group by position
+group_distinct_functions=yes # Group functions with distinct
+group_func_extra_bit_and=no # Group function BIT_AND
+group_func_extra_bit_or=no # Group function BIT_OR
+group_func_extra_count_distinct_list=no # Group function COUNT(DISTINCT expr,expr,...)
+group_func_extra_std=no # Group function STD
+group_func_extra_stddev=no # Group function STDDEV
+group_func_extra_variance=no # Group function VARIANCE
+group_func_sql_any=no # Group function ANY
+group_func_sql_avg=yes # Group function AVG
+group_func_sql_count_*=yes # Group function COUNT (*)
+group_func_sql_count_column=yes # Group function COUNT column name
+group_func_sql_count_distinct=yes # Group function COUNT(DISTINCT expr)
+group_func_sql_every=no # Group function EVERY
+group_func_sql_max=yes # Group function MAX on numbers
+group_func_sql_max_str=yes # Group function MAX on strings
+group_func_sql_min=yes # Group function MIN on numbers
+group_func_sql_min_str=yes # Group function MIN on strings
+group_func_sql_some=no # Group function SOME
+group_func_sql_sum=yes # Group function SUM
+group_functions=yes # Group functions
+group_on_unused=yes # Group on unused column
+has_true_false=no # TRUE and FALSE
+having=yes # Having
+having_with_alias=no # Having on alias
+having_with_group=yes # Having with group function
+hex_numbers=yes # hex numbers (0x41)
+hex_strings=no # hex strings (x'1ace')
+ignore_end_space=yes # Ignore end space in compare
+index_in_create=no # index in create table
+index_namespace=no # different namespace for index
+index_parts=no # index on column part (extension)
+inner_join=yes # inner join
+insert_empty_string=no # insert empty string
+insert_multi_value=no # INSERT with Value lists
+insert_select=no # insert INTO ... SELECT ...
+insert_with_set=no # INSERT with set syntax
+intersect=no # intersect
+intersect_all=no # intersect all
+intersect_all_incompat=no # intersect all (incompatible lists)
+intersect_incompat=no # intersect (incompatible lists)
+join_tables=+64 # tables in join
+left_outer_join=yes # left outer join
+left_outer_join_using=no # left outer join using
+like_with_column=no # column LIKE column
+like_with_number=no # LIKE on numbers
+lock_tables=no # lock table
+logical_value=not supported # Value of logical operation (1=1)
+max_big_expressions=1 # big expressions
+max_char_size=32767 # max char() size
+max_column_name=18 # column name length
+max_columns=4759 # Columns in table
+max_conditions=2944 # OR and AND in WHERE
+max_expressions=+10000 # simple expressions
+max_index=+64 # max index
+max_index_name=31 # index name length
+max_index_parts=16 # index parts
+max_index_varchar_part_length=249 # index varchar part length
+max_row_length=64744 # max table row length (without blobs)
+max_row_length_with_null=64744 # table row length with nulls (without blobs)
+max_select_alias_name=132 # select alias name length
+max_stack_expression=165 # stacked expressions
+max_table_alias_name=255 # table alias name length
+max_table_name=31 # table name length
+max_unique_index=+64 # unique indexes
+max_varchar_size=10923 # max varchar() size
+minus=no # minus
+minus_incompat=no # minus (incompatible lists)
+minus_neg=yes # Calculate 1--1
+multi_drop=no # many tables to drop table
+multi_strings=no # Multiple line strings
+multi_table_delete=no # DELETE FROM table1,table2...
+multi_table_update=no # Update with many tables
+natural_join=no # natural join
+natural_join_incompat=no # natural join (incompatible lists)
+natural_left_outer_join=no # natural left outer join
+no_primary_key=yes # Tables without primary key
+null_concat_expr=no # Is 'a' || NULL = NULL
+null_in_index=yes # null in index
+null_in_unique=no # null in unique index
+null_num_expr=no # Is 1+NULL = NULL
+nulls_in_unique=no # null combination in unique index
+odbc_left_outer_join=no # left outer join odbc style
+operating_system=Linux 2.4.4-64GB-SMP i686 # crash-me tested on
+order_by=yes # Order by
+order_by_alias=no # Order by alias
+order_by_function=no # Order by function
+order_by_position=yes # Order by position
+order_by_remember_desc=no # Order by DESC is remembered
+order_on_unused=yes # Order by on unused column
+primary_key_in_create=yes # primary key in create table
+psm_functions=no # PSM functions (ANSI SQL)
+psm_modules=no # PSM modules (ANSI SQL)
+psm_procedures=no # PSM procedures (ANSI SQL)
+psm_trigger=no # Triggers (ANSI SQL)
+query_size=65535 # query size
+quote_ident_with_"=yes # " as identifier quote (ANSI SQL)
+quote_ident_with_[=no # [] as identifier quote
+quote_ident_with_`=no # ` as identifier quote
+quote_with_"=no # Allows ' and " as string markers
+recursive_subqueries=61 # recursive subqueries
+remember_end_space=no # Remembers end space in char()
+remember_end_space_varchar=yes # Remembers end space in varchar()
+rename_table=no # rename table
+right_outer_join=yes # right outer join
+rowid=no # Type for row id
+select_constants=yes # Select constants
+select_limit=no # LIMIT number of rows
+select_limit2=no # SELECT with LIMIT #,#
+select_string_size=32767 # constant string size in SELECT
+select_table_update=yes # Update with sub select
+select_without_from=no # SELECT without FROM
+server_version=6.0.1 # server version
+simple_joins=yes # ANSI SQL simple joins
+storage_of_float=round # Storage of float values
+subqueries=yes # subqueries
+table_alias=no # Table alias
+table_name_case=yes # case independent table names
+table_wildcard=yes # Select table_name.*
+temporary_table=no # temporary tables
+transactions=error # constant string size in where
+truncate_table=no # truncate
+type_extra_abstime=no # Type abstime
+type_extra_bfile=no # Type bfile
+type_extra_blob=yes # Type blob
+type_extra_bool=no # Type bool
+type_extra_box=no # Type box
+type_extra_byte=no # Type byte
+type_extra_char(1_arg)_binary=no # Type char(1 arg) binary
+type_extra_cidr=no # Type cidr
+type_extra_circle=no # Type circle
+type_extra_clob=no # Type clob
+type_extra_datetime=no # Type datetime
+type_extra_double=no # Type double
+type_extra_enum(1_arg)=no # Type enum(1 arg)
+type_extra_float(2_arg)=no # Type float(2 arg)
+type_extra_float4=no # Type float4
+type_extra_float8=no # Type float8
+type_extra_image=no # Type image
+type_extra_inet=no # Type inet
+type_extra_int(1_arg)_zerofill=no # Type int(1 arg) zerofill
+type_extra_int1=no # Type int1
+type_extra_int2=no # Type int2
+type_extra_int3=no # Type int3
+type_extra_int4=no # Type int4
+type_extra_int8=no # Type int8
+type_extra_int_auto_increment=no # Type int not null auto_increment
+type_extra_int_identity=no # Type int not null identity
+type_extra_int_unsigned=no # Type int unsigned
+type_extra_interval=no # Type interval
+type_extra_line=no # Type line
+type_extra_long=no # Type long
+type_extra_long_raw=no # Type long raw
+type_extra_long_varbinary=no # Type long varbinary
+type_extra_long_varchar(1_arg)=no # Type long varchar(1 arg)
+type_extra_lseg=no # Type lseg
+type_extra_macaddr=no # Type macaddr
+type_extra_mediumint=no # Type mediumint
+type_extra_mediumtext=no # Type mediumtext
+type_extra_middleint=no # Type middleint
+type_extra_mlslabel=no # Type mlslabel
+type_extra_money=no # Type money
+type_extra_nclob=no # Type nclob
+type_extra_number=no # Type number
+type_extra_number(1_arg)=no # Type number(1 arg)
+type_extra_number(2_arg)=no # Type number(2 arg)
+type_extra_nvarchar2(1_arg)=no # Type nvarchar2(1 arg)
+type_extra_path=no # Type path
+type_extra_point=no # Type point
+type_extra_polygon=no # Type polygon
+type_extra_raw(1_arg)=no # Type raw(1 arg)
+type_extra_reltime=no # Type reltime
+type_extra_rowid=no # Type rowid
+type_extra_serial=no # Type serial
+type_extra_set(1_arg)=no # Type set(1 arg)
+type_extra_smalldatetime=no # Type smalldatetime
+type_extra_smallfloat=no # Type smallfloat
+type_extra_smallmoney=no # Type smallmoney
+type_extra_text=no # Type text
+type_extra_text(1_arg)=no # Type text(1 arg)
+type_extra_timespan=no # Type timespan
+type_extra_uint=no # Type uint
+type_extra_varchar2(1_arg)=no # Type varchar2(1 arg)
+type_extra_year=no # Type year
+type_odbc_bigint=no # Type bigint
+type_odbc_binary(1_arg)=no # Type binary(1 arg)
+type_odbc_datetime=no # Type datetime
+type_odbc_tinyint=no # Type tinyint
+type_odbc_varbinary(1_arg)=no # Type varbinary(1 arg)
+type_sql_bit=no # Type bit
+type_sql_bit(1_arg)=no # Type bit(1 arg)
+type_sql_bit_varying(1_arg)=no # Type bit varying(1 arg)
+type_sql_boolean=no # Type boolean
+type_sql_char(1_arg)=yes # Type char(1 arg)
+type_sql_char_varying(1_arg)=yes # Type char varying(1 arg)
+type_sql_character(1_arg)=yes # Type character(1 arg)
+type_sql_character_varying(1_arg)=yes # Type character varying(1 arg)
+type_sql_date=no # Type date
+type_sql_dec(2_arg)=yes # Type dec(2 arg)
+type_sql_decimal(2_arg)=yes # Type decimal(2 arg)
+type_sql_double_precision=yes # Type double precision
+type_sql_float=yes # Type float
+type_sql_float(1_arg)=yes # Type float(1 arg)
+type_sql_int=yes # Type int
+type_sql_integer=yes # Type integer
+type_sql_interval_day=no # Type interval day
+type_sql_interval_day_to_hour=no # Type interval day to hour
+type_sql_interval_day_to_minute=no # Type interval day to minute
+type_sql_interval_day_to_second=no # Type interval day to second
+type_sql_interval_hour=no # Type interval hour
+type_sql_interval_hour_to_minute=no # Type interval hour to minute
+type_sql_interval_hour_to_second=no # Type interval hour to second
+type_sql_interval_minute=no # Type interval minute
+type_sql_interval_minute_to_second=no # Type interval minute to second
+type_sql_interval_month=no # Type interval month
+type_sql_interval_second=no # Type interval second
+type_sql_interval_year=no # Type interval year
+type_sql_interval_year_to_month=no # Type interval year to month
+type_sql_national_char_varying(1_arg)=yes # Type national char varying(1 arg)
+type_sql_national_character(1_arg)=yes # Type national character(1 arg)
+type_sql_national_character_varying(1_arg)=yes # Type national character varying(1 arg)
+type_sql_nchar(1_arg)=yes # Type nchar(1 arg)
+type_sql_nchar_varying(1_arg)=yes # Type nchar varying(1 arg)
+type_sql_numeric(2_arg)=yes # Type numeric(2 arg)
+type_sql_real=yes # Type real
+type_sql_smallint=yes # Type smallint
+type_sql_time=no # Type time
+type_sql_timestamp=yes # Type timestamp
+type_sql_timestamp_with_time_zone=no # Type timestamp with time zone
+type_sql_varchar(1_arg)=yes # Type varchar(1 arg)
+union=yes # union
+union_all=yes # union all
+union_all_incompat=yes # union all (incompatible lists)
+union_incompat=yes # union (incompatible lists)
+unique_in_create=yes # unique in create table
+unique_null_in_create=no # unique null in create
+views=no # views
+where_string_size=32767 # constant string size in where
diff --git a/sql-bench/limits/interbase-dialect3.cfg b/sql-bench/limits/interbase-dialect3.cfg
new file mode 100644
index 00000000000..fdc93098688
--- /dev/null
+++ b/sql-bench/limits/interbase-dialect3.cfg
@@ -0,0 +1,514 @@
+#This file is automaticly generated by crash-me 1.57
+
+NEG=no # update of column= -column
+Need_cast_for_null=no # Need to cast NULL for arithmetic
+alter_add_col=yes # Alter table add column
+alter_add_constraint=yes # Alter table add constraint
+alter_add_foreign_key=yes # Alter table add foreign key
+alter_add_multi_col=with add # Alter table add many columns
+alter_add_primary_key=with constraint # Alter table add primary key
+alter_add_unique=no # Alter table add unique
+alter_alter_col=no # Alter table alter column default
+alter_change_col=no # Alter table change column
+alter_drop_col=no # Alter table drop column
+alter_drop_constraint=yes # Alter table drop constraint
+alter_drop_foreign_key=with drop constraint # Alter table drop foreign key
+alter_drop_primary_key=no # Alter table drop primary key
+alter_drop_unique=no # Alter table drop unique
+alter_modify_col=no # Alter table modify column
+alter_rename_table=no # Alter table rename table
+atomic_updates=no # atomic updates
+automatic_rowid=no # Automatic row id
+binary_numbers=yes # binary numbers (0b1001)
+binary_strings=no # binary strings (b'0110')
+case_insensitive_strings=no # Case insensitive compare
+char_is_space_filled=yes # char are space filled
+column_alias=yes # Column alias
+columns_in_order_by=37 # number of columns in order by
+comment_#=no # # as comment
+comment_--=no # -- as comment (ANSI)
+comment_/**/=yes # /* */ as comment
+comment_//=no # // as comment
+compute=no # Compute
+connections=1000 # Simultaneous connections (installation default)
+constraint_check=no # Column constraints
+constraint_check_table=no # Table constraints
+constraint_null=no # NULL constraint (SyBase style)
+crash_me_safe=yes # crash me safe
+crash_me_version=1.57 # crash me version
+create_default=yes # default value for column
+create_default_func=no # default value function for column
+create_if_not_exists=no # create table if not exists
+create_index=yes # create index
+create_schema=no # Create SCHEMA
+create_table_select=no # create table from select
+cross_join=no # cross join (same as from a,b)
+date_infinity=no # Supports 'infinity dates
+date_last=error # Supports 9999-12-31 dates
+date_one=error # Supports 0001-01-01 dates
+date_with_YY=no # Supports YY-MM-DD dates
+date_zero=no # Supports 0000-00-00 dates
+domains=no # Domains (ANSI SQL)
+double_quotes=yes # Double '' as ' in strings
+drop_if_exists=no # drop table if exists
+drop_index=yes # drop index
+drop_requires_cascade=no # drop table require cascade/restrict
+drop_restrict=no # drop table with cascade/restrict
+end_colon=yes # allows end ';'
+except=no # except
+except_all=no # except all
+except_all_incompat=no # except all (incompatible lists)
+except_incompat=no # except (incompatible lists)
+float_int_expr=yes # mixing of integer and float in expression
+foreign_key_syntax=no # foreign key syntax
+full_outer_join=yes # full outer join
+func_extra_!=no # Function NOT as '!' in SELECT
+func_extra_%=no # Function MOD as %
+func_extra_&=no # Function & (bitwise and)
+func_extra_&&=no # Function AND as '&&'
+func_extra_<>=no # Function <> in SELECT
+func_extra_==no # Function =
+func_extra_add_months=no # Function ADD_MONTHS
+func_extra_and_or=no # Function AND and OR in SELECT
+func_extra_ascii_char=no # Function ASCII_CHAR
+func_extra_ascii_code=no # Function ASCII_CODE
+func_extra_atn2=no # Function ATN2
+func_extra_auto_num2string=no # Function automatic num->string convert
+func_extra_auto_string2num=no # Function automatic string->num convert
+func_extra_between=no # Function BETWEEN in SELECT
+func_extra_binary_shifts=no # Function << and >> (bitwise shifts)
+func_extra_bit_count=no # Function BIT_COUNT
+func_extra_ceil=no # Function CEIL
+func_extra_charindex=no # Function CHARINDEX
+func_extra_chr=no # Function CHR
+func_extra_concat_as_+=no # Function concatenation with +
+func_extra_concat_list=no # Function CONCAT(list)
+func_extra_convert=no # Function CONVERT
+func_extra_cosh=no # Function COSH
+func_extra_date_format=no # Function DATE_FORMAT
+func_extra_dateadd=no # Function DATEADD
+func_extra_datediff=no # Function DATEDIFF
+func_extra_datename=no # Function DATENAME
+func_extra_datepart=no # Function DATEPART
+func_extra_elt=no # Function ELT
+func_extra_encrypt=no # Function ENCRYPT
+func_extra_field=no # Function FIELD
+func_extra_format=no # Function FORMAT
+func_extra_from_days=no # Function FROM_DAYS
+func_extra_from_unixtime=no # Function FROM_UNIXTIME
+func_extra_getdate=no # Function GETDATE
+func_extra_greatest=no # Function GREATEST
+func_extra_if=no # Function IF
+func_extra_in_num=no # Function IN on numbers in SELECT
+func_extra_in_str=no # Function IN on strings in SELECT
+func_extra_initcap=no # Function INITCAP
+func_extra_instr=no # Function LOCATE as INSTR
+func_extra_instr_oracle=no # Function INSTR (Oracle syntax)
+func_extra_instrb=no # Function INSTRB
+func_extra_interval=no # Function INTERVAL
+func_extra_last_day=no # Function LAST_DAY
+func_extra_last_insert_id=no # Function LAST_INSERT_ID
+func_extra_least=no # Function LEAST
+func_extra_lengthb=no # Function LENGTHB
+func_extra_like=no # Function LIKE in SELECT
+func_extra_like_escape=no # Function LIKE ESCAPE in SELECT
+func_extra_ln=no # Function LN
+func_extra_log(m_n)=no # Function LOG(m,n)
+func_extra_logn=no # Function LOGN
+func_extra_lpad=no # Function LPAD
+func_extra_mdy=no # Function MDY
+func_extra_mid=no # Function SUBSTRING as MID
+func_extra_months_between=no # Function MONTHS_BETWEEN
+func_extra_not=no # Function NOT in SELECT
+func_extra_not_between=no # Function NOT BETWEEN in SELECT
+func_extra_not_like=no # Function NOT LIKE in SELECT
+func_extra_odbc_convert=no # Function ODBC CONVERT
+func_extra_password=no # Function PASSWORD
+func_extra_paste=no # Function PASTE
+func_extra_patindex=no # Function PATINDEX
+func_extra_period_add=no # Function PERIOD_ADD
+func_extra_period_diff=no # Function PERIOD_DIFF
+func_extra_pow=no # Function POW
+func_extra_range=no # Function RANGE
+func_extra_regexp=no # Function REGEXP in SELECT
+func_extra_replicate=no # Function REPLICATE
+func_extra_reverse=no # Function REVERSE
+func_extra_root=no # Function ROOT
+func_extra_round1=no # Function ROUND(1 arg)
+func_extra_rpad=no # Function RPAD
+func_extra_sec_to_time=no # Function SEC_TO_TIME
+func_extra_sinh=no # Function SINH
+func_extra_str=no # Function STR
+func_extra_strcmp=no # Function STRCMP
+func_extra_stuff=no # Function STUFF
+func_extra_substrb=no # Function SUBSTRB
+func_extra_substring_index=no # Function SUBSTRING_INDEX
+func_extra_sysdate=no # Function SYSDATE
+func_extra_tail=no # Function TAIL
+func_extra_tanh=no # Function TANH
+func_extra_time_to_sec=no # Function TIME_TO_SEC
+func_extra_to_days=no # Function TO_DAYS
+func_extra_translate=no # Function TRANSLATE
+func_extra_trim_many_char=no # Function TRIM; Many char extension
+func_extra_trim_substring=no # Function TRIM; Substring extension
+func_extra_trunc=no # Function TRUNC
+func_extra_uid=no # Function UID
+func_extra_unix_timestamp=no # Function UNIX_TIMESTAMP
+func_extra_userenv=no # Function USERENV
+func_extra_version=no # Function VERSION
+func_extra_weekday=no # Function WEEKDAY
+func_extra_|=no # Function | (bitwise or)
+func_extra_||=no # Function OR as '||'
+func_extra_~*=no # Function ~* (case insensitive compare)
+func_odbc_abs=no # Function ABS
+func_odbc_acos=no # Function ACOS
+func_odbc_ascii=no # Function ASCII
+func_odbc_asin=no # Function ASIN
+func_odbc_atan=no # Function ATAN
+func_odbc_atan2=no # Function ATAN2
+func_odbc_ceiling=no # Function CEILING
+func_odbc_char=no # Function CHAR
+func_odbc_concat=no # Function CONCAT(2 arg)
+func_odbc_cos=no # Function COS
+func_odbc_cot=no # Function COT
+func_odbc_curdate=no # Function CURDATE
+func_odbc_curtime=no # Function CURTIME
+func_odbc_database=no # Function DATABASE
+func_odbc_dayname=no # Function DAYNAME
+func_odbc_dayofmonth=no # Function DAYOFMONTH
+func_odbc_dayofweek=no # Function DAYOFWEEK
+func_odbc_dayofyear=no # Function DAYOFYEAR
+func_odbc_degrees=no # Function DEGREES
+func_odbc_difference=no # Function DIFFERENCE()
+func_odbc_exp=no # Function EXP
+func_odbc_floor=no # Function FLOOR
+func_odbc_fn_left=no # Function ODBC syntax LEFT & RIGHT
+func_odbc_hour=no # Function HOUR
+func_odbc_hour_time=no # Function ANSI HOUR
+func_odbc_ifnull=no # Function IFNULL
+func_odbc_insert=no # Function INSERT
+func_odbc_lcase=no # Function LCASE
+func_odbc_left=no # Function LEFT
+func_odbc_length=no # Function REAL LENGTH
+func_odbc_length_without_space=no # Function ODBC LENGTH
+func_odbc_locate_2=no # Function LOCATE(2 arg)
+func_odbc_locate_3=no # Function LOCATE(3 arg)
+func_odbc_log=no # Function LOG
+func_odbc_log10=no # Function LOG10
+func_odbc_ltrim=no # Function LTRIM
+func_odbc_minute=no # Function MINUTE
+func_odbc_mod=no # Function MOD
+func_odbc_month=no # Function MONTH
+func_odbc_monthname=no # Function MONTHNAME
+func_odbc_now=no # Function NOW
+func_odbc_pi=no # Function PI
+func_odbc_power=no # Function POWER
+func_odbc_quarter=no # Function QUARTER
+func_odbc_radians=no # Function RADIANS
+func_odbc_rand=no # Function RAND
+func_odbc_repeat=no # Function REPEAT
+func_odbc_replace=no # Function REPLACE
+func_odbc_right=no # Function RIGHT
+func_odbc_round=no # Function ROUND(2 arg)
+func_odbc_rtrim=no # Function RTRIM
+func_odbc_second=no # Function SECOND
+func_odbc_sign=no # Function SIGN
+func_odbc_sin=no # Function SIN
+func_odbc_soundex=no # Function SOUNDEX
+func_odbc_space=no # Function SPACE
+func_odbc_sqrt=no # Function SQRT
+func_odbc_substring=no # Function ODBC SUBSTRING
+func_odbc_tan=no # Function TAN
+func_odbc_timestampadd=no # Function TIMESTAMPADD
+func_odbc_timestampdiff=no # Function TIMESTAMPDIFF
+func_odbc_truncate=no # Function TRUNCATE
+func_odbc_ucase=no # Function UCASE
+func_odbc_user()=no # Function USER()
+func_odbc_week=no # Function WEEK
+func_odbc_year=no # Function YEAR
+func_sql_+=yes # Function +, -, * and /
+func_sql_bit_length=no # Function BIT_LENGTH
+func_sql_cast=yes # Function CAST
+func_sql_char_length=no # Function CHAR_LENGTH
+func_sql_char_length(constant)=no # Function CHAR_LENGTH(constant)
+func_sql_character_length=no # Function CHARACTER_LENGTH
+func_sql_coalesce=no # Function COALESCE
+func_sql_concat_as_||=yes # Function concatenation with ||
+func_sql_current_date=yes # Function CURRENT_DATE
+func_sql_current_time=yes # Function CURRENT_TIME
+func_sql_current_timestamp=yes # Function CURRENT_TIMESTAMP
+func_sql_current_user=no # Function CURRENT_USER
+func_sql_extract_sql=yes # Function EXTRACT
+func_sql_localtime=no # Function LOCALTIME
+func_sql_localtimestamp=no # Function LOCALTIMESTAMP
+func_sql_lower=no # Function LOWER
+func_sql_nullif_num=no # Function NULLIF with numbers
+func_sql_nullif_string=no # Function NULLIF with strings
+func_sql_octet_length=no # Function OCTET_LENGTH
+func_sql_position=no # Function POSITION
+func_sql_searched_case=no # Function searched CASE
+func_sql_session_user=no # Function SESSION_USER
+func_sql_simple_case=no # Function simple CASE
+func_sql_substring=no # Function ANSI SQL SUBSTRING
+func_sql_system_user=no # Function SYSTEM_USER
+func_sql_trim=no # Function TRIM
+func_sql_upper=yes # Function UPPER
+func_sql_user=yes # Function USER
+func_where_between=yes # Function BETWEEN
+func_where_eq_all=yes # Function = ALL
+func_where_eq_any=yes # Function = ANY
+func_where_eq_some=yes # Function = SOME
+func_where_exists=yes # Function EXISTS
+func_where_in_num=yes # Function IN on numbers
+func_where_like=yes # Function LIKE
+func_where_like_escape=yes # Function LIKE ESCAPE
+func_where_match=no # Function MATCH
+func_where_match_unique=no # Function MATCH UNIQUE
+func_where_matches=no # Function MATCHES
+func_where_not_between=yes # Function NOT BETWEEN
+func_where_not_exists=yes # Function NOT EXISTS
+func_where_not_like=yes # Function NOT LIKE
+func_where_not_unique=no # Function NOT UNIQUE
+func_where_unique=no # Function UNIQUE
+functions=yes # Functions
+group_by=yes # Group by
+group_by_alias=no # Group by alias
+group_by_null=yes # Group on column with null values
+group_by_position=no # Group by position
+group_distinct_functions=yes # Group functions with distinct
+group_func_extra_bit_and=no # Group function BIT_AND
+group_func_extra_bit_or=no # Group function BIT_OR
+group_func_extra_count_distinct_list=no # Group function COUNT(DISTINCT expr,expr,...)
+group_func_extra_std=no # Group function STD
+group_func_extra_stddev=no # Group function STDDEV
+group_func_extra_variance=no # Group function VARIANCE
+group_func_sql_any=no # Group function ANY
+group_func_sql_avg=yes # Group function AVG
+group_func_sql_count_*=yes # Group function COUNT (*)
+group_func_sql_count_column=yes # Group function COUNT column name
+group_func_sql_count_distinct=yes # Group function COUNT(DISTINCT expr)
+group_func_sql_every=no # Group function EVERY
+group_func_sql_max=yes # Group function MAX on numbers
+group_func_sql_max_str=yes # Group function MAX on strings
+group_func_sql_min=yes # Group function MIN on numbers
+group_func_sql_min_str=yes # Group function MIN on strings
+group_func_sql_some=no # Group function SOME
+group_func_sql_sum=yes # Group function SUM
+group_functions=yes # Group functions
+group_on_unused=yes # Group on unused column
+has_true_false=no # TRUE and FALSE
+having=yes # Having
+having_with_alias=no # Having on alias
+having_with_group=yes # Having with group function
+hex_numbers=yes # hex numbers (0x41)
+hex_strings=no # hex strings (x'1ace')
+ignore_end_space=yes # Ignore end space in compare
+index_in_create=no # index in create table
+index_namespace=no # different namespace for index
+index_parts=no # index on column part (extension)
+inner_join=yes # inner join
+insert_empty_string=no # insert empty string
+insert_multi_value=no # INSERT with Value lists
+insert_select=no # insert INTO ... SELECT ...
+insert_with_set=no # INSERT with set syntax
+intersect=no # intersect
+intersect_all=no # intersect all
+intersect_all_incompat=no # intersect all (incompatible lists)
+intersect_incompat=no # intersect (incompatible lists)
+join_tables=+64 # tables in join
+left_outer_join=yes # left outer join
+left_outer_join_using=no # left outer join using
+like_with_column=no # column LIKE column
+like_with_number=no # LIKE on numbers
+lock_tables=no # lock table
+logical_value=not supported # Value of logical operation (1=1)
+max_big_expressions=1 # big expressions
+max_char_size=32767 # max char() size
+max_columns=4759 # Columns in table
+max_conditions=5888 # OR and AND in WHERE
+max_expressions=+10000 # simple expressions
+max_index=+64 # max index
+max_index_name=31 # index name length
+max_index_parts=16 # index parts
+max_index_varchar_part_length=249 # index varchar part length
+max_row_length=64744 # max table row length (without blobs)
+max_row_length_with_null=64744 # table row length with nulls (without blobs)
+max_select_alias_name=132 # select alias name length
+max_stack_expression=165 # stacked expressions
+max_table_alias_name=255 # table alias name length
+max_table_name=31 # table name length
+max_unique_index=+64 # unique indexes
+max_varchar_size=10923 # max varchar() size
+minus=no # minus
+minus_incompat=no # minus (incompatible lists)
+minus_neg=yes # Calculate 1--1
+multi_drop=no # many tables to drop table
+multi_strings=no # Multiple line strings
+multi_table_delete=no # DELETE FROM table1,table2...
+multi_table_update=no # Update with many tables
+natural_join=no # natural join
+natural_join_incompat=no # natural join (incompatible lists)
+natural_left_outer_join=no # natural left outer join
+no_primary_key=yes # Tables without primary key
+null_concat_expr=no # Is 'a' || NULL = NULL
+null_in_index=yes # null in index
+null_in_unique=no # null in unique index
+null_num_expr=no # Is 1+NULL = NULL
+nulls_in_unique=no # null combination in unique index
+odbc_left_outer_join=no # left outer join odbc style
+operating_system=Linux 2.4.4-64GB-SMP i686 # crash-me tested on
+order_by=yes # Order by
+order_by_alias=no # Order by alias
+order_by_function=no # Order by function
+order_by_position=yes # Order by position
+order_by_remember_desc=no # Order by DESC is remembered
+order_on_unused=yes # Order by on unused column
+primary_key_in_create=yes # primary key in create table
+psm_functions=no # PSM functions (ANSI SQL)
+psm_modules=no # PSM modules (ANSI SQL)
+psm_procedures=no # PSM procedures (ANSI SQL)
+psm_trigger=no # Triggers (ANSI SQL)
+query_size=65535 # query size
+quote_ident_with_"=yes # " as identifier quote (ANSI SQL)
+quote_ident_with_[=no # [] as identifier quote
+quote_ident_with_`=no # ` as identifier quote
+quote_with_"=no # Allows ' and " as string markers
+recursive_subqueries=61 # recursive subqueries
+remember_end_space=no # Remembers end space in char()
+remember_end_space_varchar=yes # Remembers end space in varchar()
+rename_table=no # rename table
+right_outer_join=yes # right outer join
+rowid=no # Type for row id
+select_constants=yes # Select constants
+select_limit=no # LIMIT number of rows
+select_limit2=no # SELECT with LIMIT #,#
+select_string_size=32767 # constant string size in SELECT
+select_table_update=yes # Update with sub select
+select_without_from=no # SELECT without FROM
+server_version=6.0.1 # server version
+simple_joins=yes # ANSI SQL simple joins
+storage_of_float=round # Storage of float values
+subqueries=yes # subqueries
+table_alias=no # Table alias
+table_name_case=yes # case independent table names
+table_wildcard=yes # Select table_name.*
+temporary_table=no # temporary tables
+transactions=error # constant string size in where
+truncate_table=no # truncate
+type_extra_abstime=no # Type abstime
+type_extra_bfile=no # Type bfile
+type_extra_blob=yes # Type blob
+type_extra_bool=no # Type bool
+type_extra_box=no # Type box
+type_extra_byte=no # Type byte
+type_extra_char(1_arg)_binary=no # Type char(1 arg) binary
+type_extra_cidr=no # Type cidr
+type_extra_circle=no # Type circle
+type_extra_clob=no # Type clob
+type_extra_datetime=no # Type datetime
+type_extra_double=no # Type double
+type_extra_enum(1_arg)=no # Type enum(1 arg)
+type_extra_float(2_arg)=no # Type float(2 arg)
+type_extra_float4=no # Type float4
+type_extra_float8=no # Type float8
+type_extra_image=no # Type image
+type_extra_inet=no # Type inet
+type_extra_int(1_arg)_zerofill=no # Type int(1 arg) zerofill
+type_extra_int1=no # Type int1
+type_extra_int2=no # Type int2
+type_extra_int3=no # Type int3
+type_extra_int4=no # Type int4
+type_extra_int8=no # Type int8
+type_extra_int_auto_increment=no # Type int not null auto_increment
+type_extra_int_identity=no # Type int not null identity
+type_extra_int_unsigned=no # Type int unsigned
+type_extra_interval=no # Type interval
+type_extra_line=no # Type line
+type_extra_long=no # Type long
+type_extra_long_raw=no # Type long raw
+type_extra_long_varbinary=no # Type long varbinary
+type_extra_long_varchar(1_arg)=no # Type long varchar(1 arg)
+type_extra_lseg=no # Type lseg
+type_extra_macaddr=no # Type macaddr
+type_extra_mediumint=no # Type mediumint
+type_extra_mediumtext=no # Type mediumtext
+type_extra_middleint=no # Type middleint
+type_extra_mlslabel=no # Type mlslabel
+type_extra_money=no # Type money
+type_extra_nclob=no # Type nclob
+type_extra_number=no # Type number
+type_extra_number(1_arg)=no # Type number(1 arg)
+type_extra_number(2_arg)=no # Type number(2 arg)
+type_extra_nvarchar2(1_arg)=no # Type nvarchar2(1 arg)
+type_extra_path=no # Type path
+type_extra_point=no # Type point
+type_extra_polygon=no # Type polygon
+type_extra_raw(1_arg)=no # Type raw(1 arg)
+type_extra_reltime=no # Type reltime
+type_extra_rowid=no # Type rowid
+type_extra_serial=no # Type serial
+type_extra_set(1_arg)=no # Type set(1 arg)
+type_extra_smalldatetime=no # Type smalldatetime
+type_extra_smallfloat=no # Type smallfloat
+type_extra_smallmoney=no # Type smallmoney
+type_extra_text=no # Type text
+type_extra_text(1_arg)=no # Type text(1 arg)
+type_extra_timespan=no # Type timespan
+type_extra_uint=no # Type uint
+type_extra_varchar2(1_arg)=no # Type varchar2(1 arg)
+type_extra_year=no # Type year
+type_odbc_bigint=no # Type bigint
+type_odbc_binary(1_arg)=no # Type binary(1 arg)
+type_odbc_datetime=no # Type datetime
+type_odbc_tinyint=no # Type tinyint
+type_odbc_varbinary(1_arg)=no # Type varbinary(1 arg)
+type_sql_=no # Type
+type_sql_bit=no # Type bit
+type_sql_bit(1_arg)=no # Type bit(1 arg)
+type_sql_bit_varying(1_arg)=no # Type bit varying(1 arg)
+type_sql_boolean=no # Type boolean
+type_sql_char(1_arg)=yes # Type char(1 arg)
+type_sql_char_varying(1_arg)=yes # Type char varying(1 arg)
+type_sql_character(1_arg)=yes # Type character(1 arg)
+type_sql_character_varying(1_arg)=yes # Type character varying(1 arg)
+type_sql_date=yes # Type date
+type_sql_dec(2_arg)=yes # Type dec(2 arg)
+type_sql_decimal(2_arg)=yes # Type decimal(2 arg)
+type_sql_double_precision=yes # Type double precision
+type_sql_float=yes # Type float
+type_sql_float(1_arg)=yes # Type float(1 arg)
+type_sql_int=yes # Type int
+type_sql_integer=yes # Type integer
+type_sql_interval_day=no # Type interval day
+type_sql_interval_day_to_hour=no # Type interval day to hour
+type_sql_interval_day_to_minute=no # Type interval day to minute
+type_sql_interval_day_to_second=no # Type interval day to second
+type_sql_interval_hour=no # Type interval hour
+type_sql_interval_hour_to_minute=no # Type interval hour to minute
+type_sql_interval_hour_to_second=no # Type interval hour to second
+type_sql_interval_minute=no # Type interval minute
+type_sql_interval_minute_to_second=no # Type interval minute to second
+type_sql_interval_month=no # Type interval month
+type_sql_interval_second=no # Type interval second
+type_sql_interval_year=no # Type interval year
+type_sql_interval_year_to_month=no # Type interval year to month
+type_sql_national_char_varying(1_arg)=yes # Type national char varying(1 arg)
+type_sql_national_character(1_arg)=yes # Type national character(1 arg)
+type_sql_national_character_varying(1_arg)=yes # Type national character varying(1 arg)
+type_sql_nchar(1_arg)=yes # Type nchar(1 arg)
+type_sql_nchar_varying(1_arg)=yes # Type nchar varying(1 arg)
+type_sql_numeric(2_arg)=yes # Type numeric(2 arg)
+type_sql_real=yes # Type real
+type_sql_smallint=yes # Type smallint
+type_sql_time=yes # Type time
+type_sql_timestamp=yes # Type timestamp
+type_sql_timestamp_with_time_zone=no # Type timestamp with time zone
+type_sql_varchar(1_arg)=yes # Type varchar(1 arg)
+union=yes # union
+union_all=yes # union all
+union_all_incompat=yes # union all (incompatible lists)
+union_incompat=yes # union (incompatible lists)
+unique_in_create=yes # unique in create table
+unique_null_in_create=no # unique null in create
+views=no # views
+where_string_size=32767 # constant string size in where
diff --git a/sql-bench/limits/interbase-superserver.cfg b/sql-bench/limits/interbase-superserver.cfg
new file mode 100644
index 00000000000..87da0d0633c
--- /dev/null
+++ b/sql-bench/limits/interbase-superserver.cfg
@@ -0,0 +1,514 @@
+#This file is automaticly generated by crash-me 1.57
+
+NEG=no # update of column= -column
+Need_cast_for_null=no # Need to cast NULL for arithmetic
+alter_add_col=yes # Alter table add column
+alter_add_constraint=yes # Alter table add constraint
+alter_add_foreign_key=yes # Alter table add foreign key
+alter_add_multi_col=with add # Alter table add many columns
+alter_add_primary_key=with constraint # Alter table add primary key
+alter_add_unique=no # Alter table add unique
+alter_alter_col=no # Alter table alter column default
+alter_change_col=no # Alter table change column
+alter_drop_col=no # Alter table drop column
+alter_drop_constraint=yes # Alter table drop constraint
+alter_drop_foreign_key=with drop constraint # Alter table drop foreign key
+alter_drop_primary_key=no # Alter table drop primary key
+alter_drop_unique=no # Alter table drop unique
+alter_modify_col=no # Alter table modify column
+alter_rename_table=no # Alter table rename table
+atomic_updates=no # atomic updates
+automatic_rowid=no # Automatic row id
+binary_numbers=yes # binary numbers (0b1001)
+binary_strings=no # binary strings (b'0110')
+case_insensitive_strings=no # Case insensitive compare
+char_is_space_filled=yes # char are space filled
+column_alias=yes # Column alias
+columns_in_order_by=37 # number of columns in order by
+comment_#=no # # as comment
+comment_--=no # -- as comment (ANSI)
+comment_/**/=yes # /* */ as comment
+comment_//=no # // as comment
+compute=no # Compute
+connections=395 # Simultaneous connections (installation default)
+constraint_check=no # Column constraints
+constraint_check_table=no # Table constraints
+constraint_null=no # NULL constraint (SyBase style)
+crash_me_safe=no # crash me safe
+crash_me_version=1.57 # crash me version
+create_default=yes # default value for column
+create_default_func=no # default value function for column
+create_if_not_exists=no # create table if not exists
+create_index=yes # create index
+create_schema=no # Create SCHEMA
+create_table_select=no # create table from select
+cross_join=no # cross join (same as from a,b)
+date_infinity=no # Supports 'infinity dates
+date_last=error # Supports 9999-12-31 dates
+date_one=error # Supports 0001-01-01 dates
+date_with_YY=no # Supports YY-MM-DD dates
+date_zero=no # Supports 0000-00-00 dates
+domains=no # Domains (ANSI SQL)
+double_quotes=yes # Double '' as ' in strings
+drop_if_exists=no # drop table if exists
+drop_index=yes # drop index
+drop_requires_cascade=no # drop table require cascade/restrict
+drop_restrict=no # drop table with cascade/restrict
+end_colon=yes # allows end ';'
+except=no # except
+except_all=no # except all
+except_all_incompat=no # except all (incompatible lists)
+except_incompat=no # except (incompatible lists)
+float_int_expr=yes # mixing of integer and float in expression
+foreign_key_syntax=no # foreign key syntax
+full_outer_join=yes # full outer join
+func_extra_!=no # Function NOT as '!' in SELECT
+func_extra_%=no # Function MOD as %
+func_extra_&=no # Function & (bitwise and)
+func_extra_&&=no # Function AND as '&&'
+func_extra_<>=no # Function <> in SELECT
+func_extra_==no # Function =
+func_extra_add_months=no # Function ADD_MONTHS
+func_extra_and_or=no # Function AND and OR in SELECT
+func_extra_ascii_char=no # Function ASCII_CHAR
+func_extra_ascii_code=no # Function ASCII_CODE
+func_extra_atn2=no # Function ATN2
+func_extra_auto_num2string=no # Function automatic num->string convert
+func_extra_auto_string2num=no # Function automatic string->num convert
+func_extra_between=no # Function BETWEEN in SELECT
+func_extra_binary_shifts=no # Function << and >> (bitwise shifts)
+func_extra_bit_count=no # Function BIT_COUNT
+func_extra_ceil=no # Function CEIL
+func_extra_charindex=no # Function CHARINDEX
+func_extra_chr=no # Function CHR
+func_extra_concat_as_+=no # Function concatenation with +
+func_extra_concat_list=no # Function CONCAT(list)
+func_extra_convert=no # Function CONVERT
+func_extra_cosh=no # Function COSH
+func_extra_date_format=no # Function DATE_FORMAT
+func_extra_dateadd=no # Function DATEADD
+func_extra_datediff=no # Function DATEDIFF
+func_extra_datename=no # Function DATENAME
+func_extra_datepart=no # Function DATEPART
+func_extra_elt=no # Function ELT
+func_extra_encrypt=no # Function ENCRYPT
+func_extra_field=no # Function FIELD
+func_extra_format=no # Function FORMAT
+func_extra_from_days=no # Function FROM_DAYS
+func_extra_from_unixtime=no # Function FROM_UNIXTIME
+func_extra_getdate=no # Function GETDATE
+func_extra_greatest=no # Function GREATEST
+func_extra_if=no # Function IF
+func_extra_in_num=no # Function IN on numbers in SELECT
+func_extra_in_str=no # Function IN on strings in SELECT
+func_extra_initcap=no # Function INITCAP
+func_extra_instr=no # Function LOCATE as INSTR
+func_extra_instr_oracle=no # Function INSTR (Oracle syntax)
+func_extra_instrb=no # Function INSTRB
+func_extra_interval=no # Function INTERVAL
+func_extra_last_day=no # Function LAST_DAY
+func_extra_last_insert_id=no # Function LAST_INSERT_ID
+func_extra_least=no # Function LEAST
+func_extra_lengthb=no # Function LENGTHB
+func_extra_like=no # Function LIKE in SELECT
+func_extra_like_escape=no # Function LIKE ESCAPE in SELECT
+func_extra_ln=no # Function LN
+func_extra_log(m_n)=no # Function LOG(m,n)
+func_extra_logn=no # Function LOGN
+func_extra_lpad=no # Function LPAD
+func_extra_mdy=no # Function MDY
+func_extra_mid=no # Function SUBSTRING as MID
+func_extra_months_between=no # Function MONTHS_BETWEEN
+func_extra_not=no # Function NOT in SELECT
+func_extra_not_between=no # Function NOT BETWEEN in SELECT
+func_extra_not_like=no # Function NOT LIKE in SELECT
+func_extra_odbc_convert=no # Function ODBC CONVERT
+func_extra_password=no # Function PASSWORD
+func_extra_paste=no # Function PASTE
+func_extra_patindex=no # Function PATINDEX
+func_extra_period_add=no # Function PERIOD_ADD
+func_extra_period_diff=no # Function PERIOD_DIFF
+func_extra_pow=no # Function POW
+func_extra_range=no # Function RANGE
+func_extra_regexp=no # Function REGEXP in SELECT
+func_extra_replicate=no # Function REPLICATE
+func_extra_reverse=no # Function REVERSE
+func_extra_root=no # Function ROOT
+func_extra_round1=no # Function ROUND(1 arg)
+func_extra_rpad=no # Function RPAD
+func_extra_sec_to_time=no # Function SEC_TO_TIME
+func_extra_sinh=no # Function SINH
+func_extra_str=no # Function STR
+func_extra_strcmp=no # Function STRCMP
+func_extra_stuff=no # Function STUFF
+func_extra_substrb=no # Function SUBSTRB
+func_extra_substring_index=no # Function SUBSTRING_INDEX
+func_extra_sysdate=no # Function SYSDATE
+func_extra_tail=no # Function TAIL
+func_extra_tanh=no # Function TANH
+func_extra_time_to_sec=no # Function TIME_TO_SEC
+func_extra_to_days=no # Function TO_DAYS
+func_extra_translate=no # Function TRANSLATE
+func_extra_trim_many_char=no # Function TRIM; Many char extension
+func_extra_trim_substring=no # Function TRIM; Substring extension
+func_extra_trunc=no # Function TRUNC
+func_extra_uid=no # Function UID
+func_extra_unix_timestamp=no # Function UNIX_TIMESTAMP
+func_extra_userenv=no # Function USERENV
+func_extra_version=no # Function VERSION
+func_extra_weekday=no # Function WEEKDAY
+func_extra_|=no # Function | (bitwise or)
+func_extra_||=no # Function OR as '||'
+func_extra_~*=no # Function ~* (case insensitive compare)
+func_odbc_abs=no # Function ABS
+func_odbc_acos=no # Function ACOS
+func_odbc_ascii=no # Function ASCII
+func_odbc_asin=no # Function ASIN
+func_odbc_atan=no # Function ATAN
+func_odbc_atan2=no # Function ATAN2
+func_odbc_ceiling=no # Function CEILING
+func_odbc_char=no # Function CHAR
+func_odbc_concat=no # Function CONCAT(2 arg)
+func_odbc_cos=no # Function COS
+func_odbc_cot=no # Function COT
+func_odbc_curdate=no # Function CURDATE
+func_odbc_curtime=no # Function CURTIME
+func_odbc_database=no # Function DATABASE
+func_odbc_dayname=no # Function DAYNAME
+func_odbc_dayofmonth=no # Function DAYOFMONTH
+func_odbc_dayofweek=no # Function DAYOFWEEK
+func_odbc_dayofyear=no # Function DAYOFYEAR
+func_odbc_degrees=no # Function DEGREES
+func_odbc_difference=no # Function DIFFERENCE()
+func_odbc_exp=no # Function EXP
+func_odbc_floor=no # Function FLOOR
+func_odbc_fn_left=no # Function ODBC syntax LEFT & RIGHT
+func_odbc_hour=no # Function HOUR
+func_odbc_hour_time=no # Function ANSI HOUR
+func_odbc_ifnull=no # Function IFNULL
+func_odbc_insert=no # Function INSERT
+func_odbc_lcase=no # Function LCASE
+func_odbc_left=no # Function LEFT
+func_odbc_length=no # Function REAL LENGTH
+func_odbc_length_without_space=no # Function ODBC LENGTH
+func_odbc_locate_2=no # Function LOCATE(2 arg)
+func_odbc_locate_3=no # Function LOCATE(3 arg)
+func_odbc_log=no # Function LOG
+func_odbc_log10=no # Function LOG10
+func_odbc_ltrim=no # Function LTRIM
+func_odbc_minute=no # Function MINUTE
+func_odbc_mod=no # Function MOD
+func_odbc_month=no # Function MONTH
+func_odbc_monthname=no # Function MONTHNAME
+func_odbc_now=no # Function NOW
+func_odbc_pi=no # Function PI
+func_odbc_power=no # Function POWER
+func_odbc_quarter=no # Function QUARTER
+func_odbc_radians=no # Function RADIANS
+func_odbc_rand=no # Function RAND
+func_odbc_repeat=no # Function REPEAT
+func_odbc_replace=no # Function REPLACE
+func_odbc_right=no # Function RIGHT
+func_odbc_round=no # Function ROUND(2 arg)
+func_odbc_rtrim=no # Function RTRIM
+func_odbc_second=no # Function SECOND
+func_odbc_sign=no # Function SIGN
+func_odbc_sin=no # Function SIN
+func_odbc_soundex=no # Function SOUNDEX
+func_odbc_space=no # Function SPACE
+func_odbc_sqrt=no # Function SQRT
+func_odbc_substring=no # Function ODBC SUBSTRING
+func_odbc_tan=no # Function TAN
+func_odbc_timestampadd=no # Function TIMESTAMPADD
+func_odbc_timestampdiff=no # Function TIMESTAMPDIFF
+func_odbc_truncate=no # Function TRUNCATE
+func_odbc_ucase=no # Function UCASE
+func_odbc_user()=no # Function USER()
+func_odbc_week=no # Function WEEK
+func_odbc_year=no # Function YEAR
+func_sql_+=yes # Function +, -, * and /
+func_sql_bit_length=no # Function BIT_LENGTH
+func_sql_cast=yes # Function CAST
+func_sql_char_length=no # Function CHAR_LENGTH
+func_sql_char_length(constant)=no # Function CHAR_LENGTH(constant)
+func_sql_character_length=no # Function CHARACTER_LENGTH
+func_sql_coalesce=no # Function COALESCE
+func_sql_concat_as_||=yes # Function concatenation with ||
+func_sql_current_date=yes # Function CURRENT_DATE
+func_sql_current_time=yes # Function CURRENT_TIME
+func_sql_current_timestamp=yes # Function CURRENT_TIMESTAMP
+func_sql_current_user=no # Function CURRENT_USER
+func_sql_extract_sql=yes # Function EXTRACT
+func_sql_localtime=no # Function LOCALTIME
+func_sql_localtimestamp=no # Function LOCALTIMESTAMP
+func_sql_lower=no # Function LOWER
+func_sql_nullif_num=no # Function NULLIF with numbers
+func_sql_nullif_string=no # Function NULLIF with strings
+func_sql_octet_length=no # Function OCTET_LENGTH
+func_sql_position=no # Function POSITION
+func_sql_searched_case=no # Function searched CASE
+func_sql_session_user=no # Function SESSION_USER
+func_sql_simple_case=no # Function simple CASE
+func_sql_substring=no # Function ANSI SQL SUBSTRING
+func_sql_system_user=no # Function SYSTEM_USER
+func_sql_trim=no # Function TRIM
+func_sql_upper=yes # Function UPPER
+func_sql_user=yes # Function USER
+func_where_between=yes # Function BETWEEN
+func_where_eq_all=yes # Function = ALL
+func_where_eq_any=yes # Function = ANY
+func_where_eq_some=yes # Function = SOME
+func_where_exists=yes # Function EXISTS
+func_where_in_num=yes # Function IN on numbers
+func_where_like=yes # Function LIKE
+func_where_like_escape=yes # Function LIKE ESCAPE
+func_where_match=no # Function MATCH
+func_where_match_unique=no # Function MATCH UNIQUE
+func_where_matches=no # Function MATCHES
+func_where_not_between=yes # Function NOT BETWEEN
+func_where_not_exists=yes # Function NOT EXISTS
+func_where_not_like=yes # Function NOT LIKE
+func_where_not_unique=no # Function NOT UNIQUE
+func_where_unique=no # Function UNIQUE
+functions=yes # Functions
+group_by=yes # Group by
+group_by_alias=no # Group by alias
+group_by_null=yes # Group on column with null values
+group_by_position=no # Group by position
+group_distinct_functions=yes # Group functions with distinct
+group_func_extra_bit_and=no # Group function BIT_AND
+group_func_extra_bit_or=no # Group function BIT_OR
+group_func_extra_count_distinct_list=no # Group function COUNT(DISTINCT expr,expr,...)
+group_func_extra_std=no # Group function STD
+group_func_extra_stddev=no # Group function STDDEV
+group_func_extra_variance=no # Group function VARIANCE
+group_func_sql_any=no # Group function ANY
+group_func_sql_avg=yes # Group function AVG
+group_func_sql_count_*=yes # Group function COUNT (*)
+group_func_sql_count_column=yes # Group function COUNT column name
+group_func_sql_count_distinct=yes # Group function COUNT(DISTINCT expr)
+group_func_sql_every=no # Group function EVERY
+group_func_sql_max=yes # Group function MAX on numbers
+group_func_sql_max_str=yes # Group function MAX on strings
+group_func_sql_min=yes # Group function MIN on numbers
+group_func_sql_min_str=yes # Group function MIN on strings
+group_func_sql_some=no # Group function SOME
+group_func_sql_sum=yes # Group function SUM
+group_functions=yes # Group functions
+group_on_unused=yes # Group on unused column
+has_true_false=no # TRUE and FALSE
+having=yes # Having
+having_with_alias=no # Having on alias
+having_with_group=yes # Having with group function
+hex_numbers=yes # hex numbers (0x41)
+hex_strings=no # hex strings (x'1ace')
+ignore_end_space=yes # Ignore end space in compare
+index_in_create=no # index in create table
+index_namespace=no # different namespace for index
+index_parts=no # index on column part (extension)
+inner_join=yes # inner join
+insert_empty_string=no # insert empty string
+insert_multi_value=no # INSERT with Value lists
+insert_select=no # insert INTO ... SELECT ...
+insert_with_set=no # INSERT with set syntax
+intersect=no # intersect
+intersect_all=no # intersect all
+intersect_all_incompat=no # intersect all (incompatible lists)
+intersect_incompat=no # intersect (incompatible lists)
+join_tables=+64 # tables in join
+left_outer_join=yes # left outer join
+left_outer_join_using=no # left outer join using
+like_with_column=no # column LIKE column
+like_with_number=no # LIKE on numbers
+lock_tables=no # lock table
+logical_value=not supported # Value of logical operation (1=1)
+max_big_expressions=1 # big expressions
+max_char_size=32745 # max char() size
+max_column_name=18 # column name length
+max_columns=4759 # Columns in table
+max_conditions=441504 # OR and AND in WHERE
+max_expressions=5486 # simple expressions
+max_index=+64 # max index
+max_index_name=31 # index name length
+max_index_parts=16 # index parts
+max_index_varchar_part_length=218 # index varchar part length
+max_row_length=64744 # max table row length (without blobs)
+max_row_length_with_null=64744 # table row length with nulls (without blobs)
+max_select_alias_name=132 # select alias name length
+max_stack_expression=165 # stacked expressions
+max_table_alias_name=255 # table alias name length
+max_table_name=31 # table name length
+max_unique_index=+64 # unique indexes
+max_varchar_size=32745 # max varchar() size
+minus=no # minus
+minus_incompat=no # minus (incompatible lists)
+minus_neg=yes # Calculate 1--1
+multi_drop=no # many tables to drop table
+multi_strings=no # Multiple line strings
+multi_table_delete=no # DELETE FROM table1,table2...
+multi_table_update=no # Update with many tables
+natural_join=no # natural join
+natural_join_incompat=no # natural join (incompatible lists)
+natural_left_outer_join=no # natural left outer join
+no_primary_key=yes # Tables without primary key
+null_concat_expr=no # Is 'a' || NULL = NULL
+null_in_index=yes # null in index
+null_in_unique=no # null in unique index
+null_num_expr=no # Is 1+NULL = NULL
+nulls_in_unique=no # null combination in unique index
+odbc_left_outer_join=no # left outer join odbc style
+operating_system=Linux 2.4.4-64GB-SMP i686 # crash-me tested on
+order_by=yes # Order by
+order_by_alias=no # Order by alias
+order_by_function=no # Order by function
+order_by_position=yes # Order by position
+order_by_remember_desc=no # Order by DESC is remembered
+order_on_unused=yes # Order by on unused column
+primary_key_in_create=yes # primary key in create table
+psm_functions=no # PSM functions (ANSI SQL)
+psm_modules=no # PSM modules (ANSI SQL)
+psm_procedures=no # PSM procedures (ANSI SQL)
+psm_trigger=no # Triggers (ANSI SQL)
+query_size=16777216 # query size
+quote_ident_with_"=yes # " as identifier quote (ANSI SQL)
+quote_ident_with_[=no # [] as identifier quote
+quote_ident_with_`=no # ` as identifier quote
+quote_with_"=no # Allows ' and " as string markers
+recursive_subqueries=61 # recursive subqueries
+remember_end_space=no # Remembers end space in char()
+remember_end_space_varchar=yes # Remembers end space in varchar()
+rename_table=no # rename table
+right_outer_join=yes # right outer join
+rowid=no # Type for row id
+select_constants=yes # Select constants
+select_limit=no # LIMIT number of rows
+select_limit2=no # SELECT with LIMIT #,#
+select_string_size=32767 # constant string size in SELECT
+select_table_update=yes # Update with sub select
+select_without_from=no # SELECT without FROM
+server_version=6.0.1 # server version
+simple_joins=yes # ANSI SQL simple joins
+storage_of_float=round # Storage of float values
+subqueries=yes # subqueries
+table_alias=no # Table alias
+table_name_case=yes # case independent table names
+table_wildcard=yes # Select table_name.*
+temporary_table=no # temporary tables
+transactions=error # constant string size in where
+truncate_table=no # truncate
+type_extra_abstime=no # Type abstime
+type_extra_bfile=no # Type bfile
+type_extra_blob=yes # Type blob
+type_extra_bool=no # Type bool
+type_extra_box=no # Type box
+type_extra_byte=no # Type byte
+type_extra_char(1_arg)_binary=no # Type char(1 arg) binary
+type_extra_cidr=no # Type cidr
+type_extra_circle=no # Type circle
+type_extra_clob=no # Type clob
+type_extra_datetime=no # Type datetime
+type_extra_double=no # Type double
+type_extra_enum(1_arg)=no # Type enum(1 arg)
+type_extra_float(2_arg)=no # Type float(2 arg)
+type_extra_float4=no # Type float4
+type_extra_float8=no # Type float8
+type_extra_image=no # Type image
+type_extra_inet=no # Type inet
+type_extra_int(1_arg)_zerofill=no # Type int(1 arg) zerofill
+type_extra_int1=no # Type int1
+type_extra_int2=no # Type int2
+type_extra_int3=no # Type int3
+type_extra_int4=no # Type int4
+type_extra_int8=no # Type int8
+type_extra_int_auto_increment=no # Type int not null auto_increment
+type_extra_int_identity=no # Type int not null identity
+type_extra_int_unsigned=no # Type int unsigned
+type_extra_interval=no # Type interval
+type_extra_line=no # Type line
+type_extra_long=no # Type long
+type_extra_long_raw=no # Type long raw
+type_extra_long_varbinary=no # Type long varbinary
+type_extra_long_varchar(1_arg)=no # Type long varchar(1 arg)
+type_extra_lseg=no # Type lseg
+type_extra_macaddr=no # Type macaddr
+type_extra_mediumint=no # Type mediumint
+type_extra_mediumtext=no # Type mediumtext
+type_extra_middleint=no # Type middleint
+type_extra_mlslabel=no # Type mlslabel
+type_extra_money=no # Type money
+type_extra_nclob=no # Type nclob
+type_extra_number=no # Type number
+type_extra_number(1_arg)=no # Type number(1 arg)
+type_extra_number(2_arg)=no # Type number(2 arg)
+type_extra_nvarchar2(1_arg)=no # Type nvarchar2(1 arg)
+type_extra_path=no # Type path
+type_extra_point=no # Type point
+type_extra_polygon=no # Type polygon
+type_extra_raw(1_arg)=no # Type raw(1 arg)
+type_extra_reltime=no # Type reltime
+type_extra_rowid=no # Type rowid
+type_extra_serial=no # Type serial
+type_extra_set(1_arg)=no # Type set(1 arg)
+type_extra_smalldatetime=no # Type smalldatetime
+type_extra_smallfloat=no # Type smallfloat
+type_extra_smallmoney=no # Type smallmoney
+type_extra_text=no # Type text
+type_extra_text(1_arg)=no # Type text(1 arg)
+type_extra_timespan=no # Type timespan
+type_extra_uint=no # Type uint
+type_extra_varchar2(1_arg)=no # Type varchar2(1 arg)
+type_extra_year=no # Type year
+type_odbc_bigint=no # Type bigint
+type_odbc_binary(1_arg)=no # Type binary(1 arg)
+type_odbc_datetime=no # Type datetime
+type_odbc_tinyint=no # Type tinyint
+type_odbc_varbinary(1_arg)=no # Type varbinary(1 arg)
+type_sql_bit=no # Type bit
+type_sql_bit(1_arg)=no # Type bit(1 arg)
+type_sql_bit_varying(1_arg)=no # Type bit varying(1 arg)
+type_sql_boolean=no # Type boolean
+type_sql_char(1_arg)=yes # Type char(1 arg)
+type_sql_char_varying(1_arg)=yes # Type char varying(1 arg)
+type_sql_character(1_arg)=yes # Type character(1 arg)
+type_sql_character_varying(1_arg)=yes # Type character varying(1 arg)
+type_sql_date=yes # Type date
+type_sql_dec(2_arg)=yes # Type dec(2 arg)
+type_sql_decimal(2_arg)=yes # Type decimal(2 arg)
+type_sql_double_precision=yes # Type double precision
+type_sql_float=yes # Type float
+type_sql_float(1_arg)=yes # Type float(1 arg)
+type_sql_int=yes # Type int
+type_sql_integer=yes # Type integer
+type_sql_interval_day=no # Type interval day
+type_sql_interval_day_to_hour=no # Type interval day to hour
+type_sql_interval_day_to_minute=no # Type interval day to minute
+type_sql_interval_day_to_second=no # Type interval day to second
+type_sql_interval_hour=no # Type interval hour
+type_sql_interval_hour_to_minute=no # Type interval hour to minute
+type_sql_interval_hour_to_second=no # Type interval hour to second
+type_sql_interval_minute=no # Type interval minute
+type_sql_interval_minute_to_second=no # Type interval minute to second
+type_sql_interval_month=no # Type interval month
+type_sql_interval_second=no # Type interval second
+type_sql_interval_year=no # Type interval year
+type_sql_interval_year_to_month=no # Type interval year to month
+type_sql_national_char_varying(1_arg)=yes # Type national char varying(1 arg)
+type_sql_national_character(1_arg)=yes # Type national character(1 arg)
+type_sql_national_character_varying(1_arg)=yes # Type national character varying(1 arg)
+type_sql_nchar(1_arg)=yes # Type nchar(1 arg)
+type_sql_nchar_varying(1_arg)=yes # Type nchar varying(1 arg)
+type_sql_numeric(2_arg)=yes # Type numeric(2 arg)
+type_sql_real=yes # Type real
+type_sql_smallint=yes # Type smallint
+type_sql_time=yes # Type time
+type_sql_timestamp=yes # Type timestamp
+type_sql_timestamp_with_time_zone=no # Type timestamp with time zone
+type_sql_varchar(1_arg)=yes # Type varchar(1 arg)
+union=yes # union
+union_all=yes # union all
+union_all_incompat=yes # union all (incompatible lists)
+union_incompat=yes # union (incompatible lists)
+unique_in_create=yes # unique in create table
+unique_null_in_create=no # unique null in create
+views=no # views
+where_string_size=32767 # constant string size in where
diff --git a/sql-bench/run-all-tests.sh b/sql-bench/run-all-tests.sh
index c2f687a9375..f392431140c 100644
--- a/sql-bench/run-all-tests.sh
+++ b/sql-bench/run-all-tests.sh
@@ -109,7 +109,9 @@ print "Running tests on: $machine\n";
print "Arguments: $log_prog_args\n";
print "Comments: $opt_comments\n";
print "Limits from: $opt_cmp\n";
-print "Server version: $server_version\n\n";
+print "Server version: $server_version\n";
+print "Optimization: $opt_optimization\n";
+print "Hardware: $opt_hw\n\n";
$estimated=$warning=$got_warning=0;
@@ -195,6 +197,10 @@ while (<test-*>)
print "Summary for $prog: ", join(" ",@prog_sum), "\n";
}
}
+ elsif ($last_line =~ /^Test skipped/i)
+ {
+ print "$last_line\n";
+ }
else
{
$errors++;
@@ -281,10 +287,6 @@ sub read_headers
{
$log_prog_args=$1;
}
- elsif (/^Comments.*:\s+(.*)$/)
- {
- $opt_comments=$1;
- }
elsif (/^Limits.*:\s+(.*)$/)
{
$opt_cmp=$1;
@@ -293,6 +295,14 @@ sub read_headers
{
$server_version=$1;
}
+ elsif (/^Optimiz.*:\s+(.*)$/)
+ {
+ $opt_optimization=$1;
+ }
+ elsif (/^Hardwar.*:\s+(.*)$/)
+ {
+ $opt_hw=$1;
+ }
}
close(TMP);
}
diff --git a/sql-bench/server-cfg.sh b/sql-bench/server-cfg.sh
index b4e134cd2c1..b8c37e5922e 100644
--- a/sql-bench/server-cfg.sh
+++ b/sql-bench/server-cfg.sh
@@ -33,10 +33,10 @@
sub get_server
{
- my ($name,$host,$database,$odbc,$machine)=@_;
+ my ($name,$host,$database,$odbc,$machine,$socket)=@_;
my ($server);
if ($name =~ /mysql/i)
- { $server=new db_MySQL($host, $database, $machine); }
+ { $server=new db_MySQL($host, $database, $machine, $socket); }
elsif ($name =~ /pg/i)
{ $server= new db_Pg($host,$database); }
elsif ($name =~ /msql/i)
@@ -73,7 +73,7 @@ sub get_server
{ $server= new db_interbase($host,$database); }
else
{
- die "Unknown sql server name used: $name\nUse one of: Access, Adabas, AdabasD, Empress, FrontBase, Oracle, Informix, DB2, mSQL, Mimer, MS-SQL, MySQL, Pg, Solid or Sybase.\nIf the connection is done trough ODBC the name must end with _ODBC\n";
+ die "Unknown sql server name used: $name\nUse one of: Access, Adabas, AdabasD, Empress, FrontBase, Oracle, Informix, InterBase, DB2, mSQL, Mimer, MS-SQL, MySQL, Pg, Solid or Sybase.\nIf the connection is done trough ODBC the name must end with _ODBC\n";
}
if ($name =~ /_ODBC$/i || defined($odbc) && $odbc)
{
@@ -106,13 +106,14 @@ package db_MySQL;
sub new
{
- my ($type,$host,$database,$machine)= @_;
+ my ($type,$host,$database,$machine,$socket)= @_;
my $self= {};
my %limits;
bless $self;
$self->{'cmp_name'} = "mysql";
- $self->{'data_source'} = "DBI:mysql:$database:$host";
+ $self->{'data_source'} = "DBI:mysql:database=$database;host=$host";
+ $self->{'data_source'} .= ";mysql_socket=$socket" if($socket);
$self->{'limits'} = \%limits;
$self->{'smds'} = \%smds;
$self->{'blob'} = "blob";
@@ -120,6 +121,7 @@ sub new
$self->{'double_quotes'} = 1; # Can handle: 'Walker''s'
$self->{'vacuum'} = 1; # When using with --fast
$self->{'drop_attr'} = "";
+ $self->{'transactions'} = 0; # Transactions disabled by default
$limits{'NEG'} = 1; # Supports -id
$limits{'alter_add_multi_col'}= 1; #Have ALTER TABLE t add a int,add b int;
@@ -144,7 +146,8 @@ sub new
$limits{'join_optimizer'} = 1; # Can optimize FROM tables
$limits{'left_outer_join'} = 1; # Supports left outer joins
$limits{'like_with_column'} = 1; # Can use column1 LIKE column2
- $limits{'limit'} = 1; # supports the limit attribute
+ $limits{'limit'} = 1; # supports the limit attribute
+ $limits{'truncate_table'} = 1;
$limits{'load_data_infile'} = 1; # Has load data infile
$limits{'lock_tables'} = 1; # Has lock tables
$limits{'max_column_name'} = 64; # max table and column name
@@ -194,12 +197,14 @@ sub new
$main::opt_create_options =~ /type=innodb/i)
{
$limits{'max_text_size'} = 8000; # Limit in Innobase
+ $self->{'transactions'} = 1; # Transactions enabled
}
if (defined($main::opt_create_options) &&
$main::opt_create_options =~ /type=gemini/i)
{
$limits{'working_blobs'} = 0; # Blobs not implemented yet
$limits{'max_tables'} = 500;
+ $self->{'transactions'} = 1; # Transactions enabled
}
return $self;
@@ -330,6 +335,12 @@ sub reconnect_on_errors
return 0;
}
+sub fix_for_insert
+{
+ my ($self,$cmd) = @_;
+ return $cmd;
+}
+
#
# Optimize tables for better performance
#
@@ -349,7 +360,6 @@ sub vacuum
}
}
-
#############################################################################
# Definitions for mSQL
#############################################################################
@@ -368,6 +378,7 @@ sub new
$self->{'limits'} = \%limits;
$self->{'double_quotes'} = 0;
$self->{'drop_attr'} = "";
+ $self->{'transactions'} = 0; # No transactions
$self->{'blob'} = "text(" . $limits{'max_text_size'} .")";
$self->{'text'} = "text(" . $limits{'max_text_size'} .")";
@@ -542,6 +553,12 @@ sub reconnect_on_errors
return 0;
}
+sub fix_for_insert
+{
+ my ($self,$cmd) = @_;
+ return $cmd;
+}
+
#############################################################################
# Definitions for PostgreSQL #
#############################################################################
@@ -563,6 +580,7 @@ sub new
$self->{'text'} = "text";
$self->{'double_quotes'} = 1;
$self->{'drop_attr'} = "";
+ $self->{'transactions'} = 1; # Transactions enabled
$self->{"vacuum"} = 1;
$limits{'join_optimizer'} = 1; # Can optimize FROM tables
$limits{'load_data_infile'} = 0;
@@ -603,6 +621,7 @@ sub new
$limits{'select_without_from'}= 1;
$limits{'subqueries'} = 1;
$limits{'table_wildcard'} = 1;
+ $limits{'truncate_table'} = 1;
$limits{'unique_index'} = 1; # Unique index works or not
$limits{'working_all_fields'} = 1;
$limits{'working_blobs'} = 1; # If big varchar/blobs works
@@ -798,6 +817,12 @@ sub reconnect_on_errors
return 0;
}
+sub fix_for_insert
+{
+ my ($self,$cmd) = @_;
+ return $cmd;
+}
+
sub vacuum
{
my ($self,$full_vacuum,$dbh_ref,@tables)=@_;
@@ -851,6 +876,7 @@ sub new
$self->{'text'} = "long varchar";
$self->{'double_quotes'} = 1;
$self->{'drop_attr'} = "";
+ $self->{'transactions'} = 1; # Transactions enabled
$limits{'max_conditions'} = 9999; # Probably big enough
$limits{'max_columns'} = 2000; # From crash-me
@@ -1063,6 +1089,12 @@ sub small_rollback_segment
return 0;
}
+sub fix_for_insert
+{
+ my ($self,$cmd) = @_;
+ return $cmd;
+}
+
sub reconnect_on_errors
{
return 0;
@@ -1092,6 +1124,7 @@ sub new
$self->{'text'} = "text";
$self->{'double_quotes'} = 1; # Can handle: 'Walker''s'
$self->{'drop_attr'} = "";
+ $self->{'transactions'} = 1; # Transactions enabled
$limits{'max_conditions'} = 1258;
$limits{'max_columns'} = 226; # server is disconnecting????
@@ -1325,6 +1358,14 @@ sub query {
return $sql;
}
+sub fix_for_insert
+{
+ my ($self,$cmd) = @_;
+ $cmd =~ s/\'\'/\' \'/g;
+ return $cmd;
+}
+
+
sub drop_index
{
my ($self,$table,$index) = @_;
@@ -1374,6 +1415,7 @@ sub new
$self->{'text'} = "long";
$self->{'double_quotes'} = 1; # Can handle: 'Walker''s'
$self->{'drop_attr'} = "";
+ $self->{'transactions'} = 1; # Transactions enabled
$self->{"vacuum"} = 1;
$limits{'max_conditions'} = 9999; # (Actually not a limit)
@@ -1385,6 +1427,7 @@ sub new
$limits{'max_index_parts'} = 16; # Max segments/key
$limits{'max_column_name'} = 32; # max table and column name
+ $limits{'truncate_table'} = 1;
$limits{'join_optimizer'} = 1; # Can optimize FROM tables
$limits{'load_data_infile'} = 0; # Has load data infile
$limits{'lock_tables'} = 0; # Has lock tables
@@ -1546,6 +1589,14 @@ sub query {
return $sql;
}
+sub fix_for_insert
+{
+ my ($self,$cmd) = @_;
+ $cmd =~ s/\'\'/\' \'/g;
+ return $cmd;
+}
+
+
sub drop_index
{
my ($self,$table,$index) = @_;
@@ -1629,6 +1680,7 @@ sub new
$self->{'text'} = "byte in table";
$self->{'double_quotes'} = 0; # Can handle: 'Walker''s'
$self->{'drop_attr'} = "";
+ $self->{'transactions'} = 1; # Transactions enabled
$self->{'host'} = $host;
$limits{'NEG'} = 1; # Supports -id
@@ -1778,6 +1830,16 @@ sub query {
return $sql;
}
+
+sub fix_for_insert
+{
+ my ($self,$cmd) = @_;
+ $cmd =~ s/\\\'//g;
+ return $cmd;
+}
+
+
+
sub drop_index
{
my ($self,$table,$index) = @_;
@@ -1805,6 +1867,7 @@ sub reconnect_on_errors
return 0;
}
+
#############################################################################
# Configuration for Access
#############################################################################
@@ -1830,6 +1893,7 @@ sub new
$self->{'text'} = "blob"; # text ?
$self->{'double_quotes'} = 1; # Can handle: 'Walker''s'
$self->{'drop_attr'} = "";
+ $self->{'transactions'} = 1; # Transactions enabled
$limits{'max_conditions'} = 97; # We get 'Query is too complex'
$limits{'max_columns'} = 255; # Max number of columns in table
@@ -1981,6 +2045,12 @@ sub reconnect_on_errors
return 1;
}
+sub fix_for_insert
+{
+ my ($self,$cmd) = @_;
+ return $cmd;
+}
+
#############################################################################
# Configuration for Microsoft SQL server
#############################################################################
@@ -2006,6 +2076,7 @@ sub new
$self->{'text'} = "text";
$self->{'double_quotes'} = 1; # Can handle: 'Walker''s'
$self->{'drop_attr'} = "";
+ $self->{'transactions'} = 1; # Transactions enabled
$limits{'max_conditions'} = 1030; # We get 'Query is too complex'
$limits{'max_columns'} = 250; # Max number of columns in table
@@ -2168,10 +2239,15 @@ sub reconnect_on_errors
return 0;
}
+sub fix_for_insert
+{
+ my ($self,$cmd) = @_;
+ return $cmd;
+}
+
#############################################################################
# Configuration for Sybase
#############################################################################
-
package db_sybase;
sub new
@@ -2182,10 +2258,10 @@ sub new
bless $self;
$self->{'cmp_name'} = "sybase";
- $self->{'data_source'} = "DBI:ODBC:$database";
+ $self->{'data_source'} = "DBI:Sybase:database=$database";
if (defined($host) && $host ne "")
{
- $self->{'data_source'} .= ":$host";
+ $self->{'data_source'} .= ";hostname=$host";
}
$self->{'limits'} = \%limits;
$self->{'smds'} = \%smds;
@@ -2193,6 +2269,7 @@ sub new
$self->{'text'} = "text";
$self->{'double_quotes'} = 1; # Can handle: 'Walker''s'
$self->{'drop_attr'} = "";
+ $self->{'transactions'} = 1; # Transactions enabled
$self->{"vacuum"} = 1;
$limits{'max_conditions'} = 1030; # We get 'Query is too complex'
@@ -2249,7 +2326,19 @@ sub new
sub version
{
my ($self)=@_;
- return "Sybase enterprise 11.5 NT"; #DBI/ODBC can't return the server version
+ my ($dbh,$sth,$version,@row);
+
+ $dbh=$self->connect();
+ $sth = $dbh->prepare('SELECT @@version') or die $DBI::errstr;
+ $version="Sybase (unknown)";
+ if ($sth->execute && (@row = $sth->fetchrow_array))
+ {
+ $version=$row[0];
+ }
+ $sth->finish;
+ $dbh->disconnect;
+ return $version;
+
}
sub connect
@@ -2257,7 +2346,7 @@ sub connect
my ($self)=@_;
my ($dbh);
$dbh=DBI->connect($self->{'data_source'}, $main::opt_user,
- $main::opt_password,{ PrintError => 0}) ||
+ $main::opt_password,{ PrintError => 0 , AutoCommit => 1}) ||
die "Got error: '$DBI::errstr' when connecting to " . $self->{'data_source'} ." with user: '$main::opt_user' password: '$main::opt_password'\n";
return $dbh;
}
@@ -2342,9 +2431,17 @@ sub reconnect_on_errors
return 0;
}
+sub fix_for_insert
+{
+ my ($self,$cmd) = @_;
+ return $cmd;
+}
+
#
# optimize the tables ....
-#
+# WARNING (from walrus)! This sub will work only from DBD:sybase
+# driver. Because if we use ODBC we don't know actual database name
+# (but DSN name only)
sub vacuum
{
my ($self,$full_vacuum,$dbh_ref)=@_;
@@ -2356,7 +2453,25 @@ sub vacuum
}
$dbh=$$dbh_ref;
$loop_time=new Benchmark;
- $dbh->do("analyze table ?? compute statistics") || die "Got error: $DBI::errstr when executing 'vacuum'\n";
+ my (@tables,$sth,$current_table,$current_base);
+ $dbh->do("dump tran $database with truncate_only");
+ $sth=$dbh->prepare("sp_tables" ) or die "prepere";
+ $sth->execute() or die "execute";
+ while (@row = $sth->fetchrow_array()) {
+ $current_table = $row[2];
+ $current_base = $row[0];
+ next if ($current_table =~ /^sys/);
+ push(@tables,$current_table) if ($database == $current_base);
+ }
+
+ $sth->finish();
+
+ foreach $table (@tables) {
+# print "$table: \n";
+ $dbh->do("update statistics $table") or print "Oops!";
+ }
+
+# $dbh->do("analyze table ?? compute statistics") || die "Got error: $DBI::errstr when executing 'vacuum'\n";
$end_time=new Benchmark;
print "Time for book-keeping (1): " .
Benchmark::timestr(Benchmark::timediff($end_time, $loop_time),"all") . "\n\n";
@@ -2364,6 +2479,8 @@ sub vacuum
}
+
+
#############################################################################
# Definitions for Adabas
#############################################################################
@@ -2385,6 +2502,7 @@ sub new
$self->{'text'} = "long";
$self->{'double_quotes'} = 1; # Can handle: 'Walker''s'
$self->{'drop_attr'} = "";
+ $self->{'transactions'} = 1; # Transactions enabled
$limits{'max_conditions'} = 50; # (Actually not a limit)
$limits{'max_columns'} = 254; # Max number of columns in table
@@ -2574,6 +2692,12 @@ sub reconnect_on_errors
return 0;
}
+sub fix_for_insert
+{
+ my ($self,$cmd) = @_;
+ return $cmd;
+}
+
#############################################################################
# Configuration for IBM DB2
#############################################################################
@@ -2599,6 +2723,7 @@ sub new
$self->{'text'} = "varchar(255)";
$self->{'double_quotes'} = 1; # Can handle: 'Walker''s'
$self->{'drop_attr'} = "";
+ $self->{'transactions'} = 1; # Transactions enabled
$limits{'max_conditions'} = 418; # We get 'Query is too complex'
$limits{'max_columns'} = 500; # Max number of columns in table
@@ -2747,6 +2872,12 @@ sub reconnect_on_errors
return 0;
}
+sub fix_for_insert
+{
+ my ($self,$cmd) = @_;
+ return $cmd;
+}
+
#############################################################################
# Configuration for MIMER
#############################################################################
@@ -2768,6 +2899,7 @@ sub new
$self->{'text'} = "character varying(15000)";
$self->{'double_quotes'} = 1; # Can handle: 'Walker''s'
$self->{'drop_attr'} = "";
+ $self->{'transactions'} = 1; # Transactions enabled
$self->{'char_null'} = "cast(NULL as char(1))";
$self->{'numeric_null'} = "cast(NULL as int)";
@@ -2836,7 +2968,6 @@ sub new
$smds{'q15'} = 'd';
$smds{'q16'} = 'a';
$smds{'q17'} = 'c';
-
return $self;
}
@@ -2885,23 +3016,35 @@ sub connect
sub create
{
my($self,$table_name,$fields,$index,$options) = @_;
- my($query,@queries);
+ my($query,@queries,@indexes);
$query="create table $table_name (";
foreach $field (@$fields)
{
$field =~ s/ decimal/ double(10,2)/i;
$field =~ s/ big_decimal/ double(10,2)/i;
- $field =~ s/ date/ int/i; # Because of tcp ?
+ $field =~ s/ tinyint\(.*\)/ smallint/i;
+ $field =~ s/ smallint\(.*\)/ smallint/i;
+ $field =~ s/ mediumint/ integer/i;
+ $field =~ s/ float\(.*\)/ float/i;
+# $field =~ s/ date/ int/i; # Because of tcp ?
$query.= $field . ',';
}
foreach $index (@$index)
{
- $query.= $index . ',';
+ if ( $index =~ /\bINDEX\b/i )
+ {
+ my @fields = split(' ',$index);
+ my $query="CREATE INDEX $fields[1] ON $table_name $fields[2]";
+ push(@indexes,$query);
+
+ } else {
+ $query.= $index . ',';
+ }
}
substr($query,-1)=")"; # Remove last ',';
$query.=" $options" if (defined($options));
- push(@queries,$query);
+ push(@queries,$query,@indexes);
return @queries;
}
@@ -2947,6 +3090,12 @@ sub reconnect_on_errors
return 0;
}
+sub fix_for_insert
+{
+ my ($self,$cmd) = @_;
+ return $cmd;
+}
+
#############################################################################
# Configuration for InterBase
#############################################################################
@@ -2961,13 +3110,14 @@ sub new
bless $self;
$self->{'cmp_name'} = "interbase";
- $self->{'data_source'} = "DBI:InterBase:database=$database";
+ $self->{'data_source'} = "DBI:InterBase:database=$database:ib_dialect=3";
$self->{'limits'} = \%limits;
$self->{'smds'} = \%smds;
$self->{'blob'} = "blob";
$self->{'text'} = "";
$self->{'double_quotes'} = 1; # Can handle: 'Walker''s'
$self->{'drop_attr'} = "";
+ $self->{'transactions'} = 1; # Transactions enabled
$self->{'char_null'} = "";
$self->{'numeric_null'} = "";
@@ -3159,6 +3309,12 @@ sub reconnect_on_errors
return 1;
}
+sub fix_for_insert
+{
+ my ($self,$cmd) = @_;
+ return $cmd;
+}
+
#############################################################################
# Configuration for FrontBase
#############################################################################
@@ -3180,6 +3336,7 @@ sub new
$self->{'text'} = "varchar(8000000)";
$self->{'double_quotes'} = 1; # Can handle: 'Walker''s'
$self->{'drop_attr'} = ' restrict';
+ $self->{'transactions'} = 1; # Transactions enabled
$self->{'error_on_execute_means_zero_rows'}=1;
$limits{'max_conditions'} = 5427; # (Actually not a limit)
@@ -3247,13 +3404,13 @@ sub version
my ($self)=@_;
my ($dbh,$sth,$version,@row);
- $dbh=$self->connect();
+# $dbh=$self->connect();
#
# Pick up SQLGetInfo option SQL_DBMS_VER (18)
#
#$version = $dbh->func(18, GetInfo);
- $version="FrontBase 2.1";
- $dbh->disconnect;
+ $version="FrontBase 3.3";
+# $dbh->disconnect;
return $version;
}
@@ -3288,7 +3445,7 @@ sub connect
sub create
{
my($self,$table_name,$fields,$index,$options) = @_;
- my($query,@queries);
+ my($query,@queries,@indexes,@keys);
$query="create table $table_name (";
foreach $field (@$fields)
@@ -3306,18 +3463,18 @@ sub create
}
foreach $ind (@$index)
{
- my @index;
- if ( $ind =~ /\bKEY\b/i ){
+# my @index;
+ if ( $ind =~ /(\bKEY\b)|(\bUNIQUE\b)/i ){
push(@keys,"ALTER TABLE $table_name ADD $ind");
}else{
- my @fields = split(' ',$index);
+ my @fields = split(' ',$ind);
my $query="CREATE INDEX $fields[1] ON $table_name $fields[2]";
- push(@index,$query);
+ push(@indexes,$query);
}
}
substr($query,-1)=")"; # Remove last ',';
$query.=" $options" if (defined($options));
- push(@queries,$query);
+ push(@queries,$query,@keys,@indexes);
return @queries;
}
@@ -3363,4 +3520,10 @@ sub reconnect_on_errors
return 1;
}
+sub fix_for_insert
+{
+ my ($self,$cmd) = @_;
+ return $cmd;
+}
+
1;
diff --git a/sql-bench/test-ATIS.sh b/sql-bench/test-ATIS.sh
index 77e0e7d79bf..ac3d7360198 100644
--- a/sql-bench/test-ATIS.sh
+++ b/sql-bench/test-ATIS.sh
@@ -106,6 +106,12 @@ if (!$opt_skip_create)
}
else
{
+ if ($opt_fast && $server->{transactions})
+ {
+ $dbh->{AutoCommit} = 0;
+ print "Transactions enabled\n" if ($opt_debug);
+ }
+
for ($ti = 0; $ti <= $#table_names; $ti++)
{
my $table_name = $table_names[$ti];
@@ -119,8 +125,7 @@ if (!$opt_skip_create)
chomp;
next unless ( $_ =~ /\w/ ); # skip blank lines
my $command = $insert_start . $_ . ")";
- $command =~ s/\'\'/\' \'/g if ($opt_server =~ /empress/i || $opt_server =~ /oracle/i);
- $command =~ s/\\'//g if ($opt_server =~ /informix/i);
+ $command = $server->fix_for_insert($command);
print "$command\n" if ($opt_debug);
$command =~ s/\\'/\'\'/g if ($double_quotes);
@@ -128,8 +133,14 @@ if (!$opt_skip_create)
$row_count++;
}
}
+ if ($opt_fast && $server->{transactions})
+ {
+ $dbh->commit;
+ $dbh->{AutoCommit} = 1;
+ }
close(DATA);
}
+
if ($opt_lock_tables)
{
$dbh->do("UNLOCK TABLES");
@@ -213,7 +224,7 @@ print "Retrieving data\n";
"SELECT airport.country_name,state.state_name,city.city_name,airport_service.direction FROM airport_service,state,airport,city WHERE airport_service.city_code=city.city_code AND airport_service.airport_code=airport.airport_code AND state.state_code=airport.state_code AND state.state_code=city.state_code AND airport.state_code=city.state_code AND airport.country_name=city.country_name AND airport.country_name=state.country_name AND city.time_zone_code=airport.time_zone_code GROUP BY airport.country_name,state.state_name,city.city_name,airport_service.direction ORDER BY state_name DESC",11,$limits->{'group_functions'},
"SELECT airport.country_name,state.state_name,city.city_name,airport_service.direction FROM airport_service,state,airport,city WHERE airport_service.city_code=city.city_code AND airport_service.airport_code=airport.airport_code AND state.state_code=airport.state_code AND state.state_code=city.state_code AND airport.state_code=city.state_code AND airport.country_name=city.country_name AND airport.country_name=state.country_name AND city.time_zone_code=airport.time_zone_code GROUP BY airport.country_name,state.state_name,city.city_name,airport_service.direction ORDER BY state_name",11,$limits->{'group_functions'},
"SELECT from_airport,to_airport,fare.fare_class,night,one_way_cost,rnd_trip_cost,class_days FROM compound_class,fare WHERE compound_class.fare_class=fare.fare_class AND one_way_cost <= 825 AND one_way_cost >= 280 AND from_airport='SFO' AND to_airport='DFW' GROUP BY from_airport,to_airport,fare.fare_class,night,one_way_cost,rnd_trip_cost,class_days ORDER BY one_way_cost",10,$limits->{'group_functions'},
- "select engines,category,cruising_speed,from_airport,to_airport FROM aircraft,flight WHERE category='JET' AND ENGINES >= 1 AND aircraft.aircraft_code=flight.aircraft_code AND to_airport NOT LIKE from_airport AND stops>0 GROUP BY engines,category,cruising_speed,from_airport,to_airport ORDER BY engines DESC",29,$limits->{'group_functions'} && $limits->{'like_with_column'},
+ "select engines,category,cruising_speed,from_airport,to_airport FROM aircraft,flight WHERE category='JET' AND engines >= 1 AND aircraft.aircraft_code=flight.aircraft_code AND to_airport NOT LIKE from_airport AND stops>0 GROUP BY engines,category,cruising_speed,from_airport,to_airport ORDER BY engines DESC",29,$limits->{'group_functions'} && $limits->{'like_with_column'},
);
@Q=(\@Q1,\@Q2,\@Q21,\@Q3,\@Q4);
diff --git a/sql-bench/test-alter-table.sh b/sql-bench/test-alter-table.sh
index 276c4863d8c..cc6453188de 100644
--- a/sql-bench/test-alter-table.sh
+++ b/sql-bench/test-alter-table.sh
@@ -74,11 +74,25 @@ do_many($dbh,$server->create("bench",\@fields,\@index));
print "Insert data into the table\n";
$loop_time=new Benchmark;
+
+if ($opt_fast && $server->{transactions})
+{
+ $dbh->{AutoCommit} = 0;
+ print "Transactions enabled\n" if ($opt_debug);
+}
+
for ($i=0 ; $i < $opt_row_count ; $i++)
{
$query="insert into bench values ( " . ("$i," x ($opt_start_field_count-1)) . "$i)";
$dbh->do($query) or die $DBI::errstr;
}
+
+if ($opt_fast && $server->{transactions})
+{
+ $dbh->commit;
+ $dbh->{AutoCommit} = 1;
+}
+
$end_time=new Benchmark;
print "Time for insert ($opt_row_count)",
diff --git a/sql-bench/test-big-tables.sh b/sql-bench/test-big-tables.sh
index ac942f2b571..151a169d31f 100644
--- a/sql-bench/test-big-tables.sh
+++ b/sql-bench/test-big-tables.sh
@@ -127,14 +127,28 @@ end_benchmark($start_time);
sub test_query
{
my($test_text,$result_text,$query,$dbh,$count)=@_;
- my($i,$loop_time,$end_time);
+ my($i,$loop_time,$end_time, $using_transactions);
print $test_text . "\n";
$loop_time=new Benchmark;
+
+ $using_transactions=0;
+ if ($opt_fast && server->{transactions} && $query=~ /^insert /i)
+ {
+ $using_transactions=1;
+ $dbh->{AutoCommit} = 0;
+ print "Transactions enabled\n" if ($opt_debug);
+ }
for ($i=0 ; $i < $count ; $i++)
{
defined(fetch_all_rows($dbh,$query)) or die $DBI::errstr;
}
+ if ($using_transactions)
+ {
+ $dbh->commit;
+ $dbh->{AutoCommit} = 1;
+ }
+
$end_time=new Benchmark;
print $result_text . "($count): " .
timestr(timediff($end_time, $loop_time),"all") . "\n\n";
diff --git a/sql-bench/test-connect.sh b/sql-bench/test-connect.sh
index 862161e3a03..0f1aca5aaa7 100644
--- a/sql-bench/test-connect.sh
+++ b/sql-bench/test-connect.sh
@@ -27,7 +27,7 @@
use DBI;
use Benchmark;
-$opt_loop_count=10000; # Change this to make test harder/easier
+$opt_loop_count=100000; # Change this to make test harder/easier
$str_length=65000; # This is the length of blob strings in PART:5
$max_test=20; # How many times to test if the server is busy
@@ -43,9 +43,10 @@ if ($opt_small_test)
}
$opt_loop_count=min(1000, $opt_loop_count) if ($opt_tcpip);
+$small_loop_count=$opt_loop_count/10; # For connect tests
print "Testing the speed of connecting to the server and sending of data\n";
-print "All tests are done $opt_loop_count times\n\n";
+print "Connect tests are done $small_loop_count times and other tests $opt_loop_count times\n\n";
################################# PART:1 ###################################
####
@@ -59,7 +60,7 @@ print "Testing connection/disconnect\n";
$loop_time=new Benchmark;
$errors=0;
-for ($i=0 ; $i < $opt_loop_count ; $i++)
+for ($i=0 ; $i < $small_loop_count ; $i++)
{
print "$i " if (($opt_debug));
for ($j=0; $j < $max_test ; $j++)
@@ -80,27 +81,27 @@ for ($i=0 ; $i < $opt_loop_count ; $i++)
}
$end_time=new Benchmark;
print "Warning: $errors connections didn't work without a time delay\n" if ($errors);
-print "Time to connect ($opt_loop_count): " .
+print "Time to connect ($small_loop_count): " .
timestr(timediff($end_time, $loop_time),"all") . "\n\n";
################################# PART:2 ###################################
#### Now we shall do first one connect, then simple select
#### (select 1..) and then close connection. This will be
-#### done $opt_loop_count times.
+#### done $small_loop_count times.
if ($limits->{'select_without_from'})
{
print "Test connect/simple select/disconnect\n";
$loop_time=new Benchmark;
- for ($i=0; $i<$opt_loop_count; $i++)
+ for ($i=0; $i < $small_loop_count; $i++)
{
$dbh = DBI->connect($server->{'data_source'}, $opt_user, $opt_password) || die $DBI::errstr;
- $sth = $dbh->do("select 1") or die $DBI::errstr;
+ $sth = $dbh->do("select $i") or die $DBI::errstr;
$dbh->disconnect;
}
$end_time=new Benchmark;
- print "Time for connect+select_simple ($opt_loop_count): " .
+ print "Time for connect+select_simple ($small_loop_count): " .
timestr(timediff($end_time, $loop_time),"all") . "\n\n";
}
@@ -116,16 +117,33 @@ if ($limits->{'select_without_from'})
{
print "Test simple select\n";
$loop_time=new Benchmark;
- for ($i=0 ; $i<$opt_loop_count ; $i++)
+ for ($i=0 ; $i < $opt_loop_count ; $i++)
{
- $sth = $dbh->do("select 1") or die $DBI::errstr;
+ $sth = $dbh->do("select $i") or die $DBI::errstr;
}
$end_time=new Benchmark;
print "Time for select_simple ($opt_loop_count): " .
timestr(timediff($end_time, $loop_time),"all") . "\n\n";
}
-################################# PART:4 ###################################
+###########################################################################
+#### The same as the previous test, but always execute the same select
+#### This is done to test the query cache for real simple selects.
+
+if ($limits->{'select_without_from'})
+{
+ print "Test simple select\n";
+ $loop_time=new Benchmark;
+ for ($i=0 ; $i < $opt_loop_count ; $i++)
+ {
+ $sth = $dbh->do("select 10000") or die $DBI::errstr;
+ }
+ $end_time=new Benchmark;
+ print "Time for select_simple_cache ($opt_loop_count): " .
+ timestr(timediff($end_time, $loop_time),"all") . "\n\n";
+}
+
+##########################################################################
#### First, we'll create a simple table 'bench1'
#### Then we shall do $opt_loop_count selects from this table.
#### Table will contain very simple data.
@@ -152,7 +170,7 @@ print "Testing connect/select 1 row from table/disconnect\n";
$loop_time=new Benchmark;
$errors=0;
-for ($i=0 ; $i<$opt_loop_count ; $i++)
+for ($i=0 ; $i < $small_loop_count ; $i++)
{
for ($j=0; $j < $max_test ; $j++)
{
@@ -161,14 +179,14 @@ for ($i=0 ; $i<$opt_loop_count ; $i++)
}
die $DBI::errstr if ($j == $max_test);
- $sth = $dbh->do("select * from bench1") #Select * from table with 1 record
+ $sth = $dbh->do("select a,i,s,$i from bench1") # Select * from table with 1 record
or die $DBI::errstr;
$dbh->disconnect;
}
$end_time=new Benchmark;
print "Warning: $errors connections didn't work without a time delay\n" if ($errors);
-print "Time to connect+select_1_row ($opt_loop_count): " .
+print "Time to connect+select_1_row ($small_loop_count): " .
timestr(timediff($end_time, $loop_time),"all") . "\n\n";
#
@@ -179,9 +197,9 @@ print "Testing select 1 row from table\n";
$dbh = $server->connect();
$loop_time=new Benchmark;
-for ($i=0 ; $i<$opt_loop_count ; $i++)
+for ($i=0 ; $i < $opt_loop_count ; $i++)
{
- $sth = $dbh->do("select * from bench1") # Select * from table with 1 record
+ $sth = $dbh->do("select a,i,s,$i from bench1") # Select * from table with 1 record
or die $DBI::errstr;
}
@@ -190,8 +208,24 @@ print "Time to select_1_row ($opt_loop_count): " .
timestr(timediff($end_time, $loop_time),"all") . "\n\n";
#
-# The same test, but with 2 rows.
+# Same test (as with one row) but now with a cacheable query
#
+
+$loop_time=new Benchmark;
+
+for ($i=0 ; $i < $opt_loop_count ; $i++)
+{
+ $sth = $dbh->do("select a,i,s from bench1") # Select * from table with 1 record
+ or die $DBI::errstr;
+}
+$end_time=new Benchmark;
+print "Time to select_1_row_cache ($opt_loop_count): " .
+ timestr(timediff($end_time, $loop_time),"all") . "\n\n";
+
+#
+# The same test, but with 2 rows (not cacheable).
+#
+
print "Testing select 2 rows from table\n";
$sth = $dbh->do("insert into bench1 values(2,200,'BBB')")
@@ -199,9 +233,9 @@ $sth = $dbh->do("insert into bench1 values(2,200,'BBB')")
$loop_time=new Benchmark;
-for ($i=0 ; $i<$opt_loop_count ; $i++)
+for ($i=0 ; $i < $opt_loop_count ; $i++)
{
- $sth = $dbh->do("select * from bench1") # Select * from table with 2 record
+ $sth = $dbh->do("select a,i,s,$i from bench1") # Select * from table with 2 record
or die $DBI::errstr;
}
@@ -209,14 +243,18 @@ $end_time=new Benchmark;
print "Time to select_2_rows ($opt_loop_count): " .
timestr(timediff($end_time, $loop_time),"all") . "\n\n";
+#
+# Simple test to test speed of functions.
+#
+
if ($limits->{'functions'})
{
print "Test select with aritmetic (+)\n";
$loop_time=new Benchmark;
- for ($i=0; $i<$opt_loop_count; $i++)
+ for ($i=0; $i < $opt_loop_count; $i++)
{
- $sth = $dbh->do("select a+a+a+a+a+a+a+a+a+a from bench1") or die $DBI::errstr;
+ $sth = $dbh->do("select a+a+a+a+a+a+a+a+a+$i from bench1") or die $DBI::errstr;
}
$end_time=new Benchmark;
print "Time for select_column+column ($opt_loop_count): " .
@@ -254,9 +292,9 @@ if ($opt_fast && defined($server->{vacuum}))
$loop_time=new Benchmark;
-for ($i=0 ; $i < $opt_loop_count ; $i++)
+for ($i=0 ; $i < $small_loop_count ; $i++)
{
- $sth = $dbh->prepare("select * from bench1");
+ $sth = $dbh->prepare("select b,$i from bench1");
if (!$sth->execute || !(@row = $sth->fetchrow_array) ||
length($row[0]) != $str_length)
{
@@ -266,14 +304,14 @@ for ($i=0 ; $i < $opt_loop_count ; $i++)
}
$end_time=new Benchmark;
-print "Time to select_big_str ($opt_loop_count): " .
+print "Time to select_big_str ($small_loop_count): " .
timestr(timediff($end_time, $loop_time),"all") . "\n\n";
$sth = $dbh->do("drop table bench1" . $server->{'drop_attr'})
or do
{
# Fix for Access 2000
- die $dbh->errstr if (!$dbh->abort_if_fatal_error());
+ die $dbh->errstr if (!$server->abort_if_fatal_error());
};
if ($opt_fast && defined($server->{vacuum}))
diff --git a/sql-bench/test-insert.sh b/sql-bench/test-insert.sh
index 655e38b1b0e..085d7cce7f3 100644
--- a/sql-bench/test-insert.sh
+++ b/sql-bench/test-insert.sh
@@ -29,6 +29,7 @@
use DBI;
use Benchmark;
+use Data::Dumper;
$opt_loop_count=100000; # number of rows/3
$small_loop_count=10; # Loop for full table retrieval
@@ -132,6 +133,12 @@ else
$query="insert into bench1 (id,id2,id3,dummy1) values ";
}
+if ($opt_fast && $server->{transactions})
+{
+ $dbh->{AutoCommit} = 0;
+ print "Transactions enabled\n" if ($opt_debug);
+}
+
if (($opt_fast || $opt_fast_insert) && $server->{'limits'}->{'insert_multi_value'})
{
$query_size=$server->{'limits'}->{'query_size'};
@@ -209,6 +216,12 @@ else
}
}
+if ($opt_fast && $server->{transactions})
+{
+ $dbh->commit;
+ $dbh->{AutoCommit} = 1;
+}
+
$end_time=new Benchmark;
print "Time for insert (" . ($total_rows) . "): " .
timestr(timediff($end_time, $loop_time),"all") . "\n\n";
@@ -234,6 +247,12 @@ if ($limits->{'unique_index'})
{
print "Testing insert of duplicates\n";
$loop_time=new Benchmark;
+
+ if ($opt_fast && $server->{transactions})
+ {
+ $dbh->{AutoCommit} = 0;
+ }
+
for ($i=0 ; $i < $opt_loop_count ; $i++)
{
$tmpvar^= ((($tmpvar + 63) + $i)*3 % $opt_loop_count);
@@ -244,6 +263,11 @@ if ($limits->{'unique_index'})
die "Didn't get an error when inserting duplicate record $tmp\n";
}
}
+ if ($opt_fast && $server->{transactions})
+ {
+ $dbh->commit;
+ $dbh->{AutoCommit} = 1;
+ }
$end_time=new Benchmark;
print "Time for insert_duplicates (" . ($opt_loop_count) . "): " .
@@ -577,7 +601,6 @@ if ($limits->{'group_functions'})
}
$sth->finish;
-
$count++;
$sth=$dbh->prepare($query="select count(*),sum(id+0.0),min(id),max(id),avg(id-0.0) from bench1") or die $DBI::errstr;
$sth->execute or die $DBI::errstr;
@@ -917,13 +940,19 @@ print "Time for update_with_key (" . ($opt_loop_count*3) . "): " .
timestr(timediff($end_time, $loop_time),"all") . "\n";
$loop_time=new Benchmark;
-for ($i=0 ; $i < $opt_loop_count*3 ; $i+=3)
+$count=0;
+for ($i=1 ; $i < $opt_loop_count*3 ; $i+=3)
{
$sth = $dbh->do("update bench1 set dummy1='updated' where id=$i") or die $DBI::errstr;
+ $end_time=new Benchmark;
+ last if ($estimated=predict_query_time($loop_time,$end_time,\$i,$tests,
+ $opt_loop_count));
}
-
-$end_time=new Benchmark;
-print "Time for update_with_key_prefix (" . ($opt_loop_count) . "): " .
+if ($estimated)
+{ print "Estimated time"; }
+else
+{ print "Time"; }
+print " for update_with_key_prefix (" . ($opt_loop_count) . "): " .
timestr(timediff($end_time, $loop_time),"all") . "\n";
print "\nTesting update of all rows\n";
@@ -1167,7 +1196,7 @@ if (!$opt_skip_delete)
}
$end_time=new Benchmark;
- print "Time for delete_all ($count): " .
+ print "Time for delete_range ($count): " .
timestr(timediff($end_time, $loop_time),"all") . "\n\n";
if ($opt_lock_tables)
@@ -1203,6 +1232,7 @@ print "Insert into table with $keys keys and with a primary key with $seg parts\
# Make keys on the most important types
@types=(0,0,0,1,0,0,0,1,1,1,1,1,1,1,1,1,1); # A 1 for each char field
push(@fields,"field1 tinyint not null");
+push(@fields,"field_search tinyint not null");
push(@fields,"field2 mediumint not null");
push(@fields,"field3 smallint not null");
push(@fields,"field4 char(16) not null");
@@ -1222,9 +1252,10 @@ for ($i= 1 ; $i <= $seg ; $i++)
}
substr($query,-1)=")";
push (@keys,$query);
+push (@keys,"index index2 (field_search)");
#Create other keys
-for ($i=2 ; $i <= $keys ; $i++)
+for ($i=3 ; $i <= $keys ; $i++)
{
push(@keys,"index index$i (field$i)");
}
@@ -1242,6 +1273,11 @@ if ($server->small_rollback_segment())
}
$loop_time=new Benchmark;
+if ($opt_fast && $server->{transactions})
+{
+ $dbh->{AutoCommit} = 0;
+}
+
$fields=$#fields;
if (($opt_fast || $opt_fast_insert) && $server->{'limits'}->{'insert_multi_value'})
{
@@ -1250,11 +1286,11 @@ if (($opt_fast || $opt_fast_insert) && $server->{'limits'}->{'insert_multi_value
$res=$query;
for ($i=0; $i < $many_keys_loop_count; $i++)
{
+ $id= $i & 127;
$rand=$random[$i];
- $tmp="(" . ($i & 127) . ",$rand," . ($i & 32766) .
- ",'ABCDEF$rand',0,";
+ $tmp="($id,$id,$rand," . ($i & 32766) . ",'ABCDEF$rand',0,";
- for ($j=5; $j <= $fields ; $j++)
+ for ($j=6; $j <= $fields ; $j++)
{
$tmp.= ($types[$j] == 0) ? "$rand," : "'$rand',";
}
@@ -1275,11 +1311,12 @@ else
{
for ($i=0; $i < $many_keys_loop_count; $i++)
{
+ $id= $i & 127;
$rand=$random[$i];
- $query="insert into bench1 values (" . ($i & 127) . ",$rand," . ($i & 32767) .
+ $query="insert into bench1 values ($id,$id,$rand," . ($i & 32767) .
",'ABCDEF$rand',0,";
- for ($j=5; $j <= $fields ; $j++)
+ for ($j=6; $j <= $fields ; $j++)
{
$query.= ($types[$j] == 0) ? "$rand," : "'$rand',";
}
@@ -1288,6 +1325,13 @@ else
$dbh->do($query) or die "Got error $DBI::errstr with query: $query\n";
}
}
+
+if ($opt_fast && $server->{transactions})
+{
+ $dbh->commit;
+ $dbh->{AutoCommit} = 1;
+}
+
$end_time=new Benchmark;
print "Time for insert_key ($many_keys_loop_count): " .
timestr(timediff($end_time, $loop_time),"all") . "\n\n";
@@ -1316,11 +1360,24 @@ if ($opt_fast && defined($server->{vacuum}))
print "Testing update of keys\n";
$loop_time=new Benchmark;
+
+if ($opt_fast && $server->{transactions})
+{
+ $dbh->{AutoCommit} = 0;
+}
+
for ($i=0 ; $i< 256; $i++)
{
- $dbh->do("update bench1 set field5=1 where field1=$i")
- or die "Got error $DBI::errstr with query: update bench1 set field5=1 where field1=$i\n";
+ $dbh->do("update bench1 set field5=1 where field_search=$i")
+ or die "Got error $DBI::errstr with query: update bench1 set field5=1 where field_search=$i\n";
+}
+
+if ($opt_fast && $server->{transactions})
+{
+ $dbh->commit;
+ $dbh->{AutoCommit} = 1;
}
+
$end_time=new Benchmark;
print "Time for update_of_primary_key_many_keys (256): " .
timestr(timediff($end_time, $loop_time),"all") . "\n\n";
@@ -1360,29 +1417,31 @@ $count=0;
for ($i=0 ; $i < 128 ; $i++)
{
$count++;
- $dbh->do("delete from bench1 where field1 = $i") or die $DBI::errstr;
+ $dbh->do("delete from bench1 where field_search = $i") or die $DBI::errstr;
}
$end_time=new Benchmark;
print "Time for delete_big_many_keys ($count): " .
timestr(timediff($end_time, $loop_time),"all") . "\n\n";
+if ($opt_lock_tables)
+{
+ $sth = $dbh->do("UNLOCK TABLES") || die $DBI::errstr;
+}
+
print "Deleting everything from table\n";
$count=1;
if ($opt_fast)
{
- $dbh->do("delete from bench1") or die $DBI::errstr;
+ $query= ($limits->{'truncate_table'} ? "truncate table bench1" :
+ "delete from bench1");
+ $dbh->do($query) or die $DBI::errstr;
}
else
{
$dbh->do("delete from bench1 where field1 > 0") or die $DBI::errstr;
}
-if ($opt_lock_tables)
-{
- $sth = $dbh->do("UNLOCK TABLES") || die $DBI::errstr;
-}
-
$end_time=new Benchmark;
print "Time for delete_all_many_keys ($count): " .
timestr(timediff($end_time, $loop_time),"all") . "\n\n";
@@ -1409,12 +1468,18 @@ if ($limits->{'insert_multi_value'})
"dummy1 char(30)"],
["primary key (id,id2)",
"index index_id3 (id3)"]));
+
+ $loop_time=new Benchmark;
+
if ($opt_lock_tables)
{
$sth = $dbh->do("LOCK TABLES bench1 write") || die $DBI::errstr;
}
+ if ($opt_fast && $server->{transactions})
+ {
+ $dbh->{AutoCommit} = 0;
+ }
- $loop_time=new Benchmark;
print "Inserting $opt_loop_count rows with multiple values\n";
$query="insert into bench1 values ";
$res=$query;
@@ -1437,6 +1502,11 @@ if ($limits->{'insert_multi_value'})
{
$sth = $dbh->do("UNLOCK TABLES ") || die $DBI::errstr;
}
+ if ($opt_fast && $server->{transactions})
+ {
+ $dbh->commit;
+ $dbh->{AutoCommit} = 1;
+ }
$end_time=new Benchmark;
print "Time for multiple_value_insert (" . ($opt_loop_count) . "): " .
diff --git a/sql-bench/test-select.sh b/sql-bench/test-select.sh
index 1ecad5804c5..a5ae1da7283 100644
--- a/sql-bench/test-select.sh
+++ b/sql-bench/test-select.sh
@@ -92,6 +92,12 @@ if ($opt_fast && defined($server->{vacuum}))
print "Inserting $opt_loop_count rows\n";
$loop_time=new Benchmark;
+
+if ($opt_fast && $server->{transactions})
+{
+ $dbh->{AutoCommit} = 0;
+}
+
$query="insert into bench1 values (";
$half_done=$opt_loop_count/2;
for ($id=0,$rev_id=$opt_loop_count-1 ; $id < $opt_loop_count ; $id++,$rev_id--)
@@ -105,6 +111,12 @@ for ($id=0,$rev_id=$opt_loop_count-1 ; $id < $opt_loop_count ; $id++,$rev_id--)
}
}
+if ($opt_fast && $server->{transactions})
+{
+ $dbh->commit;
+ $dbh->{AutoCommit} = 1;
+}
+
$end_time=new Benchmark;
print "Time to insert ($opt_loop_count): " .
timestr(timediff($end_time, $loop_time),"all") . "\n\n";
@@ -141,10 +153,10 @@ if ($limits->{'group_functions'})
$loop_time=new Benchmark;
for ($tests=0 ; $tests < $opt_loop_count ; $tests++)
{
- fetch_all_rows($dbh,"select sum(idn+$tests),sum(rev_idn-$tests) from bench1");
+ fetch_all_rows($dbh,"select sum(idn+100),sum(rev_idn-100) from bench1");
}
$end_time=new Benchmark;
- print "Time for select_query_cache ($opt_loop_count): " .
+ print "Time for select_cache ($opt_loop_count): " .
timestr(timediff($end_time, $loop_time),"all") . "\n\n";
# If the database has a query cache, the following loop should be much
@@ -156,7 +168,7 @@ if ($limits->{'group_functions'})
fetch_all_rows($dbh,"select sum(idn+$tests),sum(rev_idn-$tests) from bench1");
}
$end_time=new Benchmark;
- print "Time for select_query_cache2 ($opt_loop_count): " .
+ print "Time for select_cache2 ($opt_loop_count): " .
timestr(timediff($end_time, $loop_time),"all") . "\n\n";
}
diff --git a/sql-bench/test-transactions.sh b/sql-bench/test-transactions.sh
new file mode 100644
index 00000000000..b081b89fb69
--- /dev/null
+++ b/sql-bench/test-transactions.sh
@@ -0,0 +1,297 @@
+#!@PERL@
+# Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the Free
+# Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+# MA 02111-1307, USA
+#
+# Test of transactions performance.
+#
+
+##################### Standard benchmark inits ##############################
+
+use DBI;
+use Benchmark;
+#use warnings;
+
+$opt_groups=27; # Characters are 'A' -> Z
+
+$opt_loop_count=10000; # Change this to make test harder/easier
+$opt_medium_loop_count=100; # Change this to make test harder/easier
+
+chomp($pwd = `pwd`); $pwd = "." if ($pwd eq '');
+require "$pwd/bench-init.pl" || die "Can't read Configuration file: $!\n";
+
+# Avoid warnings for variables in bench-init.pl
+# (Only works with perl 5.6)
+#our ($opt_small_test, $opt_small_tables, $opt_debug, $opt_force);
+
+if ($opt_small_test || $opt_small_tables)
+{
+ $opt_loop_count/=100;
+ $opt_medium_loop_count/=10;
+}
+
+
+if (!$server->{transactions} && !$opt_force)
+{
+ print "Test skipped because the database doesn't support transactions\n";
+ exit(0);
+}
+
+####
+#### Connect and start timeing
+####
+
+$start_time=new Benchmark;
+$dbh = $server->connect();
+
+###
+### Create Table
+###
+
+print "Creating tables\n";
+$dbh->do("drop table bench1");
+$dbh->do("drop table bench2");
+
+do_many($dbh,$server->create("bench1",
+ ["idn int NOT NULL",
+ "rev_idn int NOT NULL",
+ "region char(1) NOT NULL",
+ "grp int NOT NULL",
+ "updated tinyint NOT NULL"],
+ ["primary key (idn)",
+ "unique (region,grp)"]));
+do_many($dbh,$server->create("bench2",
+ ["idn int NOT NULL",
+ "rev_idn int NOT NULL",
+ "region char(1) NOT NULL",
+ "grp int NOT NULL",
+ "updated tinyint NOT NULL"],
+ ["primary key (idn)",
+ "unique (region,grp)"]));
+
+$dbh->{AutoCommit} = 0;
+
+###
+### Test insert perfomance
+###
+
+test_insert("bench1","insert_commit",0);
+test_insert("bench2","insert_autocommit",1);
+
+sub test_insert
+{
+ my ($table, $test_name, $auto_commit)= @_;
+ my ($loop_time,$end_time,$id,$rev_id,$grp,$region);
+
+ $dbh->{AutoCommit}= $auto_commit;
+ $loop_time=new Benchmark;
+
+ for ($id=0,$rev_id=$opt_loop_count-1 ; $id < $opt_loop_count ;
+ $id++,$rev_id--)
+ {
+ $grp=$id/$opt_groups;
+ $region=chr(65+$id%$opt_groups);
+ do_query($dbh,"insert into $table values ($id,$rev_id,'$region',$grp,0)");
+ }
+
+ $dbh->commit if (!$auto_commit);
+ $end_time=new Benchmark;
+ print "Time for $test_name ($opt_loop_count): " .
+ timestr(timediff($end_time, $loop_time),"all") . "\n\n";
+}
+
+###
+### Test rollback performance
+###
+
+print "Test transactions rollback performance\n" if($opt_debug);
+
+##
+## Insert rollback test
+##
+
+#
+# Test is done by inserting 100 rows in a table with lots of rows and
+# then doing a rollback on these
+#
+
+{
+ my ($id,$rev_id,$grp,$region,$end,$loop_time,$end_time,$commit_loop,$count);
+
+ $dbh->{AutoCommit} = 0;
+ $loop_time=new Benchmark;
+ $end=$opt_loop_count*2;
+ $count=0;
+
+ for ($commit_loop=1, $id=$opt_loop_count ; $id < $end ;
+ $id++, $commit_loop++)
+ {
+ $rev_id=$end-$id;
+ $grp=$id/$opt_groups;
+ $region=chr(65+$id%$opt_groups);
+ do_query($dbh,"insert into bench1 values ($id,$rev_id,'$region',$grp,0)");
+ if ($commit_loop >= $opt_medium_loop_count)
+ {
+ $dbh->rollback;
+ $commit_loop=0;
+ $count++;
+ }
+ }
+ if ($commit_loop > 1)
+ {
+ $dbh->rollback;
+ $count++;
+ }
+ $end_time=new Benchmark;
+ print "Time for insert_rollback ($count:$opt_loop_count): " .
+ timestr(timediff($end_time, $loop_time),"all") . "\n\n";
+}
+
+##
+## Update rollback test
+##
+
+#
+# Test is done by updating 100 rows in a table with lots of rows and
+# then doing a rollback on these
+#
+
+{
+ my ($id,$loop_time,$end_time,$commit_loop,$count);
+
+ $dbh->{AutoCommit} = 0;
+ $loop_time=new Benchmark;
+ $end=$opt_loop_count*2;
+ $count=0;
+
+ for ($commit_loop=1, $id=0 ; $id < $opt_loop_count ; $id++, $commit_loop++)
+ {
+ do_query($dbh,"update bench1 set updated=2 where idn=$id");
+ if ($commit_loop >= $opt_medium_loop_count)
+ {
+ $dbh->rollback;
+ $commit_loop=0;
+ $count++;
+ }
+ }
+ if ($commit_loop > 1)
+ {
+ $dbh->rollback;
+ $count++;
+ }
+ $end_time=new Benchmark;
+ print "Time for update_rollback ($count:$opt_loop_count): " .
+ timestr(timediff($end_time, $loop_time),"all") . "\n\n";
+}
+
+##
+## Delete rollback test
+##
+
+#
+# Test is done by deleting 100 rows in a table with lots of rows and
+# then doing a rollback on these
+#
+
+{
+ my ($id,$loop_time,$end_time,$commit_loop,$count);
+
+ $dbh->{AutoCommit} = 0;
+ $loop_time=new Benchmark;
+ $end=$opt_loop_count*2;
+ $count=0;
+
+ for ($commit_loop=1, $id=0 ; $id < $opt_loop_count ; $id++, $commit_loop++)
+ {
+ do_query($dbh,"delete from bench1 where idn=$id");
+ if ($commit_loop >= $opt_medium_loop_count)
+ {
+ $dbh->rollback;
+ $commit_loop=0;
+ $count++;
+ }
+ }
+ if ($commit_loop > 1)
+ {
+ $dbh->rollback;
+ $count++;
+ }
+ $end_time=new Benchmark;
+ print "Time for delete_rollback ($count:$opt_loop_count): " .
+ timestr(timediff($end_time, $loop_time),"all") . "\n\n";
+}
+
+
+###
+### Test update perfomance
+###
+
+test_update("bench1","update_commit",0);
+test_update("bench2","update_autocommit",1);
+
+sub test_update
+{
+ my ($table, $test_name, $auto_commit)= @_;
+ my ($loop_time,$end_time,$id);
+
+ $dbh->{AutoCommit}= $auto_commit;
+ $loop_time=new Benchmark;
+
+ for ($id=0 ; $id < $opt_loop_count ; $id++)
+ {
+ do_query($dbh,"update bench1 set updated=1 where idn=$id");
+ }
+
+ $dbh->commit if (!$auto_commit);
+ $end_time=new Benchmark;
+ print "Time for $test_name ($opt_loop_count): " .
+ timestr(timediff($end_time, $loop_time),"all") . "\n\n";
+}
+
+###
+### Test delete perfomance
+###
+
+test_delete("bench1","delete_commit",0);
+test_delete("bench2","delete_autocommit",1);
+
+sub test_delete
+{
+ my ($table, $test_name, $auto_commit)= @_;
+ my ($loop_time,$end_time,$id);
+
+ $dbh->{AutoCommit}= $auto_commit;
+ $loop_time=new Benchmark;
+
+ for ($id=0 ; $id < $opt_loop_count ; $id++)
+ {
+ do_query($dbh,"delete from $table where idn=$id");
+ }
+ $dbh->commit if (!$auto_commit);
+ $end_time=new Benchmark;
+ print "Time for $test_name ($opt_loop_count): " .
+ timestr(timediff($end_time, $loop_time),"all") . "\n\n";
+}
+
+####
+#### End of benchmark
+####
+
+$sth = $dbh->do("drop table bench1" . $server->{'drop_attr'}) or die $DBI::errstr;
+$sth = $dbh->do("drop table bench2" . $server->{'drop_attr'}) or die $DBI::errstr;
+
+$dbh->disconnect; # close connection
+end_benchmark($start_time);
diff --git a/sql-bench/test-wisconsin.sh b/sql-bench/test-wisconsin.sh
index a017120259e..adc3e5b5aa4 100644
--- a/sql-bench/test-wisconsin.sh
+++ b/sql-bench/test-wisconsin.sh
@@ -48,27 +48,36 @@ init_query();
print "Wisconsin benchmark test\n\n";
-if (!$opt_skip_create)
+if ($opt_skip_create)
{
- $loop_time= new Benchmark;
- for($ti = 0; $ti <= $#table_names; $ti++)
+ if ($opt_lock_tables)
{
- my $table_name = $table_names[$ti];
- my $array_ref = $tables[$ti];
-
- # This may fail if we have no table so do not check answer
- $sth = $dbh->do("drop table $table_name" . $server->{'drop_attr'});
- print "Creating table $table_name\n" if ($opt_verbose);
- do_many($dbh,@$array_ref);
+ @tmp=@table_names; push(@tmp,@extra_names);
+ $sth = $dbh->do("LOCK TABLES " . join(" WRITE,", @tmp) . " WRITE") ||
+ die $DBI::errstr;
}
- $end_time=new Benchmark;
- print "Time for create_table ($#tables): " .
- timestr(timediff($end_time, $loop_time),"all") . "\n\n";
+ goto start_benchmark;
+}
- if ($opt_fast && defined($server->{vacuum}))
- {
- $server->vacuum(1,\$dbh);
- }
+$loop_time= new Benchmark;
+for($ti = 0; $ti <= $#table_names; $ti++)
+{
+ my $table_name = $table_names[$ti];
+ my $array_ref = $tables[$ti];
+
+ # This may fail if we have no table so do not check answer
+ $sth = $dbh->do("drop table $table_name" . $server->{'drop_attr'});
+ print "Creating table $table_name\n" if ($opt_verbose);
+ do_many($dbh,@$array_ref);
+}
+$end_time=new Benchmark;
+print "Time for create_table ($#tables): " .
+ timestr(timediff($end_time, $loop_time),"all") . "\n\n";
+
+if ($opt_fast && defined($server->{vacuum}))
+{
+ $server->vacuum(1,\$dbh);
+}
####
@@ -100,6 +109,11 @@ if ($opt_fast && $server->{'limits'}->{'load_data_infile'})
}
else
{
+ if ($opt_fast && $server->{transactions})
+ {
+ $dbh->{AutoCommit} = 0;
+ }
+
for ($ti = 0; $ti <= $#table_names; $ti++)
{
my $table_name = $table_names[$ti];
@@ -124,10 +138,17 @@ else
}
close(DATA);
}
+
if ($opt_lock_tables)
{
do_query($dbh,"UNLOCK TABLES");
}
+if ($opt_fast && $server->{transactions})
+{
+ $dbh->commit;
+ $dbh->{AutoCommit} = 1;
+}
+
$end_time=new Benchmark;
print "Time to insert ($row_count): " .
timestr(timediff($end_time, $loop_time),"all") . "\n";
@@ -159,13 +180,6 @@ $sth = $dbh->do("delete from Bprime where Bprime.unique2 >= 1000") or
$end_time=new Benchmark;
print "Time to delete_big (1): " .
timestr(timediff($end_time, $loop_time),"all") . "\n\n";
-}
-elsif ($opt_lock_tables)
-{
- @tmp=@table_names; push(@tmp,@extra_names);
- $sth = $dbh->do("LOCK TABLES " . join(" WRITE,", @tmp) . " WRITE") ||
- die $DBI::errstr;
-}
if ($opt_fast && defined($server->{vacuum}))
{
@@ -176,7 +190,9 @@ if ($opt_fast && defined($server->{vacuum}))
#### Running the benchmark
####
-print "Running actual benchmark\n";
+start_benchmark:
+
+print "Running the actual benchmark\n";
$loop_time= new Benchmark;
$count=0;
@@ -226,7 +242,7 @@ sub init_data
{
@onek=
$server->create("onek",
- ["unique1 int(4) NOT NULL",
+ ["unique1 int(5) NOT NULL",
"unique2 int(4) NOT NULL",
"two int(4)",
"four int(4)",
diff --git a/sql/ChangeLog b/sql/ChangeLog
index 2289765afad..a75e9761766 100644
--- a/sql/ChangeLog
+++ b/sql/ChangeLog
@@ -1,3 +1,8 @@
+2000-12-07 Jeremy Cole <jeremy@mysql.com>
+
+* Added UPDATE ... ORDER BY ...
+* Added DELETE ... ORDER BY ...
+
2000-11-11 Jeremy Cole <jeremy@mysql.com>
* Added ALTER TABLE ... ORDER BY ...
diff --git a/sql/Makefile.am b/sql/Makefile.am
index 47cee300b09..e1ed9ad8915 100644
--- a/sql/Makefile.am
+++ b/sql/Makefile.am
@@ -21,27 +21,29 @@ MYSQLDATAdir = $(localstatedir)
MYSQLSHAREdir = $(pkgdatadir)
MYSQLBASEdir= $(prefix)
INCLUDES = @MT_INCLUDES@ \
- @bdb_includes@ @innodb_includes@ @gemini_includes@ \
+ @bdb_includes@ @innodb_includes@ \
-I$(srcdir)/../include \
-I$(srcdir)/../regex \
- -I$(srcdir) -I../include -I.. -I.
+ -I$(srcdir) -I../include -I. $(openssl_includes)
WRAPLIBS= @WRAPLIBS@
SUBDIRS = share
libexec_PROGRAMS = mysqld
noinst_PROGRAMS = gen_lex_hash
-gen_lex_hash_LDFLAGS = @NOINST_LDFLAGS@
-LDADD = ../isam/libnisam.a \
- ../merge/libmerge.a \
+gen_lex_hash_LDFLAGS = @NOINST_LDFLAGS@
+LDADD = @isam_libs@ \
../myisam/libmyisam.a \
../myisammrg/libmyisammrg.a \
../heap/libheap.a \
+ ../vio/libvio.a \
../mysys/libmysys.a \
../dbug/libdbug.a \
../regex/libregex.a \
../strings/libmystrings.a
+
mysqld_LDADD = @MYSQLD_EXTRA_LDFLAGS@ \
- @bdb_libs@ @innodb_libs@ @gemini_libs@ \
- $(LDADD) $(CXXLDFLAGS) $(WRAPLIBS) @LIBDL@
+ @bdb_libs@ @innodb_libs@ @pstack_libs@ \
+ @innodb_system_libs@ \
+ $(LDADD) $(CXXLDFLAGS) $(WRAPLIBS) @LIBDL@ @openssl_libs@
noinst_HEADERS = item.h item_func.h item_sum.h item_cmpfunc.h \
item_strfunc.h item_timefunc.h item_uniq.h \
item_create.h mysql_priv.h \
@@ -49,37 +51,37 @@ noinst_HEADERS = item.h item_func.h item_sum.h item_cmpfunc.h \
sql_manager.h sql_map.h sql_string.h unireg.h \
field.h handler.h \
ha_isammrg.h ha_isam.h ha_myisammrg.h\
- ha_heap.h ha_myisam.h ha_berkeley.h ha_innobase.h \
- ha_gemini.h opt_range.h opt_ft.h \
+ ha_heap.h ha_myisam.h ha_berkeley.h ha_innodb.h \
+ opt_range.h opt_ft.h \
sql_select.h structs.h table.h sql_udf.h hash_filo.h\
- lex.h lex_symbol.h sql_acl.h sql_crypt.h md5.h \
+ lex.h lex_symbol.h sql_acl.h sql_crypt.h \
log_event.h mini_client.h sql_repl.h slave.h \
- stacktrace.h
-mysqld_SOURCES = sql_lex.cc \
+ stacktrace.h sql_sort.h sql_cache.h
+mysqld_SOURCES = sql_lex.cc sql_handler.cc \
item.cc item_sum.cc item_buff.cc item_func.cc \
item_cmpfunc.cc item_strfunc.cc item_timefunc.cc \
thr_malloc.cc item_create.cc \
field.cc key.cc sql_class.cc sql_list.cc \
- net_serv.cc violite.c net_pkg.cc lock.cc my_lock.c \
+ net_serv.cc net_pkg.cc lock.cc my_lock.c \
sql_string.cc sql_manager.cc sql_map.cc \
mysqld.cc password.c hash_filo.cc hostname.cc \
convert.cc sql_parse.cc sql_yacc.yy \
sql_base.cc table.cc sql_select.cc sql_insert.cc \
- sql_update.cc sql_delete.cc sql_do.cc \
+ sql_update.cc sql_delete.cc uniques.cc sql_do.cc \
procedure.cc item_uniq.cc sql_test.cc \
log.cc log_event.cc init.cc derror.cc sql_acl.cc \
- unireg.cc \
+ unireg.cc des_key_file.cc \
time.cc opt_range.cc opt_sum.cc opt_ft.cc \
records.cc filesort.cc handler.cc \
ha_heap.cc ha_myisam.cc ha_myisammrg.cc \
- ha_berkeley.cc ha_innobase.cc ha_gemini.cc \
+ ha_berkeley.cc ha_innodb.cc \
ha_isam.cc ha_isammrg.cc \
sql_db.cc sql_table.cc sql_rename.cc sql_crypt.cc \
sql_load.cc mf_iocache.cc field_conv.cc sql_show.cc \
sql_udf.cc sql_analyse.cc sql_analyse.h sql_cache.cc \
- slave.cc sql_repl.cc \
+ slave.cc sql_repl.cc sql_union.cc \
mini_client.cc mini_client_errors.c \
- md5.c stacktrace.c
+ stacktrace.c repl_failsafe.h repl_failsafe.cc
gen_lex_hash_SOURCES = gen_lex_hash.cc
gen_lex_hash_LDADD = $(LDADD) $(CXXLDFLAGS)
diff --git a/sql/cache_manager.cc b/sql/cache_manager.cc
index 9ea25315f8c..307fe331e5c 100644
--- a/sql/cache_manager.cc
+++ b/sql/cache_manager.cc
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -18,7 +18,7 @@
#pragma implementation /* gcc: Class implementation */
#endif
-#include <global.h>
+#include <my_global.h>
#include <my_sys.h>
#include "cache_manager.h"
@@ -117,7 +117,7 @@ void *cache_manager::alloc(uint size)
{
void *llist;
void *abs_ptr;
-
+
size=ALIGN_SIZE(size+HEADER_LENGTH+SUFFIX_LENGTH);
if (!(llist = find_in_llist(size)))
{
@@ -127,7 +127,7 @@ void *cache_manager::alloc(uint size)
}
size_of_found_block=int4korr((char*) llist) & ALLOC_MASK;
// if (size_of_found_block < SMALLEST_BLOCK)
-
+
abs_ptr = link_into_abs(llist);
return abs_ptr;
}
diff --git a/sql/cache_manager.h b/sql/cache_manager.h
index fc3b8f7016a..d422a86ea8e 100644
--- a/sql/cache_manager.h
+++ b/sql/cache_manager.h
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -59,7 +59,3 @@ class cache_manager {
bool *dealloc(void *); /* Deallocate blocks (with *ptr_arg) */
void clear(void); /* Clear the cache */
};
-
-
-
-
diff --git a/sql/convert.cc b/sql/convert.cc
index 3e0fbf18ace..7a06208759c 100644
--- a/sql/convert.cc
+++ b/sql/convert.cc
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -397,19 +397,19 @@ static unsigned char win1251ukr_koi8_ukr[256] = {
****************************************************************************/
-CONVERT conv_cp1251_koi8("cp1251_koi8", cp1251_koi8, koi8_cp1251);
+CONVERT conv_cp1251_koi8("cp1251_koi8", cp1251_koi8, koi8_cp1251, 1);
#ifdef DEFINE_ALL_CHARACTER_SETS
-CONVERT conv_cp1250_latin2("cp1250_latin2", t1250_til2, til2_t1250);
-CONVERT conv_kam_latin2("kam_latin2", tkam_til2, til2_tkam);
-CONVERT conv_mac_latin2("mac_latin2", tmac_til2, til2_tmac);
-CONVERT conv_macce_latin2("macce_latin2", tmacce_til2, til2_tmacce);
-CONVERT conv_pc2_latin2("pc2_latin2", tpc2_til2, til2_tpc2);
-CONVERT conv_vga_latin2("vga_latin2", tvga_til2, til2_tvga);
-CONVERT conv_koi8_cp1251("koi8_cp1251", koi8_cp1251, cp1251_koi8);
+CONVERT conv_cp1250_latin2("cp1250_latin2", t1250_til2, til2_t1250, 2);
+CONVERT conv_kam_latin2("kam_latin2", tkam_til2, til2_tkam, 3);
+CONVERT conv_mac_latin2("mac_latin2", tmac_til2, til2_tmac, 4);
+CONVERT conv_macce_latin2("macce_latin2", tmacce_til2, til2_tmacce, 5);
+CONVERT conv_pc2_latin2("pc2_latin2", tpc2_til2, til2_tpc2, 6);
+CONVERT conv_vga_latin2("vga_latin2", tvga_til2, til2_tvga, 7);
+CONVERT conv_koi8_cp1251("koi8_cp1251", koi8_cp1251, cp1251_koi8, 8);
CONVERT conv_win1251ukr_koi8_ukr("win1251ukr_koi8_ukr", win1251ukr_koi8_ukr,
- koi8_ukr_win1251ukr);
+ koi8_ukr_win1251ukr, 9);
CONVERT conv_koi8_ukr_win1251ukr("koi8_ukr_win1251ukr", koi8_ukr_win1251ukr,
- win1251ukr_koi8_ukr);
+ win1251ukr_koi8_ukr, 10);
#endif /* DEFINE_ALL_CHARACTER_SETS */
CONVERT *convert_tables[]= {
diff --git a/sql/custom_conf.h b/sql/custom_conf.h
index af6012e28ec..19ced12bfbb 100644
--- a/sql/custom_conf.h
+++ b/sql/custom_conf.h
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
diff --git a/sql/derror.cc b/sql/derror.cc
index 62971fde394..7ebe6e4b3c5 100644
--- a/sql/derror.cc
+++ b/sql/derror.cc
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -44,13 +44,14 @@ static void read_texts(const char *file_name,const char ***point,
uint error_messages)
{
register uint i;
- uint ant,funktpos,length,textant;
+ uint count,funktpos,length,textcount;
File file;
char name[FN_REFLEN];
const char *buff;
uchar head[32],*pos;
DBUG_ENTER("read_texts");
+ *point=0; // If something goes wrong
LINT_INIT(buff);
funktpos=0;
if ((file=my_open(fn_format(name,file_name,language,"",4),
@@ -63,37 +64,38 @@ static void read_texts(const char *file_name,const char ***point,
if (head[0] != (uchar) 254 || head[1] != (uchar) 254 ||
head[2] != 2 || head[3] != 1)
goto err; /* purecov: inspected */
- textant=head[4];
- length=uint2korr(head+6); ant=uint2korr(head+8);
+ textcount=head[4];
+ length=uint2korr(head+6); count=uint2korr(head+8);
- if (ant < error_messages)
+ if (count < error_messages)
{
- fprintf(stderr,"\n%s: Fatal error: Error message file '%s' had only %d error messages, but it should have at least %d error messages.\n\
-Check that the above file is the right version for this program!\n\n",
- my_progname,name,ant,error_messages);
+ sql_print_error("\
+Error message file '%s' had only %d error messages,\n\
+but it should contain at least %d error messages.\n\
+Check that the above file is the right version for this program!",
+ name,count,error_messages);
VOID(my_close(file,MYF(MY_WME)));
- clean_up(0); /* Clean_up frees everything */
- exit(1); /* We can't continue */
+ unireg_abort(1);
}
x_free((gptr) *point); /* Free old language */
if (!(*point= (const char**)
- my_malloc((uint) (length+ant*sizeof(char*)),MYF(0))))
+ my_malloc((uint) (length+count*sizeof(char*)),MYF(0))))
{
funktpos=2; /* purecov: inspected */
goto err; /* purecov: inspected */
}
- buff= (char*) (*point + ant);
+ buff= (char*) (*point + count);
- if (my_read(file,(byte*) buff,(uint) ant*2,MYF(MY_NABP))) goto err;
- for (i=0, pos= (uchar*) buff ; i< ant ; i++)
+ if (my_read(file,(byte*) buff,(uint) count*2,MYF(MY_NABP))) goto err;
+ for (i=0, pos= (uchar*) buff ; i< count ; i++)
{
(*point)[i]=buff+uint2korr(pos);
pos+=2;
}
if (my_read(file,(byte*) buff,(uint) length,MYF(MY_NABP))) goto err;
- for (i=1 ; i < textant ; i++)
+ for (i=1 ; i < textcount ; i++)
{
point[i]= *point +uint2korr(head+10+i+i);
}
@@ -103,20 +105,19 @@ Check that the above file is the right version for this program!\n\n",
err:
switch (funktpos) {
case 2:
- buff="\n%s: Fatal error: Not enough memory for messagefile '%s'\n\n";
+ buff="Not enough memory for messagefile '%s'";
break;
case 1:
- buff="\n%s: Fatal error: Can't read from messagefile '%s'\n\n";
+ buff="Can't read from messagefile '%s'";
break;
default:
- buff="\n%s: Fatal error: Can't find messagefile '%s'\n\n";
+ buff="Can't find messagefile '%s'";
break;
}
if (file != FERR)
VOID(my_close(file,MYF(MY_WME)));
- fprintf(stderr,buff,my_progname,name);
- clean_up(0); /* Clean_up frees everything */
- exit(1); /* We can't continue */
+ sql_print_error(buff,name);
+ unireg_abort(1);
} /* read_texts */
diff --git a/sql/des_key_file.cc b/sql/des_key_file.cc
new file mode 100644
index 00000000000..d9c924b5a3c
--- /dev/null
+++ b/sql/des_key_file.cc
@@ -0,0 +1,107 @@
+/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <mysql_priv.h>
+#include <m_ctype.h>
+
+#ifdef HAVE_OPENSSL
+
+struct st_des_keyschedule des_keyschedule[10];
+uint des_default_key;
+pthread_mutex_t LOCK_des_key_file;
+static int initialized;
+
+/*
+ Function which loads DES keys from plaintext file into memory on MySQL
+ server startup and on command FLUSH DES_KEY_FILE.
+ Blame tonu@spam.ee on bugs ;)
+
+ RETURN
+ 0 ok
+ 1 Error
+*/
+
+bool
+load_des_key_file(const char *file_name)
+{
+ bool result=1;
+ File file;
+ IO_CACHE io;
+ DBUG_ENTER("load_des_key_file");
+ DBUG_PRINT("enter",("name: %s",file_name));
+
+ if (!initialized)
+ {
+ initialized=1;
+ pthread_mutex_init(&LOCK_des_key_file,MY_MUTEX_INIT_FAST);
+ }
+
+ VOID(pthread_mutex_lock(&LOCK_des_key_file));
+ if ((file=my_open(file_name,O_RDONLY | O_BINARY ,MYF(MY_WME))) < 0 ||
+ init_io_cache(&io, file, IO_SIZE*2, READ_CACHE, 0, 0, MYF(MY_WME)))
+ goto error;
+
+ bzero((char*) des_keyschedule,sizeof(struct st_des_keyschedule) * 10);
+ des_default_key=15; // Impossible key
+ for (;;)
+ {
+ char *start, *end;
+ char buf[1024], offset;
+ st_des_keyblock keyblock;
+ uint length;
+
+ if (!(length=my_b_gets(&io,buf,sizeof(buf)-1)))
+ break; // End of file
+ offset=buf[0];
+ if (offset >= '0' && offset <= '9') // If ok key
+ {
+ offset=(char) (offset - '0');
+ // Remove newline and possible other control characters
+ for (start=buf+1 ; isspace(*start) ; start++) ;
+ end=buf+length;
+ for (end=strend(buf) ; end > start && !isgraph(end[-1]) ; end--) ;
+
+ if (start != end)
+ {
+ des_cblock ivec;
+ bzero((char*) &ivec,sizeof(ivec));
+ // We make good 24-byte (168 bit) key from given plaintext key with MD5
+ EVP_BytesToKey(EVP_des_ede3_cbc(),EVP_md5(),NULL,
+ (uchar *) start, (int) (end-start),1,
+ (uchar *) &keyblock,
+ ivec);
+ des_set_key_unchecked(&keyblock.key1,des_keyschedule[(int)offset].ks1);
+ des_set_key_unchecked(&keyblock.key2,des_keyschedule[(int)offset].ks2);
+ des_set_key_unchecked(&keyblock.key3,des_keyschedule[(int)offset].ks3);
+ if (des_default_key == 15)
+ des_default_key= (uint) offset; // use first as def.
+ }
+ }
+ else if (offset != '#')
+ sql_print_error("load_des_file: Found wrong key_number: %c",offset);
+ }
+ result=0;
+
+error:
+ if (file >= 0)
+ {
+ my_close(file,MYF(0));
+ end_io_cache(&io);
+ }
+ VOID(pthread_mutex_unlock(&LOCK_des_key_file));
+ DBUG_RETURN(result);
+}
+#endif /* HAVE_OPENSSL */
diff --git a/sql/field.cc b/sql/field.cc
index c6a26a48c0c..2a0d0160d00 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -63,7 +63,7 @@ const char field_separator=',';
*****************************************************************************/
/*
- ** Calculate length of number and it's parts
+ ** Calculate length of number and its parts
** Increment cuted_fields if wrong number
*/
@@ -215,18 +215,19 @@ static bool test_if_real(const char *str,int length)
/****************************************************************************
** Functions for the base classes
-** This is a unpacked number.
+** This is an unpacked number.
****************************************************************************/
Field::Field(char *ptr_arg,uint32 length_arg,uchar *null_ptr_arg,
- uint null_bit_arg,
+ uchar null_bit_arg,
utype unireg_check_arg, const char *field_name_arg,
struct st_table *table_arg)
- :ptr(ptr_arg),null_ptr(null_ptr_arg),null_bit(null_bit_arg),
- table(table_arg),query_id(0),key_start(0),part_of_key(0),part_of_sortkey(0),
- table_name(table_arg ? table_arg->table_name : 0),
- field_name(field_name_arg), unireg_check(unireg_check_arg),
- field_length(length_arg)
+ :ptr(ptr_arg),null_ptr(null_ptr_arg),
+ table(table_arg),table_name(table_arg ? table_arg->table_name : 0),
+ field_name(field_name_arg),
+ query_id(0),key_start(0),part_of_key(0),part_of_sortkey(0),
+ unireg_check(unireg_check_arg),
+ field_length(length_arg),null_bit(null_bit_arg)
{
flags=null_ptr ? 0: NOT_NULL_FLAG;
}
@@ -242,13 +243,13 @@ void Field::copy_from_tmp(int row_offset)
memcpy(ptr,ptr+row_offset,pack_length());
if (null_ptr)
{
- *null_ptr= ((null_ptr[0] & (uchar) ~(uint) null_bit) |
- null_ptr[row_offset] & (uchar) null_bit);
+ *null_ptr= (uchar) ((null_ptr[0] & (uchar) ~(uint) null_bit) |
+ null_ptr[row_offset] & (uchar) null_bit);
}
}
-bool Field::send(String *packet)
+bool Field::send(THD *thd, String *packet)
{
if (is_null())
return net_store_null(packet);
@@ -256,7 +257,7 @@ bool Field::send(String *packet)
String tmp(buff,sizeof(buff));
val_str(&tmp,&tmp);
CONVERT *convert;
- if ((convert=current_thd->convert_set))
+ if ((convert=thd->convert_set))
return convert->store(packet,tmp.ptr(),tmp.length());
return net_store_data(packet,tmp.ptr(),tmp.length());
}
@@ -368,7 +369,7 @@ bool Field::optimize_range()
/****************************************************************************
** Functions for the Field_decimal class
-** This is a unpacked number.
+** This is an unpacked number.
****************************************************************************/
void
@@ -410,7 +411,7 @@ void Field_decimal::store(const char *from,uint len)
{
fyllchar = '0';
if (from != end)
- while (*from == '0' && from != end-1) // Skipp prezero
+ while (*from == '0' && from != end-1) // Skip prezero
from++;
}
else
@@ -464,7 +465,7 @@ void Field_decimal::store(const char *from,uint len)
if (tmp_dec--)
{
*to++ ='.';
- if (decstr.nr_dec) from++; // Skipp '.'
+ if (decstr.nr_dec) from++; // Skip '.'
for (i=(int) min(decstr.nr_dec,tmp_dec) ; i-- > 0 ; ) *to++ = *from++;
for (i=(int) (tmp_dec-min(decstr.nr_dec,tmp_dec)) ; i-- > 0 ; ) *to++ = '0';
}
@@ -1049,7 +1050,7 @@ void Field_short::sort_string(char *to,uint length __attribute__((unused)))
if (unsigned_flag)
to[0] = ptr[0];
else
- to[0] = ptr[0] ^ 128; /* Revers signbit */
+ to[0] = (char) (ptr[0] ^ 128); /* Revers signbit */
to[1] = ptr[1];
}
else
@@ -1058,7 +1059,7 @@ void Field_short::sort_string(char *to,uint length __attribute__((unused)))
if (unsigned_flag)
to[0] = ptr[1];
else
- to[0] = ptr[1] ^ 128; /* Revers signbit */
+ to[0] = (char) (ptr[1] ^ 128); /* Revers signbit */
to[1] = ptr[0];
}
}
@@ -1129,12 +1130,12 @@ void Field_medium::store(double nr)
}
else if (nr >= (double) (long) (1L << 24))
{
- ulong tmp=(ulong) (1L << 24)-1L;
+ uint32 tmp=(uint32) (1L << 24)-1L;
int3store(ptr,tmp);
current_thd->cuted_fields++;
}
else
- int3store(ptr,(ulong) nr);
+ int3store(ptr,(uint32) nr);
}
else
{
@@ -1171,7 +1172,7 @@ void Field_medium::store(longlong nr)
current_thd->cuted_fields++;
}
else
- int3store(ptr,(ulong) nr);
+ int3store(ptr,(uint32) nr);
}
else
{
@@ -1449,7 +1450,7 @@ int Field_long::cmp(const char *a_ptr, const char *b_ptr)
longget(b,b_ptr);
}
if (unsigned_flag)
- return ((ulong) a < (ulong) b) ? -1 : ((ulong) a > (ulong) b) ? 1 : 0;
+ return ((uint32) a < (uint32) b) ? -1 : ((uint32) a > (uint32) b) ? 1 : 0;
return (a < b) ? -1 : (a > b) ? 1 : 0;
}
@@ -1461,7 +1462,7 @@ void Field_long::sort_string(char *to,uint length __attribute__((unused)))
if (unsigned_flag)
to[0] = ptr[0];
else
- to[0] = ptr[0] ^ 128; /* Revers signbit */
+ to[0] = (char) (ptr[0] ^ 128); /* Revers signbit */
to[1] = ptr[1];
to[2] = ptr[2];
to[3] = ptr[3];
@@ -1472,7 +1473,7 @@ void Field_long::sort_string(char *to,uint length __attribute__((unused)))
if (unsigned_flag)
to[0] = ptr[3];
else
- to[0] = ptr[3] ^ 128; /* Revers signbit */
+ to[0] = (char) (ptr[3] ^ 128); /* Revers signbit */
to[1] = ptr[2];
to[2] = ptr[1];
to[3] = ptr[0];
@@ -1660,7 +1661,7 @@ void Field_longlong::sort_string(char *to,uint length __attribute__((unused)))
if (unsigned_flag)
to[0] = ptr[0];
else
- to[0] = ptr[0] ^ 128; /* Revers signbit */
+ to[0] = (char) (ptr[0] ^ 128); /* Revers signbit */
to[1] = ptr[1];
to[2] = ptr[2];
to[3] = ptr[3];
@@ -1675,7 +1676,7 @@ void Field_longlong::sort_string(char *to,uint length __attribute__((unused)))
if (unsigned_flag)
to[0] = ptr[7];
else
- to[0] = ptr[7] ^ 128; /* Revers signbit */
+ to[0] = (char) (ptr[7] ^ 128); /* Revers signbit */
to[1] = ptr[6];
to[2] = ptr[5];
to[3] = ptr[4];
@@ -1910,7 +1911,7 @@ void Field_float::sort_string(char *to,uint length __attribute__((unused)))
{ /* make complement */
uint i;
for (i=0 ; i < sizeof(nr); i++)
- tmp[i]=tmp[i] ^ (uchar) 255;
+ tmp[i]= (uchar) (tmp[i] ^ (uchar) 255);
}
else
{
@@ -2278,10 +2279,10 @@ void Field_timestamp::store(longlong nr)
{
part1=(long) (nr/LL(1000000));
part2=(long) (nr - (longlong) part1*LL(1000000));
- l_time.year= part1/10000L; part1%=10000L;
+ l_time.year= (int) (part1/10000L); part1%=10000L;
l_time.month= (int) part1 / 100;
- l_time.day= (int) part1 % 100;
- l_time.hour= part2/10000L; part2%=10000L;
+ l_time.day= (int) part1 % 100;
+ l_time.hour= (int) (part2/10000L); part2%=10000L;
l_time.minute=(int) part2 / 100;
l_time.second=(int) part2 % 100;
timestamp=my_gmt_sec(&l_time);
@@ -2295,7 +2296,7 @@ void Field_timestamp::store(longlong nr)
}
else
#endif
- longstore(ptr,(ulong)timestamp);
+ longstore(ptr,(uint32) timestamp);
}
@@ -2596,7 +2597,7 @@ void Field_time::store(longlong nr)
double Field_time::val_real(void)
{
- ulong j= (ulong) uint3korr(ptr);
+ uint32 j= (uint32) uint3korr(ptr);
return (double) j;
}
@@ -2632,19 +2633,19 @@ bool Field_time::get_time(TIME *ltime)
ltime->neg= 1;
tmp=-tmp;
}
- ltime->hour=tmp/10000;
+ ltime->hour= (int) (tmp/10000);
tmp-=ltime->hour*10000;
- ltime->minute= tmp/100;
- ltime->second= tmp % 100;
+ ltime->minute= (int) tmp/100;
+ ltime->second= (int) tmp % 100;
ltime->second_part=0;
return 0;
}
int Field_time::cmp(const char *a_ptr, const char *b_ptr)
{
- long a,b;
- a=(long) sint3korr(a_ptr);
- b=(long) sint3korr(b_ptr);
+ int32 a,b;
+ a=(int32) sint3korr(a_ptr);
+ b=(int32) sint3korr(b_ptr);
return (a < b) ? -1 : (a > b) ? 1 : 0;
}
@@ -2755,14 +2756,14 @@ void Field_year::sql_type(String &res) const
** Stored as a 4 byte unsigned int
****************************************************************************/
-void Field_date::store(const char *from,uint len)
+void Field_date::store(const char *from, uint len)
{
TIME l_time;
- ulong tmp;
+ uint32 tmp;
if (str_to_TIME(from,len,&l_time,1) == TIMESTAMP_NONE)
tmp=0;
else
- tmp=(ulong) l_time.year*10000L + (ulong) (l_time.month*100+l_time.day);
+ tmp=(uint32) l_time.year*10000L + (uint32) (l_time.month*100+l_time.day);
#ifdef WORDS_BIGENDIAN
if (table->db_low_byte_first)
{
@@ -2934,7 +2935,7 @@ void Field_newdate::store(double nr)
void Field_newdate::store(longlong nr)
{
- long tmp;
+ int32 tmp;
if (nr >= LL(100000000) && nr <= LL(99991231235959))
nr=nr/LL(1000000); // Timestamp to date
if (nr < 0L || nr > 99991231L)
@@ -2944,16 +2945,16 @@ void Field_newdate::store(longlong nr)
}
else
{
- tmp=(long) nr;
+ tmp=(int32) nr;
if (tmp)
{
if (tmp < YY_PART_YEAR*10000L) // Fix short dates
- tmp+=20000000L;
+ tmp+= (uint32) 20000000L;
else if (tmp < 999999L)
- tmp+=19000000L;
+ tmp+= (uint32) 19000000L;
}
- uint month=((tmp/100) % 100);
- uint day= tmp%100;
+ uint month= (uint) ((tmp/100) % 100);
+ uint day= (uint) (tmp%100);
if (month > 12 || day > 31)
{
tmp=0L; // Don't allow date to change
@@ -2962,7 +2963,7 @@ void Field_newdate::store(longlong nr)
else
tmp= day + month*32 + (tmp/10000)*16*32;
}
- int3store(ptr,tmp);
+ int3store(ptr,(int32) tmp);
}
void Field_newdate::store_time(TIME *ltime,timestamp_type type)
@@ -2987,7 +2988,7 @@ double Field_newdate::val_real(void)
longlong Field_newdate::val_int(void)
{
- ulong j=uint3korr(ptr);
+ ulong j= uint3korr(ptr);
j= (j % 32L)+(j / 32L % 16L)*100L + (j/(16L*32L))*10000L;
return (longlong) j;
}
@@ -2997,25 +2998,25 @@ String *Field_newdate::val_str(String *val_buffer,
{
val_buffer->alloc(field_length);
val_buffer->length(field_length);
- ulong tmp=(ulong) uint3korr(ptr);
+ uint32 tmp=(uint32) uint3korr(ptr);
int part;
char *pos=(char*) val_buffer->ptr()+10;
/* Open coded to get more speed */
- *pos--=0;
+ *pos--=0; // End NULL
part=(int) (tmp & 31);
- *pos--='0'+part%10;
- *pos--='0'+part/10;
- *pos--='-';
+ *pos--= (char) ('0'+part%10);
+ *pos--= (char) ('0'+part/10);
+ *pos--= '-';
part=(int) (tmp >> 5 & 15);
- *pos--='0'+part%10;
- *pos--='0'+part/10;
- *pos--='-';
+ *pos--= (char) ('0'+part%10);
+ *pos--= (char) ('0'+part/10);
+ *pos--= '-';
part=(int) (tmp >> 9);
- *pos--='0'+part%10; part/=10;
- *pos--='0'+part%10; part/=10;
- *pos--='0'+part%10; part/=10;
- *pos='0'+part;
+ *pos--= (char) ('0'+part%10); part/=10;
+ *pos--= (char) ('0'+part%10); part/=10;
+ *pos--= (char) ('0'+part%10); part/=10;
+ *pos= (char) ('0'+part);
return val_buffer;
}
@@ -3023,7 +3024,7 @@ bool Field_newdate::get_date(TIME *ltime,bool fuzzydate)
{
if (is_null())
return 1;
- ulong tmp=(ulong) uint3korr(ptr);
+ uint32 tmp=(uint32) uint3korr(ptr);
bzero((char*) ltime,sizeof(*ltime));
ltime->day= tmp & 31;
ltime->month= (tmp >> 5) & 15;
@@ -3039,9 +3040,9 @@ bool Field_newdate::get_time(TIME *ltime)
int Field_newdate::cmp(const char *a_ptr, const char *b_ptr)
{
- ulong a,b;
- a=(ulong) uint3korr(a_ptr);
- b=(ulong) uint3korr(b_ptr);
+ uint32 a,b;
+ a=(uint32) uint3korr(a_ptr);
+ b=(uint32) uint3korr(b_ptr);
return (a < b) ? -1 : (a > b) ? 1 : 0;
}
@@ -3175,44 +3176,44 @@ String *Field_datetime::val_str(String *val_buffer,
pos=(char*) val_buffer->ptr()+19;
*pos--=0;
- *pos--='0'+(char) (part2%10); part2/=10;
- *pos--='0'+(char) (part2%10); part3= (int) (part2 / 10);
- *pos--=':';
- *pos--='0'+(char) (part3%10); part3/=10;
- *pos--='0'+(char) (part3%10); part3/=10;
- *pos--=':';
- *pos--='0'+(char) (part3%10); part3/=10;
- *pos--='0'+(char) part3;
- *pos--=' ';
- *pos--='0'+(char) (part1%10); part1/=10;
- *pos--='0'+(char) (part1%10); part1/=10;
- *pos--='-';
- *pos--='0'+(char) (part1%10); part1/=10;
- *pos--='0'+(char) (part1%10); part3= (int) (part1/10);
- *pos--='-';
- *pos--='0'+(char) (part3%10); part3/=10;
- *pos--='0'+(char) (part3%10); part3/=10;
- *pos--='0'+(char) (part3%10); part3/=10;
- *pos='0'+(char) part3;
+ *pos--= (char) ('0'+(char) (part2%10)); part2/=10;
+ *pos--= (char) ('0'+(char) (part2%10)); part3= (int) (part2 / 10);
+ *pos--= ':';
+ *pos--= (char) ('0'+(char) (part3%10)); part3/=10;
+ *pos--= (char) ('0'+(char) (part3%10)); part3/=10;
+ *pos--= ':';
+ *pos--= (char) ('0'+(char) (part3%10)); part3/=10;
+ *pos--= (char) ('0'+(char) part3);
+ *pos--= ' ';
+ *pos--= (char) ('0'+(char) (part1%10)); part1/=10;
+ *pos--= (char) ('0'+(char) (part1%10)); part1/=10;
+ *pos--= '-';
+ *pos--= (char) ('0'+(char) (part1%10)); part1/=10;
+ *pos--= (char) ('0'+(char) (part1%10)); part3= (int) (part1/10);
+ *pos--= '-';
+ *pos--= (char) ('0'+(char) (part3%10)); part3/=10;
+ *pos--= (char) ('0'+(char) (part3%10)); part3/=10;
+ *pos--= (char) ('0'+(char) (part3%10)); part3/=10;
+ *pos=(char) ('0'+(char) part3);
return val_buffer;
}
bool Field_datetime::get_date(TIME *ltime,bool fuzzydate)
{
longlong tmp=Field_datetime::val_int();
- long part1,part2;
- part1=(long) (tmp/LL(1000000));
- part2=(long) (tmp - (ulonglong) part1*LL(1000000));
+ uint32 part1,part2;
+ part1=(uint32) (tmp/LL(1000000));
+ part2=(uint32) (tmp - (ulonglong) part1*LL(1000000));
ltime->time_type= TIMESTAMP_FULL;
- ltime->neg=0;
- ltime->second_part=0;
- ltime->second= part2%100;
- ltime->minute= part2/100%100;
- ltime->hour= part2/10000;
- ltime->day= part1%100;
- ltime->month= part1/100%100;
- ltime->year= part1/10000;
+ ltime->neg= 0;
+ ltime->second_part= 0;
+ ltime->second= (int) (part2%100);
+ ltime->minute= (int) (part2/100%100);
+ ltime->hour= (int) (part2/10000);
+ ltime->day= (int) (part1%100);
+ ltime->month= (int) (part1/100%100);
+ ltime->year= (int) (part1/10000);
return (!fuzzydate && (!ltime->month || !ltime->day)) ? 1 : 0;
}
@@ -3331,7 +3332,7 @@ void Field_string::store(longlong nr)
{
char buff[22];
char *end=longlong10_to_str(nr,buff,-10);
- Field_string::store(buff,end-buff);
+ Field_string::store(buff,(uint) (end-buff));
}
@@ -3522,7 +3523,7 @@ void Field_varstring::store(longlong nr)
{
char buff[22];
char *end=longlong10_to_str(nr,buff,-10);
- Field_varstring::store(buff,end-buff);
+ Field_varstring::store(buff,(uint) (end-buff));
}
@@ -3613,9 +3614,9 @@ char *Field_varstring::pack(char *to, const char *from, uint max_length)
uint length=uint2korr(from);
if (length > max_length)
length=max_length;
- *to++= (length & 255);
+ *to++= (char) (length & 255);
if (max_length > 255)
- *to++= (uchar) (length >> 8);
+ *to++= (char) (length >> 8);
if (length)
memcpy(to, from+2, length);
return to+length;
@@ -3704,7 +3705,7 @@ uint Field_varstring::max_packed_col_length(uint max_length)
** packlength slot and may be from 1-4.
****************************************************************************/
-Field_blob::Field_blob(char *ptr_arg, uchar *null_ptr_arg, uint null_bit_arg,
+Field_blob::Field_blob(char *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg,
enum utype unireg_check_arg, const char *field_name_arg,
struct st_table *table_arg,uint blob_pack_length,
bool binary_arg)
@@ -3721,7 +3722,7 @@ Field_blob::Field_blob(char *ptr_arg, uchar *null_ptr_arg, uint null_bit_arg,
}
-void Field_blob::store_length(ulong number)
+void Field_blob::store_length(uint32 number)
{
switch (packlength) {
case 1:
@@ -3748,9 +3749,9 @@ void Field_blob::store_length(ulong number)
shortstore(ptr,(unsigned short) number);
break;
case 3:
- if (number > (ulong) (1L << 24))
+ if (number > (uint32) (1L << 24))
{
- number= (ulong) (1L << 24)-1L;
+ number= (uint32) (1L << 24)-1L;
current_thd->cuted_fields++;
}
int3store(ptr,number);
@@ -3768,11 +3769,11 @@ void Field_blob::store_length(ulong number)
}
-ulong Field_blob::get_length(const char *pos)
+uint32 Field_blob::get_length(const char *pos)
{
switch (packlength) {
case 1:
- return (ulong) (uchar) pos[0];
+ return (uint32) (uchar) pos[0];
case 2:
{
uint16 tmp;
@@ -3782,10 +3783,10 @@ ulong Field_blob::get_length(const char *pos)
else
#endif
shortget(tmp,pos);
- return (ulong) tmp;
+ return (uint32) tmp;
}
case 3:
- return (ulong) uint3korr(pos);
+ return (uint32) uint3korr(pos);
case 4:
{
uint32 tmp;
@@ -3795,7 +3796,7 @@ ulong Field_blob::get_length(const char *pos)
else
#endif
longget(tmp,pos);
- return (ulong) tmp;
+ return (uint32) tmp;
}
}
return 0; // Impossible
@@ -3841,14 +3842,14 @@ void Field_blob::store(const char *from,uint len)
void Field_blob::store(double nr)
{
value.set(nr);
- Field_blob::store(value.ptr(),value.length());
+ Field_blob::store(value.ptr(),(uint) value.length());
}
void Field_blob::store(longlong nr)
{
value.set(nr);
- Field_blob::store(value.ptr(),value.length());
+ Field_blob::store(value.ptr(), (uint) value.length());
}
@@ -3859,7 +3860,7 @@ double Field_blob::val_real(void)
memcpy_fixed(&blob,ptr+packlength,sizeof(char*));
if (!blob)
return 0.0;
- ulong length=get_length(ptr);
+ uint32 length=get_length(ptr);
char save=blob[length]; // Ok to patch blob in NISAM
blob[length]=0;
@@ -3875,7 +3876,7 @@ longlong Field_blob::val_int(void)
memcpy_fixed(&blob,ptr+packlength,sizeof(char*));
if (!blob)
return 0;
- ulong length=get_length(ptr);
+ uint32 length=get_length(ptr);
char save=blob[length]; // Ok to patch blob in NISAM
blob[length]=0;
@@ -3898,8 +3899,8 @@ String *Field_blob::val_str(String *val_buffer __attribute__((unused)),
}
-int Field_blob::cmp(const char *a,ulong a_length, const char *b,
- ulong b_length)
+int Field_blob::cmp(const char *a,uint32 a_length, const char *b,
+ uint32 b_length)
{
int diff;
if (binary_flag)
@@ -3933,11 +3934,11 @@ int Field_blob::cmp_binary_offset(uint row_offset)
int Field_blob::cmp_binary(const char *a_ptr, const char *b_ptr,
- ulong max_length)
+ uint32 max_length)
{
char *a,*b;
uint diff;
- ulong a_length,b_length;
+ uint32 a_length,b_length;
memcpy_fixed(&a,a_ptr+packlength,sizeof(char*));
memcpy_fixed(&b,b_ptr+packlength,sizeof(char*));
a_length=get_length(a_ptr);
@@ -3956,9 +3957,9 @@ int Field_blob::cmp_binary(const char *a_ptr, const char *b_ptr,
void Field_blob::get_key_image(char *buff,uint length)
{
length-=HA_KEY_BLOB_LENGTH;
- ulong blob_length=get_length(ptr);
+ uint32 blob_length=get_length(ptr);
char *blob;
- if ((ulong) length > blob_length)
+ if ((uint32) length > blob_length)
{
#ifdef HAVE_purify
bzero(buff+2+blob_length, (length-blob_length));
@@ -4052,7 +4053,7 @@ char *Field_blob::pack(char *to, const char *from, uint max_length)
{
char *save=ptr;
ptr=(char*) from;
- ulong length=get_length(); // Length of from string
+ uint32 length=get_length(); // Length of from string
if (length > max_length)
{
ptr=to;
@@ -4075,7 +4076,7 @@ char *Field_blob::pack(char *to, const char *from, uint max_length)
const char *Field_blob::unpack(char *to, const char *from)
{
memcpy(to,from,packlength);
- ulong length=get_length(from);
+ uint32 length=get_length(from);
from+=packlength;
if (length)
memcpy_fixed(to+packlength, &from, sizeof(from));
@@ -4084,60 +4085,6 @@ const char *Field_blob::unpack(char *to, const char *from)
return from+length;
}
-
-#ifdef HAVE_GEMINI_DB
-/* Blobs in Gemini tables are stored separately from the rows which contain
-** them (except for tiny blobs, which are stored in the row). For all other
-** blob types (blob, mediumblob, longblob), the row contains the length of
-** the blob data and a blob id. These methods (pack_id, get_id, and
-** unpack_id) handle packing and unpacking blob fields in Gemini rows.
-*/
-char *Field_blob::pack_id(char *to, const char *from, ulonglong id, uint max_length)
-{
- char *save=ptr;
- ptr=(char*) from;
- ulong length=get_length(); // Length of from string
- if (length > max_length)
- {
- ptr=to;
- length=max_length;
- store_length(length); // Store max length
- ptr=(char*) from;
- }
- else
- memcpy(to,from,packlength); // Copy length
- if (length)
- {
- int8store(to+packlength, id);
- }
- ptr=save; // Restore org row pointer
- return to+packlength+sizeof(id);
-}
-
-
-ulonglong Field_blob::get_id(const char *from)
-{
- ulonglong id = 0;
- ulong length=get_length(from);
- if (length)
- id=uint8korr(from+packlength);
- return id;
-}
-
-
-const char *Field_blob::unpack_id(char *to, const char *from, const char *bdata)
-{
- memcpy(to,from,packlength);
- ulong length=get_length(from);
- from+=packlength;
- if (length)
- memcpy_fixed(to+packlength, &bdata, sizeof(bdata));
- else
- bzero(to+packlength,sizeof(bdata));
- return from+sizeof(ulonglong);
-}
-#endif /* HAVE_GEMINI_DB */
-
/* Keys for blobs are like keys on varchars */
int Field_blob::pack_cmp(const char *a, const char *b, uint key_length)
@@ -4194,7 +4141,7 @@ char *Field_blob::pack_key(char *to, const char *from, uint max_length)
{
char *save=ptr;
ptr=(char*) from;
- ulong length=get_length(); // Length of from string
+ uint32 length=get_length(); // Length of from string
if (length > max_length)
length=max_length;
*to++= (uchar) length;
@@ -4217,9 +4164,9 @@ char *Field_blob::pack_key_from_key_image(char *to, const char *from,
uint length=uint2korr(from);
if (length > max_length)
length=max_length;
- *to++= (length & 255);
+ *to++= (char) (length & 255);
if (max_length > 255)
- *to++= (uchar) (length >> 8);
+ *to++= (char) (length >> 8);
if (length)
memcpy(to, from+2, length);
return to+length;
@@ -4332,7 +4279,7 @@ void Field_enum::store(const char *from,uint length)
conv=buff;
}
my_errno=0;
- tmp=strtoul(conv,&end,10);
+ tmp=(uint) strtoul(conv,&end,10);
if (my_errno || end != conv+length || tmp > typelib->count)
{
tmp=0;
@@ -4602,7 +4549,7 @@ bool Field_enum::eq_def(Field *field)
if (!Field::eq_def(field))
return 0;
TYPELIB *from_lib=((Field_enum*) field)->typelib;
-
+
if (typelib->count < from_lib->count)
return 0;
for (uint i=0 ; i < from_lib->count ; i++)
@@ -4612,7 +4559,7 @@ bool Field_enum::eq_def(Field *field)
}
bool Field_num::eq_def(Field *field)
-{
+{
if (!Field::eq_def(field))
return 0;
Field_num *from_num= (Field_num*) field;
@@ -4678,7 +4625,7 @@ uint pack_length_to_packflag(uint type)
Field *make_field(char *ptr, uint32 field_length,
- uchar *null_pos, uint null_bit,
+ uchar *null_pos, uchar null_bit,
uint pack_flag,
Field::utype unireg_check,
TYPELIB *interval,
diff --git a/sql/field.h b/sql/field.h
index b138eb772d8..a9b257f0c3a 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -1,23 +1,23 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/*
-** Because of the function new_field all field classes that have static
-** variables must declare the size_of() member function.
+ Because of the function new_field() all field classes that have static
+ variables must declare the size_of() member function.
*/
#ifdef __GNUC__
@@ -31,27 +31,28 @@ struct st_cache_field;
void field_conv(Field *to,Field *from);
class Field {
- Field(const Item &); /* Prevent use of theese */
+ Field(const Item &); /* Prevent use of these */
void operator=(Field &);
public:
static void *operator new(size_t size) {return (void*) sql_alloc((uint) size); }
static void operator delete(void *ptr_arg, size_t size) {} /*lint -e715 */
- enum utype { NONE,DATE,SHIELD,NOEMPTY,CASEUP,PNR,BGNR,PGNR,YES,NO,REL,
- CHECK,EMPTY,UNKNOWN_FIELD,CASEDN,NEXT_NUMBER,INTERVAL_FIELD,
- BIT_FIELD, TIMESTAMP_FIELD,CAPITALIZE,BLOB_FIELD};
- char *ptr; // Position to field in record
+ char *ptr; // Position to field in record
uchar *null_ptr; // Byte where null_bit is
- uint8 null_bit; // And position to it
struct st_table *table; // Pointer for table
- ulong query_id; // For quick test of used fields
- key_map key_start,part_of_key,part_of_sortkey;// Field is part of these keys.
- const char *table_name,*field_name;
- utype unireg_check;
- uint32 field_length; // Length of field
- uint16 flags;
-
- Field(char *ptr_arg,uint32 length_arg,uchar *null_ptr_arg,uint null_bit_arg,
+ const char *table_name,*field_name;
+ ulong query_id; // For quick test of used fields
+ // Field is part of the following keys
+ key_map key_start,part_of_key,part_of_sortkey;
+ enum utype { NONE,DATE,SHIELD,NOEMPTY,CASEUP,PNR,BGNR,PGNR,YES,NO,REL,
+ CHECK,EMPTY,UNKNOWN_FIELD,CASEDN,NEXT_NUMBER,INTERVAL_FIELD,
+ BIT_FIELD, TIMESTAMP_FIELD,CAPITALIZE,BLOB_FIELD};
+ utype unireg_check;
+ uint32 field_length; // Length of field
+ uint16 flags;
+ uchar null_bit; // Bit used to test null bit
+
+ Field(char *ptr_arg,uint32 length_arg,uchar *null_ptr_arg,uchar null_bit_arg,
utype unireg_check_arg, const char *field_name_arg,
struct st_table *table_arg);
virtual ~Field() {}
@@ -77,7 +78,7 @@ public:
virtual enum_field_types real_type() const { return type(); }
inline int cmp(const char *str) { return cmp(ptr,str); }
virtual int cmp(const char *,const char *)=0;
- virtual int cmp_binary(const char *a,const char *b, ulong max_length=~0L)
+ virtual int cmp_binary(const char *a,const char *b, uint32 max_length=~0L)
{ return memcmp(a,b,pack_length()); }
virtual int cmp_offset(uint row_offset)
{ return memcmp(ptr,ptr+row_offset,pack_length()); }
@@ -92,7 +93,7 @@ public:
// Caller beware: sql_type can change str.Ptr, so check
// ptr() to see if it changed if you are using your own buffer
// in str and restore it with set() if needed
-
+
virtual uint size_of() const =0; // For new field
inline bool is_null(uint row_offset=0)
{ return null_ptr ? (null_ptr[row_offset] & null_bit ? 1 : 0) : table->null_row; }
@@ -101,30 +102,30 @@ public:
inline void set_null(int row_offset=0)
{ if (null_ptr) null_ptr[row_offset]|= null_bit; }
inline void set_notnull(int row_offset=0)
- { if (null_ptr) null_ptr[row_offset]&= ~null_bit; }
+ { if (null_ptr) null_ptr[row_offset]&= (uchar) ~null_bit; }
inline bool maybe_null(void) { return null_ptr != 0 || table->maybe_null; }
inline bool real_maybe_null(void) { return null_ptr != 0; }
virtual void make_field(Send_field *)=0;
virtual void sort_string(char *buff,uint length)=0;
virtual bool optimize_range();
virtual bool store_for_compare() { return 0; }
- inline Field *new_field(struct st_table *new_table)
- {
- Field *tmp= (Field*) sql_memdup((char*) this,size_of());
- if (tmp)
- {
- tmp->table=new_table;
- tmp->key_start=tmp->part_of_key=tmp->part_of_sortkey=0;
- tmp->unireg_check=Field::NONE;
- tmp->flags&= (NOT_NULL_FLAG | BLOB_FLAG | UNSIGNED_FLAG | ZEROFILL_FLAG | BINARY_FLAG | ENUM_FLAG | SET_FLAG);
- tmp->reset_fields();
- }
- return tmp;
- }
- inline void move_field(char *ptr_arg,uchar *null_ptr_arg,uint null_bit_arg)
+ Field *new_field(MEM_ROOT *root, struct st_table *new_table)
+ {
+ Field *tmp= (Field*) memdup_root(root,(char*) this,size_of());
+ if (tmp)
{
- ptr=ptr_arg; null_ptr=null_ptr_arg; null_bit=null_bit_arg;
+ tmp->table=new_table;
+ tmp->key_start=tmp->part_of_key=tmp->part_of_sortkey=0;
+ tmp->unireg_check=Field::NONE;
+ tmp->flags&= (NOT_NULL_FLAG | BLOB_FLAG | UNSIGNED_FLAG | ZEROFILL_FLAG | BINARY_FLAG | ENUM_FLAG | SET_FLAG);
+ tmp->reset_fields();
}
+ return tmp;
+ }
+ inline void move_field(char *ptr_arg,uchar *null_ptr_arg,uchar null_bit_arg)
+ {
+ ptr=ptr_arg; null_ptr=null_ptr_arg; null_bit=null_bit_arg;
+ }
inline void move_field(char *ptr_arg) { ptr=ptr_arg; }
inline void move_field(my_ptrdiff_t ptr_diff)
{
@@ -154,10 +155,10 @@ public:
ptr-=row_offset;
return tmp;
}
- bool send(String *packet);
+ bool send(THD *thd, String *packet);
virtual char *pack(char* to, const char *from, uint max_length=~(uint) 0)
{
- uint length=pack_length();
+ uint32 length=pack_length();
memcpy(to,from,length);
return to+length;
}
@@ -212,10 +213,10 @@ public:
const uint8 dec;
bool zerofill,unsigned_flag; // Purify cannot handle bit fields
Field_num(char *ptr_arg,uint32 len_arg, uchar *null_ptr_arg,
- uint null_bit_arg, utype unireg_check_arg,
+ uchar null_bit_arg, utype unireg_check_arg,
const char *field_name_arg,
struct st_table *table_arg,
- uint dec_arg,bool zero_arg,bool unsigned_arg)
+ uint8 dec_arg,bool zero_arg,bool unsigned_arg)
:Field(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
unireg_check_arg, field_name_arg, table_arg),
dec(dec_arg),zerofill(zero_arg),unsigned_flag(unsigned_arg)
@@ -230,7 +231,7 @@ public:
void add_zerofill_and_unsigned(String &res) const;
friend class create_field;
void make_field(Send_field *);
- uint decimals() const { return dec; }
+ uint decimals() const { return (uint) dec; }
uint size_of() const { return sizeof(*this); }
bool eq_def(Field *field);
};
@@ -239,7 +240,7 @@ public:
class Field_str :public Field {
public:
Field_str(char *ptr_arg,uint32 len_arg, uchar *null_ptr_arg,
- uint null_bit_arg, utype unireg_check_arg,
+ uchar null_bit_arg, utype unireg_check_arg,
const char *field_name_arg,
struct st_table *table_arg)
:Field(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
@@ -256,10 +257,10 @@ public:
class Field_decimal :public Field_num {
public:
Field_decimal(char *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
- uint null_bit_arg,
+ uchar null_bit_arg,
enum utype unireg_check_arg, const char *field_name_arg,
struct st_table *table_arg,
- uint dec_arg,bool zero_arg,bool unsigned_arg)
+ uint8 dec_arg,bool zero_arg,bool unsigned_arg)
:Field_num(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
unireg_check_arg, field_name_arg, table_arg,
dec_arg, zero_arg,unsigned_arg)
@@ -285,7 +286,7 @@ public:
class Field_tiny :public Field_num {
public:
Field_tiny(char *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
- uint null_bit_arg,
+ uchar null_bit_arg,
enum utype unireg_check_arg, const char *field_name_arg,
struct st_table *table_arg,
bool zero_arg, bool unsigned_arg)
@@ -314,7 +315,7 @@ public:
class Field_short :public Field_num {
public:
Field_short(char *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
- uint null_bit_arg,
+ uchar null_bit_arg,
enum utype unireg_check_arg, const char *field_name_arg,
struct st_table *table_arg,
bool zero_arg, bool unsigned_arg)
@@ -343,7 +344,7 @@ public:
class Field_medium :public Field_num {
public:
Field_medium(char *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
- uint null_bit_arg,
+ uchar null_bit_arg,
enum utype unireg_check_arg, const char *field_name_arg,
struct st_table *table_arg,
bool zero_arg, bool unsigned_arg)
@@ -372,7 +373,7 @@ public:
class Field_long :public Field_num {
public:
Field_long(char *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
- uint null_bit_arg,
+ uchar null_bit_arg,
enum utype unireg_check_arg, const char *field_name_arg,
struct st_table *table_arg,
bool zero_arg, bool unsigned_arg)
@@ -407,7 +408,7 @@ public:
class Field_longlong :public Field_num {
public:
Field_longlong(char *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
- uint null_bit_arg,
+ uchar null_bit_arg,
enum utype unireg_check_arg, const char *field_name_arg,
struct st_table *table_arg,
bool zero_arg, bool unsigned_arg)
@@ -415,10 +416,11 @@ public:
unireg_check_arg, field_name_arg, table_arg,
0, zero_arg,unsigned_arg)
{}
- Field_longlong(uint32 len_arg,bool maybe_null_arg, const char *field_name_arg,
- struct st_table *table_arg)
+ Field_longlong(uint32 len_arg,bool maybe_null_arg,
+ const char *field_name_arg,
+ struct st_table *table_arg, bool unsigned_arg)
:Field_num((char*) 0, len_arg, maybe_null_arg ? (uchar*) "": 0,0,
- NONE, field_name_arg, table_arg,0,0,0)
+ NONE, field_name_arg, table_arg,0,0,unsigned_arg)
{}
enum Item_result result_type () const { return INT_RESULT; }
enum_field_types type() const { return FIELD_TYPE_LONGLONG;}
@@ -441,10 +443,10 @@ public:
class Field_float :public Field_num {
public:
Field_float(char *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
- uint null_bit_arg,
+ uchar null_bit_arg,
enum utype unireg_check_arg, const char *field_name_arg,
struct st_table *table_arg,
- uint dec_arg,bool zero_arg,bool unsigned_arg)
+ uint8 dec_arg,bool zero_arg,bool unsigned_arg)
:Field_num(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
unireg_check_arg, field_name_arg, table_arg,
dec_arg, zero_arg,unsigned_arg)
@@ -468,16 +470,16 @@ public:
class Field_double :public Field_num {
public:
Field_double(char *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
- uint null_bit_arg,
+ uchar null_bit_arg,
enum utype unireg_check_arg, const char *field_name_arg,
struct st_table *table_arg,
- uint dec_arg,bool zero_arg,bool unsigned_arg)
+ uint8 dec_arg,bool zero_arg,bool unsigned_arg)
:Field_num(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
unireg_check_arg, field_name_arg, table_arg,
dec_arg, zero_arg,unsigned_arg)
{}
Field_double(uint32 len_arg, bool maybe_null_arg, const char *field_name_arg,
- struct st_table *table_arg, uint dec_arg)
+ struct st_table *table_arg, uint8 dec_arg)
:Field_num((char*) 0, len_arg, maybe_null_arg ? (uchar*) "": 0, (uint) 0,
NONE, field_name_arg, table_arg,dec_arg,0,0)
{}
@@ -566,7 +568,7 @@ public:
class Field_year :public Field_tiny {
public:
Field_year(char *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
- uint null_bit_arg,
+ uchar null_bit_arg,
enum utype unireg_check_arg, const char *field_name_arg,
struct st_table *table_arg)
:Field_tiny(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
@@ -585,12 +587,16 @@ public:
class Field_date :public Field_str {
public:
- Field_date(char *ptr_arg, uchar *null_ptr_arg, uint null_bit_arg,
+ Field_date(char *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg,
enum utype unireg_check_arg, const char *field_name_arg,
struct st_table *table_arg)
:Field_str(ptr_arg, 10, null_ptr_arg, null_bit_arg,
unireg_check_arg, field_name_arg, table_arg)
{}
+ Field_date(bool maybe_null_arg, const char *field_name_arg,
+ struct st_table *table_arg)
+ :Field_str((char*) 0,10, maybe_null_arg ? (uchar*) "": 0,0,
+ NONE, field_name_arg, table_arg) {}
enum_field_types type() const { return FIELD_TYPE_DATE;}
enum ha_base_keytype key_type() const { return HA_KEYTYPE_ULONG_INT; }
enum Item_result cmp_type () const { return INT_RESULT; }
@@ -611,7 +617,7 @@ public:
class Field_newdate :public Field_str {
public:
- Field_newdate(char *ptr_arg, uchar *null_ptr_arg, uint null_bit_arg,
+ Field_newdate(char *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg,
enum utype unireg_check_arg, const char *field_name_arg,
struct st_table *table_arg)
:Field_str(ptr_arg, 10, null_ptr_arg, null_bit_arg,
@@ -642,12 +648,16 @@ public:
class Field_time :public Field_str {
public:
- Field_time(char *ptr_arg, uchar *null_ptr_arg, uint null_bit_arg,
+ Field_time(char *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg,
enum utype unireg_check_arg, const char *field_name_arg,
struct st_table *table_arg)
:Field_str(ptr_arg, 8, null_ptr_arg, null_bit_arg,
unireg_check_arg, field_name_arg, table_arg)
{}
+ Field_time(bool maybe_null_arg, const char *field_name_arg,
+ struct st_table *table_arg)
+ :Field_str((char*) 0,8, maybe_null_arg ? (uchar*) "": 0,0,
+ NONE, field_name_arg, table_arg) {}
enum_field_types type() const { return FIELD_TYPE_TIME;}
enum ha_base_keytype key_type() const { return HA_KEYTYPE_INT24; }
enum Item_result cmp_type () const { return INT_RESULT; }
@@ -670,12 +680,16 @@ public:
class Field_datetime :public Field_str {
public:
- Field_datetime(char *ptr_arg, uchar *null_ptr_arg, uint null_bit_arg,
+ Field_datetime(char *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg,
enum utype unireg_check_arg, const char *field_name_arg,
struct st_table *table_arg)
:Field_str(ptr_arg, 19, null_ptr_arg, null_bit_arg,
unireg_check_arg, field_name_arg, table_arg)
{}
+ Field_datetime(bool maybe_null_arg, const char *field_name_arg,
+ struct st_table *table_arg)
+ :Field_str((char*) 0,19, maybe_null_arg ? (uchar*) "": 0,0,
+ NONE, field_name_arg, table_arg) {}
enum_field_types type() const { return FIELD_TYPE_DATETIME;}
#ifdef HAVE_LONG_LONG
enum ha_base_keytype key_type() const { return HA_KEYTYPE_ULONGLONG; }
@@ -704,7 +718,7 @@ class Field_string :public Field_str {
bool binary_flag;
public:
Field_string(char *ptr_arg, uint32 len_arg,uchar *null_ptr_arg,
- uint null_bit_arg,
+ uchar null_bit_arg,
enum utype unireg_check_arg, const char *field_name_arg,
struct st_table *table_arg,bool binary_arg)
:Field_str(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
@@ -759,7 +773,7 @@ class Field_varstring :public Field_str {
bool binary_flag;
public:
Field_varstring(char *ptr_arg, uint32 len_arg,uchar *null_ptr_arg,
- uint null_bit_arg,
+ uchar null_bit_arg,
enum utype unireg_check_arg, const char *field_name_arg,
struct st_table *table_arg,bool binary_arg)
:Field_str(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
@@ -812,7 +826,7 @@ class Field_blob :public Field_str {
String value; // For temporaries
bool binary_flag;
public:
- Field_blob(char *ptr_arg, uchar *null_ptr_arg, uint null_bit_arg,
+ Field_blob(char *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg,
enum utype unireg_check_arg, const char *field_name_arg,
struct st_table *table_arg,uint blob_pack_length,
bool binary_arg);
@@ -836,21 +850,22 @@ public:
longlong val_int(void);
String *val_str(String*,String *);
int cmp(const char *,const char*);
- int cmp(const char *a, ulong a_length, const char *b, ulong b_length);
+ int cmp(const char *a, uint32 a_length, const char *b, uint32 b_length);
int cmp_offset(uint offset);
- int cmp_binary(const char *a,const char *b, ulong max_length=~0L);
+ int cmp_binary(const char *a,const char *b, uint32 max_length=~0L);
int cmp_binary_offset(uint row_offset);
int key_cmp(const byte *,const byte*);
int key_cmp(const byte *str, uint length);
uint32 key_length() const { return 0; }
void sort_string(char *buff,uint length);
- uint32 pack_length() const { return (uint32) (packlength+table->blob_ptr_size); }
- void reset(void) { bzero(ptr,packlength+sizeof(char*)); }
+ uint32 pack_length() const
+ { return (uint32) (packlength+table->blob_ptr_size); }
+ void reset(void) { bzero(ptr, packlength+sizeof(char*)); }
void reset_fields() { bzero((char*) &value,sizeof(value)); }
- void store_length(ulong number);
- inline ulong get_length(uint row_offset=0)
+ void store_length(uint32 number);
+ inline uint32 get_length(uint row_offset=0)
{ return get_length(ptr+row_offset); }
- ulong get_length(const char *ptr);
+ uint32 get_length(const char *ptr);
bool binary() const { return binary_flag; }
inline void get_ptr(char **str)
{
@@ -861,7 +876,7 @@ public:
memcpy(ptr,length,packlength);
memcpy_fixed(ptr+packlength,&data,sizeof(char*));
}
- inline void set_ptr(ulong length,char *data)
+ inline void set_ptr(uint32 length,char *data)
{
store_length(length);
memcpy_fixed(ptr+packlength,&data,sizeof(char*));
@@ -882,21 +897,6 @@ public:
}
char *pack(char *to, const char *from, uint max_length= ~(uint) 0);
const char *unpack(char *to, const char *from);
-#ifdef HAVE_GEMINI_DB
- char *pack_id(char *to, const char *from, ulonglong id,
- uint max_length= ~(uint) 0);
- ulonglong get_id(const char *from);
- const char *unpack_id(char *to, const char *from, const char *bdata);
- inline void get_ptr_from_key_image(char **str,char *key_str)
- {
- *str = key_str + sizeof(uint16);
- }
- inline uint get_length_from_key_image(char *key_str)
- {
- return uint2korr(key_str);
- }
- enum_field_types blobtype() { return (packlength == 1 ? FIELD_TYPE_TINY_BLOB : FIELD_TYPE_BLOB);}
-#endif
char *pack_key(char *to, const char *from, uint max_length);
char *pack_key_from_key_image(char* to, const char *from, uint max_length);
int pack_cmp(const char *a, const char *b, uint key_length);
@@ -916,7 +916,7 @@ protected:
public:
TYPELIB *typelib;
Field_enum(char *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
- uint null_bit_arg,
+ uchar null_bit_arg,
enum utype unireg_check_arg, const char *field_name_arg,
struct st_table *table_arg,uint packlength_arg,
TYPELIB *typelib_arg)
@@ -953,7 +953,7 @@ public:
class Field_set :public Field_enum {
public:
Field_set(char *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
- uint null_bit_arg,
+ uchar null_bit_arg,
enum utype unireg_check_arg, const char *field_name_arg,
struct st_table *table_arg,uint32 packlength_arg,
TYPELIB *typelib_arg)
@@ -1036,7 +1036,7 @@ public:
Field *make_field(char *ptr, uint32 field_length,
- uchar *null_pos, uint null_bit,
+ uchar *null_pos, uchar null_bit,
uint pack_flag, Field::utype unireg_check,
TYPELIB *interval, const char *field_name,
struct st_table *table);
@@ -1079,7 +1079,7 @@ bool test_if_int(const char *str,int length);
#define f_is_zerofill(x) ((x) & FIELDFLAG_ZEROFILL)
#define f_is_packed(x) ((x) & FIELDFLAG_PACK)
#define f_packtype(x) (((x) >> FIELDFLAG_PACK_SHIFT) & 15)
-#define f_decimals(x) (((x) >> FIELDFLAG_DEC_SHIFT) & FIELDFLAG_MAX_DEC)
+#define f_decimals(x) ((uint8) (((x) >> FIELDFLAG_DEC_SHIFT) & FIELDFLAG_MAX_DEC))
#define f_is_alpha(x) (!f_is_num(x))
#define f_is_binary(x) ((x) & FIELDFLAG_BINARY)
#define f_is_enum(x) ((x) & FIELDFLAG_INTERVAL)
diff --git a/sql/field_conv.cc b/sql/field_conv.cc
index 606edd84c74..c7a6d778953 100644
--- a/sql/field_conv.cc
+++ b/sql/field_conv.cc
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
diff --git a/sql/filesort.cc b/sql/filesort.cc
index 86c95395965..a5f42d5731e 100644
--- a/sql/filesort.cc
+++ b/sql/filesort.cc
@@ -22,13 +22,11 @@
#include <stddef.h> /* for macro offsetof */
#endif
#include <m_ctype.h>
+#include "sql_sort.h"
+
#ifndef THREAD
-#define SKIPP_DBUG_IN_FILESORT
+#define SKIP_DBUG_IN_FILESORT
#endif
- /* static variabels */
-
-#define MERGEBUFF 7
-#define MERGEBUFF2 15
/* How to write record_ref. */
@@ -36,85 +34,63 @@
if (my_b_write((file),(byte*) (from),param->ref_length)) \
DBUG_RETURN(1);
-typedef struct st_buffpek { /* Struktur om sorteringsbuffrarna */
- my_off_t file_pos; /* Where we are in the sort file */
- uchar *base,*key; /* key pointers */
- ha_rows count; /* Number of rows in table */
- ulong mem_count; /* numbers of keys in memory */
- ulong max_keys; /* Max keys in buffert */
-} BUFFPEK;
-
-
-typedef struct st_sort_param {
- uint sort_length; /* Length of sortarg */
- uint keys; /* Max antal nycklar / buffert */
- uint ref_length; /* Length of record ref. */
- ha_rows max_rows,examined_rows;
- TABLE *sort_form; /* For quicker make_sortkey */
- SORT_FIELD *local_sortorder;
- SORT_FIELD *end;
-#ifdef USE_STRCOLL
- char* tmp_buffer;
-#endif
-} SORTPARAM;
-
/* functions defined in this file */
static char **make_char_array(register uint fields, uint length, myf my_flag);
+static BUFFPEK *read_buffpek_from_file(IO_CACHE *buffer_file, uint count);
static ha_rows find_all_keys(SORTPARAM *param,SQL_SELECT *select,
- uchar * *sort_keys,
- BUFFPEK *buffpek,uint *maxbuffer,
+ uchar * *sort_keys, IO_CACHE *buffer_file,
IO_CACHE *tempfile,IO_CACHE *indexfile);
static int write_keys(SORTPARAM *param,uchar * *sort_keys,
- uint count,BUFFPEK *buffpek,
- IO_CACHE *tempfile);
-static void make_sortkey(SORTPARAM *param,uchar *to,
- byte *ref_pos);
-static bool save_index(SORTPARAM *param,uchar **sort_keys, uint count);
-static int merge_many_buff(SORTPARAM *param,uchar * *sort_keys,
- BUFFPEK *buffpek,
- uint *maxbuffer, IO_CACHE *t_file);
-static uint read_to_buffer(IO_CACHE *fromfile,BUFFPEK *buffpek,
- uint sort_length);
-static int merge_buffers(SORTPARAM *param,IO_CACHE *from_file,
- IO_CACHE *to_file,uchar * *sort_keys,
- BUFFPEK *lastbuff,BUFFPEK *Fb,
- BUFFPEK *Tb,int flag);
-static int merge_index(SORTPARAM *param,uchar * *sort_keys,
+ uint count, IO_CACHE *buffer_file, IO_CACHE *tempfile);
+static void make_sortkey(SORTPARAM *param,uchar *to, byte *ref_pos);
+static int merge_index(SORTPARAM *param,uchar *sort_buffer,
BUFFPEK *buffpek,
uint maxbuffer,IO_CACHE *tempfile,
IO_CACHE *outfile);
+static bool save_index(SORTPARAM *param,uchar **sort_keys, uint count);
static uint sortlength(SORT_FIELD *sortorder,uint length);
- /* Makes a indexfil of recordnumbers of a sorted database */
- /* outfile is reset before data is written to it, if it wasn't
- open a new file is opened */
+ /*
+ Creates a set of pointers that can be used to read the rows
+ in sorted order. This should be done with the functions
+ in records.cc
+
+ Before calling filesort, one must have done
+ table->file->info(HA_STATUS_VARIABLE)
-ha_rows filesort(TABLE **table, SORT_FIELD *sortorder, uint s_length,
+ The result set is stored in table->io_cache or
+ table->record_pointers
+ */
+
+ha_rows filesort(TABLE *table, SORT_FIELD *sortorder, uint s_length,
SQL_SELECT *select, ha_rows special, ha_rows max_rows,
ha_rows *examined_rows)
{
int error;
- uint memavl,old_memavl,maxbuffer,skr;
+ ulong memavl;
+ uint maxbuffer;
BUFFPEK *buffpek;
ha_rows records;
uchar **sort_keys;
- IO_CACHE tempfile,*selected_records_file,*outfile;
+ IO_CACHE tempfile, buffpek_pointers, *selected_records_file, *outfile;
SORTPARAM param;
DBUG_ENTER("filesort");
- DBUG_EXECUTE("info",TEST_filesort(table,sortorder,s_length,special););
-#ifdef SKIPP_DBUG_IN_FILESORT
+ DBUG_EXECUTE("info",TEST_filesort(sortorder,s_length,special););
+#ifdef SKIP_DBUG_IN_FILESORT
DBUG_PUSH(""); /* No DBUG here */
#endif
- outfile= table[0]->io_cache;
+ outfile= table->io_cache;
my_b_clear(&tempfile);
- buffpek= (BUFFPEK *) NULL; sort_keys= (uchar **) NULL; error= 1;
- maxbuffer=1;
- param.ref_length= table[0]->file->ref_length;
+ my_b_clear(&buffpek_pointers);
+ buffpek=0;
+ sort_keys= (uchar **) NULL;
+ error= 1;
+ bzero((char*) &param,sizeof(param));
+ param.ref_length= table->file->ref_length;
param.sort_length=sortlength(sortorder,s_length)+ param.ref_length;
param.max_rows= max_rows;
- param.examined_rows=0;
if (select && select->quick)
{
@@ -139,17 +115,14 @@ ha_rows filesort(TABLE **table, SORT_FIELD *sortorder, uint s_length,
#ifdef CAN_TRUST_RANGE
else if (select && select->quick && select->quick->records > 0L)
{
- /* Get record-count */
- table[0]->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
records=min((ha_rows) (select->quick->records*2+EXTRA_RECORDS*2),
- table[0]->file->records)+EXTRA_RECORDS;
+ table->file->records)+EXTRA_RECORDS;
selected_records_file=0;
}
#endif
else
{
- table[0]->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);/* Get record-count */
- records=table[0]->file->estimate_number_of_rows();
+ records=table->file->estimate_number_of_rows();
selected_records_file= 0;
}
if (param.sort_length == param.ref_length && records > param.max_rows)
@@ -164,51 +137,34 @@ ha_rows filesort(TABLE **table, SORT_FIELD *sortorder, uint s_length,
memavl=sortbuff_size;
while (memavl >= MIN_SORT_MEMORY)
{
- if ((ulonglong) (records+1)*(param.sort_length+sizeof(char*))+sizeof(BUFFPEK)*10 <
- (ulonglong) memavl)
- param.keys=(uint) records+1;
- else
- {
- maxbuffer=1;
- do
- {
- skr=maxbuffer;
- if (memavl < sizeof(BUFFPEK)*maxbuffer)
- {
- my_error(ER_OUT_OF_SORTMEMORY,MYF(ME_ERROR+ME_WAITTANG));
- goto err;
- }
- param.keys=(memavl-sizeof(BUFFPEK)*maxbuffer)/
- (param.sort_length+sizeof(char*));
- }
- while ((maxbuffer= (uint) (records/param.keys+1)) != skr);
- }
- if ((sort_keys= (uchar **) make_char_array(param.keys,param.sort_length,
+ ulong old_memavl;
+ ulong keys= memavl/(param.sort_length+sizeof(char*));
+ param.keys=(uint) min(records+1, keys);
+ if ((sort_keys= (uchar **) make_char_array(param.keys, param.sort_length,
MYF(0))))
- if ((buffpek = (BUFFPEK*) my_malloc((uint) sizeof(BUFFPEK)*
- (maxbuffer+10),
- MYF(0))))
- break;
- else
- my_free((gptr) sort_keys,MYF(0));
+ break;
old_memavl=memavl;
if ((memavl=memavl/4*3) < MIN_SORT_MEMORY && old_memavl > MIN_SORT_MEMORY)
memavl=MIN_SORT_MEMORY;
}
- param.keys--;
- maxbuffer+=10; /* Some extra range */
-
if (memavl < MIN_SORT_MEMORY)
{
my_error(ER_OUTOFMEMORY,MYF(ME_ERROR+ME_WAITTANG),sortbuff_size);
goto err;
}
- param.sort_form= table[0];
+ if (open_cached_file(&buffpek_pointers,mysql_tmpdir,TEMP_PREFIX,
+ DISK_BUFFER_SIZE, MYF(MY_WME)))
+ goto err;
+
+ param.keys--;
+ param.sort_form= table;
param.end=(param.local_sortorder=sortorder)+s_length;
- if ((records=find_all_keys(&param,select,sort_keys,buffpek,&maxbuffer,
+ if ((records=find_all_keys(&param,select,sort_keys, &buffpek_pointers,
&tempfile, selected_records_file)) ==
HA_POS_ERROR)
goto err;
+ maxbuffer= (uint) (my_b_tell(&buffpek_pointers)/sizeof(*buffpek));
+
if (maxbuffer == 0) // The whole set is in memory
{
if (save_index(&param,sort_keys,(uint) records))
@@ -216,6 +172,9 @@ ha_rows filesort(TABLE **table, SORT_FIELD *sortorder, uint s_length,
}
else
{
+ if (!(buffpek=read_buffpek_from_file(&buffpek_pointers, maxbuffer)))
+ goto err;
+ close_cached_file(&buffpek_pointers);
/* Open cached file if it isn't open */
if (! my_b_inited(outfile) &&
open_cached_file(outfile,mysql_tmpdir,TEMP_PREFIX,READ_RECORD_BUFFER,
@@ -223,14 +182,21 @@ ha_rows filesort(TABLE **table, SORT_FIELD *sortorder, uint s_length,
goto err;
reinit_io_cache(outfile,WRITE_CACHE,0L,0,0);
+ /*
+ Use also the space previously used by string pointers in sort_buffer
+ for temporary key storage.
+ */
param.keys=((param.keys*(param.sort_length+sizeof(char*))) /
param.sort_length-1);
- if (merge_many_buff(&param,sort_keys,buffpek,&maxbuffer,&tempfile))
+ maxbuffer--; // Offset from 0
+ if (merge_many_buff(&param,(uchar*) sort_keys,buffpek,&maxbuffer,
+ &tempfile))
goto err;
if (flush_io_cache(&tempfile) ||
reinit_io_cache(&tempfile,READ_CACHE,0L,0,0))
goto err;
- if (merge_index(&param,sort_keys,buffpek,maxbuffer,&tempfile,outfile))
+ if (merge_index(&param,(uchar*) sort_keys,buffpek,maxbuffer,&tempfile,
+ outfile))
goto err;
}
if (records > param.max_rows)
@@ -245,6 +211,7 @@ ha_rows filesort(TABLE **table, SORT_FIELD *sortorder, uint s_length,
x_free((gptr) sort_keys);
x_free((gptr) buffpek);
close_cached_file(&tempfile);
+ close_cached_file(&buffpek_pointers);
if (my_b_inited(outfile))
{
if (flush_io_cache(outfile))
@@ -262,7 +229,7 @@ ha_rows filesort(TABLE **table, SORT_FIELD *sortorder, uint s_length,
else
statistic_add(filesort_rows, records, &LOCK_status);
*examined_rows= param.examined_rows;
-#ifdef SKIPP_DBUG_IN_FILESORT
+#ifdef SKIP_DBUG_IN_FILESORT
DBUG_POP(); /* Ok to DBUG */
#endif
DBUG_PRINT("exit",("records: %ld",records));
@@ -289,11 +256,33 @@ static char **make_char_array(register uint fields, uint length, myf my_flag)
} /* make_char_array */
+ /* Read all buffer pointers into memory */
+
+static BUFFPEK *read_buffpek_from_file(IO_CACHE *buffpek_pointers, uint count)
+{
+ ulong length;
+ BUFFPEK *tmp;
+ DBUG_ENTER("read_buffpek_from_file");
+ tmp=(BUFFPEK*) my_malloc(length=sizeof(BUFFPEK)*count, MYF(MY_WME));
+ if (tmp)
+ {
+ if (reinit_io_cache(buffpek_pointers,READ_CACHE,0L,0,0) ||
+ my_b_read(buffpek_pointers, (byte*) tmp, length))
+ {
+ my_free((char*) tmp, MYF(0));
+ tmp=0;
+ }
+ }
+ DBUG_RETURN(tmp);
+}
+
+
+
/* Search after sort_keys and place them in a temp. file */
static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select,
uchar **sort_keys,
- BUFFPEK *buffpek, uint *maxbuffer,
+ IO_CACHE *buffpek_pointers,
IO_CACHE *tempfile, IO_CACHE *indexfile)
{
int error,flag,quick_select;
@@ -375,9 +364,8 @@ static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select,
{
if (idx == param->keys)
{
- if (indexpos >= *maxbuffer ||
- write_keys(param,sort_keys,idx,buffpek+indexpos,tempfile))
- DBUG_RETURN(HA_POS_ERROR);
+ if (write_keys(param,sort_keys,idx,buffpek_pointers,tempfile))
+ DBUG_RETURN(HA_POS_ERROR);
idx=0; indexpos++;
if (param->ref_length == param->sort_length &&
my_b_tell(tempfile)/param->sort_length >= param->max_rows)
@@ -399,11 +387,9 @@ static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select,
file->print_error(error,MYF(ME_ERROR | ME_WAITTANG)); /* purecov: inspected */
DBUG_RETURN(HA_POS_ERROR); /* purecov: inspected */
}
- if (indexpos)
- if (indexpos >= *maxbuffer ||
- write_keys(param,sort_keys,idx,buffpek+indexpos,tempfile))
- DBUG_RETURN(HA_POS_ERROR); /* purecov: inspected */
- *maxbuffer=indexpos;
+ if (indexpos &&
+ write_keys(param,sort_keys,idx,buffpek_pointers,tempfile))
+ DBUG_RETURN(HA_POS_ERROR); /* purecov: inspected */
DBUG_RETURN(my_b_inited(tempfile) ?
(ha_rows) (my_b_tell(tempfile)/param->sort_length) :
idx);
@@ -412,10 +398,13 @@ static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select,
/* Skriver en buffert med nycklar till filen */
-static int write_keys(SORTPARAM *param, register uchar **sort_keys, uint count,
- BUFFPEK *buffpek, IO_CACHE *tempfile)
+static int
+write_keys(SORTPARAM *param, register uchar **sort_keys, uint count,
+ IO_CACHE *buffpek_pointers, IO_CACHE *tempfile)
{
uint sort_length;
+ uchar **end;
+ BUFFPEK buffpek;
DBUG_ENTER("write_keys");
sort_length=param->sort_length;
@@ -427,15 +416,20 @@ static int write_keys(SORTPARAM *param, register uchar **sort_keys, uint count,
if (!my_b_inited(tempfile) &&
open_cached_file(tempfile,mysql_tmpdir,TEMP_PREFIX,DISK_BUFFER_SIZE,
MYF(MY_WME)))
- DBUG_RETURN(1); /* purecov: inspected */
- buffpek->file_pos=my_b_tell(tempfile);
+ goto err; /* purecov: inspected */
+ buffpek.file_pos=my_b_tell(tempfile);
if ((ha_rows) count > param->max_rows)
count=(uint) param->max_rows; /* purecov: inspected */
- buffpek->count=(ha_rows) count;
- for (uchar **end=sort_keys+count ; sort_keys != end ; sort_keys++)
+ buffpek.count=(ha_rows) count;
+ for (end=sort_keys+count ; sort_keys != end ; sort_keys++)
if (my_b_write(tempfile,(byte*) *sort_keys,(uint) sort_length))
- DBUG_RETURN(1);
+ goto err;
+ if (my_b_write(buffpek_pointers, (byte*) &buffpek, sizeof(buffpek)))
+ goto err;
DBUG_RETURN(0);
+
+err:
+ DBUG_RETURN(1);
} /* write_keys */
@@ -631,8 +625,8 @@ static bool save_index(SORTPARAM *param, uchar **sort_keys, uint count)
/* Merge buffers to make < MERGEBUFF2 buffers */
-static int merge_many_buff(SORTPARAM *param, uchar **sort_keys,
- BUFFPEK *buffpek, uint *maxbuffer, IO_CACHE *t_file)
+int merge_many_buff(SORTPARAM *param, uchar *sort_buffer,
+ BUFFPEK *buffpek, uint *maxbuffer, IO_CACHE *t_file)
{
register int i;
IO_CACHE t_file2,*from_file,*to_file,*temp;
@@ -654,11 +648,11 @@ static int merge_many_buff(SORTPARAM *param, uchar **sort_keys,
lastbuff=buffpek;
for (i=0 ; i <= (int) *maxbuffer-MERGEBUFF*3/2 ; i+=MERGEBUFF)
{
- if (merge_buffers(param,from_file,to_file,sort_keys,lastbuff++,
+ if (merge_buffers(param,from_file,to_file,sort_buffer,lastbuff++,
buffpek+i,buffpek+i+MERGEBUFF-1,0))
break; /* purecov: inspected */
}
- if (merge_buffers(param,from_file,to_file,sort_keys,lastbuff++,
+ if (merge_buffers(param,from_file,to_file,sort_buffer,lastbuff++,
buffpek+i,buffpek+ *maxbuffer,0))
break; /* purecov: inspected */
if (flush_io_cache(to_file))
@@ -677,8 +671,8 @@ static int merge_many_buff(SORTPARAM *param, uchar **sort_keys,
/* Read data to buffer */
/* This returns (uint) -1 if something goes wrong */
-static uint read_to_buffer(IO_CACHE *fromfile, BUFFPEK *buffpek,
- uint sort_length)
+uint read_to_buffer(IO_CACHE *fromfile, BUFFPEK *buffpek,
+ uint sort_length)
{
register uint count;
uint length;
@@ -699,39 +693,44 @@ static uint read_to_buffer(IO_CACHE *fromfile, BUFFPEK *buffpek,
/* Merge buffers to one buffer */
-static int merge_buffers(SORTPARAM *param, IO_CACHE *from_file,
- IO_CACHE *to_file, uchar **sort_keys,
- BUFFPEK *lastbuff, BUFFPEK *Fb, BUFFPEK *Tb,
- int flag)
+int merge_buffers(SORTPARAM *param, IO_CACHE *from_file,
+ IO_CACHE *to_file, uchar *sort_buffer,
+ BUFFPEK *lastbuff, BUFFPEK *Fb, BUFFPEK *Tb,
+ int flag)
{
int error;
uint sort_length,offset;
ulong maxcount;
- ha_rows count,max_rows;
+ ha_rows max_rows,org_max_rows;
my_off_t to_start_filepos;
uchar *strpos;
BUFFPEK *buffpek,**refpek;
QUEUE queue;
+ qsort2_cmp cmp;
volatile bool *killed= &current_thd->killed;
+ bool not_killable;
DBUG_ENTER("merge_buffers");
statistic_increment(filesort_merge_passes, &LOCK_status);
+ if (param->not_killable)
+ {
+ killed= &not_killable;
+ not_killable=0;
+ }
- count=error=0;
- offset=param->sort_length-param->ref_length;
+ error=0;
+ offset=(sort_length=param->sort_length)-param->ref_length;
maxcount=(ulong) (param->keys/((uint) (Tb-Fb) +1));
to_start_filepos=my_b_tell(to_file);
- strpos=(uchar*) sort_keys;
- sort_length=param->sort_length;
- max_rows=param->max_rows;
+ strpos=(uchar*) sort_buffer;
+ org_max_rows=max_rows=param->max_rows;
if (init_queue(&queue,(uint) (Tb-Fb)+1,offsetof(BUFFPEK,key),0,
(int (*) (void *, byte *,byte*))
- get_ptr_compare(sort_length),(void*) &sort_length))
+ (cmp=get_ptr_compare(sort_length)),(void*) &sort_length))
DBUG_RETURN(1); /* purecov: inspected */
for (buffpek= Fb ; buffpek <= Tb ; buffpek++)
{
- count+= buffpek->count;
buffpek->base= strpos;
buffpek->max_keys=maxcount;
strpos+= (uint) (error=(int) read_to_buffer(from_file,buffpek,
@@ -741,15 +740,46 @@ static int merge_buffers(SORTPARAM *param, IO_CACHE *from_file,
queue_insert(&queue,(byte*) buffpek);
}
+ if (param->unique_buff)
+ {
+ /*
+ Called by Unique::get()
+ Copy the first argument to param->unique_buff for unique removal.
+ Store it also in 'to_file'.
+
+ This is safe as we know that there is always more than one element
+ in each block to merge (This is guaranteed by the Unique:: algorithm
+ */
+ buffpek=(BUFFPEK*) queue_top(&queue);
+ memcpy(param->unique_buff, buffpek->key, sort_length);
+ if (my_b_write(to_file,(byte*) buffpek->key, sort_length))
+ {
+ error=1; goto err; /* purecov: inspected */
+ }
+ buffpek->key+=sort_length;
+ buffpek->mem_count--;
+ max_rows--;
+ queue_replaced(&queue); // Top element has been used
+ }
+ else
+ cmp=0; // Not unique
+
while (queue.elements > 1)
{
if (*killed)
{
- error=1; goto err; /* purecov: inspected */
+ error=1; goto err; /* purecov: inspected */
}
for (;;)
{
buffpek=(BUFFPEK*) queue_top(&queue);
+ if (cmp) // Remove duplicates
+ {
+ if (!(*cmp)(&sort_length, &(param->unique_buff),
+ (uchar**) &buffpek->key))
+ goto skip_duplicate;
+ memcpy(param->unique_buff, (uchar*) buffpek->key,sort_length);
+ }
if (flag == 0)
{
if (my_b_write(to_file,(byte*) buffpek->key, sort_length))
@@ -766,6 +796,8 @@ static int merge_buffers(SORTPARAM *param, IO_CACHE *from_file,
error=0; /* purecov: inspected */
goto end; /* purecov: inspected */
}
+
+ skip_duplicate:
buffpek->key+=sort_length;
if (! --buffpek->mem_count)
{
@@ -798,14 +830,28 @@ static int merge_buffers(SORTPARAM *param, IO_CACHE *from_file,
break; /* One buffer have been removed */
}
else if (error == -1)
- goto err; /* purecov: inspected */
+ goto err; /* purecov: inspected */
}
queue_replaced(&queue); /* Top element has been replaced */
}
}
buffpek=(BUFFPEK*) queue_top(&queue);
- buffpek->base=(uchar *) sort_keys;
+ buffpek->base= sort_buffer;
buffpek->max_keys=param->keys;
+
+ /*
+ As we know all entries in the buffer are unique, we only have to
+ check if the first one is the same as the last one we wrote
+ */
+ if (cmp)
+ {
+ if (!(*cmp)(&sort_length, &(param->unique_buff), (uchar**) &buffpek->key))
+ {
+ buffpek->key+=sort_length; // Remove duplicate
+ --buffpek->mem_count;
+ }
+ }
+
do
{
if ((ha_rows) buffpek->mem_count > max_rows)
@@ -813,6 +859,7 @@ static int merge_buffers(SORTPARAM *param, IO_CACHE *from_file,
buffpek->mem_count=(uint) max_rows;
buffpek->count=0; /* Don't read more */
}
+ max_rows-=buffpek->mem_count;
if (flag == 0)
{
if (my_b_write(to_file,(byte*) buffpek->key,
@@ -837,7 +884,7 @@ static int merge_buffers(SORTPARAM *param, IO_CACHE *from_file,
!= -1 && error != 0);
end:
- lastbuff->count=min(count,param->max_rows);
+ lastbuff->count=min(org_max_rows-max_rows,param->max_rows);
lastbuff->file_pos=to_start_filepos;
err:
delete_queue(&queue);
@@ -847,12 +894,12 @@ err:
/* Do a merge to output-file (save only positions) */
-static int merge_index(SORTPARAM *param, uchar **sort_keys,
+static int merge_index(SORTPARAM *param, uchar *sort_buffer,
BUFFPEK *buffpek, uint maxbuffer,
IO_CACHE *tempfile, IO_CACHE *outfile)
{
DBUG_ENTER("merge_index");
- if (merge_buffers(param,tempfile,outfile,sort_keys,buffpek,buffpek,
+ if (merge_buffers(param,tempfile,outfile,sort_buffer,buffpek,buffpek,
buffpek+maxbuffer,1))
DBUG_RETURN(1); /* purecov: inspected */
DBUG_RETURN(0);
diff --git a/sql/frm_crypt.cc b/sql/frm_crypt.cc
index 629e4ffab95..8dd70900648 100644
--- a/sql/frm_crypt.cc
+++ b/sql/frm_crypt.cc
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
diff --git a/sql/gen_lex_hash.cc b/sql/gen_lex_hash.cc
index 7bbf08b50f3..7ebdbcd8ba8 100644
--- a/sql/gen_lex_hash.cc
+++ b/sql/gen_lex_hash.cc
@@ -16,17 +16,18 @@
#define NO_YACC_SYMBOLS
-#include <global.h>
+#include <my_global.h>
#include <my_sys.h>
#include <m_string.h>
#ifndef __GNU_LIBRARY__
-#define __GNU_LIBRARY__ // Skipp warnings in getopt.h
+#define __GNU_LIBRARY__ // Skip warnings in getopt.h
#endif
#include <getopt.h>
#include "mysql_version.h"
#include "lex.h"
-bool opt_search=0,opt_verbose=0;
+bool opt_search=0;
+int opt_verbose=0;
ulong opt_count=100000;
#define max_allowed_array 8000 // Don't generate bigger arrays than this
@@ -216,7 +217,7 @@ you have to change 'main' to print out the new function\n");
return(1);
}
- if (opt_verbose)
+ if (opt_verbose > 1)
fprintf (stderr,"Info: Possible add values: %d\n",found-type_count);
for (prime=primes; (function_mod=*prime) ; prime++)
@@ -385,7 +386,7 @@ static int get_options(int argc, char **argv)
opt_search=1;
break;
case 'v':
- opt_verbose=1;
+ opt_verbose++;
break;
case 'V': usage(1); exit(0);
case 'I':
@@ -481,7 +482,8 @@ int main(int argc,char **argv)
int error;
MY_INIT(argv[0]);
- start_value=6130115L; best_t1=3632784L; best_t2=86437L; best_type=3; /* mode=4229 add=2 type: 0 */
+
+ start_value=1109118L; best_t1=6657025L; best_t2=6114496L; best_type=1; /* mode=4903 add=3 type: 0 */
if (get_options(argc,(char **) argv))
exit(1);
@@ -501,7 +503,7 @@ int main(int argc,char **argv)
printf("start_value=%ldL; best_t1=%ldL; best_t2=%ldL; best_type=%d; /* mode=%d add=%d type: %d */\n",
start_value, best_t1,best_t2,best_type,best_mod,best_add,
best_functype);
-
+ best_start_value=start_value;
for (uint i=1 ; i <= opt_count ; i++)
{
if (i % 10 == 0)
@@ -524,6 +526,10 @@ int main(int argc,char **argv)
best_start_value,best_t1,best_t2,best_type,best_mod,best_add,
best_functype);
}
+ if (opt_verbose && (i % 20000) == 0)
+ printf("\nstart_value=%ldL; best_t1=%ldL; best_t2=%ldL; best_type=%d; /* mode=%d add=%d type: %d */\n",
+ best_start_value,best_t1,best_t2,best_type,best_mod,best_add,
+ best_functype);
}
}
diff --git a/sql/ha_berkeley.cc b/sql/ha_berkeley.cc
index f52b99f5a12..614d1b5abf5 100644
--- a/sql/ha_berkeley.cc
+++ b/sql/ha_berkeley.cc
@@ -1043,9 +1043,9 @@ int ha_berkeley::restore_keys(DB_TXN *trans, key_map changed_keys,
break; /* purecov: inspected */
}
}
-
+
err:
- dbug_assert(error != DB_KEYEXIST);
+ DBUG_ASSERT(error != DB_KEYEXIST);
DBUG_RETURN(error);
}
@@ -1187,7 +1187,7 @@ int ha_berkeley::remove_key(DB_TXN *trans, uint keynr, const byte *record,
((table->key_info[keynr].flags & (HA_NOSAME | HA_NULL_PART_KEY)) ==
HA_NOSAME))
{ // Unique key
- dbug_assert(keynr == primary_key || prim_key->data != key_buff2);
+ DBUG_ASSERT(keynr == primary_key || prim_key->data != key_buff2);
error=key_file[keynr]->del(key_file[keynr], trans,
keynr == primary_key ?
prim_key :
@@ -1201,7 +1201,7 @@ int ha_berkeley::remove_key(DB_TXN *trans, uint keynr, const byte *record,
row to find the key to be delete and delete it.
We will never come here with keynr = primary_key
*/
- dbug_assert(keynr != primary_key && prim_key->data != key_buff2);
+ DBUG_ASSERT(keynr != primary_key && prim_key->data != key_buff2);
DBC *tmp_cursor;
if (!(error=key_file[keynr]->cursor(key_file[keynr], trans,
&tmp_cursor, 0)))
@@ -1454,6 +1454,37 @@ int ha_berkeley::index_read(byte * buf, const byte * key,
DBUG_RETURN(error);
}
+/*
+ Read last key is solved by reading the next key and then reading
+ the previous key
+*/
+
+int ha_berkeley::index_read_last(byte * buf, const byte * key, uint key_len)
+{
+ DBT row;
+ int error;
+ KEY *key_info= &table->key_info[active_index];
+ DBUG_ENTER("ha_berkeley::index_read");
+
+ statistic_increment(ha_read_key_count,&LOCK_status);
+ bzero((char*) &row,sizeof(row));
+
+ /* read of partial key */
+ pack_key(&last_key, active_index, key_buff, key, key_len);
+ /* Store for compare */
+ memcpy(key_buff2, key_buff, (key_len=last_key.size));
+ key_info->handler.bdb_return_if_eq= 1;
+ error=read_row(cursor->c_get(cursor, &last_key, &row, DB_SET_RANGE),
+ (char*) buf, active_index, &row, (DBT*) 0, 0);
+ key_info->handler.bdb_return_if_eq= 0;
+ bzero((char*) &row,sizeof(row));
+ if (read_row(cursor->c_get(cursor, &last_key, &row, DB_PREV),
+ (char*) buf, active_index, &row, &last_key, 1) ||
+ berkeley_key_cmp(table, key_info, key_buff2, key_len))
+ error=HA_ERR_KEY_NOT_FOUND;
+ DBUG_RETURN(error);
+}
+
int ha_berkeley::index_next(byte * buf)
{
@@ -1565,12 +1596,13 @@ int ha_berkeley::rnd_pos(byte * buf, byte *pos)
{
DBT db_pos;
statistic_increment(ha_read_rnd_count,&LOCK_status);
+ DBUG_ENTER("ha_berkeley::rnd_pos");
active_index= (uint) -1; // Don't delete via cursor
- return read_row(file->get(file, transaction,
- get_pos(&db_pos, pos),
- &current_row, 0),
- (char*) buf, primary_key, &current_row, (DBT*) 0, 0);
+ DBUG_RETURN(read_row(file->get(file, transaction,
+ get_pos(&db_pos, pos),
+ &current_row, 0),
+ (char*) buf, primary_key, &current_row, (DBT*) 0, 0));
}
void ha_berkeley::position(const byte *record)
@@ -1879,13 +1911,14 @@ int ha_berkeley::delete_table(const char *name)
{
int error;
char name_buff[FN_REFLEN];
+ DBUG_ENTER("delete_table");
if ((error=db_create(&file, db_env, 0)))
my_errno=error; /* purecov: inspected */
else
error=file->remove(file,fn_format(name_buff,name,"",ha_berkeley_ext,2 | 4),
NULL,0);
file=0; // Safety
- return error;
+ DBUG_RETURN(error);
}
/*
@@ -2175,7 +2208,7 @@ static BDB_SHARE *get_share(const char *table_name, TABLE *table)
char *tmp_name;
DB **key_file;
u_int32_t *key_type;
-
+
if ((share=(BDB_SHARE *)
my_multi_malloc(MYF(MY_WME | MY_ZEROFILL),
&share, sizeof(*share),
diff --git a/sql/ha_berkeley.h b/sql/ha_berkeley.h
index ab1ead5a3e9..f30d4e12d6d 100644
--- a/sql/ha_berkeley.h
+++ b/sql/ha_berkeley.h
@@ -89,15 +89,16 @@ class ha_berkeley: public handler
int_option_flag(HA_READ_NEXT | HA_READ_PREV |
HA_REC_NOT_IN_SEQ |
HA_KEYPOS_TO_RNDPOS | HA_READ_ORDER | HA_LASTKEY_ORDER |
- HA_LONGLONG_KEYS | HA_NULL_KEY | HA_HAVE_KEY_READ_ONLY |
- HA_BLOB_KEY | HA_NOT_EXACT_COUNT | HA_NO_FULLTEXT_KEY |
+ HA_NULL_KEY | HA_HAVE_KEY_READ_ONLY |
+ HA_BLOB_KEY | HA_NOT_EXACT_COUNT |
HA_PRIMARY_KEY_IN_READ_INDEX | HA_DROP_BEFORE_CREATE |
- HA_AUTO_PART_KEY),
+ HA_AUTO_PART_KEY | HA_TABLE_SCAN_ON_INDEX),
changed_rows(0),last_dup_key((uint) -1),version(0),using_ignore(0)
{
}
~ha_berkeley() {}
const char *table_type() const { return "BerkeleyDB"; }
+ const char *index_type(uint key_number) { return "BTREE"; }
const char **bas_ext() const;
ulong option_flag() const { return int_option_flag; }
uint max_record_length() const { return HA_MAX_REC_LENGTH; }
@@ -122,6 +123,7 @@ class ha_berkeley: public handler
uint key_len, enum ha_rkey_function find_flag);
int index_read_idx(byte * buf, uint index, const byte * key,
uint key_len, enum ha_rkey_function find_flag);
+ int index_read_last(byte * buf, const byte * key, uint key_len);
int index_next(byte * buf);
int index_next_same(byte * buf, const byte *key, uint keylen);
int index_prev(byte * buf);
diff --git a/sql/ha_gemini.cc b/sql/ha_gemini.cc
deleted file mode 100644
index e8130c55fc7..00000000000
--- a/sql/ha_gemini.cc
+++ /dev/null
@@ -1,3630 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & NuSphere Corporation
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-/* This file is based on ha_berkeley.cc */
-
-#ifdef __GNUC__
-#pragma implementation // gcc: Class implementation
-#endif
-
-#include "mysql_priv.h"
-#ifdef HAVE_GEMINI_DB
-#include "ha_gemini.h"
-#include "dbconfig.h"
-#include "dsmpub.h"
-#include "recpub.h"
-#include "vststat.h"
-
-#include <m_ctype.h>
-#include <myisampack.h>
-#include <m_string.h>
-#include <assert.h>
-#include <hash.h>
-#include <stdarg.h>
-#include "geminikey.h"
-
-#define gemini_msg MSGD_CALLBACK
-
-pthread_mutex_t gem_mutex;
-
-static HASH gem_open_tables;
-static GEM_SHARE *get_share(const char *table_name, TABLE *table);
-static int free_share(GEM_SHARE *share, bool mutex_is_locked);
-static byte* gem_get_key(GEM_SHARE *share,uint *length,
- my_bool not_used __attribute__((unused)));
-static void gemini_lock_table_overflow_error(dsmContext_t *pcontext);
-
-const char *ha_gemini_ext=".gmd";
-const char *ha_gemini_idx_ext=".gmi";
-
-bool gemini_skip=0;
-long gemini_options = 0;
-long gemini_buffer_cache;
-long gemini_io_threads;
-long gemini_log_cluster_size;
-long gemini_locktablesize;
-long gemini_lock_wait_timeout;
-long gemini_spin_retries;
-long gemini_connection_limit;
-char *gemini_basedir;
-
-const char gemini_dbname[] = "gemini";
-dsmContext_t *pfirstContext = NULL;
-
-ulong gemini_recovery_options = GEMINI_RECOVERY_FULL;
-/* bits in gemini_recovery_options */
-const char *gemini_recovery_names[] =
-{ "FULL", "NONE", "FORCE" };
-TYPELIB gemini_recovery_typelib= {array_elements(gemini_recovery_names),"",
- gemini_recovery_names};
-
-const int start_of_name = 2; /* Name passed as ./<db>/<table-name>
- and we're not interested in the ./ */
-static const int keyBufSize = MAXKEYSZ + FULLKEYHDRSZ + MAX_REF_PARTS + 16;
-
-static int gemini_tx_begin(THD *thd);
-static void print_msg(THD *thd, const char *table_name, const char *op_name,
- const char *msg_type, const char *fmt, ...);
-
-static int gemini_helper_threads(dsmContext_t *pContext);
-pthread_handler_decl(gemini_watchdog,arg );
-pthread_handler_decl(gemini_rl_writer,arg );
-pthread_handler_decl(gemini_apw,arg);
-
-/* General functions */
-
-bool gemini_init(void)
-{
- dsmStatus_t rc = 0;
- char pmsgsfile[MAXPATHN];
-
- DBUG_ENTER("gemini_init");
-
- gemini_basedir=mysql_home;
- /* If datadir isn't set, bail out */
- if (*mysql_real_data_home == '\0')
- {
- goto badret;
- }
-
- /* dsmContextCreate and dsmContextSetString(DSM_TAGDB_DBNAME) must
- ** be the first DSM calls we make so that we can log any errors which
- ** occur in subsequent DSM calls. DO NOT INSERT ANY DSM CALLS IN
- ** BETWEEN THIS COMMENT AND THE COMMENT THAT SAYS "END OF CODE..."
- */
- /* Gotta connect to the database regardless of the operation */
- rc = dsmContextCreate(&pfirstContext);
- if( rc != 0 )
- {
- gemini_msg(pfirstContext, "dsmContextCreate failed %l",rc);
- goto badret;
- }
- /* This call will also open the log file */
- rc = dsmContextSetString(pfirstContext, DSM_TAGDB_DBNAME,
- strlen(gemini_dbname), (TEXT *)gemini_dbname);
- if( rc != 0 )
- {
- gemini_msg(pfirstContext, "Dbname tag failed %l", rc);
- goto badret;
- }
- /* END OF CODE NOT TO MESS WITH */
-
- fn_format(pmsgsfile, GEM_MSGS_FILE, language, ".db", 2 | 4);
- rc = dsmContextSetString(pfirstContext, DSM_TAGDB_MSGS_FILE,
- strlen(pmsgsfile), (TEXT *)pmsgsfile);
- if( rc != 0 )
- {
- gemini_msg(pfirstContext, "MSGS_DIR tag failed %l", rc);
- goto badret;
- }
-
- strxmov(pmsgsfile, gemini_basedir, GEM_SYM_FILE, NullS);
- rc = dsmContextSetString(pfirstContext, DSM_TAGDB_SYMFILE,
- strlen(pmsgsfile), (TEXT *)pmsgsfile);
- if( rc != 0 )
- {
- gemini_msg(pfirstContext, "SYMFILE tag failed %l", rc);
- goto badret;
- }
-
- rc = dsmContextSetLong(pfirstContext,DSM_TAGDB_ACCESS_TYPE,DSM_ACCESS_STARTUP);
- if ( rc != 0 )
- {
- gemini_msg(pfirstContext, "ACCESS TAG set failed %l",rc);
- goto badret;
- }
- rc = dsmContextSetLong(pfirstContext,DSM_TAGDB_ACCESS_ENV, DSM_SQL_ENGINE);
- if( rc != 0 )
- {
- gemini_msg(pfirstContext, "ACCESS_ENV set failed %l",rc);
- goto badret;
- }
-
- rc = dsmContextSetString(pfirstContext, DSM_TAGDB_DATADIR,
- strlen(mysql_real_data_home),
- (TEXT *)mysql_real_data_home);
- if( rc != 0 )
- {
- gemini_msg(pfirstContext, "Datadir tag failed %l", rc);
- goto badret;
- }
-
- rc = dsmContextSetLong(pfirstContext, DSM_TAGDB_MAX_USERS,
- gemini_connection_limit);
- if(rc != 0)
- {
- gemini_msg(pfirstContext, "MAX_USERS tag set failed %l",rc);
- goto badret;
- }
-
- rc = dsmContextSetLong(pfirstContext, DSM_TAGDB_DEFAULT_LOCK_TIMEOUT,
- gemini_lock_wait_timeout);
- if(rc != 0)
- {
- gemini_msg(pfirstContext, "MAX_LOCK_ENTRIES tag set failed %l",rc);
- goto badret;
- }
-
- rc = dsmContextSetLong(pfirstContext, DSM_TAGDB_MAX_LOCK_ENTRIES,
- gemini_locktablesize);
- if(rc != 0)
- {
- gemini_msg(pfirstContext, "MAX_LOCK_ENTRIES tag set failed %l",rc);
- goto badret;
- }
-
- rc = dsmContextSetLong(pfirstContext, DSM_TAGDB_SPIN_AMOUNT,
- gemini_spin_retries);
- if(rc != 0)
- {
- gemini_msg(pfirstContext, "SPIN_AMOUNT tag set failed %l",rc);
- goto badret;
- }
-
- /* blocksize is hardcoded to 8K. Buffer cache is in bytes
- need to convert this to 8K blocks */
- gemini_buffer_cache = gemini_buffer_cache / 8192;
- rc = dsmContextSetLong(pfirstContext, DSM_TAGDB_DB_BUFFERS,
- gemini_buffer_cache);
- if(rc != 0)
- {
- gemini_msg(pfirstContext, "DB_BUFFERS tag set failed %l",rc);
- goto badret;
- }
-
- rc = dsmContextSetLong(pfirstContext, DSM_TAGDB_FLUSH_AT_COMMIT,
- ((gemini_options & GEMOPT_FLUSH_LOG) ? 0 : 1));
- if(rc != 0)
- {
- gemini_msg(pfirstContext, "FLush_Log_At_Commit tag set failed %l",rc);
- goto badret;
- }
- rc = dsmContextSetLong(pfirstContext, DSM_TAGDB_DIRECT_IO,
- ((gemini_options & GEMOPT_UNBUFFERED_IO) ? 1 : 0));
- if(rc != 0)
- {
- gemini_msg(pfirstContext, "DIRECT_IO tag set failed %l",rc);
- goto badret;
- }
-
- rc = dsmContextSetLong(pfirstContext, DSM_TAGDB_CRASH_PROTECTION,
- ((gemini_recovery_options & GEMINI_RECOVERY_FULL) ? 1 : 0));
- if(rc != 0)
- {
- gemini_msg(pfirstContext, "CRASH_PROTECTION tag set failed %l",rc);
- goto badret;
- }
-
- if (gemini_recovery_options & GEMINI_RECOVERY_FORCE)
- {
- rc = dsmContextSetLong(pfirstContext, DSM_TAGDB_FORCE_ACCESS, 1);
- if(rc != 0)
- {
- printf("CRASH_PROTECTION tag set failed %ld",rc);
- goto badret;
- }
- }
-
- /* cluster size will come in bytes, need to convert it to
- 16 K units. */
- gemini_log_cluster_size = (gemini_log_cluster_size + 16383) / 16384;
- rc = dsmContextSetLong(pfirstContext, DSM_TAGDB_BI_CLUSTER_SIZE,
- gemini_log_cluster_size);
-
- if(rc != 0)
- {
- gemini_msg(pfirstContext, "CRASH_PROTECTION tag set failed %l",rc);
- goto badret;
- }
-
- rc = dsmUserConnect(pfirstContext,(TEXT *)"Multi-user",
- DSM_DB_OPENDB | DSM_DB_OPENFILE);
- if( rc != 0 )
- {
- /* Message is output in dbenv() */
- goto badret;
- }
- /* Set access to shared for subsequent user connects */
- rc = dsmContextSetLong(pfirstContext,DSM_TAGDB_ACCESS_TYPE,DSM_ACCESS_SHARED);
-
- rc = gemini_helper_threads(pfirstContext);
-
-
- (void) hash_init(&gem_open_tables,32,0,0,
- (hash_get_key) gem_get_key,0,0);
- pthread_mutex_init(&gem_mutex,NULL);
-
-
- DBUG_RETURN(0);
-
-badret:
- gemini_skip = 1;
- DBUG_RETURN(0);
-}
-
-static int gemini_helper_threads(dsmContext_t *pContext)
-{
- int rc = 0;
- int i;
- pthread_attr_t thr_attr;
-
- pthread_t hThread;
- DBUG_ENTER("gemini_helper_threads");
-
- (void) pthread_attr_init(&thr_attr);
-#if !defined(HAVE_DEC_3_2_THREADS)
- pthread_attr_setscope(&thr_attr,PTHREAD_SCOPE_SYSTEM);
- (void) pthread_attr_setdetachstate(&thr_attr,PTHREAD_CREATE_DETACHED);
- pthread_attr_setstacksize(&thr_attr,32768);
-#endif
- rc = pthread_create (&hThread, &thr_attr, gemini_watchdog, (void *)pContext);
- if (rc)
- {
- gemini_msg(pContext, "Can't Create gemini watchdog thread");
- goto done;
- }
- if(!gemini_io_threads)
- goto done;
-
- rc = pthread_create(&hThread, &thr_attr, gemini_rl_writer, (void *)pContext);
- if(rc)
- {
- gemini_msg(pContext, "Can't create Gemini recovery log writer thread");
- goto done;
- }
-
- for(i = gemini_io_threads - 1;i;i--)
- {
- rc = pthread_create(&hThread, &thr_attr, gemini_apw, (void *)pContext);
- if(rc)
- {
- gemini_msg(pContext, "Can't create Gemini database page writer thread");
- goto done;
- }
- }
-done:
-
- DBUG_RETURN(rc);
-}
-
-pthread_handler_decl(gemini_watchdog,arg )
-{
- int rc = 0;
- dsmContext_t *pcontext = (dsmContext_t *)arg;
- dsmContext_t *pmyContext = NULL;
-
-
- rc = dsmContextCopy(pcontext,&pmyContext, DSMCONTEXTDB);
- if( rc != 0 )
- {
- gemini_msg(pcontext, "dsmContextCopy failed for Gemini watchdog %d",rc);
-
- return 0;
- }
- rc = dsmUserConnect(pmyContext,NULL,0);
-
- if( rc != 0 )
- {
- gemini_msg(pcontext, "dsmUserConnect failed for Gemini watchdog %d",rc);
-
- return 0;
- }
-
- my_thread_init();
- pthread_detach_this_thread();
-
- while(rc == 0)
- {
- rc = dsmDatabaseProcessEvents(pmyContext);
- if(!rc)
- rc = dsmWatchdog(pmyContext);
- sleep(1);
- }
- rc = dsmUserDisconnect(pmyContext,0);
- my_thread_end();
- return 0;
-}
-
-pthread_handler_decl(gemini_rl_writer,arg )
-{
- int rc = 0;
- dsmContext_t *pcontext = (dsmContext_t *)arg;
- dsmContext_t *pmyContext = NULL;
-
-
- rc = dsmContextCopy(pcontext,&pmyContext, DSMCONTEXTDB);
- if( rc != 0 )
- {
- gemini_msg(pcontext, "dsmContextCopy failed for Gemini recovery log writer %d",rc);
-
- return 0;
- }
- rc = dsmUserConnect(pmyContext,NULL,0);
-
- if( rc != 0 )
- {
- gemini_msg(pcontext, "dsmUserConnect failed for Gemini recovery log writer %d",rc);
-
- return 0;
- }
-
- my_thread_init();
- pthread_detach_this_thread();
-
- while(rc == 0)
- {
- rc = dsmRLwriter(pmyContext);
- }
- rc = dsmUserDisconnect(pmyContext,0);
- my_thread_end();
- return 0;
-}
-
-pthread_handler_decl(gemini_apw,arg )
-{
- int rc = 0;
- dsmContext_t *pcontext = (dsmContext_t *)arg;
- dsmContext_t *pmyContext = NULL;
-
- my_thread_init();
- pthread_detach_this_thread();
-
- rc = dsmContextCopy(pcontext,&pmyContext, DSMCONTEXTDB);
- if( rc != 0 )
- {
- gemini_msg(pcontext, "dsmContextCopy failed for Gemini page writer %d",rc);
- my_thread_end();
- return 0;
- }
- rc = dsmUserConnect(pmyContext,NULL,0);
-
- if( rc != 0 )
- {
- gemini_msg(pcontext, "dsmUserConnect failed for Gemini page writer %d",rc);
- my_thread_end();
- return 0;
- }
-
- while(rc == 0)
- {
- rc = dsmAPW(pmyContext);
- }
- rc = dsmUserDisconnect(pmyContext,0);
- my_thread_end();
- return 0;
-}
-
-int gemini_set_option_long(int optid, long optval)
-{
- dsmStatus_t rc = 0;
-
- switch (optid)
- {
- case GEM_OPTID_SPIN_RETRIES:
- /* If we don't have a context yet, skip the set and just save the
- ** value in gemini_spin_retries for a later gemini_init(). This
- ** may not ever happen, but we're covered if it does.
- */
- if (pfirstContext)
- {
- rc = dsmContextSetLong(pfirstContext, DSM_TAGDB_SPIN_AMOUNT,
- optval);
- }
- if (rc)
- {
- gemini_msg(pfirstContext, "SPIN_AMOUNT tag set failed %l",rc);
- }
- else
- {
- gemini_spin_retries = optval;
- }
- break;
- }
-
- return rc;
-}
-
-static int gemini_connect(THD *thd)
-{
- DBUG_ENTER("gemini_connect");
-
- dsmStatus_t rc;
-
- rc = dsmContextCopy(pfirstContext,(dsmContext_t **)&thd->gemini.context,
- DSMCONTEXTDB);
- if( rc != 0 )
- {
- gemini_msg(pfirstContext, "dsmContextCopy failed %l",rc);
-
- return(rc);
- }
- rc = dsmUserConnect((dsmContext_t *)thd->gemini.context,NULL,0);
-
- if( rc != 0 )
- {
- gemini_msg(pfirstContext, "dsmUserConnect failed %l",rc);
-
- return(rc);
- }
- rc = (dsmStatus_t)gemini_tx_begin(thd);
-
- DBUG_RETURN(rc);
-}
-
-void gemini_disconnect(THD *thd)
-{
- dsmStatus_t rc;
-
- if(thd->gemini.context)
- {
- rc = dsmUserDisconnect((dsmContext_t *)thd->gemini.context,0);
- }
- return;
-}
-
-bool gemini_end(void)
-{
- dsmStatus_t rc;
- THD *thd;
-
- DBUG_ENTER("gemini_end");
-
- hash_free(&gem_open_tables);
- pthread_mutex_destroy(&gem_mutex);
- if(pfirstContext)
- {
- rc = dsmShutdownSet(pfirstContext, DSM_SHUTDOWN_NORMAL);
- sleep(2);
- rc = dsmContextSetLong(pfirstContext,DSM_TAGDB_ACCESS_TYPE,DSM_ACCESS_STARTUP);
- rc = dsmShutdown(pfirstContext, DSMNICEBIT,DSMNICEBIT);
- }
- DBUG_RETURN(0);
-}
-
-bool gemini_flush_logs()
-{
- DBUG_ENTER("gemini_flush_logs");
-
- DBUG_RETURN(0);
-}
-
-static int gemini_tx_begin(THD *thd)
-{
- dsmStatus_t rc;
- DBUG_ENTER("gemini_tx_begin");
-
- thd->gemini.savepoint = 1;
-
- rc = dsmTransaction((dsmContext_t *)thd->gemini.context,
- &thd->gemini.savepoint,DSMTXN_START,0,NULL);
- if(!rc)
- thd->gemini.needSavepoint = 1;
-
- thd->gemini.tx_isolation = thd->tx_isolation;
-
- DBUG_PRINT("trans",("beginning transaction"));
- DBUG_RETURN(rc);
-}
-
-int gemini_commit(THD *thd)
-{
- dsmStatus_t rc;
- LONG txNumber = 0;
-
- DBUG_ENTER("gemini_commit");
-
- if(!thd->gemini.context)
- DBUG_RETURN(0);
-
- rc = dsmTransaction((dsmContext_t *)thd->gemini.context,
- 0,DSMTXN_COMMIT,0,NULL);
- if(!rc)
- rc = gemini_tx_begin(thd);
-
- thd->gemini.lock_count = 0;
-
- DBUG_PRINT("trans",("ending transaction"));
- DBUG_RETURN(rc);
-}
-
-int gemini_rollback(THD *thd)
-{
- dsmStatus_t rc;
- LONG txNumber;
-
- DBUG_ENTER("gemini_rollback");
- DBUG_PRINT("trans",("aborting transaction"));
-
- if(!thd->gemini.context)
- DBUG_RETURN(0);
-
- thd->gemini.savepoint = 0;
- rc = dsmTransaction((dsmContext_t *)thd->gemini.context,
- &thd->gemini.savepoint,DSMTXN_ABORT,0,NULL);
- if(!rc)
- rc = gemini_tx_begin(thd);
-
- thd->gemini.lock_count = 0;
-
- DBUG_RETURN(rc);
-}
-
-int gemini_rollback_to_savepoint(THD *thd)
-{
- dsmStatus_t rc = 0;
- DBUG_ENTER("gemini_rollback_to_savepoint");
- if(thd->gemini.savepoint > 1)
- {
- rc = dsmTransaction((dsmContext_t *)thd->gemini.context,
- &thd->gemini.savepoint,DSMTXN_UNSAVE,0,NULL);
- }
- DBUG_RETURN(rc);
-}
-
-int gemini_recovery_logging(THD *thd, bool on)
-{
- int error;
- int noLogging;
-
- if(!thd->gemini.context)
- return 0;
-
- if(on)
- noLogging = 0;
- else
- noLogging = 1;
-
- error = dsmContextSetLong((dsmContext_t *)thd->gemini.context,
- DSM_TAGCONTEXT_NO_LOGGING,noLogging);
- return error;
-}
-
-/* gemDataType - translates from mysql data type constant to gemini
- key services data type contstant */
-int gemDataType ( int mysqlType )
-{
- switch (mysqlType)
- {
- case FIELD_TYPE_LONG:
- case FIELD_TYPE_TINY:
- case FIELD_TYPE_SHORT:
- case FIELD_TYPE_TIMESTAMP:
- case FIELD_TYPE_LONGLONG:
- case FIELD_TYPE_INT24:
- case FIELD_TYPE_DATE:
- case FIELD_TYPE_TIME:
- case FIELD_TYPE_DATETIME:
- case FIELD_TYPE_YEAR:
- case FIELD_TYPE_NEWDATE:
- case FIELD_TYPE_ENUM:
- case FIELD_TYPE_SET:
- return GEM_INT;
- case FIELD_TYPE_DECIMAL:
- return GEM_DECIMAL;
- case FIELD_TYPE_FLOAT:
- return GEM_FLOAT;
- case FIELD_TYPE_DOUBLE:
- return GEM_DOUBLE;
- case FIELD_TYPE_TINY_BLOB:
- return GEM_TINYBLOB;
- case FIELD_TYPE_MEDIUM_BLOB:
- return GEM_MEDIUMBLOB;
- case FIELD_TYPE_LONG_BLOB:
- return GEM_LONGBLOB;
- case FIELD_TYPE_BLOB:
- return GEM_BLOB;
- case FIELD_TYPE_VAR_STRING:
- case FIELD_TYPE_STRING:
- return GEM_CHAR;
- }
- return -1;
-}
-
-/*****************************************************************************
-** Gemini tables
-*****************************************************************************/
-
-const char **ha_gemini::bas_ext() const
-{ static const char *ext[]= { ha_gemini_ext, ha_gemini_idx_ext, NullS };
- return ext;
-}
-
-
-int ha_gemini::open(const char *name, int mode, uint test_if_locked)
-{
- dsmObject_t tableId = 0;
- THD *thd;
- char name_buff[FN_REFLEN];
- char tabname_buff[FN_REFLEN];
- char dbname_buff[FN_REFLEN];
- unsigned i,nameLen;
- LONG txNumber;
- dsmStatus_t rc;
-
- DBUG_ENTER("ha_gemini::open");
-
- thd = current_thd;
- /* Init shared structure */
- if (!(share=get_share(name,table)))
- {
- DBUG_RETURN(1); /* purecov: inspected */
- }
- thr_lock_data_init(&share->lock,&lock,(void*) 0);
-
- ref_length = sizeof(dsmRecid_t);
-
- if(thd->gemini.context == NULL)
- {
- /* Need to get this thread a connection into the database */
- rc = gemini_connect(thd);
- if(rc)
- return rc;
- }
- if (!(rec_buff=(byte*)my_malloc(table->rec_buff_length,
- MYF(MY_WME))))
- {
- DBUG_RETURN(1);
- }
-
- /* separate out the name of the table and the database (a VST must be
- ** created in the mysql database)
- */
- rc = gemini_parse_table_name(name, dbname_buff, tabname_buff);
- if (rc == 0)
- {
- if (strcmp(dbname_buff, "mysql") == 0)
- {
- tableId = gemini_is_vst(tabname_buff);
- }
- }
- sprintf(name_buff, "%s.%s", dbname_buff, tabname_buff);
-
- /* if it's not a VST, get the table number the regular way */
- if (!tableId)
- {
- rc = dsmObjectNameToNum((dsmContext_t *)thd->gemini.context,
- (dsmText_t *)name_buff,
- &tableId);
- if (rc)
- {
- gemini_msg((dsmContext_t *)thd->gemini.context,
- "Unable to find table number for %s", name_buff);
- DBUG_RETURN(rc);
- }
- }
- tableNumber = tableId;
-
- if(!rc)
- rc = index_open(name_buff);
-
- fixed_length_row=!(table->db_create_options & HA_OPTION_PACK_RECORD);
- key_read = 0;
- using_ignore = 0;
-
- /* Get the gemini table status -- we want to know if the table
- crashed while being in the midst of a repair operation */
- rc = dsmTableStatus((dsmContext_t *)thd->gemini.context,
- tableNumber,&tableStatus);
- if(tableStatus == DSM_OBJECT_IN_REPAIR)
- tableStatus = HA_ERR_CRASHED;
-
- pthread_mutex_lock(&share->mutex);
- share->use_count++;
- pthread_mutex_unlock(&share->mutex);
-
- if (table->blob_fields)
- {
- /* Allocate room for the blob ids from an unpacked row. Note that
- ** we may not actually need all of this space because tiny blobs
- ** are stored in the packed row, not in a separate storage object
- ** like larger blobs. But we allocate an entry for all blobs to
- ** keep the code simpler.
- */
- pBlobDescs = (gemBlobDesc_t *)my_malloc(
- table->blob_fields * sizeof(gemBlobDesc_t),
- MYF(MY_WME | MY_ZEROFILL));
- }
- else
- {
- pBlobDescs = 0;
- }
-
- get_index_stats(thd);
- info(HA_STATUS_CONST);
-
- DBUG_RETURN (rc);
-}
-
-/* Look up and store the object numbers for the indexes on this table */
-int ha_gemini::index_open(char *tableName)
-{
- dsmStatus_t rc = 0;
- int nameLen;
-
- DBUG_ENTER("ha_gemini::index_open");
- if(table->keys)
- {
- THD *thd = current_thd;
- dsmObject_t objectNumber;
- if (!(pindexNumbers=(dsmIndex_t *)my_malloc(table->keys*sizeof(dsmIndex_t),
- MYF(MY_WME))))
- {
- DBUG_RETURN(1);
- }
- nameLen = strlen(tableName);
- tableName[nameLen] = '.';
- nameLen++;
-
- for( uint i = 0; i < table->keys && !rc; i++)
- {
- strcpy(&tableName[nameLen],table->key_info[i].name);
- rc = dsmObjectNameToNum((dsmContext_t *)thd->gemini.context,
- (dsmText_t *)tableName,
- &objectNumber);
- if (rc)
- {
- gemini_msg((dsmContext_t *)thd->gemini.context,
- "Unable to file Index number for %s", tableName);
- DBUG_RETURN(rc);
- }
- pindexNumbers[i] = objectNumber;
- }
- }
- else
- pindexNumbers = 0;
-
- DBUG_RETURN(rc);
-}
-
-int ha_gemini::close(void)
-{
- DBUG_ENTER("ha_gemini::close");
- my_free((char*)rec_buff,MYF(MY_ALLOW_ZERO_PTR));
- rec_buff = 0;
- my_free((char *)pindexNumbers,MYF(MY_ALLOW_ZERO_PTR));
- pindexNumbers = 0;
-
- if (pBlobDescs)
- {
- for (uint i = 0; i < table->blob_fields; i++)
- {
- my_free((char*)pBlobDescs[i].pBlob, MYF(MY_ALLOW_ZERO_PTR));
- }
- my_free((char *)pBlobDescs, MYF(0));
- pBlobDescs = 0;
- }
-
- DBUG_RETURN(free_share(share, 0));
-}
-
-
-int ha_gemini::write_row(byte * record)
-{
- int error = 0;
- dsmRecord_t dsmRecord;
- THD *thd;
-
- DBUG_ENTER("write_row");
-
- if(tableStatus == HA_ERR_CRASHED)
- DBUG_RETURN(tableStatus);
-
- thd = current_thd;
-
- statistic_increment(ha_write_count,&LOCK_status);
- if (table->time_stamp)
- update_timestamp(record+table->time_stamp-1);
-
- if(thd->gemini.needSavepoint || using_ignore)
- {
- thd->gemini.savepoint++;
- error = dsmTransaction((dsmContext_t *)thd->gemini.context,
- &thd->gemini.savepoint,
- DSMTXN_SAVE, 0, 0);
- if (error)
- DBUG_RETURN(error);
- thd->gemini.needSavepoint = 0;
- }
-
- if (table->next_number_field && record == table->record[0])
- {
- if(thd->next_insert_id)
- {
- ULONG64 nr;
- /* A set insert-id statement so set the auto-increment value if this
- value is higher than it's current value */
- error = dsmTableAutoIncrement((dsmContext_t *)thd->gemini.context,
- tableNumber, (ULONG64 *)&nr,1);
- if(thd->next_insert_id > nr)
- {
- error = dsmTableAutoIncrementSet((dsmContext_t *)thd->gemini.context,
- tableNumber,
- (ULONG64)thd->next_insert_id);
- }
- }
-
- update_auto_increment();
- }
-
- dsmRecord.table = tableNumber;
- dsmRecord.maxLength = table->rec_buff_length;
-
- if ((error=pack_row((byte **)&dsmRecord.pbuffer, (int *)&dsmRecord.recLength,
- record, FALSE)))
- {
- DBUG_RETURN(error);
- }
-
- error = dsmRecordCreate((dsmContext_t *)thd->gemini.context,
- &dsmRecord,0);
-
- if(!error)
- {
- error = handleIndexEntries(record, dsmRecord.recid,KEY_CREATE);
- if(error == HA_ERR_FOUND_DUPP_KEY && using_ignore)
- {
- dsmStatus_t rc;
- rc = dsmTransaction((dsmContext_t *)thd->gemini.context,
- &thd->gemini.savepoint,DSMTXN_UNSAVE,0,NULL);
- thd->gemini.needSavepoint = 1;
- }
- }
- if(error == DSM_S_RQSTREJ)
- error = HA_ERR_LOCK_WAIT_TIMEOUT;
-
- DBUG_RETURN(error);
-}
-
-longlong ha_gemini::get_auto_increment()
-{
- longlong nr;
- int error;
- int update;
- THD *thd=current_thd;
-
- if(thd->lex.sql_command == SQLCOM_SHOW_TABLES)
- update = 0;
- else
- update = 1;
-
- error = dsmTableAutoIncrement((dsmContext_t *)thd->gemini.context,
- tableNumber, (ULONG64 *)&nr,
- update);
- return nr;
-}
-
-/* Put or delete index entries for a row */
-int ha_gemini::handleIndexEntries(const byte * record, dsmRecid_t recid,
- enum_key_string_options option)
-{
- dsmStatus_t rc = 0;
-
- DBUG_ENTER("handleIndexEntries");
-
- for (uint i = 0; i < table->keys && rc == 0; i++)
- {
- rc = handleIndexEntry(record, recid,option, i);
- }
- DBUG_RETURN(rc);
-}
-
-int ha_gemini::handleIndexEntry(const byte * record, dsmRecid_t recid,
- enum_key_string_options option,uint keynr)
-{
- dsmStatus_t rc = 0;
- KEY *key_info;
- int keyStringLen;
- bool thereIsAnull;
- THD *thd;
-
- AUTOKEY(theKey,keyBufSize);
-
- DBUG_ENTER("handleIndexEntry");
-
- thd = current_thd;
- key_info=table->key_info+keynr;
- thereIsAnull = FALSE;
- rc = createKeyString(record, key_info, theKey.akey.keystr,
- sizeof(theKey.apad),&keyStringLen,
- (short)pindexNumbers[keynr],
- &thereIsAnull);
- if(!rc)
- {
- theKey.akey.index = pindexNumbers[keynr];
- theKey.akey.keycomps = (COUNT)key_info->key_parts;
-
- /* We have to subtract three here since cxKeyPrepare
- expects that the three lead bytes of the header are
- not counted in this length -- But cxKeyPrepare also
- expects that these three bytes are present in the keystr */
- theKey.akey.keyLen = (COUNT)keyStringLen - FULLKEYHDRSZ;
- theKey.akey.unknown_comp = (dsmBoolean_t)thereIsAnull;
- theKey.akey.word_index = 0;
- theKey.akey.descending_key =0;
- if(option == KEY_CREATE)
- {
- rc = dsmKeyCreate((dsmContext_t *)thd->gemini.context, &theKey.akey,
- (dsmTable_t)tableNumber, recid, NULL);
- if(rc == DSM_S_IXDUPKEY)
- {
- last_dup_key=keynr;
- rc = HA_ERR_FOUND_DUPP_KEY;
- }
- }
- else if(option == KEY_DELETE)
- {
- rc = dsmKeyDelete((dsmContext_t *)thd->gemini.context, &theKey.akey,
- (dsmTable_t)tableNumber, recid, 0, NULL);
- }
- else
- {
- /* KEY_CHECK */
- dsmCursid_t aCursorId;
- int error;
-
- rc = dsmCursorCreate((dsmContext_t *)thd->gemini.context,
- (dsmTable_t)tableNumber,
- (dsmIndex_t)pindexNumbers[keynr],
- &aCursorId,NULL);
-
- rc = dsmCursorFind((dsmContext_t *)thd->gemini.context,
- &aCursorId,&theKey.akey,NULL,DSMDBKEY,
- DSMFINDFIRST,DSM_LK_SHARE,0,
- &lastRowid,0);
- error = dsmCursorDelete((dsmContext_t *)thd->gemini.context,
- &aCursorId, 0);
-
- }
- }
- DBUG_RETURN(rc);
-}
-
-int ha_gemini::createKeyString(const byte * record, KEY *pkeyinfo,
- unsigned char *pkeyBuf, int bufSize,
- int *pkeyStringLen,
- short geminiIndexNumber,
- bool *thereIsAnull)
-{
- dsmStatus_t rc = 0;
- int componentLen;
- int fieldType;
- int isNull;
- uint key_part_length;
-
- KEY_PART_INFO *key_part;
-
- DBUG_ENTER("createKeyString");
-
- rc = gemKeyInit(pkeyBuf,pkeyStringLen, geminiIndexNumber);
-
- for(uint i = 0; i < pkeyinfo->key_parts && rc == 0; i++)
- {
- unsigned char *pos;
-
- key_part = pkeyinfo->key_part + i;
- key_part_length = key_part->length;
- fieldType = gemDataType(key_part->field->type());
- switch (fieldType)
- {
- case GEM_CHAR:
- {
- /* Save the current ptr to the field in case we're building a key
- to remove an old key value when an indexed character column
- gets updated. */
- char *ptr = key_part->field->ptr;
- key_part->field->ptr = (char *)record + key_part->offset;
- key_part->field->sort_string((char*)rec_buff, key_part->length);
- key_part->field->ptr = ptr;
- pos = (unsigned char *)rec_buff;
- }
- break;
-
- case GEM_TINYBLOB:
- case GEM_BLOB:
- case GEM_MEDIUMBLOB:
- case GEM_LONGBLOB:
- ((Field_blob*)key_part->field)->get_ptr((char**)&pos);
- key_part_length = ((Field_blob*)key_part->field)->get_length(
- (char*)record + key_part->offset);
- break;
-
- default:
- pos = (unsigned char *)record + key_part->offset;
- break;
- }
-
- isNull = record[key_part->null_offset] & key_part->null_bit;
- if(isNull)
- *thereIsAnull = TRUE;
-
- rc = gemFieldToIdxComponent(pos,
- (unsigned long) key_part_length,
- fieldType,
- isNull ,
- key_part->field->flags & UNSIGNED_FLAG,
- pkeyBuf + *pkeyStringLen,
- bufSize,
- &componentLen);
- *pkeyStringLen += componentLen;
- }
- DBUG_RETURN(rc);
-}
-
-
-int ha_gemini::update_row(const byte * old_record, byte * new_record)
-{
- int error = 0;
- dsmRecord_t dsmRecord;
- unsigned long savepoint;
- THD *thd = current_thd;
- DBUG_ENTER("update_row");
-
- statistic_increment(ha_update_count,&LOCK_status);
- if (table->time_stamp)
- update_timestamp(new_record+table->time_stamp-1);
-
- if(thd->gemini.needSavepoint || using_ignore)
- {
- thd->gemini.savepoint++;
- error = dsmTransaction((dsmContext_t *)thd->gemini.context,
- &thd->gemini.savepoint,
- DSMTXN_SAVE, 0, 0);
- if (error)
- DBUG_RETURN(error);
- thd->gemini.needSavepoint = 0;
- }
- for (uint keynr=0 ; keynr < table->keys ; keynr++)
- {
- if(key_cmp(keynr,old_record, new_record,FALSE))
- {
- error = handleIndexEntry(old_record,lastRowid,KEY_DELETE,keynr);
- if(error)
- DBUG_RETURN(error);
- error = handleIndexEntry(new_record, lastRowid, KEY_CREATE, keynr);
- if(error)
- {
- if (using_ignore && error == HA_ERR_FOUND_DUPP_KEY)
- {
- dsmStatus_t rc;
- rc = dsmTransaction((dsmContext_t *)thd->gemini.context,
- &thd->gemini.savepoint,DSMTXN_UNSAVE,0,NULL);
- thd->gemini.needSavepoint = 1;
- }
- DBUG_RETURN(error);
- }
- }
- }
-
- dsmRecord.table = tableNumber;
- dsmRecord.recid = lastRowid;
- dsmRecord.maxLength = table->rec_buff_length;
-
- if ((error=pack_row((byte **)&dsmRecord.pbuffer, (int *)&dsmRecord.recLength,
- new_record, TRUE)))
- {
- DBUG_RETURN(error);
- }
- error = dsmRecordUpdate((dsmContext_t *)thd->gemini.context,
- &dsmRecord, 0, NULL);
-
- DBUG_RETURN(error);
-}
-
-
-int ha_gemini::delete_row(const byte * record)
-{
- int error = 0;
- dsmRecord_t dsmRecord;
- THD *thd = current_thd;
- dsmContext_t *pcontext = (dsmContext_t *)thd->gemini.context;
- DBUG_ENTER("delete_row");
-
- statistic_increment(ha_delete_count,&LOCK_status);
-
- if(thd->gemini.needSavepoint)
- {
- thd->gemini.savepoint++;
- error = dsmTransaction(pcontext, &thd->gemini.savepoint, DSMTXN_SAVE, 0, 0);
- if (error)
- DBUG_RETURN(error);
- thd->gemini.needSavepoint = 0;
- }
-
- dsmRecord.table = tableNumber;
- dsmRecord.recid = lastRowid;
-
- error = handleIndexEntries(record, dsmRecord.recid,KEY_DELETE);
- if(!error)
- {
- error = dsmRecordDelete(pcontext, &dsmRecord, 0, NULL);
- }
-
- /* Delete any blobs associated with this row */
- if (table->blob_fields)
- {
- dsmBlob_t gemBlob;
-
- gemBlob.areaType = DSMOBJECT_BLOB;
- gemBlob.blobObjNo = tableNumber;
- for (uint i = 0; i < table->blob_fields; i++)
- {
- if (pBlobDescs[i].blobId)
- {
- gemBlob.blobId = pBlobDescs[i].blobId;
- my_free((char *)pBlobDescs[i].pBlob, MYF(MY_ALLOW_ZERO_PTR));
- dsmBlobStart(pcontext, &gemBlob);
- dsmBlobDelete(pcontext, &gemBlob, NULL);
- /* according to DSM doc, no need to call dsmBlobEnd() */
- }
- }
- }
-
- DBUG_RETURN(error);
-}
-
-int ha_gemini::index_init(uint keynr)
-{
- int error = 0;
- THD *thd;
- DBUG_ENTER("index_init");
- thd = current_thd;
-
- lastRowid = 0;
- active_index=keynr;
- error = dsmCursorCreate((dsmContext_t *)thd->gemini.context,
- (dsmTable_t)tableNumber,
- (dsmIndex_t)pindexNumbers[keynr],
- &cursorId,NULL);
- pbracketBase = (dsmKey_t *)my_malloc(sizeof(dsmKey_t) + keyBufSize,
- MYF(MY_WME));
- if(!pbracketBase)
- DBUG_RETURN(1);
- pbracketLimit = (dsmKey_t *)my_malloc(sizeof(dsmKey_t) + keyBufSize,MYF(MY_WME));
- if(!pbracketLimit)
- {
- my_free((char *)pbracketLimit,MYF(0));
- DBUG_RETURN(1);
- }
- pbracketBase->index = 0;
- pbracketLimit->index = (dsmIndex_t)pindexNumbers[keynr];
- pbracketBase->descending_key = pbracketLimit->descending_key = 0;
- pbracketBase->ksubstr = pbracketLimit->ksubstr = 0;
- pbracketLimit->keycomps = pbracketBase->keycomps = 1;
-
- pfoundKey = (dsmKey_t *)my_malloc(sizeof(dsmKey_t) + keyBufSize,MYF(MY_WME));
- if(!pfoundKey)
- {
- my_free((char *)pbracketLimit,MYF(0));
- my_free((char *)pbracketBase,MYF(0));
- DBUG_RETURN(1);
- }
-
- DBUG_RETURN(error);
-}
-
-int ha_gemini::index_end()
-{
- int error = 0;
- THD *thd;
- DBUG_ENTER("index_end");
- thd = current_thd;
- error = dsmCursorDelete((dsmContext_t *)thd->gemini.context,
- &cursorId, 0);
- if(pbracketLimit)
- my_free((char *)pbracketLimit,MYF(0));
- if(pbracketBase)
- my_free((char *)pbracketBase,MYF(0));
- if(pfoundKey)
- my_free((char *)pfoundKey,MYF(0));
-
- pbracketLimit = 0;
- pbracketBase = 0;
- pfoundKey = 0;
- DBUG_RETURN(error);
-}
-
-/* This is only used to read whole keys */
-
-int ha_gemini::index_read_idx(byte * buf, uint keynr, const byte * key,
- uint key_len, enum ha_rkey_function find_flag)
-{
- int error = 0;
- DBUG_ENTER("index_read_idx");
- statistic_increment(ha_read_key_count,&LOCK_status);
-
- error = index_init(keynr);
- if (!error)
- error = index_read(buf,key,key_len,find_flag);
-
- if(error == HA_ERR_END_OF_FILE)
- error = HA_ERR_KEY_NOT_FOUND;
-
- table->status = error ? STATUS_NOT_FOUND : 0;
- DBUG_RETURN(error);
-}
-
-int ha_gemini::pack_key( uint keynr, dsmKey_t *pkey,
- const byte *key_ptr, uint key_length)
-{
- 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;
- int rc;
- int componentLen;
- DBUG_ENTER("pack_key");
-
- rc = gemKeyInit(pkey->keystr,&componentLen,
- (short)pindexNumbers[active_index]);
- pkey->keyLen = componentLen;
-
- for (; key_part != end && (int) key_length > 0 && !rc; key_part++)
- {
- uint offset=0;
- unsigned char *pos;
- uint key_part_length = key_part->length;
-
- int fieldType;
- if (key_part->null_bit)
- {
- offset=1;
- if (*key_ptr != 0) // Store 0 if NULL
- {
- key_length-= key_part->store_length;
- key_ptr+= key_part->store_length;
- rc = gemFieldToIdxComponent(
- (unsigned char *)key_ptr + offset,
- (unsigned long) key_part_length,
- 0,
- 1 , /* Tells it to build a null component */
- key_part->field->flags & UNSIGNED_FLAG,
- pkey->keystr + pkey->keyLen,
- keyBufSize,
- &componentLen);
- pkey->keyLen += componentLen;
- continue;
- }
- }
- fieldType = gemDataType(key_part->field->type());
- switch (fieldType)
- {
- case GEM_CHAR:
- key_part->field->store((char*)key_ptr + offset, key_part->length);
- key_part->field->sort_string((char*)rec_buff, key_part->length);
- pos = (unsigned char *)rec_buff;
- break;
-
- case GEM_TINYBLOB:
- case GEM_BLOB:
- case GEM_MEDIUMBLOB:
- case GEM_LONGBLOB:
- ((Field_blob*)key_part->field)->get_ptr((char**)&pos);
- key_part_length = ((Field_blob*)key_part->field)->get_length(
- (char*)key_ptr + offset);
- break;
-
- default:
- pos = (unsigned char *)key_ptr + offset;
- break;
- }
-
- rc = gemFieldToIdxComponent(
- pos,
- (unsigned long) key_part_length,
- fieldType,
- 0 ,
- key_part->field->flags & UNSIGNED_FLAG,
- pkey->keystr + pkey->keyLen,
- keyBufSize,
- &componentLen);
-
- key_ptr+=key_part->store_length;
- key_length-=key_part->store_length;
- pkey->keyLen += componentLen;
- }
- DBUG_RETURN(rc);
-}
-
-void ha_gemini::unpack_key(char *record, dsmKey_t *key, uint index)
-{
- KEY *key_info=table->key_info+index;
- KEY_PART_INFO *key_part= key_info->key_part,
- *end=key_part+key_info->key_parts;
- int fieldIsNull, fieldType;
- int rc = 0;
-
- char unsigned *pos= &key->keystr[FULLKEYHDRSZ+4/* 4 for the index number*/];
-
- for ( ; key_part != end; key_part++)
- {
- fieldType = gemDataType(key_part->field->type());
- if(fieldType == GEM_CHAR)
- {
- /* Can't get data from character indexes since the sort weights
- are in the index and not the characters. */
- key_read = 0;
- }
- rc = gemIdxComponentToField(pos, fieldType,
- (unsigned char *)record + key_part->field->offset(),
- //key_part->field->field_length,
- key_part->length,
- key_part->field->decimals(),
- &fieldIsNull);
- if(fieldIsNull)
- {
- record[key_part->null_offset] |= key_part->null_bit;
- }
- else if (key_part->null_bit)
- {
- record[key_part->null_offset]&= ~key_part->null_bit;
- }
- while(*pos++); /* Advance to next field in key by finding */
- /* a null byte */
- }
-}
-
-int ha_gemini::index_read(byte * buf, const byte * key,
- uint key_len, enum ha_rkey_function find_flag)
-{
- int error = 0;
- THD *thd;
- int componentLen;
-
- DBUG_ENTER("index_read");
- statistic_increment(ha_read_key_count,&LOCK_status);
-
-
- pbracketBase->index = (short)pindexNumbers[active_index];
- pbracketBase->keycomps = 1;
-
-
- /* Its a greater than operation so create a base bracket
- from the input key data. */
- error = pack_key(active_index, pbracketBase, key, key_len);
- if(error)
- goto errorReturn;
-
- if(find_flag == HA_READ_AFTER_KEY)
- {
- /* A greater than operation */
- error = gemKeyAddLow(pbracketBase->keystr + pbracketBase->keyLen,
- &componentLen);
- pbracketBase->keyLen += componentLen;
- }
- if(find_flag == HA_READ_KEY_EXACT)
- {
- /* Need to set up a high bracket for an equality operator
- Which is a copy of the base bracket plus a hi lim term */
- bmove(pbracketLimit,pbracketBase,(size_t)pbracketBase->keyLen + sizeof(dsmKey_t));
- error = gemKeyAddHigh(pbracketLimit->keystr + pbracketLimit->keyLen,
- &componentLen);
- if(error)
- goto errorReturn;
- pbracketLimit->keyLen += componentLen;
- }
- else
- {
- /* Always add a high range -- except for HA_READ_KEY_EXACT this
- is all we need for the upper index bracket */
- error = gemKeyHigh(pbracketLimit->keystr, &componentLen,
- pbracketLimit->index);
-
- pbracketLimit->keyLen = componentLen;
- }
- /* We have to subtract the header size here since cxKeyPrepare
- expects that the three lead bytes of the header are
- not counted in this length -- But cxKeyPrepare also
- expects that these three bytes are present in the keystr */
- pbracketBase->keyLen -= FULLKEYHDRSZ;
- pbracketLimit->keyLen -= FULLKEYHDRSZ;
-
- thd = current_thd;
-
- error = findRow(thd, DSMFINDFIRST, buf);
-
-errorReturn:
- if (error == DSM_S_ENDLOOP)
- error = HA_ERR_KEY_NOT_FOUND;
-
- table->status = error ? STATUS_NOT_FOUND : 0;
- DBUG_RETURN(error);
-}
-
-
-int ha_gemini::index_next(byte * buf)
-{
- THD *thd;
- int error = 1;
- int keyStringLen=0;
- dsmMask_t findMode;
- DBUG_ENTER("index_next");
-
- if(tableStatus == HA_ERR_CRASHED)
- DBUG_RETURN(tableStatus);
-
- thd = current_thd;
-
- if(pbracketBase->index == 0)
- {
- error = gemKeyLow(pbracketBase->keystr, &keyStringLen,
- pbracketLimit->index);
-
- pbracketBase->keyLen = (COUNT)keyStringLen - FULLKEYHDRSZ;
- pbracketBase->index = pbracketLimit->index;
- error = gemKeyHigh(pbracketLimit->keystr, &keyStringLen,
- pbracketLimit->index);
- pbracketLimit->keyLen = (COUNT)keyStringLen - FULLKEYHDRSZ;
-
- findMode = DSMFINDFIRST;
- }
- else
- findMode = DSMFINDNEXT;
-
- error = findRow(thd,findMode,buf);
-
- if (error == DSM_S_ENDLOOP)
- error = HA_ERR_END_OF_FILE;
-
- table->status = error ? STATUS_NOT_FOUND : 0;
- DBUG_RETURN(error);
-}
-
-int ha_gemini::index_next_same(byte * buf, const byte *key, uint keylen)
-{
- int error = 0;
- DBUG_ENTER("index_next_same");
- statistic_increment(ha_read_next_count,&LOCK_status);
- DBUG_RETURN(index_next(buf));
-}
-
-
-int ha_gemini::index_prev(byte * buf)
-{
- int error = 0;
- THD *thd = current_thd;
-
- DBUG_ENTER("index_prev");
- statistic_increment(ha_read_prev_count,&LOCK_status);
-
- error = findRow(thd, DSMFINDPREV, buf);
-
- if (error == DSM_S_ENDLOOP)
- error = HA_ERR_END_OF_FILE;
-
-
- table->status = error ? STATUS_NOT_FOUND : 0;
- DBUG_RETURN(error);
-}
-
-
-int ha_gemini::index_first(byte * buf)
-{
- DBUG_ENTER("index_first");
- statistic_increment(ha_read_first_count,&LOCK_status);
- DBUG_RETURN(index_next(buf));
-}
-
-int ha_gemini::index_last(byte * buf)
-{
- int error = 0;
- THD *thd;
- int keyStringLen;
- dsmMask_t findMode;
- thd = current_thd;
-
- DBUG_ENTER("index_last");
- statistic_increment(ha_read_last_count,&LOCK_status);
-
- error = gemKeyLow(pbracketBase->keystr, &keyStringLen,
- pbracketLimit->index);
-
- pbracketBase->keyLen = (COUNT)keyStringLen - FULLKEYHDRSZ;
- pbracketBase->index = pbracketLimit->index;
- error = gemKeyHigh(pbracketLimit->keystr, &keyStringLen,
- pbracketLimit->index);
- pbracketLimit->keyLen = (COUNT)keyStringLen - FULLKEYHDRSZ;
-
- error = findRow(thd,DSMFINDLAST,buf);
-
- if (error == DSM_S_ENDLOOP)
- error = HA_ERR_END_OF_FILE;
-
- table->status = error ? STATUS_NOT_FOUND : 0;
- DBUG_RETURN(error);
-}
-
-int ha_gemini::rnd_init(bool scan)
-{
- THD *thd = current_thd;
-
- lastRowid = 0;
-
- return 0;
-}
-
-int ha_gemini::rnd_end()
-{
-/*
- return gem_scan_end();
-*/
- return 0;
-}
-
-int ha_gemini::rnd_next(byte *buf)
-{
- int error = 0;
- dsmRecord_t dsmRecord;
- THD *thd;
-
- DBUG_ENTER("rnd_next");
-
- if(tableStatus == HA_ERR_CRASHED)
- DBUG_RETURN(tableStatus);
-
- thd = current_thd;
- if(thd->gemini.tx_isolation == ISO_READ_COMMITTED && !(lockMode & DSM_LK_EXCL)
- && lastRowid)
- error = dsmObjectUnlock((dsmContext_t *)thd->gemini.context,
- tableNumber, DSMOBJECT_RECORD, lastRowid,
- lockMode | DSM_UNLK_FREE, 0);
-
- statistic_increment(ha_read_rnd_next_count,&LOCK_status);
- dsmRecord.table = tableNumber;
- dsmRecord.recid = lastRowid;
- dsmRecord.pbuffer = (dsmBuffer_t *)rec_buff;
- dsmRecord.recLength = table->reclength;
- dsmRecord.maxLength = table->rec_buff_length;
-
- error = dsmTableScan((dsmContext_t *)thd->gemini.context,
- &dsmRecord, DSMFINDNEXT, lockMode, 0);
-
- if(!error)
- {
- lastRowid = dsmRecord.recid;
- error = unpack_row((char *)buf,(char *)dsmRecord.pbuffer);
- }
- if(!error)
- ;
- else
- {
- lastRowid = 0;
- if (error == DSM_S_ENDLOOP)
- error = HA_ERR_END_OF_FILE;
- else if (error == DSM_S_RQSTREJ)
- error = HA_ERR_LOCK_WAIT_TIMEOUT;
- else if (error == DSM_S_LKTBFULL)
- {
- error = HA_ERR_LOCK_TABLE_FULL;
- gemini_lock_table_overflow_error((dsmContext_t *)thd->gemini.context);
- }
- }
- table->status = error ? STATUS_NOT_FOUND : 0;
- DBUG_RETURN(error);
-}
-
-
-int ha_gemini::rnd_pos(byte * buf, byte *pos)
-{
- int error;
- int rc;
-
- THD *thd;
-
- statistic_increment(ha_read_rnd_count,&LOCK_status);
- thd = current_thd;
- memcpy((void *)&lastRowid,pos,ref_length);
- if(thd->gemini.tx_isolation == ISO_READ_COMMITTED && !(lockMode & DSM_LK_EXCL))
- {
- /* Lock the row */
-
- error = dsmObjectLock((dsmContext_t *)thd->gemini.context,
- (dsmObject_t)tableNumber,DSMOBJECT_RECORD,lastRowid,
- lockMode, 1, 0);
- if ( error )
- goto errorReturn;
- }
- error = fetch_row(thd->gemini.context, buf);
- if(thd->gemini.tx_isolation == ISO_READ_COMMITTED && !(lockMode & DSM_LK_EXCL))
- {
- /* Unlock the row */
-
- rc = dsmObjectUnlock((dsmContext_t *)thd->gemini.context,
- (dsmObject_t)tableNumber,DSMOBJECT_RECORD,lastRowid,
- lockMode | DSM_UNLK_FREE , 0);
- }
- if(error == DSM_S_RMNOTFND)
- error = HA_ERR_RECORD_DELETED;
-
- errorReturn:
- table->status = error ? STATUS_NOT_FOUND : 0;
- return error;
-}
-
-int ha_gemini::fetch_row(void *gemini_context,const byte *buf)
-{
- dsmStatus_t rc = 0;
- dsmRecord_t dsmRecord;
-
- DBUG_ENTER("fetch_row");
- dsmRecord.table = tableNumber;
- dsmRecord.recid = lastRowid;
- dsmRecord.pbuffer = (dsmBuffer_t *)rec_buff;
- dsmRecord.recLength = table->reclength;
- dsmRecord.maxLength = table->rec_buff_length;
-
- rc = dsmRecordGet((dsmContext_t *)gemini_context,
- &dsmRecord, 0);
-
- if(!rc)
- {
- rc = unpack_row((char *)buf,(char *)dsmRecord.pbuffer);
- }
-
- DBUG_RETURN(rc);
-}
-int ha_gemini::findRow(THD *thd, dsmMask_t findMode, byte *buf)
-{
- dsmStatus_t rc;
- dsmKey_t *pkey;
-
- DBUG_ENTER("findRow");
-
- if(thd->gemini.tx_isolation == ISO_READ_COMMITTED && !(lockMode & DSM_LK_EXCL)
- && lastRowid)
- rc = dsmObjectUnlock((dsmContext_t *)thd->gemini.context,
- tableNumber, DSMOBJECT_RECORD, lastRowid,
- lockMode | DSM_UNLK_FREE, 0);
- if( key_read )
- pkey = pfoundKey;
- else
- pkey = 0;
-
- rc = dsmCursorFind((dsmContext_t *)thd->gemini.context,
- &cursorId,
- pbracketBase,
- pbracketLimit,
- DSMPARTIAL,
- findMode,
- lockMode,
- NULL,
- &lastRowid,
- pkey);
- if( rc )
- goto errorReturn;
-
- if(key_read)
- {
- unpack_key((char*)buf, pkey, active_index);
- }
- if(!key_read) /* unpack_key may have turned off key_read */
- {
- rc = fetch_row((dsmContext_t *)thd->gemini.context,buf);
- }
-
-errorReturn:
- if(!rc)
- ;
- else
- {
- lastRowid = 0;
- if(rc == DSM_S_RQSTREJ)
- rc = HA_ERR_LOCK_WAIT_TIMEOUT;
- else if (rc == DSM_S_LKTBFULL)
- {
- rc = HA_ERR_LOCK_TABLE_FULL;
- gemini_lock_table_overflow_error((dsmContext_t *)thd->gemini.context);
- }
- }
-
- DBUG_RETURN(rc);
-}
-
-void ha_gemini::position(const byte *record)
-{
- memcpy(ref,&lastRowid,ref_length);
-}
-
-
-void ha_gemini::info(uint flag)
-{
- DBUG_ENTER("info");
-
- if ((flag & HA_STATUS_VARIABLE))
- {
- THD *thd = current_thd;
- dsmStatus_t error;
- ULONG64 rows;
-
- if(thd->gemini.context == NULL)
- {
- /* Need to get this thread a connection into the database */
- error = gemini_connect(thd);
- if(error)
- DBUG_VOID_RETURN;
- }
-
- error = dsmRowCount((dsmContext_t *)thd->gemini.context,tableNumber,&rows);
- records = (ha_rows)rows;
- deleted = 0;
- }
- if ((flag & HA_STATUS_CONST))
- {
- ha_rows *rec_per_key = share->rec_per_key;
- for (uint i = 0; i < table->keys; i++)
- for(uint k=0;
- k < table->key_info[i].key_parts; k++,rec_per_key++)
- table->key_info[i].rec_per_key[k] = *rec_per_key;
- }
- if ((flag & HA_STATUS_ERRKEY))
- {
- errkey=last_dup_key;
- }
- if ((flag & HA_STATUS_TIME))
- {
- ;
- }
- if ((flag & HA_STATUS_AUTO))
- {
- THD *thd = current_thd;
- dsmStatus_t error;
-
- error = dsmTableAutoIncrement((dsmContext_t *)thd->gemini.context,
- tableNumber,
- (ULONG64 *)&auto_increment_value,
- 0);
- /* Should return the next auto-increment value that
- will be given -- so we need to increment the one dsm
- currently reports. */
- auto_increment_value++;
- }
-
- DBUG_VOID_RETURN;
-}
-
-
-int ha_gemini::extra(enum ha_extra_function operation)
-{
- switch (operation)
- {
- case HA_EXTRA_RESET:
- case HA_EXTRA_RESET_STATE:
- key_read=0;
- using_ignore=0;
- break;
- case HA_EXTRA_KEYREAD:
- key_read=1; // Query satisfied with key
- break;
- case HA_EXTRA_NO_KEYREAD:
- key_read=0;
- break;
- case HA_EXTRA_IGNORE_DUP_KEY:
- using_ignore=1;
- break;
- case HA_EXTRA_NO_IGNORE_DUP_KEY:
- using_ignore=0;
- break;
-
- default:
- break;
- }
- return 0;
-}
-
-
-int ha_gemini::reset(void)
-{
- key_read=0; // Reset to state after open
- return 0;
-}
-
-
-/*
- As MySQL will execute an external lock for every new table it uses
- we can use this to start the transactions.
-*/
-
-int ha_gemini::external_lock(THD *thd, int lock_type)
-{
- dsmStatus_t rc = 0;
- LONG txNumber;
-
- DBUG_ENTER("ha_gemini::external_lock");
-
- if (lock_type != F_UNLCK)
- {
- if (!thd->gemini.lock_count)
- {
- thd->gemini.lock_count = 1;
- thd->gemini.tx_isolation = thd->tx_isolation;
- }
- // lockMode has already been set in store_lock
- // If the statement about to be executed calls for
- // exclusive locks and we're running at read uncommitted
- // isolation level then raise an error.
- if(thd->gemini.tx_isolation == ISO_READ_UNCOMMITTED)
- {
- if(lockMode == DSM_LK_EXCL)
- {
- DBUG_RETURN(HA_ERR_READ_ONLY_TRANSACTION);
- }
- else
- {
- lockMode = DSM_LK_NOLOCK;
- }
- }
-
- if(thd->gemini.context == NULL)
- {
- /* Need to get this thread a connection into the database */
- rc = gemini_connect(thd);
- if(rc)
- return rc;
- }
- /* Set need savepoint flag */
- thd->gemini.needSavepoint = 1;
-
- if(rc)
- DBUG_RETURN(rc);
-
-
- if( thd->in_lock_tables || thd->gemini.tx_isolation == ISO_SERIALIZABLE )
- {
- rc = dsmObjectLock((dsmContext_t *)thd->gemini.context,
- (dsmObject_t)tableNumber,DSMOBJECT_TABLE,0,
- lockMode, 1, 0);
- if(rc == DSM_S_RQSTREJ)
- rc = HA_ERR_LOCK_WAIT_TIMEOUT;
- }
- }
- else /* lock_type == F_UNLK */
- {
- /* Commit the tx if we're in auto-commit mode */
- if (!(thd->options & OPTION_NOT_AUTO_COMMIT)&&
- !(thd->options & OPTION_BEGIN))
- gemini_commit(thd);
- }
-
- DBUG_RETURN(rc);
-}
-
-
-THR_LOCK_DATA **ha_gemini::store_lock(THD *thd, THR_LOCK_DATA **to,
- enum thr_lock_type lock_type)
-{
- if (lock_type != TL_IGNORE && lock.type == TL_UNLOCK)
- {
- /* If we are not doing a LOCK TABLE, then allow multiple writers */
- if ((lock_type >= TL_WRITE_CONCURRENT_INSERT &&
- lock_type <= TL_WRITE) &&
- !thd->in_lock_tables)
- lock_type = TL_WRITE_ALLOW_WRITE;
- lock.type=lock_type;
- }
- if(table->reginfo.lock_type > TL_WRITE_ALLOW_READ)
- lockMode = DSM_LK_EXCL;
- else
- lockMode = DSM_LK_SHARE;
-
- *to++= &lock;
- return to;
-}
-
-void ha_gemini::update_create_info(HA_CREATE_INFO *create_info)
-{
- table->file->info(HA_STATUS_AUTO | HA_STATUS_CONST);
- if (!(create_info->used_fields & HA_CREATE_USED_AUTO))
- {
- create_info->auto_increment_value=auto_increment_value;
- }
-}
-
-int ha_gemini::create(const char *name, register TABLE *form,
- HA_CREATE_INFO *create_info)
-{
- THD *thd;
- char name_buff[FN_REFLEN];
- char dbname_buff[FN_REFLEN];
- DBUG_ENTER("ha_gemini::create");
- dsmContext_t *pcontext;
- dsmStatus_t rc;
- dsmArea_t areaNumber;
- dsmObject_t tableNumber = 0;
- dsmDbkey_t dummy = 0;
- unsigned i;
- int baseNameLen;
- dsmObject_t indexNumber;
-
- /* separate out the name of the table and the database (a VST must be
- ** created in the mysql database)
- */
- rc = gemini_parse_table_name(name, dbname_buff, name_buff);
- if (rc == 0)
- {
- /* If the table is a VST, don't create areas or extents */
- if (strcmp(dbname_buff, "mysql") == 0)
- {
- tableNumber = gemini_is_vst(name_buff);
- if (tableNumber)
- {
- return 0;
- }
- }
- }
-
- thd = current_thd;
- if(thd->gemini.context == NULL)
- {
- /* Need to get this thread a connection into the database */
- rc = gemini_connect(thd);
- if(rc)
- return rc;
- }
- pcontext = (dsmContext_t *)thd->gemini.context;
-
- if(thd->gemini.needSavepoint || using_ignore)
- {
- thd->gemini.savepoint++;
- rc = dsmTransaction((dsmContext_t *)thd->gemini.context,
- &thd->gemini.savepoint,
- DSMTXN_SAVE, 0, 0);
- if (rc)
- DBUG_RETURN(rc);
- thd->gemini.needSavepoint = 0;
- }
-
- fn_format(name_buff, name, "", ha_gemini_ext, 2 | 4);
- /* Create a storage area */
- rc = dsmAreaNew(pcontext,gemini_blocksize,DSMAREA_TYPE_DATA,
- &areaNumber, gemini_recbits,
- (dsmText_t *)"gemini_data_area");
- if( rc != 0 )
- {
- gemini_msg(pcontext, "dsmAreaNew failed %l",rc);
- return(rc);
- }
-
- /* Create an extent */
- /* Don't pass in leading ./ in name_buff */
- rc = dsmExtentCreate(pcontext,areaNumber,1,15,5,
- (dsmText_t *)&name_buff[start_of_name]);
- if( rc != 0 )
- {
- gemini_msg(pcontext, "dsmExtentCreate failed %l",rc);
- return(rc);
- }
-
- /* Create the table storage object */
- /* Change slashes in the name to periods */
- for( i = 0; i < strlen(name_buff); i++)
- if(name_buff[i] == '/' || name_buff[i] == '\\')
- name_buff[i] = '.';
-
- /* Get rid of .gmd suffix */
- name_buff[strlen(name_buff) - 4] = '\0';
-
- rc = dsmObjectCreate(pcontext, areaNumber, &tableNumber,
- DSMOBJECT_MIXTABLE,0,0,0,
- (dsmText_t *)&name_buff[start_of_name],
- &dummy,&dummy);
-
- if (rc == 0 && table->blob_fields)
- {
- /* create a storage object record for blob fields */
- rc = dsmObjectCreate(pcontext, areaNumber, &tableNumber,
- DSMOBJECT_BLOB,0,0,0,
- (dsmText_t *)&name_buff[start_of_name],
- &dummy,&dummy);
- if( rc != 0 )
- {
- gemini_msg(pcontext, "dsmObjectCreate for blob object failed %l",rc);
- return(rc);
- }
- }
-
- if(rc == 0 && form->keys)
- {
- fn_format(name_buff, name, "", ha_gemini_idx_ext, 2 | 4);
- /* Create a storage area */
- rc = dsmAreaNew(pcontext,gemini_blocksize,DSMAREA_TYPE_DATA,
- &areaNumber, gemini_recbits,
- (dsmText_t *)"gemini_index_area");
- if( rc != 0 )
- {
- gemini_msg(pcontext, "dsmAreaNew failed %l",rc);
- return(rc);
- }
- /* Create an extent */
- /* Don't pass in leading ./ in name_buff */
- rc = dsmExtentCreate(pcontext,areaNumber,1,15,5,
- (dsmText_t *)&name_buff[start_of_name]);
- if( rc != 0 )
- {
- gemini_msg(pcontext, "dsmExtentCreate failed %l",rc);
- return(rc);
- }
-
- /* Change slashes in the name to periods */
- for( i = 0; i < strlen(name_buff); i++)
- if(name_buff[i] == '/' || name_buff[i] == '\\')
- name_buff[i] = '.';
-
- /* Get rid of .gmi suffix */
- name_buff[strlen(name_buff) - 4] = '\0';
-
- baseNameLen = strlen(name_buff);
- name_buff[baseNameLen] = '.';
- baseNameLen++;
- for( i = 0; i < form->keys; i++)
- {
- dsmObjectAttr_t indexUnique;
-
- indexNumber = DSMINDEX_INVALID;
- /* Create a storage object record for each index */
- /* Add the index name so the object name is in the form
- <db>.<table>.<index_name> */
- strcpy(&name_buff[baseNameLen],table->key_info[i].name);
- if(table->key_info[i].flags & HA_NOSAME)
- indexUnique = 1;
- else
- indexUnique = 0;
- rc = dsmObjectCreate(pcontext, areaNumber, &indexNumber,
- DSMOBJECT_MIXINDEX,indexUnique,tableNumber,
- DSMOBJECT_MIXTABLE,
- (dsmText_t *)&name_buff[start_of_name],
- &dummy,&dummy);
-
- }
- }
- /* The auto_increment value is the next one to be given
- out so give dsm one less than this value */
- if(create_info->auto_increment_value)
- rc = dsmTableAutoIncrementSet(pcontext,tableNumber,
- create_info->auto_increment_value-1);
-
- /* Get a table lock on this table in case this table is being
- created as part of an alter table statement. We don't want
- the alter table statement to abort because of a lock table overflow
- */
- if (thd->lex.sql_command == SQLCOM_CREATE_INDEX ||
- thd->lex.sql_command == SQLCOM_ALTER_TABLE ||
- thd->lex.sql_command == SQLCOM_DROP_INDEX)
- {
- rc = dsmObjectLock(pcontext,
- (dsmObject_t)tableNumber,DSMOBJECT_TABLE,0,
- DSM_LK_EXCL, 1, 0);
- /* and don't commit so we won't release the table on the table number
- of the table being altered */
- }
- else
- {
- if(!rc)
- rc = gemini_commit(thd);
- }
-
- DBUG_RETURN(rc);
-}
-
-int ha_gemini::delete_table(const char *pname)
-{
- THD *thd;
- dsmStatus_t rc;
- dsmContext_t *pcontext;
- unsigned i,nameLen;
- dsmArea_t indexArea = 0;
- dsmArea_t tableArea = 0;
- dsmObjectAttr_t objectAttr;
- dsmObject_t associate;
- dsmObjectType_t associateType;
- dsmDbkey_t block, root;
- int need_txn = 0;
- dsmObject_t tableNum = 0;
- char name_buff[FN_REFLEN];
- char dbname_buff[FN_REFLEN];
- DBUG_ENTER("ha_gemini::delete_table");
-
- /* separate out the name of the table and the database (a VST must be
- ** located in the mysql database)
- */
- rc = gemini_parse_table_name(pname, dbname_buff, name_buff);
- if (rc == 0)
- {
- /* If the table is a VST, there are no areas or extents to delete */
- if (strcmp(dbname_buff, "mysql") == 0)
- {
- tableNum = gemini_is_vst(name_buff);
- if (tableNum)
- {
- return 0;
- }
- }
- }
-
- thd = current_thd;
- if(thd->gemini.context == NULL)
- {
- /* Need to get this thread a connection into the database */
- rc = gemini_connect(thd);
- if(rc)
- {
- DBUG_RETURN(rc);
- }
- }
- pcontext = (dsmContext_t *)thd->gemini.context;
-
-
- bzero(name_buff, FN_REFLEN);
-
- nameLen = strlen(pname);
- for( i = start_of_name; i < nameLen; i++)
- {
- if(pname[i] == '/' || pname[i] == '\\')
- name_buff[i-start_of_name] = '.';
- else
- name_buff[i-start_of_name] = pname[i];
- }
-
- rc = dsmObjectNameToNum(pcontext, (dsmText_t *)name_buff,
- (dsmObject_t *)&tableNum);
- if (rc)
- {
- gemini_msg(pcontext, "Unable to find table number for %s", name_buff);
- rc = gemini_rollback(thd);
- if (rc)
- {
- gemini_msg(pcontext, "Error in rollback %l",rc);
- }
- DBUG_RETURN(rc);
- }
-
- rc = dsmObjectInfo(pcontext, tableNum, DSMOBJECT_MIXTABLE, tableNum,
- &tableArea, &objectAttr, &associateType, &block, &root);
- if (rc)
- {
- gemini_msg(pcontext, "Failed to get area number for table %d, %s, return %l",
- tableNum, pname, rc);
- rc = gemini_rollback(thd);
- if (rc)
- {
- gemini_msg(pcontext, "Error in rollback %l",rc);
- }
- }
-
- indexArea = DSMAREA_INVALID;
-
- /* Delete the indexes and tables storage objects for with the table */
- rc = dsmObjectDeleteAssociate(pcontext, tableNum, &indexArea);
- if (rc)
- {
- gemini_msg(pcontext, "Error deleting storage objects for table number %d, return %l",
- (int)tableNum, rc);
-
- /* roll back txn and return */
- rc = gemini_rollback(thd);
- if (rc)
- {
- gemini_msg(pcontext, "Error in rollback %l",rc);
- }
- DBUG_RETURN(rc);
- }
-
- if (indexArea != DSMAREA_INVALID)
- {
- /* Delete the extents for both Index and Table */
- rc = dsmExtentDelete(pcontext, indexArea);
- rc = dsmAreaDelete(pcontext, indexArea);
- if (rc)
- {
- gemini_msg(pcontext, "Error deleting Index Area %l, return %l", indexArea, rc);
-
- /* roll back txn and return */
- rc = gemini_rollback(thd);
- if (rc)
- {
- gemini_msg(pcontext, "Error in rollback %l",rc);
- }
- DBUG_RETURN(rc);
- }
- }
-
- rc = dsmExtentDelete(pcontext, tableArea);
- rc = dsmAreaDelete(pcontext, tableArea);
- if (rc)
- {
- gemini_msg(pcontext, "Error deleting table Area %l, name %s, return %l",
- tableArea, pname, rc);
- /* roll back txn and return */
- rc = gemini_rollback(thd);
- if (rc)
- {
- gemini_msg(pcontext, "Error in rollback %l",rc);
- }
- DBUG_RETURN(rc);
- }
-
-
- /* Commit the transaction */
- rc = gemini_commit(thd);
- if (rc)
- {
- gemini_msg(pcontext, "Failed to commit transaction %l",rc);
- }
-
-
- /* now remove all the files that need to be removed and
- cause a checkpoint so recovery will work */
- rc = dsmExtentUnlink(pcontext);
-
- DBUG_RETURN(0);
-}
-
-
-int ha_gemini::rename_table(const char *pfrom, const char *pto)
-{
- THD *thd;
- dsmContext_t *pcontext;
- dsmStatus_t rc;
- char dbname_buff[FN_REFLEN];
- char name_buff[FN_REFLEN];
- char newname_buff[FN_REFLEN];
- char newextname_buff[FN_REFLEN];
- char newidxextname_buff[FN_REFLEN];
- unsigned i, nameLen;
- dsmObject_t tableNum;
- dsmArea_t indexArea = 0;
- dsmArea_t tableArea = 0;
-
- DBUG_ENTER("ha_gemini::rename_table");
-
- /* don't allow rename of VSTs */
- rc = gemini_parse_table_name(pfrom, dbname_buff, name_buff);
- if (rc == 0)
- {
- /* If the table is a VST, don't create areas or extents */
- if (strcmp(dbname_buff, "mysql") == 0)
- {
- if (gemini_is_vst(name_buff))
- {
- return DSM_S_CANT_RENAME_VST;
- }
- }
- }
-
- thd = current_thd;
- if (thd->gemini.context == NULL)
- {
- /* Need to get this thread a connection into the database */
- rc = gemini_connect(thd);
- if (rc)
- {
- DBUG_RETURN(rc);
- }
- }
-
- pcontext = (dsmContext_t *)thd->gemini.context;
-
- /* change the slashes to dots in the old and new names */
- nameLen = strlen(pfrom);
- for( i = start_of_name; i < nameLen; i++)
- {
- if(pfrom[i] == '/' || pfrom[i] == '\\')
- name_buff[i-start_of_name] = '.';
- else
- name_buff[i-start_of_name] = pfrom[i];
- }
- name_buff[i-start_of_name] = '\0';
-
- nameLen = strlen(pto);
- for( i = start_of_name; i < nameLen; i++)
- {
- if(pto[i] == '/' || pto[i] == '\\')
- newname_buff[i-start_of_name] = '.';
- else
- newname_buff[i-start_of_name] = pto[i];
- }
- newname_buff[i-start_of_name] = '\0';
-
- /* generate new extent names (for table and index extents) */
- fn_format(newextname_buff, pto, "", ha_gemini_ext, 2 | 4);
- fn_format(newidxextname_buff, pto, "", ha_gemini_idx_ext, 2 | 4);
-
- rc = dsmObjectNameToNum(pcontext, (dsmText_t *)name_buff, &tableNum);
- if (rc)
- {
- gemini_msg(pcontext, "Unable to file Table number for %s", name_buff);
- goto errorReturn;
- }
-
- rc = dsmObjectRename(pcontext, tableNum,
- (dsmText_t *)newname_buff,
- (dsmText_t *)&newidxextname_buff[start_of_name],
- (dsmText_t *)&newextname_buff[start_of_name],
- &indexArea, &tableArea);
- if (rc)
- {
- gemini_msg(pcontext, "Failed to rename %s to %s",name_buff,newname_buff);
- goto errorReturn;
- }
-
- /* Rename the physical table and index files (if necessary).
- ** Close the file, rename it, and reopen it (have to do it this
- ** way so rename works on Windows).
- */
- if (!(rc = dsmAreaClose(pcontext, tableArea)))
- {
- if (!(rc = rename_file_ext(pfrom, pto, ha_gemini_ext)))
- {
- rc = dsmAreaOpen(pcontext, tableArea, 0);
- if (rc)
- {
- gemini_msg(pcontext, "Failed to reopen area %d",tableArea);
- }
- }
- }
-
- if (!rc && indexArea)
- {
- if (!(rc = dsmAreaClose(pcontext, indexArea)))
- {
- if (!(rc = rename_file_ext(pfrom, pto, ha_gemini_idx_ext)))
- {
- rc = dsmAreaOpen(pcontext, indexArea, 0);
- if (rc)
- {
- gemini_msg(pcontext, "Failed to reopen area %d",tableArea);
- }
- }
- }
- }
-
-errorReturn:
- DBUG_RETURN(rc);
-}
-
-
-/*
- 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_gemini::scan_time()
-{
- return (double)records /
- (double)((gemini_blocksize / (double)table->reclength));
-}
-
-int ha_gemini::analyze(THD* thd, HA_CHECK_OPT* check_opt)
-{
- int error;
- uint saveIsolation;
- dsmMask_t saveLockMode;
-
- check_opt->quick = TRUE;
- check_opt->optimize = TRUE; // Tells check not to get table lock
- saveLockMode = lockMode;
- saveIsolation = thd->gemini.tx_isolation;
- thd->gemini.tx_isolation = ISO_READ_UNCOMMITTED;
- lockMode = DSM_LK_NOLOCK;
- error = check(thd,check_opt);
- lockMode = saveLockMode;
- thd->gemini.tx_isolation = saveIsolation;
- return (error);
-}
-
-int ha_gemini::check(THD* thd, HA_CHECK_OPT* check_opt)
-{
- int error = 0;
- int checkStatus = HA_ADMIN_OK;
- ha_rows indexCount;
- byte *buf = 0, *indexBuf = 0, *prevBuf = 0;
- int errorCount = 0;
-
- info(HA_STATUS_VARIABLE); // Makes sure row count is up to date
-
- /* Get a shared table lock */
- if(thd->gemini.needSavepoint)
- {
- /* We don't really need a savepoint here but do it anyway
- just to keep the savepoint number correct. */
- thd->gemini.savepoint++;
- error = dsmTransaction((dsmContext_t *)thd->gemini.context,
- &thd->gemini.savepoint,
- DSMTXN_SAVE, 0, 0);
- if (error)
- return(error);
- thd->gemini.needSavepoint = 0;
- }
- buf = (byte*)my_malloc(table->rec_buff_length,MYF(MY_WME));
- indexBuf = (byte*)my_malloc(table->rec_buff_length,MYF(MY_WME));
- prevBuf = (byte*)my_malloc(table->rec_buff_length,MYF(MY_WME |MY_ZEROFILL ));
-
- /* Lock the table */
- if (!check_opt->optimize)
- error = dsmObjectLock((dsmContext_t *)thd->gemini.context,
- (dsmObject_t)tableNumber,
- DSMOBJECT_TABLE,0,
- DSM_LK_SHARE, 1, 0);
- if(error)
- {
- gemini_msg((dsmContext_t *)thd->gemini.context,
- "Failed to lock table %d, error %d",tableNumber, error);
- return error;
- }
-
- ha_rows *rec_per_key = share->rec_per_key;
- /* If quick option just scan along index converting and counting entries */
- for (uint i = 0; i < table->keys; i++)
- {
- key_read = 1; // Causes data to be extracted from the keys
- indexCount = 0;
- // Clear the cardinality stats for this index
- memset(table->key_info[i].rec_per_key,0,
- sizeof(table->key_info[0].rec_per_key[0]) *
- table->key_info[i].key_parts);
- error = index_init(i);
- error = index_first(indexBuf);
- while(!error)
- {
- indexCount++;
- if(!check_opt->quick)
- {
- /* Fetch row and compare to data produced from key */
- error = fetch_row(thd->gemini.context,buf);
- if(!error)
- {
- if(key_cmp(i,buf,indexBuf,FALSE))
- {
-
- gemini_msg((dsmContext_t *)thd->gemini.context,
- "Check Error! Key does not match row for rowid %d for index %s",
- lastRowid,table->key_info[i].name);
- print_msg(thd,table->real_name,"check","error",
- "Key does not match row for rowid %d for index %s",
- lastRowid,table->key_info[i].name);
- checkStatus = HA_ADMIN_CORRUPT;
- errorCount++;
- if(errorCount > 1000)
- goto error_return;
- }
- else if(error == DSM_S_RMNOTFND)
- {
- errorCount++;
- checkStatus = HA_ADMIN_CORRUPT;
- gemini_msg((dsmContext_t *)thd->gemini.context,
- "Check Error! Key does not have a valid row pointer %d for index %s",
- lastRowid,table->key_info[i].name);
- print_msg(thd,table->real_name,"check","error",
- "Key does not have a valid row pointer %d for index %s",
- lastRowid,table->key_info[i].name);
- if(errorCount > 1000)
- goto error_return;
- error = 0;
- }
- }
- }
-
- key_cmp(i,indexBuf,prevBuf,TRUE);
- bcopy((void *)indexBuf,(void *)prevBuf,table->rec_buff_length);
-
- if(!error)
- error = index_next(indexBuf);
- }
-
- for(uint j=1; j < table->key_info[i].key_parts; j++)
- {
- table->key_info[i].rec_per_key[j] += table->key_info[i].rec_per_key[j-1];
- }
- for(uint k=0; k < table->key_info[i].key_parts; k++)
- {
- if (table->key_info[i].rec_per_key[k])
- table->key_info[i].rec_per_key[k] =
- records / table->key_info[i].rec_per_key[k];
- *rec_per_key = table->key_info[i].rec_per_key[k];
- rec_per_key++;
- }
-
- if(error == HA_ERR_END_OF_FILE)
- {
- /* Check count of rows */
-
- if(records != indexCount)
- {
- /* Number of index entries does not agree with the number of
- rows in the index. */
- checkStatus = HA_ADMIN_CORRUPT;
- gemini_msg((dsmContext_t *)thd->gemini.context,
- "Check Error! Total rows %d does not match total index entries %d for %s",
- records, indexCount,
- table->key_info[i].name);
- print_msg(thd,table->real_name,"check","error",
- "Total rows %d does not match total index entries %d for %s",
- records, indexCount,
- table->key_info[i].name);
- }
- }
- else
- {
- checkStatus = HA_ADMIN_FAILED;
- goto error_return;
- }
- index_end();
- }
- if(!check_opt->quick)
- {
- /* Now scan the table and for each row generate the keys
- and find them in the index */
- error = fullCheck(thd, buf);
- if(error)
- checkStatus = error;
- }
- // Store the key distribution information
- error = saveKeyStats(thd);
-
-error_return:
- my_free((char*)buf,MYF(MY_ALLOW_ZERO_PTR));
- my_free((char*)indexBuf,MYF(MY_ALLOW_ZERO_PTR));
- my_free((char*)prevBuf,MYF(MY_ALLOW_ZERO_PTR));
-
- index_end();
- key_read = 0;
- if(!check_opt->optimize)
- {
- error = dsmObjectUnlock((dsmContext_t *)thd->gemini.context,
- (dsmObject_t)tableNumber,
- DSMOBJECT_TABLE,0,
- DSM_LK_SHARE,0);
- if (error)
- {
- gemini_msg((dsmContext_t *)thd->gemini.context,
- "Unable to unlock table %d", tableNumber);
- }
- }
-
- return checkStatus;
-}
-
-int ha_gemini::saveKeyStats(THD *thd)
-{
- dsmStatus_t rc = 0;
-
- /* Insert a row in the indexStats table for each column of
- each index of the table */
-
- for(uint i = 0; i < table->keys; i++)
- {
- for (uint j = 0; j < table->key_info[i].key_parts && !rc ;j++)
- {
- rc = dsmIndexStatsPut((dsmContext_t *)thd->gemini.context,
- tableNumber, pindexNumbers[i],
- j, (LONG64)table->key_info[i].rec_per_key[j]);
- if (rc)
- {
- gemini_msg((dsmContext_t *)thd->gemini.context,
- "Failed to update index stats for table %d, index %d",
- tableNumber, pindexNumbers[i]);
- }
- }
- }
- return rc;
-}
-
-int ha_gemini::fullCheck(THD *thd,byte *buf)
-{
- int error;
- int errorCount = 0;
- int checkStatus = 0;
-
- lastRowid = 0;
-
- while(((error = rnd_next( buf)) != HA_ERR_END_OF_FILE) && errorCount <= 1000)
- {
- if(!error)
- {
- error = handleIndexEntries(buf,lastRowid,KEY_CHECK);
- if(error)
- {
- /* Error finding an index entry for a row. */
- print_msg(thd,table->real_name,"check","error",
- "Unable to find all index entries for row %d",
- lastRowid);
- errorCount++;
- checkStatus = HA_ADMIN_CORRUPT;
- error = 0;
- }
- }
- else
- {
- /* Error reading a row */
- print_msg(thd,table->real_name,"check","error",
- "Error reading row %d status = %d",
- lastRowid,error);
- errorCount++;
- checkStatus = HA_ADMIN_CORRUPT;
- error = 0;
- }
- }
-
- return checkStatus;
-}
-
-int ha_gemini::repair(THD* thd, HA_CHECK_OPT* check_opt)
-{
- int error;
- dsmRecord_t dsmRecord;
- byte *buf;
-
- if(thd->gemini.needSavepoint)
- {
- /* We don't really need a savepoint here but do it anyway
- just to keep the savepoint number correct. */
- thd->gemini.savepoint++;
- error = dsmTransaction((dsmContext_t *)thd->gemini.context,
- &thd->gemini.savepoint,
- DSMTXN_SAVE, 0, 0);
- if (error)
- {
- gemini_msg((dsmContext_t *)thd->gemini.context,
- "Error setting savepoint number %d, error %d",
- thd->gemini.savepoint++, error);
- return(error);
- }
- thd->gemini.needSavepoint = 0;
- }
-
-
- /* Lock the table */
- error = dsmObjectLock((dsmContext_t *)thd->gemini.context,
- (dsmObject_t)tableNumber,
- DSMOBJECT_TABLE,0,
- DSM_LK_EXCL, 1, 0);
- if(error)
- {
- gemini_msg((dsmContext_t *)thd->gemini.context,
- "Failed to lock table %d, error %d",tableNumber, error);
- return error;
- }
-
- error = dsmContextSetLong((dsmContext_t *)thd->gemini.context,
- DSM_TAGCONTEXT_NO_LOGGING,1);
-
- error = dsmTableReset((dsmContext_t *)thd->gemini.context,
- (dsmTable_t)tableNumber, table->keys,
- pindexNumbers);
- if (error)
- {
- gemini_msg((dsmContext_t *)thd->gemini.context,
- "dsmTableReset failed for table %d, error %d",tableNumber, error);
- }
-
- buf = (byte*)my_malloc(table->rec_buff_length,MYF(MY_WME));
- dsmRecord.table = tableNumber;
- dsmRecord.recid = 0;
- dsmRecord.pbuffer = (dsmBuffer_t *)rec_buff;
- dsmRecord.recLength = table->reclength;
- dsmRecord.maxLength = table->rec_buff_length;
- while(!error)
- {
- error = dsmTableScan((dsmContext_t *)thd->gemini.context,
- &dsmRecord, DSMFINDNEXT, DSM_LK_NOLOCK,
- 1);
- if(!error)
- {
- if (!(error = unpack_row((char *)buf,(char *)dsmRecord.pbuffer)))
- {
- error = handleIndexEntries(buf,dsmRecord.recid,KEY_CREATE);
- if(error == HA_ERR_FOUND_DUPP_KEY)
- {
- /* We don't want to stop on duplicate keys -- we're repairing
- here so let's get as much repaired as possible. */
- error = 0;
- }
- }
- }
- }
- error = dsmObjectUnlock((dsmContext_t *)thd->gemini.context,
- (dsmObject_t)tableNumber,
- DSMOBJECT_TABLE,0,
- DSM_LK_EXCL,0);
- if (error)
- {
- gemini_msg((dsmContext_t *)thd->gemini.context,
- "Unable to unlock table %d", tableNumber);
- }
-
- my_free((char*)buf,MYF(MY_ALLOW_ZERO_PTR));
-
- error = dsmContextSetLong((dsmContext_t *)thd->gemini.context,
- DSM_TAGCONTEXT_NO_LOGGING,0);
-
- return error;
-}
-
-
-int ha_gemini::restore(THD* thd, HA_CHECK_OPT *check_opt)
-{
- dsmContext_t *pcontext = (dsmContext_t *)thd->gemini.context;
- char* backup_dir = thd->lex.backup_dir;
- char src_path[FN_REFLEN], dst_path[FN_REFLEN];
- char* table_name = table->real_name;
- int error = 0;
- int errornum;
- const char* errmsg = "";
- dsmArea_t tableArea = 0;
- dsmObjectAttr_t objectAttr;
- dsmObject_t associate;
- dsmObjectType_t associateType;
- dsmDbkey_t block, root;
- dsmStatus_t rc;
-
- rc = dsmObjectInfo(pcontext, tableNumber, DSMOBJECT_MIXTABLE, tableNumber,
- &tableArea, &objectAttr, &associateType, &block, &root);
- if (rc)
- {
- error = HA_ADMIN_FAILED;
- errmsg = "Failed in dsmObjectInfo (.gmd) (Error %d)";
- errornum = rc;
- gemini_msg(pcontext, errmsg ,errornum);
- goto err;
- }
-
- rc = dsmAreaFlush(pcontext, tableArea, FLUSH_BUFFERS | FLUSH_SYNC);
- if (rc)
- {
- error = HA_ADMIN_FAILED;
- errmsg = "Failed in dsmAreaFlush (.gmd) (Error %d)";
- errornum = rc;
- gemini_msg(pcontext, errmsg ,errornum);
- goto err;
- }
-
- rc = dsmAreaClose(pcontext, tableArea);
- if (rc)
- {
- error = HA_ADMIN_FAILED;
- errmsg = "Failed in dsmAreaClose (.gmd) (Error %d)";
- errornum = rc;
- gemini_msg(pcontext, errmsg ,errornum);
- goto err;
- }
-
- /* Restore the data file */
- if (!fn_format(src_path, table_name, backup_dir, ha_gemini_ext, 4 + 64))
- {
- return HA_ADMIN_INVALID;
- }
-
- if (my_copy(src_path, fn_format(dst_path, table->path, "",
- ha_gemini_ext, 4), MYF(MY_WME)))
- {
- error = HA_ADMIN_FAILED;
- errmsg = "Failed in my_copy (.gmd) (Error %d)";
- errornum = errno;
- gemini_msg(pcontext, errmsg ,errornum);
- goto err;
- }
-
- rc = dsmAreaFlush(pcontext, tableArea, FREE_BUFFERS);
- if (rc)
- {
- error = HA_ADMIN_FAILED;
- errmsg = "Failed in dsmAreaFlush (.gmd) (Error %d)";
- errornum = rc;
- gemini_msg(pcontext, errmsg ,errornum);
- goto err;
- }
-
- rc = dsmAreaOpen(pcontext, tableArea, 1);
- if (rc)
- {
- error = HA_ADMIN_FAILED;
- errmsg = "Failed in dsmAreaOpen (.gmd) (Error %d)";
- errornum = rc;
- gemini_msg(pcontext, errmsg ,errornum);
- goto err;
- }
-
-#ifdef GEMINI_BACKUP_IDX
- dsmArea_t indexArea = 0;
-
- rc = dsmObjectInfo(pcontext, tableNumber, DSMOBJECT_MIXINDEX, &indexArea,
- &objectAttr, &associate, &associateType, &block, &root);
- if (rc)
- {
- error = HA_ADMIN_FAILED;
- errmsg = "Failed in dsmObjectInfo (.gmi) (Error %d)";
- errornum = rc;
- gemini_msg(pcontext, errmsg ,errornum);
- goto err;
- }
-
- rc = dsmAreaClose(pcontext, indexArea);
- if (rc)
- {
- error = HA_ADMIN_FAILED;
- errmsg = "Failed in dsmAreaClose (.gmi) (Error %d)";
- errornum = rc;
- gemini_msg(pcontext, errmsg ,errornum);
- goto err;
- }
-
- /* Restore the index file */
- if (!fn_format(src_path, table_name, backup_dir, ha_gemini_idx_ext, 4 + 64))
- {
- return HA_ADMIN_INVALID;
- }
-
- if (my_copy(src_path, fn_format(dst_path, table->path, "",
- ha_gemini_idx_ext, 4), MYF(MY_WME)))
- {
- error = HA_ADMIN_FAILED;
- errmsg = "Failed in my_copy (.gmi) (Error %d)";
- errornum = errno;
- gemini_msg(pcontext, errmsg ,errornum);
- goto err;
- }
-
- rc = dsmAreaOpen(pcontext, indexArea, 1);
- if (rc)
- {
- error = HA_ADMIN_FAILED;
- errmsg = "Failed in dsmAreaOpen (.gmi) (Error %d)";
- errornum = rc;
- gemini_msg(pcontext, errmsg ,errornum);
- goto err;
- }
-
- return HA_ADMIN_OK;
-#else /* #ifdef GEMINI_BACKUP_IDX */
- HA_CHECK_OPT tmp_check_opt;
- tmp_check_opt.init();
- /* The following aren't currently implemented in ha_gemini::repair
- ** tmp_check_opt.quick = 1;
- ** tmp_check_opt.flags |= T_VERY_SILENT;
- */
- return (repair(thd, &tmp_check_opt));
-#endif /* #ifdef GEMINI_BACKUP_IDX */
-
- err:
- {
-#if 0
- /* mi_check_print_error is in ha_myisam.cc, so none of the informative
- ** error messages above is currently being printed
- */
- MI_CHECK param;
- myisamchk_init(&param);
- param.thd = thd;
- param.op_name = (char*)"restore";
- param.table_name = table->table_name;
- param.testflag = 0;
- mi_check_print_error(&param,errmsg, errornum);
-#endif
- return error;
- }
-}
-
-
-int ha_gemini::backup(THD* thd, HA_CHECK_OPT *check_opt)
-{
- dsmContext_t *pcontext = (dsmContext_t *)thd->gemini.context;
- char* backup_dir = thd->lex.backup_dir;
- char src_path[FN_REFLEN], dst_path[FN_REFLEN];
- char* table_name = table->real_name;
- int error = 0;
- int errornum;
- const char* errmsg = "";
- dsmArea_t tableArea = 0;
- dsmObjectAttr_t objectAttr;
- dsmObject_t associate;
- dsmObjectType_t associateType;
- dsmDbkey_t block, root;
- dsmStatus_t rc;
-
- rc = dsmObjectInfo(pcontext, tableNumber, DSMOBJECT_MIXTABLE, tableNumber,
- &tableArea, &objectAttr, &associateType, &block, &root);
- if (rc)
- {
- error = HA_ADMIN_FAILED;
- errmsg = "Failed in dsmObjectInfo (.gmd) (Error %d)";
- errornum = rc;
- goto err;
- }
-
- /* Flush the buffers before backing up the table */
- dsmAreaFlush((dsmContext_t *)thd->gemini.context, tableArea,
- FLUSH_BUFFERS | FLUSH_SYNC);
- if (rc)
- {
- error = HA_ADMIN_FAILED;
- errmsg = "Failed in dsmAreaFlush (.gmd) (Error %d)";
- errornum = rc;
- gemini_msg(pcontext, errmsg ,errornum);
- goto err;
- }
-
- /* Backup the .FRM file */
- if (!fn_format(dst_path, table_name, backup_dir, reg_ext, 4 + 64))
- {
- errmsg = "Failed in fn_format() for .frm file: errno = %d";
- error = HA_ADMIN_INVALID;
- errornum = errno;
- gemini_msg(pcontext, errmsg ,errornum);
- goto err;
- }
-
- if (my_copy(fn_format(src_path, table->path,"", reg_ext, 4),
- dst_path,
- MYF(MY_WME | MY_HOLD_ORIGINAL_MODES )))
- {
- error = HA_ADMIN_FAILED;
- errmsg = "Failed copying .frm file: errno = %d";
- errornum = errno;
- gemini_msg(pcontext, errmsg ,errornum);
- goto err;
- }
-
- /* Backup the data file */
- if (!fn_format(dst_path, table_name, backup_dir, ha_gemini_ext, 4 + 64))
- {
- errmsg = "Failed in fn_format() for .GMD file: errno = %d";
- error = HA_ADMIN_INVALID;
- errornum = errno;
- gemini_msg(pcontext, errmsg ,errornum);
- goto err;
- }
-
- if (my_copy(fn_format(src_path, table->path,"", ha_gemini_ext, 4),
- dst_path,
- MYF(MY_WME | MY_HOLD_ORIGINAL_MODES )) )
- {
- errmsg = "Failed copying .GMD file: errno = %d";
- error= HA_ADMIN_FAILED;
- errornum = errno;
- gemini_msg(pcontext, errmsg ,errornum);
- goto err;
- }
-
-#ifdef GEMINI_BACKUP_IDX
- dsmArea_t indexArea = 0;
-
- rc = dsmObjectInfo(pcontext, tableNumber, DSMOBJECT_MIXINDEX, &indexArea,
- &objectAttr, &associate, &associateType, &block, &root);
- if (rc)
- {
- error = HA_ADMIN_FAILED;
- errmsg = "Failed in dsmObjectInfo (.gmi) (Error %d)";
- errornum = rc;
- gemini_msg(pcontext, errmsg ,errornum);
- goto err;
- }
-
- /* Backup the index file */
- if (!fn_format(dst_path, table_name, backup_dir, ha_gemini_idx_ext, 4 + 64))
- {
- errmsg = "Failed in fn_format() for .GMI file: errno = %d";
- error = HA_ADMIN_INVALID;
- errornum = errno;
- gemini_msg(pcontext, errmsg ,errornum);
- goto err;
- }
-
- if (my_copy(fn_format(src_path, table->path,"", ha_gemini_idx_ext, 4),
- dst_path,
- MYF(MY_WME | MY_HOLD_ORIGINAL_MODES )) )
- {
- errmsg = "Failed copying .GMI file: errno = %d";
- error= HA_ADMIN_FAILED;
- errornum = errno;
- gemini_msg(pcontext, errmsg ,errornum);
- goto err;
- }
-#endif /* #ifdef GEMINI_BACKUP_IDX */
-
- return HA_ADMIN_OK;
-
- err:
- {
-#if 0
- /* mi_check_print_error is in ha_myisam.cc, so none of the informative
- ** error messages above is currently being printed
- */
- MI_CHECK param;
- myisamchk_init(&param);
- param.thd = thd;
- param.op_name = (char*)"backup";
- param.table_name = table->table_name;
- param.testflag = 0;
- mi_check_print_error(&param,errmsg, errornum);
-#endif
- return error;
- }
-}
-
-
-int ha_gemini::optimize(THD* thd, HA_CHECK_OPT *check_opt)
-{
- return HA_ADMIN_ALREADY_DONE;
-}
-
-
-ha_rows ha_gemini::records_in_range(int keynr,
- const byte *start_key,uint start_key_len,
- enum ha_rkey_function start_search_flag,
- const byte *end_key,uint end_key_len,
- enum ha_rkey_function end_search_flag)
-{
- int error;
- int componentLen;
- float pctInrange;
- ha_rows rows = 5;
-
- DBUG_ENTER("records_in_range");
-
- error = index_init(keynr);
- if(error)
- DBUG_RETURN(rows);
-
- pbracketBase->index = (short)pindexNumbers[keynr];
- pbracketBase->keycomps = 1;
-
- if(start_key)
- {
- error = pack_key(keynr, pbracketBase, start_key, start_key_len);
- if(start_search_flag == HA_READ_AFTER_KEY)
- {
- /* A greater than operation */
- error = gemKeyAddLow(pbracketBase->keystr + pbracketBase->keyLen,
- &componentLen);
- pbracketBase->keyLen += componentLen;
- }
- }
- else
- {
- error = gemKeyLow(pbracketBase->keystr, &componentLen,
- pbracketBase->index);
- pbracketBase->keyLen = componentLen;
-
- }
- pbracketBase->keyLen -= FULLKEYHDRSZ;
-
- if(end_key)
- {
- error = pack_key(keynr, pbracketLimit, end_key, end_key_len);
- if(!error && end_search_flag == HA_READ_AFTER_KEY)
- {
- error = gemKeyAddHigh(pbracketLimit->keystr + pbracketLimit->keyLen,
- &componentLen);
- pbracketLimit->keyLen += componentLen;
- }
- }
- else
- {
- error = gemKeyHigh(pbracketLimit->keystr,&componentLen,
- pbracketLimit->index);
- pbracketLimit->keyLen = componentLen;
- }
-
- pbracketLimit->keyLen -= FULLKEYHDRSZ;
- error = dsmIndexRowsInRange((dsmContext_t *)current_thd->gemini.context,
- pbracketBase,pbracketLimit,
- tableNumber,
- &pctInrange);
- if(pctInrange >= 1)
- rows = (ha_rows)pctInrange;
- else
- {
- rows = (ha_rows)(records * pctInrange);
- if(!rows && pctInrange > 0)
- rows = 1;
- }
- index_end();
-
- DBUG_RETURN(rows);
-}
-
-
-/*
- Pack a row for storage. If the row is of fixed length, just store the
- row 'as is'.
- If not, we will generate a packed row suitable for storage.
- This will only fail if we don't have enough memory to pack the row, which;
- may only happen in rows with blobs, as the default row length is
- pre-allocated.
-*/
-int ha_gemini::pack_row(byte **pprow, int *ppackedLength, const byte *record,
- bool update)
-{
- THD *thd = current_thd;
- dsmContext_t *pcontext = (dsmContext_t *)thd->gemini.context;
- gemBlobDesc_t *pBlobDesc = pBlobDescs;
-
- if (fixed_length_row)
- {
- *pprow = (byte *)record;
- *ppackedLength=(int)table->reclength;
- return 0;
- }
- /* Copy null bits */
- memcpy(rec_buff, record, table->null_bytes);
- byte *ptr=rec_buff + table->null_bytes;
-
- for (Field **field=table->field ; *field ; field++)
- {
-#ifdef GEMINI_TINYBLOB_IN_ROW
- /* Tiny blobs (255 bytes or less) are stored in the row; larger
- ** blobs are stored in a separate storage object (see ha_gemini::create).
- */
- if ((*field)->type() == FIELD_TYPE_BLOB &&
- ((Field_blob*)*field)->blobtype() != FIELD_TYPE_TINY_BLOB)
-#else
- if ((*field)->type() == FIELD_TYPE_BLOB)
-#endif
- {
- dsmBlob_t gemBlob;
- char *blobptr;
-
- gemBlob.areaType = DSMOBJECT_BLOB;
- gemBlob.blobObjNo = tableNumber;
- gemBlob.blobId = 0;
- gemBlob.totLength = gemBlob.segLength =
- ((Field_blob*)*field)->get_length((char*)record + (*field)->offset());
- ((Field_blob*)*field)->get_ptr((char**) &blobptr);
- gemBlob.pBuffer = (dsmBuffer_t *)blobptr;
- gemBlob.blobContext.blobOffset = 0;
- if (gemBlob.totLength)
- {
- dsmBlobStart(pcontext, &gemBlob);
- if (update && pBlobDesc->blobId)
- {
- gemBlob.blobId = pBlobDesc->blobId;
- dsmBlobUpdate(pcontext, &gemBlob, NULL);
- }
- else
- {
- dsmBlobPut(pcontext, &gemBlob, NULL);
- }
- dsmBlobEnd(pcontext, &gemBlob);
- }
- ptr = (byte*)((Field_blob*)*field)->pack_id((char*) ptr,
- (char*)record + (*field)->offset(), (longlong)gemBlob.blobId);
-
- pBlobDesc++;
- }
- else
- {
- ptr=(byte*) (*field)->pack((char*) ptr, (char*)record + (*field)->offset());
- }
- }
-
- *pprow=rec_buff;
- *ppackedLength= (ptr - rec_buff);
- return 0;
-}
-
-int ha_gemini::unpack_row(char *record, char *prow)
-{
- THD *thd = current_thd;
- dsmContext_t *pcontext = (dsmContext_t *)thd->gemini.context;
- gemBlobDesc_t *pBlobDesc = pBlobDescs;
-
- if (fixed_length_row)
- {
- /* If the table is a VST, the row is in Gemini internal format.
- ** Convert the fields to MySQL format.
- */
- if (RM_IS_VST(tableNumber))
- {
- int i = 2; /* VST fields are numbered sequentially starting at 2 */
- long longValue;
- char *fld;
- unsigned long unknown;
-
- for (Field **field = table->field; *field; field++, i++)
- {
- switch ((*field)->type())
- {
- case FIELD_TYPE_LONG:
- case FIELD_TYPE_TINY:
- case FIELD_TYPE_SHORT:
- case FIELD_TYPE_TIMESTAMP:
- case FIELD_TYPE_LONGLONG:
- case FIELD_TYPE_INT24:
- case FIELD_TYPE_DATE:
- case FIELD_TYPE_TIME:
- case FIELD_TYPE_DATETIME:
- case FIELD_TYPE_YEAR:
- case FIELD_TYPE_NEWDATE:
- case FIELD_TYPE_ENUM:
- case FIELD_TYPE_SET:
- recGetLONG((dsmText_t *)prow, i, 0, &longValue, &unknown);
- if (unknown)
- {
- (*field)->set_null();
- }
- else
- {
- (*field)->set_notnull();
- (*field)->store((longlong)longValue);
- }
- break;
-
- case FIELD_TYPE_DECIMAL:
- case FIELD_TYPE_DOUBLE:
- case FIELD_TYPE_TINY_BLOB:
- case FIELD_TYPE_MEDIUM_BLOB:
- case FIELD_TYPE_LONG_BLOB:
- case FIELD_TYPE_BLOB:
- case FIELD_TYPE_VAR_STRING:
- break;
-
- case FIELD_TYPE_STRING:
- svcByteString_t stringFld;
-
- fld = (char *)my_malloc((*field)->field_length, MYF(MY_WME));
- stringFld.pbyte = (TEXT *)fld;
- stringFld.size = (*field)->field_length;
- recGetBYTES((dsmText_t *)prow, i, 0, &stringFld, &unknown);
- if (unknown)
- {
- (*field)->set_null();
- }
- else
- {
- (*field)->set_notnull();
- (*field)->store(fld, (*field)->field_length);
- }
- my_free(fld, MYF(MY_ALLOW_ZERO_PTR));
- break;
-
- default:
- break;
- }
- }
- }
- else
- {
- memcpy(record,(char*) prow,table->reclength);
- }
- }
- else
- {
- /* Copy null bits */
- const char *ptr= (const char*) prow;
- memcpy(record, ptr, table->null_bytes);
- ptr+=table->null_bytes;
-
- for (Field **field=table->field ; *field ; field++)
- {
-#ifdef GEMINI_TINYBLOB_IN_ROW
- /* Tiny blobs (255 bytes or less) are stored in the row; larger
- ** blobs are stored in a separate storage object (see ha_gemini::create).
- */
- if ((*field)->type() == FIELD_TYPE_BLOB &&
- ((Field_blob*)*field)->blobtype() != FIELD_TYPE_TINY_BLOB)
-#else
- if ((*field)->type() == FIELD_TYPE_BLOB)
-#endif
- {
- dsmBlob_t gemBlob;
-
- gemBlob.areaType = DSMOBJECT_BLOB;
- gemBlob.blobObjNo = tableNumber;
- gemBlob.blobId = (dsmBlobId_t)(((Field_blob*)*field)->get_id(ptr));
- if (gemBlob.blobId)
- {
- gemBlob.totLength =
- gemBlob.segLength = ((Field_blob*)*field)->get_length(ptr);
- /* Allocate memory to store the blob. This memory is freed
- ** the next time unpack_row is called for this table.
- */
- gemBlob.pBuffer = (dsmBuffer_t *)my_malloc(gemBlob.totLength,
- MYF(0));
- if (!gemBlob.pBuffer)
- {
- return HA_ERR_OUT_OF_MEM;
- }
- gemBlob.blobContext.blobOffset = 0;
- dsmBlobStart(pcontext, &gemBlob);
- dsmBlobGet(pcontext, &gemBlob, NULL);
- dsmBlobEnd(pcontext, &gemBlob);
- }
- else
- {
- gemBlob.pBuffer = 0;
- }
- ptr = ((Field_blob*)*field)->unpack_id(record + (*field)->offset(),
- ptr, (char *)gemBlob.pBuffer);
- pBlobDesc->blobId = gemBlob.blobId;
- my_free((char*)pBlobDesc->pBlob, MYF(MY_ALLOW_ZERO_PTR));
- pBlobDesc->pBlob = gemBlob.pBuffer;
- pBlobDesc++;
- }
- else
- {
- ptr= (*field)->unpack(record + (*field)->offset(), ptr);
- }
- }
- }
-
- return 0;
-}
-
-int ha_gemini::key_cmp(uint keynr, const byte * old_row,
- const byte * new_row, bool updateStats)
-{
- KEY_PART_INFO *key_part=table->key_info[keynr].key_part;
- KEY_PART_INFO *end=key_part+table->key_info[keynr].key_parts;
-
- for ( uint i = 0 ; key_part != end ; key_part++, i++)
- {
- if (key_part->null_bit)
- {
- if ((old_row[key_part->null_offset] & key_part->null_bit) !=
- (new_row[key_part->null_offset] & key_part->null_bit))
- {
- if(updateStats)
- table->key_info[keynr].rec_per_key[i]++;
- return 1;
- }
- else if((old_row[key_part->null_offset] & key_part->null_bit) &&
- (new_row[key_part->null_offset] & key_part->null_bit))
- /* Both are null */
- continue;
- }
- if (key_part->key_part_flag & (HA_BLOB_PART | HA_VAR_LENGTH))
- {
- if (key_part->field->cmp_binary((char*)(old_row + key_part->offset),
- (char*)(new_row + key_part->offset),
- (ulong) key_part->length))
- {
- if(updateStats)
- table->key_info[keynr].rec_per_key[i]++;
- return 1;
- }
- }
- else
- {
- if (memcmp(old_row+key_part->offset, new_row+key_part->offset,
- key_part->length))
- {
- /* Check for special case of -0 which causes table check
- to find an invalid key when comparing the the index
- value of 0 to the -0 stored in the row */
- if(key_part->field->type() == FIELD_TYPE_DECIMAL)
- {
- double fieldValue;
- char *ptr = key_part->field->ptr;
-
- key_part->field->ptr = (char *)old_row + key_part->offset;
- fieldValue = key_part->field->val_real();
- if(fieldValue == 0)
- {
- key_part->field->ptr = (char *)new_row + key_part->offset;
- fieldValue = key_part->field->val_real();
- if(fieldValue == 0)
- {
- key_part->field->ptr = ptr;
- continue;
- }
- }
- key_part->field->ptr = ptr;
- }
- if(updateStats)
- {
- table->key_info[keynr].rec_per_key[i]++;
- }
- return 1;
- }
- }
- }
- return 0;
-}
-
-int gemini_parse_table_name(const char *fullname, char *dbname, char *tabname)
-{
- char *namestart;
- char *nameend;
-
- /* separate out the name of the table and the database
- */
- namestart = (char *)strchr(fullname + start_of_name, '/');
- if (!namestart)
- {
- /* if on Windows, slashes go the other way */
- namestart = (char *)strchr(fullname + start_of_name, '\\');
- }
- nameend = (char *)strchr(fullname + start_of_name, '.');
- /* sometimes fullname has an extension, sometimes it doesn't */
- if (!nameend)
- {
- nameend = (char *)fullname + strlen(fullname);
- }
- strncpy(dbname, fullname + start_of_name,
- (namestart - fullname) - start_of_name);
- dbname[(namestart - fullname) - start_of_name] = '\0';
- strncpy(tabname, namestart + 1, (nameend - namestart) - 1);
- tabname[nameend - namestart - 1] = '\0';
-
- return 0;
-}
-
-/* PROGRAM: gemini_is_vst - if the name is the name of a VST, return
- * its number
- *
- * RETURNS: Table number if a match is found
- * 0 if not a VST
- */
-int
-gemini_is_vst(const char *pname) /* IN the name */
-{
- int tablenum = 0;
-
- for (int i = 0; i < vstnumfils; i++)
- {
- if (strcmp(pname, vstfil[i].filename) == 0)
- {
- tablenum = vstfil[i].filnum;
- break;
- }
- }
-
- return tablenum;
-}
-
-static void print_msg(THD *thd, const char *table_name, const char *op_name,
- const char *msg_type, const char *fmt, ...)
-{
- String* packet = &thd->packet;
- packet->length(0);
- char msgbuf[256];
- msgbuf[0] = 0;
- va_list args;
- va_start(args,fmt);
-
- my_vsnprintf(msgbuf, sizeof(msgbuf), fmt, args);
- msgbuf[sizeof(msgbuf) - 1] = 0; // healthy paranoia
-
- DBUG_PRINT(msg_type,("message: %s",msgbuf));
-
- net_store_data(packet, table_name);
- net_store_data(packet, op_name);
- net_store_data(packet, msg_type);
- net_store_data(packet, msgbuf);
- if (my_net_write(&thd->net, (char*)thd->packet.ptr(),
- thd->packet.length()))
- thd->killed=1;
-}
-
-/* Load shared area with rows per key statistics */
-void
-ha_gemini::get_index_stats(THD *thd)
-{
- dsmStatus_t rc = 0;
- ha_rows *rec_per_key = share->rec_per_key;
-
- for(uint i = 0; i < table->keys && !rc; i++)
- {
- for (uint j = 0; j < table->key_info[i].key_parts && !rc;j++)
- {
- LONG64 rows_per_key;
- rc = dsmIndexStatsGet((dsmContext_t *)thd->gemini.context,
- tableNumber, pindexNumbers[i],(int)j,
- &rows_per_key);
- if (rc)
- {
- gemini_msg((dsmContext_t *)thd->gemini.context,
- "Index Statistics faild for table %d index %d, error %d",
- tableNumber, pindexNumbers[i], rc);
- }
- *rec_per_key = (ha_rows)rows_per_key;
- rec_per_key++;
- }
- }
- return;
-}
-
-/****************************************************************************
- Handling the shared GEM_SHARE structure that is needed to provide
- a global in memory storage location of the rec_per_key stats used
- by the optimizer.
-****************************************************************************/
-
-static byte* gem_get_key(GEM_SHARE *share,uint *length,
- my_bool not_used __attribute__((unused)))
-{
- *length=share->table_name_length;
- return (byte*) share->table_name;
-}
-
-static GEM_SHARE *get_share(const char *table_name, TABLE *table)
-{
- GEM_SHARE *share;
-
- pthread_mutex_lock(&gem_mutex);
- uint length=(uint) strlen(table_name);
- if (!(share=(GEM_SHARE*) hash_search(&gem_open_tables, (byte*) table_name,
- length)))
- {
- ha_rows *rec_per_key;
- char *tmp_name;
-
- if ((share=(GEM_SHARE *)
- my_multi_malloc(MYF(MY_WME | MY_ZEROFILL),
- &share, sizeof(*share),
- &rec_per_key, table->key_parts * sizeof(ha_rows),
- &tmp_name, length+1,
- NullS)))
- {
- share->rec_per_key = rec_per_key;
- share->table_name = tmp_name;
- share->table_name_length=length;
- strcpy(share->table_name,table_name);
- if (hash_insert(&gem_open_tables, (byte*) share))
- {
- pthread_mutex_unlock(&gem_mutex);
- my_free((gptr) share,0);
- return 0;
- }
- thr_lock_init(&share->lock);
- pthread_mutex_init(&share->mutex,NULL);
- }
- }
- pthread_mutex_unlock(&gem_mutex);
- return share;
-}
-
-static int free_share(GEM_SHARE *share, bool mutex_is_locked)
-{
- pthread_mutex_lock(&gem_mutex);
- if (mutex_is_locked)
- pthread_mutex_unlock(&share->mutex);
- if (!--share->use_count)
- {
- hash_delete(&gem_open_tables, (byte*) share);
- thr_lock_delete(&share->lock);
- pthread_mutex_destroy(&share->mutex);
- my_free((gptr) share, MYF(0));
- }
- pthread_mutex_unlock(&gem_mutex);
- return 0;
-}
-
-static void gemini_lock_table_overflow_error(dsmContext_t *pcontext)
-{
- gemini_msg(pcontext, "The total number of locks exceeds the lock table size");
- gemini_msg(pcontext, "Either increase gemini_lock_table_size or use a");
- gemini_msg(pcontext, "different transaction isolation level");
-}
-
-#endif /* HAVE_GEMINI_DB */
diff --git a/sql/ha_gemini.h b/sql/ha_gemini.h
deleted file mode 100644
index 96c0cdd4241..00000000000
--- a/sql/ha_gemini.h
+++ /dev/null
@@ -1,208 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & NuSphere Corporation
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-
-#ifdef __GNUC__
-#pragma interface /* gcc class implementation */
-#endif
-
-#include "gem_global.h"
-#include "dstd.h"
-#include "dsmpub.h"
-
-/* class for the the gemini handler */
-
-enum enum_key_string_options{KEY_CREATE,KEY_DELETE,KEY_CHECK};
-typedef struct st_gemini_share {
- ha_rows *rec_per_key;
- THR_LOCK lock;
- pthread_mutex_t mutex;
- char *table_name;
- uint table_name_length,use_count;
-} GEM_SHARE;
-
-typedef struct gemBlobDesc
-{
- dsmBlobId_t blobId;
- dsmBuffer_t *pBlob;
-} gemBlobDesc_t;
-
-class ha_gemini: public handler
-{
- /* define file as an int for now until we have a real file struct */
- int file;
- uint int_option_flag;
- int tableNumber;
- dsmIndex_t *pindexNumbers; // dsm object numbers for the indexes on this table
- dsmRecid_t lastRowid;
- uint last_dup_key;
- bool fixed_length_row, key_read, using_ignore;
- byte *rec_buff;
- dsmKey_t *pbracketBase;
- dsmKey_t *pbracketLimit;
- dsmKey_t *pfoundKey;
- dsmMask_t tableStatus; // Crashed/repair status
- gemBlobDesc_t *pBlobDescs;
-
- int index_open(char *tableName);
- int pack_row(byte **prow, int *ppackedLength, const byte *record,
- bool update);
- int unpack_row(char *record, char *prow);
- int findRow(THD *thd, dsmMask_t findMode, byte *buf);
- int fetch_row(void *gemini_context, const byte *buf);
- int handleIndexEntries(const byte * record, dsmRecid_t recid,
- enum_key_string_options option);
-
- int handleIndexEntry(const byte * record, dsmRecid_t recid,
- enum_key_string_options option,uint keynr);
-
- int createKeyString(const byte * record, KEY *pkeyinfo,
- unsigned char *pkeyBuf, int bufSize,
- int *pkeyStringLen, short geminiIndexNumber,
- bool *thereIsAnull);
- int fullCheck(THD *thd,byte *buf);
-
- int pack_key( uint keynr, dsmKey_t *pkey,
- const byte *key_ptr, uint key_length);
-
- void unpack_key(char *record, dsmKey_t *key, uint index);
-
- int key_cmp(uint keynr, const byte * old_row,
- const byte * new_row, bool updateStats);
-
- int saveKeyStats(THD *thd);
- void get_index_stats(THD *thd);
-
- short cursorId; /* cursorId of active index cursor if any */
- dsmMask_t lockMode; /* Shared or exclusive */
-
- /* FIXFIX Don't know why we need this because I don't know what
- store_lock method does but we core dump without this */
- THR_LOCK_DATA lock;
- GEM_SHARE *share;
-
- public:
- ha_gemini(TABLE *table): handler(table), file(0),
- int_option_flag(HA_READ_NEXT | HA_READ_PREV |
- HA_REC_NOT_IN_SEQ |
- HA_KEYPOS_TO_RNDPOS | HA_READ_ORDER | HA_LASTKEY_ORDER |
- HA_LONGLONG_KEYS | HA_NULL_KEY | HA_HAVE_KEY_READ_ONLY |
- HA_BLOB_KEY |
- HA_NO_TEMP_TABLES | HA_NO_FULLTEXT_KEY |
- /*HA_NOT_EXACT_COUNT | */
- /*HA_KEY_READ_WRONG_STR |*/ HA_DROP_BEFORE_CREATE),
- pbracketBase(0),pbracketLimit(0),pfoundKey(0),
- cursorId(0)
- {
- }
- ~ha_gemini() {}
- const char *table_type() const { return "Gemini"; }
- const char **bas_ext() const;
- ulong option_flag() const { return int_option_flag; }
- uint max_record_length() const { return MAXRECSZ; }
- uint max_keys() const { return MAX_KEY-1; }
- uint max_key_parts() const { return MAX_REF_PARTS; }
- uint max_key_length() const { return MAXKEYSZ / 2; }
- bool fast_key_read() { return 1;}
- bool has_transactions() { return 1;}
-
- int open(const char *name, int mode, uint test_if_locked);
- int close(void);
- double scan_time();
- int write_row(byte * buf);
- int update_row(const byte * old_data, byte * new_data);
- int delete_row(const byte * buf);
- int index_init(uint index);
- int index_end();
- int index_read(byte * buf, const byte * key,
- uint key_len, enum ha_rkey_function find_flag);
- int index_read_idx(byte * buf, uint index, const byte * key,
- uint key_len, enum ha_rkey_function find_flag);
- int index_next(byte * buf);
- int index_next_same(byte * buf, const byte *key, uint keylen);
- int index_prev(byte * buf);
- int index_first(byte * buf);
- int index_last(byte * buf);
- int rnd_init(bool scan=1);
- int rnd_end();
- int rnd_next(byte *buf);
- int rnd_pos(byte * buf, byte *pos);
- void position(const byte *record);
- void info(uint);
- int extra(enum ha_extra_function operation);
- int reset(void);
- int analyze(THD* thd, HA_CHECK_OPT* check_opt);
- int check(THD* thd, HA_CHECK_OPT* check_opt);
- int repair(THD* thd, HA_CHECK_OPT* check_opt);
- int restore(THD* thd, HA_CHECK_OPT* check_opt);
- int backup(THD* thd, HA_CHECK_OPT* check_opt);
- int optimize(THD* thd, HA_CHECK_OPT* check_opt);
- int external_lock(THD *thd, int lock_type);
- virtual longlong get_auto_increment();
- void position(byte *record);
- ha_rows records_in_range(int inx,
- const byte *start_key,uint start_key_len,
- enum ha_rkey_function start_search_flag,
- const byte *end_key,uint end_key_len,
- enum ha_rkey_function end_search_flag);
- void update_create_info(HA_CREATE_INFO *create_info);
- int create(const char *name, register TABLE *form,
- HA_CREATE_INFO *create_info);
- int delete_table(const char *name);
- int rename_table(const char* from, const char* to);
- THR_LOCK_DATA **store_lock(THD *thd, THR_LOCK_DATA **to,
- enum thr_lock_type lock_type);
-};
-
-#define GEMOPT_FLUSH_LOG 0x00000001
-#define GEMOPT_UNBUFFERED_IO 0x00000002
-
-#define GEMINI_RECOVERY_FULL 0x00000001
-#define GEMINI_RECOVERY_NONE 0x00000002
-#define GEMINI_RECOVERY_FORCE 0x00000004
-
-#define GEM_OPTID_SPIN_RETRIES 1
-
-extern bool gemini_skip;
-extern SHOW_COMP_OPTION have_gemini;
-extern long gemini_options;
-extern long gemini_buffer_cache;
-extern long gemini_io_threads;
-extern long gemini_log_cluster_size;
-extern long gemini_locktablesize;
-extern long gemini_lock_wait_timeout;
-extern long gemini_spin_retries;
-extern long gemini_connection_limit;
-extern char *gemini_basedir;
-extern TYPELIB gemini_recovery_typelib;
-extern ulong gemini_recovery_options;
-
-bool gemini_init(void);
-bool gemini_end(void);
-bool gemini_flush_logs(void);
-int gemini_commit(THD *thd);
-int gemini_rollback(THD *thd);
-int gemini_recovery_logging(THD *thd, bool on);
-void gemini_disconnect(THD *thd);
-int gemini_rollback_to_savepoint(THD *thd);
-int gemini_parse_table_name(const char *fullname, char *dbname, char *tabname);
-int gemini_is_vst(const char *pname);
-int gemini_set_option_long(int optid, long optval);
-
-const int gemini_blocksize = BLKSIZE;
-const int gemini_recbits = DEFAULT_RECBITS;
-
-extern "C" void uttrace(void);
diff --git a/sql/ha_heap.cc b/sql/ha_heap.cc
index 13dccc2bf64..5f482bca1e8 100644
--- a/sql/ha_heap.cc
+++ b/sql/ha_heap.cc
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -33,7 +33,7 @@ const char **ha_heap::bas_ext() const
int ha_heap::open(const char *name, int mode, uint test_if_locked)
{
- uint key,part,parts,mem_per_row=0;
+ uint key,parts,mem_per_row=0;
ulong max_rows;
HP_KEYDEF *keydef;
HP_KEYSEG *seg;
@@ -48,24 +48,38 @@ int ha_heap::open(const char *name, int mode, uint test_if_locked)
for (key=0 ; key < table->keys ; key++)
{
KEY *pos=table->key_info+key;
+ KEY_PART_INFO *key_part= pos->key_part;
+ KEY_PART_INFO *key_part_end= key_part+pos->key_parts;
+
mem_per_row += (pos->key_length + (sizeof(char*) * 2));
-
+
keydef[key].keysegs=(uint) pos->key_parts;
- keydef[key].flag = (pos->flags & HA_NOSAME);
+ keydef[key].flag = (pos->flags & (HA_NOSAME | HA_NULL_ARE_EQUAL));
keydef[key].seg=seg;
-
- for (part=0 ; part < pos->key_parts ; part++)
+
+ for (; key_part != key_part_end ; key_part++, seg++)
{
- uint flag=pos->key_part[part].key_type;
+ uint flag=key_part->key_type;
+ Field *field=key_part->field;
if (!f_is_packed(flag) &&
f_packtype(flag) == (int) FIELD_TYPE_DECIMAL &&
!(flag & FIELDFLAG_BINARY))
seg->type= (int) HA_KEYTYPE_TEXT;
else
seg->type= (int) HA_KEYTYPE_BINARY;
- seg->start=(uint) pos->key_part[part].offset;
- seg->length=(uint) pos->key_part[part].length;
- seg++;
+ seg->start=(uint) key_part->offset;
+ seg->length=(uint) key_part->length;
+ if (field->null_ptr)
+ {
+ seg->null_bit=field->null_bit;
+ seg->null_pos= (uint) (field->null_ptr-
+ (uchar*) table->record[0]);
+ }
+ else
+ {
+ seg->null_bit=0;
+ seg->null_pos=0;
+ }
}
}
mem_per_row += MY_ALIGN(table->reclength+1, sizeof(char*));
@@ -77,7 +91,8 @@ int ha_heap::open(const char *name, int mode, uint test_if_locked)
table->max_rows : max_rows),
table->min_rows);
my_free((gptr) keydef,MYF(0));
- info(HA_STATUS_NO_LOCK | HA_STATUS_CONST | HA_STATUS_VARIABLE);
+ if (file)
+ info(HA_STATUS_NO_LOCK | HA_STATUS_CONST | HA_STATUS_VARIABLE);
ref_length=sizeof(HEAP_PTR);
return (!file ? errno : 0);
}
@@ -147,7 +162,7 @@ int ha_heap::index_prev(byte * buf)
table->status=error ? STATUS_NOT_FOUND: 0;
return error;
}
-
+
int ha_heap::index_first(byte * buf)
{
statistic_increment(ha_read_first_count,&LOCK_status);
@@ -227,7 +242,7 @@ int ha_heap::delete_all_rows()
int ha_heap::external_lock(THD *thd, int lock_type)
{
return 0; // No external locking
-}
+}
THR_LOCK_DATA **ha_heap::store_lock(THD *thd,
THR_LOCK_DATA **to,
@@ -247,7 +262,7 @@ THR_LOCK_DATA **ha_heap::store_lock(THD *thd,
int ha_heap::delete_table(const char *name)
{
- int error=heap_delete_all(name);
+ int error=heap_delete_table(name);
return error == ENOENT ? 0 : error;
}
@@ -272,7 +287,6 @@ ha_rows ha_heap::records_in_range(int inx,
return 10; // Good guess
}
-/* We can just delete the heap on creation */
int ha_heap::create(const char *name, TABLE *form, HA_CREATE_INFO *create_info)
diff --git a/sql/ha_heap.h b/sql/ha_heap.h
index 6b7e9c6c626..c8f29dea53c 100644
--- a/sql/ha_heap.h
+++ b/sql/ha_heap.h
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -31,11 +31,12 @@ class ha_heap: public handler
ha_heap(TABLE *table): handler(table), file(0) {}
~ha_heap() {}
const char *table_type() const { return "HEAP"; }
+ const char *index_type(uint key_number) { return "HASH"; }
const char **bas_ext() const;
ulong option_flag() const
{ return (HA_READ_RND_SAME | HA_NO_INDEX | HA_ONLY_WHOLE_INDEX |
HA_WRONG_ASCII_ORDER | HA_KEYPOS_TO_RNDPOS | HA_NO_BLOBS |
- HA_REC_NOT_IN_SEQ | HA_NO_FULLTEXT_KEY); }
+ HA_NULL_KEY | HA_REC_NOT_IN_SEQ | HA_NOT_READ_PREFIX_LAST); }
uint max_record_length() const { return HA_MAX_REC_LENGTH; }
uint max_keys() const { return MAX_KEY; }
uint max_key_parts() const { return MAX_REF_PARTS; }
diff --git a/sql/ha_innobase.cc b/sql/ha_innodb.cc
index 2cdf15ce974..4cf06dfb731 100644
--- a/sql/ha_innobase.cc
+++ b/sql/ha_innodb.cc
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & InnoDB Oy
+/* Copyright (C) 2000 MySQL AB & InnoDB 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
@@ -14,14 +14,14 @@
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 */
-
+/*
+ This file defines the InnoDB handler: the interface between MySQL and InnoDB */
+
/* TODO list for the InnoDB handler:
- Ask Monty if strings of different languages can exist in the same
database. Answer: in near future yes, but not yet.
*/
-
+
#ifdef __GNUC__
#pragma implementation // gcc: Class implementation
#endif
@@ -35,7 +35,7 @@ InnoDB */
#define MAX_ULONG_BIT ((ulong) 1 << (sizeof(ulong)*8-1))
-#include "ha_innobase.h"
+#include "ha_innodb.h"
/* We must declare this here because we undef SAFE_MUTEX below */
pthread_mutex_t innobase_mutex;
@@ -82,13 +82,19 @@ long innobase_mirrored_log_groups, innobase_log_files_in_group,
innobase_file_io_threads, innobase_lock_wait_timeout,
innobase_thread_concurrency, innobase_force_recovery;
-char *innobase_data_home_dir, *innobase_data_file_path;
+char *innobase_data_home_dir;
char *innobase_log_group_home_dir, *innobase_log_arch_dir;
char *innobase_unix_file_flush_method;
my_bool innobase_flush_log_at_trx_commit, innobase_log_archive,
- innobase_use_native_aio, innobase_fast_shutdown;
+ innobase_use_native_aio, innobase_fast_shutdown;
+
+/*
+ Set default InnoDB size to 64M, to let users use InnoDB without having
+ to specify any startup options.
+*/
-/* innobase_data_file_path=ibdata:15,idata2:1,... */
+char *innobase_data_file_path= (char*) "ibdata1:64M";
+char *internal_innobase_data_file_path=0;
/* The following counter is used to convey information to InnoDB
about server activity: in selects it is not sensible to call
@@ -220,7 +226,7 @@ convert_error_code_to_mysql(
return(HA_ERR_TO_BIG_ROW);
} else {
- dbug_assert(0);
+ DBUG_ASSERT(0);
return(-1); // Unknown error
}
@@ -260,7 +266,7 @@ innobase_mysql_print_thd(
}
if (thd->query) {
- printf("\n%.100s", thd->query);
+ printf("\n%-.100s", thd->query);
}
printf("\n");
@@ -283,7 +289,7 @@ check_trx_exists(
trx = (trx_t*) thd->transaction.all.innobase_tid;
if (trx == NULL) {
- dbug_assert(thd != NULL);
+ DBUG_ASSERT(thd != NULL);
trx = trx_allocate_for_mysql();
trx->mysql_thd = thd;
@@ -347,7 +353,7 @@ innobase_parse_data_file_paths_and_sizes(void)
ulint size;
ulint i = 0;
- str = innobase_data_file_path;
+ str = internal_innobase_data_file_path;
/* First calculate the number of data files and check syntax:
path:size[M];path:size[M]... . Note that a Windows path may
@@ -417,7 +423,7 @@ innobase_parse_data_file_paths_and_sizes(void)
/* Then store the actual values to our arrays */
- str = innobase_data_file_path;
+ str = internal_innobase_data_file_path;
i = 0;
while (*str != '\0') {
@@ -465,7 +471,7 @@ innobase_parse_data_file_paths_and_sizes(void)
&& *(str + 1) == 'a'
&& *(str + 2) == 'w') {
str += 3;
-
+
if (srv_data_file_is_raw_partition[i] == 0) {
srv_data_file_is_raw_partition[i] = SRV_OLD_RAW;
}
@@ -560,12 +566,27 @@ innobase_init(void)
/*===============*/
/* out: TRUE if error */
{
- static char current_dir[3];
int err;
bool ret;
-
+ char current_lib[3], *default_path;
+
DBUG_ENTER("innobase_init");
+ /*
+ When using the embedded server, the datadirectory is not
+ in the current directory.
+ */
+ if (mysql_embedded)
+ default_path=mysql_real_data_home;
+ else
+ {
+ /* It's better to use current lib, to keep path's short */
+ current_lib[0]=FN_CURLIB;
+ current_lib[1]=FN_LIBCHAR;
+ current_lib[2]=0;
+ default_path=current_lib;
+ }
+
if (specialflag & SPECIAL_NO_PRIOR) {
srv_set_thread_priorities = FALSE;
} else {
@@ -573,46 +594,30 @@ innobase_init(void)
srv_query_thread_priority = QUERY_PRIOR;
}
- /* Use current_dir if no paths are set */
- current_dir[0]=FN_CURLIB;
- current_dir[1]=FN_LIBCHAR;
- current_dir[2]=0;
-
- /* Set InnoDB initialization parameters according to the values
- read from MySQL .cnf file */
+ /*
+ Set InnoDB initialization parameters according to the values
+ read from MySQL .cnf file
+ */
- if (!innobase_data_file_path)
- {
- fprintf(stderr,
- "Cannot initialize InnoDB as 'innodb_data_file_path' is not set.\n"
- "If you do not want to use transactional InnoDB tables, add a line\n"
- "skip-innodb\n"
- "to the [mysqld] section of init parameters in your my.cnf\n"
- "or my.ini. If you want to use InnoDB tables, add for example,\n"
- "innodb_data_file_path = ibdata1:30M\n"
- "But to get good performance you should adjust for your hardware\n"
- "the InnoDB startup options listed in section 2 at\n"
- "http://www.innodb.com/ibman.html\n");
-
- innodb_skip=1;
- DBUG_RETURN(FALSE); // Continue without innobase
- }
+ // Make a copy of innobase_data_file_path to not modify the original
+ internal_innobase_data_file_path=my_strdup(innobase_data_file_path,
+ MYF(MY_WME));
srv_data_home = (innobase_data_home_dir ? innobase_data_home_dir :
- current_dir);
+ default_path);
srv_logs_home = (char*) "";
srv_arch_dir = (innobase_log_arch_dir ? innobase_log_arch_dir :
- current_dir);
+ default_path);
ret = innobase_parse_data_file_paths_and_sizes();
if (ret == FALSE) {
- fprintf(stderr, "InnoDB: syntax error in innodb_data_file_path\n");
+ sql_print_error("InnoDB: syntax error in innodb_data_file_path");
DBUG_RETURN(TRUE);
}
if (!innobase_log_group_home_dir)
- innobase_log_group_home_dir= current_dir;
+ innobase_log_group_home_dir= default_path;
ret = innobase_parse_log_group_home_dirs();
if (ret == FALSE) {
@@ -644,12 +649,13 @@ innobase_init(void)
srv_fast_shutdown = (ibool) innobase_fast_shutdown;
+ srv_print_verbose_log = mysql_embedded ? 0 : 1;
if (strcmp(default_charset_info->name, "latin1") == 0) {
/* Store the character ordering table to InnoDB.
For non-latin1 charsets we use the MySQL comparison
functions, and consequently we do not need to know
the ordering internally in InnoDB. */
-
+
memcpy(srv_latin1_ordering,
default_charset_info->sort_order, 256);
}
@@ -680,6 +686,7 @@ innobase_end(void)
err = innobase_shutdown_for_mysql();
hash_free(&innobase_open_tables);
+ my_free(internal_innobase_data_file_path,MYF(MY_ALLOW_ZERO_PTR));
if (err != DB_SUCCESS) {
@@ -746,7 +753,6 @@ innobase_commit(
/* Release possible statement level resources */
innobase_release_stat_resources(trx);
-
trx_mark_sql_stat_end(trx);
#ifndef DBUG_OFF
@@ -907,7 +913,7 @@ normalize_table_name(
name_ptr = ptr + 1;
- dbug_assert(ptr > name);
+ DBUG_ASSERT(ptr > name);
ptr--;
@@ -934,7 +940,7 @@ normalize_table_name(
}
/*********************************************************************
-Creates and opens a handle to a table which already exists in an Innnobase
+Creates and opens a handle to a table which already exists in an Innobase
database. */
int
@@ -986,13 +992,13 @@ ha_innobase::open(
if (NULL == ib_table) {
- fprintf(stderr,
-"InnoDB: Error: cannot find table %s from the internal data dictionary\n"
-"InnoDB: of InnoDB though the .frm file for the table exists. Maybe you\n"
-"InnoDB: have deleted and recreated InnoDB data files but have forgotten\n"
-"InnoDB: to delete the corresponding .frm files of InnoDB tables, or you\n"
-"InnoDB: have moved .frm files to another database?\n",
- norm_name);
+ sql_print_error("InnoDB error:\n\
+Cannot find table %s from the internal data dictionary\n\
+of InnoDB though the .frm file for the table exists. Maybe you\n\
+have deleted and recreated InnoDB data files but have forgotten\n\
+to delete the corresponding .frm files of InnoDB tables, or you\n\
+have moved .frm files to another database?",
+ norm_name);
free_share(share);
my_free((char*) upd_buff, MYF(0));
@@ -1020,20 +1026,22 @@ ha_innobase::open(
primary_key = 0;
key_used_on_scan = 0;
- /* MySQL allocates the buffer for ref */
+ /*
+ MySQL allocates the buffer for ref.
+ This includes all keys + one byte for each column
+ that may be NULL.
+ The ref_length must be exact as possible as
+ all reference buffers are allocated based on this.
+ */
- ref_length = table->key_info->key_length
- + table->key_info->key_parts + 10;
-
- /* One byte per key field is consumed to the SQL NULL
- info of the field; we add also 10 bytes of safety margin */
+ ref_length = table->key_info->key_length;
} else {
((row_prebuilt_t*)innobase_prebuilt)
->clust_index_was_generated = TRUE;
- ref_length = DATA_ROW_ID_LEN + 10;
-
- dbug_assert(key_used_on_scan == MAX_KEY);
+ ref_length = DATA_ROW_ID_LEN;
+
+ DBUG_ASSERT(key_used_on_scan == MAX_KEY);
}
auto_inc_counter_for_this_stat = 0;
@@ -1177,8 +1185,8 @@ innobase_mysql_cmp(
enum_field_types mysql_tp;
int ret;
- dbug_assert(a_length != UNIV_SQL_NULL);
- dbug_assert(b_length != UNIV_SQL_NULL);
+ DBUG_ASSERT(a_length != UNIV_SQL_NULL);
+ DBUG_ASSERT(b_length != UNIV_SQL_NULL);
mysql_tp = (enum_field_types) mysql_type;
@@ -1216,11 +1224,11 @@ get_innobase_type_from_mysql_type(
8 bits: this is used in ibuf and also when DATA_NOT_NULL is
ORed to the type */
- dbug_assert((ulint)FIELD_TYPE_STRING < 256);
- dbug_assert((ulint)FIELD_TYPE_VAR_STRING < 256);
- dbug_assert((ulint)FIELD_TYPE_DOUBLE < 256);
- dbug_assert((ulint)FIELD_TYPE_FLOAT < 256);
- dbug_assert((ulint)FIELD_TYPE_DECIMAL < 256);
+ DBUG_ASSERT((ulint)FIELD_TYPE_STRING < 256);
+ DBUG_ASSERT((ulint)FIELD_TYPE_VAR_STRING < 256);
+ DBUG_ASSERT((ulint)FIELD_TYPE_DOUBLE < 256);
+ DBUG_ASSERT((ulint)FIELD_TYPE_FLOAT < 256);
+ DBUG_ASSERT((ulint)FIELD_TYPE_DECIMAL < 256);
switch (field->type()) {
case FIELD_TYPE_VAR_STRING: if (field->flags & BINARY_FLAG) {
@@ -1312,7 +1320,12 @@ ha_innobase::store_key_val_for_row(
buff += key_part->length;
}
- DBUG_RETURN(buff - buff_start);
+ /*
+ We have to zero-fill the buffer to be able to compare two
+ keys to see if they are equal
+ */
+ bzero(buff, (ref_length- (uint) (buff - buff_start)));
+ return ref_length;
}
/******************************************************************
@@ -1346,7 +1359,7 @@ build_template(
} else {
/* We are building a temporary table: fetch all
columns */
-
+
templ_type = ROW_MYSQL_WHOLE_ROW;
}
}
@@ -1483,7 +1496,7 @@ ha_innobase::write_row(
row_prebuilt_t* prebuilt = (row_prebuilt_t*)innobase_prebuilt;
int error;
longlong auto_inc;
-
+
DBUG_ENTER("ha_innobase::write_row");
statistic_increment(ha_write_count, &LOCK_status);
@@ -1503,7 +1516,7 @@ ha_innobase::write_row(
/* Fetch the value the user possibly has set in the
autoincrement field */
-
+
auto_inc = table->next_number_field->val_int();
/* In replication and also otherwise the auto-inc column
@@ -1531,7 +1544,7 @@ ha_innobase::write_row(
auto-inc column */
user_thd->next_insert_id = auto_inc;
}
-
+
if (auto_inc != 0) {
/* This call will calculate the max of the
current value and the value supplied by the user, if
@@ -1550,11 +1563,11 @@ ha_innobase::write_row(
srv_conc_exit_innodb(prebuilt->trx);
if (error != DB_SUCCESS) {
-
+
error = convert_error_code_to_mysql(error);
goto func_exit;
}
-
+
dict_table_autoinc_update(prebuilt->table, auto_inc);
} else {
srv_conc_enter_innodb(prebuilt->trx);
@@ -1564,8 +1577,8 @@ ha_innobase::write_row(
error = row_lock_table_autoinc_for_mysql(
prebuilt);
if (error != DB_SUCCESS) {
- srv_conc_exit_innodb(prebuilt->trx);
-
+ srv_conc_exit_innodb(prebuilt->trx);
+
error = convert_error_code_to_mysql(
error);
goto func_exit;
@@ -1583,13 +1596,13 @@ ha_innobase::write_row(
user_thd->next_insert_id = auto_inc;
}
}
-
+
/* Set the 'in_update_remember_pos' flag to FALSE to
make sure all columns are fetched in the select done by
update_auto_increment */
prebuilt->in_update_remember_pos = FALSE;
-
+
update_auto_increment();
if (auto_inc == 0) {
@@ -1603,15 +1616,15 @@ ha_innobase::write_row(
srv_conc_exit_innodb(prebuilt->trx);
if (error != DB_SUCCESS) {
-
+
error = convert_error_code_to_mysql(error);
goto func_exit;
}
-
+
dict_table_autoinc_initialize(prebuilt->table,
auto_inc);
}
-
+
/* We have to set sql_stat_start to TRUE because
update_auto_increment has called a select, and
has reset that flag; row_insert_for_mysql has to
@@ -2074,6 +2087,24 @@ ha_innobase::index_read(
DBUG_RETURN(error);
}
+
+/*
+ The following functions works like index_read, but it find the last
+ row with the current index prefix.
+ This code is disabled until Heikki has verified that InnoDB support the
+ HA_READ_PREFIX_LAST flag and removed the HA_NOT_READ_PREFIX_LAST
+ flag from ha_innodb.h
+*/
+
+int
+ha_innobase::index_read_last(mysql_byte *buf,
+ const mysql_byte *key_ptr,
+ uint key_len)
+{
+ return index_read(buf, key_ptr, key_len, HA_READ_PREFIX_LAST);
+}
+
+
/************************************************************************
Changes the active index of a handle. */
@@ -2085,47 +2116,42 @@ ha_innobase::change_active_index(
index, even if it was internally generated by
InnoDB */
{
- row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt;
- KEY* key;
-
- statistic_increment(ha_read_key_count, &LOCK_status);
-
- DBUG_ENTER("index_read_idx");
+ row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt;
+ KEY* key;
- active_index = keynr;
+ statistic_increment(ha_read_key_count, &LOCK_status);
+ DBUG_ENTER("change_active_index");
- if (keynr != MAX_KEY && table->keys > 0) {
- key = table->key_info + active_index;
+ active_index = keynr;
- prebuilt->index = dict_table_get_index_noninline(
- prebuilt->table, key->name);
- } else {
- prebuilt->index = dict_table_get_first_index_noninline(
- prebuilt->table);
- }
+ if (keynr != MAX_KEY && table->keys > 0)
+ {
+ key = table->key_info + active_index;
- if (!prebuilt->index) {
- fprintf(stderr,
- "InnoDB: Could not find key n:o %u with name %s from dict cache\n"
- "InnoDB: for table %s\n", keynr, key->name, prebuilt->table->name);
+ prebuilt->index=dict_table_get_index_noninline(prebuilt->table, key->name);
+ 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->name, prebuilt->table->name);
+ return(1);
+ }
+ }
+ else
+ prebuilt->index = dict_table_get_first_index_noninline(prebuilt->table);
- return(1);
- }
-
- assert(prebuilt->search_tuple);
+ assert(prebuilt->search_tuple != 0);
- dtuple_set_n_fields(prebuilt->search_tuple, prebuilt->index->n_fields);
+ dtuple_set_n_fields(prebuilt->search_tuple, prebuilt->index->n_fields);
- dict_index_copy_types(prebuilt->search_tuple, prebuilt->index,
- prebuilt->index->n_fields);
+ dict_index_copy_types(prebuilt->search_tuple, prebuilt->index,
+ prebuilt->index->n_fields);
- /* Maybe MySQL changes the active index for a handle also
- during some queries, we do not know: then it is safest to build
- the template such that all columns will be fetched */
+ /* Maybe MySQL changes the active index for a handle also
+ during some queries, we do not know: then it is safest to build
+ the template such that all columns will be fetched */
- build_template(prebuilt, user_thd, table, ROW_MYSQL_WHOLE_ROW);
+ build_template(prebuilt, user_thd, table, ROW_MYSQL_WHOLE_ROW);
- return(0);
+ DBUG_RETURN(0);
}
/**************************************************************************
@@ -2176,7 +2202,7 @@ ha_innobase::general_fetch(
DBUG_ENTER("general_fetch");
srv_conc_enter_innodb(prebuilt->trx);
-
+
ret = row_search_for_mysql((byte*)buf, 0, prebuilt, match_mode,
direction);
srv_conc_exit_innodb(prebuilt->trx);
@@ -2312,7 +2338,7 @@ ha_innobase::rnd_init(
bool scan) /* in: ???????? */
{
int err;
-
+
row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt;
if (prebuilt->clust_index_was_generated) {
@@ -2381,8 +2407,9 @@ ha_innobase::rnd_pos(
row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt;
int error;
uint keynr = active_index;
-
DBUG_ENTER("rnd_pos");
+ DBUG_DUMP("key", pos, ref_stored_len);
+
statistic_increment(ha_read_rnd_count, &LOCK_status);
if (prebuilt->clust_index_was_generated) {
@@ -2397,11 +2424,15 @@ ha_innobase::rnd_pos(
}
if (error) {
+ DBUG_PRINT("error",("Got error: %ld",error));
DBUG_RETURN(error);
}
-
- error = index_read(buf, pos, ref_stored_len, HA_READ_KEY_EXACT);
+ error = index_read(buf, pos, ref_stored_len, HA_READ_KEY_EXACT);
+ if (error)
+ {
+ DBUG_PRINT("error",("Got error: %ld",error));
+ }
change_active_index(keynr);
DBUG_RETURN(error);
@@ -2436,11 +2467,11 @@ ha_innobase::position(
len = store_key_val_for_row(primary_key, (char*) ref, record);
}
- dbug_assert(len <= ref_length);
-
+ DBUG_ASSERT(len == ref_length);
ref_stored_len = len;
}
+
/*********************************************************************
Creates a table definition to an InnoDB database. */
static
@@ -2528,7 +2559,8 @@ create_index(
ind_type = 0;
- if (strcmp(key->name, "PRIMARY") == 0) {
+ if (key_num == form->primary_key)
+ {
ind_type = ind_type | DICT_CLUSTERED;
}
@@ -2600,7 +2632,7 @@ ha_innobase::create(
int error;
dict_table_t* innobase_table;
trx_t* trx;
- int primary_key_no = -1;
+ int primary_key_no;
KEY* key;
uint i;
char name2[FN_REFLEN];
@@ -2616,7 +2648,7 @@ ha_innobase::create(
/* Create the table definition in InnoDB */
- if (error = create_table_def(trx, form, norm_name)) {
+ if ((error = create_table_def(trx, form, norm_name))) {
trx_commit_for_mysql(trx);
@@ -2627,13 +2659,9 @@ ha_innobase::create(
/* Look for a primary key */
- for (i = 0; i < form->keys; i++) {
- key = form->key_info + i;
-
- if (strcmp(key->name, "PRIMARY") == 0) {
- primary_key_no = (int) i;
- }
- }
+ primary_key_no= (table->primary_key != MAX_KEY ?
+ (int) table->primary_key :
+ -1);
/* Our function row_get_mysql_key_number_for_index assumes
the primary key is always number 0, if it exists */
@@ -2704,12 +2732,12 @@ ha_innobase::create(
/* 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_flush_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP);
innobase_table = dict_table_get(norm_name, NULL);
- assert(innobase_table);
+ assert(innobase_table != 0);
/* Tell the InnoDB server that there might be work for
utility threads: */
@@ -2759,7 +2787,7 @@ ha_innobase::delete_table(
/* 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_flush_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP);
/* Tell the InnoDB server that there might be work for
@@ -2793,9 +2821,9 @@ innobase_drop_database(
char* ptr;
int error;
char namebuf[10000];
-
+
ptr = strend(path) - 2;
-
+
while (ptr >= path && *ptr != '\\' && *ptr != '/') {
ptr--;
len++;
@@ -2806,16 +2834,8 @@ innobase_drop_database(
memcpy(namebuf, ptr, len);
namebuf[len] = '/';
namebuf[len + 1] = '\0';
-
#ifdef __WIN__
- /* Put to lower case */
-
- ptr = namebuf;
-
- while (*ptr != '\0') {
- *ptr = tolower(*ptr);
- ptr++;
- }
+ casedn_str(namebuf);
#endif
trx = trx_allocate_for_mysql();
@@ -2824,7 +2844,7 @@ innobase_drop_database(
/* 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_flush_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP);
/* Tell the InnoDB server that there might be work for
@@ -2877,7 +2897,7 @@ ha_innobase::rename_table(
/* 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_flush_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP);
/* Tell the InnoDB server that there might be work for
@@ -2934,7 +2954,7 @@ ha_innobase::records_in_range(
/* Warning: since it is not sure that MySQL calls external_lock
before calling this function, the trx field in prebuilt can be
obsolete! */
-
+
active_index = keynr;
key = table->key_info + active_index;
@@ -2986,7 +3006,7 @@ ha_innobase::estimate_number_of_rows(void)
dict_index_t* index;
ulonglong estimate;
ulonglong data_file_length;
-
+
/* Warning: since it is not sure that MySQL calls external_lock
before calling this function, the trx field in prebuilt can be
obsolete! */
@@ -2994,7 +3014,7 @@ ha_innobase::estimate_number_of_rows(void)
DBUG_ENTER("info");
index = dict_table_get_first_index_noninline(prebuilt->table);
-
+
data_file_length = ((ulonglong) index->stat_n_leaf_pages)
* UNIV_PAGE_SIZE;
@@ -3005,8 +3025,8 @@ ha_innobase::estimate_number_of_rows(void)
of the formula below. */
estimate = 2 * data_file_length / dict_index_calc_min_rec_len(index);
-
- return((ha_rows) estimate);
+
+ DBUG_RETURN((ha_rows) estimate);
}
/*************************************************************************
@@ -3050,7 +3070,7 @@ ha_innobase::info(
/* Warning: since it is not sure that MySQL calls external_lock
before calling this function, the trx field in prebuilt can be
obsolete! */
-
+
ib_table = prebuilt->table;
if (flag & HA_STATUS_TIME) {
@@ -3107,11 +3127,11 @@ ha_innobase::info(
if (rec_per_key == 0) {
rec_per_key = 1;
}
-
- table->key_info[i].rec_per_key[j]
+
+ table->key_info[i].rec_per_key[j]
= rec_per_key;
}
-
+
index = dict_table_get_next_index_noninline(index);
}
}
@@ -3149,7 +3169,7 @@ ha_innobase::check(
{
row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt;
ulint ret;
-
+
ut_a(prebuilt->trx && prebuilt->trx->magic_n == TRX_MAGIC_N);
if (prebuilt->mysql_template == NULL) {
@@ -3164,7 +3184,7 @@ ha_innobase::check(
if (ret == DB_SUCCESS) {
return(HA_ADMIN_OK);
}
-
+
return(HA_ADMIN_CORRUPT);
}
@@ -3206,7 +3226,7 @@ ha_innobase::update_table_comment(
/* We assume 150 bytes of space to print info */
dict_print_info_on_foreign_keys(pos, 500, prebuilt->table);
-
+
return(str);
}
@@ -3322,6 +3342,7 @@ ha_innobase::external_lock(
& (OPTION_NOT_AUTO_COMMIT | OPTION_BEGIN))) {
innobase_commit(thd, trx);
+ thd->transaction.all.innodb_active_trans=0;
}
}
}
@@ -3464,7 +3485,7 @@ ha_innobase::get_auto_increment()
prebuilt->select_lock_type = LOCK_X;
prebuilt->trx->mysql_n_tables_locked += 1;
-
+
error=index_last(table->record[1]);
if (error) {
diff --git a/sql/ha_innobase.h b/sql/ha_innodb.h
index ec77cd1a70f..faae42575b5 100644
--- a/sql/ha_innobase.h
+++ b/sql/ha_innodb.h
@@ -1,7 +1,4 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
- && Innobase Oy
-
- -This file is modified from ha_berkeley.h of MySQL distribution-
+/* Copyright (C) 2000 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
@@ -17,13 +14,17 @@
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 is based on ha_berkeley.h of MySQL distribution
+
+ This file defines the Innodb handler: the interface between MySQL and
+ Innodb
+*/
+
#ifdef __GNUC__
#pragma interface /* gcc class implementation */
#endif
-/* This file defines the Innobase handler: the interface between MySQL and
-Innobase */
-
typedef struct st_innobase_share {
THR_LOCK lock;
pthread_mutex_t mutex;
@@ -32,11 +33,11 @@ typedef struct st_innobase_share {
} INNOBASE_SHARE;
-/* The class defining a handle to an Innobase table */
+/* The class defining a handle to an Innodb table */
class ha_innobase: public handler
{
void* innobase_prebuilt; /* (row_prebuilt_t*) prebuilt
- struct in Innobase, used to save
+ struct in Innodb, used to save
CPU */
THD* user_thd; /* the thread handle of the user
currently using the handle; this is
@@ -50,7 +51,7 @@ class ha_innobase: public handler
byte* upd_buff; /* buffer used in updates */
byte* key_val_buff; /* buffer used in converting
search key values from MySQL format
- to Innobase format */
+ to Innodb format */
uint ref_stored_len; /* length of the key value stored to
'ref' buffer of the handle, if any */
ulong int_option_flag;
@@ -78,12 +79,13 @@ class ha_innobase: public handler
HA_REC_NOT_IN_SEQ |
HA_KEYPOS_TO_RNDPOS | HA_LASTKEY_ORDER |
HA_HAVE_KEY_READ_ONLY | HA_READ_NOT_EXACT_KEY |
- HA_LONGLONG_KEYS | HA_NULL_KEY |
- HA_NOT_EXACT_COUNT | HA_NO_FULLTEXT_KEY |
+ HA_NULL_KEY |
+ HA_NOT_EXACT_COUNT |
HA_NO_WRITE_DELAYED |
HA_PRIMARY_KEY_IN_READ_INDEX |
- HA_DROP_BEFORE_CREATE |
- HA_NO_PREFIX_CHAR_KEYS),
+ HA_DROP_BEFORE_CREATE | HA_NOT_READ_PREFIX_LAST |
+ HA_NO_PREFIX_CHAR_KEYS |
+ HA_TABLE_SCAN_ON_INDEX),
last_dup_key((uint) -1),
start_of_scan(0)
{
@@ -91,6 +93,7 @@ class ha_innobase: public handler
~ha_innobase() {}
const char* table_type() const { return("InnoDB");}
+ const char *index_type(uint key_number) { return "BTREE"; }
const char** bas_ext() const;
ulong option_flag() const { return int_option_flag; }
uint max_record_length() const { return HA_MAX_REC_LENGTH; }
@@ -121,9 +124,10 @@ class ha_innobase: public handler
int index_init(uint index);
int index_end();
int index_read(byte * buf, const byte * key,
- uint key_len, enum ha_rkey_function find_flag);
+ uint key_len, enum ha_rkey_function find_flag);
int index_read_idx(byte * buf, uint index, const byte * key,
- uint key_len, enum ha_rkey_function find_flag);
+ uint key_len, enum ha_rkey_function find_flag);
+ int index_read_last(byte * buf, const byte * key, uint key_len);
int index_next(byte * buf);
int index_next_same(byte * buf, const byte *key, uint keylen);
int index_prev(byte * buf);
diff --git a/sql/ha_isam.cc b/sql/ha_isam.cc
index 746fdd2f585..4b8c40f8fe6 100644
--- a/sql/ha_isam.cc
+++ b/sql/ha_isam.cc
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -20,6 +20,7 @@
#endif
#include "mysql_priv.h"
+#ifdef HAVE_ISAM
#include <m_ctype.h>
#include <myisampack.h>
#include "ha_isam.h"
@@ -108,6 +109,15 @@ int ha_isam::index_read_idx(byte * buf, uint index, const byte * key,
return !error ? 0 : my_errno ? my_errno : -1;
}
+int ha_isam::index_read_last(byte * buf, const byte * key, uint key_len)
+{
+ statistic_increment(ha_read_key_count,&LOCK_status);
+ int error=nisam_rkey(file, buf, active_index, key, key_len,
+ HA_READ_PREFIX_LAST);
+ table->status=error ? STATUS_NOT_FOUND: 0;
+ return !error ? 0 : my_errno ? my_errno : -1;
+}
+
int ha_isam::index_next(byte * buf)
{
statistic_increment(ha_read_next_count,&LOCK_status);
@@ -123,7 +133,7 @@ int ha_isam::index_prev(byte * buf)
table->status=error ? STATUS_NOT_FOUND: 0;
return !error ? 0 : my_errno ? my_errno : HA_ERR_END_OF_FILE;
}
-
+
int ha_isam::index_first(byte * buf)
{
statistic_increment(ha_read_first_count,&LOCK_status);
@@ -235,7 +245,7 @@ int ha_isam::reset(void)
int ha_isam::external_lock(THD *thd, int lock_type)
{
return nisam_lock_database(file,lock_type);
-}
+}
THR_LOCK_DATA **ha_isam::store_lock(THD *thd,
@@ -315,7 +325,7 @@ int ha_isam::create(const char *name, register TABLE *form,
{
/* skip null fields */
if (!(temp_length= (*field)->pack_length()))
- continue; /* Skipp null-fields */
+ continue; /* Skip null-fields */
if (! found || fieldpos < minpos ||
(fieldpos == minpos && temp_length < length))
{
@@ -343,15 +353,15 @@ int ha_isam::create(const char *name, register TABLE *form,
else if (!(options & HA_OPTION_PACK_RECORD))
recinfo_pos->base.type= (int) FIELD_NORMAL;
else if (found->zero_pack())
- recinfo_pos->base.type= (int) FIELD_SKIPP_ZERO;
+ recinfo_pos->base.type= (int) FIELD_SKIP_ZERO;
else
recinfo_pos->base.type= (int) ((length <= 3 ||
(found->flags & ZEROFILL_FLAG)) ?
FIELD_NORMAL :
found->type() == FIELD_TYPE_STRING ||
found->type() == FIELD_TYPE_VAR_STRING ?
- FIELD_SKIPP_ENDSPACE :
- FIELD_SKIPP_PRESPACE);
+ FIELD_SKIP_ENDSPACE :
+ FIELD_SKIP_PRESPACE);
recinfo_pos++ ->base.length=(uint16) length;
recpos=minpos+length;
DBUG_PRINT("loop",("length: %d type: %d",
@@ -388,3 +398,4 @@ ha_rows ha_isam::records_in_range(int inx,
end_key,end_key_len,
end_search_flag);
}
+#endif /* HAVE_ISAM */
diff --git a/sql/ha_isam.h b/sql/ha_isam.h
index 5e01edcf889..4194632ddbe 100644
--- a/sql/ha_isam.h
+++ b/sql/ha_isam.h
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -33,11 +33,12 @@ class ha_isam: public handler
int_option_flag(HA_READ_NEXT | HA_READ_PREV | HA_READ_RND_SAME |
HA_KEYPOS_TO_RNDPOS | HA_READ_ORDER | HA_LASTKEY_ORDER |
HA_HAVE_KEY_READ_ONLY | HA_READ_NOT_EXACT_KEY |
- HA_LONGLONG_KEYS | HA_KEY_READ_WRONG_STR | HA_DUPP_POS |
- HA_NOT_DELETE_WITH_CACHE | HA_NO_FULLTEXT_KEY)
+ HA_KEY_READ_WRONG_STR | HA_DUPP_POS |
+ HA_NOT_DELETE_WITH_CACHE)
{}
~ha_isam() {}
const char *table_type() const { return "ISAM"; }
+ const char *index_type(uint key_number) { return "BTREE"; }
const char **bas_ext() const;
ulong option_flag() const { return int_option_flag; }
uint max_record_length() const { return HA_MAX_REC_LENGTH; }
@@ -56,6 +57,7 @@ class ha_isam: public handler
uint key_len, enum ha_rkey_function find_flag);
int index_read_idx(byte * buf, uint idx, const byte * key,
uint key_len, enum ha_rkey_function find_flag);
+ int index_read_last(byte * buf, const byte * key, uint key_len);
int index_next(byte * buf);
int index_prev(byte * buf);
int index_first(byte * buf);
@@ -80,9 +82,3 @@ class ha_isam: public handler
enum thr_lock_type lock_type);
};
-
-
-
-
-
-
diff --git a/sql/ha_isammrg.cc b/sql/ha_isammrg.cc
index dd2e4e2f723..b110ffba2f9 100644
--- a/sql/ha_isammrg.cc
+++ b/sql/ha_isammrg.cc
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -20,11 +20,12 @@
#endif
#include "mysql_priv.h"
+#ifdef HAVE_ISAM
#include <m_ctype.h>
#ifndef MASTER
-#include "../srclib/merge/mrgdef.h"
+#include "../srclib/merge/mrg_def.h"
#else
-#include "../merge/mrgdef.h"
+#include "../merge/mrg_def.h"
#endif
#include "ha_isammrg.h"
@@ -109,7 +110,7 @@ int ha_isammrg::index_prev(byte * buf)
{
return (my_errno=HA_ERR_WRONG_COMMAND);
}
-
+
int ha_isammrg::index_first(byte * buf)
{
return (my_errno=HA_ERR_WRONG_COMMAND);
@@ -178,7 +179,7 @@ int ha_isammrg::reset(void)
int ha_isammrg::external_lock(THD *thd, int lock_type)
{
return !mrg_lock_database(file,lock_type) ? 0 : my_errno ? my_errno : -1;
-}
+}
uint ha_isammrg::lock_count(void) const
{
@@ -208,3 +209,4 @@ int ha_isammrg::create(const char *name, register TABLE *form,
char buff[FN_REFLEN];
return mrg_create(fn_format(buff,name,"","",2+4+16),0);
}
+#endif /* HAVE_ISAM */
diff --git a/sql/ha_isammrg.h b/sql/ha_isammrg.h
index c8eb7dd9f69..1ee0b0e2547 100644
--- a/sql/ha_isammrg.h
+++ b/sql/ha_isammrg.h
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -32,8 +32,9 @@ class ha_isammrg: public handler
~ha_isammrg() {}
const char *table_type() const { return "MRG_ISAM"; }
const char **bas_ext() const;
- ulong option_flag() const { return HA_READ_RND_SAME | HA_KEYPOS_TO_RNDPOS
- | HA_REC_NOT_IN_SEQ | HA_NO_FULLTEXT_KEY;}
+ ulong option_flag() const { return (HA_READ_RND_SAME | HA_KEYPOS_TO_RNDPOS |
+ HA_NOT_READ_PREFIX_LAST |
+ HA_REC_NOT_IN_SEQ); }
uint max_record_length() const { return HA_MAX_REC_LENGTH; }
uint max_keys() const { return 0; }
uint max_key_parts() const { return 0; }
diff --git a/sql/ha_myisam.cc b/sql/ha_myisam.cc
index fb98708c317..78ac9f3b309 100644
--- a/sql/ha_myisam.cc
+++ b/sql/ha_myisam.cc
@@ -36,7 +36,7 @@ ulong myisam_recover_options= HA_RECOVER_NONE;
/* bits in myisam_recover_options */
const char *myisam_recover_names[] =
{ "DEFAULT", "BACKUP", "FORCE", "QUICK", NullS};
-TYPELIB myisam_recover_typelib= {array_elements(myisam_recover_names),"",
+TYPELIB myisam_recover_typelib= {array_elements(myisam_recover_names)-1,"",
myisam_recover_names};
@@ -80,9 +80,8 @@ static void mi_check_print_msg(MI_CHECK *param, const char* msg_type,
net_store_data(packet, msgbuf);
if (my_net_write(&thd->net, (char*)thd->packet.ptr(), thd->packet.length()))
- fprintf(stderr,
- "Failed on my_net_write, writing to stderr instead: %s\n",
- msgbuf);
+ sql_print_error("Failed on my_net_write, writing to stderr instead: %s\n",
+ msgbuf);
return;
}
@@ -122,6 +121,13 @@ const char **ha_myisam::bas_ext() const
{ static const char *ext[]= { ".MYD",".MYI", NullS }; return ext; }
+const char *ha_myisam::index_type(uint key_number)
+{
+ return ((table->key_info[key_number].flags & HA_FULLTEXT) ?
+ "FULLTEXT" :
+ "BTREE");
+}
+
int ha_myisam::net_read_dump(NET* net)
{
int data_fd = file->dfile;
@@ -130,7 +136,7 @@ int ha_myisam::net_read_dump(NET* net)
my_seek(data_fd, 0L, MY_SEEK_SET, MYF(MY_WME));
for(;;)
{
- uint packet_len = my_net_read(net);
+ ulong packet_len = my_net_read(net);
if (!packet_len)
break ; // end of file
if (packet_len == packet_error)
@@ -139,7 +145,7 @@ int ha_myisam::net_read_dump(NET* net)
error= -1;
goto err;
}
- if (my_write(data_fd, (byte*)net->read_pos, packet_len,
+ if (my_write(data_fd, (byte*)net->read_pos, (uint) packet_len,
MYF(MY_WME|MY_FNABP)))
{
error = errno;
@@ -374,14 +380,14 @@ int ha_myisam::restore(THD* thd, HA_CHECK_OPT *check_opt)
char* backup_dir = thd->lex.backup_dir;
char src_path[FN_REFLEN], dst_path[FN_REFLEN];
char* table_name = table->real_name;
+ int error;
+ const char* errmsg;
DBUG_ENTER("restore");
- if (!fn_format(src_path, table_name, backup_dir, MI_NAME_DEXT, 4 + 64))
+ if (fn_format_relative_to_data_home(src_path, table_name, backup_dir,
+ MI_NAME_DEXT))
DBUG_RETURN(HA_ADMIN_INVALID);
- int error = 0;
- const char* errmsg = "";
-
if (my_copy(src_path, fn_format(dst_path, table->path, "",
MI_NAME_DEXT, 4), MYF(MY_WME)))
{
@@ -404,7 +410,7 @@ int ha_myisam::restore(THD* thd, HA_CHECK_OPT *check_opt)
param.db_name = table->table_cache_key;
param.table_name = table->table_name;
param.testflag = 0;
- mi_check_print_error(&param,errmsg, errno );
+ mi_check_print_error(&param,errmsg, my_errno);
DBUG_RETURN(error);
}
}
@@ -415,41 +421,47 @@ int ha_myisam::backup(THD* thd, HA_CHECK_OPT *check_opt)
char* backup_dir = thd->lex.backup_dir;
char src_path[FN_REFLEN], dst_path[FN_REFLEN];
char* table_name = table->real_name;
- int error = 0;
- const char* errmsg = "";
-
- if (!fn_format(dst_path, table_name, backup_dir, reg_ext, 4 + 64))
- {
- errmsg = "Failed in fn_format() for .frm file: errno = %d";
- error = HA_ADMIN_INVALID;
- goto err;
- }
-
- if (my_copy(fn_format(src_path, table->path,"", reg_ext, 4),
- dst_path,
- MYF(MY_WME | MY_HOLD_ORIGINAL_MODES )))
+ int error;
+ const char *errmsg;
+ DBUG_ENTER("ha_myisam::backup");
+
+ if (fn_format_relative_to_data_home(dst_path, table_name, backup_dir,
+ reg_ext))
+ {
+ errmsg = "Failed in fn_format() for .frm file: errno = %d";
+ error = HA_ADMIN_INVALID;
+ goto err;
+ }
+
+ if (my_copy(fn_format(src_path, table->path,"", reg_ext, MY_UNPACK_FILENAME),
+ dst_path,
+ MYF(MY_WME | MY_HOLD_ORIGINAL_MODES)))
{
error = HA_ADMIN_FAILED;
errmsg = "Failed copying .frm file: errno = %d";
goto err;
}
- if (!fn_format(dst_path, table_name, backup_dir, MI_NAME_DEXT, 4 + 64))
- {
- errmsg = "Failed in fn_format() for .MYD file: errno = %d";
- error = HA_ADMIN_INVALID;
- goto err;
- }
+ /* Change extension */
+ if (!fn_format(dst_path, dst_path, "", MI_NAME_DEXT,
+ MY_REPLACE_EXT | MY_UNPACK_FILENAME | MY_SAFE_PATH))
+ {
+ errmsg = "Failed in fn_format() for .MYD file: errno = %d";
+ error = HA_ADMIN_INVALID;
+ goto err;
+ }
- if (my_copy(fn_format(src_path, table->path,"", MI_NAME_DEXT, 4),
+ if (my_copy(fn_format(src_path, table->path,"", MI_NAME_DEXT,
+ MY_UNPACK_FILENAME),
dst_path,
- MYF(MY_WME | MY_HOLD_ORIGINAL_MODES )) )
- {
- errmsg = "Failed copying .MYD file: errno = %d";
- error= HA_ADMIN_FAILED;
- goto err;
- }
- return HA_ADMIN_OK;
+ MYF(MY_WME | MY_HOLD_ORIGINAL_MODES)))
+ {
+ errmsg = "Failed copying .MYD file: errno = %d";
+ error= HA_ADMIN_FAILED;
+ goto err;
+ }
+ DBUG_RETURN(HA_ADMIN_OK);
+
err:
{
MI_CHECK param;
@@ -459,8 +471,8 @@ int ha_myisam::backup(THD* thd, HA_CHECK_OPT *check_opt)
param.db_name = table->table_cache_key;
param.table_name = table->table_name;
param.testflag = 0;
- mi_check_print_error(&param,errmsg, errno );
- return error;
+ mi_check_print_error(&param,errmsg, my_errno);
+ DBUG_RETURN(error);
}
}
@@ -537,8 +549,8 @@ int ha_myisam::repair(THD *thd, MI_CHECK &param, bool optimize)
int error=0;
uint local_testflag=param.testflag;
bool optimize_done= !optimize, statistics_done=0;
- char fixed_name[FN_REFLEN];
const char *old_proc_info=thd->proc_info;
+ char fixed_name[FN_REFLEN];
MYISAM_SHARE* share = file->s;
ha_rows rows= file->state->records;
DBUG_ENTER("ha_myisam::repair");
@@ -550,8 +562,7 @@ int ha_myisam::repair(THD *thd, MI_CHECK &param, bool optimize)
param.thd=thd;
param.tmpdir=mysql_tmpdir;
param.out_flag=0;
- VOID(fn_format(fixed_name,file->filename,"",MI_NAME_IEXT,
- 4+ (param.opt_follow_links ? 16 : 0)));
+ strmov(fixed_name,file->filename);
// Don't lock tables if we have used LOCK TABLE
if (!thd->locked_tables && mi_lock_database(file,F_WRLCK))
@@ -653,8 +664,21 @@ int ha_myisam::repair(THD *thd, MI_CHECK &param, bool optimize)
void ha_myisam::deactivate_non_unique_index(ha_rows rows)
{
- if (!(specialflag & SPECIAL_SAFE_MODE))
- mi_disable_non_unique_index(file,rows);
+ MYISAM_SHARE* share = file->s;
+ if (share->state.key_map == ((ulonglong) 1L << share->base.keys)-1)
+ {
+ if (!(specialflag & SPECIAL_SAFE_MODE))
+ if (rows==HA_POS_ERROR)
+ mi_extra(file, HA_EXTRA_NO_KEYS);
+ else
+ {
+ mi_disable_non_unique_index(file,rows);
+ mi_extra(file, HA_EXTRA_BULK_INSERT_BEGIN);
+ }
+ enable_activate_all_index=1;
+ }
+ else
+ enable_activate_all_index=0;
}
@@ -664,7 +688,10 @@ bool ha_myisam::activate_all_index(THD *thd)
MI_CHECK param;
MYISAM_SHARE* share = file->s;
DBUG_ENTER("activate_all_index");
- if (share->state.key_map != ((ulonglong) 1L << share->base.keys)-1)
+
+ mi_extra(file, HA_EXTRA_BULK_INSERT_END);
+ if (enable_activate_all_index &&
+ share->state.key_map != ((ulonglong) 1L << share->base.keys)-1)
{
const char *save_proc_info=thd->proc_info;
thd->proc_info="Creating index";
@@ -679,6 +706,8 @@ bool ha_myisam::activate_all_index(THD *thd)
error=repair(thd,param,0) != HA_ADMIN_OK;
thd->proc_info=save_proc_info;
}
+ else
+ enable_activate_all_index=1;
DBUG_RETURN(error);
}
@@ -748,6 +777,14 @@ int ha_myisam::index_read_idx(byte * buf, uint index, const byte * key,
return error;
}
+int ha_myisam::index_read_last(byte * buf, const byte * key, uint key_len)
+{
+ statistic_increment(ha_read_key_count,&LOCK_status);
+ int error=mi_rkey(file,buf,active_index, key, key_len, HA_READ_PREFIX_LAST);
+ table->status=error ? STATUS_NOT_FOUND: 0;
+ return error;
+}
+
int ha_myisam::index_next(byte * buf)
{
statistic_increment(ha_read_next_count,&LOCK_status);
@@ -829,6 +866,8 @@ void ha_myisam::position(const byte* record)
void ha_myisam::info(uint flag)
{
MI_ISAMINFO info;
+ char name_buff[FN_REFLEN];
+
(void) mi_status(file,&info,flag);
if (flag & HA_STATUS_VARIABLE)
{
@@ -858,6 +897,18 @@ void ha_myisam::info(uint flag)
raid_type=info.raid_type;
raid_chunks=info.raid_chunks;
raid_chunksize=info.raid_chunksize;
+
+ /*
+ Set data_file_name and index_file_name to point at the symlink value
+ if table is symlinked (Ie; Real name is not same as generated name)
+ */
+ data_file_name=index_file_name=0;
+ fn_format(name_buff, file->filename, "", MI_NAME_DEXT, 2);
+ if (strcmp(name_buff, info.data_file_name))
+ data_file_name=info.data_file_name;
+ strmov(fn_ext(name_buff),MI_NAME_IEXT);
+ if (strcmp(name_buff, info.index_file_name))
+ index_file_name=info.index_file_name;
}
if (flag & HA_STATUS_ERRKEY)
{
@@ -875,7 +926,8 @@ int ha_myisam::extra(enum ha_extra_function operation)
{
if (((specialflag & SPECIAL_SAFE_MODE) || (test_flags & TEST_NO_EXTRA)) &&
(operation == HA_EXTRA_WRITE_CACHE ||
- operation == HA_EXTRA_KEYREAD))
+ operation == HA_EXTRA_KEYREAD ||
+ operation == HA_EXTRA_BULK_INSERT_BEGIN))
return 0;
return mi_extra(file,operation);
}
@@ -924,10 +976,12 @@ void ha_myisam::update_create_info(HA_CREATE_INFO *create_info)
create_info->raid_chunks= raid_chunks;
create_info->raid_chunksize= raid_chunksize;
}
+ create_info->data_file_name=data_file_name;
+ create_info->index_file_name=index_file_name;
}
-int ha_myisam::create(const char *name, register TABLE *form,
+int ha_myisam::create(const char *name, register TABLE *table,
HA_CREATE_INFO *info)
{
int error;
@@ -939,20 +993,20 @@ int ha_myisam::create(const char *name, register TABLE *form,
MI_KEYDEF *keydef;
MI_COLUMNDEF *recinfo,*recinfo_pos;
MI_KEYSEG *keyseg;
- uint options=form->db_options_in_use;
+ uint options=table->db_options_in_use;
DBUG_ENTER("ha_myisam::create");
type=HA_KEYTYPE_BINARY; // Keep compiler happy
if (!(my_multi_malloc(MYF(MY_WME),
- &recinfo,(form->fields*2+2)*sizeof(MI_COLUMNDEF),
- &keydef, form->keys*sizeof(MI_KEYDEF),
+ &recinfo,(table->fields*2+2)*sizeof(MI_COLUMNDEF),
+ &keydef, table->keys*sizeof(MI_KEYDEF),
&keyseg,
- ((form->key_parts + form->keys) * sizeof(MI_KEYSEG)),
+ ((table->key_parts + table->keys) * sizeof(MI_KEYSEG)),
0)))
DBUG_RETURN(1);
- pos=form->key_info;
- for (i=0; i < form->keys ; i++, pos++)
+ pos=table->key_info;
+ for (i=0; i < table->keys ; i++, pos++)
{
keydef[i].flag= (pos->flags & (HA_NOSAME | HA_FULLTEXT));
keydef[i].seg=keyseg;
@@ -995,7 +1049,7 @@ int ha_myisam::create(const char *name, register TABLE *form,
{
keydef[i].seg[j].null_bit=field->null_bit;
keydef[i].seg[j].null_pos= (uint) (field->null_ptr-
- (uchar*) form->record[0]);
+ (uchar*) table->record[0]);
}
else
{
@@ -1013,26 +1067,26 @@ int ha_myisam::create(const char *name, register TABLE *form,
keydef[i].seg[j].flag|=HA_BLOB_PART;
/* save number of bytes used to pack length */
keydef[i].seg[j].bit_start= (uint) (field->pack_length() -
- form->blob_ptr_size);
+ table->blob_ptr_size);
}
}
keyseg+=pos->key_parts;
}
recpos=0; recinfo_pos=recinfo;
- while (recpos < (uint) form->reclength)
+ while (recpos < (uint) table->reclength)
{
Field **field,*found=0;
- minpos=form->reclength; length=0;
+ minpos=table->reclength; length=0;
- for (field=form->field ; *field ; field++)
+ for (field=table->field ; *field ; field++)
{
if ((fieldpos=(*field)->offset()) >= recpos &&
fieldpos <= minpos)
{
/* skip null fields */
if (!(temp_length= (*field)->pack_length()))
- continue; /* Skipp null-fields */
+ continue; /* Skip null-fields */
if (! found || fieldpos < minpos ||
(fieldpos == minpos && temp_length < length))
{
@@ -1058,20 +1112,20 @@ int ha_myisam::create(const char *name, register TABLE *form,
else if (!(options & HA_OPTION_PACK_RECORD))
recinfo_pos->type= (int) FIELD_NORMAL;
else if (found->zero_pack())
- recinfo_pos->type= (int) FIELD_SKIPP_ZERO;
+ recinfo_pos->type= (int) FIELD_SKIP_ZERO;
else
recinfo_pos->type= (int) ((length <= 3 ||
(found->flags & ZEROFILL_FLAG)) ?
FIELD_NORMAL :
found->type() == FIELD_TYPE_STRING ||
found->type() == FIELD_TYPE_VAR_STRING ?
- FIELD_SKIPP_ENDSPACE :
- FIELD_SKIPP_PRESPACE);
+ FIELD_SKIP_ENDSPACE :
+ FIELD_SKIP_PRESPACE);
if (found->null_ptr)
{
recinfo_pos->null_bit=found->null_bit;
recinfo_pos->null_pos= (uint) (found->null_ptr-
- (uchar*) form->record[0]);
+ (uchar*) table->record[0]);
}
else
{
@@ -1086,18 +1140,23 @@ int ha_myisam::create(const char *name, register TABLE *form,
}
MI_CREATE_INFO create_info;
bzero((char*) &create_info,sizeof(create_info));
- create_info.max_rows=form->max_rows;
- create_info.reloc_rows=form->min_rows;
+ create_info.max_rows=table->max_rows;
+ create_info.reloc_rows=table->min_rows;
create_info.auto_increment=(info->auto_increment_value ?
info->auto_increment_value -1 :
(ulonglong) 0);
- create_info.data_file_length=(ulonglong) form->max_rows*form->avg_row_length;
+ create_info.data_file_length= ((ulonglong) table->max_rows *
+ table->avg_row_length);
create_info.raid_type=info->raid_type;
- create_info.raid_chunks=info->raid_chunks ? info->raid_chunks : RAID_DEFAULT_CHUNKS;
- create_info.raid_chunksize=info->raid_chunksize ? info->raid_chunksize : RAID_DEFAULT_CHUNKSIZE;
-
- error=mi_create(fn_format(buff,name,"","",2+4+16),
- form->keys,keydef,
+ create_info.raid_chunks= (info->raid_chunks ? info->raid_chunks :
+ RAID_DEFAULT_CHUNKS);
+ create_info.raid_chunksize=(info->raid_chunksize ? info->raid_chunksize :
+ RAID_DEFAULT_CHUNKSIZE);
+ create_info.data_file_name= info->data_file_name;
+ create_info.index_file_name=info->index_file_name;
+
+ error=mi_create(fn_format(buff,name,"","",2+4),
+ table->keys,keydef,
(uint) (recinfo_pos-recinfo), recinfo,
0, (MI_UNIQUEDEF*) 0,
&create_info,
@@ -1128,7 +1187,7 @@ longlong ha_myisam::get_auto_increment()
longlong nr;
int error;
- byte key[MAX_KEY_LENGTH];
+ byte key[MI_MAX_KEY_LENGTH];
(void) extra(HA_EXTRA_KEYREAD);
key_copy(key,table,table->next_number_index,
table->next_number_key_offset);
@@ -1167,9 +1226,8 @@ int ha_myisam::ft_read(byte * buf)
thread_safe_increment(ha_read_next_count,&LOCK_status); // why ?
- error=ft_read_next((FT_DOCLIST *) ft_handler,(char*) buf);
+ error=ft_handler->please->read_next(ft_handler,(char*) buf);
table->status=error ? STATUS_NOT_FOUND: 0;
return error;
}
-
diff --git a/sql/ha_myisam.h b/sql/ha_myisam.h
index 6451e2b80ee..75655a2b505 100644
--- a/sql/ha_myisam.h
+++ b/sql/ha_myisam.h
@@ -38,24 +38,29 @@ class ha_myisam: public handler
{
MI_INFO *file;
uint int_option_flag;
+ char *data_file_name, *index_file_name;
+ bool enable_activate_all_index;
int repair(THD *thd, MI_CHECK &param, bool optimize);
public:
ha_myisam(TABLE *table): handler(table), file(0),
int_option_flag(HA_READ_NEXT | HA_READ_PREV | HA_READ_RND_SAME |
- HA_KEYPOS_TO_RNDPOS | HA_READ_ORDER | HA_LASTKEY_ORDER |
+ HA_KEYPOS_TO_RNDPOS | HA_READ_ORDER | HA_LASTKEY_ORDER |
HA_HAVE_KEY_READ_ONLY | HA_READ_NOT_EXACT_KEY |
- HA_LONGLONG_KEYS | HA_NULL_KEY |
- HA_DUPP_POS | HA_BLOB_KEY | HA_AUTO_PART_KEY)
+ HA_NULL_KEY |
+ HA_CAN_FULLTEXT | HA_CAN_SQL_HANDLER |
+ HA_DUPP_POS | HA_BLOB_KEY | HA_AUTO_PART_KEY),
+ enable_activate_all_index(1)
{}
~ha_myisam() {}
const char *table_type() const { return "MyISAM"; }
+ const char *index_type(uint key_number);
const char **bas_ext() const;
ulong option_flag() const { return int_option_flag; }
uint max_record_length() const { return HA_MAX_REC_LENGTH; }
uint max_keys() const { return MI_MAX_KEY; }
uint max_key_parts() const { return MAX_REF_PARTS; }
- uint max_key_length() const { return MAX_KEY_LENGTH; }
+ uint max_key_length() const { return MI_MAX_KEY_LENGTH; }
int open(const char *name, int mode, uint test_if_locked);
int close(void);
@@ -66,6 +71,7 @@ class ha_myisam: public handler
uint key_len, enum ha_rkey_function find_flag);
int index_read_idx(byte * buf, uint idx, const byte * key,
uint key_len, enum ha_rkey_function find_flag);
+ int index_read_last(byte * buf, const byte * key, uint key_len);
int index_next(byte * buf);
int index_prev(byte * buf);
int index_first(byte * buf);
@@ -73,9 +79,15 @@ class ha_myisam: public handler
int index_next_same(byte *buf, const byte *key, uint keylen);
int index_end() { ft_handler=NULL; return 0; }
int ft_init()
- { if(!ft_handler) return 1; ft_reinit_search(ft_handler); return 0; }
- void *ft_init_ext(uint inx,const byte *key, uint keylen, bool presort)
- { return ft_init_search(file,inx,(byte*) key,keylen,presort); }
+ {
+ if (!ft_handler)
+ return 1;
+ ft_handler->please->reinit_search(ft_handler);
+ return 0;
+ }
+ FT_INFO *ft_init_ext(uint mode, uint inx,const byte *key, uint keylen,
+ bool presort)
+ { return ft_init_search(mode, file,inx,(byte*) key,keylen,presort); }
int ft_read(byte *buf);
int rnd_init(bool scan=1);
int rnd_next(byte *buf);
diff --git a/sql/ha_myisammrg.cc b/sql/ha_myisammrg.cc
index 9499c42fdc9..63a23fb708f 100644
--- a/sql/ha_myisammrg.cc
+++ b/sql/ha_myisammrg.cc
@@ -23,9 +23,9 @@
#include <m_ctype.h>
#include "ha_myisammrg.h"
#ifndef MASTER
-#include "../srclib/myisammrg/mymrgdef.h"
+#include "../srclib/myisammrg/myrg_def.h"
#else
-#include "../myisammrg/mymrgdef.h"
+#include "../myisammrg/myrg_def.h"
#endif
/*****************************************************************************
@@ -38,10 +38,15 @@ const char **ha_myisammrg::bas_ext() const
int ha_myisammrg::open(const char *name, int mode, uint test_if_locked)
{
char name_buff[FN_REFLEN];
+ DBUG_PRINT("info", ("ha_myisammrg::open"));
if (!(file=myrg_open(fn_format(name_buff,name,"","",2 | 4), mode,
test_if_locked)))
+ {
+ DBUG_PRINT("info", ("ha_myisammrg::open exit %d", my_errno));
return (my_errno ? my_errno : -1);
-
+ }
+ DBUG_PRINT("info", ("ha_myisammrg::open myrg_extrafunc..."))
+ myrg_extrafunc(file, &query_cache_invalidate_by_MyISAM_filename);
if (!(test_if_locked == HA_OPEN_WAIT_IF_LOCKED ||
test_if_locked == HA_OPEN_ABORT_IF_LOCKED))
myrg_extra(file,HA_EXTRA_NO_WAIT_LOCK);
@@ -66,7 +71,13 @@ int ha_myisammrg::close(void)
int ha_myisammrg::write_row(byte * buf)
{
- return (my_errno=HA_ERR_WRONG_COMMAND);
+ statistic_increment(ha_write_count,&LOCK_status);
+ if (table->time_stamp)
+ update_timestamp(buf+table->time_stamp-1);
+ if (table->next_number_field && buf == table->record[0])
+ return (my_errno=HA_ERR_WRONG_COMMAND);
+ // update_auto_increment(); - [phi] have to check this before allowing it
+ return myrg_write(file,buf);
}
int ha_myisammrg::update_row(const byte * old_data, byte * new_data)
@@ -101,6 +112,15 @@ int ha_myisammrg::index_read_idx(byte * buf, uint index, const byte * key,
return error;
}
+int ha_myisammrg::index_read_last(byte * buf, const byte * key, uint key_len)
+{
+ statistic_increment(ha_read_key_count,&LOCK_status);
+ int error=myrg_rkey(file,buf,active_index, key, key_len,
+ HA_READ_PREFIX_LAST);
+ table->status=error ? STATUS_NOT_FOUND: 0;
+ return error;
+}
+
int ha_myisammrg::index_next(byte * buf)
{
statistic_increment(ha_read_next_count,&LOCK_status);
@@ -185,6 +205,11 @@ void ha_myisammrg::info(uint flag)
int ha_myisammrg::extra(enum ha_extra_function operation)
{
+ /* As this is just a mapping, we don't have to force the underlying
+ tables to be closed */
+ if (operation == HA_EXTRA_FORCE_REOPEN ||
+ operation == HA_EXTRA_PREPARE_FOR_DELETE)
+ return 0;
return myrg_extra(file,operation);
}
@@ -221,6 +246,7 @@ THR_LOCK_DATA **ha_myisammrg::store_lock(THD *thd,
void ha_myisammrg::update_create_info(HA_CREATE_INFO *create_info)
{
+ // [phi] auto_increment stuff is missing (but currently not needed)
DBUG_ENTER("ha_myisammrg::update_create_info");
if (!(create_info->used_fields & HA_CREATE_USED_UNION))
{
@@ -231,7 +257,7 @@ void ha_myisammrg::update_create_info(HA_CREATE_INFO *create_info)
for (table=file->open_tables ; table != file->end_table ; table++)
{
- char *name=table->table->s->filename;
+ char *name=table->table->filename;
char buff[FN_REFLEN];
TABLE_LIST *ptr;
if (!(ptr = (TABLE_LIST *) thd->calloc(sizeof(TABLE_LIST))))
@@ -245,6 +271,10 @@ void ha_myisammrg::update_create_info(HA_CREATE_INFO *create_info)
}
*create_info->merge_list.next=0;
}
+ if (!(create_info->used_fields & HA_CREATE_USED_INSERT_METHOD))
+ {
+ create_info->merge_insert_method = file->merge_insert_method;
+ }
DBUG_VOID_RETURN;
err:
@@ -267,18 +297,25 @@ int ha_myisammrg::create(const char *name, register TABLE *form,
*pos++= tables->real_name;
*pos=0;
DBUG_RETURN(myrg_create(fn_format(buff,name,"","",2+4+16),
- (const char **) table_names, (my_bool) 0));
+ (const char **) table_names,
+ create_info->merge_insert_method,
+ (my_bool) 0));
}
void ha_myisammrg::append_create_info(String *packet)
{
char buff[FN_REFLEN];
+ if (file->merge_insert_method != MERGE_INSERT_DISABLED)
+ {
+ packet->append(" INSERT_METHOD=",15);
+ packet->append(get_type(&merge_insert_method,file->merge_insert_method-1));
+ }
packet->append(" UNION=(",8);
MYRG_TABLE *table,*first;
for (first=table=file->open_tables ; table != file->end_table ; table++)
{
- char *name=table->table->s->filename;
+ char *name=table->table->filename;
fn_format(buff,name,"","",3);
if (table != first)
packet->append(',');
diff --git a/sql/ha_myisammrg.h b/sql/ha_myisammrg.h
index b97baa0703c..2ab3a807543 100644
--- a/sql/ha_myisammrg.h
+++ b/sql/ha_myisammrg.h
@@ -35,10 +35,10 @@ class ha_myisammrg: public handler
ulong option_flag() const
{ return (HA_REC_NOT_IN_SEQ | HA_READ_NEXT |
HA_READ_PREV | HA_READ_RND_SAME |
- HA_HAVE_KEY_READ_ONLY | HA_NO_FULLTEXT_KEY |
+ HA_HAVE_KEY_READ_ONLY |
HA_KEYPOS_TO_RNDPOS | HA_READ_ORDER |
HA_LASTKEY_ORDER | HA_READ_NOT_EXACT_KEY |
- HA_LONGLONG_KEYS | HA_NULL_KEY | HA_BLOB_KEY); }
+ HA_NULL_KEY | HA_BLOB_KEY); }
uint max_record_length() const { return HA_MAX_REC_LENGTH; }
uint max_keys() const { return MI_MAX_KEY; }
uint max_key_parts() const { return MAX_REF_PARTS; }
@@ -55,6 +55,7 @@ class ha_myisammrg: public handler
uint key_len, enum ha_rkey_function find_flag);
int index_read_idx(byte * buf, uint idx, const byte * key,
uint key_len, enum ha_rkey_function find_flag);
+ int index_read_last(byte * buf, const byte * key, uint key_len);
int index_next(byte * buf);
int index_prev(byte * buf);
int index_first(byte * buf);
@@ -74,4 +75,5 @@ class ha_myisammrg: public handler
enum thr_lock_type lock_type);
void update_create_info(HA_CREATE_INFO *create_info);
void append_create_info(String *packet);
+ MYRG_INFO *myrg_info() { return file; }
};
diff --git a/sql/handler.cc b/sql/handler.cc
index 5a713bccc1e..8447797442c 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -25,7 +25,7 @@
#include "ha_heap.h"
#include "ha_myisam.h"
#include "ha_myisammrg.h"
-#ifndef NO_ISAM
+#ifdef HAVE_ISAM
#include "ha_isam.h"
#include "ha_isammrg.h"
#endif
@@ -33,10 +33,7 @@
#include "ha_berkeley.h"
#endif
#ifdef HAVE_INNOBASE_DB
-#include "ha_innobase.h"
-#endif
-#ifdef HAVE_GEMINI_DB
-#include "ha_gemini.h"
+#include "ha_innodb.h"
#endif
#include <myisampack.h>
#include <errno.h>
@@ -48,6 +45,7 @@ static int NEAR_F delete_file(const char *name,const char *ext,int extflag);
ulong ha_read_count, ha_write_count, ha_delete_count, ha_update_count,
ha_read_key_count, ha_read_next_count, ha_read_prev_count,
ha_read_first_count, ha_read_last_count,
+ ha_commit_count, ha_rollback_count,
ha_read_rnd_count, ha_read_rnd_next_count;
const char *ha_table_type[] = {
@@ -78,21 +76,15 @@ enum db_type ha_checktype(enum db_type database_type)
return(berkeley_skip ? DB_TYPE_MYISAM : database_type);
#endif
#ifdef HAVE_INNOBASE_DB
- case DB_TYPE_INNOBASE:
+ case DB_TYPE_INNODB:
return(innodb_skip ? DB_TYPE_MYISAM : database_type);
#endif
-#ifdef HAVE_GEMINI_DB
- case DB_TYPE_GEMINI:
- return(gemini_skip ? DB_TYPE_MYISAM : database_type);
-#endif
#ifndef NO_HASH
case DB_TYPE_HASH:
#endif
-#ifndef NO_MERGE
- case DB_TYPE_MRG_ISAM:
-#endif
-#ifndef NO_ISAM
+#ifdef HAVE_ISAM
case DB_TYPE_ISAM:
+ case DB_TYPE_MRG_ISAM:
#endif
case DB_TYPE_HEAP:
case DB_TYPE_MYISAM:
@@ -111,11 +103,9 @@ handler *get_new_handler(TABLE *table, enum db_type db_type)
#ifndef NO_HASH
return new ha_hash(table);
#endif
-#ifndef NO_MERGE
+#ifdef HAVE_ISAM
case DB_TYPE_MRG_ISAM:
return new ha_isammrg(table);
-#endif
-#ifndef NO_ISAM
case DB_TYPE_ISAM:
return new ha_isam(table);
#endif
@@ -124,13 +114,9 @@ handler *get_new_handler(TABLE *table, enum db_type db_type)
return new ha_berkeley(table);
#endif
#ifdef HAVE_INNOBASE_DB
- case DB_TYPE_INNOBASE:
+ case DB_TYPE_INNODB:
return new ha_innobase(table);
#endif
-#ifdef HAVE_GEMINI_DB
- case DB_TYPE_GEMINI:
- return new ha_gemini(table);
-#endif
case DB_TYPE_HEAP:
return new ha_heap(table);
case DB_TYPE_MYISAM:
@@ -166,17 +152,6 @@ int ha_init()
have_innodb=SHOW_OPTION_DISABLED;
}
#endif
-#ifdef HAVE_GEMINI_DB
- if (!gemini_skip)
- {
- if (gemini_init())
- return -1;
- if (!gemini_skip) // If we couldn't use handler
- opt_using_transactions=1;
- else
- have_gemini=SHOW_OPTION_DISABLED;
- }
-#endif
return 0;
}
@@ -186,14 +161,14 @@ int ha_init()
int ha_panic(enum ha_panic_function flag)
{
int error=0;
-#ifndef NO_MERGE
- error|=mrg_panic(flag);
-#endif
#ifndef NO_HASH
error|=h_panic(flag); /* fix hash */
#endif
- error|=heap_panic(flag);
+#ifdef HAVE_ISAM
+ error|=mrg_panic(flag);
error|=nisam_panic(flag);
+#endif
+ error|=heap_panic(flag);
error|=mi_panic(flag);
error|=myrg_panic(flag);
#ifdef HAVE_BERKELEY_DB
@@ -204,10 +179,6 @@ int ha_panic(enum ha_panic_function flag)
if (!innodb_skip)
error|=innobase_end();
#endif
-#ifdef HAVE_GEMINI_DB
- if (!gemini_skip)
- error|=gemini_end();
-#endif
return error;
} /* ha_panic */
@@ -225,12 +196,6 @@ void ha_close_connection(THD* thd)
if (!innodb_skip)
innobase_close_connection(thd);
#endif
-#ifdef HAVE_GEMINI_DB
- if (!gemini_skip && thd->gemini.context)
- {
- gemini_disconnect(thd);
- }
-#endif /* HAVE_GEMINI_DB */
}
/*
@@ -306,6 +271,7 @@ int ha_commit_trans(THD *thd, THD_TRANS* trans)
#ifdef USING_TRANSACTIONS
if (opt_using_transactions)
{
+ bool operation_done=0;
/* Update the binary log if we have cached some queries */
if (trans == &thd->transaction.all && mysql_bin_log.is_open() &&
my_b_tell(&thd->transaction.trans_log))
@@ -335,25 +301,18 @@ int ha_commit_trans(THD *thd, THD_TRANS* trans)
error=1;
}
trans->innodb_active_trans=0;
- }
-#endif
-#ifdef HAVE_GEMINI_DB
- /* Commit the transaction in behalf of the commit statement
- or if we're in auto-commit mode */
- if((trans == &thd->transaction.all) ||
- (!(thd->options & (OPTION_NOT_AUTO_COMMIT | OPTION_BEGIN))))
- {
- error=gemini_commit(thd);
- if (error)
+ if (trans == &thd->transaction.all)
{
- my_error(ER_ERROR_DURING_COMMIT, MYF(0), error);
- error=1;
+ query_cache.invalidate(Query_cache_table::INNODB);
+ operation_done=1;
}
}
#endif
if (error && trans == &thd->transaction.all && mysql_bin_log.is_open())
sql_print_error("Error: Got error during commit; Binlog is not up to date!");
thd->tx_isolation=thd->session_tx_isolation;
+ if (operation_done)
+ statistic_increment(ha_commit_count,&LOCK_status);
}
#endif // using transactions
DBUG_RETURN(error);
@@ -367,6 +326,7 @@ int ha_rollback_trans(THD *thd, THD_TRANS *trans)
#ifdef USING_TRANSACTIONS
if (opt_using_transactions)
{
+ bool operation_done=0;
#ifdef HAVE_BERKELEY_DB
if (trans->bdb_tid)
{
@@ -376,6 +336,7 @@ int ha_rollback_trans(THD *thd, THD_TRANS *trans)
error=1;
}
trans->bdb_tid=0;
+ operation_done=1;
}
#endif
#ifdef HAVE_INNOBASE_DB
@@ -387,18 +348,7 @@ int ha_rollback_trans(THD *thd, THD_TRANS *trans)
error=1;
}
trans->innodb_active_trans=0;
- }
-#endif
-#ifdef HAVE_GEMINI_DB
- if((trans == &thd->transaction.stmt) &&
- (thd->options & (OPTION_NOT_AUTO_COMMIT | OPTION_BEGIN)))
- error = gemini_rollback_to_savepoint(thd);
- else
- error=gemini_rollback(thd);
- if (error)
- {
- my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), error);
- error=1;
+ operation_done=1;
}
#endif
if (trans == &thd->transaction.all)
@@ -406,22 +356,13 @@ int ha_rollback_trans(THD *thd, THD_TRANS *trans)
WRITE_CACHE, (my_off_t) 0, 0, 1);
thd->transaction.trans_log.end_of_file= max_binlog_cache_size;
thd->tx_isolation=thd->session_tx_isolation;
+ if (operation_done)
+ statistic_increment(ha_rollback_count,&LOCK_status);
}
#endif /* USING_TRANSACTIONS */
DBUG_RETURN(error);
}
-void ha_set_spin_retries(uint retries)
-{
-#ifdef HAVE_GEMINI_DB
- if (!gemini_skip)
- {
- gemini_set_option_long(GEM_OPTID_SPIN_RETRIES, retries);
- }
-#endif /* HAVE_GEMINI_DB */
-}
-
-
bool ha_flush_logs()
{
bool result=0;
@@ -450,7 +391,7 @@ int ha_delete_table(enum db_type table_type, const char *path)
delete file;
return error;
}
-
+
void ha_store_ptr(byte *buff, uint pack_length, my_off_t pos)
{
switch (pack_length) {
@@ -537,9 +478,8 @@ int handler::ha_open(const char *name, int mode, int test_if_locked)
{
if (table->db_options_in_use & HA_OPTION_READ_ONLY_DATA)
table->db_stat|=HA_READ_ONLY;
- }
- if (!error)
- {
+ (void) extra(HA_EXTRA_NO_READCHECK); // Not needed in SQL
+
if (!alloc_root_inited(&table->mem_root)) // If temporary table
ref=(byte*) sql_alloc(ALIGN_SIZE(ref_length)*2);
else
@@ -585,17 +525,36 @@ int handler::analyze(THD* thd, HA_CHECK_OPT* check_opt)
return HA_ADMIN_NOT_IMPLEMENTED;
}
- /* Read first row from a table */
+/*
+ Read first row (only) from a table
+ This is never called for InnoDB or BDB tables, as these table types
+ has the HA_NOT_EXACT_COUNT set.
+*/
-int handler::rnd_first(byte * buf)
+int handler::read_first_row(byte * buf, uint primary_key)
{
register int error;
- DBUG_ENTER("handler::rnd_first");
+ DBUG_ENTER("handler::read_first_row");
statistic_increment(ha_read_first_count,&LOCK_status);
- (void) rnd_init();
- while ((error= rnd_next(buf)) == HA_ERR_RECORD_DELETED) ;
- (void) rnd_end();
+
+ /*
+ If there is very few deleted rows in the table, find the first row by
+ scanning the table.
+ */
+ if (deleted < 10 || primary_key >= MAX_KEY)
+ {
+ (void) rnd_init();
+ while ((error= rnd_next(buf)) == HA_ERR_RECORD_DELETED) ;
+ (void) rnd_end();
+ }
+ else
+ {
+ /* Find the first row through the primary key */
+ (void) index_init(primary_key);
+ error=index_first(buf);
+ (void) index_end();
+ }
DBUG_RETURN(error);
}
@@ -611,7 +570,7 @@ int handler::restart_rnd_next(byte *buf, byte *pos)
}
- /* Set a timestamp in record */
+/* Set a timestamp in record */
void handler::update_timestamp(byte *record)
{
@@ -627,9 +586,10 @@ void handler::update_timestamp(byte *record)
return;
}
- /* Updates field with field_type NEXT_NUMBER according to following:
- ** if field = 0 change field to the next free key in database.
- */
+/*
+ Updates field with field_type NEXT_NUMBER according to following:
+ if field = 0 change field to the next free key in database.
+*/
void handler::update_auto_increment()
{
@@ -812,22 +772,6 @@ int handler::rename_table(const char * from, const char * to)
DBUG_RETURN(0);
}
-int ha_commit_rename(THD *thd)
-{
- int error=0;
-#ifdef HAVE_GEMINI_DB
- /* Gemini needs to commit the rename; otherwise a rollback will change
- ** the table names back internally but the physical files will still
- ** have the new names.
- */
- if (ha_commit_stmt(thd))
- error= -1;
- if (ha_commit(thd))
- error= -1;
-#endif
- return error;
-}
-
/* Tell the handler to turn on or off logging to the handler's
recovery log
*/
@@ -836,14 +780,6 @@ int ha_recovery_logging(THD *thd, bool on)
int error=0;
DBUG_ENTER("ha_recovery_logging");
-#ifdef USING_TRANSACTIONS
- if (opt_using_transactions)
- {
-#ifdef HAVE_GEMINI_DB
- error = gemini_recovery_logging(thd, on);
-#endif
- }
-#endif
DBUG_RETURN(error);
}
@@ -863,8 +799,10 @@ int handler::index_next_same(byte *buf, const byte *key, uint keylen)
/*
- The following is only needed if we would like to use the database
- for internal temporary tables
+ This is called to delete all rows in a table
+ If the handler don't support this, then this function will
+ return HA_ERR_WRONG_COMMAND and MySQL will delete the rows one
+ by one.
*/
int handler::delete_all_rows()
@@ -897,14 +835,16 @@ int ha_create_table(const char *name, HA_CREATE_INFO *create_info,
}
error=table.file->create(name,&table,create_info);
VOID(closefrm(&table));
- if (error) {
- if (table.db_type == DB_TYPE_INNOBASE) {
+ if (error)
+ {
+ if (table.db_type == DB_TYPE_INNODB)
+ {
/* Creation of InnoDB table cannot fail because of an OS error:
put error as the number */
my_error(ER_CANT_CREATE_TABLE,MYF(ME_BELL+ME_WAITTANG),name,error);
- } else {
- my_error(ER_CANT_CREATE_TABLE,MYF(ME_BELL+ME_WAITTANG),name,my_errno);
}
+ else
+ my_error(ER_CANT_CREATE_TABLE,MYF(ME_BELL+ME_WAITTANG),name,my_errno);
}
DBUG_RETURN(error != 0);
}
@@ -922,5 +862,5 @@ static int NEAR_F delete_file(const char *name,const char *ext,int extflag)
{
char buff[FN_REFLEN];
VOID(fn_format(buff,name,"",ext,extflag | 4));
- return(my_delete(buff,MYF(MY_WME)));
+ return(my_delete_with_symlink(buff,MYF(MY_WME)));
}
diff --git a/sql/handler.h b/sql/handler.h
index e4cac60ed67..b083465afc5 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -21,11 +21,13 @@
#pragma interface /* gcc class implementation */
#endif
+#include <ft_global.h>
+
#ifndef NO_HASH
#define NO_HASH /* Not yet implemented */
#endif
-#if defined(HAVE_BERKELEY_DB) || defined(HAVE_INNOBASE_DB) || defined(HAVE_GEMINI_DB)
+#if defined(HAVE_BERKELEY_DB) || defined(HAVE_INNOBASE_DB)
#define USING_TRANSACTIONS
#endif
@@ -40,25 +42,21 @@
#define HA_ADMIN_INVALID -5
/* Bits in bas_flag to show what database can do */
-
#define HA_READ_NEXT 1 /* Read next record with same key */
#define HA_READ_PREV 2 /* Read prev. record with same key */
#define HA_READ_ORDER 4 /* Read through record-keys in order */
#define HA_READ_RND_SAME 8 /* Read RND-record to KEY-record
(To update with RND-read) */
#define HA_KEYPOS_TO_RNDPOS 16 /* ha_info gives pos to record */
-#define HA_LASTKEY_ORDER 32 /* Next record gives next record
- according last record read (even
- if database is updated after read) */
+#define HA_TABLE_SCAN_ON_INDEX 32 /* No separate data/index file */
#define HA_REC_NOT_IN_SEQ 64 /* ha_info don't return recnumber;
It returns a position to ha_r_rnd */
#define HA_ONLY_WHOLE_INDEX 128 /* Can't use part key searches */
-#define HA_RSAME_NO_INDEX 256 /* RSAME can't restore index */
+#define HA_NOT_READ_PREFIX_LAST 256 /* RSAME can't restore index */
#define HA_WRONG_ASCII_ORDER 512 /* Can't use sorting through key */
#define HA_HAVE_KEY_READ_ONLY 1024 /* Can read only keys (no record) */
#define HA_READ_NOT_EXACT_KEY 2048 /* Can read record after/before key */
#define HA_NO_INDEX 4096 /* No index needed for next/prev */
-#define HA_LONGLONG_KEYS 8192 /* Can have longlong as key */
#define HA_KEY_READ_WRONG_STR 16384 /* keyread returns converted strings */
#define HA_NULL_KEY 32768 /* One can have keys with NULL */
#define HA_DUPP_POS 65536 /* ha_position() gives dupp row */
@@ -74,7 +72,15 @@
#define HA_NOT_DELETE_WITH_CACHE (HA_NOT_READ_AFTER_KEY*2)
#define HA_NO_TEMP_TABLES (HA_NOT_DELETE_WITH_CACHE*2)
#define HA_NO_PREFIX_CHAR_KEYS (HA_NO_TEMP_TABLES*2)
-#define HA_NO_FULLTEXT_KEY (HA_NO_PREFIX_CHAR_KEYS*2)
+#define HA_CAN_FULLTEXT (HA_NO_PREFIX_CHAR_KEYS*2)
+#define HA_CAN_SQL_HANDLER (HA_CAN_FULLTEXT*2)
+
+/* Old not used flags */
+/*
+ Next record gives next record according last record read (even
+ if database is updated after read)
+*/
+#define HA_LASTKEY_ORDER 0
/* Parameters for open() (in register form->filestat) */
/* HA_GET_INFO does an implicit HA_ABORT_IF_LOCKED */
@@ -93,7 +99,7 @@
/* Error on write which is recoverable (Key exist) */
-#define HA_WRITE_SKIPP 121 /* Duplicate key on write */
+#define HA_WRITE_SKIP 121 /* Duplicate key on write */
#define HA_READ_CHECK 123 /* Update with is recoverable */
#define HA_CANT_DO_THAT 131 /* Databasehandler can't do it */
@@ -111,23 +117,27 @@ enum db_type { DB_TYPE_UNKNOWN=0,DB_TYPE_DIAB_ISAM=1,
DB_TYPE_HASH,DB_TYPE_MISAM,DB_TYPE_PISAM,
DB_TYPE_RMS_ISAM, DB_TYPE_HEAP, DB_TYPE_ISAM,
DB_TYPE_MRG_ISAM, DB_TYPE_MYISAM, DB_TYPE_MRG_MYISAM,
- DB_TYPE_BERKELEY_DB, DB_TYPE_INNOBASE, DB_TYPE_GEMINI,
+ DB_TYPE_BERKELEY_DB, DB_TYPE_INNODB, DB_TYPE_GEMINI,
DB_TYPE_DEFAULT };
-enum row_type { ROW_TYPE_DEFAULT, ROW_TYPE_FIXED, ROW_TYPE_DYNAMIC,
- ROW_TYPE_COMPRESSED };
+enum row_type { ROW_TYPE_NOT_USED=-1, ROW_TYPE_DEFAULT, ROW_TYPE_FIXED,
+ ROW_TYPE_DYNAMIC, ROW_TYPE_COMPRESSED};
/* struct to hold information about the table that should be created */
/* Bits in used_fields */
-#define HA_CREATE_USED_AUTO 1
-#define HA_CREATE_USED_RAID 2
-#define HA_CREATE_USED_UNION 4
+#define HA_CREATE_USED_AUTO 1
+#define HA_CREATE_USED_RAID 2
+#define HA_CREATE_USED_UNION 4
+#define HA_CREATE_USED_INSERT_METHOD 8
+#define HA_CREATE_USED_MIN_ROWS 16
+#define HA_CREATE_USED_MAX_ROWS 32
+#define HA_CREATE_USED_AVG_ROW_LENGTH 64
+#define HA_CREATE_USED_PACK_KEYS 128
typedef struct st_thd_trans {
void *bdb_tid;
void *innobase_tid;
- void *gemini_tid;
bool innodb_active_trans;
} THD_TRANS;
@@ -143,6 +153,7 @@ typedef struct st_ha_create_information
ulonglong max_rows,min_rows;
ulonglong auto_increment_value;
char *comment,*password;
+ char *data_file_name, *index_file_name;
char *create_statement;
uint options; /* OR of HA_CREATE_ options */
uint raid_type,raid_chunks;
@@ -150,6 +161,7 @@ typedef struct st_ha_create_information
bool if_not_exists;
ulong used_fields;
SQL_LIST merge_list;
+ uint merge_insert_method;
} HA_CREATE_INFO;
@@ -201,7 +213,7 @@ public:
time_t check_time;
time_t update_time;
ulong mean_rec_length; /* physical reclength */
- void *ft_handler;
+ FT_INFO *ft_handler;
bool auto_increment_column_changed;
handler(TABLE *table_arg) : table(table_arg),active_index(MAX_REF_PARTS),
@@ -227,6 +239,7 @@ public:
virtual bool has_transactions(){ return 0;}
virtual uint extra_rec_buf_length() { return 0; }
virtual ha_rows estimate_number_of_rows() { return records+EXTRA_RECORDS; }
+ virtual const char *index_type(uint key_number) { return "";}
virtual int index_init(uint idx) { active_index=idx; return 0;}
virtual int index_end() {return 0; }
@@ -238,7 +251,7 @@ public:
virtual int update_row(const byte * old_data, byte * new_data)=0;
virtual int delete_row(const byte * buf)=0;
virtual int index_read(byte * buf, const byte * key,
- uint key_len, enum ha_rkey_function find_flag)=0;
+ uint key_len, enum ha_rkey_function find_flag)=0;
virtual int index_read_idx(byte * buf, uint index, const byte * key,
uint key_len, enum ha_rkey_function find_flag)=0;
virtual int index_next(byte * buf)=0;
@@ -246,17 +259,21 @@ public:
virtual int index_first(byte * buf)=0;
virtual int index_last(byte * buf)=0;
virtual int index_next_same(byte *buf, const byte *key, uint keylen);
+ virtual int index_read_last(byte * buf, const byte * key, uint key_len)
+ {
+ return (my_errno=HA_ERR_WRONG_COMMAND);
+ }
virtual int ft_init()
{ return -1; }
- virtual void *ft_init_ext(uint inx,const byte *key, uint keylen,
+ virtual FT_INFO *ft_init_ext(uint mode,uint inx,const byte *key, uint keylen,
bool presort)
- { return (void *)NULL; }
+ { return NULL; }
virtual int ft_read(byte *buf) { return -1; }
virtual int rnd_init(bool scan=1)=0;
virtual int rnd_end() { return 0; }
virtual int rnd_next(byte *buf)=0;
virtual int rnd_pos(byte * buf, byte *pos)=0;
- virtual int rnd_first(byte *buf);
+ virtual int read_first_row(byte *buf, uint primary_key);
virtual int restart_rnd_next(byte *buf, byte *pos);
virtual ha_rows records_in_range(int inx,
const byte *start_key,uint start_key_len,
@@ -318,17 +335,6 @@ public:
enum thr_lock_type lock_type)=0;
};
-#ifdef HAVE_GEMINI_DB
-struct st_gemini
-{
- void *context;
- unsigned long savepoint;
- bool needSavepoint;
- uint tx_isolation;
- uint lock_count;
-};
-#endif
-
/* Some extern variables used with handlers */
extern const char *ha_row_type[];
@@ -340,6 +346,8 @@ extern TYPELIB ha_table_typelib, tx_isolation_typelib;
#define ha_commit(thd) (ha_commit_trans((thd), &((thd)->transaction.all)))
#define ha_rollback(thd) (ha_rollback_trans((thd), &((thd)->transaction.all)))
+#define ha_supports_generate(T) (T != DB_TYPE_INNODB)
+
handler *get_new_handler(TABLE *table, enum db_type db_type);
my_off_t ha_get_ptr(byte *ptr, uint pack_length);
void ha_store_ptr(byte *buff, uint pack_length, my_off_t pos);
@@ -362,5 +370,4 @@ int ha_rollback_trans(THD *thd, THD_TRANS *trans);
int ha_autocommit_or_rollback(THD *thd, int error);
void ha_set_spin_retries(uint retries);
bool ha_flush_logs(void);
-int ha_commit_rename(THD *thd);
int ha_recovery_logging(THD *thd, bool on);
diff --git a/sql/hash_filo.cc b/sql/hash_filo.cc
index 990d2d662d6..b85f8054f10 100644
--- a/sql/hash_filo.cc
+++ b/sql/hash_filo.cc
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
diff --git a/sql/hash_filo.h b/sql/hash_filo.h
index 157c2739add..b8d45f0d3be 100644
--- a/sql/hash_filo.h
+++ b/sql/hash_filo.h
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -24,7 +24,7 @@
#define HASH_FILO_H
#ifdef __GNUC__
-#pragma interface /* gcc class implementation */
+#pragma interface /* gcc class interface */
#endif
class hash_filo_element
diff --git a/sql/hostname.cc b/sql/hostname.cc
index bc812341337..7d4e4a8ca75 100644
--- a/sql/hostname.cc
+++ b/sql/hostname.cc
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
diff --git a/sql/init.cc b/sql/init.cc
index e6606b82b7c..df06ddd41ef 100644
--- a/sql/init.cc
+++ b/sql/init.cc
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
diff --git a/sql/item.cc b/sql/item.cc
index b268c5eb928..c081fd9dd5f 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -37,7 +37,7 @@ void item_init(void)
Item::Item()
{
marker=0;
- binary=maybe_null=null_value=with_sum_func=0;
+ binary=maybe_null=null_value=with_sum_func=unsigned_flag=0;
name=0;
decimals=0; max_length=0;
next=current_thd->free_list; // Put in free list
@@ -116,6 +116,7 @@ void Item_field::set_field(Field *field_par)
table_name=field_par->table_name;
field_name=field_par->field_name;
binary=field_par->binary();
+ unsigned_flag=test(field_par->flags & UNSIGNED_FLAG);
}
const char *Item_ident::full_name() const
@@ -231,6 +232,22 @@ void Item_int::print(String *str)
str->append(name);
}
+String *Item_uint::val_str(String *str)
+{
+ str->set((ulonglong) value);
+ return str;
+}
+
+void Item_uint::print(String *str)
+{
+ if (!name)
+ {
+ str_value.set((ulonglong) value);
+ name=str_value.c_ptr();
+ }
+ str->append(name);
+}
+
String *Item_real::val_str(String *str)
{
@@ -282,13 +299,21 @@ bool Item::fix_fields(THD *thd,
bool Item_field::fix_fields(THD *thd,TABLE_LIST *tables)
{
- if (!field)
+ if (!field) // If field is not checked
{
Field *tmp;
if (!(tmp=find_field_in_tables(thd,this,tables)))
return 1;
set_field(tmp);
}
+ else if (thd && thd->set_query_id && field->query_id != thd->query_id)
+ {
+ /* We only come here in unions */
+ TABLE *table=field->table;
+ field->query_id=thd->query_id;
+ table->used_fields++;
+ table->used_keys&=field->part_of_key;
+ }
return 0;
}
@@ -302,6 +327,8 @@ void Item::init_make_field(Send_field *tmp_field,
tmp_field->type=field_type;
tmp_field->length=max_length;
tmp_field->decimals=decimals;
+ if (unsigned_flag)
+ tmp_field->flags |= UNSIGNED_FLAG;
}
/* ARGSUSED */
@@ -317,6 +344,13 @@ void Item_int::make_field(Send_field *tmp_field)
init_make_field(tmp_field,FIELD_TYPE_LONGLONG);
}
+void Item_uint::make_field(Send_field *tmp_field)
+{
+ init_make_field(tmp_field,FIELD_TYPE_LONGLONG);
+ tmp_field->flags|= UNSIGNED_FLAG;
+ unsigned_flag=1;
+}
+
void Item_real::make_field(Send_field *tmp_field)
{
init_make_field(tmp_field,FIELD_TYPE_DOUBLE);
@@ -535,19 +569,19 @@ void Item_varbinary::make_field(Send_field *tmp_field)
** pack data in buffer for sending
*/
-bool Item::send(String *packet)
+bool Item::send(THD *thd, String *packet)
{
char buff[MAX_FIELD_WIDTH];
+ CONVERT *convert;
String s(buff,sizeof(buff)),*res;
if (!(res=val_str(&s)))
return net_store_null(packet);
- CONVERT *convert;
- if ((convert=current_thd->convert_set))
+ if ((convert=thd->convert_set))
return convert->store(packet,res->ptr(),res->length());
return net_store_data(packet,res->ptr(),res->length());
}
-bool Item_null::send(String *packet)
+bool Item_null::send(THD *thd, String *packet)
{
return net_store_null(packet);
}
@@ -561,7 +595,7 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables)
{
if (!ref)
{
- if (!(ref=find_item_in_list(this,thd->lex.item_list)))
+ if (!(ref=find_item_in_list(this,thd->lex.select->item_list)))
return 1;
max_length= (*ref)->max_length;
maybe_null= (*ref)->maybe_null;
@@ -677,5 +711,6 @@ bool field_is_equal_to_item(Field *field,Item *item)
#ifdef __GNUC__
template class List<Item>;
template class List_iterator<Item>;
+template class List_iterator_fast<Item>;
template class List<List_item>;
#endif
diff --git a/sql/item.h b/sql/item.h
index c868f9d3bf7..5028f25c6b8 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -23,7 +23,7 @@ struct st_table_list;
void item_init(void); /* Init item functions */
class Item {
- Item(const Item &); /* Prevent use of theese */
+ Item(const Item &); /* Prevent use of these */
void operator=(Item &);
public:
static void *operator new(size_t size) {return (void*) sql_alloc((uint) size); }
@@ -43,6 +43,7 @@ public:
my_bool maybe_null; /* If item may be null */
my_bool null_value; /* if item is null */
my_bool binary;
+ my_bool unsigned_flag;
my_bool with_sum_func;
@@ -55,7 +56,7 @@ public:
virtual bool save_in_field(Field *field);
virtual void save_org_in_field(Field *field)
{ (void) save_in_field(field); }
- virtual bool send(String *str);
+ virtual bool send(THD *thd, String *str);
virtual bool eq(const Item *) const;
virtual Item_result result_type () const { return REAL_RESULT; }
virtual enum Type type() const =0;
@@ -63,7 +64,7 @@ public:
virtual longlong val_int()=0;
virtual String *val_str(String*)=0;
virtual void make_field(Send_field *field)=0;
- virtual Field *tmp_table_field() { return 0; }
+ virtual Field *tmp_table_field(TABLE *t_arg=(TABLE *)0) { return 0; }
virtual const char *full_name() const { return name ? name : "???"; }
virtual double val_result() { return val(); }
virtual longlong val_int_result() { return val_int(); }
@@ -80,6 +81,7 @@ public:
virtual void split_sum_func(List<Item> &fields) {}
virtual bool get_date(TIME *ltime,bool fuzzydate);
virtual bool get_time(TIME *ltime);
+ virtual bool is_null() { return 0; }
};
@@ -116,7 +118,7 @@ public:
double val_result();
longlong val_int_result();
String *str_result(String* tmp);
- bool send(String *str_arg) { return result_field->send(str_arg); }
+ bool send(THD *thd, String *str_arg) { return result_field->send(thd,str_arg); }
void make_field(Send_field *field);
bool fix_fields(THD *,struct st_table_list *);
bool save_in_field(Field *field);
@@ -126,9 +128,10 @@ public:
{
return field->result_type();
}
- Field *tmp_table_field() { return result_field; }
+ Field *tmp_table_field(TABLE *t_arg=(TABLE *)0) { return result_field; }
bool get_date(TIME *ltime,bool fuzzydate);
bool get_time(TIME *ltime);
+ bool is_null() { return field->is_null(); }
};
@@ -146,9 +149,10 @@ public:
bool save_in_field(Field *field);
enum Item_result result_type () const
{ return STRING_RESULT; }
- bool send(String *str);
+ bool send(THD *thd, String *str);
bool basic_const_item() const { return 1; }
Item *new_item() { return new Item_null(name); }
+ bool is_null() { return 1; }
};
@@ -181,6 +185,19 @@ public:
};
+class Item_uint :public Item_int
+{
+public:
+ Item_uint(const char *str_arg, uint length) :
+ Item_int(str_arg, (longlong) strtoull(str_arg,(char**) 0,10), length) {}
+ double val() { return ulonglong2double(value); }
+ String *val_str(String*);
+ void make_field(Send_field *field);
+ Item *new_item() { return new Item_uint(name,max_length); }
+ void print(String *str);
+};
+
+
class Item_real :public Item
{
public:
@@ -189,14 +206,14 @@ public:
Item_real(const char *str_arg,uint length) :value(atof(str_arg))
{
name=(char*) str_arg;
- decimals=nr_of_decimals(str_arg);
+ decimals=(uint8) nr_of_decimals(str_arg);
max_length=length;
}
Item_real(const char *str,double val_arg,uint decimal_par,uint length)
:value(val_arg)
{
name=(char*) str;
- decimals=decimal_par;
+ decimals=(uint8) decimal_par;
max_length=length;
}
Item_real(double value_par) :value(value_par) {}
@@ -291,7 +308,7 @@ public:
Field *result_field; /* Save result here */
Item_result_field() :result_field(0) {}
~Item_result_field() {} /* Required with gcc 2.95 */
- Field *tmp_table_field() { return result_field; }
+ Field *tmp_table_field(TABLE *t_arg=(TABLE *)0) { return result_field; }
table_map used_tables() const { return 1; }
virtual void fix_length_and_dec()=0;
};
@@ -330,7 +347,7 @@ public:
{
return (null_value=(*ref)->get_date(ltime,fuzzydate));
}
- bool send(String *tmp) { return (*ref)->send(tmp); }
+ bool send(THD *thd, String *tmp) { return (*ref)->send(thd, tmp); }
void make_field(Send_field *field) { (*ref)->make_field(field); }
bool fix_fields(THD *,struct st_table_list *);
bool save_in_field(Field *field) { return (*ref)->save_in_field(field); }
@@ -370,6 +387,7 @@ public:
void copy();
table_map used_tables() const { return (table_map) 1L; }
bool const_item() const { return 0; }
+ bool is_null() { return null_value; }
};
diff --git a/sql/item_buff.cc b/sql/item_buff.cc
index 61e1f5498a9..b55a4dc66a0 100644
--- a/sql/item_buff.cc
+++ b/sql/item_buff.cc
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index 373aede7b6b..0c83698e60a 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -254,7 +254,7 @@ longlong Item_func_strcmp::val_int()
null_value=1;
return 0;
}
- int value=stringcmp(a,b);
+ int value= binary ? stringcmp(a,b) : sortcmp(a,b);
null_value=0;
return !value ? 0 : (value < 0 ? (longlong) -1 : (longlong) 1);
}
@@ -955,7 +955,7 @@ void Item_func_in::fix_length_and_dec()
for (uint i=0 ; i < arg_count ; i++)
{
array->set(j,args[i]);
- if (!args[i]->null_value) // Skipp NULL values
+ if (!args[i]->null_value) // Skip NULL values
j++;
}
if ((array->used_count=j))
@@ -1129,7 +1129,7 @@ void Item_cond::update_used_tables()
{
used_tables_cache=0;
const_item_cache=1;
- List_iterator<Item> li(list);
+ List_iterator_fast<Item> li(list);
Item *item;
while ((item=li++))
{
@@ -1143,7 +1143,7 @@ void Item_cond::update_used_tables()
void Item_cond::print(String *str)
{
str->append('(');
- List_iterator<Item> li(list);
+ List_iterator_fast<Item> li(list);
Item *item;
if ((item=li++))
item->print(str);
@@ -1160,7 +1160,7 @@ void Item_cond::print(String *str)
longlong Item_cond_and::val_int()
{
- List_iterator<Item> li(list);
+ List_iterator_fast<Item> li(list);
Item *item;
while ((item=li++))
{
@@ -1179,7 +1179,7 @@ longlong Item_cond_and::val_int()
longlong Item_cond_or::val_int()
{
- List_iterator<Item> li(list);
+ List_iterator_fast<Item> li(list);
Item *item;
null_value=0;
while ((item=li++))
@@ -1197,14 +1197,12 @@ longlong Item_cond_or::val_int()
longlong Item_func_isnull::val_int()
{
- (void) args[0]->val();
- return (args[0]->null_value) ? 1 : 0;
+ return args[0]->is_null() ? 1: 0;
}
longlong Item_func_isnotnull::val_int()
{
- (void) args[0]->val();
- return !(args[0]->null_value) ? 1 : 0;
+ return args[0]->is_null() ? 0 : 1;
}
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index 5ee0687c064..c9c7d5654d6 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -46,6 +46,7 @@ public:
virtual enum Functype rev_functype() const { return UNKNOWN_FUNC; }
bool have_rev_func() const { return rev_functype() != UNKNOWN_FUNC; }
void print(String *str) { Item_func::print_op(str); }
+ bool is_null() { return test(args[0]->is_null() || args[1]->is_null()); }
};
@@ -459,7 +460,10 @@ public:
Item_func_isnotnull(Item *a) :Item_bool_func(a) {}
longlong val_int();
enum Functype functype() const { return ISNOTNULL_FUNC; }
- void fix_length_and_dec() { decimals=0; max_length=1; maybe_null=0; }
+ void fix_length_and_dec()
+ {
+ decimals=0; max_length=1; maybe_null=0;
+ }
const char *func_name() const { return "isnotnull"; }
optimize_type select_optimize() const { return OPTIMIZE_NULL; }
};
diff --git a/sql/item_create.cc b/sql/item_create.cc
index ef9f5f2d38b..6f64e9517ba 100644
--- a/sql/item_create.cc
+++ b/sql/item_create.cc
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -65,7 +65,9 @@ Item *create_func_ceiling(Item* a)
Item *create_func_connection_id(void)
{
- return new Item_int("CONNECTION_ID()",(longlong) current_thd->thread_id,10);
+ THD *thd=current_thd;
+ thd->safe_to_cache_query=0;
+ return new Item_int("CONNECTION_ID()",(longlong) thd->thread_id,10);
}
Item *create_func_conv(Item* a, Item *b, Item *c)
@@ -129,6 +131,13 @@ Item *create_func_floor(Item* a)
return new Item_func_floor(a);
}
+Item *create_func_found_rows(void)
+{
+ THD *thd=current_thd;
+ thd->safe_to_cache_query=0;
+ return new Item_int("FOUND_ROWS()",(longlong) thd->found_rows(),21);
+}
+
Item *create_func_from_days(Item* a)
{
return new Item_func_from_days(a);
@@ -136,13 +145,13 @@ Item *create_func_from_days(Item* a)
Item *create_func_get_lock(Item* a, Item *b)
{
+ current_thd->safe_to_cache_query=0;
return new Item_func_get_lock(a, b);
}
Item *create_func_hex(Item *a)
{
- return new Item_func_conv(a,new Item_int((int32) 10,2),
- new Item_int((int32) 16,2));
+ return new Item_func_hex(a);
}
Item *create_func_inet_ntoa(Item* a)
@@ -191,6 +200,11 @@ Item *create_func_length(Item* a)
return new Item_func_length(a);
}
+Item *create_func_bit_length(Item* a)
+{
+ return new Item_func_bit_length(a);
+}
+
Item *create_func_char_length(Item* a)
{
return new Item_func_char_length(a);
@@ -274,6 +288,7 @@ Item *create_func_radians(Item *a)
Item *create_func_release_lock(Item* a)
{
+ current_thd->safe_to_cache_query=0;
return new Item_func_release_lock(a);
}
@@ -374,10 +389,27 @@ Item *create_func_year(Item* a)
Item *create_load_file(Item* a)
{
+ current_thd->safe_to_cache_query=0;
return new Item_load_file(a);
}
Item *create_wait_for_master_pos(Item* a, Item* b)
{
+ current_thd->safe_to_cache_query=0;
return new Item_master_pos_wait(a, b);
}
+
+Item *create_func_cast(Item *a, Item_cast cast_type)
+{
+ Item *res;
+ LINT_INIT(res);
+ switch (cast_type) {
+ case ITEM_CAST_BINARY: res= new Item_func_binary(a); break;
+ case ITEM_CAST_SIGNED_INT: res= new Item_func_signed(a); break;
+ case ITEM_CAST_UNSIGNED_INT: res= new Item_func_unsigned(a); break;
+ case ITEM_CAST_DATE: res= new Item_date_typecast(a); break;
+ case ITEM_CAST_TIME: res= new Item_time_typecast(a); break;
+ case ITEM_CAST_DATETIME: res= new Item_datetime_typecast(a); break;
+ }
+ return res;
+}
diff --git a/sql/item_create.h b/sql/item_create.h
index cc7497b0183..580596505da 100644
--- a/sql/item_create.h
+++ b/sql/item_create.h
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -22,6 +22,7 @@ Item *create_func_ascii(Item* a);
Item *create_func_asin(Item* a);
Item *create_func_bin(Item* a);
Item *create_func_bit_count(Item* a);
+Item *create_func_bit_length(Item* a);
Item *create_func_ceiling(Item* a);
Item *create_func_char_length(Item* a);
Item *create_func_connection_id(void);
@@ -37,6 +38,7 @@ Item *create_func_degrees(Item *);
Item *create_func_exp(Item* a);
Item *create_func_find_in_set(Item* a, Item *b);
Item *create_func_floor(Item* a);
+Item *create_func_found_rows(void);
Item *create_func_from_days(Item* a);
Item *create_func_get_lock(Item* a, Item *b);
Item *create_func_hex(Item *a);
diff --git a/sql/item_func.cc b/sql/item_func.cc
index e7e8964b07a..1818a755a43 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -43,7 +43,7 @@ Item_func::Item_func(List<Item> &list)
if ((args=(Item**) sql_alloc(sizeof(Item*)*arg_count)))
{
uint i=0;
- List_iterator<Item> li(list);
+ List_iterator_fast<Item> li(list);
Item *item;
while ((item=li++))
@@ -184,8 +184,10 @@ String *Item_num_func::val_str(String *str)
longlong nr=val_int();
if (null_value)
return 0; /* purecov: inspected */
- else
+ else if (!unsigned_flag)
str->set(nr);
+ else
+ str->set((ulonglong) nr);
}
else
{
@@ -207,24 +209,31 @@ void Item_func::fix_num_length_and_dec()
max_length=float_length(decimals);
}
-
String *Item_int_func::val_str(String *str)
{
longlong nr=val_int();
if (null_value)
return 0;
- else
+ else if (!unsigned_flag)
str->set(nr);
+ else
+ str->set((ulonglong) nr);
return str;
}
-/* Change from REAL_RESULT (default) to INT_RESULT if both arguments are integers */
+/*
+ Change from REAL_RESULT (default) to INT_RESULT if both arguments are
+ integers
+*/
void Item_num_op::find_num_type(void)
{
if (args[0]->result_type() == INT_RESULT &&
args[1]->result_type() == INT_RESULT)
+ {
hybrid_type=INT_RESULT;
+ unsigned_flag=args[0]->unsigned_flag | args[1]->unsigned_flag;
+ }
}
String *Item_num_op::val_str(String *str)
@@ -234,8 +243,10 @@ String *Item_num_op::val_str(String *str)
longlong nr=val_int();
if (null_value)
return 0; /* purecov: inspected */
- else
+ else if (!unsigned_flag)
str->set(nr);
+ else
+ str->set((ulonglong) nr);
}
else
{
@@ -269,6 +280,21 @@ longlong Item_func_plus::val_int()
return (longlong) Item_func_plus::val();
}
+
+/*
+ The following function is here to allow the user to force
+ subtraction of UNSIGNED BIGINT to return negative values.
+*/
+
+void Item_func_minus::fix_length_and_dec()
+{
+ Item_num_op::fix_length_and_dec();
+ if (unsigned_flag &&
+ (current_thd->sql_mode & MODE_NO_UNSIGNED_SUBTRACTION))
+ unsigned_flag=0;
+}
+
+
double Item_func_minus::val()
{
double value=args[0]->val() - args[1]->val();
@@ -610,8 +636,9 @@ double Item_func_rand::val()
{
if (arg_count)
{ // Only use argument once in query
- ulong tmp=((ulong) args[0]->val_int())+55555555L;
- randominit(&current_thd->rand,tmp,tmp/2);
+ uint32 tmp= (uint32) (args[0]->val_int());
+ randominit(&current_thd->rand,(uint32) (tmp*0x10001L+55555555L),
+ (uint32) (tmp*0x10000001L));
#ifdef DELETE_ITEMS
delete args[0];
#endif
@@ -667,8 +694,10 @@ String *Item_func_min_max::val_str(String *str)
longlong nr=val_int();
if (null_value)
return 0;
- else
+ else if (!unsigned_flag)
str->set(nr);
+ else
+ str->set((ulonglong) nr);
return str;
}
case REAL_RESULT:
@@ -784,9 +813,7 @@ longlong Item_func_locate::val_int()
{
String *a=args[0]->val_str(&value1);
String *b=args[1]->val_str(&value2);
-#ifdef USE_MB
bool binary_str = args[0]->binary || args[1]->binary;
-#endif
if (!a || !b)
{
null_value=1;
@@ -840,7 +867,8 @@ longlong Item_func_locate::val_int()
return 0;
}
#endif /* USE_MB */
- return (longlong) (a->strstr(*b,start)+1) ;
+ return (longlong) (binary ? a->strstr(*b,start) :
+ (a->strstr_case(*b,start)))+1;
}
@@ -1050,7 +1078,8 @@ udf_handler::~udf_handler()
}
free_udf(u_d);
}
- delete [] buffers;
+ if (buffers) // Because of bug in ecc
+ delete [] buffers;
}
@@ -1306,8 +1335,10 @@ String *Item_func_udf_int::val_str(String *str)
longlong nr=val_int();
if (null_value)
return 0;
- else
+ else if (!unsigned_flag)
str->set(nr);
+ else
+ str->set((ulonglong) nr);
return str;
}
@@ -1402,19 +1433,19 @@ void item_user_lock_release(ULL *ull)
if (mysql_bin_log.is_open())
{
THD *thd = current_thd;
- int save_errno;
+ uint save_query_length;
char buf[256];
String tmp(buf,sizeof(buf));
tmp.length(0);
tmp.append("DO RELEASE_LOCK(\"");
tmp.append(ull->key,ull->key_length);
tmp.append("\")");
- save_errno=thd->net.last_errno;
- thd->net.last_errno=0;
+ save_query_length=thd->query_length;
thd->query_length=tmp.length();
Query_log_event qev(thd,tmp.ptr());
+ qev.error_code=0; // this query is always safe to run on slave
mysql_bin_log.write(&qev);
- thd->net.last_errno=save_errno;
+ thd->query_length=save_query_length;
}
if (--ull->count)
pthread_cond_signal(&ull->cond);
@@ -1432,7 +1463,7 @@ longlong Item_master_pos_wait::val_int()
THD* thd = current_thd;
String *log_name = args[0]->val_str(&value);
int event_count;
-
+
null_value=0;
if (thd->slave_thread || !log_name || !log_name->length())
{
@@ -1440,14 +1471,83 @@ longlong Item_master_pos_wait::val_int()
return 0;
}
ulong pos = (ulong)args[1]->val_int();
- if ((event_count = glob_mi.wait_for_pos(thd, log_name, pos)) == -1)
+ LOCK_ACTIVE_MI;
+ if ((event_count = active_mi->rli.wait_for_pos(thd, log_name, pos)) == -1)
{
null_value = 1;
event_count=0;
}
+ UNLOCK_ACTIVE_MI;
return event_count;
}
+#ifdef EXTRA_DEBUG
+void debug_sync_point(const char* lock_name, uint lock_timeout)
+{
+ THD* thd=current_thd;
+ ULL* ull;
+ struct timespec abstime;
+ int lock_name_len,error=0;
+ lock_name_len=strlen(lock_name);
+ pthread_mutex_lock(&LOCK_user_locks);
+
+ if (thd->ull)
+ {
+ item_user_lock_release(thd->ull);
+ thd->ull=0;
+ }
+
+ /* if the lock has not been aquired by some client, we do not want to
+ create an entry for it, since we immediately release the lock. In
+ this case, we will not be waiting, but rather, just waste CPU and
+ memory on the whole deal
+ */
+ if (!(ull= ((ULL*) hash_search(&hash_user_locks,lock_name,
+ lock_name_len))))
+ {
+ pthread_mutex_unlock(&LOCK_user_locks);
+ return;
+ }
+ ull->count++;
+
+ /* structure is now initialized. Try to get the lock */
+ /* Set up control struct to allow others to abort locks */
+ thd->proc_info="User lock";
+ thd->mysys_var->current_mutex= &LOCK_user_locks;
+ thd->mysys_var->current_cond= &ull->cond;
+
+ set_timespec(abstime,lock_timeout);
+ while (!thd->killed &&
+ (error=pthread_cond_timedwait(&ull->cond,&LOCK_user_locks,&abstime))
+ != ETIME && error != ETIMEDOUT && ull->locked) ;
+ if (ull->locked)
+ {
+ if (!--ull->count)
+ delete ull; // Should never happen
+ }
+ else
+ {
+ ull->locked=1;
+ ull->thread=thd->real_id;
+ thd->ull=ull;
+ }
+ pthread_mutex_unlock(&LOCK_user_locks);
+ pthread_mutex_lock(&thd->mysys_var->mutex);
+ thd->proc_info=0;
+ thd->mysys_var->current_mutex= 0;
+ thd->mysys_var->current_cond= 0;
+ pthread_mutex_unlock(&thd->mysys_var->mutex);
+ pthread_mutex_lock(&LOCK_user_locks);
+ if (thd->ull)
+ {
+ item_user_lock_release(thd->ull);
+ thd->ull=0;
+ }
+ pthread_mutex_unlock(&LOCK_user_locks);
+}
+
+#endif
+
/*
Get a user level lock. If the thread has an old lock this is first released.
Returns 1: Got lock
@@ -1504,14 +1604,7 @@ longlong Item_func_get_lock::val_int()
thd->mysys_var->current_mutex= &LOCK_user_locks;
thd->mysys_var->current_cond= &ull->cond;
-#ifdef HAVE_TIMESPEC_TS_SEC
- abstime.ts_sec=time((time_t*) 0)+(time_t) timeout;
- abstime.ts_nsec=0;
-#else
- abstime.tv_sec=time((time_t*) 0)+(time_t) timeout;
- abstime.tv_nsec=0;
-#endif
-
+ set_timespec(abstime,timeout);
while (!thd->killed &&
(error=pthread_cond_timedwait(&ull->cond,&LOCK_user_locks,&abstime))
!= ETIME && error != ETIMEDOUT && ull->locked) ;
@@ -1941,44 +2034,6 @@ err:
return 0;
}
-double Item_func_match::val()
-{
- if (ft_handler==NULL)
- return -1.0;
-
- if (join_key)
- {
- if (table->file->ft_handler)
- return ft_get_relevance(ft_handler);
-
- join_key=0; // Magic here ! See ha_myisam::ft_read()
- }
-
- /* we'll have to find ft_relevance manually in ft_handler array */
-
- int a,b,c;
- FT_DOC *docs=ft_handler->doc;
- my_off_t docid=table->file->row_position();
-
- if ((null_value=(docid==HA_OFFSET_ERROR)))
- return 0.0;
-
- // Assuming docs[] is sorted by dpos...
-
- for (a=0, b=ft_handler->ndocs, c=(a+b)/2; b-a>1; c=(a+b)/2)
- {
- if (docs[c].dpos > docid)
- b=c;
- else
- a=c;
- }
- if (docs[a].dpos == docid)
- return docs[a].weight;
- else
- return 0.0;
-
-}
-
void Item_func_match::init_search(bool no_order)
{
if (ft_handler)
@@ -1993,20 +2048,24 @@ void Item_func_match::init_search(bool no_order)
return;
}
+ if (key == NO_SUCH_KEY)
+ concat=new Item_func_concat_ws (new Item_string(" ",1), fields);
+
String *ft_tmp=0;
char tmp1[FT_QUERY_MAXLEN];
String tmp2(tmp1,sizeof(tmp1));
- // MATCH ... AGAINST (NULL) is meaningless, but possible
+ // MATCH ... AGAINST (NULL) is meaningless, but possible
if (!(ft_tmp=key_item()->val_str(&tmp2)))
{
ft_tmp=&tmp2;
tmp2.set("",0);
}
- ft_handler=(FT_DOCLIST *)
- table->file->ft_init_ext(key, (byte*) ft_tmp->ptr(), ft_tmp->length(),
- join_key && !no_order);
+ ft_handler=table->file->ft_init_ext(mode, key,
+ (byte*) ft_tmp->ptr(),
+ ft_tmp->length(),
+ join_key && !no_order);
if (join_key)
{
@@ -2023,12 +2082,11 @@ bool Item_func_match::fix_fields(THD *thd,struct st_table_list *tlist)
maybe_null=1;
join_key=0;
- /* Serg:
- I'd rather say now that const_item is assumed in quite a bit of
- places, so it would be difficult to remove; If it would ever to be
- removed, this should include modifications to find_best and auto_close
- as complement to auto_init code above.
- */
+ /* const_item is assumed in quite a bit of places, so it would be difficult
+ to remove; If it would ever to be removed, this should include
+ modifications to find_best and auto_close as complement to auto_init code
+ above.
+ */
if (Item_func::fix_fields(thd,tlist) || !const_item())
{
my_error(ER_WRONG_ARGUMENTS,MYF(0),"AGAINST");
@@ -2042,29 +2100,32 @@ bool Item_func_match::fix_fields(THD *thd,struct st_table_list *tlist)
if (item->type() == Item::REF_ITEM)
li.replace(item= *((Item_ref *)item)->ref);
if (item->type() != Item::FIELD_ITEM || !item->used_tables())
- {
- my_error(ER_WRONG_ARGUMENTS,MYF(0),"MATCH");
- return 1;
- }
+ key=NO_SUCH_KEY;
used_tables_cache|=item->used_tables();
}
/* check that all columns come from the same table */
if (count_bits(used_tables_cache) != 1)
+ key=NO_SUCH_KEY;
+ const_item_cache=0;
+ table=((Item_field *)fields.head())->field->table;
+ record=table->record[0];
+ if (key == NO_SUCH_KEY && mode != FT_BOOL)
{
my_error(ER_WRONG_ARGUMENTS,MYF(0),"MATCH");
return 1;
}
- const_item_cache=0;
- table=((Item_field *)fields.head())->field->table;
return 0;
}
-
bool Item_func_match::fix_index()
{
- List_iterator<Item> li(fields);
+ List_iterator_fast<Item> li(fields);
Item_field *item;
uint ft_to_key[MAX_KEY], ft_cnt[MAX_KEY], fts=0, key;
+ uint max_cnt=0, mkeys=0;
+
+ if (this->key == NO_SUCH_KEY)
+ return 0;
for (key=0 ; key<table->keys ; key++)
{
@@ -2078,11 +2139,7 @@ bool Item_func_match::fix_index()
}
if (!fts)
- {
- my_printf_error(ER_FT_MATCHING_KEY_NOT_FOUND,
- ER(ER_FT_MATCHING_KEY_NOT_FOUND),MYF(0));
- return 1;
- }
+ goto err;
while ((item=(Item_field*)(li++)))
{
@@ -2099,7 +2156,6 @@ bool Item_func_match::fix_index()
}
}
- uint max_cnt=0, mkeys=0;
for (key=0 ; key<fts ; key++)
{
if (ft_cnt[key] > max_cnt)
@@ -2130,6 +2186,12 @@ bool Item_func_match::fix_index()
return 0;
}
+err:
+ if (mode == FT_BOOL)
+ {
+ this->key=NO_SUCH_KEY;
+ return 0;
+ }
my_printf_error(ER_FT_MATCHING_KEY_NOT_FOUND,
ER(ER_FT_MATCHING_KEY_NOT_FOUND),MYF(0));
return 1;
@@ -2152,6 +2214,30 @@ bool Item_func_match::eq(const Item *item) const
return 0;
}
+double Item_func_match::val()
+{
+ if (ft_handler == NULL)
+ return -1.0;
+
+ if (join_key)
+ {
+ if (table->file->ft_handler)
+ return ft_handler->please->get_relevance(ft_handler);
+
+ join_key=0;
+ }
+
+ if (key == NO_SUCH_KEY)
+ {
+ String *a=concat->val_str(&value);
+ if ((null_value= (a==0)))
+ return 0;
+ return ft_handler->please->find_relevance(ft_handler,
+ (byte *)a->ptr(), a->length());
+ }
+ else
+ return ft_handler->please->find_relevance(ft_handler, record, 0);
+}
/***************************************************************************
System variables
diff --git a/sql/item_func.h b/sql/item_func.h
index 4a8f808de57..823bfb44a96 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -119,6 +119,7 @@ public:
{
return (null_value=args[0]->get_time(ltime));
}
+ bool is_null() { (void) val_int(); return null_value; }
friend class udf_handler;
};
@@ -134,6 +135,11 @@ public:
longlong val_int() { return (longlong) val(); }
enum Item_result result_type () const { return REAL_RESULT; }
void fix_length_and_dec() { decimals=NOT_FIXED_DEC; max_length=float_length(decimals); }
+ Field *tmp_table_field(TABLE *t_arg)
+ {
+ if (!t_arg) return result_field;
+ return new Field_double(max_length, maybe_null, name,t_arg,decimals);
+ }
};
class Item_num_func :public Item_func
@@ -147,6 +153,7 @@ public:
longlong val_int() { return (longlong) val(); }
enum Item_result result_type () const { return hybrid_type; }
void fix_length_and_dec() { fix_num_length_and_dec(); }
+ bool is_null() { (void) val(); return null_value; }
};
@@ -161,23 +168,55 @@ class Item_num_op :public Item_func
enum Item_result result_type () const { return hybrid_type; }
void fix_length_and_dec() { fix_num_length_and_dec(); find_num_type(); }
void find_num_type(void);
+ bool is_null() { (void) val(); return null_value; }
+ Field *tmp_table_field(TABLE *t_arg)
+ {
+ if (!t_arg) return result_field;
+ return args[0]->result_type() == INT_RESULT ? ((max_length > 11) ? (Field *)new Field_longlong(max_length,maybe_null,name, t_arg,unsigned_flag) : (Field *)new Field_long(max_length,maybe_null,name, t_arg,unsigned_flag)) : (Field *) new Field_double(max_length, maybe_null, name,t_arg,decimals);
+ }
};
class Item_int_func :public Item_func
{
public:
- Item_int_func() :Item_func() {}
- Item_int_func(Item *a) :Item_func(a) {}
- Item_int_func(Item *a,Item *b) :Item_func(a,b) {}
- Item_int_func(Item *a,Item *b,Item *c) :Item_func(a,b,c) {}
- Item_int_func(List<Item> &list) :Item_func(list) {}
+ Item_int_func() :Item_func() { max_length=21; }
+ Item_int_func(Item *a) :Item_func(a) { max_length=21; }
+ Item_int_func(Item *a,Item *b) :Item_func(a,b) { max_length=21; }
+ Item_int_func(Item *a,Item *b,Item *c) :Item_func(a,b,c) { max_length=21; }
+ Item_int_func(List<Item> &list) :Item_func(list) { max_length=21; }
double val() { return (double) val_int(); }
String *val_str(String*str);
enum Item_result result_type () const { return INT_RESULT; }
- void fix_length_and_dec() { decimals=0; max_length=21; }
+ void fix_length_and_dec() {}
+ Field *tmp_table_field(TABLE *t_arg)
+ {
+ if (!t_arg) return result_field;
+ return (max_length > 11) ? (Field *)new Field_longlong(max_length,maybe_null,name, t_arg,unsigned_flag) : (Field *)new Field_long(max_length,maybe_null,name, t_arg,unsigned_flag);
+ }
+};
+
+class Item_func_signed :public Item_int_func
+{
+public:
+ Item_func_signed(Item *a) :Item_int_func(a) {}
+ double val() { return args[0]->val(); }
+ longlong val_int() { return args[0]->val_int(); }
+ void fix_length_and_dec()
+ { max_length=args[0]->max_length; unsigned_flag=0; }
+};
+
+class Item_func_unsigned :public Item_int_func
+{
+public:
+ Item_func_unsigned(Item *a) :Item_int_func(a) {}
+ double val() { return args[0]->val(); }
+ longlong val_int() { return args[0]->val_int(); }
+ void fix_length_and_dec()
+ { max_length=args[0]->max_length; unsigned_flag=1; }
};
+
class Item_func_plus :public Item_num_op
{
public:
@@ -194,8 +233,10 @@ public:
const char *func_name() const { return "-"; }
double val();
longlong val_int();
+ void fix_length_and_dec();
};
+
class Item_func_mul :public Item_num_op
{
public:
@@ -483,6 +524,14 @@ public:
void fix_length_and_dec() { max_length=10; }
};
+class Item_func_bit_length :public Item_func_length
+{
+public:
+ Item_func_bit_length(Item *a) :Item_func_length(a) {}
+ longlong val_int() { return Item_func_length::val_int()*8; }
+ const char *func_name() const { return "bit_length"; }
+};
+
class Item_func_char_length :public Item_int_func
{
String value;
@@ -551,7 +600,6 @@ public:
Item_func_ord(Item *a) :Item_int_func(a) {}
longlong val_int();
const char *func_name() const { return "ord"; }
- void fix_length_and_dec() { max_length=21; }
};
class Item_func_find_in_set :public Item_int_func
@@ -573,7 +621,7 @@ public:
Item_func_bit_or(Item *a,Item *b) :Item_int_func(a,b) {}
longlong val_int();
const char *func_name() const { return "|"; }
- void fix_length_and_dec() { decimals=0; max_length=21; }
+ void fix_length_and_dec() { unsigned_flag=1; }
};
class Item_func_bit_and :public Item_int_func
@@ -582,7 +630,7 @@ public:
Item_func_bit_and(Item *a,Item *b) :Item_int_func(a,b) {}
longlong val_int();
const char *func_name() const { return "&"; }
- void fix_length_and_dec() { decimals=0; max_length=21; }
+ void fix_length_and_dec() { unsigned_flag=1; }
};
class Item_func_bit_count :public Item_int_func
@@ -591,7 +639,7 @@ public:
Item_func_bit_count(Item *a) :Item_int_func(a) {}
longlong val_int();
const char *func_name() const { return "bit_count"; }
- void fix_length_and_dec() { decimals=0; max_length=2; }
+ void fix_length_and_dec() { max_length=2; }
};
class Item_func_shift_left :public Item_int_func
@@ -600,7 +648,7 @@ public:
Item_func_shift_left(Item *a,Item *b) :Item_int_func(a,b) {}
longlong val_int();
const char *func_name() const { return "<<"; }
- void fix_length_and_dec() { decimals=0; max_length=21; }
+ void fix_length_and_dec() { unsigned_flag=1; }
};
class Item_func_shift_right :public Item_int_func
@@ -609,7 +657,6 @@ public:
Item_func_shift_right(Item *a,Item *b) :Item_int_func(a,b) {}
longlong val_int();
const char *func_name() const { return ">>"; }
- void fix_length_and_dec() { decimals=0; max_length=21; }
};
class Item_func_bit_neg :public Item_int_func
@@ -618,7 +665,7 @@ public:
Item_func_bit_neg(Item *a) :Item_int_func(a) {}
longlong val_int();
const char *func_name() const { return "~"; }
- void fix_length_and_dec() { decimals=0; max_length=21; }
+ void fix_length_and_dec() { unsigned_flag=1; }
};
class Item_func_set_last_insert_id :public Item_int_func
@@ -627,7 +674,7 @@ public:
Item_func_set_last_insert_id(Item *a) :Item_int_func(a) {}
longlong val_int();
const char *func_name() const { return "last_insert_id"; }
- void fix_length_and_dec() { decimals=0; max_length=args[0]->max_length; }
+ void fix_length_and_dec() { max_length=args[0]->max_length; }
};
class Item_func_benchmark :public Item_int_func
@@ -639,7 +686,7 @@ class Item_func_benchmark :public Item_int_func
{}
longlong val_int();
const char *func_name() const { return "benchmark"; }
- void fix_length_and_dec() { decimals=0; max_length=1; maybe_null=0; }
+ void fix_length_and_dec() { max_length=1; maybe_null=0; }
};
@@ -771,7 +818,7 @@ class Item_func_get_lock :public Item_int_func
Item_func_get_lock(Item *a,Item *b) :Item_int_func(a,b) {}
longlong val_int();
const char *func_name() const { return "get_lock"; }
- void fix_length_and_dec() { decimals=0; max_length=1; maybe_null=1;}
+ void fix_length_and_dec() { max_length=1; maybe_null=1;}
};
class Item_func_release_lock :public Item_int_func
@@ -781,7 +828,7 @@ class Item_func_release_lock :public Item_int_func
Item_func_release_lock(Item *a) :Item_int_func(a) {}
longlong val_int();
const char *func_name() const { return "release_lock"; }
- void fix_length_and_dec() { decimals=0; max_length=1; maybe_null=1;}
+ void fix_length_and_dec() { max_length=1; maybe_null=1;}
};
/* replication functions */
@@ -793,7 +840,7 @@ class Item_master_pos_wait :public Item_int_func
Item_master_pos_wait(Item *a,Item *b) :Item_int_func(a,b) {}
longlong val_int();
const char *func_name() const { return "master_pos_wait"; }
- void fix_length_and_dec() { decimals=0; max_length=1; maybe_null=1;}
+ void fix_length_and_dec() { max_length=1; maybe_null=1;}
};
@@ -863,34 +910,62 @@ class Item_func_match :public Item_real_func
{
public:
List<Item> fields;
+ String value;
TABLE *table;
- uint key;
- bool join_key;
Item_func_match *master;
- FT_DOCLIST *ft_handler;
+ FT_INFO * ft_handler;
+ Item *concat;
+ byte *record;
+ uint key, mode;
+ bool join_key;
Item_func_match(List<Item> &a, Item *b): Item_real_func(b),
- fields(a), table(0), join_key(0), master(0), ft_handler(0) {}
+ fields(a), table(0), master(0), ft_handler(0),
+ concat(0), key(0), join_key(0) {}
~Item_func_match()
{
- if (!master)
+ if (!master && ft_handler)
{
- if (ft_handler)
- {
- ft_close_search(ft_handler);
- if(join_key)
- table->file->ft_handler=0;
- }
+ ft_handler->please->close_search(ft_handler);
+ ft_handler=0;
+ if(join_key)
+ table->file->ft_handler=0;
}
+ if (concat) delete concat;
}
- const char *func_name() const { return "match"; }
enum Functype functype() const { return FT_FUNC; }
void update_used_tables() {}
bool fix_fields(THD *thd,struct st_table_list *tlist);
bool eq(const Item *) const;
- double val();
longlong val_int() { return val()!=0.0; }
+ double val();
bool fix_index();
void init_search(bool no_order);
};
+
+class Item_func_match_nl :public Item_func_match
+{
+public:
+ Item_func_match_nl(List<Item> &a, Item *b):
+ Item_func_match(a,b) { mode=FT_NL; }
+ const char *func_name() const { return "match_nl"; }
+};
+
+class Item_func_match_bool :public Item_func_match
+{
+public:
+ Item_func_match_bool(List<Item> &a, Item *b):
+ Item_func_match(a,b) { mode=FT_BOOL; }
+ const char *func_name() const { return "match_bool"; }
+};
+
+/* For type casts */
+
+enum Item_cast
+{
+ ITEM_CAST_BINARY, ITEM_CAST_SIGNED_INT, ITEM_CAST_UNSIGNED_INT,
+ ITEM_CAST_DATE, ITEM_CAST_TIME, ITEM_CAST_DATETIME
+};
+
+Item *create_func_cast(Item *a, Item_cast cast_type);
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index bd7fde79629..c64fdc7a049 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -17,7 +17,7 @@
/* This file defines all string functions
** Warning: Some string functions doesn't always put and end-null on a String
-** (This shouldn't be neaded)
+** (This shouldn't be needed)
*/
#ifdef __GNUC__
@@ -30,7 +30,9 @@
#ifdef HAVE_CRYPT_H
#include <crypt.h>
#endif
-
+#ifdef HAVE_OPENSSL
+#include <openssl/des.h>
+#endif /* HAVE_OPENSSL */
#include "md5.h"
String empty_string("");
@@ -66,14 +68,18 @@ String *Item_func_md5::val_str(String *str)
String * sptr= args[0]->val_str(str);
if (sptr)
{
- MD5_CTX context;
+ my_MD5_CTX context;
unsigned char digest[16];
null_value=0;
- MD5Init (&context);
- MD5Update (&context,(unsigned char *) sptr->ptr(), sptr->length());
- MD5Final (digest, &context);
- str->alloc(32); // Ensure that memory is free
+ my_MD5Init (&context);
+ my_MD5Update (&context,(unsigned char *) sptr->ptr(), sptr->length());
+ my_MD5Final (digest, &context);
+ if (str->alloc(32)) // Ensure that memory is free
+ {
+ null_value=1;
+ return 0;
+ }
sprintf((char *) str->ptr(),
"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
digest[0], digest[1], digest[2], digest[3],
@@ -199,11 +205,167 @@ void Item_func_concat::fix_length_and_dec()
}
}
+/*
+ Function des_encrypt() by tonu@spam.ee & monty
+ Works only if compiled with OpenSSL library support.
+ This returns a binary string where first character is
+ CHAR(128 | key-number).
+ If one uses a string key key_number is 127.
+ Encryption result is longer than original by formula:
+ new_length= org_length + (8-(org_length % 8))+1
+*/
+
+String *Item_func_des_encrypt::val_str(String *str)
+{
+#ifdef HAVE_OPENSSL
+ des_cblock ivec;
+ struct st_des_keyblock keyblock;
+ struct st_des_keyschedule keyschedule;
+ const char *append_str="********";
+ uint key_number, res_length, tail;
+ String *res= args[0]->val_str(str);
+
+ if ((null_value=args[0]->null_value))
+ return 0;
+ if ((res_length=res->length()) == 0)
+ return &empty_string;
+
+ if (arg_count == 1)
+ {
+ /* Protect against someone doing FLUSH DES_KEY_FILE */
+ VOID(pthread_mutex_lock(&LOCK_des_key_file));
+ keyschedule= des_keyschedule[key_number=des_default_key];
+ VOID(pthread_mutex_unlock(&LOCK_des_key_file));
+ }
+ else if (args[1]->result_type() == INT_RESULT)
+ {
+ key_number= (uint) args[1]->val_int();
+ if (key_number > 9)
+ goto error;
+ VOID(pthread_mutex_lock(&LOCK_des_key_file));
+ keyschedule= des_keyschedule[key_number];
+ VOID(pthread_mutex_unlock(&LOCK_des_key_file));
+ }
+ else
+ {
+ String *keystr=args[1]->val_str(&tmp_value);
+ if (!keystr)
+ goto error;
+ key_number=127; // User key string
+
+ /* We make good 24-byte (168 bit) key from given plaintext key with MD5 */
+ bzero((char*) &ivec,sizeof(ivec));
+ EVP_BytesToKey(EVP_des_ede3_cbc(),EVP_md5(),NULL,
+ (uchar*) keystr->ptr(), (int) keystr->length(),
+ 1, (uchar*) &keyblock,ivec);
+ des_set_key_unchecked(&keyblock.key1,keyschedule.ks1);
+ des_set_key_unchecked(&keyblock.key2,keyschedule.ks2);
+ des_set_key_unchecked(&keyblock.key3,keyschedule.ks3);
+ }
+
+ /*
+ The problem: DES algorithm requires original data to be in 8-bytes
+ chunks. Missing bytes get filled with '*'s and result of encryption
+ can be up to 8 bytes longer than original string. When decrypted,
+ we do not know the size of original string :(
+ We add one byte with value 0x1..0x8 as the last byte of the padded
+ string marking change of string length.
+ */
+
+ tail= (8-(res_length) % 8); // 1..8 marking extra length
+ res_length+=tail;
+ if (tail && res->append(append_str, tail) || tmp_value.alloc(res_length+1))
+ goto error;
+ (*res)[res_length-1]=tail; // save extra length
+ tmp_value.length(res_length+1);
+ tmp_value[0]=(char) (128 | key_number);
+ // Real encryption
+ bzero((char*) &ivec,sizeof(ivec));
+ des_ede3_cbc_encrypt((const uchar*) (res->ptr()),
+ (uchar*) (tmp_value.ptr()+1),
+ res_length,
+ keyschedule.ks1,
+ keyschedule.ks2,
+ keyschedule.ks3,
+ &ivec, TRUE);
+ return &tmp_value;
+
+error:
+#endif /* HAVE_OPENSSL */
+ null_value=1;
+ return 0;
+}
+
+
+String *Item_func_des_decrypt::val_str(String *str)
+{
+#ifdef HAVE_OPENSSL
+ des_key_schedule ks1, ks2, ks3;
+ des_cblock ivec;
+ struct st_des_keyblock keyblock;
+ struct st_des_keyschedule keyschedule;
+ String *res= args[0]->val_str(str);
+ uint length=res->length(),tail;
+
+ if ((null_value=args[0]->null_value))
+ return 0;
+ length=res->length();
+ if (length < 9 || (length % 8) != 1 || !((*res)[0] & 128))
+ return res; // Skip decryption if not encrypted
+
+ if (arg_count == 1) // If automatic uncompression
+ {
+ uint key_number=(uint) (*res)[0] & 127;
+ // Check if automatic key and that we have privilege to uncompress using it
+ if (!(current_thd->master_access & PROCESS_ACL) || key_number > 9)
+ goto error;
+ VOID(pthread_mutex_lock(&LOCK_des_key_file));
+ keyschedule= des_keyschedule[key_number];
+ VOID(pthread_mutex_unlock(&LOCK_des_key_file));
+ }
+ else
+ {
+ // We make good 24-byte (168 bit) key from given plaintext key with MD5
+ String *keystr=args[1]->val_str(&tmp_value);
+ if (!keystr)
+ goto error;
+
+ bzero((char*) &ivec,sizeof(ivec));
+ EVP_BytesToKey(EVP_des_ede3_cbc(),EVP_md5(),NULL,
+ (uchar*) keystr->ptr(),(int) keystr->length(),
+ 1,(uchar*) &keyblock,ivec);
+ // Here we set all 64-bit keys (56 effective) one by one
+ des_set_key_unchecked(&keyblock.key1,keyschedule.ks1);
+ des_set_key_unchecked(&keyblock.key2,keyschedule.ks2);
+ des_set_key_unchecked(&keyblock.key3,keyschedule.ks3);
+ }
+ if (tmp_value.alloc(length-1))
+ goto error;
+
+ bzero((char*) &ivec,sizeof(ivec));
+ des_ede3_cbc_encrypt((const uchar*) res->ptr()+1,
+ (uchar*) (tmp_value.ptr()),
+ length-1,
+ keyschedule.ks1,
+ keyschedule.ks2,
+ keyschedule.ks3,
+ &ivec, FALSE);
+ /* Restore old length of key */
+ if ((tail=(uint) (uchar) tmp_value[length-2]) > 8)
+ goto error; // Wrong key
+ tmp_value.length(length-1-tail);
+ return &tmp_value;
+
+error:
+#endif /* HAVE_OPENSSL */
+ null_value=1;
+ return 0;
+}
/*
-** concat with separator. First arg is the separator
-** concat_ws takes at least two arguments.
+ concat with separator. First arg is the separator
+ concat_ws takes at least two arguments.
*/
String *Item_func_concat_ws::val_str(String *str)
@@ -232,7 +394,7 @@ String *Item_func_concat_ws::val_str(String *str)
for (i++; i < arg_count ; i++)
{
if (!(res2= args[i]->val_str(use_as_buff)) || !res2->length())
- continue; // Skipp NULL and empty string
+ continue; // Skip NULL and empty string
if (res->length() + sep_str->length() + res2->length() >
max_allowed_packet)
@@ -385,7 +547,7 @@ void Item_func_reverse::fix_length_and_dec()
/*
** Replace all occurences of string2 in string1 with string3.
-** Don't reallocate val_str() if not neaded
+** Don't reallocate val_str() if not needed
*/
/* TODO: Fix that this works with binary strings when using USE_MB */
@@ -521,7 +683,7 @@ String *Item_func_insert::val_str(String *str)
}
#endif
if (start > res->length()+1)
- return res; // Wrong param; skipp insert
+ return res; // Wrong param; skip insert
if (length > res->length()-start)
length=res->length()-start;
if (res->length() - length + res2->length() > max_allowed_packet)
@@ -1098,7 +1260,7 @@ void Item_func_soundex::fix_length_and_dec()
/*
If alpha, map input letter to soundex code.
- If not alpha and remove_garbage is set then skipp to next char
+ If not alpha and remove_garbage is set then skip to next char
else return 0
*/
@@ -1125,12 +1287,12 @@ String *Item_func_soundex::val_str(String *str)
if ((null_value=args[0]->null_value))
return 0; /* purecov: inspected */
- if (str_value.alloc(max(res->length(),4)))
+ if (tmp_value.alloc(max(res->length(),4)))
return str; /* purecov: inspected */
- char *to= (char *) str_value.ptr();
+ char *to= (char *) tmp_value.ptr();
char *from= (char *) res->ptr(), *end=from+res->length();
- while (from != end && isspace(*from)) // Skipp pre-space
+ while (from != end && isspace(*from)) // Skip pre-space
from++; /* purecov: inspected */
if (from == end)
return &empty_string; // No alpha characters.
@@ -1151,11 +1313,11 @@ String *Item_func_soundex::val_str(String *str)
last_ch = ch; // save code of last input letter
} // for next double-letter check
}
- for (end=(char*) str_value.ptr()+4 ; to < end ; to++)
+ for (end=(char*) tmp_value.ptr()+4 ; to < end ; to++)
*to = '0';
*to=0; // end string
- str_value.length((uint) (to-str_value.ptr()));
- return &str_value;
+ tmp_value.length((uint) (to-tmp_value.ptr()));
+ return &tmp_value;
}
@@ -1305,7 +1467,7 @@ String *Item_func_make_set::val_str(String *str)
if (bits & 1)
{
String *res= (*ptr)->val_str(str);
- if (res) // Skipp nulls
+ if (res) // Skip nulls
{
if (!first_found)
{ // First argument
@@ -1610,6 +1772,45 @@ String *Item_func_conv::val_str(String *str)
return str;
}
+
+String *Item_func_hex::val_str(String *str)
+{
+ if (args[0]->result_type() != STRING_RESULT)
+ {
+ /* Return hex of unsigned longlong value */
+ longlong dec= args[0]->val_int();
+ char ans[65],*ptr;
+ if ((null_value= args[0]->null_value))
+ return 0;
+ ptr= longlong2str(dec,ans,16);
+ if (str->copy(ans,(uint32) (ptr-ans)))
+ return &empty_string; // End of memory
+ return str;
+ }
+
+ /* Convert given string to a hex string, character by character */
+ String *res= args[0]->val_str(str);
+ const char *from, *end;
+ char *to;
+ if (!res || tmp_value.alloc(res->length()*2))
+ {
+ null_value=1;
+ return 0;
+ }
+ null_value=0;
+ tmp_value.length(res->length()*2);
+ for (from=res->ptr(), end=from+res->length(), to= (char*) tmp_value.ptr();
+ from != end ;
+ from++, to+=2)
+ {
+ uint tmp=(uint) (uchar) *from;
+ to[0]=_dig_vec[tmp >> 4];
+ to[1]=_dig_vec[tmp & 15];
+ }
+ return &tmp_value;
+}
+
+
#include <my_dir.h> // For my_stat
String *Item_load_file::val_str(String *str)
@@ -1731,7 +1932,7 @@ String* Item_func_inet_ntoa::val_str(String* str)
// we handle the possibility of an 8-byte IP address
// however, we do not want to confuse those who are just using
// 4 byte ones
-
+
for (p= buf + 8; p > buf+4 && p[-1] == 0 ; p-- ) ;
num[3]='.';
while (p-- > buf)
diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h
index 1b829b19439..1279a5099d5 100644
--- a/sql/item_strfunc.h
+++ b/sql/item_strfunc.h
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -35,6 +35,11 @@ public:
double val();
enum Item_result result_type () const { return STRING_RESULT; }
void left_right_max_length();
+ Field *tmp_table_field(TABLE *t_arg)
+ {
+ if (!t_arg) return result_field;
+ return (max_length > 255) ? (Field *)new Field_blob(max_length,maybe_null, name,t_arg, binary) : (Field *) new Field_string(max_length,maybe_null, name,t_arg, binary);
+ }
};
class Item_func_md5 :public Item_str_func
@@ -222,6 +227,29 @@ public:
const char *func_name() const { return "password"; }
};
+class Item_func_des_encrypt :public Item_str_func
+{
+ String tmp_value;
+public:
+ Item_func_des_encrypt(Item *a) :Item_str_func(a) {}
+ Item_func_des_encrypt(Item *a, Item *b): Item_str_func(a,b) {}
+ String *val_str(String *);
+ void fix_length_and_dec()
+ { maybe_null=1; max_length = args[0]->max_length+8; }
+ const char *func_name() const { return "des_encrypt"; }
+};
+
+class Item_func_des_decrypt :public Item_str_func
+{
+ String tmp_value;
+public:
+ Item_func_des_decrypt(Item *a) :Item_str_func(a) {}
+ Item_func_des_decrypt(Item *a, Item *b): Item_str_func(a,b) {}
+ String *val_str(String *);
+ void fix_length_and_dec() { maybe_null=1; max_length = args[0]->max_length; }
+ const char *func_name() const { return "des_decrypt"; }
+};
+
class Item_func_encrypt :public Item_str_func
{
String tmp_value;
@@ -274,6 +302,7 @@ public:
class Item_func_soundex :public Item_str_func
{
+ String tmp_value;
public:
Item_func_soundex(Item *a) :Item_str_func(a) {}
String *val_str(String *);
@@ -389,12 +418,25 @@ public:
void fix_length_and_dec() { decimals=0; max_length=64; }
};
+
+class Item_func_hex :public Item_str_func
+{
+ String tmp_value;
+public:
+ Item_func_hex(Item *a) :Item_str_func(a) {}
+ const char *func_name() const { return "hex"; }
+ String *val_str(String *);
+ void fix_length_and_dec() { decimals=0; max_length=args[0]->max_length*2; }
+};
+
+
class Item_func_binary :public Item_str_func
{
public:
Item_func_binary(Item *a) :Item_str_func(a) {}
const char *func_name() const { return "binary"; }
- String *val_str(String *a) { return (args[0]->val_str(a)); }
+ String *val_str(String *a)
+ { a=args[0]->val_str(a); null_value=args[0]->null_value; return a; }
void fix_length_and_dec() { binary=1; max_length=args[0]->max_length; }
void print(String *str) { print_op(str); }
};
diff --git a/sql/item_sum.cc b/sql/item_sum.cc
index 5b24a1eda90..e8f16e3ed56 100644
--- a/sql/item_sum.cc
+++ b/sql/item_sum.cc
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -30,7 +30,7 @@ Item_sum::Item_sum(List<Item> &list)
if ((args=(Item**) sql_alloc(sizeof(Item*)*arg_count)))
{
uint i=0;
- List_iterator<Item> li(list);
+ List_iterator_fast<Item> li(list);
Item *item;
while ((item=li++))
@@ -52,6 +52,8 @@ void Item_sum::make_field(Send_field *tmp_field)
tmp_field->flags=0;
if (!maybe_null)
tmp_field->flags|= NOT_NULL_FLAG;
+ if (unsigned_flag)
+ tmp_field->flags |= UNSIGNED_FLAG;
tmp_field->length=max_length;
tmp_field->decimals=decimals;
tmp_field->type=(result_type() == INT_RESULT ? FIELD_TYPE_LONG :
@@ -150,7 +152,7 @@ Item_sum_hybrid::fix_fields(THD *thd,TABLE_LIST *tables)
return 1;
hybrid_type=item->result_type();
if (hybrid_type == INT_RESULT)
- max_length=21;
+ max_length=20;
else if (hybrid_type == REAL_RESULT)
max_length=float_length(decimals);
else
@@ -158,6 +160,7 @@ Item_sum_hybrid::fix_fields(THD *thd,TABLE_LIST *tables)
decimals=item->decimals;
maybe_null=item->maybe_null;
binary=item->binary;
+ unsigned_flag=item->unsigned_flag;
result_field=0;
null_value=1;
fix_length_and_dec();
@@ -323,12 +326,27 @@ double Item_sum_hybrid::val()
{
if (null_value)
return 0.0;
- if (hybrid_type == STRING_RESULT)
- {
+ switch (hybrid_type) {
+ case STRING_RESULT:
String *res; res=val_str(&str_value);
return res ? atof(res->c_ptr()) : 0.0;
+ case INT_RESULT:
+ if (unsigned_flag)
+ return ulonglong2double(sum_int);
+ return (double) sum_int;
+ case REAL_RESULT:
+ return sum;
}
- return sum;
+ return 0; // Keep compiler happy
+}
+
+longlong Item_sum_hybrid::val_int()
+{
+ if (null_value)
+ return 0;
+ if (hybrid_type == INT_RESULT)
+ return sum_int;
+ return (longlong) Item_sum_hybrid::val();
}
@@ -337,25 +355,26 @@ Item_sum_hybrid::val_str(String *str)
{
if (null_value)
return 0;
- if (hybrid_type == STRING_RESULT)
+ switch (hybrid_type) {
+ case STRING_RESULT:
return &value;
- str->set(sum,decimals);
- return str;
+ case REAL_RESULT:
+ str->set(sum,decimals);
+ break;
+ case INT_RESULT:
+ if (unsigned_flag)
+ str->set((ulonglong) sum_int);
+ else
+ str->set((longlong) sum_int);
+ break;
+ }
+ return str; // Keep compiler happy
}
-
bool Item_sum_min::add()
{
- if (hybrid_type != STRING_RESULT)
- {
- double nr=args[0]->val();
- if (!args[0]->null_value && (null_value || nr < sum))
- {
- sum=nr;
- null_value=0;
- }
- }
- else
+ switch (hybrid_type) {
+ case STRING_RESULT:
{
String *result=args[0]->val_str(&tmp_value);
if (!args[0]->null_value &&
@@ -366,22 +385,39 @@ bool Item_sum_min::add()
null_value=0;
}
}
- return 0;
-}
-
-
-bool Item_sum_max::add()
-{
- if (hybrid_type != STRING_RESULT)
+ break;
+ case INT_RESULT:
+ {
+ longlong nr=args[0]->val_int();
+ if (!args[0]->null_value && (null_value ||
+ (unsigned_flag &&
+ (ulonglong) nr < (ulonglong) sum_int) ||
+ (!unsigned_flag && nr < sum_int)))
+ {
+ sum_int=nr;
+ null_value=0;
+ }
+ }
+ break;
+ case REAL_RESULT:
{
double nr=args[0]->val();
- if (!args[0]->null_value && (null_value || nr > sum))
+ if (!args[0]->null_value && (null_value || nr < sum))
{
sum=nr;
null_value=0;
}
}
- else
+ break;
+ }
+ return 0;
+}
+
+
+bool Item_sum_max::add()
+{
+ switch (hybrid_type) {
+ case STRING_RESULT:
{
String *result=args[0]->val_str(&tmp_value);
if (!args[0]->null_value &&
@@ -392,6 +428,31 @@ bool Item_sum_max::add()
null_value=0;
}
}
+ break;
+ case INT_RESULT:
+ {
+ longlong nr=args[0]->val_int();
+ if (!args[0]->null_value && (null_value ||
+ (unsigned_flag &&
+ (ulonglong) nr > (ulonglong) sum_int) ||
+ (!unsigned_flag && nr > sum_int)))
+ {
+ sum_int=nr;
+ null_value=0;
+ }
+ }
+ break;
+ case REAL_RESULT:
+ {
+ double nr=args[0]->val();
+ if (!args[0]->null_value && (null_value || nr > sum))
+ {
+ sum=nr;
+ null_value=0;
+ }
+ }
+ break;
+ }
return 0;
}
@@ -676,9 +737,17 @@ Item_sum_hybrid::min_max_update_int_field(int offset)
nr=args[0]->val_int();
if (!args[0]->null_value)
{
- if (result_field->is_null(offset) ||
- (cmp_sign > 0 ? old_nr > nr : old_nr < nr))
+ if (result_field->is_null(offset))
old_nr=nr;
+ else
+ {
+ bool res=(unsigned_flag ?
+ (ulonglong) old_nr > (ulonglong) nr :
+ old_nr > nr);
+ /* (cmp_sign > 0 && res) || (!(cmp_sign > 0) && !res) */
+ if ((cmp_sign > 0) ^ (!res))
+ old_nr=nr;
+ }
result_field->set_notnull();
}
else if (result_field->is_null(offset))
@@ -788,11 +857,74 @@ String *Item_std_field::val_str(String *str)
#include "sql_select.h"
+static int simple_raw_key_cmp(void* arg, byte* key1, byte* key2)
+{
+ return memcmp(key1, key2, *(uint*) arg);
+}
+
+static int simple_str_key_cmp(void* arg, byte* key1, byte* key2)
+{
+ return my_sortcmp((char*) key1, (char*) key2, *(uint*) arg);
+}
+
+/*
+ Did not make this one static - at least gcc gets confused when
+ I try to declare a static function as a friend. If you can figure
+ out the syntax to make a static function a friend, make this one
+ static
+*/
+
+int composite_key_cmp(void* arg, byte* key1, byte* key2)
+{
+ Item_sum_count_distinct* item = (Item_sum_count_distinct*)arg;
+ Field **field = item->table->field;
+ Field **field_end= field + item->table->fields;
+ uint32 *lengths=item->field_lengths;
+ for (; field < field_end; ++field)
+ {
+ Field* f = *field;
+ int len = *lengths++;
+ int res = f->key_cmp(key1, key2);
+ if (res)
+ return res;
+ key1 += len;
+ key2 += len;
+ }
+ return 0;
+}
+
+/*
+ helper function for walking the tree when we dump it to MyISAM -
+ tree_walk will call it for each leaf
+*/
+
+int dump_leaf(byte* key, uint32 count __attribute__((unused)),
+ Item_sum_count_distinct* item)
+{
+ byte* buf = item->table->record[0];
+ int error;
+ /*
+ The first item->rec_offset bytes are taken care of with
+ restore_record(table,2) in setup()
+ */
+ memcpy(buf + item->rec_offset, key, item->tree.size_of_element);
+ if ((error = item->table->file->write_row(buf)))
+ {
+ if (error != HA_ERR_FOUND_DUPP_KEY &&
+ error != HA_ERR_FOUND_DUPP_UNIQUE)
+ return 1;
+ }
+ return 0;
+}
+
+
Item_sum_count_distinct::~Item_sum_count_distinct()
{
if (table)
free_tmp_table(current_thd, table);
delete tmp_table_param;
+ if (use_tree)
+ delete_tree(&tree);
}
@@ -829,22 +961,125 @@ bool Item_sum_count_distinct::setup(THD *thd)
tmp_table_param->cleanup();
}
if (!(table=create_tmp_table(thd, tmp_table_param, list, (ORDER*) 0, 1,
- 0, 0, current_lex->options | thd->options)))
+ 0, 0,
+ current_lex->select->options | thd->options)))
return 1;
table->file->extra(HA_EXTRA_NO_ROWS); // Don't update rows
+ table->no_rows=1;
+
+
+ // no blobs, otherwise it would be MyISAM
+ if (table->db_type == DB_TYPE_HEAP)
+ {
+ qsort_cmp2 compare_key;
+ void* cmp_arg;
+
+ // to make things easier for dump_leaf if we ever have to dump to MyISAM
+ restore_record(table,2);
+
+ if (table->fields == 1)
+ {
+ /*
+ If we have only one field, which is the most common use of
+ count(distinct), it is much faster to use a simpler key
+ compare method that can take advantage of not having to worry
+ about other fields
+ */
+ Field* field = table->field[0];
+ switch(field->type())
+ {
+ /*
+ If we have a string, we must take care of charsets and case
+ sensitivity
+ */
+ case FIELD_TYPE_STRING:
+ case FIELD_TYPE_VAR_STRING:
+ compare_key = (qsort_cmp2)(field->binary() ? simple_raw_key_cmp:
+ simple_str_key_cmp);
+ break;
+ default:
+ /*
+ Since at this point we cannot have blobs anything else can
+ be compared with memcmp
+ */
+ compare_key = (qsort_cmp2)simple_raw_key_cmp;
+ break;
+ }
+ key_length = field->pack_length();
+ cmp_arg = (void*) &key_length;
+ rec_offset = 1;
+ }
+ else // too bad, cannot cheat - there is more than one field
+ {
+ bool all_binary = 1;
+ Field** field, **field_end;
+ field_end = (field = table->field) + table->fields;
+ uint32 *lengths;
+ if (!(field_lengths=
+ (uint32*) thd->alloc(sizeof(uint32) * table->fields)))
+ return 1;
+
+ for (key_length = 0, lengths=field_lengths; field < field_end; ++field)
+ {
+ uint32 length= (*field)->pack_length();
+ key_length += length;
+ *lengths++ = length;
+ if (!(*field)->binary())
+ all_binary = 0; // Can't break loop here
+ }
+ rec_offset = table->reclength - key_length;
+ if (all_binary)
+ {
+ compare_key = (qsort_cmp2)simple_raw_key_cmp;
+ cmp_arg = (void*) &key_length;
+ }
+ else
+ {
+ compare_key = (qsort_cmp2) composite_key_cmp ;
+ cmp_arg = (void*) this;
+ }
+ }
+
+ init_tree(&tree, min(max_heap_table_size, sortbuff_size/16), 0,
+ key_length, compare_key, 0, NULL, cmp_arg);
+ use_tree = 1;
+
+ /*
+ The only time key_length could be 0 is if someone does
+ count(distinct) on a char(0) field - stupid thing to do,
+ but this has to be handled - otherwise someone can crash
+ the server with a DoS attack
+ */
+ max_elements_in_tree = ((key_length) ? max_heap_table_size/key_length :
+ 1);
+ }
return 0;
}
+int Item_sum_count_distinct::tree_to_myisam()
+{
+ if (create_myisam_from_heap(table, tmp_table_param,
+ HA_ERR_RECORD_FILE_FULL, 1) ||
+ tree_walk(&tree, (tree_walk_action)&dump_leaf, (void*)this,
+ left_root_right))
+ return 1;
+ delete_tree(&tree);
+ use_tree = 0;
+ return 0;
+}
+
void Item_sum_count_distinct::reset()
{
- if (table)
+ if (use_tree)
+ reset_tree(&tree);
+ else if (table)
{
table->file->extra(HA_EXTRA_NO_CACHE);
table->file->delete_all_rows();
table->file->extra(HA_EXTRA_WRITE_CACHE);
- (void) add();
}
+ (void) add();
}
bool Item_sum_count_distinct::add()
@@ -859,7 +1094,21 @@ bool Item_sum_count_distinct::add()
if ((*field)->is_real_null(0))
return 0; // Don't count NULL
- if ((error=table->file->write_row(table->record[0])))
+ if (use_tree)
+ {
+ /*
+ If the tree got too big, convert to MyISAM, otherwise insert into the
+ tree.
+ */
+ if (tree.elements_in_tree > max_elements_in_tree)
+ {
+ if(tree_to_myisam())
+ return 1;
+ }
+ else if (!tree_insert(&tree, table->record[0] + rec_offset, 0))
+ return 1;
+ }
+ else if ((error=table->file->write_row(table->record[0])))
{
if (error != HA_ERR_FOUND_DUPP_KEY &&
error != HA_ERR_FOUND_DUPP_UNIQUE)
@@ -875,6 +1124,8 @@ longlong Item_sum_count_distinct::val_int()
{
if (!table) // Empty query
return LL(0);
+ if (use_tree)
+ return tree.elements_in_tree;
table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
return table->file->records;
}
@@ -897,7 +1148,7 @@ void Item_udf_sum::reset()
bool Item_udf_sum::add()
{
- DBUG_ENTER("Item_udf_sum::reset");
+ DBUG_ENTER("Item_udf_sum::add");
udf.add(&null_value);
DBUG_RETURN(0);
}
diff --git a/sql/item_sum.h b/sql/item_sum.h
index f68dfee1b61..4840ae8298d 100644
--- a/sql/item_sum.h
+++ b/sql/item_sum.h
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -21,6 +21,8 @@
#pragma interface /* gcc class implementation */
#endif
+#include <my_tree.h>
+
class Item_sum :public Item_result_field
{
public:
@@ -144,13 +146,36 @@ class Item_sum_count_distinct :public Item_sum_int
TABLE *table;
table_map used_table_cache;
bool fix_fields(THD *thd,TABLE_LIST *tables);
+ uint32 *field_lengths;
TMP_TABLE_PARAM *tmp_table_param;
- bool always_null;
+ TREE tree;
+ uint key_length;
+
+ // calculated based on max_heap_table_size. If reached,
+ // walk the tree and dump it into MyISAM table
+ uint max_elements_in_tree;
+
+ // the first few bytes of record ( at least one)
+ // are just markers for deleted and NULLs. We want to skip them since
+ // they will just bloat the tree without providing any valuable info
+ int rec_offset;
+
+ // If there are no blobs, we can use a tree, which
+ // is faster than heap table. In that case, we still use the table
+ // to help get things set up, but we insert nothing in it
+ bool use_tree;
+ bool always_null; // Set to 1 if the result is always NULL
+
+ int tree_to_myisam();
+
+ friend int composite_key_cmp(void* arg, byte* key1, byte* key2);
+ friend int dump_leaf(byte* key, uint32 count __attribute__((unused)),
+ Item_sum_count_distinct* item);
public:
Item_sum_count_distinct(List<Item> &list)
:Item_sum_int(list),table(0),used_table_cache(~(table_map) 0),
- tmp_table_param(0),always_null(0)
+ tmp_table_param(0),use_tree(0),always_null(0)
{ quick_group=0; }
~Item_sum_count_distinct();
table_map used_tables() const { return used_table_cache; }
@@ -246,6 +271,7 @@ class Item_sum_hybrid :public Item_sum
protected:
String value,tmp_value;
double sum;
+ longlong sum_int;
Item_result hybrid_type;
int cmp_sign;
table_map used_table_cache;
@@ -261,12 +287,13 @@ class Item_sum_hybrid :public Item_sum
void reset()
{
sum=0.0;
+ sum_int=0;
value.length(0);
null_value=1;
add();
}
double val();
- longlong val_int() { return (longlong) val(); } /* Real as default */
+ longlong val_int();
void reset_field();
String *val_str(String *);
void make_const() { used_table_cache=0; }
diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc
index b198900d24e..8f55a02b020 100644
--- a/sql/item_timefunc.cc
+++ b/sql/item_timefunc.cc
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -672,7 +672,7 @@ String *Item_func_date_format::val_str(String *str)
else
size=format_length(format);
if (format == str)
- str=&str_value; // Save result here
+ str= &str_value; // Save result here
if (str->alloc(size))
{
null_value=1;
@@ -1123,3 +1123,13 @@ longlong Item_extract::val_int()
}
return 0; // Impossible
}
+
+
+void Item_typecast::print(String *str)
+{
+ str->append("CAST(");
+ args[0]->print(str);
+ str->append(" AS ");
+ str->append(func_name());
+ str->append(')');
+}
diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h
index 1343cdad390..32b85e7f028 100644
--- a/sql/item_timefunc.h
+++ b/sql/item_timefunc.h
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -229,6 +229,33 @@ public:
const char *func_name() const { return "date"; }
void fix_length_and_dec() { decimals=0; max_length=10; }
bool save_in_field(Field *to);
+ void make_field(Send_field *tmp_field)
+ {
+ init_make_field(tmp_field,FIELD_TYPE_DATE);
+ }
+ Field *tmp_table_field(TABLE *t_arg)
+ {
+ if (!t_arg) return result_field;
+ return new Field_date(maybe_null, name, t_arg);
+ }
+};
+
+
+class Item_date_func :public Item_str_func
+{
+public:
+ Item_date_func() :Item_str_func() {}
+ Item_date_func(Item *a) :Item_str_func(a) {}
+ Item_date_func(Item *a,Item *b) :Item_str_func(a,b) {}
+ void make_field(Send_field *tmp_field)
+ {
+ init_make_field(tmp_field,FIELD_TYPE_DATETIME);
+ }
+ Field *tmp_table_field(TABLE *t_arg)
+ {
+ if (!t_arg) return result_field;
+ return new Field_datetime(maybe_null, name, t_arg);
+ }
};
@@ -247,6 +274,15 @@ public:
{ str_value.set(buff,buff_length); return &str_value; }
const char *func_name() const { return "curtime"; }
void fix_length_and_dec();
+ void make_field(Send_field *tmp_field)
+ {
+ init_make_field(tmp_field,FIELD_TYPE_TIME);
+ }
+ Field *tmp_table_field(TABLE *t_arg)
+ {
+ if (!t_arg) return result_field;
+ return new Field_time(maybe_null, name, t_arg);
+ }
};
@@ -263,15 +299,15 @@ public:
};
-class Item_func_now :public Item_func
+class Item_func_now :public Item_date_func
{
longlong value;
char buff[20];
uint buff_length;
TIME ltime;
public:
- Item_func_now() :Item_func() {}
- Item_func_now(Item *a) :Item_func(a) {}
+ Item_func_now() :Item_date_func() {}
+ Item_func_now(Item *a) :Item_date_func(a) {}
enum Item_result result_type () const { return STRING_RESULT; }
double val() { return (double) value; }
longlong val_int() { return value; }
@@ -307,16 +343,16 @@ public:
};
-class Item_func_from_unixtime :public Item_func
+class Item_func_from_unixtime :public Item_date_func
{
public:
- Item_func_from_unixtime(Item *a) :Item_func(a) {}
+ Item_func_from_unixtime(Item *a) :Item_date_func(a) {}
double val() { return (double) Item_func_from_unixtime::val_int(); }
longlong val_int();
String *val_str(String *str);
const char *func_name() const { return "from_unixtime"; }
void fix_length_and_dec() { decimals=0; max_length=19; }
- enum Item_result result_type () const { return STRING_RESULT; }
+// enum Item_result result_type () const { return STRING_RESULT; }
bool get_date(TIME *res,bool fuzzy_date);
};
@@ -330,6 +366,15 @@ public:
String *val_str(String *);
void fix_length_and_dec() { maybe_null=1; max_length=13; }
const char *func_name() const { return "sec_to_time"; }
+ void make_field(Send_field *tmp_field)
+ {
+ init_make_field(tmp_field,FIELD_TYPE_TIME);
+ }
+ Field *tmp_table_field(TABLE *t_arg)
+ {
+ if (!t_arg) return result_field;
+ return new Field_time(maybe_null, name, t_arg);
+ }
};
enum interval_type { INTERVAL_YEAR, INTERVAL_MONTH, INTERVAL_DAY,
@@ -339,7 +384,7 @@ enum interval_type { INTERVAL_YEAR, INTERVAL_MONTH, INTERVAL_DAY,
INTERVAL_HOUR_MINUTE, INTERVAL_HOUR_SECOND,
INTERVAL_MINUTE_SECOND};
-class Item_date_add_interval :public Item_str_func
+class Item_date_add_interval :public Item_date_func
{
const interval_type int_type;
String value;
@@ -347,7 +392,7 @@ class Item_date_add_interval :public Item_str_func
public:
Item_date_add_interval(Item *a,Item *b,interval_type type_arg,bool neg_arg)
- :Item_str_func(a,b),int_type(type_arg), date_sub_interval(neg_arg) {}
+ :Item_date_func(a,b),int_type(type_arg), date_sub_interval(neg_arg) {}
String *val_str(String *);
const char *func_name() const { return "date_add_interval"; }
void fix_length_and_dec() { maybe_null=1; max_length=19; value.alloc(32);}
@@ -368,3 +413,62 @@ class Item_extract :public Item_int_func
const char *func_name() const { return "extract"; }
void fix_length_and_dec();
};
+
+class Item_typecast :public Item_str_func
+{
+public:
+ Item_typecast(Item *a) :Item_str_func(a) {}
+ String *val_str(String *a)
+ { a=args[0]->val_str(a); null_value=args[0]->null_value; return a; }
+ void fix_length_and_dec() { max_length=args[0]->max_length; }
+ void print(String *str);
+};
+
+
+class Item_date_typecast :public Item_typecast
+{
+public:
+ Item_date_typecast(Item *a) :Item_typecast(a) {}
+ const char *func_name() const { return "date"; }
+ void make_field(Send_field *tmp_field)
+ {
+ init_make_field(tmp_field,FIELD_TYPE_DATE);
+ }
+ Field *tmp_table_field(TABLE *t_arg)
+ {
+ if (!t_arg) return result_field;
+ return new Field_date(maybe_null, name, t_arg);
+ }
+};
+
+class Item_time_typecast :public Item_typecast
+{
+public:
+ Item_time_typecast(Item *a) :Item_typecast(a) {}
+ const char *func_name() const { return "time"; }
+ void make_field(Send_field *tmp_field)
+ {
+ init_make_field(tmp_field,FIELD_TYPE_TIME);
+ }
+ Field *tmp_table_field(TABLE *t_arg)
+ {
+ if (!t_arg) return result_field;
+ return new Field_time(maybe_null, name, t_arg);
+ }
+};
+
+class Item_datetime_typecast :public Item_typecast
+{
+public:
+ Item_datetime_typecast(Item *a) :Item_typecast(a) {}
+ const char *func_name() const { return "datetime"; }
+ void make_field(Send_field *tmp_field)
+ {
+ init_make_field(tmp_field,FIELD_TYPE_DATETIME);
+ }
+ Field *tmp_table_field(TABLE *t_arg)
+ {
+ if (!t_arg) return result_field;
+ return new Field_datetime(maybe_null, name, t_arg);
+ }
+};
diff --git a/sql/item_uniq.cc b/sql/item_uniq.cc
index 80ed6433fd8..88e0cbbc0e6 100644
--- a/sql/item_uniq.cc
+++ b/sql/item_uniq.cc
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
diff --git a/sql/item_uniq.h b/sql/item_uniq.h
index ff11222e2ee..4be64ecc74a 100644
--- a/sql/item_uniq.h
+++ b/sql/item_uniq.h
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
diff --git a/sql/key.cc b/sql/key.cc
index 80a33bc45d3..d2f483e3d73 100644
--- a/sql/key.cc
+++ b/sql/key.cc
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -96,7 +96,7 @@ void key_copy(byte *key,TABLE *table,uint idx,uint key_length)
length=min(key_length,key_part->length);
set_if_smaller(blob_length,length);
int2store(key,(uint) blob_length);
- key+=2; // Skipp length info
+ key+=2; // Skip length info
memcpy(key,pos,blob_length);
}
else
@@ -250,7 +250,7 @@ void key_unpack(String *to,TABLE *table,uint idx)
bool check_if_key_used(TABLE *table, uint idx, List<Item> &fields)
{
- List_iterator<Item> f(fields);
+ List_iterator_fast<Item> f(fields);
KEY_PART_INFO *key_part,*key_part_end;
for (key_part=table->key_info[idx].key_part,key_part_end=key_part+
table->key_info[idx].key_parts ;
@@ -258,7 +258,7 @@ bool check_if_key_used(TABLE *table, uint idx, List<Item> &fields)
key_part++)
{
Item_field *field;
-
+
if (key_part->field == table->timestamp_field)
return 1; // Can't be used for update
diff --git a/sql/lex.h b/sql/lex.h
index 30fbf46e354..6bee4152e48 100644
--- a/sql/lex.h
+++ b/sql/lex.h
@@ -70,10 +70,13 @@ static SYMBOL symbols[] = {
{ "BIGINT", SYM(BIGINT),0,0},
{ "BIT", SYM(BIT_SYM),0,0},
{ "BINARY", SYM(BINARY),0,0},
+ { "BINLOG", SYM(BINLOG_SYM),0,0},
{ "BLOB", SYM(BLOB_SYM),0,0},
{ "BOOL", SYM(BOOL_SYM),0,0},
+ { "BOOLEAN", SYM(BOOLEAN_SYM),0,0},
{ "BOTH", SYM(BOTH),0,0},
{ "BY", SYM(BY),0,0},
+ { "CACHE", SYM(CACHE_SYM),0,0},
{ "CASCADE", SYM(CASCADE),0,0},
{ "CASE", SYM(CASE_SYM),0,0},
{ "CHAR", SYM(CHAR_SYM),0,0},
@@ -82,6 +85,8 @@ static SYMBOL symbols[] = {
{ "CHANGED", SYM(CHANGED),0,0},
{ "CHECK", SYM(CHECK_SYM),0,0},
{ "CHECKSUM", SYM(CHECKSUM_SYM),0,0},
+ { "CIPHER", SYM(CIPHER_SYM),0,0},
+ { "CLOSE", SYM(CLOSE_SYM),0,0},
{ "COLUMN", SYM(COLUMN_SYM),0,0},
{ "COLUMNS", SYM(COLUMNS),0,0},
{ "COMMENT", SYM(COMMENT_SYM),0,0},
@@ -106,12 +111,16 @@ static SYMBOL symbols[] = {
{ "DAY_SECOND", SYM(DAY_SECOND_SYM),0,0},
{ "DEC", SYM(DECIMAL_SYM),0,0},
{ "DECIMAL", SYM(DECIMAL_SYM),0,0},
+ { "DES_KEY_FILE", SYM(DES_KEY_FILE),0,0},
{ "DEFAULT", SYM(DEFAULT),0,0},
{ "DELAYED", SYM(DELAYED_SYM),0,0},
{ "DELAY_KEY_WRITE", SYM(DELAY_KEY_WRITE_SYM),0,0},
{ "DELETE", SYM(DELETE_SYM),0,0},
+ { "DEMAND", SYM(DEMAND_SYM),0,0},
{ "DESC", SYM(DESC),0,0},
{ "DESCRIBE", SYM(DESCRIBE),0,0},
+ { "DIRECTORY", SYM(DIRECTORY_SYM),0,0},
+ { "DISABLE", SYM(DISABLE_SYM),0,0},
{ "DISTINCT", SYM(DISTINCT),0,0},
{ "DISTINCTROW", SYM(DISTINCT),0,0}, /* Access likes this */
{ "DO", SYM(DO_SYM),0,0},
@@ -123,8 +132,10 @@ static SYMBOL symbols[] = {
{ "ELSE", SYM(ELSE),0,0},
{ "ESCAPE", SYM(ESCAPE_SYM),0,0},
{ "ESCAPED", SYM(ESCAPED),0,0},
+ { "ENABLE", SYM(ENABLE_SYM),0,0},
{ "ENCLOSED", SYM(ENCLOSED),0,0},
{ "ENUM", SYM(ENUM),0,0},
+ { "EVENTS", SYM(EVENTS_SYM),0,0},
{ "EXPLAIN", SYM(DESCRIBE),0,0},
{ "EXISTS", SYM(EXISTS),0,0},
{ "EXTENDED", SYM(EXTENDED_SYM),0,0},
@@ -147,13 +158,12 @@ static SYMBOL symbols[] = {
{ "FULL", SYM(FULL),0,0},
{ "FULLTEXT", SYM(FULLTEXT_SYM),0,0},
{ "FUNCTION", SYM(UDF_SYM),0,0},
- { "GEMINI", SYM(GEMINI_SYM),0,0},
- { "GEMINI_SPIN_RETRIES", SYM(GEMINI_SPIN_RETRIES),0,0},
{ "GLOBAL", SYM(GLOBAL_SYM),0,0},
{ "GRANT", SYM(GRANT),0,0},
{ "GRANTS", SYM(GRANTS),0,0},
{ "GROUP", SYM(GROUP),0,0},
{ "HAVING", SYM(HAVING),0,0},
+ { "HANDLER", SYM(HANDLER_SYM),0,0},
{ "HEAP", SYM(HEAP_SYM),0,0},
{ "HIGH_PRIORITY", SYM(HIGH_PRIORITY),0,0},
{ "HOUR", SYM(HOUR_SYM),0,0},
@@ -164,12 +174,14 @@ static SYMBOL symbols[] = {
{ "IGNORE", SYM(IGNORE_SYM),0,0},
{ "IN", SYM(IN_SYM),0,0},
{ "INDEX", SYM(INDEX),0,0},
+ { "INDEXES", SYM(INDEXES),0,0},
{ "INFILE", SYM(INFILE),0,0},
{ "INNER", SYM(INNER_SYM),0,0},
{ "INNOBASE", SYM(INNOBASE_SYM),0,0},
{ "INNODB", SYM(INNOBASE_SYM),0,0},
{ "INSERT", SYM(INSERT),0,0},
{ "INSERT_ID", SYM(INSERT_ID),0,0},
+ { "INSERT_METHOD", SYM(INSERT_METHOD),0,0},
{ "INT", SYM(INT_SYM),0,0},
{ "INTEGER", SYM(INT_SYM),0,0},
{ "INTERVAL", SYM(INTERVAL_SYM),0,0},
@@ -183,10 +195,12 @@ static SYMBOL symbols[] = {
{ "IS", SYM(IS),0,0},
{ "ISOLATION", SYM(ISOLATION),0,0},
{ "ISAM", SYM(ISAM_SYM),0,0},
+ { "ISSUER", SYM(ISSUER_SYM),0,0},
{ "JOIN", SYM(JOIN_SYM),0,0},
{ "KEY", SYM(KEY_SYM),0,0},
{ "KEYS", SYM(KEYS),0,0},
{ "KILL", SYM(KILL_SYM),0,0},
+ { "LAST", SYM(LAST_SYM),0,0},
{ "LAST_INSERT_ID", SYM(LAST_INSERT_ID),0,0},
{ "LEADING", SYM(LEADING),0,0},
{ "LEFT", SYM(LEFT),0,0},
@@ -210,8 +224,10 @@ static SYMBOL symbols[] = {
{ "MASTER_LOG_POS", SYM(MASTER_LOG_POS_SYM),0,0},
{ "MASTER_PASSWORD", SYM(MASTER_PASSWORD_SYM),0,0},
{ "MASTER_PORT", SYM(MASTER_PORT_SYM),0,0},
+ { "MASTER_SERVER_ID", SYM(MASTER_SERVER_ID_SYM),0,0},
{ "MASTER_USER", SYM(MASTER_USER_SYM),0,0},
{ "MAX_ROWS", SYM(MAX_ROWS),0,0},
+ { "MAX_QUERIES_PER_HOUR", SYM(MAX_QUERIES_PER_HOUR), 0,0},
{ "MATCH", SYM(MATCH),0,0},
{ "MEDIUMBLOB", SYM(MEDIUMBLOB),0,0},
{ "MEDIUMTEXT", SYM(MEDIUMTEXT),0,0},
@@ -229,11 +245,14 @@ static SYMBOL symbols[] = {
{ "MYISAM", SYM(MYISAM_SYM),0,0},
{ "NATURAL", SYM(NATURAL),0,0},
{ "NATIONAL", SYM(NATIONAL_SYM),0,0},
+ { "NEXT", SYM(NEXT_SYM),0,0},
+ { "NEW", SYM(NEW_SYM),0,0},
{ "NCHAR", SYM(NCHAR_SYM),0,0},
- { "NUMERIC", SYM(NUMERIC_SYM),0,0},
{ "NO", SYM(NO_SYM),0,0},
{ "NOT", SYM(NOT),0,0},
{ "NULL", SYM(NULL_SYM),0,0},
+ { "NUMERIC", SYM(NUMERIC_SYM),0,0},
+ { "OFF", SYM(OFF),0,0},
{ "ON", SYM(ON),0,0},
{ "OPEN", SYM(OPEN_SYM),0,0},
{ "OPTIMIZE", SYM(OPTIMIZE),0,0},
@@ -248,11 +267,13 @@ static SYMBOL symbols[] = {
{ "PASSWORD", SYM(PASSWORD),0,0},
{ "PURGE", SYM(PURGE),0,0},
{ "PRECISION", SYM(PRECISION),0,0},
+ { "PREV", SYM(PREV_SYM),0,0},
{ "PRIMARY", SYM(PRIMARY_SYM),0,0},
{ "PROCEDURE", SYM(PROCEDURE),0,0},
{ "PROCESS" , SYM(PROCESS),0,0},
{ "PROCESSLIST", SYM(PROCESSLIST_SYM),0,0},
{ "PRIVILEGES", SYM(PRIVILEGES),0,0},
+ { "QUERY", SYM(QUERY_SYM),0,0},
{ "QUICK", SYM(QUICK),0,0},
{ "RAID0", SYM(RAID_0_SYM),0,0},
{ "READ", SYM(READ_SYM),0,0},
@@ -264,6 +285,7 @@ static SYMBOL symbols[] = {
{ "REPAIR", SYM(REPAIR),0,0},
{ "REPLACE", SYM(REPLACE),0,0},
{ "REPEATABLE", SYM(REPEATABLE_SYM),0,0},
+ { "REQUIRE", SYM(REQUIRE_SYM),0,0},
{ "RESET", SYM(RESET_SYM),0,0},
{ "RESTORE", SYM(RESTORE_SYM),0,0},
{ "RESTRICT", SYM(RESTRICT),0,0},
@@ -279,6 +301,7 @@ static SYMBOL symbols[] = {
{ "SERIALIZABLE", SYM(SERIALIZABLE_SYM),0,0},
{ "SESSION", SYM(SESSION_SYM),0,0},
{ "SET", SYM(SET),0,0},
+ { "SIGNED", SYM(SIGNED_SYM),0,0},
{ "SHARE", SYM(SHARE_SYM),0,0},
{ "SHOW", SYM(SHOW),0,0},
{ "SHUTDOWN", SYM(SHUTDOWN),0,0},
@@ -290,17 +313,22 @@ static SYMBOL symbols[] = {
{ "SQL_BIG_SELECTS", SYM(SQL_BIG_SELECTS),0,0},
{ "SQL_BIG_TABLES", SYM(SQL_BIG_TABLES),0,0},
{ "SQL_BUFFER_RESULT", SYM(SQL_BUFFER_RESULT),0,0},
+ { "SQL_CACHE", SYM(SQL_CACHE_SYM), 0, 0},
+ { "SQL_CALC_FOUND_ROWS", SYM(SQL_CALC_FOUND_ROWS),0,0},
{ "SQL_LOG_BIN", SYM(SQL_LOG_BIN),0,0},
{ "SQL_LOG_OFF", SYM(SQL_LOG_OFF),0,0},
{ "SQL_LOG_UPDATE", SYM(SQL_LOG_UPDATE),0,0},
{ "SQL_LOW_PRIORITY_UPDATES", SYM(SQL_LOW_PRIORITY_UPDATES),0,0},
{ "SQL_MAX_JOIN_SIZE",SYM(SQL_MAX_JOIN_SIZE), 0, 0},
+ { "SQL_NO_CACHE", SYM(SQL_NO_CACHE_SYM), 0, 0},
+ { "SQL_QUERY_CACHE_TYPE",SYM(SQL_QUERY_CACHE_TYPE_SYM), 0, 0},
{ "SQL_QUOTE_SHOW_CREATE",SYM(SQL_QUOTE_SHOW_CREATE), 0, 0},
{ "SQL_SAFE_UPDATES", SYM(SQL_SAFE_UPDATES),0,0},
{ "SQL_SELECT_LIMIT", SYM(SQL_SELECT_LIMIT),0,0},
{ "SQL_SLAVE_SKIP_COUNTER", SYM(SQL_SLAVE_SKIP_COUNTER),0,0},
{ "SQL_SMALL_RESULT", SYM(SQL_SMALL_RESULT),0,0},
{ "SQL_WARNINGS", SYM(SQL_WARNINGS),0,0},
+ { "SSL", SYM(SSL_SYM),0,0},
{ "STRAIGHT_JOIN", SYM(STRAIGHT_JOIN),0,0},
{ "START", SYM(START_SYM),0,0},
{ "STARTING", SYM(STARTING),0,0},
@@ -308,6 +336,7 @@ static SYMBOL symbols[] = {
{ "STRING", SYM(STRING_SYM),0,0},
{ "STOP", SYM(STOP_SYM),0,0},
{ "STRIPED", SYM(RAID_STRIPED_SYM),0,0},
+ { "SUBJECT", SYM(SUBJECT_SYM),0,0},
{ "TABLE", SYM(TABLE_SYM),0,0},
{ "TABLES", SYM(TABLES),0,0},
{ "TEMPORARY", SYM(TEMPORARY),0,0},
@@ -343,6 +372,7 @@ static SYMBOL symbols[] = {
{ "WRITE", SYM(WRITE_SYM),0,0},
{ "WHEN", SYM(WHEN_SYM),0,0},
{ "WHERE", SYM(WHERE),0,0},
+ { "X509", SYM(X509_SYM),0,0},
{ "YEAR", SYM(YEAR_SYM),0,0},
{ "YEAR_MONTH", SYM(YEAR_MONTH_SYM),0,0},
{ "ZEROFILL", SYM(ZEROFILL),0,0},
@@ -363,7 +393,9 @@ static SYMBOL sql_functions[] = {
{ "BIT_COUNT", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_bit_count)},
{ "BIT_OR", SYM(BIT_OR),0,0},
{ "BIT_AND", SYM(BIT_AND),0,0},
+ { "CAST", SYM(CAST_SYM),0,0},
{ "CEILING", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_ceiling)},
+ { "BIT_LENGTH", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_bit_length)},
{ "CHAR_LENGTH", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_char_length)},
{ "CHARACTER_LENGTH", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_char_length)},
{ "COALESCE", SYM(COALESCE),0,0},
@@ -371,6 +403,7 @@ static SYMBOL sql_functions[] = {
{ "CONCAT_WS", SYM(CONCAT_WS),0,0},
{ "CONNECTION_ID", SYM(FUNC_ARG0),0,CREATE_FUNC(create_func_connection_id)},
{ "CONV", SYM(FUNC_ARG3),0,CREATE_FUNC(create_func_conv)},
+ { "CONVERT", SYM(CONVERT_SYM),0,0},
{ "COUNT", SYM(COUNT_SYM),0,0},
{ "COS", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_cos)},
{ "COT", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_cot)},
@@ -385,6 +418,8 @@ static SYMBOL sql_functions[] = {
{ "DAYOFYEAR", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_dayofyear)},
{ "DECODE", SYM(DECODE_SYM),0,0},
{ "DEGREES", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_degrees)},
+ { "DES_ENCRYPT", SYM(DES_ENCRYPT_SYM),0,0},
+ { "DES_DECRYPT", SYM(DES_DECRYPT_SYM),0,0},
{ "ELT", SYM(ELT_FUNC),0,0},
{ "ENCODE", SYM(ENCODE_SYM),0,0},
{ "ENCRYPT", SYM(ENCRYPT),0,0},
@@ -395,6 +430,7 @@ static SYMBOL sql_functions[] = {
{ "FIND_IN_SET", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_find_in_set)},
{ "FLOOR", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_floor)},
{ "FORMAT", SYM(FORMAT_SYM),0,0},
+ { "FOUND_ROWS", SYM(FUNC_ARG0),0,CREATE_FUNC(create_func_found_rows)},
{ "FROM_DAYS", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_from_days)},
{ "FROM_UNIXTIME", SYM(FROM_UNIXTIME),0,0},
{ "GET_LOCK", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_get_lock)},
diff --git a/sql/lex_symbol.h b/sql/lex_symbol.h
index a011e27b59e..9fff1751b1b 100644
--- a/sql/lex_symbol.h
+++ b/sql/lex_symbol.h
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
diff --git a/sql/lock.cc b/sql/lock.cc
index aa06822e03f..5d2856278b6 100644
--- a/sql/lock.cc
+++ b/sql/lock.cc
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -55,33 +55,13 @@ MYSQL_LOCK *mysql_lock_tables(THD *thd,TABLE **tables,uint count)
Someone has issued LOCK ALL TABLES FOR READ and we want a write lock
Wait until the lock is gone
*/
- if (thd->global_read_lock) // This thread had the read locks
+ if (wait_if_global_read_lock(thd, 1))
{
- my_error(ER_TABLE_NOT_LOCKED_FOR_WRITE,MYF(0),
- write_lock_used->table_name);
my_free((gptr) sql_lock,MYF(0));
sql_lock=0;
break;
}
-
- pthread_mutex_lock(&LOCK_open);
- thd->mysys_var->current_mutex= &LOCK_open;
- thd->mysys_var->current_cond= &COND_refresh;
- thd->proc_info="Waiting for table";
-
- while (global_read_lock && ! thd->killed &&
- thd->version == refresh_version)
- {
- (void) pthread_cond_wait(&COND_refresh,&LOCK_open);
- }
- pthread_mutex_unlock(&LOCK_open);
- pthread_mutex_lock(&thd->mysys_var->mutex);
- thd->mysys_var->current_mutex= 0;
- thd->mysys_var->current_cond= 0;
- thd->proc_info= 0;
- pthread_mutex_unlock(&thd->mysys_var->mutex);
-
- if (thd->version != refresh_version || thd->killed)
+ if (thd->version != refresh_version)
{
my_free((gptr) sql_lock,MYF(0));
goto retry;
@@ -394,6 +374,36 @@ static MYSQL_LOCK *get_lock_data(THD *thd, TABLE **table_ptr, uint count,
*****************************************************************************/
/*
+ Lock and wait for the named lock.
+ Returns 0 on ok
+*/
+
+int lock_and_wait_for_table_name(THD *thd, TABLE_LIST *table_list)
+{
+ int lock_retcode;
+ int error= -1;
+ DBUG_ENTER("lock_and_wait_for_table_name");
+
+ if (wait_if_global_read_lock(thd,0))
+ DBUG_RETURN(1);
+ VOID(pthread_mutex_lock(&LOCK_open));
+ if ((lock_retcode = lock_table_name(thd, table_list)) < 0)
+ goto end;
+ if (lock_retcode && wait_for_locked_table_names(thd, table_list))
+ {
+ unlock_table_name(thd, table_list);
+ goto end;
+ }
+ error=0;
+
+end:
+ pthread_mutex_unlock(&LOCK_open);
+ start_waiting_global_read_lock(thd);
+ DBUG_RETURN(error);
+}
+
+
+/*
Put a not open table with an old refresh version in the table cache.
This will force any other threads that uses the table to release it
as soon as possible.
@@ -404,7 +414,6 @@ static MYSQL_LOCK *get_lock_data(THD *thd, TABLE **table_ptr, uint count,
> 0 table locked, but someone is using it
*/
-
int lock_table_name(THD *thd, TABLE_LIST *table_list)
{
TABLE *table;
@@ -422,10 +431,11 @@ int lock_table_name(THD *thd, TABLE_LIST *table_list)
if (table->in_use == thd)
DBUG_RETURN(0);
- /* Create a table entry with the right key and with an old refresh version */
- /* Note that we must use my_malloc() here as this is freed by the table
- cache */
-
+ /*
+ Create a table entry with the right key and with an old refresh version
+ Note that we must use my_malloc() here as this is freed by the table
+ cache
+ */
if (!(table= (TABLE*) my_malloc(sizeof(*table)+key_length,
MYF(MY_WME | MY_ZEROFILL))))
DBUG_RETURN(-1);
@@ -503,3 +513,102 @@ static void print_lock_error(int error)
DBUG_VOID_RETURN;
}
+
+/****************************************************************************
+ Handling of global read locks
+
+ The global locks are handled through the global variables:
+ global_read_lock
+ waiting_for_read_lock
+ protect_against_global_read_lock
+****************************************************************************/
+
+volatile uint global_read_lock=0;
+static volatile uint protect_against_global_read_lock=0;
+static volatile uint waiting_for_read_lock=0;
+
+bool lock_global_read_lock(THD *thd)
+{
+ DBUG_ENTER("lock_global_read_lock");
+
+ if (!thd->global_read_lock)
+ {
+ (void) pthread_mutex_lock(&LOCK_open);
+ const char *old_message=thd->enter_cond(&COND_refresh, &LOCK_open,
+ "Waiting to get readlock");
+ DBUG_PRINT("info",
+ ("waiting_for: %d protect_against: %d",
+ waiting_for_read_lock, protect_against_global_read_lock));
+
+ waiting_for_read_lock++;
+ while (protect_against_global_read_lock && !thd->killed)
+ pthread_cond_wait(&COND_refresh, &LOCK_open);
+ waiting_for_read_lock--;
+ thd->exit_cond(old_message);
+ if (thd->killed)
+ {
+ (void) pthread_mutex_unlock(&LOCK_open);
+ DBUG_RETURN(1);
+ }
+ thd->global_read_lock=1;
+ global_read_lock++;
+ (void) pthread_mutex_unlock(&LOCK_open);
+ }
+ DBUG_RETURN(0);
+}
+
+void unlock_global_read_lock(THD *thd)
+{
+ uint tmp;
+ thd->global_read_lock=0;
+ pthread_mutex_lock(&LOCK_open);
+ tmp= --global_read_lock;
+ pthread_mutex_unlock(&LOCK_open);
+ /* Send the signal outside the mutex to avoid a context switch */
+ if (!tmp)
+ pthread_cond_broadcast(&COND_refresh);
+}
+
+
+bool wait_if_global_read_lock(THD *thd, bool abort_on_refresh)
+{
+ const char *old_message;
+ bool result=0;
+ DBUG_ENTER("wait_if_global_read_lock");
+
+ (void) pthread_mutex_lock(&LOCK_open);
+ if (global_read_lock)
+ {
+ if (thd->global_read_lock) // This thread had the read locks
+ {
+ my_error(ER_CANT_UPDATE_WITH_READLOCK,MYF(0));
+ (void) pthread_mutex_unlock(&LOCK_open);
+ DBUG_RETURN(1);
+ }
+ old_message=thd->enter_cond(&COND_refresh, &LOCK_open,
+ "Waiting for release of readlock");
+ while (global_read_lock && ! thd->killed &&
+ (!abort_on_refresh || thd->version == refresh_version))
+ (void) pthread_cond_wait(&COND_refresh,&LOCK_open);
+ if (thd->killed)
+ result=1;
+ thd->exit_cond(old_message);
+ }
+ if (!abort_on_refresh && !result)
+ protect_against_global_read_lock++;
+ pthread_mutex_unlock(&LOCK_open);
+ DBUG_RETURN(result);
+}
+
+
+void start_waiting_global_read_lock(THD *thd)
+{
+ bool tmp;
+ DBUG_ENTER("start_waiting_global_read_lock");
+ (void) pthread_mutex_lock(&LOCK_open);
+ tmp= (!--protect_against_global_read_lock && waiting_for_read_lock);
+ (void) pthread_mutex_unlock(&LOCK_open);
+ if (tmp)
+ pthread_cond_broadcast(&COND_refresh);
+ DBUG_VOID_RETURN;
+}
diff --git a/sql/log.cc b/sql/log.cc
index bc2b19d921f..892780d3882 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -29,6 +29,7 @@
#include <my_dir.h>
#include <stdarg.h>
#include <m_ctype.h> // For test_if_number
+#include <assert.h>
MYSQL_LOG mysql_log,mysql_update_log,mysql_slow_log,mysql_bin_log;
extern I_List<i_string> binlog_do_db, binlog_ignore_db;
@@ -81,7 +82,8 @@ static int find_uniq_filename(char *name)
MYSQL_LOG::MYSQL_LOG(): last_time(0), query_start(0),index_file(-1),
name(0), log_type(LOG_CLOSED),write_error(0),
- inited(0), no_rotate(0)
+ inited(0), file_id(1),no_rotate(0),
+ need_start_event(1)
{
/*
We don't want to intialize LOCK_Log here as the thread system may
@@ -136,14 +138,19 @@ bool MYSQL_LOG::open_index( int options)
MYF(MY_WME))) < 0);
}
-void MYSQL_LOG::init(enum_log_type log_type_arg)
+void MYSQL_LOG::init(enum_log_type log_type_arg,
+ enum cache_type io_cache_type_arg,
+ bool no_auto_events_arg)
{
log_type = log_type_arg;
+ io_cache_type = io_cache_type_arg;
+ no_auto_events = no_auto_events_arg;
if (!inited)
{
inited=1;
(void) pthread_mutex_init(&LOCK_log,MY_MUTEX_INIT_SLOW);
(void) pthread_mutex_init(&LOCK_index, MY_MUTEX_INIT_SLOW);
+ (void) pthread_cond_init(&update_cond, 0);
}
}
@@ -157,16 +164,17 @@ void MYSQL_LOG::close_index()
}
void MYSQL_LOG::open(const char *log_name, enum_log_type log_type_arg,
- const char *new_name)
+ const char *new_name, enum cache_type io_cache_type_arg,
+ bool no_auto_events_arg)
{
MY_STAT tmp_stat;
char buff[512];
File file= -1;
bool do_magic;
-
+ int open_flags = O_CREAT | O_APPEND | O_BINARY;
if (!inited && log_type_arg == LOG_BIN && *fn_ext(log_name))
no_rotate = 1;
- init(log_type_arg);
+ init(log_type_arg,io_cache_type_arg,no_auto_events_arg);
if (!(name=my_strdup(log_name,MYF(MY_WME))))
goto err;
@@ -174,7 +182,12 @@ void MYSQL_LOG::open(const char *log_name, enum_log_type log_type_arg,
strmov(log_file_name,new_name);
else if (generate_new_name(log_file_name, name))
goto err;
-
+
+ if (io_cache_type == SEQ_READ_APPEND)
+ open_flags |= O_RDWR;
+ else
+ open_flags |= O_WRONLY;
+
if (log_type == LOG_BIN && !index_file_name[0])
fn_format(index_file_name, name, mysql_data_home, ".index", 6);
@@ -182,9 +195,9 @@ void MYSQL_LOG::open(const char *log_name, enum_log_type log_type_arg,
do_magic = ((log_type == LOG_BIN) && !my_stat(log_file_name,
&tmp_stat, MYF(0)));
- if ((file=my_open(log_file_name,O_CREAT | O_APPEND | O_WRONLY | O_BINARY,
+ if ((file=my_open(log_file_name,open_flags,
MYF(MY_WME | ME_WAITTANG))) < 0 ||
- init_io_cache(&log_file, file, IO_SIZE, WRITE_CACHE,
+ init_io_cache(&log_file, file, IO_SIZE, io_cache_type,
my_tell(file,MYF(MY_WME)), 0, MYF(MY_WME | MY_NABP)))
goto err;
@@ -220,6 +233,7 @@ void MYSQL_LOG::open(const char *log_name, enum_log_type log_type_arg,
}
else if (log_type == LOG_BIN)
{
+ bool error;
/*
Explanation of the boolean black magic:
if we are supposed to write magic number try write
@@ -230,9 +244,14 @@ void MYSQL_LOG::open(const char *log_name, enum_log_type log_type_arg,
if ((do_magic && my_b_write(&log_file, (byte*) BINLOG_MAGIC, 4)) ||
open_index(O_APPEND | O_RDWR | O_CREAT))
goto err;
- Start_log_event s;
- bool error;
- s.write(&log_file);
+
+ if (need_start_event && !no_auto_events)
+ {
+ Start_log_event s;
+ s.set_log_pos(this);
+ s.write(&log_file);
+ need_start_event=0;
+ }
flush_io_cache(&log_file);
pthread_mutex_lock(&LOCK_index);
error=(my_write(index_file, (byte*) log_file_name, strlen(log_file_name),
@@ -254,9 +273,7 @@ err:
end_io_cache(&log_file);
x_free(name); name=0;
log_type=LOG_CLOSED;
-
return;
-
}
int MYSQL_LOG::get_current_log(LOG_INFO* linfo)
@@ -269,7 +286,8 @@ int MYSQL_LOG::get_current_log(LOG_INFO* linfo)
}
// if log_name is "" we stop at the first entry
-int MYSQL_LOG::find_first_log(LOG_INFO* linfo, const char* log_name)
+int MYSQL_LOG::find_first_log(LOG_INFO* linfo, const char* log_name,
+ bool need_mutex)
{
if (index_file < 0)
return LOG_INFO_INVALID;
@@ -280,7 +298,8 @@ int MYSQL_LOG::find_first_log(LOG_INFO* linfo, const char* log_name)
// mutex needed because we need to make sure the file pointer does not move
// from under our feet
- pthread_mutex_lock(&LOCK_index);
+ if (need_mutex)
+ pthread_mutex_lock(&LOCK_index);
if (init_io_cache(&io_cache, index_file, IO_SIZE, READ_CACHE, (my_off_t) 0,
0, MYF(MY_WME)))
{
@@ -309,14 +328,15 @@ int MYSQL_LOG::find_first_log(LOG_INFO* linfo, const char* log_name)
error = 0;
err:
- pthread_mutex_unlock(&LOCK_index);
+ if (need_mutex)
+ pthread_mutex_unlock(&LOCK_index);
end_io_cache(&io_cache);
return error;
}
-int MYSQL_LOG::find_next_log(LOG_INFO* linfo)
+int MYSQL_LOG::find_next_log(LOG_INFO* linfo, bool need_lock)
{
// mutex needed because we need to make sure the file pointer does not move
// from under our feet
@@ -325,8 +345,8 @@ int MYSQL_LOG::find_next_log(LOG_INFO* linfo)
char* fname = linfo->log_file_name;
IO_CACHE io_cache;
uint length;
-
- pthread_mutex_lock(&LOCK_index);
+ if (need_lock)
+ pthread_mutex_lock(&LOCK_index);
if (init_io_cache(&io_cache, index_file, IO_SIZE,
READ_CACHE, (my_off_t) linfo->index_file_offset, 0,
MYF(MY_WME)))
@@ -344,16 +364,135 @@ int MYSQL_LOG::find_next_log(LOG_INFO* linfo)
error = 0;
err:
- pthread_mutex_unlock(&LOCK_index);
+ if (need_lock)
+ pthread_mutex_unlock(&LOCK_index);
end_io_cache(&io_cache);
return error;
}
-
+
+int MYSQL_LOG::reset_logs(THD* thd)
+{
+ LOG_INFO linfo;
+ int error=0;
+ const char* save_name;
+ enum_log_type save_log_type;
+ pthread_mutex_lock(&LOCK_log);
+ if (find_first_log(&linfo,""))
+ {
+ error=1;
+ goto err;
+ }
+
+ for(;;)
+ {
+ my_delete(linfo.log_file_name, MYF(MY_WME));
+ if (find_next_log(&linfo))
+ break;
+ }
+ save_name=name;
+ name=0;
+ save_log_type=log_type;
+ close(1);
+ my_delete(index_file_name, MYF(MY_WME));
+ if (thd && !thd->slave_thread)
+ need_start_event=1;
+ open(save_name,save_log_type,0,io_cache_type,no_auto_events);
+ my_free((gptr)save_name,MYF(0));
+err:
+ pthread_mutex_unlock(&LOCK_log);
+ return error;
+}
+
+
+int MYSQL_LOG::purge_first_log(struct st_relay_log_info* rli)
+{
+ // pre-conditions
+ DBUG_ASSERT(is_open());
+ DBUG_ASSERT(index_file >= 0);
+ DBUG_ASSERT(rli->slave_running == 1);
+ DBUG_ASSERT(!strcmp(rli->linfo.log_file_name,rli->relay_log_name));
+ /*
+ Assume that we have previously read the first log and
+ stored it in rli->relay_log_name
+ */
+ DBUG_ASSERT(rli->linfo.index_file_offset ==
+ strlen(rli->relay_log_name) + 1);
+ int tmp_fd;
+ char* fname, *io_buf;
+ int error = 0;
+
+ if (!(fname= (char*) my_malloc(IO_SIZE+FN_REFLEN, MYF(MY_WME))))
+ return 1;
+ pthread_mutex_lock(&LOCK_index);
+ my_seek(index_file,rli->linfo.index_file_offset,
+ MY_SEEK_SET, MYF(MY_WME));
+ io_buf = fname + FN_REFLEN;
+ strxmov(fname,rli->relay_log_name,".tmp",NullS);
+
+ if ((tmp_fd = my_open(fname,O_CREAT|O_BINARY|O_RDWR, MYF(MY_WME))) < 0)
+ {
+ error = 1;
+ goto err;
+ }
+ for (;;)
+ {
+ int bytes_read;
+ bytes_read = my_read(index_file, (byte*) io_buf, IO_SIZE, MYF(0));
+ if (bytes_read < 0) // error
+ {
+ error=1;
+ goto err;
+ }
+ if (!bytes_read)
+ break; // end of file
+ // otherwise, we've read something and need to write it out
+ if (my_write(tmp_fd, (byte*) io_buf, bytes_read, MYF(MY_WME|MY_NABP)))
+ {
+ error=1;
+ goto err;
+ }
+ }
+
+err:
+ if (tmp_fd)
+ my_close(tmp_fd, MYF(MY_WME));
+ if (error)
+ my_delete(fname, MYF(0)); // do not report error if the file is not there
+ else
+ {
+ my_close(index_file, MYF(MY_WME));
+ if (my_rename(fname,index_file_name,MYF(MY_WME)) ||
+ (index_file=my_open(index_file_name,O_BINARY|O_RDWR|O_APPEND,
+ MYF(MY_WME)))<0 ||
+ my_delete(rli->relay_log_name, MYF(MY_WME)))
+ error=1;
+ if ((error=find_first_log(&rli->linfo,"",0/*no mutex*/)))
+ {
+ char buff[22];
+ sql_print_error("next log error=%d,offset=%s,log=%s",error,
+ llstr(rli->linfo.index_file_offset,buff),
+ rli->linfo.log_file_name);
+ goto err2;
+ }
+ rli->relay_log_pos = 4;
+ strnmov(rli->relay_log_name,rli->linfo.log_file_name,
+ sizeof(rli->relay_log_name));
+ }
+ /*
+ No need to free io_buf because we allocated both fname and io_buf in
+ one malloc()
+ */
+
+err2:
+ pthread_mutex_unlock(&LOCK_index);
+ my_free(fname, MYF(MY_WME));
+ return error;
+}
+
+
int MYSQL_LOG::purge_logs(THD* thd, const char* to_log)
{
- if (index_file < 0) return LOG_INFO_INVALID;
- if (no_rotate) return LOG_INFO_PURGE_NO_ROTATE;
int error;
char fname[FN_REFLEN];
char *p;
@@ -364,6 +503,10 @@ int MYSQL_LOG::purge_logs(THD* thd, const char* to_log)
LINT_INIT(purge_offset);
IO_CACHE io_cache;
+ if (index_file < 0)
+ return LOG_INFO_INVALID;
+ if (no_rotate)
+ return LOG_INFO_PURGE_NO_ROTATE;
pthread_mutex_lock(&LOCK_index);
if (init_io_cache(&io_cache,index_file, IO_SIZE*2, READ_CACHE, (my_off_t) 0,
@@ -385,9 +528,8 @@ int MYSQL_LOG::purge_logs(THD* thd, const char* to_log)
goto err;
}
logs_to_keep_inited = 1;
-
- for(;;)
+ for (;;)
{
my_off_t init_purge_offset= my_b_tell(&io_cache);
if (!(fname_len=my_b_gets(&io_cache, fname, FN_REFLEN)))
@@ -399,14 +541,14 @@ int MYSQL_LOG::purge_logs(THD* thd, const char* to_log)
}
fname[--fname_len]=0; // kill \n
- if(!memcmp(fname, to_log, fname_len + 1 ))
+ if (!memcmp(fname, to_log, fname_len + 1 ))
{
found_log = 1;
purge_offset = init_purge_offset;
}
// if one of the logs before the target is in use
- if(!found_log && log_in_use(fname))
+ if (!found_log && log_in_use(fname))
{
error = LOG_INFO_IN_USE;
goto err;
@@ -422,13 +564,13 @@ int MYSQL_LOG::purge_logs(THD* thd, const char* to_log)
}
end_io_cache(&io_cache);
- if(!found_log)
+ if (!found_log)
{
error = LOG_INFO_EOF;
goto err;
}
- for(i = 0; i < logs_to_purge.elements; i++)
+ for (i = 0; i < logs_to_purge.elements; i++)
{
char* l;
get_dynamic(&logs_to_purge, (gptr)&l, i);
@@ -436,9 +578,10 @@ int MYSQL_LOG::purge_logs(THD* thd, const char* to_log)
sql_print_error("Error deleting %s during purge", l);
}
- // if we get killed -9 here, the sysadmin would have to do a small
- // vi job on the log index file after restart - otherwise, this should
- // be safe
+ /*
+ If we get killed -9 here, the sysadmin would have to edit
+ the log index file after restart - otherwise, this should be safe
+ */
#ifdef HAVE_FTRUNCATE
if (ftruncate(index_file,0))
{
@@ -451,9 +594,9 @@ during log purge for write");
#else
my_close(index_file, MYF(MY_WME));
my_delete(index_file_name, MYF(MY_WME));
- if(!(index_file = my_open(index_file_name,
+ if ((index_file = my_open(index_file_name,
O_CREAT | O_BINARY | O_RDWR | O_APPEND,
- MYF(MY_WME))))
+ MYF(MY_WME)))<0)
{
sql_print_error("Could not re-open the binlog index file \
during log purge for write");
@@ -462,7 +605,7 @@ during log purge for write");
}
#endif
- for(i = 0; i < logs_to_keep.elements; i++)
+ for (i = 0; i < logs_to_keep.elements; i++)
{
char* l;
get_dynamic(&logs_to_keep, (gptr)&l, i);
@@ -480,15 +623,14 @@ during log purge for write");
err:
pthread_mutex_unlock(&LOCK_index);
- if(logs_to_purge_inited)
+ if (logs_to_purge_inited)
delete_dynamic(&logs_to_purge);
- if(logs_to_keep_inited)
+ if (logs_to_keep_inited)
delete_dynamic(&logs_to_keep);
end_io_cache(&io_cache);
return error;
}
-
// we assume that buf has at least FN_REFLEN bytes alloced
void MYSQL_LOG::make_log_name(char* buf, const char* log_ident)
{
@@ -533,20 +675,36 @@ void MYSQL_LOG::new_file(bool inside_mutex)
}
if (log_type == LOG_BIN)
{
- /*
- We log the whole file name for log file as the user may decide
- to change base names at some point.
- */
- Rotate_log_event r(new_name+dirname_length(new_name));
- r.write(&log_file);
- VOID(pthread_cond_broadcast(&COND_binlog_update));
+ if (!no_auto_events)
+ {
+ /*
+ We log the whole file name for log file as the user may decide
+ to change base names at some point.
+ */
+ THD* thd = current_thd;
+ Rotate_log_event r(thd,new_name+dirname_length(new_name));
+ r.set_log_pos(this);
+
+ /*
+ This log rotation could have been initiated by a master of
+ the slave running with log-bin we set the flag on rotate
+ event to prevent inifinite log rotation loop
+ */
+ if (thd && thd->slave_thread)
+ r.flags |= LOG_EVENT_FORCED_ROTATE_F;
+ r.write(&log_file);
+ }
+ // update needs to be signaled even if there is no rotate event
+ // log rotation should give the waiting thread a signal to
+ // discover EOF and move on to the next log
+ signal_update();
}
+ else
+ strmov(new_name, old_name); // Reopen old file name
}
- else
- strmov(new_name, old_name); // Reopen old file name
name=0;
close();
- open(old_name, log_type, new_name);
+ open(old_name, log_type, new_name, io_cache_type, no_auto_events);
my_free(old_name,MYF(0));
last_time=query_start=0;
write_error=0;
@@ -555,6 +713,58 @@ void MYSQL_LOG::new_file(bool inside_mutex)
}
}
+bool MYSQL_LOG::append(Log_event* ev)
+{
+ bool error = 0;
+ pthread_mutex_lock(&LOCK_log);
+
+ DBUG_ASSERT(log_file.type == SEQ_READ_APPEND);
+ // Log_event::write() is smart enough to use my_b_write() or
+ // my_b_append() depending on the kind of cache we have
+ if (ev->write(&log_file))
+ {
+ error=1;
+ goto err;
+ }
+ if ((uint)my_b_append_tell(&log_file) > max_binlog_size)
+ {
+ new_file(1);
+ }
+ signal_update();
+err:
+ pthread_mutex_unlock(&LOCK_log);
+ return error;
+}
+
+bool MYSQL_LOG::appendv(const char* buf, uint len,...)
+{
+ bool error = 0;
+ va_list(args);
+ va_start(args,len);
+
+ DBUG_ASSERT(log_file.type == SEQ_READ_APPEND);
+
+ pthread_mutex_lock(&LOCK_log);
+ do
+ {
+ if (my_b_append(&log_file,(byte*) buf,len))
+ {
+ error = 1;
+ break;
+ }
+ } while ((buf=va_arg(args,const char*)) && (len=va_arg(args,uint)));
+
+ if ((uint) my_b_append_tell(&log_file) > max_binlog_size)
+ {
+ new_file(1);
+ }
+
+ if (!error)
+ signal_update();
+ pthread_mutex_unlock(&LOCK_log);
+ return error;
+}
+
bool MYSQL_LOG::write(THD *thd,enum enum_server_command command,
const char *format,...)
@@ -635,9 +845,8 @@ bool MYSQL_LOG::write(THD *thd,enum enum_server_command command,
return 0;
}
-/* Write to binary log in a format to be used for replication */
-bool MYSQL_LOG::write(Query_log_event* event_info)
+bool MYSQL_LOG::write(Log_event* event_info)
{
/* In most cases this is only called if 'is_open()' is true */
bool error=0;
@@ -649,35 +858,46 @@ bool MYSQL_LOG::write(Query_log_event* event_info)
if (is_open())
{
THD *thd=event_info->thd;
- IO_CACHE *file = (event_info->cache_stmt ? &thd->transaction.trans_log :
+ const char* db = event_info->get_db();
+#ifdef USING_TRANSACTIONS
+ IO_CACHE *file = ((event_info->get_cache_stmt() && thd) ?
+ &thd->transaction.trans_log :
&log_file);
- if ((!(thd->options & OPTION_BIN_LOG) &&
+#else
+ IO_CACHE *file = &log_file;
+#endif
+ if ((thd && !(thd->options & OPTION_BIN_LOG) &&
(thd->master_access & PROCESS_ACL)) ||
- !db_ok(event_info->db, binlog_do_db, binlog_ignore_db))
+ (db && !db_ok(db, binlog_do_db, binlog_ignore_db)))
{
VOID(pthread_mutex_unlock(&LOCK_log));
return 0;
}
error=1;
-
- if (thd->last_insert_id_used)
+ /*
+ No check for auto events flag here - this write method should
+ never be called if auto-events are enabled
+ */
+ if (thd && thd->last_insert_id_used)
{
- Intvar_log_event e((uchar)LAST_INSERT_ID_EVENT, thd->last_insert_id);
- if(thd->server_id)
- e.server_id = thd->server_id;
+ Intvar_log_event e(thd,(uchar)LAST_INSERT_ID_EVENT,thd->last_insert_id);
+ e.set_log_pos(this);
+ if (thd->server_id)
+ e.server_id = thd->server_id;
if (e.write(file))
goto err;
}
- if (thd->insert_id_used)
+ if (thd && thd->insert_id_used)
{
- Intvar_log_event e((uchar)INSERT_ID_EVENT, thd->last_insert_id);
- if(thd->server_id)
- e.server_id = thd->server_id;
+ Intvar_log_event e(thd,(uchar)INSERT_ID_EVENT,thd->last_insert_id);
+ e.set_log_pos(this);
+ if (thd->server_id)
+ e.server_id = thd->server_id;
if (e.write(file))
goto err;
}
- if (thd->convert_set)
+ if (thd && thd->convert_set)
{
char buf[1024] = "SET CHARACTER SET ";
char* p = strend(buf);
@@ -686,27 +906,32 @@ bool MYSQL_LOG::write(Query_log_event* event_info)
// just in case somebody wants it later
thd->query_length = (uint)(p - buf);
Query_log_event e(thd, buf);
+ e.set_log_pos(this);
if (e.write(file))
goto err;
thd->query_length = save_query_length; // clean up
}
+ event_info->set_log_pos(this);
if (event_info->write(file) ||
file == &log_file && flush_io_cache(file))
goto err;
error=0;
- should_rotate = (file == &log_file && my_b_tell(file) >= max_binlog_size);
- /* Tell for transactional table handlers up to which position in the
- binlog file we wrote. The table handler can store this info, and
- after crash recovery print for the user the offset of the last
- transactions which were recovered. Actually, we must also call
- the table handler commit here, protected by the LOCK_log mutex,
- because otherwise the transactions may end up in a different order
- in the table handler log! */
+ /*
+ Tell for transactional table handlers up to which position in the
+ binlog file we wrote. The table handler can store this info, and
+ after crash recovery print for the user the offset of the last
+ transactions which were recovered. Actually, we must also call
+ the table handler commit here, protected by the LOCK_log mutex,
+ because otherwise the transactions may end up in a different order
+ in the table handler log!
+ */
- if (file == &log_file) {
+ if (file == &log_file)
+ {
error = ha_report_binlog_offset_and_commit(thd, log_file_name,
- file->pos_in_file);
+ file->pos_in_file);
+ should_rotate= (my_b_tell(file) >= (my_off_t) max_binlog_size);
}
err:
@@ -719,7 +944,7 @@ err:
write_error=1;
}
if (file == &log_file)
- VOID(pthread_cond_broadcast(&COND_binlog_update));
+ signal_update();
}
if (should_rotate)
new_file(1); // inside mutex
@@ -727,6 +952,15 @@ err:
return error;
}
+uint MYSQL_LOG::next_file_id()
+{
+ uint res;
+ pthread_mutex_lock(&LOCK_log);
+ res = file_id++;
+ pthread_mutex_unlock(&LOCK_log);
+ return res;
+}
+
/*
Write a cached log entry to the binary log
We only come here if there is something in the cache.
@@ -741,7 +975,7 @@ bool MYSQL_LOG::write(THD *thd, IO_CACHE *cache)
if (is_open())
{
uint length;
-
+ //QQ: this looks like a bug - why READ_CACHE?
if (reinit_io_cache(cache, READ_CACHE, 0, 0, 0))
{
sql_print_error(ER(ER_ERROR_ON_WRITE), cache->file_name, errno);
@@ -750,13 +984,13 @@ bool MYSQL_LOG::write(THD *thd, IO_CACHE *cache)
length=my_b_bytes_in_cache(cache);
do
{
- if (my_b_write(&log_file, cache->rc_pos, length))
+ if (my_b_write(&log_file, cache->read_pos, length))
{
if (!write_error)
sql_print_error(ER(ER_ERROR_ON_WRITE), name, errno);
goto err;
}
- cache->rc_pos=cache->rc_end; // Mark buffer used up
+ cache->read_pos=cache->read_end; // Mark buffer used up
} while ((length=my_b_fill(cache)));
if (flush_io_cache(&log_file))
{
@@ -780,7 +1014,7 @@ err:
if (error)
write_error=1;
else
- VOID(pthread_cond_broadcast(&COND_binlog_update));
+ signal_update();
VOID(pthread_mutex_unlock(&LOCK_log));
@@ -788,42 +1022,6 @@ err:
}
-bool MYSQL_LOG::write(Load_log_event* event_info)
-{
- bool error=0;
- bool should_rotate = 0;
-
- if (inited)
- {
- VOID(pthread_mutex_lock(&LOCK_log));
- if (is_open())
- {
- THD *thd=event_info->thd;
- if ((thd->options & OPTION_BIN_LOG) ||
- !(thd->master_access & PROCESS_ACL))
- {
- if (event_info->write(&log_file) || flush_io_cache(&log_file))
- {
- if (!write_error)
- sql_print_error(ER(ER_ERROR_ON_WRITE), name, errno);
- error=write_error=1;
- }
- should_rotate = (my_b_tell(&log_file) >= max_binlog_size);
- VOID(pthread_cond_broadcast(&COND_binlog_update));
- }
- }
-
- if(should_rotate)
- new_file(1); // inside mutex
-
- VOID(pthread_mutex_unlock(&LOCK_log));
- }
-
-
- return error;
-}
-
-
/* Write update log in a format suitable for incremental backup */
bool MYSQL_LOG::write(THD *thd,const char *query, uint query_length,
@@ -946,20 +1144,37 @@ bool MYSQL_LOG::write(THD *thd,const char *query, uint query_length,
return error;
}
+void MYSQL_LOG:: wait_for_update(THD* thd)
+{
+ const char* old_msg = thd->enter_cond(&update_cond, &LOCK_log,
+ "Slave: waiting for binlog update");
+ pthread_cond_wait(&update_cond, &LOCK_log);
+ // this is not a bug - we unlock the mutex for the caller, and expect him
+ // to lock it and then not unlock it upon return. This is a rather odd
+ // way of doing things, but this is the cleanest way I could think of to
+ // solve the race deadlock caused by THD::awake() first acquiring mysys_var
+ // mutex and then the current mutex, while wait_for_update being called with
+ // the current mutex already aquired and THD::exit_cond() trying to acquire
+ // mysys_var mutex. We do need the mutex to be acquired prior to the
+ // invocation of wait_for_update in all cases, so mutex acquisition inside
+ // wait_for_update() is not an option
+ pthread_mutex_unlock(&LOCK_log);
+ thd->exit_cond(old_msg);
+}
void MYSQL_LOG::close(bool exiting)
{ // One can't set log_type here!
if (is_open())
{
- File file=log_file.file;
- if (log_type == LOG_BIN)
+ if (log_type == LOG_BIN && !no_auto_events)
{
Stop_log_event s;
+ s.set_log_pos(this);
s.write(&log_file);
- VOID(pthread_cond_broadcast(&COND_binlog_update));
+ signal_update();
}
end_io_cache(&log_file);
- if (my_close(file,MYF(0)) < 0 && ! write_error)
+ if (my_close(log_file.file,MYF(0)) < 0 && ! write_error)
{
write_error=1;
sql_print_error(ER(ER_ERROR_ON_WRITE),name,errno);
diff --git a/sql/log_event.cc b/sql/log_event.cc
index c30d03adaf5..528110deb74 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -20,25 +20,377 @@
#pragma implementation // gcc: Class implementation
#endif
#include "mysql_priv.h"
+#include "slave.h"
+#include <my_dir.h>
#endif /* MYSQL_CLIENT */
+#include <assert.h>
-static void pretty_print_char(FILE* file, int c)
+inline int my_b_safe_write(IO_CACHE* file, const byte *buf,
+ int len)
{
+ /*
+ Sasha: We are not writing this with the ? operator to avoid hitting
+ a possible compiler bug. At least gcc 2.95 cannot deal with
+ several layers of ternary operators that evaluated comma(,) operator
+ expressions inside - I do have a test case if somebody wants it
+ */
+ if (file->type == SEQ_READ_APPEND)
+ return my_b_append(file, buf,len);
+ return my_b_write(file, buf,len);
+}
+
+#ifdef MYSQL_CLIENT
+static void pretty_print_str(FILE* file, char* str, int len)
+{
+ char* end = str + len;
fputc('\'', file);
- switch(c) {
- case '\n': fprintf(file, "\\n"); break;
- case '\r': fprintf(file, "\\r"); break;
- case '\\': fprintf(file, "\\\\"); break;
- case '\b': fprintf(file, "\\b"); break;
- case '\'': fprintf(file, "\\'"); break;
- case 0 : fprintf(file, "\\0"); break;
- default:
- fputc(c, file);
- break;
+ while (str < end)
+ {
+ char c;
+ switch ((c=*str++)) {
+ case '\n': fprintf(file, "\\n"); break;
+ case '\r': fprintf(file, "\\r"); break;
+ case '\\': fprintf(file, "\\\\"); break;
+ case '\b': fprintf(file, "\\b"); break;
+ case '\t': fprintf(file, "\\t"); break;
+ case '\'': fprintf(file, "\\'"); break;
+ case 0 : fprintf(file, "\\0"); break;
+ default:
+ fputc(c, file);
+ break;
+ }
}
fputc('\'', file);
}
+#endif
+
+#ifndef MYSQL_CLIENT
+
+inline int ignored_error_code(int err_code)
+{
+ return use_slave_mask && bitmap_is_set(&slave_error_mask, err_code);
+}
+
+
+static void pretty_print_str(String* packet, char* str, int len)
+{
+ char* end = str + len;
+ packet->append('\'');
+ while (str < end)
+ {
+ char c;
+ switch((c=*str++)) {
+ case '\n': packet->append( "\\n"); break;
+ case '\r': packet->append( "\\r"); break;
+ case '\\': packet->append( "\\\\"); break;
+ case '\b': packet->append( "\\b"); break;
+ case '\t': packet->append( "\\t"); break;
+ case '\'': packet->append( "\\'"); break;
+ case 0 : packet->append( "\\0"); break;
+ default:
+ packet->append((char)c);
+ break;
+ }
+ }
+ packet->append('\'');
+}
+
+
+static inline char* slave_load_file_stem(char*buf, uint file_id,
+ int event_server_id)
+{
+ fn_format(buf,"SQL_LOAD-",slave_load_tmpdir,"",4+32);
+ buf = strend(buf);
+ buf = int10_to_str(::server_id, buf, 10);
+ *buf++ = '-';
+ buf = int10_to_str(event_server_id, buf, 10);
+ *buf++ = '-';
+ return int10_to_str(file_id, buf, 10);
+}
+
+#endif
+
+const char* Log_event::get_type_str()
+{
+ switch(get_type_code())
+ {
+ case START_EVENT: return "Start";
+ case STOP_EVENT: return "Stop";
+ case QUERY_EVENT: return "Query";
+ case ROTATE_EVENT: return "Rotate";
+ case INTVAR_EVENT: return "Intvar";
+ case LOAD_EVENT: return "Load";
+ case NEW_LOAD_EVENT: return "New_load";
+ case SLAVE_EVENT: return "Slave";
+ case CREATE_FILE_EVENT: return "Create_file";
+ case APPEND_BLOCK_EVENT: return "Append_block";
+ case DELETE_FILE_EVENT: return "Delete_file";
+ case EXEC_LOAD_EVENT: return "Exec_load";
+ default: /* impossible */ return "Unknown";
+ }
+}
+
+#ifndef MYSQL_CLIENT
+Log_event::Log_event(THD* thd_arg, uint16 flags_arg):
+ exec_time(0),
+ flags(flags_arg),cached_event_len(0),
+ temp_buf(0),thd(thd_arg)
+{
+ if (thd)
+ {
+ server_id = thd->server_id;
+ when = thd->start_time;
+ log_pos = thd->log_pos;
+ }
+ else
+ {
+ server_id = ::server_id;
+ when = time(NULL);
+ log_pos=0;
+ }
+}
+
+static void cleanup_load_tmpdir()
+{
+ MY_DIR *dirp;
+ FILEINFO *file;
+ uint i;
+ if (!(dirp=my_dir(slave_load_tmpdir,MYF(MY_WME))))
+ return;
+
+ for (i=0;i<(uint)dirp->number_off_files;i++)
+ {
+ file=dirp->dir_entry+i;
+ if (!memcmp(file->name,"SQL_LOAD-",9))
+ my_delete(file->name,MYF(MY_WME));
+ }
+
+ my_dirend(dirp);
+}
+
+#endif
+
+Log_event::Log_event(const char* buf, bool old_format):
+ cached_event_len(0),temp_buf(0)
+{
+ when = uint4korr(buf);
+ server_id = uint4korr(buf + SERVER_ID_OFFSET);
+ if (old_format)
+ {
+ log_pos=0;
+ flags=0;
+ }
+ else
+ {
+ log_pos = uint4korr(buf + LOG_POS_OFFSET);
+ flags = uint2korr(buf + FLAGS_OFFSET);
+ }
+#ifndef MYSQL_CLIENT
+ thd = 0;
+#endif
+}
+
+
+#ifndef MYSQL_CLIENT
+
+int Log_event::exec_event(struct st_relay_log_info* rli)
+{
+ if (rli)
+ {
+ rli->inc_pos(get_event_len(),log_pos);
+ DBUG_ASSERT(rli->sql_thd != 0);
+ flush_relay_log_info(rli);
+ }
+ return 0;
+}
+
+void Log_event::pack_info(String* packet)
+{
+ net_store_data(packet, "", 0);
+}
+
+void Query_log_event::pack_info(String* packet)
+{
+ char buf[256];
+ String tmp(buf, sizeof(buf));
+ tmp.length(0);
+ if (db && db_len)
+ {
+ tmp.append("use ");
+ tmp.append(db, db_len);
+ tmp.append("; ", 2);
+ }
+
+ if (query && q_len)
+ tmp.append(query, q_len);
+ net_store_data(packet, (char*)tmp.ptr(), tmp.length());
+}
+
+void Start_log_event::pack_info(String* packet)
+{
+ char buf1[256];
+ String tmp(buf1, sizeof(buf1));
+ tmp.length(0);
+ char buf[22];
+
+ tmp.append("Server ver: ");
+ tmp.append(server_version);
+ tmp.append(", Binlog ver: ");
+ tmp.append(llstr(binlog_version, buf));
+ net_store_data(packet, tmp.ptr(), tmp.length());
+}
+
+void Load_log_event::pack_info(String* packet)
+{
+ char buf[256];
+ String tmp(buf, sizeof(buf));
+ tmp.length(0);
+ if(db && db_len)
+ {
+ tmp.append("use ");
+ tmp.append(db, db_len);
+ tmp.append("; ", 2);
+ }
+
+ tmp.append("LOAD DATA INFILE '");
+ tmp.append(fname, fname_len);
+ tmp.append("' ", 2);
+ if(sql_ex.opt_flags && REPLACE_FLAG )
+ tmp.append(" REPLACE ");
+ else if(sql_ex.opt_flags && IGNORE_FLAG )
+ tmp.append(" IGNORE ");
+
+ tmp.append("INTO TABLE ");
+ tmp.append(table_name);
+ if (sql_ex.field_term_len)
+ {
+ tmp.append(" FIELDS TERMINATED BY ");
+ pretty_print_str(&tmp, sql_ex.field_term, sql_ex.field_term_len);
+ }
+
+ if (sql_ex.enclosed_len)
+ {
+ if (sql_ex.opt_flags && OPT_ENCLOSED_FLAG )
+ tmp.append(" OPTIONALLY ");
+ tmp.append( " ENCLOSED BY ");
+ pretty_print_str(&tmp, sql_ex.enclosed, sql_ex.enclosed_len);
+ }
+
+ if (sql_ex.escaped_len)
+ {
+ tmp.append( " ESCAPED BY ");
+ pretty_print_str(&tmp, sql_ex.escaped, sql_ex.escaped_len);
+ }
+
+ if (sql_ex.line_term_len)
+ {
+ tmp.append(" LINES TERMINATED BY ");
+ pretty_print_str(&tmp, sql_ex.line_term, sql_ex.line_term_len);
+ }
+
+ if (sql_ex.line_start_len)
+ {
+ tmp.append(" LINES STARTING BY ");
+ pretty_print_str(&tmp, sql_ex.line_start, sql_ex.line_start_len);
+ }
+
+ if ((int)skip_lines > 0)
+ tmp.append( " IGNORE %ld LINES ", (long) skip_lines);
+
+ if (num_fields)
+ {
+ uint i;
+ const char* field = fields;
+ tmp.append(" (");
+ for(i = 0; i < num_fields; i++)
+ {
+ if(i)
+ tmp.append(" ,");
+ tmp.append( field);
+
+ field += field_lens[i] + 1;
+ }
+ tmp.append(')');
+ }
+
+ net_store_data(packet, tmp.ptr(), tmp.length());
+}
+
+void Rotate_log_event::pack_info(String* packet)
+{
+ char buf1[256];
+ String tmp(buf1, sizeof(buf1));
+ tmp.length(0);
+ char buf[22];
+ tmp.append(new_log_ident, ident_len);
+ tmp.append(";pos=");
+ tmp.append(llstr(pos,buf));
+ if(flags & LOG_EVENT_FORCED_ROTATE_F)
+ tmp.append("; forced by master");
+ net_store_data(packet, tmp.ptr(), tmp.length());
+}
+
+void Intvar_log_event::pack_info(String* packet)
+{
+ char buf1[256];
+ String tmp(buf1, sizeof(buf1));
+ tmp.length(0);
+ char buf[22];
+ tmp.append(get_var_type_name());
+ tmp.append('=');
+ tmp.append(llstr(val, buf));
+ net_store_data(packet, tmp.ptr(), tmp.length());
+}
+
+void Slave_log_event::pack_info(String* packet)
+{
+ char buf1[256];
+ String tmp(buf1, sizeof(buf1));
+ tmp.length(0);
+ char buf[22];
+ tmp.append("host=");
+ tmp.append(master_host);
+ tmp.append(",port=");
+ tmp.append(llstr(master_port,buf));
+ tmp.append(",log=");
+ tmp.append(master_log);
+ tmp.append(",pos=");
+ tmp.append(llstr(master_pos,buf));
+ net_store_data(packet, tmp.ptr(), tmp.length());
+}
+
+
+void Log_event::init_show_field_list(List<Item>* field_list)
+{
+ field_list->push_back(new Item_empty_string("Log_name", 20));
+ field_list->push_back(new Item_empty_string("Pos", 20));
+ field_list->push_back(new Item_empty_string("Event_type", 20));
+ field_list->push_back(new Item_empty_string("Server_id", 20));
+ field_list->push_back(new Item_empty_string("Orig_log_pos", 20));
+ field_list->push_back(new Item_empty_string("Info", 20));
+}
+
+int Log_event::net_send(THD* thd, const char* log_name, my_off_t pos)
+{
+ String* packet = &thd->packet;
+ const char* p = strrchr(log_name, FN_LIBCHAR);
+ const char* event_type;
+ if (p)
+ log_name = p + 1;
+
+ packet->length(0);
+ net_store_data(packet, log_name, strlen(log_name));
+ net_store_data(packet, (longlong) pos);
+ event_type = get_type_str();
+ net_store_data(packet, event_type, strlen(event_type));
+ net_store_data(packet, server_id);
+ net_store_data(packet, (longlong) log_pos);
+ pack_info(packet);
+ return my_net_write(&thd->net, (char*) packet->ptr(), packet->length());
+}
+
+#endif
int Query_log_event::write(IO_CACHE* file)
{
@@ -52,7 +404,6 @@ int Log_event::write(IO_CACHE* file)
int Log_event::write_header(IO_CACHE* file)
{
- // make sure to change this when the header gets bigger
char buf[LOG_EVENT_HEADER_LEN];
char* pos = buf;
int4store(pos, (ulong) when); // timestamp
@@ -63,7 +414,11 @@ int Log_event::write_header(IO_CACHE* file)
long tmp=get_data_size() + LOG_EVENT_HEADER_LEN;
int4store(pos, tmp);
pos += 4;
- return (my_b_write(file, (byte*) buf, (uint) (pos - buf)));
+ int4store(pos, log_pos);
+ pos += 4;
+ int2store(pos, flags);
+ pos += 2;
+ return (my_b_safe_write(file, (byte*) buf, (uint) (pos - buf)));
}
#ifndef MYSQL_CLIENT
@@ -117,157 +472,144 @@ int Log_event::read_log_event(IO_CACHE* file, String* packet,
#define UNLOCK_MUTEX
#endif
+#ifndef MYSQL_CLIENT
+#define LOCK_MUTEX if(log_lock) pthread_mutex_lock(log_lock);
+#else
+#define LOCK_MUTEX
+#endif
+
// allocates memory - the caller is responsible for clean-up
#ifndef MYSQL_CLIENT
-Log_event* Log_event::read_log_event(IO_CACHE* file, pthread_mutex_t* log_lock)
+Log_event* Log_event::read_log_event(IO_CACHE* file,
+ pthread_mutex_t* log_lock,
+ bool old_format)
#else
-Log_event* Log_event::read_log_event(IO_CACHE* file)
+Log_event* Log_event::read_log_event(IO_CACHE* file, bool old_format)
#endif
{
- time_t timestamp;
- uint32 server_id;
-
- char buf[LOG_EVENT_HEADER_LEN-4];
-#ifndef MYSQL_CLIENT
- if(log_lock) pthread_mutex_lock(log_lock);
-#endif
- if (my_b_read(file, (byte *) buf, sizeof(buf)))
+ char head[LOG_EVENT_HEADER_LEN];
+ uint header_size = old_format ? OLD_HEADER_LEN :
+ LOG_EVENT_HEADER_LEN;
+ LOCK_MUTEX;
+ if (my_b_read(file, (byte *) head, header_size ))
{
- UNLOCK_MUTEX
- return NULL;
+ UNLOCK_MUTEX;
+ return 0;
}
- timestamp = uint4korr(buf);
- server_id = uint4korr(buf + 5);
-
- switch(buf[EVENT_TYPE_OFFSET])
- {
- case QUERY_EVENT:
+
+ uint data_len = uint4korr(head + EVENT_LEN_OFFSET);
+ char* buf = 0;
+ const char* error = 0;
+ Log_event* res = 0;
+
+ if (data_len > max_allowed_packet)
{
- Query_log_event* q = new Query_log_event(file, timestamp, server_id);
- UNLOCK_MUTEX
- if (!q->query)
- {
- delete q;
- q=NULL;
- }
- return q;
+ error = "Event too big";
+ goto err;
}
-
- case LOAD_EVENT:
+
+ if (data_len < header_size)
{
- Load_log_event* l = new Load_log_event(file, timestamp, server_id);
- UNLOCK_MUTEX
- if (!l->table_name)
- {
- delete l;
- l=NULL;
- }
- return l;
+ error = "Event too small";
+ goto err;
}
-
- case ROTATE_EVENT:
+ // some events use the extra byte to null-terminate strings
+ if (!(buf = my_malloc(data_len+1, MYF(MY_WME))))
{
- Rotate_log_event* r = new Rotate_log_event(file, timestamp, server_id);
- UNLOCK_MUTEX
- if (!r->new_log_ident)
- {
- delete r;
- r=NULL;
- }
- return r;
+ error = "Out of memory";
+ goto err;
}
-
- case INTVAR_EVENT:
+ buf[data_len] = 0;
+ memcpy(buf, head, header_size);
+ if (my_b_read(file, (byte*) buf + header_size,
+ data_len - header_size))
{
- Intvar_log_event* e = new Intvar_log_event(file, timestamp, server_id);
- UNLOCK_MUTEX
- if (e->type == INVALID_INT_EVENT)
- {
- delete e;
- e=NULL;
- }
- return e;
+ error = "read error";
+ goto err;
}
-
- case START_EVENT:
- {
- Start_log_event* e = new Start_log_event(file, timestamp, server_id);
- UNLOCK_MUTEX
- return e;
- }
- case STOP_EVENT:
- {
- Stop_log_event* e = new Stop_log_event(file, timestamp, server_id);
- UNLOCK_MUTEX
- return e;
- }
- default:
- break;
+ if ((res = read_log_event(buf, data_len, &error, old_format)))
+ res->register_temp_buf(buf);
+err:
+ UNLOCK_MUTEX;
+ if (error)
+ {
+ sql_print_error("Error in Log_event::read_log_event(): '%s', \
+data_len=%d,event_type=%d",error,data_len,head[EVENT_TYPE_OFFSET]);
+ my_free(buf, MYF(MY_ALLOW_ZERO_PTR));
}
-
- // default
- UNLOCK_MUTEX
- return NULL;
+ return res;
}
-Log_event* Log_event::read_log_event(const char* buf, int event_len)
+Log_event* Log_event::read_log_event(const char* buf, int event_len,
+ const char **error, bool old_format)
{
- if(event_len < EVENT_LEN_OFFSET ||
- (uint)event_len != uint4korr(buf+EVENT_LEN_OFFSET))
+ if (event_len < EVENT_LEN_OFFSET ||
+ (uint)event_len != uint4korr(buf+EVENT_LEN_OFFSET))
return NULL; // general sanity check - will fail on a partial read
+ Log_event* ev = NULL;
+
switch(buf[EVENT_TYPE_OFFSET])
{
case QUERY_EVENT:
- {
- Query_log_event* q = new Query_log_event(buf, event_len);
- if (!q->query)
- {
- delete q;
- return NULL;
- }
-
- return q;
- }
-
+ ev = new Query_log_event(buf, event_len, old_format);
+ break;
case LOAD_EVENT:
- {
- Load_log_event* l = new Load_log_event(buf, event_len);
- if (!l->table_name)
- {
- delete l;
- return NULL;
- }
-
- return l;
- }
-
+ ev = new Create_file_log_event(buf, event_len, old_format);
+ break;
+ case NEW_LOAD_EVENT:
+ ev = new Load_log_event(buf, event_len, old_format);
+ break;
case ROTATE_EVENT:
- {
- Rotate_log_event* r = new Rotate_log_event(buf, event_len);
- if (!r->new_log_ident)
- {
- delete r;
- return NULL;
- }
-
- return r;
- }
- case START_EVENT: return new Start_log_event(buf);
- case STOP_EVENT: return new Stop_log_event(buf);
- case INTVAR_EVENT: return new Intvar_log_event(buf);
+ ev = new Rotate_log_event(buf, event_len, old_format);
+ break;
+ case SLAVE_EVENT:
+ ev = new Slave_log_event(buf, event_len);
+ break;
+ case CREATE_FILE_EVENT:
+ ev = new Create_file_log_event(buf, event_len, old_format);
+ break;
+ case APPEND_BLOCK_EVENT:
+ ev = new Append_block_log_event(buf, event_len);
+ break;
+ case DELETE_FILE_EVENT:
+ ev = new Delete_file_log_event(buf, event_len);
+ break;
+ case EXEC_LOAD_EVENT:
+ ev = new Execute_load_log_event(buf, event_len);
+ break;
+ case START_EVENT:
+ ev = new Start_log_event(buf, old_format);
+ break;
+ case STOP_EVENT:
+ ev = new Stop_log_event(buf, old_format);
+ break;
+ case INTVAR_EVENT:
+ ev = new Intvar_log_event(buf, old_format);
+ break;
default:
break;
}
- return NULL; // default value
+ if (!ev) return 0;
+ if (!ev->is_valid())
+ {
+ *error= "Found invalid event in binary log";
+ delete ev;
+ return 0;
+ }
+ ev->cached_event_len = event_len;
+ return ev;
}
+#ifdef MYSQL_CLIENT
void Log_event::print_header(FILE* file)
{
+ char llbuff[22];
fputc('#', file);
print_timestamp(file);
- fprintf(file, " server id %d ", server_id);
+ fprintf(file, " server id %d log_pos %s ", server_id,
+ llstr(log_pos,llbuff));
}
void Log_event::print_timestamp(FILE* file, time_t* ts)
@@ -321,6 +663,7 @@ void Stop_log_event::print(FILE* file, bool short_form, char* last_db)
void Rotate_log_event::print(FILE* file, bool short_form, char* last_db)
{
+ char buf[22];
if (short_form)
return;
@@ -329,64 +672,55 @@ void Rotate_log_event::print(FILE* file, bool short_form, char* last_db)
if (new_log_ident)
my_fwrite(file, (byte*) new_log_ident, (uint)ident_len,
MYF(MY_NABP | MY_WME));
- fprintf(file, "\n");
+ fprintf(file, "pos=%s\n", llstr(pos, buf));
fflush(file);
}
-Rotate_log_event::Rotate_log_event(IO_CACHE* file, time_t when_arg,
- uint32 server_id):
- Log_event(when_arg, 0, 0, server_id),new_log_ident(NULL),alloced(0)
-{
- char *tmp_ident;
- char buf[4];
-
- if (my_b_read(file, (byte*) buf, sizeof(buf)))
- return;
- ulong event_len;
- event_len = uint4korr(buf);
- if (event_len < ROTATE_EVENT_OVERHEAD)
- return;
-
- ident_len = (uchar)(event_len - ROTATE_EVENT_OVERHEAD);
- if (!(tmp_ident = (char*) my_malloc((uint)ident_len, MYF(MY_WME))))
- return;
- if (my_b_read( file, (byte*) tmp_ident, (uint) ident_len))
- {
- my_free((gptr) tmp_ident, MYF(0));
- return;
- }
-
- new_log_ident = tmp_ident;
- alloced = 1;
-}
+#endif /* #ifdef MYSQL_CLIENT */
-Start_log_event::Start_log_event(const char* buf) :Log_event(buf)
+Start_log_event::Start_log_event(const char* buf,
+ bool old_format) :Log_event(buf, old_format)
{
- buf += EVENT_LEN_OFFSET + 4; // skip even length
- binlog_version = uint2korr(buf);
- memcpy(server_version, buf + 2, sizeof(server_version));
- created = uint4korr(buf + 2 + sizeof(server_version));
+ buf += (old_format) ? OLD_HEADER_LEN : LOG_EVENT_HEADER_LEN;
+ binlog_version = uint2korr(buf+ST_BINLOG_VER_OFFSET);
+ memcpy(server_version, buf+ST_SERVER_VER_OFFSET,
+ ST_SERVER_VER_LEN);
+ created = uint4korr(buf+ST_CREATED_OFFSET);
}
int Start_log_event::write_data(IO_CACHE* file)
{
- char buff[sizeof(server_version)+2+4];
- int2store(buff,binlog_version);
- memcpy(buff+2,server_version,sizeof(server_version));
- int4store(buff+2+sizeof(server_version),created);
- return (my_b_write(file, (byte*) buff, sizeof(buff)) ? -1 : 0);
+ char buff[START_HEADER_LEN];
+ int2store(buff + ST_BINLOG_VER_OFFSET,binlog_version);
+ memcpy(buff + ST_SERVER_VER_OFFSET,server_version,ST_SERVER_VER_LEN);
+ int4store(buff + ST_CREATED_OFFSET,created);
+ return (my_b_safe_write(file, (byte*) buff, sizeof(buff)) ? -1 : 0);
}
-Rotate_log_event::Rotate_log_event(const char* buf, int event_len):
- Log_event(buf),new_log_ident(NULL),alloced(0)
+Rotate_log_event::Rotate_log_event(const char* buf, int event_len,
+ bool old_format):
+ Log_event(buf, old_format),new_log_ident(NULL),alloced(0)
{
// the caller will ensure that event_len is what we have at
// EVENT_LEN_OFFSET
- if(event_len < ROTATE_EVENT_OVERHEAD)
+ int header_size = (old_format) ? OLD_HEADER_LEN : LOG_EVENT_HEADER_LEN;
+ uint ident_offset;
+ if(event_len < header_size)
return;
-
- ident_len = (uchar)(event_len - ROTATE_EVENT_OVERHEAD);
- if (!(new_log_ident = (char*) my_memdup((byte*) buf + LOG_EVENT_HEADER_LEN,
+ buf += header_size;
+ if (old_format)
+ {
+ ident_len = (uchar)(event_len - OLD_HEADER_LEN);
+ pos = 4;
+ ident_offset = 0;
+ }
+ else
+ {
+ ident_len = (uchar)(event_len - ROTATE_EVENT_OVERHEAD);
+ pos = uint8korr(buf + R_POS_OFFSET);
+ ident_offset = ROTATE_HEADER_LEN;
+ }
+ if (!(new_log_ident = (char*) my_memdup((byte*) buf + ident_offset,
(uint) ident_len, MYF(MY_WME))))
return;
@@ -395,68 +729,66 @@ Rotate_log_event::Rotate_log_event(const char* buf, int event_len):
int Rotate_log_event::write_data(IO_CACHE* file)
{
- return my_b_write(file, (byte*) new_log_ident, (uint) ident_len) ? -1 :0;
+ char buf[ROTATE_HEADER_LEN];
+ int8store(buf, pos + R_POS_OFFSET);
+ return my_b_safe_write(file, (byte*)buf, ROTATE_HEADER_LEN) ||
+ my_b_safe_write(file, (byte*)new_log_ident, (uint) ident_len);
}
-Query_log_event::Query_log_event(IO_CACHE* file, time_t when_arg,
- uint32 server_id):
- Log_event(when_arg,0,0,server_id),data_buf(0),query(NULL),db(NULL)
-{
- char buf[QUERY_HEADER_LEN + 4];
- ulong data_len;
- if (my_b_read(file, (byte*) buf, sizeof(buf)))
- return; // query == NULL will tell the
- // caller there was a problem
- data_len = uint4korr(buf);
- if (data_len < QUERY_EVENT_OVERHEAD)
- return; // tear-drop attack protection :)
-
- data_len -= QUERY_EVENT_OVERHEAD;
- exec_time = uint4korr(buf + 8);
- db_len = (uint)buf[12];
- error_code = uint2korr(buf + 13);
-
- /* Allocate one byte extra for end \0 */
- if (!(data_buf = (char*) my_malloc(data_len+1, MYF(MY_WME))))
- return;
- if (my_b_read( file, (byte*) data_buf, data_len))
+#ifndef MYSQL_CLIENT
+Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg,
+ bool using_trans):
+ Log_event(thd_arg), data_buf(0), query(query_arg), db(thd_arg->db),
+ q_len(thd_arg->query_length),
+ error_code(thd_arg->killed ? ER_SERVER_SHUTDOWN: thd_arg->net.last_errno),
+ thread_id(thd_arg->thread_id),
+ cache_stmt(using_trans &&
+ (thd_arg->options & (OPTION_NOT_AUTO_COMMIT | OPTION_BEGIN)))
{
- my_free((gptr) data_buf, MYF(0));
- data_buf = 0;
- return;
+ time_t end_time;
+ time(&end_time);
+ exec_time = (ulong) (end_time - thd->start_time);
+ db_len = (db) ? (uint32) strlen(db) : 0;
}
+#endif
- thread_id = uint4korr(buf + 4);
- db = data_buf;
- query=data_buf + db_len + 1;
- q_len = data_len - 1 - db_len;
- *((char*) query + q_len) = 0; // Safety
-}
-
-Query_log_event::Query_log_event(const char* buf, int event_len):
- Log_event(buf),data_buf(0), query(NULL), db(NULL)
+Query_log_event::Query_log_event(const char* buf, int event_len,
+ bool old_format):
+ Log_event(buf, old_format),data_buf(0), query(NULL), db(NULL)
{
- if ((uint)event_len < QUERY_EVENT_OVERHEAD)
- return;
ulong data_len;
- buf += EVENT_LEN_OFFSET;
- data_len = event_len - QUERY_EVENT_OVERHEAD;
+ if (old_format)
+ {
+ if ((uint)event_len < OLD_HEADER_LEN + QUERY_HEADER_LEN)
+ return;
+ data_len = event_len - (QUERY_HEADER_LEN + OLD_HEADER_LEN);
+ buf += OLD_HEADER_LEN;
+ }
+ else
+ {
+ if ((uint)event_len < QUERY_EVENT_OVERHEAD)
+ return;
+ data_len = event_len - QUERY_EVENT_OVERHEAD;
+ buf += LOG_EVENT_HEADER_LEN;
+ }
- exec_time = uint4korr(buf + 8);
- error_code = uint2korr(buf + 13);
+ exec_time = uint4korr(buf + Q_EXEC_TIME_OFFSET);
+ error_code = uint2korr(buf + Q_ERR_CODE_OFFSET);
if (!(data_buf = (char*) my_malloc(data_len + 1, MYF(MY_WME))))
return;
- memcpy(data_buf, buf + QUERY_HEADER_LEN + 4, data_len);
- thread_id = uint4korr(buf + 4);
+ memcpy(data_buf, buf + Q_DATA_OFFSET, data_len);
+ thread_id = uint4korr(buf + Q_THREAD_ID_OFFSET);
db = data_buf;
- db_len = (uint)buf[12];
+ db_len = (uint)buf[Q_DB_LEN_OFFSET];
query=data_buf + db_len + 1;
q_len = data_len - 1 - db_len;
*((char*)query+q_len) = 0;
}
+#ifdef MYSQL_CLIENT
+
void Query_log_event::print(FILE* file, bool short_form, char* last_db)
{
char buff[40],*end; // Enough for SET TIMESTAMP
@@ -485,52 +817,50 @@ void Query_log_event::print(FILE* file, bool short_form, char* last_db)
fprintf(file, ";\n");
}
+#endif
+
int Query_log_event::write_data(IO_CACHE* file)
{
if (!query) return -1;
char buf[QUERY_HEADER_LEN];
- char* pos = buf;
- int4store(pos, thread_id);
- pos += 4;
- int4store(pos, exec_time);
- pos += 4;
- *pos++ = (char)db_len;
- int2store(pos, error_code);
- pos += 2;
-
- return (my_b_write(file, (byte*) buf, (uint)(pos - buf)) ||
- my_b_write(file, (db) ? (byte*) db : (byte*)"", db_len + 1) ||
- my_b_write(file, (byte*) query, q_len)) ? -1 : 0;
+ int4store(buf + Q_THREAD_ID_OFFSET, thread_id);
+ int4store(buf + Q_EXEC_TIME_OFFSET, exec_time);
+ buf[Q_DB_LEN_OFFSET] = (char)db_len;
+ int2store(buf + Q_ERR_CODE_OFFSET, error_code);
+
+ return (my_b_safe_write(file, (byte*) buf, QUERY_HEADER_LEN) ||
+ my_b_safe_write(file, (db) ? (byte*) db : (byte*)"", db_len + 1) ||
+ my_b_safe_write(file, (byte*) query, q_len)) ? -1 : 0;
}
-Intvar_log_event:: Intvar_log_event(IO_CACHE* file, time_t when_arg,
- uint32 server_id)
- :Log_event(when_arg,0,0,server_id), type(INVALID_INT_EVENT)
+Intvar_log_event::Intvar_log_event(const char* buf, bool old_format):
+ Log_event(buf, old_format)
{
- char buf[9+4];
- if (!my_b_read(file, (byte*) buf, sizeof(buf)))
- {
- type = buf[4];
- val = uint8korr(buf+1+4);
- }
+ buf += (old_format) ? OLD_HEADER_LEN : LOG_EVENT_HEADER_LEN;
+ type = buf[I_TYPE_OFFSET];
+ val = uint8korr(buf+I_VAL_OFFSET);
}
-Intvar_log_event::Intvar_log_event(const char* buf):Log_event(buf)
+const char* Intvar_log_event::get_var_type_name()
{
- buf += LOG_EVENT_HEADER_LEN;
- type = buf[0];
- val = uint8korr(buf+1);
+ switch(type)
+ {
+ case LAST_INSERT_ID_EVENT: return "LAST_INSERT_ID";
+ case INSERT_ID_EVENT: return "INSERT_ID";
+ default: /* impossible */ return "UNKNOWN";
+ }
}
int Intvar_log_event::write_data(IO_CACHE* file)
{
char buf[9];
- buf[0] = type;
- int8store(buf + 1, val);
- return my_b_write(file, (byte*) buf, sizeof(buf));
+ buf[I_TYPE_OFFSET] = type;
+ int8store(buf + I_VAL_OFFSET, val);
+ return my_b_safe_write(file, (byte*) buf, sizeof(buf));
}
+#ifdef MYSQL_CLIENT
void Intvar_log_event::print(FILE* file, bool short_form, char* last_db)
{
char llbuff[22];
@@ -554,100 +884,255 @@ void Intvar_log_event::print(FILE* file, bool short_form, char* last_db)
fflush(file);
}
+#endif
-int Load_log_event::write_data(IO_CACHE* file)
+int Load_log_event::write_data_header(IO_CACHE* file)
{
char buf[LOAD_HEADER_LEN];
- int4store(buf, thread_id);
- int4store(buf + 4, exec_time);
- int4store(buf + 8, skip_lines);
- buf[12] = (char)table_name_len;
- buf[13] = (char)db_len;
- int4store(buf + 14, num_fields);
-
- if(my_b_write(file, (byte*)buf, sizeof(buf)) ||
- my_b_write(file, (byte*)&sql_ex, sizeof(sql_ex)))
- return 1;
+ int4store(buf + L_THREAD_ID_OFFSET, thread_id);
+ int4store(buf + L_EXEC_TIME_OFFSET, exec_time);
+ int4store(buf + L_SKIP_LINES_OFFSET, skip_lines);
+ buf[L_TBL_LEN_OFFSET] = (char)table_name_len;
+ buf[L_DB_LEN_OFFSET] = (char)db_len;
+ int4store(buf + L_NUM_FIELDS_OFFSET, num_fields);
+ return my_b_safe_write(file, (byte*)buf, LOAD_HEADER_LEN);
+}
+int Load_log_event::write_data_body(IO_CACHE* file)
+{
+ if (sql_ex.write_data(file)) return 1;
if (num_fields && fields && field_lens)
{
- if(my_b_write(file, (byte*)field_lens, num_fields) ||
- my_b_write(file, (byte*)fields, field_block_len))
+ if (my_b_safe_write(file, (byte*)field_lens, num_fields) ||
+ my_b_safe_write(file, (byte*)fields, field_block_len))
return 1;
}
- if(my_b_write(file, (byte*)table_name, table_name_len + 1) ||
- my_b_write(file, (byte*)db, db_len + 1) ||
- my_b_write(file, (byte*)fname, fname_len))
+ return (my_b_safe_write(file, (byte*)table_name, table_name_len + 1) ||
+ my_b_safe_write(file, (byte*)db, db_len + 1) ||
+ my_b_safe_write(file, (byte*)fname, fname_len));
+}
+
+
+static bool write_str(IO_CACHE *file, char *str, byte length)
+{
+ return (my_b_safe_write(file, &length, 1) ||
+ my_b_safe_write(file, (byte*) str, (int) length));
+}
+
+int sql_ex_info::write_data(IO_CACHE* file)
+{
+ if (new_format())
+ {
+ return (write_str(file, field_term, field_term_len) ||
+ write_str(file, enclosed, enclosed_len) ||
+ write_str(file, line_term, line_term_len) ||
+ write_str(file, line_start, line_start_len) ||
+ write_str(file, escaped, escaped_len) ||
+ my_b_safe_write(file,(byte*) &opt_flags,1));
+ }
+ else
+ {
+ old_sql_ex old_ex;
+ old_ex.field_term= *field_term;
+ old_ex.enclosed= *enclosed;
+ old_ex.line_term= *line_term;
+ old_ex.line_start= *line_start;
+ old_ex.escaped= *escaped;
+ old_ex.opt_flags= opt_flags;
+ old_ex.empty_flags=empty_flags;
+ return my_b_safe_write(file, (byte*) &old_ex, sizeof(old_ex));
+ }
+}
+
+static inline int read_str(char * &buf, char *buf_end, char * &str,
+ uint8 &len)
+{
+ if (buf + (uint) (uchar) *buf >= buf_end)
return 1;
+ len = (uint8) *buf;
+ str= buf+1;
+ buf+= (uint) len+1;
return 0;
}
-Load_log_event::Load_log_event(IO_CACHE* file, time_t when, uint32 server_id):
- Log_event(when,0,0,server_id),data_buf(0),num_fields(0),
- fields(0),field_lens(0),field_block_len(0),
- table_name(0),db(0),fname(0)
+char* sql_ex_info::init(char* buf,char* buf_end,bool use_new_format)
{
- char buf[LOAD_HEADER_LEN + 4];
- ulong data_len;
- if (my_b_read(file, (byte*)buf, sizeof(buf)) ||
- my_b_read(file, (byte*)&sql_ex, sizeof(sql_ex)))
- return;
-
- data_len = uint4korr(buf) - LOAD_EVENT_OVERHEAD;
- if (!(data_buf = (char*)my_malloc(data_len + 1, MYF(MY_WME))))
- return;
- if (my_b_read(file, (byte*)data_buf, data_len))
- return;
- copy_log_event(buf,data_len);
+ cached_new_format = use_new_format;
+ if (use_new_format)
+ {
+ empty_flags=0;
+ /* the code below assumes that buf will not disappear from
+ under our feet during the lifetime of the event. This assumption
+ holds true in the slave thread if the log is in new format, but is not
+ the case when we have old format because we will be reusing net buffer
+ to read the actual file before we write out the Create_file event
+ */
+ if (read_str(buf, buf_end, field_term, field_term_len) ||
+ read_str(buf, buf_end, enclosed, enclosed_len) ||
+ read_str(buf, buf_end, line_term, line_term_len) ||
+ read_str(buf, buf_end, line_start, line_start_len) ||
+ read_str(buf, buf_end, escaped, escaped_len))
+ return 0;
+ opt_flags = *buf++;
+ }
+ else
+ {
+ field_term_len= enclosed_len= line_term_len= line_start_len= escaped_len=1;
+ field_term = buf++;
+ enclosed= buf++;
+ line_term= buf++;
+ line_start= buf++;
+ escaped= buf++;
+ opt_flags = *buf++;
+ empty_flags=*buf++;
+ if (empty_flags & FIELD_TERM_EMPTY)
+ field_term_len=0;
+ if (empty_flags & ENCLOSED_EMPTY)
+ enclosed_len=0;
+ if (empty_flags & LINE_TERM_EMPTY)
+ line_term_len=0;
+ if (empty_flags & LINE_START_EMPTY)
+ line_start_len=0;
+ if (empty_flags & ESCAPED_EMPTY)
+ escaped_len=0;
+ }
+ return buf;
}
-Load_log_event::Load_log_event(const char* buf, int event_len):
- Log_event(buf),data_buf(0),num_fields(0),fields(0),
+
+#ifndef MYSQL_CLIENT
+Load_log_event::Load_log_event(THD* thd, sql_exchange* ex,
+ const char* db_arg, const char* table_name_arg,
+ List<Item>& fields_arg, enum enum_duplicates handle_dup):
+ Log_event(thd),thread_id(thd->thread_id),
+ num_fields(0),fields(0),field_lens(0),field_block_len(0),
+ table_name(table_name_arg),
+ db(db_arg),
+ fname(ex->file_name)
+ {
+ time_t end_time;
+ time(&end_time);
+ exec_time = (ulong) (end_time - thd->start_time);
+ db_len = (db) ? (uint32) strlen(db) : 0;
+ table_name_len = (table_name) ? (uint32) strlen(table_name) : 0;
+ fname_len = (fname) ? (uint) strlen(fname) : 0;
+ sql_ex.field_term = (char*) ex->field_term->ptr();
+ sql_ex.field_term_len = (uint8) ex->field_term->length();
+ sql_ex.enclosed = (char*) ex->enclosed->ptr();
+ sql_ex.enclosed_len = (uint8) ex->enclosed->length();
+ sql_ex.line_term = (char*) ex->line_term->ptr();
+ sql_ex.line_term_len = (uint8) ex->line_term->length();
+ sql_ex.line_start = (char*) ex->line_start->ptr();
+ sql_ex.line_start_len = (uint8) ex->line_start->length();
+ sql_ex.escaped = (char*) ex->escaped->ptr();
+ sql_ex.escaped_len = (uint8) ex->escaped->length();
+ sql_ex.opt_flags = 0;
+ sql_ex.cached_new_format = -1;
+
+ if(ex->dumpfile)
+ sql_ex.opt_flags |= DUMPFILE_FLAG;
+ if(ex->opt_enclosed)
+ sql_ex.opt_flags |= OPT_ENCLOSED_FLAG;
+
+ sql_ex.empty_flags = 0;
+
+ switch(handle_dup)
+ {
+ case DUP_IGNORE: sql_ex.opt_flags |= IGNORE_FLAG; break;
+ case DUP_REPLACE: sql_ex.opt_flags |= REPLACE_FLAG; break;
+ case DUP_ERROR: break;
+ }
+
+
+ if(!ex->field_term->length())
+ sql_ex.empty_flags |= FIELD_TERM_EMPTY;
+ if(!ex->enclosed->length())
+ sql_ex.empty_flags |= ENCLOSED_EMPTY;
+ if(!ex->line_term->length())
+ sql_ex.empty_flags |= LINE_TERM_EMPTY;
+ if(!ex->line_start->length())
+ sql_ex.empty_flags |= LINE_START_EMPTY;
+ if(!ex->escaped->length())
+ sql_ex.empty_flags |= ESCAPED_EMPTY;
+
+ skip_lines = ex->skip_lines;
+
+ List_iterator<Item> li(fields_arg);
+ field_lens_buf.length(0);
+ fields_buf.length(0);
+ Item* item;
+ while((item = li++))
+ {
+ num_fields++;
+ uchar len = (uchar) strlen(item->name);
+ field_block_len += len + 1;
+ fields_buf.append(item->name, len + 1);
+ field_lens_buf.append((char*)&len, 1);
+ }
+
+ field_lens = (const uchar*)field_lens_buf.ptr();
+ fields = fields_buf.ptr();
+ }
+
+#endif
+
+// the caller must do buf[event_len] = 0 before he starts using the
+// constructed event
+Load_log_event::Load_log_event(const char* buf, int event_len,
+ bool old_format):
+ Log_event(buf, old_format),num_fields(0),fields(0),
field_lens(0),field_block_len(0),
table_name(0),db(0),fname(0)
{
- ulong data_len;
-
- if((uint)event_len < (LOAD_EVENT_OVERHEAD + LOG_EVENT_HEADER_LEN))
+ if (!event_len) // derived class, will call copy_log_event() itself
return;
- buf += EVENT_LEN_OFFSET;
- memcpy(&sql_ex, buf + LOAD_HEADER_LEN + 4, sizeof(sql_ex));
- data_len = event_len;
-
- if(!(data_buf = (char*)my_malloc(data_len + 1, MYF(MY_WME))))
- return;
- memcpy(data_buf, buf + 22 + sizeof(sql_ex), data_len);
- copy_log_event(buf, data_len);
+ copy_log_event(buf, event_len, old_format);
}
-void Load_log_event::copy_log_event(const char *buf, ulong data_len)
+int Load_log_event::copy_log_event(const char *buf, ulong event_len,
+ bool old_format)
{
- thread_id = uint4korr(buf+4);
- exec_time = uint4korr(buf+8);
- skip_lines = uint4korr(buf + 12);
- table_name_len = (uint)buf[16];
- db_len = (uint)buf[17];
- num_fields = uint4korr(buf + 18);
+ uint data_len;
+ char* buf_end = (char*)buf + event_len;
+ const char* data_head = buf + ((old_format) ?
+ OLD_HEADER_LEN : LOG_EVENT_HEADER_LEN);
+ thread_id = uint4korr(data_head + L_THREAD_ID_OFFSET);
+ exec_time = uint4korr(data_head + L_EXEC_TIME_OFFSET);
+ skip_lines = uint4korr(data_head + L_SKIP_LINES_OFFSET);
+ table_name_len = (uint)data_head[L_TBL_LEN_OFFSET];
+ db_len = (uint)data_head[L_DB_LEN_OFFSET];
+ num_fields = uint4korr(data_head + L_NUM_FIELDS_OFFSET);
+ int body_offset = (buf[EVENT_TYPE_OFFSET] == LOAD_EVENT) ?
+ LOAD_HEADER_LEN + OLD_HEADER_LEN : get_data_body_offset();
+
+ if ((int) event_len < body_offset)
+ return 1;
+ //sql_ex.init() on success returns the pointer to the first byte after
+ //the sql_ex structure, which is the start of field lengths array
+ if (!(field_lens=(uchar*)sql_ex.init((char*)buf + body_offset,
+ buf_end,
+ buf[EVENT_TYPE_OFFSET] != LOAD_EVENT)))
+ return 1;
+
+ data_len = event_len - body_offset;
if (num_fields > data_len) // simple sanity check against corruption
- return;
-
- field_lens = (uchar*) data_buf;
+ return 1;
uint i;
for (i = 0; i < num_fields; i++)
{
field_block_len += (uint)field_lens[i] + 1;
}
fields = (char*)field_lens + num_fields;
-
- *((char*)data_buf+data_len) = 0;
table_name = fields + field_block_len;
db = table_name + table_name_len + 1;
fname = db + db_len + 1;
- fname_len = data_len - 2 - db_len - table_name_len - num_fields -
- field_block_len;
+ fname_len = strlen(fname);
+ // null termination is accomplished by the caller doing buf[event_len]=0
+ return 0;
}
+#ifdef MYSQL_CLIENT
void Load_log_event::print(FILE* file, bool short_form, char* last_db)
{
@@ -669,7 +1154,7 @@ void Load_log_event::print(FILE* file, bool short_form, char* last_db)
if(db && db[0] && !same_db)
fprintf(file, "use %s;\n", db);
- fprintf(file, "LOAD DATA INFILE '%s' ", fname);
+ fprintf(file, "LOAD DATA INFILE '%-*s' ", fname_len, fname);
if(sql_ex.opt_flags && REPLACE_FLAG )
fprintf(file," REPLACE ");
@@ -677,36 +1162,36 @@ void Load_log_event::print(FILE* file, bool short_form, char* last_db)
fprintf(file," IGNORE ");
fprintf(file, "INTO TABLE %s ", table_name);
- if(!(sql_ex.empty_flags & FIELD_TERM_EMPTY))
+ if(sql_ex.field_term)
{
fprintf(file, " FIELDS TERMINATED BY ");
- pretty_print_char(file, sql_ex.field_term);
+ pretty_print_str(file, sql_ex.field_term, sql_ex.field_term_len);
}
- if(!(sql_ex.empty_flags & ENCLOSED_EMPTY))
+ if(sql_ex.enclosed)
{
if(sql_ex.opt_flags && OPT_ENCLOSED_FLAG )
fprintf(file," OPTIONALLY ");
fprintf(file, " ENCLOSED BY ");
- pretty_print_char(file, sql_ex.enclosed);
+ pretty_print_str(file, sql_ex.enclosed, sql_ex.enclosed_len);
}
- if(!(sql_ex.empty_flags & ESCAPED_EMPTY))
+ if (sql_ex.escaped)
{
fprintf(file, " ESCAPED BY ");
- pretty_print_char(file, sql_ex.escaped);
+ pretty_print_str(file, sql_ex.escaped, sql_ex.escaped_len);
}
- if(!(sql_ex.empty_flags & LINE_TERM_EMPTY))
+ if (sql_ex.line_term)
{
fprintf(file," LINES TERMINATED BY ");
- pretty_print_char(file, sql_ex.line_term);
+ pretty_print_str(file, sql_ex.line_term, sql_ex.line_term_len);
}
- if(!(sql_ex.empty_flags & LINE_START_EMPTY))
+ if (sql_ex.line_start)
{
fprintf(file," LINES STARTING BY ");
- pretty_print_char(file, sql_ex.line_start);
+ pretty_print_str(file, sql_ex.line_start, sql_ex.line_start_len);
}
if((int)skip_lines > 0)
@@ -731,18 +1216,794 @@ void Load_log_event::print(FILE* file, bool short_form, char* last_db)
fprintf(file, ";\n");
}
+#endif /* #ifdef MYSQL_CLIENT */
+
#ifndef MYSQL_CLIENT
+void Log_event::set_log_pos(MYSQL_LOG* log)
+ {
+ if (!log_pos)
+ log_pos = my_b_tell(&log->log_file);
+ }
+
void Load_log_event::set_fields(List<Item> &fields)
{
uint i;
const char* field = this->fields;
- for(i = 0; i < num_fields; i++)
+ for (i = 0; i < num_fields; i++)
+ {
+ fields.push_back(new Item_field(db, table_name, field));
+ field += field_lens[i] + 1;
+ }
+}
+
+
+Slave_log_event::Slave_log_event(THD* thd_arg,
+ struct st_relay_log_info* rli):
+ Log_event(thd_arg),mem_pool(0),master_host(0)
+{
+ if (!rli->inited)
+ return;
+
+ MASTER_INFO* mi = rli->mi;
+ // TODO: re-write this better without holding both locks at the same time
+ pthread_mutex_lock(&mi->data_lock);
+ pthread_mutex_lock(&rli->data_lock);
+ master_host_len = strlen(mi->host);
+ master_log_len = strlen(rli->master_log_name);
+ // on OOM, just do not initialize the structure and print the error
+ if ((mem_pool = (char*)my_malloc(get_data_size() + 1,
+ MYF(MY_WME))))
+ {
+ master_host = mem_pool + SL_MASTER_HOST_OFFSET ;
+ memcpy(master_host, mi->host, master_host_len + 1);
+ master_log = master_host + master_host_len + 1;
+ memcpy(master_log, rli->master_log_name, master_log_len + 1);
+ master_port = mi->port;
+ master_pos = rli->master_log_pos;
+ }
+ else
+ sql_print_error("Out of memory while recording slave event");
+ pthread_mutex_unlock(&rli->data_lock);
+ pthread_mutex_unlock(&mi->data_lock);
+}
+
+
+#endif
+
+
+Slave_log_event::~Slave_log_event()
+{
+ my_free(mem_pool, MYF(MY_ALLOW_ZERO_PTR));
+}
+
+#ifdef MYSQL_CLIENT
+
+void Slave_log_event::print(FILE* file, bool short_form, char* last_db)
+{
+ char llbuff[22];
+ if(short_form)
+ return;
+ print_header(file);
+ fputc('\n', file);
+ fprintf(file, "Slave: master_host='%s' master_port=%d \
+ master_log=%s master_pos=%s\n",
+ master_host, master_port, master_log, llstr(master_pos, llbuff));
+}
+
+#endif
+
+int Slave_log_event::get_data_size()
+{
+ return master_host_len + master_log_len + 1 + SL_MASTER_HOST_OFFSET;
+}
+
+int Slave_log_event::write_data(IO_CACHE* file)
+{
+ int8store(mem_pool + SL_MASTER_POS_OFFSET, master_pos);
+ int2store(mem_pool + SL_MASTER_PORT_OFFSET, master_port);
+ // log and host are already there
+ return my_b_safe_write(file, (byte*)mem_pool, get_data_size());
+}
+
+void Slave_log_event::init_from_mem_pool(int data_size)
+{
+ master_pos = uint8korr(mem_pool + SL_MASTER_POS_OFFSET);
+ master_port = uint2korr(mem_pool + SL_MASTER_PORT_OFFSET);
+ master_host = mem_pool + SL_MASTER_HOST_OFFSET;
+ master_host_len = strlen(master_host);
+ // safety
+ master_log = master_host + master_host_len + 1;
+ if(master_log > mem_pool + data_size)
+ {
+ master_host = 0;
+ return;
+ }
+ master_log_len = strlen(master_log);
+}
+
+Slave_log_event::Slave_log_event(const char* buf, int event_len):
+ Log_event(buf,0),mem_pool(0),master_host(0)
+{
+ event_len -= LOG_EVENT_HEADER_LEN;
+ if(event_len < 0)
+ return;
+ if(!(mem_pool = (char*)my_malloc(event_len + 1, MYF(MY_WME))))
+ return;
+ memcpy(mem_pool, buf + LOG_EVENT_HEADER_LEN, event_len);
+ mem_pool[event_len] = 0;
+ init_from_mem_pool(event_len);
+}
+
+#ifndef MYSQL_CLIENT
+Create_file_log_event::Create_file_log_event(THD* thd_arg, sql_exchange* ex,
+ const char* db_arg, const char* table_name_arg,
+ List<Item>& fields_arg, enum enum_duplicates handle_dup,
+ char* block_arg, uint block_len_arg):
+ Load_log_event(thd_arg,ex,db_arg,table_name_arg,fields_arg,handle_dup),
+ fake_base(0),block(block_arg),block_len(block_len_arg),
+ file_id(thd_arg->file_id = mysql_bin_log.next_file_id())
+{
+ sql_ex.force_new_format();
+}
+#endif
+
+int Create_file_log_event::write_data_body(IO_CACHE* file)
+{
+ int res;
+ if ((res = Load_log_event::write_data_body(file)) || fake_base)
+ return res;
+ return (my_b_safe_write(file, (byte*) "", 1) ||
+ my_b_safe_write(file, (byte*) block, block_len));
+}
+
+int Create_file_log_event::write_data_header(IO_CACHE* file)
+{
+ int res;
+ if ((res = Load_log_event::write_data_header(file)) || fake_base)
+ return res;
+ byte buf[CREATE_FILE_HEADER_LEN];
+ int4store(buf + CF_FILE_ID_OFFSET, file_id);
+ return my_b_safe_write(file, buf, CREATE_FILE_HEADER_LEN);
+}
+
+int Create_file_log_event::write_base(IO_CACHE* file)
+{
+ int res;
+ fake_base = 1; // pretend we are Load event
+ res = write(file);
+ fake_base = 0;
+ return res;
+}
+
+Create_file_log_event::Create_file_log_event(const char* buf, int len,
+ bool old_format):
+ Load_log_event(buf,0,old_format),fake_base(0),block(0),inited_from_old(0)
+{
+ int block_offset;
+ if (copy_log_event(buf,len,old_format))
+ return;
+ if (!old_format)
+ {
+ file_id = uint4korr(buf + LOG_EVENT_HEADER_LEN +
+ + LOAD_HEADER_LEN + CF_FILE_ID_OFFSET);
+ block_offset = LOG_EVENT_HEADER_LEN + Load_log_event::get_data_size() +
+ CREATE_FILE_HEADER_LEN + 1; // 1 for \0 terminating fname
+ if (len < block_offset)
+ return;
+ block = (char*)buf + block_offset;
+ block_len = len - block_offset;
+ }
+ else
+ {
+ sql_ex.force_new_format();
+ inited_from_old = 1;
+ }
+}
+
+
+#ifdef MYSQL_CLIENT
+void Create_file_log_event::print(FILE* file, bool short_form,
+ char* last_db)
+{
+ if (short_form)
+ return;
+ Load_log_event::print(file, 1, last_db);
+ fprintf(file, " file_id=%d, block_len=%d\n", file_id, block_len);
+}
+#endif
+
+#ifndef MYSQL_CLIENT
+void Create_file_log_event::pack_info(String* packet)
+{
+ char buf1[256];
+ String tmp(buf1, sizeof(buf1));
+ tmp.length(0);
+ char buf[22];
+ tmp.append("db=");
+ tmp.append(db, db_len);
+ tmp.append(";table=");
+ tmp.append(table_name, table_name_len);
+ tmp.append(";file_id=");
+ tmp.append(llstr(file_id,buf));
+ tmp.append(";block_len=");
+ tmp.append(llstr(block_len,buf));
+ net_store_data(packet, (char*)tmp.ptr(), tmp.length());
+}
+#endif
+
+#ifndef MYSQL_CLIENT
+Append_block_log_event::Append_block_log_event(THD* thd_arg, char* block_arg,
+ uint block_len_arg):
+ Log_event(thd_arg), block(block_arg),block_len(block_len_arg),
+ file_id(thd_arg->file_id)
+{
+}
+#endif
+
+Append_block_log_event::Append_block_log_event(const char* buf, int len):
+ Log_event(buf, 0),block(0)
+{
+ if((uint)len < APPEND_BLOCK_EVENT_OVERHEAD)
+ return;
+ file_id = uint4korr(buf + LOG_EVENT_HEADER_LEN + AB_FILE_ID_OFFSET);
+ block = (char*)buf + APPEND_BLOCK_EVENT_OVERHEAD;
+ block_len = len - APPEND_BLOCK_EVENT_OVERHEAD;
+}
+
+int Append_block_log_event::write_data(IO_CACHE* file)
+{
+ byte buf[APPEND_BLOCK_HEADER_LEN];
+ int4store(buf + AB_FILE_ID_OFFSET, file_id);
+ return (my_b_safe_write(file, buf, APPEND_BLOCK_HEADER_LEN) ||
+ my_b_safe_write(file, (byte*) block, block_len));
+}
+
+#ifdef MYSQL_CLIENT
+void Append_block_log_event::print(FILE* file, bool short_form,
+ char* last_db)
+{
+ if (short_form)
+ return;
+ print_header(file);
+ fputc('\n', file);
+ fprintf(file, "#Append_block: file_id=%d, block_len=%d\n",
+ file_id, block_len);
+}
+#endif
+#ifndef MYSQL_CLIENT
+void Append_block_log_event::pack_info(String* packet)
+{
+ char buf1[256];
+ String tmp(buf1, sizeof(buf1));
+ tmp.length(0);
+ char buf[22];
+ tmp.append(";file_id=");
+ tmp.append(llstr(file_id,buf));
+ tmp.append(";block_len=");
+ tmp.append(llstr(block_len,buf));
+ net_store_data(packet, (char*)tmp.ptr(), tmp.length());
+}
+#endif
+
+#ifndef MYSQL_CLIENT
+Delete_file_log_event::Delete_file_log_event(THD* thd_arg):
+ Log_event(thd_arg),file_id(thd_arg->file_id)
+{
+}
+#endif
+
+Delete_file_log_event::Delete_file_log_event(const char* buf, int len):
+ Log_event(buf, 0),file_id(0)
+{
+ if((uint)len < DELETE_FILE_EVENT_OVERHEAD)
+ return;
+ file_id = uint4korr(buf + LOG_EVENT_HEADER_LEN + AB_FILE_ID_OFFSET);
+}
+
+int Delete_file_log_event::write_data(IO_CACHE* file)
+{
+ byte buf[DELETE_FILE_HEADER_LEN];
+ int4store(buf + DF_FILE_ID_OFFSET, file_id);
+ return my_b_safe_write(file, buf, DELETE_FILE_HEADER_LEN);
+}
+
+#ifdef MYSQL_CLIENT
+void Delete_file_log_event::print(FILE* file, bool short_form,
+ char* last_db)
+{
+ if (short_form)
+ return;
+ print_header(file);
+ fputc('\n', file);
+ fprintf(file, "#Delete_file: file_id=%d\n",
+ file_id);
+}
+#endif
+#ifndef MYSQL_CLIENT
+void Delete_file_log_event::pack_info(String* packet)
+{
+ char buf1[256];
+ String tmp(buf1, sizeof(buf1));
+ tmp.length(0);
+ char buf[22];
+ tmp.append(";file_id=");
+ tmp.append(llstr(file_id,buf));
+ net_store_data(packet, (char*)tmp.ptr(), tmp.length());
+}
+#endif
+
+#ifndef MYSQL_CLIENT
+Execute_load_log_event::Execute_load_log_event(THD* thd_arg):
+ Log_event(thd_arg),file_id(thd_arg->file_id)
+{
+}
+#endif
+
+Execute_load_log_event::Execute_load_log_event(const char* buf,int len):
+ Log_event(buf, 0),file_id(0)
+{
+ if((uint)len < EXEC_LOAD_EVENT_OVERHEAD)
+ return;
+ file_id = uint4korr(buf + LOG_EVENT_HEADER_LEN + EL_FILE_ID_OFFSET);
+}
+
+int Execute_load_log_event::write_data(IO_CACHE* file)
+{
+ byte buf[EXEC_LOAD_HEADER_LEN];
+ int4store(buf + EL_FILE_ID_OFFSET, file_id);
+ return my_b_safe_write(file, buf, EXEC_LOAD_HEADER_LEN);
+}
+
+#ifdef MYSQL_CLIENT
+void Execute_load_log_event::print(FILE* file, bool short_form,
+ char* last_db)
+{
+ if (short_form)
+ return;
+ print_header(file);
+ fputc('\n', file);
+ fprintf(file, "#Exec_load: file_id=%d\n",
+ file_id);
+}
+#endif
+#ifndef MYSQL_CLIENT
+void Execute_load_log_event::pack_info(String* packet)
+{
+ char buf1[256];
+ String tmp(buf1, sizeof(buf1));
+ tmp.length(0);
+ char buf[22];
+ tmp.append(";file_id=");
+ tmp.append(llstr(file_id,buf));
+ net_store_data(packet, (char*)tmp.ptr(), tmp.length());
+}
+#endif
+
+#ifndef MYSQL_CLIENT
+int Query_log_event::exec_event(struct st_relay_log_info* rli)
+{
+ int expected_error,actual_error = 0;
+ init_sql_alloc(&thd->mem_root, 8192,0);
+ thd->db = rewrite_db((char*)db);
+ DBUG_ASSERT(q_len == strlen(query));
+ if (db_ok(thd->db, replicate_do_db, replicate_ignore_db))
+ {
+ thd->query = (char*)query;
+ thd->set_time((time_t)when);
+ thd->current_tablenr = 0;
+ VOID(pthread_mutex_lock(&LOCK_thread_count));
+ thd->query_id = query_id++;
+ VOID(pthread_mutex_unlock(&LOCK_thread_count));
+ thd->query_error = 0; // clear error
+ thd->net.last_errno = 0;
+ thd->net.last_error[0] = 0;
+ thd->slave_proxy_id = thread_id; // for temp tables
+
+ // sanity check to make sure the master did not get a really bad
+ // error on the query
+ if (ignored_error_code((expected_error = error_code)) ||
+ !check_expected_error(thd,rli,expected_error))
{
- fields.push_back(new Item_field(db, table_name, field));
- field += field_lens[i] + 1;
+ mysql_parse(thd, thd->query, q_len);
+ if (expected_error !=
+ (actual_error = thd->net.last_errno) && expected_error)
+ {
+ const char* errmsg = "Slave: did not get the expected error\
+ running query from master - expected: '%s' (%d), got '%s' (%d)";
+ sql_print_error(errmsg, ER_SAFE(expected_error),
+ expected_error,
+ actual_error ? thd->net.last_error: "no error",
+ actual_error);
+ thd->query_error = 1;
+ }
+ else if (expected_error == actual_error
+ || ignored_error_code(actual_error))
+ {
+ thd->query_error = 0;
+ *rli->last_slave_error = 0;
+ rli->last_slave_errno = 0;
+ }
}
+ else
+ {
+ // master could be inconsistent, abort and tell DBA to check/fix it
+ thd->db = thd->query = 0;
+ thd->convert_set = 0;
+ close_thread_tables(thd);
+ free_root(&thd->mem_root,0);
+ return 1;
+ }
+ }
+ thd->db = 0; // prevent db from being freed
+ thd->query = 0; // just to be sure
+ // assume no convert for next query unless set explictly
+ thd->convert_set = 0;
+ close_thread_tables(thd);
+
+ if (thd->query_error || thd->fatal_error)
+ {
+ slave_print_error(rli,actual_error, "error '%s' on query '%s'",
+ actual_error ? thd->net.last_error :
+ "unexpected success or fatal error", query);
+ free_root(&thd->mem_root,0);
+ return 1;
+ }
+ free_root(&thd->mem_root,0);
+ return Log_event::exec_event(rli);
+}
+
+int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli)
+{
+ init_sql_alloc(&thd->mem_root, 8192,0);
+ thd->db = rewrite_db((char*)db);
+ thd->query = 0;
+ thd->query_error = 0;
+
+ if(db_ok(thd->db, replicate_do_db, replicate_ignore_db))
+ {
+ thd->set_time((time_t)when);
+ thd->current_tablenr = 0;
+ VOID(pthread_mutex_lock(&LOCK_thread_count));
+ thd->query_id = query_id++;
+ VOID(pthread_mutex_unlock(&LOCK_thread_count));
+
+ TABLE_LIST tables;
+ bzero((char*) &tables,sizeof(tables));
+ tables.db = thd->db;
+ tables.name = tables.real_name = (char*)table_name;
+ tables.lock_type = TL_WRITE;
+ // the table will be opened in mysql_load
+ if(table_rules_on && !tables_ok(thd, &tables))
+ {
+ // TODO: this is a bug - this needs to be moved to the I/O thread
+ if (net)
+ skip_load_data_infile(net);
+ }
+ else
+ {
+ char llbuff[22];
+ enum enum_duplicates handle_dup = DUP_IGNORE;
+ if (sql_ex.opt_flags && REPLACE_FLAG)
+ handle_dup = DUP_REPLACE;
+ sql_exchange ex((char*)fname, sql_ex.opt_flags &&
+ DUMPFILE_FLAG );
+ String field_term(sql_ex.field_term,sql_ex.field_term_len);
+ String enclosed(sql_ex.enclosed,sql_ex.enclosed_len);
+ String line_term(sql_ex.line_term,sql_ex.line_term_len);
+ String line_start(sql_ex.line_start,sql_ex.line_start_len);
+ String escaped(sql_ex.escaped,sql_ex.escaped_len);
+
+ ex.opt_enclosed = (sql_ex.opt_flags & OPT_ENCLOSED_FLAG);
+ if (sql_ex.empty_flags & FIELD_TERM_EMPTY)
+ ex.field_term->length(0);
+
+ ex.skip_lines = skip_lines;
+ List<Item> fields;
+ set_fields(fields);
+ thd->slave_proxy_id = thd->thread_id;
+ if (net)
+ {
+ // mysql_load will use thd->net to read the file
+ thd->net.vio = net->vio;
+ // make sure the client does not get confused
+ // about the packet sequence
+ thd->net.pkt_nr = net->pkt_nr;
+ }
+ if(mysql_load(thd, &ex, &tables, fields, handle_dup, net != 0,
+ TL_WRITE))
+ thd->query_error = 1;
+ if(thd->cuted_fields)
+ sql_print_error("Slave: load data infile at position %s in log \
+'%s' produced %d warning(s)", llstr(rli->master_log_pos,llbuff), RPL_LOG_NAME,
+ thd->cuted_fields );
+ if(net)
+ net->pkt_nr = thd->net.pkt_nr;
+ }
+ }
+ else
+ {
+ // we will just ask the master to send us /dev/null if we do not
+ // want to load the data
+ // TODO: this a bug - needs to be done in I/O thread
+ if (net)
+ skip_load_data_infile(net);
+ }
+
+ thd->net.vio = 0;
+ thd->db = 0;// prevent db from being freed
+ close_thread_tables(thd);
+ if(thd->query_error)
+ {
+ int sql_error = thd->net.last_errno;
+ if (!sql_error)
+ sql_error = ER_UNKNOWN_ERROR;
+
+ slave_print_error(rli,sql_error,
+ "Slave: Error '%s' running load data infile ",
+ ER_SAFE(sql_error));
+ free_root(&thd->mem_root,0);
+ return 1;
+ }
+ free_root(&thd->mem_root,0);
+
+ if(thd->fatal_error)
+ {
+ sql_print_error("Slave: Fatal error running LOAD DATA INFILE ");
+ return 1;
+ }
+
+ return Log_event::exec_event(rli);
+}
+
+int Start_log_event::exec_event(struct st_relay_log_info* rli)
+{
+ close_temporary_tables(thd);
+ // if we have old format, load_tmpdir is cleaned up by the I/O thread
+ // TODO: cleanup_load_tmpdir() needs to remove only the files associated
+ // with the server id that has just started
+ if (!rli->mi->old_format)
+ cleanup_load_tmpdir();
+ return Log_event::exec_event(rli);
+}
+
+int Stop_log_event::exec_event(struct st_relay_log_info* rli)
+{
+ // do not clean up immediately after rotate event
+ if (rli->master_log_pos > 4)
+ {
+ close_temporary_tables(thd);
+ cleanup_load_tmpdir();
+ }
+ /*
+ We do not want to update master_log pos because we get a rotate event
+ before stop, so by now master_log_name is set to the next log
+ if we updated it, we will have incorrect master coordinates and this
+ could give false triggers in MASTER_POS_WAIT() that we have reached
+ the targed position when in fact we have not
+ */
+ rli->inc_pos(get_event_len(), 0);
+ flush_relay_log_info(rli);
+ return 0;
+}
+
+int Rotate_log_event::exec_event(struct st_relay_log_info* rli)
+{
+ bool rotate_binlog = 0, write_slave_event = 0;
+ char* log_name = rli->master_log_name;
+ pthread_mutex_lock(&rli->data_lock);
+ // TODO: probably needs re-write
+ // rotate local binlog only if the name of remote has changed
+ if (!*log_name || !(log_name[ident_len] == 0 &&
+ !memcmp(log_name, new_log_ident, ident_len)))
+ {
+ write_slave_event = (!(flags & LOG_EVENT_FORCED_ROTATE_F)
+ && mysql_bin_log.is_open());
+ rotate_binlog = (*log_name && write_slave_event);
+ if (ident_len >= sizeof(rli->master_log_name))
+ return 1;
+ memcpy(log_name, new_log_ident,ident_len);
+ log_name[ident_len] = 0;
+ }
+ rli->master_log_pos = pos;
+ rli->relay_log_pos += get_event_len();
+ if (rotate_binlog)
+ {
+ mysql_bin_log.new_file();
+ rli->master_log_pos = 4;
+ }
+ pthread_cond_broadcast(&rli->data_cond);
+ pthread_mutex_unlock(&rli->data_lock);
+ flush_relay_log_info(rli);
+
+ if (write_slave_event)
+ {
+ Slave_log_event s(thd, rli);
+ if (s.master_host)
+ {
+ s.set_log_pos(&mysql_bin_log);
+ s.server_id = ::server_id;
+ mysql_bin_log.write(&s);
+ }
+ }
+ return 0;
+}
+
+int Intvar_log_event::exec_event(struct st_relay_log_info* rli)
+{
+ switch (type)
+ {
+ case LAST_INSERT_ID_EVENT:
+ thd->last_insert_id_used = 1;
+ thd->last_insert_id = val;
+ break;
+ case INSERT_ID_EVENT:
+ thd->next_insert_id = val;
+ break;
+ }
+ rli->inc_pending(get_event_len());
+ return 0;
+}
+
+int Slave_log_event::exec_event(struct st_relay_log_info* rli)
+{
+ if(mysql_bin_log.is_open())
+ mysql_bin_log.write(this);
+ return Log_event::exec_event(rli);
+}
+
+int Create_file_log_event::exec_event(struct st_relay_log_info* rli)
+{
+ char fname_buf[FN_REFLEN+10];
+ char *p;
+ int fd = -1;
+ IO_CACHE file;
+ int error = 1;
+
+ bzero((char*)&file, sizeof(file));
+ p = slave_load_file_stem(fname_buf, file_id, server_id);
+ strmov(p, ".info"); // strmov takes less code than memcpy
+ if ((fd = my_open(fname_buf, O_WRONLY|O_CREAT|O_BINARY|O_TRUNC,
+ MYF(MY_WME))) < 0 ||
+ init_io_cache(&file, fd, IO_SIZE, WRITE_CACHE, (my_off_t)0, 0,
+ MYF(MY_WME|MY_NABP)))
+ {
+ slave_print_error(rli,my_errno, "Could not open file '%s'", fname_buf);
+ goto err;
+ }
+ // a trick to avoid allocating another buffer
+ strmov(p, ".data");
+ fname = fname_buf;
+ fname_len = (uint)(p-fname) + 5;
+ if (write_base(&file))
+ {
+ strmov(p, ".info"); // to have it right in the error message
+ slave_print_error(rli,my_errno, "Could not write to file '%s'", fname_buf);
+ goto err;
+ }
+ end_io_cache(&file);
+ my_close(fd, MYF(0));
+
+ // fname_buf now already has .data, not .info, because we did our trick
+ if ((fd = my_open(fname_buf, O_WRONLY|O_CREAT|O_BINARY|O_TRUNC,
+ MYF(MY_WME))) < 0)
+ {
+ slave_print_error(rli,my_errno, "Could not open file '%s'", fname_buf);
+ goto err;
+ }
+ if (my_write(fd, (byte*) block, block_len, MYF(MY_WME+MY_NABP)))
+ {
+ slave_print_error(rli,my_errno, "Write to '%s' failed", fname_buf);
+ goto err;
+ }
+ if (mysql_bin_log.is_open())
+ mysql_bin_log.write(this);
+ error=0;
+err:
+ if (error)
+ end_io_cache(&file);
+ if (fd >= 0)
+ my_close(fd, MYF(0));
+ return error ? 1 : Log_event::exec_event(rli);
+}
+
+int Delete_file_log_event::exec_event(struct st_relay_log_info* rli)
+{
+ char fname[FN_REFLEN+10];
+ char* p;
+ p = slave_load_file_stem(fname, file_id, server_id);
+ memcpy(p, ".data", 6);
+ (void)my_delete(fname, MYF(MY_WME));
+ memcpy(p, ".info", 6);
+ (void)my_delete(fname, MYF(MY_WME));
+ if (mysql_bin_log.is_open())
+ mysql_bin_log.write(this);
+ return Log_event::exec_event(rli);
}
+int Append_block_log_event::exec_event(struct st_relay_log_info* rli)
+{
+ char fname[FN_REFLEN+10];
+ char* p;
+ int fd = -1;
+ int error = 1;
+ p = slave_load_file_stem(fname, file_id, server_id);
+ memcpy(p, ".data", 6);
+ if ((fd = my_open(fname, O_WRONLY|O_APPEND|O_BINARY, MYF(MY_WME))) < 0)
+ {
+ slave_print_error(rli,my_errno, "Could not open file '%s'", fname);
+ goto err;
+ }
+ if (my_write(fd, (byte*) block, block_len, MYF(MY_WME+MY_NABP)))
+ {
+ slave_print_error(rli,my_errno, "Write to '%s' failed", fname);
+ goto err;
+ }
+ if (mysql_bin_log.is_open())
+ mysql_bin_log.write(this);
+ error=0;
+err:
+ if (fd >= 0)
+ my_close(fd, MYF(0));
+ return error ? error : Log_event::exec_event(rli);
+}
+
+int Execute_load_log_event::exec_event(struct st_relay_log_info* rli)
+{
+ char fname[FN_REFLEN+10];
+ char* p;
+ int fd = -1;
+ int error = 1;
+ ulong save_options;
+ IO_CACHE file;
+ Load_log_event* lev = 0;
+ p = slave_load_file_stem(fname, file_id, server_id);
+ memcpy(p, ".info", 6);
+ bzero((char*)&file, sizeof(file));
+ if ((fd = my_open(fname, O_RDONLY|O_BINARY, MYF(MY_WME))) < 0 ||
+ init_io_cache(&file, fd, IO_SIZE, READ_CACHE, (my_off_t)0, 0,
+ MYF(MY_WME|MY_NABP)))
+ {
+ slave_print_error(rli,my_errno, "Could not open file '%s'", fname);
+ goto err;
+ }
+ if (!(lev = (Load_log_event*)Log_event::read_log_event(&file,
+ (pthread_mutex_t*)0,
+ (bool)0))
+ || lev->get_type_code() != NEW_LOAD_EVENT)
+ {
+ slave_print_error(rli,0, "File '%s' appears corrupted", fname);
+ goto err;
+ }
+ // we want to disable binary logging in slave thread
+ // because we need the file events to appear in the same order
+ // as they do on the master relative to other events, so that we
+ // can preserve ascending order of log sequence numbers - needed
+ // to handle failover
+ save_options = thd->options;
+ thd->options &= ~ (ulong) (OPTION_BIN_LOG);
+ lev->thd = thd;
+ if (lev->exec_event(0,0))
+ {
+ slave_print_error(rli,my_errno, "Failed executing load from '%s'", fname);
+ thd->options = save_options;
+ goto err;
+ }
+ thd->options = save_options;
+ (void)my_delete(fname, MYF(MY_WME));
+ memcpy(p, ".data", 6);
+ (void)my_delete(fname, MYF(MY_WME));
+ if (mysql_bin_log.is_open())
+ mysql_bin_log.write(this);
+ error = 0;
+err:
+ delete lev;
+ end_io_cache(&file);
+ if (fd >= 0)
+ my_close(fd, MYF(0));
+ return error ? error : Log_event::exec_event(rli);
+}
+
+
#endif
diff --git a/sql/log_event.h b/sql/log_event.h
index 94f7cce0e35..a29c3952d46 100644
--- a/sql/log_event.h
+++ b/sql/log_event.h
@@ -34,40 +34,195 @@
#define LOG_READ_TOO_LARGE -7
#define LOG_EVENT_OFFSET 4
-#define BINLOG_VERSION 1
+#define BINLOG_VERSION 3
+
+/* we could have used SERVER_VERSION_LENGTH, but this introduces an
+ obscure dependency - if somebody decided to change SERVER_VERSION_LENGTH
+ this would have broke the replication protocol
+*/
+#define ST_SERVER_VER_LEN 50
+
+#define DUMPFILE_FLAG 0x1
+#define OPT_ENCLOSED_FLAG 0x2
+#define REPLACE_FLAG 0x4
+#define IGNORE_FLAG 0x8
+
+#define FIELD_TERM_EMPTY 0x1
+#define ENCLOSED_EMPTY 0x2
+#define LINE_TERM_EMPTY 0x4
+#define LINE_START_EMPTY 0x8
+#define ESCAPED_EMPTY 0x10
+
+struct old_sql_ex
+ {
+ char field_term;
+ char enclosed;
+ char line_term;
+ char line_start;
+ char escaped;
+ char opt_flags;
+ char empty_flags;
+ };
+
+#define NUM_LOAD_DELIM_STRS 5
+
+
+struct sql_ex_info
+ {
+ char* field_term;
+ char* enclosed;
+ char* line_term;
+ char* line_start;
+ char* escaped;
+ uint8 field_term_len,enclosed_len,line_term_len,line_start_len,
+ escaped_len;
+ char opt_flags;
+ char empty_flags;
+ int cached_new_format;
+
+ // store in new format even if old is possible
+ void force_new_format() { cached_new_format = 1;}
+ int data_size() { return new_format() ?
+ field_term_len + enclosed_len + line_term_len +
+ line_start_len + escaped_len + 6 : 7;}
+ int write_data(IO_CACHE* file);
+ char* init(char* buf,char* buf_end,bool use_new_format);
+ bool new_format()
+ {
+ return (cached_new_format != -1) ? cached_new_format :
+ (cached_new_format=(field_term_len > 1 ||
+ enclosed_len > 1 ||
+ line_term_len > 1 || line_start_len > 1 ||
+ escaped_len > 1));
+ }
+ } ;
+
+/* Binary log consists of events. Each event has a fixed length header,
+ followed by possibly variable ( depending on the type of event) length
+ data body. The data body consists of an optional fixed length segment
+ (post-header), and an optional variable length segment. See #defines and
+ comments below for the format specifics
+*/
+
+
+/* event-specific post-header sizes */
+#define LOG_EVENT_HEADER_LEN 19
+#define OLD_HEADER_LEN 13
+#define QUERY_HEADER_LEN (4 + 4 + 1 + 2)
+#define LOAD_HEADER_LEN (4 + 4 + 4 + 1 +1 + 4)
+#define START_HEADER_LEN (2 + ST_SERVER_VER_LEN + 4)
+#define ROTATE_HEADER_LEN 8
+#define CREATE_FILE_HEADER_LEN 4
+#define APPEND_BLOCK_HEADER_LEN 4
+#define EXEC_LOAD_HEADER_LEN 4
+#define DELETE_FILE_HEADER_LEN 4
+
+/* event header offsets */
-#define LOG_EVENT_HEADER_LEN 13
-#define QUERY_HEADER_LEN (sizeof(uint32) + sizeof(uint32) + \
- sizeof(uchar) + sizeof(uint16))
-#define LOAD_HEADER_LEN (sizeof(uint32) + sizeof(uint32) + \
- + sizeof(uint32) + 2 + sizeof(uint32))
-#define EVENT_LEN_OFFSET 9
#define EVENT_TYPE_OFFSET 4
+#define SERVER_ID_OFFSET 5
+#define EVENT_LEN_OFFSET 9
+#define LOG_POS_OFFSET 13
+#define FLAGS_OFFSET 17
+
+/* start event post-header */
+
+#define ST_BINLOG_VER_OFFSET 0
+#define ST_SERVER_VER_OFFSET 2
+#define ST_CREATED_OFFSET (ST_SERVER_VER_OFFSET + ST_SERVER_VER_LEN)
+
+/* slave event post-header */
+
+#define SL_MASTER_PORT_OFFSET 8
+#define SL_MASTER_POS_OFFSET 0
+#define SL_MASTER_HOST_OFFSET 10
+
+/* query event post-header */
+
+#define Q_THREAD_ID_OFFSET 0
+#define Q_EXEC_TIME_OFFSET 4
+#define Q_DB_LEN_OFFSET 8
+#define Q_ERR_CODE_OFFSET 9
+#define Q_DATA_OFFSET QUERY_HEADER_LEN
+
+/* Intvar event post-header */
+
+#define I_TYPE_OFFSET 0
+#define I_VAL_OFFSET 1
+
+/* Load event post-header */
+
+#define L_THREAD_ID_OFFSET 0
+#define L_EXEC_TIME_OFFSET 4
+#define L_SKIP_LINES_OFFSET 8
+#define L_TBL_LEN_OFFSET 12
+#define L_DB_LEN_OFFSET 13
+#define L_NUM_FIELDS_OFFSET 14
+#define L_SQL_EX_OFFSET 18
+#define L_DATA_OFFSET LOAD_HEADER_LEN
+
+/* Rotate event post-header */
+
+#define R_POS_OFFSET 0
+#define R_IDENT_OFFSET 8
+
+#define CF_FILE_ID_OFFSET 0
+#define CF_DATA_OFFSET CREATE_FILE_HEADER_LEN
+
+#define AB_FILE_ID_OFFSET 0
+#define AB_DATA_OFFSET APPEND_BLOCK_HEADER_LEN
+
+#define EL_FILE_ID_OFFSET 0
+
+#define DF_FILE_ID_OFFSET 0
+
#define QUERY_EVENT_OVERHEAD (LOG_EVENT_HEADER_LEN+QUERY_HEADER_LEN)
-#define ROTATE_EVENT_OVERHEAD LOG_EVENT_HEADER_LEN
-#define LOAD_EVENT_OVERHEAD (LOG_EVENT_HEADER_LEN+LOAD_HEADER_LEN+sizeof(sql_ex_info))
+#define QUERY_DATA_OFFSET (LOG_EVENT_HEADER_LEN+QUERY_HEADER_LEN)
+#define ROTATE_EVENT_OVERHEAD (LOG_EVENT_HEADER_LEN+ROTATE_HEADER_LEN)
+#define LOAD_EVENT_OVERHEAD (LOG_EVENT_HEADER_LEN+LOAD_HEADER_LEN)
+#define CREATE_FILE_EVENT_OVERHEAD (LOG_EVENT_HEADER_LEN+\
+ +LOAD_HEADER_LEN+CREATE_FILE_HEADER_LEN)
+#define DELETE_FILE_EVENT_OVERHEAD (LOG_EVENT_HEADER_LEN+DELETE_FILE_HEADER_LEN)
+#define EXEC_LOAD_EVENT_OVERHEAD (LOG_EVENT_HEADER_LEN+EXEC_LOAD_HEADER_LEN)
+#define APPEND_BLOCK_EVENT_OVERHEAD (LOG_EVENT_HEADER_LEN+APPEND_BLOCK_HEADER_LEN)
+
#define BINLOG_MAGIC "\xfe\x62\x69\x6e"
+#define LOG_EVENT_TIME_F 0x1
+#define LOG_EVENT_FORCED_ROTATE_F 0x2
+
enum Log_event_type { START_EVENT = 1, QUERY_EVENT =2,
STOP_EVENT=3, ROTATE_EVENT = 4, INTVAR_EVENT=5,
- LOAD_EVENT=6};
+ LOAD_EVENT=6, SLAVE_EVENT=7, CREATE_FILE_EVENT=8,
+ APPEND_BLOCK_EVENT=9, EXEC_LOAD_EVENT=10, DELETE_FILE_EVENT=11,
+ NEW_LOAD_EVENT=12};
enum Int_event_type { INVALID_INT_EVENT = 0, LAST_INSERT_ID_EVENT = 1, INSERT_ID_EVENT = 2
};
#ifndef MYSQL_CLIENT
class String;
+class MYSQL_LOG;
+class THD;
#endif
extern uint32 server_id;
+struct st_relay_log_info;
+
class Log_event
{
public:
time_t when;
ulong exec_time;
- int valid_exec_time; // if false, the exec time setting is bogus
uint32 server_id;
+ my_off_t log_pos;
+ uint16 flags;
+ int cached_event_len;
+ char* temp_buf;
+#ifndef MYSQL_CLIENT
+ THD* thd;
+#endif
static void *operator new(size_t size)
{
@@ -81,41 +236,63 @@ public:
int write(IO_CACHE* file);
int write_header(IO_CACHE* file);
- virtual int write_data(IO_CACHE* file __attribute__((unused))) { return 0; }
+ virtual int write_data(IO_CACHE* file)
+ { return write_data_header(file) || write_data_body(file); }
+ virtual int write_data_header(IO_CACHE* file __attribute__((unused)))
+ { return 0; }
+ virtual int write_data_body(IO_CACHE* file __attribute__((unused)))
+ { return 0; }
virtual Log_event_type get_type_code() = 0;
- Log_event(time_t when_arg, ulong exec_time_arg = 0,
- int valid_exec_time_arg = 0, uint32 server_id_arg = 0):
- when(when_arg), exec_time(exec_time_arg),
- valid_exec_time(valid_exec_time_arg)
- {
- server_id = server_id_arg ? server_id_arg : (::server_id);
- }
-
- Log_event(const char* buf): valid_exec_time(0)
- {
- when = uint4korr(buf);
- server_id = uint4korr(buf + 5);
- }
-
- virtual ~Log_event() {}
-
+ virtual bool is_valid() = 0;
+ virtual bool get_cache_stmt() { return 0; }
+ Log_event(const char* buf, bool old_format);
+#ifndef MYSQL_CLIENT
+ Log_event(THD* thd_arg, uint16 flags_arg = 0);
+#endif
+ virtual ~Log_event() { free_temp_buf();}
+ void register_temp_buf(char* buf) { temp_buf = buf; }
+ void free_temp_buf()
+ {
+ if (temp_buf)
+ {
+ my_free(temp_buf, MYF(0));
+ temp_buf = 0;
+ }
+ }
virtual int get_data_size() { return 0;}
+ virtual int get_data_body_offset() { return 0; }
+ int get_event_len() { return cached_event_len ? cached_event_len :
+ (cached_event_len = LOG_EVENT_HEADER_LEN + get_data_size()); }
+#ifdef MYSQL_CLIENT
virtual void print(FILE* file, bool short_form = 0, char* last_db = 0) = 0;
-
void print_timestamp(FILE* file, time_t *ts = 0);
void print_header(FILE* file);
-
+#endif
+
#ifndef MYSQL_CLIENT
// if mutex is 0, the read will proceed without mutex
- static Log_event* read_log_event(IO_CACHE* file, pthread_mutex_t* log_lock);
+ static Log_event* read_log_event(IO_CACHE* file,
+ pthread_mutex_t* log_lock,
+ bool old_format);
#else // avoid having to link mysqlbinlog against libpthread
- static Log_event* read_log_event(IO_CACHE* file);
+ static Log_event* read_log_event(IO_CACHE* file, bool old_format);
#endif
- static Log_event* read_log_event(const char* buf, int event_len);
+ static Log_event* read_log_event(const char* buf, int event_len,
+ const char **error, bool old_format);
+ const char* get_type_str();
#ifndef MYSQL_CLIENT
static int read_log_event(IO_CACHE* file, String* packet,
pthread_mutex_t* log_lock);
+ void set_log_pos(MYSQL_LOG* log);
+ virtual void pack_info(String* packet);
+ int net_send(THD* thd, const char* log_name, my_off_t pos);
+ static void init_show_field_list(List<Item>* field_list);
+ virtual int exec_event(struct st_relay_log_info* rli);
+ virtual const char* get_db()
+ {
+ return thd ? thd->db : 0;
+ }
#endif
};
@@ -135,28 +312,17 @@ public:
uint16 error_code;
ulong thread_id;
#if !defined(MYSQL_CLIENT)
- THD* thd;
bool cache_stmt;
- Query_log_event(THD* thd_arg, const char* query_arg, bool using_trans=0):
- Log_event(thd_arg->start_time,0,1,thd_arg->server_id), data_buf(0),
- query(query_arg), db(thd_arg->db), q_len(thd_arg->query_length),
- error_code(thd_arg->killed ? ER_SERVER_SHUTDOWN: thd_arg->net.last_errno),
- thread_id(thd_arg->thread_id), thd(thd_arg),
- cache_stmt(using_trans &&
- (thd_arg->options & (OPTION_NOT_AUTO_COMMIT | OPTION_BEGIN)))
- {
- time_t end_time;
- time(&end_time);
- exec_time = (ulong) (end_time - thd->start_time);
- db_len = (db) ? (uint32) strlen(db) : 0;
- // do not log stray system errors such as EE_WRITE
- if (error_code < ERRMOD)
- error_code = 0;
- }
+
+ Query_log_event(THD* thd_arg, const char* query_arg,
+ bool using_trans=0);
+ const char* get_db() { return db; }
+ void pack_info(String* packet);
+ int exec_event(struct st_relay_log_info* rli);
+ bool get_cache_stmt() { return cache_stmt; }
#endif
- Query_log_event(IO_CACHE* file, time_t when, uint32 server_id_arg);
- Query_log_event(const char* buf, int event_len);
+ Query_log_event(const char* buf, int event_len, bool old_format);
~Query_log_event()
{
if (data_buf)
@@ -167,46 +333,55 @@ public:
Log_event_type get_type_code() { return QUERY_EVENT; }
int write(IO_CACHE* file);
int write_data(IO_CACHE* file); // returns 0 on success, -1 on error
+ bool is_valid() { return query != 0; }
int get_data_size()
{
return q_len + db_len + 2 +
- sizeof(uint32) // thread_id
- + sizeof(uint32) // exec_time
- + sizeof(uint16) // error_code
+ 4 // thread_id
+ + 4 // exec_time
+ + 2 // error_code
;
}
-
+#ifdef MYSQL_CLIENT
void print(FILE* file, bool short_form = 0, char* last_db = 0);
+#endif
};
-#define DUMPFILE_FLAG 0x1
-#define OPT_ENCLOSED_FLAG 0x2
-#define REPLACE_FLAG 0x4
-#define IGNORE_FLAG 0x8
-
-#define FIELD_TERM_EMPTY 0x1
-#define ENCLOSED_EMPTY 0x2
-#define LINE_TERM_EMPTY 0x4
-#define LINE_START_EMPTY 0x8
-#define ESCAPED_EMPTY 0x10
+class Slave_log_event: public Log_event
+{
+protected:
+ char* mem_pool;
+ void init_from_mem_pool(int data_size);
+public:
+ my_off_t master_pos;
+ char* master_host;
+ char* master_log;
+ int master_host_len;
+ int master_log_len;
+ uint16 master_port;
+#ifndef MYSQL_CLIENT
+ Slave_log_event(THD* thd_arg, struct st_relay_log_info* rli);
+ void pack_info(String* packet);
+ int exec_event(struct st_relay_log_info* rli);
+#endif
+
+ Slave_log_event(const char* buf, int event_len);
+ ~Slave_log_event();
+ int get_data_size();
+ bool is_valid() { return master_host != 0; }
+ Log_event_type get_type_code() { return SLAVE_EVENT; }
+#ifdef MYSQL_CLIENT
+ void print(FILE* file, bool short_form = 0, char* last_db = 0);
+#endif
+ int write_data(IO_CACHE* file );
-struct sql_ex_info
- {
- char field_term;
- char enclosed;
- char line_term;
- char line_start;
- char escaped;
- char opt_flags; // flags for the options
- char empty_flags; // flags to indicate which of the terminating charact
- } ;
+};
class Load_log_event: public Log_event
{
protected:
- char* data_buf;
- void copy_log_event(const char *buf, ulong data_len);
+ int copy_log_event(const char *buf, ulong event_len, bool old_format);
public:
ulong thread_id;
@@ -217,7 +392,6 @@ public:
const char* fields;
const uchar* field_lens;
uint32 field_block_len;
-
const char* table_name;
const char* db;
@@ -226,88 +400,31 @@ public:
sql_ex_info sql_ex;
#if !defined(MYSQL_CLIENT)
- THD* thd;
String field_lens_buf;
String fields_buf;
- Load_log_event(THD* thd, sql_exchange* ex, const char* table_name_arg,
- List<Item>& fields_arg, enum enum_duplicates handle_dup ):
- Log_event(thd->start_time),data_buf(0),thread_id(thd->thread_id),
- num_fields(0),fields(0),field_lens(0),field_block_len(0),
- table_name(table_name_arg),
- db(thd->db),
- fname(ex->file_name),
- thd(thd)
- {
- time_t end_time;
- time(&end_time);
- exec_time = (ulong) (end_time - thd->start_time);
- valid_exec_time = 1;
- db_len = (db) ? (uint32) strlen(db) : 0;
- table_name_len = (table_name) ? (uint32) strlen(table_name) : 0;
- fname_len = (fname) ? (uint) strlen(fname) : 0;
- sql_ex.field_term = (*ex->field_term)[0];
- sql_ex.enclosed = (*ex->enclosed)[0];
- sql_ex.line_term = (*ex->line_term)[0];
- sql_ex.line_start = (*ex->line_start)[0];
- sql_ex.escaped = (*ex->escaped)[0];
- sql_ex.opt_flags = 0;
- if(ex->dumpfile)
- sql_ex.opt_flags |= DUMPFILE_FLAG;
- if(ex->opt_enclosed)
- sql_ex.opt_flags |= OPT_ENCLOSED_FLAG;
-
- sql_ex.empty_flags = 0;
-
- switch(handle_dup)
- {
- case DUP_IGNORE: sql_ex.opt_flags |= IGNORE_FLAG; break;
- case DUP_REPLACE: sql_ex.opt_flags |= REPLACE_FLAG; break;
- case DUP_ERROR: break;
- }
-
- if(!ex->field_term->length())
- sql_ex.empty_flags |= FIELD_TERM_EMPTY;
- if(!ex->enclosed->length())
- sql_ex.empty_flags |= ENCLOSED_EMPTY;
- if(!ex->line_term->length())
- sql_ex.empty_flags |= LINE_TERM_EMPTY;
- if(!ex->line_start->length())
- sql_ex.empty_flags |= LINE_START_EMPTY;
- if(!ex->escaped->length())
- sql_ex.empty_flags |= ESCAPED_EMPTY;
-
- skip_lines = ex->skip_lines;
-
- List_iterator<Item> li(fields_arg);
- field_lens_buf.length(0);
- fields_buf.length(0);
- Item* item;
- while((item = li++))
- {
- num_fields++;
- uchar len = (uchar) strlen(item->name);
- field_block_len += len + 1;
- fields_buf.append(item->name, len + 1);
- field_lens_buf.append((char*)&len, 1);
- }
-
- field_lens = (const uchar*)field_lens_buf.ptr();
- fields = fields_buf.ptr();
- }
+
+ Load_log_event(THD* thd, sql_exchange* ex, const char* db_arg,
+ const char* table_name_arg,
+ List<Item>& fields_arg, enum enum_duplicates handle_dup);
void set_fields(List<Item> &fields_arg);
+ void pack_info(String* packet);
+ const char* get_db() { return db; }
+ int exec_event(struct st_relay_log_info* rli)
+ {
+ return exec_event(thd->slave_net,rli);
+ }
+ int exec_event(NET* net, struct st_relay_log_info* rli);
#endif
- Load_log_event(IO_CACHE * file, time_t when, uint32 server_id_arg);
- Load_log_event(const char* buf, int event_len);
+ Load_log_event(const char* buf, int event_len, bool old_format);
~Load_log_event()
{
- if (data_buf)
- {
- my_free((gptr) data_buf, MYF(0));
- }
}
- Log_event_type get_type_code() { return LOAD_EVENT; }
- int write_data(IO_CACHE* file); // returns 0 on success, -1 on error
+ Log_event_type get_type_code() { return sql_ex.new_format() ?
+ NEW_LOAD_EVENT: LOAD_EVENT; }
+ int write_data_header(IO_CACHE* file);
+ int write_data_body(IO_CACHE* file);
+ bool is_valid() { return table_name != 0; }
int get_data_size()
{
return table_name_len + 2 + db_len + 2 + fname_len
@@ -315,11 +432,13 @@ public:
+ 4 // exec_time
+ 4 // skip_lines
+ 4 // field block len
- + sizeof(sql_ex) + field_block_len + num_fields*sizeof(uchar) ;
+ + sql_ex.data_size() + field_block_len + num_fields;
;
}
-
+ int get_data_body_offset() { return LOAD_EVENT_OVERHEAD; }
+#ifdef MYSQL_CLIENT
void print(FILE* file, bool short_form = 0, char* last_db = 0);
+#endif
};
extern char server_version[SERVER_VERSION_LENGTH];
@@ -329,35 +448,30 @@ class Start_log_event: public Log_event
public:
uint32 created;
uint16 binlog_version;
- char server_version[50];
-
- Start_log_event() :Log_event(time(NULL)),binlog_version(BINLOG_VERSION)
+ char server_version[ST_SERVER_VER_LEN];
+#ifndef MYSQL_CLIENT
+ Start_log_event() :Log_event((THD*)0),binlog_version(BINLOG_VERSION)
{
created = (uint32) when;
- memcpy(server_version, ::server_version, sizeof(server_version));
- }
- Start_log_event(IO_CACHE* file, time_t when_arg, uint32 server_id_arg) :
- Log_event(when_arg, 0, 0, server_id_arg)
- {
- char buf[sizeof(server_version) + 2 + 4 + 4];
- if (my_b_read(file, (byte*) buf, sizeof(buf)))
- return;
- binlog_version = uint2korr(buf+4);
- memcpy(server_version, buf + 6, sizeof(server_version));
- server_version[sizeof(server_version)-1]=0;
- created = uint4korr(buf + 6 + sizeof(server_version));
+ memcpy(server_version, ::server_version, ST_SERVER_VER_LEN);
}
- Start_log_event(const char* buf);
-
+#endif
+ Start_log_event(const char* buf, bool old_format);
~Start_log_event() {}
Log_event_type get_type_code() { return START_EVENT;}
int write_data(IO_CACHE* file);
+ bool is_valid() { return 1; }
int get_data_size()
{
- // sizeof(binlog_version) + sizeof(server_version) sizeof(created)
- return 2 + sizeof(server_version) + 4;
+ return START_HEADER_LEN;
}
+#ifndef MYSQL_CLIENT
+ void pack_info(String* packet);
+ int exec_event(struct st_relay_log_info* rli);
+#endif
+#ifdef MYSQL_CLIENT
void print(FILE* file, bool short_form = 0, char* last_db = 0);
+#endif
};
class Intvar_log_event: public Log_event
@@ -365,37 +479,48 @@ class Intvar_log_event: public Log_event
public:
ulonglong val;
uchar type;
- Intvar_log_event(uchar type_arg, ulonglong val_arg)
- :Log_event(time(NULL)),val(val_arg),type(type_arg)
+#ifndef MYSQL_CLIENT
+ Intvar_log_event(THD* thd_arg,uchar type_arg, ulonglong val_arg)
+ :Log_event(thd_arg),val(val_arg),type(type_arg)
{}
- Intvar_log_event(IO_CACHE* file, time_t when, uint32 server_id_arg);
- Intvar_log_event(const char* buf);
+#endif
+ Intvar_log_event(const char* buf, bool old_format);
~Intvar_log_event() {}
Log_event_type get_type_code() { return INTVAR_EVENT;}
+ const char* get_var_type_name();
int get_data_size() { return sizeof(type) + sizeof(val);}
int write_data(IO_CACHE* file);
+ bool is_valid() { return 1; }
+#ifndef MYSQL_CLIENT
+ void pack_info(String* packet);
+ int exec_event(struct st_relay_log_info* rli);
+#endif
-
+#ifdef MYSQL_CLIENT
void print(FILE* file, bool short_form = 0, char* last_db = 0);
+#endif
};
class Stop_log_event: public Log_event
{
public:
- Stop_log_event() :Log_event(time(NULL))
+#ifndef MYSQL_CLIENT
+ Stop_log_event() :Log_event((THD*)0)
{}
- Stop_log_event(IO_CACHE* file, time_t when_arg, uint32 server_id_arg):
- Log_event(when_arg,0,0,server_id_arg)
- {
- byte skip[4];
- my_b_read(file, skip, sizeof(skip)); // skip the event length
- }
- Stop_log_event(const char* buf):Log_event(buf)
+#endif
+ Stop_log_event(const char* buf, bool old_format):Log_event(buf,
+ old_format)
{
}
~Stop_log_event() {}
Log_event_type get_type_code() { return STOP_EVENT;}
+ bool is_valid() { return 1; }
+#ifdef MYSQL_CLIENT
void print(FILE* file, bool short_form = 0, char* last_db = 0);
+#endif
+#ifndef MYSQL_CLIENT
+ int exec_event(struct st_relay_log_info* rli);
+#endif
};
class Rotate_log_event: public Log_event
@@ -403,27 +528,172 @@ class Rotate_log_event: public Log_event
public:
const char* new_log_ident;
uchar ident_len;
+ ulonglong pos;
bool alloced;
-
- Rotate_log_event(const char* new_log_ident_arg, uint ident_len_arg = 0) :
- Log_event(time(NULL)),
+#ifndef MYSQL_CLIENT
+ Rotate_log_event(THD* thd_arg, const char* new_log_ident_arg,
+ uint ident_len_arg = 0,ulonglong pos_arg = 4) :
+ Log_event(thd_arg),
new_log_ident(new_log_ident_arg),
- ident_len(ident_len_arg ? ident_len_arg : (uint) strlen(new_log_ident_arg)),
+ ident_len(ident_len_arg ? ident_len_arg :
+ (uint) strlen(new_log_ident_arg)), pos(pos_arg),
alloced(0)
{}
-
- Rotate_log_event(IO_CACHE* file, time_t when, uint32 server_id_arg) ;
- Rotate_log_event(const char* buf, int event_len);
+#endif
+ Rotate_log_event(const char* buf, int event_len, bool old_format);
~Rotate_log_event()
{
if (alloced)
my_free((gptr) new_log_ident, MYF(0));
}
Log_event_type get_type_code() { return ROTATE_EVENT;}
- int get_data_size() { return ident_len;}
+ int get_data_size() { return ident_len + ROTATE_HEADER_LEN;}
+ bool is_valid() { return new_log_ident != 0; }
+ int write_data(IO_CACHE* file);
+#ifdef MYSQL_CLIENT
+ void print(FILE* file, bool short_form = 0, char* last_db = 0);
+#endif
+#ifndef MYSQL_CLIENT
+ void pack_info(String* packet);
+ int exec_event(struct st_relay_log_info* rli);
+#endif
+};
+
+/* the classes below are for the new LOAD DATA INFILE logging */
+
+class Create_file_log_event: public Load_log_event
+{
+protected:
+ // pretend we are Load event, so we can write out just
+ // our Load part - used on the slave when writing event out to
+ // SQL_LOAD-*.info file
+ bool fake_base;
+public:
+ char* block;
+ uint block_len;
+ uint file_id;
+ bool inited_from_old;
+#ifndef MYSQL_CLIENT
+ Create_file_log_event(THD* thd, sql_exchange* ex, const char* db_arg,
+ const char* table_name_arg,
+ List<Item>& fields_arg,
+ enum enum_duplicates handle_dup,
+ char* block_arg, uint block_len_arg);
+#endif
+
+ Create_file_log_event(const char* buf, int event_len, bool old_format);
+ ~Create_file_log_event()
+ {
+ }
+ Log_event_type get_type_code()
+ {
+ return fake_base ? Load_log_event::get_type_code() : CREATE_FILE_EVENT;
+ }
+ int get_data_size() { return fake_base ? Load_log_event::get_data_size() :
+ Load_log_event::get_data_size() +
+ 4 + 1 + block_len;}
+ int get_data_body_offset() { return fake_base ? LOAD_EVENT_OVERHEAD:
+ LOAD_EVENT_OVERHEAD + CREATE_FILE_HEADER_LEN; }
+ bool is_valid() { return inited_from_old || block != 0; }
+ int write_data_header(IO_CACHE* file);
+ int write_data_body(IO_CACHE* file);
+ int write_base(IO_CACHE* file); // cut out Create_file extentions and
+ // write it as Load event - used on the slave
+
+#ifdef MYSQL_CLIENT
+ void print(FILE* file, bool short_form = 0, char* last_db = 0);
+#endif
+#ifndef MYSQL_CLIENT
+ void pack_info(String* packet);
+ int exec_event(struct st_relay_log_info* rli);
+#endif
+};
+
+class Append_block_log_event: public Log_event
+{
+public:
+ char* block;
+ uint block_len;
+ uint file_id;
+
+#ifndef MYSQL_CLIENT
+ Append_block_log_event(THD* thd, char* block_arg,
+ uint block_len_arg);
+ int exec_event(struct st_relay_log_info* rli);
+#endif
+
+ Append_block_log_event(const char* buf, int event_len);
+ ~Append_block_log_event()
+ {
+ }
+ Log_event_type get_type_code() { return APPEND_BLOCK_EVENT;}
+ int get_data_size() { return block_len + APPEND_BLOCK_HEADER_LEN ;}
+ bool is_valid() { return block != 0; }
int write_data(IO_CACHE* file);
+
+#ifdef MYSQL_CLIENT
+ void print(FILE* file, bool short_form = 0, char* last_db = 0);
+#endif
+#ifndef MYSQL_CLIENT
+ void pack_info(String* packet);
+#endif
+};
+
+class Delete_file_log_event: public Log_event
+{
+public:
+ uint file_id;
+#ifndef MYSQL_CLIENT
+ Delete_file_log_event(THD* thd);
+#endif
+
+ Delete_file_log_event(const char* buf, int event_len);
+ ~Delete_file_log_event()
+ {
+ }
+ Log_event_type get_type_code() { return DELETE_FILE_EVENT;}
+ int get_data_size() { return DELETE_FILE_HEADER_LEN ;}
+ bool is_valid() { return file_id != 0; }
+ int write_data(IO_CACHE* file);
+
+#ifdef MYSQL_CLIENT
+ void print(FILE* file, bool short_form = 0, char* last_db = 0);
+#endif
+#ifndef MYSQL_CLIENT
+ void pack_info(String* packet);
+ int exec_event(struct st_relay_log_info* rli);
+#endif
+};
+
+class Execute_load_log_event: public Log_event
+{
+public:
+ uint file_id;
+
+#ifndef MYSQL_CLIENT
+ Execute_load_log_event(THD* thd);
+#endif
+
+ Execute_load_log_event(const char* buf, int event_len);
+ ~Execute_load_log_event()
+ {
+ }
+ Log_event_type get_type_code() { return EXEC_LOAD_EVENT;}
+ int get_data_size() { return EXEC_LOAD_HEADER_LEN ;}
+ bool is_valid() { return file_id != 0; }
+ int write_data(IO_CACHE* file);
+
+#ifdef MYSQL_CLIENT
void print(FILE* file, bool short_form = 0, char* last_db = 0);
+#endif
+#ifndef MYSQL_CLIENT
+ void pack_info(String* packet);
+ int exec_event(struct st_relay_log_info* rli);
+#endif
};
#endif
+
+
+
diff --git a/sql/matherr.c b/sql/matherr.c
index 8523a78ce94..ea0c15d2feb 100644
--- a/sql/matherr.c
+++ b/sql/matherr.c
@@ -1,22 +1,22 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/* Fix that we got POSTFIX_ERROR when doing unreasonable math (not core) */
-#include <global.h>
+#include <my_global.h>
#include <errno.h>
/* Fix that we gets POSTFIX_ERROR when error in math */
diff --git a/sql/mf_iocache.cc b/sql/mf_iocache.cc
index cddacaa820f..1bc65eebd23 100644
--- a/sql/mf_iocache.cc
+++ b/sql/mf_iocache.cc
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -42,293 +42,6 @@ static void my_aiowait(my_aio_result *result);
extern "C" {
/*
- ** if cachesize == 0 then use default cachesize (from s-file)
- ** if file == -1 then real_open_cached_file() will be called.
- ** returns 0 if ok
- */
-
-int init_io_cache(IO_CACHE *info, File file, uint cachesize,
- enum cache_type type, my_off_t seek_offset,
- pbool use_async_io, myf cache_myflags)
-{
- uint min_cache;
- DBUG_ENTER("init_io_cache");
- DBUG_PRINT("enter",("type: %d pos: %ld",(int) type, (ulong) seek_offset));
-
- /* There is no file in net_reading */
- info->file= file;
- if (!cachesize)
- if (! (cachesize= my_default_record_cache_size))
- DBUG_RETURN(1); /* No cache requested */
- min_cache=use_async_io ? IO_SIZE*4 : IO_SIZE*2;
- if (type == READ_CACHE)
- { /* Assume file isn't growing */
- if (cache_myflags & MY_DONT_CHECK_FILESIZE)
- {
- cache_myflags &= ~MY_DONT_CHECK_FILESIZE;
- }
- else
- {
- my_off_t file_pos,end_of_file;
- if ((file_pos=my_tell(file,MYF(0)) == MY_FILEPOS_ERROR))
- DBUG_RETURN(1);
- end_of_file=my_seek(file,0L,MY_SEEK_END,MYF(0));
- if (end_of_file < seek_offset)
- end_of_file=seek_offset;
- VOID(my_seek(file,file_pos,MY_SEEK_SET,MYF(0)));
- if ((my_off_t) cachesize > end_of_file-seek_offset+IO_SIZE*2-1)
- {
- cachesize=(uint) (end_of_file-seek_offset)+IO_SIZE*2-1;
- use_async_io=0; /* No nead to use async */
- }
- }
- }
- if ((int) type < (int) READ_NET)
- {
- for (;;)
- {
- cachesize=(uint) ((ulong) (cachesize + min_cache-1) &
- (ulong) ~(min_cache-1));
- if (cachesize < min_cache)
- cachesize = min_cache;
- if ((info->buffer=
- (byte*) my_malloc(cachesize,
- MYF((cache_myflags & ~ MY_WME) |
- (cachesize == min_cache ? MY_WME : 0)))) != 0)
- break; /* Enough memory found */
- if (cachesize == min_cache)
- DBUG_RETURN(2); /* Can't alloc cache */
- cachesize= (uint) ((long) cachesize*3/4); /* Try with less memory */
- }
- }
- else
- info->buffer=0;
- DBUG_PRINT("info",("init_io_cache: cachesize = %u",cachesize));
- info->pos_in_file= seek_offset;
- info->read_length=info->buffer_length=cachesize;
- info->seek_not_done= test(file >= 0 && type != READ_FIFO &&
- type != READ_NET);
- info->myflags=cache_myflags & ~(MY_NABP | MY_FNABP);
- info->rc_request_pos=info->rc_pos=info->buffer;
-
- if (type == READ_CACHE || type == READ_NET || type == READ_FIFO)
- {
- info->rc_end=info->buffer; /* Nothing in cache */
- }
- else /* type == WRITE_CACHE */
- {
- info->rc_end=info->buffer+info->buffer_length- (seek_offset & (IO_SIZE-1));
- }
- /* end_of_file may be changed by user later */
- info->end_of_file= ((type == READ_NET || type == READ_FIFO ) ? 0
- : ~(my_off_t) 0);
- info->type=type;
- info->error=0;
- info->read_function=(type == READ_NET) ? _my_b_net_read : _my_b_read; /* net | file */
-#ifdef HAVE_AIOWAIT
- if (use_async_io && ! my_disable_async_io)
- {
- DBUG_PRINT("info",("Using async io"));
- info->read_length/=2;
- info->read_function=_my_b_async_read;
- }
- info->inited=info->aio_result.pending=0;
-#endif
- DBUG_RETURN(0);
-} /* init_io_cache */
-
-
- /* Wait until current request is ready */
-
-#ifdef HAVE_AIOWAIT
-static void my_aiowait(my_aio_result *result)
-{
- if (result->pending)
- {
- struct aio_result_t *tmp;
- for (;;)
- {
- if ((int) (tmp=aiowait((struct timeval *) 0)) == -1)
- {
- if (errno == EINTR)
- continue;
- DBUG_PRINT("error",("No aio request, error: %d",errno));
- result->pending=0; /* Assume everythings is ok */
- break;
- }
- ((my_aio_result*) tmp)->pending=0;
- if ((my_aio_result*) tmp == result)
- break;
- }
- }
- return;
-}
-#endif
-
- /* Use this to reset cache to start or other type */
- /* Some simple optimizing is done when reinit in current buffer */
-
-my_bool reinit_io_cache(IO_CACHE *info, enum cache_type type,
- my_off_t seek_offset,
- pbool use_async_io __attribute__((unused)),
- pbool clear_cache)
-{
- DBUG_ENTER("reinit_io_cache");
-
- info->seek_not_done= test(info->file >= 0); /* Seek not done */
-
- /* If the whole file is in memory, avoid flushing to disk */
- if (! clear_cache &&
- seek_offset >= info->pos_in_file &&
- seek_offset <= info->pos_in_file +
- (uint) (info->rc_end - info->rc_request_pos))
- { /* use current buffer */
- if (info->type == WRITE_CACHE && type == READ_CACHE)
- {
- info->rc_end=info->rc_pos;
- info->end_of_file=my_b_tell(info);
- }
- else if (type == WRITE_CACHE)
- {
- if (info->type == READ_CACHE)
- info->rc_end=info->buffer+info->buffer_length;
- info->end_of_file = ~(my_off_t) 0;
- }
- info->rc_pos=info->rc_request_pos+(seek_offset-info->pos_in_file);
-#ifdef HAVE_AIOWAIT
- my_aiowait(&info->aio_result); /* Wait for outstanding req */
-#endif
- }
- else
- {
- /*
- If we change from WRITE_CACHE to READ_CACHE, assume that everything
- after the current positions should be ignored
- */
- if (info->type == WRITE_CACHE && type == READ_CACHE)
- info->end_of_file=my_b_tell(info);
- /* No need to flush cache if we want to reuse it */
- if ((type != WRITE_CACHE || !clear_cache) && flush_io_cache(info))
- DBUG_RETURN(1);
- if (info->pos_in_file != seek_offset)
- {
- info->pos_in_file=seek_offset;
- info->seek_not_done=1;
- }
- info->rc_request_pos=info->rc_pos=info->buffer;
- if (type == READ_CACHE || type == READ_NET || type == READ_FIFO)
- {
- info->rc_end=info->buffer; /* Nothing in cache */
- }
- else
- {
- info->rc_end=info->buffer+info->buffer_length-
- (seek_offset & (IO_SIZE-1));
- info->end_of_file= ((type == READ_NET || type == READ_FIFO) ? 0 :
- ~(my_off_t) 0);
- }
- }
- info->type=type;
- info->error=0;
- info->read_function=(type == READ_NET) ? _my_b_net_read : _my_b_read;
-#ifdef HAVE_AIOWAIT
- if (type != READ_NET)
- {
- if (use_async_io && ! my_disable_async_io &&
- ((ulong) info->buffer_length <
- (ulong) (info->end_of_file - seek_offset)))
- {
- info->read_length=info->buffer_length/2;
- info->read_function=_my_b_async_read;
- }
- }
- info->inited=0;
-#endif
- DBUG_RETURN(0);
-} /* init_io_cache */
-
-
-
- /*
- Read buffered. Returns 1 if can't read requested characters
- This function is only called from the my_b_read() macro
- when there isn't enough characters in the buffer to
- satisfy the request.
- Returns 0 we succeeded in reading all data
- */
-
-int _my_b_read(register IO_CACHE *info, byte *Buffer, uint Count)
-{
- uint length,diff_length,left_length;
- my_off_t max_length, pos_in_file;
-
- if ((left_length=(uint) (info->rc_end-info->rc_pos)))
- {
- dbug_assert(Count >= left_length); /* User is not using my_b_read() */
- memcpy(Buffer,info->rc_pos, (size_t) (left_length));
- Buffer+=left_length;
- Count-=left_length;
- }
- /* pos_in_file always point on where info->buffer was read */
- pos_in_file=info->pos_in_file+(uint) (info->rc_end - info->buffer);
- if (info->seek_not_done)
- { /* File touched, do seek */
- VOID(my_seek(info->file,pos_in_file,MY_SEEK_SET,MYF(0)));
- info->seek_not_done=0;
- }
- diff_length=(uint) (pos_in_file & (IO_SIZE-1));
- if (Count >= (uint) (IO_SIZE+(IO_SIZE-diff_length)))
- { /* Fill first intern buffer */
- uint read_length;
- if (info->end_of_file == pos_in_file)
- { /* End of file */
- info->error=(int) left_length;
- return 1;
- }
- length=(Count & (uint) ~(IO_SIZE-1))-diff_length;
- if ((read_length=my_read(info->file,Buffer,(uint) length,info->myflags))
- != (uint) length)
- {
- info->error= read_length == (uint) -1 ? -1 :
- (int) (read_length+left_length);
- return 1;
- }
- Count-=length;
- Buffer+=length;
- pos_in_file+=length;
- left_length+=length;
- diff_length=0;
- }
- max_length=info->read_length-diff_length;
- if (info->type != READ_FIFO &&
- (info->end_of_file - pos_in_file) < max_length)
- max_length = info->end_of_file - pos_in_file;
- if (!max_length)
- {
- if (Count)
- {
- info->error= left_length; /* We only got this many char */
- return 1;
- }
- length=0; /* Didn't read any chars */
- }
- else if ((length=my_read(info->file,info->buffer,(uint) max_length,
- info->myflags)) < Count ||
- length == (uint) -1)
- {
- if (length != (uint) -1)
- memcpy(Buffer,info->buffer,(size_t) length);
- info->error= length == (uint) -1 ? -1 : (int) (length+left_length);
- return 1;
- }
- info->rc_pos=info->buffer+Count;
- info->rc_end=info->buffer+length;
- info->pos_in_file=pos_in_file;
- memcpy(Buffer,info->buffer,(size_t) Count);
- return 0;
-}
-
- /*
** Read buffered from the net.
** Returns 1 if can't read requested characters
** Returns 0 if record read
@@ -337,353 +50,34 @@ int _my_b_read(register IO_CACHE *info, byte *Buffer, uint Count)
int _my_b_net_read(register IO_CACHE *info, byte *Buffer,
uint Count __attribute__((unused)))
{
- int read_length;
+ ulong read_length;
NET *net= &(current_thd)->net;
+ DBUG_ENTER("_my_b_net_read");
- if (info->end_of_file)
- return 1; /* because my_b_get (no _) takes 1 byte at a time */
+ if (!info->end_of_file)
+ DBUG_RETURN(1); /* because my_b_get (no _) takes 1 byte at a time */
read_length=my_net_read(net);
- if (read_length == (int) packet_error)
+ if (read_length == packet_error)
{
info->error= -1;
- return 1;
+ DBUG_RETURN(1);
}
if (read_length == 0)
{
- /* End of file from client */
- info->end_of_file = 1; return 1;
+ info->end_of_file= 0; /* End of file from client */
+ DBUG_RETURN(1);
}
/* to set up stuff for my_b_get (no _) */
- info->rc_end = (info->rc_pos = (byte*) net->read_pos) + read_length;
- Buffer[0] = info->rc_pos[0]; /* length is always 1 */
- info->rc_pos++;
- return 0;
-}
-
-#ifdef HAVE_AIOWAIT
-
-int _my_b_async_read(register IO_CACHE *info, byte *Buffer, uint Count)
-{
- uint length,read_length,diff_length,left_length,use_length,org_Count;
- my_off_t max_length;
- my_off_t next_pos_in_file;
- byte *read_buffer;
-
- memcpy(Buffer,info->rc_pos,
- (size_t) (left_length=(uint) (info->rc_end-info->rc_pos)));
- Buffer+=left_length;
- org_Count=Count;
- Count-=left_length;
-
- if (info->inited)
- { /* wait for read block */
- info->inited=0; /* No more block to read */
- my_aiowait(&info->aio_result); /* Wait for outstanding req */
- if (info->aio_result.result.aio_errno)
- {
- if (info->myflags & MY_WME)
- my_error(EE_READ, MYF(ME_BELL+ME_WAITTANG),
- my_filename(info->file),
- info->aio_result.result.aio_errno);
- my_errno=info->aio_result.result.aio_errno;
- info->error= -1;
- return(1);
- }
- if (! (read_length = (uint) info->aio_result.result.aio_return) ||
- read_length == (uint) -1)
- {
- my_errno=0; /* For testing */
- info->error= (read_length == (uint) -1 ? -1 :
- (int) (read_length+left_length));
- return(1);
- }
- info->pos_in_file+=(uint) (info->rc_end - info->rc_request_pos);
-
- if (info->rc_request_pos != info->buffer)
- info->rc_request_pos=info->buffer;
- else
- info->rc_request_pos=info->buffer+info->read_length;
- info->rc_pos=info->rc_request_pos;
- next_pos_in_file=info->aio_read_pos+read_length;
-
- /* Check if pos_in_file is changed
- (_ni_read_cache may have skipped some bytes) */
-
- if (info->aio_read_pos < info->pos_in_file)
- { /* Fix if skipped bytes */
- if (info->aio_read_pos + read_length < info->pos_in_file)
- {
- read_length=0; /* Skipp block */
- next_pos_in_file=info->pos_in_file;
- }
- else
- {
- my_off_t offset= (info->pos_in_file - info->aio_read_pos);
- info->pos_in_file=info->aio_read_pos; /* Whe are here */
- info->rc_pos=info->rc_request_pos+offset;
- read_length-=offset; /* Bytes left from rc_pos */
- }
- }
-#ifndef DBUG_OFF
- if (info->aio_read_pos > info->pos_in_file)
- {
- my_errno=EINVAL;
- return(info->read_length= -1);
- }
-#endif
- /* Copy found bytes to buffer */
- length=min(Count,read_length);
- memcpy(Buffer,info->rc_pos,(size_t) length);
- Buffer+=length;
- Count-=length;
- left_length+=length;
- info->rc_end=info->rc_pos+read_length;
- info->rc_pos+=length;
- }
- else
- next_pos_in_file=(info->pos_in_file+ (uint)
- (info->rc_end - info->rc_request_pos));
-
- /* If reading large blocks, or first read or read with skipp */
- if (Count)
- {
- if (next_pos_in_file == info->end_of_file)
- {
- info->error=(int) (read_length+left_length);
- return 1;
- }
- VOID(my_seek(info->file,next_pos_in_file,MY_SEEK_SET,MYF(0)));
- read_length=IO_SIZE*2- (uint) (next_pos_in_file & (IO_SIZE-1));
- if (Count < read_length)
- { /* Small block, read to cache */
- if ((read_length=my_read(info->file,info->rc_request_pos,
- read_length, info->myflags)) == (uint) -1)
- return info->error= -1;
- use_length=min(Count,read_length);
- memcpy(Buffer,info->rc_request_pos,(size_t) use_length);
- info->rc_pos=info->rc_request_pos+Count;
- info->rc_end=info->rc_request_pos+read_length;
- info->pos_in_file=next_pos_in_file; /* Start of block in cache */
- next_pos_in_file+=read_length;
-
- if (Count != use_length)
- { /* Didn't find hole block */
- if (info->myflags & (MY_WME | MY_FAE | MY_FNABP) && Count != org_Count)
- my_error(EE_EOFERR, MYF(ME_BELL+ME_WAITTANG),
- my_filename(info->file),my_errno);
- info->error=(int) (read_length+left_length);
- return 1;
- }
- }
- else
- { /* Big block, don't cache it */
- if ((read_length=my_read(info->file,Buffer,(uint) Count,info->myflags))
- != Count)
- {
- info->error= read_length == (uint) -1 ? -1 : read_length+left_length;
- return 1;
- }
- info->rc_pos=info->rc_end=info->rc_request_pos;
- info->pos_in_file=(next_pos_in_file+=Count);
- }
- }
-
- /* Read next block with asyncronic io */
- max_length=info->end_of_file - next_pos_in_file;
- diff_length=(next_pos_in_file & (IO_SIZE-1));
-
- if (max_length > (my_off_t) info->read_length - diff_length)
- max_length= (my_off_t) info->read_length - diff_length;
- if (info->rc_request_pos != info->buffer)
- read_buffer=info->buffer;
- else
- read_buffer=info->buffer+info->read_length;
- info->aio_read_pos=next_pos_in_file;
- if (max_length)
- {
- info->aio_result.result.aio_errno=AIO_INPROGRESS; /* Marker for test */
- DBUG_PRINT("aioread",("filepos: %ld length: %ld",
- (ulong) next_pos_in_file,(ulong) max_length));
- if (aioread(info->file,read_buffer,(int) max_length,
- (my_off_t) next_pos_in_file,MY_SEEK_SET,
- &info->aio_result.result))
- { /* Skipp async io */
- my_errno=errno;
- DBUG_PRINT("error",("got error: %d, aio_result: %d from aioread, async skipped",
- errno, info->aio_result.result.aio_errno));
- if (info->rc_request_pos != info->buffer)
- {
- bmove(info->buffer,info->rc_request_pos,
- (uint) (info->rc_end - info->rc_pos));
- info->rc_request_pos=info->buffer;
- info->rc_pos-=info->read_length;
- info->rc_end-=info->read_length;
- }
- info->read_length=info->buffer_length; /* Use hole buffer */
- info->read_function=_my_b_read; /* Use normal IO_READ next */
- }
- else
- info->inited=info->aio_result.pending=1;
- }
- return 0; /* Block read, async in use */
-} /* _my_b_async_read */
-#endif
-
-
-/* Read one byte when buffer is empty */
-
-int _my_b_get(IO_CACHE *info)
-{
- byte buff;
- if ((*(info)->read_function)(info,&buff,1))
- return my_b_EOF;
- return (int) (uchar) buff;
-}
-
- /* Returns != 0 if error on write */
-
-int _my_b_write(register IO_CACHE *info, const byte *Buffer, uint Count)
-{
- uint rest_length,length;
-
- rest_length=(uint) (info->rc_end - info->rc_pos);
- memcpy(info->rc_pos,Buffer,(size_t) rest_length);
- Buffer+=rest_length;
- Count-=rest_length;
- info->rc_pos+=rest_length;
- if (info->pos_in_file+info->buffer_length > info->end_of_file)
- {
- my_errno=errno=EFBIG;
- return info->error = -1;
- }
- if (flush_io_cache(info))
- return 1;
- if (Count >= IO_SIZE)
- { /* Fill first intern buffer */
- length=Count & (uint) ~(IO_SIZE-1);
- if (info->seek_not_done)
- { /* File touched, do seek */
- VOID(my_seek(info->file,info->pos_in_file,MY_SEEK_SET,MYF(0)));
- info->seek_not_done=0;
- }
- if (my_write(info->file,Buffer,(uint) length,info->myflags | MY_NABP))
- return info->error= -1;
- Count-=length;
- Buffer+=length;
- info->pos_in_file+=length;
- }
- memcpy(info->rc_pos,Buffer,(size_t) Count);
- info->rc_pos+=Count;
- return 0;
-}
-
-
-/*
- Write a block to disk where part of the data may be inside the record
- buffer. As all write calls to the data goes through the cache,
- we will never get a seek over the end of the buffer
-*/
-
-int my_block_write(register IO_CACHE *info, const byte *Buffer, uint Count,
- my_off_t pos)
-{
- uint length;
- int error=0;
-
- if (pos < info->pos_in_file)
- {
- /* Of no overlap, write everything without buffering */
- if (pos + Count <= info->pos_in_file)
- return my_pwrite(info->file, Buffer, Count, pos,
- info->myflags | MY_NABP);
- /* Write the part of the block that is before buffer */
- length= (uint) (info->pos_in_file - pos);
- if (my_pwrite(info->file, Buffer, length, pos, info->myflags | MY_NABP))
- info->error=error=-1;
- Buffer+=length;
- pos+= length;
- Count-= length;
- }
-
- /* Check if we want to write inside the used part of the buffer.*/
- length= (uint) (info->rc_end - info->buffer);
- if (pos < info->pos_in_file + length)
- {
- uint offset= (uint) (pos - info->pos_in_file);
- length-=offset;
- if (length > Count)
- length=Count;
- memcpy(info->buffer+offset, Buffer, length);
- Buffer+=length;
- Count-= length;
- /* Fix length of buffer if the new data was larger */
- if (info->buffer+length > info->rc_pos)
- info->rc_pos=info->buffer+length;
- if (!Count)
- return (error);
- }
- /* Write at the end of the current buffer; This is the normal case */
- if (_my_b_write(info, Buffer, Count))
- error= -1;
- return error;
-}
-
- /* Flush write cache */
-
-int flush_io_cache(IO_CACHE *info)
-{
- uint length;
- DBUG_ENTER("flush_io_cache");
-
- if (info->type == WRITE_CACHE)
- {
- if (info->file == -1)
- {
- if (real_open_cached_file(info))
- DBUG_RETURN((info->error= -1));
- }
- if (info->rc_pos != info->buffer)
- {
- length=(uint) (info->rc_pos - info->buffer);
- if (info->seek_not_done)
- { /* File touched, do seek */
- if (my_seek(info->file,info->pos_in_file,MY_SEEK_SET,MYF(0)) ==
- MY_FILEPOS_ERROR)
- DBUG_RETURN((info->error= -1));
- info->seek_not_done=0;
- }
- info->rc_pos=info->buffer;
- info->pos_in_file+=length;
- info->rc_end=(info->buffer+info->buffer_length-
- (info->pos_in_file & (IO_SIZE-1)));
- if (my_write(info->file,info->buffer,length,info->myflags | MY_NABP))
- DBUG_RETURN((info->error= -1));
- DBUG_RETURN(0);
- }
- }
-#ifdef HAVE_AIOWAIT
- else if (info->type != READ_NET)
- {
- my_aiowait(&info->aio_result); /* Wait for outstanding req */
- info->inited=0;
- }
-#endif
+ info->read_end = (info->read_pos = (byte*) net->read_pos) + read_length;
+ Buffer[0] = info->read_pos[0]; /* length is always 1 */
+ info->read_pos++;
+
+ /*
+ info->request_pos is used by log_loaded_block() to know the size
+ of the current block
+ */
+ info->request_pos=info->read_pos;
DBUG_RETURN(0);
}
-
-int end_io_cache(IO_CACHE *info)
-{
- int error=0;
- DBUG_ENTER("end_io_cache");
- if (info->buffer)
- {
- if (info->file != -1) /* File doesn't exist */
- error=flush_io_cache(info);
- my_free((gptr) info->buffer,MYF(MY_WME));
- info->buffer=info->rc_pos=(byte*) 0;
- }
- DBUG_RETURN(error);
-} /* end_io_cache */
-
} /* extern "C" */
diff --git a/sql/mini_client.cc b/sql/mini_client.cc
index 3dfd58375a5..c31fa573fea 100644
--- a/sql/mini_client.cc
+++ b/sql/mini_client.cc
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -22,25 +22,21 @@
in case we decide to make them external at some point
*/
-#define DONT_USE_RAID
+#ifdef EMBEDDED_LIBRARY
+#define net_read_timeout net_read_timeout1
+#define net_write_timeout net_write_timeout1
+#endif
+
#if defined(__WIN__)
#include <winsock.h>
-#include <odbcinst.h>
-/* Disable alarms */
-typedef my_bool ALARM;
-#define thr_alarm_init(A) (*(A))=0
-#define thr_alarm_in_use(A) (*(A))
-#define thr_end_alarm(A)
-#define thr_alarm(A,B,C) local_thr_alarm((A),(B),(C))
-inline int local_thr_alarm(my_bool *A,int B __attribute__((unused)),ALARM *C __attribute__((unused)))
-{
- *A=1;
- return 0;
-}
-#define thr_got_alarm(A) 0
+#include <odbcinst.h> /* QQ: Is this really needed ? */
+#define DONT_USE_THR_ALARM
#endif
-#include <global.h>
+#include <my_global.h>
+#include <mysql_embed.h>
+#include <mysql_com.h>
+#include <violite.h>
#include <my_sys.h>
#include <mysys_err.h>
#include <m_string.h>
@@ -50,9 +46,8 @@ inline int local_thr_alarm(my_bool *A,int B __attribute__((unused)),ALARM *C __a
#include "mysql_version.h"
#include "mysqld_error.h"
#include "errmsg.h"
-#include <violite.h>
-#if defined( OS2) && defined( MYSQL_SERVER)
+#if defined( OS2) && defined(MYSQL_SERVER)
#undef ER
#define ER CER
#endif
@@ -76,23 +71,35 @@ extern "C" { // Because of SCO 3.2V4.2
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif
-#endif
+#endif /*!defined(MSDOS) && !defined(__WIN__) */
#ifdef HAVE_SYS_UN_H
# include <sys/un.h>
#endif
#if defined(THREAD)
#include <my_pthread.h> /* because of signal() */
-#include <thr_alarm.h>
#endif
+#include <thr_alarm.h>
#ifndef INADDR_NONE
#define INADDR_NONE -1
#endif
-
}
-static void mc_end_server(MYSQL *mysql);
+static void mc_free_rows(MYSQL_DATA *cur);
+static MYSQL_FIELD *unpack_fields(MYSQL_DATA *data,MEM_ROOT *alloc,uint fields,
+ my_bool default_value,
+ my_bool long_flag_protocol);
+
+void mc_end_server(MYSQL *mysql);
static int mc_sock_connect(File s, const struct sockaddr *name, uint namelen, uint to);
static void mc_free_old_query(MYSQL *mysql);
+static int mc_send_file_to_server(MYSQL *mysql, const char *filename);
+static my_ulonglong mc_net_field_length_ll(uchar **packet);
+static ulong mc_net_field_length(uchar **packet);
+static int mc_read_one_row(MYSQL *mysql,uint fields,MYSQL_ROW row,
+ ulong *lengths);
+static MYSQL_DATA *mc_read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields,
+ uint fields);
+
#define CLIENT_CAPABILITIES (CLIENT_LONG_PASSWORD | CLIENT_LONG_FLAG | CLIENT_LOCAL_FILES)
@@ -187,8 +194,7 @@ HANDLE create_named_pipe(NET *net, uint connect_timeout, char **arg_host,
** Init MySQL structure or allocate one
****************************************************************************/
-MYSQL * STDCALL
-mc_mysql_init(MYSQL *mysql)
+MYSQL *mc_mysql_init(MYSQL *mysql)
{
init_client_errs();
if (!mysql)
@@ -210,7 +216,7 @@ mc_mysql_init(MYSQL *mysql)
** Shut down connection
**************************************************************************/
-static void
+void
mc_end_server(MYSQL *mysql)
{
DBUG_ENTER("mc_end_server");
@@ -332,11 +338,11 @@ static int mc_sock_connect(my_socket s, const struct sockaddr *name,
** or packet is an error message
*****************************************************************************/
-uint STDCALL
+ulong
mc_net_safe_read(MYSQL *mysql)
{
NET *net= &mysql->net;
- uint len=0;
+ ulong len=0;
if (net->vio != 0)
len=my_net_read(net);
@@ -393,17 +399,17 @@ max_allowed_packet on this server");
}
-char * STDCALL mc_mysql_error(MYSQL *mysql)
+char *mc_mysql_error(MYSQL *mysql)
{
return (mysql)->net.last_error;
}
-int STDCALL mc_mysql_errno(MYSQL *mysql)
+int mc_mysql_errno(MYSQL *mysql)
{
return (mysql)->net.last_errno;
}
-my_bool STDCALL mc_mysql_reconnect(MYSQL *mysql)
+my_bool mc_mysql_reconnect(MYSQL *mysql)
{
MYSQL tmp_mysql;
DBUG_ENTER("mc_mysql_reconnect");
@@ -433,7 +439,7 @@ my_bool STDCALL mc_mysql_reconnect(MYSQL *mysql)
-int STDCALL
+int
mc_simple_command(MYSQL *mysql,enum enum_server_command command,
const char *arg, uint length, my_bool skipp_check)
{
@@ -486,7 +492,7 @@ mc_simple_command(MYSQL *mysql,enum enum_server_command command,
}
-MYSQL * STDCALL
+MYSQL *
mc_mysql_connect(MYSQL *mysql,const char *host, const char *user,
const char *passwd, const char *db,
uint port, const char *unix_socket,uint client_flag)
@@ -495,7 +501,7 @@ mc_mysql_connect(MYSQL *mysql,const char *host, const char *user,
my_socket sock;
ulong ip_addr;
struct sockaddr_in sock_addr;
- uint pkt_length;
+ ulong pkt_length;
NET *net= &mysql->net;
thr_alarm_t alarmed;
ALARM alarm_buff;
@@ -761,6 +767,20 @@ mc_mysql_connect(MYSQL *mysql,const char *host, const char *user,
mysql->client_flag=client_flag;
#ifdef HAVE_OPENSSL
+ if ((mysql->server_capabilities & CLIENT_SSL) &&
+ (mysql->options.use_ssl || (client_flag & CLIENT_SSL)))
+ {
+ DBUG_PRINT("info", ("Changing IO layer to SSL"));
+ client_flag |= CLIENT_SSL;
+ }
+ else
+ {
+ if (client_flag & CLIENT_SSL)
+ {
+ DBUG_PRINT("info", ("Leaving IO layer intact because server doesn't support SSL"));
+ }
+ client_flag &= ~CLIENT_SSL;
+ }
/* Oops.. are we careful enough to not send ANY information */
/* without encryption? */
if (client_flag & CLIENT_SSL)
@@ -769,15 +789,14 @@ mc_mysql_connect(MYSQL *mysql,const char *host, const char *user,
goto error;
/* Do the SSL layering. */
DBUG_PRINT("info", ("IO layer change in progress..."));
- VioSSLConnectorFd* connector_fd = (VioSSLConnectorFd*)
- (mysql->connector_fd);
- VioSocket* vio_socket = (VioSocket*)(mysql->net.vio);
- VioSSL* vio_ssl = connector_fd->connect(vio_socket);
- mysql->net.vio = (NetVio*)(vio_ssl);
+ DBUG_PRINT("info", ("IO context %p",((struct st_VioSSLConnectorFd*)mysql->connector_fd)->ssl_context_));
+ sslconnect((struct st_VioSSLConnectorFd*)(mysql->connector_fd),mysql->net.vio,60L);
+ DBUG_PRINT("info", ("IO layer change done!"));
}
#endif /* HAVE_OPENSSL */
-
int3store(buff+2,max_allowed_packet);
+
+
if (user && user[0])
strmake(buff+5,user,32);
else
@@ -816,12 +835,38 @@ error:
DBUG_RETURN(0);
}
+
+#ifdef HAVE_OPENSSL
+/*
+**************************************************************************
+** Free strings in the SSL structure and clear 'use_ssl' flag.
+** NB! Errors are not reported until you do mysql_real_connect.
+**************************************************************************
+*/
+int
+mysql_ssl_clear(MYSQL *mysql)
+{
+ my_free(mysql->options.ssl_key, MYF(MY_ALLOW_ZERO_PTR));
+ my_free(mysql->options.ssl_cert, MYF(MY_ALLOW_ZERO_PTR));
+ my_free(mysql->options.ssl_ca, MYF(MY_ALLOW_ZERO_PTR));
+ my_free(mysql->options.ssl_capath, MYF(MY_ALLOW_ZERO_PTR));
+ mysql->options.ssl_key = 0;
+ mysql->options.ssl_cert = 0;
+ mysql->options.ssl_ca = 0;
+ mysql->options.ssl_capath = 0;
+ mysql->options.use_ssl = FALSE;
+ my_free(mysql->connector_fd,MYF(MY_ALLOW_ZERO_PTR));
+ mysql->connector_fd = 0;
+ return 0;
+}
+#endif /* HAVE_OPENSSL */
+
/*************************************************************************
** Send a QUIT to the server and close the connection
** If handle is alloced by mysql connect free it.
*************************************************************************/
-void STDCALL
+void
mc_mysql_close(MYSQL *mysql)
{
DBUG_ENTER("mysql_close");
@@ -844,11 +889,502 @@ mc_mysql_close(MYSQL *mysql)
bzero((char*) &mysql->options,sizeof(mysql->options));
mysql->net.vio = 0;
#ifdef HAVE_OPENSSL
- ((VioConnectorFd*)(mysql->connector_fd))->delete();
- mysql->connector_fd = 0;
+ mysql_ssl_clear(mysql);
#endif /* HAVE_OPENSSL */
if (mysql->free_me)
my_free((gptr) mysql,MYF(0));
}
DBUG_VOID_RETURN;
}
+
+void mc_mysql_free_result(MYSQL_RES *result)
+{
+ DBUG_ENTER("mc_mysql_free_result");
+ DBUG_PRINT("enter",("mysql_res: %lx",result));
+ if (result)
+ {
+ if (result->handle && result->handle->status == MYSQL_STATUS_USE_RESULT)
+ {
+ DBUG_PRINT("warning",("Not all rows in set were read; Ignoring rows"));
+ for (;;)
+ {
+ ulong pkt_len;
+ if ((pkt_len=mc_net_safe_read(result->handle)) == packet_error)
+ break;
+ if (pkt_len == 1 && result->handle->net.read_pos[0] == 254)
+ break; /* End of data */
+ }
+ result->handle->status=MYSQL_STATUS_READY;
+ }
+ mc_free_rows(result->data);
+ if (result->fields)
+ free_root(&result->field_alloc,MYF(0));
+ if (result->row)
+ my_free((gptr) result->row,MYF(0));
+ my_free((gptr) result,MYF(0));
+ }
+ DBUG_VOID_RETURN;
+}
+
+static void mc_free_rows(MYSQL_DATA *cur)
+{
+ if (cur)
+ {
+ free_root(&cur->alloc,MYF(0));
+ my_free((gptr) cur,MYF(0));
+ }
+}
+
+static MYSQL_FIELD *
+mc_unpack_fields(MYSQL_DATA *data,MEM_ROOT *alloc,uint fields,
+ my_bool default_value, my_bool long_flag_protocol)
+{
+ MYSQL_ROWS *row;
+ MYSQL_FIELD *field,*result;
+ DBUG_ENTER("unpack_fields");
+
+ field=result=(MYSQL_FIELD*) alloc_root(alloc,sizeof(MYSQL_FIELD)*fields);
+ if (!result)
+ DBUG_RETURN(0);
+
+ for (row=data->data; row ; row = row->next,field++)
+ {
+ field->table= strdup_root(alloc,(char*) row->data[0]);
+ field->name= strdup_root(alloc,(char*) row->data[1]);
+ field->length= (uint) uint3korr(row->data[2]);
+ field->type= (enum enum_field_types) (uchar) row->data[3][0];
+ if (long_flag_protocol)
+ {
+ field->flags= uint2korr(row->data[4]);
+ field->decimals=(uint) (uchar) row->data[4][2];
+ }
+ else
+ {
+ field->flags= (uint) (uchar) row->data[4][0];
+ field->decimals=(uint) (uchar) row->data[4][1];
+ }
+ if (INTERNAL_NUM_FIELD(field))
+ field->flags|= NUM_FLAG;
+ if (default_value && row->data[5])
+ field->def=strdup_root(alloc,(char*) row->data[5]);
+ else
+ field->def=0;
+ field->max_length= 0;
+ }
+ mc_free_rows(data); /* Free old data */
+ DBUG_RETURN(result);
+}
+
+int
+mc_mysql_send_query(MYSQL* mysql, const char* query, uint length)
+{
+ return mc_simple_command(mysql, COM_QUERY, query, length, 1);
+}
+
+int mc_mysql_read_query_result(MYSQL *mysql)
+{
+ uchar *pos;
+ ulong field_count;
+ MYSQL_DATA *fields;
+ ulong length;
+ DBUG_ENTER("mc_mysql_read_query_result");
+
+ if ((length = mc_net_safe_read(mysql)) == packet_error)
+ DBUG_RETURN(-1);
+ mc_free_old_query(mysql); /* Free old result */
+get_info:
+ pos=(uchar*) mysql->net.read_pos;
+ if ((field_count= mc_net_field_length(&pos)) == 0)
+ {
+ mysql->affected_rows= mc_net_field_length_ll(&pos);
+ mysql->insert_id= mc_net_field_length_ll(&pos);
+ if (mysql->server_capabilities & CLIENT_TRANSACTIONS)
+ {
+ mysql->server_status=uint2korr(pos); pos+=2;
+ }
+ if (pos < mysql->net.read_pos+length && mc_net_field_length(&pos))
+ mysql->info=(char*) pos;
+ DBUG_RETURN(0);
+ }
+ if (field_count == NULL_LENGTH) /* LOAD DATA LOCAL INFILE */
+ {
+ int error=mc_send_file_to_server(mysql,(char*) pos);
+ if ((length=mc_net_safe_read(mysql)) == packet_error || error)
+ DBUG_RETURN(-1);
+ goto get_info; /* Get info packet */
+ }
+ if (!(mysql->server_status & SERVER_STATUS_AUTOCOMMIT))
+ mysql->server_status|= SERVER_STATUS_IN_TRANS;
+
+ mysql->extra_info= mc_net_field_length_ll(&pos); /* Maybe number of rec */
+ if (!(fields=mc_read_rows(mysql,(MYSQL_FIELD*) 0,5)))
+ DBUG_RETURN(-1);
+ if (!(mysql->fields=mc_unpack_fields(fields,&mysql->field_alloc,
+ (uint) field_count,0,
+ (my_bool) test(mysql->server_capabilities &
+ CLIENT_LONG_FLAG))))
+ DBUG_RETURN(-1);
+ mysql->status=MYSQL_STATUS_GET_RESULT;
+ mysql->field_count=field_count;
+ DBUG_RETURN(0);
+}
+
+int mc_mysql_query(MYSQL *mysql, const char *query, uint length)
+{
+ DBUG_ENTER("mysql_real_query");
+ DBUG_PRINT("enter",("handle: %lx",mysql));
+ DBUG_PRINT("query",("Query = \"%s\"",query));
+ if (!length)
+ length = strlen(query);
+ if (mc_simple_command(mysql,COM_QUERY,query,length,1))
+ DBUG_RETURN(-1);
+ DBUG_RETURN(mc_mysql_read_query_result(mysql));
+}
+
+static int mc_send_file_to_server(MYSQL *mysql, const char *filename)
+{
+ int fd, readcount, result= -1;
+ uint packet_length=MY_ALIGN(mysql->net.max_packet-16,IO_SIZE);
+ char *buf, tmp_name[FN_REFLEN];
+ DBUG_ENTER("send_file_to_server");
+
+ if (!(buf=my_malloc(packet_length,MYF(0))))
+ {
+ strmov(mysql->net.last_error, ER(mysql->net.last_errno=CR_OUT_OF_MEMORY));
+ DBUG_RETURN(-1);
+ }
+
+ fn_format(tmp_name,filename,"","",4); /* Convert to client format */
+ if ((fd = my_open(tmp_name,O_RDONLY, MYF(0))) < 0)
+ {
+ my_net_write(&mysql->net,"",0); // Server needs one packet
+ net_flush(&mysql->net);
+ mysql->net.last_errno=EE_FILENOTFOUND;
+ my_snprintf(mysql->net.last_error,sizeof(mysql->net.last_error)-1,
+ EE(mysql->net.last_errno),tmp_name, errno);
+ goto err;
+ }
+
+ while ((readcount = (int) my_read(fd,(byte*) buf,packet_length,MYF(0))) > 0)
+ {
+ if (my_net_write(&mysql->net,buf,readcount))
+ {
+ DBUG_PRINT("error",("Lost connection to MySQL server during LOAD DATA of local file"));
+ mysql->net.last_errno=CR_SERVER_LOST;
+ strmov(mysql->net.last_error,ER(mysql->net.last_errno));
+ goto err;
+ }
+ }
+ /* Send empty packet to mark end of file */
+ if (my_net_write(&mysql->net,"",0) || net_flush(&mysql->net))
+ {
+ mysql->net.last_errno=CR_SERVER_LOST;
+ sprintf(mysql->net.last_error,ER(mysql->net.last_errno),errno);
+ goto err;
+ }
+ if (readcount < 0)
+ {
+ mysql->net.last_errno=EE_READ; /* the errmsg for not entire file read */
+ my_snprintf(mysql->net.last_error,sizeof(mysql->net.last_error)-1,
+ tmp_name,errno);
+ goto err;
+ }
+ result=0; // Ok
+
+err:
+ if (fd >= 0)
+ (void) my_close(fd,MYF(0));
+ my_free(buf,MYF(0));
+ DBUG_RETURN(result);
+}
+
+
+/* Get the length of next field. Change parameter to point at fieldstart */
+static ulong mc_net_field_length(uchar **packet)
+{
+ reg1 uchar *pos= *packet;
+ if (*pos < 251)
+ {
+ (*packet)++;
+ return (ulong) *pos;
+ }
+ if (*pos == 251)
+ {
+ (*packet)++;
+ return NULL_LENGTH;
+ }
+ if (*pos == 252)
+ {
+ (*packet)+=3;
+ return (ulong) uint2korr(pos+1);
+ }
+ if (*pos == 253)
+ {
+ (*packet)+=4;
+ return (ulong) uint3korr(pos+1);
+ }
+ (*packet)+=9; /* Must be 254 when here */
+ return (ulong) uint4korr(pos+1);
+}
+
+/* Same as above, but returns ulonglong values */
+
+static my_ulonglong mc_net_field_length_ll(uchar **packet)
+{
+ reg1 uchar *pos= *packet;
+ if (*pos < 251)
+ {
+ (*packet)++;
+ return (my_ulonglong) *pos;
+ }
+ if (*pos == 251)
+ {
+ (*packet)++;
+ return (my_ulonglong) NULL_LENGTH;
+ }
+ if (*pos == 252)
+ {
+ (*packet)+=3;
+ return (my_ulonglong) uint2korr(pos+1);
+ }
+ if (*pos == 253)
+ {
+ (*packet)+=4;
+ return (my_ulonglong) uint3korr(pos+1);
+ }
+ (*packet)+=9; /* Must be 254 when here */
+#ifdef NO_CLIENT_LONGLONG
+ return (my_ulonglong) uint4korr(pos+1);
+#else
+ return (my_ulonglong) uint8korr(pos+1);
+#endif
+}
+
+/* Read all rows (fields or data) from server */
+
+static MYSQL_DATA *mc_read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields,
+ uint fields)
+{
+ uint field;
+ ulong pkt_len;
+ ulong len;
+ uchar *cp;
+ char *to;
+ MYSQL_DATA *result;
+ MYSQL_ROWS **prev_ptr,*cur;
+ NET *net = &mysql->net;
+ DBUG_ENTER("mc_read_rows");
+
+ if ((pkt_len=mc_net_safe_read(mysql)) == packet_error)
+ DBUG_RETURN(0);
+ if (!(result=(MYSQL_DATA*) my_malloc(sizeof(MYSQL_DATA),
+ MYF(MY_ZEROFILL))))
+ {
+ net->last_errno=CR_OUT_OF_MEMORY;
+ strmov(net->last_error,ER(net->last_errno));
+ DBUG_RETURN(0);
+ }
+ init_alloc_root(&result->alloc,8192,0); /* Assume rowlength < 8192 */
+ result->alloc.min_malloc=sizeof(MYSQL_ROWS);
+ prev_ptr= &result->data;
+ result->rows=0;
+ result->fields=fields;
+
+ while (*(cp=net->read_pos) != 254 || pkt_len != 1)
+ {
+ result->rows++;
+ if (!(cur= (MYSQL_ROWS*) alloc_root(&result->alloc,
+ sizeof(MYSQL_ROWS))) ||
+ !(cur->data= ((MYSQL_ROW)
+ alloc_root(&result->alloc,
+ (fields+1)*sizeof(char *)+pkt_len))))
+ {
+ mc_free_rows(result);
+ net->last_errno=CR_OUT_OF_MEMORY;
+ strmov(net->last_error,ER(net->last_errno));
+ DBUG_RETURN(0);
+ }
+ *prev_ptr=cur;
+ prev_ptr= &cur->next;
+ to= (char*) (cur->data+fields+1);
+ for (field=0 ; field < fields ; field++)
+ {
+ if ((len=(ulong) mc_net_field_length(&cp)) == NULL_LENGTH)
+ { /* null field */
+ cur->data[field] = 0;
+ }
+ else
+ {
+ cur->data[field] = to;
+ memcpy(to,(char*) cp,len); to[len]=0;
+ to+=len+1;
+ cp+=len;
+ if (mysql_fields)
+ {
+ if (mysql_fields[field].max_length < len)
+ mysql_fields[field].max_length=len;
+ }
+ }
+ }
+ cur->data[field]=to; /* End of last field */
+ if ((pkt_len=mc_net_safe_read(mysql)) == packet_error)
+ {
+ mc_free_rows(result);
+ DBUG_RETURN(0);
+ }
+ }
+ *prev_ptr=0; /* last pointer is null */
+ DBUG_PRINT("exit",("Got %d rows",result->rows));
+ DBUG_RETURN(result);
+}
+
+
+/*
+** Read one row. Uses packet buffer as storage for fields.
+** When next packet is read, the previous field values are destroyed
+*/
+
+
+static int mc_read_one_row(MYSQL *mysql,uint fields,MYSQL_ROW row,
+ ulong *lengths)
+{
+ uint field;
+ ulong pkt_len,len;
+ uchar *pos,*prev_pos;
+
+ if ((pkt_len=mc_net_safe_read(mysql)) == packet_error)
+ return -1;
+ if (pkt_len == 1 && mysql->net.read_pos[0] == 254)
+ return 1; /* End of data */
+ prev_pos= 0; /* allowed to write at packet[-1] */
+ pos=mysql->net.read_pos;
+ for (field=0 ; field < fields ; field++)
+ {
+ if ((len=(ulong) mc_net_field_length(&pos)) == NULL_LENGTH)
+ { /* null field */
+ row[field] = 0;
+ *lengths++=0;
+ }
+ else
+ {
+ row[field] = (char*) pos;
+ pos+=len;
+ *lengths++=len;
+ }
+ if (prev_pos)
+ *prev_pos=0; /* Terminate prev field */
+ prev_pos=pos;
+ }
+ row[field]=(char*) prev_pos+1; /* End of last field */
+ *prev_pos=0; /* Terminate last field */
+ return 0;
+}
+
+my_ulonglong mc_mysql_num_rows(MYSQL_RES *res)
+{
+ return res->row_count;
+}
+
+unsigned int mc_mysql_num_fields(MYSQL_RES *res)
+{
+ return res->field_count;
+}
+
+void mc_mysql_data_seek(MYSQL_RES *result, my_ulonglong row)
+{
+ MYSQL_ROWS *tmp=0;
+ DBUG_PRINT("info",("mysql_data_seek(%ld)",(long) row));
+ if (result->data)
+ for (tmp=result->data->data; row-- && tmp ; tmp = tmp->next) ;
+ result->current_row=0;
+ result->data_cursor = tmp;
+}
+
+MYSQL_ROW STDCALL mc_mysql_fetch_row(MYSQL_RES *res)
+{
+ DBUG_ENTER("mc_mysql_fetch_row");
+ if (!res->data)
+ { /* Unbufferred fetch */
+ if (!res->eof)
+ {
+ if (!(mc_read_one_row(res->handle,res->field_count,res->row,
+ res->lengths)))
+ {
+ res->row_count++;
+ DBUG_RETURN(res->current_row=res->row);
+ }
+ else
+ {
+ DBUG_PRINT("info",("end of data"));
+ res->eof=1;
+ res->handle->status=MYSQL_STATUS_READY;
+ }
+ }
+ DBUG_RETURN((MYSQL_ROW) NULL);
+ }
+ {
+ MYSQL_ROW tmp;
+ if (!res->data_cursor)
+ {
+ DBUG_PRINT("info",("end of data"));
+ DBUG_RETURN(res->current_row=(MYSQL_ROW) NULL);
+ }
+ tmp = res->data_cursor->data;
+ res->data_cursor = res->data_cursor->next;
+ DBUG_RETURN(res->current_row=tmp);
+ }
+}
+
+int mc_mysql_select_db(MYSQL *mysql, const char *db)
+{
+ int error;
+ DBUG_ENTER("mysql_select_db");
+ DBUG_PRINT("enter",("db: '%s'",db));
+
+ if ((error=mc_simple_command(mysql,COM_INIT_DB,db,(uint) strlen(db),0)))
+ DBUG_RETURN(error);
+ my_free(mysql->db,MYF(MY_ALLOW_ZERO_PTR));
+ mysql->db=my_strdup(db,MYF(MY_WME));
+ DBUG_RETURN(0);
+}
+
+
+MYSQL_RES *mc_mysql_store_result(MYSQL *mysql)
+{
+ MYSQL_RES *result;
+ DBUG_ENTER("mysql_store_result");
+
+ if (!mysql->fields)
+ DBUG_RETURN(0);
+ if (mysql->status != MYSQL_STATUS_GET_RESULT)
+ {
+ strmov(mysql->net.last_error,
+ ER(mysql->net.last_errno=CR_COMMANDS_OUT_OF_SYNC));
+ DBUG_RETURN(0);
+ }
+ mysql->status=MYSQL_STATUS_READY; /* server is ready */
+ if (!(result=(MYSQL_RES*) my_malloc(sizeof(MYSQL_RES)+
+ sizeof(ulong)*mysql->field_count,
+ MYF(MY_ZEROFILL))))
+ {
+ mysql->net.last_errno=CR_OUT_OF_MEMORY;
+ strmov(mysql->net.last_error, ER(mysql->net.last_errno));
+ DBUG_RETURN(0);
+ }
+ result->eof=1; /* Marker for buffered */
+ result->lengths=(ulong*) (result+1);
+ if (!(result->data=mc_read_rows(mysql,mysql->fields,mysql->field_count)))
+ {
+ my_free((gptr) result,MYF(0));
+ DBUG_RETURN(0);
+ }
+ mysql->affected_rows= result->row_count= result->data->rows;
+ result->data_cursor= result->data->data;
+ result->fields= mysql->fields;
+ result->field_alloc= mysql->field_alloc;
+ result->field_count= mysql->field_count;
+ result->current_field=0;
+ result->current_row=0; /* Must do a fetch first */
+ mysql->fields=0; /* fields is now in result */
+ DBUG_RETURN(result); /* Data fetched */
+}
diff --git a/sql/mini_client.h b/sql/mini_client.h
index f7d95a1b66e..6721b072080 100644
--- a/sql/mini_client.h
+++ b/sql/mini_client.h
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -18,30 +18,34 @@
#define _MINI_CLIENT_H
-MYSQL* STDCALL
-mc_mysql_connect(MYSQL *mysql,const char *host, const char *user,
+MYSQL* mc_mysql_connect(MYSQL *mysql,const char *host, const char *user,
const char *passwd, const char *db,
uint port, const char *unix_socket,uint client_flag);
-int STDCALL
-mc_simple_command(MYSQL *mysql,enum enum_server_command command, const char *arg,
+int mc_simple_command(MYSQL *mysql,enum enum_server_command command, const char *arg,
uint length, my_bool skipp_check);
-void STDCALL
-mc_mysql_close(MYSQL *mysql);
+void mc_mysql_close(MYSQL *mysql);
-MYSQL * STDCALL
-mc_mysql_init(MYSQL *mysql);
+MYSQL * mc_mysql_init(MYSQL *mysql);
-void STDCALL
-mc_mysql_debug(const char *debug);
+void mc_mysql_debug(const char *debug);
-uint STDCALL
-mc_net_safe_read(MYSQL *mysql);
+ulong mc_net_safe_read(MYSQL *mysql);
-char * STDCALL mc_mysql_error(MYSQL *mysql);
-int STDCALL mc_mysql_errno(MYSQL *mysql);
-my_bool STDCALL mc_mysql_reconnect(MYSQL* mysql);
+char * mc_mysql_error(MYSQL *mysql);
+int mc_mysql_errno(MYSQL *mysql);
+my_bool mc_mysql_reconnect(MYSQL* mysql);
+int mc_mysql_send_query(MYSQL* mysql, const char* query, uint length);
+int mc_mysql_read_query_result(MYSQL *mysql);
+int mc_mysql_query(MYSQL *mysql, const char *query, uint length);
+MYSQL_RES * mc_mysql_store_result(MYSQL *mysql);
+void mc_mysql_free_result(MYSQL_RES *result);
+void mc_mysql_data_seek(MYSQL_RES *result, my_ulonglong row);
+my_ulonglong mc_mysql_num_rows(MYSQL_RES *res);
+unsigned int mc_mysql_num_fields(MYSQL_RES *res);
+MYSQL_ROW STDCALL mc_mysql_fetch_row(MYSQL_RES *res);
+int mc_mysql_select_db(MYSQL *mysql, const char *db);
+void mc_end_server(MYSQL *mysql);
#endif
-
diff --git a/sql/my_lock.c b/sql/my_lock.c
index 647c07a03c3..4d451fcff22 100644
--- a/sql/my_lock.c
+++ b/sql/my_lock.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -19,7 +19,7 @@
#else
#undef MAP_TO_USE_RAID /* Avoid RAID mappings */
-#include <global.h>
+#include <my_global.h>
#include <my_sys.h>
#include <mysys_err.h>
#include <my_pthread.h>
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index 657ca3274cd..924f85b0a89 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -17,16 +17,16 @@
#ifndef _MYSQL_PRIV_H
#define _MYSQL_PRIV_H
-#include <global.h>
+#include <my_global.h>
+#include "mysql_embed.h"
#include <my_sys.h>
#include <m_string.h>
-#include "mysql_version.h"
+#include <mysql_version.h>
#include <hash.h>
#include <signal.h>
#include <thr_lock.h>
#include <my_base.h> /* Needed by field.h */
#include <my_bitmap.h>
-#include <violite.h>
#ifdef __EMX__
#undef write // remove pthread.h macro definition for EMX
@@ -37,6 +37,7 @@ typedef ulong key_map; /* Used for finding keys */
typedef ulong key_part_map; /* Used for finding key parts */
#include "mysql_com.h"
+#include <violite.h>
#include "unireg.h"
void init_sql_alloc(MEM_ROOT *root, uint block_size, uint pre_alloc_size);
@@ -47,6 +48,8 @@ char *sql_strmake(const char *str,uint len);
gptr sql_memdup(const void * ptr,unsigned size);
void sql_element_free(void *ptr);
void kill_one_thread(THD *thd, ulong id);
+int net_request_file(NET* net, const char* fname);
+char* query_table_status(THD *thd,const char *db,const char *table_name);
#define x_free(A) { my_free((gptr) (A),MYF(MY_WME | MY_FAE | MY_ALLOW_ZERO_PTR)); }
#define safeFree(x) { if(x) { my_free((gptr) x,MYF(0)); x = NULL; } }
@@ -69,7 +72,6 @@ void kill_one_thread(THD *thd, ulong id);
#define HASH_PASSWORD_LENGTH 16
#define HOST_CACHE_SIZE 128
#define MAX_ACCEPT_RETRY 10 // Test accept this many times
-#define MAX_BLOB_WIDTH 8192 // Default width for blob
#define MAX_FIELDS_BEFORE_HASH 32
#define USER_VARS_HASH_SIZE 16
#define STACK_MIN_SIZE 8192 // Abort if less stack during eval.
@@ -147,9 +149,9 @@ void kill_one_thread(THD *thd, ulong id);
#define SELECT_DESCRIBE 4
#define SELECT_SMALL_RESULT 8
#define SELECT_BIG_RESULT 16
-#define SELECT_HIGH_PRIORITY 64 /* Intern */
-#define SELECT_USE_CACHE 256 /* Intern */
-#define SELECT_COUNT_DISTINCT 512 /* Intern */
+#define OPTION_FOUND_ROWS 32
+#define OPTION_TO_QUERY_CACHE 64
+#define SELECT_NO_JOIN_CACHE 256 /* Intern */
#define OPTION_BIG_TABLES 512 /* for SQL OPTION */
#define OPTION_BIG_SELECTS 1024 /* for SQL OPTION */
@@ -176,16 +178,33 @@ void kill_one_thread(THD *thd, ulong id);
#define QUERY_NO_INDEX_USED OPTION_STATUS_NO_TRANS_UPDATE*2
#define QUERY_NO_GOOD_INDEX_USED QUERY_NO_INDEX_USED*2
+#define SELECT_NO_UNLOCK (QUERY_NO_GOOD_INDEX_USED*2)
+#define TMP_TABLE_ALL_COLUMNS (SELECT_NO_UNLOCK*2)
+
/* Bits for different SQL modes modes (including ANSI mode) */
-#define MODE_REAL_AS_FLOAT 1
-#define MODE_PIPES_AS_CONCAT 2
-#define MODE_ANSI_QUOTES 4
-#define MODE_IGNORE_SPACE 8
-#define MODE_SERIALIZABLE 16
-#define MODE_ONLY_FULL_GROUP_BY 32
+#define MODE_REAL_AS_FLOAT 1
+#define MODE_PIPES_AS_CONCAT 2
+#define MODE_ANSI_QUOTES 4
+#define MODE_IGNORE_SPACE 8
+#define MODE_SERIALIZABLE 16
+#define MODE_ONLY_FULL_GROUP_BY 32
+#define MODE_NO_UNSIGNED_SUBTRACTION 64
#define RAID_BLOCK_SIZE 1024
+// Sync points allow us to force the server to reach a certain line of code
+// and block there until the client tells the server it is ok to go on.
+// The client tells the server to block with SELECT GET_LOCK()
+// and unblocks it with SELECT RELEASE_LOCK(). Used for debugging difficult
+// concurrency problems
+#ifdef EXTRA_DEBUG
+#define DBUG_SYNC_POINT(lock_name,lock_timeout) \
+ debug_sync_point(lock_name,lock_timeout)
+void debug_sync_point(const char* lock_name, uint lock_timeout);
+#else
+#define DBUG_SYNC_POINT(lock_name,lock_timeout)
+#endif
+
/* BINLOG_DUMP options */
#define BINLOG_DUMP_NON_BLOCK 1
@@ -232,17 +251,22 @@ inline THD *_current_thd(void)
#include "item.h"
#include "sql_class.h"
#include "opt_range.h"
+#include "sql_cache.h"
-
-void mysql_create_db(THD *thd, char *db, uint create_info);
+int mysql_create_db(THD *thd, char *db, uint create_info, bool silent);
+int mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent);
void mysql_binlog_send(THD* thd, char* log_ident, ulong pos, ushort flags);
int mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists);
+int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
+ bool log_query);
int quick_rm_table(enum db_type base,const char *db,
const char *table_name);
bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list);
bool mysql_change_db(THD *thd,const char *name);
void mysql_parse(THD *thd,char *inBuf,uint length);
void mysql_init_select(LEX *lex);
+bool mysql_new_select(LEX *lex);
+void mysql_init_multi_delete(LEX *lex);
void init_max_user_conn(void);
void free_max_user_conn(void);
pthread_handler_decl(handle_one_connection,arg);
@@ -252,23 +276,21 @@ void end_thread(THD *thd,bool put_in_cache);
void flush_thread_cache();
void mysql_execute_command(void);
bool do_command(THD *thd);
+bool dispatch_command(enum enum_server_command command, THD *thd,
+ char* packet, uint packet_length);
bool check_stack_overrun(THD *thd,char *dummy);
-bool reload_acl_and_cache(THD *thd, uint options, TABLE_LIST *tables);
-void mysql_rm_db(THD *thd,char *db,bool if_exists);
+bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables);
void table_cache_init(void);
void table_cache_free(void);
uint cached_tables(void);
void kill_mysql(void);
void close_connection(NET *net,uint errcode=0,bool lock=1);
bool check_access(THD *thd,uint access,const char *db=0,uint *save_priv=0,
- bool no_grant=0);
-bool check_table_access(THD *thd,uint want_access,TABLE_LIST *tables);
+ bool no_grant=0, bool no_errors=0);
+bool check_table_access(THD *thd,uint want_access, TABLE_LIST *tables,
+ bool no_errors=0);
bool check_process_priv(THD *thd=0);
-int generate_table(THD *thd, TABLE_LIST *table_list,
- TABLE *locked_table);
-
-
int mysql_backup_table(THD* thd, TABLE_LIST* table_list);
int mysql_restore_table(THD* thd, TABLE_LIST* table_list);
@@ -282,7 +304,6 @@ int mysql_optimize_table(THD* thd, TABLE_LIST* table_list,
HA_CHECK_OPT* check_opt);
/* net_pkg.c */
-void send_error(NET *net,uint sql_errno=0, const char *err=0);
void send_warning(NET *net, uint sql_errno, const char *err=0);
void net_printf(NET *net,uint sql_errno, ...);
void send_ok(NET *net,ha_rows affected_rows=0L,ulonglong id=0L,
@@ -309,10 +330,12 @@ SORT_FIELD * make_unireg_sortorder(ORDER *order, uint *length);
int setup_order(THD *thd,TABLE_LIST *tables, List<Item> &fields,
List <Item> &all_fields, ORDER *order);
+int handle_select(THD *thd, LEX *lex, select_result *result);
int mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &list,COND *conds,
ORDER *order, ORDER *group,Item *having,ORDER *proc_param,
- uint select_type,select_result *result);
-Field *create_tmp_field(TABLE *table,Item *item, Item::Type type,
+ ulong select_type,select_result *result);
+int mysql_union(THD *thd,LEX *lex,select_result *result);
+Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
Item_result_field ***copy_func, Field **from_field,
bool group,bool modify_item);
int mysql_create_table(THD *thd,const char *db, const char *table_name,
@@ -336,7 +359,9 @@ int mysql_alter_table(THD *thd, char *new_db, char *new_name,
List<Alter_column> &alter_list,
ORDER *order,
bool drop_primary,
- enum enum_duplicates handle_duplicates);
+ enum enum_duplicates handle_duplicates,
+ enum enum_enable_or_disable keys_onoff=LEAVE_AS_IS,
+ bool simple_alter=0);
bool mysql_rename_table(enum db_type base,
const char *old_db,
const char * old_name,
@@ -347,15 +372,17 @@ int mysql_create_index(THD *thd, TABLE_LIST *table_list, List<Key> &keys);
int mysql_drop_index(THD *thd, TABLE_LIST *table_list,
List<Alter_drop> &drop_list);
int mysql_update(THD *thd,TABLE_LIST *tables,List<Item> &fields,
- List<Item> &values,COND *conds, ha_rows limit,
+ List<Item> &values,COND *conds,
+ ORDER *order, ha_rows limit,
enum enum_duplicates handle_duplicates,
thr_lock_type lock_type);
int mysql_insert(THD *thd,TABLE_LIST *table,List<Item> &fields,
List<List_item> &values, enum_duplicates flag,
thr_lock_type lock_type);
void kill_delayed_threads(void);
-int mysql_delete(THD *thd,TABLE_LIST *table,COND *conds,ha_rows rows,
- thr_lock_type lock_type, ulong options);
+int mysql_delete(THD *thd, TABLE_LIST *table, COND *conds, ORDER *order,
+ ha_rows rows, thr_lock_type lock_type, ulong options);
+int mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok=0);
TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type update);
TABLE *open_table(THD *thd,const char *db,const char *table,const char *alias,
bool *refresh);
@@ -373,13 +400,28 @@ void abort_locked_tables(THD *thd,const char *db, const char *table_name);
Field *find_field_in_tables(THD *thd,Item_field *item,TABLE_LIST *tables);
Field *find_field_in_table(THD *thd,TABLE *table,const char *name,uint length,
bool check_grant,bool allow_rowid);
+#ifdef HAVE_OPENSSL
+struct st_des_keyblock
+{
+ des_cblock key1, key2, key3;
+};
+struct st_des_keyschedule
+{
+ des_key_schedule ks1, ks2, ks3;
+};
+extern char *des_key_file;
+extern struct st_des_keyschedule des_keyschedule[10];
+extern uint des_default_key;
+extern pthread_mutex_t LOCK_des_key_file;
+bool load_des_key_file(const char *file_name);
+#endif /* HAVE_OPENSSL */
/* sql_do.cc */
int mysql_do(THD *thd, List<Item> &values);
/* sql_list.c */
int mysqld_show_dbs(THD *thd,const char *wild);
-int mysqld_show_open_tables(THD *thd,const char *db,const char *wild);
+int mysqld_show_open_tables(THD *thd,const char *wild);
int mysqld_show_tables(THD *thd,const char *db,const char *wild);
int mysqld_extend_show_tables(THD *thd,const char *db,const char *wild);
int mysqld_show_fields(THD *thd,TABLE_LIST *table, const char *wild,
@@ -395,6 +437,12 @@ int mysqld_show_status(THD *thd);
int mysqld_show_variables(THD *thd,const char *wild);
int mysqld_show(THD *thd, const char *wild, show_var_st *variables);
+/* sql_handler.cc */
+int mysql_ha_open(THD *thd, TABLE_LIST *tables);
+int mysql_ha_close(THD *thd, TABLE_LIST *tables, bool dont_send_ok=0);
+int mysql_ha_read(THD *, TABLE_LIST *,enum enum_ha_read_modes,char *,
+ List<Item> *,enum ha_rkey_function,Item *,ha_rows,ha_rows);
+
/* sql_base.cc */
void set_item_name(Item *item,char *pos,uint length);
bool add_field_to_list(char *field_name, enum enum_field_types type,
@@ -416,9 +464,13 @@ TABLE *unlink_open_table(THD *thd,TABLE *list,TABLE *find);
SQL_SELECT *make_select(TABLE *head, table_map const_tables,
table_map read_tables, COND *conds, int *error);
Item ** find_item_in_list(Item *item,List<Item> &items);
+bool insert_fields(THD *thd,TABLE_LIST *tables,
+ const char *db_name, const char *table_name,
+ List_iterator<Item> *it);
bool setup_tables(TABLE_LIST *tables);
int setup_fields(THD *thd,TABLE_LIST *tables,List<Item> &item,
- bool set_query_id,List<Item> *sum_func_list);
+ bool set_query_id,List<Item> *sum_func_list,
+ bool allow_sum_func);
int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds);
int setup_ftfuncs(THD *thd);
int init_ftfuncs(THD *thd, bool no_order);
@@ -433,6 +485,7 @@ bool send_fields(THD *thd,List<Item> &item,uint send_field_count);
void free_io_cache(TABLE *entry);
void intern_close_table(TABLE *entry);
void close_thread_tables(THD *thd,bool locked=0);
+bool close_thread_table(THD *thd, TABLE **table_ptr);
void close_temporary_tables(THD *thd);
TABLE **find_temporary_table(THD *thd, const char *db, const char *table_name);
bool close_temporary_table(THD *thd, const char *db, const char *table_name);
@@ -447,8 +500,7 @@ bool close_cached_tables(THD *thd, bool wait_for_refresh, TABLE_LIST *tables);
void copy_field_from_tmp_record(Field *field,int offset);
int fill_record(List<Item> &fields,List<Item> &values);
int fill_record(Field **field,List<Item> &values);
-int list_open_tables(THD *thd,List<char> *files, const char *db,const char *wild);
-char* query_table_status(THD *thd,const char *db,const char *table_name);
+OPEN_TABLE_LIST *list_open_tables(THD *thd, const char *wild);
/* sql_calc.cc */
bool eval_const_cond(COND *cond);
@@ -463,7 +515,7 @@ int write_record(TABLE *table,COPY_INFO *info);
/* bits set in manager_status */
#define MANAGER_BERKELEY_LOG_CLEANUP (1L << 0)
extern ulong volatile manager_status;
-extern bool volatile manager_thread_in_use;
+extern bool volatile manager_thread_in_use, mqh_used;
extern pthread_t manager_thread;
extern pthread_mutex_t LOCK_manager;
extern pthread_cond_t COND_manager;
@@ -473,8 +525,7 @@ pthread_handler_decl(handle_manager, arg);
#ifndef DBUG_OFF
void print_where(COND *cond,const char *info);
void print_cached_tables(void);
-void TEST_filesort(TABLE **form,SORT_FIELD *sortorder,uint s_length,
- ha_rows special);
+void TEST_filesort(SORT_FIELD *sortorder,uint s_length, ha_rows special);
#endif
void mysql_print_status(THD *thd);
/* key.cc */
@@ -489,11 +540,17 @@ void init_errmessage(void);
void sql_perror(const char *message);
void sql_print_error(const char *format,...)
__attribute__ ((format (printf, 1, 2)));
+bool fn_format_relative_to_data_home(my_string to, const char *name,
+ const char *dir, const char *extension);
+void open_log(MYSQL_LOG *log, const char *hostname,
+ const char *opt_name, const char *extension,
+ enum_log_type type, bool read_append = 0,
+ bool no_auto_events = 0);
extern uint32 server_id;
-extern char mysql_data_home[2],server_version[SERVER_VERSION_LENGTH],
+extern char *mysql_data_home,server_version[SERVER_VERSION_LENGTH],
max_sort_char, mysql_real_data_home[];
-extern my_string mysql_unix_port,mysql_tmpdir;
+extern my_string mysql_tmpdir;
extern const char *first_keyword, *localhost, *delayed_user;
extern ulong refresh_version,flush_version, thread_id,query_id,opened_tables,
created_tmp_tables, created_tmp_disk_tables,
@@ -507,8 +564,9 @@ extern ulong filesort_merge_passes;
extern ulong select_range_check_count, select_range_count, select_scan_count;
extern ulong select_full_range_join_count,select_full_join_count,
slave_open_temp_tables;
-extern uint test_flags,select_errors,mysql_port,ha_open_options;
+extern uint test_flags,select_errors,ha_open_options;
extern ulong thd_startup_options, slow_launch_threads, slow_launch_time;
+extern ulong query_cache_startup_type;
extern time_t start_time;
extern const char *command_name[];
extern I_List<THD> threads;
@@ -520,17 +578,18 @@ extern pthread_mutex_t LOCK_mysql_create_db,LOCK_Acl,LOCK_open,
LOCK_thread_count,LOCK_mapped_file,LOCK_user_locks, LOCK_status,
LOCK_grant, LOCK_error_log, LOCK_delayed_insert,
LOCK_delayed_status, LOCK_delayed_create, LOCK_crypt, LOCK_timezone,
- LOCK_binlog_update, LOCK_slave, LOCK_server_id;
-extern pthread_cond_t COND_refresh,COND_thread_count, COND_binlog_update,
- COND_slave_stopped, COND_slave_start;
+ LOCK_server_id, LOCK_slave_list, LOCK_active_mi;
+extern pthread_cond_t COND_refresh,COND_thread_count;
extern pthread_attr_t connection_attrib;
extern bool opt_endinfo, using_udf_functions, locked_in_memory,
- opt_using_transactions, use_temp_pool, opt_local_infile;
+ opt_using_transactions, use_temp_pool, mysql_embedded;
+extern bool opt_local_infile;
extern char f_fyllchar;
extern ulong ha_read_count, ha_write_count, ha_delete_count, ha_update_count,
ha_read_key_count, ha_read_next_count, ha_read_prev_count,
ha_read_first_count, ha_read_last_count,
- ha_read_rnd_count, ha_read_rnd_next_count;
+ ha_read_rnd_count, ha_read_rnd_next_count,
+ ha_commit_count, ha_rollback_count;
extern MY_BITMAP temp_pool;
extern uchar *days_in_month;
extern DATE_FORMAT dayord;
@@ -542,14 +601,15 @@ extern ulong keybuff_size,sortbuff_size,max_item_sort_length,table_cache_size,
max_insert_delayed_threads, max_user_connections,
long_query_count,net_wait_timeout,net_interactive_timeout,
net_read_timeout,net_write_timeout,
- what_to_log,flush_time, opt_sql_mode,
+ what_to_log,flush_time,opt_sql_mode,
max_tmp_tables,max_heap_table_size,query_buff_size,
lower_case_table_names,thread_stack,thread_stack_min,
binlog_cache_size, max_binlog_cache_size, record_rnd_cache_size;
extern ulong com_stat[(uint) SQLCOM_END], com_other;
extern ulong specialflag, current_pid;
-extern bool low_priority_updates, using_update_log,opt_warnings;
-extern bool opt_sql_bin_update, opt_safe_show_db, opt_safe_user_create;
+extern bool low_priority_updates, using_update_log;
+extern bool opt_sql_bin_update, opt_safe_show_db, opt_warnings,
+ opt_safe_user_create, opt_no_mix_types;
extern char language[LIBLEN],reg_ext[FN_EXTLEN],blob_newline;
extern const char **errmesg; /* Error messages */
extern const char *default_tx_isolation_name;
@@ -558,6 +618,7 @@ extern struct show_var_st init_vars[];
extern struct show_var_st status_vars[];
extern enum db_type default_table_type;
extern enum enum_tx_isolation default_tx_isolation;
+extern char glob_hostname[FN_REFLEN];
#ifndef __WIN__
extern pthread_t signal_thread;
@@ -573,8 +634,13 @@ void mysql_unlock_some_tables(THD *thd, TABLE **table,uint count);
void mysql_lock_remove(THD *thd, MYSQL_LOCK *locked,TABLE *table);
void mysql_lock_abort(THD *thd, TABLE *table);
MYSQL_LOCK *mysql_lock_merge(MYSQL_LOCK *a,MYSQL_LOCK *b);
+bool lock_global_read_lock(THD *thd);
+void unlock_global_read_lock(THD *thd);
+bool wait_if_global_read_lock(THD *thd, bool abort_on_refresh);
+void start_waiting_global_read_lock(THD *thd);
/* Lock based on name */
+int lock_and_wait_for_table_name(THD *thd, TABLE_LIST *table_list);
int lock_table_name(THD *thd, TABLE_LIST *table_list);
void unlock_table_name(THD *thd, TABLE_LIST *table_list);
bool wait_for_locked_table_names(THD *thd, TABLE_LIST *table_list);
@@ -617,7 +683,7 @@ void init_read_record(READ_RECORD *info, THD *thd, TABLE *reg_form,
SQL_SELECT *select,
int use_record_cache, bool print_errors);
void end_read_record(READ_RECORD *info);
-ha_rows filesort(TABLE **form,struct st_sort_field *sortorder, uint s_length,
+ha_rows filesort(TABLE *form,struct st_sort_field *sortorder, uint s_length,
SQL_SELECT *select, ha_rows special,ha_rows max_rows,
ha_rows *examined_rows);
void change_double_for_sort(double nr,byte *to);
@@ -659,7 +725,6 @@ void hostname_cache_refresh(void);
bool get_interval_info(const char *str,uint length,uint count,
long *values);
/* sql_cache */
-
extern bool sql_cache_init();
extern void sql_cache_free();
extern int sql_cache_hit(THD *thd, char *inBuf, uint length);
@@ -668,7 +733,7 @@ extern int sql_cache_hit(THD *thd, char *inBuf, uint length);
inline bool add_item_to_list(Item *item)
{
- return current_lex->item_list.push_back(item);
+ return current_lex->select->item_list.push_back(item);
}
inline bool add_value_to_list(Item *value)
{
@@ -676,11 +741,11 @@ inline bool add_value_to_list(Item *value)
}
inline bool add_order_to_list(Item *item,bool asc)
{
- return add_to_list(current_lex->order_list,item,asc);
+ return add_to_list(current_lex->select->order_list,item,asc);
}
inline bool add_group_to_list(Item *item,bool asc)
{
- return add_to_list(current_lex->group_list,item,asc);
+ return add_to_list(current_lex->select->group_list,item,asc);
}
inline void mark_as_null_row(TABLE *table)
{
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 09c05a6463f..187a4732aa0 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -21,15 +21,13 @@
#include "sql_acl.h"
#include "slave.h"
#include "sql_repl.h"
+#include "repl_failsafe.h"
#include "stacktrace.h"
#ifdef HAVE_BERKELEY_DB
#include "ha_berkeley.h"
#endif
#ifdef HAVE_INNOBASE_DB
-#include "ha_innobase.h"
-#endif
-#ifdef HAVE_GEMINI_DB
-#include "ha_gemini.h"
+#include "ha_innodb.h"
#endif
#include "ha_myisam.h"
#include <nisam.h>
@@ -40,10 +38,16 @@
#define ONE_THREAD
#endif
+/* do stack traces are only supported on linux intel */
+#if defined(__linux__) && defined(__i386__) && defined(USE_PSTACK)
+#define HAVE_STACK_TRACE_ON_SEGV
+#include "../pstack/pstack.h"
+char pstack_file_name[80];
+#endif /* __linux__ */
+
#if defined(HAVE_DEC_3_2_THREADS) || defined(SIGNALS_DONT_BREAK_READ)
#define HAVE_CLOSE_SERVER_SOCK 1
-void close_server_sock();
-#endif
+#endif
extern "C" { // Because of SCO 3.2V4.2
#include <errno.h>
@@ -77,9 +81,7 @@ extern "C" { // Because of SCO 3.2V4.2
#include <sys/select.h>
#endif
#include <sys/utsname.h>
-#else
-#include <windows.h>
-#endif // __WIN__
+#endif /* __WIN__ */
#ifdef HAVE_LIBWRAP
#include <tcpd.h>
@@ -112,8 +114,13 @@ typedef fp_except fp_except_t;
inline void reset_floating_point_exceptions()
{
/* Don't fall for overflow, underflow,divide-by-zero or loss of precision */
- fpsetmask(~(FP_X_INV | FP_X_DNML | FP_X_OFL | FP_X_UFL |
- FP_X_DZ | FP_X_IMP));
+#if defined(__i386__)
+ fpsetmask(~(FP_X_INV | FP_X_DNML | FP_X_OFL | FP_X_UFL | FP_X_DZ |
+ FP_X_IMP));
+#else
+ fpsetmask(~(FP_X_INV | FP_X_OFL | FP_X_UFL | FP_X_DZ |
+ FP_X_IMP));
+#endif
}
#else
#define reset_floating_point_exceptions()
@@ -181,17 +188,12 @@ SHOW_COMP_OPTION have_berkeley_db=SHOW_OPTION_YES;
#else
SHOW_COMP_OPTION have_berkeley_db=SHOW_OPTION_NO;
#endif
-#ifdef HAVE_GEMINI_DB
-SHOW_COMP_OPTION have_gemini=SHOW_OPTION_YES;
-#else
-SHOW_COMP_OPTION have_gemini=SHOW_OPTION_NO;
-#endif
#ifdef HAVE_INNOBASE_DB
SHOW_COMP_OPTION have_innodb=SHOW_OPTION_YES;
#else
SHOW_COMP_OPTION have_innodb=SHOW_OPTION_NO;
#endif
-#ifndef NO_ISAM
+#ifdef HAVE_ISAM
SHOW_COMP_OPTION have_isam=SHOW_OPTION_YES;
#else
SHOW_COMP_OPTION have_isam=SHOW_OPTION_NO;
@@ -202,16 +204,19 @@ SHOW_COMP_OPTION have_raid=SHOW_OPTION_YES;
SHOW_COMP_OPTION have_raid=SHOW_OPTION_NO;
#endif
#ifdef HAVE_OPENSSL
-SHOW_COMP_OPTION have_ssl=SHOW_OPTION_YES;
+SHOW_COMP_OPTION have_openssl=SHOW_OPTION_YES;
#else
-SHOW_COMP_OPTION have_ssl=SHOW_OPTION_NO;
+SHOW_COMP_OPTION have_openssl=SHOW_OPTION_NO;
#endif
+SHOW_COMP_OPTION have_symlink=SHOW_OPTION_YES;
-static bool opt_skip_slave_start = 0; // if set, slave is not autostarted
+bool opt_skip_slave_start = 0; // If set, slave is not autostarted
+static bool opt_do_pstack = 0;
static ulong opt_specialflag=SPECIAL_ENGLISH;
-static my_socket unix_sock= INVALID_SOCKET,ip_sock= INVALID_SOCKET;
static ulong back_log,connect_timeout,concurrency;
+static ulong opt_myisam_block_size;
+static my_socket unix_sock= INVALID_SOCKET,ip_sock= INVALID_SOCKET;
static my_string opt_logname=0,opt_update_logname=0,
opt_binlog_index_name = 0,opt_slow_logname=0;
static char mysql_home[FN_REFLEN],pidfile_name[FN_REFLEN];
@@ -221,32 +226,30 @@ static bool opt_log,opt_update_log,opt_bin_log,opt_slow_log,opt_noacl,
opt_myisam_log=0,
opt_large_files=sizeof(my_off_t) > 4;
bool opt_sql_bin_update = 0, opt_log_slave_updates = 0, opt_safe_show_db=0,
- opt_safe_user_create=0;
+ opt_show_slave_auth_info = 0, opt_old_rpl_compat = 0,
+ opt_safe_user_create = 0, opt_no_mix_types = 0;
+volatile bool mqh_used = 0;
FILE *bootstrap_file=0;
int segfaulted = 0; // ensure we do not enter SIGSEGV handler twice
-extern MASTER_INFO glob_mi;
-extern int init_master_info(MASTER_INFO* mi);
-// if sql_bin_update is true, SQL_LOG_UPDATE and SQL_LOG_BIN are kept in sync,
-// and are treated as aliases for each other
+/*
+ If sql_bin_update is true, SQL_LOG_UPDATE and SQL_LOG_BIN are kept in sync,
+ and are treated as aliases for each other
+*/
static bool kill_in_progress=FALSE;
static struct rand_struct sql_rand;
static int cleanup_done;
static char **defaults_argv,time_zone[30];
static const char *default_table_type_name;
-static char glob_hostname[FN_REFLEN];
+char glob_hostname[FN_REFLEN];
+#include "sslopt-vars.h"
#ifdef HAVE_OPENSSL
-static bool opt_use_ssl = FALSE;
-static char *opt_ssl_key = 0;
-static char *opt_ssl_cert = 0;
-static char *opt_ssl_ca = 0;
-static char *opt_ssl_capath = 0;
-static VioSSLAcceptorFd* ssl_acceptor_fd = 0;
+char *des_key_file = 0;
+struct st_VioSSLAcceptorFd * ssl_acceptor_fd = 0;
#endif /* HAVE_OPENSSL */
-
I_List <i_string_pair> replicate_rewrite_db;
I_List<i_string> replicate_do_db, replicate_ignore_db;
// allow the user to tell us which db to replicate and which to ignore
@@ -257,9 +260,9 @@ uint32 server_id = 0;
bool server_id_supplied = 0;
uint mysql_port;
-uint test_flags, select_errors=0, dropping_tables=0,ha_open_options=0;
+uint test_flags = 0, select_errors=0, dropping_tables=0,ha_open_options=0;
uint volatile thread_count=0, thread_running=0, kill_cached_threads=0,
- wake_thread=0, global_read_lock=0;
+ wake_thread=0;
ulong thd_startup_options=(OPTION_UPDATE_LOG | OPTION_AUTO_IS_NULL |
OPTION_BIN_LOG | OPTION_QUOTE_SHOW_CREATE );
uint protocol_version=PROTOCOL_VERSION;
@@ -273,14 +276,21 @@ ulong keybuff_size,sortbuff_size,max_item_sort_length,table_cache_size,
ulong com_stat[(uint) SQLCOM_END], com_other;
ulong slave_net_timeout;
ulong thread_cache_size=0, binlog_cache_size=0, max_binlog_cache_size=0;
+ulong query_cache_size=0, query_cache_limit=0, query_cache_startup_type=1;
volatile ulong cached_thread_count=0;
// replication parameters, if master_host is not NULL, we are a slave
my_string master_user = (char*) "test", master_password = 0, master_host=0,
- master_info_file = (char*) "master.info";
+ master_info_file = (char*) "master.info",
+ relay_log_info_file = (char*) "relay-log.info",
+ master_ssl_key=0, master_ssl_cert=0;
+my_string report_user = 0, report_password = 0, report_host=0;
+
const char *localhost=LOCAL_HOST;
const char *delayed_user="DELAYED";
uint master_port = MYSQL_PORT, master_connect_retry = 60;
+uint report_port = MYSQL_PORT;
+bool master_ssl = 0;
ulong max_tmp_tables,max_heap_table_size,master_retry_count=0;
ulong bytes_sent = 0L, bytes_received = 0L;
@@ -308,11 +318,20 @@ ulong slow_launch_threads = 0;
ulong myisam_max_sort_file_size, myisam_max_extra_sort_file_size;
char mysql_real_data_home[FN_REFLEN],
- mysql_data_home[2],language[LIBLEN],reg_ext[FN_EXTLEN],
+ language[LIBLEN],reg_ext[FN_EXTLEN],
default_charset[LIBLEN],mysql_charsets_dir[FN_REFLEN], *charsets_list,
blob_newline,f_fyllchar,max_sort_char,*mysqld_user,*mysqld_chroot,
*opt_init_file;
+#ifndef EMBEDDED_LIBRARY
+char mysql_data_home_buff[2], *mysql_data_home=mysql_data_home_buff;
+bool mysql_embedded=0;
+#else
+char *mysql_data_home=mysql_real_data_home;
+bool mysql_embedded=1;
+#endif
+
char *opt_bin_logname = 0; // this one needs to be seen in sql_parse.cc
+char *opt_relay_logname = 0, *opt_relaylog_index_name=0;
char server_version[SERVER_VERSION_LENGTH]=MYSQL_SERVER_VERSION;
const char *first_keyword="first";
const char **errmesg; /* Error messages */
@@ -321,10 +340,9 @@ const char *sql_mode_str="OFF";
const char *default_tx_isolation_name;
enum_tx_isolation default_tx_isolation=ISO_READ_COMMITTED;
-#ifdef HAVE_GEMINI_DB
-const char *gemini_recovery_options_str="FULL";
-#endif
-my_string mysql_unix_port=NULL,mysql_tmpdir=NULL;
+uint rpl_recovery_rank=0;
+
+my_string mysql_unix_port=NULL, mysql_tmpdir=NULL, allocated_mysql_tmpdir=NULL;
ulong my_bind_addr; /* the address we bind to */
DATE_FORMAT dayord;
double log_10[32]; /* 10 potences */
@@ -334,8 +352,8 @@ time_t start_time;
ulong opt_sql_mode = 0L;
const char *sql_mode_names[] =
{ "REAL_AS_FLOAT", "PIPES_AS_CONCAT", "ANSI_QUOTES", "IGNORE_SPACE",
- "SERIALIZE","ONLY_FULL_GROUP_BY", NullS };
-TYPELIB sql_mode_typelib= {array_elements(sql_mode_names),"",
+ "SERIALIZE","ONLY_FULL_GROUP_BY", "NO_UNSIGNED_SUBTRACTION",NullS };
+TYPELIB sql_mode_typelib= {array_elements(sql_mode_names)-1,"",
sql_mode_names};
MY_BITMAP temp_pool;
@@ -349,8 +367,10 @@ pthread_mutex_t LOCK_mysql_create_db, LOCK_Acl, LOCK_open, LOCK_thread_count,
LOCK_error_log,
LOCK_delayed_insert, LOCK_delayed_status, LOCK_delayed_create,
LOCK_crypt, LOCK_bytes_sent, LOCK_bytes_received,
- LOCK_binlog_update, LOCK_slave, LOCK_server_id,
- LOCK_user_conn;
+ LOCK_server_id,
+ LOCK_user_conn, LOCK_slave_list, LOCK_active_mi;
+
+Query_cache query_cache;
pthread_cond_t COND_refresh,COND_thread_count,COND_binlog_update,
COND_slave_stopped, COND_slave_start;
@@ -362,10 +382,12 @@ enum db_type default_table_type=DB_TYPE_MYISAM;
#ifdef __WIN__
#undef getpid
#include <process.h>
+#if !defined(EMBEDDED_LIBRARY)
HANDLE hEventShutdown;
#include "nt_servc.h"
static NTService Service; // Service object for WinNT
#endif
+#endif
#ifdef OS2
pthread_cond_t eventShutdown;
@@ -380,6 +402,7 @@ static void fix_paths(void);
static pthread_handler_decl(handle_connections_sockets,arg);
static pthread_handler_decl(kill_server_thread,arg);
static int bootstrap(FILE *file);
+static void close_server_sock();
static bool read_init_file(char *file_name);
#ifdef __NT__
static pthread_handler_decl(handle_connections_namedpipes,arg);
@@ -429,15 +452,7 @@ static void close_connections(void)
if (pthread_kill(select_thread,THR_CLIENT_ALARM))
break; // allready dead
#endif
-#ifdef HAVE_TIMESPEC_TS_SEC
- abstime.ts_sec=time(NULL)+2; // Bsd 2.1
- abstime.ts_nsec=0;
-#else
- struct timeval tv;
- gettimeofday(&tv,0);
- abstime.tv_sec=tv.tv_sec+2;
- abstime.tv_nsec=tv.tv_usec*1000;
-#endif
+ set_timespec(abstime, 2);
for (uint tmp=0 ; tmp < 10 ; tmp++)
{
error=pthread_cond_timedwait(&COND_thread_count,&LOCK_thread_count,
@@ -449,9 +464,7 @@ static void close_connections(void)
if (error != 0 && !count++)
sql_print_error("Got error %d from pthread_cond_timedwait",error);
#endif
-#if defined(HAVE_DEC_3_2_THREADS) || defined(SIGNALS_DONT_BREAK_READ)
close_server_sock();
-#endif
}
(void) pthread_mutex_unlock(&LOCK_thread_count);
#endif /* __WIN__ */
@@ -474,7 +487,6 @@ static void close_connections(void)
HANDLE hTempPipe = &hPipe;
DBUG_PRINT( "quit", ("Closing named pipes") );
hPipe = INVALID_HANDLE_VALUE;
- CancelIo( hTempPipe );
DisconnectNamedPipe( hTempPipe );
CloseHandle( hTempPipe );
}
@@ -524,7 +536,7 @@ static void close_connections(void)
/* Force remaining threads to die by closing the connection to the client */
- (void) my_net_init(&net, (Vio*) 0);
+ (void) my_net_init(&net, (st_vio*) 0);
for (;;)
{
DBUG_PRINT("quit",("Locking LOCK_thread_count"));
@@ -565,59 +577,68 @@ static void close_connections(void)
DBUG_VOID_RETURN;
}
-#ifdef HAVE_CLOSE_SERVER_SOCK
-void close_server_sock()
+static void close_server_sock()
{
+#ifdef HAVE_CLOSE_SERVER_SOCK
DBUG_ENTER("close_server_sock");
- if (ip_sock != INVALID_SOCKET)
+ my_socket tmp_sock;
+ tmp_sock=ip_sock;
+ if (tmp_sock != INVALID_SOCKET)
{
- DBUG_PRINT("info",("closing TCP/IP socket"));
- VOID(shutdown(ip_sock,2));
- VOID(closesocket(ip_sock));
ip_sock=INVALID_SOCKET;
+ DBUG_PRINT("info",("closing TCP/IP socket"));
+ VOID(shutdown(tmp_sock,2));
+ VOID(closesocket(tmp_sock));
}
- if (unix_sock != INVALID_SOCKET)
+ tmp_sock=unix_sock;
+ if (tmp_sock != INVALID_SOCKET)
{
+ unix_sock=INVALID_SOCKET;
DBUG_PRINT("info",("closing Unix socket"));
- VOID(shutdown(unix_sock,2));
- VOID(closesocket(unix_sock));
+ VOID(shutdown(tmp_sock,2));
+ VOID(closesocket(tmp_sock));
VOID(unlink(mysql_unix_port));
- unix_sock=INVALID_SOCKET;
}
DBUG_VOID_RETURN;
-}
#endif
+}
void kill_mysql(void)
{
DBUG_ENTER("kill_mysql");
+
#ifdef SIGNALS_DONT_BREAK_READ
close_server_sock(); /* force accept to wake up */
-#endif
+#endif
+
#if defined(__WIN__)
+#if !defined(EMBEDDED_LIBRARY)
{
if (!SetEvent(hEventShutdown))
{
DBUG_PRINT("error",("Got error: %ld from SetEvent",GetLastError()));
}
- // or:
- // HANDLE hEvent=OpenEvent(0, FALSE, "MySqlShutdown");
- // SetEvent(hEventShutdown);
- // CloseHandle(hEvent);
+ /*
+ or:
+ HANDLE hEvent=OpenEvent(0, FALSE, "MySqlShutdown");
+ SetEvent(hEventShutdown);
+ CloseHandle(hEvent);
+ */
}
+#endif
#elif defined(OS2)
pthread_cond_signal( &eventShutdown); // post semaphore
#elif defined(HAVE_PTHREAD_KILL)
- if (pthread_kill(signal_thread,MYSQL_KILL_SIGNAL))// End everything nicely
+ if (pthread_kill(signal_thread,SIGTERM)) /* End everything nicely */
{
DBUG_PRINT("error",("Got error %d from pthread_kill",errno)); /* purecov: inspected */
}
#elif !defined(SIGNALS_DONT_BREAK_READ)
- kill(current_pid,MYSQL_KILL_SIGNAL);
+ kill(current_pid,SIGTERM);
#endif
DBUG_PRINT("quit",("After pthread_kill"));
shutdown_in_progress=1; // Safety if kill didn't work
-#ifdef SIGNALS_DONT_BREAK_READ
+#ifdef SIGNALS_DONT_BREAK_READ
if (!abort_loop)
{
pthread_t tmp;
@@ -647,8 +668,7 @@ static void __cdecl kill_server(int sig_ptr)
int sig=(int) (long) sig_ptr; // This is passed a int
DBUG_ENTER("kill_server");
- // if there is a signal during the kill in progress, we do not need
- // another one
+ // if there is a signal during the kill in progress, ignore the other
if (kill_in_progress) // Safety
RETURN_FROM_KILL_SERVER;
kill_in_progress=TRUE;
@@ -673,7 +693,7 @@ static void __cdecl kill_server(int sig_ptr)
#ifdef USE_ONE_SIGNAL_HAND
-pthread_handler_decl(kill_server_thread,arg __attribute__((unused)))
+static pthread_handler_decl(kill_server_thread,arg __attribute__((unused)))
{
my_thread_init(); // Initialize new thread
kill_server(0);
@@ -682,6 +702,11 @@ pthread_handler_decl(kill_server_thread,arg __attribute__((unused)))
}
#endif
+#if defined(__amiga__)
+#undef sigset
+#define sigset signal
+#endif
+
static sig_handler print_signal_warning(int sig)
{
if (opt_warnings)
@@ -700,15 +725,19 @@ static sig_handler print_signal_warning(int sig)
void unireg_end(int signal_number __attribute__((unused)))
{
clean_up();
+ my_thread_end();
pthread_exit(0); // Exit is in main thread
}
void unireg_abort(int exit_code)
{
+ DBUG_ENTER("unireg_abort");
if (exit_code)
sql_print_error("Aborting\n");
clean_up(); /* purecov: inspected */
+ DBUG_PRINT("quit",("done with cleanup in unireg_abort"));
+ my_thread_end();
exit(exit_code); /* purecov: inspected */
}
@@ -722,7 +751,7 @@ void clean_up(bool print_message)
bitmap_free(&slave_error_mask);
acl_free(1);
grant_free();
- sql_cache_free();
+ query_cache.destroy();
table_cache_free();
hostname_cache_free();
item_user_lock_free();
@@ -736,27 +765,40 @@ void clean_up(bool print_message)
#ifdef USE_RAID
end_raid();
#endif
+#ifdef HAVE_OPENSSL
+ my_free(opt_ssl_key,MYF(MY_ALLOW_ZERO_PTR));
+ my_free(opt_ssl_cert,MYF(MY_ALLOW_ZERO_PTR));
+ my_free(opt_ssl_ca,MYF(MY_ALLOW_ZERO_PTR));
+ my_free(opt_ssl_capath,MYF(MY_ALLOW_ZERO_PTR));
+ my_free(opt_ssl_cipher,MYF(MY_ALLOW_ZERO_PTR));
+ opt_ssl_key=opt_ssl_cert=opt_ssl_ca=opt_ssl_capath=0;
+#endif /* HAVE_OPENSSL */
free_defaults(defaults_argv);
my_free(charsets_list, MYF(MY_ALLOW_ZERO_PTR));
- my_free(mysql_tmpdir,MYF(0));
+ my_free(allocated_mysql_tmpdir,MYF(MY_ALLOW_ZERO_PTR));
+ my_free(slave_load_tmpdir,MYF(MY_ALLOW_ZERO_PTR));
x_free(opt_bin_logname);
+ x_free(opt_relay_logname);
bitmap_free(&temp_pool);
free_max_user_conn();
-#ifndef __WIN__
+ end_slave_list();
+
+#if !defined(__WIN__) && !defined(EMBEDDED_LIBRARY)
if (!opt_bootstrap)
(void) my_delete(pidfile_name,MYF(0)); // This may not always exist
#endif
- if (print_message)
+ if (print_message && errmesg)
sql_print_error(ER(ER_SHUTDOWN_COMPLETE),my_progname);
x_free((gptr) my_errmsg[ERRMAPP]); /* Free messages */
- my_thread_end();
-
+ DBUG_PRINT("quit", ("Error messages freed"));
/* Tell main we are ready */
(void) pthread_mutex_lock(&LOCK_thread_count);
+ DBUG_PRINT("quit", ("got thread count lock"));
ready_to_exit=1;
/* do the broadcast inside the lock to ensure that my_end() is not called */
(void) pthread_cond_broadcast(&COND_thread_count);
(void) pthread_mutex_unlock(&LOCK_thread_count);
+ DBUG_PRINT("quit", ("done with cleanup"));
} /* clean_up */
@@ -816,20 +858,33 @@ static void set_user(const char *user)
if (!strcmp(user,"root"))
return; // Avoid problem with dynamic libraries
+ uid_t uid;
if (!(ent = getpwnam(user)))
{
- fprintf(stderr,"Fatal error: Can't change to run as user '%s' ; Please check that the user exists!\n",user);
- unireg_abort(1);
+ // allow a numeric uid to be used
+ const char *pos;
+ for (pos=user; isdigit(*pos); pos++) ;
+ if (*pos) // Not numeric id
+ {
+ fprintf(stderr,"Fatal error: Can't change to run as user '%s' ; Please check that the user exists!\n",user);
+ unireg_abort(1);
+ }
+ uid=atoi(user); // Use numberic uid
}
+ else
+ {
#ifdef HAVE_INITGROUPS
- initgroups((char*) user,ent->pw_gid);
+ initgroups((char*) user,ent->pw_gid);
#endif
- if (setgid(ent->pw_gid) == -1)
- {
- sql_perror("setgid");
- unireg_abort(1);
+ if (setgid(ent->pw_gid) == -1)
+ {
+ sql_perror("setgid");
+ unireg_abort(1);
+ }
+ uid=ent->pw_uid;
}
- if (setuid(ent->pw_uid) == -1)
+
+ if (setuid(uid) == -1)
{
sql_perror("setuid");
unireg_abort(1);
@@ -1008,7 +1063,7 @@ void yyerror(const char *s)
void close_connection(NET *net,uint errcode,bool lock)
{
- Vio* vio;
+ st_vio* vio;
DBUG_ENTER("close_connection");
DBUG_PRINT("enter",("fd: %s error: '%s'",
net->vio? vio_description(net->vio):"(not connected)",
@@ -1073,6 +1128,8 @@ void end_thread(THD *thd, bool put_in_cache)
DBUG_PRINT("info", ("sending a broadcast"))
/* Tell main we are ready */
+ // TODO: explain why we broadcast outside of the lock or
+ // fix the bug - Sasha
(void) pthread_mutex_unlock(&LOCK_thread_count);
(void) pthread_cond_broadcast(&COND_thread_count);
DBUG_PRINT("info", ("unlocked thread_count mutex"))
@@ -1086,20 +1143,6 @@ void end_thread(THD *thd, bool put_in_cache)
DBUG_VOID_RETURN;
}
-#ifdef SIGNALS_DONT_BREAK_READ
-inline void kill_broken_server()
-{
- /* hack to get around signals ignored in syscalls for problem OS's */
- if (unix_sock == INVALID_SOCKET || ip_sock ==INVALID_SOCKET)
- {
- select_thread_in_use = 0;
- kill_server((void*)MYSQL_KILL_SIGNAL); /* never returns */
- }
-}
-#define MAYBE_BROKEN_SYSCALL kill_broken_server();
-#else
-#define MAYBE_BROKEN_SYSCALL
-#endif
/* Start a cached thread. LOCK_thread_count is locked on entry */
@@ -1167,19 +1210,6 @@ static void start_signal_handler(void)
}
#elif defined(__EMX__)
-static void init_signals(void)
-{
- signal(SIGQUIT, sig_kill);
- signal(SIGKILL, sig_kill);
- signal(SIGTERM, sig_kill);
- signal(SIGINT, sig_kill);
- signal(SIGHUP, sig_reload); // Flush everything
- signal(SIGALRM, SIG_IGN);
- signal(SIGBREAK,SIG_IGN);
- signal_thread = pthread_self();
-}
-
-
static void sig_reload(int signo)
{
reload_acl_and_cache((THD*) 0,REFRESH_LOG, (TABLE_LIST*) 0); // Flush everything
@@ -1196,10 +1226,22 @@ static void sig_kill(int signo)
signal(signo, SIG_ACK);
}
+static void init_signals(void)
+{
+ signal(SIGQUIT, sig_kill);
+ signal(SIGKILL, sig_kill);
+ signal(SIGTERM, sig_kill);
+ signal(SIGINT, sig_kill);
+ signal(SIGHUP, sig_reload); // Flush everything
+ signal(SIGALRM, SIG_IGN);
+ signal(SIGBREAK,SIG_IGN);
+ signal_thread = pthread_self();
+}
static void start_signal_handler(void)
{
}
+
#else /* if ! __WIN__ && ! __EMX__ */
#ifdef HAVE_LINUXTHREADS
@@ -1210,10 +1252,10 @@ static sig_handler handle_segfault(int sig)
{
THD *thd=current_thd;
/*
- Strictly speaking, we should need a mutex here
+ Strictly speaking, one needs a mutex here
but since we have got SIGSEGV already, things are a mess
so not having the mutex is not as bad as possibly using a buggy
- mutex - so we keep things simple.
+ mutex - so we keep things simple
*/
if (segfaulted)
{
@@ -1225,13 +1267,13 @@ static sig_handler handle_segfault(int sig)
fprintf(stderr,"\
mysqld got signal %d;\n\
This could be because you hit a bug. It is also possible that this binary\n\
-or one of the libraries it was linked agaist is corrupt, improperly built,\n\
+or one of the libraries it was linked against is corrupt, improperly built,\n\
or misconfigured. This error can also be caused by malfunctioning hardware.\n",
sig);
fprintf(stderr, "\
We will try our best to scrape up some info that will hopefully help diagnose\n\
the problem, but since we have already crashed, something is definitely wrong\n\
-and this may fail\n\n");
+and this may fail.\n\n");
fprintf(stderr, "key_buffer_size=%ld\n", keybuff_size);
fprintf(stderr, "record_buffer=%ld\n", my_default_record_cache_size);
fprintf(stderr, "sort_buffer=%ld\n", sortbuff_size);
@@ -1242,15 +1284,15 @@ and this may fail\n\n");
key_buffer_size + (record_buffer + sort_buffer)*max_connections = %ld K\n\
bytes of memory\n", (keybuff_size + (my_default_record_cache_size +
sortbuff_size) * max_connections)/ 1024);
- fprintf(stderr, "Hope that's ok, if not, decrease some variables in the equation\n\n");
+ fprintf(stderr, "Hope that's ok; if not, decrease some variables in the equation.\n\n");
#if defined(HAVE_LINUXTHREADS)
if (sizeof(char*) == 4 && thread_count > UNSAFE_DEFAULT_LINUX_THREADS)
{
fprintf(stderr, "\
You seem to be running 32-bit Linux and have %d concurrent connections.\n\
-If you have not changed STACK_SIZE in LinuxThreads and build the binary \n\
-yourself, LinuxThreads is quite likely to steal a part of global heap for\n\
+If you have not changed STACK_SIZE in LinuxThreads and built the binary \n\
+yourself, LinuxThreads is quite likely to steal a part of the global heap for\n\
the thread stack. Please read http://www.mysql.com/doc/L/i/Linux.html\n\n",
thread_count);
}
@@ -1259,9 +1301,7 @@ the thread stack. Please read http://www.mysql.com/doc/L/i/Linux.html\n\n",
#ifdef HAVE_STACKTRACE
if(!(test_flags & TEST_NO_STACKTRACE))
{
-#ifdef HAVE_GEMINI_DB
- utrace();
-#endif
+ fprintf(stderr,"thd=%p\n",thd);
print_stacktrace(thd ? (gptr) thd->thread_stack : (gptr) 0,
thread_stack);
}
@@ -1274,12 +1314,12 @@ Some pointers may be invalid and cause the dump to abort...\n");
fprintf(stderr, "\n\
Successfully dumped variables, if you ran with --log, take a look at the\n\
details of what thread %ld did to cause the crash. In some cases of really\n\
-bad corruption, the values shown above may be invalid\n\n",
+bad corruption, the values shown above may be invalid.\n\n",
thd->thread_id);
}
fprintf(stderr, "\
The manual page at http://www.mysql.com/doc/C/r/Crashing.html contains\n\
-information that should help you find out what is causing the crash\n");
+information that should help you find out what is causing the crash.\n");
fflush(stderr);
#endif /* HAVE_STACKTRACE */
@@ -1311,7 +1351,11 @@ static void init_signals(void)
sigprocmask(SIG_SETMASK,&sa.sa_mask,NULL);
init_stacktrace();
+#if defined(__amiga__)
+ sa.sa_handler=(void(*)())handle_segfault;
+#else
sa.sa_handler=handle_segfault;
+#endif
sigaction(SIGSEGV, &sa, NULL);
#ifdef SIGBUS
sigaction(SIGBUS, &sa, NULL);
@@ -1330,8 +1374,8 @@ static void init_signals(void)
sigaddset(&set,SIGQUIT);
sigaddset(&set,SIGTERM);
sigaddset(&set,SIGHUP);
- sigset(SIGTERM,print_signal_warning); // If it's blocked by parent
- signal(SIGHUP,print_signal_warning); // If it's blocked by parent
+ signal(SIGTERM,SIG_DFL); // If it's blocked by parent
+ signal(SIGHUP,SIG_DFL); // If it's blocked by parent
#ifdef SIGTSTP
sigaddset(&set,SIGTSTP);
#endif
@@ -1415,6 +1459,13 @@ static void *signal_hand(void *arg __attribute__((unused)))
(void) my_close(pidFile,MYF(0));
}
}
+#ifdef HAVE_STACK_TRACE_ON_SEGV
+ if (opt_do_pstack)
+ {
+ sprintf(pstack_file_name,"mysqld-%lu-%%d-%%d.backtrace", (ulong)getpid());
+ pstack_install_segv_action(pstack_file_name);
+ }
+#endif /* HAVE_STACK_TRACE_ON_SEGV */
// signal to start_signal_handler that we are ready
(void) pthread_mutex_lock(&LOCK_thread_count);
@@ -1426,7 +1477,7 @@ static void *signal_hand(void *arg __attribute__((unused)))
int error; // Used when debugging
if (shutdown_in_progress && !abort_loop)
{
- sig= MYSQL_KILL_SIGNAL;
+ sig=SIGTERM;
error=0;
}
else
@@ -1449,15 +1500,18 @@ static void *signal_hand(void *arg __attribute__((unused)))
if (!(opt_specialflag & SPECIAL_NO_PRIOR))
my_pthread_attr_setprio(&connection_attrib,INTERRUPT_PRIOR);
if (pthread_create(&tmp,&connection_attrib, kill_server_thread,
- (void*) 0))
+ (void*) sig))
sql_print_error("Error: Can't create thread to kill server");
#else
- kill_server((void*) sig); // MIT THREAD has a alarm thread
+ kill_server((void*) sig); // MIT THREAD has a alarm thread
#endif
}
break;
case SIGHUP:
- reload_acl_and_cache((THD*) 0,REFRESH_LOG,
+ reload_acl_and_cache((THD*) 0,
+ (REFRESH_LOG | REFRESH_TABLES | REFRESH_FAST |
+ REFRESH_STATUS | REFRESH_GRANT | REFRESH_THREADS |
+ REFRESH_HOSTS),
(TABLE_LIST*) 0); // Flush logs
mysql_print_status((THD*) 0); // Send debug some info
break;
@@ -1527,8 +1581,9 @@ pthread_handler_decl(handle_shutdown,arg)
/* this call should create the message queue for this thread */
PeekMessage(&msg, NULL, 1, 65534,PM_NOREMOVE);
-
+#if !defined(EMBEDDED_LIBRARY)
if (WaitForSingleObject(hEventShutdown,INFINITE)==WAIT_OBJECT_0)
+#endif
kill_server(MYSQL_KILL_SIGNAL);
return 0;
}
@@ -1556,8 +1611,10 @@ pthread_handler_decl(handle_shutdown,arg)
// close semaphore and kill server
pthread_cond_destroy( &eventShutdown);
- // exit main loop on main thread, so kill will be done from
- // main thread (this is thread 2)
+ /*
+ Exit main loop on main thread, so kill will be done from
+ main thread (this is thread 2)
+ */
abort_loop = 1;
// unblock select()
@@ -1574,15 +1631,17 @@ const char *load_default_groups[]= { "mysqld","server",0 };
char *libwrapName=NULL;
#endif
-static void open_log(MYSQL_LOG *log, const char *hostname,
+void open_log(MYSQL_LOG *log, const char *hostname,
const char *opt_name, const char *extension,
- enum_log_type type)
+ enum_log_type type, bool read_append,
+ bool no_auto_events)
{
char tmp[FN_REFLEN];
if (!opt_name || !opt_name[0])
{
- /* TODO: The following should be using fn_format(); We just need to
- first change fn_format() to cut the file name if it's too long.
+ /*
+ TODO: The following should be using fn_format(); We just need to
+ first change fn_format() to cut the file name if it's too long.
*/
strmake(tmp,hostname,FN_REFLEN-5);
strmov(strcend(tmp,'.'),extension);
@@ -1599,7 +1658,8 @@ static void open_log(MYSQL_LOG *log, const char *hostname,
opt_name=tmp;
}
}
- log->open(opt_name,type);
+ log->open(opt_name,type,0,(read_append) ? SEQ_READ_APPEND : WRITE_CACHE,
+ no_auto_events);
}
@@ -1695,33 +1755,34 @@ int main(int argc, char **argv)
(void) pthread_mutex_init(&LOCK_bytes_sent,MY_MUTEX_INIT_FAST);
(void) pthread_mutex_init(&LOCK_bytes_received,MY_MUTEX_INIT_FAST);
(void) pthread_mutex_init(&LOCK_timezone,MY_MUTEX_INIT_FAST);
- (void) pthread_mutex_init(&LOCK_binlog_update, MY_MUTEX_INIT_FAST); // QQ NOT USED
- (void) pthread_mutex_init(&LOCK_slave, MY_MUTEX_INIT_FAST);
(void) pthread_mutex_init(&LOCK_server_id, MY_MUTEX_INIT_FAST);
(void) pthread_mutex_init(&LOCK_user_conn, MY_MUTEX_INIT_FAST);
+ (void) pthread_mutex_init(&LOCK_rpl_status, MY_MUTEX_INIT_FAST);
+ (void) pthread_mutex_init(&LOCK_active_mi, MY_MUTEX_INIT_FAST);
(void) pthread_cond_init(&COND_thread_count,NULL);
(void) pthread_cond_init(&COND_refresh,NULL);
(void) pthread_cond_init(&COND_thread_cache,NULL);
(void) pthread_cond_init(&COND_flush_thread_cache,NULL);
(void) pthread_cond_init(&COND_manager,NULL);
- (void) pthread_cond_init(&COND_binlog_update, NULL);
- (void) pthread_cond_init(&COND_slave_stopped, NULL);
- (void) pthread_cond_init(&COND_slave_start, NULL);
+ (void) pthread_cond_init(&COND_rpl_status, NULL);
init_signals();
if (set_default_charset_by_name(default_charset, MYF(MY_WME)))
- unireg_abort(1);
+ exit( 1 );
charsets_list = list_charsets(MYF(MY_COMPILED_SETS|MY_CONFIG_SETS));
#ifdef HAVE_OPENSSL
if (opt_use_ssl)
{
- ssl_acceptor_fd = VioSSLAcceptorFd_new(opt_ssl_key, opt_ssl_cert,
- opt_ssl_ca, opt_ssl_capath);
+ ssl_acceptor_fd = new_VioSSLAcceptorFd(opt_ssl_key, opt_ssl_cert,
+ opt_ssl_ca, opt_ssl_capath, opt_ssl_cipher);
+ DBUG_PRINT("info",("ssl_acceptor_fd: %p",ssl_acceptor_fd));
if (!ssl_acceptor_fd)
- opt_use_ssl=0;
- /* having ssl_acceptor_fd!=0 signals the use of SSL */
+ opt_use_ssl = 0;
+ /* having ssl_acceptor_fd != 0 signals the use of SSL */
}
+ if (des_key_file)
+ load_des_key_file(des_key_file);
#endif /* HAVE_OPENSSL */
#ifdef HAVE_LIBWRAP
@@ -1742,7 +1803,7 @@ int main(int argc, char **argv)
pthread_attr_setscope(&connection_attrib, PTHREAD_SCOPE_SYSTEM);
#if defined( SET_RLIMIT_NOFILE) || defined( OS2)
- /* connections and databases neads lots of files */
+ /* connections and databases needs lots of files */
{
uint wanted_files=10+(uint) max(max_connections*5,
max_connections+table_cache_size*2);
@@ -1786,14 +1847,12 @@ int main(int argc, char **argv)
server_init();
table_cache_init();
hostname_cache_init();
- sql_cache_init();
+ query_cache.result_size_limit(query_cache_limit);
+ query_cache.resize(query_cache_size);
randominit(&sql_rand,(ulong) start_time,(ulong) start_time/2);
reset_floating_point_exceptions();
init_thr_lock();
-
- /* Fix varibles that are base 1024*1024 */
- myisam_max_temp_length= (my_off_t) min(((ulonglong) myisam_max_sort_file_size)*1024*1024, (ulonglong) MAX_FILE_SIZE);
- myisam_max_extra_temp_length= (my_off_t) min(((ulonglong) myisam_max_extra_sort_file_size)*1024*1024, (ulonglong) MAX_FILE_SIZE);
+ init_slave_list();
/* Setup log files */
if (opt_log)
@@ -1804,19 +1863,9 @@ int main(int argc, char **argv)
LOG_NEW);
using_update_log=1;
}
-
- //make sure slave thread gets started
- // if server_id is set, valid master.info is present, and master_host has
- // not been specified
- if(server_id && !master_host)
- {
- char fname[FN_REFLEN+128];
- MY_STAT stat_area;
- fn_format(fname, master_info_file, mysql_data_home, "", 4+16+32);
- if(my_stat(fname, &stat_area, MYF(0)) && !init_master_info(&glob_mi))
- master_host = glob_mi.host;
- }
-
+
+ init_slave();
+
if (opt_bin_log && !server_id)
{
server_id= !master_host ? 1 : 2;
@@ -1853,7 +1902,7 @@ The server will not act as a slave.");
LOG_BIN);
using_update_log=1;
}
-
+
if (opt_slow_log)
open_log(&mysql_slow_log, glob_hostname, opt_slow_logname, "-slow.log",
LOG_NORMAL);
@@ -1875,11 +1924,11 @@ The server will not act as a slave.");
}
#else
locked_in_memory=0;
-#endif
+#endif
if (opt_myisam_log)
(void) mi_log( 1 );
- ft_init_stopwords(ft_precompiled_stopwords); /* SerG */
+ ft_init_stopwords(ft_precompiled_stopwords);
#ifdef __WIN__
#define MYSQL_ERR_FILE "mysql.err"
@@ -1909,14 +1958,13 @@ The server will not act as a slave.");
(void) pthread_kill(signal_thread,MYSQL_KILL_SIGNAL);
#ifndef __WIN__
if (!opt_bootstrap)
- (void) my_delete(pidfile_name,MYF(MY_WME)); // Not neaded anymore
+ (void) my_delete(pidfile_name,MYF(MY_WME)); // Not needed anymore
#endif
exit(1);
}
if (!opt_noacl)
(void) grant_init();
- if (max_user_connections)
- init_max_user_conn();
+ init_max_user_conn();
#ifdef HAVE_DLOPEN
if (!opt_noacl)
@@ -1938,7 +1986,7 @@ The server will not act as a slave.");
}
}
(void) thr_setconcurrency(concurrency); // 10 by default
-#ifdef __WIN__ //IRENA
+#if defined(__WIN__) && !defined(EMBEDDED_LIBRARY) //IRENA
{
hEventShutdown=CreateEvent(0, FALSE, FALSE, "MySqlShutdown");
pthread_t hThread;
@@ -1969,17 +2017,6 @@ The server will not act as a slave.");
sql_print_error("Warning: Can't create thread to manage maintenance");
}
- // slave thread
- if (master_host)
- {
- pthread_t hThread;
- if (!opt_skip_slave_start &&
- pthread_create(&hThread, &connection_attrib, handle_slave, 0))
- sql_print_error("Warning: Can't create thread to handle slave");
- else if(opt_skip_slave_start)
- init_master_info(&glob_mi);
- }
-
printf(ER(ER_READY),my_progname,server_version,"");
fflush(stdout);
@@ -2024,7 +2061,7 @@ The server will not act as a slave.");
}
#else
handle_connections_sockets(0);
-#ifdef EXTRA_DEBUG
+#ifdef EXTRA_DEBUG2
sql_print_error("Exiting main thread");
#endif
#endif /* __NT__ */
@@ -2034,17 +2071,19 @@ The server will not act as a slave.");
DBUG_PRINT("quit",("Exiting main thread"));
#ifndef __WIN__
-#ifdef EXTRA_DEBUG
+#ifdef EXTRA_DEBUG2
sql_print_error("Before Lock_thread_count");
#endif
(void) pthread_mutex_lock(&LOCK_thread_count);
+ DBUG_PRINT("quit", ("Got thread_count mutex"));
select_thread_in_use=0; // For close_connections
(void) pthread_cond_broadcast(&COND_thread_count);
(void) pthread_mutex_unlock(&LOCK_thread_count);
-#ifdef EXTRA_DEBUG
+#ifdef EXTRA_DEBUG2
sql_print_error("After lock_thread_count");
#endif
#else
+#if !defined(EMBEDDED_LIBRARY)
if (Service.IsNT())
{
if(start_mode)
@@ -2064,13 +2103,20 @@ The server will not act as a slave.");
if(hEventShutdown) CloseHandle(hEventShutdown);
}
#endif
-
+#endif
+#ifdef HAVE_OPENSSL
+ my_free((gptr)ssl_acceptor_fd,MYF(MY_ALLOW_ZERO_PTR));
+#endif /* HAVE_OPENSSL */
/* Wait until cleanup is done */
(void) pthread_mutex_lock(&LOCK_thread_count);
+ DBUG_PRINT("quit", ("Got thread_count mutex for clean up wait"));
+
while (!ready_to_exit)
{
+ DBUG_PRINT("quit", ("not yet ready to exit"));
pthread_cond_wait(&COND_thread_count,&LOCK_thread_count);
}
+ DBUG_PRINT("quit", ("ready to exit"));
(void) pthread_mutex_unlock(&LOCK_thread_count);
my_end(opt_endinfo ? MY_CHECK_ERROR | MY_GIVE_INFO : 0);
exit(0);
@@ -2078,7 +2124,7 @@ The server will not act as a slave.");
}
-#ifdef __WIN__
+#if defined(__WIN__) && !defined(EMBEDDED_LIBRARY)
/* ------------------------------------------------------------------------
main and thread entry function for Win32
(all this is needed only to run mysqld as a service on WinNT)
@@ -2125,9 +2171,11 @@ int main(int argc, char **argv)
}
}
- // This is a WIN95 machine or a start of mysqld as a standalone program
- // we have to pass the arguments, in case of NT-service this will be done
- // by ServiceMain()
+ /*
+ This is a WIN95 machine or a start of mysqld as a standalone program
+ we have to pass the arguments, in case of NT-service this will be done
+ by ServiceMain()
+ */
Service.my_argc=argc;
Service.my_argv=argv;
@@ -2144,7 +2192,7 @@ static int bootstrap(FILE *file)
int error;
thd->bootstrap=1;
thd->client_capabilities=0;
- my_net_init(&thd->net,(Vio*) 0);
+ my_net_init(&thd->net,(st_vio*) 0);
thd->max_packet_length=thd->net.max_packet;
thd->master_access= ~0;
thd->thread_id=thread_id++;
@@ -2262,7 +2310,7 @@ static void create_new_thread(THD *thd)
(void) pthread_mutex_unlock(&LOCK_thread_count);
DBUG_VOID_RETURN;
}
-
+
(void) pthread_mutex_unlock(&LOCK_thread_count);
}
}
@@ -2270,6 +2318,20 @@ static void create_new_thread(THD *thd)
DBUG_VOID_RETURN;
}
+#ifdef SIGNALS_DONT_BREAK_READ
+inline void kill_broken_server()
+{
+ /* hack to get around signals ignored in syscalls for problem OS's */
+ if (unix_sock == INVALID_SOCKET || ip_sock ==INVALID_SOCKET)
+ {
+ select_thread_in_use = 0;
+ kill_server((void*)MYSQL_KILL_SIGNAL); /* never returns */
+ }
+}
+#define MAYBE_BROKEN_SYSCALL kill_broken_server();
+#else
+#define MAYBE_BROKEN_SYSCALL
+#endif
/* Handle new connections and spawn new process to handle them */
@@ -2282,7 +2344,7 @@ pthread_handler_decl(handle_connections_sockets,arg __attribute__((unused)))
THD *thd;
struct sockaddr_in cAddr;
int ip_flags=0,socket_flags=0,flags;
- Vio *vio_tmp;
+ st_vio *vio_tmp;
DBUG_ENTER("handle_connections_sockets");
LINT_INIT(new_sock);
@@ -2320,13 +2382,15 @@ pthread_handler_decl(handle_connections_sockets,arg __attribute__((unused)))
if (!select_errors++ && !abort_loop) /* purecov: inspected */
sql_print_error("mysqld: Got error %d from select",socket_errno); /* purecov: inspected */
}
- MAYBE_BROKEN_SYSCALL;
+ MAYBE_BROKEN_SYSCALL
continue;
}
#endif /* HPUX */
if (abort_loop)
+ {
+ MAYBE_BROKEN_SYSCALL;
break;
-
+ }
/*
** Is this a new connection request
*/
@@ -2395,18 +2459,21 @@ pthread_handler_decl(handle_connections_sockets,arg __attribute__((unused)))
fromhost(&req);
if (!hosts_access(&req))
{
- // This may be stupid but refuse() includes an exit(0)
- // which we surely don't want...
- // clean_exit() - same stupid thing ...
+ /*
+ This may be stupid but refuse() includes an exit(0)
+ which we surely don't want...
+ clean_exit() - same stupid thing ...
+ */
syslog(deny_severity, "refused connect from %s", eval_client(&req));
if (req.sink)
((void (*)(int))req.sink)(req.fd);
- // C++ sucks (the gibberish in front just translates the supplied
- // sink function pointer in the req structure from a void (*sink)();
- // to a void(*sink)(int) if you omit the cast, the C++ compiler
- // will cry...
-
+ /*
+ C++ sucks (the gibberish in front just translates the supplied
+ sink function pointer in the req structure from a void (*sink)();
+ to a void(*sink)(int) if you omit the cast, the C++ compiler
+ will cry...
+ */
(void) shutdown(new_sock,2); // This looks fine to me...
(void) closesocket(new_sock);
continue;
@@ -2434,7 +2501,8 @@ pthread_handler_decl(handle_connections_sockets,arg __attribute__((unused)))
if (!(thd= new THD))
{
- (void) shutdown(new_sock,2); VOID(closesocket(new_sock));
+ (void) shutdown(new_sock,2);
+ VOID(closesocket(new_sock));
continue;
}
if (!(vio_tmp=vio_new(new_sock,
@@ -2586,6 +2654,8 @@ enum options {
OPT_MASTER_PASSWORD, OPT_MASTER_PORT,
OPT_MASTER_INFO_FILE, OPT_MASTER_CONNECT_RETRY,
OPT_MASTER_RETRY_COUNT,
+ OPT_MASTER_SSL, OPT_MASTER_SSL_KEY,
+ OPT_MASTER_SSL_CERT,
OPT_SQL_BIN_UPDATE_SAME, OPT_REPLICATE_DO_DB,
OPT_REPLICATE_IGNORE_DB, OPT_LOG_SLAVE_UPDATES,
OPT_BINLOG_DO_DB, OPT_BINLOG_IGNORE_DB,
@@ -2604,17 +2674,21 @@ enum options {
OPT_INNODB_LOG_ARCH_DIR,
OPT_INNODB_LOG_ARCHIVE,
OPT_INNODB_FLUSH_LOG_AT_TRX_COMMIT,
+ OPT_INNODB_FLUSH_METHOD,
OPT_INNODB_FAST_SHUTDOWN,
- OPT_INNODB_UNIX_FILE_FLUSH_METHOD,
OPT_SAFE_SHOW_DB,
- OPT_GEMINI_SKIP, OPT_INNODB_SKIP,
+ OPT_INNODB_SKIP, OPT_SKIP_SAFEMALLOC,
OPT_TEMP_POOL, OPT_TX_ISOLATION,
- OPT_GEMINI_FLUSH_LOG, OPT_GEMINI_RECOVER,
- OPT_GEMINI_UNBUFFERED_IO, OPT_SKIP_SAFEMALLOC,
OPT_SKIP_STACK_TRACE, OPT_SKIP_SYMLINKS,
OPT_MAX_BINLOG_DUMP_EVENTS, OPT_SPORADIC_BINLOG_DUMP_FAIL,
OPT_SAFE_USER_CREATE, OPT_SQL_MODE,
- OPT_SLAVE_SKIP_ERRORS, OPT_LOCAL_INFILE
+ OPT_DO_PSTACK, OPT_REPORT_HOST,
+ OPT_REPORT_USER, OPT_REPORT_PASSWORD, OPT_REPORT_PORT,
+ OPT_SHOW_SLAVE_AUTH_INFO, OPT_OLD_RPL_COMPAT,
+ OPT_SLAVE_LOAD_TMPDIR, OPT_NO_MIX_TYPE,
+ OPT_RPL_RECOVERY_RANK,OPT_INIT_RPL_ROLE,
+ OPT_RELAY_LOG, OPT_RELAY_LOG_INDEX, OPT_RELAY_LOG_INFO_FILE,
+ OPT_SLAVE_SKIP_ERRORS, OPT_DES_KEY_FILE, OPT_LOCAL_INFILE
};
static struct option long_options[] = {
@@ -2642,18 +2716,16 @@ static struct option long_options[] = {
{"character-sets-dir", required_argument, 0, (int) OPT_CHARSETS_DIR},
{"datadir", required_argument, 0, 'h'},
{"debug", optional_argument, 0, '#'},
+ {"des-key-file", required_argument, 0, (int) OPT_DES_KEY_FILE},
{"default-character-set", required_argument, 0, 'C'},
{"default-table-type", required_argument, 0, (int) OPT_TABLE_TYPE},
{"delay-key-write-for-all-tables",
no_argument, 0, (int) OPT_DELAY_KEY_WRITE},
{"enable-locking", no_argument, 0, (int) OPT_ENABLE_LOCK},
+ {"enable-pstack", no_argument, 0, (int) OPT_DO_PSTACK},
{"exit-info", optional_argument, 0, 'T'},
{"flush", no_argument, 0, (int) OPT_FLUSH},
-#ifdef HAVE_GEMINI_DB
- {"gemini-flush-log-at-commit",no_argument, 0, (int) OPT_GEMINI_FLUSH_LOG},
- {"gemini-recovery", required_argument, 0, (int) OPT_GEMINI_RECOVER},
- {"gemini-unbuffered-io", no_argument, 0, (int) OPT_GEMINI_UNBUFFERED_IO},
-#endif
+ {"init-rpl-role", required_argument, 0, (int) OPT_INIT_RPL_ROLE},
/* We must always support this option to make scripts like mysqltest easier
to do */
{"innodb_data_file_path", required_argument, 0,
@@ -2672,7 +2744,7 @@ static struct option long_options[] = {
{"innodb_fast_shutdown", optional_argument, 0,
OPT_INNODB_FAST_SHUTDOWN},
{"innodb_flush_method", required_argument, 0,
- OPT_INNODB_UNIX_FILE_FLUSH_METHOD},
+ OPT_INNODB_FLUSH_METHOD},
#endif
{"help", no_argument, 0, '?'},
{"init-file", required_argument, 0, (int) OPT_INIT_FILE},
@@ -2694,10 +2766,15 @@ static struct option long_options[] = {
{"master-connect-retry", required_argument, 0, (int) OPT_MASTER_CONNECT_RETRY},
{"master-retry-count", required_argument, 0, (int) OPT_MASTER_RETRY_COUNT},
{"master-info-file", required_argument, 0, (int) OPT_MASTER_INFO_FILE},
+ {"master-ssl", optional_argument, 0, (int) OPT_MASTER_SSL},
+ {"master-ssl-key", optional_argument, 0, (int) OPT_MASTER_SSL_KEY},
+ {"master-ssl-cert", optional_argument, 0, (int) OPT_MASTER_SSL_CERT},
{"myisam-recover", optional_argument, 0, (int) OPT_MYISAM_RECOVER},
{"memlock", no_argument, 0, (int) OPT_MEMLOCK},
- // needs to be available for the test case to pass in non-debugging mode
- // is a no-op
+ /*
+ Option needs to be available for the test case to pass in non-debugging
+ mode. is a no-op.
+ */
{"disconnect-slave-event-count", required_argument, 0,
(int) OPT_DISCONNECT_SLAVE_EVENT_COUNT},
{"abort-slave-event-count", required_argument, 0,
@@ -2709,7 +2786,11 @@ static struct option long_options[] = {
{"safemalloc-mem-limit", required_argument, 0, (int)
OPT_SAFEMALLOC_MEM_LIMIT},
{"new", no_argument, 0, 'n'},
- {"old-protocol", no_argument, 0, 'o'},
+#ifdef NOT_YET
+ {"no-mix-table-types", no_argument, 0, (int) OPT_NO_MIX_TYPE},
+#endif
+ {"old-protocol", no_argument, 0, 'o'},
+ {"old-rpl-compat", no_argument, 0, (int) OPT_OLD_RPL_COMPAT},
#ifdef ONE_THREAD
{"one-thread", no_argument, 0, (int) OPT_ONE_THREAD},
#endif
@@ -2718,24 +2799,33 @@ static struct option long_options[] = {
{"replicate-do-db", required_argument, 0, (int) OPT_REPLICATE_DO_DB},
{"replicate-do-table", required_argument, 0,
(int) OPT_REPLICATE_DO_TABLE},
- {"replicate-wild-do-table", required_argument, 0,
+ {"replicate-wild-do-table", required_argument, 0,
(int) OPT_REPLICATE_WILD_DO_TABLE},
- {"replicate-ignore-db", required_argument, 0,
+ {"replicate-ignore-db", required_argument, 0,
(int) OPT_REPLICATE_IGNORE_DB},
{"replicate-ignore-table", required_argument, 0,
(int) OPT_REPLICATE_IGNORE_TABLE},
{"replicate-wild-ignore-table", required_argument, 0,
(int) OPT_REPLICATE_WILD_IGNORE_TABLE},
- {"replicate-rewrite-db", required_argument, 0,
+ {"replicate-rewrite-db", required_argument, 0,
(int) OPT_REPLICATE_REWRITE_DB},
+ // In replication, we may need to tell the other servers how to connect
+ {"report-host", required_argument, 0, (int) OPT_REPORT_HOST},
+ {"report-user", required_argument, 0, (int) OPT_REPORT_USER},
+ {"report-password", required_argument, 0, (int) OPT_REPORT_PASSWORD},
+ {"report-port", required_argument, 0, (int) OPT_REPORT_PORT},
+ {"rpl-recovery-rank", required_argument, 0, (int) OPT_RPL_RECOVERY_RANK},
+ {"relay-log", required_argument, 0, (int) OPT_RELAY_LOG},
+ {"relay-log-index", required_argument, 0, (int) OPT_RELAY_LOG_INDEX},
{"safe-mode", no_argument, 0, (int) OPT_SAFE},
{"safe-show-database", no_argument, 0, (int) OPT_SAFE_SHOW_DB},
{"safe-user-create", no_argument, 0, (int) OPT_SAFE_USER_CREATE},
{"server-id", required_argument, 0, (int) OPT_SERVER_ID},
{"set-variable", required_argument, 0, 'O'},
+ {"show-slave-auth-info", no_argument, 0,
+ (int) OPT_SHOW_SLAVE_AUTH_INFO},
{"skip-bdb", no_argument, 0, (int) OPT_BDB_SKIP},
{"skip-innodb", no_argument, 0, (int) OPT_INNODB_SKIP},
- {"skip-gemini", no_argument, 0, (int) OPT_GEMINI_SKIP},
{"skip-concurrent-insert", no_argument, 0, (int) OPT_SKIP_CONCURRENT_INSERT},
{"skip-delay-key-write", no_argument, 0, (int) OPT_SKIP_DELAY_KEY_WRITE},
{"skip-grant-tables", no_argument, 0, (int) OPT_SKIP_GRANT},
@@ -2750,7 +2840,10 @@ static struct option long_options[] = {
{"skip-stack-trace", no_argument, 0, (int) OPT_SKIP_STACK_TRACE},
{"skip-symlink", no_argument, 0, (int) OPT_SKIP_SYMLINKS},
{"skip-thread-priority", no_argument, 0, (int) OPT_SKIP_PRIOR},
- {"slave-skip-errors", required_argument,0,
+ {"relay-log-info-file", required_argument, 0,
+ (int) OPT_RELAY_LOG_INFO_FILE},
+ {"slave-load-tmpdir", required_argument, 0, (int) OPT_SLAVE_LOAD_TMPDIR},
+ {"slave-skip-errors", required_argument, 0,
(int) OPT_SLAVE_SKIP_ERRORS},
{"socket", required_argument, 0, (int) OPT_SOCKET},
{"sql-bin-update-same", no_argument, 0, (int) OPT_SQL_BIN_UPDATE_SAME},
@@ -2800,22 +2893,12 @@ CHANGEABLE_VAR changeable_vars[] = {
DELAYED_QUEUE_SIZE, 1, ~0L, 0, 1 },
{ "flush_time", (long*) &flush_time,
FLUSH_TIME, 0, LONG_TIMEOUT, 0, 1 },
-#ifdef HAVE_GEMINI_DB
- { "gemini_buffer_cache", (long*) &gemini_buffer_cache,
- 128 * 8192, 16, LONG_MAX, 0, 1 },
- { "gemini_connection_limit", (long*) &gemini_connection_limit,
- 100, 10, LONG_MAX, 0, 1 },
- { "gemini_io_threads", (long*) &gemini_io_threads,
- 2, 0, 256, 0, 1 },
- { "gemini_log_cluster_size", (long*) &gemini_log_cluster_size,
- 256 * 1024, 16 * 1024, LONG_MAX, 0, 1 },
- { "gemini_lock_table_size", (long*) &gemini_locktablesize,
- 4096, 1024, LONG_MAX, 0, 1 },
- { "gemini_lock_wait_timeout",(long*) &gemini_lock_wait_timeout,
- 10, 1, LONG_MAX, 0, 1 },
- { "gemini_spin_retries", (long*) &gemini_spin_retries,
- 1, 0, LONG_MAX, 0, 1 },
-#endif
+ { "ft_min_word_len", (long*) &ft_min_word_len,
+ 4, 1, HA_FT_MAXLEN, 0, 1 },
+ { "ft_max_word_len", (long*) &ft_max_word_len,
+ HA_FT_MAXLEN, 10, HA_FT_MAXLEN, 0, 1 },
+ { "ft_max_word_len_for_sort",(long*) &ft_max_word_len_for_sort,
+ 20, 4, HA_FT_MAXLEN, 0, 1 },
#ifdef HAVE_INNOBASE_DB
{"innodb_mirrored_log_groups",
(long*) &innobase_mirrored_log_groups, 1, 1, 10, 0, 1},
@@ -2877,6 +2960,11 @@ CHANGEABLE_VAR changeable_vars[] = {
0, 1, ~0L, 0, 1 },
{ "max_write_lock_count", (long*) &max_write_lock_count,
~0L, 1, ~0L, 0, 1 },
+ { "myisam_bulk_insert_tree_size", (long*) &myisam_bulk_insert_tree_size,
+ 8192*1024, 0, ~0L, 0, 1 },
+ { "myisam_block_size", (long*) &opt_myisam_block_size,
+ MI_KEY_BLOCK_LENGTH, MI_MIN_KEY_BLOCK_LENGTH, MI_MAX_KEY_BLOCK_LENGTH,
+ 0, MI_MIN_KEY_BLOCK_LENGTH },
{ "myisam_max_extra_sort_file_size",
(long*) &myisam_max_extra_sort_file_size,
(long) (MI_MAX_TEMP_LENGTH/(1024L*1024L)), 0, ~0L, 0, 1 },
@@ -2896,6 +2984,12 @@ CHANGEABLE_VAR changeable_vars[] = {
0, 0, 65535, 0, 1},
{ "query_buffer_size", (long*) &query_buff_size,
0, MALLOC_OVERHEAD, (long) ~0, MALLOC_OVERHEAD, IO_SIZE },
+ { "query_cache_limit", (long*) &query_cache_limit,
+ 1024*1024L, 0, ULONG_MAX, 0, 1},
+ { "query_cache_size", (long*) &query_cache_size,
+ 0, 0, ULONG_MAX, 0, 1},
+ { "query_cache_startup_type",(long*) &query_cache_startup_type,
+ 1, 0, 2, 0, 1},
{ "record_buffer", (long*) &my_default_record_cache_size,
128*1024L, IO_SIZE*2+MALLOC_OVERHEAD, ~0L, MALLOC_OVERHEAD, IO_SIZE },
{ "record_rnd_buffer", (long*) &record_rnd_cache_size,
@@ -2947,22 +3041,16 @@ struct show_var_st init_vars[]= {
{"delayed_queue_size", (char*) &delayed_queue_size, SHOW_LONG},
{"flush", (char*) &myisam_flush, SHOW_MY_BOOL},
{"flush_time", (char*) &flush_time, SHOW_LONG},
-#ifdef HAVE_GEMINI_DB
- {"gemini_buffer_cache", (char*) &gemini_buffer_cache, SHOW_LONG},
- {"gemini_connection_limit", (char*) &gemini_connection_limit, SHOW_LONG},
- {"gemini_io_threads", (char*) &gemini_io_threads, SHOW_LONG},
- {"gemini_log_cluster_size", (char*) &gemini_log_cluster_size, SHOW_LONG},
- {"gemini_lock_table_size", (char*) &gemini_locktablesize, SHOW_LONG},
- {"gemini_lock_wait_timeout",(char*) &gemini_lock_wait_timeout, SHOW_LONG},
- {"gemini_recovery_options", (char*) &gemini_recovery_options_str, SHOW_CHAR_PTR},
- {"gemini_spin_retries", (char*) &gemini_spin_retries, SHOW_LONG},
-#endif
+ {"ft_min_word_len", (char*) &ft_min_word_len, SHOW_LONG},
+ {"ft_max_word_len", (char*) &ft_max_word_len, SHOW_LONG},
+ {"ft_max_word_len_for_sort",(char*) &ft_max_word_len_for_sort, SHOW_LONG},
+ {"ft_boolean_syntax", (char*) ft_boolean_syntax, SHOW_CHAR},
{"have_bdb", (char*) &have_berkeley_db, SHOW_HAVE},
- {"have_gemini", (char*) &have_gemini, SHOW_HAVE},
{"have_innodb", (char*) &have_innodb, SHOW_HAVE},
{"have_isam", (char*) &have_isam, SHOW_HAVE},
{"have_raid", (char*) &have_raid, SHOW_HAVE},
- {"have_openssl", (char*) &have_ssl, SHOW_HAVE},
+ {"have_symlink", (char*) &have_symlink, SHOW_HAVE},
+ {"have_openssl", (char*) &have_openssl, SHOW_HAVE},
{"init_file", (char*) &opt_init_file, SHOW_CHAR_PTR},
#ifdef HAVE_INNOBASE_DB
{"innodb_additional_mem_pool_size", (char*) &innobase_additional_mem_pool_size, SHOW_LONG },
@@ -2996,7 +3084,7 @@ struct show_var_st init_vars[]= {
{"log_update", (char*) &opt_update_log, SHOW_BOOL},
{"log_bin", (char*) &opt_bin_log, SHOW_BOOL},
{"log_slave_updates", (char*) &opt_log_slave_updates, SHOW_BOOL},
- {"log_long_queries", (char*) &opt_slow_log, SHOW_BOOL},
+ {"log_slow_queries", (char*) &opt_slow_log, SHOW_BOOL},
{"long_query_time", (char*) &long_query_time, SHOW_LONG},
{"low_priority_updates", (char*) &low_priority_updates, SHOW_BOOL},
{"lower_case_table_names", (char*) &lower_case_table_names, SHOW_LONG},
@@ -3012,10 +3100,11 @@ struct show_var_st init_vars[]= {
{"max_user_connections", (char*) &max_user_connections, SHOW_LONG},
{"max_tmp_tables", (char*) &max_tmp_tables, SHOW_LONG},
{"max_write_lock_count", (char*) &max_write_lock_count, SHOW_LONG},
+ {"myisam_bulk_insert_tree_size", (char*) &myisam_bulk_insert_tree_size, SHOW_INT},
{"myisam_max_extra_sort_file_size", (char*) &myisam_max_extra_sort_file_size,
SHOW_LONG},
{"myisam_max_sort_file_size",(char*) &myisam_max_sort_file_size, SHOW_LONG},
- {"myisam_recover_options", (char*) &myisam_recover_options, SHOW_LONG},
+ {"myisam_recover_options", (char*) &myisam_recover_options_str, SHOW_CHAR_PTR},
{"myisam_sort_buffer_size", (char*) &myisam_sort_buffer_size, SHOW_LONG},
{"net_buffer_length", (char*) &net_buffer_length, SHOW_LONG},
{"net_read_timeout", (char*) &net_read_timeout, SHOW_LONG},
@@ -3027,7 +3116,11 @@ struct show_var_st init_vars[]= {
{"protocol_version", (char*) &protocol_version, SHOW_INT},
{"record_buffer", (char*) &my_default_record_cache_size,SHOW_LONG},
{"record_rnd_buffer", (char*) &record_rnd_cache_size, SHOW_LONG},
+ {"rpl_recovery_rank", (char*) &rpl_recovery_rank, SHOW_LONG},
{"query_buffer_size", (char*) &query_buff_size, SHOW_LONG},
+ {"query_cache_limit", (char*) &query_cache.query_cache_limit, SHOW_LONG},
+ {"query_cache_size", (char*) &query_cache.query_cache_size, SHOW_LONG},
+ {"query_cache_startup_type",(char*) &query_cache_startup_type, SHOW_LONG},
{"safe_show_database", (char*) &opt_safe_show_db, SHOW_BOOL},
{"server_id", (char*) &server_id, SHOW_LONG},
{"slave_net_timeout", (char*) &slave_net_timeout, SHOW_LONG},
@@ -3075,16 +3168,21 @@ struct show_var_st status_vars[]= {
{"Com_create_index", (char*) (com_stat+(uint) SQLCOM_CREATE_INDEX),SHOW_LONG},
{"Com_create_table", (char*) (com_stat+(uint) SQLCOM_CREATE_TABLE),SHOW_LONG},
{"Com_delete", (char*) (com_stat+(uint) SQLCOM_DELETE),SHOW_LONG},
+ {"Com_delete_multi", (char*) (com_stat+(uint) SQLCOM_DELETE_MULTI),SHOW_LONG},
{"Com_drop_db", (char*) (com_stat+(uint) SQLCOM_DROP_DB),SHOW_LONG},
{"Com_drop_function", (char*) (com_stat+(uint) SQLCOM_DROP_FUNCTION),SHOW_LONG},
{"Com_drop_index", (char*) (com_stat+(uint) SQLCOM_DROP_INDEX),SHOW_LONG},
{"Com_drop_table", (char*) (com_stat+(uint) SQLCOM_DROP_TABLE),SHOW_LONG},
{"Com_flush", (char*) (com_stat+(uint) SQLCOM_FLUSH),SHOW_LONG},
{"Com_grant", (char*) (com_stat+(uint) SQLCOM_GRANT),SHOW_LONG},
+ {"Com_ha_close", (char*) (com_stat+(uint) SQLCOM_HA_CLOSE),SHOW_LONG},
+ {"Com_ha_open", (char*) (com_stat+(uint) SQLCOM_HA_OPEN),SHOW_LONG},
+ {"Com_ha_read", (char*) (com_stat+(uint) SQLCOM_HA_READ),SHOW_LONG},
{"Com_insert", (char*) (com_stat+(uint) SQLCOM_INSERT),SHOW_LONG},
{"Com_insert_select", (char*) (com_stat+(uint) SQLCOM_INSERT_SELECT),SHOW_LONG},
{"Com_kill", (char*) (com_stat+(uint) SQLCOM_KILL),SHOW_LONG},
{"Com_load", (char*) (com_stat+(uint) SQLCOM_LOAD),SHOW_LONG},
+ {"Com_load_master_data", (char*) (com_stat+(uint) SQLCOM_LOAD_MASTER_DATA),SHOW_LONG},
{"Com_load_master_table", (char*) (com_stat+(uint) SQLCOM_LOAD_MASTER_TABLE),SHOW_LONG},
{"Com_lock_tables", (char*) (com_stat+(uint) SQLCOM_LOCK_TABLES),SHOW_LONG},
{"Com_optimize", (char*) (com_stat+(uint) SQLCOM_OPTIMIZE),SHOW_LONG},
@@ -3099,6 +3197,7 @@ struct show_var_st status_vars[]= {
{"Com_rollback", (char*) (com_stat+(uint) SQLCOM_ROLLBACK),SHOW_LONG},
{"Com_select", (char*) (com_stat+(uint) SQLCOM_SELECT),SHOW_LONG},
{"Com_set_option", (char*) (com_stat+(uint) SQLCOM_SET_OPTION),SHOW_LONG},
+ {"Com_show_binlog_events", (char*) (com_stat+(uint) SQLCOM_SHOW_BINLOG_EVENTS),SHOW_LONG},
{"Com_show_binlogs", (char*) (com_stat+(uint) SQLCOM_SHOW_BINLOGS),SHOW_LONG},
{"Com_show_create", (char*) (com_stat+(uint) SQLCOM_SHOW_CREATE),SHOW_LONG},
{"Com_show_databases", (char*) (com_stat+(uint) SQLCOM_SHOW_DATABASES),SHOW_LONG},
@@ -3107,8 +3206,10 @@ struct show_var_st status_vars[]= {
{"Com_show_keys", (char*) (com_stat+(uint) SQLCOM_SHOW_KEYS),SHOW_LONG},
{"Com_show_logs", (char*) (com_stat+(uint) SQLCOM_SHOW_LOGS),SHOW_LONG},
{"Com_show_master_stat", (char*) (com_stat+(uint) SQLCOM_SHOW_MASTER_STAT),SHOW_LONG},
+ {"Com_show_new_master", (char*) (com_stat+(uint) SQLCOM_SHOW_NEW_MASTER),SHOW_LONG},
{"Com_show_open_tables", (char*) (com_stat+(uint) SQLCOM_SHOW_OPEN_TABLES),SHOW_LONG},
{"Com_show_processlist", (char*) (com_stat+(uint) SQLCOM_SHOW_PROCESSLIST),SHOW_LONG},
+ {"Com_show_slave_hosts", (char*) (com_stat+(uint) SQLCOM_SHOW_SLAVE_HOSTS),SHOW_LONG},
{"Com_show_slave_stat", (char*) (com_stat+(uint) SQLCOM_SHOW_SLAVE_STAT),SHOW_LONG},
{"Com_show_status", (char*) (com_stat+(uint) SQLCOM_SHOW_STATUS),SHOW_LONG},
{"Com_show_tables", (char*) (com_stat+(uint) SQLCOM_SHOW_TABLES),SHOW_LONG},
@@ -3126,6 +3227,7 @@ struct show_var_st status_vars[]= {
{"Delayed_writes", (char*) &delayed_insert_writes, SHOW_LONG},
{"Delayed_errors", (char*) &delayed_insert_errors, SHOW_LONG},
{"Flush_commands", (char*) &refresh_version, SHOW_LONG_CONST},
+ {"Handler_commit", (char*) &ha_commit_count, SHOW_LONG},
{"Handler_delete", (char*) &ha_delete_count, SHOW_LONG},
{"Handler_read_first", (char*) &ha_read_first_count, SHOW_LONG},
{"Handler_read_key", (char*) &ha_read_key_count, SHOW_LONG},
@@ -3133,6 +3235,7 @@ struct show_var_st status_vars[]= {
{"Handler_read_prev", (char*) &ha_read_prev_count, SHOW_LONG},
{"Handler_read_rnd", (char*) &ha_read_rnd_count, SHOW_LONG},
{"Handler_read_rnd_next", (char*) &ha_read_rnd_next_count, SHOW_LONG},
+ {"Handler_rollback", (char*) &ha_rollback_count, SHOW_LONG},
{"Handler_update", (char*) &ha_update_count, SHOW_LONG},
{"Handler_write", (char*) &ha_write_count, SHOW_LONG},
{"Key_blocks_used", (char*) &_my_blocks_used, SHOW_LONG_CONST},
@@ -3148,19 +3251,55 @@ struct show_var_st status_vars[]= {
{"Open_streams", (char*) &my_stream_opened, SHOW_INT_CONST},
{"Opened_tables", (char*) &opened_tables, SHOW_LONG},
{"Questions", (char*) 0, SHOW_QUESTION},
+ {"Qcache_queries_in_cache", (char*) &query_cache.queries_in_cache, SHOW_LONG_CONST},
+ {"Qcache_inserts", (char*) &query_cache.inserts, SHOW_LONG},
+ {"Qcache_hits", (char*) &query_cache.hits, SHOW_LONG},
+ {"Qcache_not_cached", (char*) &query_cache.refused, SHOW_LONG},
+ {"Qcache_free_memory", (char*) &query_cache.free_memory,
+ SHOW_LONG_CONST},
+ {"Qcache_free_blocks", (char*) &query_cache.free_memory_blocks,
+ SHOW_LONG_CONST},
+ {"Qcache_total_blocks", (char*) &query_cache.total_blocks,
+ SHOW_LONG_CONST},
+ {"Rpl_status", (char*) 0, SHOW_RPL_STATUS},
{"Select_full_join", (char*) &select_full_join_count, SHOW_LONG},
{"Select_full_range_join", (char*) &select_full_range_join_count, SHOW_LONG},
{"Select_range", (char*) &select_range_count, SHOW_LONG},
{"Select_range_check", (char*) &select_range_check_count, SHOW_LONG},
{"Select_scan", (char*) &select_scan_count, SHOW_LONG},
- {"Slave_running", (char*) &slave_running, SHOW_BOOL},
{"Slave_open_temp_tables", (char*) &slave_open_temp_tables, SHOW_LONG},
+ {"Slave_running", (char*) 0, SHOW_SLAVE_RUNNING},
{"Slow_launch_threads", (char*) &slow_launch_threads, SHOW_LONG},
{"Slow_queries", (char*) &long_query_count, SHOW_LONG},
{"Sort_merge_passes", (char*) &filesort_merge_passes, SHOW_LONG},
{"Sort_range", (char*) &filesort_range_count, SHOW_LONG},
{"Sort_rows", (char*) &filesort_rows, SHOW_LONG},
{"Sort_scan", (char*) &filesort_scan_count, SHOW_LONG},
+#ifdef HAVE_OPENSSL
+ {"ssl_accepts", (char*) 0, SHOW_SSL_CTX_SESS_ACCEPT},
+ {"ssl_finished_accepts", (char*) 0, SHOW_SSL_CTX_SESS_ACCEPT_GOOD},
+ {"ssl_finished_connects", (char*) 0, SHOW_SSL_CTX_SESS_CONNECT_GOOD},
+ {"ssl_accept_renegotiates", (char*) 0, SHOW_SSL_CTX_SESS_ACCEPT_RENEGOTIATE},
+ {"ssl_connect_renegotiates", (char*) 0, SHOW_SSL_CTX_SESS_CONNECT_RENEGOTIATE},
+ {"ssl_callback_cache_hits", (char*) 0, SHOW_SSL_CTX_SESS_CB_HITS},
+ {"ssl_session_cache_hits", (char*) 0, SHOW_SSL_CTX_SESS_HITS},
+ {"ssl_session_cache_misses", (char*) 0, SHOW_SSL_CTX_SESS_MISSES},
+ {"ssl_session_cache_timeouts", (char*) 0, SHOW_SSL_CTX_SESS_TIMEOUTS},
+ {"ssl_used_session_cache_entries",(char*) 0, SHOW_SSL_CTX_SESS_NUMBER},
+ {"ssl_client_connects", (char*) 0, SHOW_SSL_CTX_SESS_CONNECT},
+ {"ssl_session_cache_overflows", (char*) 0, SHOW_SSL_CTX_SESS_CACHE_FULL},
+ {"ssl_session_cache_size", (char*) 0, SHOW_SSL_CTX_SESS_GET_CACHE_SIZE},
+ {"ssl_session_cache_mode", (char*) 0, SHOW_SSL_CTX_GET_SESSION_CACHE_MODE},
+ {"ssl_sessions_reused", (char*) 0, SHOW_SSL_SESSION_REUSED},
+ {"ssl_ctx_verify_mode", (char*) 0, SHOW_SSL_CTX_GET_VERIFY_MODE},
+ {"ssl_ctx_verify_depth", (char*) 0, SHOW_SSL_CTX_GET_VERIFY_DEPTH},
+ {"ssl_verify_mode", (char*) 0, SHOW_SSL_GET_VERIFY_MODE},
+ {"ssl_verify_depth", (char*) 0, SHOW_SSL_GET_VERIFY_DEPTH},
+ {"ssl_version", (char*) 0, SHOW_SSL_GET_VERSION},
+ {"ssl_cipher", (char*) 0, SHOW_SSL_GET_CIPHER},
+ {"ssl_cipher_list", (char*) 0, SHOW_SSL_GET_CIPHER_LIST},
+ {"ssl_default_timeout", (char*) 0, SHOW_SSL_GET_DEFAULT_TIMEOUT},
+#endif /* HAVE_OPENSSL */
{"Table_locks_immediate", (char*) &locks_immediate, SHOW_LONG},
{"Table_locks_waited", (char*) &locks_waited, SHOW_LONG},
{"Threads_cached", (char*) &cached_thread_count, SHOW_LONG_CONST},
@@ -3181,7 +3320,7 @@ static void use_help(void)
{
print_version();
printf("Use '--help' or '--no-defaults --help' for a list of available options\n");
-}
+}
static void usage(void)
{
@@ -3221,8 +3360,15 @@ Starts the MySQL server\n");
Set the default table type for tables\n\
--delay-key-write-for-all-tables\n\
Don't flush key buffers between writes for any MyISAM\n\
- table\n\
+ table\n");
+#ifdef HAVE_OPENSSL
+ puts("\
+ --des-key-file Load keys for des_encrypt() and des_encrypt\n\
+ from given file");
+#endif /* HAVE_OPENSSL */
+ puts("\
--enable-locking Enable system locking\n\
+ --enable-pstack Print a symbolic stack trace on failure\n\
-T, --exit-info Used for debugging; Use at your own risk!\n\
--flush Flush tables to disk between SQL commands\n\
-?, --help Display this help and exit\n\
@@ -3254,18 +3400,17 @@ Starts the MySQL server\n");
puts("\
-O, --set-variable var=option\n\
Give a variable an value. --help lists variables\n\
- -Sg, --skip-grant-tables\n\
- Start without grant tables. This gives all users\n\
- FULL ACCESS to all tables!\n\
--safe-mode Skip some optimize stages (for testing)\n\
--safe-show-database Don't show databases for which the user has no\n\
privileges\n\
- --safe-user-create Don't new users cretaion without privileges to the\n\
- mysql.user table\n\
+ --safe-user-create Don't allow new user creation by the user who has\n\
+ no write privileges to the mysql.user table\n\
--skip-concurrent-insert\n\
Don't use concurrent insert with MyISAM\n\
--skip-delay-key-write\n\
Ignore the delay_key_write option for all tables\n\
+ --skip-grant-tables Start without grant tables. This gives all users\n\
+ FULL ACCESS to all tables!\n\
--skip-host-cache Don't cache host names\n\
--skip-locking Don't use system locking. To use isamchk one has\n\
to shut down the server.\n\
@@ -3276,6 +3421,7 @@ Starts the MySQL server\n");
/* We have to break the string here because of VC++ limits */
puts("\
--skip-stack-trace Don't print a stack trace on failure\n\
+ --skip-symlink Don't allow symlinking of tables\n\
--skip-show-database Don't allow 'SHOW DATABASE' commands\n\
--skip-thread-priority\n\
Don't give threads different priorities.\n\
@@ -3283,7 +3429,8 @@ Starts the MySQL server\n");
-t, --tmpdir=path Path for temporary files\n\
--sql-mode=option[,option[,option...]] where option can be one of:\n\
REAL_AS_FLOAT, PIPES_AS_CONCAT, ANSI_QUOTES,\n\
- IGNORE_SPACE, SERIALIZE, ONLY_FULL_GROUP_BY.\n\
+ IGNORE_SPACE, SERIALIZE, ONLY_FULL_GROUP_BY,\n\
+ NO_UNSIGNED_SUBTRACTION.\n\
--transaction-isolation\n\
Default transaction isolation level\n\
--temp-pool Use a pool of temporary files\n\
@@ -3315,16 +3462,6 @@ Starts the MySQL server\n");
--skip-bdb Don't use berkeley db (will save memory)\n\
");
#endif /* HAVE_BERKELEY_DB */
-#ifdef HAVE_GEMINI_DB
- puts("\
- --gemini-recovery=mode Set Crash Recovery operating mode\n\
- (FULL, NONE, FORCE - default FULL)\n\
- --gemini-flush-log-at-commit\n\
- Every commit forces a write to the reovery log\n\
- --gemini-unbuffered-io Use unbuffered i/o\n\
- --skip-gemini Don't use gemini (will save memory)\n\
-");
-#endif
#ifdef HAVE_INNOBASE_DB
puts("\
--innodb_data_home_dir=dir The common part for Innodb table spaces\n\
@@ -3411,7 +3548,7 @@ static void set_options(void)
#endif
#if defined( HAVE_mit_thread ) || defined( __WIN__ ) || defined( HAVE_LINUXTHREADS )
- my_disable_locking = 1;
+ my_disable_locking=myisam_single_user= 1;
#endif
my_bind_addr = htonl( INADDR_ANY );
}
@@ -3423,6 +3560,16 @@ static void get_options(int argc,char **argv)
int c,option_index=0;
myisam_delay_key_write=1; // Allow use of this
+#ifndef HAVE_purify
+ my_use_symdir=1; // Use internal symbolic links
+#else
+ /* Symlinks gives too many warnings with purify */
+ my_disable_symlinks=1;
+ my_use_symdir=0;
+ have_symlink=SHOW_OPTION_DISABLED;
+#endif
+
+ optind = 0; // setup in case getopt() was called previously
while ((c=getopt_long(argc,argv,"ab:C:h:#::T::?l::L:O:P:sS::t:u:noVvWI?",
long_options, &option_index)) != EOF)
{
@@ -3482,6 +3629,18 @@ static void get_options(int argc,char **argv)
safemalloc_mem_limit = atoi(optarg);
#endif
break;
+ case OPT_RPL_RECOVERY_RANK:
+ rpl_recovery_rank=atoi(optarg);
+ break;
+ case OPT_SLAVE_LOAD_TMPDIR:
+ slave_load_tmpdir = my_strdup(optarg, MYF(MY_FAE));
+ break;
+ case OPT_OLD_RPL_COMPAT:
+ opt_old_rpl_compat = 1;
+ break;
+ case OPT_SHOW_SLAVE_AUTH_INFO:
+ opt_show_slave_auth_info = 1;
+ break;
case OPT_SOCKET:
mysql_unix_port= optarg;
break;
@@ -3514,20 +3673,6 @@ static void get_options(int argc,char **argv)
test_flags= optarg ? (uint) atoi(optarg) : 0;
opt_endinfo=1;
break;
- case 'S':
- if (!optarg)
- opt_specialflag|= SPECIAL_NO_NEW_FUNC | SPECIAL_SAFE_MODE;
- else if (!strcmp(optarg,"l"))
- my_disable_locking=1;
- else if (!strcmp(optarg,"g"))
- opt_noacl=1;
- else
- {
- fprintf(stderr,"%s: Unrecognized option: %s\n",my_progname,optarg);
- use_help();
- exit(1);
- }
- break;
case (int) OPT_BIG_TABLES:
thd_startup_options|=OPTION_BIG_TABLES;
break;
@@ -3540,6 +3685,14 @@ static void get_options(int argc,char **argv)
opt_update_log=1;
opt_update_logname=optarg; // Use hostname.# if null
break;
+ case (int) OPT_RELAY_LOG_INDEX:
+ opt_relaylog_index_name = optarg;
+ break;
+ case (int) OPT_RELAY_LOG:
+ x_free(opt_relay_logname);
+ if (optarg && optarg[0])
+ opt_relay_logname=my_strdup(optarg,MYF(0));
+ break;
case (int) OPT_BIN_LOG_INDEX:
opt_binlog_index_name = optarg;
break;
@@ -3575,6 +3728,17 @@ static void get_options(int argc,char **argv)
opt_log_slave_updates = 1;
break;
+ case (int) OPT_INIT_RPL_ROLE:
+ {
+ int role;
+ if ((role=find_type(optarg, &rpl_role_typelib, 2)) <= 0)
+ {
+ fprintf(stderr, "Unknown replication role: %s\n", optarg);
+ exit(1);
+ }
+ rpl_status = (role == 1) ? RPL_AUTH_MASTER : RPL_IDLE_SLAVE;
+ break;
+ }
case (int)OPT_REPLICATE_IGNORE_DB:
{
i_string *db = new i_string(optarg);
@@ -3694,12 +3858,14 @@ static void get_options(int argc,char **argv)
break;
case (int) OPT_SKIP_NEW:
opt_specialflag|= SPECIAL_NO_NEW_FUNC;
- default_table_type=DB_TYPE_ISAM;
myisam_delay_key_write=0;
myisam_concurrent_insert=0;
myisam_recover_options= HA_RECOVER_NONE;
my_disable_symlinks=1;
+ my_use_symdir=0;
+ have_symlink=SHOW_OPTION_DISABLED;
ha_open_options&= ~HA_OPEN_ABORT_IF_CRASHED;
+ query_cache_size=0;
break;
case (int) OPT_SAFE:
opt_specialflag|= SPECIAL_SAFE_MODE;
@@ -3717,13 +3883,13 @@ static void get_options(int argc,char **argv)
opt_noacl=1;
break;
case (int) OPT_SKIP_LOCK:
- my_disable_locking=1;
+ my_disable_locking=myisam_single_user= 1;
break;
case (int) OPT_SKIP_HOST_CACHE:
opt_specialflag|= SPECIAL_NO_HOST_CACHE;
break;
case (int) OPT_ENABLE_LOCK:
- my_disable_locking=0;
+ my_disable_locking=myisam_single_user=0;
break;
case (int) OPT_USE_LOCKING:
my_disable_locking=0;
@@ -3734,6 +3900,9 @@ static void get_options(int argc,char **argv)
case (int) OPT_LONG_FORMAT:
opt_specialflag|=SPECIAL_LONG_LOG_FORMAT;
break;
+ case (int) OPT_NO_MIX_TYPE:
+ opt_no_mix_types = 1;
+ break;
case (int) OPT_SKIP_NETWORKING:
opt_disable_networking=1;
mysql_port=0;
@@ -3757,6 +3926,8 @@ static void get_options(int argc,char **argv)
break;
case (int) OPT_SKIP_SYMLINKS:
my_disable_symlinks=1;
+ my_use_symdir=0;
+ have_symlink=SHOW_OPTION_DISABLED;
break;
case (int) OPT_BIND_ADDRESS:
if (optarg && isdigit(optarg[0]))
@@ -3800,7 +3971,10 @@ static void get_options(int argc,char **argv)
break;
#endif
case (int) OPT_FLUSH:
- nisam_flush=myisam_flush=1;
+#ifdef HAVE_ISAM
+ nisam_flush=1;
+#endif
+ myisam_flush=1;
flush_time=0; // No auto flush
break;
case OPT_LOW_PRIORITY_UPDATES:
@@ -3841,6 +4015,11 @@ static void get_options(int argc,char **argv)
charsets_dir = mysql_charsets_dir;
break;
#include "sslopt-case.h"
+ case OPT_DES_KEY_FILE:
+#ifdef HAVE_OPENSSL
+ des_key_file=optarg;
+#endif
+ break;
case OPT_TX_ISOLATION:
{
int type;
@@ -3896,27 +4075,6 @@ static void get_options(int argc,char **argv)
have_berkeley_db=SHOW_OPTION_DISABLED;
#endif
break;
- case OPT_GEMINI_SKIP:
-#ifdef HAVE_GEMINI_DB
- gemini_skip=1;
- have_gemini=SHOW_OPTION_DISABLED;
- break;
- case OPT_GEMINI_RECOVER:
- gemini_recovery_options_str=optarg;
- if ((gemini_recovery_options=
- find_bit_type(optarg, &gemini_recovery_typelib)) == ~(ulong) 0)
- {
- fprintf(stderr, "Unknown option to gemini-recovery: %s\n",optarg);
- exit(1);
- }
- break;
- case OPT_GEMINI_FLUSH_LOG:
- gemini_options |= GEMOPT_FLUSH_LOG;
- break;
- case OPT_GEMINI_UNBUFFERED_IO:
- gemini_options |= GEMOPT_UNBUFFERED_IO;
-#endif
- break;
case OPT_INNODB_SKIP:
#ifdef HAVE_INNOBASE_DB
innodb_skip=1;
@@ -3947,13 +4105,16 @@ static void get_options(int argc,char **argv)
case OPT_INNODB_FAST_SHUTDOWN:
innobase_fast_shutdown= optarg ? test(atoi(optarg)) : 1;
break;
- case OPT_INNODB_UNIX_FILE_FLUSH_METHOD:
+ case OPT_INNODB_FLUSH_METHOD:
innobase_unix_file_flush_method=optarg;
break;
#endif /* HAVE_INNOBASE_DB */
+ case OPT_DO_PSTACK:
+ opt_do_pstack = 1;
+ break;
case OPT_MYISAM_RECOVER:
{
- if (!optarg)
+ if (!optarg || !optarg[0])
{
myisam_recover_options= HA_RECOVER_DEFAULT;
myisam_recover_options_str= myisam_recover_typelib.type_names[0];
@@ -3997,9 +4158,33 @@ static void get_options(int argc,char **argv)
case OPT_MASTER_INFO_FILE:
master_info_file=optarg;
break;
+ case OPT_RELAY_LOG_INFO_FILE:
+ relay_log_info_file=optarg;
+ break;
case OPT_MASTER_PORT:
master_port= atoi(optarg);
break;
+ case OPT_MASTER_SSL:
+ master_ssl=atoi(optarg);
+ break;
+ case OPT_MASTER_SSL_KEY:
+ master_ssl_key=optarg;
+ break;
+ case OPT_MASTER_SSL_CERT:
+ master_ssl_cert=optarg;
+ break;
+ case OPT_REPORT_HOST:
+ report_host=optarg;
+ break;
+ case OPT_REPORT_USER:
+ report_user=optarg;
+ break;
+ case OPT_REPORT_PASSWORD:
+ report_password=optarg;
+ break;
+ case OPT_REPORT_PORT:
+ report_port= atoi(optarg);
+ break;
case OPT_MASTER_CONNECT_RETRY:
master_connect_retry= atoi(optarg);
break;
@@ -4023,7 +4208,7 @@ static void get_options(int argc,char **argv)
exit(1);
}
}
- // Skipp empty arguments (from shell)
+ // Skip empty arguments (from shell)
while (argc != optind && !argv[optind][0])
optind++;
if (argc != optind)
@@ -4032,12 +4217,19 @@ static void get_options(int argc,char **argv)
use_help();
exit(1);
}
+ optind = 0; // setup so that getopt_long() can be called again
fix_paths();
default_table_type_name=ha_table_typelib.type_names[default_table_type-1];
default_tx_isolation_name=tx_isolation_typelib.type_names[default_tx_isolation];
/* To be deleted in MySQL 4.0 */
if (!record_rnd_cache_size)
record_rnd_cache_size=my_default_record_cache_size;
+
+ /* Fix variables that are base 1024*1024 */
+ myisam_max_temp_length= (my_off_t) min(((ulonglong) myisam_max_sort_file_size)*1024*1024, (ulonglong) MAX_FILE_SIZE);
+ myisam_max_extra_temp_length= (my_off_t) min(((ulonglong) myisam_max_extra_sort_file_size)*1024*1024, (ulonglong) MAX_FILE_SIZE);
+
+ myisam_block_size=(uint) 1 << my_bit_log2(opt_myisam_block_size);
}
@@ -4055,12 +4247,34 @@ static char *get_relative_path(const char *path)
}
+/*
+ Fix filename and replace extension where 'dir' is relative to
+ mysql_real_data_home.
+ Return 1 if len(path) > FN_REFLEN
+*/
+
+bool
+fn_format_relative_to_data_home(my_string to, const char *name,
+ const char *dir, const char *extension)
+{
+ char tmp_path[FN_REFLEN];
+ if (!test_if_hard_path(dir))
+ {
+ strxnmov(tmp_path,sizeof(tmp_path)-1, mysql_real_data_home,
+ dir, NullS);
+ dir=tmp_path;
+ }
+ return !fn_format(to, name, dir, extension,
+ MY_REPLACE_EXT | MY_UNPACK_FILENAME | MY_SAFE_PATH);
+}
+
+
static void fix_paths(void)
{
(void) fn_format(mysql_home,mysql_home,"","",16); // Remove symlinks
- convert_dirname(mysql_home);
- convert_dirname(mysql_real_data_home);
- convert_dirname(language);
+ convert_dirname(mysql_home,mysql_home,NullS);
+ convert_dirname(mysql_real_data_home,mysql_real_data_home,NullS);
+ convert_dirname(language,language,NullS);
(void) my_load_path(mysql_home,mysql_home,""); // Resolve current dir
(void) my_load_path(mysql_real_data_home,mysql_real_data_home,mysql_home);
(void) my_load_path(pidfile_name,pidfile_name,mysql_real_data_home);
@@ -4070,7 +4284,7 @@ static void fix_paths(void)
strmov(buff,sharedir); /* purecov: tested */
else
strxmov(buff,mysql_home,sharedir,NullS);
- convert_dirname(buff);
+ convert_dirname(buff,buff,NullS);
(void) my_load_path(language,language,buff);
/* If --character-sets-dir isn't given, use shared library dir */
@@ -4084,11 +4298,16 @@ static void fix_paths(void)
char *tmp= (char*) my_malloc(FN_REFLEN,MYF(MY_FAE));
if (tmp)
{
- strmov(tmp,mysql_tmpdir);
- mysql_tmpdir=tmp;
- convert_dirname(mysql_tmpdir);
- mysql_tmpdir=(char*) my_realloc(mysql_tmpdir,(uint) strlen(mysql_tmpdir)+1,
+ char *end=convert_dirname(tmp, mysql_tmpdir, NullS);
+
+ mysql_tmpdir=(char*) my_realloc(tmp,(uint) (end-tmp)+1,
MYF(MY_HOLD_ON_ERROR));
+ allocated_mysql_tmpdir=mysql_tmpdir;
+ }
+ if (!slave_load_tmpdir)
+ {
+ // no need to check return value, if we fail, my_malloc() never returns
+ slave_load_tmpdir = (char*) my_strdup(mysql_tmpdir, MYF(MY_FAE));
}
}
@@ -4107,16 +4326,17 @@ static uint set_maximum_open_files(uint max_file_limit)
rlimit.rlim_cur=rlimit.rlim_max=max_file_limit;
if (setrlimit(RLIMIT_NOFILE,&rlimit))
{
- sql_print_error("Warning: setrlimit couldn't increase number of open files to more than %ld",
- old_cur); /* purecov: inspected */
+ sql_print_error("Warning: setrlimit couldn't increase number of open files to more than %lu (request: %u)",
+ old_cur, max_file_limit); /* purecov: inspected */
max_file_limit=old_cur;
}
else
{
(void) getrlimit(RLIMIT_NOFILE,&rlimit);
if ((uint) rlimit.rlim_cur != max_file_limit)
- sql_print_error("Warning: setrlimit returned ok, but didn't change limits. Max open files is %ld",
- (ulong) rlimit.rlim_cur); /* purecov: inspected */
+ sql_print_error("Warning: setrlimit returned ok, but didn't change limits. Max open files is %ld (request: %u)",
+ (ulong) rlimit.rlim_cur,
+ max_file_limit); /* purecov: inspected */
max_file_limit=rlimit.rlim_cur;
}
}
@@ -4164,6 +4384,7 @@ static ulong find_bit_type(const char *x, TYPELIB *bit_lib)
DBUG_PRINT("enter",("x: '%s'",x));
found=0;
+ found_end= 0;
pos=(my_string) x;
while (*pos == ' ') pos++;
found_end= *pos == 0;
@@ -4172,7 +4393,7 @@ static ulong find_bit_type(const char *x, TYPELIB *bit_lib)
if (!*(end=strcend(pos,','))) /* Let end point at fieldend */
{
while (end > pos && end[-1] == ' ')
- end--; /* Skipp end-space */
+ end--; /* Skip end-space */
found_end=1;
}
found_int=0; found_count=0;
diff --git a/sql/net_pkg.cc b/sql/net_pkg.cc
index 0b50b34c7bd..64c1b07a493 100644
--- a/sql/net_pkg.cc
+++ b/sql/net_pkg.cc
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -30,6 +30,7 @@ void send_error(NET *net, uint sql_errno, const char *err)
err ? err : net->last_error[0] ?
net->last_error : "NULL"));
+ query_cache_abort(net);
if (thd)
thd->query_error = 1; // needed to catch query errors during replication
if (!err)
@@ -51,6 +52,7 @@ void send_error(NET *net, uint sql_errno, const char *err)
{
if (thd && thd->bootstrap)
{
+ /* In bootstrap it's ok to print on stderr */
fprintf(stderr,"ERROR: %d %s\n",sql_errno,err);
}
DBUG_VOID_RETURN;
@@ -102,9 +104,9 @@ net_printf(NET *net, uint errcode, ...)
DBUG_ENTER("net_printf");
DBUG_PRINT("enter",("message: %u",errcode));
- if(thd) thd->query_error = 1;
- // if we are here, something is wrong :-)
-
+ if (thd)
+ thd->query_error = 1; // if we are here, something is wrong :-)
+ query_cache_abort(net); // Safety
va_start(args,errcode);
format=ER(errcode);
offset= net->return_errno ? 2 : 0;
@@ -119,6 +121,7 @@ net_printf(NET *net, uint errcode, ...)
{
if (thd && thd->bootstrap)
{
+ /* In bootstrap it's ok to print on stderr */
fprintf(stderr,"ERROR: %d %s\n",errcode,text_pos);
thd->fatal_error=1;
}
@@ -142,7 +145,7 @@ send_ok(NET *net,ha_rows affected_rows,ulonglong id,const char *message)
{
if (net->no_send_ok) // hack for re-parsing queries
return;
-
+
char buff[MYSQL_ERRMSG_SIZE+10],*pos;
DBUG_ENTER("send_ok");
buff[0]=0; // No fields
diff --git a/sql/net_serv.cc b/sql/net_serv.cc
index 750079b39a5..811f36bd82e 100644
--- a/sql/net_serv.cc
+++ b/sql/net_serv.cc
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/* Write and read of logical packets to/from socket
** Writes are cached into net_buffer_length big packets.
@@ -22,95 +21,83 @@
** 3 byte length & 1 byte package-number.
*/
+#ifdef EMBEDDED_LIBRARY
+#define net_read_timeout net_read_timeout1
+#define net_write_timeout net_write_timeout1
+#endif
+
#ifdef __WIN__
#include <winsock.h>
#endif
-#include <global.h>
-#include <violite.h>
+#include <my_global.h>
+#include <mysql.h>
+#include <mysql_embed.h>
+#include <mysql_com.h>
+#include <mysqld_error.h>
#include <my_sys.h>
#include <m_string.h>
-#include "mysql.h"
-#include "mysqld_error.h"
+#include <my_net.h>
+#include <violite.h>
#include <signal.h>
#include <errno.h>
-#include <sys/types.h>
+
+/*
+ The following handles the differences when this is linked between the
+ client and the server.
+
+ This gives an error if a too big packet is found
+ The server can change this with the -O switch, but because the client
+ can't normally do this the client should have a bigger max_allowed_packet.
+*/
#ifdef MYSQL_SERVER
ulong max_allowed_packet=65536;
extern ulong net_read_timeout,net_write_timeout;
extern uint test_flags;
+#define USE_QUERY_CACHE
+extern void query_cache_insert(NET *net, const char *packet, ulong length);
#else
ulong max_allowed_packet=16*1024*1024L;
ulong net_read_timeout= NET_READ_TIMEOUT;
ulong net_write_timeout= NET_WRITE_TIMEOUT;
#endif
-ulong net_buffer_length=8192; /* Default length. Enlarged if necessary */
-#if !defined(__WIN__) && !defined(MSDOS)
-#include <sys/socket.h>
-#else
-#undef MYSQL_SERVER /* Win32 can't handle interrupts */
-#endif
-#if !defined(MSDOS) && !defined(__WIN__) && !defined(HAVE_BROKEN_NETINET_INCLUDES) && !defined(__BEOS__)
-#include <netinet/in_systm.h>
-#include <netinet/in.h>
-#include <netinet/ip.h>
-#if !defined(alpha_linux_port)
-#include <netinet/tcp.h>
+#if defined(__WIN__) || !defined(MYSQL_SERVER)
+ /* The following is because alarms doesn't work on windows. */
+#define NO_ALARM
#endif
-#endif
-#include "mysqld_error.h"
-#ifdef MYSQL_SERVER
+
+#ifndef NO_ALARM
#include "my_pthread.h"
-#include "thr_alarm.h"
void sql_print_error(const char *format,...);
#define RETRY_COUNT mysqld_net_retry_count
extern ulong mysqld_net_retry_count;
-#else
-
-#ifdef OS2 /* avoid name conflict */
-#define thr_alarm_t thr_alarm_t_net
-#define ALARM ALARM_net
-#endif
-
-typedef my_bool thr_alarm_t;
-typedef my_bool ALARM;
-#define thr_alarm_init(A) (*(A))=0
-#define thr_alarm_in_use(A) (*(A))
-#define thr_end_alarm(A)
-#define thr_alarm(A,B,C) local_thr_alarm((A),(B),(C))
-inline int local_thr_alarm(my_bool *A,int B __attribute__((unused)),ALARM *C __attribute__((unused)))
-{
- *A=1;
- return 0;
-}
-#define thr_got_alarm(A) 0
-#define RETRY_COUNT 1
-#endif
-
-#ifdef MYSQL_SERVER
-extern ulong bytes_sent, bytes_received;
+extern ulong bytes_sent, bytes_received;
extern pthread_mutex_t LOCK_bytes_sent , LOCK_bytes_received;
#else
#undef statistic_add
#define statistic_add(A,B,C)
-#endif
+#define DONT_USE_THR_ALARM
+#define RETRY_COUNT 1
+#endif /* NO_ALARM */
-/*
-** Give error if a too big packet is found
-** The server can change this with the -O switch, but because the client
-** can't normally do this the client should have a bigger max-buffer.
-*/
+#include "thr_alarm.h"
#define TEST_BLOCKING 8
-static int net_write_buff(NET *net,const char *packet,uint len);
+#define MAX_THREE_BYTES 255L*255L*255L
+
+ulong net_buffer_length=8192; /* Default length. Enlarged if necessary */
+
+static int net_write_buff(NET *net,const char *packet,ulong len);
/* Init with packet info */
int my_net_init(NET *net, Vio* vio)
{
- if (!(net->buff=(uchar*) my_malloc(net_buffer_length,MYF(MY_WME))))
+ if (!(net->buff=(uchar*) my_malloc((uint32) net_buffer_length+
+ NET_HEADER_SIZE + COMP_HEADER_SIZE,
+ MYF(MY_WME))))
return 1;
if (net_buffer_length > max_allowed_packet)
max_allowed_packet=net_buffer_length;
@@ -119,12 +106,13 @@ int my_net_init(NET *net, Vio* vio)
net->no_send_ok = 0;
net->error=0; net->return_errno=0; net->return_status=0;
net->timeout=(uint) net_read_timeout; /* Timeout for read */
- net->pkt_nr=0;
+ net->pkt_nr=net->compress_pkt_nr=0;
net->write_pos=net->read_pos = net->buff;
net->last_error[0]=0;
net->compress=0; net->reading_or_writing=0;
net->where_b = net->remain_in_buf=0;
net->last_errno=0;
+ net->query_cache_query=0;
if (vio != 0) /* If real connection */
{
@@ -157,8 +145,12 @@ static my_bool net_realloc(NET *net, ulong length)
net->last_errno=ER_NET_PACKET_TOO_LARGE;
return 1;
}
- pkt_length = (length+IO_SIZE-1) & ~(IO_SIZE-1);
- if (!(buff=(uchar*) my_realloc((char*) net->buff, pkt_length, MYF(MY_WME))))
+ pkt_length = (length+IO_SIZE-1) & ~(IO_SIZE-1);
+ /* We must allocate some extra bytes for the end 0 and to be able to
+ read big compressed blocks */
+ if (!(buff=(uchar*) my_realloc((char*) net->buff, (uint32) pkt_length +
+ NET_HEADER_SIZE + COMP_HEADER_SIZE,
+ MYF(MY_WME))))
{
net->error=1;
#ifdef MYSQL_SERVER
@@ -175,22 +167,22 @@ static my_bool net_realloc(NET *net, ulong length)
void net_clear(NET *net)
{
-#ifndef EXTRA_DEBUG
- int count; // One may get 'unused' warning
+#if !defined(EXTRA_DEBUG) && !defined(EMBEDDED_LIBRARY)
+ int count; /* One may get 'unused' warn */
bool is_blocking=vio_is_blocking(net->vio);
if (is_blocking)
vio_blocking(net->vio, FALSE);
if (!vio_is_blocking(net->vio)) /* Safety if SSL */
{
while ( (count = vio_read(net->vio, (char*) (net->buff),
- net->max_packet)) > 0)
+ (uint32) net->max_packet)) > 0)
DBUG_PRINT("info",("skipped %d bytes from file: %s",
count,vio_description(net->vio)));
if (is_blocking)
vio_blocking(net->vio, TRUE);
}
#endif /* EXTRA_DEBUG */
- net->pkt_nr=0; /* Ready for new command */
+ net->pkt_nr=net->compress_pkt_nr=0; /* Ready for new command */
net->write_pos=net->buff;
}
@@ -203,9 +195,12 @@ int net_flush(NET *net)
if (net->buff != net->write_pos)
{
error=net_real_write(net,(char*) net->buff,
- (uint) (net->write_pos - net->buff));
+ (ulong) (net->write_pos - net->buff));
net->write_pos=net->buff;
}
+ /* Sync packet number if using compression */
+ if (net->compress)
+ net->pkt_nr=net->compress_pkt_nr;
DBUG_RETURN(error);
}
@@ -214,44 +209,91 @@ int net_flush(NET *net)
** Write something to server/client buffer
*****************************************************************************/
-
/*
** Write a logical packet with packet header
** Format: Packet length (3 bytes), packet number(1 byte)
** When compression is used a 3 byte compression length is added
-** NOTE: If compression is used the original package is destroyed!
+** NOTE: If compression is used the original package is modified!
*/
int
my_net_write(NET *net,const char *packet,ulong len)
{
uchar buff[NET_HEADER_SIZE];
+ /*
+ Big packets are handled by splitting them in packets of MAX_THREE_BYTES
+ length. The last packet is always a packet that is < MAX_THREE_BYTES.
+ (The last packet may even have a lengt of 0)
+ */
+ while (len >= MAX_THREE_BYTES)
+ {
+ const ulong z_size = MAX_THREE_BYTES;
+ int3store(buff, z_size);
+ buff[3]= (uchar) net->pkt_nr++;
+ if (net_write_buff(net, (char*) buff, NET_HEADER_SIZE) ||
+ net_write_buff(net, packet, z_size))
+ return 1;
+ packet += z_size;
+ len-= z_size;
+ }
+ /* Write last packet */
int3store(buff,len);
- buff[3]= (net->compress) ? 0 : (uchar) (net->pkt_nr++);
+ buff[3]= (uchar) net->pkt_nr++;
if (net_write_buff(net,(char*) buff,NET_HEADER_SIZE))
return 1;
return net_write_buff(net,packet,len);
}
+/*
+ Send a command to the server.
+ As the command is part of the first data packet, we have to do some data
+ juggling to put the command in there, without having to create a new
+ packet.
+ This function will split big packets into sub-packets if needed.
+ (Each sub packet can only be 2^24 bytes)
+*/
+
int
net_write_command(NET *net,uchar command,const char *packet,ulong len)
{
+ ulong length=len+1; /* 1 extra byte for command */
uchar buff[NET_HEADER_SIZE+1];
- uint length=len+1; /* 1 extra byte for command */
+ uint header_size=NET_HEADER_SIZE+1;
+ buff[4]=command; /* For first packet */
+ if (length >= MAX_THREE_BYTES)
+ {
+ /* Take into account that we have the command in the first header */
+ len= MAX_THREE_BYTES -1;
+ do
+ {
+ int3store(buff, MAX_THREE_BYTES);
+ buff[3]= (uchar) net->pkt_nr++;
+ if (net_write_buff(net,(char*) buff, header_size) ||
+ net_write_buff(net,packet,len))
+ return 1;
+ packet+= len;
+ length-= MAX_THREE_BYTES;
+ len=MAX_THREE_BYTES;
+ header_size=NET_HEADER_SIZE;
+ } while (length >= MAX_THREE_BYTES);
+ len=length; /* Data left to be written */
+ }
int3store(buff,length);
- buff[3]= (net->compress) ? 0 : (uchar) (net->pkt_nr++);
- buff[4]=command;
- if (net_write_buff(net,(char*) buff,5))
- return 1;
- return test(net_write_buff(net,packet,len) || net_flush(net));
+ buff[3]= (uchar) net->pkt_nr++;
+ return test(net_write_buff(net,(char*) buff,header_size) ||
+ net_write_buff(net,packet,len) || net_flush(net));
}
+/*
+ Caching the data in a local buffer before sending it.
+ One can force the buffer to be flushed with 'net_flush'.
+*/
static int
-net_write_buff(NET *net,const char *packet,uint len)
+net_write_buff(NET *net,const char *packet,ulong len)
{
- uint left_length=(uint) (net->buff_end - net->write_pos);
+ ulong left_length=(ulong) (net->buff_end - net->write_pos);
while (len > left_length)
{
@@ -268,21 +310,30 @@ net_write_buff(NET *net,const char *packet,uint len)
return 0;
}
-/* Read and write using timeouts */
+
+/*
+ Read and write one packet using timeouts.
+ If needed, the packet is compressed before sending.
+*/
int
net_real_write(NET *net,const char *packet,ulong len)
{
- int length;
+ long int length;
char *pos,*end;
thr_alarm_t alarmed;
-#if !defined(__WIN__)
+#ifndef NO_ALARM
ALARM alarm_buff;
#endif
uint retry_count=0;
my_bool net_blocking = vio_is_blocking(net->vio);
DBUG_ENTER("net_real_write");
+#ifdef MYSQL_SERVER
+ if (net->query_cache_query != 0)
+ query_cache_insert(net, packet, len);
+#endif
+
if (net->error == 2)
DBUG_RETURN(-1); /* socket can't be used */
@@ -293,8 +344,8 @@ net_real_write(NET *net,const char *packet,ulong len)
ulong complen;
uchar *b;
uint header_length=NET_HEADER_SIZE+COMP_HEADER_SIZE;
- if (!(b=(uchar*) my_malloc(len + NET_HEADER_SIZE + COMP_HEADER_SIZE,
- MYF(MY_WME))))
+ if (!(b=(uchar*) my_malloc((uint32) len + NET_HEADER_SIZE +
+ COMP_HEADER_SIZE, MYF(MY_WME))))
{
#ifdef MYSQL_SERVER
net->last_errno=ER_OUT_OF_RESOURCES;
@@ -313,25 +364,25 @@ net_real_write(NET *net,const char *packet,ulong len)
}
int3store(&b[NET_HEADER_SIZE],complen);
int3store(b,len);
- b[3]=(uchar) (net->pkt_nr++);
+ b[3]=(uchar) (net->compress_pkt_nr++);
len+= header_length;
packet= (char*) b;
}
#endif /* HAVE_COMPRESS */
/* DBUG_DUMP("net",packet,len); */
-#ifdef MYSQL_SERVER
+#ifndef NO_ALARM
thr_alarm_init(&alarmed);
if (net_blocking)
thr_alarm(&alarmed,(uint) net_write_timeout,&alarm_buff);
#else
alarmed=0;
-#endif /* MYSQL_SERVER */
+#endif /* NO_ALARM */
pos=(char*) packet; end=pos+len;
while (pos != end)
{
- if ((int) (length=vio_write(net->vio,pos,(int) (end-pos))) <= 0)
+ if ((long) (length=vio_write(net->vio,pos,(uint32) (end-pos))) <= 0)
{
my_bool interrupted = vio_should_retry(net->vio);
#if (!defined(__WIN__) && !defined(__EMX__) && !defined(OS2))
@@ -408,14 +459,13 @@ net_real_write(NET *net,const char *packet,ulong len)
** Read something from server/clinet
*****************************************************************************/
-#ifdef MYSQL_SERVER
-
+#ifndef NO_ALARM
/*
Help function to clear the commuication buffer when we get a too
big packet
*/
-static void my_net_skip_rest(NET *net, ulong remain, thr_alarm_t *alarmed)
+static void my_net_skip_rest(NET *net, uint32 remain, thr_alarm_t *alarmed)
{
ALARM alarm_buff;
uint retry_count=0;
@@ -431,21 +481,27 @@ static void my_net_skip_rest(NET *net, ulong remain, thr_alarm_t *alarmed)
if ((int) (length=vio_read(net->vio,(char*) net->buff,remain)) <= 0L)
{
my_bool interrupted = vio_should_retry(net->vio);
- if (!thr_got_alarm(alarmed) && interrupted)
+ if (!thr_got_alarm(&alarmed) && interrupted)
{ /* Probably in MIT threads */
if (retry_count++ < RETRY_COUNT)
continue;
}
return;
}
- remain -=(ulong) length;
- statistic_add(bytes_received,(ulong) length,&LOCK_bytes_received);
+ remain -= (uint32) length;
+ statistic_add(bytes_received,length,&LOCK_bytes_received);
}
}
-#endif /* MYSQL_SERVER */
+#endif /* NO_ALARM */
+
+/*
+ Reads one packet to net->buff + net->where_b
+ Returns length of packet. Long packets are handled by my_net_read().
+ This function reallocates the net->buff buffer if necessary.
+*/
-static uint
+static ulong
my_real_read(NET *net, ulong *complen)
{
uchar *pos;
@@ -453,20 +509,20 @@ my_real_read(NET *net, ulong *complen)
uint i,retry_count=0;
ulong len=packet_error;
thr_alarm_t alarmed;
-#if (!defined(__WIN__) && !defined(__EMX__) && !defined(OS2)) || defined(MYSQL_SERVER)
+#ifndef NO_ALARM
ALARM alarm_buff;
#endif
my_bool net_blocking=vio_is_blocking(net->vio);
- ulong remain= (net->compress ? NET_HEADER_SIZE+COMP_HEADER_SIZE :
- NET_HEADER_SIZE);
+ uint32 remain= (net->compress ? NET_HEADER_SIZE+COMP_HEADER_SIZE :
+ NET_HEADER_SIZE);
*complen = 0;
net->reading_or_writing=1;
thr_alarm_init(&alarmed);
-#ifdef MYSQL_SERVER
+#ifndef NO_ALARM
if (net_blocking)
thr_alarm(&alarmed,net->timeout,&alarm_buff);
-#endif /* MYSQL_SERVER */
+#endif /* NO_ALARM */
pos = net->buff + net->where_b; /* net->packet -4 */
for (i=0 ; i < 2 ; i++)
@@ -535,7 +591,7 @@ my_real_read(NET *net, ulong *complen)
continue;
}
#endif
- DBUG_PRINT("error",("Couldn't read packet: remain: %d errno: %d length: %d alarmed: %d", remain,vio_errno(net->vio),length,alarmed));
+ DBUG_PRINT("error",("Couldn't read packet: remain: %lu errno: %d length: %ld alarmed: %d", remain,vio_errno(net->vio),length,alarmed));
len= packet_error;
net->error=2; /* Close socket */
#ifdef MYSQL_SERVER
@@ -544,7 +600,7 @@ my_real_read(NET *net, ulong *complen)
#endif
goto end;
}
- remain -= (ulong) length;
+ remain -= (uint32) length;
pos+= (ulong) length;
statistic_add(bytes_received,(ulong) length,&LOCK_bytes_received);
}
@@ -556,9 +612,9 @@ my_real_read(NET *net, ulong *complen)
if (net->buff[net->where_b] != (uchar) 255)
{
DBUG_PRINT("error",
- ("Packets out of order (Found: %d, expected %d)",
+ ("Packets out of order (Found: %d, expected %u)",
(int) net->buff[net->where_b + 3],
- (uint) (uchar) net->pkt_nr));
+ net->pkt_nr));
#ifdef EXTRA_DEBUG
fprintf(stderr,"Packets out of order (Found: %d, expected %d)\n",
(int) net->buff[net->where_b + 3],
@@ -571,7 +627,7 @@ my_real_read(NET *net, ulong *complen)
#endif
goto end;
}
- net->pkt_nr++;
+ net->compress_pkt_nr= ++net->pkt_nr;
#ifdef HAVE_COMPRESS
if (net->compress)
{
@@ -581,23 +637,24 @@ my_real_read(NET *net, ulong *complen)
#endif
len=uint3korr(net->buff+net->where_b);
+ if (!len) /* End of big multi-packet */
+ goto end;
helping = max(len,*complen) + net->where_b;
/* The necessary size of net->buff */
if (helping >= net->max_packet)
{
- /* We must allocate one extra byte for the end null */
- if (net_realloc(net,helping+1))
+ if (net_realloc(net,helping))
{
-#ifdef MYSQL_SERVER
+#ifndef NO_ALARM
if (i == 1)
- my_net_skip_rest(net, len, &alarmed);
+ my_net_skip_rest(net, (uint32) len, &alarmed);
#endif
len= packet_error; /* Return error */
goto end;
}
}
pos=net->buff + net->where_b;
- remain = len;
+ remain = (uint32) len;
}
}
@@ -611,7 +668,21 @@ end:
return(len);
}
-uint
+
+/*
+ Read a packet from the client/server and return it without the internal
+ package header.
+ If the packet is the first packet of a multi-packet packet
+ (which is indicated by the length of the packet = 0xffffff) then
+ all sub packets are read and concatenated.
+ If the packet was compressed, its uncompressed and the length of the
+ uncompressed packet is returned.
+
+ The function returns the length of the found packet or packet_error.
+ net->read_pos points to the read data.
+*/
+
+ulong
my_net_read(NET *net)
{
ulong len,complen;
@@ -620,65 +691,137 @@ my_net_read(NET *net)
if (!net->compress)
{
#endif
- len = my_real_read (net,&complen);
+ len = my_real_read(net,&complen);
+ if (len == MAX_THREE_BYTES)
+ {
+ /* First packet of a multi-packet. Concatenate the packets */
+ ulong save_pos = net->where_b;
+ ulong total_length=0;
+ do
+ {
+ net->where_b += len;
+ total_length += len;
+ len = my_real_read (net,&complen);
+ } while (len == MAX_THREE_BYTES);
+ if (len != packet_error)
+ len+= total_length;
+ net->where_b = save_pos;
+ }
net->read_pos = net->buff + net->where_b;
if (len != packet_error)
net->read_pos[len]=0; /* Safeguard for mysql_use_result */
return len;
#ifdef HAVE_COMPRESS
}
- if (net->remain_in_buf)
- net->buff[net->buf_length - net->remain_in_buf]=net->save_char;
- for (;;)
+ else
{
+ /* We are using the compressed protocol */
+
+ ulong buf_length= net->buf_length;
+ ulong start_of_packet= net->buf_length - net->remain_in_buf;
+ ulong first_packet_offset=start_of_packet;
+ uint read_length, multi_byte_packet=0;
+
if (net->remain_in_buf)
{
- uchar *pos = net->buff + net->buf_length - net->remain_in_buf;
- if (net->remain_in_buf >= 4)
+ /* Restore the character that was overwritten by the end 0 */
+ net->buff[start_of_packet]=net->save_char;
+ }
+ else
+ {
+ /* reuse buffer, as there is noting in it that we need */
+ buf_length=start_of_packet=first_packet_offset=0;
+ }
+ for (;;)
+ {
+ ulong packet_len;
+
+ if (buf_length - start_of_packet >= NET_HEADER_SIZE)
{
- net->length = uint3korr(pos);
- if (net->length <= net->remain_in_buf - 4)
+ read_length = uint3korr(net->buff+start_of_packet);
+ if (!read_length)
+ {
+ /* End of multi-byte packet */
+ start_of_packet += NET_HEADER_SIZE;
+ break;
+ }
+ if (read_length + NET_HEADER_SIZE <= buf_length - start_of_packet)
{
- /* We have a full packet */
- len=net->length;
- net->remain_in_buf -= net->length + 4;
- net->read_pos=pos + 4;
- break; /* We have a full packet */
+ if (multi_byte_packet)
+ {
+ /* Remove packet header for second packet */
+ memmove(net->buff + first_packet_offset + start_of_packet,
+ net->buff + first_packet_offset + start_of_packet +
+ NET_HEADER_SIZE,
+ buf_length - start_of_packet);
+ start_of_packet += read_length;
+ buf_length -= NET_HEADER_SIZE;
+ }
+ else
+ start_of_packet+= read_length + NET_HEADER_SIZE;
+
+ if (read_length != MAX_THREE_BYTES) /* last package */
+ {
+ multi_byte_packet= 0; /* No last zero len packet */
+ break;
+ }
+ multi_byte_packet= NET_HEADER_SIZE;
+ /* Move data down to read next data packet after current one */
+ if (first_packet_offset)
+ {
+ memmove(net->buff,net->buff+first_packet_offset,
+ buf_length-first_packet_offset);
+ buf_length-=first_packet_offset;
+ start_of_packet -= first_packet_offset;
+ first_packet_offset=0;
+ }
+ continue;
}
}
/* Move data down to read next data packet after current one */
- if (net->buf_length != net->remain_in_buf)
+ if (first_packet_offset)
{
- memmove(net->buff,pos,net->remain_in_buf);
- net->buf_length=net->remain_in_buf;
+ memmove(net->buff,net->buff+first_packet_offset,
+ buf_length-first_packet_offset);
+ buf_length-=first_packet_offset;
+ start_of_packet -= first_packet_offset;
+ first_packet_offset=0;
}
- net->where_b=net->buf_length;
- }
- else
- {
- net->where_b=0;
- net->buf_length=0;
- }
- if ((len = my_real_read(net,&complen)) == packet_error)
- break;
- if (my_uncompress((byte*) net->buff + net->where_b, &len, &complen))
- {
- len= packet_error;
- net->error=2; /* caller will close socket */
+ net->where_b=buf_length;
+ if ((packet_len = my_real_read(net,&complen)) == packet_error)
+ return packet_error;
+ if (my_uncompress((byte*) net->buff + net->where_b, &packet_len,
+ &complen))
+ {
+ net->error=2; /* caller will close socket */
#ifdef MYSQL_SERVER
- net->last_errno=ER_NET_UNCOMPRESS_ERROR;
+ net->last_errno=ER_NET_UNCOMPRESS_ERROR;
#endif
- break;
+ return packet_error;
+ }
+ buf_length+=packet_len;
}
- net->buf_length+=len;
- net->remain_in_buf+=len;
- }
- if (len != packet_error)
- {
+
+ net->read_pos= net->buff+ first_packet_offset + NET_HEADER_SIZE;
+ net->buf_length= buf_length;
+ net->remain_in_buf= (ulong) (buf_length - start_of_packet);
+ len = ((ulong) (start_of_packet - first_packet_offset) - NET_HEADER_SIZE -
+ multi_byte_packet);
net->save_char= net->read_pos[len]; /* Must be saved */
net->read_pos[len]=0; /* Safeguard for mysql_use_result */
}
+#endif /* HAVE_COMPRESS */
return len;
-#endif
}
+
+int net_request_file(NET* net, const char* fname)
+{
+ char tmp [FN_REFLEN+1],*end;
+ DBUG_ENTER("net_request_file");
+ tmp[0] = (char) 251; /* NULL_LENGTH */
+ end=strnmov(tmp+1,fname,sizeof(tmp)-2);
+ DBUG_RETURN(my_net_write(net,tmp,(uint) (end-tmp)) ||
+ net_flush(net));
+}
+
diff --git a/sql/opt_ft.h b/sql/opt_ft.h
index dcbbb8abcec..b055edc107c 100644
--- a/sql/opt_ft.h
+++ b/sql/opt_ft.h
@@ -29,7 +29,7 @@ public:
TABLE_REF *ref;
FT_SELECT(TABLE *table, TABLE_REF *tref) :
- QUICK_SELECT (table,tref->key,1), ref(tref) {}
+ QUICK_SELECT (table,tref->key,1), ref(tref) { init(); }
int init() { return error=file->ft_init(); }
int get_next() { return error=file->ft_read(record); }
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index b95b97d670f..c3f4c91b718 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -33,6 +33,7 @@
#include <m_ctype.h>
#include <nisam.h>
#include "sql_select.h"
+#include <assert.h>
#ifndef EXTRA_DEBUG
@@ -279,21 +280,21 @@ public:
typedef struct st_qsel_param {
- uint baseflag,keys,max_key_part;
- table_map prev_tables,read_tables,current_table;
TABLE *table;
- bool quick; // Don't calulate possible keys
KEY_PART *key_parts,*key_parts_end,*key[MAX_KEY];
+ MEM_ROOT *mem_root;
+ table_map prev_tables,read_tables,current_table;
+ uint baseflag,keys,max_key_part;
uint real_keynr[MAX_KEY];
char min_key[MAX_KEY_LENGTH+MAX_FIELD_WIDTH],
max_key[MAX_KEY_LENGTH+MAX_FIELD_WIDTH];
+ bool quick; // Don't calulate possible keys
} PARAM;
-
static SEL_TREE * get_mm_parts(PARAM *param,Field *field,
Item_func::Functype type,Item *value,
Item_result cmp_type);
-static SEL_ARG *get_mm_leaf(Field *field,KEY_PART *key_part,
+static SEL_ARG *get_mm_leaf(PARAM *param,Field *field,KEY_PART *key_part,
Item_func::Functype type,Item *value);
static bool like_range(const char *ptr,uint length,char wild_prefix,
uint field_length, char *min_str,char *max_str,
@@ -382,7 +383,7 @@ SQL_SELECT::~SQL_SELECT()
#undef index // Fix for Unixware 7
QUICK_SELECT::QUICK_SELECT(TABLE *table,uint key_nr,bool no_alloc)
- :error(0),index(key_nr),max_used_key_length(0),head(table),
+ :dont_free(0),error(0),index(key_nr),max_used_key_length(0),head(table),
it(ranges),range(0)
{
if (!no_alloc)
@@ -399,13 +400,11 @@ QUICK_SELECT::QUICK_SELECT(TABLE *table,uint key_nr,bool no_alloc)
QUICK_SELECT::~QUICK_SELECT()
{
- file->index_end();
- free_root(&alloc,MYF(0));
-}
-
-int QUICK_SELECT::init()
-{
- return error=file->index_init(index);
+ if (!dont_free)
+ {
+ file->index_end();
+ free_root(&alloc,MYF(0));
+ }
}
QUICK_RANGE::QUICK_RANGE()
@@ -533,7 +532,7 @@ static int sel_cmp(Field *field, char *a,char *b,uint8 a_flag,uint8 b_flag)
}
if (*a)
goto end; // NULL where equal
- a++; b++; // Skipp NULL marker
+ a++; b++; // Skip NULL marker
}
cmp=field->key_cmp((byte*) a,(byte*) b);
if (cmp) return cmp < 0 ? -1 : 1; // The values differed
@@ -586,6 +585,9 @@ int SQL_SELECT::test_quick_select(key_map keys_to_use, table_map prev_tables,
uint idx;
double scan_time;
DBUG_ENTER("test_quick_select");
+ DBUG_PRINT("enter",("keys_to_use: %lu prev_tables: %lu const_tables: %lu",
+ (ulong) keys_to_use, (ulong) prev_tables,
+ (ulong) const_tables));
delete quick;
quick=0;
@@ -604,7 +606,7 @@ int SQL_SELECT::test_quick_select(key_map keys_to_use, table_map prev_tables,
if (limit < records)
read_time=(double) records+scan_time+1; // Force to use index
else if (read_time <= 2.0 && !force_quick_range)
- DBUG_RETURN(0); /* No nead for quick select */
+ DBUG_RETURN(0); /* No need for quick select */
DBUG_PRINT("info",("Time to scan table: %ld",(long) read_time));
@@ -623,6 +625,7 @@ int SQL_SELECT::test_quick_select(key_map keys_to_use, table_map prev_tables,
param.current_table= head->map;
param.table=head;
param.keys=0;
+ param.mem_root= &alloc;
current_thd->no_errors=1; // Don't warn about NULL
init_sql_alloc(&alloc,2048,0);
@@ -891,7 +894,7 @@ get_mm_parts(PARAM *param,Field *field, Item_func::Functype type,Item *value,
tree=new SEL_TREE();
if (!value || !(value->used_tables() & ~param->read_tables))
{
- sel_arg=get_mm_leaf(key_part->field,key_part,type,value);
+ sel_arg=get_mm_leaf(param,key_part->field,key_part,type,value);
if (!sel_arg)
continue;
if (sel_arg->type == SEL_ARG::IMPOSSIBLE)
@@ -911,7 +914,7 @@ get_mm_parts(PARAM *param,Field *field, Item_func::Functype type,Item *value,
static SEL_ARG *
-get_mm_leaf(Field *field,KEY_PART *key_part,
+get_mm_leaf(PARAM *param, Field *field, KEY_PART *key_part,
Item_func::Functype type,Item *value)
{
uint maybe_null=(uint) field->real_maybe_null();
@@ -956,7 +959,7 @@ get_mm_leaf(Field *field,KEY_PART *key_part,
field_length=length;
}
length+=offset;
- if (!(min_str= (char*) sql_alloc(length*2)))
+ if (!(min_str= (char*) alloc_root(param->mem_root, length*2)))
DBUG_RETURN(0);
max_str=min_str+length;
if (maybe_null)
@@ -1023,7 +1026,8 @@ get_mm_leaf(Field *field,KEY_PART *key_part,
if (type == Item_func::EQUAL_FUNC)
{
/* convert column_name <=> NULL -> column_name IS NULL */
- char *str= (char*) sql_alloc(1); // Get local copy of key
+ // Get local copy of key
+ char *str= (char*) alloc_root(param->mem_root,1);
if (!*str)
DBUG_RETURN(0);
*str = 1;
@@ -1032,7 +1036,8 @@ get_mm_leaf(Field *field,KEY_PART *key_part,
DBUG_RETURN(&null_element); // NULL is never true
}
// Get local copy of key
- char *str= (char*) sql_alloc(key_part->part_length+maybe_null);
+ char *str= (char*) alloc_root(param->mem_root,
+ key_part->part_length+maybe_null);
if (!str)
DBUG_RETURN(0);
if (maybe_null)
@@ -1098,7 +1103,7 @@ static bool like_range(const char *ptr,uint ptr_length,char escape,
{
if (*ptr == escape && ptr+1 != end)
{
- ptr++; // Skipp escape
+ ptr++; // Skip escape
*min_str++= *max_str++ = *ptr;
continue;
}
@@ -2232,7 +2237,7 @@ get_quick_select(PARAM *param,uint idx,SEL_ARG *key_tree)
else
{
quick->key_parts=(KEY_PART*)
- sql_memdup(param->key[idx],
+ memdup_root(&quick->alloc,(char*) param->key[idx],
sizeof(KEY_PART)*
param->table->key_info[param->real_keynr[idx]].key_parts);
}
@@ -2403,7 +2408,7 @@ QUICK_SELECT *get_quick_select_for_ref(TABLE *table, TABLE_REF *ref)
(key_info->flags & HA_NOSAME)) ? EQ_RANGE : 0);
if (!(quick->key_parts=key_part=(KEY_PART *)
- sql_alloc(sizeof(KEY_PART)*ref->key_parts)))
+ alloc_root(&quick->alloc,sizeof(KEY_PART)*ref->key_parts)))
goto err;
for (part=0 ; part < ref->key_parts ;part++,key_part++)
@@ -2455,8 +2460,8 @@ int QUICK_SELECT::get_next()
if ((error=file->index_first(record)))
DBUG_RETURN(error); // Empty table
if (cmp_next(range) == 0)
- DBUG_RETURN(0); // No matching records
- range=0; // To next range
+ DBUG_RETURN(0);
+ range=0; // No matching records; go to next range
continue;
}
if ((result = file->index_read(record,(byte*) range->min_key,
@@ -2516,6 +2521,224 @@ int QUICK_SELECT::cmp_next(QUICK_RANGE *range)
return (range->flag & NEAR_MAX) ? 1 : 0; // Exact match
}
+
+/*
+ * This is a hack: we inherit from QUICK_SELECT so that we can use the
+ * get_next() interface, but we have to hold a pointer to the original
+ * QUICK_SELECT because its data are used all over the place. What
+ * should be done is to factor out the data that is needed into a base
+ * class (QUICK_SELECT), and then have two subclasses (_ASC and _DESC)
+ * which handle the ranges and implement the get_next() function. But
+ * for now, this seems to work right at least.
+ */
+
+QUICK_SELECT_DESC::QUICK_SELECT_DESC(QUICK_SELECT *q, uint used_key_parts)
+ : QUICK_SELECT(*q), rev_it(rev_ranges)
+{
+ bool not_read_after_key = file->option_flag() & HA_NOT_READ_AFTER_KEY;
+ QUICK_RANGE *r;
+
+ for (r = it++; r; r = it++)
+ {
+ rev_ranges.push_front(r);
+ if (not_read_after_key && range_reads_after_key(r) ||
+ test_if_null_range(r,used_key_parts))
+ {
+ it.rewind(); // Reset range
+ error = HA_ERR_UNSUPPORTED;
+ dont_free=1; // Don't free memory from 'q'
+ return;
+ }
+ }
+ /* Remove EQ_RANGE flag for keys that are not using the full key */
+ for (r = rev_it++; r; r = rev_it++)
+ {
+ if ((r->flag & EQ_RANGE) &&
+ head->key_info[index].key_length != r->max_length)
+ r->flag&= ~EQ_RANGE;
+ }
+ rev_it.rewind();
+ q->dont_free=1; // Don't free shared mem
+ delete q;
+}
+
+
+int QUICK_SELECT_DESC::get_next()
+{
+ DBUG_ENTER("QUICK_SELECT_DESC::get_next");
+
+ /* The max key is handled as follows:
+ * - if there is NO_MAX_RANGE, start at the end and move backwards
+ * - if it is an EQ_RANGE, which means that max key covers the entire
+ * key, go directly to the key and read through it (sorting backwards is
+ * same as sorting forwards)
+ * - if it is NEAR_MAX, go to the key or next, step back once, and
+ * move backwards
+ * - otherwise (not NEAR_MAX == include the key), go after the key,
+ * step back once, and move backwards
+ */
+
+ for (;;)
+ {
+ int result;
+ if (range)
+ { // Already read through key
+ result = ((range->flag & EQ_RANGE)
+ ? file->index_next_same(record, (byte*) range->min_key,
+ range->min_length) :
+ file->index_prev(record));
+ if (!result)
+ {
+ if (cmp_prev(*rev_it.ref()) == 0)
+ DBUG_RETURN(0);
+ }
+ else if (result != HA_ERR_END_OF_FILE)
+ DBUG_RETURN(result);
+ }
+
+ if (!(range=rev_it++))
+ DBUG_RETURN(HA_ERR_END_OF_FILE); // All ranges used
+
+ if (range->flag & NO_MAX_RANGE) // Read last record
+ {
+ int error;
+ if ((error=file->index_last(record)))
+ DBUG_RETURN(error); // Empty table
+ if (cmp_prev(range) == 0)
+ DBUG_RETURN(0);
+ range=0; // No matching records; go to next range
+ continue;
+ }
+
+ if (range->flag & EQ_RANGE)
+ {
+ result = file->index_read(record, (byte*) range->max_key,
+ range->max_length, HA_READ_KEY_EXACT);
+ }
+ else
+ {
+ DBUG_ASSERT(range->flag & NEAR_MAX || range_reads_after_key(range));
+ /* Note: even if max_key is only a prefix, HA_READ_AFTER_KEY will
+ * do the right thing - go past all keys which match the prefix */
+ result=file->index_read(record, (byte*) range->max_key,
+ range->max_length,
+ ((range->flag & NEAR_MAX) ?
+ HA_READ_KEY_EXACT : HA_READ_AFTER_KEY));
+ result = file->index_prev(record);
+ }
+ if (result)
+ {
+ if (result != HA_ERR_KEY_NOT_FOUND)
+ DBUG_RETURN(result);
+ range=0; // Not found, to next range
+ continue;
+ }
+ if (cmp_prev(range) == 0)
+ {
+ if (range->flag == (UNIQUE_RANGE | EQ_RANGE))
+ range = 0; // Stop searching
+ DBUG_RETURN(0); // Found key is in range
+ }
+ range = 0; // To next range
+ }
+}
+
+/*
+ * Returns 0 if found key is inside range (found key >= range->min_key).
+ */
+int QUICK_SELECT_DESC::cmp_prev(QUICK_RANGE *range)
+{
+ if (range->flag & NO_MIN_RANGE)
+ return (0); /* key can't be to small */
+
+ KEY_PART *key_part = key_parts;
+ for (char *key = range->min_key, *end = key + range->min_length;
+ key < end;
+ key += key_part++->part_length)
+ {
+ int cmp;
+ if (key_part->null_bit)
+ {
+ // this key part allows null values; NULL is lower than everything else
+ if (*key++)
+ {
+ // the range is expecting a null value
+ if (!key_part->field->is_null())
+ return 0; // not null -- still inside the range
+ continue; // null -- exact match, go to next key part
+ }
+ else if (key_part->field->is_null())
+ return 1; // null -- outside the range
+ }
+ if ((cmp = key_part->field->key_cmp((byte*) key,
+ key_part->part_length)) > 0)
+ return 0;
+ if (cmp < 0)
+ return 1;
+ }
+ return (range->flag & NEAR_MIN) ? 1 : 0; // Exact match
+}
+
+/*
+ * True if this range will require using HA_READ_AFTER_KEY
+ See comment in get_next() about this
+ */
+
+bool QUICK_SELECT_DESC::range_reads_after_key(QUICK_RANGE *range)
+{
+ return ((range->flag & (NO_MAX_RANGE | NEAR_MAX)) ||
+ !(range->flag & EQ_RANGE) ||
+ head->key_info[index].key_length != range->max_length) ? 1 : 0;
+}
+
+/* True if we are reading over a key that may have a NULL value */
+
+bool QUICK_SELECT_DESC::test_if_null_range(QUICK_RANGE *range,
+ uint used_key_parts)
+{
+ uint offset,end;
+ KEY_PART *key_part = key_parts,
+ *key_part_end= key_part+used_key_parts;
+
+ for (offset= 0, end = min(range->min_length, range->max_length) ;
+ offset < end && key_part != key_part_end ;
+ offset += key_part++->part_length)
+ {
+ uint null_length=test(key_part->null_bit);
+ if (!memcmp((char*) range->min_key+offset, (char*) range->max_key+offset,
+ key_part->part_length + null_length))
+ {
+ offset+=null_length;
+ continue;
+ }
+ if (null_length && range->min_key[offset])
+ return 1; // min_key is null and max_key isn't
+ // Range doesn't cover NULL. This is ok if there is no more null parts
+ break;
+ }
+ /*
+ If the next min_range is > NULL, then we can use this, even if
+ it's a NULL key
+ Example: SELECT * FROM t1 WHERE a = 2 AND b >0 ORDER BY a DESC,b DESC;
+
+ */
+ if (key_part != key_part_end && key_part->null_bit)
+ {
+ if (offset >= range->min_length || range->min_key[offset])
+ return 1; // Could be null
+ key_part++;
+ }
+ /*
+ If any of the key parts used in the ORDER BY could be NULL, we can't
+ use the key to sort the data.
+ */
+ for (; key_part != key_part_end ; key_part++)
+ if (key_part->null_bit)
+ return 1; // Covers null part
+ return 0;
+}
+
+
/*****************************************************************************
** Print a quick range for debugging
** TODO:
diff --git a/sql/opt_range.h b/sql/opt_range.h
index 247dd260817..83eb10235ea 100644
--- a/sql/opt_range.h
+++ b/sql/opt_range.h
@@ -48,15 +48,16 @@ class QUICK_RANGE :public Sql_alloc {
uint flag_arg)
: min_key((char*) sql_memdup(min_key_arg,min_length_arg+1)),
max_key((char*) sql_memdup(max_key_arg,max_length_arg+1)),
- min_length(min_length_arg),
- max_length(max_length_arg),
- flag(flag_arg)
+ min_length((uint16) min_length_arg),
+ max_length((uint16) max_length_arg),
+ flag((uint16) flag_arg)
{}
};
+
class QUICK_SELECT {
public:
- bool next;
+ bool next,dont_free;
int error;
uint index,max_used_key_length;
TABLE *head;
@@ -74,12 +75,27 @@ public:
QUICK_SELECT(TABLE *table,uint index_arg,bool no_alloc=0);
virtual ~QUICK_SELECT();
void reset(void) { next=0; it.rewind(); }
- virtual int init();
+ int init() { return error=file->index_init(index); }
virtual int get_next();
int cmp_next(QUICK_RANGE *range);
bool unique_key_range();
};
+
+class QUICK_SELECT_DESC: public QUICK_SELECT
+{
+public:
+ QUICK_SELECT_DESC(QUICK_SELECT *q, uint used_key_parts);
+ int get_next();
+private:
+ int cmp_prev(QUICK_RANGE *range);
+ bool range_reads_after_key(QUICK_RANGE *range);
+ bool test_if_null_range(QUICK_RANGE *range, uint used_key_parts);
+ void reset(void) { next=0; rev_it.rewind(); }
+ List<QUICK_RANGE> rev_ranges;
+ List_iterator<QUICK_RANGE> rev_it;
+};
+
class SQL_SELECT :public Sql_alloc {
public:
QUICK_SELECT *quick; // If quick-select used
diff --git a/sql/opt_sum.cc b/sql/opt_sum.cc
index df49d52d54a..78878c40b37 100644
--- a/sql/opt_sum.cc
+++ b/sql/opt_sum.cc
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -32,7 +32,7 @@ static bool find_range_key(TABLE_REF *ref, Field* field,COND *cond);
int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds)
{
- List_iterator<Item> it(all_fields);
+ List_iterator_fast<Item> it(all_fields);
int const_result=1;
bool recalc_const_item=0;
table_map removed_tables=0;
@@ -205,7 +205,7 @@ uint count_table_entries(COND *cond,TABLE *table)
if (((Item_cond*) cond)->functype() == Item_func::COND_OR_FUNC)
return (cond->used_tables() & table->map) ? MAX_REF_PARTS+1 : 0;
- List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
+ List_iterator_fast<Item> li(*((Item_cond*) cond)->argument_list());
Item *item;
uint count=0;
while ((item=li++))
@@ -250,7 +250,7 @@ bool part_of_cond(COND *cond,Field *field)
if (((Item_cond*) cond)->functype() == Item_func::COND_OR_FUNC)
return 0; // Already checked
- List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
+ List_iterator_fast<Item> li(*((Item_cond*) cond)->argument_list());
Item *item;
while ((item=li++))
{
@@ -291,7 +291,7 @@ bool part_of_cond(COND *cond,Field *field)
static bool find_range_key(TABLE_REF *ref, Field* field, COND *cond)
{
if (!(field->flags & PART_KEY_FLAG))
- return 0; // Not part of a key. Skipp it
+ return 0; // Not part of a key. Skip it
TABLE *table=field->table;
if (table->file->option_flag() & HA_WRONG_ASCII_ORDER)
@@ -299,13 +299,14 @@ static bool find_range_key(TABLE_REF *ref, Field* field, COND *cond)
uint idx=0;
/* Check if some key has field as first key part */
- if (field->key_start && (! cond || ! (cond->used_tables() & table->map)))
+ if ((field->key_start & field->table->keys_in_use_for_query) &&
+ (! cond || ! (cond->used_tables() & table->map)))
{
for (key_map key=field->key_start ; !(key & 1) ; idx++)
key>>=1;
ref->key_length=0;
ref->key=idx;
- if (field->part_of_key & ((table_map) 1 << idx))
+ if (field->part_of_key & ((key_map) 1 << idx))
{
table->key_read=1;
table->file->extra(HA_EXTRA_KEYREAD);
@@ -350,7 +351,7 @@ static bool find_range_key(TABLE_REF *ref, Field* field, COND *cond)
{
ref->key_length= (uint) (key_ptr-ref->key_buff);
ref->key=idx;
- if (field->part_of_key & ((table_map) 1 << idx))
+ if (field->part_of_key & ((key_map) 1 << idx))
{
table->key_read=1;
table->file->extra(HA_EXTRA_KEYREAD);
diff --git a/sql/password.c b/sql/password.c
index 1c88aabcce2..48181ea18e6 100644
--- a/sql/password.c
+++ b/sql/password.c
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -34,7 +34,7 @@
This saves a hashed number as a string in the password field.
*****************************************************************************/
-#include <global.h>
+#include <my_global.h>
#include <my_sys.h>
#include <m_string.h>
#include "mysql.h"
diff --git a/sql/procedure.cc b/sql/procedure.cc
index 526bbe0feab..437bd82d6e5 100644
--- a/sql/procedure.cc
+++ b/sql/procedure.cc
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
diff --git a/sql/procedure.h b/sql/procedure.h
index 1583f1169ce..db0e0b7f9e2 100644
--- a/sql/procedure.h
+++ b/sql/procedure.h
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
diff --git a/sql/records.cc b/sql/records.cc
index d436f4f58fe..f156fdaf406 100644
--- a/sql/records.cc
+++ b/sql/records.cc
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -51,12 +51,7 @@ void init_read_record(READ_RECORD *info,THD *thd, TABLE *table,
tempfile= &select->file;
else
tempfile= table->io_cache;
- if (select && select->quick && (! tempfile || !tempfile->buffer))
- {
- DBUG_PRINT("info",("using rr_quick"));
- info->read_record=rr_quick;
- }
- else if (tempfile && my_b_inited(tempfile)) // Test if ref-records was used
+ if (tempfile && my_b_inited(tempfile)) // Test if ref-records was used
{
DBUG_PRINT("info",("using rr_from_tempfile"));
info->read_record=rr_from_tempfile;
@@ -84,8 +79,14 @@ void init_read_record(READ_RECORD *info,THD *thd, TABLE *table,
}
}
}
+ else if (select && select->quick)
+ {
+ DBUG_PRINT("info",("using rr_quick"));
+ info->read_record=rr_quick;
+ }
else if (table->record_pointers)
{
+ DBUG_PRINT("info",("using record_pointers"));
table->file->rnd_init(0);
info->cache_pos=table->record_pointers;
info->cache_end=info->cache_pos+ table->found_records*info->ref_length;
diff --git a/sql/repl_failsafe.cc b/sql/repl_failsafe.cc
new file mode 100644
index 00000000000..257418d1682
--- /dev/null
+++ b/sql/repl_failsafe.cc
@@ -0,0 +1,853 @@
+/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB & Sasha
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+// Sasha Pachev <sasha@mysql.com> is currently in charge of this file
+
+#include "mysql_priv.h"
+#include "repl_failsafe.h"
+#include "sql_repl.h"
+#include "slave.h"
+#include "sql_acl.h"
+#include "mini_client.h"
+#include "log_event.h"
+#include <mysql.h>
+#include <thr_alarm.h>
+
+#define SLAVE_LIST_CHUNK 128
+#define SLAVE_ERRMSG_SIZE (FN_REFLEN+64)
+
+
+RPL_STATUS rpl_status=RPL_NULL;
+pthread_mutex_t LOCK_rpl_status;
+pthread_cond_t COND_rpl_status;
+HASH slave_list;
+extern const char* any_db;
+
+const char *rpl_role_type[] = {"MASTER","SLAVE",NullS};
+TYPELIB rpl_role_typelib = {array_elements(rpl_role_type)-1,"",
+ rpl_role_type};
+
+const char* rpl_status_type[] = {"AUTH_MASTER","ACTIVE_SLAVE","IDLE_SLAVE",
+ "LOST_SOLDIER","TROOP_SOLDIER",
+ "RECOVERY_CAPTAIN","NULL",NullS};
+TYPELIB rpl_status_typelib= {array_elements(rpl_status_type)-1,"",
+ rpl_status_type};
+
+static Slave_log_event* find_slave_event(IO_CACHE* log,
+ const char* log_file_name,
+ char* errmsg);
+
+static int init_failsafe_rpl_thread(THD* thd)
+{
+ DBUG_ENTER("init_failsafe_rpl_thread");
+ thd->system_thread = thd->bootstrap = 1;
+ thd->client_capabilities = 0;
+ my_net_init(&thd->net, 0);
+ thd->net.timeout = slave_net_timeout;
+ thd->max_packet_length=thd->net.max_packet;
+ thd->master_access= ~0;
+ thd->priv_user = 0;
+ thd->system_thread = 1;
+ pthread_mutex_lock(&LOCK_thread_count);
+ thd->thread_id = thread_id++;
+ pthread_mutex_unlock(&LOCK_thread_count);
+
+ if (init_thr_lock() ||
+ my_pthread_setspecific_ptr(THR_THD, thd) ||
+ my_pthread_setspecific_ptr(THR_MALLOC, &thd->mem_root) ||
+ my_pthread_setspecific_ptr(THR_NET, &thd->net))
+ {
+ close_connection(&thd->net,ER_OUT_OF_RESOURCES); // is this needed?
+ end_thread(thd,0);
+ DBUG_RETURN(-1);
+ }
+
+ thd->mysys_var=my_thread_var;
+ thd->dbug_thread_id=my_thread_id();
+#if !defined(__WIN__) && !defined(OS2)
+ sigset_t set;
+ VOID(sigemptyset(&set)); // Get mask in use
+ VOID(pthread_sigmask(SIG_UNBLOCK,&set,&thd->block_signals));
+#endif
+
+ thd->mem_root.free=thd->mem_root.used=0;
+ if (thd->max_join_size == (ulong) ~0L)
+ thd->options |= OPTION_BIG_SELECTS;
+
+ thd->proc_info="Thread initialized";
+ thd->version=refresh_version;
+ thd->set_time();
+ DBUG_RETURN(0);
+}
+
+void change_rpl_status(RPL_STATUS from_status, RPL_STATUS to_status)
+{
+ pthread_mutex_lock(&LOCK_rpl_status);
+ if (rpl_status == from_status || rpl_status == RPL_ANY)
+ rpl_status = to_status;
+ pthread_cond_signal(&COND_rpl_status);
+ pthread_mutex_unlock(&LOCK_rpl_status);
+}
+
+#define get_object(p, obj) \
+{\
+ uint len = (uint)*p++; \
+ if (p + len > p_end || len >= sizeof(obj)) \
+ goto err; \
+ strmake(obj,(char*) p,len); \
+ p+= len; \
+}\
+
+static inline int cmp_master_pos(Slave_log_event* sev, LEX_MASTER_INFO* mi)
+{
+ return cmp_master_pos(sev->master_log, sev->master_pos, mi->log_file_name,
+ mi->pos);
+}
+
+void unregister_slave(THD* thd, bool only_mine, bool need_mutex)
+{
+ if (need_mutex)
+ pthread_mutex_lock(&LOCK_slave_list);
+ if (thd->server_id)
+ {
+ SLAVE_INFO* old_si;
+ if ((old_si = (SLAVE_INFO*)hash_search(&slave_list,
+ (byte*)&thd->server_id, 4)) &&
+ (!only_mine || old_si->thd == thd))
+ hash_delete(&slave_list, (byte*)old_si);
+ }
+ if (need_mutex)
+ pthread_mutex_unlock(&LOCK_slave_list);
+}
+
+int register_slave(THD* thd, uchar* packet, uint packet_length)
+{
+ SLAVE_INFO *si;
+ int res = 1;
+ uchar* p = packet, *p_end = packet + packet_length;
+
+ if (check_access(thd, FILE_ACL, any_db))
+ return 1;
+
+ if (!(si = (SLAVE_INFO*)my_malloc(sizeof(SLAVE_INFO), MYF(MY_WME))))
+ goto err;
+
+ thd->server_id = si->server_id = uint4korr(p);
+ p += 4;
+ get_object(p,si->host);
+ get_object(p,si->user);
+ get_object(p,si->password);
+ si->port = uint2korr(p);
+ p += 2;
+ si->rpl_recovery_rank = uint4korr(p);
+ p += 4;
+ if (!(si->master_id = uint4korr(p)))
+ si->master_id = server_id;
+ si->thd = thd;
+ pthread_mutex_lock(&LOCK_slave_list);
+
+ unregister_slave(thd,0,0);
+ res = hash_insert(&slave_list, (byte*) si);
+ pthread_mutex_unlock(&LOCK_slave_list);
+ return res;
+
+err:
+ if (si)
+ my_free((gptr) si, MYF(MY_WME));
+ return res;
+}
+
+static uint32* slave_list_key(SLAVE_INFO* si, uint* len,
+ my_bool not_used __attribute__((unused)))
+{
+ *len = 4;
+ return &si->server_id;
+}
+
+static void slave_info_free(void *s)
+{
+ my_free((gptr) s, MYF(MY_WME));
+}
+
+void init_slave_list()
+{
+ hash_init(&slave_list, SLAVE_LIST_CHUNK, 0, 0,
+ (hash_get_key) slave_list_key, slave_info_free, 0);
+ pthread_mutex_init(&LOCK_slave_list, MY_MUTEX_INIT_FAST);
+}
+
+void end_slave_list()
+{
+ /* No protection by a mutex needed as we are only called at shutdown */
+ if (hash_inited(&slave_list))
+ {
+ hash_free(&slave_list);
+ pthread_mutex_destroy(&LOCK_slave_list);
+ }
+}
+
+static int find_target_pos(LEX_MASTER_INFO* mi, IO_CACHE* log, char* errmsg)
+{
+ uint32 log_pos = (uint32) mi->pos;
+ uint32 target_server_id = mi->server_id;
+
+ for (;;)
+ {
+ Log_event* ev;
+ if (!(ev = Log_event::read_log_event(log, (pthread_mutex_t*)0,
+ 0)))
+ {
+ if (log->error > 0)
+ strmov(errmsg, "Binary log truncated in the middle of event");
+ else if (log->error < 0)
+ strmov(errmsg, "I/O error reading binary log");
+ else
+ strmov(errmsg, "Could not find target event in the binary log");
+ return 1;
+ }
+
+ if (ev->log_pos == log_pos && ev->server_id == target_server_id)
+ {
+ delete ev;
+ mi->pos = my_b_tell(log);
+ return 0;
+ }
+
+ delete ev;
+ }
+}
+
+
+int translate_master(THD* thd, LEX_MASTER_INFO* mi, char* errmsg)
+{
+ LOG_INFO linfo;
+ char search_file_name[FN_REFLEN],last_log_name[FN_REFLEN];
+ IO_CACHE log;
+ File file = -1, last_file = -1;
+ pthread_mutex_t *log_lock;
+ const char* errmsg_p;
+ Slave_log_event* sev = 0;
+ my_off_t last_pos = 0;
+ int error = 1;
+ int cmp_res;
+ LINT_INIT(cmp_res);
+
+ if (!mysql_bin_log.is_open())
+ {
+ strmov(errmsg,"Binary log is not open");
+ return 1;
+ }
+
+ if (!server_id_supplied)
+ {
+ strmov(errmsg, "Misconfigured master - server id was not set");
+ return 1;
+ }
+
+ linfo.index_file_offset = 0;
+
+
+ search_file_name[0] = 0;
+
+ if (mysql_bin_log.find_first_log(&linfo, search_file_name))
+ {
+ strmov(errmsg,"Could not find first log");
+ return 1;
+ }
+ thd->current_linfo = &linfo;
+
+ bzero((char*) &log,sizeof(log));
+ log_lock = mysql_bin_log.get_log_lock();
+ pthread_mutex_lock(log_lock);
+
+ for (;;)
+ {
+ if ((file=open_binlog(&log, linfo.log_file_name, &errmsg_p)) < 0)
+ {
+ strmov(errmsg, errmsg_p);
+ goto err;
+ }
+
+ if (!(sev = find_slave_event(&log, linfo.log_file_name, errmsg)))
+ goto err;
+
+ cmp_res = cmp_master_pos(sev, mi);
+ delete sev;
+
+ if (!cmp_res)
+ {
+ /* Copy basename */
+ fn_format(mi->log_file_name, linfo.log_file_name, "","",1);
+ mi->pos = my_b_tell(&log);
+ goto mi_inited;
+ }
+ else if (cmp_res > 0)
+ {
+ if (!last_pos)
+ {
+ strmov(errmsg,
+ "Slave event in first log points past the target position");
+ goto err;
+ }
+ end_io_cache(&log);
+ (void) my_close(file, MYF(MY_WME));
+ if (init_io_cache(&log, (file = last_file), IO_SIZE, READ_CACHE, 0, 0,
+ MYF(MY_WME)))
+ {
+ errmsg[0] = 0;
+ goto err;
+ }
+ break;
+ }
+
+ strmov(last_log_name, linfo.log_file_name);
+ last_pos = my_b_tell(&log);
+
+ switch (mysql_bin_log.find_next_log(&linfo)) {
+ case LOG_INFO_EOF:
+ if (last_file >= 0)
+ (void)my_close(last_file, MYF(MY_WME));
+ last_file = -1;
+ goto found_log;
+ case 0:
+ break;
+ default:
+ strmov(errmsg, "Error reading log index");
+ goto err;
+ }
+
+ end_io_cache(&log);
+ if (last_file >= 0)
+ (void) my_close(last_file, MYF(MY_WME));
+ last_file = file;
+ }
+
+found_log:
+ my_b_seek(&log, last_pos);
+ if (find_target_pos(mi,&log,errmsg))
+ goto err;
+ fn_format(mi->log_file_name, last_log_name, "","",1); /* Copy basename */
+
+mi_inited:
+ error = 0;
+err:
+ pthread_mutex_unlock(log_lock);
+ end_io_cache(&log);
+ pthread_mutex_lock(&LOCK_thread_count);
+ thd->current_linfo = 0;
+ pthread_mutex_unlock(&LOCK_thread_count);
+ if (file >= 0)
+ (void) my_close(file, MYF(MY_WME));
+ if (last_file >= 0 && last_file != file)
+ (void) my_close(last_file, MYF(MY_WME));
+
+ return error;
+}
+
+// caller must delete result when done
+static Slave_log_event* find_slave_event(IO_CACHE* log,
+ const char* log_file_name,
+ char* errmsg)
+{
+ Log_event* ev;
+ int i;
+ bool slave_event_found = 0;
+ LINT_INIT(ev);
+
+ for (i = 0; i < 2; i++)
+ {
+ if (!(ev = Log_event::read_log_event(log, (pthread_mutex_t*)0, 0)))
+ {
+ my_snprintf(errmsg, SLAVE_ERRMSG_SIZE,
+ "Error reading event in log '%s'",
+ (char*)log_file_name);
+ return 0;
+ }
+ if (ev->get_type_code() == SLAVE_EVENT)
+ {
+ slave_event_found = 1;
+ break;
+ }
+ delete ev;
+ }
+ if (!slave_event_found)
+ {
+ my_snprintf(errmsg, SLAVE_ERRMSG_SIZE,
+ "Could not find slave event in log '%s'",
+ (char*)log_file_name);
+ delete ev;
+ return 0;
+ }
+
+ return (Slave_log_event*)ev;
+}
+
+
+int show_new_master(THD* thd)
+{
+ DBUG_ENTER("show_new_master");
+ List<Item> field_list;
+ char errmsg[SLAVE_ERRMSG_SIZE];
+ LEX_MASTER_INFO* lex_mi = &thd->lex.mi;
+
+ errmsg[0]=0; // Safety
+ if (translate_master(thd, lex_mi, errmsg))
+ {
+ if (errmsg[0])
+ net_printf(&thd->net, ER_ERROR_WHEN_EXECUTING_COMMAND,
+ "SHOW NEW MASTER", errmsg);
+ else
+ send_error(&thd->net, 0);
+
+ DBUG_RETURN(1);
+ }
+ else
+ {
+ String* packet = &thd->packet;
+ field_list.push_back(new Item_empty_string("Log_name", 20));
+ field_list.push_back(new Item_empty_string("Log_pos", 20));
+ if (send_fields(thd, field_list, 1))
+ DBUG_RETURN(-1);
+ packet->length(0);
+ net_store_data(packet, lex_mi->log_file_name);
+ net_store_data(packet, (longlong)lex_mi->pos);
+ if (my_net_write(&thd->net, packet->ptr(), packet->length()))
+ DBUG_RETURN(-1);
+ send_eof(&thd->net);
+ DBUG_RETURN(0);
+ }
+}
+
+int update_slave_list(MYSQL* mysql)
+{
+ MYSQL_RES* res=0;
+ MYSQL_ROW row;
+ const char* error=0;
+ bool have_auth_info;
+ int port_ind;
+
+ if (mc_mysql_query(mysql,"SHOW SLAVE HOSTS",0) ||
+ !(res = mc_mysql_store_result(mysql)))
+ {
+ error = "Query error";
+ goto err;
+ }
+
+ switch (mc_mysql_num_fields(res))
+ {
+ case 5:
+ have_auth_info = 0;
+ port_ind=2;
+ break;
+ case 7:
+ have_auth_info = 1;
+ port_ind=4;
+ break;
+ default:
+ error = "Invalid number of fields in SHOW SLAVE HOSTS";
+ goto err;
+ }
+
+ pthread_mutex_lock(&LOCK_slave_list);
+
+ while ((row = mc_mysql_fetch_row(res)))
+ {
+ uint32 server_id;
+ SLAVE_INFO* si, *old_si;
+ server_id = atoi(row[0]);
+ if ((old_si = (SLAVE_INFO*)hash_search(&slave_list,
+ (byte*)&server_id,4)))
+ si = old_si;
+ else
+ {
+ if (!(si = (SLAVE_INFO*)my_malloc(sizeof(SLAVE_INFO), MYF(MY_WME))))
+ {
+ error = "Out of memory";
+ pthread_mutex_unlock(&LOCK_slave_list);
+ goto err;
+ }
+ si->server_id = server_id;
+ hash_insert(&slave_list, (byte*)si);
+ }
+ strnmov(si->host, row[1], sizeof(si->host));
+ si->port = atoi(row[port_ind]);
+ si->rpl_recovery_rank = atoi(row[port_ind+1]);
+ si->master_id = atoi(row[port_ind+2]);
+ if (have_auth_info)
+ {
+ strnmov(si->user, row[2], sizeof(si->user));
+ strnmov(si->password, row[3], sizeof(si->password));
+ }
+ }
+ pthread_mutex_unlock(&LOCK_slave_list);
+err:
+ if (res)
+ mc_mysql_free_result(res);
+ if (error)
+ {
+ sql_print_error("Error updating slave list:",error);
+ return 1;
+ }
+ return 0;
+}
+
+int find_recovery_captain(THD* thd, MYSQL* mysql)
+{
+
+ return 0;
+}
+
+pthread_handler_decl(handle_failsafe_rpl,arg)
+{
+ DBUG_ENTER("handle_failsafe_rpl");
+ THD *thd = new THD;
+ thd->thread_stack = (char*)&thd;
+ MYSQL* recovery_captain = 0;
+ pthread_detach_this_thread();
+ if (init_failsafe_rpl_thread(thd) || !(recovery_captain=mc_mysql_init(0)))
+ {
+ sql_print_error("Could not initialize failsafe replication thread");
+ goto err;
+ }
+ pthread_mutex_lock(&LOCK_rpl_status);
+ while (!thd->killed && !abort_loop)
+ {
+ bool break_req_chain = 0;
+ const char* msg = thd->enter_cond(&COND_rpl_status,
+ &LOCK_rpl_status, "Waiting for request");
+ pthread_cond_wait(&COND_rpl_status, &LOCK_rpl_status);
+ thd->proc_info="Processing request";
+ while (!break_req_chain)
+ {
+ switch (rpl_status)
+ {
+ case RPL_LOST_SOLDIER:
+ if (find_recovery_captain(thd, recovery_captain))
+ rpl_status=RPL_TROOP_SOLDIER;
+ else
+ rpl_status=RPL_RECOVERY_CAPTAIN;
+ break_req_chain=1; /* for now until other states are implemented */
+ break;
+ default:
+ break_req_chain=1;
+ break;
+ }
+ }
+ thd->exit_cond(msg);
+ }
+ pthread_mutex_unlock(&LOCK_rpl_status);
+err:
+ if (recovery_captain)
+ mc_mysql_close(recovery_captain);
+ delete thd;
+ my_thread_end();
+ pthread_exit(0);
+ DBUG_RETURN(0);
+}
+
+int show_slave_hosts(THD* thd)
+{
+ List<Item> field_list;
+ NET* net = &thd->net;
+ String* packet = &thd->packet;
+ DBUG_ENTER("show_slave_hosts");
+
+ field_list.push_back(new Item_empty_string("Server_id", 20));
+ field_list.push_back(new Item_empty_string("Host", 20));
+ if (opt_show_slave_auth_info)
+ {
+ field_list.push_back(new Item_empty_string("User",20));
+ field_list.push_back(new Item_empty_string("Password",20));
+ }
+ field_list.push_back(new Item_empty_string("Port",20));
+ field_list.push_back(new Item_empty_string("Rpl_recovery_rank", 20));
+ field_list.push_back(new Item_empty_string("Master_id", 20));
+
+ if (send_fields(thd, field_list, 1))
+ DBUG_RETURN(-1);
+
+ pthread_mutex_lock(&LOCK_slave_list);
+
+ for (uint i = 0; i < slave_list.records; ++i)
+ {
+ SLAVE_INFO* si = (SLAVE_INFO*) hash_element(&slave_list, i);
+ packet->length(0);
+ net_store_data(packet, si->server_id);
+ net_store_data(packet, si->host);
+ if (opt_show_slave_auth_info)
+ {
+ net_store_data(packet, si->user);
+ net_store_data(packet, si->password);
+ }
+ net_store_data(packet, (uint32) si->port);
+ net_store_data(packet, si->rpl_recovery_rank);
+ net_store_data(packet, si->master_id);
+ if (my_net_write(net, (char*)packet->ptr(), packet->length()))
+ {
+ pthread_mutex_unlock(&LOCK_slave_list);
+ DBUG_RETURN(-1);
+ }
+ }
+ pthread_mutex_unlock(&LOCK_slave_list);
+ send_eof(net);
+ DBUG_RETURN(0);
+}
+
+int connect_to_master(THD *thd, MYSQL* mysql, MASTER_INFO* mi)
+{
+ if (!mc_mysql_connect(mysql, mi->host, mi->user, mi->password, 0,
+ mi->port, 0, 0))
+ {
+ sql_print_error("Connection to master failed: %s",
+ mc_mysql_error(mysql));
+ return 1;
+ }
+ return 0;
+}
+
+
+static inline void cleanup_mysql_results(MYSQL_RES* db_res,
+ MYSQL_RES** cur, MYSQL_RES** start)
+{
+ for( ; cur >= start; --cur)
+ {
+ if (*cur)
+ mc_mysql_free_result(*cur);
+ }
+ mc_mysql_free_result(db_res);
+}
+
+
+static inline int fetch_db_tables(THD* thd, MYSQL* mysql, const char* db,
+ MYSQL_RES* table_res, MASTER_INFO* mi)
+{
+ MYSQL_ROW row;
+ for( row = mc_mysql_fetch_row(table_res); row;
+ row = mc_mysql_fetch_row(table_res))
+ {
+ TABLE_LIST table;
+ const char* table_name = row[0];
+ int error;
+ if (table_rules_on)
+ {
+ table.next = 0;
+ table.db = (char*)db;
+ table.real_name = (char*)table_name;
+ table.updating = 1;
+ if (!tables_ok(thd, &table))
+ continue;
+ }
+ if ((error = fetch_master_table(thd, db, table_name, mi, mysql)))
+ return error;
+ }
+ return 0;
+}
+
+
+int load_master_data(THD* thd)
+{
+ MYSQL mysql;
+ MYSQL_RES* master_status_res = 0;
+ bool slave_was_running = 0;
+ int error = 0;
+ const char* errmsg=0;
+ int restart_thread_mask;
+ mc_mysql_init(&mysql);
+
+ // we do not want anyone messing with the slave at all for the entire
+ // duration of the data load;
+ LOCK_ACTIVE_MI;
+ lock_slave_threads(active_mi);
+ init_thread_mask(&restart_thread_mask,active_mi,0 /*not inverse*/);
+ if (restart_thread_mask &&
+ (error=terminate_slave_threads(active_mi,restart_thread_mask,
+ 1 /*skip lock*/)))
+ {
+ send_error(&thd->net,error);
+ unlock_slave_threads(active_mi);
+ UNLOCK_ACTIVE_MI;
+ return 1;
+ }
+
+ if (connect_to_master(thd, &mysql, active_mi))
+ {
+ net_printf(&thd->net, error = ER_CONNECT_TO_MASTER,
+ mc_mysql_error(&mysql));
+ goto err;
+ }
+
+ // now that we are connected, get all database and tables in each
+ {
+ MYSQL_RES *db_res, **table_res, **table_res_end, **cur_table_res;
+ uint num_dbs;
+
+ if (mc_mysql_query(&mysql, "show databases", 0) ||
+ !(db_res = mc_mysql_store_result(&mysql)))
+ {
+ net_printf(&thd->net, error = ER_QUERY_ON_MASTER,
+ mc_mysql_error(&mysql));
+ goto err;
+ }
+
+ if (!(num_dbs = (uint) mc_mysql_num_rows(db_res)))
+ goto err;
+ // in theory, the master could have no databases at all
+ // and run with skip-grant
+
+ if (!(table_res = (MYSQL_RES**)thd->alloc(num_dbs * sizeof(MYSQL_RES*))))
+ {
+ net_printf(&thd->net, error = ER_OUTOFMEMORY);
+ goto err;
+ }
+
+ // this is a temporary solution until we have online backup
+ // capabilities - to be replaced once online backup is working
+ // we wait to issue FLUSH TABLES WITH READ LOCK for as long as we
+ // can to minimize the lock time
+ if (mc_mysql_query(&mysql, "FLUSH TABLES WITH READ LOCK", 0) ||
+ mc_mysql_query(&mysql, "SHOW MASTER STATUS",0) ||
+ !(master_status_res = mc_mysql_store_result(&mysql)))
+ {
+ net_printf(&thd->net, error = ER_QUERY_ON_MASTER,
+ mc_mysql_error(&mysql));
+ goto err;
+ }
+
+ // go through every table in every database, and if the replication
+ // rules allow replicating it, get it
+
+ table_res_end = table_res + num_dbs;
+
+ for(cur_table_res = table_res; cur_table_res < table_res_end;
+ cur_table_res++)
+ {
+ // since we know how many rows we have, this can never be NULL
+ MYSQL_ROW row = mc_mysql_fetch_row(db_res);
+ char* db = row[0];
+
+ /*
+ Do not replicate databases excluded by rules
+ also skip mysql database - in most cases the user will
+ mess up and not exclude mysql database with the rules when
+ he actually means to - in this case, he is up for a surprise if
+ his priv tables get dropped and downloaded from master
+ TODO - add special option, not enabled
+ by default, to allow inclusion of mysql database into load
+ data from master
+ */
+
+ if (!db_ok(db, replicate_do_db, replicate_ignore_db) ||
+ !strcmp(db,"mysql"))
+ {
+ *cur_table_res = 0;
+ continue;
+ }
+
+ if (mysql_rm_db(thd, db, 1,1) ||
+ mysql_create_db(thd, db, 0, 1))
+ {
+ send_error(&thd->net, 0, 0);
+ cleanup_mysql_results(db_res, cur_table_res - 1, table_res);
+ goto err;
+ }
+
+ if (mc_mysql_select_db(&mysql, db) ||
+ mc_mysql_query(&mysql, "show tables", 0) ||
+ !(*cur_table_res = mc_mysql_store_result(&mysql)))
+ {
+ net_printf(&thd->net, error = ER_QUERY_ON_MASTER,
+ mc_mysql_error(&mysql));
+ cleanup_mysql_results(db_res, cur_table_res - 1, table_res);
+ goto err;
+ }
+
+ if ((error = fetch_db_tables(thd,&mysql,db,*cur_table_res,active_mi)))
+ {
+ // we do not report the error - fetch_db_tables handles it
+ cleanup_mysql_results(db_res, cur_table_res, table_res);
+ goto err;
+ }
+ }
+
+ cleanup_mysql_results(db_res, cur_table_res - 1, table_res);
+
+ // adjust position in the master
+ if (master_status_res)
+ {
+ MYSQL_ROW row = mc_mysql_fetch_row(master_status_res);
+
+ /*
+ We need this check because the master may not be running with
+ log-bin, but it will still allow us to do all the steps
+ of LOAD DATA FROM MASTER - no reason to forbid it, really,
+ although it does not make much sense for the user to do it
+ */
+ if (row[0] && row[1])
+ {
+ strmake(active_mi->master_log_name, row[0],
+ sizeof(active_mi->master_log_name));
+ active_mi->master_log_pos = strtoull(row[1], (char**) 0, 10);
+ if (active_mi->master_log_pos < 4)
+ active_mi->master_log_pos = 4; // don't hit the magic number
+ active_mi->rli.pending = 0;
+ flush_master_info(active_mi);
+ }
+ mc_mysql_free_result(master_status_res);
+ }
+
+ if (mc_mysql_query(&mysql, "UNLOCK TABLES", 0))
+ {
+ net_printf(&thd->net, error = ER_QUERY_ON_MASTER,
+ mc_mysql_error(&mysql));
+ goto err;
+ }
+ }
+ thd->proc_info="purging old relay logs";
+ if (purge_relay_logs(&active_mi->rli,0 /* not only reset, but also reinit*/,
+ &errmsg))
+ {
+ send_error(&thd->net, 0, "Failed purging old relay logs");
+ unlock_slave_threads(active_mi);
+ UNLOCK_ACTIVE_MI;
+ return 1;
+ }
+ pthread_mutex_lock(&active_mi->rli.data_lock);
+ active_mi->rli.master_log_pos = active_mi->master_log_pos;
+ strnmov(active_mi->rli.master_log_name,active_mi->master_log_name,
+ sizeof(active_mi->rli.master_log_name));
+ flush_relay_log_info(&active_mi->rli);
+ pthread_cond_broadcast(&active_mi->rli.data_cond);
+ pthread_mutex_unlock(&active_mi->rli.data_lock);
+ thd->proc_info = "starting slave";
+ if (restart_thread_mask)
+ {
+ error=start_slave_threads(0 /* mutex not needed*/,
+ 1 /* wait for start*/,
+ active_mi,master_info_file,relay_log_info_file,
+ restart_thread_mask);
+ }
+
+err:
+ unlock_slave_threads(active_mi);
+ UNLOCK_ACTIVE_MI;
+ thd->proc_info = 0;
+
+ mc_mysql_close(&mysql); // safe to call since we always do mc_mysql_init()
+ if (!error)
+ send_ok(&thd->net);
+
+ return error;
+}
diff --git a/sql/repl_failsafe.h b/sql/repl_failsafe.h
new file mode 100644
index 00000000000..77bc03ce8c0
--- /dev/null
+++ b/sql/repl_failsafe.h
@@ -0,0 +1,38 @@
+#ifndef REPL_FAILSAFE_H
+#define REPL_FAILSAFE_H
+
+#include "mysql.h"
+#include "my_sys.h"
+#include "slave.h"
+
+typedef enum {RPL_AUTH_MASTER=0,RPL_ACTIVE_SLAVE,RPL_IDLE_SLAVE,
+ RPL_LOST_SOLDIER,RPL_TROOP_SOLDIER,
+ RPL_RECOVERY_CAPTAIN,RPL_NULL /* inactive */,
+ RPL_ANY /* wild card used by change_rpl_status */ } RPL_STATUS;
+extern RPL_STATUS rpl_status;
+
+extern pthread_mutex_t LOCK_rpl_status;
+extern pthread_cond_t COND_rpl_status;
+extern TYPELIB rpl_role_typelib, rpl_status_typelib;
+extern uint rpl_recovery_rank;
+extern const char* rpl_role_type[], *rpl_status_type[];
+
+pthread_handler_decl(handle_failsafe_rpl,arg);
+void change_rpl_status(RPL_STATUS from_status, RPL_STATUS to_status);
+int find_recovery_captain(THD* thd, MYSQL* mysql);
+int update_slave_list(MYSQL* mysql);
+
+extern HASH slave_list;
+
+int load_master_data(THD* thd);
+int connect_to_master(THD *thd, MYSQL* mysql, MASTER_INFO* mi);
+
+int show_new_master(THD* thd);
+int show_slave_hosts(THD* thd);
+int translate_master(THD* thd, LEX_MASTER_INFO* mi, char* errmsg);
+void init_slave_list();
+void end_slave_list();
+int register_slave(THD* thd, uchar* packet, uint packet_length);
+void unregister_slave(THD* thd, bool only_mine, bool need_mutex);
+
+#endif
diff --git a/sql/share/Makefile.am b/sql/share/Makefile.am
index 6bc05aa33cd..cb3056b5f5a 100644
--- a/sql/share/Makefile.am
+++ b/sql/share/Makefile.am
@@ -27,5 +27,11 @@ install-data-local:
$(INSTALL_DATA) $(srcdir)/charsets/Index $(DESTDIR)$(pkgdatadir)/charsets/Index
$(INSTALL_DATA) $(srcdir)/charsets/*.conf $(DESTDIR)$(pkgdatadir)/charsets
+fix_errors:
+ for lang in @AVAILABLE_LANGUAGES@; \
+ do \
+ ../../extra/comp_err $(srcdir)/$$lang/errmsg.txt $(srcdir)/$$lang/errmsg.sys; \
+ done
+
# Don't update the files from bitkeeper
%::SCCS/s.%
diff --git a/sql/share/charsets/Index b/sql/share/charsets/Index
index b91e27e7c02..5cf30682cc0 100644
--- a/sql/share/charsets/Index
+++ b/sql/share/charsets/Index
@@ -1,6 +1,7 @@
# sql/share/charsets/Index
#
-# This file lists all of the available character sets.
+# This file lists all of the available character sets. Please keep this
+# file sorted by character set number.
big5 1
@@ -34,3 +35,4 @@ croat 27
gbk 28
cp1257 29
latin5 30
+latin1_de 31
diff --git a/sql/share/czech/errmsg.txt b/sql/share/czech/errmsg.txt
index d1638bee16e..950ca4f6623 100644
--- a/sql/share/czech/errmsg.txt
+++ b/sql/share/czech/errmsg.txt
@@ -14,198 +14,198 @@
"isamchk",
"NE",
"ANO",
-"Nemohu vytvo-Bøit soubor '%-.64s' (chybový kód: %d)",-A
-"Nemohu vytvo-Bøit tabulku '%-.64s' (chybový kód: %d)",-A
-"Nemohu vytvo-Bøit databázi '%-.64s', chyba %d",-A
-"Nemohu vytvo-Bøit databázi '%-.64s', databáze ji¾ existuje",-A
-"Nemohu zru-B¹it databázi '%-.64s', databáze neexistuje",-A
-"Chyba p-Bøi ru¹ení databáze (nemohu vymazat '%-.64s', chyba %d)",-A
-"Chyba p-Bøi ru¹ení databáze (nemohu vymazat adresáø '%-.64s', chyba %d)",-A
-"Chyba p-Bøi výmazu '%-.64s' (chybový kód: %d)",-A
-"Nemohu -Bèíst záznam v systémové tabulce",-A
-"Nemohu z-Bískat stav '%-.64s' (chybový kód: %d)",-A
-"Chyba p-Bøi zji¹»ování pracovní adresáø (chybový kód: %d)",-A
-"Nemohu uzamknout soubor (chybov-Bý kód: %d)",-A
-"Nemohu otev-Bøít soubor '%-.64s' (chybový kód: %d)",-A
-"Nemohu naj-Bít soubor '%-.64s' (chybový kód: %d)",-A
-"Nemohu -Bèíst adresáø '%-.64s' (chybový kód: %d)",-A
-"Nemohu zm-Bìnit adresáø na '%-.64s' (chybový kód: %d)",-A
-"Z-Báznam byl zmìnìn od posledního ètení v tabulce '%-.64s'",-A
-"Disk je pln-Bý (%s), èekám na uvolnìní nìjakého místa ...",-A
-"Nemohu zapsat, zdvojen-Bý klíè v tabulce '%-.64s'",-A
-"Chyba p-Bøi zavírání '%-.64s' (chybový kód: %d)",-A
-"Chyba p-Bøi ètení souboru '%-.64s' (chybový kód: %d)",-A
-"Chyba p-Bøi pøejmenování '%-.64s' na '%-.64s' (chybový kód: %d)",-A
-"Chyba p-Bøi zápisu do souboru '%-.64s' (chybový kód: %d)",-A
-"'%-.64s' je zam-Bèen proti zmìnám",-A
-"T-Bøídìní pøeru¹eno",-A
+"Nemohu vytvo-Bøit soubor '%-.64s' (chybový kód: %d)",
+"Nemohu vytvo-Bøit tabulku '%-.64s' (chybový kód: %d)",
+"Nemohu vytvo-Bøit databázi '%-.64s', chyba %d",
+"Nemohu vytvo-Bøit databázi '%-.64s', databáze ji¾ existuje",
+"Nemohu zru-B¹it databázi '%-.64s', databáze neexistuje",
+"Chyba p-Bøi ru¹ení databáze (nemohu vymazat '%-.64s', chyba %d)",
+"Chyba p-Bøi ru¹ení databáze (nemohu vymazat adresáø '%-.64s', chyba %d)",
+"Chyba p-Bøi výmazu '%-.64s' (chybový kód: %d)",
+"Nemohu -Bèíst záznam v systémové tabulce",
+"Nemohu z-Bískat stav '%-.64s' (chybový kód: %d)",
+"Chyba p-Bøi zji¹»ování pracovní adresáø (chybový kód: %d)",
+"Nemohu uzamknout soubor (chybov-Bý kód: %d)",
+"Nemohu otev-Bøít soubor '%-.64s' (chybový kód: %d)",
+"Nemohu naj-Bít soubor '%-.64s' (chybový kód: %d)",
+"Nemohu -Bèíst adresáø '%-.64s' (chybový kód: %d)",
+"Nemohu zm-Bìnit adresáø na '%-.64s' (chybový kód: %d)",
+"Z-Báznam byl zmìnìn od posledního ètení v tabulce '%-.64s'",
+"Disk je pln-Bý (%s), èekám na uvolnìní nìjakého místa ...",
+"Nemohu zapsat, zdvojen-Bý klíè v tabulce '%-.64s'",
+"Chyba p-Bøi zavírání '%-.64s' (chybový kód: %d)",
+"Chyba p-Bøi ètení souboru '%-.64s' (chybový kód: %d)",
+"Chyba p-Bøi pøejmenování '%-.64s' na '%-.64s' (chybový kód: %d)",
+"Chyba p-Bøi zápisu do souboru '%-.64s' (chybový kód: %d)",
+"'%-.64s' je zam-Bèen proti zmìnám",
+"T-Bøídìní pøeru¹eno",
"Pohled '%-.64s' pro '%-.64s' neexistuje",
-"Obsluha tabulky vr-Bátila chybu %d",-A
-"Obsluha tabulky '%-.64s' nem-Bá tento parametr",-A
-"Nemohu naj-Bít záznam v '%-.64s'",-A
-"Nespr-Bávná informace v souboru '%-.64s'",-A
-"Nespr-Bávný klíè pro tabulku '%-.64s'. Pokuste se ho opravit",-A
-"Star-Bý klíèový soubor pro '%-.64s'. Opravte ho.",-A
-"'%-.64s' je jen pro -Bètení",-A
-"M-Bálo pamìti. Pøestartujte daemona a zkuste znovu (je potøeba %d bytù)",-A
-"M-Bálo pamìti pro tøídìní. Zvy¹te velikost tøídícího bufferu",-A
-"Neo-Bèekávaný konec souboru pøi ètení '%-.64s' (chybový kód: %d)",-A
-"P-Bøíli¹ mnoho spojení",-A
-"M-Bálo prostoru/pamìti pro thread",-A
-"Nemohu zjistit jm-Béno stroje pro Va¹i adresu",-A
-"Chyba p-Bøi ustavování spojení",-A
-"P-Bøístup pro u¾ivatele '%-.32s@%-.64s' k databázi '%-.64s' není povolen",-A
-"P-Bøístup pro u¾ivatele '%-.32s@%-.64s' (s heslem %s)",-A
-"Nebyla vybr-Bána ¾ádná databáze",-A
-"Nezn-Bámý pøíkaz",-A
-"Sloupec '%-.64s' nem-Bù¾e být null",-A
-"Nezn-Bámá databáze '%-.64s'",-A
-"Tabulka '%-.64s' ji-B¾ existuje",-A
-"Nezn-Bámá tabulka '%-.64s'",-A
-"Sloupec '%-.64s' v %s nen-Bí zcela jasný",-A
-"Prob-Bíhá ukonèování práce serveru",-A
-"Nezn-Bámý sloupec '%-.64s' v %s",-A
-"Pou-B¾ité '%-.64s' nebylo v group by",-A
-"Nemohu pou-B¾ít group na '%-.64s'",-A
-"P-Bøíkaz obsahuje zároveò funkci sum a sloupce",-A
-"Po-Bèet sloupcù neodpovídá zadané hodnotì",-A
-"Jm-Béno identifikátoru '%-.64s' je pøíli¹ dlouhé",-A
-"Zdvojen-Bé jméno sloupce '%-.64s'",-A
-"Zdvojen-Bé jméno klíèe '%-.64s'",-A
-"Zvojen-Bý klíè '%-.64s' (èíslo klíèe %d)",-A
-"Chybn-Bá specifikace sloupce '%-.64s'",-A
-"%s bl-Bízko '%-.64s' na øádku %d",-A
-"V-Býsledek dotazu je prázdný",-A
-"Nejednozna-Bèná tabulka/alias: '%-.64s'",-A
-"Chybn-Bá defaultní hodnota pro '%-.64s'",-A
-"Definov-Báno více primárních klíèù",-A
-"Zad-Báno pøíli¹ mnoho klíèù, je povoleno nejvíce %d klíèù",-A
-"Zad-Báno pøíli¹ mnoho èást klíèù, je povoleno nejvíce %d èástí",-A
-"Zadan-Bý klíè byl pøíli¹ dlouhý, nejvìt¹í délka klíèe je %d",-A
-"Kl-Bíèový sloupec '%-.64s' v tabulce neexistuje",-A
-"Blob sloupec '%-.64s' nem-Bù¾e být pou¾it jako klíè",-A
-"P-Bøíli¹ velká délka sloupce '%-.64s' (nejvíce %d). Pou¾ijte BLOB",-A
-"M-Bù¾ete mít pouze jedno AUTO pole a to musí být definováno jako klíè",-A
-"%s: p-Bøipraven na spojení\n",-A
-"%s: norm-Bální ukonèení\n",-A
-"%s: p-Bøijat signal %d, konèím\n",-A
-"%s: ukon-Bèení práce hotovo\n",-A
-"%s: n-Básilné uzavøení threadu %ld u¾ivatele '%-.64s'\n",-A
-"Nemohu vytvo-Bøit IP socket",-A
-"Tabulka '%-.64s' nem-Bá index odpovídající CREATE INDEX. Vytvoøte tabulku znovu",-A
-"Argument separ-Bátoru polo¾ek nebyl oèekáván. Pøeètìte si manuál",-A
-"Nen-Bí mo¾né pou¾ít pevný rowlength s BLOBem. Pou¾ijte 'fields terminated by'.",-A
-"Soubor '%-.64s' mus-Bí být v adresáøi databáze nebo èitelný pro v¹echny",-A
-"Soubor '%-.64s' ji-B¾ existuje",-A
-"Z-Báznamù: %ld Vymazáno: %ld Pøeskoèeno: %ld Varování: %ld",-A
-"Z-Báznamù: %ld Zdvojených: %ld",-A
-"Chybn-Bá podèást klíèe -- není to øetìzec nebo je del¹í ne¾ délka èásti klíèe",-A
-"Nen-Bí mo¾né vymazat v¹echny polo¾ky s ALTER TABLE. Pou¾ijte DROP TABLE",-A
-"Nemohu zru-B¹it '%-.64s' (provést DROP). Zkontrolujte, zda neexistují záznamy/klíèe",-A
-"Z-Báznamù: %ld Zdvojených: %ld Varování: %ld",-A
-"INSERT TABLE '%-.64s' nen-Bí dovoleno v seznamu tabulek FROM",-A
-"Nezn-Bámá identifikace threadu: %lu",-A
-"Nejste vlastn-Bíkem threadu %lu",-A
-"Nejsou pou-B¾ity ¾ádné tabulky",-A
-"P-Bøíli¹ mnoho øetìzcù pro sloupec %s a SET",-A
-"Nemohu vytvo-Bøit jednoznaèné jméno logovacího souboru %s.(1-999)\n",-A
-"Tabulka '%-.64s' byla zam-Bèena s READ a nemù¾e být zmìnìna",-A
-"Tabulka '%-.64s' nebyla zam-Bèena s LOCK TABLES",-A
-"Blob polo-B¾ka '%-.64s' nemù¾e mít defaultní hodnotu",-A
-"Nep-Bøípustné jméno databáze '%-.64s'",-A
-"Nep-Bøípustné jméno tabulky '%-.64s'",-A
-"Zadan-Bý SELECT by procházel pøíli¹ mnoho záznamù a trval velmi dlouho. Zkontrolujte tvar WHERE a je-li SELECT v poøádku, pou¾ijte SET OPTION SQL_BIG_SELECTS=1",-A
-"Nezn-Bámá chyba",-A
-"Nezn-Bámá procedura %s",-A
-"Chybn-Bý poèet parametrù procedury %s",-A
-"Chybn-Bé parametry procedury %s",-A
-"Nezn-Bámá tabulka '%-.64s' v %s",-A
-"Polo-B¾ka '%-.64s' je zadána dvakrát",-A
-"Nespr-Bávné pou¾ití funkce group",-A
-"Tabulka '%-.64s' pou-B¾ívá roz¹íøení, které v této verzi MySQL není",-A
-"Tabulka mus-Bí mít alespoò jeden sloupec",-A
-"Tabulka '%-.64s' je pln-Bá",-A
-"Nezn-Bámá znaková sada: '%-.64s'",-A
-"P-Bøíli¹ mnoho tabulek, MySQL jich mù¾e mít v joinu jen %d",-A
-"P-Bøíli¹ mnoho polo¾ek",-A
-"-BØádek je pøíli¹ velký. Maximální velikost øádku, nepoèítaje polo¾ky blob, je %d. Musíte zmìnit nìkteré polo¾ky na blob",-A
-"P-Bøeteèení zásobníku threadu: pou¾ito %ld z %ld. Pou¾ijte 'mysqld -O thread_stack=#' k zadání vìt¹ího zásobníku",-A
-"V OUTER JOIN byl nalezen k-Bøí¾ový odkaz. Provìøte ON podmínky",-A
-"Sloupec '%-.32s' je pou-B¾it s UNIQUE nebo INDEX, ale není definován jako NOT NULL",-A
-"Nemohu na-Bèíst funkci '%-.64s'",-A
+"Obsluha tabulky vr-Bátila chybu %d",
+"Obsluha tabulky '%-.64s' nem-Bá tento parametr",
+"Nemohu naj-Bít záznam v '%-.64s'",
+"Nespr-Bávná informace v souboru '%-.64s'",
+"Nespr-Bávný klíè pro tabulku '%-.64s'. Pokuste se ho opravit",
+"Star-Bý klíèový soubor pro '%-.64s'. Opravte ho.",
+"'%-.64s' je jen pro -Bètení",
+"M-Bálo pamìti. Pøestartujte daemona a zkuste znovu (je potøeba %d bytù)",
+"M-Bálo pamìti pro tøídìní. Zvy¹te velikost tøídícího bufferu",
+"Neo-Bèekávaný konec souboru pøi ètení '%-.64s' (chybový kód: %d)",
+"P-Bøíli¹ mnoho spojení",
+"M-Bálo prostoru/pamìti pro thread",
+"Nemohu zjistit jm-Béno stroje pro Va¹i adresu",
+"Chyba p-Bøi ustavování spojení",
+"P-Bøístup pro u¾ivatele '%-.32s@%-.64s' k databázi '%-.64s' není povolen",
+"P-Bøístup pro u¾ivatele '%-.32s@%-.64s' (s heslem %s)",
+"Nebyla vybr-Bána ¾ádná databáze",
+"Nezn-Bámý pøíkaz",
+"Sloupec '%-.64s' nem-Bù¾e být null",
+"Nezn-Bámá databáze '%-.64s'",
+"Tabulka '%-.64s' ji-B¾ existuje",
+"Nezn-Bámá tabulka '%-.64s'",
+"Sloupec '%-.64s' v %s nen-Bí zcela jasný",
+"Prob-Bíhá ukonèování práce serveru",
+"Nezn-Bámý sloupec '%-.64s' v %s",
+"Pou-B¾ité '%-.64s' nebylo v group by",
+"Nemohu pou-B¾ít group na '%-.64s'",
+"P-Bøíkaz obsahuje zároveò funkci sum a sloupce",
+"Po-Bèet sloupcù neodpovídá zadané hodnotì",
+"Jm-Béno identifikátoru '%-.64s' je pøíli¹ dlouhé",
+"Zdvojen-Bé jméno sloupce '%-.64s'",
+"Zdvojen-Bé jméno klíèe '%-.64s'",
+"Zvojen-Bý klíè '%-.64s' (èíslo klíèe %d)",
+"Chybn-Bá specifikace sloupce '%-.64s'",
+"%s bl-Bízko '%-.64s' na øádku %d",
+"V-Býsledek dotazu je prázdný",
+"Nejednozna-Bèná tabulka/alias: '%-.64s'",
+"Chybn-Bá defaultní hodnota pro '%-.64s'",
+"Definov-Báno více primárních klíèù",
+"Zad-Báno pøíli¹ mnoho klíèù, je povoleno nejvíce %d klíèù",
+"Zad-Báno pøíli¹ mnoho èást klíèù, je povoleno nejvíce %d èástí",
+"Zadan-Bý klíè byl pøíli¹ dlouhý, nejvìt¹í délka klíèe je %d",
+"Kl-Bíèový sloupec '%-.64s' v tabulce neexistuje",
+"Blob sloupec '%-.64s' nem-Bù¾e být pou¾it jako klíè",
+"P-Bøíli¹ velká délka sloupce '%-.64s' (nejvíce %d). Pou¾ijte BLOB",
+"M-Bù¾ete mít pouze jedno AUTO pole a to musí být definováno jako klíè",
+"%s: p-Bøipraven na spojení\n",
+"%s: norm-Bální ukonèení\n",
+"%s: p-Bøijat signal %d, konèím\n",
+"%s: ukon-Bèení práce hotovo\n",
+"%s: n-Básilné uzavøení threadu %ld u¾ivatele '%-.64s'\n",
+"Nemohu vytvo-Bøit IP socket",
+"Tabulka '%-.64s' nem-Bá index odpovídající CREATE INDEX. Vytvoøte tabulku znovu",
+"Argument separ-Bátoru polo¾ek nebyl oèekáván. Pøeètìte si manuál",
+"Nen-Bí mo¾né pou¾ít pevný rowlength s BLOBem. Pou¾ijte 'fields terminated by'.",
+"Soubor '%-.64s' mus-Bí být v adresáøi databáze nebo èitelný pro v¹echny",
+"Soubor '%-.64s' ji-B¾ existuje",
+"Z-Báznamù: %ld Vymazáno: %ld Pøeskoèeno: %ld Varování: %ld",
+"Z-Báznamù: %ld Zdvojených: %ld",
+"Chybn-Bá podèást klíèe -- není to øetìzec nebo je del¹í ne¾ délka èásti klíèe",
+"Nen-Bí mo¾né vymazat v¹echny polo¾ky s ALTER TABLE. Pou¾ijte DROP TABLE",
+"Nemohu zru-B¹it '%-.64s' (provést DROP). Zkontrolujte, zda neexistují záznamy/klíèe",
+"Z-Báznamù: %ld Zdvojených: %ld Varování: %ld",
+"INSERT TABLE '%-.64s' nen-Bí dovoleno v seznamu tabulek FROM",
+"Nezn-Bámá identifikace threadu: %lu",
+"Nejste vlastn-Bíkem threadu %lu",
+"Nejsou pou-B¾ity ¾ádné tabulky",
+"P-Bøíli¹ mnoho øetìzcù pro sloupec %s a SET",
+"Nemohu vytvo-Bøit jednoznaèné jméno logovacího souboru %s.(1-999)\n",
+"Tabulka '%-.64s' byla zam-Bèena s READ a nemù¾e být zmìnìna",
+"Tabulka '%-.64s' nebyla zam-Bèena s LOCK TABLES",
+"Blob polo-B¾ka '%-.64s' nemù¾e mít defaultní hodnotu",
+"Nep-Bøípustné jméno databáze '%-.64s'",
+"Nep-Bøípustné jméno tabulky '%-.64s'",
+"Zadan-Bý SELECT by procházel pøíli¹ mnoho záznamù a trval velmi dlouho. Zkontrolujte tvar WHERE a je-li SELECT v poøádku, pou¾ijte SET OPTION SQL_BIG_SELECTS=1",
+"Nezn-Bámá chyba",
+"Nezn-Bámá procedura %s",
+"Chybn-Bý poèet parametrù procedury %s",
+"Chybn-Bé parametry procedury %s",
+"Nezn-Bámá tabulka '%-.64s' v %s",
+"Polo-B¾ka '%-.64s' je zadána dvakrát",
+"Nespr-Bávné pou¾ití funkce group",
+"Tabulka '%-.64s' pou-B¾ívá roz¹íøení, které v této verzi MySQL není",
+"Tabulka mus-Bí mít alespoò jeden sloupec",
+"Tabulka '%-.64s' je pln-Bá",
+"Nezn-Bámá znaková sada: '%-.64s'",
+"P-Bøíli¹ mnoho tabulek, MySQL jich mù¾e mít v joinu jen %d",
+"P-Bøíli¹ mnoho polo¾ek",
+"-BØádek je pøíli¹ velký. Maximální velikost øádku, nepoèítaje polo¾ky blob, je %d. Musíte zmìnit nìkteré polo¾ky na blob",
+"P-Bøeteèení zásobníku threadu: pou¾ito %ld z %ld. Pou¾ijte 'mysqld -O thread_stack=#' k zadání vìt¹ího zásobníku",
+"V OUTER JOIN byl nalezen k-Bøí¾ový odkaz. Provìøte ON podmínky",
+"Sloupec '%-.32s' je pou-B¾it s UNIQUE nebo INDEX, ale není definován jako NOT NULL",
+"Nemohu na-Bèíst funkci '%-.64s'",
"Nemohu inicializovat funkci '%-.64s'; %-.80s",
-"Pro sd-Bílenou knihovnu nejsou povoleny cesty",-A
-"Funkce '%-.64s' ji-B¾ existuje",-A
-"Nemohu otev-Bøít sdílenou knihovnu '%-.64s' (errno: %d %s)",-A
-"Nemohu naj-Bít funkci '%-.64s' v knihovnì'",-A
-"Funkce '%-.64s' nen-Bí definována",-A
-"Stroj '%-.64s' je zablokov-Bán kvùli mnoha chybám pøi pøipojování. Odblokujete pou¾itím 'mysqladmin flush-hosts'",-A
-"Stroj '%-.64s' nem-Bá povoleno se k tomuto MySQL serveru pøipojit",-A
-"Pou-B¾íváte MySQL jako anonymní u¾ivatel a anonymní u¾ivatelé nemají povoleno mìnit hesla",-A
-"Na zm-Bìnu hesel ostatním musíte mít právo provést update tabulek v databázi mysql",-A
-"V tabulce user nen-Bí ¾ádný odpovídající øádek",-A
-"Nalezen-Bých øádkù: %ld Zmìnìno: %ld Varování: %ld",-A
-"Nemohu vytvo-Bøit nový thread (errno %d). Pokud je je¹tì nìjaká volná pamì», podívejte se do manuálu na èást o chybách specifických pro jednotlivé operaèní systémy",-A
-"Po-Bèet sloupcù neodpovídá poètu hodnot na øádku %ld",-A
-"Nemohu znovuotev-Bøít tabulku: '%-.64s',-A
-"Neplatn-Bé u¾ití hodnoty NULL",-A
-"Regul-Bární výraz vrátil chybu '%-.64s'",-A
-"Pokud nen-Bí ¾ádná GROUP BY klauzule, není dovoleno souèasné pou¾ití GROUP polo¾ek (MIN(),MAX(),COUNT()...) s ne GROUP polo¾kami",-A
-"Neexistuje odpov-Bídající grant pro u¾ivatele '%-.32s' na stroji '%-.64s'",-A
-"%-.16s p-Bøíkaz nepøístupný pro u¾ivatele: '%-.32s@%-.64s' pro tabulku '%-.64s'",-A
-"%-.16s p-Bøíkaz nepøístupný pro u¾ivatele: '%-.32s@%-.64s' pro sloupec '%-.64s' v tabulce '%-.64s'",-A
-"Neplatn-Bý pøíkaz GRANT/REVOKE. Prosím, pøeètìte si v manuálu, jaká privilegia je mo¾né pou¾ít.",-A
-"Argument p-Bøíkazu GRANT u¾ivatel nebo stroj je pøíli¹ dlouhý",-A
+"Pro sd-Bílenou knihovnu nejsou povoleny cesty",
+"Funkce '%-.64s' ji-B¾ existuje",
+"Nemohu otev-Bøít sdílenou knihovnu '%-.64s' (errno: %d %s)",
+"Nemohu naj-Bít funkci '%-.64s' v knihovnì'",
+"Funkce '%-.64s' nen-Bí definována",
+"Stroj '%-.64s' je zablokov-Bán kvùli mnoha chybám pøi pøipojování. Odblokujete pou¾itím 'mysqladmin flush-hosts'",
+"Stroj '%-.64s' nem-Bá povoleno se k tomuto MySQL serveru pøipojit",
+"Pou-B¾íváte MySQL jako anonymní u¾ivatel a anonymní u¾ivatelé nemají povoleno mìnit hesla",
+"Na zm-Bìnu hesel ostatním musíte mít právo provést update tabulek v databázi mysql",
+"V tabulce user nen-Bí ¾ádný odpovídající øádek",
+"Nalezen-Bých øádkù: %ld Zmìnìno: %ld Varování: %ld",
+"Nemohu vytvo-Bøit nový thread (errno %d). Pokud je je¹tì nìjaká volná pamì», podívejte se do manuálu na èást o chybách specifických pro jednotlivé operaèní systémy",
+"Po-Bèet sloupcù neodpovídá poètu hodnot na øádku %ld",
+"Nemohu znovuotev-Bøít tabulku: '%-.64s',
+"Neplatn-Bé u¾ití hodnoty NULL",
+"Regul-Bární výraz vrátil chybu '%-.64s'",
+"Pokud nen-Bí ¾ádná GROUP BY klauzule, není dovoleno souèasné pou¾ití GROUP polo¾ek (MIN(),MAX(),COUNT()...) s ne GROUP polo¾kami",
+"Neexistuje odpov-Bídající grant pro u¾ivatele '%-.32s' na stroji '%-.64s'",
+"%-.16s p-Bøíkaz nepøístupný pro u¾ivatele: '%-.32s@%-.64s' pro tabulku '%-.64s'",
+"%-.16s p-Bøíkaz nepøístupný pro u¾ivatele: '%-.32s@%-.64s' pro sloupec '%-.64s' v tabulce '%-.64s'",
+"Neplatn-Bý pøíkaz GRANT/REVOKE. Prosím, pøeètìte si v manuálu, jaká privilegia je mo¾né pou¾ít.",
+"Argument p-Bøíkazu GRANT u¾ivatel nebo stroj je pøíli¹ dlouhý",
"Tabulka '%-64s.%s' neexistuje",
-"Neexistuje odpov-Bídající grant pro u¾ivatele '%-.32s' na stroji '%-.64s' pro tabulku '%-.64s'",-A
-"Pou-B¾itý pøíkaz není v této verzi MySQL povolen",-A
-"Va-B¹e syntaxe je nìjaká divná",-A
-"Zpo-B¾dìný insert threadu nebyl schopen získat po¾adovaný zámek pro tabulku %-.64s",-A
-"P-Bøíli¹ mnoho zpo¾dìných threadù",-A
-"Zru-B¹eno spojení %ld do databáze: '%-.64s' u¾ivatel: '%-.64s' (%s)",-A
-"Zji-B¹tìn pøíchozí packet del¹í ne¾ 'max_allowed_packet'",-A
-"Zji-B¹tìna chyba pøi ètení z roury spojení",-A
-"Zji-B¹tìna chyba fcntl()",-A
-"P-Bøíchozí packety v chybném poøadí",-A
-"Nemohu rozkomprimovat komunika-Bèní packet",-A
-"Zji-B¹tìna chyba pøi ètení komunikaèního packetu",-A
-"Zji-B¹tìn timeout pøi ètení komunikaèního packetu",-A
-"Zji-B¹tìna chyba pøi zápisu komunikaèního packetu",-A
-"Zji-B¹tìn timeout pøi zápisu komunikaèního packetu",-A
-"V-Býsledný øetìzec je del¹í ne¾ max_allowed_packet",-A
-"Typ pou-B¾ité tabulky nepodporuje BLOB/TEXT sloupce",-A
-"Typ pou-B¾ité tabulky nepodporuje AUTO_INCREMENT sloupce",-A
-"INSERT DELAYED nen-Bí mo¾no s tabulkou '%-.64s' pou¾ít, proto¾e je zamèená pomocí LOCK TABLES",-A
-"Nespr-Bávné jméno sloupce '%-.100s'",-A
-"Handler pou-B¾ité tabulky neumí indexovat sloupce '%-.64s'",-A
-"V-B¹echny tabulky v MERGE tabulce nejsou definovány stejnì",-A
-"Kv-Bùli unique constraintu nemozu zapsat do tabulky '%-.64s'",-A
-"BLOB sloupec '%-.64s' je pou-B¾it ve specifikaci klíèe bez délky",-A
-"V-B¹echny èásti primárního klíèe musejí být NOT NULL; pokud potøebujete NULL, pou¾ijte UNIQUE",-A
-"V-Býsledek obsahuje více ne¾ jeden øádek",-A
-"Tento typ tabulky vy-B¾aduje primární klíè",-A
-"Tato verze MySQL nen-Bí zkompilována s podporou RAID",-A
-"Update tabulky bez WHERE s kl-Bíèem není v módu bezpeèných update dovoleno",-A
-"Kl-Bíè '%-.64s' v tabulce '%-.64s' neexistuje",-A
-"Nemohu otev-Bøít tabulku",-A
+"Neexistuje odpov-Bídající grant pro u¾ivatele '%-.32s' na stroji '%-.64s' pro tabulku '%-.64s'",
+"Pou-B¾itý pøíkaz není v této verzi MySQL povolen",
+"Va-B¹e syntaxe je nìjaká divná",
+"Zpo-B¾dìný insert threadu nebyl schopen získat po¾adovaný zámek pro tabulku %-.64s",
+"P-Bøíli¹ mnoho zpo¾dìných threadù",
+"Zru-B¹eno spojení %ld do databáze: '%-.64s' u¾ivatel: '%-.64s' (%s)",
+"Zji-B¹tìn pøíchozí packet del¹í ne¾ 'max_allowed_packet'",
+"Zji-B¹tìna chyba pøi ètení z roury spojení",
+"Zji-B¹tìna chyba fcntl()",
+"P-Bøíchozí packety v chybném poøadí",
+"Nemohu rozkomprimovat komunika-Bèní packet",
+"Zji-B¹tìna chyba pøi ètení komunikaèního packetu",
+"Zji-B¹tìn timeout pøi ètení komunikaèního packetu",
+"Zji-B¹tìna chyba pøi zápisu komunikaèního packetu",
+"Zji-B¹tìn timeout pøi zápisu komunikaèního packetu",
+"V-Býsledný øetìzec je del¹í ne¾ max_allowed_packet",
+"Typ pou-B¾ité tabulky nepodporuje BLOB/TEXT sloupce",
+"Typ pou-B¾ité tabulky nepodporuje AUTO_INCREMENT sloupce",
+"INSERT DELAYED nen-Bí mo¾no s tabulkou '%-.64s' pou¾ít, proto¾e je zamèená pomocí LOCK TABLES",
+"Nespr-Bávné jméno sloupce '%-.100s'",
+"Handler pou-B¾ité tabulky neumí indexovat sloupce '%-.64s'",
+"V-B¹echny tabulky v MERGE tabulce nejsou definovány stejnì",
+"Kv-Bùli unique constraintu nemozu zapsat do tabulky '%-.64s'",
+"BLOB sloupec '%-.64s' je pou-B¾it ve specifikaci klíèe bez délky",
+"V-B¹echny èásti primárního klíèe musejí být NOT NULL; pokud potøebujete NULL, pou¾ijte UNIQUE",
+"V-Býsledek obsahuje více ne¾ jeden øádek",
+"Tento typ tabulky vy-B¾aduje primární klíè",
+"Tato verze MySQL nen-Bí zkompilována s podporou RAID",
+"Update tabulky bez WHERE s kl-Bíèem není v módu bezpeèných update dovoleno",
+"Kl-Bíè '%-.64s' v tabulce '%-.64s' neexistuje",
+"Nemohu otev-Bøít tabulku",
"Handler tabulky nepodporuje check/repair",
-"Proveden-Bí tohoto pøíkazu není v transakci dovoleno",-A
-"Chyba %d p-Bøi COMMIT",-A
-"Chyba %d p-Bøi ROLLBACK",-A
-"Chyba %d p-Bøi FLUSH_LOGS",-A
-"Chyba %d p-Bøi CHECKPOINT",-A
-"Spojen-Bí %ld do databáze: '%-.64s' u¾ivatel: '%-.32s' stroj: `%-.64s' (%-.64s) bylo pøeru¹eno",-A
-"Handler tabulky nepodporuje bin-Bární dump",-A
-"Binlog uzav-Bøen pøi pokusu o FLUSH MASTER",-A
-"P-Bøebudování indexu dumpnuté tabulky '%-.64s' nebylo úspì¹né",-A
+"Proveden-Bí tohoto pøíkazu není v transakci dovoleno",
+"Chyba %d p-Bøi COMMIT",
+"Chyba %d p-Bøi ROLLBACK",
+"Chyba %d p-Bøi FLUSH_LOGS",
+"Chyba %d p-Bøi CHECKPOINT",
+"Spojen-Bí %ld do databáze: '%-.64s' u¾ivatel: '%-.32s' stroj: `%-.64s' (%-.64s) bylo pøeru¹eno",
+"Handler tabulky nepodporuje bin-Bární dump",
+"Binlog uzav-Bøen pøi pokusu o FLUSH MASTER",
+"P-Bøebudování indexu dumpnuté tabulky '%-.64s' nebylo úspì¹né",
"Chyba masteru: '%-.64s'",
-"S-Bí»ová chyba pøi ètení z masteru",-A
-"S-Bí»ová chyba pøi zápisu na master",-A
-"-B®ádný sloupec nemá vytvoøen fulltextový index",-A
-"Nemohu prov-Bést zadaný pøíkaz, proto¾e existují aktivní zamèené tabulky nebo aktivní transakce",-A
-"Nezn-Bámá systémová promìnná '%-.64'",-A
-"Tabulka '%-.64s' je ozna-Bèena jako poru¹ená a mìla by být opravena",-A
-"Tabulka '%-.64s' je ozna-Bèena jako poru¹ená a poslední (automatická?) oprava se nezdaøila",-A
+"S-Bí»ová chyba pøi ètení z masteru",
+"S-Bí»ová chyba pøi zápisu na master",
+"-B®ádný sloupec nemá vytvoøen fulltextový index",
+"Nemohu prov-Bést zadaný pøíkaz, proto¾e existují aktivní zamèené tabulky nebo aktivní transakce",
+"Nezn-Bámá systémová promìnná '%-.64'",
+"Tabulka '%-.64s' je ozna-Bèena jako poru¹ená a mìla by být opravena",
+"Tabulka '%-.64s' je ozna-Bèena jako poru¹ená a poslední (automatická?) oprava se nezdaøila",
"Warning: Some non-transactional changed tables couldn't be rolled back",
"Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage. Increase this mysqld variable and try again',
"This operation cannot be performed with a running slave, run SLAVE STOP first",
@@ -228,3 +228,12 @@
"Cannot add foreign key constraint",
"Cannot add a child row: a foreign key constraint fails",
"Cannot delete a parent row: a foreign key constraint fails",
+"Error connecting to master: %-.128s",
+"Error running query on master: %-.128s",
+"Error when executing command %s: %-.128s",
+"Wrong usage of %s and %s",
+"The used SELECT statements have a different number of columns",
+"Can't execute the query because you have a conflicting read lock",
+"Mixing of transactional and non-transactional tables is disabled",
+"Option '%s' used twice in statement",
+"User '%-64s' has exceeded the '%s' resource (current value: %ld)",
diff --git a/sql/share/danish/errmsg.txt b/sql/share/danish/errmsg.txt
index 6585f717a78..d87ed4ee629 100644
--- a/sql/share/danish/errmsg.txt
+++ b/sql/share/danish/errmsg.txt
@@ -222,3 +222,12 @@
"Cannot add foreign key constraint",
"Cannot add a child row: a foreign key constraint fails",
"Cannot delete a parent row: a foreign key constraint fails",
+"Error connecting to master: %-.128s",
+"Error running query on master: %-.128s",
+"Error when executing command %s: %-.128s",
+"Wrong usage of %s and %s",
+"The used SELECT statements have a different number of columns",
+"Can't execute the query because you have a conflicting read lock",
+"Mixing of transactional and non-transactional tables is disabled",
+"Option '%s' used twice in statement",
+"User '%-64s' has exceeded the '%s' resource (current value: %ld)",
diff --git a/sql/share/dutch/errmsg.txt b/sql/share/dutch/errmsg.txt
index d14400edc69..9af197e9e4b 100644
--- a/sql/share/dutch/errmsg.txt
+++ b/sql/share/dutch/errmsg.txt
@@ -2,9 +2,10 @@
This file is public domain and comes with NO WARRANTY of any kind
Dutch error messages (share/dutch/errmsg.txt)
- Arjen G. Lentz (agl@bitbike.com)
+ 2001-08-02 - Arjen Lentz (agl@bitbike.com)
Completed earlier partial translation; worked on consistency and spelling.
- Version: 02-08-2001
+ 2002-01-29 - Arjen Lentz (arjen@mysql.com)
+ Translated new error messages.
*/
"hashchk",
@@ -16,9 +17,9 @@
"Kan database '%-.64s' niet aanmaken (Errcode: %d)",
"Kan database '%-.64s' niet aanmaken. Database bestaat reeds",
"Kan database '%-.64s' niet verwijderen. Database bestaat niet",
-"Error verwijderen database (kan '%-.64s' niet verwijderen, Errcode: %d)",
-"Error verwijderen database (kan rmdir '%-.64s' niet uitvoeren, Errcode: %d)",
-"Error bij het verwijderen van '%-.64s' (Errcode: %d)",
+"Fout bij verwijderen database (kan '%-.64s' niet verwijderen, Errcode: %d)",
+"Fout bij verwijderen database (kan rmdir '%-.64s' niet uitvoeren, Errcode: %d)",
+"Fout bij het verwijderen van '%-.64s' (Errcode: %d)",
"Kan record niet lezen in de systeem tabel",
"Kan de status niet krijgen van '%-.64s' (Errcode: %d)",
"Kan de werkdirectory niet krijgen (Errcode: %d)",
@@ -167,8 +168,8 @@
"Communicatiepakket kon niet worden gedecomprimeerd",
"Fout bij het lezen van communicatiepakketten"
"Timeout bij het lezen van communicatiepakketten",
-"Got an error writing communication packets",
-"Got timeout writing communication packets",
+"Fout bij het schrijven van communicatiepakketten",
+"Timeout bij het schrijven van communicatiepakketten",
"Resultaat string is langer dan max_allowed_packet",
"Het gebruikte tabel type ondersteunt geen BLOB/TEXT kolommen",
"Het gebruikte tabel type ondersteunt geen AUTO_INCREMENT kolommen",
@@ -218,10 +219,19 @@
"DROP DATABASE niet toegestaan terwijl thread een globale 'read lock' bezit",
"CREATE DATABASE niet toegestaan terwijl thread een globale 'read lock' bezit",
"Foutieve parameters voor %s",
-"%-.32s@%-.64s is not allowed to create new users",
-"Incorrect table definition; All MERGE tables must be in the same database",
-"Deadlock found when trying to get lock; Try restarting transaction",
-"The used table type doesn't support FULLTEXT indexes",
-"Cannot add foreign key constraint",
-"Cannot add a child row: a foreign key constraint fails",
-"Cannot delete a parent row: a foreign key constraint fails",
+"%-.32s@%-.64s mag geen nieuwe gebruikers creeren",
+"Incorrecte tabel definitie; Alle MERGE tabellen moeten tot dezelfde database behoren",
+"Deadlock gevonden tijdens lock-aanvraag poging; Probeer herstart van de transactie",
+"Het gebruikte tabel type ondersteund geen FULLTEXT indexen",
+"Kan foreign key beperking niet toevoegen",
+"Kan onderliggende rij niet toevoegen: foreign key beperking gefaald",
+"Kan bovenliggende rij nite verwijderen: foreign key beperking gefaald",
+"Fout bij opbouwen verbinding naar master: %-.128s",
+"Fout bij uitvoeren query op master: %-.128s",
+"Fout tijdens uitvoeren van commando %s: %-.128s",
+"Foutief gebruik van %s en %s",
+"De gebruikte SELECT commando's hebben een verschillend aantal kolommen",
+"Kan de query niet uitvoeren vanwege een conflicterende read lock",
+"Het combineren van transactionele en niet-transactionele tabellen is uitgeschakeld.",
+"Optie '%s' tweemaal gebruikt in opdracht",
+"User '%-64s' has exceeded the '%s' resource (current value: %ld)",
diff --git a/sql/share/english/errmsg.txt b/sql/share/english/errmsg.txt
index 384d2c846c2..5033449c266 100644
--- a/sql/share/english/errmsg.txt
+++ b/sql/share/english/errmsg.txt
@@ -219,3 +219,12 @@
"Cannot add foreign key constraint",
"Cannot add a child row: a foreign key constraint fails",
"Cannot delete a parent row: a foreign key constraint fails",
+"Error connecting to master: %-.128s",
+"Error running query on master: %-.128s",
+"Error when executing command %s: %-.128s",
+"Wrong usage of %s and %s",
+"The used SELECT statements have a different number of columns",
+"Can't execute the query because you have a conflicting read lock",
+"Mixing of transactional and non-transactional tables is disabled",
+"Option '%s' used twice in statement",
+"User '%-64s' has exceeded the '%s' resource (current value: %ld)",
diff --git a/sql/share/estonian/errmsg.txt b/sql/share/estonian/errmsg.txt
index 20891c7b001..6a83468eae5 100644
--- a/sql/share/estonian/errmsg.txt
+++ b/sql/share/estonian/errmsg.txt
@@ -1,225 +1,235 @@
-/* Copyright Abandoned 1997 TCX DataKonsult AB & Monty Program KB & Detron HB
- This file is public domain and comes with NO WARRANTY of any kind
+/*
+ Copyright Abandoned 1997 MySQL AB
+ This file is public domain and comes with NO WARRANTY of any kind
+ Esialgne tõlge: Tõnu Samuel (tonu@spam.ee)
+ Parandanud ja täiendanud: Indrek Siitan (tfr@mysql.com)
- Translated into estonian language by Tonu Samuel
- email: tonu@spam.ee
*/
"hashchk",
"isamchk",
"EI",
"JAH",
-"Ei saa luua tabelit '%-.64s' (vea kood: %d)",
-"Ei saa luua tabelit '%-.64s' (vea kood: %d)",
-"Ei saa luua andmebaasi '%-.64s'. (vea kood: %d)",
-"Ei saa luua andmebaasi '%-.64s'. Andmebaas on juba olemas",
-"Ei saa kustutada andmebaasi '%-.64s'. Andmebaasi ei eksisteeri",
-"Ei saa kustutada andmebaasi (Ei saa kustutada faili '%-.64s', vea kood: %d)",
-"Ei saa kustutada andmebaasi (Ei saa kustutada kataloogi '%-.64s', vea kood: %d)",
-"Viga '%-.64s' kustutamisel (vea kood: %d)",
-"Ei saa lugeda kirjet in süsteemsest tabelist",
-"Ei saa lugeda '%-.64s' olekut (vea kood: %d)",
-"Ei saa teada jooksva kataloogi nime (vea kood: %d)",
-"Ei saa avada lukustusfaili (vea kood: %d)",
-"Ei saa avada faili: '%-.64s'. (vea kood: %d)",
-"Ei leia faili: '%-.64s' (vea kood: %d)",
-"Ei saa lugeda kataloogi '%-.64s' (vea kood: %d)",
-"Ei saa siseneda kataloogi '%-.64s' (vea kood: %d)",
-"Kirje on muutunud võrreldes eelmise lugemisega tabelis '%-.64s'",
-"Ketas on täis (%s). Ootame kuni tekib vaba ruumi....",
-"Ei saa kirjutada, Korduv võti tabelis '%-.64s'",
-"Viga faili '%-.64s' sulgemisel (vea kood: %d)",
-"Viga faili '%-.64s' lugemisel (vea kood: %d)",
-"Viga faili '%-.64s' ringi nimetamisel '%-.64s'-ks (vea kood: %d)",
-"Viga faili '%-.64s' kirjutamisel (vea kood: %d)",
+"Ei suuda luua faili '%-.64s' (veakood: %d)",
+"Ei suuda luua tabelit '%-.64s' (veakood: %d)",
+"Ei suuda luua andmebaasi '%-.64s'. (veakood: %d)",
+"Ei suuda luua andmebaasi '%-.64s': andmebaas juba eksisteerib",
+"Ei suuda kustutada andmebaasi '%-.64s': andmebaasi ei eksisteeri",
+"Viga andmebaasi kustutamisel (ei suuda kustutada faili '%-.64s', veakood: %d)",
+"Viga andmebaasi kustutamisel (ei suuda kustutada kataloogi '%-.64s', veakood: %d)",
+"Viga '%-.64s' kustutamisel (veakood: %d)",
+"Ei suuda lugeda kirjet süsteemsest tabelist",
+"Ei suuda lugeda '%-.64s' olekut (veakood: %d)",
+"Ei suuda identifitseerida jooksvat kataloogi (veakood: %d)",
+"Ei suuda lukustada faili (veakood: %d)",
+"Ei suuda avada faili '%-.64s'. (veakood: %d)",
+"Ei suuda leida faili '%-.64s' (veakood: %d)",
+"Ei suuda lugeda kataloogi '%-.64s' (veakood: %d)",
+"Ei suuda siseneda kataloogi '%-.64s' (veakood: %d)",
+"Kirje tabelis '%-.64s' on muutunud viimasest lugemisest saadik",
+"Ketas täis (%s). Ootame kuni tekib vaba ruumi...",
+"Ei saa kirjutada, korduv võti tabelis '%-.64s'",
+"Viga faili '%-.64s' sulgemisel (veakood: %d)",
+"Viga faili '%-.64s' lugemisel (veakood: %d)",
+"Viga faili '%-.64s' ümbernimetamisel '%-.64s'-ks (veakood: %d)",
+"Viga faili '%-.64s' kirjutamisel (veakood: %d)",
"'%-.64s' on lukustatud muudatuste vastu",
"Sorteerimine katkestatud",
-"Vaade '%-.64s' puudub '%-.64s' jaoks",
-"Viga %d tabelitöötluses",
-"Table handler for '%-.64s' doesn't have this option",
+"Vaade '%-.64s' ei eksisteeri '%-.64s' jaoks",
+"Tabeli handler tagastas vea %d",
+"Tabeli '%-.64s' handler ei toeta antud operatsiooni",
"Ei suuda leida kirjet '%-.64s'-s",
-"Väär informatsiion failis '%-.64s'",
-"Vigastatud võtmefail tabelile '%-.64s'",
-"Vana võtmefail tabelile '%-.64s'. Proovi teda parandada",
-"Tabel '%-.64s' on ainult lugemise õigusega",
-"Mälu sai otsa. Proovi MySQL uuesti käivitada (Puudu jäi %d baiti)",
-"Mälu sai sorteerimie ajal otsa. Suurenda MySQL-i sorteerimispuhvrit",
-"Ootamatu faili lõpp leitud faili '%-.64s' lugemisel (vea kood: %d)",
+"Vigane informatsioon failis '%-.64s'",
+"Tabeli '%-.64s' võtmefail on vigane; Proovi seda parandada",
+"Tabeli '%-.64s' võtmefail on aegunud; Paranda see!",
+"Tabel '%-.64s' on ainult lugemiseks",
+"Mälu sai otsa. Proovi MySQL uuesti käivitada (puudu jäi %d baiti)",
+"Mälu sai sorteerimisel otsa. Suurenda MySQL-i sorteerimispuhvrit",
+"Ootamatu faililõpumärgend faili '%-.64s' lugemisel (veakood: %d)",
"Liiga palju samaaegseid ühendusi",
-"Mälu sai otsa. Võimalik, et aitab swap-i lisamine või käsu 'ulimit' abil MySQL-le rohkema mälu kasutamise lubamine.",
+"Mälu sai otsa. Võimalik, et aitab swap-i lisamine või käsu 'ulimit' abil MySQL-le rohkema mälu kasutamise lubamine",
"Ei suuda lahendada IP aadressi masina nimeks",
"Väär handshake",
-"Ligipääs piiratud kasutajale: '%-.32s@%-.64s' andmebaasi '%-.64s'",
-"Ligipääs piiratud kasutajale: '%-.32s@%-.64s' (Kasutab parooli: %s)",
-"Andmebaas pole valitud",
+"Ligipääs keelatud kasutajale '%-.32s@%-.64s' andmebaasile '%-.64s'",
+"Ligipääs keelatud kasutajale '%-.32s@%-.64s' (kasutab parooli: %s)",
+"Andmebaasi ei ole valitud",
"Tundmatu käsk",
-"Tulp '%-.64s' ei saa olla null",
+"Tulp '%-.64s' ei saa omada nullväärtust",
"Tundmatu andmebaas '%-.64s'",
-"Tabel '%-.64s' on juba olemas",
+"Tabel '%-.64s' juba eksisteerib",
"Tundmatu tabel '%-.64s'",
-"Tulp: '%-.64s' in %-.64s on väär",
+"Väli '%-.64s' %-.64s-s ei ole ühene",
"Serveri seiskamine käib",
-"Tundmatu tulp '%-.64s' in '%-.64s'",
-"'%-.64s' puudub GROUP BY-s",
+"Tundmatu tulp '%-.64s' '%-.64s'-s",
+"'%-.64s' puudub GROUP BY klauslis",
"Ei saa grupeerida '%-.64s' järgi",
-"Lauses on korraga nii tulbad kui summad",
-"Tuplade arv tabelis erineb antud väärtuste arvust",
+"Lauses on korraga nii tulbad kui summeerimisfunktsioonid",
+"Tulpade arv erineb väärtuste arvust",
"Identifikaatori '%-.100s' nimi on liiga pikk",
"Kattuv tulba nimi '%-.64s'",
"Kattuv võtme nimi '%-.64s'",
-"Kattuv nimi '%-.64s' võtmele %d",
-"Väär tulba kirjeldus tulbale '%-.64s'",
-"%s '%-.80s' ligidal reas %d",
+"Kattuv väärtus '%-.64s' võtmele %d",
+"Vigane tulba kirjeldus tulbale '%-.64s'",
+"%s '%-.80s' ligidal real %d",
"Tühi päring",
-"Pole unikaalne tabel/alias '%-.64s'",
-"Vale vaikeväärtus '%-.64s'",
-"Mitut põhivõtit (PRIMARY KEY) ei saa olla",
-"Liiga palju võtmeid määratletud. Maksimaalselt võib olla %d võtit",
+"Ei ole unikaalne tabel/alias '%-.64s'",
+"Vigane vaikeväärtus '%-.64s' jaoks",
+"Mitut primaarset võtit ei saa olla",
+"Liiga palju võtmeid. Maksimaalselt võib olla %d võtit",
"Võti koosneb liiga paljudest osadest. Maksimaalselt võib olla %d osa",
-"Määratletud võti sai liiga pikk. Maksimaalne lubatud pikkus on %d",
-"Võtme tulp '%-.64s' puudub antud tabelis",
-"BLOB tulpa '%-.64s' ei saa kasutada võtmena",
-"Tulba '%-.64s' pikkus on liiga pikk (maksimaalne = %d).",
-"Tabeli kohta saab olla ainult üks auto_increment tulp ja see peab olema samas ka võtmena",
+"Võti on liiga pikk. Maksimaalne võtmepikkus on %d",
+"Võtme tulp '%-.64s' puudub tabelis",
+"BLOB-tüüpi tulpa '%-.64s' ei saa kasutada võtmena",
+"Tulba '%-.64s' pikkus on liiga pikk (maksimaalne pikkus: %d). Kasuta BLOB väljatüüpi",
+"Vigane tabelikirjeldus; Tabelis tohib olla üks auto_increment tüüpi tulp ning see peab olema defineeritud võtmena",
"%s: ootab ühendusi\n",
"%s: MySQL lõpetas\n",
-"%s: Sain signaali %d. Lõpetan!\n",
+"%s: sain signaali %d. Lõpetan!\n",
"%s: Lõpp\n",
-"%s: Sulgen jõuga threadi %ld kasutaja: '%-.64s'\n",
-"Ei saa luua IP pesa",
+"%s: Sulgen jõuga lõime %ld kasutaja: '%-.32s'\n",
+"Ei suuda luua IP socketit",
"Tabelil '%-.64s' puuduvad võtmed. Loo tabel uuesti",
-"Väljade eraldaja on väär. Vaata kasutamisjuhendisse",
-"BLOB väljadega ei saa kasutada fikseeritud väljapikkust. Seetõttu on vajalik lisaklausel 'fields terminated by'.",
-"Fail '%-.64s' peab asuma andmebaasi kataloogis ning olema loetav",
-"Fail '%-.64s' on juba olemas",
-"Kirjed: %ld Kustutatud: %ld Vahele jäetud: %ld Hoiatusi: %ld",
-"Kirjed: %ld Topelt: %ld",
-"Väär võtme osa. Kasutatud võtme osa ei ole string või on pikkus pikem kui võtme osa",
-"ALTER TABLE abil ei saa koiki tulpasid kustutada. DROP TABLE kustutab terve tabeli",
-"Ei saa kustutada '%-.64s'. On selline tulp või võti üldse olemas?",
-"Kirjed: %ld Topelt: %ld Hoiatusi: %ld",
-"INSERT TABLE '%-.64s' pole lubatud FROM tabelite nimekirjas",
-"Tundmatu threadi id: %lu",
-"Pole threadi %lu omanik",
-"Pole kasutatud tabeleid",
-"Liiga palju stringe tulbale %-.64s ja tüübile SET",
-"Ei saa luua ainulaadset failinime %-.64s.(1-999)\n",
-"Tabel '%-.64s' on lukustatud ainult lugemiseks ja sinna kirjutada ei saa",
-"Tabel '%-.64s' pole lukustatud käsuga LOCK TABLES",
-"BLOB tüüpi tulbal '%-.64s' ei saa olla vaikeväärtust",
-"Väär andmebaasi nimi '%-.100s'",
-"Väär tabeli nimi '%-.100s'",
-"SELECT lause peab läbi vaatama suure hulga kirjeid ja võtaks tõenäoliselt liiga kaua aega. Tasub kontrollide WHERE klauslit ja vajadusel kasutada käsku SET OPTION SQL_BIG_SELECTS=1",
+"Väljade eraldaja erineb oodatust. Tutvu kasutajajuhendiga",
+"BLOB-tüüpi väljade olemasolul ei saa kasutada fikseeritud väljapikkust. Vajalik 'fields terminated by' määrang.",
+"Fail '%-.64s' peab asuma andmebaasi kataloogis või olema kõigile loetav",
+"Fail '%-.80s' juba eksisteerib",
+"Kirjeid: %ld Kustutatud: %ld Vahele jäetud: %ld Hoiatusi: %ld",
+"Kirjeid: %ld Kattuvaid: %ld",
+"Vigane võtme osa. Kasutatud võtmeosa ei ole string tüüpi, määratud pikkus on pikem kui võtmeosa või tabelihandler ei toeta seda tüüpi võtmeid",
+"ALTER TABLE kasutades ei saa kustutada kõiki tulpasid. Kustuta tabel DROP TABLE abil",
+"Ei suuda kustutada '%-.64s'. Kontrolli kas tulp/võti eksisteerib",
+"Kirjeid: %ld Kattuvaid: %ld Hoiatusi: %ld",
+"INSERT TABLE '%-.64s' ei ole lubatud FROM tabelite nimekirjas",
+"Tundmatu lõim: %lu",
+"Ei ole lõime %lu omanik",
+"Ühtegi tabelit pole kasutusel",
+"Liiga palju string tulbale %-.64s tüübile SET",
+"Ei suuda luua unikaalset logifaili nime %-.64s.(1-999)\n",
+"Tabel '%-.64s' on lukustatud READ lukuga ning ei ole muudetav",
+"Tabel '%-.64s' ei ole lukustatud käsuga LOCK TABLES",
+"BLOB-tüüpi tulp '%-.64s' ei saa omada vaikeväärtust",
+"Vigane andmebaasi nimi '%-.100s'",
+"Vigane tabeli nimi '%-.100s'",
+"SELECT lause peab läbi vaatama suure hulga kirjeid ja võtaks tõenäoliselt liiga kaua aega. Tasub kontrollida WHERE klauslit ja vajadusel kasutada käsku SET OPTION SQL_BIG_SELECTS=1",
"Tundmatu viga",
"Tundmatu protseduur '%-.64s'",
-"Väär parameetrite hulk protseduurile '%-.64s'",
-"Valed parameetrid protseduurile '%-.64s'",
-"Tundmatu tabel '%-.64s' %s-s",
+"Vale parameetrite hulk protseduurile '%-.64s'",
+"Vigased parameetrid protseduurile '%-.64s'",
+"Tundmatu tabel '%-.64s' %-.32s-s",
"Tulp '%-.64s' on määratletud topelt",
-"GROUP BY funktsiooni väärkasutamine",
-"Tabel '%-.64s' kasutab laiendit, mis on tundmatu sellele MySQL versioonile",
-"Tabelil peab olema vähemalt üks tulp",
+"Vigane grupeerimisfunktsiooni kasutus",
+"Tabel '%-.64s' kasutab laiendust, mis ei eksisteeri antud MySQL versioonis",
+"Tabelis peab olema vähemalt üks tulp",
"Tabel '%-.64s' on täis",
-"Tundmatu kooditabel: '%-.64s'",
-"Liiga palju tabeleid. MySQL oskab kasutada kuni %d tabelit JOINi puhul",
+"Vigane kooditabel '%-.64s'",
+"Liiga palju tabeleid. MySQL suudab JOINiga ühendada kuni %d tabelit",
"Liiga palju tulpasid",
-"Liiga pikk kirje. Maksimaalne kirje pikkus arvestamata BLOB tüüpi on %d. Võib-olla aitab mõnede väljade muutmine BLOB tüübiks",
-"Threadi stack overrun: Used: %ld of a %ld stack. Use 'mysqld -O thlugeda_stack=#' to specify a bigger stack if needed",
-"Ristsõltuvus OUTER JOIN-s. ON tingimused tuleks üle kontrollida",
-"Tulp '%-.64s' on kasutused indeksis kui pole defineeritud tüübiga NOT NULL",
-"Ei saa avada funktsiooni '%-.64s'",
-"Ei saa algväärtustada funktsiooni '%-.64s'; %-.80s",
+"Liiga pikk kirje. Kirje maksimumpikkus arvestamata BLOB-tüüpi välju on %d. Muuda mõned väljad BLOB-tüüpi väljadeks",
+"Thread stack overrun: Used: %ld of a %ld stack. Use 'mysqld -O thread_stack=#' to specify a bigger stack if needed",
+"Ristsõltuvus OUTER JOIN klauslis. Kontrolli oma ON tingimusi",
+"Tulp '%-.64s' on kasutusel indeksina, kuid ei ole määratletud kui NOT NULL",
+"Ei suuda avada funktsiooni '%-.64s'",
+"Ei suuda algväärtustada funktsiooni '%-.64s'; %-.80s",
"Teegi nimes ei tohi olla kataloogi",
-"Funktsioon '%-.64s' on juba olemas",
-"Ei saa avada teeki '%-.64s' (vea kood: %d %s)",
-"Ei leia funktsiooni '%-.64s' selles teegis'",
-"Funktsiooni '%-.64s' pole defineeritud",
-"Masin '%-.64s' blokeeritud hulgaliste ühendusvigade pärast. Blokeeringu saab eemaldada käsuga 'mysqladmin flush-hosts'",
-"Masinale '%-.64s' pole lubatud ligipääsu sellele MySQL serverile",
+"Funktsioon '%-.64s' juba eksisteerib",
+"Ei suuda avada jagatud teeki '%-.64s' (veakood: %d %-.64s)",
+"Ei leia funktsiooni '%-.64s' antud teegis",
+"Funktsioon '%-.64s' ei ole defineeritud",
+"Masin '%-.64s' on blokeeritud hulgaliste ühendusvigade tõttu. Blokeeringu saab tühistada 'mysqladmin flush-hosts' käsuga",
+"Masinal '%-.64s' puudub ligipääs sellele MySQL serverile",
"Te kasutate MySQL-i anonüümse kasutajana, kelledel pole parooli muutmise õigust",
-"Teil peab olema tabelite muutmise õigus muutmaks teiste paroole",
-"Ei leia kirjet kasutajate tabelis",
-"Sobinud kirjed: %ld Muudetud: %ld Hoiatusi: %ld",
-"Ei saa luua threadi (vea kood %d). Kui mälu pole otsas, tasub operatsioonisüsteemi spetsiifilist viga",
-"Tulpade arv ei vasta väärtuste hulgale reas %ld",
-"Ei saa avada tabelit: '%-.64s',
+"Teiste paroolide muutmiseks on nõutav tabelite muutmisõigus 'mysql' andmebaasis",
+"Ei leia vastavat kirjet kasutajate tabelis",
+"Sobinud kirjeid: %ld Muudetud: %ld Hoiatusi: %ld",
+"Ei suuda luua uut lõime (veakood %d). Kui mälu ei ole otsas, on tõenäoliselt tegemist operatsioonisüsteemispetsiifilise veaga",
+"Tulpade hulk erineb väärtuste hulgast real %ld",
+"Ei suuda taasavada tabelit '%-.64s'",
"NULL väärtuse väärkasutus",
-"Viga '%-.64s' regexp-i käest",
-"GROUP tulpade segamine (MIN(),MAX(),COUNT()...) on väär kui ei kasutata GROUP BY klauslit",
-"Sellist õigust ei ole kasutajale '%-.32s' masinast '%-.64s'",
-"%-.16s käsk pole lubatud kasutajale '%-.32s@%-.64s' tabelile '%-.64s'",
-"%-.16s käsk pole lubatud kasutajale '%-.32s@%-.64s' tulbale '%-.64s' tabelis '%-.64s'",
-"Väär GRANT/REVOKE kasutus",
-"Masina või kasutaja nimi on liiga pikk GRANT lauses",
-"Tabelit '%-64s.%s' ei leitud",
-"Sellist õigust pole kasutajale '%-.32s' masinast '%-.64s' tabelile '%-.64s'",
-"Antud käsk pole lubatud selle MySQL-i versiooniga",
+"regexp tagastas vea '%-.64s'",
+"GROUP tulpade (MIN(),MAX(),COUNT()...) kooskasutamine tavaliste tulpadega ilma GROUP BY klauslita ei ole lubatud",
+"Sellist õigust ei ole defineeritud kasutajale '%-.32s' masinast '%-.64s'",
+"%-.16s käsk ei ole lubatud kasutajale '%-.32s@%-.64s' tabelis '%-.64s'",
+"%-.16s käsk ei ole lubatud kasutajale '%-.32s@%-.64s' tulbale '%-.64s' tabelis '%-.64s'",
+"Vigane GRANT/REVOKE käsk. Tutvu kasutajajuhendiga",
+"Masina või kasutaja nimi GRANT lauses on liiga pikk",
+"Tabelit '%-.64s.%-.64s' ei eksisteeri",
+"Sellist õigust ei ole defineeritud kasutajale '%-.32s' masinast '%-.64s' tabelile '%-.64s'",
+"Antud käsk ei ole lubatud käesolevas MySQL versioonis",
"Viga SQL süntaksis",
-"INSERT DELAYED thread ei saanud nõutavat lukku tabelile %-.64s",
-"Liiga palju DELAYED threade on kasutusel",
-"Ühendus katkestatud %ld andmebaasile '%-.64s' kasutaja '%-.64s' (%s)",
-"Sain lubatust suurema paketi (max_allowed_packet)",
-"Got a read error from the connection pipe",
-"Got an error from fcntl()",
-"Got packets out of order",
-"Ei suuda ühendust lahti pakkida",
-"Viga ühenduse lugemisel",
-"Aeg sai otsa ühenduse lugemisel",
-"Viga ühenduse kirjutamisel",
-"Aeg sai otsa ühenduse kirjutamisel",
-"Tulemuseks saadud string on pikem kui max_allowed_packet väärtus",
-"Kasutatud tabeli tüüp ei toeta BLOB/TEXT tulpasid",
-"Kasutatud tabeli tüüp ei toeta AUTO_INCREMENT tulpasid",
-"INSERT DELAYED käsku ei saa kasutada tabeliga '%-.64s', kuna see on lukus käsuga LOCK TABLES",
-"Väär tulba nimi '%-.100s'",
-"Kasutusel olev tabelite haldur ei oska indekseerida tulpa '%-.64s'",
-"All tables in the MERGE table are not identically defined",
-"Can't write, because of unique constraint, to table '%-.64s'",
-"BLOB column '%-.64s' used in key specification without a key length",
-"All parts of a PRIMARY KEY must be NOT NULL; If you need NULL in a key, use UNIQUE instead",
-"Tulemis on rohkem kui üks kirje",
-"This table type requires a primary key",
-"Antud MySQL ei ole kompileeritud RAID-i toega",
-"You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column",
-"Key '%-.64s' doesn't exist in table '%-.64s'",
-"Ei suuda tabelit avada",
-"See tabelitüüp ei toeta käske CHECK/REPAIR",
-"Puudub õigus selle transaktsioonikäsu andmiseks",
-"Sain vea %d COMMIT käsu täitmisel",
-"Sain vea %d ROLLBACK käsu täitmisel",
-"Sain vea %d FLUSH_LOGS käsu täitmisel",
-"Sain vea %d CHECKPOINT käsu täitmisel",
-"Ühendus %ld katkestatud andmebaas: '%-.64s' kasutaja: '%-.32s' masin: `%-.64s' (%-.64s)",
+"INSERT DELAYED lõim ei suutnud saada soovitud lukku tabelile %-.64s",
+"Liiga palju DELAYED lõimesid kasutusel",
+"Ühendus katkestatud %ld andmebaasile: '%-.64s' kasutajale: '%-.32s' (%-.64s)",
+"Saabus suurem pakett kui lubatud 'max_allowed_packet' muutujaga",
+"Viga ühendustoru lugemisel",
+"fcntl() tagastas vea",
+"Paketid saabusid vales järjekorras",
+"Viga andmepaketi lahtipakkimisel",
+"Viga andmepaketi lugemisel",
+"Kontrollaja ületamine andmepakettide lugemisel",
+"Viga andmepaketi kirjutamisel",
+"Kontrollaja ületamine andmepakettide kirjutamisel",
+"Tulemus on pikem kui lubatud 'max_allowed_packet' muutujaga",
+"Valitud tabelitüüp ei toeta BLOB/TEXT tüüpi välju",
+"Valitud tabelitüüp ei toeta AUTO_INCREMENT tüüpi välju",
+"INSERT DELAYED ei saa kasutada tabeli '%-.64s' peal, kuna see on lukustatud LOCK TABLES käsuga",
+"Vigane tulba nimi '%-.100s'",
+"Tabelihandler ei oska indekseerida tulpa '%-.64s'",
+"Kõik tabelid MERGE tabeli määratluses ei ole identsed",
+"Ei suuda kirjutada tabelisse '%-.64s', kuna see rikub ühesuse kitsendust",
+"BLOB-tüüpi tulp '%-.64s' on kasutusel võtmes ilma pikkust määratlemata",
+"Kõik PRIMARY KEY peavad olema määratletud NOT NULL piiranguga; vajadusel kasuta UNIQUE tüüpi võtit",
+"Tulemis oli rohkem kui üks kirje",
+"Antud tabelitüüp nõuab primaarset võtit",
+"Antud MySQL versioon on kompileeritud ilma RAID toeta",
+"Katse muuta tabelit turvalises rezhiimis ilma WHERE klauslita",
+"Võti '%-.64s' ei eksisteeri tabelis '%-.64s'",
+"Ei suuda avada tabelit",
+"Antud tabelitüüp ei toeta CHECK/REPAIR käske",
+"Seda käsku ei saa kasutada transaktsiooni sees",
+"Viga %d käsu COMMIT täitmisel",
+"Viga %d käsu ROLLBACK täitmisel",
+"Viga %d käsu FLUSH_LOGS täitmisel",
+"Viga %d käsu CHECKPOINT täitmisel",
+"Ühendus katkestatud %ld andmebaas: '%-.64s' kasutaja: '%-.32s' masin: `%-.64s' (%-.64s)",
"The handler for the table does not support binary table dump",
"Binlog closed while trying to FLUSH MASTER",
"Failed rebuilding the index of dumped table '%-.64s'",
"Error from master: '%-.64s'",
"Net error reading from master",
"Net error writing to master",
-"Can't find FULLTEXT index matching the column list",
-"Can't execute the given command because you have active locked tables or an active transaction",
-"Tundmatu süsteemne muutja '%-.64'",
+"Ei suutnud leida FULLTEXT indeksit, mis kattuks kasutatud tulpadega",
+"Ei suuda täita antud käsku kuna on aktiivseid lukke või käimasolev transaktsioon",
+"Tundmatu süsteemne muutuja '%-.64'",
"Tabel '%-.64s' on märgitud vigaseks ja tuleb parandada",
-"Tabel '%-.64s' on märgitud vigaseks ja viimane (automaatne?) parandamiskatse ebaõnnestus",
-"Warning: Some non-transactional changed tables couldn't be rolled back",
-"Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage. Increase this mysqld variable and try again',
+"Tabel '%-.64s' on märgitud vigaseks ja viimane (automaatne?) parandus ebaõnnestus",
+"Hoiatus: mõnesid transaktsioone mittetoetavaid tabeleid ei suudetud tagasi kerida",
+"Mitme lausendiga transaktsioon nõudis rohkem ruumi kui lubatud 'max_binlog_cache_size' muutujaga. Suurenda muutuja väärtust ja proovi uuesti",
"This operation cannot be performed with a running slave, run SLAVE STOP first",
"This operation requires a running slave, configure slave and do SLAVE START",
"The server is not configured as slave, fix in config file or with CHANGE MASTER TO",
"Could not initialize master info structure, check permisions on master.info",
"Could not create slave thread, check system resources",
-"User %-.64s has already more than 'max_user_connections' active connections",
-"You may only use constant expressions with SET",
-"Lock wait timeout exceeded",
-"The total number of locks exceeds the lock table size",
-"Update locks cannot be acquired during a READ UNCOMMITTED transaction",
-"DROP DATABASE not allowed while thread is holding global read lock",
-"CREATE DATABASE not allowed while thread is holding global read lock",
-"Wrong arguments to %s",
-"%-.32s@%-.64s is not allowed to create new users",
-"Incorrect table definition; All MERGE tables must be in the same database",
-"Deadlock found when trying to get lock; Try restarting transaction",
-"The used table type doesn't support FULLTEXT indexes",
+"Kasutajal %-.64s on juba rohkem ühendusi kui lubatud 'max_user_connections' muutujaga",
+"Ainult konstantsed suurused on lubatud SET klauslis",
+"Kontrollaeg ületatud luku järel ootamisel; Proovi transaktsiooni otsast alata",
+"Lukkude koguarv ületab lukutabeli suuruse",
+"Uuenduslukke ei saa kasutada READ UNCOMMITTED transaktsiooni käigus",
+"DROP DATABASE ei ole lubatud kui lõim omab globaalset READ lukku",
+"CREATE DATABASE ei ole lubatud kui lõim omab globaalset READ lukku",
+"Vigased parameetrid %s-le",
+"Kasutajal %-.32s@%-.64s ei ole lubatud luua uusi kasutajaid",
+"Vigane tabelimääratlus; kõik MERGE tabeli liikmed peavad asuma samas andmebaasis",
+"Lukustamisel tekkis tupik (deadlock); alusta transaktsiooni otsast",
+"Antud tabelitüüp ei toeta FULLTEXT indekseid",
"Cannot add foreign key constraint",
"Cannot add a child row: a foreign key constraint fails",
"Cannot delete a parent row: a foreign key constraint fails",
+"Error connecting to master: %-.128s",
+"Error running query on master: %-.128s",
+"Viga käsu %s täitmisel: %-.128s",
+"Vigane %s ja %s kasutus",
+"Tulpade arv kasutatud SELECT lausetes ei kattu",
+"Ei suuda täita päringut konfliktse luku tõttu",
+"Transaktsioone toetavate ning mittetoetavate tabelite kooskasutamine ei ole lubatud",
+"Määrangut '%s' on lauses kasutatud topelt",
+"User '%-64s' has exceeded the '%s' resource (current value: %ld)",
diff --git a/sql/share/french/errmsg.txt b/sql/share/french/errmsg.txt
index 104e561d642..cf3e3e845e4 100644
--- a/sql/share/french/errmsg.txt
+++ b/sql/share/french/errmsg.txt
@@ -219,3 +219,12 @@
"Cannot add foreign key constraint",
"Cannot add a child row: a foreign key constraint fails",
"Cannot delete a parent row: a foreign key constraint fails",
+"Error connecting to master: %-.128s",
+"Error running query on master: %-.128s",
+"Error when executing command %s: %-.128s",
+"Wrong usage of %s and %s",
+"The used SELECT statements have a different number of columns",
+"Can't execute the query because you have a conflicting read lock",
+"Mixing of transactional and non-transactional tables is disabled",
+"Option '%s' used twice in statement",
+"User '%-64s' has exceeded the '%s' resource (current value: %ld)",
diff --git a/sql/share/german/errmsg.txt b/sql/share/german/errmsg.txt
index d0a08a1e7a8..19d46fabab8 100644
--- a/sql/share/german/errmsg.txt
+++ b/sql/share/german/errmsg.txt
@@ -222,3 +222,12 @@
"Cannot add foreign key constraint",
"Cannot add a child row: a foreign key constraint fails",
"Cannot delete a parent row: a foreign key constraint fails",
+"Error connecting to master: %-.128s",
+"Error running query on master: %-.128s",
+"Error when executing command %s: %-.128s",
+"Wrong usage of %s and %s",
+"The used SELECT statements have a different number of columns",
+"Can't execute the query because you have a conflicting read lock",
+"Mixing of transactional and non-transactional tables is disabled",
+"Option '%s' used twice in statement",
+"User '%-64s' has exceeded the '%s' resource (current value: %ld)",
diff --git a/sql/share/greek/errmsg.txt b/sql/share/greek/errmsg.txt
index f778cb857d7..f9b4f137f82 100644
--- a/sql/share/greek/errmsg.txt
+++ b/sql/share/greek/errmsg.txt
@@ -219,3 +219,12 @@
"Cannot add foreign key constraint",
"Cannot add a child row: a foreign key constraint fails",
"Cannot delete a parent row: a foreign key constraint fails",
+"Error connecting to master: %-.128s",
+"Error running query on master: %-.128s",
+"Error when executing command %s: %-.128s",
+"Wrong usage of %s and %s",
+"The used SELECT statements have a different number of columns",
+"Can't execute the query because you have a conflicting read lock",
+"Mixing of transactional and non-transactional tables is disabled",
+"Option '%s' used twice in statement",
+"User '%-64s' has exceeded the '%s' resource (current value: %ld)",
diff --git a/sql/share/hungarian/errmsg.txt b/sql/share/hungarian/errmsg.txt
index 6ff12c8b49e..38877371243 100644
--- a/sql/share/hungarian/errmsg.txt
+++ b/sql/share/hungarian/errmsg.txt
@@ -221,3 +221,12 @@
"Cannot add foreign key constraint",
"Cannot add a child row: a foreign key constraint fails",
"Cannot delete a parent row: a foreign key constraint fails",
+"Error connecting to master: %-.128s",
+"Error running query on master: %-.128s",
+"Error when executing command %s: %-.128s",
+"Wrong usage of %s and %s",
+"The used SELECT statements have a different number of columns",
+"Can't execute the query because you have a conflicting read lock",
+"Mixing of transactional and non-transactional tables is disabled",
+"Option '%s' used twice in statement",
+"User '%-64s' has exceeded the '%s' resource (current value: %ld)",
diff --git a/sql/share/italian/errmsg.txt b/sql/share/italian/errmsg.txt
index 7a3daca9a59..e8cfd5a63a9 100644
--- a/sql/share/italian/errmsg.txt
+++ b/sql/share/italian/errmsg.txt
@@ -219,3 +219,12 @@
"Cannot add foreign key constraint",
"Cannot add a child row: a foreign key constraint fails",
"Cannot delete a parent row: a foreign key constraint fails",
+"Error connecting to master: %-.128s",
+"Error running query on master: %-.128s",
+"Error when executing command %s: %-.128s",
+"Wrong usage of %s and %s",
+"The used SELECT statements have a different number of columns",
+"Can't execute the query because you have a conflicting read lock",
+"Mixing of transactional and non-transactional tables is disabled",
+"Option '%s' used twice in statement",
+"User '%-64s' has exceeded the '%s' resource (current value: %ld)",
diff --git a/sql/share/japanese/errmsg.txt b/sql/share/japanese/errmsg.txt
index fab60948943..98bc099954f 100644
--- a/sql/share/japanese/errmsg.txt
+++ b/sql/share/japanese/errmsg.txt
@@ -221,3 +221,12 @@
"Cannot add foreign key constraint",
"Cannot add a child row: a foreign key constraint fails",
"Cannot delete a parent row: a foreign key constraint fails",
+"Error connecting to master: %-.128s",
+"Error running query on master: %-.128s",
+"Error when executing command %s: %-.128s",
+"Wrong usage of %s and %s",
+"The used SELECT statements have a different number of columns",
+"Can't execute the query because you have a conflicting read lock",
+"Mixing of transactional and non-transactional tables is disabled",
+"Option '%s' used twice in statement",
+"User '%-64s' has exceeded the '%s' resource (current value: %ld)",
diff --git a/sql/share/korean/errmsg.txt b/sql/share/korean/errmsg.txt
index 0dac448e2b2..f6cc890cb39 100644
--- a/sql/share/korean/errmsg.txt
+++ b/sql/share/korean/errmsg.txt
@@ -219,3 +219,12 @@
"Cannot add foreign key constraint",
"Cannot add a child row: a foreign key constraint fails",
"Cannot delete a parent row: a foreign key constraint fails",
+"Error connecting to master: %-.128s",
+"Error running query on master: %-.128s",
+"Error when executing command %s: %-.128s",
+"Wrong usage of %s and %s",
+"The used SELECT statements have a different number of columns",
+"Can't execute the query because you have a conflicting read lock",
+"Mixing of transactional and non-transactional tables is disabled",
+"Option '%s' used twice in statement",
+"User '%-64s' has exceeded the '%s' resource (current value: %ld)",
diff --git a/sql/share/norwegian-ny/errmsg.txt b/sql/share/norwegian-ny/errmsg.txt
index 78075c3990c..adffc27949f 100644
--- a/sql/share/norwegian-ny/errmsg.txt
+++ b/sql/share/norwegian-ny/errmsg.txt
@@ -221,3 +221,12 @@
"Cannot add foreign key constraint",
"Cannot add a child row: a foreign key constraint fails",
"Cannot delete a parent row: a foreign key constraint fails",
+"Error connecting to master: %-.128s",
+"Error running query on master: %-.128s",
+"Error when executing command %s: %-.128s",
+"Wrong usage of %s and %s",
+"The used SELECT statements have a different number of columns",
+"Can't execute the query because you have a conflicting read lock",
+"Mixing of transactional and non-transactional tables is disabled",
+"Option '%s' used twice in statement",
+"User '%-64s' has exceeded the '%s' resource (current value: %ld)",
diff --git a/sql/share/norwegian/errmsg.txt b/sql/share/norwegian/errmsg.txt
index 997d667f812..09a1ea4684c 100644
--- a/sql/share/norwegian/errmsg.txt
+++ b/sql/share/norwegian/errmsg.txt
@@ -221,3 +221,12 @@
"Cannot add foreign key constraint",
"Cannot add a child row: a foreign key constraint fails",
"Cannot delete a parent row: a foreign key constraint fails",
+"Error connecting to master: %-.128s",
+"Error running query on master: %-.128s",
+"Error when executing command %s: %-.128s",
+"Wrong usage of %s and %s",
+"The used SELECT statements have a different number of columns",
+"Can't execute the query because you have a conflicting read lock",
+"Mixing of transactional and non-transactional tables is disabled",
+"Option '%s' used twice in statement",
+"User '%-64s' has exceeded the '%s' resource (current value: %ld)",
diff --git a/sql/share/polish/errmsg.txt b/sql/share/polish/errmsg.txt
index f317d99d48f..12a9bd358b5 100644
--- a/sql/share/polish/errmsg.txt
+++ b/sql/share/polish/errmsg.txt
@@ -223,3 +223,12 @@
"Cannot add foreign key constraint",
"Cannot add a child row: a foreign key constraint fails",
"Cannot delete a parent row: a foreign key constraint fails",
+"Error connecting to master: %-.128s",
+"Error running query on master: %-.128s",
+"Error when executing command %s: %-.128s",
+"Wrong usage of %s and %s",
+"The used SELECT statements have a different number of columns",
+"Can't execute the query because you have a conflicting read lock",
+"Mixing of transactional and non-transactional tables is disabled",
+"Option '%s' used twice in statement",
+"User '%-64s' has exceeded the '%s' resource (current value: %ld)",
diff --git a/sql/share/portuguese/errmsg.txt b/sql/share/portuguese/errmsg.txt
index a3ae06d193f..b7feb0a7b0d 100644
--- a/sql/share/portuguese/errmsg.txt
+++ b/sql/share/portuguese/errmsg.txt
@@ -219,3 +219,12 @@
"Cannot add foreign key constraint",
"Cannot add a child row: a foreign key constraint fails",
"Cannot delete a parent row: a foreign key constraint fails",
+"Error connecting to master: %-.128s",
+"Error running query on master: %-.128s",
+"Error when executing command %s: %-.128s",
+"Wrong usage of %s and %s",
+"The used SELECT statements have a different number of columns",
+"Can't execute the query because you have a conflicting read lock",
+"Mixing of transactional and non-transactional tables is disabled",
+"Option '%s' used twice in statement",
+"User '%-64s' has exceeded the '%s' resource (current value: %ld)",
diff --git a/sql/share/romanian/errmsg.txt b/sql/share/romanian/errmsg.txt
index 26d9f34528a..8e48cabfc39 100644
--- a/sql/share/romanian/errmsg.txt
+++ b/sql/share/romanian/errmsg.txt
@@ -223,3 +223,12 @@
"Cannot add foreign key constraint",
"Cannot add a child row: a foreign key constraint fails",
"Cannot delete a parent row: a foreign key constraint fails",
+"Error connecting to master: %-.128s",
+"Error running query on master: %-.128s",
+"Error when executing command %s: %-.128s",
+"Wrong usage of %s and %s",
+"The used SELECT statements have a different number of columns",
+"Can't execute the query because you have a conflicting read lock",
+"Mixing of transactional and non-transactional tables is disabled",
+"Option '%s' used twice in statement",
+"User '%-64s' has exceeded the '%s' resource (current value: %ld)",
diff --git a/sql/share/russian/errmsg.txt b/sql/share/russian/errmsg.txt
index c02c47696b0..8ed33ec21a0 100644
--- a/sql/share/russian/errmsg.txt
+++ b/sql/share/russian/errmsg.txt
@@ -222,3 +222,12 @@
"Cannot add foreign key constraint",
"Cannot add a child row: a foreign key constraint fails",
"Cannot delete a parent row: a foreign key constraint fails",
+"ïÛÉÂËÁ ÓÏÅÄÉÎÅÎÉÑ Ó master: %-.128s",
+"ïÛÉÂËÁ ×Ù×ÏÌÎÅÎÉÑ ÚÁÐÒÏÓÁ ÎÁ master: %-.128s",
+"ïÛÉÂËÁ ×ÙÐÏÌÎÅÎÉÑ ËÏÍÁÎÄÙ %s: %-.128s",
+"îÅÐÒÁ×ÉÌØÎÏÅ ÉÓÐÏÌØÚÏ×ÁÎÉÅ %s É %s",
+"éÓÐÏÌØÚÕÅÍÙÅ SELECT-×ÙÒÁÖÅÎÉÑ ÉÍÅÀÔ ÒÁÚÎÙÅ ËÏÌÉÞÅÓÔ×Á ÓÔÏÌÂÃÏ×",
+"îÅ×ÏÚÍÏÖÎÏ ×ÙÐÏÌÎÉÔØ ÚÁÐÒÏÓ ÉÚ-ÚÁ ËÏÎÆÌÉËÔÎÏÊ ÂÌÏËÉÒÏ×ËÉ ÞÔÅÎÉÑ",
+"ïÄÎÏ×ÒÅÍÅÎÎÏÅ ÉÓÐÏÌØÚÏ×ÁÎÉÅ transactional É non-transactional ÔÁÂÌÉà ÏÔËÌÀÞÅÎÏ",
+"ïÐÃÉÑ '%s' ÉÓÐÏÌØÚÏ×ÁÎÁ Ä×ÁÖÄÙ",
+"User '%-64s' has exceeded the '%s' resource (current value: %ld)",
diff --git a/sql/share/slovak/errmsg.txt b/sql/share/slovak/errmsg.txt
index 189db8a66f8..06503cdf69e 100644
--- a/sql/share/slovak/errmsg.txt
+++ b/sql/share/slovak/errmsg.txt
@@ -227,3 +227,12 @@
"Cannot add foreign key constraint",
"Cannot add a child row: a foreign key constraint fails",
"Cannot delete a parent row: a foreign key constraint fails",
+"Error connecting to master: %-.128s",
+"Error running query on master: %-.128s",
+"Error when executing command %s: %-.128s",
+"Wrong usage of %s and %s",
+"The used SELECT statements have a different number of columns",
+"Can't execute the query because you have a conflicting read lock",
+"Mixing of transactional and non-transactional tables is disabled",
+"Option '%s' used twice in statement",
+"User '%-64s' has exceeded the '%s' resource (current value: %ld)",
diff --git a/sql/share/spanish/errmsg.txt b/sql/share/spanish/errmsg.txt
index 57d4ac9646a..4240581c5b8 100644
--- a/sql/share/spanish/errmsg.txt
+++ b/sql/share/spanish/errmsg.txt
@@ -220,3 +220,12 @@
"Cannot add foreign key constraint",
"Cannot add a child row: a foreign key constraint fails",
"Cannot delete a parent row: a foreign key constraint fails",
+"Error de coneccion a master: %-128s",
+"Error executando el query en master: %-128%",
+"Error de %s: %-128%",
+"Wrong usage of %s and %s",
+"The used SELECT statements have a different number of columns",
+"Can't execute the query because you have a conflicting read lock",
+"Mixing of transactional and non-transactional tables is disabled",
+"Option '%s' used twice in statement",
+"User '%-64s' has exceeded the '%s' resource (current value: %ld)",
diff --git a/sql/share/swedish/errmsg.OLD b/sql/share/swedish/errmsg.OLD
index cc54e051e63..3dd14c8b613 100644
--- a/sql/share/swedish/errmsg.OLD
+++ b/sql/share/swedish/errmsg.OLD
@@ -205,11 +205,17 @@
"Kunde inte initializera replications-strukturerna. Kontrollera privilegerna för 'master.info'",
"Kunde inte starta en tråd för replikering",
"Användare '%-.64s' har redan 'max_user_connections' aktiva inloggningar",
-"Du kan endast använda konstant-uttryck med SET",
-"Lock wait timeout exceeded",
-"The total number of locks exceeds the lock table size",
-"Update locks cannot be acquired during a READ UNCOMMITTED transaction",
-"DROP DATABASE not allowed while thread is holding global read lock",
-"CREATE DATABASE not allowed while thread is holding global read lock",
-#ER_WRONG_ARGUMENTS
+"Man kan endast använda konstant-uttryck med SET",
+"Fick inte ett lås i tid",
+"Antal lås överskrider antalet reserverade lås",
+"Updaterings-lås kan inte göras när man använder READ UNCOMMITTED",
+"DROP DATABASE är inte tillåtet när man har ett globalt läs-lås",
+"CREATE DATABASE är inte tillåtet när man har ett globalt läs-lås",
"Felaktiga argument till %s",
+"%-.32s@%-.64s har inte rättigheter att skapa nya användare",
+"Fick fel vid anslutning till master: %-.128s",
+"Fick fel vid utförande av command på mastern: %-.128s",
+"Fick fel vid utförande av %s: %-.128s",
+"Felaktig använding av %s and %s",
+"SELECT kommandona har olika antal kolumner"
+"Kan inte utföra kommandot emedan du har ett READ lås",
diff --git a/sql/share/swedish/errmsg.txt b/sql/share/swedish/errmsg.txt
index 1b7b6012a39..e774f4a2c5c 100644
--- a/sql/share/swedish/errmsg.txt
+++ b/sql/share/swedish/errmsg.txt
@@ -219,3 +219,12 @@
"Kan inte lägga till 'FOREIGN KEY constraint'",
"FOREIGN KEY konflikt: Kan inte skriva barn",
"FOREIGN KEY konflikt: Kan inte radera fader",
+"Fick fel vid anslutning till master: %-.128s",
+"Fick fel vid utförande av command på mastern: %-.128s",
+"Fick fel vid utförande av %s: %-.128s",
+"Felaktig använding av %s and %s",
+"SELECT kommandona har olika antal kolumner"
+"Kan inte utföra kommandot emedan du har ett READ lås",
+"Blandning av transaktionella och icke-transaktionella tabeller är inaktiverat",
+"Option '%s' användes två gånger",
+"Användare '%-64s' har överskridit '%s' (nuvarande värde: %ld)",
diff --git a/sql/share/ukrainian/errmsg.txt b/sql/share/ukrainian/errmsg.txt
index 4508fc75c27..c4c89433331 100644
--- a/sql/share/ukrainian/errmsg.txt
+++ b/sql/share/ukrainian/errmsg.txt
@@ -224,3 +224,12 @@
"Cannot add foreign key constraint",
"Cannot add a child row: a foreign key constraint fails",
"Cannot delete a parent row: a foreign key constraint fails",
+"Error connecting to master: %-.128s",
+"Error running query on master: %-.128s",
+"Error when executing command %s: %-.128s",
+"Wrong usage of %s and %s",
+"The used SELECT statements have a different number of columns",
+"Can't execute the query because you have a conflicting read lock",
+"Mixing of transactional and non-transactional tables is disabled",
+"Option '%s' used twice in statement",
+"User '%-64s' has exceeded the '%s' resource (current value: %ld)",
diff --git a/sql/slave.cc b/sql/slave.cc
index cff3af42ce1..100e305530f 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -20,48 +20,131 @@
#include <myisam.h>
#include "mini_client.h"
#include "slave.h"
+#include "sql_repl.h"
+#include "repl_failsafe.h"
#include <thr_alarm.h>
#include <my_dir.h>
+#include <assert.h>
-#define RPL_LOG_NAME (glob_mi.log_file_name[0] ? glob_mi.log_file_name :\
- "FIRST")
-
-volatile bool slave_running = 0;
-pthread_t slave_real_id;
-MASTER_INFO glob_mi;
-MY_BITMAP slave_error_mask;
bool use_slave_mask = 0;
+MY_BITMAP slave_error_mask;
+
+volatile bool slave_sql_running = 0, slave_io_running = 0;
+char* slave_load_tmpdir = 0;
+MASTER_INFO main_mi;
+MASTER_INFO* active_mi;
+volatile int active_mi_in_use = 0;
HASH replicate_do_table, replicate_ignore_table;
DYNAMIC_ARRAY replicate_wild_do_table, replicate_wild_ignore_table;
bool do_table_inited = 0, ignore_table_inited = 0;
bool wild_do_table_inited = 0, wild_ignore_table_inited = 0;
bool table_rules_on = 0;
-uint32 slave_skip_counter = 0;
static TABLE* save_temporary_tables = 0;
-THD* slave_thd = 0;
// when slave thread exits, we need to remember the temporary tables so we
// can re-use them on slave start
-static int last_slave_errno = 0;
-static char last_slave_error[1024] = "";
+// TODO: move the vars below under MASTER_INFO
#ifndef DBUG_OFF
int disconnect_slave_event_count = 0, abort_slave_event_count = 0;
-static int events_till_disconnect = -1, events_till_abort = -1;
+static int events_till_disconnect = -1;
+int events_till_abort = -1;
static int stuck_count = 0;
#endif
+typedef enum { SLAVE_THD_IO, SLAVE_THD_SQL} SLAVE_THD_TYPE;
-inline void skip_load_data_infile(NET* net);
-inline bool slave_killed(THD* thd);
-static int init_slave_thread(THD* thd);
+void skip_load_data_infile(NET* net);
+static int process_io_rotate(MASTER_INFO* mi, Rotate_log_event* rev);
+static int process_io_create_file(MASTER_INFO* mi, Create_file_log_event* cev);
+static int queue_old_event(MASTER_INFO* mi, const char* buf,
+ uint event_len);
+static inline bool slave_killed(THD* thd,MASTER_INFO* mi);
+static inline bool slave_killed(THD* thd,RELAY_LOG_INFO* rli);
+static int init_slave_thread(THD* thd, SLAVE_THD_TYPE thd_type);
static int safe_connect(THD* thd, MYSQL* mysql, MASTER_INFO* mi);
static int safe_reconnect(THD* thd, MYSQL* mysql, MASTER_INFO* mi);
-static int safe_sleep(THD* thd, int sec);
-static int request_table_dump(MYSQL* mysql, char* db, char* table);
+static int connect_to_master(THD* thd, MYSQL* mysql, MASTER_INFO* mi,
+ bool reconnect);
+static int safe_sleep(THD* thd, MASTER_INFO* mi, int sec);
+static int request_table_dump(MYSQL* mysql, const char* db, const char* table);
static int create_table_from_dump(THD* thd, NET* net, const char* db,
const char* table_name);
-inline char* rewrite_db(char* db);
-static int check_expected_error(THD* thd, int expected_error);
+static int check_master_version(MYSQL* mysql, MASTER_INFO* mi);
+
+char* rewrite_db(char* db);
+
+void init_thread_mask(int* mask,MASTER_INFO* mi,bool inverse)
+{
+ bool set_io = mi->slave_running, set_sql = mi->rli.slave_running;
+ if (inverse)
+ {
+ /* This makes me think of the Russian idiom "I am not I, and this is
+ not my horse", which is used to deny reponsibility for
+ one's actions.
+ */
+ set_io = !set_io;
+ set_sql = !set_sql;
+ }
+ register int tmp_mask=0;
+ if (set_io)
+ tmp_mask |= SLAVE_IO;
+ if (set_sql)
+ tmp_mask |= SLAVE_SQL;
+ *mask = tmp_mask;
+}
+
+void lock_slave_threads(MASTER_INFO* mi)
+{
+ //TODO: see if we can do this without dual mutex
+ pthread_mutex_lock(&mi->run_lock);
+ pthread_mutex_lock(&mi->rli.run_lock);
+}
+
+void unlock_slave_threads(MASTER_INFO* mi)
+{
+ //TODO: see if we can do this without dual mutex
+ pthread_mutex_unlock(&mi->rli.run_lock);
+ pthread_mutex_unlock(&mi->run_lock);
+}
+
+int init_slave()
+{
+ // TODO (multi-master): replace this with list initialization
+ active_mi = &main_mi;
+
+ // TODO: the code below is a copy-paste mess - clean it up
+ /*
+ make sure slave thread gets started if server_id is set,
+ valid master.info is present, and master_host has not been specified
+ */
+ if (server_id && !master_host)
+ {
+ // TODO: re-write this to interate through the list of files
+ // for multi-master
+ char fname[FN_REFLEN+128];
+ MY_STAT stat_area;
+ fn_format(fname, master_info_file, mysql_data_home, "", 4+16+32);
+ if (my_stat(fname, &stat_area, MYF(0)) &&
+ !init_master_info(active_mi,master_info_file,relay_log_info_file))
+ master_host = active_mi->host;
+ }
+ // slave thread
+ if (master_host)
+ {
+ if (!opt_skip_slave_start && start_slave_threads(1 /* need mutex */,
+ 0 /* no wait for start*/,
+ active_mi,
+ master_info_file,
+ relay_log_info_file,
+ SLAVE_IO|SLAVE_SQL
+ ))
+ sql_print_error("Warning: Can't create threads to handle slave");
+ else if (opt_skip_slave_start)
+ if (init_master_info(active_mi, master_info_file, relay_log_info_file))
+ sql_print_error("Warning: failed to initialized master info");
+ }
+ return 0;
+}
static void free_table_ent(TABLE_RULE_ENT* e)
{
@@ -75,10 +158,79 @@ static byte* get_table_key(TABLE_RULE_ENT* e, uint* len,
return (byte*)e->db;
}
+// TODO: check proper initialization of master_log_name/master_log_pos
+int init_relay_log_pos(RELAY_LOG_INFO* rli,const char* log,
+ ulonglong pos, bool need_data_lock,
+ const char** errmsg)
+{
+ if (rli->log_pos_current)
+ return 0;
+ pthread_mutex_t *log_lock=rli->relay_log.get_log_lock();
+ pthread_mutex_lock(log_lock);
+ if (need_data_lock)
+ pthread_mutex_lock(&rli->data_lock);
+
+ if (rli->cur_log_fd >= 0)
+ {
+ end_io_cache(&rli->cache_buf);
+ my_close(rli->cur_log_fd, MYF(MY_WME));
+ rli->cur_log_fd = -1;
+ }
+
+ if (!log)
+ log = rli->relay_log_name; // already inited
+ if (!pos)
+ pos = rli->relay_log_pos; // already inited
+ else
+ rli->relay_log_pos = pos;
+ if (rli->relay_log.find_first_log(&rli->linfo,log))
+ {
+ *errmsg="Could not find first log during relay log initialization";
+ goto err;
+ }
+ strnmov(rli->relay_log_name,rli->linfo.log_file_name,
+ sizeof(rli->relay_log_name));
+ // to make end_io_cache(&rli->cache_buf) safe in all cases
+ if (!rli->inited)
+ bzero((char*) &rli->cache_buf, sizeof(IO_CACHE));
+ if (rli->relay_log.is_active(rli->linfo.log_file_name))
+ {
+ if (my_b_tell((rli->cur_log=rli->relay_log.get_log_file())) == 0 &&
+ check_binlog_magic(rli->cur_log,errmsg))
+ {
+ goto err;
+ }
+ rli->cur_log_init_count=rli->cur_log->init_count;
+ }
+ else
+ {
+ if (rli->inited)
+ end_io_cache(&rli->cache_buf);
+ if (rli->cur_log_fd>=0)
+ my_close(rli->cur_log_fd,MYF(MY_WME));
+ if ((rli->cur_log_fd=open_binlog(&rli->cache_buf,
+ rli->linfo.log_file_name,errmsg)) < 0)
+ {
+ goto err;
+ }
+ rli->cur_log = &rli->cache_buf;
+ }
+ if (pos > 4)
+ my_b_seek(rli->cur_log,(off_t)pos);
+ rli->log_pos_current=1;
+err:
+ pthread_cond_broadcast(&rli->data_cond);
+ if (need_data_lock)
+ pthread_mutex_unlock(&rli->data_lock);
+ pthread_mutex_unlock(log_lock);
+ return (*errmsg) ? 1 : 0;
+}
+
/* called from get_options() in mysqld.cc on start-up */
void init_slave_skip_errors(char* arg)
{
char* p;
+ my_bool last_was_digit = 0;
if (bitmap_init(&slave_error_mask,MAX_SLAVE_ERROR,0))
{
fprintf(stderr, "Badly out of memory, please check your system status\n");
@@ -104,6 +256,218 @@ void init_slave_skip_errors(char* arg)
}
}
+// we assume we have a run lock on rli and that the both slave thread
+// are not running
+int purge_relay_logs(RELAY_LOG_INFO* rli, bool just_reset, const char** errmsg)
+{
+ if (!rli->inited)
+ return 0; /* successfully do nothing */
+ DBUG_ASSERT(rli->slave_running == 0);
+ DBUG_ASSERT(rli->mi->slave_running == 0);
+ int error=0;
+ rli->slave_skip_counter=0;
+ pthread_mutex_lock(&rli->data_lock);
+ rli->pending=0;
+ rli->master_log_name[0]=0;
+ rli->master_log_pos=0; // 0 means uninitialized
+ if (rli->relay_log.reset_logs(rli->sql_thd) ||
+ rli->relay_log.find_first_log(&rli->linfo,""))
+ {
+ *errmsg = "Failed during log reset";
+ error=1;
+ goto err;
+ }
+ strnmov(rli->relay_log_name,rli->linfo.log_file_name,
+ sizeof(rli->relay_log_name));
+ rli->relay_log_pos=4;
+ rli->log_pos_current=0;
+ if (!just_reset)
+ error = init_relay_log_pos(rli,0,0,0/*do not need data lock*/,errmsg);
+err:
+ pthread_mutex_unlock(&rli->data_lock);
+ return error;
+}
+
+int terminate_slave_threads(MASTER_INFO* mi,int thread_mask,bool skip_lock)
+{
+ if (!mi->inited)
+ return 0; /* successfully do nothing */
+ int error,force_all = (thread_mask & SLAVE_FORCE_ALL);
+ pthread_mutex_t *sql_lock = &mi->rli.run_lock, *io_lock = &mi->run_lock;
+ pthread_mutex_t *sql_cond_lock,*io_cond_lock;
+
+ sql_cond_lock=sql_lock;
+ io_cond_lock=io_lock;
+
+ if (skip_lock)
+ {
+ sql_lock = io_lock = 0;
+ }
+ if ((thread_mask & (SLAVE_IO|SLAVE_FORCE_ALL)) && mi->slave_running)
+ {
+ mi->abort_slave=1;
+ if ((error=terminate_slave_thread(mi->io_thd,io_lock,
+ io_cond_lock,
+ &mi->stop_cond,
+ &mi->slave_running)) &&
+ !force_all)
+ return error;
+ }
+ if ((thread_mask & (SLAVE_SQL|SLAVE_FORCE_ALL)) && mi->rli.slave_running)
+ {
+ DBUG_ASSERT(mi->rli.sql_thd != 0) ;
+ mi->rli.abort_slave=1;
+ if ((error=terminate_slave_thread(mi->rli.sql_thd,sql_lock,
+ sql_cond_lock,
+ &mi->rli.stop_cond,
+ &mi->rli.slave_running)) &&
+ !force_all)
+ return error;
+ }
+ return 0;
+}
+
+int terminate_slave_thread(THD* thd, pthread_mutex_t* term_lock,
+ pthread_mutex_t *cond_lock,
+ pthread_cond_t* term_cond,
+ volatile bool* slave_running)
+{
+ if (term_lock)
+ {
+ pthread_mutex_lock(term_lock);
+ if (!*slave_running)
+ {
+ pthread_mutex_unlock(term_lock);
+ return ER_SLAVE_NOT_RUNNING;
+ }
+ }
+ DBUG_ASSERT(thd != 0);
+ KICK_SLAVE(thd);
+ while (*slave_running)
+ {
+ /* there is a small chance that slave thread might miss the first
+ alarm. To protect againts it, resend the signal until it reacts
+ */
+ struct timespec abstime;
+#ifdef HAVE_TIMESPEC_TS_SEC
+ abstime.ts_sec=time(NULL)+2;
+ abstime.ts_nsec=0;
+#elif defined(__WIN__)
+ abstime.tv_sec=time((time_t*) 0)+2;
+ abstime.tv_nsec=0;
+#else
+ struct timeval tv;
+ gettimeofday(&tv,0);
+ abstime.tv_sec=tv.tv_sec+2;
+ abstime.tv_nsec=tv.tv_usec*1000;
+#endif
+ pthread_cond_timedwait(term_cond, cond_lock, &abstime);
+ if (*slave_running)
+ KICK_SLAVE(thd);
+ }
+ if (term_lock)
+ pthread_mutex_unlock(term_lock);
+ return 0;
+}
+
+int start_slave_thread(pthread_handler h_func, pthread_mutex_t* start_lock,
+ pthread_mutex_t *cond_lock,
+ pthread_cond_t* start_cond,
+ volatile bool* slave_running,
+ MASTER_INFO* mi)
+{
+ pthread_t th;
+ DBUG_ASSERT(mi->inited);
+ if (start_lock)
+ pthread_mutex_lock(start_lock);
+ if (!server_id)
+ {
+ if (start_cond)
+ pthread_cond_broadcast(start_cond);
+ if (start_lock)
+ pthread_mutex_unlock(start_lock);
+ sql_print_error("Server id not set, will not start slave");
+ return ER_BAD_SLAVE;
+ }
+
+ if (*slave_running)
+ {
+ if (start_cond)
+ pthread_cond_broadcast(start_cond);
+ if (start_lock)
+ pthread_mutex_unlock(start_lock);
+ return ER_SLAVE_MUST_STOP;
+ }
+ if (pthread_create(&th, &connection_attrib, h_func, (void*)mi))
+ {
+ if (start_lock)
+ pthread_mutex_unlock(start_lock);
+ return ER_SLAVE_THREAD;
+ }
+ if (start_cond && cond_lock)
+ {
+ THD* thd = current_thd;
+ while (!*slave_running)
+ {
+ const char* old_msg = thd->enter_cond(start_cond,cond_lock,
+ "Waiting for slave thread to start");
+ pthread_cond_wait(start_cond,cond_lock);
+ thd->exit_cond(old_msg);
+ // TODO: in a very rare case of init_slave_thread failing, it is
+ // possible that we can get stuck here since slave_running will not
+ // be set. We need to change slave_running to int and have -1 as
+ // error code
+ if (thd->killed)
+ {
+ pthread_mutex_unlock(cond_lock);
+ return ER_SERVER_SHUTDOWN;
+ }
+ }
+ }
+ if (start_lock)
+ pthread_mutex_unlock(start_lock);
+ return 0;
+}
+/* SLAVE_FORCE_ALL is not implemented here on purpose since it does not make
+ sense to do that for starting a slave - we always care if it actually
+ started the threads that were not previously running
+*/
+int start_slave_threads(bool need_slave_mutex, bool wait_for_start,
+ MASTER_INFO* mi, const char* master_info_fname,
+ const char* slave_info_fname, int thread_mask)
+{
+ pthread_mutex_t *lock_io=0,*lock_sql=0,*lock_cond_io=0,*lock_cond_sql=0;
+ pthread_cond_t* cond_io=0,*cond_sql=0;
+ int error=0;
+
+ if (need_slave_mutex)
+ {
+ lock_io = &mi->run_lock;
+ lock_sql = &mi->rli.run_lock;
+ }
+ if (wait_for_start)
+ {
+ cond_io = &mi->start_cond;
+ cond_sql = &mi->rli.start_cond;
+ lock_cond_io = &mi->run_lock;
+ lock_cond_sql = &mi->rli.run_lock;
+ }
+ if (init_master_info(mi,master_info_fname,slave_info_fname))
+ return ER_MASTER_INFO;
+
+ if ((thread_mask & SLAVE_IO) &&
+ (error=start_slave_thread(handle_slave_io,lock_io,lock_cond_io,
+ cond_io,&mi->slave_running,
+ mi)))
+ return error;
+ if ((thread_mask & SLAVE_SQL) &&
+ (error=start_slave_thread(handle_slave_sql,lock_sql,lock_cond_sql,
+ cond_sql,
+ &mi->rli.slave_running,mi)))
+ return error;
+ return 0;
+}
+
void init_table_rule_hash(HASH* h, bool* h_inited)
{
hash_init(h, TABLE_RULE_HASH_SIZE,0,0,
@@ -124,11 +488,11 @@ static TABLE_RULE_ENT* find_wild(DYNAMIC_ARRAY *a, const char* key, int len)
uint i;
const char* key_end = key + len;
- for(i = 0; i < a->elements; i++)
+ for (i = 0; i < a->elements; i++)
{
TABLE_RULE_ENT* e ;
get_dynamic(a, (gptr)&e, i);
- if(!wild_case_compare(key, key_end, (const char*)e->db,
+ if (!wild_case_compare(key, key_end, (const char*)e->db,
(const char*)(e->db + e->key_len),'\\'))
return e;
}
@@ -152,7 +516,7 @@ int tables_ok(THD* thd, TABLE_LIST* tables)
if (hash_search(&replicate_do_table, (byte*) hash_key, len))
return 1;
}
- if (ignore_table_inited) // if there are any do's
+ if (ignore_table_inited) // if there are any ignores
{
if (hash_search(&replicate_ignore_table, (byte*) hash_key, len))
return 0;
@@ -217,38 +581,55 @@ static void free_string_array(DYNAMIC_ARRAY *a)
delete_dynamic(a);
}
+static int end_slave_on_walk(MASTER_INFO* mi, gptr /*unused*/)
+{
+ end_master_info(mi);
+ return 0;
+}
+
void end_slave()
{
- pthread_mutex_lock(&LOCK_slave);
- if (slave_running)
- {
- abort_slave = 1;
- thr_alarm_kill(slave_real_id);
-#ifdef SIGNAL_WITH_VIO_CLOSE
- slave_thd->close_active_vio();
-#endif
- while (slave_running)
- pthread_cond_wait(&COND_slave_stopped, &LOCK_slave);
- }
- pthread_mutex_unlock(&LOCK_slave);
-
- end_master_info(&glob_mi);
- if(do_table_inited)
+ // TODO: replace the line below with
+ // list_walk(&master_list, (list_walk_action)end_slave_on_walk,0);
+ // once multi-master code is ready
+ terminate_slave_threads(active_mi,SLAVE_FORCE_ALL);
+ end_master_info(active_mi);
+ if (do_table_inited)
hash_free(&replicate_do_table);
- if(ignore_table_inited)
+ if (ignore_table_inited)
hash_free(&replicate_ignore_table);
- if(wild_do_table_inited)
+ if (wild_do_table_inited)
free_string_array(&replicate_wild_do_table);
- if(wild_ignore_table_inited)
+ if (wild_ignore_table_inited)
free_string_array(&replicate_wild_ignore_table);
}
-inline bool slave_killed(THD* thd)
+static inline bool slave_killed(THD* thd, MASTER_INFO* mi)
{
- return abort_slave || abort_loop || thd->killed;
+ DBUG_ASSERT(mi->io_thd == thd);
+ DBUG_ASSERT(mi->slave_running == 1); // tracking buffer overrun
+ return mi->abort_slave || abort_loop || thd->killed;
}
-inline void skip_load_data_infile(NET* net)
+static inline bool slave_killed(THD* thd, RELAY_LOG_INFO* rli)
+{
+ DBUG_ASSERT(rli->sql_thd == thd);
+ DBUG_ASSERT(rli->slave_running == 1);// tracking buffer overrun
+ return rli->abort_slave || abort_loop || thd->killed;
+}
+
+void slave_print_error(RELAY_LOG_INFO* rli, int err_code, const char* msg, ...)
+{
+ va_list args;
+ va_start(args,msg);
+ my_vsnprintf(rli->last_slave_error,
+ sizeof(rli->last_slave_error), msg, args);
+ sql_print_error("Slave: %s, error_code=%d", rli->last_slave_error,
+ err_code);
+ rli->last_slave_errno = err_code;
+}
+
+void skip_load_data_infile(NET* net)
{
(void)my_net_write(net, "\xfb/dev/null", 10);
(void)net_flush(net);
@@ -256,7 +637,7 @@ inline void skip_load_data_infile(NET* net)
send_ok(net); // the master expects it
}
-inline char* rewrite_db(char* db)
+char* rewrite_db(char* db)
{
if(replicate_rewrite_db.is_empty() || !db) return db;
I_List_iterator<i_string_pair> it(replicate_rewrite_db);
@@ -274,7 +655,7 @@ inline char* rewrite_db(char* db)
int db_ok(const char* db, I_List<i_string> &do_list,
I_List<i_string> &ignore_list )
{
- if(do_list.is_empty() && ignore_list.is_empty())
+ if (do_list.is_empty() && ignore_list.is_empty())
return 1; // ok to replicate if the user puts no constraints
// if the user has specified restrictions on which databases to replicate
@@ -352,16 +733,65 @@ static int init_intvar_from_file(int* var, IO_CACHE* f, int default_val)
return 1;
}
+static int check_master_version(MYSQL* mysql, MASTER_INFO* mi)
+{
+ MYSQL_RES* res;
+ MYSQL_ROW row;
+ const char* version;
+ const char* errmsg = 0;
+
+ if (mc_mysql_query(mysql, "SELECT VERSION()", 0)
+ || !(res = mc_mysql_store_result(mysql)))
+ {
+ sql_print_error("Error checking master version: %s",
+ mc_mysql_error(mysql));
+ return 1;
+ }
+ if (!(row = mc_mysql_fetch_row(res)))
+ {
+ errmsg = "Master returned no rows for SELECT VERSION()";
+ goto err;
+ }
+ if (!(version = row[0]))
+ {
+ errmsg = "Master reported NULL for the version";
+ goto err;
+ }
+
+ switch (*version)
+ {
+ case '3':
+ mi->old_format = 1;
+ break;
+ case '4':
+ mi->old_format = 0;
+ break;
+ default:
+ errmsg = "Master reported unrecognized MySQL version";
+ goto err;
+ }
+err:
+ if (res)
+ mc_mysql_free_result(res);
+ if (errmsg)
+ {
+ sql_print_error(errmsg);
+ return 1;
+ }
+ return 0;
+}
+
static int create_table_from_dump(THD* thd, NET* net, const char* db,
const char* table_name)
{
- uint packet_len = my_net_read(net); // read create table statement
+ ulong packet_len = my_net_read(net); // read create table statement
Vio* save_vio;
HA_CHECK_OPT check_opt;
TABLE_LIST tables;
int error= 1;
handler *file;
+ uint save_options;
if (packet_len == packet_error)
{
@@ -387,12 +817,17 @@ static int create_table_from_dump(THD* thd, NET* net, const char* db,
thd->current_tablenr = 0;
thd->query_error = 0;
thd->net.no_send_ok = 1;
+
+ /* we do not want to log create table statement */
+ save_options = thd->options;
+ thd->options &= ~OPTION_BIN_LOG;
thd->proc_info = "Creating table from master dump";
// save old db in case we are creating in a different database
char* save_db = thd->db;
- thd->db = thd->last_nx_db;
+ thd->db = (char*)db;
mysql_parse(thd, thd->query, packet_len); // run create table
thd->db = save_db; // leave things the way the were before
+ thd->options = save_options;
if (thd->query_error)
goto err; // mysql_parse took care of the error send
@@ -439,51 +874,62 @@ err:
return error;
}
-int fetch_nx_table(THD* thd, MASTER_INFO* mi)
+int fetch_master_table(THD* thd, const char* db_name, const char* table_name,
+ MASTER_INFO* mi, MYSQL* mysql)
{
- MYSQL* mysql = mc_mysql_init(NULL);
int error = 1;
- int nx_errno = 0;
- if (!mysql)
- {
- sql_print_error("fetch_nx_table: Error in mysql_init()");
- nx_errno = ER_GET_ERRNO;
+ int fetch_errno = 0;
+ bool called_connected = (mysql != NULL);
+ if (!called_connected && !(mysql = mc_mysql_init(NULL)))
+ {
+ sql_print_error("fetch_master_table: Error in mysql_init()");
+ fetch_errno = ER_GET_ERRNO;
goto err;
}
- safe_connect(thd, mysql, mi);
- if (slave_killed(thd))
+ if (!called_connected)
+ {
+ if (connect_to_master(thd, mysql, mi))
+ {
+ sql_print_error("Could not connect to master while fetching table\
+ '%-64s.%-64s'", db_name, table_name);
+ fetch_errno = ER_CONNECT_TO_MASTER;
+ goto err;
+ }
+ }
+ if (thd->killed)
goto err;
- if (request_table_dump(mysql, thd->last_nx_db, thd->last_nx_table))
+ if (request_table_dump(mysql, db_name, table_name))
{
- nx_errno = ER_GET_ERRNO;
- sql_print_error("fetch_nx_table: failed on table dump request ");
+ fetch_errno = ER_GET_ERRNO;
+ sql_print_error("fetch_master_table: failed on table dump request ");
goto err;
}
- if (create_table_from_dump(thd, &mysql->net, thd->last_nx_db,
- thd->last_nx_table))
- {
+ if (create_table_from_dump(thd, &mysql->net, db_name,
+ table_name))
+ {
// create_table_from_dump will have sent the error alread
- sql_print_error("fetch_nx_table: failed on create table ");
+ sql_print_error("fetch_master_table: failed on create table ");
goto err;
}
-
error = 0;
-
err:
- if (mysql)
+ if (mysql && !called_connected)
mc_mysql_close(mysql);
- if (nx_errno && thd->net.vio)
- send_error(&thd->net, nx_errno, "Error in fetch_nx_table");
+ if (fetch_errno && thd->net.vio)
+ send_error(&thd->net, fetch_errno, "Error in fetch_master_table");
thd->net.no_send_ok = 0; // Clear up garbage after create_table_from_dump
return error;
}
void end_master_info(MASTER_INFO* mi)
{
- if(mi->fd >= 0)
+ if (!mi->inited)
+ return;
+ end_relay_log_info(&mi->rli);
+ if (mi->fd >= 0)
{
end_io_cache(&mi->file);
(void)my_close(mi->fd, MYF(MY_WME));
@@ -492,21 +938,142 @@ void end_master_info(MASTER_INFO* mi)
mi->inited = 0;
}
-int init_master_info(MASTER_INFO* mi)
+int init_relay_log_info(RELAY_LOG_INFO* rli, const char* info_fname)
+{
+ if (rli->inited)
+ return 0;
+ MY_STAT stat_area;
+ char fname[FN_REFLEN+128];
+ int info_fd;
+ const char* msg = 0;
+ int error = 0;
+
+ fn_format(fname, info_fname,
+ mysql_data_home, "", 4+32);
+ pthread_mutex_lock(&rli->data_lock);
+ info_fd = rli->info_fd;
+ rli->pending = 0;
+ rli->cur_log_fd = -1;
+ rli->slave_skip_counter=0;
+ rli->log_pos_current=0;
+ // TODO: make this work with multi-master
+ if (!opt_relay_logname)
+ {
+ char tmp[FN_REFLEN];
+ /* TODO: The following should be using fn_format(); We just need to
+ first change fn_format() to cut the file name if it's too long.
+ */
+ strmake(tmp,glob_hostname,FN_REFLEN-5);
+ strmov(strcend(tmp,'.'),"-relay-bin");
+ opt_relay_logname=my_strdup(tmp,MYF(MY_WME));
+ }
+ rli->relay_log.set_index_file_name(opt_relaylog_index_name);
+ open_log(&rli->relay_log, glob_hostname, opt_relay_logname, "-relay-bin",
+ LOG_BIN, 1 /* read_append cache */,
+ 1 /* no auto events*/);
+
+ /* if file does not exist */
+ if (!my_stat(fname, &stat_area, MYF(0)))
+ {
+ // if someone removed the file from underneath our feet, just close
+ // the old descriptor and re-create the old file
+ if (info_fd >= 0)
+ my_close(info_fd, MYF(MY_WME));
+ if ((info_fd = my_open(fname, O_CREAT|O_RDWR|O_BINARY, MYF(MY_WME))) < 0
+ || init_io_cache(&rli->info_file, info_fd, IO_SIZE*2, READ_CACHE, 0L,0,
+ MYF(MY_WME)))
+ {
+ if(info_fd >= 0)
+ my_close(info_fd, MYF(0));
+ rli->info_fd=-1;
+ pthread_mutex_unlock(&rli->data_lock);
+ return 1;
+ }
+ if (init_relay_log_pos(rli,"",4,0/*no data mutex*/,&msg))
+ goto err;
+ rli->master_log_pos = 0; // uninitialized
+ rli->info_fd = info_fd;
+ }
+ else // file exists
+ {
+ if(info_fd >= 0)
+ reinit_io_cache(&rli->info_file, READ_CACHE, 0L,0,0);
+ else if((info_fd = my_open(fname, O_RDWR|O_BINARY, MYF(MY_WME))) < 0
+ || init_io_cache(&rli->info_file, info_fd,
+ IO_SIZE*2, READ_CACHE, 0L,
+ 0, MYF(MY_WME)))
+ {
+ if (info_fd >= 0)
+ my_close(info_fd, MYF(0));
+ rli->info_fd=-1;
+ pthread_mutex_unlock(&rli->data_lock);
+ return 1;
+ }
+
+ rli->info_fd = info_fd;
+ if (init_strvar_from_file(rli->relay_log_name,
+ sizeof(rli->relay_log_name), &rli->info_file,
+ (char*)"") ||
+ init_intvar_from_file((int*)&rli->relay_log_pos,
+ &rli->info_file, 4) ||
+ init_strvar_from_file(rli->master_log_name,
+ sizeof(rli->master_log_name), &rli->info_file,
+ (char*)"") ||
+ init_intvar_from_file((int*)&rli->master_log_pos,
+ &rli->info_file, 0))
+ {
+ msg="Error reading slave log configuration";
+ goto err;
+ }
+ if (init_relay_log_pos(rli,0 /*log already inited*/,
+ 0 /*pos already inited*/,
+ 0 /* no data lock*/,
+ &msg))
+ goto err;
+ }
+ DBUG_ASSERT(rli->relay_log_pos >= 4);
+ DBUG_ASSERT(my_b_tell(rli->cur_log) == rli->relay_log_pos);
+ rli->inited = 1;
+ // now change the cache from READ to WRITE - must do this
+ // before flush_relay_log_info
+ reinit_io_cache(&rli->info_file, WRITE_CACHE,0L,0,1);
+ error=test(flush_relay_log_info(rli));
+ pthread_mutex_unlock(&rli->data_lock);
+ return error;
+
+err:
+ sql_print_error(msg);
+ end_io_cache(&rli->info_file);
+ my_close(info_fd, MYF(0));
+ rli->info_fd=-1;
+ pthread_mutex_unlock(&rli->data_lock);
+ return 1;
+}
+
+
+int init_master_info(MASTER_INFO* mi, const char* master_info_fname,
+ const char* slave_info_fname)
{
if (mi->inited)
return 0;
- int fd,length,error;
+ if (init_relay_log_info(&mi->rli, slave_info_fname))
+ return 1;
+ mi->rli.mi = mi;
+ mi->mysql=0;
+ mi->file_id=1;
+ mi->ignore_stop_event=0;
+ int fd,error;
MY_STAT stat_area;
char fname[FN_REFLEN+128];
const char *msg;
- fn_format(fname, master_info_file, mysql_data_home, "", 4+16+32);
+ fn_format(fname, master_info_fname, mysql_data_home, "", 4+32);
- // we need a mutex while we are changing master info parameters to
- // keep other threads from reading bogus info
+ /*
+ We need a mutex while we are changing master info parameters to
+ keep other threads from reading bogus info
+ */
- pthread_mutex_lock(&mi->lock);
- mi->pending = 0;
+ pthread_mutex_lock(&mi->data_lock);
fd = mi->fd;
// we do not want any messages if the file does not exist
@@ -522,11 +1089,13 @@ int init_master_info(MASTER_INFO* mi)
{
if(fd >= 0)
my_close(fd, MYF(0));
- pthread_mutex_unlock(&mi->lock);
+ mi->fd=-1;
+ end_relay_log_info(&mi->rli);
+ pthread_mutex_unlock(&mi->data_lock);
return 1;
}
- mi->log_file_name[0] = 0;
- mi->pos = 4; // skip magic number
+ mi->master_log_name[0] = 0;
+ mi->master_log_pos = 4; // skip magic number
mi->fd = fd;
if (master_host)
@@ -548,99 +1117,145 @@ int init_master_info(MASTER_INFO* mi)
{
if(fd >= 0)
my_close(fd, MYF(0));
- pthread_mutex_unlock(&mi->lock);
+ mi->fd=-1;
+ end_relay_log_info(&mi->rli);
+ pthread_mutex_unlock(&mi->data_lock);
return 1;
}
-
- if ((length=my_b_gets(&mi->file, mi->log_file_name,
- sizeof(mi->log_file_name))) < 1)
- {
- msg="Error reading log file name from master info file ";
- goto error;
- }
-
- mi->log_file_name[length-1]= 0; // kill \n
- /* Reuse fname buffer */
- if(!my_b_gets(&mi->file, fname, sizeof(fname)))
- {
- msg="Error reading log file position from master info file";
- goto error;
- }
- mi->pos = strtoull(fname,(char**) 0, 10);
mi->fd = fd;
- if(init_strvar_from_file(mi->host, sizeof(mi->host), &mi->file,
- master_host) ||
- init_strvar_from_file(mi->user, sizeof(mi->user), &mi->file,
- master_user) ||
- init_strvar_from_file(mi->password, HASH_PASSWORD_LENGTH+1, &mi->file,
- master_password) ||
- init_intvar_from_file((int*)&mi->port, &mi->file, master_port) ||
- init_intvar_from_file((int*)&mi->connect_retry, &mi->file,
- master_connect_retry))
+ if (init_strvar_from_file(mi->master_log_name,
+ sizeof(mi->master_log_name), &mi->file,
+ (char*)"") ||
+ init_intvar_from_file((int*)&mi->master_log_pos, &mi->file, 4) ||
+ init_strvar_from_file(mi->host, sizeof(mi->host), &mi->file,
+ master_host) ||
+ init_strvar_from_file(mi->user, sizeof(mi->user), &mi->file,
+ master_user) ||
+ init_strvar_from_file(mi->password, HASH_PASSWORD_LENGTH+1, &mi->file,
+ master_password) ||
+ init_intvar_from_file((int*)&mi->port, &mi->file, master_port) ||
+ init_intvar_from_file((int*)&mi->connect_retry, &mi->file,
+ master_connect_retry))
{
msg="Error reading master configuration";
- goto error;
+ goto err;
}
}
mi->inited = 1;
- // now change the cache from READ to WRITE - must do this
- // before flush_master_info
- reinit_io_cache(&mi->file, WRITE_CACHE, 0L,0,1);
+ // now change cache READ -> WRITE - must do this before flush_master_info
+ reinit_io_cache(&mi->file, WRITE_CACHE,0L,0,1);
error=test(flush_master_info(mi));
- pthread_mutex_unlock(&mi->lock);
+ pthread_mutex_unlock(&mi->data_lock);
return error;
-error:
+err:
sql_print_error(msg);
end_io_cache(&mi->file);
+ end_relay_log_info(&mi->rli);
+ DBUG_ASSERT(fd>=0);
my_close(fd, MYF(0));
- pthread_mutex_unlock(&mi->lock);
+ mi->fd=-1;
+ pthread_mutex_unlock(&mi->data_lock);
return 1;
}
-int show_master_info(THD* thd)
+int register_slave_on_master(MYSQL* mysql)
{
+ String packet;
+ char buf[4];
+
+ if (!report_host)
+ return 0;
+
+ int4store(buf, server_id);
+ packet.append(buf, 4);
+
+ net_store_data(&packet, report_host);
+ if (report_user)
+ net_store_data(&packet, report_user);
+ else
+ packet.append((char)0);
+
+ if(report_password)
+ net_store_data(&packet, report_user);
+ else
+ packet.append((char)0);
+
+ int2store(buf, (uint16)report_port);
+ packet.append(buf, 2);
+ int4store(buf, rpl_recovery_rank);
+ packet.append(buf, 4);
+ int4store(buf, 0); /* tell the master will fill in master_id */
+ packet.append(buf, 4);
+
+ if (mc_simple_command(mysql, COM_REGISTER_SLAVE, (char*)packet.ptr(),
+ packet.length(), 0))
+ {
+ sql_print_error("Error on COM_REGISTER_SLAVE: '%s'",
+ mc_mysql_error(mysql));
+ return 1;
+ }
+
+ return 0;
+}
+
+int show_master_info(THD* thd, MASTER_INFO* mi)
+{
+ // TODO: fix this for multi-master
DBUG_ENTER("show_master_info");
List<Item> field_list;
field_list.push_back(new Item_empty_string("Master_Host",
- sizeof(glob_mi.host)));
+ sizeof(mi->host)));
field_list.push_back(new Item_empty_string("Master_User",
- sizeof(glob_mi.user)));
+ sizeof(mi->user)));
field_list.push_back(new Item_empty_string("Master_Port", 6));
field_list.push_back(new Item_empty_string("Connect_retry", 6));
- field_list.push_back( new Item_empty_string("Log_File",
+ field_list.push_back(new Item_empty_string("Master_Log_File",
+ FN_REFLEN));
+ field_list.push_back(new Item_empty_string("Read_Master_Log_Pos", 12));
+ field_list.push_back(new Item_empty_string("Relay_Log_File",
FN_REFLEN));
- field_list.push_back(new Item_empty_string("Pos", 12));
- field_list.push_back(new Item_empty_string("Slave_Running", 3));
+ field_list.push_back(new Item_empty_string("Relay_Log_Pos", 12));
+ field_list.push_back(new Item_empty_string("Relay_Master_Log_File",
+ FN_REFLEN));
+ field_list.push_back(new Item_empty_string("Slave_IO_Running", 3));
+ field_list.push_back(new Item_empty_string("Slave_SQL_Running", 3));
field_list.push_back(new Item_empty_string("Replicate_do_db", 20));
field_list.push_back(new Item_empty_string("Replicate_ignore_db", 20));
field_list.push_back(new Item_empty_string("Last_errno", 4));
field_list.push_back(new Item_empty_string("Last_error", 20));
field_list.push_back(new Item_empty_string("Skip_counter", 12));
+ field_list.push_back(new Item_empty_string("Exec_master_log_pos", 12));
if(send_fields(thd, field_list, 1))
DBUG_RETURN(-1);
String* packet = &thd->packet;
packet->length(0);
- pthread_mutex_lock(&glob_mi.lock);
- net_store_data(packet, glob_mi.host);
- net_store_data(packet, glob_mi.user);
- net_store_data(packet, (uint32) glob_mi.port);
- net_store_data(packet, (uint32) glob_mi.connect_retry);
- net_store_data(packet, glob_mi.log_file_name);
- net_store_data(packet, (uint32) glob_mi.pos); // QQ: Should be fixed
- pthread_mutex_unlock(&glob_mi.lock);
- pthread_mutex_lock(&LOCK_slave);
- net_store_data(packet, slave_running ? "Yes":"No");
- pthread_mutex_unlock(&LOCK_slave);
+ pthread_mutex_lock(&mi->data_lock);
+ pthread_mutex_lock(&mi->rli.data_lock);
+ net_store_data(packet, mi->host);
+ net_store_data(packet, mi->user);
+ net_store_data(packet, (uint32) mi->port);
+ net_store_data(packet, (uint32) mi->connect_retry);
+ net_store_data(packet, mi->master_log_name);
+ net_store_data(packet, (longlong) mi->master_log_pos);
+ net_store_data(packet, mi->rli.relay_log_name +
+ dirname_length(mi->rli.relay_log_name));
+ net_store_data(packet, (longlong) mi->rli.relay_log_pos);
+ net_store_data(packet, mi->rli.master_log_name);
+ net_store_data(packet, mi->slave_running ? "Yes":"No");
+ net_store_data(packet, mi->rli.slave_running ? "Yes":"No");
net_store_data(packet, &replicate_do_db);
net_store_data(packet, &replicate_ignore_db);
- net_store_data(packet, (uint32)last_slave_errno);
- net_store_data(packet, last_slave_error);
- net_store_data(packet, slave_skip_counter);
+ net_store_data(packet, (uint32)mi->rli.last_slave_errno);
+ net_store_data(packet, mi->rli.last_slave_error);
+ net_store_data(packet, mi->rli.slave_skip_counter);
+ net_store_data(packet, (longlong) mi->rli.master_log_pos);
+ pthread_mutex_unlock(&mi->rli.data_lock);
+ pthread_mutex_unlock(&mi->data_lock);
if (my_net_write(&thd->net, (char*)thd->packet.ptr(), packet->length()))
DBUG_RETURN(-1);
@@ -655,54 +1270,58 @@ int flush_master_info(MASTER_INFO* mi)
char lbuf[22];
my_b_seek(file, 0L);
- my_b_printf(file, "%s\n%s\n%s\n%s\n%s\n%d\n%d\n",
- mi->log_file_name, llstr(mi->pos, lbuf), mi->host, mi->user,
- mi->password, mi->port, mi->connect_retry);
+ my_b_printf(file, "%s\n%s\n%s\n%s\n%s\n%d\n%d\n%d\n",
+ mi->master_log_name, llstr(mi->master_log_pos, lbuf),
+ mi->host, mi->user,
+ mi->password, mi->port, mi->connect_retry
+ );
flush_io_cache(file);
return 0;
}
-int st_master_info::wait_for_pos(THD* thd, String* log_name, ulonglong log_pos)
+int st_relay_log_info::wait_for_pos(THD* thd, String* log_name,
+ ulonglong log_pos)
{
if (!inited) return -1;
- bool pos_reached;
+ bool pos_reached = 0;
int event_count = 0;
- pthread_mutex_lock(&lock);
- while(!thd->killed)
+ pthread_mutex_lock(&data_lock);
+ while (!thd->killed)
{
int cmp_result;
- if (*log_file_name)
+ DBUG_ASSERT(*master_log_name || master_log_pos == 0);
+ if (*master_log_name)
{
/*
We should use dirname_length() here when we have a version of
this that doesn't modify the argument */
- char *basename = strrchr(log_file_name, FN_LIBCHAR);
+ char *basename = strrchr(master_log_name, FN_LIBCHAR);
if (basename)
++basename;
else
- basename = log_file_name;
+ basename = master_log_name;
cmp_result = strncmp(basename, log_name->ptr(),
log_name->length());
}
else
cmp_result = 0;
- pos_reached = ((!cmp_result && pos >= log_pos) || cmp_result > 0);
+ pos_reached = ((!cmp_result && master_log_pos >= log_pos) ||
+ cmp_result > 0);
if (pos_reached || thd->killed)
break;
- const char* msg = thd->enter_cond(&cond, &lock,
+ const char* msg = thd->enter_cond(&data_cond, &data_lock,
"Waiting for master update");
- pthread_cond_wait(&cond, &lock);
+ pthread_cond_wait(&data_cond, &data_lock);
thd->exit_cond(msg);
event_count++;
}
- pthread_mutex_unlock(&lock);
+ pthread_mutex_unlock(&data_lock);
return thd->killed ? -1 : event_count;
}
-
-static int init_slave_thread(THD* thd)
+static int init_slave_thread(THD* thd, SLAVE_THD_TYPE thd_type)
{
DBUG_ENTER("init_slave_thread");
thd->system_thread = thd->bootstrap = 1;
@@ -716,7 +1335,7 @@ static int init_slave_thread(THD* thd)
thd->options = (((opt_log_slave_updates) ? OPTION_BIN_LOG:0) | OPTION_AUTO_IS_NULL) ;
thd->system_thread = 1;
thd->client_capabilities = CLIENT_LOCAL_FILES;
- slave_real_id=thd->real_id=pthread_self();
+ thd->real_id=pthread_self();
pthread_mutex_lock(&LOCK_thread_count);
thd->thread_id = thread_id++;
pthread_mutex_unlock(&LOCK_thread_count);
@@ -726,7 +1345,6 @@ static int init_slave_thread(THD* thd)
my_pthread_setspecific_ptr(THR_MALLOC, &thd->mem_root) ||
my_pthread_setspecific_ptr(THR_NET, &thd->net))
{
- close_connection(&thd->net,ER_OUT_OF_RESOURCES); // is this needed?
end_thread(thd,0);
DBUG_RETURN(-1);
}
@@ -743,14 +1361,21 @@ static int init_slave_thread(THD* thd)
if (thd->max_join_size == (ulong) ~0L)
thd->options |= OPTION_BIG_SELECTS;
- thd->proc_info="Waiting for master update";
+ if (thd_type == SLAVE_THD_SQL)
+ {
+ thd->proc_info = "Waiting for the next event in slave queue";
+ }
+ else
+ {
+ thd->proc_info="Waiting for master update";
+ }
thd->version=refresh_version;
thd->set_time();
DBUG_RETURN(0);
}
-static int safe_sleep(THD* thd, int sec)
+static int safe_sleep(THD* thd, MASTER_INFO* mi, int sec)
{
thr_alarm_t alarmed;
thr_alarm_init(&alarmed);
@@ -773,21 +1398,21 @@ static int safe_sleep(THD* thd, int sec)
if (thr_alarm_in_use(&alarmed))
thr_end_alarm(&alarmed);
- if (slave_killed(thd))
+ if (slave_killed(thd,mi))
return 1;
start_time=time((time_t*) 0);
}
return 0;
}
-
static int request_dump(MYSQL* mysql, MASTER_INFO* mi)
{
char buf[FN_REFLEN + 10];
int len;
int binlog_flags = 0; // for now
- char* logname = mi->log_file_name;
- int4store(buf, mi->pos);
+ char* logname = mi->master_log_name;
+ // TODO if big log files: Change next to int8store()
+ int4store(buf, (longlong) mi->master_log_pos);
int2store(buf + 4, binlog_flags);
int4store(buf + 6, server_id);
len = (uint) strlen(logname);
@@ -805,7 +1430,7 @@ static int request_dump(MYSQL* mysql, MASTER_INFO* mi)
return 0;
}
-static int request_table_dump(MYSQL* mysql, char* db, char* table)
+static int request_table_dump(MYSQL* mysql, const char* db, const char* table)
{
char buf[1024];
char * p = buf;
@@ -833,10 +1458,9 @@ command");
return 0;
}
-
-static uint read_event(MYSQL* mysql, MASTER_INFO *mi)
+static ulong read_event(MYSQL* mysql, MASTER_INFO *mi)
{
- uint len = packet_error;
+ ulong len = packet_error;
// for convinience lets think we start by
// being in the interrupted state :-)
int read_errno = EINTR;
@@ -848,15 +1472,15 @@ static uint read_event(MYSQL* mysql, MASTER_INFO *mi)
return packet_error;
#endif
- while (!abort_loop && !abort_slave && len == packet_error &&
+ while (!abort_loop && !mi->abort_slave && len == packet_error &&
read_errno == EINTR )
{
len = mc_net_safe_read(mysql);
read_errno = errno;
}
- if (abort_loop || abort_slave)
+ if (abort_loop || mi->abort_slave)
return packet_error;
- if (len == packet_error || (int) len < 1)
+ if (len == packet_error || (long) len < 1)
{
sql_print_error("Error reading packet from server: %s (read_errno %d,\
server_errno=%d)",
@@ -877,328 +1501,71 @@ server_errno=%d)",
return len - 1;
}
-static int check_expected_error(THD* thd, int expected_error)
+int check_expected_error(THD* thd, RELAY_LOG_INFO* rli, int expected_error)
{
- switch(expected_error)
+ switch (expected_error)
{
case ER_NET_READ_ERROR:
case ER_NET_ERROR_ON_WRITE:
case ER_SERVER_SHUTDOWN:
case ER_NEW_ABORTING_CONNECTION:
- my_snprintf(last_slave_error, sizeof(last_slave_error),
+ my_snprintf(rli->last_slave_error, sizeof(rli->last_slave_error),
"Slave: query '%s' partially completed on the master \
and was aborted. There is a chance that your master is inconsistent at this \
point. If you are sure that your master is ok, run this query manually on the\
slave and then restart the slave with SET SQL_SLAVE_SKIP_COUNTER=1;\
SLAVE START;", thd->query);
- last_slave_errno = expected_error;
- sql_print_error("%s",last_slave_error);
+ rli->last_slave_errno = expected_error;
+ sql_print_error("%s",rli->last_slave_error);
return 1;
default:
return 0;
}
}
-inline int ignored_error_code(int err_code)
+static int exec_relay_log_event(THD* thd, RELAY_LOG_INFO* rli)
{
- return use_slave_mask && bitmap_is_set(&slave_error_mask, err_code);
-}
-
-static int exec_event(THD* thd, NET* net, MASTER_INFO* mi, int event_len)
-{
- Log_event * ev = Log_event::read_log_event((const char*)net->read_pos + 1,
- event_len);
- char llbuff[22];
-
+ DBUG_ASSERT(rli->sql_thd==thd);
+ Log_event * ev = next_event(rli);
+ DBUG_ASSERT(rli->sql_thd==thd);
+ if (slave_killed(thd,rli))
+ return 1;
if (ev)
{
int type_code = ev->get_type_code();
- if (ev->server_id == ::server_id || slave_skip_counter)
+ int exec_res;
+ pthread_mutex_lock(&rli->data_lock);
+ if (ev->server_id == ::server_id ||
+ (rli->slave_skip_counter && type_code != ROTATE_EVENT))
{
- if(type_code == LOAD_EVENT)
- skip_load_data_infile(net);
-
- mi->inc_pos(event_len);
- flush_master_info(mi);
- if(slave_skip_counter && /* protect against common user error of
+ /* TODO: I/O thread should not even log events with the same server id */
+ rli->inc_pos(ev->get_event_len(),
+ type_code != STOP_EVENT ? ev->log_pos : LL(0),
+ 1/* skip lock*/);
+ flush_relay_log_info(rli);
+ if (rli->slave_skip_counter && /* protect against common user error of
setting the counter to 1 instead of 2
while recovering from an failed
auto-increment insert */
- !(type_code == INTVAR_EVENT &&
- slave_skip_counter == 1))
- --slave_skip_counter;
+ !((type_code == INTVAR_EVENT || type_code == STOP_EVENT) &&
+ rli->slave_skip_counter == 1))
+ --rli->slave_skip_counter;
+ pthread_mutex_unlock(&rli->data_lock);
delete ev;
return 0; // avoid infinite update loops
}
+ pthread_mutex_unlock(&rli->data_lock);
thd->server_id = ev->server_id; // use the original server id for logging
thd->set_time(); // time the query
- if(!ev->when)
+ if (!ev->when)
ev->when = time(NULL);
-
- switch(type_code) {
- case QUERY_EVENT:
- {
- Query_log_event* qev = (Query_log_event*)ev;
- int q_len = qev->q_len;
- int expected_error,actual_error = 0;
- init_sql_alloc(&thd->mem_root, 8192,0);
- thd->db = rewrite_db((char*)qev->db);
- if (db_ok(thd->db, replicate_do_db, replicate_ignore_db))
- {
- thd->query = (char*)qev->query;
- thd->set_time((time_t)qev->when);
- thd->current_tablenr = 0;
- VOID(pthread_mutex_lock(&LOCK_thread_count));
- thd->query_id = query_id++;
- VOID(pthread_mutex_unlock(&LOCK_thread_count));
- thd->last_nx_table = thd->last_nx_db = 0;
- thd->query_error = 0; // clear error
- thd->net.last_errno = 0;
- thd->net.last_error[0] = 0;
- thd->slave_proxy_id = qev->thread_id; // for temp tables
-
- // sanity check to make sure the master did not get a really bad
- // error on the query
- if (ignored_error_code((expected_error=qev->error_code)) ||
- !check_expected_error(thd, expected_error))
- {
- mysql_parse(thd, thd->query, q_len);
- if (expected_error !=
- (actual_error = thd->net.last_errno) && expected_error &&
- !ignored_error_code(actual_error))
- {
- const char* errmsg = "Slave: did not get the expected error\
- running query from master - expected: '%s' (%d), got '%s' (%d)";
- sql_print_error(errmsg, ER_SAFE(expected_error),
- expected_error,
- actual_error ? thd->net.last_error:"no error",
- actual_error);
- thd->query_error = 1;
- }
- else if (expected_error == actual_error ||
- ignored_error_code(actual_error))
- {
- thd->query_error = 0;
- *last_slave_error = 0;
- last_slave_errno = 0;
- }
- }
- else
- {
- // master could be inconsistent, abort and tell DBA to check/fix it
- thd->db = thd->query = 0;
- thd->convert_set = 0;
- close_thread_tables(thd);
- free_root(&thd->mem_root,0);
- delete ev;
- return 1;
- }
- }
- thd->db = 0; // prevent db from being freed
- thd->query = 0; // just to be sure
- // assume no convert for next query unless set explictly
- thd->convert_set = 0;
- close_thread_tables(thd);
-
- if (thd->query_error || thd->fatal_error)
- {
- sql_print_error("Slave: error running query '%s' ",
- qev->query);
- last_slave_errno = actual_error ? actual_error : -1;
- my_snprintf(last_slave_error, sizeof(last_slave_error),
- "error '%s' on query '%s'",
- actual_error ? thd->net.last_error :
- "unexpected success or fatal error",
- qev->query
- );
- free_root(&thd->mem_root,0);
- delete ev;
- return 1;
- }
- free_root(&thd->mem_root,0);
- delete ev;
-
- mi->inc_pos(event_len);
- flush_master_info(mi);
- break;
- }
-
- case LOAD_EVENT:
- {
- Load_log_event* lev = (Load_log_event*)ev;
- init_sql_alloc(&thd->mem_root, 8192,0);
- thd->db = rewrite_db((char*)lev->db);
- thd->query = 0;
- thd->query_error = 0;
-
- if(db_ok(thd->db, replicate_do_db, replicate_ignore_db))
- {
- thd->set_time((time_t)lev->when);
- thd->current_tablenr = 0;
- VOID(pthread_mutex_lock(&LOCK_thread_count));
- thd->query_id = query_id++;
- VOID(pthread_mutex_unlock(&LOCK_thread_count));
-
- TABLE_LIST tables;
- bzero((char*) &tables,sizeof(tables));
- tables.db = thd->db;
- tables.name = tables.real_name = (char*)lev->table_name;
- tables.lock_type = TL_WRITE;
- // the table will be opened in mysql_load
- if(table_rules_on && !tables_ok(thd, &tables))
- {
- skip_load_data_infile(net);
- }
- else
- {
- enum enum_duplicates handle_dup = DUP_IGNORE;
- if(lev->sql_ex.opt_flags && REPLACE_FLAG)
- handle_dup = DUP_REPLACE;
- sql_exchange ex((char*)lev->fname, lev->sql_ex.opt_flags &&
- DUMPFILE_FLAG );
- String field_term(&lev->sql_ex.field_term, 1),
- enclosed(&lev->sql_ex.enclosed, 1),
- line_term(&lev->sql_ex.line_term,1),
- escaped(&lev->sql_ex.escaped, 1),
- line_start(&lev->sql_ex.line_start, 1);
-
- ex.field_term = &field_term;
- if(lev->sql_ex.empty_flags & FIELD_TERM_EMPTY)
- ex.field_term->length(0);
-
- ex.enclosed = &enclosed;
- if(lev->sql_ex.empty_flags & ENCLOSED_EMPTY)
- ex.enclosed->length(0);
-
- ex.line_term = &line_term;
- if(lev->sql_ex.empty_flags & LINE_TERM_EMPTY)
- ex.line_term->length(0);
-
- ex.line_start = &line_start;
- if(lev->sql_ex.empty_flags & LINE_START_EMPTY)
- ex.line_start->length(0);
-
- ex.escaped = &escaped;
- if(lev->sql_ex.empty_flags & ESCAPED_EMPTY)
- ex.escaped->length(0);
-
- ex.opt_enclosed = (lev->sql_ex.opt_flags & OPT_ENCLOSED_FLAG);
- if(lev->sql_ex.empty_flags & FIELD_TERM_EMPTY)
- ex.field_term->length(0);
-
- ex.skip_lines = lev->skip_lines;
-
-
- List<Item> fields;
- lev->set_fields(fields);
- thd->slave_proxy_id = thd->thread_id;
- thd->net.vio = net->vio;
- // mysql_load will use thd->net to read the file
- thd->net.pkt_nr = net->pkt_nr;
- // make sure the client does not get confused
- // about the packet sequence
- if(mysql_load(thd, &ex, &tables, fields, handle_dup, 1,
- TL_WRITE))
- thd->query_error = 1;
- if(thd->cuted_fields)
- sql_print_error("Slave: load data infile at position %s in log \
-'%s' produced %d warning(s)", llstr(glob_mi.pos,llbuff), RPL_LOG_NAME,
- thd->cuted_fields );
- net->pkt_nr = thd->net.pkt_nr;
- }
- }
- else
- {
- // we will just ask the master to send us /dev/null if we do not
- // want to load the data :-)
- skip_load_data_infile(net);
- }
-
- thd->net.vio = 0;
- thd->db = 0;// prevent db from being freed
- close_thread_tables(thd);
- if(thd->query_error)
- {
- int sql_error = thd->net.last_errno;
- if(!sql_error)
- sql_error = ER_UNKNOWN_ERROR;
-
- sql_print_error("Slave: Error '%s' running load data infile ",
- ER(sql_error));
- delete ev;
- free_root(&thd->mem_root,0);
- return 1;
- }
-
- delete ev;
- free_root(&thd->mem_root,0);
-
- if(thd->fatal_error)
- {
- sql_print_error("Slave: Fatal error running query '%s' ",
- thd->query);
- return 1;
- }
-
- mi->inc_pos(event_len);
- flush_master_info(mi);
- break;
- }
-
- case START_EVENT:
- mi->inc_pos(event_len);
- flush_master_info(mi);
- delete ev;
- break;
-
- case STOP_EVENT:
- if(mi->pos > 4) // stop event should be ignored after rotate event
- {
- close_temporary_tables(thd);
- mi->inc_pos(event_len);
- flush_master_info(mi);
- }
- delete ev;
- break;
- case ROTATE_EVENT:
- {
- Rotate_log_event* rev = (Rotate_log_event*)ev;
- int ident_len = rev->ident_len;
- pthread_mutex_lock(&mi->lock);
- memcpy(mi->log_file_name, rev->new_log_ident,ident_len );
- mi->log_file_name[ident_len] = 0;
- mi->pos = 4; // skip magic number
- pthread_cond_broadcast(&mi->cond);
- pthread_mutex_unlock(&mi->lock);
- flush_master_info(mi);
-#ifndef DBUG_OFF
- if(abort_slave_event_count)
- ++events_till_abort;
-#endif
- delete ev;
- break;
- }
-
- case INTVAR_EVENT:
- {
- Intvar_log_event* iev = (Intvar_log_event*)ev;
- switch(iev->type)
- {
- case LAST_INSERT_ID_EVENT:
- thd->last_insert_id_used = 1;
- thd->last_insert_id = iev->val;
- break;
- case INSERT_ID_EVENT:
- thd->next_insert_id = iev->val;
- break;
-
- }
- mi->inc_pending(event_len);
- delete ev;
- break;
- }
- }
+ ev->thd = thd;
+ thd->log_pos = ev->log_pos;
+ exec_res = ev->exec_event(rli);
+ DBUG_ASSERT(rli->sql_thd==thd);
+ delete ev;
+ return exec_res;
}
else
{
@@ -1208,338 +1575,698 @@ This may also be a network problem, or just a bug in the master or slave code.\
");
return 1;
}
- return 0;
}
-
-// slave thread
-pthread_handler_decl(handle_slave,arg __attribute__((unused)))
+/* slave I/O thread */
+pthread_handler_decl(handle_slave_io,arg)
{
#ifndef DBUG_OFF
- slave_begin:
+slave_begin:
#endif
THD *thd; // needs to be first for thread_stack
MYSQL *mysql = NULL ;
+ MASTER_INFO* mi = (MASTER_INFO*)arg;
char llbuff[22];
-
- pthread_mutex_lock(&LOCK_slave);
- if (!server_id)
- {
- pthread_cond_broadcast(&COND_slave_start);
- pthread_mutex_unlock(&LOCK_slave);
- sql_print_error("Server id not set, will not start slave");
- pthread_exit((void*)1);
- }
+ bool retried_once = 0;
+ ulonglong last_failed_pos = 0; // TODO: see if last_failed_pos is needed
+ DBUG_ASSERT(mi->inited);
- if(slave_running)
- {
- pthread_cond_broadcast(&COND_slave_start);
- pthread_mutex_unlock(&LOCK_slave);
- pthread_exit((void*)1); // safety just in case
- }
- slave_running = 1;
- abort_slave = 0;
+ pthread_mutex_lock(&mi->run_lock);
#ifndef DBUG_OFF
- events_till_abort = abort_slave_event_count;
+ mi->events_till_abort = abort_slave_event_count;
#endif
- pthread_cond_broadcast(&COND_slave_start);
- pthread_mutex_unlock(&LOCK_slave);
-
- // int error = 1;
- bool retried_once = 0;
- ulonglong last_failed_pos = 0;
// needs to call my_thread_init(), otherwise we get a coredump in DBUG_ stuff
my_thread_init();
- slave_thd = thd = new THD; // note that contructor of THD uses DBUG_ !
- thd->set_time();
- DBUG_ENTER("handle_slave");
+ thd = new THD; // note that contructor of THD uses DBUG_ !
+ DBUG_ENTER("handle_slave_io");
pthread_detach_this_thread();
- if (init_slave_thread(thd) || init_master_info(&glob_mi))
- {
- sql_print_error("Failed during slave thread initialization");
- goto err;
- }
+ if (init_slave_thread(thd, SLAVE_THD_IO))
+ {
+ pthread_cond_broadcast(&mi->start_cond);
+ pthread_mutex_unlock(&mi->run_lock);
+ sql_print_error("Failed during slave I/O thread initialization");
+ goto err;
+ }
+ mi->io_thd = thd;
thd->thread_stack = (char*)&thd; // remember where our stack is
- thd->temporary_tables = save_temporary_tables; // restore temp tables
threads.append(thd);
- glob_mi.pending = 0; //this should always be set to 0 when the slave thread
- // is started
+ mi->slave_running = 1;
+ mi->abort_slave = 0;
+ pthread_cond_broadcast(&mi->start_cond);
+ pthread_mutex_unlock(&mi->run_lock);
DBUG_PRINT("info",("master info: log_file_name=%s, position=%s",
- glob_mi.log_file_name, llstr(glob_mi.pos,llbuff)));
-
+ mi->master_log_name, llstr(mi->master_log_pos,llbuff)));
- if (!(mysql = mc_mysql_init(NULL)))
+ if (!(mi->mysql = mysql = mc_mysql_init(NULL)))
{
- sql_print_error("Slave thread: error in mc_mysql_init()");
+ sql_print_error("Slave I/O thread: error in mc_mysql_init()");
goto err;
}
thd->proc_info = "connecting to master";
#ifndef DBUG_OFF
- sql_print_error("Slave thread initialized");
+ sql_print_error("Slave I/O thread initialized");
#endif
// we can get killed during safe_connect
- if (!safe_connect(thd, mysql, &glob_mi))
- sql_print_error("Slave: connected to master '%s@%s:%d',\
- replication started in log '%s' at position %s", glob_mi.user,
- glob_mi.host, glob_mi.port,
- RPL_LOG_NAME,
- llstr(glob_mi.pos,llbuff));
+ if (!safe_connect(thd, mysql, mi))
+ sql_print_error("Slave I/O thread: connected to master '%s@%s:%d',\
+ replication started in log '%s' at position %s", mi->user,
+ mi->host, mi->port,
+ IO_RPL_LOG_NAME,
+ llstr(mi->master_log_pos,llbuff));
else
{
- sql_print_error("Slave thread killed while connecting to master");
+ sql_print_error("Slave I/O thread killed while connecting to master");
goto err;
}
-
+
connected:
+
+ thd->slave_net = &mysql->net;
+ thd->proc_info = "Checking master version";
+ if (check_master_version(mysql, mi))
+ goto err;
+ if (!mi->old_format)
+ {
+ /*
+ Register ourselves with the master.
+ If fails, this is not fatal - we just print the error message and go
+ on with life.
+ */
+ thd->proc_info = "Registering slave on master";
+ if (register_slave_on_master(mysql) || update_slave_list(mysql))
+ goto err;
+ }
- while (!slave_killed(thd))
+ while (!slave_killed(thd,mi))
{
- thd->proc_info = "Requesting binlog dump";
- if(request_dump(mysql, &glob_mi))
- {
- sql_print_error("Failed on request_dump()");
- if(slave_killed(thd))
- {
- sql_print_error("Slave thread killed while requesting master \
+ thd->proc_info = "Requesting binlog dump";
+ if (request_dump(mysql, mi))
+ {
+ sql_print_error("Failed on request_dump()");
+ if(slave_killed(thd,mi))
+ {
+ sql_print_error("Slave I/O thread killed while requesting master \
dump");
- goto err;
- }
+ goto err;
+ }
- thd->proc_info = "Waiiting to reconnect after a failed dump request";
- if(mysql->net.vio)
- vio_close(mysql->net.vio);
- // first time retry immediately, assuming that we can recover
- // right away - if first time fails, sleep between re-tries
- // hopefuly the admin can fix the problem sometime
- if(retried_once)
- safe_sleep(thd, glob_mi.connect_retry);
- else
- retried_once = 1;
+ thd->proc_info = "Waiiting to reconnect after a failed dump request";
+ mc_end_server(mysql);
+ /*
+ First time retry immediately, assuming that we can recover
+ right away - if first time fails, sleep between re-tries
+ hopefuly the admin can fix the problem sometime
+ */
+ if (retried_once)
+ safe_sleep(thd, mi, mi->connect_retry);
+ else
+ retried_once = 1;
- if(slave_killed(thd))
- {
- sql_print_error("Slave thread killed while retrying master \
+ if (slave_killed(thd,mi))
+ {
+ sql_print_error("Slave I/O thread killed while retrying master \
dump");
- goto err;
- }
-
- thd->proc_info = "Reconnecting after a failed dump request";
- last_failed_pos=glob_mi.pos;
- sql_print_error("Slave: failed dump request, reconnecting to \
-try again, log '%s' at postion %s", RPL_LOG_NAME,
- llstr(last_failed_pos,llbuff));
- if(safe_reconnect(thd, mysql, &glob_mi) || slave_killed(thd))
- {
- sql_print_error("Slave thread killed during or after reconnect");
- goto err;
- }
-
- goto connected;
- }
+ goto err;
+ }
- while(!slave_killed(thd))
- {
- thd->proc_info = "Reading master update";
- uint event_len = read_event(mysql, &glob_mi);
- if(slave_killed(thd))
- {
- sql_print_error("Slave thread killed while reading event");
- goto err;
- }
+ thd->proc_info = "Reconnecting after a failed dump request";
+ sql_print_error("Slave I/O thread: failed dump request, \
+reconnecting to try again, log '%s' at postion %s", IO_RPL_LOG_NAME,
+ llstr(mi->master_log_pos,llbuff));
+ if (safe_reconnect(thd, mysql, mi) || slave_killed(thd,mi))
+ {
+ sql_print_error("Slave I/O thread killed during or \
+after reconnect");
+ goto err;
+ }
+
+ goto connected;
+ }
+
+ while (!slave_killed(thd,mi))
+ {
+ thd->proc_info = "Reading master update";
+ ulong event_len = read_event(mysql, mi);
+ if (slave_killed(thd,mi))
+ {
+ sql_print_error("Slave I/O thread killed while reading event");
+ goto err;
+ }
- if (event_len == packet_error)
- {
- if(mc_mysql_errno(mysql) == ER_NET_PACKET_TOO_LARGE)
- {
- sql_print_error("Log entry on master is longer than \
-max_allowed_packet on slave. Slave thread will be aborted. If the entry is \
-really supposed to be that long, restart the server with a higher value of \
-max_allowed_packet. The current value is %ld", max_allowed_packet);
- goto err;
- }
+ if (event_len == packet_error)
+ {
+ if (mc_mysql_errno(mysql) == ER_NET_PACKET_TOO_LARGE)
+ {
+ sql_print_error("Log entry on master is longer than \
+max_allowed_packet (%ld) on slave. Slave thread will be aborted. If the entry \
+is correct, restart the server with a higher value of max_allowed_packet",
+ max_allowed_packet);
+ goto err;
+ }
- thd->proc_info = "Waiting to reconnect after a failed read";
- if(mysql->net.vio)
- vio_close(mysql->net.vio);
- if(retried_once) // punish repeat offender with sleep
- safe_sleep(thd, glob_mi.connect_retry);
- else
- retried_once = 1;
+ thd->proc_info = "Waiting to reconnect after a failed read";
+ mc_end_server(mysql);
+ if (retried_once) // punish repeat offender with sleep
+ safe_sleep(thd,mi,mi->connect_retry);
+ else
+ retried_once = 1;
- if(slave_killed(thd))
- {
- sql_print_error("Slave thread killed while waiting to \
+ if (slave_killed(thd,mi))
+ {
+ sql_print_error("Slave I/O thread killed while waiting to \
reconnect after a failed read");
- goto err;
- }
- thd->proc_info = "Reconnecting after a failed read";
- last_failed_pos= glob_mi.pos;
- sql_print_error("Slave: Failed reading log event, \
-reconnecting to retry, log '%s' position %s", RPL_LOG_NAME,
- llstr(last_failed_pos, llbuff));
- if(safe_reconnect(thd, mysql, &glob_mi) || slave_killed(thd))
- {
- sql_print_error("Slave thread killed during or after a \
+ goto err;
+ }
+ thd->proc_info = "Reconnecting after a failed read";
+ sql_print_error("Slave I/O thread: Failed reading log event, \
+reconnecting to retry, log '%s' position %s", IO_RPL_LOG_NAME,
+ llstr(mi->master_log_pos, llbuff));
+ if (safe_reconnect(thd, mysql, mi) || slave_killed(thd,mi))
+ {
+ sql_print_error("Slave I/O thread killed during or after a \
reconnect done to recover from failed read");
- goto err;
- }
-
- goto connected;
- } // if(event_len == packet_error)
+ goto err;
+ }
+ goto connected;
+ } // if(event_len == packet_error)
- thd->proc_info = "Processing master log event";
- if(exec_event(thd, &mysql->net, &glob_mi, event_len))
- {
- sql_print_error("\
-Error running query, slave aborted. Fix the problem, and re-start \
-the slave thread with \"mysqladmin start-slave\". We stopped at log \
-'%s' position %s",
- RPL_LOG_NAME, llstr(glob_mi.pos, llbuff));
- goto err;
- // there was an error running the query
- // abort the slave thread, when the problem is fixed, the user
- // should restart the slave with mysqladmin start-slave
- }
+ thd->proc_info = "Queueing event from master";
+ if (queue_event(mi,(const char*)mysql->net.read_pos + 1,
+ event_len))
+ {
+ sql_print_error("Slave I/O thread could not queue event \
+from master");
+ goto err;
+ }
+ // TODO: check debugging abort code
#ifndef DBUG_OFF
- if(abort_slave_event_count && !--events_till_abort)
- {
- sql_print_error("Slave: debugging abort");
- goto err;
- }
+ if (abort_slave_event_count && !--events_till_abort)
+ {
+ sql_print_error("Slave I/O thread: debugging abort");
+ goto err;
+ }
#endif
-
- // successful exec with offset advance,
- // the slave repents and his sins are forgiven!
- if(glob_mi.pos > last_failed_pos)
- {
- retried_once = 0;
+ } // while(!slave_killed(thd,mi)) - read/exec loop
+ } // while(!slave_killed(thd,mi)) - slave loop
+
+ // error = 0;
+err:
+ // print the current replication position
+ sql_print_error("Slave I/O thread exiting, read up to log '%s', position %s",
+ IO_RPL_LOG_NAME, llstr(mi->master_log_pos,llbuff));
+ thd->query = thd->db = 0; // extra safety
+ if (mysql)
+ {
+ mc_mysql_close(mysql);
+ mi->mysql=0;
+ }
+ thd->proc_info = "Waiting for slave mutex on exit";
+ pthread_mutex_lock(&mi->run_lock);
+ mi->slave_running = 0;
+ mi->io_thd = 0;
+ // TODO: make rpl_status part of MASTER_INFO
+ change_rpl_status(RPL_ACTIVE_SLAVE,RPL_IDLE_SLAVE);
+ mi->abort_slave = 0; // TODO: check if this is needed
+ DBUG_ASSERT(thd->net.buff != 0);
+ net_end(&thd->net); // destructor will not free it, because net.vio is 0
+ pthread_mutex_lock(&LOCK_thread_count);
+ delete thd;
+ pthread_mutex_unlock(&LOCK_thread_count);
+ pthread_cond_broadcast(&mi->stop_cond); // tell the world we are done
+ pthread_mutex_unlock(&mi->run_lock);
+ my_thread_end();
#ifndef DBUG_OFF
- stuck_count = 0;
-#endif
- }
+ if(abort_slave_event_count && !events_till_abort)
+ goto slave_begin;
+#endif
+ pthread_exit(0);
+ DBUG_RETURN(0); // Can't return anything here
+}
+
+
+/* slave SQL logic thread */
+
+pthread_handler_decl(handle_slave_sql,arg)
+{
#ifndef DBUG_OFF
- else
- {
- // show a little mercy, allow slave to read one more event
- // before cutting him off - otherwise he gets stuck
- // on Intvar events, since they do not advance the offset
- // immediately
- if (++stuck_count > 2)
- events_till_disconnect++;
- }
-#endif
- } // while(!slave_killed(thd)) - read/exec loop
- } // while(!slave_killed(thd)) - slave loop
+slave_begin:
+#endif
+ THD *thd; /* needs to be first for thread_stack */
+ MYSQL *mysql = NULL ;
+ bool retried_once = 0;
+ ulonglong last_failed_pos = 0; // TODO: see if this can be removed
+ char llbuff[22],llbuff1[22];
+ RELAY_LOG_INFO* rli = &((MASTER_INFO*)arg)->rli;
+ const char* errmsg=0;
+ DBUG_ASSERT(rli->inited);
+ pthread_mutex_lock(&rli->run_lock);
+ DBUG_ASSERT(!rli->slave_running);
+#ifndef DBUG_OFF
+ rli->events_till_abort = abort_slave_event_count;
+#endif
+
+
+ // needs to call my_thread_init(), otherwise we get a coredump in DBUG_ stuff
+ my_thread_init();
+ thd = new THD; // note that contructor of THD uses DBUG_ !
+ DBUG_ENTER("handle_slave_sql");
+
+ pthread_detach_this_thread();
+ if (init_slave_thread(thd, SLAVE_THD_SQL))
+ {
+ /*
+ TODO: this is currently broken - slave start and change master
+ will be stuck if we fail here
+ */
+ pthread_cond_broadcast(&rli->start_cond);
+ pthread_mutex_unlock(&rli->run_lock);
+ sql_print_error("Failed during slave thread initialization");
+ goto err;
+ }
+ thd->thread_stack = (char*)&thd; // remember where our stack is
+ thd->temporary_tables = rli->save_temporary_tables; // restore temp tables
+ threads.append(thd);
+ rli->sql_thd = thd;
+ rli->slave_running = 1;
+ rli->abort_slave = 0;
+ pthread_cond_broadcast(&rli->start_cond);
+ pthread_mutex_unlock(&rli->run_lock);
+ rli->pending = 0; //this should always be set to 0 when the slave thread
+ // is started
+ if (init_relay_log_pos(rli,0,0,1/*need data lock*/,&errmsg))
+ {
+ sql_print_error("Error initializing relay log position: %s",
+ errmsg);
+ goto err;
+ }
+ DBUG_ASSERT(rli->relay_log_pos >= 4);
+ DBUG_ASSERT(my_b_tell(rli->cur_log) == rli->relay_log_pos);
+
+ DBUG_PRINT("info",("master info: log_file_name=%s, position=%s",
+ rli->master_log_name, llstr(rli->master_log_pos,llbuff)));
+ DBUG_ASSERT(rli->sql_thd == thd);
+ sql_print_error("Slave SQL thread initialized, starting replication in \
+log '%s' at position %s,relay log: name='%s',pos='%s'", RPL_LOG_NAME,
+ llstr(rli->master_log_pos,llbuff),rli->relay_log_name,
+ llstr(rli->relay_log_pos,llbuff1));
+ while (!slave_killed(thd,rli))
+ {
+ thd->proc_info = "Processing master log event";
+ DBUG_ASSERT(rli->sql_thd == thd);
+ if (exec_relay_log_event(thd,rli))
+ {
+ // do not scare the user if SQL thread was simply killed or stopped
+ if (!slave_killed(thd,rli))
+ sql_print_error("\
+Error running query, slave SQL thread aborted. Fix the problem, and restart \
+the slave SQL thread with \"SLAVE START\". We stopped at log \
+'%s' position %s",
+ RPL_LOG_NAME, llstr(rli->master_log_pos, llbuff));
+ goto err;
+ }
+ } // while(!slave_killed(thd,rli)) - read/exec loop
// error = 0;
err:
// print the current replication position
- sql_print_error("Slave thread exiting, replication stopped in log '%s' at \
-position %s",
- RPL_LOG_NAME, llstr(glob_mi.pos,llbuff));
+ sql_print_error("Slave SQL thread exiting, replication stopped in log \
+ '%s' at position %s",
+ RPL_LOG_NAME, llstr(rli->master_log_pos,llbuff));
thd->query = thd->db = 0; // extra safety
- if(mysql)
- mc_mysql_close(mysql);
thd->proc_info = "Waiting for slave mutex on exit";
- pthread_mutex_lock(&LOCK_slave);
- slave_running = 0;
- abort_slave = 0;
- save_temporary_tables = thd->temporary_tables;
+ pthread_mutex_lock(&rli->run_lock);
+ DBUG_ASSERT(rli->slave_running == 1); // tracking buffer overrun
+ rli->slave_running = 0;
+ rli->save_temporary_tables = thd->temporary_tables;
+
+ /*
+ TODO: see if we can do this conditionally in next_event() instead
+ to avoid unneeded position re-init
+ */
+ rli->log_pos_current=0;
thd->temporary_tables = 0; // remove tempation from destructor to close them
- pthread_cond_broadcast(&COND_slave_stopped); // tell the world we are done
- pthread_mutex_unlock(&LOCK_slave);
+ DBUG_ASSERT(thd->net.buff != 0);
net_end(&thd->net); // destructor will not free it, because we are weird
- slave_thd = 0;
+ DBUG_ASSERT(rli->sql_thd == thd);
+ rli->sql_thd = 0;
+ pthread_mutex_lock(&LOCK_thread_count);
delete thd;
+ pthread_mutex_unlock(&LOCK_thread_count);
+ pthread_cond_broadcast(&rli->stop_cond);
+ // tell the world we are done
+ pthread_mutex_unlock(&rli->run_lock);
my_thread_end();
-#ifndef DBUG_OFF
- if(abort_slave_event_count && !events_till_abort)
+#ifndef DBUG_OFF // TODO: reconsider the code below
+ if (abort_slave_event_count && !rli->events_till_abort)
goto slave_begin;
#endif
pthread_exit(0);
DBUG_RETURN(0); // Can't return anything here
}
+static int process_io_create_file(MASTER_INFO* mi, Create_file_log_event* cev)
+{
+ int error = 1;
+ ulong num_bytes;
+ bool cev_not_written;
+ THD* thd;
+ NET* net = &mi->mysql->net;
-/* try to connect until successful or slave killed */
+ if (unlikely(!cev->is_valid()))
+ return 1;
+ /*
+ TODO: fix to honor table rules, not only db rules
+ */
+ if (!db_ok(cev->db, replicate_do_db, replicate_ignore_db))
+ {
+ skip_load_data_infile(net);
+ return 0;
+ }
+ DBUG_ASSERT(cev->inited_from_old);
+ thd = mi->io_thd;
+ thd->file_id = cev->file_id = mi->file_id++;
+ thd->server_id = cev->server_id;
+ cev_not_written = 1;
+
+ if (unlikely(net_request_file(net,cev->fname)))
+ {
+ sql_print_error("Slave I/O: failed requesting download of '%s'",
+ cev->fname);
+ goto err;
+ }
-static int safe_connect(THD* thd, MYSQL* mysql, MASTER_INFO* mi)
+ /* this dummy block is so we could insantiate Append_block_log_event
+ once and then modify it slightly instead of doing it multiple times
+ in the loop
+ */
+ {
+ Append_block_log_event aev(thd,0,0);
+
+ for (;;)
+ {
+ if (unlikely((num_bytes=my_net_read(net)) == packet_error))
+ {
+ sql_print_error("Network read error downloading '%s' from master",
+ cev->fname);
+ goto err;
+ }
+ if (unlikely(!num_bytes)) /* eof */
+ {
+ send_ok(net); /* 3.23 master wants it */
+ Execute_load_log_event xev(thd);
+ xev.log_pos = mi->master_log_pos;
+ if (unlikely(mi->rli.relay_log.append(&xev)))
+ {
+ sql_print_error("Slave I/O: error writing Exec_load event to \
+relay log");
+ goto err;
+ }
+ break;
+ }
+ if (unlikely(cev_not_written))
+ {
+ cev->block = (char*)net->read_pos;
+ cev->block_len = num_bytes;
+ cev->log_pos = mi->master_log_pos;
+ if (unlikely(mi->rli.relay_log.append(cev)))
+ {
+ sql_print_error("Slave I/O: error writing Create_file event to \
+relay log");
+ goto err;
+ }
+ cev_not_written=0;
+ }
+ else
+ {
+ aev.block = (char*)net->read_pos;
+ aev.block_len = num_bytes;
+ aev.log_pos = mi->master_log_pos;
+ if (unlikely(mi->rli.relay_log.append(&aev)))
+ {
+ sql_print_error("Slave I/O: error writing Append_block event to \
+relay log");
+ goto err;
+ }
+ }
+ }
+ }
+ error=0;
+err:
+ return error;
+}
+
+// We assume we already locked mi->data_lock
+static int process_io_rotate(MASTER_INFO* mi, Rotate_log_event* rev)
{
- int slave_was_killed;
+ if (unlikely(!rev->is_valid()))
+ return 1;
+ DBUG_ASSERT(rev->ident_len<sizeof(mi->master_log_name));
+ memcpy(mi->master_log_name,rev->new_log_ident,
+ rev->ident_len);
+ mi->master_log_name[rev->ident_len] = 0;
+ mi->master_log_pos = rev->pos;
#ifndef DBUG_OFF
- events_till_disconnect = disconnect_slave_event_count;
-#endif
- while(!(slave_was_killed = slave_killed(thd)) &&
- !mc_mysql_connect(mysql, mi->host, mi->user, mi->password, 0,
- mi->port, 0, 0))
+ /*
+ If we do not do this, we will be getting the first
+ rotate event forever, so we need to not disconnect after one.
+ */
+ if (disconnect_slave_event_count)
+ events_till_disconnect++;
+#endif
+ return 0;
+}
+
+/*
+ TODO: verify the issue with stop events, see if we need them at all
+ in the relay log
+ TODO: test this code before release - it has to be tested on a separte
+ setup with 3.23 master
+*/
+
+static int queue_old_event(MASTER_INFO *mi, const char *buf,
+ ulong event_len)
+{
+ const char *errmsg = 0;
+ bool inc_pos = 1;
+ bool processed_stop_event = 0;
+ char* tmp_buf = 0;
+ /* if we get Load event, we need to pass a non-reusable buffer
+ to read_log_event, so we do a trick
+ */
+ if (buf[EVENT_TYPE_OFFSET] == LOAD_EVENT)
{
- sql_print_error("Slave thread: error connecting to master: %s (%d),\
- retry in %d sec", mc_mysql_error(mysql), errno, mi->connect_retry);
- safe_sleep(thd, mi->connect_retry);
+ if (unlikely(!(tmp_buf=(char*)my_malloc(event_len+1,MYF(MY_WME)))))
+ {
+ sql_print_error("Slave I/O: out of memory for Load event");
+ return 1;
+ }
+ memcpy(tmp_buf,buf,event_len);
+ tmp_buf[event_len]=0; // Create_file constructor wants null-term buffer
+ buf = (const char*)tmp_buf;
}
-
- if(!slave_was_killed)
+ Log_event *ev = Log_event::read_log_event(buf,event_len, &errmsg,
+ 1 /*old format*/ );
+ if (unlikely(!ev))
+ {
+ sql_print_error("Read invalid event from master: '%s',\
+ master could be corrupt but a more likely cause of this is a bug",
+ errmsg);
+ my_free((char*)tmp_buf, MYF(MY_ALLOW_ZERO_PTR));
+ return 1;
+ }
+ pthread_mutex_lock(&mi->data_lock);
+ ev->log_pos = mi->master_log_pos;
+ switch (ev->get_type_code()) {
+ case ROTATE_EVENT:
+ if (unlikely(process_io_rotate(mi,(Rotate_log_event*)ev)))
{
- mysql_log.write(thd, COM_CONNECT_OUT, "%s@%s:%d",
- mi->user, mi->host, mi->port);
-#ifdef SIGNAL_WITH_VIO_CLOSE
- thd->set_active_vio(mysql->net.vio);
-#endif
+ delete ev;
+ pthread_mutex_unlock(&mi->data_lock);
+ DBUG_ASSERT(!tmp_buf);
+ return 1;
}
+ mi->ignore_stop_event=1;
+ inc_pos = 0;
+ break;
+ case STOP_EVENT:
+ processed_stop_event=1;
+ break;
+ case CREATE_FILE_EVENT:
+ {
+ int error = process_io_create_file(mi,(Create_file_log_event*)ev);
+ delete ev;
+ mi->master_log_pos += event_len;
+ pthread_mutex_unlock(&mi->data_lock);
+ DBUG_ASSERT(tmp_buf);
+ my_free((char*)tmp_buf, MYF(0));
+ return error;
+ }
+ default:
+ mi->ignore_stop_event=0;
+ break;
+ }
+ if (likely(!processed_stop_event || !mi->ignore_stop_event))
+ {
+ if (unlikely(mi->rli.relay_log.append(ev)))
+ {
+ delete ev;
+ pthread_mutex_unlock(&mi->data_lock);
+ DBUG_ASSERT(!tmp_buf);
+ return 1;
+ }
+ }
+ delete ev;
+ if (likely(inc_pos))
+ mi->master_log_pos += event_len;
+ if (unlikely(processed_stop_event))
+ mi->ignore_stop_event=1;
+ pthread_mutex_unlock(&mi->data_lock);
+ DBUG_ASSERT(!tmp_buf);
+ return 0;
+}
+
+/*
+ TODO: verify the issue with stop events, see if we need them at all
+ in the relay log
+*/
+
+int queue_event(MASTER_INFO* mi,const char* buf, ulong event_len)
+{
+ int error=0;
+ bool inc_pos = 1;
+ bool processed_stop_event = 0;
+ if (mi->old_format)
+ return queue_old_event(mi,buf,event_len);
+
+ pthread_mutex_lock(&mi->data_lock);
- return slave_was_killed;
+ /*
+ TODO: figure out if other events in addition to Rotate
+ require special processing
+ */
+ switch (buf[EVENT_TYPE_OFFSET]) {
+ case STOP_EVENT:
+ processed_stop_event=1;
+ break;
+ case ROTATE_EVENT:
+ {
+ Rotate_log_event rev(buf,event_len,0);
+ if (unlikely(process_io_rotate(mi,&rev)))
+ return 1;
+ inc_pos=0;
+ mi->ignore_stop_event=1;
+ break;
+ }
+ default:
+ mi->ignore_stop_event=0;
+ break;
+ }
+
+ if (likely((!processed_stop_event || !mi->ignore_stop_event) &&
+ !(error = mi->rli.relay_log.appendv(buf,event_len,0))))
+ {
+ if (likely(inc_pos))
+ mi->master_log_pos += event_len;
+ }
+ if (unlikely(processed_stop_event))
+ mi->ignore_stop_event=1;
+ pthread_mutex_unlock(&mi->data_lock);
+ return error;
}
+
+void end_relay_log_info(RELAY_LOG_INFO* rli)
+{
+ if (!rli->inited)
+ return;
+ if (rli->info_fd >= 0)
+ {
+ end_io_cache(&rli->info_file);
+ (void)my_close(rli->info_fd, MYF(MY_WME));
+ rli->info_fd = -1;
+ }
+ if (rli->cur_log_fd >= 0)
+ {
+ end_io_cache(&rli->cache_buf);
+ (void)my_close(rli->cur_log_fd, MYF(MY_WME));
+ rli->cur_log_fd = -1;
+ }
+ rli->inited = 0;
+ rli->log_pos_current=0;
+ rli->relay_log.close(1);
+}
+
+/* try to connect until successful or slave killed */
+static int safe_connect(THD* thd, MYSQL* mysql, MASTER_INFO* mi)
+{
+ return connect_to_master(thd, mysql, mi, 0);
+}
+
+
/*
Try to connect until successful or slave killed or we have retried
master_retry_count times
*/
-static int safe_reconnect(THD* thd, MYSQL* mysql, MASTER_INFO* mi)
+static int connect_to_master(THD* thd, MYSQL* mysql, MASTER_INFO* mi,
+ bool reconnect)
{
int slave_was_killed;
int last_errno= -2; // impossible error
ulong err_count=0;
char llbuff[22];
- /*
- If we lost connection after reading a state set event
- we will be re-reading it, so pending needs to be cleared
- */
- mi->pending = 0;
#ifndef DBUG_OFF
events_till_disconnect = disconnect_slave_event_count;
#endif
- while (!(slave_was_killed = slave_killed(thd)) && mc_mysql_reconnect(mysql))
+ while (!(slave_was_killed = slave_killed(thd,mi)) &&
+ (reconnect ? mc_mysql_reconnect(mysql) != 0 :
+ !mc_mysql_connect(mysql, mi->host, mi->user, mi->password, 0,
+ mi->port, 0, 0)))
{
/* Don't repeat last error */
if (mc_mysql_errno(mysql) != last_errno)
{
- sql_print_error("Slave thread: error re-connecting to master: \
-%s, last_errno=%d, retry in %d sec",
+ sql_print_error("Slave I/O thread: error connecting to master \
+'%s@%s:%d': \
+%s, last_errno=%d, retry in %d sec",mi->user,mi->host,mi->port,
mc_mysql_error(mysql), last_errno=mc_mysql_errno(mysql),
mi->connect_retry);
}
- safe_sleep(thd, mi->connect_retry);
- /* if master_retry_count is not set, keep trying until success */
+ safe_sleep(thd,mi,mi->connect_retry);
+ /*
+ By default we try forever. The reason is that failure will trigger
+ master election, so if the user did not set master_retry_count we
+ do not want to have electioin triggered on the first failure to
+ connect
+ */
if (master_retry_count && err_count++ == master_retry_count)
{
slave_was_killed=1;
+ if (reconnect)
+ change_rpl_status(RPL_ACTIVE_SLAVE,RPL_LOST_SOLDIER);
break;
}
}
if (!slave_was_killed)
{
- sql_print_error("Slave: reconnected to master '%s@%s:%d',\
-replication resumed in log '%s' at position %s", glob_mi.user,
- glob_mi.host, glob_mi.port,
- RPL_LOG_NAME,
- llstr(glob_mi.pos,llbuff));
+ if (reconnect)
+ sql_print_error("Slave: connected to master '%s@%s:%d',\
+replication resumed in log '%s' at position %s", mi->user,
+ mi->host, mi->port,
+ IO_RPL_LOG_NAME,
+ llstr(mi->master_log_pos,llbuff));
+ else
+ {
+ change_rpl_status(RPL_IDLE_SLAVE,RPL_ACTIVE_SLAVE);
+ mysql_log.write(thd, COM_CONNECT_OUT, "%s@%s:%d",
+ mi->user, mi->host, mi->port);
+ }
#ifdef SIGNAL_WITH_VIO_CLOSE
thd->set_active_vio(mysql->net.vio);
#endif
@@ -1548,6 +2275,208 @@ replication resumed in log '%s' at position %s", glob_mi.user,
return slave_was_killed;
}
+
+/*
+ Try to connect until successful or slave killed or we have retried
+ master_retry_count times
+*/
+
+static int safe_reconnect(THD* thd, MYSQL* mysql, MASTER_INFO* mi)
+{
+ return connect_to_master(thd, mysql, mi, 1);
+}
+
+int flush_relay_log_info(RELAY_LOG_INFO* rli)
+{
+ register IO_CACHE* file = &rli->info_file;
+ char lbuf[22],lbuf1[22];
+
+ my_b_seek(file, 0L);
+ my_b_printf(file, "%s\n%s\n%s\n%s\n",
+ rli->relay_log_name, llstr(rli->relay_log_pos, lbuf),
+ rli->master_log_name, llstr(rli->master_log_pos, lbuf1)
+ );
+ flush_io_cache(file);
+ flush_io_cache(rli->cur_log);
+ return 0;
+}
+
+IO_CACHE* reopen_relay_log(RELAY_LOG_INFO* rli, const char** errmsg)
+{
+ DBUG_ASSERT(rli->cur_log != &rli->cache_buf);
+ IO_CACHE* cur_log = rli->cur_log=&rli->cache_buf;
+ DBUG_ASSERT(rli->cur_log_fd == -1);
+ if ((rli->cur_log_fd=open_binlog(cur_log,rli->relay_log_name,
+ errmsg)) <0)
+ return 0;
+ my_b_seek(cur_log,rli->relay_log_pos);
+ return cur_log;
+}
+
+Log_event* next_event(RELAY_LOG_INFO* rli)
+{
+ Log_event* ev;
+ IO_CACHE* cur_log = rli->cur_log;
+ pthread_mutex_t *log_lock = rli->relay_log.get_log_lock();
+ const char* errmsg=0;
+ THD* thd = rli->sql_thd;
+ bool was_killed;
+ DBUG_ASSERT(thd != 0);
+
+ /*
+ For most operations we need to protect rli members with data_lock,
+ so we will hold it for the most of the loop below
+ However, we will release it whenever it is worth the hassle,
+ and in the cases when we go into a pthread_cond_wait() with the
+ non-data_lock mutex
+ */
+ pthread_mutex_lock(&rli->data_lock);
+
+ for (; !(was_killed=slave_killed(thd,rli)) ;)
+ {
+ /*
+ We can have two kinds of log reading:
+ hot_log - rli->cur_log points at the IO_CACHE of relay_log, which
+ is actively being updated by the I/O thread. We need to be careful
+ in this case and make sure that we are not looking at a stale log that
+ has already been rotated. If it has been, we reopen the log
+ the other case is much simpler - we just have a read only log that
+ nobody else will be updating.
+ */
+ bool hot_log;
+ if ((hot_log = (cur_log != &rli->cache_buf)))
+ {
+ DBUG_ASSERT(rli->cur_log_fd == -1); // foreign descriptor
+ pthread_mutex_lock(log_lock);
+
+ /*
+ Reading cur_log->init_count here is safe because the log will only
+ be rotated when we hold relay_log.LOCK_log
+ */
+ if (cur_log->init_count != rli->cur_log_init_count)
+ {
+ if (!(cur_log=reopen_relay_log(rli,&errmsg)))
+ {
+ pthread_mutex_unlock(log_lock);
+ goto err;
+ }
+ pthread_mutex_unlock(log_lock);
+ hot_log=0;
+ }
+ }
+ DBUG_ASSERT(my_b_tell(cur_log) >= 4);
+ DBUG_ASSERT(my_b_tell(cur_log) == rli->relay_log_pos + rli->pending);
+ /* relay log is always in new format - if the master is 3.23, the
+ I/O thread will convert the format for us
+ */
+ if ((ev=Log_event::read_log_event(cur_log,0,(bool)0/*new format*/)))
+ {
+ DBUG_ASSERT(thd==rli->sql_thd);
+ if (hot_log)
+ pthread_mutex_unlock(log_lock);
+ pthread_mutex_unlock(&rli->data_lock);
+ return ev;
+ }
+ DBUG_ASSERT(thd==rli->sql_thd);
+ if (!cur_log->error) /* EOF */
+ {
+ /*
+ On a hot log, EOF means that there are no more updates to
+ process and we must block until I/O thread adds some and
+ signals us to continue
+ */
+ if (hot_log)
+ {
+ DBUG_ASSERT(cur_log->init_count == rli->cur_log_init_count);
+ /*
+ We can, and should release data_lock while we are waiting for
+ update. If we do not, show slave status will block
+ */
+ pthread_mutex_unlock(&rli->data_lock);
+
+ /*
+ IMPORTANT: note that wait_for_update will unlock LOCK_log, but
+ expects the caller to lock it
+ */
+ rli->relay_log.wait_for_update(rli->sql_thd);
+
+ // re-acquire data lock since we released it earlier
+ pthread_mutex_lock(&rli->data_lock);
+ continue;
+ }
+ else
+ {
+ /*
+ If the log was not hot, we need to move to the next log in
+ sequence. The next log could be hot or cold, we deal with both
+ cases separately after doing some common initialization
+ */
+ end_io_cache(cur_log);
+ DBUG_ASSERT(rli->cur_log_fd >= 0);
+ my_close(rli->cur_log_fd, MYF(MY_WME));
+ rli->cur_log_fd = -1;
+
+ // purge_first_log will properly set up relay log coordinates in rli
+ if (rli->relay_log.purge_first_log(rli))
+ {
+ errmsg = "Error purging processed log";
+ goto err;
+ }
+
+ // next log is hot
+ if (rli->relay_log.is_active(rli->linfo.log_file_name))
+ {
+#ifdef EXTRA_DEBUG
+ sql_print_error("next log '%s' is currently active",
+ rli->linfo.log_file_name);
+#endif
+ rli->cur_log = cur_log = rli->relay_log.get_log_file();
+ rli->cur_log_init_count = cur_log->init_count;
+ DBUG_ASSERT(rli->cur_log_fd == -1);
+
+ /*
+ Read pointer has to be at the start since we are the only
+ reader
+ */
+ if (check_binlog_magic(cur_log,&errmsg))
+ goto err;
+ continue;
+ }
+ /*
+ if we get here, the log was not hot, so we will have to
+ open it ourselves
+ */
+#ifdef EXTRA_DEBUG
+ sql_print_error("next log '%s' is not active",
+ rli->linfo.log_file_name);
+#endif
+ // open_binlog() will check the magic header
+ if ((rli->cur_log_fd=open_binlog(cur_log,rli->linfo.log_file_name,
+ &errmsg)) <0)
+ goto err;
+ }
+ }
+ else // read failed with a non-EOF error
+ {
+ // TODO: come up with something better to handle this error
+ sql_print_error("Slave SQL thread: I/O error reading \
+event(errno=%d,cur_log->error=%d)",
+ my_errno,cur_log->error);
+ // no need to hog the mutex while we sleep
+ pthread_mutex_unlock(&rli->data_lock);
+ safe_sleep(rli->sql_thd,rli->mi,1);
+ pthread_mutex_lock(&rli->data_lock);
+ }
+ }
+ if (!errmsg && was_killed)
+ errmsg = "slave SQL thread was killed";
+err:
+ pthread_mutex_unlock(&rli->data_lock);
+ sql_print_error("Error reading relay log event: %s", errmsg);
+ return 0;
+}
+
+
#ifdef __GNUC__
template class I_List_iterator<i_string>;
template class I_List_iterator<i_string_pair>;
diff --git a/sql/slave.h b/sql/slave.h
index 2934e675d56..59263a96687 100644
--- a/sql/slave.h
+++ b/sql/slave.h
@@ -1,65 +1,296 @@
#ifndef SLAVE_H
#define SLAVE_H
+#include "mysql.h"
+#include "my_list.h"
#define SLAVE_NET_TIMEOUT 3600
+#define MAX_SLAVE_ERRMSG 1024
#define MAX_SLAVE_ERROR 2000
+/*
+ The replication is accomplished by starting two threads - I/O
+ thread, and SQL thread. I/O thread is associated with its
+ MASTER_INFO struct, so MASTER_INFO can be viewed as I/O thread
+ descriptor. SQL thread is associated with RELAY_LOG_INFO struct.
+
+ I/O thread reads maintains a connection to the master, and reads log
+ events from the master as they arrive, queueing them by writing them
+ out into the temporary slave binary log (relay log). The SQL thread,
+ in turn, reads the slave binary log executing each event.
+
+ Relay log is needed to be able to handle situations when there is a large
+ backlog of unprocessed events from the master (eg. one particular update
+ takes a day to finish), and to be able to restart the slave server without
+ having to re-read the master updates.
+ */
+
extern ulong slave_net_timeout, master_retry_count;
extern MY_BITMAP slave_error_mask;
extern bool use_slave_mask;
+extern char* slave_load_tmpdir;
+extern my_string master_info_file,relay_log_info_file;
+extern my_string opt_relay_logname, opt_relaylog_index_name;
+extern bool opt_skip_slave_start;
+struct st_master_info;
+
+/*
+ TODO: this needs to be redone, but for now it does not matter since
+ we do not have multi-master yet.
+*/
+
+#define LOCK_ACTIVE_MI { pthread_mutex_lock(&LOCK_active_mi); \
+ ++active_mi_in_use; \
+ pthread_mutex_unlock(&LOCK_active_mi);}
+
+#define UNLOCK_ACTIVE_MI { pthread_mutex_lock(&LOCK_active_mi); \
+ --active_mi_in_use; \
+ pthread_mutex_unlock(&LOCK_active_mi); }
+
+/*
+ st_relay_log_info contains information on the current relay log and
+ relay log offset, and master log name and log sequence corresponding to the
+ last update. Additionally, misc information specific to the SQL thread is
+ included.
+
+ st_relay_log_info is initialized from the slave.info file if such exists.
+ Otherwise, data members are intialized with defaults. The initialization is
+ done with init_relay_log_info() call.
+
+ The format of slave.info file:
+
+ relay_log_name
+ relay_log_pos
+ master_log_name
+ master_log_pos
+
+ To clean up, call end_relay_log_info()
+ */
+
+typedef struct st_relay_log_info
+{
+ /*** The following variables can only be read when protect by data lock ****/
+ /*
+ info_fd - file descriptor of the info file. set only during
+ initialization or clean up - safe to read anytime
+ cur_log_fd - file descriptor of the current read relay log
+ */
+ File info_fd,cur_log_fd;
+ // name of current read relay log
+ char relay_log_name[FN_REFLEN];
+ // master log name corresponding to current read position
+ char master_log_name[FN_REFLEN];
+ // original log position of last processed event
+ volatile my_off_t master_log_pos;
+
+ /*
+ current offset in the relay log.
+ pending - in some cases we do not increment offset immediately after
+ processing an event, because the following event needs to be processed
+ atomically together with this one ( so far, there is only one type of
+ such event - Intvar_event that sets auto_increment value). However, once
+ both events have been processed, we need to increment by the cumulative
+ offset. pending stored the extra offset to be added to the position.
+ */
+ ulonglong relay_log_pos, pending;
+
+ // protected with internal locks
+ // must get data_lock when resetting the logs
+ MYSQL_LOG relay_log;
+ LOG_INFO linfo;
+ IO_CACHE cache_buf,*cur_log;
+
+ /*** The following variables are safe to read any time ***/
+
+ // IO_CACHE of the info file - set only during init or end
+ IO_CACHE info_file;
+
+ /*
+ When we restart slave thread we need to have access to the previously
+ created temporary tables. Modified only on init/end and by the SQL
+ thread, read only by SQL thread.
+ */
+ TABLE* save_temporary_tables;
+
+ /*
+ standard lock acquistion order to avoid deadlocks:
+ run_lock, data_lock, relay_log.LOCK_log, relay_log.LOCK_index
+ */
+ pthread_mutex_t data_lock,run_lock;
+
+ /*
+ start_cond is broadcast when SQL thread is started
+ stop_cond - when stopped
+ data_cond - when data protected by data_lock changes
+ */
+ pthread_cond_t start_cond, stop_cond, data_cond;
+ // if not set, the value of other members of the structure are undefined
+ bool inited;
+
+ // parent master info structure
+ struct st_master_info *mi;
+
+ /*
+ Needed to deal properly with cur_log getting closed and re-opened with
+ a different log under our feet
+ */
+ int cur_log_init_count;
+
+ volatile bool abort_slave, slave_running;
+
+ /*
+ Needed for problems when slave stops and we want to restart it
+ skipping one or more events in the master log that have caused
+ errors, and have been manually applied by DBA already.
+ */
+ volatile uint32 slave_skip_counter;
+#ifndef DBUG_OFF
+ int events_till_abort;
+#endif
+ int last_slave_errno;
+ char last_slave_error[MAX_SLAVE_ERRMSG];
+ THD* sql_thd;
+ bool log_pos_current;
+
+ st_relay_log_info():info_fd(-1),cur_log_fd(-1),inited(0),
+ cur_log_init_count(0),
+ log_pos_current(0)
+ {
+ relay_log_name[0] = master_log_name[0] = 0;
+ pthread_mutex_init(&run_lock, MY_MUTEX_INIT_FAST);
+ pthread_mutex_init(&data_lock, MY_MUTEX_INIT_FAST);
+ pthread_cond_init(&data_cond, NULL);
+ pthread_cond_init(&start_cond, NULL);
+ pthread_cond_init(&stop_cond, NULL);
+ }
+ ~st_relay_log_info()
+ {
+ pthread_mutex_destroy(&run_lock);
+ pthread_mutex_destroy(&data_lock);
+ pthread_cond_destroy(&data_cond);
+ pthread_cond_destroy(&start_cond);
+ pthread_cond_destroy(&stop_cond);
+ }
+ inline void inc_pending(ulonglong val)
+ {
+ pending += val;
+ }
+ // TODO: this probably needs to be fixed
+ inline void inc_pos(ulonglong val, ulonglong log_pos, bool skip_lock=0)
+ {
+ if (!skip_lock)
+ pthread_mutex_lock(&data_lock);
+ relay_log_pos += val+pending;
+ pending = 0;
+ if (log_pos)
+ master_log_pos = log_pos+ val;
+ pthread_cond_broadcast(&data_cond);
+ if (!skip_lock)
+ pthread_mutex_unlock(&data_lock);
+ }
+ /*
+ thread safe read of position - not needed if we are in the slave thread,
+ but required otherwise
+ */
+ inline void read_pos(ulonglong& var)
+ {
+ pthread_mutex_lock(&data_lock);
+ var = relay_log_pos;
+ pthread_mutex_unlock(&data_lock);
+ }
+
+ int wait_for_pos(THD* thd, String* log_name, ulonglong log_pos);
+} RELAY_LOG_INFO;
+
+/*
+ repopen_relay_log() is called when we notice that the current "hot" log
+ got rotated under our feet
+*/
+
+IO_CACHE* reopen_relay_log(RELAY_LOG_INFO* rli, const char** errmsg);
+Log_event* next_event(RELAY_LOG_INFO* rli);
+
+
+/*
+ st_master_info contains information about how to connect to a master,
+ current master log name, and current log offset, as well as misc
+ control variables
+
+ st_master_info is initialized once from the master.info file if such
+ exists. Otherwise, data members corresponding to master.info fields are
+ initialized with defaults specified by master-* options. The initialization
+ is done through init_master_info() call.
+
+ The format of master.info file:
+
+ log_name
+ log_pos
+ master_host
+ master_user
+ master_pass
+ master_port
+ master_connect_retry
+
+ To write out the contents of master.info file to disk ( needed every
+ time we read and queue data from the master ), a call to
+ flush_master_info() is required.
+
+ To clean up, call end_master_info()
+*/
+
+
typedef struct st_master_info
{
- char log_file_name[FN_REFLEN];
- ulonglong pos,pending;
- File fd; // we keep the file open, so we need to remember the file pointer
+ char master_log_name[FN_REFLEN];
+
+ my_off_t master_log_pos;
+ File fd;
IO_CACHE file;
+
// the variables below are needed because we can change masters on the fly
char host[HOSTNAME_LENGTH+1];
char user[USERNAME_LENGTH+1];
char password[HASH_PASSWORD_LENGTH+1];
+ pthread_mutex_t data_lock,run_lock;
+ pthread_cond_t data_cond,start_cond,stop_cond;
+ THD *io_thd;
+ MYSQL* mysql;
+ uint32 file_id; // for 3.23 load data infile
+ RELAY_LOG_INFO rli;
uint port;
uint connect_retry;
- pthread_mutex_t lock;
- pthread_cond_t cond;
+#ifndef DBUG_OFF
+ int events_till_abort;
+#endif
bool inited;
+ bool old_format; // master binlog is in 3.23 format
+ volatile bool abort_slave, slave_running;
+ bool ignore_stop_event;
+
- st_master_info():pending(0),fd(-1),inited(0)
+ st_master_info():fd(-1), io_thd(0), inited(0), old_format(0)
{
host[0] = 0; user[0] = 0; password[0] = 0;
- pthread_mutex_init(&lock, MY_MUTEX_INIT_FAST);
- pthread_cond_init(&cond, NULL);
+ pthread_mutex_init(&run_lock, MY_MUTEX_INIT_FAST);
+ pthread_mutex_init(&data_lock, MY_MUTEX_INIT_FAST);
+ pthread_cond_init(&data_cond, NULL);
+ pthread_cond_init(&start_cond, NULL);
+ pthread_cond_init(&stop_cond, NULL);
}
~st_master_info()
{
- pthread_mutex_destroy(&lock);
- pthread_cond_destroy(&cond);
- }
- inline void inc_pending(ulonglong val)
- {
- pending += val;
- }
- inline void inc_pos(ulonglong val)
- {
- pthread_mutex_lock(&lock);
- pos += val + pending;
- pending = 0;
- pthread_cond_broadcast(&cond);
- pthread_mutex_unlock(&lock);
- }
- // thread safe read of position - not needed if we are in the slave thread,
- // but required otherwise
- inline void read_pos(ulonglong& var)
- {
- pthread_mutex_lock(&lock);
- var = pos;
- pthread_mutex_unlock(&lock);
+ pthread_mutex_destroy(&run_lock);
+ pthread_mutex_destroy(&data_lock);
+ pthread_cond_destroy(&data_cond);
+ pthread_cond_destroy(&start_cond);
+ pthread_cond_destroy(&stop_cond);
}
- int wait_for_pos(THD* thd, String* log_name, ulonglong log_pos);
} MASTER_INFO;
+int queue_event(MASTER_INFO* mi,const char* buf,ulong event_len);
+
typedef struct st_table_rule_ent
{
char* db;
@@ -69,45 +300,100 @@ typedef struct st_table_rule_ent
#define TABLE_RULE_HASH_SIZE 16
#define TABLE_RULE_ARR_SIZE 16
+#define MAX_SLAVE_ERRMSG 1024
+
+#define RPL_LOG_NAME (rli->master_log_name[0] ? rli->master_log_name :\
+ "FIRST")
+#define IO_RPL_LOG_NAME (mi->master_log_name[0] ? mi->master_log_name :\
+ "FIRST")
+
+/* masks for start/stop operations on io and sql slave threads */
+#define SLAVE_IO 1
+#define SLAVE_SQL 2
+/*
+ If the following is set, if first gives an error, second will be
+ tried. Otherwise, if first fails, we fail.
+*/
+#define SLAVE_FORCE_ALL 4
+
+int init_slave();
+void init_slave_skip_errors(char* arg);
int flush_master_info(MASTER_INFO* mi);
+int flush_relay_log_info(RELAY_LOG_INFO* rli);
+int register_slave_on_master(MYSQL* mysql);
+int terminate_slave_threads(MASTER_INFO* mi, int thread_mask,
+ bool skip_lock = 0);
+int terminate_slave_thread(THD* thd, pthread_mutex_t* term_mutex,
+ pthread_mutex_t* cond_lock,
+ pthread_cond_t* term_cond,
+ volatile bool* slave_running);
+int start_slave_threads(bool need_slave_mutex, bool wait_for_start,
+ MASTER_INFO* mi, const char* master_info_fname,
+ const char* slave_info_fname, int thread_mask);
+/*
+ cond_lock is usually same as start_lock. It is needed for the case when
+ start_lock is 0 which happens if start_slave_thread() is called already
+ inside the start_lock section, but at the same time we want a
+ pthread_cond_wait() on start_cond,start_lock
+*/
+int start_slave_thread(pthread_handler h_func, pthread_mutex_t* start_lock,
+ pthread_mutex_t *cond_lock,
+ pthread_cond_t* start_cond,
+ volatile bool* slave_running,
+ MASTER_INFO* mi);
+
+// If fd is -1, dump to NET
+int mysql_table_dump(THD* thd, const char* db,
+ const char* tbl_name, int fd = -1);
-int mysql_table_dump(THD* thd, char* db, char* tbl_name, int fd = -1);
-// if fd is -1, dump to NET
-int fetch_nx_table(THD* thd, MASTER_INFO* mi);
// retrieve non-exitent table from master
-// the caller must set thd->last_nx_table and thd->last_nx_db first
-int show_master_info(THD* thd);
+int fetch_master_table(THD* thd, const char* db_name, const char* table_name,
+ MASTER_INFO* mi, MYSQL* mysql);
+
+int show_master_info(THD* thd, MASTER_INFO* mi);
int show_binlog_info(THD* thd);
+// See if the query uses any tables that should not be replicated
int tables_ok(THD* thd, TABLE_LIST* tables);
-// see if the query uses any tables that should not be replicated
+/*
+ Check to see if the database is ok to operate on with respect to the
+ do and ignore lists - used in replication
+*/
int db_ok(const char* db, I_List<i_string> &do_list,
I_List<i_string> &ignore_list );
-// check to see if the database is ok to operate on with respect to the
-// do and ignore lists - used in replication
int add_table_rule(HASH* h, const char* table_spec);
int add_wild_table_rule(DYNAMIC_ARRAY* a, const char* table_spec);
void init_table_rule_hash(HASH* h, bool* h_inited);
void init_table_rule_array(DYNAMIC_ARRAY* a, bool* a_inited);
-void init_slave_skip_errors(char* arg);
+char* rewrite_db(char* db);
+int check_expected_error(THD* thd, RELAY_LOG_INFO* rli, int error_code);
+void skip_load_data_infile(NET* net);
+void slave_print_error(RELAY_LOG_INFO* rli,int err_code, const char* msg, ...);
void end_slave(); // clean up
-int init_master_info(MASTER_INFO* mi);
+int init_master_info(MASTER_INFO* mi, const char* master_info_fname,
+ const char* slave_info_fname);
void end_master_info(MASTER_INFO* mi);
+int init_relay_log_info(RELAY_LOG_INFO* rli, const char* info_fname);
+void end_relay_log_info(RELAY_LOG_INFO* rli);
+void lock_slave_threads(MASTER_INFO* mi);
+void unlock_slave_threads(MASTER_INFO* mi);
+void init_thread_mask(int* mask,MASTER_INFO* mi,bool inverse);
+int init_relay_log_pos(RELAY_LOG_INFO* rli,const char* log,ulonglong pos,
+ bool need_data_lock, const char** errmsg);
+
+int purge_relay_logs(RELAY_LOG_INFO* rli,bool just_reset,const char** errmsg);
+
extern bool opt_log_slave_updates ;
-pthread_handler_decl(handle_slave,arg);
-extern bool volatile abort_loop, abort_slave, slave_running;
-extern uint32 slave_skip_counter;
-// needed for problems when slave stops and
-// we want to restart it skipping one or more events in the master log that
-// have caused errors, and have been manually applied by DBA already
-
-extern pthread_t slave_real_id;
-extern THD* slave_thd;
-extern MASTER_INFO glob_mi;
+pthread_handler_decl(handle_slave_io,arg);
+pthread_handler_decl(handle_slave_sql,arg);
+extern bool volatile abort_loop;
+extern MASTER_INFO main_mi, *active_mi; // active_mi for multi-master
+extern volatile int active_mi_in_use;
+extern LIST master_list;
extern HASH replicate_do_table, replicate_ignore_table;
extern DYNAMIC_ARRAY replicate_wild_do_table, replicate_wild_ignore_table;
extern bool do_table_inited, ignore_table_inited,
@@ -119,14 +405,13 @@ extern int disconnect_slave_event_count, abort_slave_event_count ;
#endif
// the master variables are defaults read from my.cnf or command line
-extern uint master_port, master_connect_retry;
+extern uint master_port, master_connect_retry, report_port;
extern my_string master_user, master_password, master_host,
- master_info_file;
+ master_info_file, relay_log_info_file, report_user, report_host,
+ report_password;
extern I_List<i_string> replicate_do_db, replicate_ignore_db;
extern I_List<i_string_pair> replicate_rewrite_db;
extern I_List<THD> threads;
#endif
-
-
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index 7ad778cf5d0..577084a650a 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -1,15 +1,15 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+/* Copyright (C) 2000 MySQL AB
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -58,9 +58,13 @@ class ACL_USER :public ACL_ACCESS
{
public:
acl_host_and_ip host;
- uint hostname_length;
+ uint hostname_length, questions, updates;
char *user,*password;
ulong salt[2];
+#ifdef HAVE_OPENSSL
+ enum SSL_type ssl_type;
+ const char *ssl_cipher, *x509_issuer, *x509_subject;
+#endif /* HAVE_OPENSSL */
};
class ACL_DB :public ACL_ACCESS
@@ -106,7 +110,7 @@ static void update_hostname(acl_host_and_ip *host, const char *hostname);
static bool compare_hostname(const acl_host_and_ip *host, const char *hostname,
const char *ip);
-int acl_init(bool dont_read_acl_tables)
+int acl_init(bool dont_read_acl_tables)
{
THD *thd;
TABLE_LIST tables[3];
@@ -128,7 +132,8 @@ int acl_init(bool dont_read_acl_tables)
thd->mysys_var=my_thread_var;
thd->current_tablenr=0;
thd->open_tables=0;
- thd->db=my_strdup("mysql",MYF(0));
+ thd->db= my_strdup("mysql",MYF(0));
+ thd->db_length=5; // Safety
bzero((char*) &tables,sizeof(tables));
tables[0].name=tables[0].real_name=(char*) "host";
tables[1].name=tables[1].real_name=(char*) "user";
@@ -199,6 +204,24 @@ int acl_init(bool dont_read_acl_tables)
update_hostname(&user.host,get_field(&mem, table,0));
user.user=get_field(&mem, table,1);
user.password=get_field(&mem, table,2);
+#ifdef HAVE_OPENSSL
+ DBUG_PRINT("info",("table->fields=%d",table->fields));
+ if (table->fields >= 21) /* From 4.0.0 we have more fields */
+ {
+ char *ssl_type=get_field(&mem, table,17);
+ if (!strcmp(ssl_type, "ANY"))
+ user.ssl_type=SSL_TYPE_ANY;
+ else if (!strcmp(ssl_type, "X509"))
+ user.ssl_type=SSL_TYPE_X509;
+ else if (!strcmp(ssl_type, "SPECIFIED"))
+ user.ssl_type=SSL_TYPE_SPECIFIED;
+ else
+ user.ssl_type=SSL_TYPE_NONE;
+ user.ssl_cipher=get_field(&mem, table, 18);
+ user.x509_issuer=get_field(&mem, table, 19);
+ user.x509_subject=get_field(&mem, table, 20);
+ }
+#endif /* HAVE_OPENSSL */
if (user.password && (length=(uint) strlen(user.password)) == 8 &&
protocol_version == PROTOCOL_VERSION)
{
@@ -218,6 +241,18 @@ int acl_init(bool dont_read_acl_tables)
user.access=get_access(table,3);
user.sort=get_sort(2,user.host.hostname,user.user);
user.hostname_length=user.host.hostname ? (uint) strlen(user.host.hostname) : 0;
+ if (table->fields >=23)
+ {
+ /* Table has new MySQL usage limits */
+ char *ptr = get_field(&mem, table, 21);
+ user.questions=atoi(ptr);
+ ptr = get_field(&mem, table, 22);
+ user.updates=atoi(ptr);
+ if (user.questions)
+ mqh_used=1;
+ }
+ else
+ user.questions=user.updates=0;
#ifndef TO_BE_REMOVED
if (table->fields <= 13)
{ // Without grant
@@ -398,16 +433,20 @@ static int acl_compare(ACL_ACCESS *a,ACL_ACCESS *b)
}
-/* Get master privilges for user (priviliges for all tables) */
-
+/*
+ Get master privilges for user (priviliges for all tables).
+ Required before connecting to MySQL
+*/
-uint acl_getroot(const char *host, const char *ip, const char *user,
+uint acl_getroot(THD *thd, const char *host, const char *ip, const char *user,
const char *password,const char *message,char **priv_user,
- bool old_ver)
+ bool old_ver, uint *max_questions)
{
uint user_access=NO_ACCESS;
*priv_user=(char*) user;
+ char *ptr=0;
+ *max_questions=0;
if (!initialized)
return (uint) ~NO_ACCESS; // If no data allow anything /* purecov: tested */
VOID(pthread_mutex_lock(&acl_cache->lock));
@@ -428,7 +467,94 @@ uint acl_getroot(const char *host, const char *ip, const char *user,
!check_scramble(password,message,acl_user->salt,
(my_bool) old_ver)))
{
+#ifdef HAVE_OPENSSL
+ Vio *vio=thd->net.vio;
+ /*
+ In this point we know that user is allowed to connect
+ from given host by given username/password pair. Now
+ we check if SSL is required, if user is using SSL and
+ if X509 certificate attributes are OK
+ */
+ switch(acl_user->ssl_type) {
+ case SSL_TYPE_NONE: /* SSL is not required to connect */
+ user_access=acl_user->access;
+ break;
+ case SSL_TYPE_ANY: /* Any kind of SSL is good enough */
+ if (vio_type(vio) == VIO_TYPE_SSL)
+ user_access=acl_user->access;
+ break;
+ case SSL_TYPE_X509: /* Client should have any valid certificate. */
+ /*
+ Connections with non-valid certificates are dropped already
+ in sslaccept() anyway, so we do not check validity here.
+ */
+ if (SSL_get_peer_certificate(vio->ssl_))
+ user_access=acl_user->access;
+ break;
+ case SSL_TYPE_SPECIFIED: /* Client should have specified attrib */
+ /*
+ We do not check for absence of SSL because without SSL it does
+ not pass all checks here anyway.
+ If cipher name is specified, we compare it to actual cipher in
+ use.
+ */
+ if (acl_user->ssl_cipher)
+ DBUG_PRINT("info",("comparing ciphers: '%s' and '%s'",
+ acl_user->ssl_cipher,
+ SSL_get_cipher(vio->ssl_)));
+ if (!strcmp(acl_user->ssl_cipher,SSL_get_cipher(vio->ssl_)))
+ user_access=acl_user->access;
+ else
+ {
+ user_access=NO_ACCESS;
+ break;
+ }
+ /* Prepare certificate (if exists) */
+ DBUG_PRINT("info",("checkpoint 1"));
+ X509* cert=SSL_get_peer_certificate(vio->ssl_);
+ DBUG_PRINT("info",("checkpoint 2"));
+ /* If X509 issuer is speified, we check it... */
+ if (acl_user->x509_issuer)
+ {
+ DBUG_PRINT("info",("checkpoint 3"));
+ ptr = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0);
+ DBUG_PRINT("info",("comparing issuers: '%s' and '%s'",
+ acl_user->x509_issuer, ptr));
+ if (!strcmp(acl_user->x509_issuer,ptr))
+ user_access=acl_user->access;
+ else
+ {
+ user_access=NO_ACCESS;
+ free(ptr);
+ break;
+ }
+ free(ptr);
+ }
+ DBUG_PRINT("info",("checkpoint 4"));
+ /* X509 subject is specified, we check it .. */
+ if (acl_user->x509_subject)
+ {
+ ptr = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0);
+ DBUG_PRINT("info",("comparing subjects: '%s' and '%s'",
+ acl_user->x509_subject, ptr));
+ if (!strcmp(acl_user->x509_subject,ptr))
+ user_access=acl_user->access;
+ else
+ {
+ user_access=NO_ACCESS;
+ free(ptr);
+ break;
+ }
+ free(ptr);
+ }
+ DBUG_PRINT("info",("checkpoint 5"));
+ break;
+ }
+ DBUG_PRINT("info",("checkpoint 6"));
+#else /* HAVE_OPENSSL */
user_access=acl_user->access;
+#endif /* HAVE_OPENSSL */
+ *max_questions=acl_user->questions;
if (!acl_user->user)
*priv_user=(char*) ""; // Change to anonymous user /* purecov: inspected */
break;
@@ -457,7 +583,13 @@ static byte* check_get_key(ACL_USER *buff,uint *length,
}
static void acl_update_user(const char *user, const char *host,
- const char *password, uint privileges)
+ const char *password,
+ enum SSL_type ssl_type,
+ const char *ssl_cipher,
+ const char *x509_issuer,
+ const char *x509_subject,
+ unsigned int mqh,
+ uint privileges)
{
for (uint i=0 ; i < acl_users.elements ; i++)
{
@@ -470,6 +602,13 @@ static void acl_update_user(const char *user, const char *host,
acl_user->host.hostname && !strcmp(host,acl_user->host.hostname))
{
acl_user->access=privileges;
+ acl_user->questions=mqh;
+#ifdef HAVE_OPENSSL
+ acl_user->ssl_type=ssl_type;
+ acl_user->ssl_cipher=ssl_cipher;
+ acl_user->x509_issuer=x509_issuer;
+ acl_user->x509_subject=x509_subject;
+#endif /* HAVE_OPENSSL */
if (password)
{
if (!password[0])
@@ -488,7 +627,12 @@ static void acl_update_user(const char *user, const char *host,
static void acl_insert_user(const char *user, const char *host,
- const char *password,
+ const char *password,
+ enum SSL_type ssl_type,
+ const char *ssl_cipher,
+ const char *x509_issuer,
+ const char *x509_subject,
+ unsigned int mqh,
uint privileges)
{
ACL_USER acl_user;
@@ -496,8 +640,15 @@ static void acl_insert_user(const char *user, const char *host,
update_hostname(&acl_user.host,strdup_root(&mem,host));
acl_user.password=0;
acl_user.access=privileges;
+ acl_user.questions=mqh;
acl_user.sort=get_sort(2,acl_user.host.hostname,acl_user.user);
acl_user.hostname_length=(uint) strlen(acl_user.host.hostname);
+#ifdef HAVE_OPENSSL
+ acl_user.ssl_type=ssl_type;
+ acl_user.ssl_cipher=ssl_cipher;
+ acl_user.x509_issuer=x509_issuer;
+ acl_user.x509_subject=x509_subject;
+#endif /* HAVE_OPENSSL */
if (password)
{
acl_user.password=(char*) ""; // Just point at something
@@ -570,12 +721,17 @@ uint acl_get(const char *host, const char *ip, const char *bin_ip,
{
uint host_access,db_access,i,key_length;
db_access=0; host_access= ~0;
- char key[ACL_KEY_LENGTH],*end;
+ char key[ACL_KEY_LENGTH],*tmp_db,*end;
acl_entry *entry;
VOID(pthread_mutex_lock(&acl_cache->lock));
memcpy_fixed(&key,bin_ip,sizeof(struct in_addr));
- end=strmov(strmov(key+sizeof(struct in_addr),user)+1,db);
+ end=strmov((tmp_db=strmov(key+sizeof(struct in_addr),user)+1),db);
+ if (lower_case_table_names)
+ {
+ casedn_str(tmp_db);
+ db=tmp_db;
+ }
key_length=(uint) (end-key);
if ((entry=(acl_entry*) acl_cache->search(key,key_length)))
{
@@ -641,7 +797,7 @@ int wild_case_compare(const char *str,const char *wildstr)
{
reg3 int flag;
DBUG_ENTER("wild_case_compare");
-
+ DBUG_PRINT("enter",("str='%s', wildstr='%s'",str,wildstr));
while (*wildstr)
{
while (*wildstr && *wildstr != wild_many && *wildstr != wild_one)
@@ -653,7 +809,7 @@ int wild_case_compare(const char *str,const char *wildstr)
if (! *wildstr ) DBUG_RETURN (*str != 0);
if (*wildstr++ == wild_one)
{
- if (! *str++) DBUG_RETURN (1); /* One char; skipp */
+ if (! *str++) DBUG_RETURN (1); /* One char; skip */
}
else
{ /* Found '*' */
@@ -764,16 +920,18 @@ bool acl_check_host(const char *host, const char *ip)
bool change_password(THD *thd, const char *host, const char *user,
char *new_password)
{
+ DBUG_ENTER("change_password");
+ DBUG_PRINT("enter",("thd=%x, host='%s', user='%s', new_password='%s'",thd,host,user,new_password));
uint length=0;
if (!user[0])
{
send_error(&thd->net, ER_PASSWORD_ANONYMOUS_USER);
- return 1;
+ DBUG_RETURN(1);
}
if (!initialized)
{
send_error(&thd->net, ER_PASSWORD_NOT_ALLOWED); /* purecov: inspected */
- return 1; /* purecov: inspected */
+ DBUG_RETURN(1); /* purecov: inspected */
}
if (!host)
host=thd->ip; /* purecov: tested */
@@ -785,15 +943,16 @@ bool change_password(THD *thd, const char *host, const char *user,
my_strcasecmp(host,thd->host ? thd->host : thd->ip))))
{
if (check_access(thd, UPDATE_ACL, "mysql",0,1))
- return 1;
+ DBUG_RETURN(1);
}
VOID(pthread_mutex_lock(&acl_cache->lock));
ACL_USER *acl_user;
+ DBUG_PRINT("info",("host=%s, user=%s",host,user));
if (!(acl_user= find_acl_user(host,user)) || !acl_user->user)
{
send_error(&thd->net, ER_PASSWORD_NO_MATCH);
VOID(pthread_mutex_unlock(&acl_cache->lock));
- return 1;
+ DBUG_RETURN(1);
}
if (update_user_table(thd,
acl_user->host.hostname ? acl_user->host.hostname : "",
@@ -801,7 +960,7 @@ bool change_password(THD *thd, const char *host, const char *user,
{
VOID(pthread_mutex_unlock(&acl_cache->lock)); /* purecov: deadcode */
send_error(&thd->net,0); /* purecov: deadcode */
- return 1; /* purecov: deadcode */
+ DBUG_RETURN(1); /* purecov: deadcode */
}
get_salt_from_password(acl_user->salt,new_password);
if (!new_password[0])
@@ -812,7 +971,7 @@ bool change_password(THD *thd, const char *host, const char *user,
VOID(pthread_mutex_unlock(&acl_cache->lock));
char buff[460];
-
+
Query_log_event qinfo(thd, buff);
qinfo.q_len =
my_sprintf(buff,
@@ -822,7 +981,7 @@ bool change_password(THD *thd, const char *host, const char *user,
new_password));
mysql_update_log.write(thd,buff,qinfo.q_len);
mysql_bin_log.write(&qinfo);
- return 0;
+ DBUG_RETURN(0);
}
@@ -833,17 +992,23 @@ bool change_password(THD *thd, const char *host, const char *user,
static ACL_USER *
find_acl_user(const char *host, const char *user)
{
+ DBUG_ENTER("find_acl_user");
+ DBUG_PRINT("enter",("host='%s', user='%s'",host,user));
for (uint i=0 ; i < acl_users.elements ; i++)
{
ACL_USER *acl_user=dynamic_element(&acl_users,i,ACL_USER*);
+ DBUG_PRINT("info",("strcmp('%s','%s'), compare_hostname('%s','%s'),",
+ user,acl_user->user,(host),(acl_user->host)));
if (!acl_user->user && !user[0] ||
acl_user->user && !strcmp(user,acl_user->user))
{
- if (compare_hostname(&acl_user->host,host,host))
- return acl_user;
+ if (compare_hostname(&(acl_user->host),host,host))
+ {
+ DBUG_RETURN(acl_user);
+ }
}
}
- return 0;
+ DBUG_RETURN(0);
}
/*****************************************************************************
@@ -972,7 +1137,7 @@ static bool test_if_create_new_users(THD *thd)
** Handle GRANT commands
****************************************************************************/
-static int replace_user_table(TABLE *table, const LEX_USER &combo,
+static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo,
uint rights, char what, bool create_user)
{
int error = -1;
@@ -1006,7 +1171,7 @@ static int replace_user_table(TABLE *table, const LEX_USER &combo,
my_printf_error(ER_NO_PERMISSION_TO_CREATE_USER,
ER(ER_NO_PERMISSION_TO_CREATE_USER),
MYF(0),thd->user,
- thd->host ? thd->host : thd->ip ? thd->ip: "");
+ thd->host_or_ip);
error= -1;
goto end;
}
@@ -1032,7 +1197,43 @@ static int replace_user_table(TABLE *table, const LEX_USER &combo,
table->field[i]->store(&what,1);
}
rights=get_access(table,3);
-
+#ifdef HAVE_OPENSSL
+ /* We write down SSL related ACL stuff */
+ DBUG_PRINT("info",("table->fields=%d",table->fields));
+ if (table->fields >= 21) /* From 4.0.0 we have more fields */
+ {
+ table->field[18]->store("",0);
+ table->field[19]->store("",0);
+ table->field[20]->store("",0);
+ switch (thd->lex.ssl_type) {
+ case SSL_TYPE_ANY:
+ table->field[17]->store("ANY",3);
+ break;
+ case SSL_TYPE_X509:
+ table->field[17]->store("X509",4);
+ break;
+ case SSL_TYPE_SPECIFIED:
+ table->field[17]->store("SPECIFIED",9);
+ if (thd->lex.ssl_cipher)
+ table->field[18]->store(thd->lex.ssl_cipher,
+ strlen(thd->lex.ssl_cipher));
+ if (thd->lex.x509_issuer)
+ table->field[19]->store(thd->lex.x509_issuer,
+ strlen(thd->lex.x509_issuer));
+ if (thd->lex.x509_subject)
+ table->field[20]->store(thd->lex.x509_subject,
+ strlen(thd->lex.x509_subject));
+ break;
+ default:
+ table->field[17]->store("NONE",4);
+ }
+ }
+#endif /* HAVE_OPENSSL */
+ if (table->fields >= 23 && thd->lex.mqh)
+ {
+ table->field[21]->store((longlong) thd->lex.mqh);
+ mqh_used=1;
+ }
if (old_row_exists)
{
/*
@@ -1059,16 +1260,28 @@ static int replace_user_table(TABLE *table, const LEX_USER &combo,
}
error=0; // Privileges granted / revoked
- end:
+end:
if (!error)
{
acl_cache->clear(1); // Clear privilege cache
if (!combo.password.str)
password=0; // No password given on command
if (old_row_exists)
- acl_update_user(combo.user.str,combo.host.str,password,rights);
+ acl_update_user(combo.user.str,combo.host.str,password,
+ thd->lex.ssl_type,
+ thd->lex.ssl_cipher,
+ thd->lex.x509_issuer,
+ thd->lex.x509_subject,
+ thd->lex.mqh,
+ rights);
else
- acl_insert_user(combo.user.str,combo.host.str,password,rights);
+ acl_insert_user(combo.user.str,combo.host.str,password,
+ thd->lex.ssl_type,
+ thd->lex.ssl_cipher,
+ thd->lex.x509_issuer,
+ thd->lex.x509_subject,
+ thd->lex.mqh,
+ rights);
}
table->file->index_end();
DBUG_RETURN(error);
@@ -1199,6 +1412,11 @@ public:
db = strdup_root(&memex,d);
user = strdup_root(&memex,u);
tname= strdup_root(&memex,t);
+ if (lower_case_table_names)
+ {
+ casedn_str(db);
+ casedn_str(tname);
+ }
key_length =(uint) strlen(d)+(uint) strlen(u)+(uint) strlen(t)+3;
hash_key = (char*) alloc_root(&memex,key_length);
strmov(strmov(strmov(hash_key,user)+1,db)+1,tname);
@@ -1220,7 +1438,13 @@ public:
privs = cols = 0; /* purecov: inspected */
return; /* purecov: inspected */
}
- key_length = (uint) strlen(db) + (uint) strlen(user) + (uint) strlen (tname) + 3;
+ if (lower_case_table_names)
+ {
+ casedn_str(db);
+ casedn_str(tname);
+ }
+ key_length = ((uint) strlen(db) + (uint) strlen(user) +
+ (uint) strlen(tname) + 3);
hash_key = (char*) alloc_root(&memex,key_length);
strmov(strmov(strmov(hash_key,user)+1,db)+1,tname);
privs = (uint) form->field[6]->val_int();
@@ -1503,8 +1727,7 @@ static int replace_table_table(THD *thd, GRANT_TABLE *grant_table,
uint store_table_rights,store_col_rights;
DBUG_ENTER("replace_table_table");
- strxmov(grantor,thd->user,"@",thd->host ? thd->host : thd->ip ? thd->ip :"",
- NullS);
+ strxmov(grantor, thd->user, "@", thd->host_or_ip, NullS);
// The following should always succeed as new users are created before
// this function is called!
@@ -1615,6 +1838,9 @@ int mysql_table_grant (THD *thd, TABLE_LIST *table_list,
TABLE_LIST tables[3];
bool create_new_users=0;
DBUG_ENTER("mysql_table_grant");
+ DBUG_PRINT("info",("ssl_cipher=%s",thd->lex.ssl_cipher));
+ DBUG_PRINT("info",("x509_issuer=%s",thd->lex.x509_issuer));
+ DBUG_PRINT("info",("x509_subject=%s",thd->lex.x509_subject));
if (!initialized)
{
@@ -1704,9 +1930,10 @@ int mysql_table_grant (THD *thd, TABLE_LIST *table_list,
continue;
}
/* Create user if needed */
- if (replace_user_table(tables[0].table,
- *Str,
- 0,
+ if (replace_user_table(thd,
+ tables[0].table,
+ *Str,
+ 0,
revoke_grant ? 'N' : 'Y',
create_new_users))
{
@@ -1799,7 +2026,7 @@ int mysql_table_grant (THD *thd, TABLE_LIST *table_list,
pthread_mutex_unlock(&LOCK_grant);
if (!result)
send_ok(&thd->net);
- /* Tables are automaticly closed */
+ /* Tables are automatically closed */
DBUG_RETURN(result);
}
@@ -1809,7 +2036,7 @@ int mysql_grant (THD *thd, const char *db, List <LEX_USER> &list, uint rights,
{
List_iterator <LEX_USER> str_list (list);
LEX_USER *Str;
- char what;
+ char what,tmp_db[NAME_LEN+1];
bool create_new_users=0;
TABLE_LIST tables[2];
DBUG_ENTER("mysql_grant");
@@ -1821,6 +2048,12 @@ int mysql_grant (THD *thd, const char *db, List <LEX_USER> &list, uint rights,
}
what = (revoke_grant) ? 'N' : 'Y';
+ if (lower_case_table_names && db)
+ {
+ strmov(tmp_db,db);
+ casedn_str(tmp_db);
+ db=tmp_db;
+ }
/* open the mysql.user and mysql.db tables */
@@ -1860,7 +2093,8 @@ int mysql_grant (THD *thd, const char *db, List <LEX_USER> &list, uint rights,
result= -1;
continue;
}
- if ((replace_user_table(tables[0].table,
+ if ((replace_user_table(thd,
+ tables[0].table,
*Str,
(!db ? rights : 0), what, create_new_users)))
result= -1;
@@ -1916,7 +2150,8 @@ int grant_init (void)
thd->mysys_var=my_thread_var;
thd->current_tablenr=0;
thd->open_tables=0;
- thd->db=my_strdup("mysql",MYF(0));
+ thd->db= my_strdup("mysql",MYF(0));
+ thd->db_length=5; // Safety
bzero((char*) &tables,sizeof(tables));
tables[0].name=tables[0].real_name= (char*) "tables_priv";
tables[1].name=tables[1].real_name= (char*) "columns_priv";
@@ -1952,7 +2187,7 @@ int grant_init (void)
delete thd;
DBUG_RETURN(0); // Empty table is ok!
}
- grant_option = TRUE;
+ grant_option= TRUE;
t_table->file->index_end();
MEM_ROOT *old_root=my_pthread_getspecific_ptr(MEM_ROOT*,THR_MALLOC);
@@ -2038,8 +2273,8 @@ bool check_grant(THD *thd, uint want_access, TABLE_LIST *tables,
table->grant.want_privilege=0;
continue; // Already checked
}
- const char *db = table->db ? table->db : thd->db;
- GRANT_TABLE *grant_table = table_hash_search(thd->host,thd->ip,db,user,
+ GRANT_TABLE *grant_table = table_hash_search(thd->host,thd->ip,
+ table->db,user,
table->real_name,0);
if (!grant_table)
{
@@ -2093,7 +2328,7 @@ bool check_grant(THD *thd, uint want_access, TABLE_LIST *tables,
net_printf(&thd->net,ER_TABLEACCESS_DENIED_ERROR,
command,
thd->priv_user,
- thd->host ? thd->host : (thd->ip ? thd->ip : "unknown"),
+ thd->host_or_ip,
table ? table->real_name : "unknown");
}
return 1;
@@ -2156,7 +2391,7 @@ bool check_grant_column (THD *thd,TABLE *table, const char *name,
MYF(0),
command,
thd->priv_user,
- thd->host ? thd->host : (thd->ip ? thd->ip : "unknown"),
+ thd->host_or_ip,
name,
table ? table->real_name : "unknown");
}
@@ -2214,7 +2449,7 @@ bool check_grant_all_columns(THD *thd,uint want_access, TABLE *table)
MYF(0),
command,
thd->priv_user,
- thd->host ? thd->host : (thd->ip ? thd->ip : "unknown"),
+ thd->host_or_ip,
field ? field->field_name : "unknown",
table->real_name);
return 1;
@@ -2321,9 +2556,10 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
{
uint counter, want_access,index;
int error = 0;
+ int ssl_options = 0;
ACL_USER *acl_user; ACL_DB *acl_db;
char buff[1024];
- DBUG_ENTER("mysql_grant");
+ DBUG_ENTER("mysql_show_grants");
LINT_INIT(acl_user);
if (!initialized)
@@ -2414,6 +2650,41 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
global.append(passd_buff);
global.append('\'');
}
+#ifdef HAVE_OPENSSL
+ /* "show grants" SSL related stuff */
+ if (acl_user->ssl_type == SSL_TYPE_ANY)
+ global.append(" REQUIRE SSL",12);
+ else if (acl_user->ssl_type==SSL_TYPE_X509)
+ global.append(" REQUIRE X509",13);
+ else if (acl_user->ssl_type==SSL_TYPE_SPECIFIED)
+ {
+ global.append(" REQUIRE ",9);
+ if (acl_user->x509_issuer)
+ {
+ if (ssl_options++)
+ global.append(" AND ",5);
+ global.append("ISSUER \"",8);
+ global.append(acl_user->x509_issuer,strlen(acl_user->x509_issuer));
+ global.append("\"",1);
+ }
+ if (acl_user->x509_subject)
+ {
+ if (ssl_options++)
+ global.append(" AND ",5);
+ global.append("SUBJECT \"",9);
+ global.append(acl_user->x509_subject,strlen(acl_user->x509_subject));
+ global.append("\"",1);
+ }
+ if (acl_user->ssl_cipher)
+ {
+ if (ssl_options++)
+ global.append(" AND ",5);
+ global.append("CIPHER \"",8);
+ global.append(acl_user->ssl_cipher,strlen(acl_user->ssl_cipher));
+ global.append("\"",1);
+ }
+ }
+#endif /* HAVE_OPENSSL */
if (want_access & GRANT_ACL)
global.append(" WITH GRANT OPTION",18);
thd->packet.length(0);
@@ -2578,6 +2849,16 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
}
+uint get_mqh(const char *user, const char *host)
+{
+ if (!initialized) return 0;
+
+ ACL_USER *acl_user;
+ acl_user= find_acl_user(host,user);
+ return (acl_user) ? acl_user->questions : 0;
+}
+
+
/*****************************************************************************
** Instantiate used templates
*****************************************************************************/
diff --git a/sql/sql_acl.h b/sql/sql_acl.h
index cf9696d51e7..f118ac17789 100644
--- a/sql/sql_acl.h
+++ b/sql/sql_acl.h
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -59,9 +59,9 @@ void acl_reload(void);
void acl_free(bool end=0);
uint acl_get(const char *host, const char *ip, const char *bin_ip,
const char *user, const char *db);
-uint acl_getroot(const char *host, const char *ip, const char *user,
+uint acl_getroot(THD *thd, const char *host, const char *ip, const char *user,
const char *password,const char *scramble,char **priv_user,
- bool old_ver);
+ bool old_ver, uint *max);
bool acl_check_host(const char *host, const char *ip);
bool change_password(THD *thd, const char *host, const char *user,
char *password);
@@ -82,3 +82,4 @@ bool check_grant_db(THD *thd,const char *db);
uint get_table_grant(THD *thd, TABLE_LIST *table);
uint get_column_grant(THD *thd, TABLE_LIST *table, Field *field);
int mysql_show_grants(THD *thd, LEX_USER *user);
+uint get_mqh(const char *user, const char *host);
diff --git a/sql/sql_analyse.cc b/sql/sql_analyse.cc
index de367e8c052..df8a8f1fdde 100644
--- a/sql/sql_analyse.cc
+++ b/sql/sql_analyse.cc
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -38,6 +38,37 @@
#define UINT_MAX24 0xffffff
#define UINT_MAX32 0xffffffff
+int sortcmp2(void* cmp_arg __attribute__((unused)),
+ const String *a,const String *b)
+{
+ return sortcmp(a,b);
+}
+
+int stringcmp2(void* cmp_arg __attribute__((unused)),
+ const String *a,const String *b)
+{
+ return stringcmp(a,b);
+}
+
+int compare_double2(void* cmp_arg __attribute__((unused)),
+ const double *s, const double *t)
+{
+ return compare_double(s,t);
+}
+
+int compare_longlong2(void* cmp_arg __attribute__((unused)),
+ const longlong *s, const longlong *t)
+{
+ return compare_longlong(s,t);
+}
+
+int compare_ulonglong2(void* cmp_arg __attribute__((unused)),
+ const ulonglong *s, const ulonglong *t)
+{
+ return compare_ulonglong(s,t);
+}
+
+
Procedure *
proc_analyse_init(THD *thd, ORDER *param, select_result *result,
List<Item> &field_list)
@@ -96,7 +127,7 @@ proc_analyse_init(THD *thd, ORDER *param, select_result *result,
pc->f_end = pc->f_info + field_list.elements;
pc->fields = field_list;
- List_iterator<Item> it(pc->fields);
+ List_iterator_fast<Item> it(pc->fields);
f_info = pc->f_info;
Item *item;
@@ -859,7 +890,7 @@ int collect_string(String *element,
int collect_real(double *element, element_count count __attribute__((unused)),
TREE_INFO *info)
{
- char buff[255];
+ char buff[MAX_FIELD_WIDTH];
String s(buff, sizeof(buff));
if (info->found)
@@ -878,7 +909,7 @@ int collect_longlong(longlong *element,
element_count count __attribute__((unused)),
TREE_INFO *info)
{
- char buff[255];
+ char buff[MAX_FIELD_WIDTH];
String s(buff, sizeof(buff));
if (info->found)
@@ -897,7 +928,7 @@ int collect_ulonglong(ulonglong *element,
element_count count __attribute__((unused)),
TREE_INFO *info)
{
- char buff[255];
+ char buff[MAX_FIELD_WIDTH];
String s(buff, sizeof(buff));
if (info->found)
diff --git a/sql/sql_analyse.h b/sql/sql_analyse.h
index ce5c0af6a96..1c60d0c150f 100644
--- a/sql/sql_analyse.h
+++ b/sql/sql_analyse.h
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -21,8 +21,6 @@
#pragma interface /* gcc class implementation */
#endif
-#include <my_tree.h>
-
#define DEC_IN_AVG 4
typedef struct st_number_info
@@ -53,8 +51,14 @@ uint check_ulonglong(const char *str, uint length);
bool get_ev_num_info(EV_NUM_INFO *ev_info, NUM_INFO *info, const char *num);
bool test_if_number(NUM_INFO *info, const char *str, uint str_len);
int compare_double(const double *s, const double *t);
+int compare_double2(void* cmp_arg __attribute__((unused)),
+ const double *s, const double *t);
int compare_longlong(const longlong *s, const longlong *t);
+int compare_longlong2(void* cmp_arg __attribute__((unused)),
+ const longlong *s, const longlong *t);
int compare_ulonglong(const ulonglong *s, const ulonglong *t);
+int compare_ulonglong2(void* cmp_arg __attribute__((unused)),
+ const ulonglong *s, const ulonglong *t);
Procedure *proc_analyse_init(THD *thd, ORDER *param, select_result *result,
List<Item> &field_list);
void free_string(String*);
@@ -91,6 +95,11 @@ public:
int collect_string(String *element, element_count count,
TREE_INFO *info);
+int sortcmp2(void* cmp_arg __attribute__((unused)),
+ const String *a,const String *b);
+int stringcmp2(void* cmp_arg __attribute__((unused)),
+ const String *a,const String *b);
+
class field_str :public field_info
{
String min_arg, max_arg;
@@ -105,9 +114,9 @@ public:
max_arg(""), sum(0),
must_be_blob(0), was_zero_fill(0),
was_maybe_zerofill(0), can_be_still_num(1)
- { init_tree(&tree, 0, sizeof(String), a->binary ?
- (qsort_cmp) stringcmp : (qsort_cmp) sortcmp,
- 0, (void (*)(void*)) free_string); };
+ { init_tree(&tree, 0, 0, sizeof(String), a->binary ?
+ (qsort_cmp2) stringcmp2 : (qsort_cmp2) sortcmp2,
+ 0, (tree_element_free) free_string, NULL); };
void add();
void get_opt_type(String*, ha_rows);
@@ -145,8 +154,8 @@ class field_real: public field_info
public:
field_real(Item* a, analyse* b) :field_info(a,b),
min_arg(0), max_arg(0), sum(0), sum_sqr(0), max_notzero_dec_len(0)
- { init_tree(&tree, 0, sizeof(double),
- (qsort_cmp) compare_double, 0, NULL); }
+ { init_tree(&tree, 0, 0, sizeof(double),
+ (qsort_cmp2) compare_double2, 0, NULL, NULL); }
void add();
void get_opt_type(String*, ha_rows);
@@ -191,8 +200,8 @@ class field_longlong: public field_info
public:
field_longlong(Item* a, analyse* b) :field_info(a,b),
min_arg(0), max_arg(0), sum(0), sum_sqr(0)
- { init_tree(&tree, 0, sizeof(longlong),
- (qsort_cmp) compare_longlong, 0, NULL); }
+ { init_tree(&tree, 0, 0, sizeof(longlong),
+ (qsort_cmp2) compare_longlong2, 0, NULL, NULL); }
void add();
void get_opt_type(String*, ha_rows);
@@ -236,8 +245,8 @@ class field_ulonglong: public field_info
public:
field_ulonglong(Item* a, analyse * b) :field_info(a,b),
min_arg(0), max_arg(0), sum(0),sum_sqr(0)
- { init_tree(&tree, 0, sizeof(ulonglong),
- (qsort_cmp) compare_ulonglong, 0, NULL); }
+ { init_tree(&tree, 0, 0, sizeof(ulonglong),
+ (qsort_cmp2) compare_ulonglong2, 0, NULL, NULL); }
void add();
void get_opt_type(String*, ha_rows);
String *get_min_arg(String *s) { s->set(min_arg); return s; }
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 656758623bc..f4a70db2e5d 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -15,7 +15,7 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-/* Basic functions neaded by many modules */
+/* Basic functions needed by many modules */
#include "mysql_priv.h"
#include "sql_acl.h"
@@ -34,8 +34,6 @@ HASH open_cache; /* Used by mysql_test */
static int open_unireg_entry(THD *thd,TABLE *entry,const char *db,
const char *name, const char *alias, bool locked);
-static bool insert_fields(THD *thd,TABLE_LIST *tables, const char *db_name,
- const char *table_name, List_iterator<Item> *it);
static void free_cache_entry(TABLE *entry);
static void mysql_rm_tmp_tables(void);
static key_map get_key_map_from_key_list(TABLE *table,
@@ -111,75 +109,73 @@ static void check_unused(void)
#define check_unused()
#endif
-int list_open_tables(THD *thd,List<char> *tables, const char *db,
- const char *wild)
+OPEN_TABLE_LIST *list_open_tables(THD *thd, const char *wild)
{
int result = 0;
uint col_access=thd->col_access;
+ OPEN_TABLE_LIST **start_list, *open_list;
TABLE_LIST table_list;
+ char name[NAME_LEN*2];
DBUG_ENTER("list_open_tables");
+
VOID(pthread_mutex_lock(&LOCK_open));
bzero((char*) &table_list,sizeof(table_list));
+ start_list= &open_list;
+ open_list=0;
- for (uint idx=0 ; idx < open_cache.records; idx++)
+ for (uint idx=0 ; result == 0 && idx < open_cache.records; idx++)
{
+ OPEN_TABLE_LIST *table;
TABLE *entry=(TABLE*) hash_element(&open_cache,idx);
- if ((!entry->real_name) || strcmp(entry->table_cache_key,db))
- continue;
- if (wild && wild[0] && wild_compare(entry->real_name,wild))
- continue;
- if (db && !(col_access & TABLE_ACLS))
+
+ if ((!entry->real_name))
+ continue; // Shouldn't happen
+ if (wild)
{
- table_list.db= (char*) db;
- table_list.real_name= entry->real_name;/*real name*/
- table_list.grant.privilege=col_access;
- if (check_grant(thd,TABLE_ACLS,&table_list,1,1))
- continue;
+ strxmov(name,entry->table_cache_key,".",entry->real_name,NullS);
+ if (wild_compare(name,wild))
+ continue;
}
- /* need to check if he have't already listed it */
- List_iterator<char> it(*tables);
- char *table_name;
- int check = 0;
- while (check == 0 && (table_name=it++))
+ /* Check if user has SELECT privilege for any column in the table */
+ table_list.db= (char*) entry->table_cache_key;
+ table_list.real_name= entry->real_name;
+ table_list.grant.privilege=0;
+ if (check_table_access(thd,SELECT_ACL | EXTRA_ACL,&table_list))
+ continue;
+
+ /* need to check if we haven't already listed it */
+ for (table= open_list ; table ; table=table->next)
{
- if (!strcmp(table_name,entry->real_name))
- check++;
+ if (!strcmp(table->table,entry->real_name) &&
+ !strcmp(table->db,entry->table_cache_key))
+ {
+ if (entry->in_use)
+ table->in_use++;
+ if (entry->locked_by_name)
+ table->locked++;
+ break;
+ }
}
- if (check)
+ if (table)
continue;
-
- if (tables->push_back(thd->strdup(entry->real_name)))
+ if (!(*start_list = (OPEN_TABLE_LIST *)
+ sql_alloc(sizeof(**start_list)+entry->key_length)))
{
- result = -1;
+ open_list=0; // Out of memory
break;
}
+ strmov((*start_list)->table=
+ strmov(((*start_list)->db= (char*) ((*start_list)+1)),
+ entry->table_cache_key)+1,
+ entry->real_name);
+ (*start_list)->in_use= entry->in_use ? 1 : 0;
+ (*start_list)->locked= entry->locked_by_name ? 1 : 0;
+ start_list= &(*start_list)->next;
+ *start_list=0;
}
-
VOID(pthread_mutex_unlock(&LOCK_open));
- DBUG_RETURN(result);
-}
-
-char*
-query_table_status(THD *thd,const char *db,const char *table_name)
-{
- int cached = 0, in_use = 0;
- char info[256];
-
- for (uint idx=0 ; idx < open_cache.records; idx++)
- {
- TABLE *entry=(TABLE*) hash_element(&open_cache,idx);
- if (strcmp(entry->table_cache_key,db) ||
- strcmp(entry->real_name,table_name))
- continue;
-
- cached++;
- if (entry->in_use)
- in_use++;
- }
-
- sprintf(info, "cached=%d, in_use=%d", cached, in_use);
- return thd->strdup(info);
+ DBUG_RETURN(open_list);
}
@@ -195,7 +191,7 @@ query_table_status(THD *thd,const char *db,const char *table_name)
bool
send_fields(THD *thd,List<Item> &list,uint flag)
{
- List_iterator<Item> it(list);
+ List_iterator_fast<Item> it(list);
Item *item;
char buff[80];
CONVERT *convert= (flag & 4) ? (CONVERT*) 0 : thd->convert_set;
@@ -259,7 +255,7 @@ send_fields(THD *thd,List<Item> &list,uint flag)
if (my_net_write(&thd->net, (char*) packet->ptr(),packet->length()))
break; /* purecov: inspected */
}
- send_eof(&thd->net,(test_flags & TEST_MIT_THREAD) ? 0: 1);
+ send_eof(&thd->net);
return 0;
err:
send_error(&thd->net,ER_OUT_OF_RESOURCES); /* purecov: inspected */
@@ -304,6 +300,7 @@ static void free_cache_entry(TABLE *table)
void free_io_cache(TABLE *table)
{
+ DBUG_ENTER("free_io_cache");
if (table->io_cache)
{
close_cached_file(table->io_cache);
@@ -315,6 +312,7 @@ void free_io_cache(TABLE *table)
my_free((gptr) table->record_pointers,MYF(0));
table->record_pointers=0;
}
+ DBUG_VOID_RETURN;
}
/* Close all tables which aren't in use by any thread */
@@ -418,7 +416,6 @@ void close_thread_tables(THD *thd, bool locked)
DBUG_VOID_RETURN; // LOCK TABLES in use
}
- TABLE *table,*next;
bool found_old_table=0;
if (thd->lock)
@@ -431,40 +428,9 @@ void close_thread_tables(THD *thd, bool locked)
DBUG_PRINT("info", ("thd->open_tables=%p", thd->open_tables));
- for (table=thd->open_tables ; table ; table=next)
- {
- next=table->next;
- if (table->version != refresh_version ||
- thd->version != refresh_version || !table->db_stat)
- {
- VOID(hash_delete(&open_cache,(byte*) table));
- found_old_table=1;
- }
- else
- {
- if (table->flush_version != flush_version)
- {
- table->flush_version=flush_version;
- table->file->extra(HA_EXTRA_FLUSH);
- }
- else
- {
- // Free memory and reset for next loop
- table->file->extra(HA_EXTRA_RESET);
- }
- table->in_use=0;
- if (unused_tables)
- {
- table->next=unused_tables; /* Link in last */
- table->prev=unused_tables->prev;
- unused_tables->prev=table;
- table->prev->next=table;
- }
- else
- unused_tables=table->next=table->prev=table;
- }
- }
- thd->open_tables=0;
+ while (thd->open_tables)
+ found_old_table|=close_thread_table(thd, &thd->open_tables);
+
/* Free tables to hold down open files */
while (open_cache.records > table_cache_size && unused_tables)
VOID(hash_delete(&open_cache,(byte*) unused_tables)); /* purecov: tested */
@@ -480,6 +446,48 @@ void close_thread_tables(THD *thd, bool locked)
DBUG_VOID_RETURN;
}
+/* move one table to free list */
+
+bool close_thread_table(THD *thd, TABLE **table_ptr)
+{
+ DBUG_ENTER("close_thread_table");
+
+ bool found_old_table=0;
+ TABLE *table=*table_ptr;
+
+ *table_ptr=table->next;
+ if (table->version != refresh_version ||
+ thd->version != refresh_version || !table->db_stat)
+ {
+ VOID(hash_delete(&open_cache,(byte*) table));
+ found_old_table=1;
+ }
+ else
+ {
+ if (table->flush_version != flush_version)
+ {
+ table->flush_version=flush_version;
+ table->file->extra(HA_EXTRA_FLUSH);
+ }
+ else
+ {
+ // Free memory and reset for next loop
+ table->file->extra(HA_EXTRA_RESET);
+ }
+ table->in_use=0;
+ if (unused_tables)
+ {
+ table->next=unused_tables; /* Link in last */
+ table->prev=unused_tables->prev;
+ unused_tables->prev=table;
+ table->prev->next=table;
+ }
+ else
+ unused_tables=table->next=table->prev=table;
+ }
+ DBUG_RETURN(found_old_table);
+}
+
/* Close and delete temporary tables */
void close_temporary(TABLE *table,bool delete_table)
@@ -504,7 +512,7 @@ void close_temporary_tables(THD *thd)
const uint init_query_buf_size = 11; // "drop table "
uint query_buf_size;
bool found_user_tables = 0;
-
+
LINT_INIT(end);
query_buf_size = init_query_buf_size;
@@ -581,7 +589,7 @@ bool close_temporary_table(THD *thd, const char *db, const char *table_name)
table= *prev;
*prev= table->next;
close_temporary(table);
- if(thd->slave_thread)
+ if (thd->slave_thread)
--slave_open_temp_tables;
return 0;
}
@@ -604,8 +612,6 @@ bool rename_temporary_table(THD* thd, TABLE *table, const char *db,
}
-
-
/* move table first in unused links */
static void relink_unused(TABLE *table)
@@ -689,7 +695,7 @@ TABLE *reopen_name_locked_table(THD* thd, TABLE_LIST* table_list)
if (thd->killed)
DBUG_RETURN(0);
TABLE* table;
- if(!(table = table_list->table))
+ if (!(table = table_list->table))
DBUG_RETURN(0);
char* db = thd->db ? thd->db : table_list->db;
@@ -702,11 +708,11 @@ TABLE *reopen_name_locked_table(THD* thd, TABLE_LIST* table_list)
if (open_unireg_entry(thd, table, db, table_name, table_name, 1) ||
!(table->table_cache_key =memdup_root(&table->mem_root,(char*) key,
key_length)))
- {
- closefrm(table);
- pthread_mutex_unlock(&LOCK_open);
- DBUG_RETURN(0);
- }
+ {
+ closefrm(table);
+ pthread_mutex_unlock(&LOCK_open);
+ DBUG_RETURN(0);
+ }
table->key_length=key_length;
table->version=0;
@@ -836,25 +842,6 @@ TABLE *open_table(THD *thd,const char *db,const char *table_name,
!(table->table_cache_key=memdup_root(&table->mem_root,(char*) key,
key_length)))
{
- MEM_ROOT* glob_alloc;
- LINT_INIT(glob_alloc);
-
- if (errno == ENOENT &&
- (glob_alloc = my_pthread_getspecific_ptr(MEM_ROOT*,THR_MALLOC)))
- // Sasha: needed for replication
- // remember the name of the non-existent table
- // so we can try to download it from the master
- {
- int table_name_len = (uint) strlen(table_name);
- int db_len = (uint) strlen(db);
- thd->last_nx_db = alloc_root(glob_alloc,db_len + table_name_len + 2);
- if(thd->last_nx_db)
- {
- thd->last_nx_table = thd->last_nx_db + db_len + 1;
- memcpy(thd->last_nx_table, table_name, table_name_len + 1);
- memcpy(thd->last_nx_db, db, db_len + 1);
- }
- }
table->next=table->prev=table;
free_cache_entry(table);
VOID(pthread_mutex_unlock(&LOCK_open));
@@ -895,7 +882,7 @@ TABLE *open_table(THD *thd,const char *db,const char *table_name,
table->outer_join=table->null_row=table->maybe_null=0;
table->status=STATUS_NO_RECORD;
table->keys_in_use_for_query=table->used_keys= table->keys_in_use;
- dbug_assert(table->key_read == 0);
+ DBUG_ASSERT(table->key_read == 0);
DBUG_RETURN(table);
}
@@ -1179,7 +1166,7 @@ bool wait_for_tables(THD *thd)
/* Now we can open all tables without any interference */
thd->proc_info="Reopen tables";
result=reopen_tables(thd,0,0);
-
+
}
pthread_mutex_unlock(&LOCK_open);
thd->proc_info=0;
@@ -1314,7 +1301,6 @@ static int open_unireg_entry(THD *thd, TABLE *entry, const char *db,
if (error)
goto err;
}
- (void) entry->file->extra(HA_EXTRA_NO_READCHECK); // Not needed in SQL
DBUG_RETURN(0);
err:
DBUG_RETURN(1);
@@ -1337,7 +1323,7 @@ int open_tables(THD *thd,TABLE_LIST *start)
{
if (!tables->table &&
!(tables->table=open_table(thd,
- tables->db ? tables->db : thd->db,
+ tables->db,
tables->real_name,
tables->name, &refresh)))
{
@@ -1394,7 +1380,7 @@ TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type lock_type)
DBUG_ENTER("open_ltable");
thd->proc_info="Opening table";
- while (!(table=open_table(thd,table_list->db ? table_list->db : thd->db,
+ while (!(table=open_table(thd,table_list->db,
table_list->real_name,table_list->name,
&refresh)) && refresh) ;
if (table)
@@ -1403,11 +1389,7 @@ TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type lock_type)
#if defined( __WIN__) || defined(OS2)
/* Win32 can't drop a file that is open */
- if (lock_type == TL_WRITE_ALLOW_READ
-#ifdef HAVE_GEMINI_DB
- && table->db_type != DB_TYPE_GEMINI
-#endif /* HAVE_GEMINI_DB */
- )
+ if (lock_type == TL_WRITE_ALLOW_READ)
{
lock_type= TL_WRITE;
}
@@ -1516,7 +1498,6 @@ TABLE *open_temporary_table(THD *thd, const char *path, const char *db,
DBUG_RETURN(0);
}
- tmp_table->file->extra(HA_EXTRA_NO_READCHECK); // Not needed in SQL
tmp_table->reginfo.lock_type=TL_WRITE; // Simulate locked
tmp_table->tmp_table = (tmp_table->file->has_transactions() ?
TRANSACTIONAL_TMP_TABLE : TMP_TABLE);
@@ -1533,8 +1514,8 @@ TABLE *open_temporary_table(THD *thd, const char *path, const char *db,
{
tmp_table->next=thd->temporary_tables;
thd->temporary_tables=tmp_table;
- if(thd->slave_thread)
- ++slave_open_temp_tables;
+ if (thd->slave_thread)
+ slave_open_temp_tables++;
}
DBUG_RETURN(tmp_table);
}
@@ -1594,18 +1575,13 @@ Field *find_field_in_table(THD *thd,TABLE *table,const char *name,uint length,
{
field->query_id=thd->query_id;
table->used_fields++;
- if (field->part_of_key)
- {
- if (!(field->part_of_key & table->ref_primary_key))
- table->used_keys&=field->part_of_key;
- }
- else
- table->used_keys=0;
+ table->used_keys&=field->part_of_key;
}
else
thd->dupp_field=field;
}
- if (check_grants && !thd->master_access && check_grant_column(thd,table,name,length))
+ if (check_grants && !thd->master_access &&
+ check_grant_column(thd,table,name,length))
return WRONG_GRANT;
return field;
}
@@ -1626,9 +1602,7 @@ find_field_in_tables(THD *thd,Item_field *item,TABLE_LIST *tables)
for (; tables ; tables=tables->next)
{
if (!strcmp(tables->name,table_name) &&
- (!db ||
- (tables->db && !strcmp(db,tables->db)) ||
- (!tables->db && !strcmp(db,thd->db))))
+ (!db || !strcmp(db,tables->db)))
{
found_table=1;
Field *find=find_field_in_table(thd,tables->table,name,length,
@@ -1671,7 +1645,8 @@ find_field_in_tables(THD *thd,Item_field *item,TABLE_LIST *tables)
for (; tables ; tables=tables->next)
{
Field *field=find_field_in_table(thd,tables->table,name,length,
- grant_option && !thd->master_access, allow_rowid);
+ grant_option &&
+ !thd->master_access, allow_rowid);
if (field)
{
if (field == WRONG_GRANT)
@@ -1752,14 +1727,15 @@ find_item_in_list(Item *find,List<Item> &items)
****************************************************************************/
int setup_fields(THD *thd, TABLE_LIST *tables, List<Item> &fields,
- bool set_query_id, List<Item> *sum_func_list)
+ bool set_query_id, List<Item> *sum_func_list,
+ bool allow_sum_func)
{
reg2 Item *item;
List_iterator<Item> it(fields);
DBUG_ENTER("setup_fields");
thd->set_query_id=set_query_id;
- thd->allow_sum_func= test(sum_func_list);
+ thd->allow_sum_func= allow_sum_func;
thd->where="field list";
while ((item=it++))
@@ -1775,7 +1751,8 @@ int setup_fields(THD *thd, TABLE_LIST *tables, List<Item> &fields,
{
if (item->fix_fields(thd,tables))
DBUG_RETURN(-1); /* purecov: inspected */
- if (item->with_sum_func && item->type() != Item::SUM_FUNC_ITEM)
+ if (item->with_sum_func && item->type() != Item::SUM_FUNC_ITEM &&
+ sum_func_list)
item->split_sum_func(*sum_func_list);
thd->used_tables|=item->used_tables();
}
@@ -1794,27 +1771,40 @@ bool setup_tables(TABLE_LIST *tables)
{
DBUG_ENTER("setup_tables");
uint tablenr=0;
- for (TABLE_LIST *table=tables ; table ; table=table->next,tablenr++)
- {
- table->table->tablenr=tablenr;
- table->table->map= (table_map) 1 << tablenr;
- if ((table->table->outer_join=table->outer_join))
- table->table->maybe_null=1; // LEFT OUTER JOIN ...
- if (table->use_index)
+ for (TABLE_LIST *table_list=tables ; table_list ;
+ table_list=table_list->next,tablenr++)
+ {
+ TABLE *table=table_list->table;
+
+ table->used_fields=0;
+ table->const_table=0;
+ table->outer_join=table->null_row=0;
+ table->status=STATUS_NO_RECORD;
+ table->keys_in_use_for_query=table->used_keys= table->keys_in_use;
+ table->maybe_null=test(table->outer_join=table_list->outer_join);
+ table->tablenr=tablenr;
+ table->map= (table_map) 1 << tablenr;
+ if (table_list->use_index)
{
- key_map map= get_key_map_from_key_list(table->table,
- table->use_index);
+ key_map map= get_key_map_from_key_list(table,
+ table_list->use_index);
if (map == ~(key_map) 0)
DBUG_RETURN(1);
- table->table->keys_in_use_for_query=map;
+ table->keys_in_use_for_query=map;
}
- if (table->ignore_index)
+ if (table_list->ignore_index)
{
- key_map map= get_key_map_from_key_list(table->table,
- table->ignore_index);
+ key_map map= get_key_map_from_key_list(table,
+ table_list->ignore_index);
if (map == ~(key_map) 0)
DBUG_RETURN(1);
- table->table->keys_in_use_for_query &= ~map;
+ table->keys_in_use_for_query &= ~map;
+ }
+ if (table_list->shared)
+ {
+ /* Clear query_id that may have been set by previous select */
+ for (Field **ptr=table->field ; *ptr ; ptr++)
+ (*ptr)->query_id=0;
}
}
if (tablenr > MAX_TABLES)
@@ -1830,7 +1820,7 @@ static key_map get_key_map_from_key_list(TABLE *table,
List<String> *index_list)
{
key_map map=0;
- List_iterator<String> it(*index_list);
+ List_iterator_fast<String> it(*index_list);
String *name;
uint pos;
while ((name=it++))
@@ -1851,7 +1841,7 @@ static key_map get_key_map_from_key_list(TABLE *table,
** Returns pointer to last inserted field if ok
****************************************************************************/
-static bool
+bool
insert_fields(THD *thd,TABLE_LIST *tables, const char *db_name,
const char *table_name, List_iterator<Item> *it)
{
@@ -1866,8 +1856,7 @@ insert_fields(THD *thd,TABLE_LIST *tables, const char *db_name,
check_grant_all_columns(thd,SELECT_ACL,table) )
DBUG_RETURN(-1);
if (!table_name || (!strcmp(table_name,tables->name) &&
- (!db_name || !tables->db ||
- !strcmp(tables->db,db_name))))
+ (!db_name || !strcmp(tables->db,db_name))))
{
Field **ptr=table->field,*field;
thd->used_tables|=table->map;
@@ -1881,14 +1870,7 @@ insert_fields(THD *thd,TABLE_LIST *tables, const char *db_name,
if (field->query_id == thd->query_id)
thd->dupp_field=field;
field->query_id=thd->query_id;
-
- if (field->part_of_key)
- {
- if (!(field->part_of_key & table->ref_primary_key))
- table->used_keys&=field->part_of_key;
- }
- else
- table->used_keys=0;
+ table->used_keys&=field->part_of_key;
}
/* All fields are used */
table->used_fields=table->fields;
@@ -1956,7 +1938,6 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
// TODO: This could be optimized to use hashed names if t2 had a hash
for (j=0 ; j < t2->fields ; j++)
{
- key_map tmp_map;
if (!my_strcasecmp(t1->field[i]->field_name,
t2->field[j]->field_name))
{
@@ -1969,20 +1950,8 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
/* Mark field used for table cache */
t1->field[i]->query_id=t2->field[j]->query_id=thd->query_id;
cond_and->list.push_back(tmp);
- if ((tmp_map=t1->field[i]->part_of_key))
- {
- if (!(tmp_map & t1->ref_primary_key))
- t1->used_keys&=tmp_map;
- }
- else
- t1->used_keys=0;
- if ((tmp_map=t2->field[j]->part_of_key))
- {
- if (!(tmp_map & t2->ref_primary_key))
- t2->used_keys&=tmp_map;
- }
- else
- t2->used_keys=0;
+ t1->used_keys&= t1->field[i]->part_of_key;
+ t2->used_keys&= t2->field[j]->part_of_key;
break;
}
}
@@ -2010,7 +1979,7 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
int
fill_record(List<Item> &fields,List<Item> &values)
{
- List_iterator<Item> f(fields),v(values);
+ List_iterator_fast<Item> f(fields),v(values);
Item *value;
Item_field *field;
DBUG_ENTER("fill_record");
@@ -2028,7 +1997,7 @@ fill_record(List<Item> &fields,List<Item> &values)
int
fill_record(Field **ptr,List<Item> &values)
{
- List_iterator<Item> v(values);
+ List_iterator_fast<Item> v(values);
Item *value;
DBUG_ENTER("fill_record");
@@ -2091,7 +2060,8 @@ int mysql_create_index(THD *thd, TABLE_LIST *table_list, List<Key> &keys)
create_info.db_type=DB_TYPE_DEFAULT;
DBUG_RETURN(mysql_alter_table(thd,table_list->db,table_list->real_name,
&create_info, table_list,
- fields, keys, drop, alter, (ORDER*)0, FALSE, DUP_ERROR));
+ fields, keys, drop, alter, (ORDER*)0, FALSE,
+ DUP_ERROR));
}
@@ -2106,7 +2076,8 @@ int mysql_drop_index(THD *thd, TABLE_LIST *table_list, List<Alter_drop> &drop)
create_info.db_type=DB_TYPE_DEFAULT;
DBUG_RETURN(mysql_alter_table(thd,table_list->db,table_list->real_name,
&create_info, table_list,
- fields, keys, drop, alter, (ORDER*)0, FALSE, DUP_ERROR));
+ fields, keys, drop, alter, (ORDER*)0, FALSE,
+ DUP_ERROR));
}
/*****************************************************************************
@@ -2171,7 +2142,10 @@ bool remove_table_from_cache(THD *thd, const char *db, const char *table_name,
THD *in_use;
table->version=0L; /* Free when thread is ready */
if (!(in_use=table->in_use))
+ {
+ DBUG_PRINT("info",("Table was not in use"));
relink_unused(table);
+ }
else if (in_use != thd)
{
in_use->some_tables_deleted=1;
@@ -2201,8 +2175,8 @@ bool remove_table_from_cache(THD *thd, const char *db, const char *table_name,
int setup_ftfuncs(THD *thd)
{
- List_iterator<Item_func_match> li(thd->lex.ftfunc_list),
- lj(thd->lex.ftfunc_list);
+ List_iterator<Item_func_match> li(thd->lex.select_lex.ftfunc_list),
+ lj(thd->lex.select_lex.ftfunc_list);
Item_func_match *ftf, *ftf2;
while ((ftf=li++))
@@ -2222,16 +2196,17 @@ int setup_ftfuncs(THD *thd)
int init_ftfuncs(THD *thd, bool no_order)
{
- List_iterator<Item_func_match> li(thd->lex.ftfunc_list);
- Item_func_match *ifm;
- DBUG_PRINT("info",("Performing FULLTEXT search"));
- thd->proc_info="FULLTEXT initialization";
-
- while ((ifm=li++))
+ if (thd->lex.select_lex.ftfunc_list.elements)
{
- ifm->init_search(no_order);
- }
+ List_iterator<Item_func_match> li(thd->lex.select_lex.ftfunc_list);
+ Item_func_match *ifm;
+ DBUG_PRINT("info",("Performing FULLTEXT search"));
+ thd->proc_info="FULLTEXT initialization";
+ while ((ifm=li++))
+ {
+ ifm->init_search(no_order);
+ }
+ }
return 0;
}
-
diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc
index 09d436c0c9c..c5ebeead05a 100644
--- a/sql/sql_cache.cc
+++ b/sql/sql_cache.cc
@@ -1,98 +1,3448 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+/* Copyright (C) 2000 MySQL AB
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+/*
+ Description of the query cache:
+
+1. Query_cache object consists of
+ - query cache memory pool (cache)
+ - queries hash (queries)
+ - tables hash (tables)
+ - list of blocks ordered as they allocated in memory
+(first_block)
+ - list of queries block (queries_blocks)
+ - list of used tables (tables_blocks)
+
+2. Query cache memory pool (cache) consists of
+ - table of steps of memory bins allocation
+ - table of free memory bins
+ - blocks of memory
+
+3. Memory blocks
+
+Every memory block has the following structure:
+
++----------------------------------------------------------+
+| Block header (Query_cache_block structure) |
++----------------------------------------------------------+
+|Table of database table lists (used for queries & tables) |
++----------------------------------------------------------+
+| Type depended header |
+|(Query_cache_query, Query_cache_table, Query_cache_result)|
++----------------------------------------------------------+
+| Data ... |
++----------------------------------------------------------+
+
+Block header consists of:
+- type:
+ FREE Free memory block
+ QUERY Query block
+ RESULT Ready to send result
+ RES_CONT Result's continuation
+ RES_BEG First block of results, that is not yet complete,
+ written to cache
+ RES_INCOMPLETE Allocated for results data block
+ TABLE Block with database table description
+ INCOMPLETE The destroyed block
+- length of block (length)
+- length of data & headers (used)
+- physical list links (pnext/pprev) - used for the list of
+ blocks ordered as they are allocated in physical memory
+- logical list links (next/prev) - used for queries block list, tables block
+ list, free memory block lists and list of results block in query
+- number of elements in table of database table list (n_tables)
+
+4. Query & results blocks
+
+Query stored in cache consists of following blocks:
+
+more more
+recent+-------------+ old
+<-----|Query block 1|------> double linked list of queries block
+ prev | | next
+ +-------------+
+ <-| table 0 |-> (see "Table of database table lists" description)
+ <-| table 1 |->
+ | ... | +--------------------------+
+ +-------------+ +-------------------------+ |
+NET | | | V V |
+struct| | +-+------------+ +------------+ |
+<-----|query header |----->|Result block|-->|Result block|-+ doublelinked
+writer| |result| |<--| | list of results
+ +-------------+ +------------+ +------------+
+ |charset | +------------+ +------------+ no table of dbtables
+ |encoding + | | result | | result |
+ |query text |<-----| header | | header |------+
+ +-------------+parent| | | |parent|
+ ^ +------------+ +------------+ |
+ | |result data | |result data | |
+ | +------------+ +------------+ |
+ +---------------------------------------------------+
+
+First query is registered. During the registration query block is
+allocated. This query block is included in query hash and is linked
+with appropriate database tables lists (if there is no appropriate
+list exists it will be created).
+
+Later when query has performed results is written into the result blocks.
+A result block cannot be smaller then QUERY_CACHE_MIN_RESULT_DATA_SIZE.
+
+When new result is written to cache it is appended to the last result
+block, if no more free space left in the last block, new block is
+allocated.
+
+5. Table of database table lists.
+
+For quick invalidation of queries all query are linked in lists on used
+database tables basis (when table will be changed (insert/delete/...)
+this queries will be removed from cache).
+
+Root of such list is table block:
+
+ +------------+ list of used tables (used while invalidation of
+<----| Table |-----> whole database)
+ prev| block |next +-----------+
+ | | +-----------+ |Query block|
+ | | |Query block| +-----------+
+ +------------+ +-----------+ | ... |
+ +->| table 0 |------>|table 0 |----->| table N |---+
+ |+-| |<------| |<-----| |<-+|
+ || +------------+ | ... | | ... | ||
+ || |table header| +-----------+ +-----------+ ||
+ || +------------+ | ... | | ... | ||
+ || |db name + | +-----------+ +-----------+ ||
+ || |table name | ||
+ || +------------+ ||
+ |+--------------------------------------------------------+|
+ +----------------------------------------------------------+
+
+Table block is included into the tables hash (tables).
+
+6. Free blocks, free blocks bins & steps of freeblock bins.
+
+When we just started only one free memory block existed. All query
+cache memory (that will be used for block allocation) were
+containing in this block.
+When a new block is allocated we find most suitable memory block
+(minimal of >= required size). If such a block can not be found, we try
+to find max block < required size (if we allocate block for results).
+If there is no free memory, oldest query is removed from cache, and then
+we try to allocate memory. Last step should be repeated until we find
+suitable block or until there is no unlocked query found.
+
+If the block is found and its length more then we need, it should be
+split into 2 blocks.
+New blocks cannot be smaller then min_allocation_unit_bytes.
+
+When a block becomes free, its neighbor-blocks should be tested and if
+there are free blocks among them, they should be joined into one block.
+
+Free memory blocks are stored in bins according to their sizes.
+The bins are stored in size-descending order.
+These bins are distributed (by size) approximately logarithmically.
+
+First bin (number 0) stores free blocks with
+size <= query_cache_size>>QUERY_CACHE_MEM_BIN_FIRST_STEP_PWR2.
+It is first (number 0) step.
+On the next step distributed (1 + QUERY_CACHE_MEM_BIN_PARTS_INC) *
+QUERY_CACHE_MEM_BIN_PARTS_MUL bins. This bins allocated in interval from
+query_cache_size>>QUERY_CACHE_MEM_BIN_FIRST_STEP_PWR2 to
+query_cache_size>>QUERY_CACHE_MEM_BIN_FIRST_STEP_PWR2 >>
+QUERY_CACHE_MEM_BIN_STEP_PWR2
+...
+On each step interval decreases in 2 power of
+QUERY_CACHE_MEM_BIN_STEP_PWR2
+times, number of bins (that distributed on this step) increases. If on
+the previous step there were N bins distributed , on the current there
+would be distributed
+(N + QUERY_CACHE_MEM_BIN_PARTS_INC) * QUERY_CACHE_MEM_BIN_PARTS_MUL
+bins.
+Last distributed bin stores blocks with size near min_allocation_unit
+bytes.
+
+For example:
+ query_cache_size>>QUERY_CACHE_MEM_BIN_FIRST_STEP_PWR2 = 100,
+ min_allocation_unit = 17,
+ QUERY_CACHE_MEM_BIN_STEP_PWR2 = 1,
+ QUERY_CACHE_MEM_BIN_PARTS_INC = 1,
+ QUERY_CACHE_MEM_BIN_PARTS_MUL = 1
+ (in followed picture showed right (low) bound of bin):
+
+ | 100>>1 50>>1 |25>>1|
+ | | | | | |
+ | 100 75 50 41 33 25 21 18 15| 12 | - bins right (low) bounds
+
+ |\---/\-----/\--------/\--------|---/ |
+ | 0 1 2 3 | | - steps
+ \-----------------------------/ \---/
+ bins that we store in cache this bin showed for example only
+
+
+Calculation of steps/bins distribution is performed only when query cache
+is resized.
+
+When we need to find appropriate bin, first we should find appropriate
+step, then we should calculate number of bins that are using data
+stored in Query_cache_memory_bin_step structure.
+
+Free memory blocks are sorted in bins in lists with size-ascending order
+(more small blocks needed frequently then bigger one).
+
+7. Packing cache.
+
+Query cache packing is divided into two operation:
+ - pack_cache
+ - join_results
+
+pack_cache moved all blocks to "top" of cache and create one block of free
+space at the "bottom":
+
+ before pack_cache after pack_cache
+ +-------------+ +-------------+
+ | query 1 | | query 1 |
+ +-------------+ +-------------+
+ | table 1 | | table 1 |
+ +-------------+ +-------------+
+ | results 1.1 | | results 1.1 |
+ +-------------+ +-------------+
+ | free | | query 2 |
+ +-------------+ +-------------+
+ | query 2 | | table 2 |
+ +-------------+ ---> +-------------+
+ | table 2 | | results 1.2 |
+ +-------------+ +-------------+
+ | results 1.2 | | results 2 |
+ +-------------+ +-------------+
+ | free | | free |
+ +-------------+ | |
+ | results 2 | | |
+ +-------------+ | |
+ | free | | |
+ +-------------+ +-------------+
+
+pack_cache scan blocks in physical address order and move every non-free
+block "higher".
+
+pack_cach remove every free block it finds. The length of the deleted block
+is accumulated to the "gap". All non free blocks should be shifted with the
+"gap" step.
+
+join_results scans all complete queries. If the results of query are not
+stored in the same block, join_results tries to move results so, that they
+are stored in one block.
+
+ before join_results after join_results
+ +-------------+ +-------------+
+ | query 1 | | query 1 |
+ +-------------+ +-------------+
+ | table 1 | | table 1 |
+ +-------------+ +-------------+
+ | results 1.1 | | free |
+ +-------------+ +-------------+
+ | query 2 | | query 2 |
+ +-------------+ +-------------+
+ | table 2 | | table 2 |
+ +-------------+ ---> +-------------+
+ | results 1.2 | | free |
+ +-------------+ +-------------+
+ | results 2 | | results 2 |
+ +-------------+ +-------------+
+ | free | | results 1 |
+ | | | |
+ | | +-------------+
+ | | | free |
+ | | | |
+ +-------------+ +-------------+
+
+If join_results allocated new block(s) then we need call pack_cache again.
+
+TODO list:
+
+ - Invalidate queries that use innoDB tables changed in transaction & remove
+ invalidation by table type
+ - Delayed till after-parsing qache answer (for column rights processing)
+ - Optimize cache resizing
+ - if new_size < old_size then pack & shrink
+ - if new_size > old_size copy cached query to new cache
+ - Move MRG_MYISAM table type processing to handlers, something like:
+ tables_used->table->file->register_used_filenames(callback,
+ first_argument);
+ - In Query_cache::insert_table eliminate strlen(). To do this we have to
+ add db_len to the TABLE_LIST and TABLE structures.
+*/
+
#include "mysql_priv.h"
#include <m_ctype.h>
#include <my_dir.h>
#include <hash.h>
+#include "sql_acl.h"
+#include "ha_myisammrg.h"
+#ifndef MASTER
+#include "../srclib/myisammrg/myrg_def.h"
+#else
+#include "../myisammrg/myrg_def.h"
+#endif
+#include <assert.h>
+
+#if defined(EXTRA_DEBUG) && !defined(DBUG_OFF)
+#define MUTEX_LOCK(M) { DBUG_PRINT("lock", ("mutex lock 0x%lx", (ulong)(M))); \
+ pthread_mutex_lock(M);}
+#define MUTEX_UNLOCK(M) {DBUG_PRINT("lock", ("mutex unlock 0x%lx",\
+ (ulong)(M))); pthread_mutex_unlock(M);}
+#define SEM_LOCK(M) { int val = 0; sem_getvalue (M, &val); \
+ DBUG_PRINT("lock", ("sem lock 0x%lx (%d)", (ulong)(M), val)); \
+ sem_wait(M); DBUG_PRINT("lock", ("sem lock ok")); }
+#define SEM_UNLOCK(M) {DBUG_PRINT("info", ("sem unlock 0x%lx", (ulong)(M))); \
+ sem_post(M); DBUG_PRINT("info", ("sem unlock ok")); }
+#define STRUCT_LOCK(M) {DBUG_PRINT("lock", ("%d struct lock...",__LINE__)); \
+ pthread_mutex_lock(M);DBUG_PRINT("lock", ("struct lock OK"));}
+#define STRUCT_UNLOCK(M) { \
+ DBUG_PRINT("lock", ("%d struct unlock...",__LINE__)); \
+ pthread_mutex_unlock(M);DBUG_PRINT("lock", ("struct unlock OK"));}
+#define BLOCK_LOCK_WR(B) {DBUG_PRINT("lock", ("%d LOCK_WR 0x%lx",\
+ __LINE__,(ulong)(B))); \
+ B->query()->lock_writing();}
+#define BLOCK_LOCK_RD(B) {DBUG_PRINT("lock", ("%d LOCK_RD 0x%lx",\
+ __LINE__,(ulong)(B))); \
+ B->query()->lock_reading();}
+#define BLOCK_UNLOCK_WR(B) { \
+ DBUG_PRINT("lock", ("%d UNLOCK_WR 0x%lx",\
+ __LINE__,(ulong)(B)));B->query()->unlock_writing();}
+#define BLOCK_UNLOCK_RD(B) { \
+ DBUG_PRINT("lock", ("%d UNLOCK_RD 0x%lx",\
+ __LINE__,(ulong)(B)));B->query()->unlock_reading();}
+#define DUMP(C) DBUG_EXECUTE("qcache", {\
+ (C)->cache_dump(); (C)->queries_dump();(C)->tables_dump();})
+#else
+#define MUTEX_LOCK(M) pthread_mutex_lock(M)
+#define MUTEX_UNLOCK(M) pthread_mutex_unlock(M)
+#define SEM_LOCK(M) sem_wait(M)
+#define SEM_UNLOCK(M) sem_post(M)
+#define STRUCT_LOCK(M) pthread_mutex_lock(M)
+#define STRUCT_UNLOCK(M) pthread_mutex_unlock(M)
+#define BLOCK_LOCK_WR(B) B->query()->lock_writing()
+#define BLOCK_LOCK_RD(B) B->query()->lock_reading()
+#define BLOCK_UNLOCK_WR(B) B->query()->unlock_writing()
+#define BLOCK_UNLOCK_RD(B) B->query()->unlock_reading()
+#define DUMP(C)
+#endif
+
+/*****************************************************************************
+ Query_cache_block_table method(s)
+*****************************************************************************/
+
+inline Query_cache_block * Query_cache_block_table::block()
+{
+ return (Query_cache_block *)(((byte*)this) -
+ ALIGN_SIZE(sizeof(Query_cache_block_table)*n) -
+ ALIGN_SIZE(sizeof(Query_cache_block)));
+};
+
+/*****************************************************************************
+ Query_cache_block method(s)
+*****************************************************************************/
+
+void Query_cache_block::init(ulong block_length)
+{
+ DBUG_ENTER("Query_cache_block::init");
+ DBUG_PRINT("qcache", ("init block 0x%lx length: %lu", (ulong) this,
+ block_length));
+ length = block_length;
+ used = 0;
+ type = Query_cache_block::FREE;
+ n_tables = 0;
+ DBUG_VOID_RETURN;
+}
+
+void Query_cache_block::destroy()
+{
+ DBUG_ENTER("Query_cache_block::destroy");
+ DBUG_PRINT("qcache", ("destroy block 0x%lx, type %d",
+ (ulong) this, type));
+ type = INCOMPLETE;
+ DBUG_VOID_RETURN;
+}
+
+inline uint Query_cache_block::headers_len()
+{
+ return (ALIGN_SIZE(sizeof(Query_cache_block_table)*n_tables) +
+ ALIGN_SIZE(sizeof(Query_cache_block)));
+}
+
+inline gptr Query_cache_block::data(void)
+{
+ return (gptr)( ((byte*)this) + headers_len() );
+}
+
+inline Query_cache_query * Query_cache_block::query()
+{
+#ifndef DBUG_OFF
+ if (type != QUERY)
+ query_cache.wreck(__LINE__, "incorrect block type");
+#endif
+ return (Query_cache_query *) data();
+}
+
+inline Query_cache_table * Query_cache_block::table()
+{
+#ifndef DBUG_OFF
+ if (type != TABLE)
+ query_cache.wreck(__LINE__, "incorrect block type");
+#endif
+ return (Query_cache_table *) data();
+}
+
+inline Query_cache_result * Query_cache_block::result()
+{
+#ifndef DBUG_OFF
+ if (type != RESULT && type != RES_CONT && type != RES_BEG &&
+ type != RES_INCOMPLETE)
+ query_cache.wreck(__LINE__, "incorrect block type");
+#endif
+ return (Query_cache_result *) data();
+}
+
+inline Query_cache_block_table * Query_cache_block::table(TABLE_COUNTER_TYPE n)
+{
+ return ((Query_cache_block_table *)
+ (((byte*)this)+ALIGN_SIZE(sizeof(Query_cache_block)) +
+ n*sizeof(Query_cache_block_table)));
+}
+
+
+/*****************************************************************************
+ * Query_cache_table method(s)
+ *****************************************************************************/
+
+extern "C"
+{
+byte *query_cache_table_get_key(const byte *record, uint *length,
+ my_bool not_used __attribute__((unused)))
+{
+ Query_cache_block* table_block = (Query_cache_block*) record;
+ *length = (table_block->used - table_block->headers_len() -
+ ALIGN_SIZE(sizeof(Query_cache_table)));
+ return (((byte *) table_block->data()) +
+ ALIGN_SIZE(sizeof(Query_cache_table)));
+}
+}
+
+/*****************************************************************************
+ Query_cache_query methods
+*****************************************************************************/
+
+void Query_cache_query::init_n_lock()
+{
+ DBUG_ENTER("Query_cache_query::init_n_lock");
+ res=0; wri = 0; len = 0;
+ sem_init(&lock, 0, 1);
+ pthread_mutex_init(&clients_guard,MY_MUTEX_INIT_FAST);
+ clients = 0;
+ lock_writing();
+ DBUG_PRINT("qcache", ("inited & locked query for block 0x%lx",
+ ((byte*) this)-ALIGN_SIZE(sizeof(Query_cache_block))));
+ DBUG_VOID_RETURN;
+}
+
+
+void Query_cache_query::unlock_n_destroy()
+{
+ DBUG_ENTER("Query_cache_query::unlock_n_destroy");
+ DBUG_PRINT("qcache", ("destroyed & unlocked query for block 0x%lx",
+ ((byte*)this)-ALIGN_SIZE(sizeof(Query_cache_block))));
+ /*
+ The following call is not needed on system where one can destroy an
+ active semaphore
+ */
+ this->unlock_writing();
+ sem_destroy(&lock);
+ pthread_mutex_destroy(&clients_guard);
+ DBUG_VOID_RETURN;
+}
-#define SQL_CACHE_LENGTH 30 // 300 crashes apple gcc.
-HASH sql_cache;
-static LEX lex_array_static[SQL_CACHE_LENGTH];
-LEX * lex_array = lex_array_static;
-int last_lex_array_item = SQL_CACHE_LENGTH - 1;
+/*
+ Following methods work for block read/write locking only in this
+ particular case and in interaction with structure_guard_mutex.
-/* Function to return a text string from a LEX struct */
-static byte *cache_key(const byte *record, uint *length, my_bool not_used)
+ Lock for write prevents any other locking. (exclusive use)
+ Lock for read prevents only locking for write.
+*/
+
+void Query_cache_query::lock_writing()
+{
+ SEM_LOCK(&lock);
+}
+
+
+/*
+ Needed for finding queries, that we may delete from cache.
+ We don't want to wait while block become unlocked. In addition,
+ block locking means that query is now used and we don't need to
+ remove it.
+*/
+
+my_bool Query_cache_query::try_lock_writing()
+{
+ DBUG_ENTER("Query_cache_block::try_lock_writing");
+ if (sem_trywait(&lock)!=0 || clients != 0)
+ {
+ DBUG_PRINT("info", ("can't lock semaphore"));
+ DBUG_RETURN(0);
+ }
+ DBUG_PRINT("info", ("mutex 'lock' 0x%lx locked", (ulong) &lock));
+ DBUG_RETURN(1);
+}
+
+
+void Query_cache_query::lock_reading()
+{
+ MUTEX_LOCK(&clients_guard);
+ if ( ++clients == 1 )
+ SEM_LOCK(&lock);
+ MUTEX_UNLOCK(&clients_guard);
+}
+
+
+void Query_cache_query::unlock_writing()
+{
+ SEM_UNLOCK(&lock);
+}
+
+
+void Query_cache_query::unlock_reading()
+{
+ /*
+ To avoid unlocking semaphore before unlocking mutex (that may cause
+ destroying locked mutex), we use temporary boolean variable 'unlock'.
+ */
+ MUTEX_LOCK(&clients_guard);
+ bool ulock = ((--clients) == 0);
+ MUTEX_UNLOCK(&clients_guard);
+ if (ulock) SEM_UNLOCK(&lock);
+}
+
+extern "C"
+{
+byte *query_cache_query_get_key(const byte *record, uint *length,
+ my_bool not_used)
+{
+ Query_cache_block *query_block = (Query_cache_block*) record;
+ *length = (query_block->used - query_block->headers_len() -
+ ALIGN_SIZE(sizeof(Query_cache_query)));
+ return (((byte *) query_block->data()) +
+ ALIGN_SIZE(sizeof(Query_cache_query)));
+}
+}
+
+/*****************************************************************************
+ Functions to store things into the query cache
+*****************************************************************************/
+
+/*
+ Insert the packet into the query cache.
+ This should only be called if net->query_cache_query != 0
+*/
+
+void query_cache_insert(NET *net, const char *packet, ulong length)
+{
+ DBUG_ENTER("query_cache_insert");
+
+#ifndef DBUG_OFF
+ // Check if we have called query_cache.wreck() (which disables the cache)
+ if (query_cache.query_cache_size == 0)
+ DBUG_VOID_RETURN;
+#endif
+
+ STRUCT_LOCK(&query_cache.structure_guard_mutex);
+ Query_cache_block *query_block = ((Query_cache_block*)
+ net->query_cache_query);
+ if (query_block)
+ {
+ Query_cache_query *header = query_block->query();
+ Query_cache_block *result = header->result();
+
+ DUMP(&query_cache);
+ BLOCK_LOCK_WR(query_block);
+ DBUG_PRINT("qcache", ("insert packet %lu bytes long",length));
+
+ /*
+ On success STRUCT_UNLOCK(&query_cache.structure_guard_mutex) will be
+ done by query_cache.append_result_data if success (if not we need
+ query_cache.structure_guard_mutex locked to free query)
+ */
+ if (!query_cache.append_result_data(&result, length, (gptr) packet,
+ query_block))
+ {
+ query_cache.refused++;
+ DBUG_PRINT("warning", ("Can't append data"));
+ header->result(result);
+ DBUG_PRINT("qcache", ("free query 0x%lx", (ulong) query_block));
+ // The following call will remove the lock on query_block
+ query_cache.free_query(query_block);
+ // append_result_data no success => we need unlock
+ STRUCT_UNLOCK(&query_cache.structure_guard_mutex);
+ DBUG_VOID_RETURN;
+ }
+ header->result(result);
+ BLOCK_UNLOCK_WR(query_block);
+ }
+ else
+ STRUCT_UNLOCK(&query_cache.structure_guard_mutex);
+ DBUG_EXECUTE("check_querycache",query_cache.check_integrity(0););
+ DBUG_VOID_RETURN;
+}
+
+
+void query_cache_abort(NET *net)
+{
+ DBUG_ENTER("query_cache_abort");
+
+#ifndef DBUG_OFF
+ // Check if we have called query_cache.wreck() (which disables the cache)
+ if (query_cache.query_cache_size == 0)
+ DBUG_VOID_RETURN;
+#endif
+ if (net->query_cache_query != 0) // Quick check on unlocked structure
+ {
+ STRUCT_LOCK(&query_cache.structure_guard_mutex);
+ Query_cache_block *query_block = ((Query_cache_block*)
+ net->query_cache_query);
+ if (query_block) // Test if changed by other thread
+ {
+ DUMP(&query_cache);
+ BLOCK_LOCK_WR(query_block);
+ // The following call will remove the lock on query_block
+ query_cache.free_query(query_block);
+ }
+ net->query_cache_query=0;
+ DBUG_EXECUTE("check_querycache",query_cache.check_integrity(1););
+ STRUCT_UNLOCK(&query_cache.structure_guard_mutex);
+ }
+ DBUG_VOID_RETURN;
+}
+
+
+void query_cache_end_of_result(NET *net)
{
-#ifdef QQ
- LEX *lex=(LEX*) record;
- *length = lex->sql_query_length;
- // *length = strlen(lex->ptr);
- return (byte*) lex->sql_query_text;
- // return (byte*) lex->ptr;
+ DBUG_ENTER("query_cache_end_of_result");
+
+#ifndef DBUG_OFF
+ // Check if we have called query_cache.wreck() (which disables the cache)
+ if (query_cache.query_cache_size == 0) DBUG_VOID_RETURN;
+#endif
+
+ if (net->query_cache_query != 0) // Quick check on unlocked structure
+ {
+ STRUCT_LOCK(&query_cache.structure_guard_mutex);
+ Query_cache_block *query_block = ((Query_cache_block*)
+ net->query_cache_query);
+ if (query_block)
+ {
+ DUMP(&query_cache);
+ BLOCK_LOCK_WR(query_block);
+ Query_cache_query *header = query_block->query();
+ Query_cache_block *last_result_block = header->result()->prev;
+ ulong allign_size = ALIGN_SIZE(last_result_block->used);
+ ulong len = max(query_cache.min_allocation_unit, allign_size);
+ if (last_result_block->length >= query_cache.min_allocation_unit + len)
+ query_cache.split_block(last_result_block,len);
+ STRUCT_UNLOCK(&query_cache.structure_guard_mutex);
+
+#ifndef DBUG_OFF
+ if (header->result() == 0)
+ {
+ DBUG_PRINT("error", ("end of data whith no result. query '%s'",
+ header->query()));
+ query_cache.wreck(__LINE__, "");
+ DBUG_VOID_RETURN;
+ }
#endif
- return 0;
+ header->found_rows(current_thd->limit_found_rows);
+ header->result()->type = Query_cache_block::RESULT;
+ header->writer(0);
+ BLOCK_UNLOCK_WR(query_block);
+ }
+ else
+ {
+ // Cache was flushed or resized and query was deleted => do nothing
+ STRUCT_UNLOCK(&query_cache.structure_guard_mutex);
+ }
+ net->query_cache_query=0;
+ DBUG_EXECUTE("check_querycache",query_cache.check_integrity(0););
+ }
+ DBUG_VOID_RETURN;
+}
+
+void query_cache_invalidate_by_MyISAM_filename(const char *filename)
+{
+ query_cache.invalidate_by_MyISAM_filename(filename);
+ DBUG_EXECUTE("check_querycache",query_cache.check_integrity(0););
+}
+
+
+/*****************************************************************************
+ Query_cache methods
+*****************************************************************************/
+
+Query_cache::Query_cache(ulong query_cache_limit,
+ ulong min_allocation_unit,
+ ulong min_result_data_size,
+ uint def_query_hash_size ,
+ uint def_table_hash_size)
+ :query_cache_size(0),
+ query_cache_limit(query_cache_limit),
+ queries_in_cache(0), hits(0), inserts(0), refused(0),
+ total_blocks(0),
+ min_allocation_unit(min_allocation_unit),
+ min_result_data_size(min_result_data_size),
+ def_query_hash_size(def_query_hash_size),
+ def_table_hash_size(def_table_hash_size),
+ initialized(0)
+{
+ ulong min_needed=(ALIGN_SIZE(sizeof(Query_cache_block)) +
+ ALIGN_SIZE(sizeof(Query_cache_block_table)) +
+ ALIGN_SIZE(sizeof(Query_cache_query)) + 3);
+ set_if_bigger(min_allocation_unit,min_needed);
+ this->min_allocation_unit = min_allocation_unit;
+ set_if_bigger(this->min_result_data_size,min_allocation_unit);
+}
+
+
+ulong Query_cache::resize(ulong query_cache_size)
+{
+ DBUG_ENTER("Query_cache::resize");
+ DBUG_PRINT("qcache", ("from %lu to %lu",this->query_cache_size,
+ query_cache_size));
+ free_cache(0);
+ this->query_cache_size=query_cache_size;
+ DBUG_RETURN(init_cache());
+}
+
+
+void Query_cache::store_query(THD *thd, TABLE_LIST *tables_used)
+{
+ TABLE_COUNTER_TYPE tables;
+ ulong tot_length;
+ DBUG_ENTER("Query_cache::store_query");
+ if (query_cache_size == 0)
+ DBUG_VOID_RETURN;
+
+ if ((tables = is_cacheable(thd, thd->query_length,
+ thd->query, &thd->lex, tables_used)))
+ {
+ NET *net = &thd->net;
+ byte flags = (thd->client_capabilities & CLIENT_LONG_FLAG ? 0x80 : 0);
+ STRUCT_LOCK(&structure_guard_mutex);
+
+ if (query_cache_size == 0)
+ DBUG_VOID_RETURN;
+ DUMP(this);
+
+ /* Key is query + database + flag */
+ if (thd->db_length)
+ {
+ memcpy(thd->query+thd->query_length+1, thd->db, thd->db_length);
+ DBUG_PRINT("qcache", ("database : %s length %u",
+ thd->db, thd->db_length));
+ }
+ else
+ {
+ DBUG_PRINT("qcache", ("No active database"));
+ }
+ /*
+ Prepare flags:
+ most significant bit - CLIENT_LONG_FLAG,
+ other - charset number (0 no charset convertion)
+ */
+ if (thd->convert_set != 0)
+ {
+ flags|= (byte) thd->convert_set->number();
+ DBUG_ASSERT(thd->convert_set->number() < 128);
+ }
+ tot_length=thd->query_length+thd->db_length+2;
+ thd->query[tot_length-1] = (char) flags;
+
+ /* Check if another thread is processing the same query? */
+ Query_cache_block *competitor = (Query_cache_block *)
+ hash_search(&queries, (byte*) thd->query, tot_length);
+ DBUG_PRINT("qcache", ("competitor 0x%lx, flags %x", (ulong) competitor,
+ flags));
+ if (competitor == 0)
+ {
+ /* Query is not in cache and no one is working with it; Store it */
+ Query_cache_block *query_block;
+ query_block= write_block_data(tot_length, (gptr) thd->query,
+ ALIGN_SIZE(sizeof(Query_cache_query)),
+ Query_cache_block::QUERY, tables, 1);
+ if (query_block != 0)
+ {
+ DBUG_PRINT("qcache", ("query block 0x%lx allocated, %lu",
+ (ulong) query_block, query_block->used));
+
+ Query_cache_query *header = query_block->query();
+ header->init_n_lock();
+ if (hash_insert(&queries, (byte*) query_block))
+ {
+ refused++;
+ DBUG_PRINT("qcache", ("insertion in query hash"));
+ header->unlock_n_destroy();
+ free_memory_block(query_block);
+ STRUCT_UNLOCK(&structure_guard_mutex);
+ goto end;
+ }
+ if (!register_all_tables(query_block, tables_used, tables))
+ {
+ refused++;
+ DBUG_PRINT("warning", ("tables list including failed"));
+ hash_delete(&queries, (byte *) query_block);
+ header->unlock_n_destroy();
+ free_memory_block(query_block);
+ STRUCT_UNLOCK(&structure_guard_mutex);
+ goto end;
+ }
+ double_linked_list_simple_include(query_block, &queries_blocks);
+ inserts++;
+ queries_in_cache++;
+ STRUCT_UNLOCK(&structure_guard_mutex);
+
+ net->query_cache_query= (gptr) query_block;
+ header->writer(net);
+ // init_n_lock make query block locked
+ BLOCK_UNLOCK_WR(query_block);
+ }
+ else
+ {
+ // We have not enough memory to store query => do nothing
+ refused++;
+ STRUCT_UNLOCK(&structure_guard_mutex);
+ DBUG_PRINT("warning", ("Can't allocate query"));
+ }
+ }
+ else
+ {
+ // Another thread is processing the same query => do nothing
+ refused++;
+ STRUCT_UNLOCK(&structure_guard_mutex);
+ DBUG_PRINT("qcache", ("Another thread process same query"));
+ }
+ }
+ else
+ statistic_increment(refused, &structure_guard_mutex);
+
+end:
+ DBUG_VOID_RETURN;
+}
+
+/*
+ Check if the query is in the cache. If it was cached, send it
+ to the user.
+
+ RESULTS
+ 1 Query was not cached.
+ 0 The query was cached and user was sent the result.
+ -1 The query was cached but we didn't have rights to use it.
+ No error is sent to the client yet.
+*/
+
+
+
+int
+Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length)
+{
+ Query_cache_query *query;
+ Query_cache_block *first_result_block, *result_block;
+ Query_cache_block_table *block_table, *block_table_end;
+ ulong tot_length;
+ byte flags;
+ DBUG_ENTER("Query_cache::send_result_to_client");
+
+ if (query_cache_size == 0 ||
+ /*
+ it is not possible to check has_transactions() function of handler
+ because tables not opened yet
+ */
+ (thd->options & (OPTION_NOT_AUTO_COMMIT | OPTION_BEGIN)) ||
+ thd->query_cache_type == 0)
+
+ {
+ DBUG_PRINT("qcache", ("query cache disabled or not in autocommit mode"));
+ goto err;
+ }
+
+ /* Check that we haven't forgot to reset the query cache variables */
+ DBUG_ASSERT(thd->net.query_cache_query == 0);
+
+ if (!thd->safe_to_cache_query)
+ {
+ DBUG_PRINT("qcache", ("SELECT is non-cacheable"));
+ goto err;
+ }
+
+ /*
+ Test if the query is a SELECT
+ (pre-space is removed in dispatch_command)
+ */
+ if (toupper(sql[0]) != 'S' || toupper(sql[1]) != 'E' ||
+ toupper(sql[2]) !='L')
+ {
+ DBUG_PRINT("qcache", ("The statement is not a SELECT; Not cached"));
+ goto err;
+ }
+
+ STRUCT_LOCK(&structure_guard_mutex);
+ if (query_cache_size == 0)
+ {
+ DBUG_PRINT("qcache", ("query cache disabled"));
+ goto err_unlock;
+ }
+ Query_cache_block *query_block;
+
+ tot_length=query_length+thd->db_length+2;
+ if (thd->db_length)
+ {
+ memcpy(sql+query_length+1, thd->db, thd->db_length);
+ DBUG_PRINT("qcache", ("database: '%s' length %u",
+ thd->db, thd->db_length));
+ }
+ else
+ {
+ DBUG_PRINT("qcache", ("No active database"));
+ }
+ /*
+ prepare flags:
+ Most significant bit - CLIENT_LONG_FLAG,
+ Other - charset number (0 no charset convertion)
+ */
+ flags = (thd->client_capabilities & CLIENT_LONG_FLAG ? 0x80 : 0);
+ if (thd->convert_set != 0)
+ {
+ flags |= (byte) thd->convert_set->number();
+ DBUG_ASSERT(thd->convert_set->number() < 128);
+ }
+ sql[tot_length-1] = (char) flags;
+ query_block = (Query_cache_block *) hash_search(&queries, (byte*) sql,
+ tot_length);
+ /* Quick abort on unlocked data */
+ if (query_block == 0 ||
+ query_block->query()->result() == 0 ||
+ query_block->query()->result()->type != Query_cache_block::RESULT)
+ {
+ DBUG_PRINT("qcache", ("No query in query hash or no results"));
+ goto err_unlock;
+ }
+ DBUG_PRINT("qcache", ("Query in query hash 0x%lx", (ulong)query_block));
+
+ /* Now lock and test that nothing changed while blocks was unlocked */
+ BLOCK_LOCK_RD(query_block);
+
+ query = query_block->query();
+ result_block= first_result_block= query->result();
+
+ if (result_block == 0 || result_block->type != Query_cache_block::RESULT)
+ {
+ /* The query is probably yet processed */
+ DBUG_PRINT("qcache", ("query found, but no data or data incomplete"));
+ BLOCK_UNLOCK_RD(query_block);
+ goto err_unlock;
+ }
+ DBUG_PRINT("qcache", ("Query have result 0x%lx", (ulong) query));
+
+ // Check access;
+ block_table= query_block->table(0);
+ block_table_end= block_table+query_block->n_tables;
+ for ( ; block_table != block_table_end; block_table++)
+ {
+ TABLE_LIST table_list;
+ bzero((char*) &table_list,sizeof(table_list));
+
+ Query_cache_table *table = block_table->parent;
+ table_list.db = table->db();
+ table_list.name = table_list.real_name = table->table();
+ if (check_table_access(thd,SELECT_ACL,&table_list,1))
+ {
+ DBUG_PRINT("qcache",
+ ("probably no SELECT access to %s.%s => return to normal processing",
+ table_list.db, table_list.name));
+ refused++; // This is actually a hit
+ STRUCT_UNLOCK(&structure_guard_mutex);
+ thd->safe_to_cache_query=0; // Don't try to cache this
+ BLOCK_UNLOCK_RD(query_block);
+ DBUG_RETURN(-1); // Privilege error
+ }
+ if (table_list.grant.want_privilege)
+ {
+ DBUG_PRINT("qcache", ("Need to check column privileges for %s.%s",
+ table_list.db, table_list.name));
+ BLOCK_UNLOCK_RD(query_block);
+ thd->safe_to_cache_query=0; // Don't try to cache this
+ goto err_unlock; // Parse query
+ }
+ }
+ move_to_query_list_end(query_block);
+ hits++;
+ STRUCT_UNLOCK(&structure_guard_mutex);
+
+ /*
+ Send cached result to client
+ */
+ do
+ {
+ DBUG_PRINT("qcache", ("Results (len %lu, used %lu, headers %lu)",
+ result_block->length, result_block->used,
+ result_block->headers_len()+
+ ALIGN_SIZE(sizeof(Query_cache_result))));
+
+ Query_cache_result *result = result_block->result();
+ if (net_real_write(&thd->net, result->data(),
+ result_block->used -
+ result_block->headers_len() -
+ ALIGN_SIZE(sizeof(Query_cache_result))))
+ break; // Client aborted
+ result_block = result_block->next;
+ } while (result_block != first_result_block);
+
+ thd->limit_found_rows = query->found_rows();
+
+ BLOCK_UNLOCK_RD(query_block);
+ DBUG_RETURN(1); // Result sent to client
+
+err_unlock:
+ STRUCT_UNLOCK(&structure_guard_mutex);
+err:
+ DBUG_RETURN(0); // Query was not cached
+}
+
+/*
+ Remove all cached queries that uses any of the tables in the list
+*/
+
+void Query_cache::invalidate(TABLE_LIST *tables_used)
+{
+ DBUG_ENTER("Query_cache::invalidate (table list)");
+ if (query_cache_size > 0)
+ {
+ STRUCT_LOCK(&structure_guard_mutex);
+ if (query_cache_size > 0)
+ {
+ DUMP(this);
+ for ( ; tables_used; tables_used=tables_used->next)
+ invalidate_table(tables_used);
+ }
+ STRUCT_UNLOCK(&structure_guard_mutex);
+ }
+ DBUG_VOID_RETURN;
+}
+
+/*
+ Remove all cached queries that uses the given table
+*/
+
+void Query_cache::invalidate(TABLE *table)
+{
+ DBUG_ENTER("Query_cache::invalidate (table)");
+ if (query_cache_size > 0)
+ {
+ STRUCT_LOCK(&structure_guard_mutex);
+ if (query_cache_size > 0)
+ invalidate_table(table);
+ STRUCT_UNLOCK(&structure_guard_mutex);
+ }
+ DBUG_VOID_RETURN;
+}
+
+/*
+ Remove all cached queries that uses the given table type.
+*/
+
+void Query_cache::invalidate(Query_cache_table::query_cache_table_type type)
+{
+ DBUG_ENTER("Query_cache::invalidate (type)");
+ if (query_cache_size > 0)
+ {
+ STRUCT_LOCK(&structure_guard_mutex);
+ DUMP(this);
+ if (query_cache_size > 0)
+ {
+ /* invalidate_table reduce list while only root of list remain */
+ while (tables_blocks[type] != 0)
+ invalidate_table(tables_blocks[type]);
+ }
+ STRUCT_UNLOCK(&structure_guard_mutex);
+ }
+ DBUG_VOID_RETURN;
+}
+
+
+/*
+ Remove all cached queries that uses the given database
+*/
+
+void Query_cache::invalidate(char *db)
+{
+ DBUG_ENTER("Query_cache::invalidate (db)");
+ if (query_cache_size > 0)
+ {
+ STRUCT_LOCK(&structure_guard_mutex);
+ if (query_cache_size > 0)
+ {
+ DUMP(this);
+ for (int i=0 ; i < (int) Query_cache_table::TYPES_NUMBER; i++)
+ {
+ /* invalidate_table reduce list while only root of list remain */
+ while (tables_blocks[i] !=0 )
+ invalidate_table(tables_blocks[i]);
+ }
+ }
+ STRUCT_UNLOCK(&structure_guard_mutex);
+ }
+ DBUG_VOID_RETURN;
+}
+
+
+void Query_cache::invalidate_by_MyISAM_filename(const char *filename)
+{
+ DBUG_ENTER("Query_cache::invalidate_by_MyISAM_filename");
+ if (query_cache_size > 0)
+ {
+ /* Calculate the key outside the lock to make the lock shorter */
+ char key[MAX_DBKEY_LENGTH];
+ uint key_length= filename_2_table_key(key, filename);
+ STRUCT_LOCK(&structure_guard_mutex);
+ if (query_cache_size > 0) // Safety if cache removed
+ {
+ Query_cache_block *table_block;
+ if ((table_block = (Query_cache_block*) hash_search(&tables,
+ (byte*) key,
+ key_length)))
+ invalidate_table(table_block);
+ }
+ STRUCT_UNLOCK(&structure_guard_mutex);
+ }
+ DBUG_VOID_RETURN;
+}
+
+ /* Remove all queries from cache */
+
+void Query_cache::flush()
+{
+ DBUG_ENTER("Query_cache::flush");
+ STRUCT_LOCK(&structure_guard_mutex);
+ if (query_cache_size > 0)
+ {
+ DUMP(this);
+ flush_cache();
+ DUMP(this);
+ }
+
+ DBUG_EXECUTE("check_querycache",query_cache.check_integrity(1););
+ STRUCT_UNLOCK(&structure_guard_mutex);
+ DBUG_VOID_RETURN;
+}
+
+ /* Join result in cache in 1 block (if result length > join_limit) */
+
+void Query_cache::pack(ulong join_limit, uint iteration_limit)
+{
+ DBUG_ENTER("Query_cache::pack");
+ uint i = 0;
+ do
+ {
+ pack_cache();
+ } while ((++i < iteration_limit) && join_results(join_limit));
+ DBUG_VOID_RETURN;
+}
+
+
+void Query_cache::destroy()
+{
+ if ( !initialized )
+ {
+ DBUG_PRINT("qcache", ("Query Cache not initialized"));
+ return;
+ }
+ DBUG_ENTER("Query_cache::destroy");
+ free_cache(1);
+ pthread_mutex_destroy(&structure_guard_mutex);
+ initialized = 0;
+ DBUG_VOID_RETURN;
+}
+
+
+/*****************************************************************************
+ init/destroy
+*****************************************************************************/
+
+void Query_cache::init()
+{
+ DBUG_ENTER("Query_cache::init");
+ pthread_mutex_init(&structure_guard_mutex,MY_MUTEX_INIT_FAST);
+ initialized = 1;
+ DBUG_VOID_RETURN;
+}
+
+
+ulong Query_cache::init_cache()
+{
+ uint mem_bin_count, num, step;
+ ulong mem_bin_size, prev_size, inc;
+ ulong additional_data_size, max_mem_bin_size, approx_additional_data_size;
+
+ DBUG_ENTER("Query_cache::init_cache");
+ if (!initialized)
+ init();
+ approx_additional_data_size = (sizeof(Query_cache) +
+ sizeof(gptr)*(def_query_hash_size+
+ def_query_hash_size));
+ if (query_cache_size < approx_additional_data_size)
+ goto err;
+
+ query_cache_size -= approx_additional_data_size;
+
+ /*
+ Count memory bins number.
+ Check section 6. in start comment for the used algorithm.
+ */
+
+ max_mem_bin_size = query_cache_size >> QUERY_CACHE_MEM_BIN_FIRST_STEP_PWR2;
+ mem_bin_count = (uint) ((1 + QUERY_CACHE_MEM_BIN_PARTS_INC) *
+ QUERY_CACHE_MEM_BIN_PARTS_MUL);
+ mem_bin_num = 1;
+ mem_bin_steps = 1;
+ mem_bin_size = max_mem_bin_size >> QUERY_CACHE_MEM_BIN_STEP_PWR2;
+ prev_size = 0;
+ while (mem_bin_size > min_allocation_unit)
+ {
+ mem_bin_num += mem_bin_count;
+ prev_size = mem_bin_size;
+ mem_bin_size >>= QUERY_CACHE_MEM_BIN_STEP_PWR2;
+ mem_bin_steps++;
+ mem_bin_count += QUERY_CACHE_MEM_BIN_PARTS_INC;
+ mem_bin_count = (uint) (mem_bin_count * QUERY_CACHE_MEM_BIN_PARTS_MUL);
+
+ // Prevent too small bins spacing
+ if (mem_bin_count > (mem_bin_size >> QUERY_CACHE_MEM_BIN_SPC_LIM_PWR2))
+ mem_bin_count= (mem_bin_size >> QUERY_CACHE_MEM_BIN_SPC_LIM_PWR2);
+ }
+ inc = (prev_size - mem_bin_size) / mem_bin_count;
+ mem_bin_num += (mem_bin_count - (min_allocation_unit - mem_bin_size)/inc);
+ mem_bin_steps++;
+ additional_data_size = ((mem_bin_num+1) *
+ ALIGN_SIZE(sizeof(Query_cache_memory_bin))+
+ (mem_bin_steps *
+ ALIGN_SIZE(sizeof(Query_cache_memory_bin_step))));
+
+ if (query_cache_size < additional_data_size)
+ goto err;
+ query_cache_size -= additional_data_size;
+
+ STRUCT_LOCK(&structure_guard_mutex);
+ if (query_cache_size <= min_allocation_unit)
+ {
+ DBUG_PRINT("qcache",
+ (" query_cache_size <= min_allocation_unit => cache disabled"));
+ STRUCT_UNLOCK(&structure_guard_mutex);
+ goto err;
+ }
+
+ if (!(cache = (byte *)
+ my_malloc_lock(query_cache_size+additional_data_size, MYF(0))))
+ {
+ STRUCT_UNLOCK(&structure_guard_mutex);
+ goto err;
+ }
+
+ DBUG_PRINT("qcache", ("cache length %lu, min unit %lu, %u bins",
+ query_cache_size, min_allocation_unit, mem_bin_num));
+
+ steps = (Query_cache_memory_bin_step *) cache;
+ bins = ((Query_cache_memory_bin *)
+ (cache + mem_bin_steps *
+ ALIGN_SIZE(sizeof(Query_cache_memory_bin_step))));
+
+ first_block = (Query_cache_block *) (cache + additional_data_size);
+ first_block->init(query_cache_size);
+ total_blocks++;
+ first_block->pnext=first_block->pprev=first_block;
+ first_block->next=first_block->prev=first_block;
+
+ /* Prepare bins */
+
+ bins[0].init(max_mem_bin_size);
+ steps[0].init(max_mem_bin_size,0,0);
+ mem_bin_count = (uint) ((1 + QUERY_CACHE_MEM_BIN_PARTS_INC) *
+ QUERY_CACHE_MEM_BIN_PARTS_MUL);
+ num= step= 1;
+ mem_bin_size = max_mem_bin_size >> QUERY_CACHE_MEM_BIN_STEP_PWR2;
+ while (mem_bin_size > min_allocation_unit)
+ {
+ ulong incr = (steps[step-1].size - mem_bin_size) / mem_bin_count;
+ unsigned long size = mem_bin_size;
+ for (uint i= mem_bin_count; i > 0; i--)
+ {
+ bins[num+i-1].init(size);
+ size += incr;
+ }
+ num += mem_bin_count;
+ steps[step].init(mem_bin_size, num-1, incr);
+ mem_bin_size >>= QUERY_CACHE_MEM_BIN_STEP_PWR2;
+ step++;
+ mem_bin_count += QUERY_CACHE_MEM_BIN_PARTS_INC;
+ mem_bin_count = (uint) (mem_bin_count * QUERY_CACHE_MEM_BIN_PARTS_MUL);
+ if (mem_bin_count > (mem_bin_size >> QUERY_CACHE_MEM_BIN_SPC_LIM_PWR2))
+ mem_bin_count=(mem_bin_size >> QUERY_CACHE_MEM_BIN_SPC_LIM_PWR2);
+ }
+ inc = (steps[step-1].size - mem_bin_size) / mem_bin_count;
+
+ /*
+ num + mem_bin_count > mem_bin_num, but index never be > mem_bin_num
+ because block with size < min_allocated_unit never will be requested
+ */
+
+ steps[step].init(mem_bin_size, num + mem_bin_count - 1, inc);
+ {
+ uint skiped = (min_allocation_unit - mem_bin_size)/inc;
+ ulong size = mem_bin_size + inc*skiped;
+ uint i = mem_bin_count - skiped;
+ while (i-- > 0)
+ {
+ bins[num+i].init(size);
+ size += inc;
+ }
+ }
+ bins[mem_bin_num].number = 1; // For easy end test in get_free_block
+ free_memory = free_memory_blocks = 0;
+ insert_into_free_memory_list(first_block);
+
+ DUMP(this);
+
+ VOID(hash_init(&queries,def_query_hash_size, 0, 0,
+ query_cache_query_get_key, 0, 0));
+ VOID(hash_init(&tables,def_table_hash_size, 0, 0,
+ query_cache_table_get_key, 0, 0));
+
+ queries_in_cache = 0;
+ queries_blocks = 0;
+ STRUCT_UNLOCK(&structure_guard_mutex);
+ DBUG_RETURN(query_cache_size +
+ additional_data_size + approx_additional_data_size);
+
+err:
+ make_disabled();
+ DBUG_RETURN(0);
+}
+
+
+/* Disable the use of the query cache */
+
+void Query_cache::make_disabled()
+{
+ DBUG_ENTER("Query_cache::make_disabled");
+ query_cache_size= 0;
+ free_memory= 0;
+ bins= 0;
+ steps= 0;
+ cache= 0;
+ mem_bin_num= mem_bin_steps= 0;
+ queries_in_cache= 0;
+ first_block= 0;
+ DBUG_VOID_RETURN;
+}
+
+
+void Query_cache::free_cache(my_bool destruction)
+{
+ DBUG_ENTER("Query_cache::free_cache");
+ if (query_cache_size > 0)
+ {
+ if (!destruction)
+ STRUCT_LOCK(&structure_guard_mutex);
+
+ flush_cache();
+#ifndef DBUG_OFF
+ if (bins[0].free_blocks == 0)
+ {
+ wreck(__LINE__,"no free memory found in (bins[0].free_blocks");
+ DBUG_VOID_RETURN;
+ }
+#endif
+
+ /* Becasue we did a flush, all cache memory must be in one this block */
+ bins[0].free_blocks->destroy();
+ total_blocks--;
+#ifndef DBUG_OFF
+ if (free_memory != query_cache_size)
+ DBUG_PRINT("qcache", ("free memory %lu (should be %lu)",
+ free_memory , query_cache_size));
+#endif
+ my_free((gptr) cache, MYF(MY_ALLOW_ZERO_PTR));
+ make_disabled();
+ hash_free(&queries);
+ hash_free(&tables);
+ if (!destruction)
+ STRUCT_UNLOCK(&structure_guard_mutex);
+ }
+ DBUG_VOID_RETURN;
+}
+
+/*****************************************************************************
+ Free block data
+*****************************************************************************/
+
+/*
+ The following assumes we have a lock on the cache
+*/
+
+void Query_cache::flush_cache()
+{
+ while (queries_blocks != 0)
+ {
+ BLOCK_LOCK_WR(queries_blocks);
+ free_query(queries_blocks);
+ }
+}
+
+/*
+ Free oldest query that is not in use by another thread.
+ Returns 1 if we couldn't remove anything
+*/
+
+my_bool Query_cache::free_old_query()
+{
+ DBUG_ENTER("Query_cache::free_old_query");
+ if (queries_blocks)
+ {
+ /*
+ try_lock_writing used to prevent client because here lock
+ sequence is breached.
+ Also we don't need remove locked queries at this point.
+ */
+ Query_cache_block *query_block = 0;
+ if (queries_blocks != 0)
+ {
+ Query_cache_block *block = queries_blocks;
+ /* Search until we find first query that we can remove */
+ do
+ {
+ Query_cache_query *header = block->query();
+ if (header->result() != 0 &&
+ header->result()->type == Query_cache_block::RESULT &&
+ block->query()->try_lock_writing())
+ {
+ query_block = block;
+ break;
+ }
+ } while ((block=block->next) != queries_blocks );
+ }
+
+ if (query_block != 0)
+ {
+ free_query(query_block);
+ DBUG_RETURN(0);
+ }
+ }
+ DBUG_RETURN(1); // Nothing to remove
+}
+
+/*
+ Free query from query cache.
+ query_block must be locked for writing.
+ This function will remove (and destroy) the lock for the query.
+*/
+
+void Query_cache::free_query(Query_cache_block *query_block)
+{
+ DBUG_ENTER("Query_cache::free_query");
+ DBUG_PRINT("qcache", ("free query 0x%lx %lu bytes result",
+ (ulong) query_block,
+ query_block->query()->length() ));
+
+ queries_in_cache--;
+ hash_delete(&queries,(byte *) query_block);
+
+ Query_cache_query *query = query_block->query();
+
+ if (query->writer() != 0)
+ {
+ /* Tell MySQL that this query should not be cached anymore */
+ query->writer()->query_cache_query = 0;
+ query->writer(0);
+ }
+ double_linked_list_exclude(query_block, &queries_blocks);
+ Query_cache_block_table *table=query_block->table(0);
+
+ for (TABLE_COUNTER_TYPE i=0; i < query_block->n_tables; i++)
+ unlink_table(table++);
+ Query_cache_block *result_block = query->result();
+
+ /*
+ The following is true when query destruction was called and no results
+ in query . (query just registered and then abort/pack/flush called)
+ */
+ if (result_block != 0)
+ {
+ Query_cache_block *block = result_block;
+ do
+ {
+ Query_cache_block *current = block;
+ block = block->next;
+ free_memory_block(current);
+ } while (block != result_block);
+ }
+
+ query->unlock_n_destroy();
+ free_memory_block(query_block);
+
+ DBUG_VOID_RETURN;
+}
+
+/*****************************************************************************
+ Query data creation
+*****************************************************************************/
+
+Query_cache_block *
+Query_cache::write_block_data(ulong data_len, gptr data,
+ ulong header_len,
+ Query_cache_block::block_type type,
+ TABLE_COUNTER_TYPE ntab,
+ my_bool under_guard)
+{
+ ulong all_headers_len = (ALIGN_SIZE(sizeof(Query_cache_block)) +
+ ALIGN_SIZE(ntab*sizeof(Query_cache_block_table)) +
+ header_len);
+ ulong len = data_len + all_headers_len;
+ DBUG_ENTER("Query_cache::write_block_data");
+ DBUG_PRINT("qcache", ("data: %ld, header: %ld, all header: %ld",
+ data_len, header_len, all_headers_len));
+ Query_cache_block *block = allocate_block(max(len, min_allocation_unit),
+ 1, 0, under_guard);
+ if (block != 0)
+ {
+ block->type = type;
+ block->n_tables = ntab;
+ block->used = len;
+
+ memcpy((void*) (((byte *) block)+ all_headers_len),
+ (void*) data, data_len);
+ }
+ DBUG_RETURN(block);
+}
+
+
+/*
+ On success STRUCT_UNLOCK(&query_cache.structure_guard_mutex) will be done.
+*/
+
+my_bool
+Query_cache::append_result_data(Query_cache_block **current_block,
+ ulong data_len, gptr data,
+ Query_cache_block *query_block)
+{
+ DBUG_ENTER("Query_cache::append_result_data");
+ DBUG_PRINT("qcache", ("append %lu bytes to 0x%lx query",
+ data_len, query_block));
+
+ if (query_block->query()->add(data_len) > query_cache_limit)
+ {
+ DBUG_PRINT("qcache", ("size limit reached %lu > %lu",
+ query_block->query()->length(),
+ query_cache_limit));
+ DBUG_RETURN(0);
+ }
+ if (*current_block == 0)
+ {
+ DBUG_PRINT("qcache", ("allocated first result data block %lu", data_len));
+ /*
+ STRUCT_UNLOCK(&structure_guard_mutex) Will be done by
+ write_result_data if success;
+ */
+ DBUG_RETURN(write_result_data(current_block, data_len, data, query_block,
+ Query_cache_block::RES_BEG));
+ }
+ Query_cache_block *last_block = (*current_block)->prev;
+
+ DBUG_PRINT("qcache", ("lastblock 0x%lx len %lu used %lu",
+ (ulong) last_block, last_block->length,
+ last_block->used));
+ my_bool success = 1;
+ ulong last_block_free_space= last_block->length - last_block->used;
+
+ /*
+ We will first allocate and write the 'tail' of data, that doesn't fit
+ in the 'last_block'. Only if this succeeds, we will fill the last_block.
+ This saves us a memcpy if the query doesn't fit in the query cache.
+ */
+
+ // Try join blocks if physically next block is free...
+ ulong tail = data_len - last_block_free_space;
+ ulong append_min = get_min_append_result_data_size();
+ if (last_block_free_space < data_len &&
+ append_next_free_block(last_block,
+ max(tail, append_min)))
+ last_block_free_space = last_block->length - last_block->used;
+ // If no space in last block (even after join) allocate new block
+ if (last_block_free_space < data_len)
+ {
+ DBUG_PRINT("qcache", ("allocate new block for %lu bytes",
+ data_len-last_block_free_space));
+ Query_cache_block *new_block = 0;
+ /*
+ On success STRUCT_UNLOCK(&structure_guard_mutex) will be done
+ by the next call
+ */
+ success = write_result_data(&new_block, data_len-last_block_free_space,
+ (gptr)(((byte*)data)+last_block_free_space),
+ query_block,
+ Query_cache_block::RES_CONT);
+ /*
+ new_block may be != 0 even !success (if write_result_data
+ allocate a small block but failed to allocate continue)
+ */
+ if (new_block != 0)
+ double_linked_list_join(last_block, new_block);
+ }
+ else
+ {
+ // It is success (nobody can prevent us write data)
+ STRUCT_UNLOCK(&structure_guard_mutex);
+ }
+
+ // Now finally write data to the last block
+ if (success && last_block_free_space > 0)
+ {
+ ulong to_copy = min(data_len,last_block_free_space);
+ DBUG_PRINT("qcache", ("use free space %lub at block 0x%lx to copy %lub",
+ last_block_free_space, (ulong)last_block, to_copy));
+ memcpy((void*) (((byte*) last_block) + last_block->used), (void*) data,
+ to_copy);
+ last_block->used+=to_copy;
+ }
+ DBUG_RETURN(success);
+}
+
+
+my_bool Query_cache::write_result_data(Query_cache_block **result_block,
+ ulong data_len, gptr data,
+ Query_cache_block *query_block,
+ Query_cache_block::block_type type)
+{
+ DBUG_ENTER("Query_cache::write_result_data");
+ DBUG_PRINT("qcache", ("data_len %lu",data_len));
+
+ /*
+ Reserve block(s) for filling
+ During data allocation we must have structure_guard_mutex locked.
+ As data copy is not a fast operation, it's better if we don't have
+ structure_guard_mutex locked during data coping.
+ Thus we first allocate space and lock query, then unlock
+ structure_guard_mutex and copy data.
+ */
+
+ my_bool success = allocate_data_chain(result_block, data_len, query_block,
+ type == Query_cache_block::RES_BEG);
+ if (success)
+ {
+ // It is success (nobody can prevent us write data)
+ STRUCT_UNLOCK(&structure_guard_mutex);
+ byte *rest = (byte*) data;
+ Query_cache_block *block = *result_block;
+ uint headers_len = (ALIGN_SIZE(sizeof(Query_cache_block)) +
+ ALIGN_SIZE(sizeof(Query_cache_result)));
+ // Now fill list of blocks that created by allocate_data_chain
+ do
+ {
+ block->type = type;
+ ulong length = block->used - headers_len;
+ DBUG_PRINT("qcache", ("write %lu byte in block 0x%lx",length,
+ (ulong)block));
+ memcpy((void*)(((byte*) block)+headers_len), (void*) rest, length);
+ rest += length;
+ block = block->next;
+ type = Query_cache_block::RES_CONT;
+ } while (block != *result_block);
+ }
+ else
+ {
+ if (*result_block != 0)
+ {
+ // Destroy list of blocks that was created & locked by lock_result_data
+ Query_cache_block *block = *result_block;
+ do
+ {
+ Query_cache_block *current = block;
+ block = block->next;
+ free_memory_block(current);
+ } while (block != *result_block);
+ *result_block = 0;
+ /*
+ It is not success => not unlock structure_guard_mutex (we need it to
+ free query)
+ */
+ }
+ }
+ DBUG_PRINT("qcache", ("success %d", (int) success));
+ DBUG_RETURN(success);
+}
+
+inline ulong Query_cache::get_min_first_result_data_size()
+{
+ if (queries_in_cache < QUERY_CACHE_MIN_ESTIMATED_QUERIES_NUMBER)
+ return min_result_data_size;
+ ulong avg_result = (query_cache_size - free_memory) / queries_in_cache;
+ avg_result = min(avg_result, query_cache_limit);
+ return max(min_result_data_size, avg_result);
+}
+
+inline ulong Query_cache::get_min_append_result_data_size()
+{
+ return min_result_data_size;
+}
+
+/*
+ Allocate one or more blocks to hold data
+*/
+
+my_bool Query_cache::allocate_data_chain(Query_cache_block **result_block,
+ ulong data_len,
+ Query_cache_block *query_block,
+ my_bool first_block)
+{
+ ulong all_headers_len = (ALIGN_SIZE(sizeof(Query_cache_block)) +
+ ALIGN_SIZE(sizeof(Query_cache_result)));
+ ulong len = data_len + all_headers_len;
+ DBUG_ENTER("Query_cache::allocate_data_chain");
+ DBUG_PRINT("qcache", ("data_len %lu, all_headers_len %lu",
+ data_len, all_headers_len));
+
+ ulong min_size = (first_block ?
+ get_min_first_result_data_size():
+ get_min_append_result_data_size());
+ *result_block = allocate_block(max(min_size,len),
+ min_result_data_size == 0,
+ all_headers_len + min_result_data_size,
+ 1);
+ my_bool success = (*result_block != 0);
+ if (success)
+ {
+ Query_cache_block *new_block= *result_block;
+ new_block->n_tables = 0;
+ new_block->used = 0;
+ new_block->type = Query_cache_block::RES_INCOMPLETE;
+ new_block->next = new_block->prev = new_block;
+ Query_cache_result *header = new_block->result();
+ header->parent(query_block);
+
+ if (new_block->length < len)
+ {
+ /*
+ We got less memory then we need (no big memory blocks) =>
+ Continue to allocated more blocks until we got everything we need.
+ */
+ Query_cache_block *next_block;
+ if ((success = allocate_data_chain(&next_block,
+ len - new_block->length,
+ query_block, first_block)))
+ double_linked_list_join(new_block, next_block);
+ }
+ if (success)
+ {
+ new_block->used = min(len, new_block->length);
+
+ DBUG_PRINT("qcache", ("Block len %lu used %lu",
+ new_block->length, new_block->used));
+ }
+ else
+ DBUG_PRINT("warning", ("Can't allocate block for continue"));
+ }
+ else
+ DBUG_PRINT("warning", ("Can't allocate block for results"));
+ DBUG_RETURN(success);
+}
+
+/*****************************************************************************
+ Tables management
+*****************************************************************************/
+
+/*
+ Invalidate the first table in the table_list
+*/
+
+void Query_cache::invalidate_table(TABLE_LIST *table_list)
+{
+ if (table_list->table != 0)
+ invalidate_table(table_list->table); // Table is open
+ else
+ {
+ char key[MAX_DBKEY_LENGTH];
+ uint key_length;
+ Query_cache_block *table_block;
+ key_length=(uint) (strmov(strmov(key,table_list->db)+1,
+ table_list->real_name) -key)+ 1;
+
+ // We don't store temporary tables => no key_length+=4 ...
+ if ((table_block = (Query_cache_block*)
+ hash_search(&tables,(byte*) key,key_length)))
+ invalidate_table(table_block);
+ }
}
-/* At the moment we do not really want to do anything upon delete */
-static void free_cache_entry(void *entry)
+void Query_cache::invalidate_table(TABLE *table)
{
+ Query_cache_block *table_block;
+ if ((table_block = ((Query_cache_block*)
+ hash_search(&tables, (byte*) table->table_cache_key,
+ table->key_length))))
+ invalidate_table(table_block);
}
-/* Initialization of the SQL cache hash -- should be called during
- the bootstrap stage */
-bool sql_cache_init(void)
+void Query_cache::invalidate_table(Query_cache_block *table_block)
{
- if (query_buff_size)
+ Query_cache_block_table *list_root = table_block->table(0);
+ while (list_root->next != list_root)
{
- VOID(hash_init(&sql_cache, 4096, 0, 0,
- cache_key,
- (void (*)(void*)) free_cache_entry,
- 0));
+ Query_cache_block *query_block = list_root->next->block();
+ BLOCK_LOCK_WR(query_block);
+ free_query(query_block);
}
- return 0;
}
-/* Clearing the SQL cache hash -- during shutdown */
-void sql_cache_free(void)
+
+my_bool Query_cache::register_all_tables(Query_cache_block *block,
+ TABLE_LIST *tables_used,
+ TABLE_COUNTER_TYPE tables)
{
- hash_free(&sql_cache);
+ TABLE_COUNTER_TYPE n;
+ DBUG_PRINT("qcache", ("register tables block 0x%lx, n %d, header %x",
+ (ulong) block, (int) tables,
+ (int) ALIGN_SIZE(sizeof(Query_cache_block))));
+
+ Query_cache_block_table *block_table = block->table(0);
+
+ for (n=0; tables_used; tables_used=tables_used->next, n++, block_table++)
+ {
+ DBUG_PRINT("qcache",
+ ("table %s, db %s, openinfo at 0x%lx, keylen %u, key at 0x%lx",
+ tables_used->real_name, tables_used->db,
+ (ulong) tables_used->table,
+ tables_used->table->key_length,
+ (ulong) tables_used->table->table_cache_key));
+ block_table->n=n;
+ if (!insert_table(tables_used->table->key_length,
+ tables_used->table->table_cache_key, block_table,
+ Query_cache_table::type_convertion(tables_used->table->
+ db_type)))
+ break;
+
+ if (tables_used->table->db_type == DB_TYPE_MRG_MYISAM)
+ {
+ ha_myisammrg *handler = (ha_myisammrg *) tables_used->table->file;
+ MYRG_INFO *file = handler->myrg_info();
+ for (MYRG_TABLE *table = file->open_tables;
+ table != file->end_table ;
+ table++)
+ {
+ char key[MAX_DBKEY_LENGTH];
+ uint key_length =filename_2_table_key(key, table->table->filename);
+ (++block_table)->n= ++n;
+ if (!insert_table(key_length, key, block_table,
+ Query_cache_table::type_convertion(DB_TYPE_MYISAM)))
+ goto err;
+ }
+ }
+ }
+
+err:
+ if (tables_used)
+ {
+ DBUG_PRINT("qcache", ("failed at table %d", (int) n));
+ /* Unlink the tables we allocated above */
+ for (Query_cache_block_table *tmp = block->table(0) ;
+ tmp != block_table;
+ tmp++)
+ unlink_table(tmp);
+ }
+ return (tables_used == 0);
}
-/* Finds whether the SQL command is already in the cache, at any case
- establishes correct LEX structure in the THD (either from
- cache or a new one) */
+/*
+ Insert used tablename in cache
+ Returns 0 on error
+*/
-int sql_cache_hit(THD *thd, char *sql, uint length)
+my_bool
+Query_cache::insert_table(uint key_len, char *key,
+ Query_cache_block_table *node,
+ Query_cache_table::query_cache_table_type type)
{
-#ifdef QQ
- LEX *ptr;
- ptr = (LEX *)hash_search(&sql_cache, sql, length);
- if (ptr) {
- fprintf(stderr, "Query `%s' -- hit in the cache (%p)\n", ptr->sql_query_text, ptr);
- thd->lex_ptr = ptr;
- ptr->thd = thd;
- } else {
- thd->lex_ptr = ptr = lex_array + last_lex_array_item--;
+ DBUG_ENTER("Query_cache::insert_table");
+ DBUG_PRINT("qcache", ("insert table node 0x%lx, len %d",
+ (ulong)node, key_len));
+
+ Query_cache_block *table_block = ((Query_cache_block *)
+ hash_search(&tables, (byte*) key,
+ key_len));
+
+ if (table_block == 0)
+ {
+ DBUG_PRINT("qcache", ("new table block from 0x%lx (%u)",
+ (ulong) key, (int) key_len));
+ table_block = write_block_data(key_len, (gptr) key,
+ ALIGN_SIZE(sizeof(Query_cache_table)),
+ Query_cache_block::TABLE,
+ 1, 1);
+ if (table_block == 0)
+ {
+ DBUG_PRINT("qcache", ("Can't write table name to cache"));
+ DBUG_RETURN(0);
+ }
+ Query_cache_table *header = table_block->table();
+ header->type(type);
+ double_linked_list_simple_include(table_block,
+ &tables_blocks[type]);
+ Query_cache_block_table *list_root = table_block->table(0);
+ list_root->n = 0;
+ list_root->next = list_root->prev = list_root;
+ if (hash_insert(&tables, (const byte *) table_block))
+ {
+ DBUG_PRINT("qcache", ("Can't insert table to hash"));
+ // write_block_data return locked block
+ free_memory_block(table_block);
+ DBUG_RETURN(0);
+ }
+ char *db = header->db();
+ header->table(db + strlen(db) + 1);
+ }
+
+ Query_cache_block_table *list_root = table_block->table(0);
+ node->next = list_root->next;
+ list_root->next = node;
+ node->next->prev = node;
+ node->prev = list_root;
+ node->parent = table_block->table();
+ DBUG_RETURN(1);
+}
+
+
+void Query_cache::unlink_table(Query_cache_block_table *node)
+{
+ DBUG_ENTER("Query_cache::unlink_table");
+ node->prev->next = node->next;
+ node->next->prev = node->prev;
+ Query_cache_block_table *neighbour = node->next;
+ if (neighbour->next == neighbour)
+ {
+ // list is empty (neighbor is root of list)
+ Query_cache_block *table_block = neighbour->block();
+ double_linked_list_exclude(table_block,
+ &tables_blocks[table_block->table()->type()]);
+ hash_delete(&tables,(byte *) table_block);
+ free_memory_block(table_block);
+ }
+ DBUG_VOID_RETURN;
+}
+
+/*****************************************************************************
+ Free memory management
+*****************************************************************************/
+
+Query_cache_block *
+Query_cache::allocate_block(ulong len, my_bool not_less, ulong min,
+ my_bool under_guard)
+{
+ DBUG_ENTER("Query_cache::allocate_n_lock_block");
+ DBUG_PRINT("qcache", ("len %lu, not less %d, min %lu, uder_guard %d",
+ len, not_less,min,under_guard));
+
+ if (len >= min(query_cache_size, query_cache_limit))
+ {
+ DBUG_PRINT("qcache", ("Query cache hase only %lu memory and limit %lu",
+ query_cache_size, query_cache_limit));
+ DBUG_RETURN(0); // in any case we don't have such piece of memory
+ }
+
+ if (!under_guard)
+ STRUCT_LOCK(&structure_guard_mutex);
+
+ /* Free old queries until we have enough memory to store this block */
+ Query_cache_block *block;
+ do
+ {
+ block= get_free_block(len, not_less, min);
+ }
+ while (block == 0 && !free_old_query());
+
+ if (block != 0) // If we found a suitable block
+ {
+ if (block->length >= ALIGN_SIZE(len) + min_allocation_unit)
+ split_block(block,ALIGN_SIZE(len));
+ }
- lex_start(thd, (uchar *)sql, length);
+ if (!under_guard)
+ STRUCT_UNLOCK(&structure_guard_mutex);
+ DBUG_RETURN(block);
+}
+
+
+Query_cache_block *
+Query_cache::get_free_block(ulong len, my_bool not_less, ulong min)
+{
+ Query_cache_block *block = 0, *first = 0;
+ DBUG_ENTER("Query_cache::get_free_block");
+ DBUG_PRINT("qcache",("length %lu, not_less %d, min %lu", len,
+ (int)not_less, min));
- if (hash_insert(&sql_cache, (const byte *)ptr)) {
- fprintf(stderr, "Out of memory during hash_insert?\n");
+ /* Find block with minimal size > len */
+ uint start = find_bin(len);
+ // try matching bin
+ if (bins[start].number != 0)
+ {
+ Query_cache_block *list = bins[start].free_blocks;
+ ulong max_len = list->prev->length;
+ if (list->prev->length >= len) // check block with max size
+ {
+ first = list;
+ uint n = 0;
+ while ( n < QUERY_CACHE_MEM_BIN_TRY &&
+ first->length < len) //we don't need irst->next != list
+ {
+ first=first->next;
+ n++;
+ }
+ if (first->length >= len)
+ block=first;
+ else // we don't need if (first->next != list)
+ {
+ n = 0;
+ block = list->prev;
+ while (n < QUERY_CACHE_MEM_BIN_TRY &&
+ block->length > len)
+ {
+ block=block->prev;
+ n++;
+ }
+ if(block->length < len)
+ block=block->next;
+ }
}
- fprintf(stderr, "Query `%s' not found in the cache -- insert %p from slot %d\n", thd->lex_ptr->ptr, ptr, last_lex_array_item+1);
- if (!hash_search(&sql_cache, sql, length)) {
- fprintf(stderr, "I just enterred a hash key but it's not where -- what's that?\n");
- } else {
- fprintf(stderr, "Inserted to cache\n");
+ else
+ first = list->prev;
+ }
+ if (block == 0 && start > 0)
+ {
+ DBUG_PRINT("qcache",("Try bins with bigger block size"));
+ // Try more big bins
+ int i = start - 1;
+ while (i > 0 && bins[i].number == 0)
+ i--;
+ if (bins[i].number > 0)
+ block = bins[i].free_blocks;
+ }
+
+ // If no big blocks => try less size (if it is possible)
+ if (block == 0 && ! not_less)
+ {
+ DBUG_PRINT("qcache",("Try to allocate a smaller block"));
+ if (first != 0 && first->length > min)
+ block = first;
+ else
+ {
+ uint i = start + 1;
+ /* bins[mem_bin_num].number contains 1 for easy end test */
+ for (i= start+1 ; bins[i].number == 0 ; i++) ;
+ if (i < mem_bin_num && bins[i].free_blocks->prev->length >= min)
+ block = bins[i].free_blocks->prev;
}
- return 0;
}
+ if (block != 0)
+ exclude_from_free_memory_list(block);
+
+ DBUG_PRINT("qcache",("getting block 0x%lx", (ulong) block));
+ DBUG_RETURN(block);
+}
+
+
+void Query_cache::free_memory_block(Query_cache_block *block)
+{
+ DBUG_ENTER("Query_cache::free_memory_block");
+ block->used=0;
+ DBUG_PRINT("qcache",("first_block 0x%lx, block 0x%lx, pnext 0x%lx pprev 0x%lx",
+ (ulong) first_block, (ulong) block,block->pnext,
+ (ulong) block->pprev));
+
+ if (block->pnext != first_block && block->pnext->is_free())
+ block = join_free_blocks(block, block->pnext);
+ if (block != first_block && block->pprev->is_free())
+ block = join_free_blocks(block->pprev, block->pprev);
+ insert_into_free_memory_list(block);
+ DBUG_VOID_RETURN;
+}
+
+
+void Query_cache::split_block(Query_cache_block *block, ulong len)
+{
+ DBUG_ENTER("Query_cache::split_block");
+ Query_cache_block *new_block = (Query_cache_block*)(((byte*) block)+len);
+
+ new_block->init(block->length - len);
+ total_blocks++;
+ block->length=len;
+ new_block->pnext = block->pnext;
+ block->pnext = new_block;
+ new_block->pprev = block;
+ new_block->pnext->pprev = new_block;
+
+ if (block->type == Query_cache_block::FREE)
+ // if block was free then it already joined with all free neighbours
+ insert_into_free_memory_list(new_block);
+ else
+ free_memory_block(new_block);
+
+ DBUG_PRINT("qcache", ("split 0x%lx (%lu) new 0x%lx",
+ (ulong) block, len, (ulong) new_block));
+ DBUG_VOID_RETURN;
+}
+
+
+Query_cache_block *
+Query_cache::join_free_blocks(Query_cache_block *first_block,
+ Query_cache_block *block_in_list)
+{
+ Query_cache_block *second_block;
+ DBUG_ENTER("Query_cache::join_free_blocks");
+ DBUG_PRINT("qcache",
+ ("join first 0x%lx, pnext 0x%lx, in list 0x%lx",
+ (ulong) first_block, (ulong) first_block->pnext,
+ (ulong) block_in_list));
+
+ exclude_from_free_memory_list(block_in_list);
+ second_block = first_block->pnext;
+ // May be was not free block
+ second_block->used=0;
+ second_block->destroy();
+ total_blocks--;
+
+ first_block->length += second_block->length;
+ first_block->pnext = second_block->pnext;
+ second_block->pnext->pprev = first_block;
+
+ DBUG_RETURN(first_block);
+}
+
+
+my_bool Query_cache::append_next_free_block(Query_cache_block *block,
+ ulong add_size)
+{
+ Query_cache_block *next_block = block->pnext;
+ DBUG_ENTER("Query_cache::append_next_free_block");
+ DBUG_PRINT("enter", ("block 0x%lx, add_size %lu", (ulong) block,
+ add_size));
+
+ if (next_block != first_block && next_block->is_free())
+ {
+ ulong old_len = block->length;
+ exclude_from_free_memory_list(next_block);
+ next_block->destroy();
+ total_blocks--;
+
+ block->length += next_block->length;
+ block->pnext = next_block->pnext;
+ next_block->pnext->pprev = block;
+
+ if (block->length > ALIGN_SIZE(old_len + add_size) + min_allocation_unit)
+ split_block(block,ALIGN_SIZE(old_len + add_size));
+ DBUG_PRINT("exit", ("block was appended"));
+ DBUG_RETURN(1);
+ }
+ DBUG_RETURN(0);
+}
+
+
+void Query_cache::exclude_from_free_memory_list(Query_cache_block *free_block)
+{
+ DBUG_ENTER("Query_cache::exclude_from_free_memory_list");
+ Query_cache_memory_bin *bin = *((Query_cache_memory_bin **)
+ free_block->data());
+ double_linked_list_exclude(free_block, &bin->free_blocks);
+ bin->number--;
+ free_memory-=free_block->length;
+ free_memory_blocks--;
+ DBUG_PRINT("qcache",("exclude block 0x%lx, bin 0x%lx", (ulong) free_block,
+ (ulong) bin));
+ DBUG_VOID_RETURN;
+}
+
+void Query_cache::insert_into_free_memory_list(Query_cache_block *free_block)
+{
+ DBUG_ENTER("Query_cache::insert_into_free_memory_list");
+ uint idx = find_bin(free_block->length);
+ insert_into_free_memory_sorted_list(free_block, &bins[idx].free_blocks);
+ /*
+ We have enough memory in block for storing bin reference due to
+ min_allocation_unit choice
+ */
+ Query_cache_memory_bin **bin_ptr = ((Query_cache_memory_bin**)
+ free_block->data());
+ *bin_ptr = bins+idx;
+ (*bin_ptr)->number++;
+ DBUG_PRINT("qcache",("insert block 0x%lx, bin[%d] 0x%lx",
+ (ulong) free_block, idx, (ulong) *bin_ptr));
+ DBUG_VOID_RETURN;
+}
+
+uint Query_cache::find_bin(ulong size)
+{
+ DBUG_ENTER("Query_cache::find_bin");
+ // Binary search
+ int left = 0, right = mem_bin_steps;
+ do
+ {
+ int middle = (left + right) / 2;
+ if (steps[middle].size > size)
+ left = middle+1;
+ else
+ right = middle;
+ } while (left < right);
+ if (left == 0)
+ {
+ // first bin not subordinate of common rules
+ DBUG_PRINT("qcache", ("first bin (# 0), size %lu",size));
+ DBUG_RETURN(0);
+ }
+ uint bin = steps[left].idx -
+ (uint)((size - steps[left].size)/steps[left].increment);
+#ifndef DBUG_OFF
+ bins_dump();
#endif
- return 1;
+ DBUG_PRINT("qcache", ("bin %u step %u, size %lu step size %lu",
+ bin, left, size, steps[left].size));
+ DBUG_RETURN(bin);
+}
+
+
+/*****************************************************************************
+ Lists management
+*****************************************************************************/
+
+void Query_cache::move_to_query_list_end(Query_cache_block *query_block)
+{
+ DBUG_ENTER("Query_cache::move_to_query_list_end");
+ double_linked_list_exclude(query_block, &queries_blocks);
+ double_linked_list_simple_include(query_block, &queries_blocks);
+ DBUG_VOID_RETURN;
+}
+
+
+void Query_cache::insert_into_free_memory_sorted_list(Query_cache_block *
+ new_block,
+ Query_cache_block **
+ list)
+{
+ DBUG_ENTER("Query_cache::insert_into_free_memory_sorted_list");
+ /*
+ list sorted by size in ascendant order, because we need small blocks
+ more frequently than bigger ones
+ */
+
+ new_block->used = 0;
+ new_block->n_tables = 0;
+ new_block->type = Query_cache_block::FREE;
+
+ if (*list == 0)
+ {
+ *list = new_block->next=new_block->prev=new_block;
+ DBUG_PRINT("qcache", ("inserted into empty list"));
+ }
+ else
+ {
+ Query_cache_block *point = *list;
+ if (point->length >= new_block->length)
+ {
+ point = point->prev;
+ *list = new_block;
+ }
+ else
+ {
+ /* Find right position in sorted list to put block */
+ while (point->next != *list &&
+ point->next->length < new_block->length)
+ point=point->next;
+ }
+ new_block->prev = point;
+ new_block->next = point->next;
+ new_block->next->prev = new_block;
+ point->next = new_block;
+ }
+ free_memory+=new_block->length;
+ free_memory_blocks++;
+ DBUG_VOID_RETURN;
}
+
+
+void
+Query_cache::double_linked_list_simple_include(Query_cache_block *point,
+ Query_cache_block **
+ list_pointer)
+{
+ DBUG_ENTER("Query_cache::double_linked_list_simple_include");
+ DBUG_PRINT("qcache", ("including block 0x%lx", (ulong) point));
+ if (*list_pointer == 0)
+ *list_pointer=point->next=point->prev=point;
+ else
+ {
+ // insert to and of list
+ point->next = (*list_pointer);
+ point->prev = (*list_pointer)->prev;
+ point->prev->next = point;
+ (*list_pointer)->prev = point;
+ }
+ DBUG_VOID_RETURN;
+}
+
+void
+Query_cache::double_linked_list_exclude(Query_cache_block *point,
+ Query_cache_block **list_pointer)
+{
+ DBUG_ENTER("Query_cache::double_linked_list_exclude");
+ DBUG_PRINT("qcache", ("excluding block 0x%lx, list 0x%lx",
+ (ulong) point, (ulong) list_pointer));
+ if (point->next == point)
+ *list_pointer = 0; // empty list
+ else
+ {
+ point->next->prev = point->prev;
+ point->prev->next = point->next;
+ if (point == *list_pointer)
+ *list_pointer = point->next;
+ }
+ DBUG_VOID_RETURN;
+}
+
+
+void Query_cache::double_linked_list_join(Query_cache_block *head_tail,
+ Query_cache_block *tail_head)
+{
+ Query_cache_block *head_head = head_tail->next,
+ *tail_tail = tail_head->prev;
+ head_head->prev = tail_tail;
+ head_tail->next = tail_head;
+ tail_head->prev = head_tail;
+ tail_tail->next = head_head;
+}
+
+/*****************************************************************************
+ Query
+*****************************************************************************/
+
+/*
+ If query is cacheable return number tables in query
+ (query without tables are not cached)
+*/
+
+TABLE_COUNTER_TYPE Query_cache::is_cacheable(THD *thd, uint32 query_len,
+ char *query,
+ LEX *lex, TABLE_LIST *tables_used)
+{
+ TABLE_COUNTER_TYPE tables = 0;
+ DBUG_ENTER("Query_cache::is_cacheable");
+
+ if (lex->sql_command == SQLCOM_SELECT &&
+ thd->temporary_tables == 0 &&
+ (thd->query_cache_type == 1 ||
+ (thd->query_cache_type == 2 && (lex->select->options &
+ OPTION_TO_QUERY_CACHE))) &&
+ thd->safe_to_cache_query)
+ {
+ my_bool has_transactions = 0;
+ DBUG_PRINT("qcache", ("options %lx %lx, type %u",
+ OPTION_TO_QUERY_CACHE,
+ lex->select->options,
+ (int) thd->query_cache_type));
+
+ for (; tables_used; tables_used=tables_used->next)
+ {
+ tables++;
+ DBUG_PRINT("qcache", ("table %s, db %s, type %u",
+ tables_used->real_name,
+ tables_used->db, tables_used->table->db_type));
+ has_transactions = (has_transactions ||
+ tables_used->table->file->has_transactions());
+
+ if (tables_used->table->db_type == DB_TYPE_MRG_ISAM)
+ {
+ DBUG_PRINT("qcache", ("select not cacheable: used MRG_ISAM table(s)"));
+ DBUG_RETURN(0);
+ }
+ if (tables_used->table->db_type == DB_TYPE_MRG_MYISAM)
+ {
+ ha_myisammrg *handler = (ha_myisammrg *)tables_used->table->file;
+ MYRG_INFO *file = handler->myrg_info();
+ tables+= (file->end_table - file->open_tables);
+ }
+ }
+
+ if ((thd->options & (OPTION_NOT_AUTO_COMMIT | OPTION_BEGIN)) &&
+ has_transactions)
+ {
+ DBUG_PRINT("qcache", ("not in autocommin mode"));
+ DBUG_RETURN(0);
+ }
+ DBUG_PRINT("qcache", ("select is using %d tables", tables));
+ DBUG_RETURN(tables);
+ }
+
+ DBUG_PRINT("qcache",
+ ("not interesting query: %d or not cacheable, options %lx %lx, type %u",
+ (int) lex->sql_command,
+ OPTION_TO_QUERY_CACHE,
+ lex->select->options,
+ (int) thd->query_cache_type));
+ DBUG_RETURN(0);
+}
+
+
+/*****************************************************************************
+ Packing
+*****************************************************************************/
+
+void Query_cache::pack_cache()
+{
+ DBUG_ENTER("Query_cache::pack_cache");
+ STRUCT_LOCK(&structure_guard_mutex);
+ DBUG_EXECUTE("check_querycache",query_cache.check_integrity(1););
+
+ byte *border = 0;
+ Query_cache_block *before = 0;
+ ulong gap = 0;
+ my_bool ok = 1;
+ Query_cache_block *block = first_block;
+ DUMP(this);
+
+ if (first_block)
+ {
+ do
+ {
+ Query_cache_block *next=block->pnext;
+ ok = move_by_type(&border, &before, &gap, block);
+ block = next;
+ } while (ok && block != first_block);
+
+ if (border != 0)
+ {
+ Query_cache_block *new_block = (Query_cache_block *) border;
+ new_block->init(gap);
+ total_blocks++;
+ new_block->pnext = before->pnext;
+ before->pnext = new_block;
+ new_block->pprev = before;
+ new_block->pnext->pprev = new_block;
+ insert_into_free_memory_list(new_block);
+ }
+ DUMP(this);
+ }
+
+ DBUG_EXECUTE("check_querycache",query_cache.check_integrity(1););
+ STRUCT_UNLOCK(&structure_guard_mutex);
+ DBUG_VOID_RETURN;
+}
+
+
+my_bool Query_cache::move_by_type(byte **border,
+ Query_cache_block **before, ulong *gap,
+ Query_cache_block *block)
+{
+ DBUG_ENTER("Query_cache::move_by_type");
+
+ my_bool ok = 1;
+ switch (block->type) {
+ case Query_cache_block::FREE:
+ {
+ DBUG_PRINT("qcache", ("block 0x%lx FREE", (ulong) block));
+ if (*border == 0)
+ {
+ *border = (byte *) block;
+ *before = block->pprev;
+ DBUG_PRINT("qcache", ("gap beginning here"));
+ }
+ exclude_from_free_memory_list(block);
+ *gap +=block->length;
+ block->pprev->pnext=block->pnext;
+ block->pnext->pprev=block->pprev;
+ block->destroy();
+ total_blocks--;
+ DBUG_PRINT("qcache", ("added to gap (%lu)", *gap));
+ break;
+ }
+ case Query_cache_block::TABLE:
+ {
+ DBUG_PRINT("qcache", ("block 0x%lx TABLE", (ulong) block));
+ if (*border == 0)
+ break;
+ ulong len = block->length, used = block->used;
+ Query_cache_block_table *list_root = block->table(0);
+ Query_cache_block_table *tprev = list_root->prev,
+ *tnext = list_root->next;
+ Query_cache_block *prev = block->prev,
+ *next = block->next,
+ *pprev = block->pprev,
+ *pnext = block->pnext,
+ *new_block =(Query_cache_block *) *border;
+ uint tablename_offset = block->table()->table() - block->table()->db();
+ char *data = (char*) block->data();
+ byte *key;
+ uint key_length;
+ key=query_cache_table_get_key((byte*) block, &key_length, 0);
+ hash_search(&tables, (byte*) key, key_length);
+
+ block->destroy();
+ new_block->init(len);
+ new_block->type=Query_cache_block::TABLE;
+ new_block->used=used;
+ new_block->n_tables=1;
+ memmove((char*) new_block->data(), data, len-new_block->headers_len());
+ relink(block, new_block, next, prev, pnext, pprev);
+ if (tables_blocks[new_block->table()->type()] == block)
+ tables_blocks[new_block->table()->type()] = new_block;
+
+ Query_cache_block_table *nlist_root = new_block->table(0);
+ nlist_root->n = 0;
+ nlist_root->next = tnext;
+ tnext->prev = nlist_root;
+ nlist_root->prev = tprev;
+ tprev->next = nlist_root;
+ DBUG_PRINT("qcache",
+ ("list_root: 0x%lx tnext 0x%lx tprev 0x%lx tprev->next 0x%lx tnext->prev 0x%lx",
+ (ulong) list_root, (ulong) tnext, (ulong) tprev,
+ (ulong)tprev->next, (ulong)tnext->prev));
+ /*
+ Go through all queries that uses this table and change them to
+ point to the new table object
+ */
+ Query_cache_table *new_block_table=new_block->table();
+ for (;tnext != nlist_root; tnext=tnext->next)
+ tnext->parent= new_block_table;
+ *border += len;
+ *before = new_block;
+ /* Fix pointer to table name */
+ new_block->table()->table(new_block->table()->db() + tablename_offset);
+ /* Fix hash to point at moved block */
+ hash_replace(&tables, tables.current_record, (byte*) new_block);
+
+ DBUG_PRINT("qcache", ("moved %lu bytes to 0x%lx, new gap at 0x%lx",
+ len, (ulong) new_block, (ulong) *border));
+ break;
+ }
+ case Query_cache_block::QUERY:
+ {
+ DBUG_PRINT("qcache", ("block 0x%lx QUERY", (ulong) block));
+ if (*border == 0)
+ break;
+ BLOCK_LOCK_WR(block);
+ ulong len = block->length, used = block->used;
+ TABLE_COUNTER_TYPE n_tables = block->n_tables;
+ Query_cache_block *prev = block->prev,
+ *next = block->next,
+ *pprev = block->pprev,
+ *pnext = block->pnext,
+ *new_block =(Query_cache_block*) *border;
+ char *data = (char*) block->data();
+ Query_cache_block *first_result_block = ((Query_cache_query *)
+ block->data())->result();
+ byte *key;
+ uint key_length;
+ key=query_cache_query_get_key((byte*) block, &key_length, 0);
+ hash_search(&queries, (byte*) key, key_length);
+ // Move table of used tables
+ memmove((char*) new_block->table(0), (char*) block->table(0),
+ ALIGN_SIZE(n_tables*sizeof(Query_cache_block_table)));
+ block->query()->unlock_n_destroy();
+ block->destroy();
+ new_block->init(len);
+ new_block->type=Query_cache_block::QUERY;
+ new_block->used=used;
+ new_block->n_tables=n_tables;
+ memmove((char*) new_block->data(), data, len - new_block->headers_len());
+ relink(block, new_block, next, prev, pnext, pprev);
+ if (queries_blocks == block)
+ queries_blocks = new_block;
+ for (TABLE_COUNTER_TYPE j=0; j < n_tables; j++)
+ {
+ Query_cache_block_table *block_table = new_block->table(j);
+ block_table->next->prev = block_table;
+ block_table->prev->next = block_table;
+ }
+ DBUG_PRINT("qcache", ("after circle tt"));
+ *border += len;
+ *before = new_block;
+ new_block->query()->result(first_result_block);
+ if (first_result_block != 0)
+ {
+ Query_cache_block *result_block = first_result_block;
+ do
+ {
+ result_block->result()->parent(new_block);
+ result_block = result_block->next;
+ } while ( result_block != first_result_block );
+ }
+ Query_cache_query *new_query= ((Query_cache_query *) new_block->data());
+ sem_init(&new_query->lock, 0, 1);
+ pthread_mutex_init(&new_query->clients_guard,MY_MUTEX_INIT_FAST);
+
+ /*
+ If someone is writing to this block, inform the writer that the block
+ has been moved.
+ */
+ NET *net = new_block->query()->writer();
+ if (net != 0)
+ {
+ net->query_cache_query= (gptr) new_block;
+ }
+ /* Fix hash to point at moved block */
+ hash_replace(&queries, queries.current_record, (byte*) new_block);
+ DBUG_PRINT("qcache", ("moved %lu bytes to 0x%lx, new gap at 0x%lx",
+ len, (ulong) new_block, (ulong) *border));
+ break;
+ }
+ case Query_cache_block::RES_INCOMPLETE:
+ case Query_cache_block::RES_BEG:
+ case Query_cache_block::RES_CONT:
+ case Query_cache_block::RESULT:
+ {
+ DBUG_PRINT("qcache", ("block 0x%lx RES* (%d)", (ulong) block,
+ (int) block->type));
+ if (*border == 0)
+ break;
+ Query_cache_block *query_block = block->result()->parent(),
+ *next = block->next,
+ *prev = block->prev;
+ Query_cache_block::block_type type = block->type;
+ BLOCK_LOCK_WR(query_block);
+ ulong len = block->length, used = block->used;
+ Query_cache_block *pprev = block->pprev,
+ *pnext = block->pnext,
+ *new_block =(Query_cache_block*) *border;
+ char *data = (char*) block->data();
+ block->destroy();
+ new_block->init(len);
+ new_block->type=type;
+ new_block->used=used;
+ memmove((char*) new_block->data(), data, len - new_block->headers_len());
+ relink(block, new_block, next, prev, pnext, pprev);
+ new_block->result()->parent(query_block);
+ Query_cache_query *query = query_block->query();
+ if (query->result() == block)
+ query->result(new_block);
+ *border += len;
+ *before = new_block;
+ /* If result writing complete && we have free space in block */
+ ulong free_space = new_block->length - new_block->used;
+ if (query->result()->type == Query_cache_block::RESULT &&
+ new_block->length > new_block->used &&
+ *gap + free_space > min_allocation_unit &&
+ new_block->length - free_space > min_allocation_unit)
+ {
+ *border -= free_space;
+ *gap += free_space;
+ new_block->length -= free_space;
+ }
+ BLOCK_UNLOCK_WR(query_block);
+ DBUG_PRINT("qcache", ("moved %lu bytes to 0x%lx, new gap at 0x%lx",
+ len, (ulong) new_block, (ulong) *border));
+ break;
+ }
+ default:
+ DBUG_PRINT("error", ("unexpected block type %d, block 0x%lx",
+ (int)block->type, (ulong) block));
+ ok = 0;
+ }
+ DBUG_RETURN(ok);
+}
+
+
+void Query_cache::relink(Query_cache_block *oblock,
+ Query_cache_block *nblock,
+ Query_cache_block *next, Query_cache_block *prev,
+ Query_cache_block *pnext, Query_cache_block *pprev)
+{
+ if (prev == oblock) //check pointer to himself
+ {
+ nblock->prev = nblock;
+ nblock->next = nblock;
+ }
+ else
+ {
+ nblock->prev = prev;
+ prev->next=nblock;
+ }
+ if (next != oblock)
+ {
+ nblock->next = next;
+ next->prev=nblock;
+ }
+ nblock->pprev = pprev; // Physical pointer to himself have only 1 free block
+ nblock->pnext = pnext;
+ pprev->pnext=nblock;
+ pnext->pprev=nblock;
+}
+
+
+my_bool Query_cache::join_results(ulong join_limit)
+{
+ my_bool has_moving = 0;
+ DBUG_ENTER("Query_cache::join_results");
+
+ STRUCT_LOCK(&structure_guard_mutex);
+ if (queries_blocks != 0)
+ {
+ Query_cache_block *block = queries_blocks;
+ do
+ {
+ Query_cache_query *header = block->query();
+ if (header->result() != 0 &&
+ header->result()->type == Query_cache_block::RESULT &&
+ header->length() > join_limit)
+ {
+ Query_cache_block *new_result_block =
+ get_free_block(header->length() +
+ ALIGN_SIZE(sizeof(Query_cache_block)) +
+ ALIGN_SIZE(sizeof(Query_cache_result)), 1, 0);
+ if (new_result_block != 0)
+ {
+ has_moving = 1;
+ Query_cache_block *first_result = header->result();
+ ulong new_len = (header->length() +
+ ALIGN_SIZE(sizeof(Query_cache_block)) +
+ ALIGN_SIZE(sizeof(Query_cache_result)));
+ if (new_result_block->length >
+ ALIGN_SIZE(new_len) + min_allocation_unit)
+ split_block(new_result_block, ALIGN_SIZE(new_len));
+ BLOCK_LOCK_WR(block);
+ header->result(new_result_block);
+ new_result_block->type = Query_cache_block::RESULT;
+ new_result_block->n_tables = 0;
+ new_result_block->used = new_len;
+
+ new_result_block->next = new_result_block->prev = new_result_block;
+ DBUG_PRINT("qcache", ("new block %lu/%lu (%lu)",
+ new_result_block->length,
+ new_result_block->used,
+ header->length()));
+
+ Query_cache_result *new_result = new_result_block->result();
+ new_result->parent(block);
+ byte *write_to = (byte*) new_result->data();
+ Query_cache_block *result_block = first_result;
+ do
+ {
+ ulong len = (result_block->used - result_block->headers_len() -
+ ALIGN_SIZE(sizeof(Query_cache_result)));
+ DBUG_PRINT("loop", ("add block %lu/%lu (%lu)",
+ result_block->length,
+ result_block->used,
+ len));
+ memcpy((char *) write_to,
+ (char*) result_block->result()->data(),
+ len);
+ write_to += len;
+ Query_cache_block *old_result_block = result_block;
+ result_block = result_block->next;
+ free_memory_block(old_result_block);
+ } while (result_block != first_result);
+ BLOCK_UNLOCK_WR(block);
+ }
+ }
+ block = block->next;
+ } while ( block != queries_blocks );
+ }
+ STRUCT_UNLOCK(&structure_guard_mutex);
+ DBUG_RETURN(has_moving);
+}
+
+
+uint Query_cache::filename_2_table_key (char *key, const char *path)
+{
+ char tablename[FN_REFLEN+2], *filename, *dbname;
+ uint db_length;
+ DBUG_ENTER("Query_cache::filename_2_table_key");
+
+ /* Safety if filename didn't have a directory name */
+ tablename[0]= FN_LIBCHAR;
+ tablename[1]= FN_LIBCHAR;
+ /* Convert filename to this OS's format in tablename */
+ fn_format(tablename + 2, path, "", "", MY_REPLACE_EXT);
+ filename= tablename + dirname_length(tablename + 2) + 2;
+ /* Find start of databasename */
+ for (dbname= filename - 2 ; dbname[-1] != FN_LIBCHAR ; dbname--) ;
+ db_length= (filename - dbname) - 1;
+ DBUG_PRINT("qcache", ("table '%-.*s.%s'", db_length, dbname, filename));
+
+ DBUG_RETURN((uint) (strmov(strmake(key, dbname, db_length) + 1,
+ filename) -key) + 1);
+}
+
+
+/****************************************************************************
+ Functions to be used when debugging
+****************************************************************************/
+
+#if defined(DBUG_OFF) && !defined(USE_QUERY_CACHE_INTEGRITY_CHECK)
+
+void wreck(uint line, const char *message) {}
+void bins_dump() {}
+void cache_dump() {}
+void queries_dump() {}
+void tables_dump() {}
+my_bool check_integrity(bool not_locked) { return 0; }
+my_bool in_list(Query_cache_block * root, Query_cache_block * point,
+ const char *name) { return 0;}
+my_bool in_blocks(Query_cache_block * point) { return 0; }
+
+#else
+
+void Query_cache::wreck(uint line, const char *message)
+{
+ THD *thd=current_thd;
+ DBUG_ENTER("Query_cache::wreck");
+ query_cache_size = 0;
+ if (*message)
+ DBUG_PRINT("error", (" %s", message));
+ DBUG_PRINT("warning", ("=================================="));
+ DBUG_PRINT("warning", ("%5d QUERY CACHE WRECK => DISABLED",line));
+ DBUG_PRINT("warning", ("=================================="));
+ if (thd)
+ thd->killed = 1;
+ cache_dump();
+ /* check_integrity(0); */ /* Can't call it here because of locks */
+ bins_dump();
+ DBUG_VOID_RETURN;
+}
+
+
+void Query_cache::bins_dump()
+{
+ uint i;
+
+ if ( !initialized )
+ {
+ DBUG_PRINT("qcache", ("Query Cache not initialized"));
+ return;
+ }
+
+ DBUG_PRINT("qcache", ("mem_bin_num=%u, mem_bin_steps=%u",
+ mem_bin_num, mem_bin_steps));
+ DBUG_PRINT("qcache", ("-------------------------"));
+ DBUG_PRINT("qcache", (" size idx step"));
+ DBUG_PRINT("qcache", ("-------------------------"));
+ for (i=0; i < mem_bin_steps; i++)
+ {
+ DBUG_PRINT("qcache", ("%10lu %3d %10lu", steps[i].size, steps[i].idx,
+ steps[i].increment));
+ }
+ DBUG_PRINT("qcache", ("-------------------------"));
+ DBUG_PRINT("qcache", (" size num"));
+ DBUG_PRINT("qcache", ("-------------------------"));
+ for (i=0; i < mem_bin_num; i++)
+ {
+ DBUG_PRINT("qcache", ("%10lu %3d 0x%lx", bins[i].size, bins[i].number,
+ (ulong)&(bins[i])));
+ if (bins[i].free_blocks)
+ {
+ Query_cache_block *block = bins[i].free_blocks;
+ do{
+ DBUG_PRINT("qcache", ("\\-- %lu 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx",
+ block->length, (ulong)block,
+ (ulong)block->next, (ulong)block->prev,
+ (ulong)block->pnext, (ulong)block->pprev));
+ block = block->next;
+ } while ( block != bins[i].free_blocks );
+ }
+ }
+ DBUG_PRINT("qcache", ("-------------------------"));
+}
+
+
+void Query_cache::cache_dump()
+{
+
+ if ( !initialized )
+ {
+ DBUG_PRINT("qcache", ("Query Cache not initialized"));
+ return;
+ }
+
+ DBUG_PRINT("qcache", ("-------------------------------------"));
+ DBUG_PRINT("qcache", (" length used t nt"));
+ DBUG_PRINT("qcache", ("-------------------------------------"));
+ Query_cache_block *i = first_block;
+ do
+ {
+ DBUG_PRINT("qcache",
+ ("%10lu %10lu %1d %2d 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx",
+ i->length, i->used, (int)i->type,
+ i->n_tables, (ulong)i,
+ (ulong)i->next, (ulong)i->prev, (ulong)i->pnext,
+ (ulong)i->pprev));
+ i = i->pnext;
+ } while ( i != first_block );
+ DBUG_PRINT("qcache", ("-------------------------------------"));
+}
+
+
+void Query_cache::queries_dump()
+{
+
+ if ( !initialized )
+ {
+ DBUG_PRINT("qcache", ("Query Cache not initialized"));
+ return;
+ }
+
+ DBUG_PRINT("qcache", ("------------------"));
+ DBUG_PRINT("qcache", (" QUERIES"));
+ DBUG_PRINT("qcache", ("------------------"));
+ if (queries_blocks != 0)
+ {
+ Query_cache_block *block = queries_blocks;
+ do
+ {
+ uint len;
+ char *str = (char*) query_cache_query_get_key((byte*) block, &len, 0);
+ len--; // Point at flags
+ uint flags = (uint) (uchar) str[len];
+ str[len]=0;
+ DBUG_PRINT("qcache", ("%u (%u,%u) '%s' '%s'",
+ ((flags & QUERY_CACHE_CLIENT_LONG_FLAG_MASK)? 1:0),
+ (flags & QUERY_CACHE_CHARSET_CONVERT_MASK), len,
+ str,strend(str)+1));
+ DBUG_PRINT("qcache", ("-b- 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx", (ulong) block,
+ (ulong) block->next, (ulong) block->prev,
+ (ulong)block->pnext, (ulong)block->pprev));
+ str[len]=(char) flags;
+ for (TABLE_COUNTER_TYPE t = 0; t < block->n_tables; t++)
+ {
+ Query_cache_table *table = block->table(t)->parent;
+ DBUG_PRINT("qcache", ("-t- '%s' '%s'", table->db(), table->table()));
+ }
+ Query_cache_query *header = block->query();
+ if (header->result())
+ {
+ Query_cache_block *result_block = header->result();
+ Query_cache_block *result_beg = result_block;
+ do
+ {
+ DBUG_PRINT("qcache", ("-r- %u %lu/%lu 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx",
+ (uint) result_block->type,
+ result_block->length, result_block->used,
+ (ulong) result_block,
+ (ulong) result_block->next,
+ (ulong) result_block->prev,
+ (ulong) result_block->pnext,
+ (ulong) result_block->pprev));
+ result_block = result_block->next;
+ } while ( result_block != result_beg );
+ }
+ } while ((block=block->next) != queries_blocks);
+ }
+ else
+ {
+ DBUG_PRINT("qcache", ("no queries in list"));
+ }
+ DBUG_PRINT("qcache", ("------------------"));
+}
+
+
+void Query_cache::tables_dump()
+{
+
+ if ( !initialized )
+ {
+ DBUG_PRINT("qcache", ("Query Cache not initialized"));
+ return;
+ }
+
+ DBUG_PRINT("qcache", ("--------------------"));
+ DBUG_PRINT("qcache", ("TABLES"));
+ DBUG_PRINT("qcache", ("--------------------"));
+ for (int i=0; i < (int) Query_cache_table::TYPES_NUMBER; i++)
+ {
+ DBUG_PRINT("qcache", ("--- type %u", i));
+ if (tables_blocks[i] != 0)
+ {
+ Query_cache_block *table_block = tables_blocks[i];
+ do
+ {
+ Query_cache_table *table = table_block->table();
+ DBUG_PRINT("qcache", ("'%s' '%s'", table->db(), table->table()));
+ table_block = table_block->next;
+ } while ( table_block != tables_blocks[i]);
+ }
+ else
+ DBUG_PRINT("qcache", ("no tables in list"));
+ }
+ DBUG_PRINT("qcache", ("--------------------"));
+}
+
+
+my_bool Query_cache::check_integrity(bool not_locked)
+{
+ my_bool result = 0;
+ uint i;
+ DBUG_ENTER("check_integrity");
+
+ if (query_cache_size == 0)
+ {
+ DBUG_PRINT("qcache", ("Query Cache not initialized"));
+ DBUG_RETURN(0);
+ }
+ if (!not_locked)
+ STRUCT_LOCK(&structure_guard_mutex);
+
+ if (hash_check(&queries))
+ {
+ DBUG_PRINT("error", ("queries hash is damaged"));
+ result = 1;
+ }
+
+ if (hash_check(&tables))
+ {
+ DBUG_PRINT("error", ("tables hash is damaged"));
+ result = 1;
+ }
+
+ DBUG_PRINT("qcache", ("physical address check ..."));
+ ulong free=0, used=0;
+ Query_cache_block * block = first_block;
+ do
+ {
+ DBUG_PRINT("qcache", ("block 0x%lx, type %u...",
+ (ulong) block, (uint) block->type));
+ // Check memory allocation
+ if (block->pnext == first_block) // Is it last block?
+ {
+ if ( ((byte*)block) + block->length !=
+ ((byte*)first_block) + query_cache_size )
+ {
+ DBUG_PRINT("error",
+ ("block 0x%lx, type %u, ended at 0x%lx, but cache ended at 0x%lx",
+ (ulong) block, (uint) block->type,
+ (ulong) (((byte*)block) + block->length),
+ (ulong) (((byte*)first_block) + query_cache_size)));
+ result = 1;
+ }
+ }
+ else
+ if (((byte*)block) + block->length != ((byte*)block->pnext))
+ {
+ DBUG_PRINT("error",
+ ("block 0x%lx, type %u, ended at 0x%lx, but next block begining at 0x%lx",
+ (ulong) block, (uint) block->type,
+ (ulong) (((byte*)block) + block->length),
+ (ulong) ((byte*)block->pnext)));
+ }
+ if (block->type == Query_cache_block::FREE)
+ free+=block->length;
+ else
+ used+=block->length;
+ switch(block->type) {
+ case Query_cache_block::FREE:
+ {
+ Query_cache_memory_bin *bin = *((Query_cache_memory_bin **)
+ block->data());
+ //is it correct pointer?
+ if ( ((byte*)bin) < ((byte*)bins) ||
+ ((byte*)bin) >= ((byte*)first_block))
+ {
+ DBUG_PRINT("error",
+ ("free block 0x%lx have bin pointer 0x%lx beyaond of bins array bounds [0x%lx,0x%lx]",
+ (ulong) block,
+ (ulong) bin,
+ (ulong) bins,
+ (ulong) first_block));
+ result = 1;
+ }
+ else
+ {
+ int idx = (((byte*)bin) - ((byte*)bins)) /
+ sizeof(Query_cache_memory_bin);
+ if (in_list(bins[idx].free_blocks, block, "free memory"))
+ result = 1;
+ }
+ break;
+ }
+ case Query_cache_block::TABLE:
+ if (in_list(tables_blocks[block->table()->type()], block, "tables"))
+ result = 1;
+ if (in_table_list(block->table(0), block->table(0), "table list root"))
+ result = 1;
+ break;
+ case Query_cache_block::QUERY:
+ {
+ if (in_list(queries_blocks, block, "query"))
+ result = 1;
+ for (TABLE_COUNTER_TYPE j=0; j < block->n_tables; j++)
+ {
+ Query_cache_block_table *block_table = block->table(j);
+ Query_cache_block_table *block_table_root =
+ (Query_cache_block_table *)
+ (((byte*)block_table->parent) -
+ ALIGN_SIZE(sizeof(Query_cache_block_table)));
+
+ if (in_table_list(block_table, block_table_root, "table list"))
+ result = 1;
+ }
+ break;
+ }
+ case Query_cache_block::RES_INCOMPLETE:
+ // This type of block can be not lincked yet (in multithread environment)
+ break;
+ case Query_cache_block::RES_BEG:
+ case Query_cache_block::RES_CONT:
+ case Query_cache_block::RESULT:
+ {
+ Query_cache_block * query_block = block->result()->parent();
+ if ( ((byte*)query_block) < ((byte*)first_block) ||
+ ((byte*)query_block) >= (((byte*)first_block) + query_cache_size))
+ {
+ DBUG_PRINT("error",
+ ("result block 0x%lx have query block pointer 0x%lx beyaond of block pool bounds [0x%lx,0x%lx]",
+ (ulong) block,
+ (ulong) query_block,
+ (ulong) first_block,
+ (ulong) (((byte*)first_block) + query_cache_size)));
+ result = 1;
+ }
+ else
+ {
+ BLOCK_LOCK_RD(query_block);
+ if (in_list(queries_blocks, query_block, "query from results"))
+ result = 1;
+ if (in_list(query_block->query()->result(), block,
+ "results"))
+ result = 1;
+ BLOCK_UNLOCK_RD(query_block);
+ }
+ break;
+ }
+ default:
+ DBUG_PRINT("error",
+ ("block 0x%lx have incorrect type %u",
+ block, block->type));
+ result = 1;
+ }
+
+ block = block->pnext;
+ } while (block != first_block);
+
+ if (used + free != query_cache_size)
+ {
+ DBUG_PRINT("error",
+ ("used memory (%lu) + free memory (%lu) != query_cache_size (%lu)",
+ used, free, query_cache_size));
+ result = 1;
+ }
+
+ if (free != free_memory)
+ {
+ DBUG_PRINT("error",
+ ("free memory (%lu) != free_memory (%lu)",
+ free, free_memory));
+ result = 1;
+ }
+
+ DBUG_PRINT("qcache", ("check queries ..."));
+ if ((block = queries_blocks))
+ {
+ do
+ {
+ DBUG_PRINT("qcache", ("block 0x%lx, type %u...",
+ (ulong) block, (uint) block->type));
+ uint length;
+ byte *key = query_cache_query_get_key((byte*) block, &length, 0);
+ gptr val = hash_search(&queries, key, length);
+ if (((gptr)block) != val)
+ {
+ DBUG_PRINT("error", ("block 0x%lx found in queries hash like 0x%lx",
+ (ulong) block, (ulong) val));
+ }
+ if (in_blocks(block))
+ result = 1;
+ Query_cache_block * results = block->query()->result();
+ if (results)
+ {
+ Query_cache_block * result_block = results;
+ do
+ {
+ DBUG_PRINT("qcache", ("block 0x%lx, type %u...",
+ (ulong) block, (uint) block->type));
+ if (in_blocks(result_block))
+ result = 1;
+
+ result_block = result_block->next;
+ } while (result_block != results);
+ }
+ block = block->next;
+ } while (block != queries_blocks);
+ }
+
+ DBUG_PRINT("qcache", ("check tables ..."));
+ for (i=0 ; (int) i < (int) Query_cache_table::TYPES_NUMBER; i++)
+ {
+ if ((block = tables_blocks[i]))
+ {
+ do
+ {
+ DBUG_PRINT("qcache", ("block 0x%lx, type %u...",
+ (ulong) block, (uint) block->type));
+ uint length;
+ byte *key = query_cache_table_get_key((byte*) block, &length, 0);
+ gptr val = hash_search(&tables, key, length);
+ if (((gptr)block) != val)
+ {
+ DBUG_PRINT("error", ("block 0x%lx found in tables hash like 0x%lx",
+ (ulong) block, (ulong) val));
+ }
+
+ if (in_blocks(block))
+ result = 1;
+ block=block->next;
+ } while (block != tables_blocks[i]);
+ }
+ }
+
+ DBUG_PRINT("qcache", ("check free blocks"));
+ for (i = 0; i < mem_bin_num; i++)
+ {
+ if ((block = bins[i].free_blocks))
+ {
+ uint count = 0;
+ do
+ {
+ DBUG_PRINT("qcache", ("block 0x%lx, type %u...",
+ (ulong) block, (uint) block->type));
+ if (in_blocks(block))
+ result = 1;
+
+ count++;
+ block=block->next;
+ } while (block != bins[i].free_blocks);
+ if (count != bins[i].number)
+ {
+ DBUG_PRINT("error", ("bin[%d].number is %d, but bin have %d blocks",
+ bins[i].number, count));
+ result = 1;
+ }
+ }
+ }
+ DBUG_ASSERT(result == 0);
+ if (!not_locked)
+ STRUCT_UNLOCK(&structure_guard_mutex);
+ DBUG_RETURN(result);
+}
+
+
+my_bool Query_cache::in_blocks(Query_cache_block * point)
+{
+ my_bool result = 0;
+ Query_cache_block *block = point;
+ //back
+ do
+ {
+ if (block->pprev->pnext != block)
+ {
+ DBUG_PRINT("error",
+ ("block 0x%lx in physical list is incorrect linked, prev block 0x%lx refered as next to 0x%lx (check from 0x%lx)",
+ (ulong) block, (ulong) block->pprev,
+ (ulong) block->pprev->pnext,
+ (ulong) point));
+ //back trace
+ for(; block != point; block = block->pnext)
+ DBUG_PRINT("error", ("back trace 0x%lx", (ulong) block));
+ result = 1;
+ goto err1;
+ }
+ block = block->pprev;
+ } while (block != first_block && block != point);
+ if (block != first_block)
+ {
+ DBUG_PRINT("error",
+ ("block 0x%lx (0x%lx<-->0x%lx) not owned by pysical list",
+ (ulong) block, (ulong) block->pprev, (ulong )block->pnext));
+ return 1;
+ }
+
+err1:
+ //forward
+ block = point;
+ do
+ {
+ if (block->pnext->pprev != block)
+ {
+ DBUG_PRINT("error",
+ ("block 0x%lx in physicel list is incorrect linked, next block 0x%lx refered as prev to 0x%lx (check from 0x%lx)",
+ (ulong) block, (ulong) block->pnext,
+ (ulong) block->pnext->pprev,
+ (ulong) point));
+ //back trace
+ for(; block != point; block = block->pprev)
+ DBUG_PRINT("error", ("back trace 0x%lx", (ulong) block));
+ result = 1;
+ goto err2;
+ }
+ block = block->pnext;
+ } while (block != first_block);
+err2:
+ return result;
+}
+
+
+my_bool Query_cache::in_list(Query_cache_block * root,
+ Query_cache_block * point,
+ const char *name)
+{
+ my_bool result = 0;
+ Query_cache_block *block = point;
+ //back
+ do
+ {
+ if (block->prev->next != block)
+ {
+ DBUG_PRINT("error",
+ ("block 0x%lx in list '%s' 0x%lx is incorrect linked, prev block 0x%lx refered as next to 0x%lx (check from 0x%lx)",
+ (ulong) block, name, (ulong) root, (ulong) block->prev,
+ (ulong) block->prev->next,
+ (ulong) point));
+ //back trace
+ for(; block != point; block = block->next)
+ DBUG_PRINT("error", ("back trace 0x%lx", (ulong) block));
+ result = 1;
+ goto err1;
+ }
+ block = block->prev;
+ } while (block != root && block != point);
+ if (block != root)
+ {
+ DBUG_PRINT("error",
+ ("block 0x%lx (0x%lx<-->0x%lx) not owned by list '%s' 0x%lx",
+ (ulong) block,
+ (ulong) block->prev, (ulong) block->next,
+ name, (ulong) root));
+ return 1;
+ }
+err1:
+ // forward
+ block = point;
+ do
+ {
+ if (block->next->prev != block)
+ {
+ DBUG_PRINT("error",
+ ("block 0x%lx in list '%s' 0x%lx is incorrect linked, next block 0x%lx refered as prev to 0x%lx (check from 0x%lx)",
+ (ulong) block, name, (ulong) root, (ulong) block->next,
+ (ulong) block->next->prev,
+ (ulong) point));
+ //back trace
+ for (; block != point; block = block->prev)
+ DBUG_PRINT("error", ("back trace 0x%lx", (ulong) block));
+ result = 1;
+ goto err2;
+ }
+ block = block->next;
+ } while (block != root);
+err2:
+ return result;
+}
+
+void dump_node(Query_cache_block_table * node,
+ const char * call, const char * descr)
+{
+ DBUG_PRINT("qcache", ("%s: %s: node: 0x%lx", call, descr, (ulong) node));
+ DBUG_PRINT("qcache", ("%s: %s: node block: 0x%lx",
+ call, descr, (ulong) node->block()));
+ DBUG_PRINT("qcache", ("%s: %s: next: 0x%lx", call, descr,
+ (ulong) node->next));
+ DBUG_PRINT("qcache", ("%s: %s: prev: 0x%lx", call, descr,
+ (ulong) node->prev));
+}
+
+my_bool Query_cache::in_table_list(Query_cache_block_table * root,
+ Query_cache_block_table * point,
+ const char *name)
+{
+ my_bool result = 0;
+ Query_cache_block_table *table = point;
+ dump_node(root, name, "parameter root");
+ //back
+ do
+ {
+ dump_node(table, name, "list element << ");
+ if (table->prev->next != table)
+ {
+ DBUG_PRINT("error",
+ ("table 0x%lx(0x%lx) in list '%s' 0x%lx(0x%lx) is incorrect linked, prev table 0x%lx(0x%lx) refered as next to 0x%lx(0x%lx) (check from 0x%lx(0x%lx))",
+ (ulong) table, (ulong) table->block(), name,
+ (ulong) root, (ulong) root->block(),
+ (ulong) table->prev, (ulong) table->prev->block(),
+ (ulong) table->prev->next,
+ (ulong) table->prev->next->block(),
+ (ulong) point, (ulong) point->block()));
+ //back trace
+ for(; table != point; table = table->next)
+ DBUG_PRINT("error", ("back trace 0x%lx(0x%lx)",
+ (ulong) table, (ulong) table->block()));
+ result = 1;
+ goto err1;
+ }
+ table = table->prev;
+ } while (table != root && table != point);
+ if (table != root)
+ {
+ DBUG_PRINT("error",
+ ("table 0x%lx(0x%lx) (0x%lx(0x%lx)<-->0x%lx(0x%lx)) not owned by list '%s' 0x%lx(0x%lx)",
+ (ulong) table, (ulong) table->block(),
+ (ulong) table->prev, (ulong) table->prev->block(),
+ (ulong) table->next, (ulong) table->next->block(),
+ name, (ulong) root, (ulong) root->block()));
+ return 1;
+ }
+err1:
+ // forward
+ table = point;
+ do
+ {
+ dump_node(table, name, "list element >> ");
+ if (table->next->prev != table)
+ {
+ DBUG_PRINT("error",
+ ("table 0x%lx(0x%lx) in list '%s' 0x%lx(0x%lx) is incorrect linked, next table 0x%lx(0x%lx) refered as prev to 0x%lx(0x%lx) (check from 0x%lx(0x%lx))",
+ (ulong) table, (ulong) table->block(),
+ name, (ulong) root, (ulong) root->block(),
+ (ulong) table->next, (ulong) table->next->block(),
+ (ulong) table->next->prev,
+ (ulong) table->next->prev->block(),
+ (ulong) point, (ulong) point->block()));
+ //back trace
+ for (; table != point; table = table->prev)
+ DBUG_PRINT("error", ("back trace 0x%lx(0x%lx)",
+ (ulong) table, (ulong) table->block()));
+ result = 1;
+ goto err2;
+ }
+ table = table->next;
+ } while (table != root);
+err2:
+ return result;
+}
+
+#endif /* DBUG_OFF */
diff --git a/sql/sql_cache.h b/sql/sql_cache.h
new file mode 100644
index 00000000000..b1d8eb23198
--- /dev/null
+++ b/sql/sql_cache.h
@@ -0,0 +1,418 @@
+/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef _SQL_CACHE_H
+#define _SQL_CACHE_H
+
+/* Query cache */
+
+/*
+ Can't create new free memory block if unused memory in block less
+ then QUERY_CACHE_MIN_ALLOCATION_UNIT.
+ if QUERY_CACHE_MIN_ALLOCATION_UNIT == 0 then
+ QUERY_CACHE_MIN_ALLOCATION_UNIT choosed automaticaly
+*/
+#define QUERY_CACHE_MIN_ALLOCATION_UNIT 512
+
+/* inittial size of hashes */
+#define QUERY_CACHE_DEF_QUERY_HASH_SIZE 1024
+#define QUERY_CACHE_DEF_TABLE_HASH_SIZE 1024
+
+/* minimal result data size when data allocated */
+#define QUERY_CACHE_MIN_RESULT_DATA_SIZE 1024*4
+
+/*
+ start estimation of first result block size only when number of queries
+ bigger then:
+*/
+#define QUERY_CACHE_MIN_ESTIMATED_QUERIES_NUMBER 3
+
+
+
+/* memory bins size spacing (see at Query_cache::init_cache (sql_cache.cc)) */
+#define QUERY_CACHE_MEM_BIN_FIRST_STEP_PWR2 4
+#define QUERY_CACHE_MEM_BIN_STEP_PWR2 2
+#define QUERY_CACHE_MEM_BIN_PARTS_INC 1
+#define QUERY_CACHE_MEM_BIN_PARTS_MUL 1.2
+#define QUERY_CACHE_MEM_BIN_SPC_LIM_PWR2 3
+
+/* how many free blocks check when finding most suitable before other 'end'
+ of list of free blocks */
+#define QUERY_CACHE_MEM_BIN_TRY 5
+
+/* query flags masks */
+#define QUERY_CACHE_CLIENT_LONG_FLAG_MASK 0x80
+#define QUERY_CACHE_CHARSET_CONVERT_MASK 0x7F
+
+/* packing parameters */
+#define QUERY_CACHE_PACK_ITERATION 2
+#define QUERY_CACHE_PACK_LIMIT (512*1024L)
+
+#define TABLE_COUNTER_TYPE uint8
+
+#include <my_semaphore.h>
+
+struct Query_cache_block;
+struct Query_cache_block_table;
+struct Query_cache_table;
+struct Query_cache_query;
+struct Query_cache_result;
+class Query_cache;
+
+
+struct Query_cache_block_table
+{
+ TABLE_COUNTER_TYPE n; // numbr in table (from 0)
+ Query_cache_block_table *next, *prev;
+ Query_cache_table *parent;
+ inline Query_cache_block *block();
+};
+
+
+struct Query_cache_block
+{
+ enum block_type {FREE, QUERY, RESULT, RES_CONT, RES_BEG,
+ RES_INCOMPLETE, TABLE, INCOMPLETE};
+
+ ulong length; // length of all block
+ ulong used; // length of data
+ /*
+ Not used **pprev, **prev because really needed access to pervious block:
+ *pprev to join free blocks
+ *prev to access to opposite side of list in cyclic sorted list
+ */
+ Query_cache_block *pnext,*pprev, // physical next/previous block
+ *next,*prev; // logical next/previous block
+ block_type type;
+ TABLE_COUNTER_TYPE n_tables; // number of tables in query
+
+ inline my_bool is_free(void) { return type == FREE; }
+ void init(ulong length);
+ void destroy();
+ inline uint headers_len();
+ inline gptr data(void);
+ inline Query_cache_query *query();
+ inline Query_cache_table *table();
+ inline Query_cache_result *result();
+ inline Query_cache_block_table *table(TABLE_COUNTER_TYPE n);
+};
+
+
+struct Query_cache_query
+{
+ ulonglong limit_found_rows;
+ Query_cache_block *res;
+ NET *wri;
+ ulong len;
+ sem_t lock; // R/W lock of block
+ pthread_mutex_t clients_guard;
+ uint clients;
+
+ inline void init_n_lock();
+ void unlock_n_destroy();
+ inline ulonglong found_rows() { return limit_found_rows; }
+ inline void found_rows(ulonglong rows) { limit_found_rows = rows; }
+ inline Query_cache_block *result() { return res; }
+ inline void result(Query_cache_block *p) { res=p; }
+ inline NET *writer() { return wri; }
+ inline void writer(NET *p) { wri=p; }
+ inline ulong length() { return len; }
+ inline ulong add(ulong packet_len) { return(len += packet_len); }
+ inline void length(ulong length) { len = length; }
+ inline gptr query()
+ {
+ return (gptr)(((byte*)this)+
+ ALIGN_SIZE(sizeof(Query_cache_query)));
+ }
+ void lock_writing();
+ void lock_reading();
+ my_bool try_lock_writing();
+ void unlock_writing();
+ void unlock_reading();
+ static byte *cache_key(const byte *record, uint *length, my_bool not_used);
+};
+
+
+struct Query_cache_table
+{
+ enum query_cache_table_type {OTHER=0, INNODB=1, TYPES_NUMBER=2};
+ inline static query_cache_table_type type_convertion(db_type type)
+ {
+ return (type == DB_TYPE_INNODB ? INNODB : OTHER);
+ }
+
+ char *tbl;
+ query_cache_table_type tp;
+
+ inline query_cache_table_type type() { return tp; }
+ inline void type(query_cache_table_type t) { tp = t;}
+ inline char *db() { return (char *) data(); }
+ inline char *table() { return tbl; }
+ inline void table(char *table) { tbl = table; }
+ inline gptr data()
+ {
+ return (gptr)(((byte*)this)+
+ ALIGN_SIZE(sizeof(Query_cache_table)));
+ }
+};
+
+struct Query_cache_result
+{
+ Query_cache_block *query;
+
+ inline gptr data()
+ {
+ return (gptr)(((byte*) this)+
+ ALIGN_SIZE(sizeof(Query_cache_result)));
+ }
+ /* data_continue (if not whole packet contained by this block) */
+ inline Query_cache_block *parent() { return query; }
+ inline void parent (Query_cache_block *p) { query=p; }
+};
+
+
+extern "C" {
+ byte *query_cache_query_get_key(const byte *record, uint *length,
+ my_bool not_used);
+ byte *query_cache_table_get_key(const byte *record, uint *length,
+ my_bool not_used);
+ void query_cache_insert(THD *thd, const char *packet, ulong length);
+ void query_cache_end_of_result(THD *thd);
+ void query_cache_abort(THD *thd);
+ void query_cache_invalidate_by_MyISAM_filename(const char* filename);
+}
+
+struct Query_cache_memory_bin
+{
+#ifndef DBUG_OFF
+ ulong size;
+#endif
+ uint number;
+ Query_cache_block *free_blocks;
+
+ inline void init(ulong size)
+ {
+#ifndef DBUG_OFF
+ this->size = size;
+#endif
+ number = 0;
+ free_blocks = 0;
+ }
+};
+
+struct Query_cache_memory_bin_step
+{
+ ulong size;
+ ulong increment;
+ uint idx;
+ inline void init(ulong size, uint idx, ulong increment)
+ {
+ this->size = size;
+ this->idx = idx;
+ this->increment = increment;
+ }
+};
+
+class Query_cache
+{
+public:
+ /* Info */
+ ulong query_cache_size, query_cache_limit;
+ /* statistics */
+ ulong free_memory, queries_in_cache, hits, inserts, refused,
+ free_memory_blocks, total_blocks;
+
+protected:
+ /*
+ The following mutex is locked when searching or changing global
+ query, tables lists or hashes. When we are operating inside the
+ query structure we locked an internal query block mutex.
+ LOCK SEQUENCE (to prevent deadlocks):
+ 1. structure_guard_mutex
+ 2. query block (for operation inside query (query block/results))
+ */
+ pthread_mutex_t structure_guard_mutex;
+ byte *cache; // cache memory
+ Query_cache_block *first_block; // physical location block list
+ Query_cache_block *queries_blocks; // query list (LIFO)
+ Query_cache_block *tables_blocks[Query_cache_table::TYPES_NUMBER];
+
+ Query_cache_memory_bin *bins; // free block lists
+ Query_cache_memory_bin_step *steps; // bins spacing info
+ HASH queries, tables;
+ /* options */
+ ulong min_allocation_unit, min_result_data_size;
+ uint def_query_hash_size, def_table_hash_size;
+ uint mem_bin_num, mem_bin_steps; // See at init_cache & find_bin
+
+ my_bool initialized;
+
+ /* Exclude/include from cyclic double linked list */
+ static void double_linked_list_exclude(Query_cache_block *point,
+ Query_cache_block **list_pointer);
+ static void double_linked_list_simple_include(Query_cache_block *point,
+ Query_cache_block **
+ list_pointer);
+ static void double_linked_list_join(Query_cache_block *head_tail,
+ Query_cache_block *tail_head);
+
+ /* Table key generation */
+ static uint filename_2_table_key (char *key, const char *filename);
+
+ /* The following functions require that structure_guard_mutex is locked */
+ void flush_cache();
+ my_bool free_old_query();
+ void free_query(Query_cache_block *point);
+ my_bool allocate_data_chain(Query_cache_block **result_block,
+ ulong data_len,
+ Query_cache_block *query_block,
+ my_bool first_block);
+ void invalidate_table(TABLE_LIST *table);
+ void invalidate_table(TABLE *table);
+ void invalidate_table(Query_cache_block *table_block);
+ my_bool register_all_tables(Query_cache_block *block,
+ TABLE_LIST *tables_used,
+ TABLE_COUNTER_TYPE tables);
+ my_bool insert_table(uint key_len, char *key,
+ Query_cache_block_table *node,
+ Query_cache_table::query_cache_table_type type);
+ void unlink_table(Query_cache_block_table *node);
+ Query_cache_block *get_free_block (ulong len, my_bool not_less,
+ ulong min);
+ void free_memory_block(Query_cache_block *point);
+ void split_block(Query_cache_block *block, ulong len);
+ Query_cache_block *join_free_blocks(Query_cache_block *first_block,
+ Query_cache_block *block_in_list);
+ my_bool append_next_free_block(Query_cache_block *block,
+ ulong add_size);
+ void exclude_from_free_memory_list(Query_cache_block *free_block);
+ void insert_into_free_memory_list(Query_cache_block *new_block);
+ my_bool move_by_type(byte **border, Query_cache_block **before,
+ ulong *gap, Query_cache_block *i);
+ uint find_bin(ulong size);
+ void move_to_query_list_end(Query_cache_block *block);
+ void insert_into_free_memory_sorted_list(Query_cache_block *new_block,
+ Query_cache_block **list);
+ void pack_cache();
+ void relink(Query_cache_block *oblock,
+ Query_cache_block *nblock,
+ Query_cache_block *next,
+ Query_cache_block *prev,
+ Query_cache_block *pnext,
+ Query_cache_block *pprev);
+ my_bool join_results(ulong join_limit);
+
+ /*
+ Following function control structure_guard_mutex
+ by themself or don't need structure_guard_mutex
+ */
+ void init();
+ ulong init_cache();
+ void make_disabled();
+ void free_cache(my_bool destruction);
+ Query_cache_block *write_block_data(ulong data_len, gptr data,
+ ulong header_len,
+ Query_cache_block::block_type type,
+ TABLE_COUNTER_TYPE ntab = 0,
+ my_bool under_guard=0);
+ my_bool append_result_data(Query_cache_block **result,
+ ulong data_len, gptr data,
+ Query_cache_block *parent);
+ my_bool write_result_data(Query_cache_block **result,
+ ulong data_len, gptr data,
+ Query_cache_block *parent,
+ Query_cache_block::block_type
+ type=Query_cache_block::RESULT);
+ inline ulong get_min_first_result_data_size();
+ inline ulong get_min_append_result_data_size();
+ Query_cache_block *allocate_block(ulong len, my_bool not_less,
+ ulong min,
+ my_bool under_guard=0);
+ /*
+ If query is cacheable return number tables in query
+ (query without tables not cached)
+ */
+ TABLE_COUNTER_TYPE is_cacheable(THD *thd, uint32 query_len, char *query,
+ LEX *lex, TABLE_LIST *tables_used);
+ public:
+
+ Query_cache(ulong query_cache_limit = ULONG_MAX,
+ ulong min_allocation_unit = QUERY_CACHE_MIN_ALLOCATION_UNIT,
+ ulong min_result_data_size = QUERY_CACHE_MIN_RESULT_DATA_SIZE,
+ uint def_query_hash_size = QUERY_CACHE_DEF_QUERY_HASH_SIZE,
+ uint def_table_hash_size = QUERY_CACHE_DEF_TABLE_HASH_SIZE);
+
+ /* resize query cache (return real query size, 0 if disabled) */
+ ulong resize(ulong query_cache_size);
+ inline void result_size_limit(ulong limit){query_cache_limit=limit;}
+
+ /* register query in cache */
+ void store_query(THD *thd, TABLE_LIST *used_tables);
+
+ /*
+ Check if the query is in the cache and if this is true send the
+ data to client.
+ */
+ int send_result_to_client(THD *thd, char *query, uint query_length);
+
+ /* Remove all queries that uses any of the listed following tables */
+ void invalidate(TABLE_LIST *tables_used);
+ void invalidate(TABLE *table);
+
+ /* Remove all queries that uses tables of pointed type*/
+ void invalidate(Query_cache_table::query_cache_table_type type);
+
+ /* Remove all queries that uses any of the tables in following database */
+ void invalidate(char *db);
+
+ /* Remove all queries that uses any of the listed following table */
+ void invalidate_by_MyISAM_filename(const char *filename);
+
+ void flush();
+ void pack(ulong join_limit = QUERY_CACHE_PACK_LIMIT,
+ uint iteration_limit = QUERY_CACHE_PACK_ITERATION);
+
+ void destroy();
+
+ friend void query_cache_insert(NET *net, const char *packet, ulong length);
+ friend void query_cache_end_of_result(NET *net);
+ friend void query_cache_abort(NET *net);
+
+ /*
+ The following functions are only used when debugging
+ We don't protect these with ifndef DEBUG_OFF to not have to recompile
+ everything if we want to add checks of the cache at some places.
+ */
+ void wreck(uint line, const char *message);
+ void bins_dump();
+ void cache_dump();
+ void queries_dump();
+ void tables_dump();
+ my_bool check_integrity(bool not_locked);
+ my_bool in_list(Query_cache_block * root, Query_cache_block * point,
+ const char *name);
+ my_bool in_table_list(Query_cache_block_table * root,
+ Query_cache_block_table * point,
+ const char *name);
+ my_bool in_blocks(Query_cache_block * point);
+};
+
+extern Query_cache query_cache;
+void query_cache_insert(NET *net, const char *packet, ulong length);
+void query_cache_end_of_result(NET *net);
+void query_cache_abort(NET *net);
+
+#endif
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index ace7c291ed3..f6f66b0b7da 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -49,6 +49,8 @@ template class List<Alter_drop>;
template class List_iterator<Alter_drop>;
template class List<Alter_column>;
template class List_iterator<Alter_column>;
+template class List<Set_option>;
+template class List_iterator<Set_option>;
#endif
/****************************************************************************
@@ -80,22 +82,23 @@ THD::THD():user_time(0),fatal_error(0),last_insert_id_used(0),
global_read_lock(0),bootstrap(0)
{
host=user=priv_user=db=query=ip=0;
+ host_or_ip="unknown ip";
locked=killed=count_cuted_fields=some_tables_deleted=no_errors=password=
- query_start_used=0;
- query_length=col_access=0;
+ query_start_used=safe_to_cache_query=0;
+ db_length=query_length=col_access=0;
query_error=0;
next_insert_id=last_insert_id=0;
- open_tables=temporary_tables=0;
+ open_tables=temporary_tables=handler_tables=0;
+ handler_items=0;
tmp_table=0;
lock=locked_tables=0;
used_tables=0;
- gemini_spin_retries=0;
cuted_fields=sent_row_count=0L;
start_time=(time_t) 0;
current_linfo = 0;
slave_thread = 0;
slave_proxy_id = 0;
- last_nx_table = last_nx_db = 0;
+ file_id = 0;
cond_count=0;
convert_set=0;
mysys_var=0;
@@ -105,9 +108,6 @@ THD::THD():user_time(0),fatal_error(0),last_insert_id_used(0),
#ifdef __WIN__
real_id = 0;
#endif
-#ifdef HAVE_GEMINI_DB
- bzero((char *)&gemini, sizeof(gemini));
-#endif
#ifdef SIGNAL_WITH_VIO_CLOSE
active_vio = 0;
pthread_mutex_init(&active_vio_lock, MY_MUTEX_INIT_FAST);
@@ -117,9 +117,12 @@ THD::THD():user_time(0),fatal_error(0),last_insert_id_used(0),
proc_info="login";
where="field list";
server_id = ::server_id;
+ slave_net = 0;
+ log_pos = 0;
server_status=SERVER_STATUS_AUTOCOMMIT;
update_lock_default= low_priority_updates ? TL_WRITE_LOW_PRIORITY : TL_WRITE;
options=thd_startup_options;
+ query_cache_type = (byte) query_cache_startup_type;
sql_mode=(uint) opt_sql_mode;
inactive_timeout=net_wait_timeout;
open_options=ha_open_options;
@@ -133,6 +136,7 @@ THD::THD():user_time(0),fatal_error(0),last_insert_id_used(0),
/* Initialize sub structures */
bzero((char*) &mem_root,sizeof(mem_root));
+ user_connect=(UC *)0;
hash_init(&user_vars, USER_VARS_HASH_SIZE, 0, 0,
(hash_get_key) get_var_key,
(void (*)(void*)) free_var,0);
@@ -160,6 +164,11 @@ void THD::cleanup(void)
lock=locked_tables; locked_tables=0;
close_thread_tables(this);
}
+ if (handler_tables)
+ {
+ open_tables=handler_tables; handler_tables=0;
+ close_thread_tables(this);
+ }
close_temporary_tables(this);
#ifdef USING_TRANSACTIONS
if (opt_using_transactions)
@@ -184,12 +193,7 @@ THD::~THD()
if (!cleanup_done)
cleanup();
if (global_read_lock)
- {
- pthread_mutex_lock(&LOCK_open);
- ::global_read_lock--;
- pthread_cond_broadcast(&COND_refresh);
- pthread_mutex_unlock(&LOCK_open);
- }
+ unlock_global_read_lock(this);
if (ull)
{
pthread_mutex_lock(&LOCK_user_locks);
@@ -199,7 +203,7 @@ THD::~THD()
hash_free(&user_vars);
DBUG_PRINT("info", ("freeing host"));
-
+
if (host != localhost) // If not pointer to constant
safeFree(host);
if (user != delayed_user)
@@ -214,10 +218,11 @@ THD::~THD()
DBUG_VOID_RETURN;
}
-void THD::prepare_to_die()
+void THD::awake(bool prepare_to_die)
{
+ if (prepare_to_die)
+ killed = 1;
thr_alarm_kill(real_id);
- killed = 1;
#ifdef SIGNAL_WITH_VIO_CLOSE
close_active_vio();
#endif
@@ -226,6 +231,10 @@ void THD::prepare_to_die()
pthread_mutex_lock(&mysys_var->mutex);
if (!system_thread) // Don't abort locks
mysys_var->abort=1;
+ // this broadcast could be up in the air if the victim thread
+ // exits the cond in the time between read and broadcast, but that is
+ // ok since all we want to do is to make the victim thread get out
+ // of waiting on current_cond
if (mysys_var->current_cond)
{
pthread_mutex_lock(mysys_var->current_mutex);
@@ -277,7 +286,7 @@ bool select_send::send_fields(List<Item> &list,uint flag)
bool select_send::send_data(List<Item> &items)
{
- List_iterator<Item> li(items);
+ List_iterator_fast<Item> li(items);
String *packet= &thd->packet;
DBUG_ENTER("send_data");
@@ -290,7 +299,7 @@ bool select_send::send_data(List<Item> &items)
Item *item;
while ((item=li++))
{
- if (item->send(packet))
+ if (item->send(thd, packet))
{
packet->free(); // Free used
my_error(ER_OUT_OF_RESOURCES,MYF(0));
@@ -302,12 +311,6 @@ bool select_send::send_data(List<Item> &items)
DBUG_RETURN(error);
}
-
-void select_send::send_error(uint errcode,const char *err)
-{
- ::send_error(&thd->net,errcode,err);
-}
-
bool select_send::send_eof()
{
/* Unlock tables before sending packet to gain some speed */
@@ -370,7 +373,7 @@ select_export::prepare(List<Item> &list)
}
/* Check if there is any blobs in data */
{
- List_iterator<Item> li(list);
+ List_iterator_fast<Item> li(list);
Item *item;
while ((item=li++))
{
@@ -417,7 +420,7 @@ bool select_export::send_data(List<Item> &items)
Item *item;
char *buff_ptr=buff;
uint used_length=0,items_left=items.elements;
- List_iterator<Item> li(items);
+ List_iterator_fast<Item> li(items);
if (my_b_write(&cache,(byte*) exchange->line_start->ptr(),
exchange->line_start->length()))
@@ -610,7 +613,7 @@ select_dump::prepare(List<Item> &list __attribute__((unused)))
bool select_dump::send_data(List<Item> &items)
{
- List_iterator<Item> li(items);
+ List_iterator_fast<Item> li(items);
char buff[MAX_FIELD_WIDTH];
String tmp(buff,sizeof(buff)),*res;
tmp.length(0);
diff --git a/sql/sql_class.h b/sql/sql_class.h
index d9497907926..a1423cfcdf1 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -21,10 +21,14 @@
#pragma interface /* gcc class implementation */
#endif
+// TODO: create log.h and move all the log header stuff there
+
class Query_log_event;
class Load_log_event;
+class Slave_log_event;
-
+enum enum_enable_or_disable { LEAVE_AS_IS, ENABLE, DISABLE };
+enum enum_ha_read_modes { RFIRST, RNEXT, RPREV, RLAST, RKEY };
enum enum_duplicates { DUP_ERROR, DUP_REPLACE, DUP_IGNORE };
enum enum_log_type { LOG_CLOSED, LOG_NORMAL, LOG_NEW, LOG_BIN };
@@ -38,6 +42,8 @@ enum enum_log_type { LOG_CLOSED, LOG_NORMAL, LOG_NEW, LOG_BIN };
#define LOG_INFO_FATAL -7
#define LOG_INFO_IN_USE -8
+struct st_relay_log_info;
+
typedef struct st_log_info
{
char log_file_name[FN_REFLEN];
@@ -49,6 +55,7 @@ typedef struct st_log_info
~st_log_info() { pthread_mutex_destroy(&lock);}
} LOG_INFO;
+class Log_event;
class MYSQL_LOG {
private:
@@ -61,39 +68,65 @@ class MYSQL_LOG {
char time_buff[20],db[NAME_LEN+1];
char log_file_name[FN_REFLEN],index_file_name[FN_REFLEN];
bool write_error,inited;
+ uint file_id; // current file sequence number for load data infile
+ // binary logging
bool no_rotate; // for binlog - if log name can never change
// we should not try to rotate it or write any rotation events
// the user should use FLUSH MASTER instead of FLUSH LOGS for
// purging
+ enum cache_type io_cache_type;
+ bool need_start_event;
+ pthread_cond_t update_cond;
+ bool no_auto_events; // for relay binlog
+ friend class Log_event;
public:
MYSQL_LOG();
~MYSQL_LOG();
pthread_mutex_t* get_log_lock() { return &LOCK_log; }
+ IO_CACHE* get_log_file() { return &log_file; }
+ void signal_update() { pthread_cond_broadcast(&update_cond);}
+ void wait_for_update(THD* thd);
+ void set_need_start_event() { need_start_event = 1; }
void set_index_file_name(const char* index_file_name = 0);
- void init(enum_log_type log_type_arg);
+ void init(enum_log_type log_type_arg,
+ enum cache_type io_cache_type_arg = WRITE_CACHE,
+ bool no_auto_events_arg = 0);
void open(const char *log_name,enum_log_type log_type,
- const char *new_name=0);
+ const char *new_name, enum cache_type io_cache_type_arg,
+ bool no_auto_events_arg);
void new_file(bool inside_mutex = 0);
bool open_index(int options);
void close_index();
- bool write(THD *thd, enum enum_server_command command,const char *format,...);
+ bool write(THD *thd, enum enum_server_command command,
+ const char *format,...);
bool write(THD *thd, const char *query, uint query_length,
time_t query_start=0);
- bool write(Query_log_event* event_info); // binary log write
- bool write(Load_log_event* event_info);
+ bool write(Log_event* event_info); // binary log write
bool write(THD *thd, IO_CACHE *cache);
+
+ /*
+ v stands for vector
+ invoked as appendv(buf1,len1,buf2,len2,...,bufn,lenn,0)
+ */
+ bool appendv(const char* buf,uint len,...);
+ bool append(Log_event* ev);
+
int generate_new_name(char *new_name,const char *old_name);
void make_log_name(char* buf, const char* log_ident);
bool is_active(const char* log_file_name);
int purge_logs(THD* thd, const char* to_log);
+ int purge_first_log(struct st_relay_log_info* rli);
+ int reset_logs(THD* thd);
void close(bool exiting = 0); // if we are exiting, we also want to close the
// index file
// iterating through the log index file
- int find_first_log(LOG_INFO* linfo, const char* log_name);
- int find_next_log(LOG_INFO* linfo);
+ int find_first_log(LOG_INFO* linfo, const char* log_name,
+ bool need_mutex=1);
+ int find_next_log(LOG_INFO* linfo, bool need_mutex=1);
int get_current_log(LOG_INFO* linfo);
+ uint next_file_id();
inline bool is_open() { return log_type != LOG_CLOSED; }
char* get_index_fname() { return index_file_name;}
@@ -114,14 +147,16 @@ class CONVERT
void convert_array(const uchar *mapping,uchar *buff,uint length);
public:
const char *name;
- CONVERT(const char *name_par,uchar *from_par,uchar *to_par)
- :from_map(from_par),to_map(to_par),name(name_par) {}
+ uint numb;
+ CONVERT(const char *name_par,uchar *from_par,uchar *to_par, uint number)
+ :from_map(from_par),to_map(to_par),name(name_par),numb(number) {}
friend CONVERT *get_convert_set(const char *name_ptr);
inline void convert(char *a,uint length)
{
convert_array(from_map, (uchar*) a,length);
}
bool store(String *, const char *,uint);
+ inline uint number() { return numb; }
};
typedef struct st_copy_info {
@@ -214,49 +249,85 @@ public:
};
-/****************************************************************************
-** every connection is handle by a thread with a THD
-****************************************************************************/
-
class delayed_insert;
+/* For each client connection we create a separate thread with THD serving as
+ a thread/connection descriptor */
+
class THD :public ilink {
public:
- NET net;
- LEX lex;
- MEM_ROOT mem_root;
- HASH user_vars;
- String packet; /* Room for 1 row */
- struct sockaddr_in remote;
- struct rand_struct rand;
+ NET net; // client connection descriptor
+ LEX lex; // parse tree descriptor
+ MEM_ROOT mem_root; // memory allocation pool
+ HASH user_vars; // hash for user variables
+ String packet; // dynamic string buffer used for network I/O
+ struct sockaddr_in remote; // client socket address
+ struct rand_struct rand; // used for authentication
+
+ /* query points to the current query,
+ thread_stack is a pointer to the stack frame of handle_one_connection(),
+ which is called first in the thread for handling a client
+ */
char *query,*thread_stack;
+ /*
+ host - host of the client
+ user - user of the client, set to NULL until the user has been read from
+ the connection
+ priv_user - not sure why we have it, but it is set to "boot" when we run
+ with --bootstrap
+ db - currently selected database
+ ip - client IP
+ */
+
char *host,*user,*priv_user,*db,*ip;
- const char *proc_info;
+ /* proc_info points to a string that will show in the Info column of
+ SHOW PROCESSLIST output
+ host_or_ip points to host if host is available, otherwise points to ip
+ */
+ const char *proc_info, *host_or_ip;
+
+ /*
+ client_capabilities has flags describing what the client can do
+ sql_mode determines if certain non-standard SQL behaviour should be
+ enabled
+ max_packet_length - supposed to be maximum packet length the client
+ can handle, but it currently appears to be assigned but never used
+ except for one debugging statement
+ */
uint client_capabilities,sql_mode,max_packet_length;
+
+ /*
+ master_access - privillege descriptor mask for system threads
+ db_access - privillege descriptor mask for regular threads
+ */
uint master_access,db_access;
- TABLE *open_tables,*temporary_tables;
+
+ /*
+ open_tables - list of regular tables in use by this thread
+ temporary_tables - list of temp tables in use by this thread
+ handler_tables - list of tables that were opened with HANDLER OPEN
+ and are still in use by this thread
+ */
+ TABLE *open_tables,*temporary_tables, *handler_tables;
+ // TODO: document the variables below
MYSQL_LOCK *lock,*locked_tables;
ULL *ull;
struct st_my_thread_var *mysys_var;
enum enum_server_command command;
uint32 server_id;
+ uint32 file_id; // for LOAD DATA INFILE
const char *where;
- char* last_nx_table; // last non-existent table, we need this for replication
- char* last_nx_db; // database of the last nx table
- time_t start_time,time_after_lock,user_time;
- time_t connect_time,thr_create_time; // track down slow pthread_create
+ time_t start_time,time_after_lock,user_time;
+ time_t connect_time,thr_create_time; // track down slow pthread_create
thr_lock_type update_lock_default;
delayed_insert *di;
struct st_transactions {
IO_CACHE trans_log;
- THD_TRANS all; /* Trans since BEGIN WORK */
- THD_TRANS stmt; /* Trans for current statement */
+ THD_TRANS all; // Trans since BEGIN WORK
+ THD_TRANS stmt; // Trans for current statement
uint bdb_lock_count;
} transaction;
-#ifdef HAVE_GEMINI_DB
- struct st_gemini gemini;
-#endif
- Item *free_list;
+ Item *free_list, *handler_items;
CONVERT *convert_set;
Field *dupp_field;
#ifndef __WIN__
@@ -266,32 +337,43 @@ public:
Vio* active_vio;
pthread_mutex_t active_vio_lock;
#endif
- ulonglong next_insert_id,last_insert_id,current_insert_id;
- ha_rows select_limit,offset_limit,default_select_limit,cuted_fields,
- max_join_size, sent_row_count, examined_row_count;
- table_map used_tables;
- ulong query_id,version, inactive_timeout,options,thread_id;
- ulong gemini_spin_retries;
- long dbug_thread_id;
+ ulonglong next_insert_id,last_insert_id,current_insert_id,
+ limit_found_rows;
+ ha_rows select_limit,offset_limit,default_select_limit,cuted_fields,
+ max_join_size, sent_row_count, examined_row_count;
+ table_map used_tables;
+ UC *user_connect;
+ ulong query_id,version, inactive_timeout,options,thread_id;
+ long dbug_thread_id;
pthread_t real_id;
- uint current_tablenr,tmp_table,cond_count,col_access,query_length;
- uint server_status,open_options;
+ uint current_tablenr,tmp_table,cond_count,col_access;
+ uint server_status,open_options;
+ uint32 query_length;
+ uint32 db_length;
enum_tx_isolation tx_isolation, session_tx_isolation;
char scramble[9];
+ uint8 query_cache_type; // type of query cache processing
bool slave_thread;
bool set_query_id,locked,count_cuted_fields,some_tables_deleted;
bool no_errors, allow_sum_func, password, fatal_error;
bool query_start_used,last_insert_id_used,insert_id_used;
bool system_thread,in_lock_tables,global_read_lock;
bool query_error, bootstrap, cleanup_done;
+ bool safe_to_cache_query;
bool volatile killed;
+ /*
+ If we do a purge of binary logs, log index info of the threads
+ that are currently reading it needs to be adjusted. To do that
+ each thread that is using LOG_INFO needs to adjust the pointer to it
+ */
LOG_INFO* current_linfo;
- // if we do a purge of binary logs, log index info of the threads
- // that are currently reading it needs to be adjusted. To do that
- // each thread that is using LOG_INFO needs to adjust the pointer to it
-
- ulong slave_proxy_id; // in slave thread we need to know in behalf of which
- // thread the query is being run to replicate temp tables properly
+ /*
+ In slave thread we need to know in behalf of which
+ thread the query is being run to replicate temp tables properly
+ */
+ ulong slave_proxy_id;
+ NET* slave_net; // network connection from slave -> m.
+ my_off_t log_pos;
THD();
~THD();
@@ -321,7 +403,7 @@ public:
pthread_mutex_unlock(&active_vio_lock);
}
#endif
- void prepare_to_die();
+ void awake(bool prepare_to_die);
inline const char* enter_cond(pthread_cond_t *cond, pthread_mutex_t* mutex,
const char* msg)
{
@@ -355,16 +437,18 @@ public:
}
return last_insert_id;
}
+ inline ulonglong found_rows(void)
+ {
+ return limit_found_rows;
+ }
inline bool active_transaction()
{
#ifdef USING_TRANSACTIONS
return (transaction.all.bdb_tid != 0 ||
- transaction.all.innodb_active_trans != 0 ||
- transaction.all.gemini_tid != 0);
+ transaction.all.innodb_active_trans != 0);
#else
return 0;
#endif
-
}
inline gptr alloc(unsigned int size) { return alloc_root(&mem_root,size); }
inline gptr calloc(unsigned int size)
@@ -376,8 +460,17 @@ public:
}
inline char *strdup(const char *str)
{ return strdup_root(&mem_root,str); }
- inline char *memdup(const char *str, unsigned int size)
+ inline char *strmake(const char *str, uint size)
+ { return strmake_root(&mem_root,str,size); }
+ inline char *memdup(const char *str, uint size)
{ return memdup_root(&mem_root,str,size); }
+ inline char *memdup_w_gap(const char *str, uint size, uint gap)
+ {
+ gptr ptr;
+ if ((ptr=alloc_root(&mem_root,size+gap)))
+ memcpy(ptr,str,size);
+ return ptr;
+ }
};
@@ -399,6 +492,10 @@ public:
** This is used to get result from a select
*/
+class JOIN;
+
+void send_error(NET *net,uint sql_errno=0, const char *err=0);
+
class select_result :public Sql_alloc {
protected:
THD *thd;
@@ -408,7 +505,11 @@ public:
virtual int prepare(List<Item> &list) { return 0; }
virtual bool send_fields(List<Item> &list,uint flag)=0;
virtual bool send_data(List<Item> &items)=0;
- virtual void send_error(uint errcode,const char *err)=0;
+ virtual void initialize_tables (JOIN *join=0) {}
+ virtual void send_error(uint errcode,const char *err)
+ {
+ ::send_error(&thd->net,errcode,err);
+ }
virtual bool send_eof()=0;
virtual void abort() {}
};
@@ -419,7 +520,6 @@ public:
select_send() {}
bool send_fields(List<Item> &list,uint flag);
bool send_data(List<Item> &items);
- void send_error(uint errcode,const char *err);
bool send_eof();
};
@@ -443,6 +543,7 @@ public:
bool send_eof();
};
+
class select_dump :public select_result {
sql_exchange *exchange;
File file;
@@ -463,29 +564,28 @@ public:
class select_insert :public select_result {
- protected:
+ public:
TABLE *table;
List<Item> *fields;
- uint save_time_stamp;
ulonglong last_insert_id;
COPY_INFO info;
+ uint save_time_stamp;
-public:
select_insert(TABLE *table_par,List<Item> *fields_par,enum_duplicates duplic)
- :table(table_par),fields(fields_par), save_time_stamp(0),last_insert_id(0)
- {
- bzero((char*) &info,sizeof(info));
- info.handle_duplicates=duplic;
- }
+ :table(table_par),fields(fields_par), last_insert_id(0), save_time_stamp(0) {
+ bzero((char*) &info,sizeof(info));
+ info.handle_duplicates=duplic;
+ }
~select_insert();
int prepare(List<Item> &list);
- bool send_fields(List<Item> &list,
- uint flag) { return 0; }
+ bool send_fields(List<Item> &list, uint flag)
+ { return 0; }
bool send_data(List<Item> &items);
void send_error(uint errcode,const char *err);
bool send_eof();
};
+
class select_create: public select_insert {
ORDER *group;
const char *db;
@@ -512,6 +612,22 @@ public:
void abort();
};
+class select_union :public select_result {
+ public:
+ TABLE *table;
+ COPY_INFO info;
+ uint save_time_stamp;
+
+ select_union(TABLE *table_par);
+ ~select_union();
+ int prepare(List<Item> &list);
+ bool send_fields(List<Item> &list, uint flag)
+ { return 0; }
+ bool send_data(List<Item> &items);
+ bool send_eof();
+ bool flush();
+};
+
/* Structs used when sorting */
typedef struct st_sort_field {
@@ -561,3 +677,89 @@ class user_var_entry
Item_result type;
};
+/* Class for unique (removing of duplicates) */
+
+class Unique :public Sql_alloc
+{
+ DYNAMIC_ARRAY file_ptrs;
+ ulong max_elements, max_in_memory_size;
+ IO_CACHE file;
+ TREE tree;
+ byte *record_pointers;
+ bool flush();
+
+public:
+ ulong elements;
+ Unique(qsort_cmp2 comp_func, void * comp_func_fixed_arg,
+ uint size, ulong max_in_memory_size_arg);
+ ~Unique();
+ inline bool unique_add(gptr ptr)
+ {
+ if (tree.elements_in_tree > max_elements && flush())
+ return 1;
+ return !tree_insert(&tree,ptr,0);
+ }
+
+ bool get(TABLE *table);
+
+ friend int unique_write_to_file(gptr key, element_count count, Unique *unique);
+ friend int unique_write_to_ptrs(gptr key, element_count count, Unique *unique);
+};
+
+ class multi_delete : public select_result {
+ TABLE_LIST *delete_tables, *table_being_deleted;
+#ifdef SINISAS_STRIP
+ IO_CACHE **tempfiles;
+ byte *memory_lane;
+#else
+ Unique **tempfiles;
+#endif
+ THD *thd;
+ ha_rows deleted;
+ uint num_of_tables;
+ int error;
+ thr_lock_type lock_option;
+ bool do_delete, not_trans_safe;
+ public:
+ multi_delete(THD *thd, TABLE_LIST *dt, thr_lock_type lock_option_arg,
+ uint num_of_tables);
+ ~multi_delete();
+ int prepare(List<Item> &list);
+ bool send_fields(List<Item> &list,
+ uint flag) { return 0; }
+ bool send_data(List<Item> &items);
+ void initialize_tables (JOIN *join);
+ void send_error(uint errcode,const char *err);
+ int do_deletes (bool from_send_error);
+ bool send_eof();
+ };
+
+ class multi_update : public select_result {
+ TABLE_LIST *update_tables, *table_being_updated;
+// Unique **tempfiles;
+ COPY_INFO *infos;
+ TABLE **tmp_tables;
+ THD *thd;
+ ha_rows updated, found;
+ List<Item> fields;
+ List <Item> **fields_by_tables;
+ thr_lock_type lock_option;
+ enum enum_duplicates dupl;
+ uint num_of_tables, num_fields, num_updated, *save_time_stamps, *field_sequence;
+ int error;
+ bool do_update, not_trans_safe;
+ public:
+ multi_update(THD *thd_arg, TABLE_LIST *ut, List<Item> &fs,
+ enum enum_duplicates handle_duplicates,
+ thr_lock_type lock_option_arg, uint num);
+ ~multi_update();
+ int prepare(List<Item> &list);
+ bool send_fields(List<Item> &list,
+ uint flag) { return 0; }
+ bool send_data(List<Item> &items);
+ void initialize_tables (JOIN *join);
+ void send_error(uint errcode,const char *err);
+ int do_updates (bool from_send_error);
+ bool send_eof();
+ };
+
diff --git a/sql/sql_crypt.cc b/sql/sql_crypt.cc
index 371d63f8c73..f2e4a8934be 100644
--- a/sql/sql_crypt.cc
+++ b/sql/sql_crypt.cc
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
diff --git a/sql/sql_crypt.h b/sql/sql_crypt.h
index b3a9d54133f..1b27f0a4d27 100644
--- a/sql/sql_crypt.h
+++ b/sql/sql_crypt.h
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
diff --git a/sql/sql_db.cc b/sql/sql_db.cc
index 1e798a392b1..dd8ed634011 100644
--- a/sql/sql_db.cc
+++ b/sql/sql_db.cc
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -25,45 +25,28 @@
#include <direct.h>
#endif
-static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *path,
+static long mysql_rm_known_files(THD *thd, MY_DIR *dirp,
+ const char *db, const char *path,
uint level);
/* db-name is already validated when we come here */
-void mysql_create_db(THD *thd, char *db, uint create_options)
+int mysql_create_db(THD *thd, char *db, uint create_options, bool silent)
{
char path[FN_REFLEN+16];
MY_DIR *dirp;
long result=1;
+ int error = 0;
DBUG_ENTER("mysql_create_db");
-
+
VOID(pthread_mutex_lock(&LOCK_mysql_create_db));
- VOID(pthread_mutex_lock(&LOCK_open));
// do not create database if another thread is holding read lock
- if (global_read_lock)
+ if (wait_if_global_read_lock(thd,0))
{
- if (thd->global_read_lock)
- {
- net_printf(&thd->net, ER_CREATE_DB_WITH_READ_LOCK);
- VOID(pthread_mutex_unlock(&LOCK_open));
- goto exit;
- }
- while (global_read_lock && ! thd->killed)
- {
- (void) pthread_cond_wait(&COND_refresh,&LOCK_open);
- }
-
- if (thd->killed)
- {
- net_printf(&thd->net, ER_SERVER_SHUTDOWN);
- VOID(pthread_mutex_unlock(&LOCK_open));
- goto exit;
- }
-
+ error= -1;
+ goto exit2;
}
-
- VOID(pthread_mutex_unlock(&LOCK_open));
/* Check directory */
(void)sprintf(path,"%s/%s", mysql_data_home, db);
@@ -73,7 +56,8 @@ void mysql_create_db(THD *thd, char *db, uint create_options)
my_dirend(dirp);
if (!(create_options & HA_LEX_CREATE_IF_NOT_EXISTS))
{
- net_printf(&thd->net,ER_DB_CREATE_EXISTS,db);
+ my_error(ER_DB_CREATE_EXISTS,MYF(0),db);
+ error = -1;
goto exit;
}
result = 0;
@@ -83,137 +67,148 @@ void mysql_create_db(THD *thd, char *db, uint create_options)
strend(path)[-1]=0; // Remove last '/' from path
if (my_mkdir(path,0777,MYF(0)) < 0)
{
- net_printf(&thd->net,ER_CANT_CREATE_DB,db,my_errno);
+ my_error(ER_CANT_CREATE_DB,MYF(0),db,my_errno);
+ error = -1;
goto exit;
}
}
- if (!thd->query)
- {
- thd->query = path;
- thd->query_length = (uint) (strxmov(path,"create database ", db, NullS)-
- path);
- }
+
+ if (!silent)
{
- mysql_update_log.write(thd,thd->query, thd->query_length);
- if (mysql_bin_log.is_open())
+ if (!thd->query)
{
- Query_log_event qinfo(thd, thd->query);
- mysql_bin_log.write(&qinfo);
+ thd->query = path;
+ thd->query_length = (uint) (strxmov(path,"create database ", db, NullS)-
+ path);
}
+ {
+ mysql_update_log.write(thd,thd->query, thd->query_length);
+ if (mysql_bin_log.is_open())
+ {
+ Query_log_event qinfo(thd, thd->query);
+ mysql_bin_log.write(&qinfo);
+ }
+ }
+ if (thd->query == path)
+ {
+ thd->query = 0; // just in case
+ thd->query_length = 0;
+ }
+ send_ok(&thd->net, result);
}
- if (thd->query == path)
- {
- thd->query = 0; // just in case
- thd->query_length = 0;
- }
- send_ok(&thd->net, result);
exit:
+ start_waiting_global_read_lock(thd);
+exit2:
VOID(pthread_mutex_unlock(&LOCK_mysql_create_db));
- DBUG_VOID_RETURN;
+ DBUG_RETURN(error);
}
-const char *del_exts[]=
-{".frm",".ISM",".ISD",".ISM",".HSH",".DAT",".MRG",".MYI",".MYD", ".db", ".BAK", NullS};
+const char *del_exts[]= {".frm", ".BAK", ".TMD", NullS};
static TYPELIB deletable_extentions=
{array_elements(del_exts)-1,"del_exts", del_exts};
+const char *known_exts[]=
+{".ISM",".ISD",".ISM",".MRG",".MYI",".MYD",".db",NullS};
+static TYPELIB known_extentions=
+{array_elements(known_exts)-1,"known_exts", known_exts};
+
+/*
+ Drop all tables in a database.
+
+ db-name is already validated when we come here
+ If thd == 0, do not write any messages; This is useful in replication
+ when we want to remove a stale database before replacing it with the new one
+*/
-/* db-name is already validated when we come here */
-void mysql_rm_db(THD *thd,char *db,bool if_exists)
+int mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent)
{
long deleted=0;
+ int error = 0;
char path[FN_REFLEN+16];
MY_DIR *dirp;
DBUG_ENTER("mysql_rm_db");
VOID(pthread_mutex_lock(&LOCK_mysql_create_db));
- VOID(pthread_mutex_lock(&LOCK_open));
// do not drop database if another thread is holding read lock
- if (global_read_lock)
+ if (wait_if_global_read_lock(thd,0))
{
- if (thd->global_read_lock)
- {
- net_printf(&thd->net, ER_DROP_DB_WITH_READ_LOCK);
- goto exit;
- }
- while (global_read_lock && ! thd->killed)
- {
- (void) pthread_cond_wait(&COND_refresh,&LOCK_open);
- }
-
- if (thd->killed)
- {
- net_printf(&thd->net, ER_SERVER_SHUTDOWN);
- goto exit;
- }
+ error= -1;
+ goto exit2;
}
(void) sprintf(path,"%s/%s",mysql_data_home,db);
unpack_dirname(path,path); // Convert if not unix
/* See if the directory exists */
- if (!(dirp = my_dir(path,MYF(MY_WME | MY_DONT_SORT))))
+ if (!(dirp = my_dir(path,MYF(MY_DONT_SORT))))
{
if (!if_exists)
- net_printf(&thd->net,ER_DB_DROP_EXISTS,db);
- else
+ {
+ error= -1;
+ my_error(ER_DB_DROP_EXISTS,MYF(0),db);
+ }
+ else if (!silent)
send_ok(&thd->net,0);
goto exit;
}
remove_db_from_cache(db);
- if ((deleted=mysql_rm_known_files(thd, dirp, path,0)) >= 0)
+ error = -1;
+ if ((deleted=mysql_rm_known_files(thd, dirp, db, path,0)) >= 0 && thd)
{
- if (!thd->query)
- {
- thd->query = path;
- thd->query_length = (uint) (strxmov(path,"drop database ", db, NullS)-
- path);
- }
- mysql_update_log.write(thd, thd->query, thd->query_length);
- if (mysql_bin_log.is_open())
- {
- Query_log_event qinfo(thd, thd->query);
- mysql_bin_log.write(&qinfo);
- }
- if (thd->query == path)
+ ha_drop_database(path);
+ query_cache.invalidate(db);
+ if (!silent)
{
- thd->query = 0; // just in case
- thd->query_length = 0;
+ if (!thd->query)
+ {
+ thd->query = path;
+ thd->query_length = (uint) (strxmov(path,"drop database ", db, NullS)-
+ path);
+ }
+ mysql_update_log.write(thd, thd->query, thd->query_length);
+ if (mysql_bin_log.is_open())
+ {
+ Query_log_event qinfo(thd, thd->query);
+ mysql_bin_log.write(&qinfo);
+ }
+ if (thd->query == path)
+ {
+ thd->query = 0; // just in case
+ thd->query_length = 0;
+ }
+ send_ok(&thd->net,(ulong) deleted);
}
- send_ok(&thd->net,(ulong) deleted);
+ error = 0;
}
exit:
- VOID(pthread_mutex_unlock(&LOCK_open));
+ start_waiting_global_read_lock(thd);
+exit2:
VOID(pthread_mutex_unlock(&LOCK_mysql_create_db));
- /* It seems MySQL may call this function when there still are queries
- running on tables of the database. Since InnoDB waits until the
- queries have ended, we have to call ha_drop_database outside
- the above two mutexes to avoid deadlocks. */
-
- ha_drop_database(path);
-
- DBUG_VOID_RETURN;
+ DBUG_RETURN(error);
}
/*
Removes files with known extensions plus all found subdirectories that
are 2 digits (raid directories).
+ thd MUST be set when calling this function!
*/
-static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *org_path,
- uint level)
+static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *db,
+ const char *org_path, uint level)
{
long deleted=0;
ulong found_other_files=0;
char filePath[FN_REFLEN];
+ TABLE_LIST *tot_list=0, **tot_list_next;
DBUG_ENTER("mysql_rm_known_files");
DBUG_PRINT("enter",("path: %s", org_path));
- /* remove all files with known extensions */
+
+ tot_list_next= &tot_list;
for (uint idx=2 ;
idx < (uint) dirp->number_off_files && !thd->killed ;
@@ -233,7 +228,7 @@ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *org_path,
if ((new_dirp = my_dir(newpath,MYF(MY_DONT_SORT))))
{
DBUG_PRINT("my",("New subdir found: %s", newpath));
- if ((mysql_rm_known_files(thd,new_dirp,newpath,1)) < 0)
+ if ((mysql_rm_known_files(thd, new_dirp, NullS, newpath,1)) < 0)
{
my_dirend(dirp);
DBUG_RETURN(-1);
@@ -243,27 +238,44 @@ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *org_path,
}
if (find_type(fn_ext(file->name),&deletable_extentions,1+2) <= 0)
{
- found_other_files++;
+ if (find_type(fn_ext(file->name),&known_extentions,1+2) <= 0)
+ found_other_files++;
continue;
}
strxmov(filePath,org_path,"/",file->name,NullS);
- unpack_filename(filePath,filePath);
- if (my_delete(filePath,MYF(MY_WME)))
+ if (db && !my_strcasecmp(fn_ext(file->name), reg_ext))
{
- net_printf(&thd->net,ER_DB_DROP_DELETE,filePath,my_error);
- my_dirend(dirp);
- DBUG_RETURN(-1);
+ /* Drop the table nicely */
+ *fn_ext(file->name)=0; // Remove extension
+ TABLE_LIST *table_list=(TABLE_LIST*)
+ thd->calloc(sizeof(*table_list)+ strlen(db)+strlen(file->name)+2);
+ if (!table_list)
+ {
+ my_dirend(dirp);
+ DBUG_RETURN(-1);
+ }
+ table_list->db= (char*) (table_list+1);
+ strmov(table_list->real_name=strmov(table_list->db,db)+1,
+ file->name);
+ /* Link into list */
+ (*tot_list_next)= table_list;
+ tot_list_next= &table_list->next;
}
- deleted++;
- }
+ else
+ {
+ if (my_delete_with_symlink(filePath,MYF(MY_WME)))
+ {
+ my_dirend(dirp);
+ DBUG_RETURN(-1);
+ }
+ deleted++;
+ }
+ }
my_dirend(dirp);
- if (thd->killed)
- {
- send_error(&thd->net,ER_SERVER_SHUTDOWN);
+ if (thd->killed || (tot_list && mysql_rm_table_part2(thd, tot_list, 1, 1)))
DBUG_RETURN(-1);
- }
/*
If the directory is a symbolic link, remove the link first, then
@@ -283,20 +295,19 @@ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *org_path,
/* Don't give errors if we can't delete 'RAID' directory */
if (level)
DBUG_RETURN(deleted);
- send_error(&thd->net);
DBUG_RETURN(-1);
}
path=filePath;
}
#endif
- /* Remove last FN_LIBCHAR to not cause a probelm on OS/2 */
+ /* Remove last FN_LIBCHAR to not cause a problem on OS/2 */
char *pos=strend(path);
if (pos > path && pos[-1] == FN_LIBCHAR)
*--pos=0;
/* Don't give errors if we can't delete 'RAID' directory */
if (rmdir(path) < 0 && !level)
{
- net_printf(&thd->net,ER_DB_DROP_RMDIR, path,errno);
+ my_error(ER_DB_DROP_RMDIR, MYF(0), path, errno);
DBUG_RETURN(-1);
}
}
@@ -306,25 +317,25 @@ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *org_path,
bool mysql_change_db(THD *thd,const char *name)
{
- int length;
+ int length, db_length;
char *dbname=my_strdup((char*) name,MYF(MY_WME));
char path[FN_REFLEN];
uint db_access;
DBUG_ENTER("mysql_change_db");
- if (!dbname || !(length=stripp_sp(dbname)))
+ if (!dbname || !(db_length=stripp_sp(dbname)))
{
x_free(dbname); /* purecov: inspected */
send_error(&thd->net,ER_NO_DB_ERROR); /* purecov: inspected */
DBUG_RETURN(1); /* purecov: inspected */
}
- if ((length > NAME_LEN) || check_db_name(dbname))
+ if ((db_length > NAME_LEN) || check_db_name(dbname))
{
net_printf(&thd->net,ER_WRONG_DB_NAME, dbname);
x_free(dbname);
DBUG_RETURN(1);
}
- DBUG_PRINT("general",("Use database: %s", dbname));
+ DBUG_PRINT("info",("Use database: %s", dbname));
if (test_all_bits(thd->master_access,DB_ACLS))
db_access=DB_ACLS;
else
@@ -335,11 +346,11 @@ bool mysql_change_db(THD *thd,const char *name)
{
net_printf(&thd->net,ER_DBACCESS_DENIED_ERROR,
thd->priv_user,
- thd->host ? thd->host : thd->ip ? thd->ip : "unknown",
+ thd->host_or_ip,
dbname);
mysql_log.write(thd,COM_INIT_DB,ER(ER_DBACCESS_DENIED_ERROR),
thd->priv_user,
- thd->host ? thd->host : thd->ip ? thd->ip : "unknown",
+ thd->host_or_ip,
dbname);
my_free(dbname,MYF(0));
DBUG_RETURN(1);
@@ -358,6 +369,7 @@ bool mysql_change_db(THD *thd,const char *name)
send_ok(&thd->net);
x_free(thd->db);
thd->db=dbname;
+ thd->db_length=db_length;
thd->db_access=db_access;
DBUG_RETURN(0);
}
diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc
index 930e71d7678..a155abc522b 100644
--- a/sql/sql_delete.cc
+++ b/sql/sql_delete.cc
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+/* Copyright (C) 2000 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -15,118 +15,28 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-/* Delete of records */
-
-#include "mysql_priv.h"
-#include "ha_innobase.h"
-
/*
- Optimize delete of all rows by doing a full generate of the table
- This will work even if the .ISM and .ISD tables are destroyed
-*/
-
-int generate_table(THD *thd, TABLE_LIST *table_list, TABLE *locked_table)
-{
- char path[FN_REFLEN];
- int error;
- TABLE **table_ptr;
- DBUG_ENTER("generate_table");
-
- thd->proc_info="generate_table";
+ Delete of records and truncate of tables.
- if (global_read_lock)
- {
- if(thd->global_read_lock)
- {
- my_error(ER_TABLE_NOT_LOCKED_FOR_WRITE,MYF(0),
- table_list->real_name);
- DBUG_RETURN(-1);
- }
- pthread_mutex_lock(&LOCK_open);
- while (global_read_lock && ! thd->killed ||
- thd->version != refresh_version)
- {
- (void) pthread_cond_wait(&COND_refresh,&LOCK_open);
- }
- pthread_mutex_unlock(&LOCK_open);
- }
+ Multi-table deletes were introduced by Monty and Sinisa
+*/
- /* If it is a temporary table, close and regenerate it */
- if ((table_ptr=find_temporary_table(thd,table_list->db,
- table_list->real_name)))
- {
- TABLE *table= *table_ptr;
- HA_CREATE_INFO create_info;
- table->file->info(HA_STATUS_AUTO | HA_STATUS_NO_LOCK);
- bzero((char*) &create_info,sizeof(create_info));
- create_info.auto_increment_value= table->file->auto_increment_value;
- db_type table_type=table->db_type;
- strmov(path,table->path);
- *table_ptr= table->next; // Unlink table from list
- close_temporary(table,0);
- *fn_ext(path)=0; // Remove the .frm extension
- ha_create_table(path, &create_info,1);
- if ((error= (int) !(open_temporary_table(thd, path, table_list->db,
- table_list->real_name, 1))))
- {
- (void) rm_temporary_table(table_type, path);
- }
- }
- else
- {
- (void) sprintf(path,"%s/%s/%s%s",mysql_data_home,table_list->db,
- table_list->real_name,reg_ext);
- fn_format(path,path,"","",4);
- VOID(pthread_mutex_lock(&LOCK_open));
- if (locked_table)
- mysql_lock_abort(thd,locked_table); // end threads waiting on lock
- // close all copies in use
- if (remove_table_from_cache(thd,table_list->db,table_list->real_name))
- {
- if (!locked_table)
- {
- VOID(pthread_mutex_unlock(&LOCK_open));
- DBUG_RETURN(1); // We must get a lock on table
- }
- }
- if (locked_table)
- locked_table->file->extra(HA_EXTRA_FORCE_REOPEN);
- if (thd->locked_tables)
- close_data_tables(thd,table_list->db,table_list->real_name);
- else
- close_thread_tables(thd,1);
- HA_CREATE_INFO create_info;
- bzero((char*) &create_info,sizeof(create_info));
- *fn_ext(path)=0; // Remove the .frm extension
- error= ha_create_table(path,&create_info,1) ? -1 : 0;
- if (thd->locked_tables && reopen_tables(thd,1,0))
- error= -1;
- VOID(pthread_mutex_unlock(&LOCK_open));
- }
- if (!error)
- {
- mysql_update_log.write(thd,thd->query,thd->query_length);
- if (mysql_bin_log.is_open())
- {
- Query_log_event qinfo(thd, thd->query);
- mysql_bin_log.write(&qinfo);
- }
- send_ok(&thd->net); // This should return record count
- }
- DBUG_RETURN(error ? -1 : 0);
-}
+#include "mysql_priv.h"
+#include "ha_innodb.h"
+#include "sql_select.h"
-int mysql_delete(THD *thd,TABLE_LIST *table_list,COND *conds,ha_rows limit,
- thr_lock_type lock_type, ulong options)
+int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ORDER *order,
+ ha_rows limit, thr_lock_type lock_type, ulong options)
{
int error;
TABLE *table;
- SQL_SELECT *select;
+ SQL_SELECT *select=0;
READ_RECORD info;
- bool using_limit=limit != HA_POS_ERROR;
- bool use_generate_table,using_transactions;
+ bool using_limit=limit != HA_POS_ERROR;
+ bool using_transactions;
+ ha_rows deleted;
DBUG_ENTER("mysql_delete");
if (!table_list->db)
@@ -137,40 +47,39 @@ int mysql_delete(THD *thd,TABLE_LIST *table_list,COND *conds,ha_rows limit,
DBUG_RETURN(1);
}
- use_generate_table= (!using_limit && !conds &&
- !(specialflag &
- (SPECIAL_NO_NEW_FUNC | SPECIAL_SAFE_MODE)) &&
- !(thd->options &
- (OPTION_NOT_AUTO_COMMIT | OPTION_BEGIN)));
-#ifdef HAVE_INNOBASE_DB
- /* We need to add code to not generate table based on the table type */
- if (!innodb_skip)
- use_generate_table=0; // Innodb can't use re-generate table
-#endif
- if (use_generate_table && ! thd->open_tables)
- {
- error=generate_table(thd,table_list,(TABLE*) 0);
- if (error <= 0)
- DBUG_RETURN(error); // Error or ok
- }
- if (!(table = open_ltable(thd,table_list,
- limit != HA_POS_ERROR ? TL_WRITE_LOW_PRIORITY :
- lock_type)))
+ if (!(table = open_ltable(thd,table_list, lock_type)))
DBUG_RETURN(-1);
table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
thd->proc_info="init";
- if (use_generate_table)
- DBUG_RETURN(generate_table(thd,table_list,table));
table->map=1;
if (setup_conds(thd,table_list,&conds) || setup_ftfuncs(thd))
DBUG_RETURN(-1);
+ /* Test if the user wants to delete all rows */
+ if (!using_limit && (!conds || conds->const_item()) &&
+ !(specialflag & (SPECIAL_NO_NEW_FUNC | SPECIAL_SAFE_MODE)))
+ {
+ deleted= table->file->records;
+ if (!(error=table->file->delete_all_rows()))
+ {
+ error= -1; // ok
+ goto cleanup;
+ }
+ if (error != HA_ERR_WRONG_COMMAND)
+ {
+ table->file->print_error(error,MYF(0));
+ error=0;
+ goto cleanup;
+ }
+ /* Handler didn't support fast delete; Delete rows one by one */
+ }
+
table->used_keys=table->quick_keys=0; // Can't use 'only index'
select=make_select(table,0,0,conds,&error);
if (error)
DBUG_RETURN(-1);
if ((select && select->check_quick(test(thd->options & SQL_SAFE_UPDATES),
- limit)) ||
+ limit)) ||
!limit)
{
delete select;
@@ -181,7 +90,7 @@ int mysql_delete(THD *thd,TABLE_LIST *table_list,COND *conds,ha_rows limit,
/* If running in safe sql mode, don't allow updates without keys */
if (!table->quick_keys)
{
- thd->lex.options|=QUERY_NO_INDEX_USED;
+ thd->lex.select_lex.options|=QUERY_NO_INDEX_USED;
if ((thd->options & OPTION_SAFE_UPDATES) && limit == HA_POS_ERROR)
{
delete select;
@@ -189,11 +98,37 @@ int mysql_delete(THD *thd,TABLE_LIST *table_list,COND *conds,ha_rows limit,
DBUG_RETURN(1);
}
}
- (void) table->file->extra(HA_EXTRA_NO_READCHECK);
if (options & OPTION_QUICK)
(void) table->file->extra(HA_EXTRA_QUICK);
- init_read_record(&info,thd,table,select,-1,1);
- ulong deleted=0L;
+
+ if (order)
+ {
+ uint length;
+ SORT_FIELD *sortorder;
+ TABLE_LIST tables;
+ List<Item> fields;
+ List<Item> all_fields;
+ ha_rows examined_rows;
+
+ bzero((char*) &tables,sizeof(tables));
+ tables.table = table;
+
+ table->io_cache = (IO_CACHE *) my_malloc(sizeof(IO_CACHE),
+ MYF(MY_FAE | MY_ZEROFILL));
+ if (setup_order(thd, &tables, fields, all_fields, order) ||
+ !(sortorder=make_unireg_sortorder(order, &length)) ||
+ (table->found_records = filesort(table, sortorder, length,
+ (SQL_SELECT *) 0, 0L, HA_POS_ERROR,
+ &examined_rows))
+ == HA_POS_ERROR)
+ {
+ delete select;
+ DBUG_RETURN(-1); // This will force out message
+ }
+ }
+
+ init_read_record(&info,thd,table,select,1,1);
+ deleted=0L;
init_ftfuncs(thd,1);
thd->proc_info="updating";
while (!(error=info.read_record(&info)) && !thd->killed)
@@ -221,9 +156,11 @@ int mysql_delete(THD *thd,TABLE_LIST *table_list,COND *conds,ha_rows limit,
}
thd->proc_info="end";
end_read_record(&info);
- (void) table->file->extra(HA_EXTRA_READCHECK);
+ free_io_cache(table); // Will not do any harm
if (options & OPTION_QUICK)
(void) table->file->extra(HA_EXTRA_NORMAL);
+
+cleanup:
using_transactions=table->file->has_transactions();
if (deleted && (error <= 0 || !using_transactions))
{
@@ -244,6 +181,8 @@ int mysql_delete(THD *thd,TABLE_LIST *table_list,COND *conds,ha_rows limit,
mysql_unlock_tables(thd, thd->lock);
thd->lock=0;
}
+ if (deleted)
+ query_cache.invalidate(table_list);
delete select;
if (error >= 0) // Fatal error
send_error(&thd->net,thd->killed ? ER_SERVER_SHUTDOWN: 0);
@@ -255,3 +194,377 @@ int mysql_delete(THD *thd,TABLE_LIST *table_list,COND *conds,ha_rows limit,
DBUG_RETURN(0);
}
+
+/***************************************************************************
+** delete multiple tables from join
+***************************************************************************/
+
+#define MEM_STRIP_BUF_SIZE sortbuff_size
+
+int refposcmp2(void* arg, const void *a,const void *b)
+{
+ return memcmp(a,b, *(int*) arg);
+}
+
+multi_delete::multi_delete(THD *thd_arg, TABLE_LIST *dt,
+ thr_lock_type lock_option_arg,
+ uint num_of_tables_arg)
+ : delete_tables (dt), thd(thd_arg), deleted(0),
+ num_of_tables(num_of_tables_arg), error(0), lock_option(lock_option_arg),
+ do_delete(false)
+{
+ uint counter=0;
+ not_trans_safe=false;
+ tempfiles = (Unique **) sql_calloc(sizeof(Unique *) * (num_of_tables-1));
+
+ /* Don't use key read with MULTI-TABLE-DELETE */
+ dt->table->used_keys=0;
+ for (dt=dt->next ; dt ; dt=dt->next,counter++)
+ {
+ TABLE *table=dt->table;
+ table->used_keys=0;
+ tempfiles[counter] = new Unique (refposcmp2,
+ (void *) &table->file->ref_length,
+ table->file->ref_length,
+ MEM_STRIP_BUF_SIZE);
+ }
+}
+
+
+int
+multi_delete::prepare(List<Item> &values)
+{
+ DBUG_ENTER("multi_delete::prepare");
+ do_delete = true;
+ thd->proc_info="deleting from main table";
+
+ if (thd->options & OPTION_SAFE_UPDATES)
+ {
+ TABLE_LIST *table_ref;
+ for (table_ref=delete_tables; table_ref; table_ref=table_ref->next)
+ {
+ TABLE *table=table_ref->table;
+ if ((thd->options & OPTION_SAFE_UPDATES) && !table->quick_keys)
+ {
+ my_error(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE,MYF(0));
+ DBUG_RETURN(1);
+ }
+ }
+ }
+ DBUG_RETURN(0);
+}
+
+
+void
+multi_delete::initialize_tables(JOIN *join)
+{
+ TABLE_LIST *walk;
+ table_map tables_to_delete_from=0;
+ for (walk= delete_tables ; walk ; walk=walk->next)
+ tables_to_delete_from|= walk->table->map;
+
+ walk= delete_tables;
+ for (JOIN_TAB *tab=join->join_tab, *end=join->join_tab+join->tables;
+ tab < end;
+ tab++)
+ {
+ if (tab->table->map & tables_to_delete_from)
+ {
+ /* We are going to delete from this table */
+ walk->table=tab->table;
+ walk=walk->next;
+ if (tab == join->join_tab)
+ tab->table->no_keyread=1;
+ if (!not_trans_safe && !tab->table->file->has_transactions())
+ not_trans_safe=true;
+ }
+ }
+ init_ftfuncs(thd,1);
+}
+
+
+multi_delete::~multi_delete()
+{
+ for (table_being_deleted=delete_tables ;
+ table_being_deleted ;
+ table_being_deleted=table_being_deleted->next)
+ {
+ TABLE *t=table_being_deleted->table;
+ free_io_cache(t); // Alloced by unique
+ t->no_keyread=0;
+ }
+
+ for (uint counter = 0; counter < num_of_tables-1; counter++)
+ {
+ if (tempfiles[counter])
+ delete tempfiles[counter];
+ }
+}
+
+
+bool multi_delete::send_data(List<Item> &values)
+{
+ int secure_counter= -1;
+ DBUG_ENTER("multi_delete::send_data");
+
+ for (table_being_deleted=delete_tables ;
+ table_being_deleted ;
+ table_being_deleted=table_being_deleted->next, secure_counter++)
+ {
+ TABLE *table=table_being_deleted->table;
+
+ /* Check if we are using outer join and we didn't find the row */
+ if (table->status & (STATUS_NULL_ROW | STATUS_DELETED))
+ continue;
+
+ table->file->position(table->record[0]);
+
+ if (secure_counter < 0)
+ {
+ /* If this is the table we are scanning */
+ table->status|= STATUS_DELETED;
+ if (!(error=table->file->delete_row(table->record[0])))
+ deleted++;
+ else
+ {
+ table->file->print_error(error,MYF(0));
+ DBUG_RETURN(1);
+ }
+ }
+ else
+ {
+ error=tempfiles[secure_counter]->unique_add((char*) table->file->ref);
+ if (error)
+ {
+ error=-1;
+ DBUG_RETURN(1);
+ }
+ }
+ }
+ DBUG_RETURN(0);
+}
+
+void multi_delete::send_error(uint errcode,const char *err)
+{
+ DBUG_ENTER("multi_delete::send_error");
+
+ /* First send error what ever it is ... */
+ ::send_error(&thd->net,errcode,err);
+
+ /* If nothing deleted return */
+ if (!deleted)
+ DBUG_VOID_RETURN;
+
+ /* Below can happen when thread is killed early ... */
+ if (!table_being_deleted)
+ table_being_deleted=delete_tables;
+
+ /*
+ If rows from the first table only has been deleted and it is
+ transactional, just do rollback.
+ The same if all tables are transactional, regardless of where we are.
+ In all other cases do attempt deletes ...
+ */
+ if ((table_being_deleted->table->file->has_transactions() &&
+ table_being_deleted == delete_tables) || !not_trans_safe)
+ ha_rollback_stmt(thd);
+ else if (do_delete)
+ {
+ VOID(do_deletes(1));
+ }
+ DBUG_VOID_RETURN;
+}
+
+
+/*
+ Do delete from other tables.
+ Returns values:
+ 0 ok
+ 1 error
+*/
+
+int multi_delete::do_deletes(bool from_send_error)
+{
+ int error = 0, counter = 0;
+
+ if (from_send_error)
+ {
+ /* Found out table number for 'table_being_deleted' */
+ for (TABLE_LIST *aux=delete_tables;
+ aux != table_being_deleted;
+ aux=aux->next)
+ counter++;
+ }
+ else
+ table_being_deleted = delete_tables;
+
+ do_delete = false;
+ for (table_being_deleted=table_being_deleted->next;
+ table_being_deleted ;
+ table_being_deleted=table_being_deleted->next, counter++)
+ {
+ TABLE *table = table_being_deleted->table;
+ if (tempfiles[counter]->get(table))
+ {
+ error=1;
+ break;
+ }
+
+ READ_RECORD info;
+ init_read_record(&info,thd,table,NULL,0,0);
+ while (!(error=info.read_record(&info)) &&
+ (!thd->killed || from_send_error || not_trans_safe))
+ {
+ if ((error=table->file->delete_row(table->record[0])))
+ {
+ table->file->print_error(error,MYF(0));
+ break;
+ }
+ deleted++;
+ }
+ end_read_record(&info);
+ if (error == -1) // End of file
+ error = 0;
+ }
+ return error;
+}
+
+
+/*
+ return: 0 sucess
+ 1 error
+*/
+
+bool multi_delete::send_eof()
+{
+ thd->proc_info="deleting from reference tables";
+
+ /* Does deletes for the last n - 1 tables, returns 0 if ok */
+ int error = do_deletes(0); // returns 0 if success
+
+ /* reset used flags */
+ thd->proc_info="end";
+ if (error)
+ {
+ ::send_error(&thd->net);
+ return 1;
+ }
+
+ /*
+ Write the SQL statement to the binlog if we deleted
+ rows and we succeeded, or also in an error case when there
+ was a non-transaction-safe table involved, since
+ modifications in it cannot be rolled back.
+ */
+ if (deleted || not_trans_safe)
+ {
+ mysql_update_log.write(thd,thd->query,thd->query_length);
+ if (mysql_bin_log.is_open())
+ {
+ Query_log_event qinfo(thd, thd->query);
+ if (mysql_bin_log.write(&qinfo) &&
+ !not_trans_safe)
+ error=1; // Log write failed: roll back the SQL statement
+ }
+ /* Commit or rollback the current SQL statement */
+ VOID(ha_autocommit_or_rollback(thd,error > 0));
+ }
+ if (deleted)
+ query_cache.invalidate(delete_tables);
+ ::send_ok(&thd->net,deleted);
+ return 0;
+}
+
+
+/***************************************************************************
+* TRUNCATE TABLE
+****************************************************************************/
+
+/*
+ Optimize delete of all rows by doing a full generate of the table
+ This will work even if the .ISM and .ISD tables are destroyed
+
+ dont_send_ok should be set if:
+ - We should always wants to generate the table (even if the table type
+ normally can't safely do this.
+ - We don't want an ok to be sent to the end user.
+ - We don't want to log the truncate command
+ - If we want to have a name lock on the table on exit without errors.
+*/
+
+int mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok)
+{
+ HA_CREATE_INFO create_info;
+ char path[FN_REFLEN];
+ TABLE **table_ptr;
+ int error;
+ DBUG_ENTER("mysql_truncate");
+
+ /* If it is a temporary table, close and regenerate it */
+ if (!dont_send_ok && (table_ptr=find_temporary_table(thd,table_list->db,
+ table_list->real_name)))
+ {
+ TABLE *table= *table_ptr;
+ HA_CREATE_INFO create_info;
+ table->file->info(HA_STATUS_AUTO | HA_STATUS_NO_LOCK);
+ bzero((char*) &create_info,sizeof(create_info));
+ create_info.auto_increment_value= table->file->auto_increment_value;
+ db_type table_type=table->db_type;
+
+ strmov(path,table->path);
+ *table_ptr= table->next; // Unlink table from list
+ close_temporary(table,0);
+ *fn_ext(path)=0; // Remove the .frm extension
+ ha_create_table(path, &create_info,1);
+ // We don't need to call invalidate() because this table is not in cache
+ if ((error= (int) !(open_temporary_table(thd, path, table_list->db,
+ table_list->real_name, 1))))
+ (void) rm_temporary_table(table_type, path);
+ DBUG_RETURN(error ? -1 : 0);
+ }
+
+ (void) sprintf(path,"%s/%s/%s%s",mysql_data_home,table_list->db,
+ table_list->real_name,reg_ext);
+ fn_format(path,path,"","",4);
+
+ if (!dont_send_ok)
+ {
+ db_type table_type;
+ if ((table_type=get_table_type(path)) == DB_TYPE_UNKNOWN)
+ {
+ my_error(ER_NO_SUCH_TABLE, MYF(0), table_list->real_name);
+ DBUG_RETURN(-1);
+ }
+ if (!ha_supports_generate(table_type))
+ {
+ /* Probably InnoDB table */
+ DBUG_RETURN(mysql_delete(thd,table_list, (COND*) 0, (ORDER*) 0,
+ HA_POS_ERROR, TL_WRITE, 0));
+ }
+ if (lock_and_wait_for_table_name(thd, table_list))
+ DBUG_RETURN(-1);
+ }
+
+ bzero((char*) &create_info,sizeof(create_info));
+ *fn_ext(path)=0; // Remove the .frm extension
+ error= ha_create_table(path,&create_info,1) ? -1 : 0;
+ query_cache.invalidate(table_list);
+
+ if (!dont_send_ok)
+ {
+ if (!error)
+ {
+ mysql_update_log.write(thd,thd->query,thd->query_length);
+ if (mysql_bin_log.is_open())
+ {
+ Query_log_event qinfo(thd, thd->query);
+ mysql_bin_log.write(&qinfo);
+ }
+ send_ok(&thd->net); // This should return record count
+ }
+ unlock_table_name(thd, table_list);
+ }
+ else if (error)
+ unlock_table_name(thd, table_list);
+ DBUG_RETURN(error ? -1 : 0);
+}
diff --git a/sql/sql_do.cc b/sql/sql_do.cc
index 57a6f88ed63..70124c2d796 100644
--- a/sql/sql_do.cc
+++ b/sql/sql_do.cc
@@ -25,7 +25,7 @@ int mysql_do(THD *thd, List<Item> &values)
List_iterator<Item> li(values);
Item *value;
DBUG_ENTER("mysql_do");
- if (setup_fields(thd,0, values, 0, 0))
+ if (setup_fields(thd,0, values, 0, 0, 0))
DBUG_RETURN(-1);
while ((value = li++))
value->val_int();
diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc
new file mode 100644
index 00000000000..8f9d3474ce2
--- /dev/null
+++ b/sql/sql_handler.cc
@@ -0,0 +1,278 @@
+/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+
+/* HANDLER ... commands - direct access to ISAM */
+
+#include <assert.h>
+#include "mysql_priv.h"
+#include "sql_select.h"
+
+/* TODO:
+ HANDLER blabla OPEN [ AS foobar ] [ (column-list) ]
+
+ the most natural (easiest, fastest) way to do it is to
+ compute List<Item> field_list not in mysql_ha_read
+ but in mysql_ha_open, and then store it in TABLE structure.
+
+ The problem here is that mysql_parse calls free_item to free all the
+ items allocated at the end of every query. The workaround would to
+ keep two item lists per THD - normal free_list and handler_items.
+ The second is to be freeed only on thread end. mysql_ha_open should
+ then do { handler_items=concat(handler_items, free_list); free_list=0; }
+
+ But !!! do_cammand calls free_root at the end of every query and frees up
+ all the sql_alloc'ed memory. It's harder to work around...
+ */
+
+#define HANDLER_TABLES_HACK(thd) { \
+ TABLE *tmp=thd->open_tables; \
+ thd->open_tables=thd->handler_tables; \
+ thd->handler_tables=tmp; }
+
+static TABLE **find_table_ptr_by_name(THD *thd, const char *db,
+ const char *table_name);
+
+int mysql_ha_open(THD *thd, TABLE_LIST *tables)
+{
+ HANDLER_TABLES_HACK(thd);
+ int err=open_tables(thd,tables);
+ HANDLER_TABLES_HACK(thd);
+ if (err)
+ return -1;
+
+ // there can be only one table in *tables
+ if (!(tables->table->file->option_flag() & HA_CAN_SQL_HANDLER))
+ {
+ my_printf_error(ER_ILLEGAL_HA,ER(ER_ILLEGAL_HA),MYF(0), tables->name);
+ mysql_ha_close(thd, tables,1);
+ return -1;
+ }
+
+ send_ok(&thd->net);
+ return 0;
+}
+
+int mysql_ha_close(THD *thd, TABLE_LIST *tables, bool dont_send_ok)
+{
+ TABLE **ptr=find_table_ptr_by_name(thd, tables->db, tables->name);
+
+ if (*ptr)
+ {
+ VOID(pthread_mutex_lock(&LOCK_open));
+ close_thread_table(thd, ptr);
+ VOID(pthread_mutex_unlock(&LOCK_open));
+ }
+ else
+ {
+ my_printf_error(ER_UNKNOWN_TABLE,ER(ER_UNKNOWN_TABLE),MYF(0),
+ tables->name,"HANDLER");
+ return -1;
+ }
+ if (!dont_send_ok)
+ send_ok(&thd->net);
+ return 0;
+}
+
+static enum enum_ha_read_modes rkey_to_rnext[]=
+ { RNEXT, RNEXT, RPREV, RNEXT, RPREV, RNEXT, RPREV };
+
+
+int mysql_ha_read(THD *thd, TABLE_LIST *tables,
+ enum enum_ha_read_modes mode, char *keyname, List<Item> *key_expr,
+ enum ha_rkey_function ha_rkey_mode, Item *cond,
+ ha_rows select_limit,ha_rows offset_limit)
+{
+ int err, keyno=-1;
+ TABLE *table=*find_table_ptr_by_name(thd, tables->db, tables->name);
+ if (!table)
+ {
+ my_printf_error(ER_UNKNOWN_TABLE,ER(ER_UNKNOWN_TABLE),MYF(0),
+ tables->name,"HANDLER");
+ return -1;
+ }
+ tables->table=table;
+
+ if (cond && cond->fix_fields(thd,tables))
+ return -1;
+
+ if (keyname)
+ {
+ if ((keyno=find_type(keyname, &table->keynames, 1+2)-1)<0)
+ {
+ my_printf_error(ER_KEY_DOES_NOT_EXITS,ER(ER_KEY_DOES_NOT_EXITS),MYF(0),
+ keyname,tables->name);
+ return -1;
+ }
+ }
+
+ List<Item> list;
+ list.push_front(new Item_field(NULL,NULL,"*"));
+ List_iterator<Item> it(list);
+ uint num_rows;
+ it++;
+
+ insert_fields(thd,tables,tables->db,tables->name,&it);
+
+ table->file->index_init(keyno);
+
+ select_limit+=offset_limit;
+ send_fields(thd,list,1);
+
+ HANDLER_TABLES_HACK(thd);
+ MYSQL_LOCK *lock=mysql_lock_tables(thd,&tables->table,1);
+ HANDLER_TABLES_HACK(thd);
+ if (!lock)
+ goto err0; // mysql_lock_tables() printed error message already
+
+ for (num_rows=0; num_rows < select_limit; )
+ {
+ switch(mode) {
+ case RFIRST:
+ err=keyname ?
+ table->file->index_first(table->record[0]) :
+ table->file->rnd_init(1) ||
+ table->file->rnd_next(table->record[0]);
+ mode=RNEXT;
+ break;
+ case RLAST:
+ DBUG_ASSERT(keyname != 0);
+ err=table->file->index_last(table->record[0]);
+ mode=RPREV;
+ break;
+ case RNEXT:
+ err=keyname ?
+ table->file->index_next(table->record[0]) :
+ table->file->rnd_next(table->record[0]);
+ break;
+ case RPREV:
+ DBUG_ASSERT(keyname != 0);
+ err=table->file->index_prev(table->record[0]);
+ break;
+ case RKEY:
+ {
+ DBUG_ASSERT(keyname != 0);
+ KEY *keyinfo=table->key_info+keyno;
+ KEY_PART_INFO *key_part=keyinfo->key_part;
+ uint key_len;
+ byte *key;
+ if (key_expr->elements > keyinfo->key_parts)
+ {
+ my_printf_error(ER_TOO_MANY_KEY_PARTS,ER(ER_TOO_MANY_KEY_PARTS),
+ MYF(0),keyinfo->key_parts);
+ goto err;
+ }
+ List_iterator_fast<Item> it_ke(*key_expr);
+ Item *item;
+ for (key_len=0 ; (item=it_ke++) ; key_part++)
+ {
+ item->save_in_field(key_part->field);
+ key_len+=key_part->store_length;
+ }
+ if (!(key= (byte*) sql_calloc(ALIGN_SIZE(key_len))))
+ {
+ send_error(&thd->net,ER_OUTOFMEMORY);
+ goto err;
+ }
+ key_copy(key, table, keyno, key_len);
+ err=table->file->index_read(table->record[0],
+ key,key_len,ha_rkey_mode);
+ mode=rkey_to_rnext[(int)ha_rkey_mode];
+ break;
+ }
+ default:
+ send_error(&thd->net,ER_ILLEGAL_HA);
+ goto err;
+ }
+
+ if (err)
+ {
+ if (err != HA_ERR_KEY_NOT_FOUND && err != HA_ERR_END_OF_FILE)
+ {
+ sql_print_error("mysql_ha_read: Got error %d when reading table",
+ err);
+ table->file->print_error(err,MYF(0));
+ goto err;
+ }
+ goto ok;
+ }
+ if (cond)
+ {
+ err=err;
+ if(!cond->val_int())
+ continue;
+ }
+ if (num_rows>=offset_limit)
+ {
+ if (!err)
+ {
+ String *packet = &thd->packet;
+ Item *item;
+ packet->length(0);
+ it.rewind();
+ while ((item=it++))
+ {
+ if (item->send(thd,packet))
+ {
+ packet->free(); // Free used
+ my_error(ER_OUT_OF_RESOURCES,MYF(0));
+ goto err;
+ }
+ }
+ my_net_write(&thd->net, (char*)packet->ptr(), packet->length());
+ }
+ }
+ num_rows++;
+ }
+ok:
+ mysql_unlock_tables(thd,lock);
+ send_eof(&thd->net);
+ return 0;
+err:
+ mysql_unlock_tables(thd,lock);
+err0:
+ return -1;
+}
+
+/**************************************************************************
+ 2Monty: It could easily happen, that the following service functions are
+ already defined somewhere in the code, but I failed to find them.
+ If this is the case, just say a word and I'll use old functions here.
+**************************************************************************/
+
+/* Note: this function differs from find_locked_table() because we're looking
+ here for alias, not real table name
+ */
+static TABLE **find_table_ptr_by_name(THD *thd, const char *db,
+ const char *table_name)
+{
+ int dblen;
+ TABLE **ptr;
+
+ if (!db || ! *db)
+ db= thd->db ? thd->db : "";
+ dblen=strlen(db)+1;
+ ptr=&(thd->handler_tables);
+
+ for (TABLE *table=*ptr; table ; table=*ptr)
+ {
+ if (!memcmp(table->table_cache_key, db, dblen) &&
+ !my_strcasecmp(table->table_name,table_name))
+ break;
+ ptr=&(table->next);
+ }
+ return ptr;
+}
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index d8861390d87..0898ad4bffb 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -78,7 +78,8 @@ check_insert_fields(THD *thd,TABLE *table,List<Item> &fields,
table_list.grant=table->grant;
thd->dupp_field=0;
- if (setup_tables(&table_list) || setup_fields(thd,&table_list,fields,1,0))
+ if (setup_tables(&table_list) ||
+ setup_fields(thd,&table_list,fields,1,0,0))
return -1;
if (thd->dupp_field)
{
@@ -102,14 +103,14 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields,
int error;
bool log_on= ((thd->options & OPTION_UPDATE_LOG) ||
!(thd->master_access & PROCESS_ACL));
- bool using_transactions;
+ bool using_transactions, bulk_insert=0;
uint value_count;
uint save_time_stamp;
ulong counter = 1;
ulonglong id;
COPY_INFO info;
TABLE *table;
- List_iterator<List_item> its(values_list);
+ List_iterator_fast<List_item> its(values_list);
List_item *values;
char *query=thd->query;
DBUG_ENTER("mysql_insert");
@@ -151,7 +152,7 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields,
save_time_stamp=table->time_stamp;
values= its++;
if (check_insert_fields(thd,table,fields,*values,1) ||
- setup_tables(table_list) || setup_fields(thd,table_list,*values,0,0))
+ setup_tables(table_list) || setup_fields(thd,table_list,*values,0,0,0))
{
table->time_stamp=save_time_stamp;
goto abort;
@@ -168,7 +169,7 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields,
table->time_stamp=save_time_stamp;
goto abort;
}
- if (setup_fields(thd,table_list,*values,0,0))
+ if (setup_fields(thd,table_list,*values,0,0,0))
{
table->time_stamp=save_time_stamp;
goto abort;
@@ -192,6 +193,14 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields,
thd->proc_info="update";
if (duplic == DUP_IGNORE || duplic == DUP_REPLACE)
table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
+ if ((bulk_insert= (values_list.elements > 1 &&
+ lock_type != TL_WRITE_DELAYED &&
+ !(specialflag & SPECIAL_SAFE_MODE))))
+ {
+ table->file->extra(HA_EXTRA_WRITE_CACHE);
+ table->file->extra(HA_EXTRA_BULK_INSERT_BEGIN);
+ }
+
while ((values = its++))
{
if (fields.elements || !value_count)
@@ -256,6 +265,25 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields,
}
else
{
+ if (bulk_insert)
+ {
+ if (table->file->extra(HA_EXTRA_NO_CACHE))
+ {
+ if (!error)
+ {
+ table->file->print_error(my_errno,MYF(0));
+ error=1;
+ }
+ }
+ if (table->file->extra(HA_EXTRA_BULK_INSERT_END))
+ {
+ if (!error)
+ {
+ table->file->print_error(my_errno,MYF(0));
+ error=1;
+ }
+ }
+ }
if (id && values_list.elements != 1)
thd->insert_id(id); // For update log
else if (table->next_number_field)
@@ -282,13 +310,14 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields,
}
}
thd->proc_info="end";
+ if (info.copied || info.deleted)
+ query_cache.invalidate(table_list);
table->time_stamp=save_time_stamp; // Restore auto timestamp ptr
table->next_number_field=0;
thd->count_cuted_fields=0;
thd->next_insert_id=0; // Reset this if wrongly used
if (duplic == DUP_IGNORE || duplic == DUP_REPLACE)
table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
-
if (error)
goto abort;
@@ -335,18 +364,18 @@ int write_record(TABLE *table,COPY_INFO *info)
{
int error;
char *key=0;
-
+
info->records++;
if (info->handle_duplicates == DUP_REPLACE)
{
while ((error=table->file->write_row(table->record[0])))
{
- if (error != HA_WRITE_SKIPP)
+ if (error != HA_WRITE_SKIP)
goto err;
uint key_nr;
if ((int) (key_nr = table->file->get_dup_key(error)) < 0)
{
- error=HA_WRITE_SKIPP; /* Database can't find key */
+ error=HA_WRITE_SKIP; /* Database can't find key */
goto err;
}
/*
@@ -364,12 +393,12 @@ int write_record(TABLE *table,COPY_INFO *info)
}
else
{
- if (table->file->extra(HA_EXTRA_FLUSH_CACHE)) /* Not neaded with NISAM */
+ if (table->file->extra(HA_EXTRA_FLUSH_CACHE)) /* Not needed with NISAM */
{
error=my_errno;
goto err;
}
-
+
if (!key)
{
if (!(key=(char*) my_safe_alloca(table->max_unique_length,
@@ -507,7 +536,7 @@ public:
}
~delayed_insert()
{
- /* The following is not really neaded, but just for safety */
+ /* The following is not really needed, but just for safety */
delayed_row *row;
while ((row=rows.get()))
delete row;
@@ -646,7 +675,7 @@ static TABLE *delayed_get_table(THD *thd,TABLE_LIST *table_list)
/* Copy error message and abort */
thd->fatal_error=1;
strmov(thd->net.last_error,tmp->thd.net.last_error);
- thd->net.last_errno=thd->net.last_errno;
+ thd->net.last_errno=tmp->thd.net.last_errno;
}
tmp->unlock();
pthread_mutex_unlock(&LOCK_delayed_create);
@@ -710,9 +739,9 @@ TABLE *delayed_insert::get_local_table(THD* client_thd)
}
client_thd->proc_info="allocating local table";
- copy= (TABLE*) sql_alloc(sizeof(*copy)+
- (table->fields+1)*sizeof(Field**)+
- table->reclength);
+ copy= (TABLE*) client_thd->alloc(sizeof(*copy)+
+ (table->fields+1)*sizeof(Field**)+
+ table->reclength);
if (!copy)
goto error;
*copy= *table;
@@ -730,7 +759,7 @@ TABLE *delayed_insert::get_local_table(THD* client_thd)
found_next_number_field=table->found_next_number_field;
for (org_field=table->field ; *org_field ; org_field++,field++)
{
- if (!(*field= (*org_field)->new_field(copy)))
+ if (!(*field= (*org_field)->new_field(&client_thd->mem_root,copy)))
return 0;
(*field)->move_field(adjust_ptrs); // Point at copy->record[0]
if (*org_field == found_next_number_field)
@@ -959,23 +988,12 @@ static pthread_handler_decl(handle_delayed_insert,arg)
if (!di->status && !di->stacked_inserts)
{
struct timespec abstime;
-#if defined(HAVE_TIMESPEC_TS_SEC)
- abstime.ts_sec=time((time_t*) 0)+(time_t) delayed_insert_timeout;
- abstime.ts_nsec=0;
-#elif defined(__WIN__)
- abstime.tv_sec=time((time_t*) 0)+(time_t) delayed_insert_timeout;
- abstime.tv_nsec=0;
-#else
- struct timeval tv;
- gettimeofday(&tv,0);
- abstime.tv_sec=tv.tv_sec+(time_t) delayed_insert_timeout;
- abstime.tv_nsec=tv.tv_usec*1000;
-#endif
+ set_timespec(abstime, delayed_insert_timeout);
/* Information for pthread_kill */
di->thd.mysys_var->current_mutex= &di->mutex;
di->thd.mysys_var->current_cond= &di->cond;
- di->thd.proc_info=0;
+ di->thd.proc_info="Waiting for INSERT";
DBUG_PRINT("info",("Waiting for someone to insert rows"));
while (!thd->killed)
@@ -1010,6 +1028,7 @@ static pthread_handler_decl(handle_delayed_insert,arg)
pthread_mutex_unlock(&di->thd.mysys_var->mutex);
pthread_mutex_lock(&di->mutex);
}
+ di->thd.proc_info=0;
if (di->tables_in_use && ! thd->lock)
{
@@ -1198,6 +1217,7 @@ bool delayed_insert::handle_inserts(void)
sql_print_error("%s",thd.net.last_error);
goto err;
}
+ query_cache.invalidate(table);
if (thr_reschedule_write_lock(*thd.lock->locks))
{
/* This should never happen */
@@ -1222,6 +1242,7 @@ bool delayed_insert::handle_inserts(void)
sql_print_error("%s",thd.net.last_error);
goto err;
}
+ query_cache.invalidate(table);
pthread_mutex_lock(&mutex);
DBUG_RETURN(0);
@@ -1255,7 +1276,7 @@ select_insert::prepare(List<Item> &values)
restore_record(table,2); // Get empty record
table->next_number_field=table->found_next_number_field;
- thd->count_cuted_fields=1; /* calc cuted fields */
+ thd->count_cuted_fields=1; // calc cuted fields
thd->cuted_fields=0;
if (info.handle_duplicates != DUP_REPLACE)
table->file->extra(HA_EXTRA_WRITE_CACHE);
@@ -1307,7 +1328,9 @@ void select_insert::send_error(uint errcode,const char *err)
::send_error(&thd->net,errcode,err);
table->file->extra(HA_EXTRA_NO_CACHE);
table->file->activate_all_index(thd);
- ha_rollback(thd);
+ ha_rollback_stmt(thd);
+ if (info.copied || info.deleted)
+ query_cache.invalidate(table);
}
@@ -1319,6 +1342,8 @@ bool select_insert::send_eof()
table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
if ((error2=ha_autocommit_or_rollback(thd,error)) && ! error)
error=error2;
+ if (info.copied || info.deleted)
+ query_cache.invalidate(table);
if (error)
{
@@ -1407,6 +1432,7 @@ bool select_create::send_data(List<Item> &values)
extern HASH open_cache;
+
bool select_create::send_eof()
{
bool tmp=select_insert::send_eof();
@@ -1419,7 +1445,8 @@ bool select_create::send_eof()
mysql_unlock_tables(thd, lock);
if (!table->tmp_table)
hash_delete(&open_cache,(byte*) table);
- lock=0; table=0;
+ lock=0;
+ table=0;
VOID(pthread_mutex_unlock(&LOCK_open));
}
return tmp;
@@ -1451,7 +1478,7 @@ void select_create::abort()
*****************************************************************************/
#ifdef __GNUC__
-template class List_iterator<List_item>;
+template class List_iterator_fast<List_item>;
template class I_List<delayed_insert>;
template class I_List_iterator<delayed_insert>;
template class I_List<delayed_row>;
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index a3c3db8947e..a3497d23ee5 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -142,12 +142,12 @@ LEX *lex_start(THD *thd, uchar *buf,uint length)
lex->next_state=STATE_START;
lex->end_of_query=(lex->ptr=buf)+length;
lex->yylineno = 1;
- lex->create_refs=lex->in_comment=0;
+ lex->select->create_refs=lex->in_comment=0;
lex->length=0;
- lex->in_sum_expr=0;
- lex->expr_list.empty();
- lex->ftfunc_list.empty();
- lex->convert_set=thd->convert_set;
+ lex->select->in_sum_expr=0;
+ lex->select->expr_list.empty();
+ lex->select->ftfunc_list.empty();
+ lex->convert_set=(lex->thd=thd)->convert_set;
lex->yacc_yyss=lex->yacc_yyvs=0;
lex->ignore_space=test(thd->sql_mode & MODE_IGNORE_SPACE);
return lex;
@@ -155,7 +155,7 @@ LEX *lex_start(THD *thd, uchar *buf,uint length)
void lex_end(LEX *lex)
{
- lex->expr_list.delete_elements(); // If error when parsing sql-varargs
+ lex->select->expr_list.delete_elements(); // If error when parsing sql-varargs
x_free(lex->yacc_yyss);
x_free(lex->yacc_yyvs);
}
@@ -196,12 +196,12 @@ static int find_keyword(LEX *lex, uint len, bool function)
/* make a copy of token before ptr and set yytoklen */
-static inline LEX_STRING get_token(LEX *lex,uint length)
+LEX_STRING get_token(LEX *lex,uint length)
{
LEX_STRING tmp;
yyUnget(); // ptr points now after last token char
tmp.length=lex->yytoklen=length;
- tmp.str=(char*) sql_strmake((char*) lex->tok_start,tmp.length);
+ tmp.str=(char*) lex->thd->strmake((char*) lex->tok_start,tmp.length);
return tmp;
}
@@ -250,7 +250,7 @@ static char *get_text(LEX *lex)
str=lex->tok_start+1;
end=lex->ptr-1;
- if (!(start=(uchar*) sql_alloc((uint) (end-str)+1)))
+ if (!(start=(uchar*) lex->thd->alloc((uint) (end-str)+1)))
return (char*) ""; // Sql_alloc has set error flag
if (!found_escape)
{
@@ -337,7 +337,8 @@ static const char *longlong_str="9223372036854775807";
static const uint longlong_len=19;
static const char *signed_longlong_str="-9223372036854775808";
static const uint signed_longlong_len=19;
-
+static const char *unsigned_longlong_str="18446744073709551615";
+static const uint unsigned_longlong_len=20;
inline static uint int_token(const char *str,uint length)
{
@@ -393,7 +394,13 @@ inline static uint int_token(const char *str,uint length)
else if (length < longlong_len)
return LONG_NUM;
else if (length > longlong_len)
- return REAL_NUM;
+ {
+ if (length > unsigned_longlong_len)
+ return REAL_NUM;
+ cmp=unsigned_longlong_str;
+ smaller=ULONGLONG_NUM;
+ bigger=REAL_NUM;
+ }
else
{
cmp=longlong_str;
@@ -430,7 +437,7 @@ int yylex(void *arg)
switch(state) {
case STATE_OPERATOR_OR_IDENT: // Next is operator or keyword
case STATE_START: // Start of token
- // Skipp startspace
+ // Skip startspace
for (c=yyGet() ; (state_map[c] == STATE_SKIP) ; c= yyGet())
{
if (c == '\n')
@@ -458,6 +465,11 @@ int yylex(void *arg)
return((int) c);
case STATE_IDENT: // Incomplete keyword or ident
+ if ((c == 'x' || c == 'X') && yyPeek() == '\'')
+ { // Found x'hex-number'
+ state=STATE_HEX_NUMBER;
+ break;
+ }
#if defined(USE_MB) && defined(USE_MB_IDENT)
if (use_mb(default_charset_info))
{
@@ -509,6 +521,8 @@ int yylex(void *arg)
yySkip(); // next state does a unget
}
yylval->lex_str=get_token(lex,length);
+ if (lex->convert_set)
+ lex->convert_set->convert((char*) yylval->lex_str.str,lex->yytoklen);
return(IDENT);
case STATE_IDENT_SEP: // Found ident and now '.'
@@ -518,7 +532,7 @@ int yylex(void *arg)
c=yyGet(); // should be '.'
return((int) c);
- case STATE_NUMBER_IDENT: // number or ident which starts with num
+ case STATE_NUMBER_IDENT: // number or ident which num-start
while (isdigit((c = yyGet()))) ;
if (state_map[c] != STATE_IDENT)
{ // Can't be identifier
@@ -544,10 +558,10 @@ int yylex(void *arg)
lex->tok_start[0] == '0' )
{ // Varbinary
while (isxdigit((c = yyGet()))) ;
- if ((lex->ptr - lex->tok_start) >= 4)
+ if ((lex->ptr - lex->tok_start) >= 4 && state_map[c] != STATE_IDENT)
{
yylval->lex_str=get_token(lex,yyLength());
- yylval->lex_str.str+=2; // Skipp 0x
+ yylval->lex_str.str+=2; // Skip 0x
yylval->lex_str.length-=2;
lex->yytoklen-=2;
return (HEX_NUM);
@@ -597,10 +611,12 @@ int yylex(void *arg)
case STATE_FOUND_IDENT: // Complete ident
yylval->lex_str=get_token(lex,yyLength());
+ if (lex->convert_set)
+ lex->convert_set->convert((char*) yylval->lex_str.str,lex->yytoklen);
return(IDENT);
case STATE_USER_VARIABLE_DELIMITER:
- lex->tok_start=lex->ptr; // Skipp first `
+ lex->tok_start=lex->ptr; // Skip first `
#ifdef USE_MB
if (use_mb(default_charset_info))
{
@@ -625,14 +641,17 @@ int yylex(void *arg)
c != (uchar) NAMES_SEP_CHAR) ;
}
yylval->lex_str=get_token(lex,yyLength());
+ if (lex->convert_set)
+ lex->convert_set->convert((char*) yylval->lex_str.str,lex->yytoklen);
if (state_map[c] == STATE_USER_VARIABLE_DELIMITER)
- yySkip(); // Skipp end `
+ yySkip(); // Skip end `
return(IDENT);
case STATE_SIGNED_NUMBER: // Incomplete signed number
if (prev_state == STATE_OPERATOR_OR_IDENT)
{
- if (c == '-' && yyPeek() == '-' && isspace(yyPeek2()))
+ if (c == '-' && yyPeek() == '-' &&
+ (isspace(yyPeek2()) || iscntrl(yyPeek2())))
state=STATE_COMMENT;
else
state= STATE_CHAR; // Must be operator
@@ -672,7 +691,7 @@ int yylex(void *arg)
{
c = yyGet();
if (c == '-' || c == '+')
- c = yyGet(); // Skipp sign
+ c = yyGet(); // Skip sign
if (!isdigit(c))
{ // No digit after sign
state= STATE_CHAR;
@@ -685,6 +704,21 @@ int yylex(void *arg)
yylval->lex_str=get_token(lex,yyLength());
return(REAL_NUM);
+ case STATE_HEX_NUMBER: // Found x'hexstring'
+ yyGet(); // Skip '
+ while (isxdigit((c = yyGet()))) ;
+ length=(lex->ptr - lex->tok_start); // Length of hexnum+3
+ if (!(length & 1) || c != '\'')
+ {
+ return(ABORT_SYM); // Illegal hex constant
+ }
+ yyGet(); // get_token makes an unget
+ yylval->lex_str=get_token(lex,length);
+ yylval->lex_str.str+=2; // Skip x'
+ yylval->lex_str.length-=3; // Don't count x' and last '
+ lex->yytoklen-=3;
+ return (HEX_NUM);
+
case STATE_CMP_OP: // Incomplete comparison operator
if (state_map[yyPeek()] == STATE_CMP_OP ||
state_map[yyPeek()] == STATE_LONG_CMP_OP)
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 2b889d356bb..c0ede015eb8 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -22,7 +22,7 @@ class Table_ident;
class sql_exchange;
class LEX_COLUMN;
-// The following hack is neaded because mysql_yacc.cc does not define
+// The following hack is needed because mysql_yacc.cc does not define
// YYSTYPE before including this file
#ifdef MYSQL_YACC
@@ -53,7 +53,11 @@ enum enum_sql_command {
SQLCOM_BEGIN, SQLCOM_LOAD_MASTER_TABLE, SQLCOM_CHANGE_MASTER,
SQLCOM_RENAME_TABLE, SQLCOM_BACKUP_TABLE, SQLCOM_RESTORE_TABLE,
SQLCOM_RESET, SQLCOM_PURGE, SQLCOM_SHOW_BINLOGS,
- SQLCOM_SHOW_OPEN_TABLES, SQLCOM_DO, SQLCOM_EMPTY_QUERY,
+ SQLCOM_SHOW_OPEN_TABLES, SQLCOM_LOAD_MASTER_DATA,
+ SQLCOM_HA_OPEN, SQLCOM_HA_CLOSE, SQLCOM_HA_READ,
+ SQLCOM_SHOW_SLAVE_HOSTS, SQLCOM_DELETE_MULTI, SQLCOM_MULTI_UPDATE,
+ SQLCOM_SHOW_BINLOG_EVENTS, SQLCOM_SHOW_NEW_MASTER, SQLCOM_DO,
+ SQLCOM_EMPTY_QUERY,
SQLCOM_END
};
@@ -63,6 +67,7 @@ enum lex_states { STATE_START, STATE_CHAR, STATE_IDENT,
STATE_FOUND_IDENT,
STATE_SIGNED_NUMBER,
STATE_REAL,
+ STATE_HEX_NUMBER,
STATE_CMP_OP,
STATE_LONG_CMP_OP,
STATE_STRING,
@@ -92,59 +97,95 @@ typedef struct st_lex_master_info
char* host, *user, *password,*log_file_name;
uint port, connect_retry;
ulonglong pos;
+ ulong server_id;
} LEX_MASTER_INFO;
+
+enum sub_select_type {UNSPECIFIED_TYPE,UNION_TYPE, INTERSECT_TYPE, EXCEPT_TYPE, NOT_A_SELECT};
+
+/* The state of the lex parsing for selects */
+
+typedef struct st_select_lex {
+ enum sub_select_type linkage;
+ char *db,*db1,*table1,*db2,*table2; /* For outer join using .. */
+ Item *where,*having;
+ ha_rows select_limit,offset_limit;
+ ulong options;
+ List<List_item> expr_list;
+ List<List_item> when_list;
+ SQL_LIST order_list,table_list,group_list;
+ List<Item> item_list;
+ List<String> interval_list,use_index, *use_index_ptr,
+ ignore_index, *ignore_index_ptr;
+ List<Item_func_match> ftfunc_list;
+ uint in_sum_expr, sort_default;
+ bool create_refs, braces;
+ st_select_lex *next;
+} SELECT_LEX;
+
+
+class Set_option :public Sql_alloc {
+public:
+ const char *name;
+ Item *item;
+ uint name_length;
+ bool type; /* 1 if global */
+ Set_option(bool par_type, const char *par_name, uint length,
+ Item *par_item)
+ :name(par_name), item(par_item), name_length(length), type(par_type) {}
+};
+
+
/* The state of the lex parsing. This is saved in the THD struct */
typedef struct st_lex {
uint yylineno,yytoklen; /* Simulate lex */
LEX_YYSTYPE yylval;
+ SELECT_LEX select_lex, *select;
uchar *ptr,*tok_start,*tok_end,*end_of_query;
char *length,*dec,*change,*name;
- char *db,*db1,*table1,*db2,*table2; /* For outer join using .. */
char *backup_dir; /* For RESTORE/BACKUP */
char* to_log; /* For PURGE MASTER LOGS TO */
+ char* x509_subject,*x509_issuer,*ssl_cipher;
+ enum SSL_type ssl_type; /* defined in violite.h */
String *wild;
sql_exchange *exchange;
- ha_rows select_limit,offset_limit;
- List<List_item> expr_list;
- List<List_item> when_list;
- List<List_item> many_values;
List<key_part_spec> col_list;
List<Alter_drop> drop_list;
List<Alter_column> alter_list;
- List<String> interval_list,use_index,*use_index_ptr,
- ignore_index, *ignore_index_ptr;
+ List<String> interval_list;
List<st_lex_user> users_list;
List<LEX_COLUMN> columns;
List<Key> key_list;
List<create_field> create_list;
- List<Item> item_list,*insert_list,field_list,value_list;
- List<Item_func_match> ftfunc_list;
- SQL_LIST order_list,table_list,group_list,proc_list;
+ List<Item> *insert_list,field_list,value_list;
+ List<List_item> many_values;
+ List<Set_option> option_list;
+ SQL_LIST proc_list, auxilliary_table_list;
TYPELIB *interval;
create_field *last_field;
-
- Item *where,*having,*default_value;
+ Item *default_value;
CONVERT *convert_set;
LEX_USER *grant_user;
gptr yacc_yyss,yacc_yyvs;
+ THD *thd;
udf_func udf;
HA_CHECK_OPT check_opt; // check/repair options
HA_CREATE_INFO create_info;
LEX_MASTER_INFO mi; // used by CHANGE MASTER
ulong thread_id,type;
- ulong options;
- ulong gemini_spin_retries;
enum_sql_command sql_command;
enum lex_states next_state;
enum enum_duplicates duplicates;
enum enum_tx_isolation tx_isolation;
- uint in_sum_expr,grant,grant_tot_col,which_columns;
+ enum enum_ha_read_modes ha_read_mode;
+ enum ha_rkey_function ha_rkey_mode;
+ enum enum_enable_or_disable alter_keys_onoff;
+ uint grant,grant_tot_col,which_columns, union_option, mqh;
thr_lock_type lock_option;
- bool create_refs,drop_primary,drop_if_exists,local_file;
- bool in_comment,ignore_space,verbose;
+ bool drop_primary,drop_if_exists,local_file;
+ bool in_comment,ignore_space,verbose,simple_alter, option_type;
} LEX;
diff --git a/sql/sql_list.cc b/sql/sql_list.cc
index 7d5fc442121..1124605ca24 100644
--- a/sql/sql_list.cc
+++ b/sql/sql_list.cc
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -20,3 +20,5 @@
#endif
#include "mysql_priv.h"
+
+list_node end_of_list;
diff --git a/sql/sql_list.h b/sql/sql_list.h
index d21f2e658dc..542eef623f0 100644
--- a/sql/sql_list.h
+++ b/sql/sql_list.h
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -41,25 +41,40 @@ public:
/*
** basic single linked list
** Used for item and item_buffs.
+** All list ends with a pointer to the 'end_of_list' element, which
+** data pointer is a null pointer and the next pointer points to itself.
+** This makes it very fast to traverse lists as we don't have to
+** test for a specialend condition for list that can't contain a null
+** pointer.
*/
+class list_node :public Sql_alloc
+{
+public:
+ list_node *next;
+ void *info;
+ list_node(void *info_par,list_node *next_par)
+ :next(next_par),info(info_par)
+ {}
+ list_node() /* For end_of_list */
+ {
+ info=0;
+ next= this;
+ }
+ friend class base_list;
+ friend class base_list_iterator;
+};
+
+extern list_node end_of_list;
+
class base_list :public Sql_alloc {
protected:
- class list_node :public Sql_alloc
- {
- public:
- list_node *next;
- void *info;
- list_node(void *info_par,list_node *next_par) : next(next_par),info(info_par) {}
- friend class base_list;
- friend class base_list_iterator;
- };
list_node *first,**last;
public:
uint elements;
- inline void empty() { elements=0; first=0; last=&first;}
+ inline void empty() { elements=0; first= &end_of_list; last=&first;}
inline base_list() { empty(); }
inline base_list(const base_list &tmp) :Sql_alloc()
{
@@ -69,7 +84,7 @@ public:
}
inline bool push_back(void *info)
{
- if (((*last)=new list_node(info,0)))
+ if (((*last)=new list_node(info, &end_of_list)))
{
last= &(*last)->next;
elements++;
@@ -82,7 +97,7 @@ public:
list_node *node=new list_node(info,first);
if (node)
{
- if (!first)
+ if (last == &first)
last= &node->next;
first=node;
elements++;
@@ -96,22 +111,21 @@ public:
delete *prev;
*prev=node;
if (!--elements)
- {
last= &first;
- first=0;
- }
}
inline void *pop(void)
{
- if (!first) return 0;
+ if (first == &end_of_list) return 0;
list_node *tmp=first;
first=first->next;
if (!--elements)
last= &first;
return tmp->info;
}
- inline void *head() { return first ? first->info : 0; }
- inline void **head_ref() { return first ? &first->info : 0; }
+ inline void *head() { return first->info; }
+ inline void **head_ref() { return first != &end_of_list ? &first->info : 0; }
+ inline bool is_empty() { return first == &end_of_list ; }
+ inline list_node *last_ref() { return &end_of_list; }
friend class base_list_iterator;
protected:
@@ -129,7 +143,7 @@ protected:
class base_list_iterator
{
base_list *list;
- base_list::list_node **el,**prev,*current;
+ list_node **el,**prev,*current;
public:
base_list_iterator(base_list &list_par) :list(&list_par),el(&list_par.first),
prev(0),current(0)
@@ -137,16 +151,22 @@ public:
inline void *next(void)
{
prev=el;
- if (!(current= *el))
- return 0;
+ current= *el;
el= &current->next;
return current->info;
}
+ inline void *next_fast(void)
+ {
+ list_node *tmp;
+ tmp= *el;
+ el= &tmp->next;
+ return tmp->info;
+ }
inline void rewind(void)
{
el= &list->first;
}
- void *replace(void *element)
+ inline void *replace(void *element)
{ // Return old element
void *tmp=current->info;
current->info=element;
@@ -155,7 +175,7 @@ public:
void *replace(base_list &new_list)
{
void *ret_value=current->info;
- if (new_list.first)
+ if (!new_list.is_empty())
{
*new_list.last=current->next;
current->info=new_list.first->info;
@@ -182,7 +202,7 @@ public:
}
inline bool is_last(void)
{
- return *el == 0;
+ return el == &list->last_ref()->next;
}
};
@@ -200,7 +220,7 @@ public:
void delete_elements(void)
{
list_node *element,*next;
- for (element=first; element ; element=next)
+ for (element=first; element != &end_of_list; element=next)
{
next=element->next;
delete (T*) element->info;
@@ -215,18 +235,30 @@ template <class T> class List_iterator :public base_list_iterator
public:
List_iterator(List<T> &a) : base_list_iterator(a) {}
inline T* operator++(int) { return (T*) base_list_iterator::next(); }
- inline void rewind(void) { base_list_iterator::rewind(); }
inline T *replace(T *a) { return (T*) base_list_iterator::replace(a); }
inline T *replace(List<T> &a) { return (T*) base_list_iterator::replace(a); }
- inline void remove(void) { base_list_iterator::remove(); }
inline void after(T *a) { base_list_iterator::after(a); }
inline T** ref(void) { return (T**) base_list_iterator::ref(); }
- inline bool is_last(void) { return base_list_iterator::is_last(); }
+};
+
+template <class T> class List_iterator_fast :public base_list_iterator
+{
+protected:
+ inline T *replace(T *a) { return (T*) 0; }
+ inline T *replace(List<T> &a) { return (T*) 0; }
+ inline void remove(void) { }
+ inline void after(T *a) { }
+ inline T** ref(void) { return (T**) 0; }
+
+public:
+ List_iterator_fast(List<T> &a) : base_list_iterator(a) {}
+ inline T* operator++(int) { return (T*) base_list_iterator::next_fast(); }
+ inline void rewind(void) { base_list_iterator::rewind(); }
};
/*
-** An simple intrusive list with automaticly removes element from list
+** A simple intrusive list which automaticly removes element from list
** on delete (for THD element)
*/
diff --git a/sql/sql_load.cc b/sql/sql_load.cc
index dd8487ceecc..419e3fccabd 100644
--- a/sql/sql_load.cc
+++ b/sql/sql_load.cc
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -20,6 +20,7 @@
#include "mysql_priv.h"
#include <my_dir.h>
#include <m_ctype.h>
+#include "sql_repl.h"
class READ_INFO {
File file;
@@ -32,6 +33,7 @@ class READ_INFO {
int field_term_char,line_term_char,enclosed_char,escape_char;
int *stack,*stack_pos;
bool found_end_of_line,start_of_line,eof;
+ bool need_end_io_cache;
IO_CACHE cache;
NET *io_net;
@@ -50,6 +52,18 @@ public:
char unescape(char chr);
int terminator(char *ptr,uint length);
bool find_start_of_fields();
+ // we need to force cache close before destructor is invoked to log
+ // the last read block
+ void end_io_cache()
+ {
+ ::end_io_cache(&cache);
+ need_end_io_cache = 0;
+ }
+
+ // either this method, or we need to make cache public
+ // arg must be set from mysql_load() since constructor does not see
+ // either the table or THD value
+ void set_io_cache_arg(void* arg) { cache.arg = arg; }
};
static int read_fixed_length(THD *thd,COPY_INFO &info,TABLE *table,
@@ -67,12 +81,12 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
File file;
TABLE *table;
int error;
- uint save_skip_lines = ex->skip_lines;
String *field_term=ex->field_term,*escaped=ex->escaped,
*enclosed=ex->enclosed;
bool is_fifo=0;
+ LOAD_FILE_INFO lf_info;
+ char * db = table_list->db ? table_list->db : thd->db;
bool using_transactions;
-
DBUG_ENTER("mysql_load");
if (escaped->length() > 1 || enclosed->length() > 1)
@@ -81,7 +95,6 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
MYF(0));
DBUG_RETURN(-1);
}
-
if (!(table = open_ltable(thd,table_list,lock_type)))
DBUG_RETURN(-1);
if (!fields.elements)
@@ -93,7 +106,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
else
{ // Part field list
thd->dupp_field=0;
- if (setup_tables(table_list) || setup_fields(thd,table_list,fields,1,0))
+ if (setup_tables(table_list) || setup_fields(thd,table_list,fields,1,0,0))
DBUG_RETURN(-1);
if (thd->dupp_field)
{
@@ -104,7 +117,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
uint tot_length=0;
bool use_blobs=0,use_timestamp=0;
- List_iterator<Item> it(fields);
+ List_iterator_fast<Item> it(fields);
Item_field *field;
while ((field=(Item_field*) it++))
@@ -134,12 +147,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
if (read_file_from_client)
{
- char tmp [FN_REFLEN+1],*end;
- DBUG_PRINT("info",("reading local file"));
- tmp[0] = (char) 251; /* NULL_LENGTH */
- end=strnmov(tmp+1,ex->file_name,sizeof(tmp)-2);
- (void) my_net_write(&thd->net,tmp,(uint) (end-tmp));
- (void) net_flush(&thd->net);
+ (void)net_request_file(&thd->net,ex->file_name);
file = -1;
}
else
@@ -162,9 +170,10 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
MY_STAT stat_info;
if (!my_stat(name,&stat_info,MYF(MY_WME)))
DBUG_RETURN(-1);
-
- // the file must be:
- if (!((stat_info.st_mode & S_IROTH) == S_IROTH && // readable by others
+
+ // if we are not in slave thread, the file must be:
+ if (!thd->slave_thread &&
+ !((stat_info.st_mode & S_IROTH) == S_IROTH && // readable by others
#ifndef __EMX__
(stat_info.st_mode & S_IFLNK) != S_IFLNK && // and not a symlink
#endif
@@ -197,13 +206,27 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
DBUG_RETURN(-1); // Can't allocate buffers
}
+ if (!opt_old_rpl_compat && mysql_bin_log.is_open())
+ {
+ lf_info.thd = thd;
+ lf_info.ex = ex;
+ lf_info.db = db;
+ lf_info.table_name = table_list->real_name;
+ lf_info.fields = &fields;
+ lf_info.handle_dup = handle_duplicates;
+ lf_info.wrote_create_file = 0;
+ lf_info.last_pos_in_file = HA_POS_ERROR;
+ read_info.set_io_cache_arg((void*)&lf_info);
+ }
restore_record(table,2);
thd->count_cuted_fields=1; /* calc cuted fields */
thd->cuted_fields=0L;
if (ex->line_term->length() && field_term->length())
{
- while (ex->skip_lines--)
+ // ex->skip_lines needs to be preserved for logging
+ uint skip_lines = ex->skip_lines;
+ while (skip_lines--)
{
if (read_info.next_line())
break;
@@ -216,6 +239,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
table->time_stamp=0;
table->next_number_field=table->found_next_number_field;
VOID(table->file->extra(HA_EXTRA_WRITE_CACHE));
+ VOID(table->file->extra(HA_EXTRA_BULK_INSERT_BEGIN));
if (handle_duplicates == DUP_IGNORE ||
handle_duplicates == DUP_REPLACE)
table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
@@ -225,9 +249,10 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
error=read_fixed_length(thd,info,table,fields,read_info);
else
error=read_sep_field(thd,info,table,fields,read_info,*enclosed);
- if (table->file->extra(HA_EXTRA_NO_CACHE) ||
- table->file->activate_all_index(thd))
- error=1; /* purecov: inspected */
+ if (table->file->extra(HA_EXTRA_NO_CACHE))
+ error=1; /* purecov: inspected */
+ if (table->file->activate_all_index(thd))
+ error=1; /* purecov: inspected */
table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
table->time_stamp=save_time_stamp;
table->next_number_field=0;
@@ -246,7 +271,15 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
{
if (using_transactions)
ha_autocommit_or_rollback(thd,error);
- DBUG_RETURN(-1); // Error on read
+ if (!opt_old_rpl_compat && mysql_bin_log.is_open())
+ {
+ if (lf_info.wrote_create_file)
+ {
+ Delete_file_log_event d(thd);
+ mysql_bin_log.write(&d);
+ }
+ }
+ DBUG_RETURN(-1); // Error on read
}
sprintf(name,ER(ER_LOAD_INFO),info.records,info.deleted,
info.records-info.copied,thd->cuted_fields);
@@ -254,15 +287,26 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
// on the slave thd->query is never initialized
if(!thd->slave_thread)
mysql_update_log.write(thd,thd->query,thd->query_length);
-
+
if (!using_transactions)
thd->options|=OPTION_STATUS_NO_TRANS_UPDATE;
- if (!read_file_from_client && mysql_bin_log.is_open())
+ if (mysql_bin_log.is_open())
{
- ex->skip_lines = save_skip_lines;
- Load_log_event qinfo(thd, ex, table->table_name, fields,
+ if (opt_old_rpl_compat && !read_file_from_client)
+ {
+ Load_log_event qinfo(thd, ex, db, table->table_name, fields,
handle_duplicates);
- mysql_bin_log.write(&qinfo);
+ mysql_bin_log.write(&qinfo);
+ }
+ if (!opt_old_rpl_compat)
+ {
+ read_info.end_io_cache(); // make sure last block gets logged
+ if (lf_info.wrote_create_file)
+ {
+ Execute_load_log_event e(thd);
+ mysql_bin_log.write(&e);
+ }
+ }
}
if (using_transactions)
error=ha_autocommit_or_rollback(thd,error);
@@ -278,7 +322,7 @@ static int
read_fixed_length(THD *thd,COPY_INFO &info,TABLE *table,List<Item> &fields,
READ_INFO &read_info)
{
- List_iterator<Item> it(fields);
+ List_iterator_fast<Item> it(fields);
Item_field *sql_field;
DBUG_ENTER("read_fixed_length");
@@ -326,7 +370,7 @@ read_fixed_length(THD *thd,COPY_INFO &info,TABLE *table,List<Item> &fields,
DBUG_RETURN(1);
if (table->next_number_field)
table->next_number_field->reset(); // Clear for next record
- if (read_info.next_line()) // Skipp to next line
+ if (read_info.next_line()) // Skip to next line
break;
if (read_info.line_cuted)
thd->cuted_fields++; /* To long row */
@@ -341,7 +385,7 @@ read_sep_field(THD *thd,COPY_INFO &info,TABLE *table,
List<Item> &fields, READ_INFO &read_info,
String &enclosed)
{
- List_iterator<Item> it(fields);
+ List_iterator_fast<Item> it(fields);
Item_field *sql_field;
uint enclosed_length;
DBUG_ENTER("read_sep_field");
@@ -402,7 +446,7 @@ read_sep_field(THD *thd,COPY_INFO &info,TABLE *table,
DBUG_RETURN(1);
if (table->next_number_field)
table->next_number_field->reset(); // Clear for next record
- if (read_info.next_line()) // Skipp to next line
+ if (read_info.next_line()) // Skip to next line
break;
if (read_info.line_cuted)
thd->cuted_fields++; /* To long row */
@@ -489,6 +533,21 @@ READ_INFO::READ_INFO(File file_par, uint tot_length, String &field_term,
my_free((gptr) buffer,MYF(0)); /* purecov: inspected */
error=1;
}
+ else
+ {
+ /* init_io_cache() will not initialize read_function member
+ if the cache is READ_NET. The reason is explained in
+ mysys/mf_iocache.c. So we work around the problem with a
+ manual assignment
+ */
+ if (get_it_from_net)
+ cache.read_function = _my_b_net_read;
+
+ need_end_io_cache = 1;
+ if (!opt_old_rpl_compat && mysql_bin_log.is_open())
+ cache.pre_read = cache.pre_close =
+ (IO_CACHE_CALLBACK) log_loaded_block;
+ }
}
}
@@ -497,7 +556,8 @@ READ_INFO::~READ_INFO()
{
if (!error)
{
- end_io_cache(&cache);
+ if (need_end_io_cache)
+ ::end_io_cache(&cache);
my_free((gptr) buffer,MYF(0));
error=1;
}
@@ -537,10 +597,10 @@ int READ_INFO::read_field()
if (found_end_of_line)
return 1; // One have to call next_line
- /* Skipp until we find 'line_start' */
+ /* Skip until we find 'line_start' */
if (start_of_line)
- { // Skipp until line_start
+ { // Skip until line_start
start_of_line=0;
if (find_start_of_fields())
return 1;
@@ -683,7 +743,7 @@ found_eof:
/*
** One can't use fixed length with multi-byte charset **
*/
-
+
int READ_INFO::read_fixed_length()
{
int chr;
@@ -692,7 +752,7 @@ int READ_INFO::read_fixed_length()
return 1; // One have to call next_line
if (start_of_line)
- { // Skipp until line_start
+ { // Skip until line_start
start_of_line=0;
if (find_start_of_fields())
return 1;
diff --git a/sql/sql_manager.cc b/sql/sql_manager.cc
index 53953c96d0b..13cac83fc3f 100644
--- a/sql/sql_manager.cc
+++ b/sql/sql_manager.cc
@@ -55,13 +55,7 @@ pthread_handler_decl(handle_manager,arg __attribute__((unused)))
{
if (reset_flush_time)
{
-#ifdef HAVE_TIMESPEC_TS_SEC
- abstime.ts_sec = time(NULL)+flush_time; // Bsd 2.1
- abstime.ts_nsec = 0;
-#else
- abstime.tv_sec = time(NULL)+flush_time; // Linux or Solairs
- abstime.tv_nsec = 0;
-#endif
+ set_timespec(abstime, flush_time);
reset_flush_time = FALSE;
}
while (!manager_status && !error && !abort_loop)
diff --git a/sql/sql_map.cc b/sql/sql_map.cc
index 4578b85d10a..e7e24f957c6 100644
--- a/sql/sql_map.cc
+++ b/sql/sql_map.cc
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
diff --git a/sql/sql_map.h b/sql/sql_map.h
index 34f2f755b43..632eb6e4f64 100644
--- a/sql/sql_map.h
+++ b/sql/sql_map.h
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index fa4a4fd4f3b..7f9c8da05c1 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+/* Copyright (C) 2000 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -14,16 +14,38 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+#ifdef EMBEDDED_LIBRARY
+#define net_read_timeout net_read_timeout1
+#define net_write_timeout net_write_timeout1
+#endif
#include "mysql_priv.h"
#include "sql_acl.h"
#include "sql_repl.h"
+#include "repl_failsafe.h"
#include <m_ctype.h>
#include <thr_alarm.h>
#include <myisam.h>
#include <my_dir.h>
#include <assert.h>
+#ifdef HAVE_OPENSSL
+/*
+ Without SSL the handshake consists of one packet. This packet
+ has both client capabilites and scrambled password.
+ With SSL the handshake might consist of two packets. If the first
+ packet (client capabilities) has CLIENT_SSL flag set, we have to
+ switch to SSL and read the second packet. The scrambled password
+ is in the second packet and client_capabilites field will be ignored.
+ Maybe it is better to accept flags other than CLIENT_SSL from the
+ second packet?
+*/
+#define SSL_HANDSHAKE_SIZE 2
+#define NORMAL_HANDSHAKE_SIZE 6
+#define MIN_HANDSHAKE_SIZE 2
+#else
+#define MIN_HANDSHAKE_SIZE 6
+#endif /* HAVE_OPENSSL */
#define SCRAMBLE_LENGTH 8
@@ -33,16 +55,18 @@ extern "C" pthread_mutex_t THR_LOCK_keycache;
extern "C" int gethostname(char *name, int namelen);
#endif
-static int check_for_max_user_connections(const char *user, int u_length,
- const char *host);
-static void decrease_user_connections(const char *user, const char *host);
+static int check_for_max_user_connections(UC *uc);
+static bool check_mqh(THD *thd);
+static void decrease_user_connections(UC *uc);
static bool check_db_used(THD *thd,TABLE_LIST *tables);
static bool check_merge_table_access(THD *thd, char *db, TABLE_LIST *tables);
-static bool check_dup(THD *thd,const char *db,const char *name,
- TABLE_LIST *tables);
+static bool check_dup(const char *db, const char *name, TABLE_LIST *tables);
static void mysql_init_query(THD *thd);
static void remove_escape(char *name);
static void refresh_status(void);
+static bool append_file_to_dir(THD *thd, char **filename_ptr,
+ char *table_name);
+static bool create_total_list(THD *thd, LEX *lex, TABLE_LIST **result);
const char *any_db="*any*"; // Special symbol for check_access
@@ -50,13 +74,13 @@ const char *command_name[]={
"Sleep", "Quit", "Init DB", "Query", "Field List", "Create DB",
"Drop DB", "Refresh", "Shutdown", "Statistics", "Processlist",
"Connect","Kill","Debug","Ping","Time","Delayed_insert","Change user",
- "Binlog Dump","Table Dump", "Connect Out"
+ "Binlog Dump","Table Dump", "Connect Out", "Register Slave"
};
bool volatile abort_slave = 0;
#ifdef HAVE_OPENSSL
-extern VioSSLAcceptorFd* ssl_acceptor_fd;
+extern struct st_VioSSLAcceptorFd * ssl_acceptor_fd;
#endif /* HAVE_OPENSSL */
#ifdef __WIN__
@@ -66,8 +90,8 @@ static void test_signal(int sig_ptr)
MessageBox(NULL,"Test signal","DBUG",MB_OK);
#endif
#if defined(OS2)
- fprintf( stderr, "Test signal %d\n", sig_ptr);
- fflush( stderr);
+ fprintf(stderr, "Test signal %d\n", sig_ptr);
+ fflush(stderr);
#endif
}
static void init_signals(void)
@@ -93,43 +117,98 @@ inline bool end_active_trans(THD *thd)
}
+static HASH hash_user_connections;
+extern pthread_mutex_t LOCK_user_conn;
+
+static int get_or_create_user_conn(THD *thd, const char *user,
+ const char *host,
+ uint max_questions)
+{
+ int return_val=0;
+ uint temp_len;
+ char temp_user[USERNAME_LENGTH+HOSTNAME_LENGTH+2];
+ struct user_conn *uc;
+
+ DBUG_ASSERT(user != 0);
+ DBUG_ASSERT(host != 0);
+
+ temp_len= (uint) (strxnmov(temp_user, sizeof(temp_user)-1, user, "@", host,
+ NullS) - temp_user);
+ (void) pthread_mutex_lock(&LOCK_user_conn);
+ if (!(uc = (struct user_conn *) hash_search(&hash_user_connections,
+ (byte*) temp_user, temp_len)))
+ {
+ /* First connection for user; Create a user connection object */
+ if (!(uc= ((struct user_conn*)
+ my_malloc(sizeof(struct user_conn) + temp_len+1,
+ MYF(MY_WME)))
+ {
+ send_error(&current_thd->net, 0, NullS); // Out of memory
+ return_val=1;
+ goto end;
+ }
+ uc->user=(char*) (uc+1);
+ memcpy(uc->user,temp_user,temp_len+1);
+ uc->len = temp_len;
+ uc->connections = 1;
+ uc->questions=0;
+ uc->max_questions=max_questions;
+ uc->intime=thd->thr_create_time;
+ if (hash_insert(&hash_user_connections, (byte*) uc))
+ {
+ my_free((char*) uc,0);
+ send_error(&current_thd->net, 0, NullS); // Out of memory
+ return_val=1;
+ goto end;
+ }
+ }
+ thd->user_connect=uc;
+end:
+ (void) pthread_mutex_unlock(&LOCK_user_conn);
+ return return_val;
+
+}
+
+
/*
-** Check if user is ok
-** Updates:
-** thd->user, thd->master_access, thd->priv_user, thd->db, thd->db_access
+ Check if user is ok
+ Updates:
+ thd->user, thd->master_access, thd->priv_user, thd->db, thd->db_access
*/
static bool check_user(THD *thd,enum_server_command command, const char *user,
const char *passwd, const char *db, bool check_count)
{
NET *net= &thd->net;
+ uint max_questions=0;
thd->db=0;
+ thd->db_length=0;
if (!(thd->user = my_strdup(user, MYF(0))))
{
send_error(net,ER_OUT_OF_RESOURCES);
return 1;
}
- thd->master_access=acl_getroot(thd->host, thd->ip, thd->user,
+ thd->master_access=acl_getroot(thd, thd->host, thd->ip, thd->user,
passwd, thd->scramble, &thd->priv_user,
protocol_version == 9 ||
!(thd->client_capabilities &
- CLIENT_LONG_PASSWORD));
- DBUG_PRINT("general",
+ CLIENT_LONG_PASSWORD),&max_questions);
+ DBUG_PRINT("info",
("Capabilities: %d packet_length: %d Host: '%s' User: '%s' Using password: %s Access: %u db: '%s'",
thd->client_capabilities, thd->max_packet_length,
- thd->host ? thd->host : thd->ip, thd->priv_user,
+ thd->host_or_ip, thd->priv_user,
passwd[0] ? "yes": "no",
thd->master_access, thd->db ? thd->db : "*none*"));
if (thd->master_access & NO_ACCESS)
{
net_printf(net, ER_ACCESS_DENIED_ERROR,
thd->user,
- thd->host ? thd->host : thd->ip,
+ thd->host_or_ip,
passwd[0] ? ER(ER_YES) : ER(ER_NO));
mysql_log.write(thd,COM_CONNECT,ER(ER_ACCESS_DENIED_ERROR),
thd->user,
- thd->host ? thd->host : thd->ip ? thd->ip : "unknown ip",
+ thd->host_or_ip,
passwd[0] ? ER(ER_YES) : ER(ER_NO));
return(1); // Error already given
}
@@ -150,17 +229,21 @@ static bool check_user(THD *thd,enum_server_command command, const char *user,
(char*) "%s@%s on %s" :
(char*) "%s@%s as anonymous on %s"),
user,
- thd->host ? thd->host : thd->ip ? thd->ip : "unknown ip",
+ thd->host_or_ip,
db ? db : (char*) "");
thd->db_access=0;
- if (max_user_connections &&
- check_for_max_user_connections(user, strlen(user), thd->host))
+ /* Don't allow user to connect if he has done too many queries */
+ if (get_or_create_user_conn(thd,user,thd->host_or_ip,max_questions) &&
+ (max_questions || max_user_connections))
+ return -1;
+ if (max_user_connections && thd->user_connect &&
+ check_for_max_user_connections(thd->user_connect))
return -1;
if (db && db[0])
{
bool error=test(mysql_change_db(thd,db));
- if (error)
- decrease_user_connections(thd->user,thd->host);
+ if (error && thd->user_connect)
+ decrease_user_connections(thd->user_connect);
return error;
}
else
@@ -169,19 +252,10 @@ static bool check_user(THD *thd,enum_server_command command, const char *user,
}
/*
-** check for maximum allowable user connections
-** if mysql server is started with corresponding
-** variable that is greater then 0
+ Check for maximum allowable user connections, if the mysqld server is
+ started with corresponding variable that is greater then 0.
*/
-static HASH hash_user_connections;
-extern pthread_mutex_t LOCK_user_conn;
-
-struct user_conn {
- char *user;
- uint len, connections;
-};
-
static byte* get_key_conn(user_conn *buff, uint *length,
my_bool not_used __attribute__((unused)))
{
@@ -189,8 +263,6 @@ static byte* get_key_conn(user_conn *buff, uint *length,
return (byte*) buff->user;
}
-#define DEF_USER_COUNT 50
-
static void free_user(struct user_conn *uc)
{
my_free((char*) uc,MYF(0));
@@ -198,100 +270,44 @@ static void free_user(struct user_conn *uc)
void init_max_user_conn(void)
{
- (void) hash_init(&hash_user_connections,DEF_USER_COUNT,0,0,
+ (void) hash_init(&hash_user_connections,max_connections,0,0,
(hash_get_key) get_key_conn, (void (*)(void*)) free_user,
0);
}
-static int check_for_max_user_connections(const char *user, int u_length,
- const char *host)
+static int check_for_max_user_connections(UC *uc)
{
- int error=1;
- uint temp_len;
- char temp_user[USERNAME_LENGTH+HOSTNAME_LENGTH+2];
- struct user_conn *uc;
- if (!user)
- user="";
- if (!host)
- host="";
+ int error=0;
DBUG_ENTER("check_for_max_user_connections");
- DBUG_PRINT("enter",("user: '%s' host: '%s'", user, host));
-
- temp_len= (uint) (strxnmov(temp_user, sizeof(temp_user), user, "@", host,
- NullS) - temp_user);
- (void) pthread_mutex_lock(&LOCK_user_conn);
- uc = (struct user_conn *) hash_search(&hash_user_connections,
- (byte*) temp_user, temp_len);
- if (uc) /* user found ; check for no. of connections */
- {
- if (max_user_connections == (uint) uc->connections)
- {
- net_printf(&(current_thd->net),ER_TOO_MANY_USER_CONNECTIONS, temp_user);
- goto end;
- }
- uc->connections++;
- }
- else
+
+ if (max_user_connections <= (uint) uc->connections)
{
- /* the user is not found in the cache; Insert it */
- struct user_conn *uc= ((struct user_conn*)
- my_malloc(sizeof(struct user_conn) + temp_len+1,
- MYF(MY_WME)));
- if (!uc)
- {
- send_error(&current_thd->net, 0, NullS); // Out of memory
- goto end;
- }
- uc->user=(char*) (uc+1);
- memcpy(uc->user,temp_user,temp_len+1);
- uc->len = temp_len;
- uc->connections = 1;
- if (hash_insert(&hash_user_connections, (byte*) uc))
- {
- my_free((char*) uc,0);
- send_error(&current_thd->net, 0, NullS); // Out of memory
- goto end;
- }
+ net_printf(&(current_thd->net),ER_TOO_MANY_USER_CONNECTIONS, uc->user);
+ error=1;
+ goto end;
}
- error=0;
+ uc->connections++;
end:
- (void) pthread_mutex_unlock(&LOCK_user_conn);
DBUG_RETURN(error);
}
-static void decrease_user_connections(const char *user, const char *host)
+static void decrease_user_connections(UC *uc)
{
- char temp_user[USERNAME_LENGTH+HOSTNAME_LENGTH+2];
- int temp_len;
- struct user_conn *uc;
if (!max_user_connections)
return;
- if (!user)
- user="";
- if (!host)
- host="";
- DBUG_ENTER("decrease_user_connections");
- DBUG_PRINT("enter",("user: '%s' host: '%s'", user, host));
- temp_len= (uint) (strxnmov(temp_user, sizeof(temp_user), user, "@", host,
- NullS) - temp_user);
- (void) pthread_mutex_lock(&LOCK_user_conn);
+ DBUG_ENTER("decrease_user_connections");
- uc = (struct user_conn *) hash_search(&hash_user_connections,
- (byte*) temp_user, temp_len);
- dbug_assert(uc != 0); // We should always find the user
- if (!uc)
- goto end; // Safety; Something went wrong
- if (! --uc->connections)
+ if (!--uc->connections && !mqh_used)
{
/* Last connection for user; Delete it */
+ (void) pthread_mutex_lock(&LOCK_user_conn);
(void) hash_delete(&hash_user_connections,(byte*) uc);
+ (void) pthread_mutex_unlock(&LOCK_user_conn);
}
-end:
- (void) pthread_mutex_unlock(&LOCK_user_conn);
DBUG_VOID_RETURN;
}
@@ -303,22 +319,93 @@ void free_max_user_conn(void)
/*
-** check connnetion and get priviliges
-** returns 0 on ok, -1 < if error is given > 0 on error.
+ Check if maximum queries per hour limit has been reached
+ returns 0 if OK.
+
+ In theory we would need a mutex in the UC structure for this to be 100 %
+ safe, but as the worst scenario is that we would miss counting a couple of
+ queries, this isn't critical.
*/
+static bool check_mqh(THD *thd)
+{
+ bool error=0;
+ DBUG_ENTER("check_mqh");
+ UC *uc=thd->user_connect;
+ DBUG_ASSERT(uc != 0);
+
+ bool my_start = thd->start_time != 0;
+ time_t check_time = (my_start) ? thd->start_time : time(NULL);
+ if (check_time - uc->intime >= 3600)
+ {
+ (void) pthread_mutex_lock(&LOCK_user_conn);
+ uc->questions=1;
+ uc->intime=check_time;
+ (void) pthread_mutex_unlock(&LOCK_user_conn);
+ }
+ else if (uc->max_questions && ++(uc->questions) > uc->max_questions)
+ {
+ net_printf(&thd->net, ER_USER_LIMIT_REACHED, uc->user, "max_questions",
+ (long) uc->max_questions);
+ error=1;
+ goto end;
+ }
+
+end:
+ DBUG_RETURN(error);
+}
+
+
+static void reset_mqh(THD *thd, LEX_USER *lu, uint mq)
+{
+
+ (void) pthread_mutex_lock(&LOCK_user_conn);
+ if (lu) // for GRANT
+ {
+ UC *uc;
+ uint temp_len=lu->user.length+lu->host.length+2;
+ char temp_user[USERNAME_LENGTH+HOSTNAME_LENGTH+2];
+
+ memcpy(temp_user,lu->user.str,lu->user.length);
+ memcpy(temp_user+lu->user.length+1,lu->host.str,lu->host.length);
+ temp_user[lu->user.length]=temp_user[temp_len-1]=0;
+ if ((uc = (struct user_conn *) hash_search(&hash_user_connections,
+ (byte*) temp_user, temp_len)))
+ {
+ uc->questions=0;
+ uc->max_questions=mq;
+ }
+ }
+ else // for FLUSH PRIVILEGES
+ {
+ for (uint idx=0;idx < hash_user_connections.records; idx++)
+ {
+ char user[USERNAME_LENGTH+1];
+ char *where;
+ UC *uc=(struct user_conn *) hash_element(&hash_element, idx);
+ where=strchr(uc->user,'@');
+ strmake(user,uc->user,where - uc->user);
+ uc->max_questions=get_mqh(user,where+1);
+ }
+ }
+ (void) pthread_mutex_unlock(&LOCK_user_conn);
+}
+
+
+/*
+ Check connnetion and get priviliges
+ Returns 0 on ok, -1 < if error is given > 0 on error.
+*/
static int
check_connections(THD *thd)
{
uint connect_errors=0;
NET *net= &thd->net;
- /*
- ** store the connection details
- */
+ /* Store the connection details */
DBUG_PRINT("info", (("check_connections called by thread %d"),
thd->thread_id));
- DBUG_PRINT("general",("New connection received on %s",
+ DBUG_PRINT("info",("New connection received on %s",
vio_description(net->vio)));
if (!thd->host) // If TCP/IP connection
{
@@ -328,6 +415,7 @@ check_connections(THD *thd)
return (ER_BAD_HOST_ERROR);
if (!(thd->ip = my_strdup(ip,MYF(0))))
return (ER_OUT_OF_RESOURCES);
+ thd->host_or_ip=thd->ip;
#if !defined(HAVE_SYS_UN_H) || defined(HAVE_mit_thread)
/* Fast local hostname resolve for Win32 */
if (!strcmp(thd->ip,"127.0.0.1"))
@@ -341,65 +429,50 @@ check_connections(THD *thd)
if (connect_errors > max_connect_errors)
return(ER_HOST_IS_BLOCKED);
}
- DBUG_PRINT("general",("Host: %s ip: %s",
- thd->host ? thd->host : "unknown host",
- thd->ip ? thd->ip : "unknown ip"));
+ DBUG_PRINT("info",("Host: %s ip: %s",
+ thd->host ? thd->host : "unknown host",
+ thd->ip ? thd->ip : "unknown ip"));
if (acl_check_host(thd->host,thd->ip))
return(ER_HOST_NOT_PRIVILEGED);
}
else /* Hostname given means that the connection was on a socket */
{
- DBUG_PRINT("general",("Host: %s",thd->host));
+ DBUG_PRINT("info",("Host: %s",thd->host));
+ thd->host_or_ip=thd->host;
thd->ip=0;
bzero((char*) &thd->remote,sizeof(struct sockaddr));
}
vio_keepalive(net->vio, TRUE);
- /* nasty, but any other way? */
- uint pkt_len = 0;
+ ulong pkt_len=0;
{
/* buff[] needs to big enough to hold the server_version variable */
char buff[SERVER_VERSION_LENGTH + SCRAMBLE_LENGTH+32],*end;
int client_flags = CLIENT_LONG_FLAG | CLIENT_CONNECT_WITH_DB;
+
if (opt_using_transactions)
client_flags|=CLIENT_TRANSACTIONS;
#ifdef HAVE_COMPRESS
client_flags |= CLIENT_COMPRESS;
#endif /* HAVE_COMPRESS */
+#ifdef HAVE_OPENSSL
+ if (ssl_acceptor_fd)
+ client_flags |= CLIENT_SSL; /* Wow, SSL is avalaible! */
+#endif /* HAVE_OPENSSL */
- end=strmov(buff,server_version)+1;
+ end=strnmov(buff,server_version,SERVER_VERSION_LENGTH)+1;
int4store((uchar*) end,thd->thread_id);
end+=4;
memcpy(end,thd->scramble,SCRAMBLE_LENGTH+1);
end+=SCRAMBLE_LENGTH +1;
-#ifdef HAVE_OPENSSL
- if (ssl_acceptor_fd)
- client_flags |= CLIENT_SSL; /* Wow, SSL is avalaible! */
- /*
- * Without SSL the handshake consists of one packet. This packet
- * has both client capabilites and scrambled password.
- * With SSL the handshake might consist of two packets. If the first
- * packet (client capabilities) has CLIENT_SSL flag set, we have to
- * switch to SSL and read the second packet. The scrambled password
- * is in the second packet and client_capabilites field will be ignored.
- * Maybe it is better to accept flags other than CLIENT_SSL from the
- * second packet?
- */
-#define SSL_HANDSHAKE_SIZE 2
-#define NORMAL_HANDSHAKE_SIZE 6
-#define MIN_HANDSHAKE_SIZE 2
-
-#else
-#define MIN_HANDSHAKE_SIZE 6
-#endif /* HAVE_OPENSSL */
int2store(end,client_flags);
- end[2]=MY_CHARSET_CURRENT;
+ end[2]=(char) MY_CHARSET_CURRENT;
int2store(end+3,thd->server_status);
bzero(end+5,13);
end+=18;
- if (net_write_command(net,protocol_version, buff,
+ if (net_write_command(net,(uchar) protocol_version, buff,
(uint) (end-buff)) ||
- (pkt_len=my_net_read(net)) == packet_error ||
+ (pkt_len= my_net_read(net)) == packet_error ||
pkt_len < MIN_HANDSHAKE_SIZE)
{
inc_host_errors(&thd->remote.sin_addr);
@@ -418,23 +491,18 @@ check_connections(THD *thd)
if (thd->client_capabilities & CLIENT_IGNORE_SPACE)
thd->sql_mode|= MODE_IGNORE_SPACE;
#ifdef HAVE_OPENSSL
- DBUG_PRINT("info",
- ("pkt_len:%d, client capabilities: %d",
- pkt_len, thd->client_capabilities) );
+ DBUG_PRINT("info", ("client capabilities: %d", thd->client_capabilities));
if (thd->client_capabilities & CLIENT_SSL)
{
- DBUG_PRINT("info", ("Agreed to change IO layer to SSL") );
/* Do the SSL layering. */
DBUG_PRINT("info", ("IO layer change in progress..."));
- VioSocket* vio_socket = my_reinterpret_cast(VioSocket*)(net->vio);
- VioSSL* vio_ssl = ssl_acceptor_fd->accept(vio_socket);
- net->vio = my_reinterpret_cast(NetVio*) (vio_ssl);
+ sslaccept(ssl_acceptor_fd, net->vio, thd->inactive_timeout);
DBUG_PRINT("info", ("Reading user information over SSL layer"));
if ((pkt_len=my_net_read(net)) == packet_error ||
pkt_len < NORMAL_HANDSHAKE_SIZE)
{
- DBUG_PRINT("info", ("pkt_len:%d", pkt_len));
- DBUG_PRINT("error", ("Failed to read user information"));
+ DBUG_PRINT("error", ("Failed to read user information (pkt_len= %lu)",
+ pkt_len));
inc_host_errors(&thd->remote.sin_addr);
return(ER_HANDSHAKE_ERROR);
}
@@ -463,7 +531,7 @@ check_connections(THD *thd)
if ((thd->client_capabilities & CLIENT_TRANSACTIONS) &&
opt_using_transactions)
thd->net.return_status= &thd->server_status;
- net->timeout=net_read_timeout;
+ net->timeout=(uint) net_read_timeout;
if (check_user(thd,COM_CONNECT, user, passwd, db, 1))
return (-1);
thd->password=test(passwd[0]);
@@ -481,9 +549,9 @@ pthread_handler_decl(handle_one_connection,arg)
pthread_detach_this_thread();
-#if !defined( __WIN__) && !defined(OS2) /* Win32 calls this in pthread_create */
- if (my_thread_init()) // needed to be called first before we call
- // DBUG_ macros
+#if !defined( __WIN__) && !defined(OS2) // Win32 calls this in pthread_create
+ // The following calls needs to be done before we call DBUG_ macros
+ if (my_thread_init())
{
close_connection(&thd->net,ER_OUT_OF_RESOURCES);
statistic_increment(aborted_connects,&LOCK_thread_count);
@@ -492,13 +560,13 @@ pthread_handler_decl(handle_one_connection,arg)
}
#endif
- // handle_one_connection() is the only way a thread would start
- // and would always be on top of the stack
- // therefore, the thread stack always starts at the address of the first
- // local variable of handle_one_connection, which is thd
- // we need to know the start of the stack so that we could check for
- // stack overruns
-
+ /*
+ handle_one_connection() is the only way a thread would start
+ and would always be on top of the stack, therefore, the thread
+ stack always starts at the address of the first local variable
+ of handle_one_connection, which is thd. We need to know the
+ start of the stack so that we could check for stack overruns.
+ */
DBUG_PRINT("info", ("handle_one_connection called by thread %d\n",
thd->thread_id));
// now that we've called my_thread_init(), it is safe to call DBUG_*
@@ -530,7 +598,7 @@ pthread_handler_decl(handle_one_connection,arg)
if ((error=check_connections(thd)))
{ // Wrong permissions
if (error > 0)
- net_printf(net,error,thd->host ? thd->host : thd->ip);
+ net_printf(net,error,thd->host_or_ip);
#ifdef __NT__
if (vio_type(net->vio) == VIO_TYPE_NAMEDPIPE)
sleep(1); /* must wait after eof() */
@@ -554,21 +622,22 @@ pthread_handler_decl(handle_one_connection,arg)
if (do_command(thd))
break;
}
+ if (thd->user_connect)
+ decrease_user_connections(thd->user_connect);
free_root(&thd->mem_root,MYF(0));
if (net->error && net->vio != 0)
{
if (!thd->killed && opt_warnings)
- sql_print_error(ER(ER_NEW_ABORTING_CONNECTION),
- thd->thread_id,(thd->db ? thd->db : "unconnected"),
- thd->user ? thd->user : "unauthenticated",
- (thd->host ? thd->host : thd->ip ? thd->ip : "unknown"),
- (net->last_errno ? ER(net->last_errno) :
- ER(ER_UNKNOWN_ERROR)));
+ sql_print_error(ER(ER_NEW_ABORTING_CONNECTION),
+ thd->thread_id,(thd->db ? thd->db : "unconnected"),
+ thd->user ? thd->user : "unauthenticated",
+ thd->host_or_ip,
+ (net->last_errno ? ER(net->last_errno) :
+ ER(ER_UNKNOWN_ERROR)));
send_error(net,net->last_errno,NullS);
thread_safe_increment(aborted_threads,&LOCK_thread_count);
}
-
- decrease_user_connections(thd->user,thd->host);
+
end_thread:
close_connection(net);
end_thread(thd,1);
@@ -628,8 +697,17 @@ pthread_handler_decl(handle_bootstrap,arg)
length--;
buff[length]=0;
thd->current_tablenr=0;
- thd->query= thd->memdup(buff,length+1);
+ thd->query_length=length;
+ thd->query= thd->memdup_w_gap(buff, length+1, thd->db_length+1);
+ thd->query[length] = '\0';
thd->query_id=query_id++;
+ if (thd->user_connect && check_mqh(thd))
+ {
+ thd->net.error = 0;
+ close_thread_tables(thd); // Free tables
+ free_root(&thd->mem_root,MYF(MY_KEEP_PREALLOC));
+ break;
+ }
mysql_parse(thd,thd->query,length);
close_thread_tables(thd); // Free tables
if (thd->fatal_error)
@@ -664,7 +742,7 @@ int mysql_table_dump(THD* thd, char* db, char* tbl_name, int fd)
int error = 0;
DBUG_ENTER("mysql_table_dump");
db = (db && db[0]) ? db : thd->db;
- if (!(table_list = (TABLE_LIST*) sql_calloc(sizeof(TABLE_LIST))))
+ if (!(table_list = (TABLE_LIST*) thd->calloc(sizeof(TABLE_LIST))))
DBUG_RETURN(1); // out of memory
table_list->db = db;
table_list->real_name = table_list->name = tbl_name;
@@ -686,21 +764,19 @@ int mysql_table_dump(THD* thd, char* db, char* tbl_name, int fd)
goto err;
thd->free_list = 0;
+ thd->query_length=(uint) strlen(tbl_name);
thd->query = tbl_name;
- if((error = mysqld_dump_create_info(thd, table, -1)))
- {
- my_error(ER_GET_ERRNO, MYF(0));
- goto err;
- }
+ if ((error = mysqld_dump_create_info(thd, table, -1)))
+ {
+ my_error(ER_GET_ERRNO, MYF(0));
+ goto err;
+ }
net_flush(&thd->net);
- error = table->file->dump(thd,fd);
- if(error)
- my_error(ER_GET_ERRNO, MYF(0));
+ if ((error = table->file->dump(thd,fd)))
+ my_error(ER_GET_ERRNO, MYF(0));
err:
-
close_thread_tables(thd);
-
DBUG_RETURN(error);
}
@@ -710,13 +786,10 @@ err:
bool do_command(THD *thd)
{
char *packet;
- uint old_timeout,packet_length;
- bool error=0;
+ uint old_timeout;
+ ulong packet_length;
NET *net;
enum enum_server_command command;
- // commands which will always take a long time should be marked with
- // this so that they will not get logged to the slow query log
- bool slow_command=FALSE;
DBUG_ENTER("do_command");
net= &thd->net;
@@ -724,26 +797,42 @@ bool do_command(THD *thd)
packet=0;
old_timeout=net->timeout;
- net->timeout=thd->inactive_timeout; /* Wait max for 8 hours */
+ net->timeout=(uint) thd->inactive_timeout; // Wait max for 8 hours
net->last_error[0]=0; // Clear error message
net->last_errno=0;
net_new_transaction(net);
if ((packet_length=my_net_read(net)) == packet_error)
{
- DBUG_PRINT("general",("Got error reading command from socket %s",
- vio_description(net->vio) ));
+ DBUG_PRINT("info",("Got error reading command from socket %s",
+ vio_description(net->vio) ));
return TRUE;
}
else
{
packet=(char*) net->read_pos;
command = (enum enum_server_command) (uchar) packet[0];
- DBUG_PRINT("general",("Command on %s = %d (%s)",
- vio_description(net->vio), command,
- command_name[command]));
+ DBUG_PRINT("info",("Command on %s = %d (%s)",
+ vio_description(net->vio), command,
+ command_name[command]));
}
- net->timeout=old_timeout; /* Timeout */
+ net->timeout=old_timeout; // Timeout for writing
+ DBUG_RETURN(dispatch_command(command,thd, packet+1, (uint) packet_length));
+}
+
+
+bool dispatch_command(enum enum_server_command command, THD *thd,
+ char* packet, uint packet_length)
+{
+ NET *net= &thd->net;
+ bool error=0;
+ /*
+ Commands which will always take a long time should be marked with
+ this so that they will not get logged to the slow query log
+ */
+ bool slow_command=FALSE;
+ DBUG_ENTER("dispatch_command");
+
thd->command=command;
VOID(pthread_mutex_lock(&LOCK_thread_count));
thd->query_id=query_id;
@@ -752,27 +841,34 @@ bool do_command(THD *thd)
thread_running++;
VOID(pthread_mutex_unlock(&LOCK_thread_count));
thd->set_time();
- thd->lex.options=0; // We store status here
- switch(command) {
+ thd->lex.select_lex.options=0; // We store status here
+ switch (command) {
case COM_INIT_DB:
thread_safe_increment(com_stat[SQLCOM_CHANGE_DB],&LOCK_thread_count);
- if (!mysql_change_db(thd,packet+1))
+ if (!mysql_change_db(thd,packet))
mysql_log.write(thd,command,"%s",thd->db);
break;
+ case COM_REGISTER_SLAVE:
+ {
+ if (register_slave(thd, (uchar*)packet, packet_length))
+ send_error(&thd->net);
+ else
+ send_ok(&thd->net);
+ break;
+ }
case COM_TABLE_DUMP:
{
thread_safe_increment(com_other,&LOCK_thread_count);
slow_command = TRUE;
- char* data = packet + 1;
- uint db_len = *data;
- uint tbl_len = *(data + db_len + 1);
- char* db = sql_alloc(db_len + tbl_len + 2);
- memcpy(db, data + 1, db_len);
+ uint db_len = *(uchar*)packet;
+ uint tbl_len = *(uchar*)(packet + db_len + 1);
+ char* db = thd->alloc(db_len + tbl_len + 2);
+ memcpy(db, packet + 1, db_len);
char* tbl_name = db + db_len;
*tbl_name++ = 0;
- memcpy(tbl_name, data + db_len + 2, tbl_len);
+ memcpy(tbl_name, packet + db_len + 2, tbl_len);
tbl_name[tbl_len] = 0;
- if(mysql_table_dump(thd, db, tbl_name, -1))
+ if (mysql_table_dump(thd, db, tbl_name, -1))
send_error(&thd->net); // dump to NET
break;
@@ -780,16 +876,18 @@ bool do_command(THD *thd)
case COM_CHANGE_USER:
{
thread_safe_increment(com_other,&LOCK_thread_count);
- char *user= (char*) packet+1;
+ char *user= (char*) packet;
char *passwd= strend(user)+1;
char *db= strend(passwd)+1;
/* Save user and privileges */
uint save_master_access=thd->master_access;
uint save_db_access= thd->db_access;
+ uint save_db_length= thd->db_length;
char *save_user= thd->user;
char *save_priv_user= thd->priv_user;
char *save_db= thd->db;
+ UC *save_uc= thd->user_connect;
if ((uint) ((uchar*) db - net->read_pos) > packet_length)
{ // Check if protocol is ok
@@ -803,11 +901,13 @@ bool do_command(THD *thd)
thd->master_access=save_master_access;
thd->db_access=save_db_access;
thd->db=save_db;
+ thd->db_length=save_db_length;
thd->user=save_user;
thd->priv_user=save_priv_user;
break;
}
- decrease_user_connections (save_user, thd->host);
+ if (max_connections && save_uc)
+ decrease_user_connections(save_uc);
x_free((gptr) save_db);
x_free((gptr) save_user);
thd->password=test(passwd[0]);
@@ -816,28 +916,44 @@ bool do_command(THD *thd)
case COM_QUERY:
{
+ packet_length--; // Remove end null
+ /* Remove garage at start and end of query */
+ while (isspace(packet[0]) && packet_length > 0)
+ {
+ packet++;
+ packet_length--;
+ }
char *pos=packet+packet_length; // Point at end null
- /* Remove garage at end of query */
- while (packet_length > 0 && pos[-1] == ';')
+ while (packet_length > 0 && (pos[-1] == ';' || isspace(pos[-1])))
{
pos--;
packet_length--;
}
- *pos=0;
- if (!(thd->query= (char*) thd->memdup((gptr) (packet+1),packet_length)))
+ /* We must allocate some extra memory for query cache */
+ if (!(thd->query= (char*) thd->memdup_w_gap((gptr) (packet),
+ packet_length,
+ thd->db_length+2)))
break;
+ thd->query[packet_length]=0;
thd->packet.shrink(net_buffer_length); // Reclaim some memory
if (!(specialflag & SPECIAL_NO_PRIOR))
my_pthread_setprio(pthread_self(),QUERY_PRIOR);
mysql_log.write(thd,command,"%s",thd->query);
DBUG_PRINT("query",("%s",thd->query));
- mysql_parse(thd,thd->query,packet_length-1);
+ if (thd->user_connect && check_mqh(thd))
+ {
+ error = TRUE; // Abort client
+ net->error = 0; // Don't give abort message
+ break;
+ }
+ /* thd->query_length is set by mysql_parse() */
+ mysql_parse(thd,thd->query,packet_length);
if (!(specialflag & SPECIAL_NO_PRIOR))
my_pthread_setprio(pthread_self(),WAIT_PRIOR);
DBUG_PRINT("info",("query ready"));
break;
}
- case COM_FIELD_LIST: // This isn't actually neaded
+ case COM_FIELD_LIST: // This isn't actually needed
#ifdef DONT_ALLOW_SHOW_COMMANDS
send_error(&thd->net,ER_NOT_ALLOWED_COMMAND); /* purecov: inspected */
break;
@@ -853,8 +969,11 @@ bool do_command(THD *thd)
break;
}
thd->free_list=0;
- table_list.name=table_list.real_name=thd->strdup(packet+1);
- thd->query=fields=thd->strdup(strend(packet+1)+1);
+ table_list.name=table_list.real_name=thd->strdup(packet);
+ packet=strend(packet)+1;
+ // command not cachable => no gap for data base name
+ if (!(thd->query=fields=thd->memdup(packet,thd->query_length+1)))
+ break;
mysql_log.write(thd,command,"%s %s",table_list.real_name,fields);
remove_escape(table_list.real_name); // This can't have wildcards
@@ -875,10 +994,10 @@ bool do_command(THD *thd)
error=TRUE; // End server
break;
- case COM_CREATE_DB:
+ case COM_CREATE_DB: // QQ: To be removed
{
- char *db=thd->strdup(packet+1);
thread_safe_increment(com_stat[SQLCOM_CREATE_DB],&LOCK_thread_count);
+ char *db=thd->strdup(packet);
// null test to handle EOM
if (!db || !stripp_sp(db) || check_db_name(db))
{
@@ -887,44 +1006,49 @@ bool do_command(THD *thd)
}
if (check_access(thd,CREATE_ACL,db,0,1))
break;
- mysql_log.write(thd,command,packet+1);
- mysql_create_db(thd,db,0);
+ mysql_log.write(thd,command,packet);
+ mysql_create_db(thd,db,0,0);
break;
}
- case COM_DROP_DB:
+ case COM_DROP_DB: // QQ: To be removed
{
- char *db=thd->strdup(packet+1);
thread_safe_increment(com_stat[SQLCOM_DROP_DB],&LOCK_thread_count);
+ char *db=thd->strdup(packet);
// null test to handle EOM
if (!db || !stripp_sp(db) || check_db_name(db))
{
net_printf(&thd->net,ER_WRONG_DB_NAME, db ? db : "NULL");
break;
}
- if (check_access(thd,DROP_ACL,db,0,1) || end_active_trans(thd))
+ if (thd->locked_tables || thd->active_transaction())
+ {
+ send_error(&thd->net,ER_LOCK_OR_ACTIVE_TRANSACTION);
break;
+ }
mysql_log.write(thd,command,db);
- mysql_rm_db(thd,db,0);
+ mysql_rm_db(thd,db,0,0);
break;
}
case COM_BINLOG_DUMP:
{
thread_safe_increment(com_other,&LOCK_thread_count);
slow_command = TRUE;
- if(check_access(thd, FILE_ACL, any_db))
+ if (check_access(thd, FILE_ACL, any_db))
break;
mysql_log.write(thd,command, 0);
ulong pos;
ushort flags;
uint32 slave_server_id;
- pos = uint4korr(packet + 1);
- flags = uint2korr(packet + 5);
+ pos = uint4korr(packet);
+ flags = uint2korr(packet + 4);
pthread_mutex_lock(&LOCK_server_id);
- kill_zombie_dump_threads(slave_server_id = uint4korr(packet+7));
+ thd->server_id=0; /* avoid suicide */
+ kill_zombie_dump_threads(slave_server_id = uint4korr(packet+6));
thd->server_id = slave_server_id;
pthread_mutex_unlock(&LOCK_server_id);
- mysql_binlog_send(thd, thd->strdup(packet + 11), pos, flags);
+ mysql_binlog_send(thd, thd->strdup(packet + 10), pos, flags);
+ unregister_slave(thd,1,1);
// fake COM_QUIT -- if we get here, the thread needs to terminate
error = TRUE;
net->error = 0;
@@ -932,8 +1056,8 @@ bool do_command(THD *thd)
}
case COM_REFRESH:
{
- uint options=(uchar) packet[1];
thread_safe_increment(com_stat[SQLCOM_FLUSH],&LOCK_thread_count);
+ ulong options= (ulong) (uchar) packet[0];
if (check_access(thd,RELOAD_ACL,any_db))
break;
mysql_log.write(thd,command,NullS);
@@ -941,6 +1065,8 @@ bool do_command(THD *thd)
send_error(net,0);
else
send_eof(net);
+ if (mqh_used)
+ reset_mqh(thd,(LEX_USER *) NULL, 0);
break;
}
case COM_SHUTDOWN:
@@ -970,7 +1096,7 @@ bool do_command(THD *thd)
char buff[200];
ulong uptime = (ulong) (thd->start_time - start_time);
sprintf((char*) buff,
- "Uptime: %ld Threads: %d Questions: %lu Slow queries: %ld Opens: %ld Flush tables: %ld Open tables: %d Queries per second avg: %.3f",
+ "Uptime: %ld Threads: %d Questions: %lu Slow queries: %ld Opens: %ld Flush tables: %ld Open tables: %u Queries per second avg: %.3f",
uptime,
(int) thread_count,thd->query_id,long_query_count,
opened_tables,refresh_version, cached_tables(),
@@ -999,7 +1125,7 @@ bool do_command(THD *thd)
case COM_PROCESS_KILL:
{
thread_safe_increment(com_stat[SQLCOM_KILL],&LOCK_thread_count);
- ulong id=(ulong) uint4korr(packet+1);
+ ulong id=(ulong) uint4korr(packet);
kill_one_thread(thd,id);
break;
}
@@ -1037,7 +1163,7 @@ bool do_command(THD *thd)
thd->proc_info="logging slow query";
if ((ulong) (thd->start_time - thd->time_after_lock) > long_query_time ||
- ((thd->lex.options &
+ ((thd->lex.select_lex.options &
(QUERY_NO_INDEX_USED | QUERY_NO_GOOD_INDEX_USED)) &&
(specialflag & SPECIAL_LONG_LOG_FORMAT)))
{
@@ -1068,33 +1194,47 @@ mysql_execute_command(void)
int res=0;
THD *thd=current_thd;
LEX *lex= &thd->lex;
- TABLE_LIST *tables=(TABLE_LIST*) lex->table_list.first;
+ TABLE_LIST *tables=(TABLE_LIST*) lex->select_lex.table_list.first;
+ SELECT_LEX *select_lex = lex->select;
DBUG_ENTER("mysql_execute_command");
if (thd->slave_thread)
{
- // skip if we are in the slave thread, some table
- // rules have been given and the table list says the query should not be
- // replicated
- if(table_rules_on && tables && !tables_ok(thd,tables))
+ /*
+ Skip if we are in the slave thread, some table rules have been
+ given and the table list says the query should not be replicated
+ */
+ if (table_rules_on && tables && !tables_ok(thd,tables))
DBUG_VOID_RETURN;
- // this is a workaround to deal with the shortcoming
- // in 3.23.44-3.23.46 masters
- // in RELEASE_LOCK() logging. We re-write SELECT RELEASE_LOCK() as
- // DO RELEASE_LOCK()
+#ifndef TO_BE_DELETED
+ /*
+ This is a workaround to deal with the shortcoming in 3.23.44-3.23.46
+ masters in RELEASE_LOCK() logging. We re-write SELECT RELEASE_LOCK()
+ as DO RELEASE_LOCK()
+ */
if (lex->sql_command == SQLCOM_SELECT)
{
lex->sql_command = SQLCOM_DO;
- lex->insert_list = &lex->item_list;
+ lex->insert_list = &select_lex->item_list;
}
+#endif
}
+ /*
+ Skip if we are in the slave thread, some table rules have been given
+ and the table list says the query should not be replicated
+ */
+ if ((lex->select_lex.next && create_total_list(thd,lex,&tables)) ||
+ (table_rules_on && tables && thd->slave_thread &&
+ !tables_ok(thd,tables)))
+ DBUG_VOID_RETURN;
+
thread_safe_increment(com_stat[lex->sql_command],&LOCK_thread_count);
switch (lex->sql_command) {
case SQLCOM_SELECT:
{
select_result *result;
- if (lex->options & SELECT_DESCRIBE)
+ if (select_lex->options & SELECT_DESCRIBE)
lex->exchange=0;
if (tables)
{
@@ -1112,10 +1252,12 @@ mysql_execute_command(void)
break; // Error message is given
}
- thd->offset_limit=lex->offset_limit;
- thd->select_limit=lex->select_limit+lex->offset_limit;
- if (thd->select_limit < lex->select_limit)
+ thd->offset_limit=select_lex->offset_limit;
+ thd->select_limit=select_lex->select_limit+select_lex->offset_limit;
+ if (thd->select_limit < select_lex->select_limit)
thd->select_limit= HA_POS_ERROR; // no limit
+ if (thd->select_limit == HA_POS_ERROR)
+ select_lex->options&= ~OPTION_FOUND_ROWS;
if (lex->exchange)
{
@@ -1140,8 +1282,8 @@ mysql_execute_command(void)
{
res= -1;
#ifdef DELETE_ITEMS
- delete lex->having;
- delete lex->where;
+ delete select_lex->having;
+ delete select_lex->where;
#endif
break;
}
@@ -1159,22 +1301,11 @@ mysql_execute_command(void)
if (!(res=open_and_lock_tables(thd,tables)))
{
- res=mysql_select(thd,tables,lex->item_list,
- lex->where,
- (ORDER*) lex->order_list.first,
- (ORDER*) lex->group_list.first,
- lex->having,
- (ORDER*) lex->proc_list.first,
- lex->options | thd->options,
- result);
- if (res)
- result->abort();
+ query_cache.store_query(thd, tables);
+ res=handle_select(thd, lex, result);
}
- delete result;
-#ifdef DELETE_ITEMS
- delete lex->having;
- delete lex->where;
-#endif
+ else
+ delete result;
break;
}
case SQLCOM_DO:
@@ -1186,54 +1317,86 @@ mysql_execute_command(void)
break;
case SQLCOM_PURGE:
- {
- if (check_process_priv(thd))
- goto error;
- res = purge_master_logs(thd, lex->to_log);
- break;
- }
+ {
+ if (check_process_priv(thd))
+ goto error;
+ res = purge_master_logs(thd, lex->to_log);
+ break;
+ }
+ case SQLCOM_SHOW_NEW_MASTER:
+ {
+ if (check_access(thd, FILE_ACL, any_db))
+ goto error;
+ res = show_new_master(thd);
+ break;
+ }
+ case SQLCOM_SHOW_SLAVE_HOSTS:
+ {
+ if (check_access(thd, FILE_ACL, any_db))
+ goto error;
+ res = show_slave_hosts(thd);
+ break;
+ }
+ case SQLCOM_SHOW_BINLOG_EVENTS:
+ {
+ if (check_access(thd, FILE_ACL, any_db))
+ goto error;
+ res = show_binlog_events(thd);
+ break;
+ }
case SQLCOM_BACKUP_TABLE:
- {
- if (check_db_used(thd,tables) ||
- check_table_access(thd,SELECT_ACL, tables) ||
- check_access(thd, FILE_ACL, any_db))
- goto error; /* purecov: inspected */
- res = mysql_backup_table(thd, tables);
+ {
+ if (check_db_used(thd,tables) ||
+ check_table_access(thd,SELECT_ACL, tables) ||
+ check_access(thd, FILE_ACL, any_db))
+ goto error; /* purecov: inspected */
+ res = mysql_backup_table(thd, tables);
- break;
- }
+ break;
+ }
case SQLCOM_RESTORE_TABLE:
- {
- if (check_db_used(thd,tables) ||
- check_table_access(thd,INSERT_ACL, tables) ||
- check_access(thd, FILE_ACL, any_db))
- goto error; /* purecov: inspected */
- res = mysql_restore_table(thd, tables);
- break;
- }
+ {
+ if (check_db_used(thd,tables) ||
+ check_table_access(thd,INSERT_ACL, tables) ||
+ check_access(thd, FILE_ACL, any_db))
+ goto error; /* purecov: inspected */
+ res = mysql_restore_table(thd, tables);
+ break;
+ }
case SQLCOM_CHANGE_MASTER:
- {
- if(check_access(thd, PROCESS_ACL, any_db))
- goto error;
- res = change_master(thd);
- break;
- }
+ {
+ if (check_access(thd, PROCESS_ACL, any_db))
+ goto error;
+ LOCK_ACTIVE_MI;
+ res = change_master(thd,active_mi);
+ UNLOCK_ACTIVE_MI;
+ break;
+ }
case SQLCOM_SHOW_SLAVE_STAT:
- {
- if (check_process_priv(thd))
- goto error;
- res = show_master_info(thd);
- break;
- }
+ {
+ if (check_process_priv(thd))
+ goto error;
+ LOCK_ACTIVE_MI;
+ res = show_master_info(thd,active_mi);
+ UNLOCK_ACTIVE_MI;
+ break;
+ }
case SQLCOM_SHOW_MASTER_STAT:
- {
- if (check_process_priv(thd))
- goto error;
- res = show_binlog_info(thd);
- break;
- }
+ {
+ if (check_process_priv(thd))
+ goto error;
+ res = show_binlog_info(thd);
+ break;
+ }
+
+ case SQLCOM_LOAD_MASTER_DATA: // sync with master
+ if (check_process_priv(thd))
+ goto error;
+ res = load_master_data(thd);
+ break;
+
case SQLCOM_LOAD_MASTER_TABLE:
-
+ {
if (!tables->db)
tables->db=thd->db;
if (check_access(thd,CREATE_ACL,tables->db,&tables->grant.privilege))
@@ -1246,21 +1409,23 @@ mysql_execute_command(void)
bool error=check_grant(thd,CREATE_ACL,tables);
tables->next=tmp_table_list;
if (error)
- goto error;
+ goto error;
}
if (strlen(tables->name) > NAME_LEN)
{
net_printf(&thd->net,ER_WRONG_TABLE_NAME,tables->name);
break;
}
-
- thd->last_nx_table = tables->real_name;
- thd->last_nx_db = tables->db;
- if (fetch_nx_table(thd, &glob_mi))
- break; // fetch_nx_table did send the error to the client
- send_ok(&thd->net);
+ LOCK_ACTIVE_MI;
+ // fetch_master_table will send the error to the client on failure
+ if (!fetch_master_table(thd, tables->db, tables->real_name,
+ active_mi, 0))
+ {
+ send_ok(&thd->net);
+ }
+ UNLOCK_ACTIVE_MI;
break;
-
+ }
case SQLCOM_CREATE_TABLE:
if (!tables->db)
tables->db=thd->db;
@@ -1285,12 +1450,25 @@ mysql_execute_command(void)
res=0;
break;
}
- if (lex->item_list.elements) // With select
+#ifndef HAVE_READLINK
+ lex->create_info.data_file_name=lex->create_info.index_file_name=0;
+#else
+ /* Fix names if symlinked tables */
+ if (append_file_to_dir(thd, &lex->create_info.data_file_name,
+ tables->name) ||
+ append_file_to_dir(thd,&lex->create_info.index_file_name,
+ tables->name))
+ {
+ res=-1;
+ break;
+ }
+#endif
+ if (select_lex->item_list.elements) // With select
{
select_result *result;
if (!(lex->create_info.options & HA_LEX_CREATE_TMP_TABLE) &&
- check_dup(thd,tables->db,tables->real_name,tables->next))
+ check_dup(tables->db, tables->real_name, tables->next))
{
net_printf(&thd->net,ER_INSERT_TABLE_USED,tables->real_name);
DBUG_VOID_RETURN;
@@ -1303,31 +1481,22 @@ mysql_execute_command(void)
for (table = tables->next ; table ; table=table->next)
table->lock_type= lex->lock_option;
}
- thd->offset_limit=lex->offset_limit;
- thd->select_limit=lex->select_limit+lex->offset_limit;
- if (thd->select_limit < lex->select_limit)
+ thd->offset_limit=select_lex->offset_limit;
+ thd->select_limit=select_lex->select_limit+select_lex->offset_limit;
+ if (thd->select_limit < select_lex->select_limit)
thd->select_limit= HA_POS_ERROR; // No limit
+ /* Skip first table, which is the table we are creating */
+ lex->select_lex.table_list.first=
+ (byte*) (((TABLE_LIST *) lex->select_lex.table_list.first)->next);
if (!(res=open_and_lock_tables(thd,tables->next)))
{
- if ((result=new select_create(tables->db ? tables->db : thd->db,
- tables->real_name, &lex->create_info,
- lex->create_list,
- lex->key_list,
- lex->item_list,lex->duplicates)))
- {
- res=mysql_select(thd,tables->next,lex->item_list,
- lex->where,
- (ORDER*) lex->order_list.first,
- (ORDER*) lex->group_list.first,
- lex->having,
- (ORDER*) lex->proc_list.first,
- lex->options | thd->options,
- result);
- if (res)
- result->abort();
- delete result;
- }
+ if ((result=new select_create(tables->db ? tables->db : thd->db,
+ tables->real_name, &lex->create_info,
+ lex->create_list,
+ lex->key_list,
+ select_lex->item_list,lex->duplicates)))
+ res=handle_select(thd, lex, result);
else
res= -1;
}
@@ -1356,12 +1525,19 @@ mysql_execute_command(void)
break;
case SQLCOM_SLAVE_START:
- start_slave(thd);
+ {
+ LOCK_ACTIVE_MI;
+ start_slave(thd,active_mi,1 /* net report*/);
+ UNLOCK_ACTIVE_MI;
break;
+ }
case SQLCOM_SLAVE_STOP:
- stop_slave(thd);
+ {
+ LOCK_ACTIVE_MI;
+ stop_slave(thd,active_mi,1/* net report*/);
+ UNLOCK_ACTIVE_MI;
break;
-
+ }
case SQLCOM_ALTER_TABLE:
#if defined(DONT_ALLOW_SHOW_COMMANDS)
send_error(&thd->net,ER_NOT_ALLOWED_COMMAND); /* purecov: inspected */
@@ -1377,10 +1553,10 @@ mysql_execute_command(void)
}
if (!tables->db)
tables->db=thd->db;
- if (!lex->db)
- lex->db=tables->db;
+ if (!select_lex->db)
+ select_lex->db=tables->db;
if (check_access(thd,ALTER_ACL,tables->db,&tables->grant.privilege) ||
- check_access(thd,INSERT_ACL | CREATE_ACL,lex->db,&priv) ||
+ check_access(thd,INSERT_ACL | CREATE_ACL,select_lex->db,&priv) ||
check_merge_table_access(thd, tables->db,
(TABLE_LIST *)
lex->create_info.merge_list.first))
@@ -1396,22 +1572,27 @@ mysql_execute_command(void)
TABLE_LIST tmp_table;
bzero((char*) &tmp_table,sizeof(tmp_table));
tmp_table.real_name=lex->name;
- tmp_table.db=lex->db;
+ tmp_table.db=select_lex->db;
tmp_table.grant.privilege=priv;
if (check_grant(thd,INSERT_ACL | CREATE_ACL,tables))
goto error;
}
}
+ /* Don't yet allow changing of symlinks with ALTER TABLE */
+ lex->create_info.data_file_name=lex->create_info.index_file_name=0;
/* ALTER TABLE ends previous transaction */
if (end_active_trans(thd))
res= -1;
else
- res= mysql_alter_table(thd, lex->db, lex->name,
+ {
+ res= mysql_alter_table(thd, select_lex->db, lex->name,
&lex->create_info,
tables, lex->create_list,
lex->key_list, lex->drop_list, lex->alter_list,
- (ORDER *) lex->order_list.first,
- lex->drop_primary, lex->duplicates);
+ (ORDER *) select_lex->order_list.first,
+ lex->drop_primary, lex->duplicates,
+ lex->alter_keys_onoff, lex->simple_alter);
+ }
break;
}
#endif
@@ -1435,11 +1616,12 @@ mysql_execute_command(void)
old_list.next=new_list.next=0;
if (check_grant(thd,ALTER_ACL,&old_list) ||
(!test_all_bits(table->next->grant.privilege,
- INSERT_ACL | CREATE_ACL) &&
+ INSERT_ACL | CREATE_ACL) &&
check_grant(thd,INSERT_ACL | CREATE_ACL, &new_list)))
goto error;
}
}
+ query_cache.invalidate(tables);
if (end_active_trans(thd))
res= -1;
else if (mysql_rename_tables(thd,tables))
@@ -1473,21 +1655,23 @@ mysql_execute_command(void)
}
#endif
case SQLCOM_REPAIR:
- {
- if (check_db_used(thd,tables) ||
- check_table_access(thd,SELECT_ACL | INSERT_ACL, tables))
- goto error; /* purecov: inspected */
- res = mysql_repair_table(thd, tables, &lex->check_opt);
- break;
- }
+ {
+ if (check_db_used(thd,tables) ||
+ check_table_access(thd,SELECT_ACL | INSERT_ACL, tables))
+ goto error; /* purecov: inspected */
+ res = mysql_repair_table(thd, tables, &lex->check_opt);
+ query_cache.invalidate(tables);
+ break;
+ }
case SQLCOM_CHECK:
- {
- if (check_db_used(thd,tables) ||
- check_table_access(thd, SELECT_ACL | EXTRA_ACL , tables))
- goto error; /* purecov: inspected */
- res = mysql_check_table(thd, tables, &lex->check_opt);
- break;
- }
+ {
+ if (check_db_used(thd,tables) ||
+ check_table_access(thd, SELECT_ACL | EXTRA_ACL , tables))
+ goto error; /* purecov: inspected */
+ res = mysql_check_table(thd, tables, &lex->check_opt);
+ query_cache.invalidate(tables);
+ break;
+ }
case SQLCOM_ANALYZE:
{
if (check_db_used(thd,tables) ||
@@ -1529,23 +1713,73 @@ mysql_execute_command(void)
goto error;
if (grant_option && check_grant(thd,UPDATE_ACL,tables))
goto error;
- if (lex->item_list.elements != lex->value_list.elements)
+ if (select_lex->item_list.elements != lex->value_list.elements)
{
send_error(&thd->net,ER_WRONG_VALUE_COUNT);
DBUG_VOID_RETURN;
}
- res = mysql_update(thd,tables,
- lex->item_list,
- lex->value_list,
- lex->where,
- lex->select_limit,
- lex->duplicates,
- lex->lock_option);
+ if (select_lex->table_list.elements == 1)
+ {
+ res = mysql_update(thd,tables,
+ select_lex->item_list,
+ lex->value_list,
+ select_lex->where,
+ (ORDER *) select_lex->order_list.first,
+ select_lex->select_limit,
+ lex->duplicates,
+ lex->lock_option);
#ifdef DELETE_ITEMS
- delete lex->where;
+ delete select_lex->where;
#endif
- break;
+ }
+ else
+ {
+ multi_update *result;
+ uint table_count;
+ TABLE_LIST *auxi;
+ lex->sql_command=SQLCOM_MULTI_UPDATE;
+ for (auxi=(TABLE_LIST*) tables, table_count=0 ; auxi ; auxi=auxi->next)
+ {
+ table_count++;
+ auxi->lock_type=TL_WRITE;
+ }
+ if (select_lex->order_list.elements || (select_lex->select_limit && select_lex->select_limit < INT_MAX))
+ {
+ send_error(&thd->net,ER_NOT_ALLOWED_COMMAND); /// will have to come up with something better eventually
+ DBUG_VOID_RETURN;
+ }
+ tables->grant.want_privilege=(SELECT_ACL & ~tables->grant.privilege);
+ if ((res=open_and_lock_tables(thd,tables)))
+ break;
+ if (!setup_fields(thd,tables,select_lex->item_list,1,0,0) &&
+ !setup_fields(thd,tables,lex->value_list,0,0,0) && ! thd->fatal_error &&
+ (result=new multi_update(thd,tables,select_lex->item_list,lex->duplicates,
+ lex->lock_option, table_count)))
+ {
+ List <Item> total_list;
+ List_iterator <Item> field_list(select_lex->item_list);
+ List_iterator <Item> value_list(lex->value_list);
+ Item *item;
+ while ((item=field_list++))
+ total_list.push_back(item);
+ while ((item=value_list++))
+ total_list.push_back(item);
+
+ res=mysql_select(thd,tables,total_list,
+ select_lex->where,
+ (ORDER *)NULL,(ORDER *)NULL,(Item *)NULL,
+ (ORDER *)NULL,
+ select_lex->options | thd->options |
+ SELECT_NO_JOIN_CACHE,
+ result);
+ delete result;
+ }
+ else
+ res= -1; // Error is not sent
+ close_thread_tables(thd);
+ }
+ break;
case SQLCOM_INSERT:
if (check_access(thd,INSERT_ACL,tables->db,&tables->grant.privilege))
goto error; /* purecov: inspected */
@@ -1570,6 +1804,7 @@ mysql_execute_command(void)
case SQLCOM_REPLACE_SELECT:
case SQLCOM_INSERT_SELECT:
{
+
// Check that we have modify privileges for the first table and
// select privileges for the rest
{
@@ -1587,51 +1822,50 @@ mysql_execute_command(void)
}
select_result *result;
- thd->offset_limit=lex->offset_limit;
- thd->select_limit=lex->select_limit+lex->offset_limit;
- if (thd->select_limit < lex->select_limit)
+ thd->offset_limit=select_lex->offset_limit;
+ thd->select_limit=select_lex->select_limit+select_lex->offset_limit;
+ if (thd->select_limit < select_lex->select_limit)
thd->select_limit= HA_POS_ERROR; // No limit
- if (check_dup(thd,tables->db,tables->real_name,tables->next))
+ if (check_dup(tables->db, tables->real_name, tables->next))
{
net_printf(&thd->net,ER_INSERT_TABLE_USED,tables->real_name);
DBUG_VOID_RETURN;
}
- tables->lock_type=TL_WRITE; // update first table
+ tables->lock_type=TL_WRITE; // update first table
{
TABLE_LIST *table;
for (table = tables->next ; table ; table=table->next)
table->lock_type= lex->lock_option;
}
- if (!(res=open_and_lock_tables(thd,tables)))
+
+ /* Skip first table, which is the table we are inserting in */
+ lex->select_lex.table_list.first=
+ (byte*) (((TABLE_LIST *) lex->select_lex.table_list.first)->next);
+ if (!(res=open_and_lock_tables(thd, tables)))
{
if ((result=new select_insert(tables->table,&lex->field_list,
- lex->sql_command == SQLCOM_REPLACE_SELECT ?
- DUP_REPLACE : DUP_IGNORE)))
- {
- res=mysql_select(thd,tables->next,lex->item_list,
- lex->where,
- (ORDER*) lex->order_list.first,
- (ORDER*) lex->group_list.first,
- lex->having,
- (ORDER*) lex->proc_list.first,
- lex->options | thd->options,
- result);
- delete result;
- }
- else
- res= -1;
+ lex->duplicates)))
+ res=handle_select(thd,lex,result);
}
-#ifdef DELETE_ITEMS
- delete lex->having;
- delete lex->where;
-#endif
+ else
+ res= -1;
break;
}
case SQLCOM_TRUNCATE:
- lex->where=0;
- lex->select_limit=HA_POS_ERROR;
- /* Fall through */
+ if (check_access(thd,DELETE_ACL,tables->db,&tables->grant.privilege))
+ goto error; /* purecov: inspected */
+ /*
+ Don't allow this within a transaction because we want to use
+ re-generate table
+ */
+ if (thd->locked_tables || thd->active_transaction())
+ {
+ send_error(&thd->net,ER_LOCK_OR_ACTIVE_TRANSACTION,NullS);
+ goto error;
+ }
+ res=mysql_truncate(thd,tables);
+ break;
case SQLCOM_DELETE:
{
if (check_access(thd,DELETE_ACL,tables->db,&tables->grant.privilege))
@@ -1644,20 +1878,87 @@ mysql_execute_command(void)
if (lex->sql_command == SQLCOM_TRUNCATE && end_active_trans(thd))
res= -1;
else
- res = mysql_delete(thd,tables,lex->where,lex->select_limit,
- lex->lock_option, lex->options);
+ res = mysql_delete(thd,tables, select_lex->where,
+ (ORDER*) select_lex->order_list.first,
+ select_lex->select_limit, lex->lock_option,
+ select_lex->options);
break;
}
- case SQLCOM_DROP_TABLE:
+ case SQLCOM_DELETE_MULTI:
+ {
+ TABLE_LIST *aux_tables=(TABLE_LIST *)thd->lex.auxilliary_table_list.first;
+ TABLE_LIST *auxi;
+ uint table_count=0;
+ multi_delete *result;
+
+ /* sql_yacc guarantees that tables and aux_tables are not zero */
+ if (check_db_used(thd, tables) || check_db_used(thd,aux_tables) ||
+ check_table_access(thd,SELECT_ACL, tables) ||
+ check_table_access(thd,DELETE_ACL, aux_tables))
+ goto error;
+ if ((thd->options & OPTION_SAFE_UPDATES) && !select_lex->where)
+ {
+ send_error(&thd->net,ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE);
+ goto error;
+ }
+ for (auxi=(TABLE_LIST*) aux_tables ; auxi ; auxi=auxi->next)
{
- if (check_table_access(thd,DROP_ACL,tables))
- goto error; /* purecov: inspected */
- if (end_active_trans(thd))
- res= -1;
- else
- res = mysql_rm_table(thd,tables,lex->drop_if_exists);
+ table_count++;
+ /* All tables in aux_tables must be found in FROM PART */
+ TABLE_LIST *walk;
+ for (walk=(TABLE_LIST*) tables ; walk ; walk=walk->next)
+ {
+ if (!strcmp(auxi->real_name,walk->real_name) &&
+ !strcmp(walk->db,auxi->db))
+ break;
+ }
+ if (!walk)
+ {
+ net_printf(&thd->net,ER_NONUNIQ_TABLE,auxi->real_name);
+ goto error;
+ }
+ auxi->lock_type=walk->lock_type=TL_WRITE;
+ auxi->table= (TABLE *) walk; // Remember corresponding table
}
+ tables->grant.want_privilege=(SELECT_ACL & ~tables->grant.privilege);
+ if (add_item_to_list(new Item_null()))
+ {
+ res= -1;
+ break;
+ }
+ thd->proc_info="init";
+ if ((res=open_and_lock_tables(thd,tables)))
+ break;
+ /* Fix tables-to-be-deleted-from list to point at opened tables */
+ for (auxi=(TABLE_LIST*) aux_tables ; auxi ; auxi=auxi->next)
+ auxi->table= ((TABLE_LIST*) auxi->table)->table;
+ if (!thd->fatal_error && (result=new multi_delete(thd,aux_tables,
+ lex->lock_option,table_count)))
+ {
+ res=mysql_select(thd,tables,select_lex->item_list,
+ select_lex->where,
+ (ORDER *)NULL,(ORDER *)NULL,(Item *)NULL,
+ (ORDER *)NULL,
+ select_lex->options | thd->options |
+ SELECT_NO_JOIN_CACHE,
+ result);
+ delete result;
+ }
+ else
+ res= -1; // Error is not sent
+ close_thread_tables(thd);
break;
+ }
+ case SQLCOM_DROP_TABLE:
+ {
+ if (check_table_access(thd,DROP_ACL,tables))
+ goto error; /* purecov: inspected */
+ if (end_active_trans(thd))
+ res= -1;
+ else
+ res = mysql_rm_table(thd,tables,lex->drop_if_exists);
+ }
+ break;
case SQLCOM_DROP_INDEX:
if (!tables->db)
tables->db=thd->db;
@@ -1672,7 +1973,7 @@ mysql_execute_command(void)
break;
case SQLCOM_SHOW_DATABASES:
#if defined(DONT_ALLOW_SHOW_COMMANDS)
- send_error(&thd->net,ER_NOT_ALLOWED_COMMAND); /* purecov: inspected */
+ send_error(&thd->net,ER_NOT_ALLOWED_COMMAND); /* purecov: inspected */
DBUG_VOID_RETURN;
#else
if ((specialflag & SPECIAL_SKIP_SHOW_DB) &&
@@ -1708,13 +2009,12 @@ mysql_execute_command(void)
#endif
case SQLCOM_SHOW_TABLES:
/* FALL THROUGH */
- case SQLCOM_SHOW_OPEN_TABLES:
#ifdef DONT_ALLOW_SHOW_COMMANDS
send_error(&thd->net,ER_NOT_ALLOWED_COMMAND); /* purecov: inspected */
DBUG_VOID_RETURN;
#else
{
- char *db=lex->db ? lex->db : thd->db;
+ char *db=select_lex->db ? select_lex->db : thd->db;
if (!db)
{
send_error(&thd->net,ER_NO_DB_ERROR); /* purecov: inspected */
@@ -1729,34 +2029,32 @@ mysql_execute_command(void)
if (check_access(thd,SELECT_ACL,db,&thd->col_access))
goto error; /* purecov: inspected */
/* grant is checked in mysqld_show_tables */
- if (lex->sql_command == SQLCOM_SHOW_OPEN_TABLES)
- res= mysqld_show_open_tables(thd,db,
- (lex->wild ? lex->wild->ptr() : NullS));
- else if (lex->options & SELECT_DESCRIBE)
+ if (select_lex->options & SELECT_DESCRIBE)
res= mysqld_extend_show_tables(thd,db,
- (lex->wild ? lex->wild->ptr() : NullS));
+ (lex->wild ? lex->wild->ptr() : NullS));
else
res= mysqld_show_tables(thd,db,
(lex->wild ? lex->wild->ptr() : NullS));
break;
}
#endif
+ case SQLCOM_SHOW_OPEN_TABLES:
+ res= mysqld_show_open_tables(thd,(lex->wild ? lex->wild->ptr() : NullS));
+ break;
case SQLCOM_SHOW_FIELDS:
#ifdef DONT_ALLOW_SHOW_COMMANDS
send_error(&thd->net,ER_NOT_ALLOWED_COMMAND); /* purecov: inspected */
DBUG_VOID_RETURN;
#else
{
- char *db=tables->db ? tables->db : thd->db;
- if (!db)
+ char *db=tables->db;
+ if (!*db)
{
send_error(&thd->net,ER_NO_DB_ERROR); /* purecov: inspected */
goto error; /* purecov: inspected */
}
remove_escape(db); // Fix escaped '_'
remove_escape(tables->name);
- if (!tables->db)
- tables->db=thd->db;
if (check_access(thd,SELECT_ACL | EXTRA_ACL,db,&thd->col_access))
goto error; /* purecov: inspected */
tables->grant.privilege=thd->col_access;
@@ -1774,7 +2072,7 @@ mysql_execute_command(void)
DBUG_VOID_RETURN;
#else
{
- char *db=tables->db ? tables->db : thd->db;
+ char *db=tables->db;
if (!db)
{
send_error(&thd->net,ER_NO_DB_ERROR); /* purecov: inspected */
@@ -1794,7 +2092,7 @@ mysql_execute_command(void)
}
#endif
case SQLCOM_CHANGE_DB:
- mysql_change_db(thd,lex->db);
+ mysql_change_db(thd,select_lex->db);
break;
case SQLCOM_LOAD:
{
@@ -1815,7 +2113,7 @@ mysql_execute_command(void)
goto error;
}
if (check_access(thd,privilege,tables->db,&tables->grant.privilege) ||
- grant_option && check_grant(thd,privilege,tables))
+ grant_option && check_grant(thd,privilege,tables))
goto error;
}
res=mysql_load(thd, lex->exchange, tables, lex->field_list,
@@ -1824,22 +2122,17 @@ mysql_execute_command(void)
}
case SQLCOM_SET_OPTION:
{
- uint org_options=thd->options;
- thd->options=lex->options;
+ ulong org_options=thd->options;
+ thd->options=select_lex->options;
thd->update_lock_default= ((thd->options & OPTION_LOW_PRIORITY_UPDATES) ?
TL_WRITE_LOW_PRIORITY : TL_WRITE);
- thd->default_select_limit=lex->select_limit;
+ thd->default_select_limit=select_lex->select_limit;
thd->tx_isolation=lex->tx_isolation;
- if (thd->gemini_spin_retries != lex->gemini_spin_retries)
- {
- thd->gemini_spin_retries= lex->gemini_spin_retries;
- ha_set_spin_retries(thd->gemini_spin_retries);
- }
DBUG_PRINT("info",("options: %ld limit: %ld",
thd->options,(long) thd->default_select_limit));
/* Check if auto_commit mode changed */
- if ((org_options ^ lex->options) & OPTION_NOT_AUTO_COMMIT)
+ if ((org_options ^ select_lex->options) & OPTION_NOT_AUTO_COMMIT)
{
if ((org_options & OPTION_NOT_AUTO_COMMIT))
{
@@ -1873,13 +2166,7 @@ mysql_execute_command(void)
thd->options&= ~(ulong) (OPTION_TABLE_LOCK);
}
if (thd->global_read_lock)
- {
- thd->global_read_lock=0;
- pthread_mutex_lock(&LOCK_open);
- global_read_lock--;
- pthread_cond_broadcast(&COND_refresh);
- pthread_mutex_unlock(&LOCK_open);
- }
+ unlock_global_read_lock(thd);
send_ok(&thd->net);
break;
case SQLCOM_LOCK_TABLES:
@@ -1891,6 +2178,8 @@ mysql_execute_command(void)
}
if (check_db_used(thd,tables) || end_active_trans(thd))
goto error;
+ if (grant_option && check_grant(thd,SELECT_ACL | INSERT_ACL | UPDATE_ACL | DELETE_ACL,tables))
+ goto error;
thd->in_lock_tables=1;
thd->options|= OPTION_TABLE_LOCK;
if (!(res=open_and_lock_tables(thd,tables)))
@@ -1904,30 +2193,34 @@ mysql_execute_command(void)
thd->in_lock_tables=0;
break;
case SQLCOM_CREATE_DB:
+ {
+ if (!stripp_sp(lex->name) || check_db_name(lex->name))
{
- if (!stripp_sp(lex->name) || check_db_name(lex->name))
- {
- net_printf(&thd->net,ER_WRONG_DB_NAME, lex->name);
- break;
- }
- if (check_access(thd,CREATE_ACL,lex->name,0,1))
- break;
- mysql_create_db(thd,lex->name,lex->create_info.options);
+ net_printf(&thd->net,ER_WRONG_DB_NAME, lex->name);
break;
}
+ if (check_access(thd,CREATE_ACL,lex->name,0,1))
+ break;
+ res=mysql_create_db(thd,lex->name,lex->create_info.options,0);
+ break;
+ }
case SQLCOM_DROP_DB:
+ {
+ if (!stripp_sp(lex->name) || check_db_name(lex->name))
{
- if (!stripp_sp(lex->name) || check_db_name(lex->name))
- {
- net_printf(&thd->net,ER_WRONG_DB_NAME, lex->name);
- break;
- }
- if (check_access(thd,DROP_ACL,lex->name,0,1) ||
- end_active_trans(thd))
- break;
- mysql_rm_db(thd,lex->name,lex->drop_if_exists);
+ net_printf(&thd->net,ER_WRONG_DB_NAME, lex->name);
+ break;
+ }
+ if (check_access(thd,DROP_ACL,lex->name,0,1))
break;
+ if (thd->locked_tables || thd->active_transaction())
+ {
+ send_error(&thd->net,ER_LOCK_OR_ACTIVE_TRANSACTION);
+ goto error;
}
+ res=mysql_rm_db(thd,lex->name,lex->drop_if_exists,0);
+ break;
+ }
case SQLCOM_CREATE_FUNCTION:
if (check_access(thd,INSERT_ACL,"mysql",0,1))
break;
@@ -1948,78 +2241,83 @@ mysql_execute_command(void)
res= -1;
#endif
break;
- case SQLCOM_REVOKE:
- case SQLCOM_GRANT:
- {
- if (tables && !tables->db)
- tables->db=thd->db;
- if (check_access(thd, lex->grant | lex->grant_tot_col | GRANT_ACL,
- tables && tables->db ? tables->db : lex->db,
- tables ? &tables->grant.privilege : 0,
- tables ? 0 : 1))
- goto error;
-
- /* Check that the user isn't trying to change a password for another
- user if he doesn't have UPDATE privilege to the MySQL database */
-
- if (thd->user) // If not replication
- {
- LEX_USER *user;
- List_iterator <LEX_USER> user_list(lex->users_list);
- while ((user=user_list++))
- {
- if (user->password.str &&
- (strcmp(thd->user,user->user.str) ||
- user->host.str &&
- my_strcasecmp(user->host.str, thd->host ? thd->host : thd->ip)))
- {
- if (check_access(thd, UPDATE_ACL, "mysql",0,1))
- goto error;
- break; // We are allowed to do changes
- }
- }
- }
- if (tables)
- {
- if (grant_option && check_grant(thd,
- (lex->grant | lex->grant_tot_col |
- GRANT_ACL),
- tables))
- goto error;
- res = mysql_table_grant(thd,tables,lex->users_list, lex->columns,
- lex->grant, lex->sql_command == SQLCOM_REVOKE);
- if(!res)
- {
- mysql_update_log.write(thd, thd->query,thd->query_length);
- if (mysql_bin_log.is_open())
- {
- Query_log_event qinfo(thd, thd->query);
- mysql_bin_log.write(&qinfo);
- }
- }
- }
- else
- {
- if (lex->columns.elements)
- {
- net_printf(&thd->net,ER_ILLEGAL_GRANT_FOR_TABLE);
- res=1;
- }
- else
- res = mysql_grant(thd, lex->db, lex->users_list, lex->grant,
- lex->sql_command == SQLCOM_REVOKE);
- if (!res)
- {
- mysql_update_log.write(thd, thd->query,thd->query_length);
- if (mysql_bin_log.is_open())
- {
- Query_log_event qinfo(thd, thd->query);
- mysql_bin_log.write(&qinfo);
- }
- }
- }
- break;
- }
+ case SQLCOM_REVOKE:
+ case SQLCOM_GRANT:
+ {
+ if (check_access(thd, lex->grant | lex->grant_tot_col | GRANT_ACL,
+ tables && tables->db ? tables->db : select_lex->db,
+ tables ? &tables->grant.privilege : 0,
+ tables ? 0 : 1))
+ goto error;
+
+ /* Check that the user isn't trying to change a password for another
+ user if he doesn't have UPDATE privilege to the MySQL database */
+
+ if (thd->user) // If not replication
+ {
+ LEX_USER *user;
+ List_iterator <LEX_USER> user_list(lex->users_list);
+ while ((user=user_list++))
+ {
+ if (user->password.str &&
+ (strcmp(thd->user,user->user.str) ||
+ user->host.str &&
+ my_strcasecmp(user->host.str, thd->host_or_ip)))
+ {
+ if (check_access(thd, UPDATE_ACL, "mysql",0,1))
+ goto error;
+ break; // We are allowed to do changes
+ }
+ }
+ }
+ if (tables)
+ {
+ if (grant_option && check_grant(thd,
+ (lex->grant | lex->grant_tot_col |
+ GRANT_ACL),
+ tables))
+ goto error;
+ if (!(res = mysql_table_grant(thd,tables,lex->users_list, lex->columns,
+ lex->grant,
+ lex->sql_command == SQLCOM_REVOKE)))
+ {
+ mysql_update_log.write(thd, thd->query, thd->query_length);
+ if (mysql_bin_log.is_open())
+ {
+ Query_log_event qinfo(thd, thd->query);
+ mysql_bin_log.write(&qinfo);
+ }
+ }
+ }
+ else
+ {
+ if (lex->columns.elements)
+ {
+ send_error(&thd->net,ER_ILLEGAL_GRANT_FOR_TABLE);
+ res=1;
+ }
+ else
+ res = mysql_grant(thd, select_lex->db, lex->users_list, lex->grant,
+ lex->sql_command == SQLCOM_REVOKE);
+ if (!res)
+ {
+ mysql_update_log.write(thd, thd->query, thd->query_length);
+ if (mysql_bin_log.is_open())
+ {
+ Query_log_event qinfo(thd, thd->query);
+ mysql_bin_log.write(&qinfo);
+ }
+ if (mqh_used && lex->mqh)
+ {
+ List_iterator <LEX_USER> str_list(lex->users_list);
+ LEX_USER *user;
+ while ((user=str_list++))
+ reset_mqh(thd,user,lex->mqh);
+ }
+ }
+ }
+ break;
+ }
case SQLCOM_FLUSH:
case SQLCOM_RESET:
if (check_access(thd,RELOAD_ACL,any_db) || check_db_used(thd, tables))
@@ -2034,13 +2332,40 @@ mysql_execute_command(void)
break;
case SQLCOM_SHOW_GRANTS:
res=0;
- if ((thd->priv_user && !strcmp(thd->priv_user,lex->grant_user->user.str)) ||
+ if ((thd->priv_user &&
+ !strcmp(thd->priv_user,lex->grant_user->user.str)) ||
!check_access(thd, SELECT_ACL, "mysql",0,1))
{
res = mysql_show_grants(thd,lex->grant_user);
}
break;
+ case SQLCOM_HA_OPEN:
+ if (check_db_used(thd,tables) ||
+ check_table_access(thd,SELECT_ACL, tables))
+ goto error;
+ res = mysql_ha_open(thd, tables);
+ break;
+ case SQLCOM_HA_CLOSE:
+ if (check_db_used(thd,tables))
+ goto error;
+ res = mysql_ha_close(thd, tables);
+ break;
+ case SQLCOM_HA_READ:
+ if (check_db_used(thd,tables) ||
+ check_table_access(thd,SELECT_ACL, tables))
+ goto error;
+ res = mysql_ha_read(thd, tables, lex->ha_read_mode, lex->backup_dir,
+ lex->insert_list, lex->ha_rkey_mode, select_lex->where,
+ select_lex->select_limit, select_lex->offset_limit);
+ break;
+
case SQLCOM_BEGIN:
+ if (thd->locked_tables)
+ {
+ thd->lock=thd->locked_tables;
+ thd->locked_tables=0; // Will be automaticly closed
+ close_thread_tables(thd); // Free tables
+ }
if (end_active_trans(thd))
{
res= -1;
@@ -2059,13 +2384,17 @@ mysql_execute_command(void)
even if there is a problem with the OPTION_AUTO_COMMIT flag
(Which of course should never happen...)
*/
+ {
thd->options&= ~(ulong) (OPTION_BEGIN | OPTION_STATUS_NO_TRANS_UPDATE);
thd->server_status&= ~SERVER_STATUS_IN_TRANS;
if (!ha_commit(thd))
+ {
send_ok(&thd->net);
+ }
else
res= -1;
break;
+ }
case SQLCOM_ROLLBACK:
thd->server_status&= ~SERVER_STATUS_IN_TRANS;
if (!ha_rollback(thd))
@@ -2104,7 +2433,7 @@ error:
bool
check_access(THD *thd,uint want_access,const char *db, uint *save_priv,
- bool dont_check_global_grants)
+ bool dont_check_global_grants, bool no_errors)
{
uint db_access,dummy;
if (save_priv)
@@ -2112,9 +2441,10 @@ check_access(THD *thd,uint want_access,const char *db, uint *save_priv,
else
save_priv= &dummy;
- if (!db && !thd->db && !dont_check_global_grants)
+ if ((!db || !db[0]) && !thd->db && !dont_check_global_grants)
{
- send_error(&thd->net,ER_NO_DB_ERROR); /* purecov: tested */
+ if (!no_errors)
+ send_error(&thd->net,ER_NO_DB_ERROR); /* purecov: tested */
return TRUE; /* purecov: tested */
}
@@ -2126,16 +2456,17 @@ check_access(THD *thd,uint want_access,const char *db, uint *save_priv,
if ((want_access & ~thd->master_access) & ~(DB_ACLS | EXTRA_ACL) ||
! db && dont_check_global_grants)
{ // We can never grant this
- net_printf(&thd->net,ER_ACCESS_DENIED_ERROR,
- thd->priv_user,
- thd->host ? thd->host : (thd->ip ? thd->ip : "unknown"),
- thd->password ? ER(ER_YES) : ER(ER_NO));/* purecov: tested */
+ if (!no_errors)
+ net_printf(&thd->net,ER_ACCESS_DENIED_ERROR,
+ thd->priv_user,
+ thd->host_or_ip,
+ thd->password ? ER(ER_YES) : ER(ER_NO));/* purecov: tested */
return TRUE; /* purecov: tested */
}
if (db == any_db)
return FALSE; // Allow select on anything
-
+
if (db && (!thd->db || strcmp(db,thd->db)))
db_access=acl_get(thd->host, thd->ip, (char*) &thd->remote.sin_addr,
thd->priv_user, db); /* purecov: inspected */
@@ -2149,10 +2480,11 @@ check_access(THD *thd,uint want_access,const char *db, uint *save_priv,
((grant_option && !dont_check_global_grants) &&
!(want_access & ~TABLE_ACLS)))
return FALSE; /* Ok */
- net_printf(&thd->net,ER_DBACCESS_DENIED_ERROR,
- thd->priv_user,
- thd->host ? thd->host : (thd->ip ? thd->ip : "unknown"),
- db ? db : thd->db ? thd->db : "unknown"); /* purecov: tested */
+ if (!no_errors)
+ net_printf(&thd->net,ER_DBACCESS_DENIED_ERROR,
+ thd->priv_user,
+ thd->host_or_ip,
+ db ? db : thd->db ? thd->db : "unknown"); /* purecov: tested */
return TRUE; /* purecov: tested */
}
@@ -2169,7 +2501,8 @@ bool check_process_priv(THD *thd)
*/
bool
-check_table_access(THD *thd,uint want_access,TABLE_LIST *tables)
+check_table_access(THD *thd,uint want_access,TABLE_LIST *tables,
+ bool no_errors)
{
uint found=0,found_access=0;
TABLE_LIST *org_tables=tables;
@@ -2184,20 +2517,20 @@ check_table_access(THD *thd,uint want_access,TABLE_LIST *tables)
tables->grant.privilege=found_access;
else
{
- if (check_access(thd,want_access,tables->db,&tables->grant.privilege))
+ if (check_access(thd,want_access,tables->db,&tables->grant.privilege,
+ 0, no_errors))
return TRUE; // Access denied
found_access=tables->grant.privilege;
found=1;
}
}
- else if (check_access(thd,want_access,tables->db,&tables->grant.privilege))
+ else if (check_access(thd,want_access,tables->db,&tables->grant.privilege,
+ 0, no_errors))
return TRUE; // Access denied
}
if (grant_option)
- {
- want_access &= ~EXTRA_ACL; // Remove SHOW attribute
- return check_grant(thd,want_access,org_tables);
- }
+ return check_grant(thd,want_access & ~EXTRA_ACL,org_tables,
+ test(want_access & EXTRA_ACL), no_errors);
return FALSE;
}
@@ -2301,42 +2634,75 @@ bool my_yyoverflow(short **yyss, YYSTYPE **yyvs, int *yystacksize)
/****************************************************************************
- Initialize global thd variables neaded for query
+ Initialize global thd variables needed for query
****************************************************************************/
static void
mysql_init_query(THD *thd)
{
DBUG_ENTER("mysql_init_query");
- thd->lex.item_list.empty();
+ thd->lex.select_lex.item_list.empty();
thd->lex.value_list.empty();
- thd->lex.table_list.elements=0;
- thd->free_list=0;
-
- thd->lex.table_list.first=0;
- thd->lex.table_list.next= (byte**) &thd->lex.table_list.first;
+ thd->lex.select_lex.table_list.elements=0;
+ thd->free_list=0; thd->lex.union_option=0;
+ thd->lex.select = &thd->lex.select_lex;
+ thd->lex.select_lex.table_list.first=0;
+ thd->lex.select_lex.table_list.next= (byte**) &thd->lex.select_lex.table_list.first;
+ thd->lex.select_lex.next=0;
thd->fatal_error=0; // Safety
thd->last_insert_id_used=thd->query_start_used=thd->insert_id_used=0;
thd->sent_row_count=thd->examined_row_count=0;
+ thd->safe_to_cache_query=1;
DBUG_VOID_RETURN;
}
void
mysql_init_select(LEX *lex)
{
- lex->where=lex->having=0;
- lex->select_limit=current_thd->default_select_limit;
- lex->offset_limit=0L;
- lex->options=0;
+ SELECT_LEX *select_lex = lex->select;
+ select_lex->where=select_lex->having=0;
+ select_lex->select_limit=lex->thd->default_select_limit;
+ select_lex->offset_limit=0;
+ select_lex->options=0;
+ select_lex->linkage=UNSPECIFIED_TYPE;
lex->exchange = 0;
lex->proc_list.first=0;
- lex->order_list.elements=lex->group_list.elements=0;
- lex->order_list.first=0;
- lex->order_list.next= (byte**) &lex->order_list.first;
- lex->group_list.first=0;
- lex->group_list.next= (byte**) &lex->group_list.first;
+ select_lex->order_list.elements=select_lex->group_list.elements=0;
+ select_lex->order_list.first=0;
+ select_lex->order_list.next= (byte**) &select_lex->order_list.first;
+ select_lex->group_list.first=0;
+ select_lex->group_list.next= (byte**) &select_lex->group_list.first;
+ select_lex->next = (SELECT_LEX *)NULL;
+}
+
+bool
+mysql_new_select(LEX *lex)
+{
+ SELECT_LEX *select_lex = (SELECT_LEX *) lex->thd->calloc(sizeof(SELECT_LEX));
+ if (!select_lex)
+ return 1;
+ lex->select->next=select_lex;
+ lex->select=select_lex;
+ select_lex->table_list.next= (byte**) &select_lex->table_list.first;
+ select_lex->item_list.empty();
+ select_lex->when_list.empty();
+ select_lex->expr_list.empty();
+ select_lex->interval_list.empty();
+ select_lex->use_index.empty();
+ select_lex->ftfunc_list.empty();
+ return 0;
}
+void mysql_init_multi_delete(LEX *lex)
+{
+ lex->sql_command = SQLCOM_DELETE_MULTI;
+ mysql_init_select(lex);
+ lex->select->select_limit=HA_POS_ERROR;
+ lex->auxilliary_table_list=lex->select_lex.table_list;
+ lex->select->table_list.elements=0;
+ lex->select->table_list.first=0;
+ lex->select->table_list.next= (byte**) &(lex->select->table_list.first);
+}
void
mysql_parse(THD *thd,char *inBuf,uint length)
@@ -2345,12 +2711,20 @@ mysql_parse(THD *thd,char *inBuf,uint length)
mysql_init_query(thd);
thd->query_length = length;
- LEX *lex=lex_start(thd, (uchar*) inBuf, length);
- if (!yyparse() && ! thd->fatal_error)
- mysql_execute_command();
- thd->proc_info="freeing items";
- free_items(thd); /* Free strings used by items */
- lex_end(lex);
+ if (query_cache.send_result_to_client(thd, inBuf, length) <= 0)
+ {
+ LEX *lex=lex_start(thd, (uchar*) inBuf, length);
+ if (!yyparse() && ! thd->fatal_error)
+ {
+ mysql_execute_command();
+ query_cache_end_of_result(&thd->net);
+ }
+ else
+ query_cache_abort(&thd->net);
+ thd->proc_info="freeing items";
+ free_items(thd); /* Free strings used by items */
+ lex_end(lex);
+ }
DBUG_VOID_RETURN;
}
@@ -2656,6 +3030,8 @@ add_proc_to_list(Item *item)
static void remove_escape(char *name)
{
+ if (!*name) // For empty DB names
+ return;
char *to;
#ifdef USE_MB
char *strend=name+(uint) strlen(name);
@@ -2675,7 +3051,7 @@ static void remove_escape(char *name)
}
#endif
if (*name == '\\' && name[1])
- name++; // Skipp '\\'
+ name++; // Skip '\\'
*to++= *name;
}
*to=0;
@@ -2714,7 +3090,6 @@ TABLE_LIST *add_table_to_list(Table_ident *table, LEX_STRING *alias,
register TABLE_LIST *ptr;
THD *thd=current_thd;
char *alias_str;
- const char *current_db;
DBUG_ENTER("add_table_to_list");
if (!table)
@@ -2729,15 +3104,19 @@ TABLE_LIST *add_table_to_list(Table_ident *table, LEX_STRING *alias,
}
if (!alias) /* Alias is case sensitive */
- if (!(alias_str=sql_strmake(alias_str,table->table.length)))
+ if (!(alias_str=thd->memdup(alias_str,table->table.length+1)))
DBUG_RETURN(0);
- if (lower_case_table_names)
- casedn_str(table->table.str);
+
if (!(ptr = (TABLE_LIST *) thd->calloc(sizeof(TABLE_LIST))))
DBUG_RETURN(0); /* purecov: inspected */
- ptr->db= table->db.str;
- ptr->real_name=table->table.str;
+ ptr->db= table->db.str ? table->db.str : (thd->db ? thd->db : (char*) "");
ptr->name=alias_str;
+ if (lower_case_table_names)
+ {
+ casedn_str(ptr->db);
+ casedn_str(table->table.str);
+ }
+ ptr->real_name=table->table.str;
ptr->lock_type=flags;
ptr->updating=updating;
if (use_index)
@@ -2748,26 +3127,86 @@ TABLE_LIST *add_table_to_list(Table_ident *table, LEX_STRING *alias,
sizeof(*ignore_index));
/* check that used name is unique */
- current_db=thd->db ? thd->db : "";
-
if (flags != TL_IGNORE)
{
- for (TABLE_LIST *tables=(TABLE_LIST*) thd->lex.table_list.first ; tables ;
+ for (TABLE_LIST *tables=(TABLE_LIST*) thd->lex.select->table_list.first ;
+ tables ;
tables=tables->next)
{
- if (!strcmp(alias_str,tables->name) &&
- !strcmp(ptr->db ? ptr->db : current_db,
- tables->db ? tables->db : current_db))
+ if (!strcmp(alias_str,tables->name) && !strcmp(ptr->db, tables->db))
{
net_printf(&thd->net,ER_NONUNIQ_TABLE,alias_str); /* purecov: tested */
DBUG_RETURN(0); /* purecov: tested */
}
}
}
- link_in_list(&thd->lex.table_list,(byte*) ptr,(byte**) &ptr->next);
+ link_in_list(&thd->lex.select->table_list,(byte*) ptr,(byte**) &ptr->next);
DBUG_RETURN(ptr);
}
+
+/*
+** This is used for UNION to create a new table list of all used tables
+** The table_list->table entry in all used tables are set to point
+** to the entries in this list.
+*/
+
+static bool create_total_list(THD *thd, LEX *lex, TABLE_LIST **result)
+{
+ /* Handle the case when we are not using union */
+ if (!lex->select_lex.next)
+ {
+ *result= (TABLE_LIST*) lex->select_lex.table_list.first;
+ return 0;
+ }
+
+ SELECT_LEX *sl;
+ TABLE_LIST **new_table_list= result, *aux;
+
+ *new_table_list=0; // end result list
+ for (sl= &lex->select_lex; sl; sl=sl->next)
+ {
+ if (sl->order_list.first && sl->next && !sl->braces)
+ {
+ net_printf(&thd->net,ER_WRONG_USAGE,"UNION","ORDER BY");
+ return 1;
+ }
+ if ((aux= (TABLE_LIST*) sl->table_list.first))
+ {
+ TABLE_LIST *next;
+ for (; aux; aux=next)
+ {
+ TABLE_LIST *cursor;
+ next= aux->next;
+ for (cursor= *result; cursor; cursor=cursor->next)
+ if (!strcmp(cursor->db,aux->db) &&
+ !strcmp(cursor->real_name,aux->real_name) &&
+ !strcmp(cursor->name, aux->name))
+ break;
+ if (!cursor)
+ {
+ /* Add not used table to the total table list */
+ aux->lock_type= lex->lock_option;
+ if (!(cursor = (TABLE_LIST *) thd->memdup((char*) aux,
+ sizeof(*aux))))
+ {
+ send_error(&thd->net,0);
+ return 1;
+ }
+ *new_table_list= cursor;
+ new_table_list= &cursor->next;
+ *new_table_list=0; // end result list
+ }
+ else
+ aux->shared=1; // Mark that it's used twice
+ aux->table=(TABLE *) cursor;
+ }
+ }
+ }
+ return 0;
+}
+
+
void add_join_on(TABLE_LIST *b,Item *expr)
{
if (!b->on_expr)
@@ -2787,22 +3226,20 @@ void add_join_natural(TABLE_LIST *a,TABLE_LIST *b)
/* Check if name is used in table list */
-static bool check_dup(THD *thd,const char *db,const char *name,
- TABLE_LIST *tables)
+static bool check_dup(const char *db, const char *name, TABLE_LIST *tables)
{
- const char *thd_db=thd->db ? thd->db : any_db;
for (; tables ; tables=tables->next)
- if (!strcmp(name,tables->real_name) &&
- !strcmp(db ? db : thd_db, tables->db ? tables->db : thd_db))
+ if (!strcmp(name,tables->real_name) && !strcmp(db,tables->db))
return 1;
return 0;
}
-bool reload_acl_and_cache(THD *thd, uint options, TABLE_LIST *tables)
+bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables)
{
bool result=0;
select_errors=0; /* Write if more errors */
+ // TODO: figure out what's up with the commented out line below
// mysql_log.flush(); // Flush log
if (options & REFRESH_GRANT)
{
@@ -2818,12 +3255,21 @@ bool reload_acl_and_cache(THD *thd, uint options, TABLE_LIST *tables)
if (ha_flush_logs())
result=1;
}
+ if (options & REFRESH_QUERY_CACHE_FREE)
+ {
+ query_cache.pack(); // FLUSH QUERY CACHE
+ options &= ~REFRESH_QUERY_CACHE; //don't flush all cache, just free memory
+ }
+ if (options & (REFRESH_TABLES | REFRESH_QUERY_CACHE))
+ {
+ query_cache.flush(); // RESET QUERY CACHE
+ }
if (options & (REFRESH_TABLES | REFRESH_READ_LOCK))
{
- if ((options & REFRESH_READ_LOCK) && thd && ! thd->global_read_lock)
+ if ((options & REFRESH_READ_LOCK) && thd)
{
- thd->global_read_lock=1;
- thread_safe_increment(global_read_lock,&LOCK_open);
+ if (lock_global_read_lock(thd))
+ return 1;
}
result=close_cached_tables(thd,(options & REFRESH_FAST) ? 0 : 1, tables);
}
@@ -2834,10 +3280,22 @@ bool reload_acl_and_cache(THD *thd, uint options, TABLE_LIST *tables)
if (options & REFRESH_THREADS)
flush_thread_cache();
if (options & REFRESH_MASTER)
- reset_master();
- if (options & REFRESH_SLAVE)
- reset_slave();
-
+ if (reset_master(thd))
+ result=1;
+#ifdef OPENSSL
+ if (options & REFRESH_DES_KEY_FILE)
+ {
+ if (des_key_file)
+ result=load_des_key_file(des_key_file);
+ }
+#endif
+ if (options & REFRESH_SLAVE)
+ {
+ LOCK_ACTIVE_MI;
+ if (reset_slave(active_mi))
+ result=1;
+ UNLOCK_ACTIVE_MI;
+ }
return result;
}
@@ -2855,7 +3313,7 @@ void kill_one_thread(THD *thd, ulong id)
if ((thd->master_access & PROCESS_ACL) ||
!strcmp(thd->user,tmp->user))
{
- tmp->prepare_to_die();
+ tmp->awake(1 /*prepare to die*/);
error=0;
}
else
@@ -2884,3 +3342,29 @@ static void refresh_status(void)
pthread_mutex_unlock(&LOCK_status);
pthread_mutex_unlock(&THR_LOCK_keycache);
}
+
+
+ /* If pointer is not a null pointer, append filename to it */
+
+static bool append_file_to_dir(THD *thd, char **filename_ptr, char *table_name)
+{
+ char buff[FN_REFLEN],*ptr, *end;
+ if (!*filename_ptr)
+ return 0; // nothing to do
+
+ /* Check that the filename is not too long and it's a hard path */
+ if (strlen(*filename_ptr)+strlen(table_name) >= FN_REFLEN-1 ||
+ !test_if_hard_path(*filename_ptr))
+ {
+ my_error(ER_WRONG_TABLE_NAME, MYF(0), *filename_ptr);
+ return 1;
+ }
+ /* Fix is using unix filename format on dos */
+ strmov(buff,*filename_ptr);
+ end=convert_dirname(buff, *filename_ptr, NullS);
+ if (!(ptr=thd->alloc((uint) (end-buff)+(uint) strlen(table_name)+1)))
+ return 1; // End of memory
+ *filename_ptr=ptr;
+ strxmov(ptr,buff,table_name,NullS);
+ return 0;
+}
diff --git a/sql/sql_rename.cc b/sql/sql_rename.cc
index 0f6e2f9fbf3..f2a0351361b 100644
--- a/sql/sql_rename.cc
+++ b/sql/sql_rename.cc
@@ -31,19 +31,21 @@ static TABLE_LIST *rename_tables(THD *thd, TABLE_LIST *table_list,
bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list)
{
- bool error=1,cerror,got_all_locks=1;
+ bool error=1,got_all_locks=1;
TABLE_LIST *lock_table,*ren_table=0;
DBUG_ENTER("mysql_rename_tables");
-
- /* Avoid problems with a rename on a table that we have locked or
- if the user is trying to to do this in a transcation context */
+
+ /*
+ Avoid problems with a rename on a table that we have locked or
+ if the user is trying to to do this in a transcation context
+ */
if (thd->locked_tables || thd->active_transaction())
{
my_error(ER_LOCK_OR_ACTIVE_TRANSACTION,MYF(0));
DBUG_RETURN(1);
}
-
+
VOID(pthread_mutex_lock(&LOCK_open));
for (lock_table=table_list ; lock_table ; lock_table=lock_table->next)
{
@@ -53,13 +55,13 @@ bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list)
if (got_lock)
got_all_locks=0;
}
-
+
if (!got_all_locks && wait_for_locked_table_names(thd,table_list))
goto end;
if (!(ren_table=rename_tables(thd,table_list,0)))
error=0;
-
+
end:
if (ren_table)
{
@@ -80,19 +82,14 @@ end:
for (table=table_list ;
table->next != ren_table ;
table=table->next->next) ;
- table=table->next->next; // Skipp error table
+ table=table->next->next; // Skip error table
/* Revert to old names */
rename_tables(thd, table, 1);
/* Note that lock_table == 0 here, so the unlock loop will work */
}
/* Lets hope this doesn't fail as the result will be messy */
- if ((cerror=ha_commit_rename(thd)))
- {
- my_error(ER_GET_ERRNO,MYF(0),cerror);
- error= 1;
- }
- else if (!error)
+ if (!error)
{
mysql_update_log.write(thd,thd->query,thd->query_length);
if (mysql_bin_log.is_open())
@@ -134,7 +131,7 @@ rename_tables(THD *thd, TABLE_LIST *table_list, bool skip_error)
if (!access(name,F_OK))
{
my_error(ER_TABLE_EXISTS_ERROR,MYF(0),name);
- return ren_table; // This can't be skipped
+ DBUG_RETURN(ren_table); // This can't be skipped
}
sprintf(name,"%s/%s/%s%s",mysql_data_home,
ren_table->db,ren_table->name,
@@ -143,7 +140,7 @@ rename_tables(THD *thd, TABLE_LIST *table_list, bool skip_error)
{
my_error(ER_FILE_NOT_FOUND, MYF(0), name, my_errno);
if (!skip_error)
- return ren_table;
+ DBUG_RETURN(ren_table);
}
else if (mysql_rename_table(table_type,
ren_table->db, ren_table->name,
diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc
index 1940ff360c2..0b408920703 100644
--- a/sql/sql_repl.cc
+++ b/sql/sql_repl.cc
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB & Sasha
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
@@ -15,17 +15,17 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
// Sasha Pachev <sasha@mysql.com> is currently in charge of this file
-// Do not mess with it without his permission!
#include "mysql_priv.h"
#include "sql_repl.h"
#include "sql_acl.h"
#include "log_event.h"
+#include "mini_client.h"
#include <thr_alarm.h>
#include <my_dir.h>
+#include <assert.h>
extern const char* any_db;
-extern pthread_handler_decl(handle_slave,arg);
#ifndef DBUG_OFF
int max_binlog_dump_events = 0; // unlimited
@@ -33,43 +33,66 @@ bool opt_sporadic_binlog_dump_fail = 0;
static int binlog_dump_count = 0;
#endif
+int check_binlog_magic(IO_CACHE* log, const char** errmsg)
+{
+ char magic[4];
+ DBUG_ASSERT(my_b_tell(log) == 0);
+
+ if (my_b_read(log, (byte*) magic, sizeof(magic)))
+ {
+ *errmsg = "I/O error reading the header from the binary log";
+ sql_print_error("%s, errno=%d, io cache code=%d", *errmsg, my_errno,
+ log->error);
+ return 1;
+ }
+ if (memcmp(magic, BINLOG_MAGIC, sizeof(magic)))
+ {
+ *errmsg = "Binlog has bad magic number; It's not a binary log file that can be used by this version of MySQL";
+ return 1;
+ }
+ return 0;
+}
+
static int fake_rotate_event(NET* net, String* packet, char* log_file_name,
const char**errmsg)
{
- char header[LOG_EVENT_HEADER_LEN];
+ char header[LOG_EVENT_HEADER_LEN], buf[ROTATE_HEADER_LEN];
memset(header, 0, 4); // when does not matter
header[EVENT_TYPE_OFFSET] = ROTATE_EVENT;
- char* p = strrchr(log_file_name, FN_LIBCHAR);
- // find the last slash
- if(p)
- p++;
- else
- p = log_file_name;
+ char* p = log_file_name+dirname_length(log_file_name);
uint ident_len = (uint) strlen(p);
- ulong event_len = ident_len + sizeof(header);
- int4store(header + EVENT_TYPE_OFFSET + 1, server_id);
+ ulong event_len = ident_len + ROTATE_EVENT_OVERHEAD;
+ int4store(header + SERVER_ID_OFFSET, server_id);
int4store(header + EVENT_LEN_OFFSET, event_len);
+ int2store(header + FLAGS_OFFSET, 0);
+
+ // TODO: check what problems this may cause and fix them
+ int4store(header + LOG_POS_OFFSET, 0);
+
packet->append(header, sizeof(header));
+ /* We need to split the next statement because of problem with cxx */
+ int4store(buf,4); // tell slave to skip magic number
+ int4store(buf+4,0);
+ packet->append(buf, ROTATE_HEADER_LEN);
packet->append(p,ident_len);
- if(my_net_write(net, (char*)packet->ptr(), packet->length()))
- {
- *errmsg = "failed on my_net_write()";
- return -1;
- }
+ if (my_net_write(net, (char*)packet->ptr(), packet->length()))
+ {
+ *errmsg = "failed on my_net_write()";
+ return -1;
+ }
return 0;
}
-
static int send_file(THD *thd)
{
NET* net = &thd->net;
int fd = -1,bytes, error = 1;
char fname[FN_REFLEN+1];
- char *buf;
const char *errmsg = 0;
int old_timeout;
uint packet_len;
+ char buf[IO_SIZE]; // It's safe to alloc this
DBUG_ENTER("send_file");
// the client might be slow loading the data, give him wait_timeout to do
@@ -77,40 +100,32 @@ static int send_file(THD *thd)
old_timeout = thd->net.timeout;
thd->net.timeout = thd->inactive_timeout;
- // spare the stack
- if(!(buf = alloc_root(&thd->mem_root,IO_SIZE)))
- {
- errmsg = "Out of memory";
- goto err;
- }
-
// we need net_flush here because the client will not know it needs to send
// us the file name until it has processed the load event entry
if (net_flush(net) || (packet_len = my_net_read(net)) == packet_error)
{
- errmsg = "Failed reading file name";
+ errmsg = "while reading file name";
goto err;
}
- *((char*)net->read_pos + packet_len) = 0; // terminate with \0
- //for fn_format
- fn_format(fname, (char*)net->read_pos + 1, "", "", 4);
+ // terminate with \0 for fn_format
+ *((char*)net->read_pos + packet_len) = 0;
+ fn_format(fname, (char*) net->read_pos + 1, "", "", 4);
// this is needed to make replicate-ignore-db
if (!strcmp(fname,"/dev/null"))
goto end;
- if ((fd = my_open(fname, O_RDONLY, MYF(MY_WME))) < 0)
+ if ((fd = my_open(fname, O_RDONLY, MYF(0))) < 0)
{
- errmsg = "Failed on my_open()";
+ errmsg = "on open of file";
goto err;
}
- while ((bytes = (int) my_read(fd, (byte*) buf, IO_SIZE,
- MYF(MY_WME))) > 0)
+ while ((bytes = (int) my_read(fd, (byte*) buf, IO_SIZE, MYF(0))) > 0)
{
if (my_net_write(net, buf, bytes))
{
- errmsg = "Failed on my_net_write()";
+ errmsg = "while writing data to client";
goto err;
}
}
@@ -119,18 +134,18 @@ static int send_file(THD *thd)
if (my_net_write(net, "", 0) || net_flush(net) ||
(my_net_read(net) == packet_error))
{
- errmsg = "failed negotiating file transfer close";
+ errmsg = "while negotiating file transfer close";
goto err;
}
error = 0;
err:
thd->net.timeout = old_timeout;
- if(fd >= 0)
- (void) my_close(fd, MYF(MY_WME));
+ if (fd >= 0)
+ (void) my_close(fd, MYF(0));
if (errmsg)
{
- sql_print_error("failed in send_file() : %s", errmsg);
+ sql_print_error("Failed in send_file() %s", errmsg);
DBUG_PRINT("error", (errmsg));
}
DBUG_RETURN(error);
@@ -138,34 +153,27 @@ static int send_file(THD *thd)
File open_binlog(IO_CACHE *log, const char *log_file_name,
- const char **errmsg)
+ const char **errmsg)
{
File file;
- char magic[4];
+
if ((file = my_open(log_file_name, O_RDONLY | O_BINARY, MYF(MY_WME))) < 0 ||
init_io_cache(log, file, IO_SIZE*2, READ_CACHE, 0, 0,
- MYF(MY_WME)))
+ MYF(MY_WME | MY_DONT_CHECK_FILESIZE)))
{
- *errmsg = "Could not open log file"; // This will not be sent
+ *errmsg = "Could not open log file"; // This will not be sent
goto err;
}
-
- if (my_b_read(log, (byte*) magic, sizeof(magic)))
- {
- *errmsg = "I/O error reading binlog magic number";
- goto err;
- }
- if (memcmp(magic, BINLOG_MAGIC, 4))
- {
- *errmsg = "Binlog has bad magic number, fire your magician";
+ if (check_binlog_magic(log,errmsg))
goto err;
- }
return file;
err:
- if (file > 0)
+ if (file >= 0)
+ {
my_close(file,MYF(0));
- end_io_cache(log);
+ end_io_cache(log);
+ }
return -1;
}
@@ -173,26 +181,27 @@ err:
void adjust_linfo_offsets(my_off_t purge_offset)
{
THD *tmp;
-
+
pthread_mutex_lock(&LOCK_thread_count);
I_List_iterator<THD> it(threads);
-
- while((tmp=it++))
- {
- LOG_INFO* linfo;
- if((linfo = tmp->current_linfo))
- {
- pthread_mutex_lock(&linfo->lock);
- // no big deal if we just started reading the log
- // nothing to adjust
- if(linfo->index_file_offset < purge_offset)
- linfo->fatal = (linfo->index_file_offset != 0);
- else
- linfo->index_file_offset -= purge_offset;
- pthread_mutex_unlock(&linfo->lock);
- }
- }
+ while ((tmp=it++))
+ {
+ LOG_INFO* linfo;
+ if ((linfo = tmp->current_linfo))
+ {
+ pthread_mutex_lock(&linfo->lock);
+ /* index file offset can be less that purge offset
+ only if we just started reading the index file. In that case
+ we have nothing to adjust
+ */
+ if (linfo->index_file_offset < purge_offset)
+ linfo->fatal = (linfo->index_file_offset != 0);
+ else
+ linfo->index_file_offset -= purge_offset;
+ pthread_mutex_unlock(&linfo->lock);
+ }
+ }
pthread_mutex_unlock(&LOCK_thread_count);
}
@@ -202,21 +211,21 @@ bool log_in_use(const char* log_name)
int log_name_len = strlen(log_name) + 1;
THD *tmp;
bool result = 0;
-
+
pthread_mutex_lock(&LOCK_thread_count);
I_List_iterator<THD> it(threads);
-
- while((tmp=it++))
+
+ while ((tmp=it++))
+ {
+ LOG_INFO* linfo;
+ if ((linfo = tmp->current_linfo))
{
- LOG_INFO* linfo;
- if((linfo = tmp->current_linfo))
- {
- pthread_mutex_lock(&linfo->lock);
- result = !memcmp(log_name, linfo->log_file_name, log_name_len);
- pthread_mutex_unlock(&linfo->lock);
- if(result) break;
- }
- }
+ pthread_mutex_lock(&linfo->lock);
+ result = !memcmp(log_name, linfo->log_file_name, log_name_len);
+ pthread_mutex_unlock(&linfo->lock);
+ if (result) break;
+ }
+ }
pthread_mutex_unlock(&LOCK_thread_count);
return result;
@@ -226,35 +235,35 @@ bool log_in_use(const char* log_name)
int purge_master_logs(THD* thd, const char* to_log)
{
char search_file_name[FN_REFLEN];
+ const char* errmsg = 0;
+
mysql_bin_log.make_log_name(search_file_name, to_log);
int res = mysql_bin_log.purge_logs(thd, search_file_name);
- const char* errmsg = 0;
- switch(res)
- {
- case 0: break;
- case LOG_INFO_EOF: errmsg = "Target log not found in binlog index"; break;
- case LOG_INFO_IO: errmsg = "I/O error reading log index file"; break;
- case LOG_INFO_INVALID: errmsg = "Server configuration does not permit \
+
+ switch(res) {
+ case 0: break;
+ case LOG_INFO_EOF: errmsg = "Target log not found in binlog index"; break;
+ case LOG_INFO_IO: errmsg = "I/O error reading log index file"; break;
+ case LOG_INFO_INVALID: errmsg = "Server configuration does not permit \
binlog purge"; break;
- case LOG_INFO_SEEK: errmsg = "Failed on fseek()"; break;
- case LOG_INFO_PURGE_NO_ROTATE: errmsg = "Cannot purge unrotatable log";
- break;
- case LOG_INFO_MEM: errmsg = "Out of memory"; break;
- case LOG_INFO_FATAL: errmsg = "Fatal error during purge"; break;
- case LOG_INFO_IN_USE: errmsg = "A purgeable log is in use, will not purge";
- break;
- default:
- errmsg = "Unknown error during purge"; break;
- }
-
- if(errmsg)
- {
- send_error(&thd->net, 0, errmsg);
- return 1;
- }
+ case LOG_INFO_SEEK: errmsg = "Failed on fseek()"; break;
+ case LOG_INFO_PURGE_NO_ROTATE: errmsg = "Cannot purge unrotatable log";
+ break;
+ case LOG_INFO_MEM: errmsg = "Out of memory"; break;
+ case LOG_INFO_FATAL: errmsg = "Fatal error during purge"; break;
+ case LOG_INFO_IN_USE: errmsg = "A purgeable log is in use, will not purge";
+ break;
+ default: errmsg = "Unknown error during purge"; break;
+ }
+
+ if (errmsg)
+ {
+ send_error(&thd->net, 0, errmsg);
+ return 1;
+ }
else
send_ok(&thd->net);
-
+
return 0;
}
@@ -272,7 +281,7 @@ void mysql_binlog_send(THD* thd, char* log_ident, ulong pos, ushort flags)
NET* net = &thd->net;
#ifndef DBUG_OFF
int left_events = max_binlog_dump_events;
-#endif
+#endif
DBUG_ENTER("mysql_binlog_send");
bzero((char*) &log,sizeof(log));
@@ -282,25 +291,25 @@ void mysql_binlog_send(THD* thd, char* log_ident, ulong pos, ushort flags)
errmsg = "Master failed COM_BINLOG_DUMP to test if slave can recover";
goto err;
}
-#endif
+#endif
- if(!mysql_bin_log.is_open())
+ if (!mysql_bin_log.is_open())
{
errmsg = "Binary log is not open";
goto err;
}
- if(!server_id_supplied)
- {
- errmsg = "Misconfigured master - server id was not set";
- goto err;
- }
-
+ if (!server_id_supplied)
+ {
+ errmsg = "Misconfigured master - server id was not set";
+ goto err;
+ }
+
if (log_ident[0])
mysql_bin_log.make_log_name(search_file_name, log_ident);
else
search_file_name[0] = 0;
-
+
linfo.index_file_offset = 0;
thd->current_linfo = &linfo;
@@ -315,20 +324,21 @@ void mysql_binlog_send(THD* thd, char* log_ident, ulong pos, ushort flags)
if (pos < 4)
{
- errmsg = "Client requested master to start repliction from impossible position.\n";
+ errmsg = "Client requested master to start repliction from \
+impossible position";
goto err;
}
-
+
my_b_seek(&log, pos); // Seek will done on next read
packet->length(0);
- packet->append("\0", 1);
// we need to start a packet with something other than 255
// to distiquish it from error
+ packet->append("\0", 1);
- // tell the client log name with a fake rotate_event
// if we are at the start of the log
- if(pos == 4)
+ if (pos == 4)
{
+ // tell the client log name with a fake rotate_event
if (fake_rotate_event(net, packet, log_file_name, &errmsg))
goto err;
packet->length(0);
@@ -338,17 +348,17 @@ void mysql_binlog_send(THD* thd, char* log_ident, ulong pos, ushort flags)
while (!net->error && net->vio != 0 && !thd->killed)
{
pthread_mutex_t *log_lock = mysql_bin_log.get_log_lock();
-
+
while (!(error = Log_event::read_log_event(&log, packet, log_lock)))
{
#ifndef DBUG_OFF
- if(max_binlog_dump_events && !left_events--)
+ if (max_binlog_dump_events && !left_events--)
{
net_flush(net);
errmsg = "Debugging binlog dump abort";
goto err;
}
-#endif
+#endif
if (my_net_write(net, (char*)packet->ptr(), packet->length()) )
{
errmsg = "Failed on my_net_write()";
@@ -358,7 +368,7 @@ void mysql_binlog_send(THD* thd, char* log_ident, ulong pos, ushort flags)
(*packet)[LOG_EVENT_OFFSET+1] ));
if ((*packet)[LOG_EVENT_OFFSET+1] == LOAD_EVENT)
{
- if(send_file(thd))
+ if (send_file(thd))
{
errmsg = "failed in send_file()";
goto err;
@@ -367,15 +377,15 @@ void mysql_binlog_send(THD* thd, char* log_ident, ulong pos, ushort flags)
packet->length(0);
packet->append("\0",1);
}
-
+ // TODO: now that we are logging the offset, check to make sure
+ // the recorded offset and the actual match
if (error != LOG_READ_EOF)
{
- switch(error)
- {
- case LOG_READ_BOGUS:
+ switch(error) {
+ case LOG_READ_BOGUS:
errmsg = "bogus data in log event";
break;
- case LOG_READ_TOO_LARGE:
+ case LOG_READ_TOO_LARGE:
errmsg = "log event entry exceeded max_allowed_packet -\
increase max_allowed_packet on master";
break;
@@ -395,12 +405,12 @@ void mysql_binlog_send(THD* thd, char* log_ident, ulong pos, ushort flags)
goto err;
}
- if(!(flags & BINLOG_DUMP_NON_BLOCK) &&
+ if (!(flags & BINLOG_DUMP_NON_BLOCK) &&
mysql_bin_log.is_active(log_file_name))
+ {
// block until there is more data in the log
// unless non-blocking mode requested
- {
- if(net_flush(net))
+ if (net_flush(net))
{
errmsg = "failed on net_flush()";
goto err;
@@ -412,64 +422,56 @@ void mysql_binlog_send(THD* thd, char* log_ident, ulong pos, ushort flags)
// to signal us
{
log.error=0;
-
- // tell the kill thread how to wake us up
- thd->mysys_var->current_mutex = log_lock;
- thd->mysys_var->current_cond = &COND_binlog_update;
- const char* proc_info = thd->proc_info;
- thd->proc_info = "Slave connection: waiting for binlog update";
-
bool read_packet = 0, fatal_error = 0;
#ifndef DBUG_OFF
- if(max_binlog_dump_events && !left_events--)
+ if (max_binlog_dump_events && !left_events--)
{
net_flush(net);
errmsg = "Debugging binlog dump abort";
goto err;
}
-#endif
+#endif
// no one will update the log while we are reading
// now, but we'll be quick and just read one record
pthread_mutex_lock(log_lock);
- switch (Log_event::read_log_event(&log, packet, (pthread_mutex_t*) 0))
+ switch (Log_event::read_log_event(&log, packet, (pthread_mutex_t*)0))
{
case 0:
+ pthread_mutex_unlock(log_lock);
read_packet = 1;
// we read successfully, so we'll need to send it to the
// slave
break;
case LOG_READ_EOF:
- DBUG_PRINT("wait",("waiting for data on binary log"));
+ DBUG_PRINT("wait",("waiting for data in binary log"));
+ // wait_for_update unlocks the log lock - needed to avoid race
if (!thd->killed)
- pthread_cond_wait(&COND_binlog_update, log_lock);
+ mysql_bin_log.wait_for_update(thd);
+ else
+ pthread_mutex_unlock(log_lock);
+ DBUG_PRINT("wait",("binary log received update"));
break;
default:
+ pthread_mutex_unlock(log_lock);
fatal_error = 1;
break;
}
- pthread_mutex_unlock(log_lock);
-
- pthread_mutex_lock(&thd->mysys_var->mutex);
- thd->mysys_var->current_mutex= 0;
- thd->mysys_var->current_cond= 0;
- thd->proc_info= proc_info;
- pthread_mutex_unlock(&thd->mysys_var->mutex);
-
- if(read_packet)
+
+ if (read_packet)
{
thd->proc_info = "sending update to slave";
- if(my_net_write(net, (char*)packet->ptr(), packet->length()) )
+ if (my_net_write(net, (char*)packet->ptr(), packet->length()) )
{
errmsg = "Failed on my_net_write()";
goto err;
}
- if((*packet)[LOG_EVENT_OFFSET+1] == LOAD_EVENT)
+ if ((*packet)[LOG_EVENT_OFFSET+1] == LOAD_EVENT)
{
- if(send_file(thd))
+ if (send_file(thd))
{
errmsg = "failed in send_file()";
goto err;
@@ -481,7 +483,7 @@ void mysql_binlog_send(THD* thd, char* log_ident, ulong pos, ushort flags)
// we hit EOF pretty quick
}
- if(fatal_error)
+ if (fatal_error)
{
errmsg = "error reading log entry";
goto err;
@@ -494,8 +496,7 @@ void mysql_binlog_send(THD* thd, char* log_ident, ulong pos, ushort flags)
bool loop_breaker = 0;
// need this to break out of the for loop from switch
thd->proc_info = "switching to next log";
- switch(mysql_bin_log.find_next_log(&linfo))
- {
+ switch (mysql_bin_log.find_next_log(&linfo)) {
case LOG_INFO_EOF:
loop_breaker = (flags & BINLOG_DUMP_NON_BLOCK);
break;
@@ -506,12 +507,12 @@ void mysql_binlog_send(THD* thd, char* log_ident, ulong pos, ushort flags)
goto err;
}
- if(loop_breaker)
+ if (loop_breaker)
break;
end_io_cache(&log);
(void) my_close(file, MYF(MY_WME));
-
+
// fake Rotate_log event just in case it did not make it to the log
// otherwise the slave make get confused about the offset
if ((file=open_binlog(&log, log_file_name, &errmsg)) < 0 ||
@@ -525,13 +526,14 @@ void mysql_binlog_send(THD* thd, char* log_ident, ulong pos, ushort flags)
end_io_cache(&log);
(void)my_close(file, MYF(MY_WME));
-
+
send_eof(&thd->net);
thd->proc_info = "waiting to finalize termination";
pthread_mutex_lock(&LOCK_thread_count);
thd->current_linfo = 0;
pthread_mutex_unlock(&LOCK_thread_count);
DBUG_VOID_RETURN;
+
err:
thd->proc_info = "waiting to finalize termination";
end_io_cache(&log);
@@ -549,126 +551,110 @@ void mysql_binlog_send(THD* thd, char* log_ident, ulong pos, ushort flags)
DBUG_VOID_RETURN;
}
-int start_slave(THD* thd , bool net_report)
+int start_slave(THD* thd , MASTER_INFO* mi, bool net_report)
{
- if(!thd) thd = current_thd;
- NET* net = &thd->net;
int slave_errno = 0;
+ if (!thd) thd = current_thd;
+ NET* net = &thd->net;
+ int thread_mask;
+
if (check_access(thd, PROCESS_ACL, any_db))
return 1;
- pthread_mutex_lock(&LOCK_slave);
- if(!slave_running)
- {
- if(init_master_info(&glob_mi))
- slave_errno = ER_MASTER_INFO;
- else if(server_id_supplied && *glob_mi.host)
- {
- pthread_t hThread;
- if(pthread_create(&hThread, &connection_attrib, handle_slave, 0))
- {
- slave_errno = ER_SLAVE_THREAD;
- }
- while(!slave_running) // slave might already be running by now
- pthread_cond_wait(&COND_slave_start, &LOCK_slave);
- }
- else
- slave_errno = ER_BAD_SLAVE;
- }
+ lock_slave_threads(mi); // this allows us to cleanly read slave_running
+ init_thread_mask(&thread_mask,mi,1 /* inverse */);
+ if (thread_mask)
+ {
+ if (server_id_supplied && (!mi->inited || (mi->inited && *mi->host)))
+ slave_errno = start_slave_threads(0 /*no mutex */,
+ 1 /* wait for start */,
+ mi,
+ master_info_file,relay_log_info_file,
+ thread_mask);
+ else
+ slave_errno = ER_BAD_SLAVE;
+ }
else
slave_errno = ER_SLAVE_MUST_STOP;
-
- pthread_mutex_unlock(&LOCK_slave);
- if(slave_errno)
- {
- if(net_report) send_error(net, slave_errno);
- return 1;
- }
- else if(net_report)
+
+ unlock_slave_threads(mi);
+
+ if (slave_errno)
+ {
+ if (net_report)
+ send_error(net, slave_errno);
+ return 1;
+ }
+ else if (net_report)
send_ok(net);
return 0;
}
-int stop_slave(THD* thd, bool net_report )
+int stop_slave(THD* thd, MASTER_INFO* mi, bool net_report )
{
- if(!thd) thd = current_thd;
- NET* net = &thd->net;
int slave_errno = 0;
-
+ if (!thd) thd = current_thd;
+ NET* net = &thd->net;
+
if (check_access(thd, PROCESS_ACL, any_db))
return 1;
+ thd->proc_info = "Killing slave";
+ int thread_mask;
+ lock_slave_threads(mi);
+ init_thread_mask(&thread_mask,mi,0 /* not inverse*/);
+ slave_errno = (thread_mask) ?
+ terminate_slave_threads(mi,thread_mask,
+ 1 /*skip lock */) : ER_SLAVE_NOT_RUNNING;
+ unlock_slave_threads(mi);
+ thd->proc_info = 0;
- pthread_mutex_lock(&LOCK_slave);
- if (slave_running)
+ if (slave_errno)
{
- abort_slave = 1;
- KICK_SLAVE;
- // do not abort the slave in the middle of a query, so we do not set
- // thd->killed for the slave thread
- thd->proc_info = "waiting for slave to die";
- while(slave_running)
- {
- /* there is a small chance that slave thread might miss the first
- alarm. To protect againts it, resend the signal until it reacts
- */
-
- struct timespec abstime;
-#ifdef HAVE_TIMESPEC_TS_SEC
- abstime.ts_sec=time(NULL)+2;
- abstime.ts_nsec=0;
-#elif defined(__WIN__)
- abstime.tv_sec=time((time_t*) 0)+2;
- abstime.tv_nsec=0;
-#else
- struct timeval tv;
- gettimeofday(&tv,0);
- abstime.tv_sec=tv.tv_sec+2;
- abstime.tv_nsec=tv.tv_usec*1000;
-#endif
- pthread_cond_timedwait(&COND_slave_stopped, &LOCK_slave, &abstime);
- if (slave_running)
- KICK_SLAVE;
- }
+ if (net_report)
+ send_error(net, slave_errno);
+ return 1;
}
- else
- slave_errno = ER_SLAVE_NOT_RUNNING;
-
- pthread_mutex_unlock(&LOCK_slave);
- thd->proc_info = 0;
-
- if(slave_errno)
- {
- if(net_report) send_error(net, slave_errno);
- return 1;
- }
- else if(net_report)
+ else if (net_report)
send_ok(net);
return 0;
}
-void reset_slave()
+int reset_slave(MASTER_INFO* mi)
{
MY_STAT stat_area;
char fname[FN_REFLEN];
- bool slave_was_running ;
-
- pthread_mutex_lock(&LOCK_slave);
- if((slave_was_running = slave_running))
- {
- pthread_mutex_unlock(&LOCK_slave);
- stop_slave(0,0);
- }
- else
- pthread_mutex_unlock(&LOCK_slave);
+ int restart_thread_mask = 0,error=0;
+ const char* errmsg=0;
- end_master_info(&glob_mi);
- fn_format(fname, master_info_file, mysql_data_home, "", 4+16+32);
- if(my_stat(fname, &stat_area, MYF(0)))
- if(my_delete(fname, MYF(MY_WME)))
- return;
- if(slave_was_running)
- start_slave(0,0);
+ lock_slave_threads(mi);
+ init_thread_mask(&restart_thread_mask,mi,0 /* not inverse */);
+ if ((error=terminate_slave_threads(mi,restart_thread_mask,1 /*skip lock*/))
+ || (error=purge_relay_logs(&mi->rli,1 /*just reset*/,&errmsg)))
+ goto err;
+
+ end_master_info(mi);
+ fn_format(fname, master_info_file, mysql_data_home, "", 4+32);
+ if (my_stat(fname, &stat_area, MYF(0)) && my_delete(fname, MYF(MY_WME)))
+ {
+ error=1;
+ goto err;
+ }
+ fn_format(fname, relay_log_info_file, mysql_data_home, "", 4+32);
+ if (my_stat(fname, &stat_area, MYF(0)) && my_delete(fname, MYF(MY_WME)))
+ {
+ error=1;
+ goto err;
+ }
+ if (restart_thread_mask)
+ error=start_slave_threads(0 /* mutex not needed*/,
+ 1 /* wait for start*/,
+ mi,master_info_file,relay_log_info_file,
+ restart_thread_mask);
+ // TODO: fix error messages so they get to the client
+err:
+ unlock_slave_threads(mi);
+ return error;
}
void kill_zombie_dump_threads(uint32 slave_server_id)
@@ -677,121 +663,234 @@ void kill_zombie_dump_threads(uint32 slave_server_id)
I_List_iterator<THD> it(threads);
THD *tmp;
- while((tmp=it++))
+ while ((tmp=it++))
+ {
+ if (tmp->command == COM_BINLOG_DUMP &&
+ tmp->server_id == slave_server_id)
{
- if(tmp->command == COM_BINLOG_DUMP &&
- tmp->server_id == slave_server_id)
- {
- // here we do not call kill_one_thread()
- // it will be slow because it will iterate through the list
- // again. Plus it double-locks LOCK_thread_count, which
- // make safe_mutex complain and abort
- // so we just to our own thread murder
-
- thr_alarm_kill(tmp->real_id);
- tmp->killed = 1;
- tmp->mysys_var->abort = 1;
- pthread_mutex_lock(&tmp->mysys_var->mutex);
- if(tmp->mysys_var->current_cond)
- {
- pthread_mutex_lock(tmp->mysys_var->current_mutex);
- pthread_cond_broadcast(tmp->mysys_var->current_cond);
- pthread_mutex_unlock(tmp->mysys_var->current_mutex);
- }
- pthread_mutex_unlock(&tmp->mysys_var->mutex);
- }
- }
-
+ /*
+ Here we do not call kill_one_thread() as
+ it will be slow because it will iterate through the list
+ again. Plus it double-locks LOCK_tread_count, which
+ make safe_mutex complain and abort.
+ We just to do kill the thread ourselves.
+ */
+ tmp->awake(1/*prepare to die*/);
+ }
+ }
pthread_mutex_unlock(&LOCK_thread_count);
}
-int change_master(THD* thd)
+
+int change_master(THD* thd, MASTER_INFO* mi)
{
- bool slave_was_running;
+ int error=0,restart_thread_mask;
+ const char* errmsg=0;
+
// kill slave thread
- pthread_mutex_lock(&LOCK_slave);
- if((slave_was_running = slave_running))
- {
- abort_slave = 1;
- KICK_SLAVE;
- thd->proc_info = "waiting for slave to die";
- while(slave_running)
- pthread_cond_wait(&COND_slave_stopped, &LOCK_slave); // wait until done
- }
- pthread_mutex_unlock(&LOCK_slave);
+ lock_slave_threads(mi);
+ init_thread_mask(&restart_thread_mask,mi,0 /*not inverse*/);
+ if (restart_thread_mask &&
+ (error=terminate_slave_threads(mi,
+ restart_thread_mask,
+ 1 /*skip lock*/)))
+ {
+ send_error(&thd->net,error);
+ unlock_slave_threads(mi);
+ return 1;
+ }
thd->proc_info = "changing master";
LEX_MASTER_INFO* lex_mi = &thd->lex.mi;
+ // TODO: see if needs re-write
+ if (init_master_info(mi,master_info_file,relay_log_info_file))
+ {
+ send_error(&thd->net, 0, "Could not initialize master info");
+ unlock_slave_threads(mi);
+ return 1;
+ }
- if(init_master_info(&glob_mi))
- {
- send_error(&thd->net, 0, "Could not initialize master info");
- return 1;
- }
-
- pthread_mutex_lock(&glob_mi.lock);
- if((lex_mi->host || lex_mi->port) && !lex_mi->log_file_name && !lex_mi->pos)
- {
- // if we change host or port, we must reset the postion
- glob_mi.log_file_name[0] = 0;
- glob_mi.pos = 4; // skip magic number
- glob_mi.pending = 0;
- }
+ pthread_mutex_lock(&mi->data_lock);
+ if ((lex_mi->host || lex_mi->port) && !lex_mi->log_file_name && !lex_mi->pos)
+ {
+ // if we change host or port, we must reset the postion
+ mi->master_log_name[0] = 0;
+ mi->master_log_pos = 4; // skip magic number
+ mi->rli.pending = 0;
+ }
- if(lex_mi->log_file_name)
- strmake(glob_mi.log_file_name, lex_mi->log_file_name,
- sizeof(glob_mi.log_file_name));
- if(lex_mi->pos)
+ if (lex_mi->log_file_name)
+ strmake(mi->master_log_name, lex_mi->log_file_name,
+ sizeof(mi->master_log_name));
+ if (lex_mi->pos)
{
- glob_mi.pos = lex_mi->pos;
- glob_mi.pending = 0;
+ mi->master_log_pos = lex_mi->pos;
+ mi->rli.pending = 0;
}
-
- if(lex_mi->host)
- {
- strmake(glob_mi.host, lex_mi->host, sizeof(glob_mi.host));
- }
- if(lex_mi->user)
- strmake(glob_mi.user, lex_mi->user, sizeof(glob_mi.user));
- if(lex_mi->password)
- strmake(glob_mi.password, lex_mi->password, sizeof(glob_mi.password));
- if(lex_mi->port)
- glob_mi.port = lex_mi->port;
- if(lex_mi->connect_retry)
- glob_mi.connect_retry = lex_mi->connect_retry;
-
- flush_master_info(&glob_mi);
- pthread_mutex_unlock(&glob_mi.lock);
+
+ if (lex_mi->host)
+ strmake(mi->host, lex_mi->host, sizeof(mi->host));
+ if (lex_mi->user)
+ strmake(mi->user, lex_mi->user, sizeof(mi->user));
+ if (lex_mi->password)
+ strmake(mi->password, lex_mi->password, sizeof(mi->password));
+ if (lex_mi->port)
+ mi->port = lex_mi->port;
+ if (lex_mi->connect_retry)
+ mi->connect_retry = lex_mi->connect_retry;
+
+ flush_master_info(mi);
+ pthread_mutex_unlock(&mi->data_lock);
+ thd->proc_info="purging old relay logs";
+ if (purge_relay_logs(&mi->rli,0 /* not only reset, but also reinit*/,
+ &errmsg))
+ {
+ send_error(&thd->net, 0, "Failed purging old relay logs");
+ unlock_slave_threads(mi);
+ return 1;
+ }
+ pthread_mutex_lock(&mi->rli.data_lock);
+ mi->rli.master_log_pos = mi->master_log_pos;
+ strnmov(mi->rli.master_log_name,mi->master_log_name,
+ sizeof(mi->rli.master_log_name));
+ if (!mi->rli.master_log_name[0]) // uninitialized case
+ mi->rli.master_log_pos=0;
+ pthread_cond_broadcast(&mi->rli.data_cond);
+ pthread_mutex_unlock(&mi->rli.data_lock);
+
thd->proc_info = "starting slave";
- if(slave_was_running)
- start_slave(0,0);
+ if (restart_thread_mask)
+ error=start_slave_threads(0 /* mutex not needed*/,
+ 1 /* wait for start*/,
+ mi,master_info_file,relay_log_info_file,
+ restart_thread_mask);
+ unlock_slave_threads(mi);
thd->proc_info = 0;
-
- send_ok(&thd->net);
+ if (error)
+ send_error(&thd->net,error);
+ else
+ send_ok(&thd->net);
return 0;
}
-void reset_master()
+int reset_master(THD* thd)
{
- if(!mysql_bin_log.is_open())
+ if (!mysql_bin_log.is_open())
{
my_error(ER_FLUSH_MASTER_BINLOG_CLOSED, MYF(ME_BELL+ME_WAITTANG));
- return;
+ return 1;
}
+ return mysql_bin_log.reset_logs(thd);
+}
- LOG_INFO linfo;
- if (mysql_bin_log.find_first_log(&linfo, ""))
- return;
+int cmp_master_pos(const char* log_file_name1, ulonglong log_pos1,
+ const char* log_file_name2, ulonglong log_pos2)
+{
+ int res;
+ if ((res = strcmp(log_file_name1, log_file_name2)))
+ return res;
+ if (log_pos1 > log_pos2)
+ return 1;
+ else if (log_pos1 == log_pos2)
+ return 0;
+ return -1;
+}
- for(;;)
+int show_binlog_events(THD* thd)
+{
+ DBUG_ENTER("show_binlog_events");
+ List<Item> field_list;
+ const char* errmsg = 0;
+ IO_CACHE log;
+ File file = -1;
+
+ Log_event::init_show_field_list(&field_list);
+ if (send_fields(thd, field_list, 1))
+ DBUG_RETURN(-1);
+
+ if (mysql_bin_log.is_open())
+ {
+ LOG_INFO linfo;
+ char search_file_name[FN_REFLEN];
+ LEX_MASTER_INFO* lex_mi = &thd->lex.mi;
+ uint event_count, limit_start, limit_end;
+ const char* log_file_name = lex_mi->log_file_name;
+ Log_event* ev;
+ my_off_t pos = lex_mi->pos;
+
+ limit_start = thd->lex.select->offset_limit;
+ limit_end = thd->lex.select->select_limit + limit_start;
+
+ if (log_file_name)
+ mysql_bin_log.make_log_name(search_file_name, log_file_name);
+ else
+ search_file_name[0] = 0;
+
+ linfo.index_file_offset = 0;
+ thd->current_linfo = &linfo;
+
+ if (mysql_bin_log.find_first_log(&linfo, search_file_name))
+ {
+ errmsg = "Could not find target log";
+ goto err;
+ }
+
+ if ((file=open_binlog(&log, linfo.log_file_name, &errmsg)) < 0)
+ goto err;
+
+ if (pos < 4)
+ {
+ errmsg = "Invalid log position";
+ goto err;
+ }
+
+ pthread_mutex_lock(mysql_bin_log.get_log_lock());
+ my_b_seek(&log, pos);
+
+ for (event_count = 0;
+ (ev = Log_event::read_log_event(&log,(pthread_mutex_t*)0,0)); )
+ {
+ if (event_count >= limit_start &&
+ ev->net_send(thd, linfo.log_file_name, pos))
+ {
+ errmsg = "Net error";
+ delete ev;
+ pthread_mutex_unlock(mysql_bin_log.get_log_lock());
+ goto err;
+ }
+
+ pos = my_b_tell(&log);
+ delete ev;
+
+ if (++event_count >= limit_end)
+ break;
+ }
+
+ if (event_count < limit_end && log.error)
+ {
+ errmsg = "Wrong offset or I/O error";
+ pthread_mutex_unlock(mysql_bin_log.get_log_lock());
+ goto err;
+ }
+
+ pthread_mutex_unlock(mysql_bin_log.get_log_lock());
+ }
+
+err:
+ if (file >= 0)
{
- my_delete(linfo.log_file_name, MYF(MY_WME));
- if (mysql_bin_log.find_next_log(&linfo))
- break;
+ end_io_cache(&log);
+ (void) my_close(file, MYF(MY_WME));
}
- mysql_bin_log.close(1); // exiting close
- my_delete(mysql_bin_log.get_index_fname(), MYF(MY_WME));
- mysql_bin_log.open(opt_bin_logname,LOG_BIN);
+ if (errmsg)
+ {
+ net_printf(&thd->net, ER_ERROR_WHEN_EXECUTING_COMMAND,
+ "SHOW BINLOG EVENTS", errmsg);
+ DBUG_RETURN(1);
+ }
+
+ send_eof(&thd->net);
+ DBUG_RETURN(0);
}
int show_binlog_info(THD* thd)
@@ -803,36 +902,37 @@ int show_binlog_info(THD* thd)
field_list.push_back(new Item_empty_string("Binlog_do_db",20));
field_list.push_back(new Item_empty_string("Binlog_ignore_db",20));
- if(send_fields(thd, field_list, 1))
+ if (send_fields(thd, field_list, 1))
DBUG_RETURN(-1);
String* packet = &thd->packet;
packet->length(0);
- if(mysql_bin_log.is_open())
- {
- LOG_INFO li;
- mysql_bin_log.get_current_log(&li);
- int dir_len = dirname_length(li.log_file_name);
- net_store_data(packet, li.log_file_name + dir_len);
- net_store_data(packet, (longlong)li.pos);
- net_store_data(packet, &binlog_do_db);
- net_store_data(packet, &binlog_ignore_db);
- }
+ if (mysql_bin_log.is_open())
+ {
+ LOG_INFO li;
+ mysql_bin_log.get_current_log(&li);
+ int dir_len = dirname_length(li.log_file_name);
+ net_store_data(packet, li.log_file_name + dir_len);
+ net_store_data(packet, (longlong)li.pos);
+ net_store_data(packet, &binlog_do_db);
+ net_store_data(packet, &binlog_ignore_db);
+ }
else
- {
- net_store_null(packet);
- net_store_null(packet);
- net_store_null(packet);
- net_store_null(packet);
- }
+ {
+ net_store_null(packet);
+ net_store_null(packet);
+ net_store_null(packet);
+ net_store_null(packet);
+ }
- if(my_net_write(&thd->net, (char*)thd->packet.ptr(), packet->length()))
+ if (my_net_write(&thd->net, (char*)thd->packet.ptr(), packet->length()))
DBUG_RETURN(-1);
send_eof(&thd->net);
DBUG_RETURN(0);
}
+
int show_binlogs(THD* thd)
{
const char* errmsg = 0;
@@ -843,20 +943,20 @@ int show_binlogs(THD* thd)
String* packet = &thd->packet;
IO_CACHE io_cache;
uint length;
-
- if(!mysql_bin_log.is_open())
+
+ if (!mysql_bin_log.is_open())
{
errmsg = "binlog is not open";
goto err;
}
field_list.push_back(new Item_empty_string("Log_name", 128));
- if(send_fields(thd, field_list, 1))
+ if (send_fields(thd, field_list, 1))
{
sql_print_error("Failed in send_fields");
return 1;
}
-
+
mysql_bin_log.lock_index();
index_file = mysql_bin_log.get_index_file();
if (index_file < 0)
@@ -876,7 +976,7 @@ int show_binlogs(THD* thd)
int dir_len = dirname_length(fname);
packet->length(0);
net_store_data(packet, fname + dir_len, length-dir_len);
- if(my_net_write(net, (char*) packet->ptr(), packet->length()))
+ if (my_net_write(net, (char*) packet->ptr(), packet->length()))
{
sql_print_error("Failed in my_net_write");
end_io_cache(&io_cache);
@@ -884,10 +984,10 @@ int show_binlogs(THD* thd)
return 1;
}
}
-
+
mysql_bin_log.unlock_index();
end_io_cache(&io_cache);
- send_eof(net);
+ send_eof(net);
return 0;
err2:
@@ -898,5 +998,34 @@ err:
return 1;
}
-
-
+int log_loaded_block(IO_CACHE* file)
+{
+ LOAD_FILE_INFO* lf_info;
+ uint block_len ;
+
+ /* file->request_pos contains position where we started last read */
+ char* buffer = (char*) file->request_pos;
+ if (!(block_len = (char*) file->read_end - (char*) buffer))
+ return 0;
+ lf_info = (LOAD_FILE_INFO*) file->arg;
+ if (lf_info->last_pos_in_file != HA_POS_ERROR &&
+ lf_info->last_pos_in_file >= file->pos_in_file)
+ return 0;
+ lf_info->last_pos_in_file = file->pos_in_file;
+ if (lf_info->wrote_create_file)
+ {
+ Append_block_log_event a(lf_info->thd, buffer, block_len);
+ mysql_bin_log.write(&a);
+ }
+ else
+ {
+ Create_file_log_event c(lf_info->thd,lf_info->ex,lf_info->db,
+ lf_info->table_name, *lf_info->fields,
+ lf_info->handle_dup, buffer,
+ block_len);
+ mysql_bin_log.write(&c);
+ lf_info->wrote_create_file = 1;
+ DBUG_SYNC_POINT("debug_lock.created_file_event",10);
+ }
+ return 0;
+}
diff --git a/sql/sql_repl.h b/sql/sql_repl.h
index aa07d859aec..360fd50a1e3 100644
--- a/sql/sql_repl.h
+++ b/sql/sql_repl.h
@@ -3,6 +3,18 @@
#include "slave.h"
+typedef struct st_slave_info
+{
+ uint32 server_id;
+ uint32 rpl_recovery_rank, master_id;
+ char host[HOSTNAME_LENGTH+1];
+ char user[USERNAME_LENGTH+1];
+ char password[HASH_PASSWORD_LENGTH+1];
+ uint16 port;
+ THD* thd;
+} SLAVE_INFO;
+
+extern bool opt_show_slave_auth_info, opt_old_rpl_compat;
extern char* master_host;
extern my_string opt_bin_logname, master_info_file;
extern uint32 server_id;
@@ -14,26 +26,40 @@ extern int max_binlog_dump_events;
extern bool opt_sporadic_binlog_dump_fail;
#endif
-#ifdef SIGNAL_WITH_VIO_CLOSE
-#define KICK_SLAVE { slave_thd->close_active_vio(); \
- thr_alarm_kill(slave_real_id); }
-#else
-#define KICK_SLAVE thr_alarm_kill(slave_real_id);
-#endif
+#define KICK_SLAVE(thd) thd->awake(0 /* do not prepare to die*/);
File open_binlog(IO_CACHE *log, const char *log_file_name,
const char **errmsg);
-int start_slave(THD* thd = 0, bool net_report = 1);
-int stop_slave(THD* thd = 0, bool net_report = 1);
-int change_master(THD* thd);
-void reset_slave();
-void reset_master();
+int start_slave(THD* thd, MASTER_INFO* mi, bool net_report);
+int stop_slave(THD* thd, MASTER_INFO* mi, bool net_report);
+int change_master(THD* thd, MASTER_INFO* mi);
+int show_binlog_events(THD* thd);
+int cmp_master_pos(const char* log_file_name1, ulonglong log_pos1,
+ const char* log_file_name2, ulonglong log_pos2);
+int reset_slave(MASTER_INFO* mi);
+int reset_master(THD* thd);
int purge_master_logs(THD* thd, const char* to_log);
bool log_in_use(const char* log_name);
void adjust_linfo_offsets(my_off_t purge_offset);
int show_binlogs(THD* thd);
extern int init_master_info(MASTER_INFO* mi);
void kill_zombie_dump_threads(uint32 slave_server_id);
+int check_binlog_magic(IO_CACHE* log, const char** errmsg);
+
+typedef struct st_load_file_info
+{
+ THD* thd;
+ sql_exchange* ex;
+ List <Item> *fields;
+ enum enum_duplicates handle_dup;
+ char* db;
+ char* table_name;
+ bool wrote_create_file;
+ my_off_t last_pos_in_file;
+} LOAD_FILE_INFO;
+
+int log_loaded_block(IO_CACHE* file);
#endif
+
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 1ee0d84e182..69cac90e2be 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -41,13 +41,16 @@ static bool update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,
uint tables,COND *conds,table_map table_map);
static int sort_keyuse(KEYUSE *a,KEYUSE *b);
static void set_position(JOIN *join,uint index,JOIN_TAB *table,KEYUSE *key);
+static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, KEYUSE *org_keyuse,
+ table_map used_tables);
static void find_best_combination(JOIN *join,table_map rest_tables);
static void find_best(JOIN *join,table_map rest_tables,uint index,
double record_count,double read_time);
static uint cache_record_length(JOIN *join,uint index);
static double prev_record_reads(JOIN *join,table_map found_ref);
static bool get_best_combination(JOIN *join);
-static store_key *get_store_key(KEYUSE *keyuse, table_map used_tables,
+static store_key *get_store_key(THD *thd,
+ KEYUSE *keyuse, table_map used_tables,
KEY_PART_INFO *key_part, char *key_buff,
uint maybe_null);
static bool make_simple_join(JOIN *join,TABLE *tmp_table);
@@ -68,7 +71,7 @@ static COND *remove_eq_conds(COND *cond,Item::cond_result *cond_value);
static bool const_expression_in_where(COND *conds,Item *item, Item **comp_item);
static bool open_tmp_table(TABLE *table);
static bool create_myisam_tmp_table(TABLE *table,TMP_TABLE_PARAM *param,
- uint options);
+ ulong options);
static int do_select(JOIN *join,List<Item> *fields,TABLE *tmp_table,
Procedure *proc);
static int sub_select_cache(JOIN *join,JOIN_TAB *join_tab,bool end_of_records);
@@ -83,20 +86,23 @@ static int end_unique_update(JOIN *join,JOIN_TAB *join_tab,
static int end_write_group(JOIN *join, JOIN_TAB *join_tab,
bool end_of_records);
static int test_if_group_changed(List<Item_buff> &list);
-static int join_read_const_tables(JOIN *join);
+static int join_read_const_table(JOIN_TAB *tab, POSITION *pos);
static int join_read_system(JOIN_TAB *tab);
static int join_read_const(JOIN_TAB *tab);
static int join_read_key(JOIN_TAB *tab);
static int join_read_always_key(JOIN_TAB *tab);
+static int join_read_last_key(JOIN_TAB *tab);
static int join_no_more_records(READ_RECORD *info);
static int join_read_next(READ_RECORD *info);
static int join_init_quick_read_record(JOIN_TAB *tab);
static int test_if_quick_select(JOIN_TAB *tab);
static int join_init_read_record(JOIN_TAB *tab);
-static int join_init_read_first_with_key(JOIN_TAB *tab);
-static int join_init_read_next_with_key(READ_RECORD *info);
-static int join_init_read_last_with_key(JOIN_TAB *tab);
-static int join_init_read_prev_with_key(READ_RECORD *info);
+static int join_read_first(JOIN_TAB *tab);
+static int join_read_next(READ_RECORD *info);
+static int join_read_next_same(READ_RECORD *info);
+static int join_read_last(JOIN_TAB *tab);
+static int join_read_prev_same(READ_RECORD *info);
+static int join_read_prev(READ_RECORD *info);
static int join_ft_read_first(JOIN_TAB *tab);
static int join_ft_read_next(READ_RECORD *info);
static COND *make_cond_for_table(COND *cond,table_map table,
@@ -104,9 +110,8 @@ static COND *make_cond_for_table(COND *cond,table_map table,
static Item* part_of_refkey(TABLE *form,Field *field);
static uint find_shortest_key(TABLE *table, key_map usable_keys);
static bool test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,
- ha_rows select_limit);
+ ha_rows select_limit, bool no_changes);
static int create_sort_index(JOIN_TAB *tab,ORDER *order,ha_rows select_limit);
-static bool fix_having(JOIN *join, Item **having);
static int remove_duplicates(JOIN *join,TABLE *entry,List<Item> &fields,
Item *having);
static int remove_dup_with_compare(THD *thd, TABLE *entry, Field **field,
@@ -142,20 +147,47 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
bool distinct);
static void describe_info(THD *thd, const char *info);
+/*
+ This handles SELECT with and without UNION
+*/
+
+int handle_select(THD *thd, LEX *lex, select_result *result)
+{
+ int res;
+ register SELECT_LEX *select_lex = &lex->select_lex;
+ if (select_lex->next)
+ res=mysql_union(thd,lex,result);
+ else
+ res=mysql_select(thd,(TABLE_LIST*) select_lex->table_list.first,
+ select_lex->item_list,
+ select_lex->where,
+ (ORDER*) select_lex->order_list.first,
+ (ORDER*) select_lex->group_list.first,
+ select_lex->having,
+ (ORDER*) lex->proc_list.first,
+ select_lex->options | thd->options,
+ result);
+ if (res && result)
+ result->abort();
+ delete result;
+ return res;
+}
+
+
/*****************************************************************************
** check fields, find best join, do the select and output fields.
-** mysql_select assumes that all tables are allready opened
+** mysql_select assumes that all tables are already opened
*****************************************************************************/
int
mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
ORDER *order, ORDER *group,Item *having,ORDER *proc_param,
- uint select_options,select_result *result)
+ ulong select_options,select_result *result)
{
TABLE *tmp_table;
- int error,tmp;
+ int error, tmp_error;
bool need_tmp,hidden_group_fields;
- bool simple_order,simple_group,no_order;
+ bool simple_order,simple_group,no_order, skip_sort_order;
Item::cond_result cond_value;
SQL_SELECT *select;
DYNAMIC_ARRAY keyuse;
@@ -170,13 +202,13 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
select_distinct=test(select_options & SELECT_DISTINCT);
tmp_table=0;
select=0;
- no_order=0;
+ no_order=skip_sort_order=0;
bzero((char*) &keyuse,sizeof(keyuse));
thd->proc_info="init";
thd->used_tables=0; // Updated by setup_fields
if (setup_tables(tables) ||
- setup_fields(thd,tables,fields,1,&all_fields) ||
+ setup_fields(thd,tables,fields,1,&all_fields,1) ||
setup_conds(thd,tables,&conds) ||
setup_order(thd,tables,fields,all_fields,order) ||
setup_group(thd,tables,fields,all_fields,group,&hidden_group_fields))
@@ -205,7 +237,7 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
if (!group)
{
uint flag=0;
- List_iterator<Item> it(fields);
+ List_iterator_fast<Item> it(fields);
Item *item;
while ((item= it++))
{
@@ -274,12 +306,15 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
count_field_types(&join.tmp_table_param,all_fields,0);
join.const_tables=0;
join.having=0;
+ join.do_send_rows = 1;
join.group= group != 0;
+ join.row_limit= ((select_distinct || order || group) ? HA_POS_ERROR :
+ thd->select_limit);
#ifdef RESTRICTED_GROUP
if (join.sum_func_count && !group && (join.func_count || join.field_count))
{
- my_message(ER_WRONG_SUM_SELECT,ER(ER_WRONG_SUM_SELECT));
+ my_message(ER_WRONG_SUM_SELECT,ER(ER_WRONG_SUM_SELECT),MYF(0));
delete procedure;
DBUG_RETURN(-1);
}
@@ -356,7 +391,7 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
result->send_fields(fields,1);
if (!having || having->val_int())
{
- if (result->send_data(fields))
+ if (join.do_send_rows && result->send_data(fields))
{
result->send_error(0,NullS); /* purecov: inspected */
error=1;
@@ -368,7 +403,7 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
error=(int) result->send_eof();
}
delete procedure;
- DBUG_RETURN(0);
+ DBUG_RETURN(error);
}
error = -1;
@@ -376,13 +411,12 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
/* Calculate how to do the join */
thd->proc_info="statistics";
- if (make_join_statistics(&join,tables,conds,&keyuse) ||
- thd->fatal_error)
+ if (make_join_statistics(&join,tables,conds,&keyuse) || thd->fatal_error)
goto err;
thd->proc_info="preparing";
- if ((tmp=join_read_const_tables(&join)) > 0)
- goto err;
- if (tmp && !(select_options & SELECT_DESCRIBE))
+ result->initialize_tables(&join);
+ if (join.const_table_map != join.found_const_table_map &&
+ !(select_options & SELECT_DESCRIBE))
{
error=return_zero_rows(result,tables,fields,
join.tmp_table_param.sum_func_count != 0 &&
@@ -397,7 +431,8 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
error= 1; /* purecov: inspected */
goto err; /* purecov: inspected */
}
- if (join.const_tables && !thd->locked_tables)
+ if (join.const_tables && !thd->locked_tables &&
+ !(select_options & SELECT_NO_UNLOCK))
{
TABLE **table, **end;
for (table=join.table, end=table + join.const_tables ;
@@ -446,7 +481,12 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
select_distinct=0;
}
else if (select_distinct && join.tables - join.const_tables == 1 &&
- (order || thd->select_limit == HA_POS_ERROR))
+ (thd->select_limit == HA_POS_ERROR ||
+ (join.select_options & OPTION_FOUND_ROWS) ||
+ order &&
+ !(skip_sort_order=
+ test_if_skip_sort_order(&join.join_tab[join.const_tables],
+ order, thd->select_limit,1))))
{
if ((group=create_distinct_group(order,fields)))
{
@@ -477,7 +517,7 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
(!group && join.tmp_table_param.sum_func_count))
order=0;
- // Can't use sort on head table if using cache
+ // Can't use sort on head table if using row cache
if (join.full_join)
{
if (group)
@@ -491,8 +531,11 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
(group && order) ||
test(select_options & OPTION_BUFFER_RESULT)));
- make_join_readinfo(&join, (select_options & SELECT_DESCRIBE) |
- (thd->lex.ftfunc_list.elements ? 0 : SELECT_USE_CACHE)); // No cache for MATCH
+ // No cache for MATCH
+ make_join_readinfo(&join,
+ (select_options & (SELECT_DESCRIBE |
+ SELECT_NO_JOIN_CACHE)) |
+ (thd->lex.select_lex.ftfunc_list.elements ? SELECT_NO_JOIN_CACHE : 0));
/* Need to tell Innobase that to play it safe, it should fetch all
columns of the tables: this is because MySQL
@@ -506,7 +549,7 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
for (uint i_h = join.const_tables; i_h < join.tables; i_h++)
{
TABLE* table_h = join.join_tab[i_h].table;
- if (table_h->db_type == DB_TYPE_INNOBASE)
+ if (table_h->db_type == DB_TYPE_INNODB)
table_h->file->extra(HA_EXTRA_DONT_USE_CURSOR_TO_UPDATE);
}
}
@@ -531,7 +574,7 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
((group && join.const_tables != join.tables &&
(!simple_group ||
!test_if_skip_sort_order(&join.join_tab[join.const_tables], group,
- HA_POS_ERROR))) ||
+ thd->select_limit,0))) ||
select_distinct) &&
join.tmp_table_param.quick_group && !procedure)
{
@@ -546,8 +589,9 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
(join.const_tables == join.tables ||
(simple_order &&
test_if_skip_sort_order(&join.join_tab[join.const_tables], order,
- (group ? HA_POS_ERROR :
- thd->select_limit)))))
+ (join.const_tables != join.tables - 1 ||
+ (join.select_options & OPTION_FOUND_ROWS)) ?
+ HA_POS_ERROR : thd->select_limit,0))))
order=0;
select_describe(&join,need_tmp,
(order != 0 &&
@@ -558,7 +602,7 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
}
/* Perform FULLTEXT search before all regular searches */
- init_ftfuncs(thd, test(order));
+ init_ftfuncs(thd,test(order));
/* Create a tmp table if distinct or if the sort is too complicated */
if (need_tmp)
@@ -573,7 +617,8 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
group : (ORDER*) 0),
group ? 0 : select_distinct,
group && simple_group,
- order == 0,
+ (order == 0 || skip_sort_order) &&
+ !(join.select_options & OPTION_FOUND_ROWS),
join.select_options)))
goto err; /* purecov: inspected */
@@ -623,12 +668,22 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
break;
join_tab->not_used_in_distinct=1;
} while (join_tab-- != join.join_tab);
+ /* Optimize "select distinct b from t1 order by key_part_1 limit #" */
+ if (order && skip_sort_order)
+ {
+ (void) test_if_skip_sort_order(&join.join_tab[join.const_tables],
+ order, thd->select_limit,0);
+ order=0;
+ }
}
/* Copy data to the temporary table */
thd->proc_info="Copying to tmp table";
- if (do_select(&join,(List<Item> *) 0,tmp_table,0))
+ if ((tmp_error=do_select(&join,(List<Item> *) 0,tmp_table,0)))
+ {
+ error=tmp_error;
goto err; /* purecov: inspected */
+ }
if (join.having)
join.having=having=0; // Allready done
@@ -701,9 +756,11 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
group=0;
}
thd->proc_info="Copying to group table";
+ tmp_error= -1;
if (make_sum_func_list(&join,all_fields) ||
- do_select(&join,(List<Item> *) 0,tmp_table2,0))
+ (tmp_error=do_select(&join,(List<Item> *) 0,tmp_table2,0)))
{
+ error=tmp_error;
free_tmp_table(thd,tmp_table2);
goto err; /* purecov: inspected */
}
@@ -750,7 +807,7 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
(procedure && (procedure->flags & PROC_GROUP)))
{
alloc_group_fields(&join,group);
- setup_copy_fields(&join.tmp_table_param,all_fields);
+ setup_copy_fields(thd, &join.tmp_table_param,all_fields);
if (make_sum_func_list(&join,all_fields) || thd->fatal_error)
goto err; /* purecov: inspected */
}
@@ -761,13 +818,34 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
/* If we have already done the group, add HAVING to sorted table */
if (having && ! group && ! join.sort_and_group)
{
- if (fix_having(&join,&having))
- goto err;
+ having->update_used_tables(); // Some tables may have been const
+ JOIN_TAB *table=&join.join_tab[join.const_tables];
+ table_map used_tables= join.const_table_map | table->table->map;
+
+ Item* sort_table_cond=make_cond_for_table(having,used_tables,used_tables);
+ if (sort_table_cond)
+ {
+ if (!table->select)
+ if (!(table->select=new SQL_SELECT))
+ goto err;
+ if (!table->select->cond)
+ table->select->cond=sort_table_cond;
+ else // This should never happen
+ if (!(table->select->cond=new Item_cond_and(table->select->cond,
+ sort_table_cond)))
+ goto err;
+ table->select_cond=table->select->cond;
+ DBUG_EXECUTE("where",print_where(table->select->cond,
+ "select and having"););
+ having=make_cond_for_table(having,~ (table_map) 0,~used_tables);
+ DBUG_EXECUTE("where",print_where(conds,"having after sort"););
+ }
}
if (create_sort_index(&join.join_tab[join.const_tables],
group ? group : order,
(having || group ||
- join.const_tables != join.tables - 1) ?
+ join.const_tables != join.tables - 1 ||
+ (join.select_options & OPTION_FOUND_ROWS)) ?
HA_POS_ERROR : thd->select_limit))
goto err; /* purecov: inspected */
}
@@ -776,7 +854,8 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
error=do_select(&join,&fields,NULL,procedure);
err:
- thd->examined_row_count=join.examined_rows;
+ thd->limit_found_rows = join.send_records;
+ thd->examined_row_count = join.examined_rows;
thd->proc_info="end";
join.lock=0; // It's faster to unlock later
join_free(&join);
@@ -797,7 +876,7 @@ err:
*****************************************************************************/
static ha_rows get_quick_record_count(SQL_SELECT *select,TABLE *table,
- key_map keys)
+ key_map keys,ha_rows limit)
{
int error;
DBUG_ENTER("get_quick_record_count");
@@ -805,7 +884,7 @@ static ha_rows get_quick_record_count(SQL_SELECT *select,TABLE *table,
{
select->head=table;
table->reginfo.impossible_range=0;
- if ((error=select->test_quick_select(keys,(table_map) 0,HA_POS_ERROR))
+ if ((error=select->test_quick_select(keys,(table_map) 0,limit))
== 1)
DBUG_RETURN(select->quick->records);
if (error == -1)
@@ -825,7 +904,7 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds,
{
int error;
uint i,table_count,const_count,found_ref,refs,key,const_ref,eq_part;
- table_map const_table_map,all_table_map;
+ table_map const_table_map,found_const_table_map,all_table_map;
TABLE **table_vector;
JOIN_TAB *stat,*stat_end,*s,**stat_ref;
SQL_SELECT *select;
@@ -845,7 +924,7 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds,
join->best_ref=stat_vector;
stat_end=stat+table_count;
- const_table_map=all_table_map=0;
+ const_table_map=found_const_table_map=all_table_map=0;
const_count=0;
for (s=stat,i=0 ; tables ; s++,tables=tables->next,i++)
@@ -860,13 +939,13 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds,
bzero((char*) table->const_key_parts, sizeof(key_part_map)*table->keys);
all_table_map|= table->map;
s->join=join;
+ s->info=0; // For describe
if ((s->on_expr=tables->on_expr))
{
+ /* Left join */
if (!table->file->records)
{ // Empty table
- s->key_dependent=s->dependent=0;
- s->type=JT_SYSTEM;
- const_table_map|=table->map;
+ s->key_dependent=s->dependent=0; // Ignore LEFT JOIN depend.
set_position(join,const_count++,s,(KEYUSE*) 0);
continue;
}
@@ -887,8 +966,6 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds,
if ((table->system || table->file->records <= 1) && ! s->dependent &&
!(table->file->option_flag() & HA_NOT_EXACT_COUNT))
{
- s->type=JT_SYSTEM;
- const_table_map|=table->map;
set_position(join,const_count++,s,(KEYUSE*) 0);
}
}
@@ -896,10 +973,10 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds,
join->outer_join=outer_join;
/*
- ** If outer join: Re-arrange tables in stat_vector so that outer join
- ** tables are after all tables it is dependent of.
- ** For example: SELECT * from A LEFT JOIN B ON B.c=C.c, C WHERE A.C=C.C
- ** Will shift table B after table C.
+ If outer join: Re-arrange tables in stat_vector so that outer join
+ tables are after all tables it is dependent of.
+ For example: SELECT * from A LEFT JOIN B ON B.c=C.c, C WHERE A.C=C.C
+ Will shift table B after table C.
*/
if (outer_join)
{
@@ -936,31 +1013,66 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds,
conds,~outer_join))
DBUG_RETURN(1);
+ /* Read tables with 0 or 1 rows (system tables) */
+ join->const_table_map=const_table_map;
+
+ for (POSITION *p_pos=join->positions, *p_end=p_pos+const_count;
+ p_pos < p_end ;
+ p_pos++)
+ {
+ int tmp;
+ s= p_pos->table;
+ s->type=JT_SYSTEM;
+ join->const_table_map|=s->table->map;
+ if ((tmp=join_read_const_table(s, p_pos)))
+ {
+ if (tmp > 0)
+ DBUG_RETURN(1); // Fatal error
+ }
+ else
+ found_const_table_map|= s->table->map;
+ }
+
/* loop until no more const tables are found */
int ref_changed;
do
{
ref_changed = 0;
found_ref=0;
- for (JOIN_TAB **pos=stat_vector+const_count; (s= *pos) ; pos++)
+
+ /*
+ We only have to loop from stat_vector + const_count as
+ set_position() will move all const_tables first in stat_vector
+ */
+
+ for (JOIN_TAB **pos=stat_vector+const_count ; (s= *pos) ; pos++)
{
+ TABLE *table=s->table;
if (s->dependent) // If dependent on some table
{
- if (s->dependent & ~(const_table_map)) // All dep. must be constants
+ // All dep. must be constants
+ if (s->dependent & ~(join->const_table_map))
continue;
- if (s->table->file->records <= 1L &&
- !(s->table->file->option_flag() & HA_NOT_EXACT_COUNT))
+ if (table->file->records <= 1L &&
+ !(table->file->option_flag() & HA_NOT_EXACT_COUNT))
{ // system table
+ int tmp;
s->type=JT_SYSTEM;
- const_table_map|=s->table->map;
+ join->const_table_map|=table->map;
set_position(join,const_count++,s,(KEYUSE*) 0);
+ if ((tmp=join_read_const_table(s,join->positions+const_count-1)))
+ {
+ if (tmp > 0)
+ DBUG_RETURN(1); // Fatal error
+ }
+ else
+ found_const_table_map|= table->map;
continue;
}
}
/* check if table can be read by key or table only uses const refs */
if ((keyuse=s->keyuse))
{
- TABLE *table=s->table;
s->type= JT_REF;
while (keyuse->table == table)
{
@@ -973,7 +1085,7 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds,
{
if (keyuse->val->type() != Item::NULL_ITEM)
{
- if (!((~const_table_map) & keyuse->used_tables))
+ if (!((~join->const_table_map) & keyuse->used_tables))
const_ref|= (key_map) 1 << keyuse->keypart;
else
refs|=keyuse->used_tables;
@@ -987,10 +1099,22 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds,
{
if (const_ref == eq_part)
{ // Found everything for ref.
+ int tmp;
+ ref_changed = 1;
s->type=JT_CONST;
- const_table_map|=table->map;
+ join->const_table_map|=table->map;
set_position(join,const_count++,s,start_keyuse);
- ref_changed = 1;
+ if (create_ref_for_key(join, s, start_keyuse,
+ join->const_table_map))
+ DBUG_RETURN(1);
+ if ((tmp=join_read_const_table(s,
+ join->positions+const_count-1)))
+ {
+ if (tmp > 0)
+ DBUG_RETURN(1); // Fatal error
+ }
+ else
+ found_const_table_map|= table->map;
break;
}
else
@@ -999,7 +1123,7 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds,
}
}
}
- } while (const_table_map & found_ref && ref_changed);
+ } while (join->const_table_map & found_ref && ref_changed);
/* Calc how many (possible) matched records in each table */
@@ -1015,8 +1139,11 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds,
s->found_records=s->records=s->table->file->records;
s->read_time=(ha_rows) s->table->file->scan_time();
- /* Set a max range of how many seeks we can expect when using keys */
- s->worst_seeks= (double) (s->read_time*2);
+ /*
+ Set a max range of how many seeks we can expect when using keys
+ This was (s->read_time*5), but this was too low with small rows
+ */
+ s->worst_seeks= (double) s->found_records / 5;
if (s->worst_seeks < 2.0) // Fix for small tables
s->worst_seeks=2.0;
@@ -1026,10 +1153,11 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds,
{
ha_rows records;
if (!select)
- select=make_select(s->table,0,
- 0,
+ select=make_select(s->table, join->const_table_map,
+ join->const_table_map,
and_conds(conds,s->on_expr),&error);
- records=get_quick_record_count(select,s->table, s->const_keys);
+ records=get_quick_record_count(select,s->table, s->const_keys,
+ join->row_limit);
s->quick=select->quick;
s->needed_reg=select->needed_reg;
select->quick=0;
@@ -1047,10 +1175,10 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds,
join->map2table=stat_ref;
join->table= join->all_tables=table_vector;
join->const_tables=const_count;
- join->const_table_map=const_table_map;
+ join->found_const_table_map=found_const_table_map;
if (join->const_tables != join->tables)
- find_best_combination(join,all_table_map & ~const_table_map);
+ find_best_combination(join,all_table_map & ~join->const_table_map);
else
{
memcpy((gptr) join->best_positions,(gptr) join->positions,
@@ -1087,7 +1215,7 @@ merge_key_fields(KEY_FIELD *start,KEY_FIELD *new_fields,KEY_FIELD *end,
if (start == new_fields)
return start; // Impossible or
if (new_fields == end)
- return start; // No new fields, skipp all
+ return start; // No new fields, skip all
KEY_FIELD *first_free=new_fields;
@@ -1149,7 +1277,7 @@ add_key_field(KEY_FIELD **key_fields,uint and_level,
// Don't remove column IS NULL on a LEFT JOIN table
if (!eq_func || !value || value->type() != Item::NULL_ITEM ||
!field->table->maybe_null || field->null_ptr)
- return; // Not a key. Skipp it
+ return; // Not a key. Skip it
exists_optimize=1;
}
else
@@ -1168,11 +1296,13 @@ add_key_field(KEY_FIELD **key_fields,uint and_level,
else
{
JOIN_TAB *stat=field->table->reginfo.join_tab;
- stat[0].keys|=field->key_start; // Add possible keys
+ key_map possible_keys= (field->key_start &
+ field->table->keys_in_use_for_query);
+ stat[0].keys|= possible_keys; // Add possible keys
if (!value)
{ // Probably BETWEEN or IN
- stat[0].const_keys |= field->key_start;
+ stat[0].const_keys |= possible_keys;
return; // Can't be used as eq key
}
@@ -1186,7 +1316,7 @@ add_key_field(KEY_FIELD **key_fields,uint and_level,
*/
stat[0].key_dependent|=used_tables;
if (value->const_item())
- stat[0].const_keys |= field->key_start;
+ stat[0].const_keys |= possible_keys;
/* We can't always use indexes when comparing a string index to a
number. cmp_type() is checked to allow compare of dates to numbers */
@@ -1213,7 +1343,7 @@ add_key_fields(JOIN_TAB *stat,KEY_FIELD **key_fields,uint *and_level,
{
if (cond->type() == Item_func::COND_ITEM)
{
- List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
+ List_iterator_fast<Item> li(*((Item_cond*) cond)->argument_list());
KEY_FIELD *org_key_fields= *key_fields;
if (((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC)
@@ -1367,27 +1497,27 @@ add_ft_keys(DYNAMIC_ARRAY *keyuse_array,
*arg1=(Item_func *)(func->arguments()[1]);
if ((functype == Item_func::GE_FUNC ||
functype == Item_func::GT_FUNC) &&
- arg0->type() == Item::FUNC_ITEM &&
+ arg0->type() == Item::FUNC_ITEM &&
arg0->functype() == Item_func::FT_FUNC &&
- arg1->const_item() && arg1->val()>=0)
+ arg1->const_item() && arg1->val()>0)
cond_func=(Item_func_match *) arg0;
else if ((functype == Item_func::LE_FUNC ||
functype == Item_func::LT_FUNC) &&
arg1->type() == Item::FUNC_ITEM &&
arg1->functype() == Item_func::FT_FUNC &&
- arg0->const_item() && arg0->val()>=0)
+ arg0->const_item() && arg0->val()>0)
cond_func=(Item_func_match *) arg1;
}
}
else if (cond->type() == Item::COND_ITEM)
{
- List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
+ List_iterator_fast<Item> li(*((Item_cond*) cond)->argument_list());
if (((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC)
{
Item *item;
/*
- I', (Sergei) too lazy to implement proper recursive descent here,
+ I'm (Sergei) too lazy to implement proper recursive descent here,
and anyway, nobody will use such a stupid queries
that will require it :-)
May be later...
@@ -1404,7 +1534,7 @@ add_ft_keys(DYNAMIC_ARRAY *keyuse_array,
}
}
- if(!cond_func)
+ if (!cond_func || cond_func->key == NO_SUCH_KEY)
return;
KEYUSE keyuse;
@@ -1467,7 +1597,7 @@ update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab,
add_key_part(keyuse,field);
}
- if (thd->lex.ftfunc_list.elements)
+ if (thd->lex.select_lex.ftfunc_list.elements)
{
add_ft_keys(keyuse,join_tab,cond,normal_tables);
}
@@ -1475,7 +1605,7 @@ update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab,
/*
** remove ref if there is a keypart which is a ref and a const.
** remove keyparts without previous keyparts.
- ** Special treatment for ft-keys. SerG.
+ ** Special treatment for ft-keys.
*/
if (keyuse->elements)
{
@@ -1716,7 +1846,7 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count,
{
/* we can use only index tree */
uint keys_per_block= table->file->block_size/2/
- keyinfo->key_length+1;
+ (keyinfo->key_length+table->file->ref_length)+1;
tmp=(record_count*(records+keys_per_block-1)/
keys_per_block);
}
@@ -1786,7 +1916,7 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count,
{
/* we can use only index tree */
uint keys_per_block= table->file->block_size/2/
- keyinfo->key_length+1;
+ (keyinfo->key_length+table->file->ref_length)+1;
tmp=record_count*(tmp+keys_per_block-1)/keys_per_block;
}
else
@@ -1811,10 +1941,17 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count,
/*
Don't test table scan if it can't be better.
Prefer key lookup if we would use the same key for scanning.
+
+ Don't do a table scan on InnoDB tables, if we can read the used
+ parts of the row from any of the used index.
+ This is because table scans uses index and we would not win
+ anything by using a table scan.
*/
if ((records >= s->found_records || best > s->read_time) &&
!(s->quick && best_key && s->quick->index == best_key->key &&
- best_max_key_part >= s->table->quick_key_parts[best_key->key]))
+ best_max_key_part >= s->table->quick_key_parts[best_key->key]) &&
+ !((s->table->file->option_flag() & HA_TABLE_SCAN_ON_INDEX) &&
+ s->table->used_keys && best_key))
{ // Check full join
if (s->on_expr)
{
@@ -1959,21 +2096,18 @@ prev_record_reads(JOIN *join,table_map found_ref)
static bool
get_best_combination(JOIN *join)
{
- uint i,key,tablenr;
+ uint i,tablenr;
table_map used_tables;
- TABLE *table;
JOIN_TAB *join_tab,*j;
KEYUSE *keyuse;
- KEY *keyinfo;
uint table_count;
+ THD *thd=join->thd;
table_count=join->tables;
if (!(join->join_tab=join_tab=
- (JOIN_TAB*) join->thd->alloc(sizeof(JOIN_TAB)*table_count)))
+ (JOIN_TAB*) thd->alloc(sizeof(JOIN_TAB)*table_count)))
return TRUE;
- join->const_tables=0; /* for checking */
- join->const_table_map=0;
join->full_join=0;
used_tables=0;
@@ -1982,188 +2116,188 @@ get_best_combination(JOIN *join)
TABLE *form;
*j= *join->best_positions[tablenr].table;
form=join->table[tablenr]=j->table;
- j->ref.key = -1;
- j->ref.key_parts=0;
- j->info=0; // For describe
used_tables|= form->map;
form->reginfo.join_tab=j;
if (!j->on_expr)
form->reginfo.not_exists_optimize=0; // Only with LEFT JOIN
+ if (j->type == JT_CONST)
+ continue; // Handled in make_join_stat..
+
+ j->ref.key = -1;
+ j->ref.key_parts=0;
if (j->type == JT_SYSTEM)
- {
- j->table->const_table=1;
- if (join->const_tables == tablenr)
- {
- join->const_tables++;
- join->const_table_map|=form->map;
- }
continue;
- }
if (!j->keys || !(keyuse= join->best_positions[tablenr].key))
{
j->type=JT_ALL;
if (tablenr != join->const_tables)
join->full_join=1;
}
- else
- {
- uint keyparts,length;
- bool ftkey=(keyuse->keypart == FT_KEYPART);
- /*
- ** Use best key from find_best
- */
- table=j->table;
- key=keyuse->key;
+ else if (create_ref_for_key(join, j, keyuse, used_tables))
+ return TRUE; // Something went wrong
+ }
- keyinfo=table->key_info+key;
- if (ftkey)
- {
- Item_func_match *ifm=(Item_func_match *)keyuse->val;
+ for (i=0 ; i < table_count ; i++)
+ join->map2table[join->join_tab[i].table->tablenr]=join->join_tab+i;
+ update_depend_map(join);
+ return 0;
+}
- length=0;
- keyparts=1;
- ifm->join_key=1;
- }
- else
- {
- keyparts=length=0;
- do
- {
- if (!((~used_tables) & keyuse->used_tables))
- {
- if (keyparts == keyuse->keypart)
- {
- keyparts++;
- length+=keyinfo->key_part[keyuse->keypart].store_length;
- }
- }
- keyuse++;
- } while (keyuse->table == table && keyuse->key == key);
- } /* not ftkey */
-
- /* set up fieldref */
- keyinfo=table->key_info+key;
- j->ref.key_parts=keyparts;
- j->ref.key_length=length;
- j->ref.key=(int) key;
- if (!(j->ref.key_buff= (byte*) sql_calloc(ALIGN_SIZE(length)*2)) ||
- !(j->ref.key_copy= (store_key**) sql_alloc((sizeof(store_key*) *
- (keyparts+1)))) ||
- !(j->ref.items= (Item**) sql_alloc(sizeof(Item*)*keyparts)))
- {
- return TRUE;
- }
- j->ref.key_buff2=j->ref.key_buff+ALIGN_SIZE(length);
- j->ref.key_err=1;
- keyuse=join->best_positions[tablenr].key;
- store_key **ref_key=j->ref.key_copy;
- byte *key_buff=j->ref.key_buff;
- if (ftkey)
- {
- j->ref.items[0]=((Item_func*)(keyuse->val))->key_item();
- if (keyuse->used_tables)
- return TRUE; // not supported yet. SerG
+static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, KEYUSE *org_keyuse,
+ table_map used_tables)
+{
+ KEYUSE *keyuse=org_keyuse;
+ bool ftkey=(keyuse->keypart == FT_KEYPART);
+ THD *thd= join->thd;
+ uint keyparts,length,key;
+ TABLE *table;
+ KEY *keyinfo;
- j->type=JT_FT;
- }
- else
- {
- THD *thd=join->thd;
- for (i=0 ; i < keyparts ; keyuse++,i++)
- {
- while (keyuse->keypart != i ||
- ((~used_tables) & keyuse->used_tables))
- keyuse++; /* Skipp other parts */
-
- uint maybe_null= test(keyinfo->key_part[i].null_bit);
- j->ref.items[i]=keyuse->val; // Save for cond removal
- if (!keyuse->used_tables &&
- !(join->select_options & SELECT_DESCRIBE))
- { // Compare against constant
- store_key_item *tmp=new store_key_item(keyinfo->key_part[i].field,
- (char*)key_buff +
- maybe_null,
- maybe_null ?
- (char*) key_buff : 0,
- keyinfo->key_part[i].length,
- keyuse->val);
- if (thd->fatal_error)
- {
- return TRUE;
- }
- tmp->copy();
- }
- else
- *ref_key++= get_store_key(keyuse,join->const_table_map,
- &keyinfo->key_part[i],
- (char*) key_buff,maybe_null);
- key_buff+=keyinfo->key_part[i].store_length;
- }
- } /* not ftkey */
- *ref_key=0; // end_marker
- if (j->type == JT_FT) /* no-op */;
- else if (j->type == JT_CONST)
+ /*
+ ** Use best key from find_best
+ */
+ table=j->table;
+ key=keyuse->key;
+ keyinfo=table->key_info+key;
+
+ if (ftkey)
+ {
+ Item_func_match *ifm=(Item_func_match *)keyuse->val;
+
+ length=0;
+ keyparts=1;
+ ifm->join_key=1;
+ }
+ else
+ {
+ keyparts=length=0;
+ do
+ {
+ if (!((~used_tables) & keyuse->used_tables))
{
- j->table->const_table=1;
- if (join->const_tables == tablenr)
+ if (keyparts == keyuse->keypart)
{
- join->const_tables++;
- join->const_table_map|=form->map;
+ keyparts++;
+ length+=keyinfo->key_part[keyuse->keypart].store_length;
}
}
- else if (((keyinfo->flags & (HA_NOSAME | HA_NULL_PART_KEY)) != HA_NOSAME) ||
- keyparts != keyinfo->key_parts)
- j->type=JT_REF; /* Must read with repeat */
- else if (ref_key == j->ref.key_copy)
- { /* Should never be reached */
- /*
- This happen if we are using a constant expression in the ON part
- of an LEFT JOIN.
- SELECT * FROM a LEFT JOIN b ON b.key=30
- Here we should not mark the table as a 'const' as a field may
- have a 'normal' value or a NULL value.
- */
- j->type=JT_CONST;
- if (join->const_tables == tablenr)
+ keyuse++;
+ } while (keyuse->table == table && keyuse->key == key);
+ } /* not ftkey */
+
+ /* set up fieldref */
+ keyinfo=table->key_info+key;
+ j->ref.key_parts=keyparts;
+ j->ref.key_length=length;
+ j->ref.key=(int) key;
+ if (!(j->ref.key_buff= (byte*) thd->calloc(ALIGN_SIZE(length)*2)) ||
+ !(j->ref.key_copy= (store_key**) thd->alloc((sizeof(store_key*) *
+ (keyparts+1)))) ||
+ !(j->ref.items= (Item**) thd->alloc(sizeof(Item*)*keyparts)))
+ {
+ return TRUE;
+ }
+ j->ref.key_buff2=j->ref.key_buff+ALIGN_SIZE(length);
+ j->ref.key_err=1;
+ keyuse=org_keyuse;
+
+ store_key **ref_key=j->ref.key_copy;
+ byte *key_buff=j->ref.key_buff;
+ if (ftkey)
+ {
+ j->ref.items[0]=((Item_func*)(keyuse->val))->key_item();
+ if (keyuse->used_tables)
+ return TRUE; // not supported yet. SerG
+
+ j->type=JT_FT;
+ }
+ else
+ {
+ uint i;
+ for (i=0 ; i < keyparts ; keyuse++,i++)
+ {
+ while (keyuse->keypart != i ||
+ ((~used_tables) & keyuse->used_tables))
+ keyuse++; /* Skip other parts */
+
+ uint maybe_null= test(keyinfo->key_part[i].null_bit);
+ j->ref.items[i]=keyuse->val; // Save for cond removal
+ if (!keyuse->used_tables &&
+ !(join->select_options & SELECT_DESCRIBE))
+ { // Compare against constant
+ store_key_item *tmp=new store_key_item(thd,
+ keyinfo->key_part[i].field,
+ (char*)key_buff +
+ maybe_null,
+ maybe_null ?
+ (char*) key_buff : 0,
+ keyinfo->key_part[i].length,
+ keyuse->val);
+ if (thd->fatal_error)
{
- join->const_tables++;
- join->const_table_map|=form->map;
+ return TRUE;
}
+ tmp->copy();
}
else
- j->type=JT_EQ_REF;
- }
+ *ref_key++= get_store_key(thd,
+ keyuse,join->const_table_map,
+ &keyinfo->key_part[i],
+ (char*) key_buff,maybe_null);
+ key_buff+=keyinfo->key_part[i].store_length;
+ }
+ } /* not ftkey */
+ *ref_key=0; // end_marker
+ if (j->type == JT_FT) /* no-op */;
+ else if (j->type == JT_CONST)
+ j->table->const_table=1;
+ else if (((keyinfo->flags & (HA_NOSAME | HA_NULL_PART_KEY))
+ != HA_NOSAME) ||
+ keyparts != keyinfo->key_parts)
+ j->type=JT_REF; /* Must read with repeat */
+ else if (ref_key == j->ref.key_copy)
+ { /* Should never be reached */
+ /*
+ This happen if we are using a constant expression in the ON part
+ of an LEFT JOIN.
+ SELECT * FROM a LEFT JOIN b ON b.key=30
+ Here we should not mark the table as a 'const' as a field may
+ have a 'normal' value or a NULL value.
+ */
+ j->type=JT_CONST;
}
-
- for (i=0 ; i < table_count ; i++)
- join->map2table[join->join_tab[i].table->tablenr]=join->join_tab+i;
- update_depend_map(join);
+ else
+ j->type=JT_EQ_REF;
return 0;
}
+
static store_key *
-get_store_key(KEYUSE *keyuse, table_map used_tables, KEY_PART_INFO *key_part,
- char *key_buff, uint maybe_null)
+get_store_key(THD *thd, KEYUSE *keyuse, table_map used_tables,
+ KEY_PART_INFO *key_part, char *key_buff, uint maybe_null)
{
if (!((~used_tables) & keyuse->used_tables)) // if const item
{
- return new store_key_const_item(key_part->field,
+ return new store_key_const_item(thd,
+ key_part->field,
key_buff + maybe_null,
maybe_null ? key_buff : 0,
key_part->length,
keyuse->val);
}
else if (keyuse->val->type() == Item::FIELD_ITEM)
- return new store_key_field(key_part->field,
+ return new store_key_field(thd,
+ key_part->field,
key_buff + maybe_null,
maybe_null ? key_buff : 0,
key_part->length,
((Item_field*) keyuse->val)->field,
keyuse->val->full_name());
- return new store_key_item(key_part->field,
+ return new store_key_item(thd,
+ key_part->field,
key_buff + maybe_null,
maybe_null ? key_buff : 0,
key_part->length,
@@ -2201,13 +2335,15 @@ make_simple_join(JOIN *join,TABLE *tmp_table)
join->tables=1;
join->const_tables=0;
join->const_table_map=0;
- join->tmp_table_param.copy_field_count=join->tmp_table_param.field_count=
- join->tmp_table_param.sum_func_count= join->tmp_table_param.func_count=0;
- join->tmp_table_param.copy_field=0;
+ join->tmp_table_param.field_count= join->tmp_table_param.sum_func_count=
+ join->tmp_table_param.func_count=0;
+ join->tmp_table_param.copy_field=join->tmp_table_param.copy_field_end=0;
join->first_record=join->sort_and_group=0;
join->sum_funcs=0;
join->send_records=(ha_rows) 0;
join->group=0;
+ join->do_send_rows = 1;
+ join->row_limit=HA_POS_ERROR;
join_tab->cache.buff=0; /* No cacheing */
join_tab->table=tmp_table;
@@ -2281,7 +2417,7 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
{
DBUG_EXECUTE("where",print_where(tmp,tab->table->table_name););
SQL_SELECT *sel=tab->select=(SQL_SELECT*)
- sql_memdup((gptr) select, sizeof(SQL_SELECT));
+ join->thd->memdup((gptr) select, sizeof(SQL_SELECT));
if (!sel)
DBUG_RETURN(1); // End of memory
tab->select_cond=sel->cond=tmp;
@@ -2323,15 +2459,19 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
*/
if ((tab->keys & ~ tab->const_keys && i > 0) ||
- tab->const_keys && i == join->const_tables &&
- join->thd->select_limit < join->best_positions[i].records_read)
+ (tab->const_keys && i == join->const_tables &&
+ join->thd->select_limit < join->best_positions[i].records_read &&
+ !(join->select_options & OPTION_FOUND_ROWS)))
{
/* Join with outer join condition */
COND *orig_cond=sel->cond;
sel->cond=and_conds(sel->cond,tab->on_expr);
if (sel->test_quick_select(tab->keys,
used_tables & ~ current_map,
- join->thd->select_limit) < 0)
+ (join->select_options &
+ OPTION_FOUND_ROWS ?
+ HA_POS_ERROR :
+ join->thd->select_limit)) < 0)
DBUG_RETURN(1); // Impossible range
sel->cond=orig_cond;
}
@@ -2358,8 +2498,8 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
current_map)))
{
DBUG_EXECUTE("where",print_where(tmp,"cache"););
- tab->cache.select=(SQL_SELECT*) sql_memdup((gptr) sel,
- sizeof(SQL_SELECT));
+ tab->cache.select=(SQL_SELECT*)
+ join->thd->memdup((gptr) sel, sizeof(SQL_SELECT));
tab->cache.select->cond=tmp;
tab->cache.select->read_tables=join->const_table_map;
}
@@ -2408,7 +2548,8 @@ make_join_readinfo(JOIN *join,uint options)
table->file->index_init(tab->ref.key);
tab->read_first_record= join_read_key;
tab->read_record.read_record= join_no_more_records;
- if (table->used_keys & ((key_map) 1 << tab->ref.key))
+ if (table->used_keys & ((key_map) 1 << tab->ref.key) &&
+ !table->no_keyread)
{
table->key_read=1;
table->file->extra(HA_EXTRA_KEYREAD);
@@ -2425,8 +2566,9 @@ make_join_readinfo(JOIN *join,uint options)
tab->quick=0;
table->file->index_init(tab->ref.key);
tab->read_first_record= join_read_always_key;
- tab->read_record.read_record= join_read_next;
- if (table->used_keys & ((key_map) 1 << tab->ref.key))
+ tab->read_record.read_record= join_read_next_same;
+ if (table->used_keys & ((key_map) 1 << tab->ref.key) &&
+ !table->no_keyread)
{
table->key_read=1;
table->file->extra(HA_EXTRA_KEYREAD);
@@ -2443,7 +2585,7 @@ make_join_readinfo(JOIN *join,uint options)
** if previous table use cache
*/
table->status=STATUS_NO_RECORD;
- if (i != join->const_tables && (options & SELECT_USE_CACHE) &&
+ if (i != join->const_tables && !(options & SELECT_NO_JOIN_CACHE) &&
tab->use_quick != 2 && !tab->on_expr)
{
if ((options & SELECT_DESCRIBE) ||
@@ -2456,7 +2598,7 @@ make_join_readinfo(JOIN *join,uint options)
/* These init changes read_record */
if (tab->use_quick == 2)
{
- join->thd->lex.options|=QUERY_NO_GOOD_INDEX_USED;
+ join->thd->lex.select_lex.options|=QUERY_NO_GOOD_INDEX_USED;
tab->read_first_record= join_init_quick_read_record;
statistic_increment(select_range_check_count, &LOCK_status);
}
@@ -2471,7 +2613,7 @@ make_join_readinfo(JOIN *join,uint options)
}
else
{
- join->thd->lex.options|=QUERY_NO_INDEX_USED;
+ join->thd->lex.select_lex.options|=QUERY_NO_INDEX_USED;
statistic_increment(select_scan_count, &LOCK_status);
}
}
@@ -2483,22 +2625,25 @@ make_join_readinfo(JOIN *join,uint options)
}
else
{
- join->thd->lex.options|=QUERY_NO_INDEX_USED;
+ join->thd->lex.select_lex.options|=QUERY_NO_INDEX_USED;
statistic_increment(select_full_join_count, &LOCK_status);
}
}
- if (tab->select && tab->select->quick &&
- table->used_keys & ((key_map) 1 << tab->select->quick->index))
+ if (!table->no_keyread)
{
- table->key_read=1;
- table->file->extra(HA_EXTRA_KEYREAD);
- }
- else if (table->used_keys && ! (tab->select && tab->select->quick))
- { // Only read index tree
- tab->index=find_shortest_key(table, table->used_keys);
- tab->table->file->index_init(tab->index);
- tab->read_first_record= join_init_read_first_with_key;
- tab->type=JT_NEXT; // Read with index_first / index_next
+ if (tab->select && tab->select->quick &&
+ table->used_keys & ((key_map) 1 << tab->select->quick->index))
+ {
+ table->key_read=1;
+ table->file->extra(HA_EXTRA_KEYREAD);
+ }
+ else if (table->used_keys && ! (tab->select && tab->select->quick))
+ { // Only read index tree
+ tab->index=find_shortest_key(table, table->used_keys);
+ tab->table->file->index_init(tab->index);
+ tab->read_first_record= join_read_first;
+ tab->type=JT_NEXT; // Read with index_first / index_next
+ }
}
}
break;
@@ -2551,14 +2696,16 @@ join_free(JOIN *join)
}
// We are not using tables anymore
// Unlock all tables. We may be in an INSERT .... SELECT statement.
- if (join->lock && join->thd->lock)
+ if (join->lock && join->thd->lock &&
+ !(join->select_options & SELECT_NO_UNLOCK))
{
mysql_unlock_read_tables(join->thd, join->lock);// Don't free join->lock
join->lock=0;
}
join->group_fields.delete_elements();
join->tmp_table_param.copy_funcs.delete_elements();
- delete [] join->tmp_table_param.copy_field;
+ if (join->tmp_table_param.copy_field) // Because of bug in ecc
+ delete [] join->tmp_table_param.copy_field;
join->tmp_table_param.copy_field=0;
DBUG_VOID_RETURN;
}
@@ -2608,7 +2755,7 @@ eq_ref_table(JOIN *join, ORDER *start_order, JOIN_TAB *tab)
if (order)
{
found++;
- dbug_assert(!(order->used & map));
+ DBUG_ASSERT(!(order->used & map));
order->used|=map;
continue; // Used in ORDER BY
}
@@ -2723,7 +2870,7 @@ remove_const(JOIN *join,ORDER *first_order, COND *cond, bool *simple_order)
else if (!(order_tables & not_const_tables))
{
DBUG_PRINT("info",("removing: %s", order->item[0]->full_name()));
- continue; // skipp const item
+ continue; // skip const item
}
else
{
@@ -2782,17 +2929,17 @@ return_zero_rows(select_result *result,TABLE_LIST *tables,List<Item> &fields,
if (having && having->val_int() == 0)
send_row=0;
}
- if (!tables || !(result->send_fields(fields,1)))
+ if (!(result->send_fields(fields,1)))
{
if (send_row)
result->send_data(fields);
- if (tables) // Not from do_select()
+ if (tables) // Not from do_select()
{
/* Close open cursors */
for (TABLE_LIST *table=tables; table ; table=table->next)
table->table->file->index_end();
- result->send_eof(); // Should be safe
}
+ result->send_eof(); // Should be safe
}
DBUG_RETURN(0);
}
@@ -2910,7 +3057,7 @@ propagate_cond_constants(I_List<COND_CMP> *save_list,COND *and_level,
{
bool and_level= ((Item_cond*) cond)->functype() ==
Item_func::COND_AND_FUNC;
- List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
+ List_iterator_fast<Item> li(*((Item_cond*) cond)->argument_list());
Item *item;
I_List<COND_CMP> save;
while ((item=li++))
@@ -3064,13 +3211,13 @@ remove_eq_conds(COND *cond,Item::cond_result *cond_value)
((Item_func*) cond)->functype() == Item_func::ISNULL_FUNC)
{
/*
- ** Handles this special case for some ODBC applications:
- ** The are requesting the row that was just updated with a auto_increment
- ** value with this construct:
- **
- ** SELECT * from table_name where auto_increment_column IS NULL
- ** This will be changed to:
- ** SELECT * from table_name where auto_increment_column = LAST_INSERT_ID
+ Handles this special case for some ODBC applications:
+ The are requesting the row that was just updated with a auto_increment
+ value with this construct:
+
+ SELECT * from table_name where auto_increment_column IS NULL
+ This will be changed to:
+ SELECT * from table_name where auto_increment_column = LAST_INSERT_ID
*/
Item_func_isnull *func=(Item_func_isnull*) cond;
@@ -3083,6 +3230,7 @@ remove_eq_conds(COND *cond,Item::cond_result *cond_value)
(thd->options & OPTION_AUTO_IS_NULL) &&
thd->insert_id())
{
+ query_cache_abort(&thd->net);
COND *new_cond;
if ((new_cond= new Item_func_eq(args[0],
new Item_int("last_insert_id()",
@@ -3126,7 +3274,7 @@ remove_eq_conds(COND *cond,Item::cond_result *cond_value)
}
}
*cond_value=Item::COND_OK;
- return cond; /* Point at next and level */
+ return cond; // Point at next and level
}
/*
@@ -3140,7 +3288,7 @@ const_expression_in_where(COND *cond, Item *comp_item, Item **const_item)
{
bool and_level= (((Item_cond*) cond)->functype()
== Item_func::COND_AND_FUNC);
- List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
+ List_iterator_fast<Item> li(*((Item_cond*) cond)->argument_list());
Item *item;
while ((item=li++))
{
@@ -3195,7 +3343,7 @@ const_expression_in_where(COND *cond, Item *comp_item, Item **const_item)
** for send_fields
****************************************************************************/
-Field *create_tmp_field(TABLE *table,Item *item, Item::Type type,
+Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
Item_result_field ***copy_func, Field **from_field,
bool group, bool modify_item)
{
@@ -3228,7 +3376,7 @@ Field *create_tmp_field(TABLE *table,Item *item, Item::Type type,
item->name,table,item_sum->decimals);
case INT_RESULT:
return new Field_longlong(item_sum->max_length,maybe_null,
- item->name,table);
+ item->name,table,item->unsigned_flag);
case STRING_RESULT:
if (item_sum->max_length > 255)
return new Field_blob(item_sum->max_length,maybe_null,
@@ -3237,7 +3385,7 @@ Field *create_tmp_field(TABLE *table,Item *item, Item::Type type,
item->name,table,item->binary);
}
}
- current_thd->fatal_error=1;
+ thd->fatal_error=1;
return 0; // Error
}
case Item::FIELD_ITEM:
@@ -3245,7 +3393,8 @@ Field *create_tmp_field(TABLE *table,Item *item, Item::Type type,
Field *org_field=((Item_field*) item)->field,*new_field;
*from_field=org_field;
- if ((new_field= org_field->new_field(table))) // Should always be true
+ // The following should always be true
+ if ((new_field= org_field->new_field(&thd->mem_root,table)))
{
if (modify_item)
((Item_field*) item)->result_field= new_field;
@@ -3279,7 +3428,7 @@ Field *create_tmp_field(TABLE *table,Item *item, Item::Type type,
break;
case INT_RESULT:
new_field=new Field_longlong(item->max_length,maybe_null,
- item->name,table);
+ item->name,table, item->unsigned_flag);
break;
case STRING_RESULT:
if (item->max_length > 255)
@@ -3305,13 +3454,14 @@ Field *create_tmp_field(TABLE *table,Item *item, Item::Type type,
TABLE *
create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
ORDER *group, bool distinct, bool save_sum_fields,
- bool allow_distinct_limit, uint select_options)
+ bool allow_distinct_limit, ulong select_options)
{
TABLE *table;
uint i,field_count,reclength,null_count,null_pack_length,
hidden_null_count, hidden_null_pack_length, hidden_field_count,
blob_count,group_null_items;
bool using_unique_constraint=0;
+ bool not_all_columns= !(select_options & TMP_TABLE_ALL_COLUMNS);
char *tmpname,path[FN_REFLEN];
byte *pos,*group_buff;
uchar *null_flags;
@@ -3334,7 +3484,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
temp_pool_slot = bitmap_set_next(&temp_pool);
if (temp_pool_slot != MY_BIT_NONE) // we got a slot
- sprintf(path, "%s%s_%lx_%i", mysql_tmpdir, tmp_file_prefix,
+ sprintf(path, "%s%s_%lx_%i", mysql_tmpdir, tmp_file_prefix,
current_pid, temp_pool_slot);
else // if we run out of slots or we are not using tempool
sprintf(path,"%s%s%lx_%lx_%x",mysql_tmpdir,tmp_file_prefix,current_pid,
@@ -3345,7 +3495,11 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
if (!param->quick_group)
group=0; // Can't use group key
else for (ORDER *tmp=group ; tmp ; tmp=tmp->next)
+ {
(*tmp->item)->marker=4; // Store null in key
+ if ((*tmp->item)->max_length >= MAX_CHAR_WIDTH)
+ using_unique_constraint=1;
+ }
if (param->group_length >= MAX_BLOB_WIDTH)
using_unique_constraint=1;
if (group)
@@ -3402,24 +3556,27 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
reclength=blob_count=null_count=hidden_null_count=group_null_items=0;
param->using_indirect_summary_function=0;
- List_iterator<Item> li(fields);
+ List_iterator_fast<Item> li(fields);
Item *item;
Field **tmp_from_field=from_field;
while ((item=li++))
{
Item::Type type=item->type();
- if (item->with_sum_func && type != Item::SUM_FUNC_ITEM)
+ if (not_all_columns)
{
- /*
- Mark that the we have ignored an item that refers to a summary
- function. We need to know this if someone is going to use
- DISTINCT on the result.
- */
- param->using_indirect_summary_function=1;
- continue;
+ if (item->with_sum_func && type != Item::SUM_FUNC_ITEM)
+ {
+ /*
+ Mark that the we have ignored an item that refers to a summary
+ function. We need to know this if someone is going to use
+ DISTINCT on the result.
+ */
+ param->using_indirect_summary_function=1;
+ continue;
+ }
+ if (item->const_item()) // We don't have to store this
+ continue;
}
- if (item->const_item()) // We don't have to store this
- continue;
if (type == Item::SUM_FUNC_ITEM && !group && !save_sum_fields)
{ /* Can't calc group yet */
((Item_sum*) item)->result_field=0;
@@ -3429,8 +3586,8 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
if (!arg->const_item())
{
Field *new_field=
- create_tmp_field(table,arg,arg->type(),&copy_func,tmp_from_field,
- group != 0,1);
+ create_tmp_field(thd, table,arg,arg->type(),&copy_func,
+ tmp_from_field, group != 0,not_all_columns);
if (!new_field)
goto err; // Should be OOM
tmp_from_field++;
@@ -3446,8 +3603,9 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
}
else
{
- Field *new_field=create_tmp_field(table,item,type,&copy_func,
- tmp_from_field, group != 0,1);
+ Field *new_field=create_tmp_field(thd, table, item,type, &copy_func,
+ tmp_from_field, group != 0,
+ not_all_columns);
if (!new_field)
{
if (thd->fatal_error)
@@ -3543,6 +3701,10 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
{
if (field->flags & GROUP_FLAG && !using_unique_constraint)
{
+ /*
+ We have to reserve one byte here for NULL bits,
+ as this is updated by 'end_update()'
+ */
*pos++=0; // Null is stored here
recinfo->length=1;
recinfo->type=FIELD_NORMAL;
@@ -3577,14 +3739,14 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
(field->type() == FIELD_TYPE_STRING ||
field->type() == FIELD_TYPE_VAR_STRING) &&
length >= 10 && blob_count)
- recinfo->type=FIELD_SKIPP_ENDSPACE;
+ recinfo->type=FIELD_SKIP_ENDSPACE;
else
recinfo->type=FIELD_NORMAL;
if (!--hidden_field_count)
null_count=(null_count+7) & ~7; // move to next byte
}
- param->copy_field_count=(uint) (copy - param->copy_field);
+ param->copy_field_end=copy;
param->recinfo=recinfo;
store_record(table,2); // Make empty default record
@@ -3626,19 +3788,21 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
if (!using_unique_constraint)
{
group->buff=(char*) group_buff;
- if (!(group->field=field->new_field(table)))
+ if (!(group->field=field->new_field(&thd->mem_root,table)))
goto err; /* purecov: inspected */
if (maybe_null)
{
/*
- To be able to group on NULL, we move the null bit to be
- just before the column and extend the key to cover the null bit
+ To be able to group on NULL, we reserve place in group_buff
+ for the NULL flag just before the column.
+ The field data is after this flag.
+ The NULL flag is updated by 'end_update()' and 'end_write()'
*/
- *group_buff= 0; // Init null byte
- key_part_info->offset--;
- key_part_info->length++;
- group->field->move_field((char*) group_buff+1, (uchar*) group_buff,
- 1);
+ keyinfo->flags|= HA_NULL_ARE_EQUAL; // def. that NULL == NULL
+ key_part_info->null_bit=field->null_bit;
+ key_part_info->null_offset= (uint) (field->null_ptr -
+ (uchar*) table->record[0]);
+ group->field->move_field((char*) ++group->buff);
}
else
group->field->move_field((char*) group_buff);
@@ -3740,14 +3904,13 @@ static bool open_tmp_table(TABLE *table)
return(1);
}
/* VOID(ha_lock(table,F_WRLCK)); */ /* Single thread table */
- (void) table->file->extra(HA_EXTRA_NO_READCHECK); /* Not needed */
(void) table->file->extra(HA_EXTRA_QUICK); /* Faster */
return(0);
}
static bool create_myisam_tmp_table(TABLE *table,TMP_TABLE_PARAM *param,
- uint options)
+ ulong options)
{
int error;
MI_KEYDEF keydef;
@@ -3794,10 +3957,10 @@ static bool create_myisam_tmp_table(TABLE *table,TMP_TABLE_PARAM *param,
for (uint i=0; i < keyinfo->key_parts ; i++,seg++)
{
Field *field=keyinfo->key_part[i].field;
- seg->flag=0;
- seg->language=MY_CHARSET_CURRENT;
- seg->length=keyinfo->key_part[i].length;
- seg->start=keyinfo->key_part[i].offset;
+ seg->flag= 0;
+ seg->language= MY_CHARSET_CURRENT;
+ seg->length= keyinfo->key_part[i].length;
+ seg->start= keyinfo->key_part[i].offset;
if (field->flags & BLOB_FLAG)
{
seg->type=
@@ -3818,11 +3981,17 @@ static bool create_myisam_tmp_table(TABLE *table,TMP_TABLE_PARAM *param,
keyinfo->key_part[i].length > 4)
seg->flag|=HA_SPACE_PACK;
}
- if (using_unique_constraint &&
- !(field->flags & NOT_NULL_FLAG))
+ if (!(field->flags & NOT_NULL_FLAG))
{
seg->null_bit= field->null_bit;
seg->null_pos= (uint) (field->null_ptr - (uchar*) table->record[0]);
+ /*
+ We are using a GROUP BY on something that contains NULL
+ In this case we have to tell MyISAM that two NULL should
+ on INSERT be compared as equal
+ */
+ if (!using_unique_constraint)
+ keydef.flag|= HA_NULL_ARE_EQUAL;
}
}
}
@@ -3908,12 +4077,18 @@ bool create_myisam_from_heap(TABLE *table, TMP_TABLE_PARAM *param, int error,
thd->proc_info="converting HEAP to MyISAM";
if (create_myisam_tmp_table(&new_table,param,
- thd->lex.options | thd->options))
+ thd->lex.select_lex.options | thd->options))
goto err2;
if (open_tmp_table(&new_table))
goto err1;
table->file->index_end();
table->file->rnd_init();
+ if (table->no_rows)
+ {
+ new_table.file->extra(HA_EXTRA_NO_ROWS);
+ new_table.no_rows=1;
+ }
+
/* copy all old rows */
while (!table->file->rnd_next(new_table.record[1]))
{
@@ -3954,9 +4129,12 @@ bool create_myisam_from_heap(TABLE *table, TMP_TABLE_PARAM *param, int error,
}
-/*****************************************************************************
-** Make a join of all tables and write it on socket or to table
-*****************************************************************************/
+/****************************************************************************
+ Make a join of all tables and write it on socket or to table
+ Return: 0 if ok
+ 1 if error is sent
+ -1 if error should be sent
+****************************************************************************/
static int
do_select(JOIN *join,List<Item> *fields,TABLE *table,Procedure *procedure)
@@ -4033,22 +4211,22 @@ do_select(JOIN *join,List<Item> *fields,TABLE *table,Procedure *procedure)
if (error == -3)
error=0; /* select_limit used */
}
- if (!table) /* If sending data to client */
+
+ /* Return 1 if error is sent; -1 if error should be sent */
+ if (error < 0)
{
- if (error < 0)
- join->result->send_error(0,NullS); /* purecov: inspected */
- else
+ join->result->send_error(0,NullS); /* purecov: inspected */
+ error=1; // Error sent
+ }
+ else
+ {
+ error=0;
+ if (!table) // If sending data to client
{
join_free(join); // Unlock all cursors
if (join->result->send_eof())
- error= -1;
+ error= 1; // Don't send error
}
- }
- else if (error < 0)
- join->result->send_error(0,NullS); /* purecov: inspected */
-
- if (error >= 0)
- {
DBUG_PRINT("info",("%ld records output",join->send_records));
}
if (table)
@@ -4059,15 +4237,15 @@ do_select(JOIN *join,List<Item> *fields,TABLE *table,Procedure *procedure)
my_errno=tmp;
error= -1;
}
- if (table->file->index_end())
+ if ((tmp=table->file->index_end()))
{
my_errno=tmp;
error= -1;
}
- if (error != old_error)
+ if (error == -1)
table->file->print_error(my_errno,MYF(0));
}
- DBUG_RETURN(error < 0);
+ DBUG_RETURN(error);
}
@@ -4143,10 +4321,8 @@ sub_select(JOIN *join,JOIN_TAB *join_tab,bool end_of_records)
info->file->unlock_row();
}
} while (!(error=info->read_record(info)));
- if (error > 0) // Fatal error
- return -1;
}
- else if (error > 0)
+ if (error > 0) // Fatal error
return -1;
if (!found && on_expr)
@@ -4237,45 +4413,44 @@ flush_cached_records(JOIN *join,JOIN_TAB *join_tab,bool skipp_last)
*****************************************************************************/
static int
-join_read_const_tables(JOIN *join)
+join_read_const_table(JOIN_TAB *tab, POSITION *pos)
{
- uint i;
int error;
- DBUG_ENTER("join_read_const_tables");
- for (i=0 ; i < join->const_tables ; i++)
- {
- TABLE *form=join->table[i];
- form->null_row=0;
- form->status=STATUS_NO_RECORD;
-
- if (join->join_tab[i].type == JT_SYSTEM)
- {
- if ((error=join_read_system(join->join_tab+i)))
- { // Info for DESCRIBE
- join->join_tab[i].info="const row not found";
- join->best_positions[i].records_read=0.0;
- if (!form->outer_join || error > 0)
- DBUG_RETURN(error);
- }
- }
- else
- {
- if ((error=join_read_const(join->join_tab+i)))
- {
- join->join_tab[i].info="unique row not found";
- join->best_positions[i].records_read=0.0;
- if (!form->outer_join || error > 0)
- DBUG_RETURN(error);
- }
+ DBUG_ENTER("join_read_const_table");
+ TABLE *table=tab->table;
+ table->const_table=1;
+ table->null_row=0;
+ table->status=STATUS_NO_RECORD;
+
+ if (tab->type == JT_SYSTEM)
+ {
+ if ((error=join_read_system(tab)))
+ { // Info for DESCRIBE
+ tab->info="const row not found";
+ /* Mark for EXPLAIN that the row was not found */
+ pos->records_read=0.0;
+ if (!table->outer_join || error > 0)
+ DBUG_RETURN(error);
}
- if (join->join_tab[i].on_expr && !form->null_row)
+ }
+ else
+ {
+ if ((error=join_read_const(tab)))
{
- if ((form->null_row= test(join->join_tab[i].on_expr->val_int() == 0)))
- empty_record(form);
+ tab->info="unique row not found";
+ /* Mark for EXPLAIN that the row was not found */
+ pos->records_read=0.0;
+ if (!table->outer_join || error > 0)
+ DBUG_RETURN(error);
}
- if (!form->null_row)
- form->maybe_null=0;
}
+ if (tab->on_expr && !table->null_row)
+ {
+ if ((table->null_row= test(tab->on_expr->val_int() == 0)))
+ empty_record(table);
+ }
+ if (!table->null_row)
+ table->maybe_null=0;
DBUG_RETURN(0);
}
@@ -4287,7 +4462,8 @@ join_read_system(JOIN_TAB *tab)
int error;
if (table->status & STATUS_GARBAGE) // If first read
{
- if ((error=table->file->rnd_first(table->record[0])))
+ if ((error=table->file->read_first_row(table->record[0],
+ table->primary_key)))
{
if (error != HA_ERR_END_OF_FILE)
{
@@ -4401,6 +4577,35 @@ join_read_always_key(JOIN_TAB *tab)
return 0;
}
+/*
+ This function is used when optimizing away ORDER BY in
+ SELECT * FROM t1 WHERE a=1 ORDER BY a DESC,b DESC
+*/
+
+static int
+join_read_last_key(JOIN_TAB *tab)
+{
+ int error;
+ TABLE *table= tab->table;
+
+ if (cp_buffer_from_ref(&tab->ref))
+ return -1;
+ if ((error=table->file->index_read_last(table->record[0],
+ tab->ref.key_buff,
+ tab->ref.key_length)))
+ {
+ if (error != HA_ERR_KEY_NOT_FOUND)
+ {
+ sql_print_error("read_const: Got error %d when reading table %s",error,
+ table->path);
+ table->file->print_error(error,MYF(0));
+ return 1;
+ }
+ return -1; /* purecov: inspected */
+ }
+ return 0;
+}
+
/* ARGSUSED */
static int
@@ -4411,7 +4616,7 @@ join_no_more_records(READ_RECORD *info __attribute__((unused)))
static int
-join_read_next(READ_RECORD *info)
+join_read_next_same(READ_RECORD *info)
{
int error;
TABLE *table= info->table;
@@ -4434,6 +4639,37 @@ join_read_next(READ_RECORD *info)
return 0;
}
+static int
+join_read_prev_same(READ_RECORD *info)
+{
+ int error;
+ TABLE *table= info->table;
+ JOIN_TAB *tab=table->reginfo.join_tab;
+
+ if ((error=table->file->index_prev(table->record[0])))
+ {
+ if (error != HA_ERR_END_OF_FILE)
+ {
+ sql_print_error("read_next: Got error %d when reading table %s",error,
+ table->path);
+ table->file->print_error(error,MYF(0));
+ error= 1;
+ }
+ else
+ {
+ table->status= STATUS_GARBAGE;
+ error= -1;
+ }
+ }
+ else if (key_cmp(table, tab->ref.key_buff, tab->ref.key,
+ tab->ref.key_length))
+ {
+ table->status=STATUS_NOT_FOUND;
+ error= 1;
+ }
+ return error;
+}
+
static int
join_init_quick_read_record(JOIN_TAB *tab)
@@ -4464,17 +4700,18 @@ join_init_read_record(JOIN_TAB *tab)
}
static int
-join_init_read_first_with_key(JOIN_TAB *tab)
+join_read_first(JOIN_TAB *tab)
{
int error;
TABLE *table=tab->table;
- if (!table->key_read && (table->used_keys & ((key_map) 1 << tab->index)))
+ if (!table->key_read && (table->used_keys & ((key_map) 1 << tab->index)) &&
+ !table->no_keyread)
{
table->key_read=1;
table->file->extra(HA_EXTRA_KEYREAD);
}
tab->table->status=0;
- tab->read_record.read_record=join_init_read_next_with_key;
+ tab->read_record.read_record=join_read_next;
tab->read_record.table=table;
tab->read_record.file=table->file;
tab->read_record.index=tab->index;
@@ -4494,8 +4731,9 @@ join_init_read_first_with_key(JOIN_TAB *tab)
return 0;
}
+
static int
-join_init_read_next_with_key(READ_RECORD *info)
+join_read_next(READ_RECORD *info)
{
int error=info->file->index_next(info->record);
if (error)
@@ -4512,9 +4750,8 @@ join_init_read_next_with_key(READ_RECORD *info)
return 0;
}
-
static int
-join_init_read_last_with_key(JOIN_TAB *tab)
+join_read_last(JOIN_TAB *tab)
{
TABLE *table=tab->table;
int error;
@@ -4524,7 +4761,7 @@ join_init_read_last_with_key(JOIN_TAB *tab)
table->file->extra(HA_EXTRA_KEYREAD);
}
tab->table->status=0;
- tab->read_record.read_record=join_init_read_prev_with_key;
+ tab->read_record.read_record=join_read_prev;
tab->read_record.table=table;
tab->read_record.file=table->file;
tab->read_record.index=tab->index;
@@ -4544,8 +4781,9 @@ join_init_read_last_with_key(JOIN_TAB *tab)
return 0;
}
+
static int
-join_init_read_prev_with_key(READ_RECORD *info)
+join_read_prev(READ_RECORD *info)
{
int error=info->file->index_prev(info->record);
if (error)
@@ -4562,13 +4800,14 @@ join_init_read_prev_with_key(READ_RECORD *info)
return 0;
}
+
static int
join_ft_read_first(JOIN_TAB *tab)
{
int error;
TABLE *table= tab->table;
-#if 0
+#if NOT_USED_YET
if (cp_buffer_from_ref(&tab->ref)) // as ft-key doesn't use store_key's
return -1; // see also FT_SELECT::init()
#endif
@@ -4625,14 +4864,35 @@ end_send(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
int error;
if (join->having && join->having->val_int() == 0)
DBUG_RETURN(0); // Didn't match having
+ error=0;
if (join->procedure)
error=join->procedure->send_row(*join->fields);
- else
+ else if (join->do_send_rows)
error=join->result->send_data(*join->fields);
if (error)
DBUG_RETURN(-1); /* purecov: inspected */
- if (++join->send_records >= join->thd->select_limit)
+ if (++join->send_records >= join->thd->select_limit && join->do_send_rows)
+ {
+ if (join->select_options & OPTION_FOUND_ROWS)
+ {
+ JOIN_TAB *jt=join->join_tab;
+ if ((join->tables == 1) && !join->tmp_table && !join->sort_and_group
+ && !join->send_group_parts && !join->having && !jt->select_cond &&
+ !(jt->table->file->option_flag() & HA_NOT_EXACT_COUNT))
+ {
+ /* Join over all rows in table; Return number of found rows */
+ join->select_options ^= OPTION_FOUND_ROWS;
+ join->send_records = jt->records;
+ }
+ else
+ {
+ join->do_send_rows=0;
+ join->thd->select_limit = HA_POS_ERROR;
+ DBUG_RETURN(0);
+ }
+ }
DBUG_RETURN(-3); // Abort nicely
+ }
}
else
{
@@ -4663,9 +4923,10 @@ end_send_group(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
int error;
if (join->procedure)
{
+ error=0;
if (join->having && join->having->val_int() == 0)
error= -1; // Didn't satisfy having
- else
+ else if (join->do_send_rows)
error=join->procedure->send_row(*join->fields) ? 1 : 0;
if (end_of_records && join->procedure->end_of_records())
error= 1; // Fatal error
@@ -4687,8 +4948,14 @@ end_send_group(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
DBUG_RETURN(-1); /* purecov: inspected */
if (end_of_records)
DBUG_RETURN(0);
- if (!error && ++join->send_records >= join->thd->select_limit)
- DBUG_RETURN(-3); /* Abort nicely */
+ if (!error && ++join->send_records >= join->thd->select_limit &&
+ join->do_send_rows)
+ {
+ if (!(join->select_options & OPTION_FOUND_ROWS))
+ DBUG_RETURN(-3); // Abort nicely
+ join->do_send_rows=0;
+ join->thd->select_limit = HA_POS_ERROR;
+ }
}
}
else
@@ -4734,6 +5001,7 @@ end_write(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
copy_fields(&join->tmp_table_param);
copy_funcs(join->tmp_table_param.funcs);
+#ifdef TO_BE_DELETED
if (!table->uniques) // If not unique handling
{
/* Copy null values from group to row */
@@ -4744,10 +5012,11 @@ end_write(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
if (item->maybe_null)
{
Field *field=item->tmp_table_field();
- field->ptr[-1]= (byte) (field->is_null() ? 0 : 1);
+ field->ptr[-1]= (byte) (field->is_null() ? 1 : 0);
}
}
}
+#endif
if (!join->having || join->having->val_int())
{
join->found_records++;
@@ -4759,8 +5028,15 @@ end_write(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
if (create_myisam_from_heap(table, &join->tmp_table_param, error,1))
DBUG_RETURN(1); // Not a table_is_full error
table->uniques=0; // To ensure rows are the same
- if (++join->send_records >= join->tmp_table_param.end_write_records)
+ }
+ if (++join->send_records >= join->tmp_table_param.end_write_records &&
+ join->do_send_rows)
+ {
+ if (!(join->select_options & OPTION_FOUND_ROWS))
DBUG_RETURN(-3);
+ join->do_send_rows=0;
+ join->thd->select_limit = HA_POS_ERROR;
+ DBUG_RETURN(0);
}
}
}
@@ -4795,8 +5071,9 @@ end_update(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
{
Item *item= *group->item;
item->save_org_in_field(group->field);
+ /* Store in the used key if the field was 0 */
if (item->maybe_null)
- group->buff[0]=item->null_value ? 0: 1; // Save reversed value
+ group->buff[-1]=item->null_value ? 1 : 0;
}
// table->file->index_init(0);
if (!table->file->index_read(table->record[1],
@@ -4955,7 +5232,7 @@ end_write_group(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
/*****************************************************************************
** Remove calculation with tables that aren't yet read. Remove also tests
-** against fields that are read through key where the table is not a
+** against fields that are read through key where the table is not a
** outer join table.
** We can't remove tests that are made against columns which are stored
** in sorted order.
@@ -4974,8 +5251,7 @@ static bool test_if_ref(Item_field *left_item,Item *right_item)
{
if (right_item->type() == Item::FIELD_ITEM)
return (field->eq_def(((Item_field *) right_item)->field));
- if (right_item->const_item() &&
- (right_item->val_int() || !right_item->null_value))
+ if (right_item->const_item() && !(right_item->is_null()))
{
// We can remove binary fields and numerical fields except float,
// as float comparison isn't 100 % secure
@@ -5096,9 +5372,11 @@ part_of_refkey(TABLE *table,Field *field)
** Returns: 1 if key is ok.
** 0 if key can't be used
** -1 if reverse key can be used
+** used_key_parts is set to key parts used if length != 0
*****************************************************************************/
-static int test_if_order_by_key(ORDER *order, TABLE *table, uint idx)
+static int test_if_order_by_key(ORDER *order, TABLE *table, uint idx,
+ uint *used_key_parts)
{
KEY_PART_INFO *key_part,*key_part_end;
key_part=table->key_info[idx].key_part;
@@ -5130,6 +5408,7 @@ static int test_if_order_by_key(ORDER *order, TABLE *table, uint idx)
reverse=flag; // Remember if reverse
key_part++;
}
+ *used_key_parts= (uint) (key_part - table->key_info[idx].key_part);
return reverse;
}
@@ -5152,17 +5431,11 @@ static uint find_shortest_key(TABLE *table, key_map usable_keys)
}
-/*****************************************************************************
-** If not selecting by given key, create a index how records should be read
-** return: 0 ok
-** -1 some fatal error
-** 1 no records
-*****************************************************************************/
-
/* Return 1 if we don't have to do file sorting */
static bool
-test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit)
+test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
+ bool no_changes)
{
int ref_key;
TABLE *table=tab->table;
@@ -5190,10 +5463,48 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit)
if (ref_key >= 0)
{
+ /*
+ We come here when there is a REF key.
+ */
+ int order_direction;
+ uint used_key_parts;
/* Check if we get the rows in requested sorted order by using the key */
if ((usable_keys & ((key_map) 1 << ref_key)) &&
- test_if_order_by_key(order,table,ref_key) == 1)
+ (order_direction = test_if_order_by_key(order,table,ref_key,
+ &used_key_parts)))
+ {
+ if (order_direction == -1) // If ORDER BY ... DESC
+ {
+ if (select && select->quick)
+ {
+ // ORDER BY range_key DESC
+ QUICK_SELECT_DESC *tmp=new QUICK_SELECT_DESC(select->quick,
+ used_key_parts);
+ if (!tmp || tmp->error)
+ {
+ delete tmp;
+ DBUG_RETURN(0); // Reverse sort not supported
+ }
+ select->quick=tmp;
+ DBUG_RETURN(1);
+ }
+ if (tab->ref.key_parts < used_key_parts)
+ {
+ /*
+ SELECT * FROM t1 WHERE a=1 ORDER BY a DESC,b DESC
+
+ Use a traversal function that starts by reading the last row
+ with key part (A) and then traverse the index backwards.
+ */
+ if (table->file->option_flag() & HA_NOT_READ_PREFIX_LAST)
+ DBUG_RETURN(1);
+ tab->read_first_record= join_read_last_key;
+ tab->read_record.read_record= join_read_prev_same;
+ /* fall through */
+ }
+ }
DBUG_RETURN(1); /* No need to sort */
+ }
}
else
{
@@ -5212,20 +5523,24 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit)
for (nr=0; keys ; keys>>=1, nr++)
{
+ uint not_used;
if (keys & 1)
{
int flag;
- if ((flag=test_if_order_by_key(order,table,nr)))
+ if ((flag=test_if_order_by_key(order, table, nr, &not_used)))
{
- tab->index=nr;
- tab->read_first_record= (flag > 0 ? join_init_read_first_with_key:
- join_init_read_last_with_key);
- table->file->index_init(nr);
- tab->type=JT_NEXT; // Read with index_first(), index_next()
- if (table->used_keys & ((key_map) 1 << nr))
+ if (!no_changes)
{
- table->key_read=1;
- table->file->extra(HA_EXTRA_KEYREAD);
+ tab->index=nr;
+ tab->read_first_record= (flag > 0 ? join_read_first:
+ join_read_last);
+ table->file->index_init(nr);
+ tab->type=JT_NEXT; // Read with index_first(), index_next()
+ if (table->used_keys & ((key_map) 1 << nr))
+ {
+ table->key_read=1;
+ table->file->extra(HA_EXTRA_KEYREAD);
+ }
}
DBUG_RETURN(1);
}
@@ -5235,6 +5550,14 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit)
DBUG_RETURN(0); // Can't use index.
}
+
+/*****************************************************************************
+ If not selecting by given key, create an index how records should be read
+ return: 0 ok
+ -1 some fatal error
+ 1 no records
+*****************************************************************************/
+
static int
create_sort_index(JOIN_TAB *tab,ORDER *order,ha_rows select_limit)
{
@@ -5245,7 +5568,7 @@ create_sort_index(JOIN_TAB *tab,ORDER *order,ha_rows select_limit)
SQL_SELECT *select=tab->select;
DBUG_ENTER("create_sort_index");
- if (test_if_skip_sort_order(tab,order,select_limit))
+ if (test_if_skip_sort_order(tab,order,select_limit,0))
DBUG_RETURN(0);
if (!(sortorder=make_unireg_sortorder(order,&length)))
goto err; /* purecov: inspected */
@@ -5278,8 +5601,11 @@ create_sort_index(JOIN_TAB *tab,ORDER *order,ha_rows select_limit)
goto err;
}
}
- table->found_records=filesort(&table,sortorder,length,
+ if (table->tmp_table)
+ table->file->info(HA_STATUS_VARIABLE); // Get record count
+ table->found_records=filesort(table,sortorder,length,
select, 0L, select_limit, &examined_rows);
+ tab->records=table->found_records; // For SQL_CALC_ROWS
delete select; // filesort did select
tab->select=0;
tab->select_cond=0;
@@ -5296,11 +5622,11 @@ err:
DBUG_RETURN(-1);
}
-
/*
** Add the HAVING criteria to table->select
*/
+#ifdef NOT_YET
static bool fix_having(JOIN *join, Item **having)
{
(*having)->update_used_tables(); // Some tables may have been const
@@ -5328,6 +5654,7 @@ static bool fix_having(JOIN *join, Item **having)
}
return 0;
}
+#endif
/*****************************************************************************
@@ -5378,7 +5705,6 @@ remove_duplicates(JOIN *join, TABLE *entry,List<Item> &fields, Item *having)
DBUG_ENTER("remove_duplicates");
entry->reginfo.lock_type=TL_WRITE;
- entry->file->extra(HA_EXTRA_NO_READCHECK);
/* Calculate how many saved fields there is in list */
field_count=0;
@@ -5564,7 +5890,7 @@ static int remove_dup_with_hash_index(THD *thd, TABLE *table,
if ((error=file->delete_row(record)))
goto err;
continue;
- }
+ }
/* copy fields to key buffer */
field_length=field_lengths;
@@ -6104,7 +6430,7 @@ count_field_types(TMP_TABLE_PARAM *param, List<Item> &fields,
List_iterator<Item> li(fields);
Item *field;
- param->field_count=param->sum_func_count=param->func_count=
+ param->field_count=param->sum_func_count=param->func_count=
param->hidden_field_count=0;
param->quick_group=1;
while ((field=li++))
@@ -6198,7 +6524,8 @@ get_sort_by_table(ORDER *a,ORDER *b,TABLE_LIST *tables)
static void
calc_group_buffer(JOIN *join,ORDER *group)
{
- uint key_length=0,parts=0;
+ uint key_length=0, parts=0, null_parts=0;
+
if (group)
join->group= 1;
for (; group ; group=group->next)
@@ -6219,10 +6546,11 @@ calc_group_buffer(JOIN *join,ORDER *group)
key_length+=(*group->item)->max_length;
parts++;
if ((*group->item)->maybe_null)
- key_length++;
+ null_parts++;
}
- join->tmp_table_param.group_length=key_length;
+ join->tmp_table_param.group_length=key_length+null_parts;
join->tmp_table_param.group_parts=parts;
+ join->tmp_table_param.group_null_parts=null_parts;
}
@@ -6273,7 +6601,7 @@ test_if_group_changed(List<Item_buff> &list)
*/
bool
-setup_copy_fields(TMP_TABLE_PARAM *param,List<Item> &fields)
+setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields)
{
Item *pos;
List_iterator<Item> li(fields);
@@ -6281,7 +6609,7 @@ setup_copy_fields(TMP_TABLE_PARAM *param,List<Item> &fields)
DBUG_ENTER("setup_copy_fields");
if (!(copy=param->copy_field= new Copy_field[param->field_count]))
- goto err;
+ goto err2;
param->copy_funcs.empty();
while ((pos=li++))
@@ -6301,7 +6629,7 @@ setup_copy_fields(TMP_TABLE_PARAM *param,List<Item> &fields)
/* set up save buffer and change result_field to point at saved value */
Field *field= item->field;
- item->result_field=field->new_field(field->table);
+ item->result_field=field->new_field(&thd->mem_root,field->table);
char *tmp=(char*) sql_alloc(field->pack_length()+1);
if (!tmp)
goto err;
@@ -6326,12 +6654,13 @@ setup_copy_fields(TMP_TABLE_PARAM *param,List<Item> &fields)
goto err;
}
}
- param->copy_field_count= (uint) (copy - param->copy_field);
+ param->copy_field_end= copy;
DBUG_RETURN(0);
err:
- delete [] param->copy_field;
+ delete [] param->copy_field; // This is never 0
param->copy_field=0;
+err2:
DBUG_RETURN(TRUE);
}
@@ -6344,17 +6673,16 @@ void
copy_fields(TMP_TABLE_PARAM *param)
{
Copy_field *ptr=param->copy_field;
- Copy_field *end=ptr+param->copy_field_count;
+ Copy_field *end=param->copy_field_end;
for ( ; ptr != end; ptr++)
(*ptr->do_copy)(ptr);
- List_iterator<Item> it(param->copy_funcs);
+ List_iterator_fast<Item> &it=param->copy_funcs_it;
+ it.rewind();
Item_copy_string *item;
while ((item = (Item_copy_string*) it++))
- {
item->copy();
- }
}
@@ -6620,24 +6948,26 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
DBUG_ENTER("select_describe");
/* Don't log this into the slow query log */
- join->thd->lex.options&= ~(QUERY_NO_INDEX_USED | QUERY_NO_GOOD_INDEX_USED);
- field_list.push_back(new Item_empty_string("table",NAME_LEN));
- field_list.push_back(new Item_empty_string("type",10));
- field_list.push_back(item=new Item_empty_string("possible_keys",
+ join->thd->lex.select_lex.options&= ~(QUERY_NO_INDEX_USED | QUERY_NO_GOOD_INDEX_USED);
+ if (join->thd->lex.select == &join->thd->lex.select_lex)
+ {
+ field_list.push_back(new Item_empty_string("table",NAME_LEN));
+ field_list.push_back(new Item_empty_string("type",10));
+ field_list.push_back(item=new Item_empty_string("possible_keys",
NAME_LEN*MAX_KEY));
- item->maybe_null=1;
- field_list.push_back(item=new Item_empty_string("key",NAME_LEN));
- item->maybe_null=1;
- field_list.push_back(item=new Item_int("key_len",0,3));
- item->maybe_null=1;
- field_list.push_back(item=new Item_empty_string("ref",
- NAME_LEN*MAX_REF_PARTS));
- item->maybe_null=1;
- field_list.push_back(new Item_real("rows",0.0,0,10));
- field_list.push_back(new Item_empty_string("Extra",255));
- if (send_fields(thd,field_list,1))
- return; /* purecov: inspected */
-
+ item->maybe_null=1;
+ field_list.push_back(item=new Item_empty_string("key",NAME_LEN));
+ item->maybe_null=1;
+ field_list.push_back(item=new Item_int("key_len",0,3));
+ item->maybe_null=1;
+ field_list.push_back(item=new Item_empty_string("ref",
+ NAME_LEN*MAX_REF_PARTS));
+ item->maybe_null=1;
+ field_list.push_back(new Item_real("rows",0.0,0,10));
+ field_list.push_back(new Item_empty_string("Extra",255));
+ if (send_fields(thd,field_list,1))
+ return;
+ }
char buff[512],*buff_ptr;
String tmp(buff,sizeof(buff)),*packet= &thd->packet;
table_map used_tables=0;
@@ -6768,7 +7098,8 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
// For next iteration
used_tables|=table->map;
}
- send_eof(&thd->net);
+ if (!join->thd->lex.select->next)
+ send_eof(&thd->net);
DBUG_VOID_RETURN;
}
@@ -6779,7 +7110,7 @@ static void describe_info(THD *thd, const char *info)
String *packet= &thd->packet;
/* Don't log this into the slow query log */
- thd->lex.options&= ~(QUERY_NO_INDEX_USED | QUERY_NO_GOOD_INDEX_USED);
+ thd->lex.select_lex.options&= ~(QUERY_NO_INDEX_USED | QUERY_NO_GOOD_INDEX_USED);
field_list.push_back(new Item_empty_string("Comment",80));
if (send_fields(thd,field_list,1))
return; /* purecov: inspected */
diff --git a/sql/sql_select.h b/sql/sql_select.h
index 1bf7d7863eb..befa1efde53 100644
--- a/sql/sql_select.h
+++ b/sql/sql_select.h
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -118,19 +118,22 @@ typedef struct st_position { /* Used in find_best */
class TMP_TABLE_PARAM {
public:
List<Item> copy_funcs;
- Copy_field *copy_field;
+ List_iterator_fast<Item> copy_funcs_it;
+ Copy_field *copy_field, *copy_field_end;
byte *group_buff;
Item_result_field **funcs;
MI_COLUMNDEF *recinfo,*start_recinfo;
KEY *keyinfo;
ha_rows end_write_records;
- uint copy_field_count,field_count,sum_func_count,func_count;
+ uint field_count,sum_func_count,func_count;
uint hidden_field_count;
- uint group_parts,group_length;
+ uint group_parts,group_length,group_null_parts;
uint quick_group;
bool using_indirect_summary_function;
- TMP_TABLE_PARAM() :copy_field(0), group_parts(0), group_length(0)
+ TMP_TABLE_PARAM()
+ :copy_funcs_it(copy_funcs), copy_field(0), group_parts(0),
+ group_length(0), group_null_parts(0)
{}
~TMP_TABLE_PARAM()
{
@@ -154,7 +157,8 @@ class JOIN {
uint tables,const_tables;
uint send_group_parts;
bool sort_and_group,first_record,full_join,group, no_field_update;
- table_map const_table_map,outer_join;
+ bool do_send_rows;
+ table_map const_table_map,found_const_table_map,outer_join;
ha_rows send_records,found_records,examined_rows,row_limit;
POSITION positions[MAX_TABLES+1],best_positions[MAX_TABLES+1];
double best_read;
@@ -183,11 +187,11 @@ void TEST_join(JOIN *join);
bool store_val_in_field(Field *field,Item *val);
TABLE *create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
ORDER *group, bool distinct, bool save_sum_fields,
- bool allow_distinct_limit, uint select_options);
+ bool allow_distinct_limit, ulong select_options);
void free_tmp_table(THD *thd, TABLE *entry);
void count_field_types(TMP_TABLE_PARAM *param, List<Item> &fields,
bool reset_with_sum_func);
-bool setup_copy_fields(TMP_TABLE_PARAM *param,List<Item> &fields);
+bool setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param,List<Item> &fields);
void copy_fields(TMP_TABLE_PARAM *param);
void copy_funcs(Item_result_field **func_ptr);
bool create_myisam_from_heap(TABLE *table, TMP_TABLE_PARAM *param, int error,
@@ -207,7 +211,7 @@ class store_key :public Sql_alloc
char *null_ptr;
char err;
public:
- store_key(Field *field_arg, char *ptr, char *null, uint length)
+ store_key(THD *thd, Field *field_arg, char *ptr, char *null, uint length)
:null_ptr(null),err(0)
{
if (field_arg->type() == FIELD_TYPE_BLOB)
@@ -216,7 +220,7 @@ class store_key :public Sql_alloc
field_arg->table, field_arg->binary());
else
{
- to_field=field_arg->new_field(field_arg->table);
+ to_field=field_arg->new_field(&thd->mem_root,field_arg->table);
if (to_field)
to_field->move_field(ptr, (uchar*) null, 1);
}
@@ -232,9 +236,9 @@ class store_key_field: public store_key
Copy_field copy_field;
const char *field_name;
public:
- store_key_field(Field *to_field_arg, char *ptr, char *null_ptr_arg,
+ store_key_field(THD *thd, Field *to_field_arg, char *ptr, char *null_ptr_arg,
uint length, Field *from_field, const char *name_arg)
- :store_key(to_field_arg,ptr,
+ :store_key(thd, to_field_arg,ptr,
null_ptr_arg ? null_ptr_arg : from_field->maybe_null() ? &err
: NullS,length), field_name(name_arg)
{
@@ -257,9 +261,9 @@ class store_key_item :public store_key
protected:
Item *item;
public:
- store_key_item(Field *to_field_arg, char *ptr, char *null_ptr_arg,
+ store_key_item(THD *thd, Field *to_field_arg, char *ptr, char *null_ptr_arg,
uint length, Item *item_arg)
- :store_key(to_field_arg,ptr,
+ :store_key(thd, to_field_arg,ptr,
null_ptr_arg ? null_ptr_arg : item_arg->maybe_null ?
&err : NullS, length), item(item_arg)
{}
@@ -276,10 +280,10 @@ class store_key_const_item :public store_key_item
{
bool inited;
public:
- store_key_const_item(Field *to_field_arg, char *ptr,
+ store_key_const_item(THD *thd, Field *to_field_arg, char *ptr,
char *null_ptr_arg, uint length,
Item *item_arg)
- :store_key_item(to_field_arg,ptr,
+ :store_key_item(thd, to_field_arg,ptr,
null_ptr_arg ? null_ptr_arg : item_arg->maybe_null ?
&err : NullS, length, item_arg), inited(0)
{
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index 6ae7eeb41d3..131266a11d6 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -20,6 +20,7 @@
#include "mysql_priv.h"
#include "sql_select.h" // For select_describe
#include "sql_acl.h"
+#include "repl_failsafe.h"
#include <my_dir.h>
#ifdef HAVE_BERKELEY_DB
@@ -45,6 +46,8 @@ store_create_info(THD *thd, TABLE *table, String *packet);
static void
append_identifier(THD *thd, String *packet, const char *name);
+extern struct st_VioSSLAcceptorFd * ssl_acceptor_fd;
+
/****************************************************************************
** Send list of databases
** A database is a directory in the mysql_data_home directory
@@ -72,7 +75,7 @@ mysqld_show_dbs(THD *thd,const char *wild)
DBUG_RETURN(1);
if (mysql_find_files(thd,&files,NullS,mysql_data_home,wild,1))
DBUG_RETURN(1);
- List_iterator<char> it(files);
+ List_iterator_fast<char> it(files);
while ((file_name=it++))
{
if (!opt_safe_show_db || thd->master_access ||
@@ -81,7 +84,7 @@ mysqld_show_dbs(THD *thd,const char *wild)
(grant_option && !check_grant_db(thd, file_name)))
{
thd->packet.length(0);
- net_store_data(&thd->packet,file_name);
+ net_store_data(&thd->packet, thd->convert_set, file_name);
if (my_net_write(&thd->net, (char*) thd->packet.ptr(),
thd->packet.length()))
DBUG_RETURN(-1);
@@ -95,34 +98,31 @@ mysqld_show_dbs(THD *thd,const char *wild)
** List all open tables in a database
***************************************************************************/
-int mysqld_show_open_tables(THD *thd,const char *db,const char *wild)
+int mysqld_show_open_tables(THD *thd,const char *wild)
{
- Item_string *field=new Item_string("",0);
List<Item> field_list;
- char *end,*table_name;
- List<char> tables;
+ OPEN_TABLE_LIST *open_list;
+ CONVERT *convert=thd->convert_set;
DBUG_ENTER("mysqld_show_open_tables");
- field->name=(char*) thd->alloc(20+(uint) strlen(db)+(wild ? (uint) strlen(wild)+4:0));
- end=strxmov(field->name,"Open_tables_in_",db,NullS);
- if (wild && wild[0])
- strxmov(end," (",wild,")",NullS);
- field->max_length=NAME_LEN;
- field_list.push_back(field);
- field_list.push_back(new Item_empty_string("Comment",80));
+ field_list.push_back(new Item_empty_string("Database",NAME_LEN));
+ field_list.push_back(new Item_empty_string("Table",NAME_LEN));
+ field_list.push_back(new Item_int("In_use",0, 4));
+ field_list.push_back(new Item_int("Name_locked",0, 4));
if (send_fields(thd,field_list,1))
DBUG_RETURN(1);
- if (list_open_tables(thd,&tables,db,wild))
+ if (!(open_list=list_open_tables(thd,wild)) && thd->fatal_error)
DBUG_RETURN(-1);
- List_iterator<char> it(tables);
- while ((table_name=it++))
+ for ( ; open_list ; open_list=open_list->next)
{
thd->packet.length(0);
- net_store_data(&thd->packet,table_name);
- net_store_data(&thd->packet,query_table_status(thd,db,table_name));
+ net_store_data(&thd->packet,convert, open_list->db);
+ net_store_data(&thd->packet,convert, open_list->table);
+ net_store_data(&thd->packet,open_list->in_use);
+ net_store_data(&thd->packet,open_list->locked);
if (my_net_write(&thd->net,(char*) thd->packet.ptr(),thd->packet.length()))
DBUG_RETURN(-1);
}
@@ -157,11 +157,11 @@ int mysqld_show_tables(THD *thd,const char *db,const char *wild)
DBUG_RETURN(1);
if (mysql_find_files(thd,&files,db,path,wild,0))
DBUG_RETURN(-1);
- List_iterator<char> it(files);
+ List_iterator_fast<char> it(files);
while ((file_name=it++))
{
thd->packet.length(0);
- net_store_data(&thd->packet,file_name);
+ net_store_data(&thd->packet, thd->convert_set, file_name);
if (my_net_write(&thd->net,(char*) thd->packet.ptr(),thd->packet.length()))
DBUG_RETURN(-1);
}
@@ -257,6 +257,7 @@ int mysqld_extend_show_tables(THD *thd,const char *db,const char *wild)
char *file_name;
TABLE *table;
String *packet= &thd->packet;
+ CONVERT *convert=thd->convert_set;
DBUG_ENTER("mysqld_extend_show_tables");
(void) sprintf(path,"%s/%s",mysql_data_home,db);
@@ -296,20 +297,20 @@ int mysqld_extend_show_tables(THD *thd,const char *db,const char *wild)
if (mysql_find_files(thd,&files,db,path,wild,0))
DBUG_RETURN(-1);
- List_iterator<char> it(files);
+ List_iterator_fast<char> it(files);
while ((file_name=it++))
{
TABLE_LIST table_list;
bzero((char*) &table_list,sizeof(table_list));
packet->length(0);
- net_store_data(packet,file_name);
+ net_store_data(packet,convert, file_name);
table_list.db=(char*) db;
table_list.real_name=table_list.name=file_name;
if (!(table = open_ltable(thd, &table_list, TL_READ)))
{
for (uint i=0 ; i < field_list.elements ; i++)
net_store_null(packet);
- net_store_data(packet,thd->net.last_error);
+ net_store_data(packet,convert, thd->net.last_error);
thd->net.last_error[0]=0;
}
else
@@ -317,8 +318,8 @@ int mysqld_extend_show_tables(THD *thd,const char *db,const char *wild)
struct tm tm_tmp;
handler *file=table->file;
file->info(HA_STATUS_VARIABLE | HA_STATUS_TIME | HA_STATUS_NO_LOCK);
- net_store_data(packet, file->table_type());
- net_store_data(packet,
+ net_store_data(packet, convert, file->table_type());
+ net_store_data(packet, convert,
(table->db_options_in_use & HA_OPTION_PACK_RECORD) ?
"Dynamic" :
(table->db_options_in_use & HA_OPTION_COMPRESS_RECORD)
@@ -399,7 +400,7 @@ int mysqld_extend_show_tables(THD *thd,const char *db,const char *wild)
my_raid_type(file->raid_type), file->raid_chunks, file->raid_chunksize/RAID_BLOCK_SIZE);
ptr=strmov(ptr,buff);
}
- net_store_data(packet, option_buff+1,
+ net_store_data(packet, convert, option_buff+1,
(ptr == option_buff ? 0 : (uint) (ptr-option_buff)-1));
}
{
@@ -431,6 +432,7 @@ mysqld_show_fields(THD *thd, TABLE_LIST *table_list,const char *wild,
TABLE *table;
handler *file;
char tmp[MAX_FIELD_WIDTH];
+ CONVERT *convert=thd->convert_set;
DBUG_ENTER("mysqld_show_fields");
DBUG_PRINT("enter",("db: %s table: %s",table_list->db,
table_list->real_name));
@@ -485,18 +487,18 @@ mysqld_show_fields(THD *thd, TABLE_LIST *table_list,const char *wild,
bool null_default_value=0;
packet->length(0);
- net_store_data(packet,field->field_name);
+ net_store_data(packet,convert,field->field_name);
field->sql_type(type);
- net_store_data(packet,type.ptr(),type.length());
+ net_store_data(packet,convert,type.ptr(),type.length());
pos=(byte*) ((flags & NOT_NULL_FLAG) &&
field->type() != FIELD_TYPE_TIMESTAMP ?
"" : "YES");
- net_store_data(packet,(const char*) pos);
+ net_store_data(packet,convert,(const char*) pos);
pos=(byte*) ((field->flags & PRI_KEY_FLAG) ? "PRI" :
(field->flags & UNIQUE_KEY_FLAG) ? "UNI" :
(field->flags & MULTIPLE_KEY_FLAG) ? "MUL":"");
- net_store_data(packet,(char*) pos);
+ net_store_data(packet,convert,(char*) pos);
if (field->type() == FIELD_TYPE_TIMESTAMP ||
field->unireg_check == Field::NEXT_NUMBER)
@@ -505,17 +507,17 @@ mysqld_show_fields(THD *thd, TABLE_LIST *table_list,const char *wild,
{ // Not null by default
type.set(tmp,sizeof(tmp));
field->val_str(&type,&type);
- net_store_data(packet,type.ptr(),type.length());
+ net_store_data(packet,convert,type.ptr(),type.length());
}
else if (field->maybe_null() || null_default_value)
net_store_null(packet); // Null as default
else
- net_store_data(packet,tmp,0);
+ net_store_data(packet,convert,tmp,0);
char *end=tmp;
if (field->unireg_check == Field::NEXT_NUMBER)
end=strmov(tmp,"auto_increment");
- net_store_data(packet,tmp,(uint) (end-tmp));
+ net_store_data(packet,convert,tmp,(uint) (end-tmp));
if (verbose)
{
@@ -530,7 +532,7 @@ mysqld_show_fields(THD *thd, TABLE_LIST *table_list,const char *wild,
end=strmov(end,grant_types.type_names[bitnr]);
}
}
- net_store_data(packet,tmp+1,end == tmp ? 0 : (uint) (end-tmp-1));
+ net_store_data(packet,convert, tmp+1,end == tmp ? 0 : (uint) (end-tmp-1));
}
if (my_net_write(&thd->net,(char*) packet->ptr(),packet->length()))
DBUG_RETURN(1);
@@ -545,6 +547,7 @@ int
mysqld_show_create(THD *thd, TABLE_LIST *table_list)
{
TABLE *table;
+ CONVERT *convert=thd->convert_set;
DBUG_ENTER("mysqld_show_create");
DBUG_PRINT("enter",("db: %s table: %s",table_list->db,
table_list->real_name));
@@ -566,7 +569,7 @@ mysqld_show_create(THD *thd, TABLE_LIST *table_list)
String *packet = &thd->packet;
{
packet->length(0);
- net_store_data(packet, table->table_name);
+ net_store_data(packet,convert, table->table_name);
// a hack - we need to reserve some space for the length before
// we know what it is - let's assume that the length of create table
// statement will fit into 3 bytes ( 16 MB max :-) )
@@ -623,6 +626,7 @@ mysqld_show_keys(THD *thd, TABLE_LIST *table_list)
{
TABLE *table;
char buff[256];
+ CONVERT *convert=thd->convert_set;
DBUG_ENTER("mysqld_show_keys");
DBUG_PRINT("enter",("db: %s table: %s",table_list->db,
table_list->real_name));
@@ -648,6 +652,8 @@ mysqld_show_keys(THD *thd, TABLE_LIST *table_list)
item->maybe_null=1;
field_list.push_back(item=new Item_empty_string("Packed",10));
item->maybe_null=1;
+ field_list.push_back(new Item_empty_string("Null",3));
+ field_list.push_back(new Item_empty_string("Index_type",16));
field_list.push_back(new Item_empty_string("Comment",255));
item->maybe_null=1;
@@ -664,16 +670,18 @@ mysqld_show_keys(THD *thd, TABLE_LIST *table_list)
for (uint j=0 ; j < key_info->key_parts ; j++,key_part++)
{
packet->length(0);
- net_store_data(packet,table->table_name);
- net_store_data(packet,((key_info->flags & HA_NOSAME) ? "0" :"1"), 1);
- net_store_data(packet,key_info->name);
+ net_store_data(packet,convert,table->table_name);
+ net_store_data(packet,convert,((key_info->flags & HA_NOSAME) ? "0" :"1"), 1);
+ net_store_data(packet,convert,key_info->name);
end=int10_to_str((long) (j+1),(char*) buff,10);
- net_store_data(packet,buff,(uint) (end-buff));
- net_store_data(packet,key_part->field ? key_part->field->field_name :
+ net_store_data(packet,convert,buff,(uint) (end-buff));
+ net_store_data(packet,convert,
+ key_part->field ? key_part->field->field_name :
"?unknown field?");
if (table->file->option_flag() & HA_READ_ORDER)
- net_store_data(packet,((key_part->key_part_flag & HA_REVERSE_SORT)
- ? "D" : "A"), 1);
+ net_store_data(packet,convert,
+ ((key_part->key_part_flag & HA_REVERSE_SORT) ?
+ "D" : "A"), 1);
else
net_store_null(packet); /* purecov: inspected */
KEY *key=table->key_info+i;
@@ -681,21 +689,30 @@ mysqld_show_keys(THD *thd, TABLE_LIST *table_list)
{
ulong records=(table->file->records / key->rec_per_key[j]);
end=int10_to_str((long) records, buff, 10);
- net_store_data(packet,buff,(uint) (end-buff));
+ net_store_data(packet,convert,buff,(uint) (end-buff));
}
else
net_store_null(packet);
+
+ /* Check if we have a key part that only uses part of the field */
if (!key_part->field ||
key_part->length !=
table->field[key_part->fieldnr-1]->key_length())
{
end=int10_to_str((long) key_part->length, buff,10); /* purecov: inspected */
- net_store_data(packet,buff,(uint) (end-buff)); /* purecov: inspected */
+ net_store_data(packet,convert,buff,(uint) (end-buff)); /* purecov: inspected */
}
else
net_store_null(packet);
net_store_null(packet); // No pack_information yet
- net_store_data(packet,key_info->flags & HA_FULLTEXT ? "FULLTEXT":"");
+
+ /* Null flag */
+ uint flags= key_part->field ? key_part->field->flags : 0;
+ char *pos=(char*) ((flags & NOT_NULL_FLAG) ? "" : "YES");
+ net_store_data(packet,convert,(const char*) pos);
+ net_store_data(packet,convert,table->file->index_type(i));
+ /* Comment */
+ net_store_data(packet,convert,"");
if (my_net_write(&thd->net,(char*) packet->ptr(),packet->length()))
DBUG_RETURN(1); /* purecov: inspected */
}
@@ -740,27 +757,29 @@ mysqld_list_fields(THD *thd, TABLE_LIST *table_list, const char *wild)
int
mysqld_dump_create_info(THD *thd, TABLE *table, int fd)
{
+ CONVERT *convert=thd->convert_set;
DBUG_ENTER("mysqld_dump_create_info");
DBUG_PRINT("enter",("table: %s",table->real_name));
+
String* packet = &thd->packet;
packet->length(0);
-
- if(store_create_info(thd,table,packet))
+ if (store_create_info(thd,table,packet))
DBUG_RETURN(-1);
- if(fd < 0)
+ if (convert)
+ convert->convert((char*) packet->ptr(), packet->length());
+ if (fd < 0)
{
- if(my_net_write(&thd->net, (char*)packet->ptr(), packet->length()))
+ if (my_net_write(&thd->net, (char*)packet->ptr(), packet->length()))
DBUG_RETURN(-1);
VOID(net_flush(&thd->net));
}
else
{
- if(my_write(fd, (const byte*) packet->ptr(), packet->length(),
- MYF(MY_WME)))
+ if (my_write(fd, (const byte*) packet->ptr(), packet->length(),
+ MYF(MY_WME)))
DBUG_RETURN(-1);
}
-
DBUG_RETURN(0);
}
@@ -977,6 +996,7 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose)
List<Item> field_list;
I_List<thread_info> thread_infos;
ulong max_query_length= verbose ? max_allowed_packet : PROCESS_LIST_WIDTH;
+ CONVERT *convert=thd->convert_set;
DBUG_ENTER("mysqld_list_processes");
field_list.push_back(new Item_int("Id",0,7));
@@ -1006,10 +1026,13 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose)
thread_info *thd_info=new thread_info;
thd_info->thread_id=tmp->thread_id;
- thd_info->user=thd->strdup(tmp->user ? tmp->user : (tmp->system_thread ?
- "system user" : "unauthenticated user"));
- thd_info->host=thd->strdup(tmp->host ? tmp->host : (tmp->ip ? tmp->ip :
- (tmp->system_thread ? "none" : "connecting host")));
+ thd_info->user=thd->strdup(tmp->user ? tmp->user :
+ (tmp->system_thread ?
+ "system user" : "unauthenticated user"));
+ thd_info->host=thd->strdup(tmp->host ? tmp->host :
+ (tmp->ip ? tmp->ip :
+ (tmp->system_thread ? "none" :
+ "connecting host")));
if ((thd_info->db=tmp->db)) // Safe test
thd_info->db=thd->strdup(thd_info->db);
thd_info->command=(int) tmp->command;
@@ -1041,9 +1064,8 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose)
thd_info->query=0;
if (tmp->query)
{
- uint length=(uint) strlen(tmp->query);
- if (length > max_query_length)
- length=max_query_length;
+ /* query_length is always set before tmp->query */
+ uint length= min(max_query_length, tmp->query_length);
thd_info->query=(char*) thd->memdup(tmp->query,length+1);
thd_info->query[length]=0;
}
@@ -1060,28 +1082,28 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose)
char buff[20],*end;
packet->length(0);
end=int10_to_str((long) thd_info->thread_id, buff,10);
- net_store_data(packet,buff,(uint) (end-buff));
- net_store_data(packet,thd_info->user);
- net_store_data(packet,thd_info->host);
+ net_store_data(packet,convert,buff,(uint) (end-buff));
+ net_store_data(packet,convert,thd_info->user);
+ net_store_data(packet,convert,thd_info->host);
if (thd_info->db)
- net_store_data(packet,thd_info->db);
+ net_store_data(packet,convert,thd_info->db);
else
net_store_null(packet);
if (thd_info->proc_info)
- net_store_data(packet,thd_info->proc_info);
+ net_store_data(packet,convert,thd_info->proc_info);
else
- net_store_data(packet,command_name[thd_info->command]);
+ net_store_data(packet,convert,command_name[thd_info->command]);
if (thd_info->start_time)
- net_store_data(packet,(uint32)
- (time((time_t*) 0) - thd_info->start_time));
+ net_store_data(packet,
+ (uint32) (time((time_t*) 0) - thd_info->start_time));
else
net_store_null(packet);
if (thd_info->state_info)
- net_store_data(packet,thd_info->state_info);
+ net_store_data(packet,convert,thd_info->state_info);
else
net_store_null(packet);
if (thd_info->query)
- net_store_data(packet,thd_info->query);
+ net_store_data(packet,convert,thd_info->query);
else
net_store_null(packet);
if (my_net_write(&thd->net,(char*) packet->ptr(),packet->length()))
@@ -1103,6 +1125,7 @@ int mysqld_show(THD *thd, const char *wild, show_var_st *variables)
char buff[8192];
String packet2(buff,sizeof(buff));
List<Item> field_list;
+ CONVERT *convert=thd->convert_set;
DBUG_ENTER("mysqld_show");
field_list.push_back(new Item_empty_string("Variable_name",30));
field_list.push_back(new Item_empty_string("Value",256));
@@ -1116,7 +1139,7 @@ int mysqld_show(THD *thd, const char *wild, show_var_st *variables)
if (!(wild && wild[0] && wild_compare(variables[i].name,wild)))
{
packet2.length(0);
- net_store_data(&packet2,variables[i].name);
+ net_store_data(&packet2,convert,variables[i].name);
switch (variables[i].type){
case SHOW_LONG:
case SHOW_LONG_CONST:
@@ -1143,7 +1166,7 @@ int mysqld_show(THD *thd, const char *wild, show_var_st *variables)
break;
}
case SHOW_CHAR:
- net_store_data(&packet2,variables[i].value);
+ net_store_data(&packet2,convert, variables[i].value);
break;
case SHOW_STARTTIME:
net_store_data(&packet2,(uint32) (thd->query_start() - start_time));
@@ -1151,15 +1174,183 @@ int mysqld_show(THD *thd, const char *wild, show_var_st *variables)
case SHOW_QUESTION:
net_store_data(&packet2,(uint32) thd->query_id);
break;
+ case SHOW_RPL_STATUS:
+ net_store_data(&packet2, rpl_status_type[(int)rpl_status]);
+ break;
+ case SHOW_SLAVE_RUNNING:
+ {
+ LOCK_ACTIVE_MI;
+ net_store_data(&packet2, (active_mi->slave_running &&
+ active_mi->rli.slave_running)
+ ? "ON" : "OFF");
+ UNLOCK_ACTIVE_MI;
+ break;
+ }
case SHOW_OPENTABLES:
net_store_data(&packet2,(uint32) cached_tables());
break;
case SHOW_CHAR_PTR:
{
char *value= *(char**) variables[i].value;
- net_store_data(&packet2,value ? value : "");
+ net_store_data(&packet2,convert, value ? value : "");
break;
}
+#ifdef HAVE_OPENSSL
+ /* First group - functions relying on CTX */
+ case SHOW_SSL_CTX_SESS_ACCEPT:
+ net_store_data(&packet2,(uint32)
+ (!ssl_acceptor_fd ? 0 :
+ SSL_CTX_sess_accept(ssl_acceptor_fd->ssl_context_)));
+ break;
+ case SHOW_SSL_CTX_SESS_ACCEPT_GOOD:
+ net_store_data(&packet2,(uint32)
+ (!ssl_acceptor_fd ? 0 :
+ SSL_CTX_sess_accept_good(ssl_acceptor_fd->ssl_context_)));
+ break;
+ case SHOW_SSL_CTX_SESS_CONNECT_GOOD:
+ net_store_data(&packet2,(uint32)
+ (!ssl_acceptor_fd ? 0 :
+ SSL_CTX_sess_connect_good(ssl_acceptor_fd->ssl_context_)));
+ break;
+ case SHOW_SSL_CTX_SESS_ACCEPT_RENEGOTIATE:
+ net_store_data(&packet2,(uint32)
+ (!ssl_acceptor_fd ? 0 :
+ SSL_CTX_sess_accept_renegotiate(ssl_acceptor_fd->ssl_context_)));
+ break;
+ case SHOW_SSL_CTX_SESS_CONNECT_RENEGOTIATE:
+ net_store_data(&packet2,(uint32)
+ (!ssl_acceptor_fd ? 0 :
+ SSL_CTX_sess_connect_renegotiate(ssl_acceptor_fd->ssl_context_)));
+ break;
+ case SHOW_SSL_CTX_SESS_CB_HITS:
+ net_store_data(&packet2,(uint32)
+ (!ssl_acceptor_fd ? 0 :
+ SSL_CTX_sess_cb_hits(ssl_acceptor_fd->ssl_context_)));
+ break;
+ case SHOW_SSL_CTX_SESS_HITS:
+ net_store_data(&packet2,(uint32)
+ (!ssl_acceptor_fd ? 0 :
+ SSL_CTX_sess_hits(ssl_acceptor_fd->ssl_context_)));
+ break;
+ case SHOW_SSL_CTX_SESS_CACHE_FULL:
+ net_store_data(&packet2,(uint32)
+ (!ssl_acceptor_fd ? 0 :
+ SSL_CTX_sess_cache_full(ssl_acceptor_fd->ssl_context_)));
+ break;
+ case SHOW_SSL_CTX_SESS_MISSES:
+ net_store_data(&packet2,(uint32)
+ (!ssl_acceptor_fd ? 0 :
+ SSL_CTX_sess_misses(ssl_acceptor_fd->ssl_context_)));
+ break;
+ case SHOW_SSL_CTX_SESS_TIMEOUTS:
+ net_store_data(&packet2,(uint32)
+ (!ssl_acceptor_fd ? 0 :
+ SSL_CTX_sess_timeouts(ssl_acceptor_fd->ssl_context_)));
+ break;
+ case SHOW_SSL_CTX_SESS_NUMBER:
+ net_store_data(&packet2,(uint32)
+ (!ssl_acceptor_fd ? 0 :
+ SSL_CTX_sess_number(ssl_acceptor_fd->ssl_context_)));
+ break;
+ case SHOW_SSL_CTX_SESS_CONNECT:
+ net_store_data(&packet2,(uint32)
+ (!ssl_acceptor_fd ? 0 :
+ SSL_CTX_sess_connect(ssl_acceptor_fd->ssl_context_)));
+ break;
+ case SHOW_SSL_CTX_SESS_GET_CACHE_SIZE:
+ net_store_data(&packet2,(uint32)
+ (!ssl_acceptor_fd ? 0 :
+ SSL_CTX_sess_get_cache_size(ssl_acceptor_fd->ssl_context_)));
+ break;
+ case SHOW_SSL_CTX_GET_VERIFY_MODE:
+ net_store_data(&packet2,(uint32)
+ (!ssl_acceptor_fd ? 0 :
+ SSL_CTX_get_verify_mode(ssl_acceptor_fd->ssl_context_)));
+ break;
+ case SHOW_SSL_CTX_GET_VERIFY_DEPTH:
+ net_store_data(&packet2,(uint32)
+ (!ssl_acceptor_fd ? 0 :
+ SSL_CTX_get_verify_depth(ssl_acceptor_fd->ssl_context_)));
+ break;
+ case SHOW_SSL_CTX_GET_SESSION_CACHE_MODE:
+ if (!ssl_acceptor_fd)
+ {
+ net_store_data(&packet2,"NONE" );
+ break;
+ }
+ switch(SSL_CTX_get_session_cache_mode(ssl_acceptor_fd->ssl_context_))
+ {
+ case SSL_SESS_CACHE_OFF:
+ net_store_data(&packet2,"OFF" );
+ break;
+ case SSL_SESS_CACHE_CLIENT:
+ net_store_data(&packet2,"CLIENT" );
+ break;
+ case SSL_SESS_CACHE_SERVER:
+ net_store_data(&packet2,"SERVER" );
+ break;
+ case SSL_SESS_CACHE_BOTH:
+ net_store_data(&packet2,"BOTH" );
+ break;
+ case SSL_SESS_CACHE_NO_AUTO_CLEAR:
+ net_store_data(&packet2,"NO_AUTO_CLEAR" );
+ break;
+ case SSL_SESS_CACHE_NO_INTERNAL_LOOKUP:
+ net_store_data(&packet2,"NO_INTERNAL_LOOKUP" );
+ break;
+ default:
+ net_store_data(&packet2,"Unknown");
+ break;
+ }
+ break;
+ /* First group - functions relying on SSL */
+ case SHOW_SSL_GET_VERSION:
+ net_store_data(&packet2, thd->net.vio->ssl_ ?
+ SSL_get_version(thd->net.vio->ssl_) : "");
+ break;
+ case SHOW_SSL_SESSION_REUSED:
+ net_store_data(&packet2,(uint32) (thd->net.vio->ssl_ ?
+ SSL_session_reused(thd->net.vio->ssl_) : 0));
+ break;
+ case SHOW_SSL_GET_DEFAULT_TIMEOUT:
+ net_store_data(&packet2,(uint32) (thd->net.vio->ssl_ ?
+ SSL_get_default_timeout(thd->net.vio->ssl_):0));
+ break;
+ case SHOW_SSL_GET_VERIFY_MODE:
+ net_store_data(&packet2,(uint32) (thd->net.vio->ssl_ ?
+ SSL_get_verify_mode(thd->net.vio->ssl_):0));
+ break;
+ case SHOW_SSL_GET_VERIFY_DEPTH:
+ net_store_data(&packet2,(uint32) (thd->net.vio->ssl_ ?
+ SSL_get_verify_depth(thd->net.vio->ssl_):0));
+ break;
+ case SHOW_SSL_GET_CIPHER:
+ net_store_data(&packet2, thd->net.vio->ssl_ ?
+ SSL_get_cipher(thd->net.vio->ssl_) : "");
+ break;
+ case SHOW_SSL_GET_CIPHER_LIST:
+ if (thd->net.vio->ssl_)
+ {
+ char buf[1024], *pos;
+ pos=buf;
+ for (int i=0 ; i++ ;)
+ {
+ const char *p=SSL_get_cipher_list(thd->net.vio->ssl_,i);
+ if (p == NULL)
+ break;
+ pos=strmov(pos, p);
+ *pos++= ':';
+ }
+ if (pos != buf)
+ pos--; // Remove last ':'
+ *pos=0;
+ net_store_data(&packet2, buf);
+ }
+ else
+ net_store_data(&packet2, "");
+ break;
+
+#endif /* HAVE_OPENSSL */
}
if (my_net_write(&thd->net, (char*) packet2.ptr(),packet2.length()))
goto err; /* purecov: inspected */
@@ -1177,6 +1368,6 @@ int mysqld_show(THD *thd, const char *wild, show_var_st *variables)
}
#ifdef __GNUC__
-template class List_iterator<char>;
+template class List_iterator_fast<char>;
template class List<char>;
#endif
diff --git a/sql/sql_sort.h b/sql/sql_sort.h
new file mode 100644
index 00000000000..62c5f1cb164
--- /dev/null
+++ b/sql/sql_sort.h
@@ -0,0 +1,55 @@
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+/* Defines used by filesort and uniques */
+
+#define MERGEBUFF 7
+#define MERGEBUFF2 15
+
+typedef struct st_buffpek { /* Struktur om sorteringsbuffrarna */
+ my_off_t file_pos; /* Where we are in the sort file */
+ uchar *base,*key; /* key pointers */
+ ha_rows count; /* Number of rows in table */
+ ulong mem_count; /* numbers of keys in memory */
+ ulong max_keys; /* Max keys in buffert */
+} BUFFPEK;
+
+
+typedef struct st_sort_param {
+ uint sort_length; /* Length of sort columns */
+ uint keys; /* Max keys / buffert */
+ uint ref_length; /* Length of record ref. */
+ ha_rows max_rows,examined_rows;
+ TABLE *sort_form; /* For quicker make_sortkey */
+ SORT_FIELD *local_sortorder;
+ SORT_FIELD *end;
+ uchar *unique_buff;
+ bool not_killable;
+#ifdef USE_STRCOLL
+ char* tmp_buffer;
+#endif
+} SORTPARAM;
+
+
+int merge_many_buff(SORTPARAM *param, uchar *sort_buffer,
+ BUFFPEK *buffpek,
+ uint *maxbuffer, IO_CACHE *t_file);
+uint read_to_buffer(IO_CACHE *fromfile,BUFFPEK *buffpek,
+ uint sort_length);
+int merge_buffers(SORTPARAM *param,IO_CACHE *from_file,
+ IO_CACHE *to_file, uchar *sort_buffer,
+ BUFFPEK *lastbuff,BUFFPEK *Fb,
+ BUFFPEK *Tb,int flag);
diff --git a/sql/sql_string.cc b/sql/sql_string.cc
index e6cdd089bf1..8fe84947ac2 100644
--- a/sql/sql_string.cc
+++ b/sql/sql_string.cc
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This program file is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 is originally from the mysql distribution. Coded by monty */
@@ -21,7 +20,7 @@
#pragma implementation // gcc: Class implementation
#endif
-#include <global.h>
+#include <my_global.h>
#include <my_sys.h>
#include <m_string.h>
#include <m_ctype.h>
@@ -362,6 +361,37 @@ skipp:
return -1;
}
+/*
+ Search after a string without regarding to case
+ This needs to be replaced when we have character sets per string
+*/
+
+int String::strstr_case(const String &s,uint32 offset)
+{
+ if (s.length()+offset <= str_length)
+ {
+ if (!s.length())
+ return ((int) offset); // Empty string is always found
+
+ register const char *str = Ptr+offset;
+ register const char *search=s.ptr();
+ const char *end=Ptr+str_length-s.length()+1;
+ const char *search_end=s.ptr()+s.length();
+skipp:
+ while (str != end)
+ {
+ if (my_sort_order[*str++] == my_sort_order[*search])
+ {
+ register char *i,*j;
+ i=(char*) str; j=(char*) search+1;
+ while (j != search_end)
+ if (my_sort_order[*i++] != my_sort_order[*j++]) goto skipp;
+ return (int) (str-Ptr) -1;
+ }
+ }
+ }
+ return -1;
+}
/*
** Search string from end. Offset is offset to the end of string
@@ -577,7 +607,7 @@ int wild_case_compare(const char *str,const char *str_end,
{
do
{
- if (str == str_end) // Skipp one char if possible
+ if (str == str_end) // Skip one char if possible
return (result);
INC_PTR(str,str_end);
} while (++wildstr < wildend && *wildstr == wild_one);
@@ -668,8 +698,11 @@ int wild_case_compare(const char *str,const char *str_end,
int wild_case_compare(String &match,String &wild, char escape)
{
- return wild_case_compare(match.ptr(),match.ptr()+match.length(),
- wild.ptr(), wild.ptr()+wild.length(),escape);
+ DBUG_ENTER("wild_case_compare");
+ DBUG_PRINT("enter",("match='%s', wild='%s', escape='%c'"
+ ,match.ptr(),wild.ptr(),escape));
+ DBUG_RETURN(wild_case_compare(match.ptr(),match.ptr()+match.length(),
+ wild.ptr(), wild.ptr()+wild.length(),escape));
}
/*
@@ -679,6 +712,9 @@ int wild_case_compare(String &match,String &wild, char escape)
int wild_compare(const char *str,const char *str_end,
const char *wildstr,const char *wildend,char escape)
{
+ DBUG_ENTER("wild_compare");
+ DBUG_PRINT("enter",("str='%s', str_end='%s', wildstr='%s', wildend='%s', escape='%c'"
+ ,str,str_end,wildstr,wildend,escape));
int result= -1; // Not found, using wildcards
while (wildstr != wildend)
{
@@ -687,17 +723,21 @@ int wild_compare(const char *str,const char *str_end,
if (*wildstr == escape && wildstr+1 != wildend)
wildstr++;
if (str == str_end || *wildstr++ != *str++)
- return(1);
+ {
+ DBUG_RETURN(1);
+ }
if (wildstr == wildend)
- return (str != str_end); // Match if both are at end
+ {
+ DBUG_RETURN(str != str_end); // Match if both are at end
+ }
result=1; // Found an anchor char
}
if (*wildstr == wild_one)
{
do
{
- if (str == str_end) // Skipp one char if possible
- return (result);
+ if (str == str_end) // Skip one char if possible
+ DBUG_RETURN(result);
str++;
} while (*++wildstr == wild_one && wildstr != wildend);
if (wildstr == wildend)
@@ -714,17 +754,22 @@ int wild_compare(const char *str,const char *str_end,
if (*wildstr == wild_one)
{
if (str == str_end)
- return (-1);
+ {
+ DBUG_RETURN(-1);
+ }
str++;
continue;
}
break; // Not a wild character
}
if (wildstr == wildend)
- return(0); // Ok if wild_many is last
+ {
+ DBUG_RETURN(0); // Ok if wild_many is last
+ }
if (str == str_end)
- return -1;
-
+ {
+ DBUG_RETURN(-1);
+ }
char cmp;
if ((cmp= *wildstr) == escape && wildstr+1 != wildend)
cmp= *++wildstr;
@@ -733,22 +778,30 @@ int wild_compare(const char *str,const char *str_end,
{
while (str != str_end && *str != cmp)
str++;
- if (str++ == str_end) return (-1);
+ if (str++ == str_end)
+ {
+ DBUG_RETURN(-1);
+ }
{
int tmp=wild_compare(str,str_end,wildstr,wildend,escape);
if (tmp <= 0)
- return (tmp);
+ {
+ DBUG_RETURN(tmp);
+ }
}
} while (str != str_end && wildstr[0] != wild_many);
- return(-1);
+ DBUG_RETURN(-1);
}
}
- return (str != str_end ? 1 : 0);
+ DBUG_RETURN(str != str_end ? 1 : 0);
}
int wild_compare(String &match,String &wild, char escape)
{
- return wild_compare(match.ptr(),match.ptr()+match.length(),
- wild.ptr(), wild.ptr()+wild.length(),escape);
+ DBUG_ENTER("wild_compare");
+ DBUG_PRINT("enter",("match='%s', wild='%s', escape='%c'"
+ ,match.ptr(),wild.ptr(),escape));
+ DBUG_RETURN(wild_compare(match.ptr(),match.ptr()+match.length(),
+ wild.ptr(), wild.ptr()+wild.length(),escape));
}
diff --git a/sql/sql_string.h b/sql/sql_string.h
index 31dea9991cc..ad7455ecbf1 100644
--- a/sql/sql_string.h
+++ b/sql/sql_string.h
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 is originally from the mysql distribution. Coded by monty */
@@ -161,6 +160,7 @@ public:
bool append(const char *s,uint32 arg_length=0);
bool append(IO_CACHE* file, uint32 arg_length);
int strstr(const String &search,uint32 offset=0); // Returns offset to substring or -1
+ int strstr_case(const String &s,uint32 offset=0);
int strrstr(const String &search,uint32 offset=0); // Returns offset to substring or -1
bool replace(uint32 offset,uint32 arg_length,const String &to);
inline bool append(char chr)
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 7b5fc5797c9..8013afa194b 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -26,6 +26,7 @@
#endif
extern HASH open_cache;
+static const char *primary_key_name="PRIMARY";
static bool check_if_keyname_exists(const char *name,KEY *start, KEY *end);
static char *make_unique_key_name(const char *field_name,KEY *start,KEY *end);
@@ -43,12 +44,7 @@ static int copy_data_between_tables(TABLE *from,TABLE *to,
int mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists)
{
- char path[FN_REFLEN];
- String wrong_tables;
- bool some_tables_deleted=0;
- uint error;
- db_type table_type;
- TABLE_LIST *table;
+ int error;
DBUG_ENTER("mysql_rm_table");
/* mark for close and remove all cached entries */
@@ -72,7 +68,35 @@ int mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists)
}
}
-
+ error=mysql_rm_table_part2(thd,tables,if_exists,0);
+
+ err:
+ VOID(pthread_cond_broadcast(&COND_refresh)); // Signal to refresh
+ pthread_mutex_unlock(&LOCK_open);
+
+ pthread_mutex_lock(&thd->mysys_var->mutex);
+ thd->mysys_var->current_mutex= 0;
+ thd->mysys_var->current_cond= 0;
+ pthread_mutex_unlock(&thd->mysys_var->mutex);
+
+ if (error)
+ DBUG_RETURN(-1);
+ send_ok(&thd->net);
+ DBUG_RETURN(0);
+}
+
+
+int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
+ bool dont_log_query)
+{
+ TABLE_LIST *table;
+ char path[FN_REFLEN];
+ String wrong_tables;
+ db_type table_type;
+ int error;
+ bool some_tables_deleted=0;
+ DBUG_ENTER("mysql_rm_table_part2");
+
for (table=tables ; table ; table=table->next)
{
char *db=table->db ? table->db : thd->db;
@@ -137,33 +161,25 @@ int mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists)
}
if (some_tables_deleted)
{
- mysql_update_log.write(thd, thd->query,thd->query_length);
- if (mysql_bin_log.is_open())
+ query_cache.invalidate(tables);
+ if (!dont_log_query)
{
- Query_log_event qinfo(thd, thd->query);
- mysql_bin_log.write(&qinfo);
+ mysql_update_log.write(thd, thd->query,thd->query_length);
+ if (mysql_bin_log.is_open())
+ {
+ Query_log_event qinfo(thd, thd->query);
+ mysql_bin_log.write(&qinfo);
+ }
}
}
-
- error = 0;
- err:
- VOID(pthread_cond_broadcast(&COND_refresh)); // Signal to refresh
- pthread_mutex_unlock(&LOCK_open);
-
- pthread_mutex_lock(&thd->mysys_var->mutex);
- thd->mysys_var->current_mutex= 0;
- thd->mysys_var->current_cond= 0;
- pthread_mutex_unlock(&thd->mysys_var->mutex);
+ error = 0;
if (wrong_tables.length())
{
my_error(ER_BAD_TABLE_ERROR,MYF(0),wrong_tables.c_ptr());
error=1;
}
- if(error)
- DBUG_RETURN(-1);
- send_ok(&thd->net);
- DBUG_RETURN(0);
+ DBUG_RETURN(error);
}
@@ -181,6 +197,52 @@ int quick_rm_table(enum db_type base,const char *db,
return ha_delete_table(base,path) || error;
}
+/*
+ Sort keys in the following order:
+ - PRIMARY KEY
+ - UNIQUE keyws where all column are NOT NULL
+ - Other UNIQUE keys
+ - Normal keys
+ - Fulltext keys
+
+ This will make checking for duplicated keys faster and ensure that
+ PRIMARY keys are prioritized.
+*/
+
+
+static int sort_keys(KEY *a, KEY *b)
+{
+ if (a->flags & HA_NOSAME)
+ {
+ if (!(b->flags & HA_NOSAME))
+ return -1;
+ if ((a->flags ^ b->flags) & HA_NULL_PART_KEY)
+ {
+ /* Sort NOT NULL keys before other keys */
+ return (a->flags & HA_NULL_PART_KEY) ? 1 : -1;
+ }
+ if (a->name == primary_key_name)
+ return -1;
+ if (b->name == primary_key_name)
+ return 1;
+ }
+ else if (b->flags & HA_NOSAME)
+ return 1; // Prefer b
+
+ if ((a->flags ^ b->flags) & HA_FULLTEXT)
+ {
+ return (a->flags & HA_FULLTEXT) ? 1 : -1;
+ }
+ /*
+ Prefer original key order. usable_key_parts contains here
+ the original key position.
+ */
+ return ((a->usable_key_parts < b->usable_key_parts) ? -1 :
+ (a->usable_key_parts > b->usable_key_parts) ? 1 :
+ 0);
+}
+
+
/*****************************************************************************
* Create a table.
* If one creates a temporary table, this is automaticly opened
@@ -336,10 +398,9 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
List_iterator<Key> key_iterator(keys);
uint key_parts=0,key_count=keys.elements;
List<Key> keys_in_order; // Add new keys here
- Key *primary_key=0;
- bool unique_key=0;
+ bool primary_key=0,unique_key=0;
Key *key;
- uint tmp;
+ uint tmp, key_number;
tmp=min(file->max_keys(), MAX_KEY);
if (key_count > tmp)
{
@@ -347,12 +408,7 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
DBUG_RETURN(-1);
}
- /*
- Check keys;
- Put PRIMARY KEY first, then UNIQUE keys and other keys last
- This will make checking for duplicated keys faster and ensure that
- primary keys are prioritized.
- */
+ /* Calculate number of key segements */
while ((key=key_iterator++))
{
@@ -368,33 +424,6 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
DBUG_RETURN(-1);
}
key_parts+=key->columns.elements;
- if (key->type == Key::PRIMARY)
- {
- if (primary_key)
- {
- my_error(ER_MULTIPLE_PRI_KEY,MYF(0));
- DBUG_RETURN(-1);
- }
- primary_key=key;
- }
- else if (key->type == Key::UNIQUE)
- {
- unique_key=1;
- if (keys_in_order.push_front(key))
- DBUG_RETURN(-1);
- }
- else if (keys_in_order.push_back(key))
- DBUG_RETURN(-1);
- }
- if (primary_key)
- {
- if (keys_in_order.push_front(primary_key))
- DBUG_RETURN(-1);
- }
- else if (!unique_key && (file->option_flag() & HA_REQUIRE_PRIMARY_KEY))
- {
- my_error(ER_REQUIRES_PRIMARY_KEY,MYF(0));
- DBUG_RETURN(-1);
}
key_info_buffer=key_info=(KEY*) sql_calloc(sizeof(KEY)*key_count);
@@ -402,8 +431,9 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
if (!key_info_buffer || ! key_part_info)
DBUG_RETURN(-1); // Out of memory
- List_iterator<Key> key_iterator_in_order(keys_in_order);
- for (; (key=key_iterator_in_order++) ; key_info++)
+ key_iterator.rewind();
+ key_number=0;
+ for (; (key=key_iterator++) ; key_info++, key_number++)
{
uint key_length=0;
key_part_spec *column;
@@ -412,10 +442,11 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
(key->type == Key::FULLTEXT) ? HA_FULLTEXT : HA_NOSAME;
key_info->key_parts=(uint8) key->columns.elements;
key_info->key_part=key_part_info;
+ key_info->usable_key_parts= key_number;
if (key->type == Key::FULLTEXT)
{
- if (file->option_flag() & HA_NO_FULLTEXT_KEY)
+ if (!(file->option_flag() & HA_CAN_FULLTEXT))
{
my_error(ER_TABLE_CANT_HANDLE_FULLTEXT, MYF(0));
DBUG_RETURN(-1);
@@ -471,6 +502,7 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
MYF(0),column->field_name);
DBUG_RETURN(-1);
}
+ key_info->flags|= HA_NULL_PART_KEY;
}
if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER)
{
@@ -530,7 +562,15 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
if (column_nr == 0)
{
if (key->type == Key::PRIMARY)
- key_name="PRIMARY";
+ {
+ if (primary_key)
+ {
+ my_error(ER_MULTIPLE_PRI_KEY,MYF(0));
+ DBUG_RETURN(-1);
+ }
+ key_name=primary_key_name;
+ primary_key=1;
+ }
else if (!(key_name = key->name()))
key_name=make_unique_key_name(sql_field->field_name,
key_info_buffer,key_info);
@@ -542,18 +582,29 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
key_info->name=(char*) key_name;
}
}
+ if (!(key_info->flags & HA_NULL_PART_KEY))
+ unique_key=1;
key_info->key_length=(uint16) key_length;
- if (key_length > file->max_key_length() && key->type != Key::FULLTEXT)
+ uint max_key_length= max(file->max_key_length(), MAX_KEY_LENGTH);
+ if (key_length > max_key_length && key->type != Key::FULLTEXT)
{
- my_error(ER_TOO_LONG_KEY,MYF(0),file->max_key_length());
+ my_error(ER_TOO_LONG_KEY,MYF(0),max_key_length);
DBUG_RETURN(-1);
}
}
+ if (!unique_key && !primary_key &&
+ (file->option_flag() & HA_REQUIRE_PRIMARY_KEY))
+ {
+ my_error(ER_REQUIRES_PRIMARY_KEY,MYF(0));
+ DBUG_RETURN(-1);
+ }
if (auto_increment > 0)
{
my_error(ER_WRONG_AUTO_KEY,MYF(0));
DBUG_RETURN(-1);
}
+ /* Sort keys in optimized order */
+ qsort((gptr) key_info_buffer, key_count, sizeof(KEY), (qsort_cmp) sort_keys);
/* Check if table exists */
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
@@ -670,7 +721,7 @@ TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info,
DBUG_ENTER("create_table_from_items");
/* Add selected items to field list */
- List_iterator<Item> it(*items);
+ List_iterator_fast<Item> it(*items);
Item *item;
Field *tmp_field;
tmp_table.db_create_options=0;
@@ -688,8 +739,11 @@ TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info,
my_error(ER_WRONG_COLUMN_NAME,MYF(0),item->name);
DBUG_RETURN(0);
}
-
- Field *field=create_tmp_field(&tmp_table,item,item->type(),
+ Field *field;
+ if (item->type() == Item::FUNC_ITEM)
+ field=item->tmp_table_field(&tmp_table);
+ else
+ field=create_tmp_field(thd, &tmp_table, item, item->type(),
(Item_result_field***) 0, &tmp_field,0,0);
if (!field ||
!(cr_field=new create_field(field,(item->type() == Item::FIELD_ITEM ?
@@ -833,61 +887,46 @@ static int prepare_for_restore(THD* thd, TABLE_LIST* table)
char* table_name = table->name;
char* db = thd->db ? thd->db : table->db;
- if (!fn_format(src_path, table_name, backup_dir, reg_ext, 4 + 64))
+ if (fn_format_relative_to_data_home(src_path, table_name, backup_dir,
+ reg_ext))
DBUG_RETURN(-1); // protect buffer overflow
sprintf(dst_path, "%s/%s/%s", mysql_real_data_home, db, table_name);
- int lock_retcode;
- pthread_mutex_lock(&LOCK_open);
- if ((lock_retcode = lock_table_name(thd, table)) < 0)
- {
- pthread_mutex_unlock(&LOCK_open);
- DBUG_RETURN(-1);
- }
-
- if (lock_retcode && wait_for_locked_table_names(thd, table))
- {
- unlock_table_name(thd, table);
- pthread_mutex_unlock(&LOCK_open);
+ if (lock_and_wait_for_table_name(thd,table))
DBUG_RETURN(-1);
- }
- pthread_mutex_unlock(&LOCK_open);
if (my_copy(src_path,
- fn_format(dst_path, dst_path,"",
- reg_ext, 4),
- MYF(MY_WME)))
+ fn_format(dst_path, dst_path,"", reg_ext, 4),
+ MYF(MY_WME)))
{
unlock_table_name(thd, table);
DBUG_RETURN(send_check_errmsg(thd, table, "restore",
"Failed copying .frm file"));
}
- bool save_no_send_ok = thd->net.no_send_ok;
- thd->net.no_send_ok = 1;
- // generate table will try to send OK which messes up the output
- // for the client
-
- if (generate_table(thd, table, 0))
+ if (mysql_truncate(thd, table, 1))
{
unlock_table_name(thd, table);
- thd->net.no_send_ok = save_no_send_ok;
DBUG_RETURN(send_check_errmsg(thd, table, "restore",
"Failed generating table from .frm file"));
}
-
- thd->net.no_send_ok = save_no_send_ok;
}
+ // now we should be able to open the partially restored table
+ // to finish the restore in the handler later on
+ if (!(table->table = reopen_name_locked_table(thd, table)))
+ unlock_table_name(thd, table);
DBUG_RETURN(0);
}
+
static int mysql_admin_table(THD* thd, TABLE_LIST* tables,
HA_CHECK_OPT* check_opt,
const char *operator_name,
thr_lock_type lock_type,
- bool open_for_modify, bool restore,
+ bool open_for_modify,
uint extra_open_options,
+ int (*prepare_func)(THD *, TABLE_LIST *),
int (handler::*operator_func)
(THD *, HA_CHECK_OPT *))
{
@@ -919,18 +958,13 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables,
table->table = open_ltable(thd, table, lock_type);
thd->open_options&= ~extra_open_options;
packet->length(0);
- if (restore)
+ if (prepare_func)
{
- switch (prepare_for_restore(thd, table)) {
- case 1: continue; // error, message written to net
- case -1: goto err; // error, message could be written to net
- default: ;// should be 0 otherwise
+ switch ((*prepare_func)(thd, table)) {
+ case 1: continue; // error, message written to net
+ case -1: goto err; // error, message could be written to net
+ default: ; // should be 0 otherwise
}
-
- // now we should be able to open the partially restored table
- // to finish the restore in the handler later on
- if (!(table->table = reopen_name_locked_table(thd, table)))
- unlock_table_name(thd, table);
}
if (!table->table)
@@ -957,6 +991,7 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables,
sprintf(buff, ER(ER_OPEN_AS_READONLY), table_name);
net_store_data(packet, buff);
close_thread_tables(thd);
+ table->table=0; // For query cache
if (my_net_write(&thd->net, (char*) thd->packet.ptr(),
packet->length()))
goto err;
@@ -1034,6 +1069,7 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables,
remove_table_from_cache(thd, table->table->table_cache_key,
table->table->real_name);
close_thread_tables(thd);
+ table->table=0; // For query cache
if (my_net_write(&thd->net, (char*) packet->ptr(),
packet->length()))
goto err;
@@ -1043,9 +1079,12 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables,
DBUG_RETURN(0);
err:
close_thread_tables(thd); // Shouldn't be needed
+ if (table)
+ table->table=0;
DBUG_RETURN(-1);
}
+
int mysql_backup_table(THD* thd, TABLE_LIST* table_list)
{
DBUG_ENTER("mysql_backup_table");
@@ -1058,7 +1097,8 @@ int mysql_restore_table(THD* thd, TABLE_LIST* table_list)
{
DBUG_ENTER("mysql_restore_table");
DBUG_RETURN(mysql_admin_table(thd, table_list, 0,
- "restore", TL_WRITE, 1, 1,0,
+ "restore", TL_WRITE, 1, 0,
+ &prepare_for_restore,
&handler::restore));
}
@@ -1066,7 +1106,7 @@ int mysql_repair_table(THD* thd, TABLE_LIST* tables, HA_CHECK_OPT* check_opt)
{
DBUG_ENTER("mysql_repair_table");
DBUG_RETURN(mysql_admin_table(thd, tables, check_opt,
- "repair", TL_WRITE, 1, 0, HA_OPEN_FOR_REPAIR,
+ "repair", TL_WRITE, 1, HA_OPEN_FOR_REPAIR, 0,
&handler::repair));
}
@@ -1105,7 +1145,7 @@ int mysql_check_table(THD* thd, TABLE_LIST* tables,HA_CHECK_OPT* check_opt)
DBUG_ENTER("mysql_check_table");
DBUG_RETURN(mysql_admin_table(thd, tables, check_opt,
"check", lock_type,
- 0, 0, HA_OPEN_FOR_REPAIR,
+ 0, HA_OPEN_FOR_REPAIR, 0,
&handler::check));
}
@@ -1118,16 +1158,19 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
List<Alter_column> &alter_list,
ORDER *order,
bool drop_primary,
- enum enum_duplicates handle_duplicates)
+ enum enum_duplicates handle_duplicates,
+ enum enum_enable_or_disable keys_onoff,
+ bool simple_alter)
{
TABLE *table,*new_table;
int error;
char tmp_name[80],old_name[32],new_name_buff[FN_REFLEN],
- *table_name,*db;
+ *table_name,*db;
+ char index_file[FN_REFLEN], data_file[FN_REFLEN];
bool use_timestamp=0;
ha_rows copied,deleted;
ulonglong next_insert_id;
- uint save_time_stamp,db_create_options;
+ uint save_time_stamp,db_create_options, used_fields;
enum db_type old_db_type,new_db_type;
DBUG_ENTER("mysql_alter_table");
@@ -1136,6 +1179,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
db=table_list->db;
if (!new_db)
new_db=db;
+ used_fields=create_info->used_fields;
if (!(table=open_ltable(thd,table_list,TL_WRITE_ALLOW_READ)))
DBUG_RETURN(-1);
@@ -1181,42 +1225,49 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
if (create_info->db_type == DB_TYPE_DEFAULT)
create_info->db_type=old_db_type;
new_db_type=create_info->db_type= ha_checktype(create_info->db_type);
- if (create_info->row_type == ROW_TYPE_DEFAULT)
+ if (create_info->row_type == ROW_TYPE_NOT_USED)
create_info->row_type=table->row_type;
- /* Check if the user only wants to do a simple RENAME */
+ /* In some simple cases we need not to recreate the table */
thd->proc_info="setup";
- if (new_name != table_name &&
- !fields.elements && !keys.elements && ! drop_list.elements &&
- !alter_list.elements && !drop_primary &&
- new_db_type == old_db_type && create_info->max_rows == 0 &&
- create_info->auto_increment_value == 0 && !table->tmp_table)
+ if (simple_alter)
{
- thd->proc_info="rename";
- VOID(pthread_mutex_lock(&LOCK_open));
- /* Then do a 'simple' rename of the table */
error=0;
- if (!access(new_name_buff,F_OK))
- {
- my_error(ER_TABLE_EXISTS_ERROR,MYF(0),new_name);
- error= -1;
- }
- else
+ if (new_name != table_name)
{
- *fn_ext(new_name)=0;
- close_cached_table(thd,table);
- if (mysql_rename_table(old_db_type,db,table_name,new_db,new_name))
- error= -1;
+ thd->proc_info="rename";
+ VOID(pthread_mutex_lock(&LOCK_open));
+ /* Then do a 'simple' rename of the table */
+ error=0;
+ if (!access(new_name_buff,F_OK))
+ {
+ my_error(ER_TABLE_EXISTS_ERROR,MYF(0),new_name);
+ error= -1;
+ }
+ else
+ {
+ *fn_ext(new_name)=0;
+ close_cached_table(thd,table);
+ if (mysql_rename_table(old_db_type,db,table_name,new_db,new_name))
+ error= -1;
+ }
+ VOID(pthread_cond_broadcast(&COND_refresh));
+ VOID(pthread_mutex_unlock(&LOCK_open));
}
- if (!error && (error=ha_commit_rename(thd)))
+ if (!error)
{
- my_error(ER_GET_ERRNO,MYF(0),error);
- error=1;
+ switch (keys_onoff)
+ {
+ case LEAVE_AS_IS: break;
+ case ENABLE:
+ error=table->file->activate_all_index(thd);
+ break;
+ case DISABLE:
+ table->file->deactivate_non_unique_index(HA_POS_ERROR);
+ break;
+ }
}
-
- VOID(pthread_cond_broadcast(&COND_refresh));
- VOID(pthread_mutex_unlock(&LOCK_open));
if (!error)
{
mysql_update_log.write(thd, thd->query, thd->query_length);
@@ -1227,7 +1278,6 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
}
send_ok(&thd->net);
}
-
DBUG_RETURN(error);
}
@@ -1257,7 +1307,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
{
/* Reset auto_increment value if it was dropped */
if (MTYP_TYPENR(field->unireg_check) == Field::NEXT_NUMBER &&
- !(create_info->used_fields & HA_CREATE_USED_AUTO))
+ !(used_fields & HA_CREATE_USED_AUTO))
{
create_info->auto_increment_value=0;
create_info->used_fields|=HA_CREATE_USED_AUTO;
@@ -1282,8 +1332,11 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
def->field=field;
if (def->sql_type == FIELD_TYPE_TIMESTAMP)
use_timestamp=1;
- create_list.push_back(def);
- def_it.remove();
+ if (!def->after)
+ {
+ create_list.push_back(def);
+ def_it.remove();
+ }
}
else
{ // Use old field value
@@ -1314,7 +1367,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
List_iterator<create_field> find_it(create_list);
while ((def=def_it++)) // Add new columns
{
- if (def->change)
+ if (def->change && ! def->field)
{
my_error(ER_BAD_FIELD_ERROR,MYF(0),def->change,table_name);
DBUG_RETURN(-1);
@@ -1443,20 +1496,25 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
goto err;
}
+ db_create_options=table->db_create_options & ~(HA_OPTION_PACK_RECORD);
(void) sprintf(tmp_name,"%s-%lx_%lx", tmp_file_prefix, current_pid,
thd->thread_id);
create_info->db_type=new_db_type;
- if (!create_info->max_rows)
- create_info->max_rows=table->max_rows;
- if (!create_info->avg_row_length)
- create_info->avg_row_length=table->avg_row_length;
- table->file->update_create_info(create_info);
if (!create_info->comment)
create_info->comment=table->comment;
+
/* let new create options override the old ones */
- db_create_options=table->db_create_options & ~(HA_OPTION_PACK_RECORD);
- if (create_info->table_options &
- (HA_OPTION_PACK_KEYS | HA_OPTION_NO_PACK_KEYS))
+ if (!(used_fields & HA_CREATE_USED_MIN_ROWS))
+ create_info->min_rows=table->min_rows;
+ if (!(used_fields & HA_CREATE_USED_MAX_ROWS))
+ create_info->max_rows=table->max_rows;
+ if (!(used_fields & HA_CREATE_USED_AVG_ROW_LENGTH))
+ create_info->avg_row_length=table->avg_row_length;
+
+ table->file->update_create_info(create_info);
+ if ((create_info->table_options &
+ (HA_OPTION_PACK_KEYS | HA_OPTION_NO_PACK_KEYS)) ||
+ (used_fields & HA_CREATE_USED_PACK_KEYS))
db_create_options&= ~(HA_OPTION_PACK_KEYS | HA_OPTION_NO_PACK_KEYS);
if (create_info->table_options &
(HA_OPTION_CHECKSUM | HA_OPTION_NO_CHECKSUM))
@@ -1470,6 +1528,53 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
if (table->tmp_table)
create_info->options|=HA_LEX_CREATE_TMP_TABLE;
+ /*
+ Handling of symlinked tables:
+ If no rename:
+ Create new data file and index file on the same disk as the
+ old data and index files.
+ Copy data.
+ Rename new data file over old data file and new index file over
+ old index file.
+ Symlinks are not changed.
+
+ If rename:
+ Create new data file and index file on the same disk as the
+ old data and index files. Create also symlinks to point at
+ the new tables.
+ Copy data.
+ At end, rename temporary tables and symlinks to temporary table
+ to final table name.
+ Remove old table and old symlinks
+
+ If rename is made to another database:
+ Create new tables in new database.
+ Copy data.
+ Remove old table and symlinks.
+ */
+
+ if (!strcmp(db, new_db)) // Ignore symlink if db changed
+ {
+ if (create_info->index_file_name)
+ {
+ /* Fix index_file_name to have 'tmp_name' as basename */
+ strmov(index_file, tmp_name);
+ create_info->index_file_name=fn_same(index_file,
+ create_info->index_file_name,
+ 1);
+ }
+ if (create_info->data_file_name)
+ {
+ /* Fix data_file_name to have 'tmp_name' as basename */
+ strmov(data_file, tmp_name);
+ create_info->data_file_name=fn_same(data_file,
+ create_info->data_file_name,
+ 1);
+ }
+ }
+ else
+ create_info->data_file_name=create_info->index_file_name=0;
+
if ((error=mysql_create_table(thd, new_db, tmp_name,
create_info,
create_list,key_list,1,1))) // no logging
@@ -1608,24 +1713,30 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
}
if (error)
{
- // This shouldn't happen. We solve this the safe way by
- // closing the locked table.
+ /*
+ This shouldn't happen. We solve this the safe way by
+ closing the locked table.
+ */
close_cached_table(thd,table);
VOID(pthread_mutex_unlock(&LOCK_open));
goto err;
}
if (thd->lock || new_name != table_name) // True if WIN32
{
- // Not table locking or alter table with rename
- // free locks and remove old table
+ /*
+ Not table locking or alter table with rename
+ free locks and remove old table
+ */
close_cached_table(thd,table);
VOID(quick_rm_table(old_db_type,db,old_name));
}
else
{
- // Using LOCK TABLES without rename.
- // This code is never executed on WIN32!
- // Remove old renamed table, reopen table and get new locks
+ /*
+ Using LOCK TABLES without rename.
+ This code is never executed on WIN32!
+ Remove old renamed table, reopen table and get new locks
+ */
if (table)
{
VOID(table->file->extra(HA_EXTRA_FORCE_REOPEN)); // Use new file
@@ -1662,6 +1773,8 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
}
VOID(pthread_cond_broadcast(&COND_refresh));
VOID(pthread_mutex_unlock(&LOCK_open));
+ table_list->table=0; // For query cache
+ query_cache.invalidate(table_list);
end_temporary:
sprintf(tmp_name,ER(ER_INSERT_INFO),(ulong) (copied+deleted),
@@ -1671,7 +1784,6 @@ end_temporary:
DBUG_RETURN(0);
err:
- (void) ha_commit_rename(thd); // Just for safety
DBUG_RETURN(-1);
}
@@ -1730,8 +1842,8 @@ copy_data_between_tables(TABLE *from,TABLE *to,
if (setup_order(thd, &tables, fields, all_fields, order) ||
!(sortorder=make_unireg_sortorder(order, &length)) ||
- (from->found_records = filesort(&from, sortorder, length,
- (SQL_SELECT *) 0, 0L, HA_POS_ERROR,
+ (from->found_records = filesort(from, sortorder, length,
+ (SQL_SELECT *) 0, 0L, HA_POS_ERROR,
&examined_rows))
== HA_POS_ERROR)
goto err;
@@ -1781,7 +1893,7 @@ copy_data_between_tables(TABLE *from,TABLE *to,
}
end_read_record(&info);
free_io_cache(from);
- delete [] copy;
+ delete [] copy; // This is never 0
uint tmp_error;
if ((tmp_error=to->file->extra(HA_EXTRA_NO_CACHE)))
{
diff --git a/sql/sql_test.cc b/sql/sql_test.cc
index c4c2855a63e..43c24da85a2 100644
--- a/sql/sql_test.cc
+++ b/sql/sql_test.cc
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -96,8 +96,7 @@ void print_cached_tables(void)
}
-void TEST_filesort(TABLE **table,SORT_FIELD *sortorder,uint s_length,
- ha_rows special)
+void TEST_filesort(SORT_FIELD *sortorder,uint s_length, ha_rows special)
{
char buff[256],buff2[256];
String str(buff,sizeof(buff)),out(buff2,sizeof(buff2));
diff --git a/sql/sql_udf.cc b/sql/sql_udf.cc
index 8184ae3b15e..9493f969802 100644
--- a/sql/sql_udf.cc
+++ b/sql/sql_udf.cc
@@ -1,21 +1,19 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+/* Copyright (C) 2000 MySQL AB
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-
/* This implements 'user defined functions' */
/*
@@ -52,11 +50,11 @@ extern "C"
{
FreeLibrary((HMODULE)lib);
}
-
+
#elif !defined(OS2)
#include <dlfcn.h>
#endif
-
+
#include <stdarg.h>
#include <hash.h>
}
@@ -141,7 +139,8 @@ void udf_init()
new_thd->version = refresh_version; //current_thd->version;
new_thd->current_tablenr = 0;
new_thd->open_tables = 0;
- new_thd->db = my_strdup("mysql", MYF(0));
+ new_thd->db= my_strdup("mysql", MYF(0));
+ new_thd->db_length=5;
bzero((gptr) &tables,sizeof(tables));
tables.name = tables.real_name = (char*) "func";
diff --git a/sql/sql_udf.h b/sql/sql_udf.h
index d0b20f0a734..1ee9c44ce48 100644
--- a/sql/sql_udf.h
+++ b/sql/sql_udf.h
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
diff --git a/sql/sql_union.cc b/sql/sql_union.cc
new file mode 100644
index 00000000000..0d8a41e9966
--- /dev/null
+++ b/sql/sql_union.cc
@@ -0,0 +1,254 @@
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+
+/*
+ UNION of select's
+ UNION's were introduced by Monty and Sinisa <sinisa@mysql.com>
+*/
+
+
+#include "mysql_priv.h"
+#include "sql_select.h"
+
+
+int mysql_union(THD *thd, LEX *lex,select_result *result)
+{
+ SELECT_LEX *sl, *last_sl, *lex_sl;
+ ORDER *order;
+ List<Item> item_list;
+ TABLE *table;
+ TABLE_LIST result_table_list;
+ TMP_TABLE_PARAM tmp_table_param;
+ select_union *union_result;
+ int res;
+ DBUG_ENTER("mysql_union");
+
+ /* Fix tables 'to-be-unioned-from' list to point at opened tables */
+ last_sl= &lex->select_lex;
+ for (sl= last_sl;
+ sl && sl->linkage != NOT_A_SELECT;
+ last_sl=sl, sl=sl->next)
+ {
+ for (TABLE_LIST *cursor= (TABLE_LIST *)sl->table_list.first;
+ cursor;
+ cursor=cursor->next)
+ cursor->table= ((TABLE_LIST*) cursor->table)->table;
+ }
+
+ /* last_sel now points at the last select where the ORDER BY is stored */
+ if (sl)
+ {
+ /*
+ The found SL is an extra SELECT_LEX argument that contains
+ the ORDER BY and LIMIT parameter for the whole UNION
+ */
+ lex_sl= sl;
+ last_sl->next=0; // Remove this extra element
+ order= (ORDER *) lex_sl->order_list.first;
+ }
+ else if (!last_sl->braces)
+ {
+ lex_sl= last_sl; // ORDER BY is here
+ order= (ORDER *) lex_sl->order_list.first;
+ }
+ else
+ {
+ lex_sl=0;
+ order=0;
+ }
+
+ if (lex->select_lex.options & SELECT_DESCRIBE)
+ {
+ for (sl= &lex->select_lex; sl; sl=sl->next)
+ {
+ lex->select=sl;
+ res=mysql_select(thd, (TABLE_LIST*) sl->table_list.first,
+ sl->item_list,
+ sl->where,
+ ((sl->braces) ?
+ (ORDER *) sl->order_list.first : (ORDER *) 0),
+ (ORDER*) sl->group_list.first,
+ sl->having,
+ (ORDER*) NULL,
+ (sl->options | thd->options | SELECT_NO_UNLOCK |
+ SELECT_DESCRIBE),
+ result);
+ }
+ DBUG_RETURN(0);
+ }
+
+ {
+ Item *item;
+ List_iterator<Item> it(lex->select_lex.item_list);
+ TABLE_LIST *first_table= (TABLE_LIST*) lex->select_lex.table_list.first;
+
+ /* Create a list of items that will be in the result set */
+ while ((item= it++))
+ if (item_list.push_back(item))
+ DBUG_RETURN(-1);
+ if (setup_fields(thd,first_table,item_list,0,0,1))
+ DBUG_RETURN(-1);
+ }
+
+ bzero((char*) &tmp_table_param,sizeof(tmp_table_param));
+ tmp_table_param.field_count=item_list.elements;
+ if (!(table=create_tmp_table(thd, &tmp_table_param, item_list,
+ (ORDER*) 0, !lex->union_option,
+ 1, 0,
+ (lex->select_lex.options | thd->options |
+ TMP_TABLE_ALL_COLUMNS))))
+ DBUG_RETURN(-1);
+ table->file->extra(HA_EXTRA_WRITE_CACHE);
+ table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
+ bzero((char*) &result_table_list,sizeof(result_table_list));
+ result_table_list.db= (char*) "";
+ result_table_list.real_name=result_table_list.name=(char*) "union";
+ result_table_list.table=table;
+
+ if (!(union_result=new select_union(table)))
+ {
+ res= -1;
+ goto exit;
+ }
+ for (sl= &lex->select_lex; sl; sl=sl->next)
+ {
+ thd->offset_limit=sl->offset_limit;
+ thd->select_limit=sl->select_limit+sl->offset_limit;
+ if (thd->select_limit < sl->select_limit)
+ thd->select_limit= HA_POS_ERROR; // no limit
+ if (thd->select_limit == HA_POS_ERROR)
+ sl->options&= ~OPTION_FOUND_ROWS;
+
+ res=mysql_select(thd, (TABLE_LIST*) sl->table_list.first,
+ sl->item_list,
+ sl->where,
+ (sl->braces) ? (ORDER *)sl->order_list.first : (ORDER *) 0,
+ (ORDER*) sl->group_list.first,
+ sl->having,
+ (ORDER*) NULL,
+ sl->options | thd->options | SELECT_NO_UNLOCK,
+ union_result);
+ if (res)
+ goto exit;
+ }
+ if (union_result->flush())
+ {
+ res= 1; // Error is already sent
+ goto exit;
+ }
+ delete union_result;
+
+ /* Send result to 'result' */
+ res =-1;
+ {
+ /* Create a list of fields in the temporary table */
+ List_iterator<Item> it(item_list);
+ Field **field;
+#if 0
+ List<Item_func_match> ftfunc_list;
+ ftfunc_list.empty();
+#else
+ thd->lex.select_lex.ftfunc_list.empty();
+#endif
+
+ for (field=table->field ; *field ; field++)
+ {
+ (void) it++;
+ (void) it.replace(new Item_field(*field));
+ }
+ if (!thd->fatal_error) // Check if EOM
+ {
+ if (lex_sl)
+ {
+ thd->offset_limit=lex_sl->offset_limit;
+ thd->select_limit=lex_sl->select_limit+lex_sl->offset_limit;
+ if (thd->select_limit < lex_sl->select_limit)
+ thd->select_limit= HA_POS_ERROR; // no limit
+ if (thd->select_limit == HA_POS_ERROR)
+ thd->options&= ~OPTION_FOUND_ROWS;
+ }
+ res=mysql_select(thd,&result_table_list,
+ item_list, NULL, /*ftfunc_list,*/ order,
+ (ORDER*) NULL, NULL, (ORDER*) NULL,
+ thd->options, result);
+ }
+ }
+
+exit:
+ free_tmp_table(thd,table);
+ DBUG_RETURN(res);
+}
+
+
+/***************************************************************************
+** store records in temporary table for UNION
+***************************************************************************/
+
+select_union::select_union(TABLE *table_par)
+ :table(table_par)
+{
+ bzero((char*) &info,sizeof(info));
+ /*
+ We can always use DUP_IGNORE because the temporary table will only
+ contain a unique key if we are using not using UNION ALL
+ */
+ info.handle_duplicates=DUP_IGNORE;
+}
+
+select_union::~select_union()
+{
+}
+
+
+int select_union::prepare(List<Item> &list)
+{
+ if (list.elements != table->fields)
+ {
+ my_message(ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT,
+ ER(ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT),MYF(0));
+ return -1;
+ }
+ return 0;
+}
+
+bool select_union::send_data(List<Item> &values)
+{
+ if (thd->offset_limit)
+ { // using limit offset,count
+ thd->offset_limit--;
+ return 0;
+ }
+ fill_record(table->field,values);
+ return write_record(table,&info) ? 1 : 0;
+}
+
+bool select_union::send_eof()
+{
+ return 0;
+}
+
+bool select_union::flush()
+{
+ int error;
+ if ((error=table->file->extra(HA_EXTRA_NO_CACHE)))
+ {
+ table->file->print_error(error,MYF(0));
+ ::send_error(&thd->net);
+ return 1;
+ }
+ return 0;
+}
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index e5e246b3962..6c868b542d1 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -1,24 +1,29 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-/* Update of records */
+/* Update of records
+
+ Multi-table updates were introduced by Monty and Sinisa <sinisa@mysql.com>
+
+*/
#include "mysql_priv.h"
#include "sql_acl.h"
+#include "sql_select.h"
/* Return 0 if row hasn't changed */
@@ -40,8 +45,12 @@ static bool compare_record(TABLE *table, ulong query_id)
}
-int mysql_update(THD *thd,TABLE_LIST *table_list,List<Item> &fields,
- List<Item> &values, COND *conds,
+int mysql_update(THD *thd,
+ TABLE_LIST *table_list,
+ List<Item> &fields,
+ List<Item> &values,
+ COND *conds,
+ ORDER *order,
ha_rows limit,
enum enum_duplicates handle_duplicates,
thr_lock_type lock_type)
@@ -87,7 +96,7 @@ int mysql_update(THD *thd,TABLE_LIST *table_list,List<Item> &fields,
/* Check the fields we are going to modify */
table->grant.want_privilege=want_privilege;
- if (setup_fields(thd,table_list,fields,1,0))
+ if (setup_fields(thd,table_list,fields,1,0,0))
DBUG_RETURN(-1); /* purecov: inspected */
if (table->timestamp_field)
{
@@ -100,7 +109,7 @@ int mysql_update(THD *thd,TABLE_LIST *table_list,List<Item> &fields,
/* Check values */
table->grant.want_privilege=(SELECT_ACL & ~table->grant.privilege);
- if (setup_fields(thd,table_list,values,0,0))
+ if (setup_fields(thd,table_list,values,0,0,0))
{
table->time_stamp=save_time_stamp; // Restore timestamp pointer
DBUG_RETURN(-1); /* purecov: inspected */
@@ -126,7 +135,7 @@ int mysql_update(THD *thd,TABLE_LIST *table_list,List<Item> &fields,
/* If running in safe sql mode, don't allow updates without keys */
if (!table->quick_keys)
{
- thd->lex.options|=QUERY_NO_INDEX_USED;
+ thd->lex.select_lex.options|=QUERY_NO_INDEX_USED;
if ((thd->options & OPTION_SAFE_UPDATES) && limit == HA_POS_ERROR)
{
delete select;
@@ -146,7 +155,7 @@ int mysql_update(THD *thd,TABLE_LIST *table_list,List<Item> &fields,
used_key_is_modified=check_if_key_used(table, used_index, fields);
else
used_key_is_modified=0;
- if (used_key_is_modified)
+ if (used_key_is_modified || order)
{
/*
** We can't update table directly; We must first search after all
@@ -166,8 +175,36 @@ int mysql_update(THD *thd,TABLE_LIST *table_list,List<Item> &fields,
table->key_read=1;
table->file->extra(HA_EXTRA_KEYREAD);
}
+
+ if (order)
+ {
+ uint length;
+ SORT_FIELD *sortorder;
+ TABLE_LIST tables;
+ List<Item> fields;
+ List<Item> all_fields;
+ ha_rows examined_rows;
+
+ bzero((char*) &tables,sizeof(tables));
+ tables.table = table;
+
+ table->io_cache = (IO_CACHE *) my_malloc(sizeof(IO_CACHE),
+ MYF(MY_FAE | MY_ZEROFILL));
+ if (setup_order(thd, &tables, fields, all_fields, order) ||
+ !(sortorder=make_unireg_sortorder(order, &length)) ||
+ (table->found_records = filesort(table, sortorder, length,
+ (SQL_SELECT *) 0, 0L,
+ HA_POS_ERROR, &examined_rows))
+ == HA_POS_ERROR)
+ {
+ delete select;
+ table->time_stamp=save_time_stamp; // Restore timestamp pointer
+ DBUG_RETURN(-1);
+ }
+ }
+
init_read_record(&info,thd,table,select,0,1);
- thd->proc_info="searching";
+ thd->proc_info="Searching rows for update";
while (!(error=info.read_record(&info)) && !thd->killed)
{
@@ -183,7 +220,7 @@ int mysql_update(THD *thd,TABLE_LIST *table_list,List<Item> &fields,
}
else
{
- if (!(test_flags & 512)) /* For debugging */
+ if (!(test_flags & 512)) /* For debugging */
{
DBUG_DUMP("record",(char*) table->record[0],table->reclength);
}
@@ -205,7 +242,7 @@ int mysql_update(THD *thd,TABLE_LIST *table_list,List<Item> &fields,
select->cond=0;
}
else
- {
+ {
select= new SQL_SELECT;
select->head=table;
}
@@ -216,12 +253,10 @@ int mysql_update(THD *thd,TABLE_LIST *table_list,List<Item> &fields,
{
delete select;
table->time_stamp=save_time_stamp; // Restore timestamp pointer
- DBUG_RETURN(-1);
+ DBUG_RETURN(-1);
}
}
- if (!(test_flags & TEST_READCHECK)) /* For debugging */
- VOID(table->file->extra(HA_EXTRA_NO_READCHECK));
if (handle_duplicates == DUP_IGNORE)
table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
init_read_record(&info,thd,table,select,0,1);
@@ -229,7 +264,7 @@ int mysql_update(THD *thd,TABLE_LIST *table_list,List<Item> &fields,
ha_rows updated=0L,found=0L;
thd->count_cuted_fields=1; /* calc cuted fields */
thd->cuted_fields=0L;
- thd->proc_info="updating";
+ thd->proc_info="Updating";
query_id=thd->query_id;
while (!(error=info.read_record(&info)) && !thd->killed)
@@ -266,7 +301,6 @@ int mysql_update(THD *thd,TABLE_LIST *table_list,List<Item> &fields,
}
end_read_record(&info);
thd->proc_info="end";
- VOID(table->file->extra(HA_EXTRA_READCHECK));
VOID(table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY));
table->time_stamp=save_time_stamp; // Restore auto timestamp pointer
using_transactions=table->file->has_transactions();
@@ -289,6 +323,8 @@ int mysql_update(THD *thd,TABLE_LIST *table_list,List<Item> &fields,
mysql_unlock_tables(thd, thd->lock);
thd->lock=0;
}
+ if (updated)
+ query_cache.invalidate(table_list);
delete select;
if (error >= 0)
send_error(&thd->net,thd->killed ? ER_SERVER_SHUTDOWN : 0); /* purecov: inspected */
@@ -303,5 +339,459 @@ int mysql_update(THD *thd,TABLE_LIST *table_list,List<Item> &fields,
DBUG_PRINT("info",("%d records updated",updated));
}
thd->count_cuted_fields=0; /* calc cuted fields */
+ free_io_cache(table);
+ DBUG_RETURN(0);
+}
+
+/***************************************************************************
+** update multiple tables from join
+***************************************************************************/
+
+multi_update::multi_update(THD *thd_arg, TABLE_LIST *ut, List<Item> &fs,
+ enum enum_duplicates handle_duplicates, thr_lock_type lock_option_arg, uint num)
+ : update_tables (ut), thd(thd_arg), updated(0), found(0), fields(fs), lock_option(lock_option_arg),
+ dupl(handle_duplicates), num_of_tables(num), num_fields(0), num_updated(0) , error(0), do_update(false)
+{
+ save_time_stamps = (uint *) sql_calloc (sizeof(uint) * num_of_tables);
+ tmp_tables = (TABLE **)NULL;
+ int counter=0;
+ ulong timestamp_query_id;
+ not_trans_safe=false;
+ for (TABLE_LIST *dt=ut ; dt ; dt=dt->next,counter++)
+ {
+ TABLE *table=ut->table;
+// (void) ut->table->file->extra(HA_EXTRA_NO_KEYREAD);
+ dt->table->used_keys=0;
+ if (table->timestamp_field)
+ {
+ // Don't set timestamp column if this is modified
+ timestamp_query_id=table->timestamp_field->query_id;
+ table->timestamp_field->query_id=thd->query_id-1;
+ if (table->timestamp_field->query_id == thd->query_id)
+ table->time_stamp=0;
+ else
+ table->timestamp_field->query_id=timestamp_query_id;
+ }
+ save_time_stamps[counter]=table->time_stamp;
+ }
+ error = 1; // In case we do not reach prepare we have to reset timestamps
+}
+
+int
+multi_update::prepare(List<Item> &values)
+{
+ DBUG_ENTER("multi_update::prepare");
+ do_update = true;
+ thd->count_cuted_fields=1;
+ thd->cuted_fields=0L;
+ thd->proc_info="updating the main table";
+ TABLE_LIST *table_ref;
+
+ if (thd->options & OPTION_SAFE_UPDATES)
+ {
+ for (table_ref=update_tables; table_ref; table_ref=table_ref->next)
+ {
+ TABLE *table=table_ref->table;
+ if ((thd->options & OPTION_SAFE_UPDATES) && !table->quick_keys)
+ {
+ my_error(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE,MYF(0));
+ DBUG_RETURN(1);
+ }
+ }
+ }
+// Here I have to connect fields with tables and only update tables that need to be updated ...
+
+// I calculate num_updated and fill-up table_sequence
+// Set table_list->shared to true or false, depending on whether table is to be updated or not
+ Item_field *item;
+ List_iterator<Item> it(fields);
+ num_fields=fields.elements;
+ field_sequence = (uint *) sql_alloc(sizeof(uint)*num_fields);
+ uint *int_ptr=field_sequence;
+ while ((item= (Item_field *)it++))
+ {
+ unsigned int counter=0;
+ for (table_ref=update_tables; table_ref; table_ref=table_ref->next, counter++)
+ {
+ if (table_ref->table == item->field->table && !table_ref->shared)
+ {
+ num_updated++;
+ table_ref->shared=1;
+ if (!not_trans_safe && !table_ref->table->file->has_transactions())
+ not_trans_safe=true;
+ table_ref->table->no_keyread=1; // to be moved if initialize_tables has to be used
+ break;
+ }
+ }
+ if (!table_ref)
+ {
+ error = 1; // A proper error message is due here
+ DBUG_RETURN(1);
+ }
+ else
+ *int_ptr++=counter;
+ }
+ if (!num_updated)
+ {
+ error = 1; // A proper error message is due here
+ DBUG_RETURN(1);
+ }
+
+// Here, I have to allocate the array of temporary tables
+// I have to treat a case of num_updated=1 differently in send_data() method.
+ if (num_updated > 1)
+ {
+ tmp_tables = (TABLE **) sql_calloc(sizeof(TABLE *) * (num_updated - 1));
+ infos = (COPY_INFO *) sql_calloc(sizeof(COPY_INFO) * (num_updated - 1));
+ fields_by_tables = (List_item **)sql_calloc(sizeof(List_item *) * num_updated);
+ unsigned int counter;
+ List<Item> *temp_fields;
+ for (table_ref=update_tables, counter = 0; table_ref; table_ref=table_ref->next)
+ {
+ if (!table_ref->shared)
+ continue;
+// Here we have to add row offset as an additional field ...
+ if (!(temp_fields = (List_item *)sql_calloc(sizeof(List_item))))
+ {
+ error = 1; // A proper error message is due here
+ DBUG_RETURN(1);
+ }
+ temp_fields->empty();
+ it.rewind(); int_ptr=field_sequence;
+ while ((item= (Item_field *)it++))
+ {
+ if (*int_ptr++ == counter)
+ temp_fields->push_back(item);
+ }
+ if (counter)
+ {
+ Field_string offset(table_ref->table->file->ref_length,false,"offset",table_ref->table,true);
+ temp_fields->push_front(new Item_field(((Field *)&offset)));
+// Here I make tmp tables
+ int cnt=counter-1;
+ TMP_TABLE_PARAM tmp_table_param;
+ bzero((char*) &tmp_table_param,sizeof(tmp_table_param));
+ tmp_table_param.field_count=temp_fields->elements;
+ if (!(tmp_tables[cnt]=create_tmp_table(thd, &tmp_table_param, *temp_fields,
+ (ORDER*) 0, 1, 0, 0, TMP_TABLE_ALL_COLUMNS)))
+ {
+ error = 1; // A proper error message is due here
+ DBUG_RETURN(1);
+ }
+ tmp_tables[cnt]->file->extra(HA_EXTRA_WRITE_CACHE);
+ tmp_tables[cnt]->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
+ infos[cnt].handle_duplicates=DUP_IGNORE;
+ temp_fields->pop(); // because we shall use those for values only ...
+ }
+ fields_by_tables[counter]=temp_fields;
+ counter++;
+ }
+ }
+ error = 0; // Timestamps do not need to be restored, so far ...
DBUG_RETURN(0);
}
+
+
+void
+multi_update::initialize_tables(JOIN *join)
+{
+/* We skip it as it only makes a mess ...........
+ TABLE_LIST *walk;
+ table_map tables_to_update_from=0;
+ for (walk= update_tables ; walk ; walk=walk->next)
+ tables_to_update_from|= walk->table->map;
+
+ walk= update_tables;
+ for (JOIN_TAB *tab=join->join_tab, *end=join->join_tab+join->tables;
+ tab < end;
+ tab++)
+ {
+ if (tab->table->map & tables_to_update_from)
+ {
+ We are going to update from this table
+ walk->table=tab->table;
+ walk=walk->next;
+ if (tab == join->join_tab)
+ tab->table->no_keyread=1;
+ }
+ }
+*/
+}
+
+
+multi_update::~multi_update()
+{
+ int counter = 0;
+ for (table_being_updated=update_tables ;
+ table_being_updated ;
+ counter++, table_being_updated=table_being_updated->next)
+ {
+ TABLE *table=table_being_updated->table;
+ table->no_keyread=0;
+ if (error)
+ table->time_stamp=save_time_stamps[counter];
+ }
+ if (tmp_tables)
+ for (uint counter = 0; counter < num_updated-1; counter++)
+ if (tmp_tables[counter])
+ free_tmp_table(thd,tmp_tables[counter]);
+}
+
+
+bool multi_update::send_data(List<Item> &values)
+{
+ List<Item> real_values(values);
+ for (uint counter = 0; counter < fields.elements; counter++)
+ real_values.pop();
+// We have skipped fields ....
+ if (num_updated == 1)
+ {
+ for (table_being_updated=update_tables ;
+ table_being_updated ;
+ table_being_updated=table_being_updated->next)
+ {
+ if (!table_being_updated->shared)
+ continue;
+ TABLE *table=table_being_updated->table;
+ /* Check if we are using outer join and we didn't find the row */
+ if (table->status & (STATUS_NULL_ROW | STATUS_UPDATED))
+ return 0;
+ table->file->position(table->record[0]);
+// Only one table being updated receives a completely different treatment
+ table->status|= STATUS_UPDATED;
+ store_record(table,1);
+ if (fill_record(fields,real_values))
+ return 1;
+ found++;
+ if (/* compare_record(table, query_id) && */
+ !(error=table->file->update_row(table->record[1], table->record[0])))
+ updated++;
+ return error;
+ }
+ }
+ else
+ {
+ int secure_counter= -1;
+ for (table_being_updated=update_tables ;
+ table_being_updated ;
+ table_being_updated=table_being_updated->next, secure_counter++)
+ {
+ if (!table_being_updated->shared)
+ continue;
+
+ TABLE *table=table_being_updated->table;
+ /* Check if we are using outer join and we didn't find the row */
+ if (table->status & (STATUS_NULL_ROW | STATUS_UPDATED))
+ continue;
+ table->file->position(table->record[0]);
+ Item *item;
+ List_iterator<Item> it(real_values);
+ List <Item> values_by_table;
+ uint *int_ptr=field_sequence;
+ while ((item= (Item *)it++))
+ {
+ if (*int_ptr++ == (uint) (secure_counter + 1))
+ values_by_table.push_back(item);
+ }
+// Here I am breaking values as per each table
+ if (secure_counter < 0)
+ {
+ table->status|= STATUS_UPDATED;
+ store_record(table,1);
+ if (fill_record(*fields_by_tables[0],values_by_table))
+ return 1;
+ found++;
+ if (/*compare_record(table, query_id) && */
+ !(error=table->file->update_row(table->record[1], table->record[0])))
+ updated++;
+ else
+ {
+ table->file->print_error(error,MYF(0));
+ if (!error) error=1;
+ return 1;
+ }
+ }
+ else
+ {
+ // Here we insert into each temporary table
+ values_by_table.push_front(new Item_string((char*) table->file->ref,
+ table->file->ref_length));
+ fill_record(tmp_tables[secure_counter]->field,values_by_table);
+ error= write_record(tmp_tables[secure_counter],
+ &(infos[secure_counter]));
+ if (error)
+ {
+ error=-1;
+ return 1;
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+void multi_update::send_error(uint errcode,const char *err)
+{
+ /* First send error what ever it is ... */
+ ::send_error(&thd->net,errcode,err);
+
+ /* reset used flags */
+// update_tables->table->no_keyread=0;
+
+ /* If nothing updated return */
+ if (!updated)
+ return;
+ /* Below can happen when thread is killed early ... */
+ if (!table_being_updated)
+ table_being_updated=update_tables;
+
+ /*
+ If rows from the first table only has been updated and it is transactional,
+ just do rollback.
+ The same if all tables are transactional, regardless of where we are.
+ In all other cases do attempt updates ...
+ */
+ if ((table_being_updated->table->file->has_transactions() &&
+ table_being_updated == update_tables) || !not_trans_safe)
+ ha_rollback_stmt(thd);
+ else if (do_update)
+ VOID(do_updates(true));
+}
+
+
+int multi_update::do_updates (bool from_send_error)
+{
+ int error = 0, counter = 0;
+
+ if (num_updated == 1)
+ return 0;
+ if (from_send_error)
+ {
+ /* Found out table number for 'table_being_updated' */
+ for (TABLE_LIST *aux=update_tables;
+ aux != table_being_updated;
+ aux=aux->next)
+ counter++;
+ }
+ else
+ table_being_updated = update_tables;
+
+ do_update = false;
+ for (table_being_updated=table_being_updated->next;
+ table_being_updated ;
+ table_being_updated=table_being_updated->next, counter++)
+ {
+ if (!table_being_updated->shared)
+ continue;
+
+ TABLE *table = table_being_updated->table;
+ TABLE *tmp_table=tmp_tables[counter];
+ if (tmp_table->file->extra(HA_EXTRA_NO_CACHE))
+ {
+ error=1;
+ break;
+ }
+ List<Item> list;
+ Field **ptr=tmp_table->field,*field;
+ // This is supposed to be something like insert_fields
+ thd->used_tables|=tmp_table->map;
+ while ((field = *ptr++))
+ {
+ list.push_back((Item *)new Item_field(field));
+ if (field->query_id == thd->query_id)
+ thd->dupp_field=field;
+ field->query_id=thd->query_id;
+ tmp_table->used_keys&=field->part_of_key;
+ }
+ tmp_table->used_fields=tmp_table->fields;
+ error=0; list.pop(); // we get position some other way ...
+ error = tmp_table->file->rnd_init(1);
+ if (error)
+ return error;
+ while (!(error=tmp_table->file->rnd_next(tmp_table->record[0])) &&
+ (!thd->killed || from_send_error || not_trans_safe))
+ {
+ found++;
+ error= table->file->rnd_pos(table->record[0],
+ (byte*) (*(tmp_table->field))->ptr);
+ if (error)
+ return error;
+ table->status|= STATUS_UPDATED;
+ store_record(table,1);
+ error= fill_record(*fields_by_tables[counter + 1],list) ||
+ /* compare_record(table, query_id) || */
+ table->file->update_row(table->record[1],table->record[0]);
+ if (error)
+ {
+ table->file->print_error(error,MYF(0));
+ break;
+ }
+ else
+ updated++;
+ }
+ if (error == HA_ERR_END_OF_FILE)
+ error = 0;
+ }
+ return error;
+}
+
+
+/* out: 1 if error, 0 if success */
+
+bool multi_update::send_eof()
+{
+ thd->proc_info="updating the reference tables";
+
+ /* Does updates for the last n - 1 tables, returns 0 if ok */
+ int error = do_updates(false); /* do_updates returns 0 if success */
+
+ /* reset used flags */
+#ifndef NOT_USED
+ update_tables->table->no_keyread=0;
+#endif
+ if (error == -1)
+ error = 0;
+ thd->proc_info="end";
+ if (error)
+ send_error(error,"An error occured in multi-table update");
+
+ /*
+ Write the SQL statement to the binlog if we updated
+ rows and we succeeded, or also in an error case when there
+ was a non-transaction-safe table involved, since
+ modifications in it cannot be rolled back.
+ */
+
+ if (updated || not_trans_safe)
+ {
+ mysql_update_log.write(thd,thd->query,thd->query_length);
+ Query_log_event qinfo(thd, thd->query);
+
+ /*
+ mysql_bin_log is not open if binlogging or replication
+ is not used
+ */
+
+ if (mysql_bin_log.is_open() && mysql_bin_log.write(&qinfo) &&
+ !not_trans_safe)
+ error=1; /* Log write failed: roll back the SQL statement */
+
+ /* Commit or rollback the current SQL statement */
+ VOID(ha_autocommit_or_rollback(thd,error > 0));
+ }
+ else
+ error=0; // this can happen only if it is end of file error
+ if (!error) // if the above log write did not fail ...
+ {
+ char buff[80];
+ sprintf(buff,ER(ER_UPDATE_INFO), (long) found, (long) updated,
+ (long) thd->cuted_fields);
+ if (updated)
+ query_cache.invalidate(update_tables);
+ ::send_ok(&thd->net,
+ (thd->client_capabilities & CLIENT_FOUND_ROWS) ? found : updated,
+ thd->insert_id_used ? thd->insert_id() : 0L,buff);
+ }
+ thd->count_cuted_fields=0;
+ return 0;
+}
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 54a03d4a714..c3db58ce20b 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+/* Copyright (C) 2000-2001 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -21,11 +21,13 @@
#define YYINITDEPTH 100
#define YYMAXDEPTH 3200 /* Because of 64K stack */
#define Lex current_lex
+#define Select Lex->select
#include "mysql_priv.h"
-#include "slave.h"
+#include "slave.h"
#include "sql_acl.h"
#include "lex_symbol.h"
#include <myisam.h>
+#include <myisammrg.h>
extern void yyerror(const char*);
int yylex(void *yylval);
@@ -42,7 +44,7 @@ inline Item *or_or_concat(Item* A, Item* B)
%union {
int num;
ulong ulong_num;
- ulonglong ulonglong_num;
+ ulonglong ulonglong_number;
LEX_STRING lex_str;
LEX_STRING *lex_str_ptr;
LEX_SYMBOL symbol;
@@ -54,7 +56,9 @@ inline Item *or_or_concat(Item* A, Item* B)
Key::Keytype key_type;
enum db_type db_type;
enum row_type row_type;
+ enum ha_rkey_function ha_rkey_mode;
enum enum_tx_isolation tx_isolation;
+ enum Item_cast cast_type;
String *string;
key_part_spec *key_part;
TABLE_LIST *table_list;
@@ -72,6 +76,13 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token END_OF_INPUT
+%token CLOSE_SYM
+%token HANDLER_SYM
+%token LAST_SYM
+%token NEXT_SYM
+%token PREV_SYM
+%token SQL_CALC_FOUND_ROWS
+
%token EQ
%token EQUAL_SYM
%token GE
@@ -90,7 +101,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token MIN_SYM
%token SUM_SYM
%token STD_SYM
-
+%token ABORT_SYM
%token ADD
%token ALTER
%token AFTER_SYM
@@ -124,6 +135,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token LOCK_SYM
%token LOCKS_SYM
%token UNLOCK_SYM
+%token BINLOG_SYM
+%token EVENTS_SYM
%token ACTION
%token AGGREGATE_SYM
@@ -139,27 +152,37 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token BINARY
%token BIT_SYM
%token BOOL_SYM
+%token BOOLEAN_SYM
%token BOTH
%token BY
+%token CACHE_SYM
%token CASCADE
+%token CAST_SYM
%token CHECKSUM_SYM
%token CHECK_SYM
+%token CIPHER
%token COMMITTED_SYM
%token COLUMNS
%token COLUMN_SYM
%token CONCURRENT
%token CONSTRAINT
+%token CONVERT_SYM
%token DATABASES
%token DATA_SYM
%token DEFAULT
%token DELAYED_SYM
%token DELAY_KEY_WRITE_SYM
+%token DEMAND_SYM
%token DESC
%token DESCRIBE
+%token DES_KEY_FILE
+%token DISABLE_SYM
%token DISTINCT
%token DYNAMIC_SYM
+%token ENABLE_SYM
%token ENCLOSED
%token ESCAPED
+%token DIRECTORY_SYM
%token ESCAPE_SYM
%token EXISTS
%token EXTENDED_SYM
@@ -171,8 +194,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token FROM
%token FULL
%token FULLTEXT_SYM
-%token GEMINI_SYM
-%token GEMINI_SPIN_RETRIES
%token GLOBAL_SYM
%token GRANT
%token GRANTS
@@ -186,6 +207,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token IDENT
%token IGNORE_SYM
%token INDEX
+%token INDEXES
%token INFILE
%token INNER_SYM
%token INNOBASE_SYM
@@ -193,6 +215,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token IN_SYM
%token ISOLATION
%token ISAM_SYM
+%token ISSUER
%token JOIN_SYM
%token KEYS
%token KEY_SYM
@@ -211,22 +234,27 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token MASTER_USER_SYM
%token MASTER_LOG_FILE_SYM
%token MASTER_LOG_POS_SYM
+%token MASTER_LOG_SEQ_SYM
%token MASTER_PASSWORD_SYM
%token MASTER_PORT_SYM
%token MASTER_CONNECT_RETRY_SYM
+%token MASTER_SERVER_ID_SYM
%token MATCH
%token MAX_ROWS
+%token MAX_QUERIES_PER_HOUR
%token MEDIUM_SYM
%token MERGE_SYM
%token MIN_ROWS
%token MYISAM_SYM
%token NATIONAL_SYM
%token NATURAL
+%token NEW_SYM
%token NCHAR_SYM
%token NOT
%token NO_SYM
%token NULL_SYM
%token NUM
+%token OFF
%token ON
%token OPEN_SYM
%token OPTION
@@ -243,6 +271,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token PRIVILEGES
%token PROCESS
%token PROCESSLIST_SYM
+%token QUERY_SYM
%token RAID_0_SYM
%token RAID_STRIPED_SYM
%token RAID_TYPE
@@ -255,6 +284,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token RELOAD
%token RENAME
%token REPEATABLE_SYM
+%token REQUIRE_SYM
%token RESTORE_SYM
%token RESTRICT
%token REVOKE
@@ -265,9 +295,13 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token SERIALIZABLE_SYM
%token SESSION_SYM
%token SHUTDOWN
+%token SQL_CACHE_SYM
+%token SQL_NO_CACHE_SYM
+%token SSL_SYM
%token STARTING
%token STATUS_SYM
%token STRAIGHT_JOIN
+%token SUBJECT_SYM
%token TABLES
%token TABLE_SYM
%token TEMPORARY
@@ -295,6 +329,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token WHERE
%token WITH
%token WRITE_SYM
+%token X509_SYM
%token COMPRESSED_SYM
%token BIGINT
@@ -320,6 +355,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token PRECISION
%token QUICK
%token REAL
+%token SIGNED_SYM
%token SMALLINT
%token STRING_SYM
%token TEXT_SYM
@@ -328,6 +364,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token TINYBLOB
%token TINYINT
%token TINYTEXT
+%token ULONGLONG_NUM
%token UNSIGNED
%token VARBINARY
%token VARCHAR
@@ -352,6 +389,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token DAY_SECOND_SYM
%token DAY_SYM
%token DECODE_SYM
+%token DES_ENCRYPT_SYM
+%token DES_DECRYPT_SYM
%token ELSE
%token ELT_FUNC
%token ENCODE_SYM
@@ -369,6 +408,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token IDENTIFIED_SYM
%token IF
%token INSERT_ID
+%token INSERT_METHOD
%token INTERVAL_SYM
%token LAST_INSERT_ID
%token LEFT
@@ -425,9 +465,14 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token SQL_WARNINGS
%token SQL_AUTO_IS_NULL
%token SQL_SAFE_UPDATES
+%token SQL_QUERY_CACHE_TYPE_SYM
%token SQL_QUOTE_SHOW_CREATE
%token SQL_SLAVE_SKIP_COUNTER
+%token ISSUER_SYM
+%token SUBJECT_SYM
+%token CIPHER_SYM
+
%left SET_VAR
%left OR_OR_CONCAT OR
%left AND
@@ -444,7 +489,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%type <lex_str>
IDENT TEXT_STRING REAL_NUM FLOAT_NUM NUM LONG_NUM HEX_NUM LEX_HOSTNAME
- field_ident select_alias ident ident_or_text
+ ULONGLONG_NUM field_ident select_alias ident ident_or_text
%type <lex_str_ptr>
opt_table_alias
@@ -457,18 +502,18 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
opt_escape
%type <string>
- text_string
+ text_string
%type <num>
type int_type real_type order_dir opt_field_spec set_option lock_option
udf_type if_exists opt_local opt_table_options table_options
- table_option opt_if_not_exists
+ table_option opt_if_not_exists
%type <ulong_num>
- ULONG_NUM raid_types
+ ULONG_NUM raid_types merge_insert_types
-%type <ulonglong_num>
- ULONGLONG_NUM
+%type <ulonglong_number>
+ ulonglong_num
%type <item>
literal text_literal insert_ident order_ident
@@ -477,7 +522,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
using_list
%type <item_list>
- expr_list udf_expr_list when_list ident_list
+ expr_list udf_expr_list when_list ident_list ident_list_arg
%type <key_type>
key_type opt_unique_or_fulltext
@@ -503,6 +548,10 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%type <tx_isolation> tx_isolation isolation_types
+%type <ha_rkey_mode> handler_rkey_mode
+
+%type <cast_type> cast_type
+
%type <udf_type> udf_func_type
%type <symbol> FUNC_ARG0 FUNC_ARG1 FUNC_ARG2 FUNC_ARG3 keyword
@@ -519,13 +568,13 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
select_item_list select_item values_list no_braces
limit_clause delete_limit_clause fields opt_values values
procedure_list procedure_list2 procedure_item
- when_list2 expr_list2
+ when_list2 expr_list2 handler
opt_precision opt_ignore opt_column opt_restrict
grant revoke set lock unlock string_list field_options field_option
field_opt_list opt_binary table_lock_list table_lock varchar
references opt_on_delete opt_on_delete_list opt_on_delete_item use
opt_delete_options opt_delete_option
- opt_outer table_list table opt_option opt_place opt_low_priority
+ opt_outer table_list table_name opt_option opt_place opt_low_priority
opt_attribute opt_attribute_list attribute column_list column_list_id
opt_column_list grant_privileges opt_table user_list grant_option
grant_privilege grant_privilege_list
@@ -533,7 +582,10 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
equal optional_braces opt_key_definition key_usage_list2
opt_mi_check_type opt_to mi_check_types normal_join
table_to_table_list table_to_table opt_table_list opt_as
- END_OF_INPUT
+ handler_rkey_function handler_read_or_scan
+ single_multi table_wild_list table_wild_one opt_wild union union_list
+ precision union_option
+END_OF_INPUT
%type <NONE>
'-' '+' '*' '/' '%' '(' ')'
@@ -591,6 +643,7 @@ verb_clause:
| slave
| show
| truncate
+ | handler
| unlock
| update
| use
@@ -636,7 +689,7 @@ master_def:
Lex->mi.port = $3;
}
|
- MASTER_LOG_POS_SYM EQ ULONGLONG_NUM
+ MASTER_LOG_POS_SYM EQ ulonglong_num
{
Lex->mi.pos = $3;
}
@@ -647,7 +700,6 @@ master_def:
}
-
/* create a table */
create:
@@ -671,36 +723,41 @@ create:
| CREATE opt_unique_or_fulltext INDEX ident ON table_ident
{
- Lex->sql_command= SQLCOM_CREATE_INDEX;
+ LEX *lex=Lex;
+ lex->sql_command= SQLCOM_CREATE_INDEX;
if (!add_table_to_list($6,NULL,1))
YYABORT;
- Lex->create_list.empty();
- Lex->key_list.empty();
- Lex->col_list.empty();
- Lex->change=NullS;
+ lex->create_list.empty();
+ lex->key_list.empty();
+ lex->col_list.empty();
+ lex->change=NullS;
}
'(' key_list ')'
{
- Lex->key_list.push_back(new Key($2,$4.str,Lex->col_list));
- Lex->col_list.empty();
+ LEX *lex=Lex;
+ lex->key_list.push_back(new Key($2,$4.str,lex->col_list));
+ lex->col_list.empty();
}
| CREATE DATABASE opt_if_not_exists ident
{
- Lex->sql_command=SQLCOM_CREATE_DB;
- Lex->name=$4.str;
- Lex->create_info.options=$3;
+ LEX *lex=Lex;
+ lex->sql_command=SQLCOM_CREATE_DB;
+ lex->name=$4.str;
+ lex->create_info.options=$3;
}
| CREATE udf_func_type UDF_SYM ident
{
- Lex->sql_command = SQLCOM_CREATE_FUNCTION;
- Lex->udf.name=$4.str;
- Lex->udf.name_length=$4.length;
- Lex->udf.type= $2;
+ LEX *lex=Lex;
+ lex->sql_command = SQLCOM_CREATE_FUNCTION;
+ lex->udf.name=$4.str;
+ lex->udf.name_length=$4.length;
+ lex->udf.type= $2;
}
UDF_RETURNS_SYM udf_type UDF_SONAME_SYM TEXT_STRING
{
- Lex->udf.returns=(Item_result) $7;
- Lex->udf.dl=$9.str;
+ LEX *lex=Lex;
+ lex->udf.returns=(Item_result) $7;
+ lex->udf.dl=$9.str;
}
create2:
@@ -711,10 +768,11 @@ create3:
/* empty */ {}
| opt_duplicate opt_as SELECT_SYM
{
- Lex->lock_option= (using_update_log) ? TL_READ_NO_INSERT : TL_READ;
- mysql_init_select(Lex);
+ LEX *lex=Lex;
+ lex->lock_option= (using_update_log) ? TL_READ_NO_INSERT : TL_READ;
+ mysql_init_select(lex);
}
- select_options select_item_list opt_select_from {}
+ select_options select_item_list opt_select_from union {}
opt_as:
/* empty */ {}
@@ -745,13 +803,14 @@ create_table_options:
create_table_option:
TYPE_SYM EQ table_types { Lex->create_info.db_type= $3; }
- | MAX_ROWS EQ ULONGLONG_NUM { Lex->create_info.max_rows= $3; }
- | MIN_ROWS EQ ULONGLONG_NUM { Lex->create_info.min_rows= $3; }
- | AVG_ROW_LENGTH EQ ULONG_NUM { Lex->create_info.avg_row_length=$3; }
+ | MAX_ROWS EQ ulonglong_num { Lex->create_info.max_rows= $3; Lex->create_info.used_fields|= HA_CREATE_USED_MAX_ROWS;}
+ | MIN_ROWS EQ ulonglong_num { Lex->create_info.min_rows= $3; Lex->create_info.used_fields|= HA_CREATE_USED_MIN_ROWS;}
+ | AVG_ROW_LENGTH EQ ULONG_NUM { Lex->create_info.avg_row_length=$3; Lex->create_info.used_fields|= HA_CREATE_USED_AVG_ROW_LENGTH;}
| PASSWORD EQ TEXT_STRING { Lex->create_info.password=$3.str; }
| COMMENT_SYM EQ TEXT_STRING { Lex->create_info.comment=$3.str; }
- | AUTO_INC EQ ULONGLONG_NUM { Lex->create_info.auto_increment_value=$3; Lex->create_info.used_fields|= HA_CREATE_USED_AUTO;}
- | PACK_KEYS_SYM EQ ULONG_NUM { Lex->create_info.table_options|= $3 ? HA_OPTION_PACK_KEYS : HA_OPTION_NO_PACK_KEYS; }
+ | AUTO_INC EQ ulonglong_num { Lex->create_info.auto_increment_value=$3; Lex->create_info.used_fields|= HA_CREATE_USED_AUTO;}
+ | PACK_KEYS_SYM EQ ULONG_NUM { Lex->create_info.table_options|= $3 ? HA_OPTION_PACK_KEYS : HA_OPTION_NO_PACK_KEYS; Lex->create_info.used_fields|= HA_CREATE_USED_PACK_KEYS;}
+ | PACK_KEYS_SYM EQ DEFAULT { Lex->create_info.table_options&= ~(HA_OPTION_PACK_KEYS | HA_OPTION_NO_PACK_KEYS); Lex->create_info.used_fields|= HA_CREATE_USED_PACK_KEYS;}
| CHECKSUM_SYM EQ ULONG_NUM { Lex->create_info.table_options|= $3 ? HA_OPTION_CHECKSUM : HA_OPTION_NO_CHECKSUM; }
| DELAY_KEY_WRITE_SYM EQ ULONG_NUM { Lex->create_info.table_options|= $3 ? HA_OPTION_DELAY_KEY_WRITE : HA_OPTION_NO_DELAY_KEY_WRITE; }
| ROW_FORMAT_SYM EQ row_types { Lex->create_info.row_type= $3; }
@@ -762,15 +821,18 @@ create_table_option:
{
/* Move the union list to the merge_list */
LEX *lex=Lex;
- TABLE_LIST *table_list= (TABLE_LIST*) lex->table_list.first;
- lex->create_info.merge_list= lex->table_list;
+ TABLE_LIST *table_list= (TABLE_LIST*) lex->select->table_list.first;
+ lex->create_info.merge_list= lex->select->table_list;
lex->create_info.merge_list.elements--;
lex->create_info.merge_list.first= (byte*) (table_list->next);
- lex->table_list.elements=1;
- lex->table_list.next= (byte**) &(table_list->next);
+ lex->select->table_list.elements=1;
+ lex->select->table_list.next= (byte**) &(table_list->next);
table_list->next=0;
lex->create_info.used_fields|= HA_CREATE_USED_UNION;
}
+ | INSERT_METHOD EQ merge_insert_types { Lex->create_info.merge_insert_method= $3; Lex->create_info.used_fields|= HA_CREATE_USED_INSERT_METHOD;}
+ | DATA_SYM DIRECTORY_SYM EQ TEXT_STRING { Lex->create_info.data_file_name= $4.str; }
+ | INDEX DIRECTORY_SYM EQ TEXT_STRING { Lex->create_info.index_file_name= $4.str; }
table_types:
ISAM_SYM { $$= DB_TYPE_ISAM; }
@@ -778,8 +840,7 @@ table_types:
| MERGE_SYM { $$= DB_TYPE_MRG_MYISAM; }
| HEAP_SYM { $$= DB_TYPE_HEAP; }
| BERKELEY_DB_SYM { $$= DB_TYPE_BERKELEY_DB; }
- | INNOBASE_SYM { $$= DB_TYPE_INNOBASE; }
- | GEMINI_SYM { $$= DB_TYPE_GEMINI; }
+ | INNOBASE_SYM { $$= DB_TYPE_INNODB; }
row_types:
DEFAULT { $$= ROW_TYPE_DEFAULT; }
@@ -792,6 +853,11 @@ raid_types:
| RAID_0_SYM { $$= RAID_TYPE_0; }
| ULONG_NUM { $$=$1;}
+merge_insert_types:
+ NO_SYM { $$= MERGE_INSERT_DISABLED; }
+ | FIRST_SYM { $$= MERGE_INSERT_TO_FIRST; }
+ | LAST_SYM { $$= MERGE_INSERT_TO_LAST; }
+
opt_select_from:
/* empty */
| select_from select_lock_type
@@ -818,8 +884,9 @@ field_list_item:
}
| key_type opt_ident '(' key_list ')'
{
- Lex->key_list.push_back(new Key($1,$2,Lex->col_list));
- Lex->col_list.empty(); /* Alloced by sql_alloc */
+ LEX *lex=Lex;
+ lex->key_list.push_back(new Key($1,$2,lex->col_list));
+ lex->col_list.empty(); /* Alloced by sql_alloc */
}
| opt_constraint FOREIGN KEY_SYM opt_ident '(' key_list ')' references
{
@@ -837,16 +904,18 @@ opt_constraint:
field_spec:
field_ident
{
- Lex->length=Lex->dec=0; Lex->type=0; Lex->interval=0;
- Lex->default_value=0;
+ LEX *lex=Lex;
+ lex->length=lex->dec=0; lex->type=0; lex->interval=0;
+ lex->default_value=0;
}
type opt_attribute
{
+ LEX *lex=Lex;
if (add_field_to_list($1.str,
(enum enum_field_types) $3,
- Lex->length,Lex->dec,Lex->type,
- Lex->default_value,Lex->change,
- Lex->interval))
+ lex->length,lex->dec,lex->type,
+ lex->default_value,lex->change,
+ lex->interval))
YYABORT;
}
@@ -898,12 +967,14 @@ type:
{ $$=FIELD_TYPE_DECIMAL;}
| ENUM {Lex->interval_list.empty();} '(' string_list ')'
{
- Lex->interval=typelib(Lex->interval_list);
+ LEX *lex=Lex;
+ lex->interval=typelib(lex->interval_list);
$$=FIELD_TYPE_ENUM;
}
| SET { Lex->interval_list.empty();} '(' string_list ')'
{
- Lex->interval=typelib(Lex->interval_list);
+ LEX *lex=Lex;
+ lex->interval=typelib(lex->interval_list);
$$=FIELD_TYPE_SET;
}
@@ -935,7 +1006,14 @@ real_type:
float_options:
/* empty */ {}
| '(' NUM ')' { Lex->length=$2.str; }
- | '(' NUM ',' NUM ')' { Lex->length=$2.str; Lex->dec=$4.str; }
+ | precision {}
+
+precision:
+ '(' NUM ',' NUM ')'
+ {
+ LEX *lex=Lex;
+ lex->length=$2.str; lex->dec=$4.str;
+ }
field_options:
/* empty */ {}
@@ -946,7 +1024,8 @@ field_opt_list:
| field_option {}
field_option:
- UNSIGNED { Lex->type|= UNSIGNED_FLAG;}
+ SIGNED_SYM {}
+ | UNSIGNED { Lex->type|= UNSIGNED_FLAG;}
| ZEROFILL { Lex->type|= UNSIGNED_FLAG | ZEROFILL_FLAG; }
opt_len:
@@ -955,7 +1034,7 @@ opt_len:
opt_precision:
/* empty */ {}
- | '(' NUM ',' NUM ')' { Lex->length=$2.str; Lex->dec=$4.str; }
+ | precision {}
opt_attribute:
/* empty */ {}
@@ -1022,6 +1101,7 @@ key_or_index:
keys_or_index:
KEYS {}
| INDEX {}
+ | INDEXES {}
opt_unique_or_fulltext:
/* empty */ { $$= Key::MULTIPLE; }
@@ -1062,12 +1142,15 @@ alter:
lex->col_list.empty();
lex->drop_list.empty();
lex->alter_list.empty();
- lex->order_list.elements=0;
- lex->order_list.first=0;
- lex->order_list.next= (byte**) &lex->order_list.first;
- lex->db=lex->name=0;
+ lex->select->order_list.elements=0;
+ lex->select->order_list.first=0;
+ lex->select->order_list.next= (byte**) &lex->select->order_list.first;
+ lex->select->db=lex->name=0;
bzero((char*) &lex->create_info,sizeof(lex->create_info));
lex->create_info.db_type= DB_TYPE_DEFAULT;
+ lex->create_info.row_type= ROW_TYPE_NOT_USED;
+ lex->alter_keys_onoff=LEAVE_AS_IS;
+ lex->simple_alter=1;
}
alter_list
@@ -1076,42 +1159,78 @@ alter_list:
| alter_list ',' alter_list_item
add_column:
- ADD opt_column { Lex->change=0;}
+ ADD opt_column { Lex->change=0; }
alter_list_item:
- add_column field_list_item opt_place
- | add_column '(' field_list ')'
- | CHANGE opt_column field_ident { Lex->change= $3.str; } field_spec
+ add_column field_list_item opt_place { Lex->simple_alter=0; }
+ | add_column '(' field_list ')' { Lex->simple_alter=0; }
+ | CHANGE opt_column field_ident
+ {
+ LEX *lex=Lex;
+ lex->change= $3.str; lex->simple_alter=0;
+ }
+ field_spec opt_place
| MODIFY_SYM opt_column field_ident
{
- Lex->length=Lex->dec=0; Lex->type=0; Lex->interval=0;
- Lex->default_value=0;
+ LEX *lex=Lex;
+ lex->length=lex->dec=0; lex->type=0; lex->interval=0;
+ lex->default_value=0;
+ lex->simple_alter=0;
}
type opt_attribute
{
+ LEX *lex=Lex;
if (add_field_to_list($3.str,
(enum enum_field_types) $5,
- Lex->length,Lex->dec,Lex->type,
- Lex->default_value, $3.str,
- Lex->interval))
+ lex->length,lex->dec,lex->type,
+ lex->default_value, $3.str,
+ lex->interval))
YYABORT;
+ lex->simple_alter=0;
}
+ opt_place
| DROP opt_column field_ident opt_restrict
- { Lex->drop_list.push_back(new Alter_drop(Alter_drop::COLUMN,
- $3.str)); }
- | DROP PRIMARY_SYM KEY_SYM { Lex->drop_primary=1; }
- | DROP FOREIGN KEY_SYM opt_ident {}
+ {
+ LEX *lex=Lex;
+ lex->drop_list.push_back(new Alter_drop(Alter_drop::COLUMN,
+ $3.str)); lex->simple_alter=0;
+ }
+ | DROP PRIMARY_SYM KEY_SYM
+ {
+ LEX *lex=Lex;
+ lex->drop_primary=1; lex->simple_alter=0;
+ }
+ | DROP FOREIGN KEY_SYM opt_ident { Lex->simple_alter=0; }
| DROP key_or_index field_ident
- { Lex->drop_list.push_back(new Alter_drop(Alter_drop::KEY,
- $3.str)); }
+ {
+ LEX *lex=Lex;
+ lex->drop_list.push_back(new Alter_drop(Alter_drop::KEY,
+ $3.str));
+ lex->simple_alter=0;
+ }
+ | DISABLE_SYM KEYS { Lex->alter_keys_onoff=DISABLE; }
+ | ENABLE_SYM KEYS { Lex->alter_keys_onoff=ENABLE; }
| ALTER opt_column field_ident SET DEFAULT literal
- { Lex->alter_list.push_back(new Alter_column($3.str,$6)); }
+ {
+ LEX *lex=Lex;
+ lex->alter_list.push_back(new Alter_column($3.str,$6));
+ lex->simple_alter=0;
+ }
| ALTER opt_column field_ident DROP DEFAULT
- { Lex->alter_list.push_back(new Alter_column($3.str,(Item*) 0)); }
+ {
+ LEX *lex=Lex;
+ lex->alter_list.push_back(new Alter_column($3.str,(Item*) 0));
+ lex->simple_alter=0;
+ }
| RENAME opt_to table_alias table_ident
- { Lex->db=$4->db.str ; Lex->name= $4->table.str; }
- | create_table_options
- | order_clause
+ {
+ LEX *lex=Lex;
+ lex->select->db=$4->db.str;
+ lex->name= $4->table.str;
+ lex->simple_alter=0;
+ }
+ | create_table_options { Lex->simple_alter=0; }
+ | order_clause { Lex->simple_alter=0; }
opt_column:
/* empty */ {}
@@ -1139,14 +1258,16 @@ opt_to:
slave:
SLAVE START_SYM
{
- Lex->sql_command = SQLCOM_SLAVE_START;
- Lex->type = 0;
+ LEX *lex=Lex;
+ lex->sql_command = SQLCOM_SLAVE_START;
+ lex->type = 0;
}
|
SLAVE STOP_SYM
{
- Lex->sql_command = SQLCOM_SLAVE_STOP;
- Lex->type = 0;
+ LEX *lex=Lex;
+ lex->sql_command = SQLCOM_SLAVE_STOP;
+ lex->type = 0;
};
restore:
@@ -1172,8 +1293,9 @@ backup:
repair:
REPAIR table_or_tables
{
- Lex->sql_command = SQLCOM_REPAIR;
- Lex->check_opt.init();
+ LEX *lex=Lex;
+ lex->sql_command = SQLCOM_REPAIR;
+ lex->check_opt.init();
}
table_list opt_mi_check_type
@@ -1197,24 +1319,27 @@ mi_check_type:
analyze:
ANALYZE_SYM table_or_tables
{
- Lex->sql_command = SQLCOM_ANALYZE;
- Lex->check_opt.init();
+ LEX *lex=Lex;
+ lex->sql_command = SQLCOM_ANALYZE;
+ lex->check_opt.init();
}
table_list opt_mi_check_type
check:
CHECK_SYM table_or_tables
{
- Lex->sql_command = SQLCOM_CHECK;
- Lex->check_opt.init();
+ LEX *lex=Lex;
+ lex->sql_command = SQLCOM_CHECK;
+ lex->check_opt.init();
}
table_list opt_mi_check_type
optimize:
OPTIMIZE table_or_tables
{
- Lex->sql_command = SQLCOM_OPTIMIZE;
- Lex->check_opt.init();
+ LEX *lex=Lex;
+ lex->sql_command = SQLCOM_OPTIMIZE;
+ lex->check_opt.init();
}
table_list opt_mi_check_type
@@ -1242,17 +1367,24 @@ table_to_table:
select:
- SELECT_SYM
+ select_init { Lex->sql_command=SQLCOM_SELECT; }
+
+select_init:
+ SELECT_SYM select_part2 { Select->braces=false; } union
+ |
+ '(' SELECT_SYM select_part2 ')' { Select->braces=true;} union_opt
+
+
+select_part2:
{
LEX *lex=Lex;
- lex->sql_command= SQLCOM_SELECT;
lex->lock_option=TL_READ;
- mysql_init_select(lex);
+ mysql_init_select(lex);
}
select_options select_item_list select_into select_lock_type
select_into:
- /* empty */
+ limit_clause {}
| select_from
| opt_into select_from
| select_from opt_into
@@ -1270,20 +1402,23 @@ select_option_list:
| select_option
select_option:
- STRAIGHT_JOIN { Lex->options|= SELECT_STRAIGHT_JOIN; }
+ STRAIGHT_JOIN { Select->options|= SELECT_STRAIGHT_JOIN; }
| HIGH_PRIORITY { Lex->lock_option= TL_READ_HIGH_PRIORITY; }
- | DISTINCT { Lex->options|= SELECT_DISTINCT; }
- | SQL_SMALL_RESULT { Lex->options|= SELECT_SMALL_RESULT; }
- | SQL_BIG_RESULT { Lex->options|= SELECT_BIG_RESULT; }
- | SQL_BUFFER_RESULT { Lex->options|= OPTION_BUFFER_RESULT; }
+ | DISTINCT { Select->options|= SELECT_DISTINCT; }
+ | SQL_SMALL_RESULT { Select->options|= SELECT_SMALL_RESULT; }
+ | SQL_BIG_RESULT { Select->options|= SELECT_BIG_RESULT; }
+ | SQL_BUFFER_RESULT { Select->options|= OPTION_BUFFER_RESULT; }
+ | SQL_CALC_FOUND_ROWS { Select->options|= OPTION_FOUND_ROWS; }
+ | SQL_NO_CACHE_SYM { current_thd->safe_to_cache_query=0; }
+ | SQL_CACHE_SYM { Select->options |= OPTION_TO_QUERY_CACHE; }
| ALL {}
select_lock_type:
/* empty */
| FOR_SYM UPDATE_SYM
- { Lex->lock_option= TL_WRITE; }
+ { Lex->lock_option= TL_WRITE; current_thd->safe_to_cache_query=0; }
| LOCK_SYM IN_SYM SHARE_SYM MODE_SYM
- { Lex->lock_option= TL_READ_WITH_SHARED_LOCKS; }
+ { Lex->lock_option= TL_READ_WITH_SHARED_LOCKS; current_thd->safe_to_cache_query=0; }
select_item_list:
select_item_list ',' select_item
@@ -1451,9 +1586,18 @@ no_and_expr:
simple_expr:
simple_ident
| literal
- | '@' ident_or_text SET_VAR expr { $$= new Item_func_set_user_var($2,$4); }
- | '@' ident_or_text { $$= new Item_func_get_user_var($2); }
- | '@' '@' ident_or_text { if (!($$= get_system_var($3))) YYABORT; }
+ | '@' ident_or_text SET_VAR expr
+ { $$= new Item_func_set_user_var($2,$4);
+ current_thd->safe_to_cache_query=0;
+ }
+ | '@' ident_or_text
+ { $$= new Item_func_get_user_var($2);
+ current_thd->safe_to_cache_query=0;
+ }
+ | '@' '@' ident_or_text
+ { if (!($$= get_system_var($3))) YYABORT;
+ current_thd->safe_to_cache_query=0;
+ }
| sum_expr
| '-' expr %prec NEG { $$= new Item_func_neg($2); }
| '~' expr %prec NEG { $$= new Item_func_bit_neg($2); }
@@ -1461,15 +1605,17 @@ simple_expr:
| '!' expr %prec NEG { $$= new Item_func_not($2); }
| '(' expr ')' { $$= $2; }
| '{' ident expr '}' { $$= $3; }
- | MATCH '(' ident_list ')' AGAINST '(' expr ')'
- { Lex->ftfunc_list.push_back(
- (Item_func_match *)($$=new Item_func_match(*$3,$7))); }
- | MATCH ident_list AGAINST '(' expr ')'
- { Lex->ftfunc_list.push_back(
- (Item_func_match *)($$=new Item_func_match(*$2,$5))); }
+ | MATCH ident_list_arg AGAINST '(' expr ')'
+ { Select->ftfunc_list.push_back((Item_func_match *)
+ ($$=new Item_func_match_nl(*$2,$5))); }
+ | MATCH ident_list_arg AGAINST '(' expr IN_SYM BOOLEAN_SYM MODE_SYM ')'
+ { Select->ftfunc_list.push_back((Item_func_match *)
+ ($$=new Item_func_match_bool(*$2,$5))); }
| BINARY expr %prec NEG { $$= new Item_func_binary($2); }
+ | CAST_SYM '(' expr AS cast_type ')' { $$= create_func_cast($3, $5); }
| CASE_SYM opt_expr WHEN_SYM when_list opt_else END
{ $$= new Item_func_case(* $4, $2, $5 ) }
+ | CONVERT_SYM '(' expr ',' cast_type ')' { $$= create_func_cast($3, $5); }
| FUNC_ARG0 '(' ')'
{ $$= ((Item*(*)(void))($1.symbol->create_func))();}
| FUNC_ARG1 '(' expr ')'
@@ -1491,27 +1637,45 @@ simple_expr:
| CONCAT_WS '(' expr ',' expr_list ')'
{ $$= new Item_func_concat_ws($3, *$5); }
| CURDATE optional_braces
- { $$= new Item_func_curdate(); }
+ { $$= new Item_func_curdate(); current_thd->safe_to_cache_query=0; }
| CURTIME optional_braces
- { $$= new Item_func_curtime(); }
+ { $$= new Item_func_curtime(); current_thd->safe_to_cache_query=0; }
| CURTIME '(' expr ')'
- { $$= new Item_func_curtime($3); }
+ {
+ $$= new Item_func_curtime($3);
+ current_thd->safe_to_cache_query=0;
+ }
| DATE_ADD_INTERVAL '(' expr ',' INTERVAL_SYM expr interval ')'
{ $$= new Item_date_add_interval($3,$6,$7,0); }
| DATE_SUB_INTERVAL '(' expr ',' INTERVAL_SYM expr interval ')'
{ $$= new Item_date_add_interval($3,$6,$7,1); }
| DATABASE '(' ')'
- { $$= new Item_func_database(); }
+ {
+ $$= new Item_func_database();
+ current_thd->safe_to_cache_query=0;
+ }
| ELT_FUNC '(' expr ',' expr_list ')'
{ $$= new Item_func_elt($3, *$5); }
| MAKE_SET_SYM '(' expr ',' expr_list ')'
{ $$= new Item_func_make_set($3, *$5); }
- | ENCRYPT '(' expr ')' { $$= new Item_func_encrypt($3); }
+ | ENCRYPT '(' expr ')'
+ {
+ $$= new Item_func_encrypt($3);
+ current_thd->safe_to_cache_query=0;
+ }
| ENCRYPT '(' expr ',' expr ')' { $$= new Item_func_encrypt($3,$5); }
| DECODE_SYM '(' expr ',' TEXT_STRING ')'
{ $$= new Item_func_decode($3,$5.str); }
| ENCODE_SYM '(' expr ',' TEXT_STRING ')'
{ $$= new Item_func_encode($3,$5.str); }
+ | DES_DECRYPT_SYM '(' expr ')'
+ { $$= new Item_func_des_decrypt($3); }
+ | DES_DECRYPT_SYM '(' expr ',' expr ')'
+ { $$= new Item_func_des_decrypt($3,$5); }
+ | DES_ENCRYPT_SYM '(' expr ')'
+ { $$= new Item_func_des_encrypt($3); }
+ | DES_ENCRYPT_SYM '(' expr ',' expr ')'
+ { $$= new Item_func_des_encrypt($3,$5); }
| EXPORT_SET '(' expr ',' expr ',' expr ')'
{ $$= new Item_func_export_set($3, $5, $7); }
| EXPORT_SET '(' expr ',' expr ',' expr ',' expr ')'
@@ -1524,7 +1688,7 @@ simple_expr:
{ $$= new Item_func_from_unixtime($3); }
| FROM_UNIXTIME '(' expr ',' expr ')'
{
- $$= new Item_func_date_format(new Item_func_from_unixtime($3),$5,0);
+ $$= new Item_func_date_format (new Item_func_from_unixtime($3),$5,0);
}
| FIELD_FUNC '(' expr ',' expr_list ')'
{ $$= new Item_func_field($3, *$5); }
@@ -1543,10 +1707,12 @@ simple_expr:
{
$$= new Item_int((char*) "last_insert_id()",
current_thd->insert_id(),21);
+ current_thd->safe_to_cache_query=0;
}
| LAST_INSERT_ID '(' expr ')'
{
$$= new Item_func_set_last_insert_id($3);
+ current_thd->safe_to_cache_query=0;
}
| LEFT '(' expr ',' expr ')'
{ $$= new Item_func_left($3,$5); }
@@ -1563,14 +1729,19 @@ simple_expr:
| MONTH_SYM '(' expr ')'
{ $$= new Item_func_month($3); }
| NOW_SYM optional_braces
- { $$= new Item_func_now(); }
+ { $$= new Item_func_now(); current_thd->safe_to_cache_query=0;}
| NOW_SYM '(' expr ')'
- { $$= new Item_func_now($3); }
- | PASSWORD '(' expr ')' { $$= new Item_func_password($3); }
+ { $$= new Item_func_now($3); current_thd->safe_to_cache_query=0;}
+ | PASSWORD '(' expr ')'
+ {
+ $$= new Item_func_password($3);
+ }
| POSITION_SYM '(' no_in_expr IN_SYM expr ')'
{ $$ = new Item_func_locate($5,$3); }
- | RAND '(' expr ')' { $$= new Item_func_rand($3); }
- | RAND '(' ')' { $$= new Item_func_rand(); }
+ | RAND '(' expr ')'
+ { $$= new Item_func_rand($3); current_thd->safe_to_cache_query=0;}
+ | RAND '(' ')'
+ { $$= new Item_func_rand(); current_thd->safe_to_cache_query=0;}
| REPLACE '(' expr ',' expr ',' expr ')'
{ $$= new Item_func_replace($3,$5,$7); }
| RIGHT '(' expr ',' expr ')'
@@ -1608,6 +1779,7 @@ simple_expr:
$$ = new Item_sum_udf_str($1, *$3);
else
$$ = new Item_sum_udf_str($1);
+ current_thd->safe_to_cache_query=0;
}
| UDA_FLOAT_SUM '(' udf_expr_list ')'
{
@@ -1615,6 +1787,7 @@ simple_expr:
$$ = new Item_sum_udf_float($1, *$3);
else
$$ = new Item_sum_udf_float($1);
+ current_thd->safe_to_cache_query=0;
}
| UDA_INT_SUM '(' udf_expr_list ')'
{
@@ -1629,6 +1802,7 @@ simple_expr:
$$ = new Item_func_udf_str($1, *$3);
else
$$ = new Item_func_udf_str($1);
+ current_thd->safe_to_cache_query=0;
}
| UDF_FLOAT_FUNC '(' udf_expr_list ')'
{
@@ -1636,6 +1810,7 @@ simple_expr:
$$ = new Item_func_udf_float($1, *$3);
else
$$ = new Item_func_udf_float($1);
+ current_thd->safe_to_cache_query=0;
}
| UDF_INT_FUNC '(' udf_expr_list ')'
{
@@ -1643,15 +1818,21 @@ simple_expr:
$$ = new Item_func_udf_int($1, *$3);
else
$$ = new Item_func_udf_int($1);
+ current_thd->safe_to_cache_query=0;
}
| UNIQUE_USERS '(' text_literal ',' NUM ',' NUM ',' expr_list ')'
- { $$= new Item_func_unique_users($3,atoi($5.str),atoi($7.str), * $9); }
+ {
+ $$= new Item_func_unique_users($3,atoi($5.str),atoi($7.str), * $9);
+ }
| UNIX_TIMESTAMP '(' ')'
- { $$= new Item_func_unix_timestamp(); }
+ {
+ $$= new Item_func_unix_timestamp();
+ current_thd->safe_to_cache_query=0;
+ }
| UNIX_TIMESTAMP '(' expr ')'
{ $$= new Item_func_unix_timestamp($3); }
| USER '(' ')'
- { $$= new Item_func_user(); }
+ { $$= new Item_func_user(); current_thd->safe_to_cache_query=0; }
| WEEK_SYM '(' expr ')'
{ $$= new Item_func_week($3,new Item_int((char*) "0",0,1)); }
| WEEK_SYM '(' expr ',' expr ')'
@@ -1663,7 +1844,10 @@ simple_expr:
| YEARWEEK '(' expr ',' expr ')'
{ $$= new Item_func_yearweek($3, $5); }
| BENCHMARK_SYM '(' ULONG_NUM ',' expr ')'
- { $$=new Item_func_benchmark($3,$5); }
+ {
+ $$=new Item_func_benchmark($3,$5);
+ current_thd->safe_to_cache_query=0;
+ }
| EXTRACT_SYM '(' interval FROM expr ')'
{ $$=new Item_extract( $3, $5); }
@@ -1696,30 +1880,44 @@ sum_expr:
{ $$=new Item_sum_sum($3); }
in_sum_expr:
- { Lex->in_sum_expr++ }
+ { Select->in_sum_expr++ }
expr
{
- Lex->in_sum_expr--;
+ Select->in_sum_expr--;
$$=$2;
}
+cast_type:
+ BINARY { $$=ITEM_CAST_BINARY; }
+ | SIGNED_SYM { $$=ITEM_CAST_SIGNED_INT; }
+ | SIGNED_SYM INT_SYM { $$=ITEM_CAST_SIGNED_INT; }
+ | UNSIGNED { $$=ITEM_CAST_UNSIGNED_INT; }
+ | UNSIGNED INT_SYM { $$=ITEM_CAST_UNSIGNED_INT; }
+ | DATE_SYM { $$=ITEM_CAST_DATE; }
+ | TIME_SYM { $$=ITEM_CAST_TIME; }
+ | DATETIME { $$=ITEM_CAST_DATETIME; }
+
expr_list:
- { Lex->expr_list.push_front(new List<Item>); }
+ { Select->expr_list.push_front(new List<Item>); }
expr_list2
- { $$= Lex->expr_list.pop(); }
+ { $$= Select->expr_list.pop(); }
expr_list2:
- expr { Lex->expr_list.head()->push_back($1); }
- | expr_list2 ',' expr { Lex->expr_list.head()->push_back($3); }
+ expr { Select->expr_list.head()->push_back($1); }
+ | expr_list2 ',' expr { Select->expr_list.head()->push_back($3); }
+
+ident_list_arg:
+ ident_list { $$= $1; }
+ | '(' ident_list ')' { $$= $2; }
ident_list:
- { Lex->expr_list.push_front(new List<Item>); }
+ { Select->expr_list.push_front(new List<Item>); }
ident_list2
- { $$= Lex->expr_list.pop(); }
+ { $$= Select->expr_list.pop(); }
ident_list2:
- simple_ident { Lex->expr_list.head()->push_back($1); }
- | ident_list2 ',' simple_ident { Lex->expr_list.head()->push_back($3); }
+ simple_ident { Select->expr_list.head()->push_back($1); }
+ | ident_list2 ',' simple_ident { Select->expr_list.head()->push_back($3); }
opt_expr:
/* empty */ { $$= NULL; }
@@ -1730,20 +1928,22 @@ opt_else:
| ELSE expr { $$= $2; }
when_list:
- { Lex->when_list.push_front(new List<Item>) }
+ { Select->when_list.push_front(new List<Item>) }
when_list2
- { $$= Lex->when_list.pop(); }
+ { $$= Select->when_list.pop(); }
when_list2:
expr THEN_SYM expr
{
- Lex->when_list.head()->push_back($1);
- Lex->when_list.head()->push_back($3);
+ SELECT_LEX *sel=Select;
+ sel->when_list.head()->push_back($1);
+ sel->when_list.head()->push_back($3);
}
| when_list2 WHEN_SYM expr THEN_SYM expr
{
- Lex->when_list.head()->push_back($3);
- Lex->when_list.head()->push_back($5);
+ SELECT_LEX *sel=Select;
+ sel->when_list.head()->push_back($3);
+ sel->when_list.head()->push_back($5);
}
opt_pad:
@@ -1758,15 +1958,21 @@ join_table_list:
| join_table_list INNER_SYM JOIN_SYM join_table ON expr
{ add_join_on($4,$6); $$=$4; }
| join_table_list INNER_SYM JOIN_SYM join_table
- { Lex->db1=$1->db; Lex->table1=$1->name;
- Lex->db2=$4->db; Lex->table2=$4->name; }
+ {
+ SELECT_LEX *sel=Select;
+ sel->db1=$1->db; sel->table1=$1->name;
+ sel->db2=$4->db; sel->table2=$4->name;
+ }
USING '(' using_list ')'
{ add_join_on($4,$8); $$=$4; }
| join_table_list LEFT opt_outer JOIN_SYM join_table ON expr
{ add_join_on($5,$7); $5->outer_join|=JOIN_TYPE_LEFT; $$=$5; }
| join_table_list LEFT opt_outer JOIN_SYM join_table
- { Lex->db1=$1->db; Lex->table1=$1->name;
- Lex->db2=$5->db; Lex->table2=$5->name; }
+ {
+ SELECT_LEX *sel=Select;
+ sel->db1=$1->db; sel->table1=$1->name;
+ sel->db2=$5->db; sel->table2=$5->name;
+ }
USING '(' using_list ')'
{ add_join_on($5,$9); $5->outer_join|=JOIN_TYPE_LEFT; $$=$5; }
| join_table_list NATURAL LEFT opt_outer JOIN_SYM join_table
@@ -1774,8 +1980,11 @@ join_table_list:
| join_table_list RIGHT opt_outer JOIN_SYM join_table ON expr
{ add_join_on($1,$7); $1->outer_join|=JOIN_TYPE_RIGHT; $$=$1; }
| join_table_list RIGHT opt_outer JOIN_SYM join_table
- { Lex->db1=$1->db; Lex->table1=$1->name;
- Lex->db2=$5->db; Lex->table2=$5->name; }
+ {
+ SELECT_LEX *sel=Select;
+ sel->db1=$1->db; sel->table1=$1->name;
+ sel->db2=$5->db; sel->table2=$5->name;
+ }
USING '(' using_list ')'
{ add_join_on($1,$9); $1->outer_join|=JOIN_TYPE_RIGHT; $$=$1; }
| join_table_list NATURAL RIGHT opt_outer JOIN_SYM join_table
@@ -1789,10 +1998,16 @@ normal_join:
| CROSS JOIN_SYM {}
join_table:
- { Lex->use_index_ptr=Lex->ignore_index_ptr=0; }
+ {
+ SELECT_LEX *sel=Select;
+ sel->use_index_ptr=sel->ignore_index_ptr=0;
+ }
table_ident opt_table_alias opt_key_definition
- { if (!($$=add_table_to_list($2,$3,0,TL_UNLOCK, Lex->use_index_ptr,
- Lex->ignore_index_ptr))) YYABORT; }
+ {
+ SELECT_LEX *sel=Select;
+ if (!($$=add_table_to_list($2,$3,0,TL_UNLOCK, sel->use_index_ptr,
+ sel->ignore_index_ptr))) YYABORT;
+ }
| '{' ident join_table LEFT OUTER JOIN_SYM join_table ON expr '}'
{ add_join_on($7,$9); $7->outer_join|=JOIN_TYPE_LEFT; $$=$7; }
@@ -1803,30 +2018,41 @@ opt_outer:
opt_key_definition:
/* empty */ {}
| USE_SYM key_usage_list
- { Lex->use_index= *$2; Lex->use_index_ptr= &Lex->use_index; }
+ {
+ SELECT_LEX *sel=Select;
+ sel->use_index= *$2;
+ sel->use_index_ptr= &sel->use_index;
+ }
| IGNORE_SYM key_usage_list
- { Lex->ignore_index= *$2; Lex->ignore_index_ptr= &Lex->ignore_index;}
+ {
+ SELECT_LEX *sel=Select;
+ sel->ignore_index= *$2;
+ sel->ignore_index_ptr= &sel->ignore_index;
+ }
key_usage_list:
- key_or_index { Lex->interval_list.empty() } '(' key_usage_list2 ')'
- { $$= &Lex->interval_list; }
+ key_or_index { Select->interval_list.empty() } '(' key_usage_list2 ')'
+ { $$= &Select->interval_list; }
key_usage_list2:
key_usage_list2 ',' ident
- { Lex->interval_list.push_back(new String((const char*) $3.str,$3.length)); }
+ { Select->interval_list.push_back(new String((const char*) $3.str,$3.length)); }
| ident
- { Lex->interval_list.push_back(new String((const char*) $1.str,$1.length)); }
+ { Select->interval_list.push_back(new String((const char*) $1.str,$1.length)); }
| PRIMARY_SYM
- { Lex->interval_list.push_back(new String("PRIMARY",7)); }
+ { Select->interval_list.push_back(new String("PRIMARY",7)); }
using_list:
ident
- { if (!($$= new Item_func_eq(new Item_field(Lex->db1,Lex->table1, $1.str), new Item_field(Lex->db2,Lex->table2,$1.str))))
+ {
+ SELECT_LEX *sel=Select;
+ if (!($$= new Item_func_eq(new Item_field(sel->db1,sel->table1, $1.str), new Item_field(sel->db2,sel->table2,$1.str))))
YYABORT;
}
| using_list ',' ident
{
- if (!($$= new Item_cond_and(new Item_func_eq(new Item_field(Lex->db1,Lex->table1,$3.str), new Item_field(Lex->db2,Lex->table2,$3.str)), $1)))
+ SELECT_LEX *sel=Select;
+ if (!($$= new Item_cond_and(new Item_func_eq(new Item_field(sel->db1,sel->table1,$3.str), new Item_field(sel->db2,sel->table2,$3.str)), $1)))
YYABORT;
}
@@ -1857,13 +2083,16 @@ opt_table_alias:
where_clause:
- /* empty */ { Lex->where= 0; }
- | WHERE expr { Lex->where= $2; }
+ /* empty */ { Select->where= 0; }
+ | WHERE expr { Select->where= $2; }
having_clause:
/* empty */
- | HAVING { Lex->create_refs=1; } expr
- { Lex->having= $3; Lex->create_refs=0; }
+ | HAVING { Select->create_refs=1; } expr
+ {
+ SELECT_LEX *sel=Select;
+ sel->having= $3; sel->create_refs=0;
+ }
opt_escape:
ESCAPE_SYM TEXT_STRING { $$= $2.str; }
@@ -1893,7 +2122,13 @@ opt_order_clause:
| order_clause
order_clause:
- ORDER_SYM BY order_list
+ ORDER_SYM BY
+ {
+ LEX *lex=Lex;
+ if (lex->sql_command == SQLCOM_MULTI_UPDATE)
+ YYABORT;
+ lex->select->sort_default=1;
+ } order_list
order_list:
order_list ',' order_ident order_dir
@@ -1908,33 +2143,41 @@ order_dir:
limit_clause:
- /* empty */
- {
- Lex->select_limit= current_thd->default_select_limit;
- Lex->offset_limit= 0L;
- }
+ /* empty */ {}
| LIMIT ULONG_NUM
- { Lex->select_limit= $2; Lex->offset_limit=0L; }
+ {
+ SELECT_LEX *sel=Select;
+ sel->select_limit= $2;
+ sel->offset_limit=0L;
+ }
| LIMIT ULONG_NUM ',' ULONG_NUM
- { Lex->select_limit= $4; Lex->offset_limit=$2; }
+ {
+ SELECT_LEX *sel=Select;
+ sel->select_limit= $4; sel->offset_limit=$2;
+ }
delete_limit_clause:
/* empty */
{
- Lex->select_limit= HA_POS_ERROR;
+ LEX *lex=Lex;
+ if (lex->sql_command == SQLCOM_MULTI_UPDATE)
+ YYABORT;
+ lex->select->select_limit= HA_POS_ERROR;
}
- | LIMIT ULONGLONG_NUM
- { Lex->select_limit= (ha_rows) $2; }
+ | LIMIT ulonglong_num
+ { Select->select_limit= (ha_rows) $2; }
ULONG_NUM:
- NUM { $$= strtoul($1.str,NULL,10); }
- | REAL_NUM { $$= strtoul($1.str,NULL,10); }
+ NUM { $$= strtoul($1.str,NULL,10); }
+ | ULONGLONG_NUM { $$= (ulong) strtoull($1.str,NULL,10); }
+ | REAL_NUM { $$= strtoul($1.str,NULL,10); }
| FLOAT_NUM { $$= strtoul($1.str,NULL,10); }
-ULONGLONG_NUM:
- NUM { $$= (ulonglong) strtoul($1.str,NULL,10); }
- | LONG_NUM { $$= strtoull($1.str,NULL,10); }
- | REAL_NUM { $$= strtoull($1.str,NULL,10); }
+ulonglong_num:
+ NUM { $$= (ulonglong) strtoul($1.str,NULL,10); }
+ | ULONGLONG_NUM { $$= strtoull($1.str,NULL,10); }
+ | LONG_NUM { $$= (ulonglong) strtoul($1.str,NULL,10); }
+ | REAL_NUM { $$= strtoull($1.str,NULL,10); }
| FLOAT_NUM { $$= strtoull($1.str,NULL,10); }
procedure_clause:
@@ -1947,6 +2190,7 @@ procedure_clause:
lex->proc_list.next= (byte**) &lex->proc_list.first;
if (add_proc_to_list(new Item_field(NULL,NULL,$2.str)))
YYABORT;
+ current_thd->safe_to_cache_query=0;
}
'(' procedure_list ')'
@@ -2000,36 +2244,40 @@ do: DO_SYM
drop:
DROP TABLE_SYM if_exists table_list opt_restrict
{
- Lex->sql_command = SQLCOM_DROP_TABLE;
- Lex->drop_if_exists = $3;
+ LEX *lex=Lex;
+ lex->sql_command = SQLCOM_DROP_TABLE;
+ lex->drop_if_exists = $3;
}
| DROP INDEX ident ON table_ident {}
{
- Lex->sql_command= SQLCOM_DROP_INDEX;
- Lex->drop_list.empty();
- Lex->drop_list.push_back(new Alter_drop(Alter_drop::KEY,
+ LEX *lex=Lex;
+ lex->sql_command= SQLCOM_DROP_INDEX;
+ lex->drop_list.empty();
+ lex->drop_list.push_back(new Alter_drop(Alter_drop::KEY,
$3.str));
if (!add_table_to_list($5,NULL, 1))
YYABORT;
}
| DROP DATABASE if_exists ident
{
- Lex->sql_command= SQLCOM_DROP_DB;
- Lex->drop_if_exists=$3;
- Lex->name=$4.str;
+ LEX *lex=Lex;
+ lex->sql_command= SQLCOM_DROP_DB;
+ lex->drop_if_exists=$3;
+ lex->name=$4.str;
}
| DROP UDF_SYM ident
{
- Lex->sql_command = SQLCOM_DROP_FUNCTION;
- Lex->udf.name=$3.str;
+ LEX *lex=Lex;
+ lex->sql_command = SQLCOM_DROP_FUNCTION;
+ lex->udf.name=$3.str;
}
table_list:
- table
- | table_list ',' table
+ table_name
+ | table_list ',' table_name
-table:
+table_name:
table_ident
{ if (!add_table_to_list($1,NULL,1)) YYABORT; }
@@ -2045,7 +2293,13 @@ insert:
INSERT { Lex->sql_command = SQLCOM_INSERT; } insert_lock_option opt_ignore insert2 insert_field_spec
replace:
- REPLACE { Lex->sql_command = SQLCOM_REPLACE; } replace_lock_option insert2 insert_field_spec
+ REPLACE
+ {
+ LEX *lex=Lex;
+ lex->sql_command = SQLCOM_REPLACE;
+ lex->duplicates= DUP_REPLACE;
+ }
+ replace_lock_option insert2 insert_field_spec
insert_lock_option:
/* empty */ { Lex->lock_option= TL_WRITE_CONCURRENT_INSERT; }
@@ -2062,19 +2316,21 @@ insert2:
| insert_table {}
insert_table:
- table
+ table_name
{
- Lex->field_list.empty();
- Lex->many_values.empty();
- Lex->insert_list=0;
+ LEX *lex=Lex;
+ lex->field_list.empty();
+ lex->many_values.empty();
+ lex->insert_list=0;
}
insert_field_spec:
opt_field_spec insert_values {}
| SET
{
- if (!(Lex->insert_list = new List_item) ||
- Lex->many_values.push_back(Lex->insert_list))
+ LEX *lex=Lex;
+ if (!(lex->insert_list = new List_item) ||
+ lex->many_values.push_back(lex->insert_list))
YYABORT;
}
ident_eq_list
@@ -2098,7 +2354,7 @@ insert_values:
lex->lock_option= (using_update_log) ? TL_READ_NO_INSERT : TL_READ;
mysql_init_select(lex);
}
- select_options select_item_list select_from select_lock_type {}
+ select_options select_item_list select_from select_lock_type union {}
values_list:
values_list ',' no_braces
@@ -2112,8 +2368,9 @@ ident_eq_list:
ident_eq_value:
simple_ident equal expr
{
- if (Lex->field_list.push_back($1) ||
- Lex->insert_list->push_back($3))
+ LEX *lex=Lex;
+ if (lex->field_list.push_back($1) ||
+ lex->insert_list->push_back($3))
YYABORT;
}
@@ -2128,7 +2385,8 @@ no_braces:
}
opt_values ')'
{
- if (Lex->many_values.push_back(Lex->insert_list))
+ LEX *lex=Lex;
+ if (lex->many_values.push_back(lex->insert_list))
YYABORT;
}
@@ -2151,8 +2409,15 @@ values:
/* Update rows in a table */
update:
- UPDATE_SYM opt_low_priority opt_ignore table SET update_list where_clause delete_limit_clause
- { Lex->sql_command = SQLCOM_UPDATE; }
+ UPDATE_SYM
+ {
+ LEX *lex=Lex;
+ lex->sql_command = SQLCOM_UPDATE;
+ lex->select->order_list.elements=0;
+ lex->select->order_list.first=0;
+ lex->select->order_list.next= (byte**) &lex->select->order_list.first;
+ }
+ opt_low_priority opt_ignore join_table_list SET update_list where_clause opt_order_clause delete_limit_clause
update_list:
update_list ',' simple_ident equal expr
@@ -2174,31 +2439,69 @@ opt_low_priority:
delete:
DELETE_SYM
- {
- Lex->sql_command= SQLCOM_DELETE; Lex->options=0;
- Lex->lock_option= current_thd->update_lock_default;
+ {
+ LEX *lex=Lex;
+ lex->sql_command= SQLCOM_DELETE; lex->select->options=0;
+ lex->lock_option= lex->thd->update_lock_default;
+ lex->select->order_list.elements=0;
+ lex->select->order_list.first=0;
+ lex->select->order_list.next= (byte**) &lex->select->order_list.first;
}
- opt_delete_options FROM table
- where_clause delete_limit_clause
+ opt_delete_options single_multi {}
+
+single_multi:
+ FROM table_name where_clause opt_order_clause delete_limit_clause {}
+ | table_wild_list
+ { mysql_init_multi_delete(Lex); }
+ FROM join_table_list where_clause
+ | FROM table_wild_list
+ { mysql_init_multi_delete(Lex); }
+ USING join_table_list where_clause
+
+table_wild_list:
+ table_wild_one {}
+ | table_wild_list ',' table_wild_one {}
+
+table_wild_one:
+ ident opt_wild
+ {
+ if (!add_table_to_list(new Table_ident($1),NULL,1,TL_WRITE))
+ YYABORT;
+ }
+ | ident '.' ident opt_wild
+ {
+ if (!add_table_to_list(new Table_ident($1,$3,0),NULL,1,TL_WRITE))
+ YYABORT;
+ }
+
+opt_wild:
+ /* empty */ {}
+ | '.' '*' {}
opt_delete_options:
- /* empty */ {}
+ /* empty */ {}
| opt_delete_option opt_delete_options {}
opt_delete_option:
- QUICK { Lex->options|= OPTION_QUICK; }
+ QUICK { Select->options|= OPTION_QUICK; }
| LOW_PRIORITY { Lex->lock_option= TL_WRITE_LOW_PRIORITY; }
truncate:
- TRUNCATE_SYM opt_table_sym table
- { Lex->sql_command= SQLCOM_TRUNCATE; Lex->options=0;
- Lex->lock_option= current_thd->update_lock_default; }
+ TRUNCATE_SYM opt_table_sym table_name
+ {
+ LEX* lex = Lex;
+ lex->sql_command= SQLCOM_TRUNCATE;
+ lex->select->options=0;
+ lex->select->order_list.elements=0;
+ lex->select->order_list.first=0;
+ lex->select->order_list.next= (byte**) &lex->select->order_list.first;
+ lex->lock_option= current_thd->update_lock_default; }
opt_table_sym:
/* empty */
| TABLE_SYM
-
+
/* Show things */
show: SHOW { Lex->wild=0;} show_param
@@ -2207,18 +2510,26 @@ show_param:
DATABASES wild
{ Lex->sql_command= SQLCOM_SHOW_DATABASES; }
| TABLES opt_db wild
- { Lex->sql_command= SQLCOM_SHOW_TABLES; Lex->db= $2; Lex->options=0;}
+ {
+ LEX *lex=Lex;
+ lex->sql_command= SQLCOM_SHOW_TABLES;
+ lex->select->db= $2; lex->select->options=0;
+ }
| TABLE_SYM STATUS_SYM opt_db wild
- { Lex->sql_command= SQLCOM_SHOW_TABLES;
- Lex->options|= SELECT_DESCRIBE;
- Lex->db= $3;
+ {
+ LEX *lex=Lex;
+ lex->sql_command= SQLCOM_SHOW_TABLES;
+ lex->select->options|= SELECT_DESCRIBE;
+ lex->select->db= $3;
}
| OPEN_SYM TABLES opt_db wild
- { Lex->sql_command= SQLCOM_SHOW_OPEN_TABLES;
- Lex->db= $3;
- Lex->options=0;
+ {
+ LEX *lex=Lex;
+ lex->sql_command= SQLCOM_SHOW_OPEN_TABLES;
+ lex->select->db= $3;
+ lex->select->options=0;
}
- | opt_full COLUMNS FROM table_ident opt_db wild
+ | opt_full COLUMNS from_or_in table_ident opt_db wild
{
Lex->sql_command= SQLCOM_SHOW_FIELDS;
if ($5)
@@ -2226,10 +2537,31 @@ show_param:
if (!add_table_to_list($4,NULL,0))
YYABORT;
}
+ | NEW_SYM MASTER_SYM FOR_SYM SLAVE WITH MASTER_LOG_FILE_SYM EQ
+ TEXT_STRING AND MASTER_LOG_POS_SYM EQ ulonglong_num
+ AND MASTER_SERVER_ID_SYM EQ
+ ULONG_NUM
+ {
+ Lex->sql_command = SQLCOM_SHOW_NEW_MASTER;
+ Lex->mi.log_file_name = $8.str;
+ Lex->mi.pos = $12;
+ Lex->mi.server_id = $16;
+ }
| MASTER_SYM LOGS_SYM
{
Lex->sql_command = SQLCOM_SHOW_BINLOGS;
- }
+ }
+ | SLAVE HOSTS_SYM
+ {
+ Lex->sql_command = SQLCOM_SHOW_SLAVE_HOSTS;
+ }
+ | BINLOG_SYM EVENTS_SYM binlog_in binlog_from
+ {
+ LEX *lex=Lex;
+ lex->sql_command = SQLCOM_SHOW_BINLOG_EVENTS;
+ lex->select->select_limit= lex->thd->default_select_limit;
+ lex->select->offset_limit= 0L;
+ } limit_clause
| keys_or_index FROM table_ident opt_db
{
Lex->sql_command= SQLCOM_SHOW_KEYS;
@@ -2247,8 +2579,12 @@ show_param:
| LOGS_SYM
{ Lex->sql_command= SQLCOM_SHOW_LOGS; }
| GRANTS FOR_SYM user
- { Lex->sql_command= SQLCOM_SHOW_GRANTS;
- Lex->grant_user=$3; Lex->grant_user->password.str=NullS; }
+ {
+ LEX *lex=Lex;
+ lex->sql_command= SQLCOM_SHOW_GRANTS;
+ lex->grant_user=$3;
+ lex->grant_user->password.str=NullS;
+ }
| CREATE TABLE_SYM table_ident
{
Lex->sql_command = SQLCOM_SHOW_CREATE;
@@ -2266,7 +2602,7 @@ show_param:
opt_db:
/* empty */ { $$= 0; }
- | FROM ident { $$= $2.str; }
+ | from_or_in ident { $$= $2.str; }
wild:
/* empty */
@@ -2276,18 +2612,32 @@ opt_full:
/* empty */ { Lex->verbose=0; }
| FULL { Lex->verbose=1; }
+from_or_in:
+ FROM
+ | IN_SYM
+
+binlog_in:
+ /* empty */ { Lex->mi.log_file_name = 0; }
+ | IN_SYM TEXT_STRING { Lex->mi.log_file_name = $2.str; }
+
+binlog_from:
+ /* empty */ { Lex->mi.pos = 4; /* skip magic number */ }
+ | FROM ulonglong_num { Lex->mi.pos = $2; }
+
+
/* A Oracle compatible synonym for show */
describe:
describe_command table_ident
{
- Lex->wild=0;
- Lex->verbose=0;
- Lex->sql_command=SQLCOM_SHOW_FIELDS;
+ LEX *lex=Lex;
+ lex->wild=0;
+ lex->verbose=0;
+ lex->sql_command=SQLCOM_SHOW_FIELDS;
if (!add_table_to_list($2, NULL,0))
YYABORT;
}
opt_describe_column
- | describe_command select { Lex->options|= SELECT_DESCRIBE };
+ | describe_command select { Lex->select_lex.options|= SELECT_DESCRIBE };
describe_command:
@@ -2303,7 +2653,12 @@ opt_describe_column:
/* flush things */
flush:
- FLUSH_SYM {Lex->sql_command= SQLCOM_FLUSH; Lex->type=0; } flush_options
+ FLUSH_SYM
+ {
+ LEX *lex=Lex;
+ lex->sql_command= SQLCOM_FLUSH; lex->type=0;
+ }
+ flush_options
flush_options:
flush_options ',' flush_option
@@ -2312,30 +2667,41 @@ flush_options:
flush_option:
table_or_tables { Lex->type|= REFRESH_TABLES; } opt_table_list
| TABLES WITH READ_SYM LOCK_SYM { Lex->type|= REFRESH_TABLES | REFRESH_READ_LOCK; }
+ | QUERY_SYM CACHE_SYM { Lex->type|= REFRESH_QUERY_CACHE_FREE; }
| HOSTS_SYM { Lex->type|= REFRESH_HOSTS; }
| PRIVILEGES { Lex->type|= REFRESH_GRANT; }
| LOGS_SYM { Lex->type|= REFRESH_LOG; }
| STATUS_SYM { Lex->type|= REFRESH_STATUS; }
| SLAVE { Lex->type|= REFRESH_SLAVE; }
| MASTER_SYM { Lex->type|= REFRESH_MASTER; }
+ | DES_KEY_FILE { Lex->type|= REFRESH_DES_KEY_FILE; }
opt_table_list:
/* empty */ {}
| table_list {}
reset:
- RESET_SYM {Lex->sql_command= SQLCOM_RESET; Lex->type=0; } reset_options
-
+ RESET_SYM
+ {
+ LEX *lex=Lex;
+ lex->sql_command= SQLCOM_RESET; lex->type=0;
+ } reset_options
reset_options:
reset_options ',' reset_option
| reset_option
reset_option:
- SLAVE { Lex->type|= REFRESH_SLAVE; }
- | MASTER_SYM { Lex->type|= REFRESH_MASTER; }
+ SLAVE { Lex->type|= REFRESH_SLAVE; }
+ | MASTER_SYM { Lex->type|= REFRESH_MASTER; }
+ | QUERY_SYM CACHE_SYM { Lex->type|= REFRESH_QUERY_CACHE;}
purge:
- PURGE { Lex->sql_command = SQLCOM_PURGE; Lex->type=0;}
+ PURGE
+ {
+ LEX *lex=Lex;
+ lex->sql_command = SQLCOM_PURGE;
+ lex->type=0;
+ }
MASTER_SYM LOGS_SYM TO_SYM TEXT_STRING
{
Lex->to_log = $6.str;
@@ -2346,30 +2712,34 @@ purge:
kill:
KILL_SYM expr
{
- if ($2->fix_fields(current_thd,0))
- {
- send_error(&current_thd->net, ER_SET_CONSTANTS_ONLY);
- YYABORT;
- }
- Lex->sql_command=SQLCOM_KILL;
- Lex->thread_id= (ulong) $2->val_int();
+ LEX *lex=Lex;
+ if ($2->fix_fields(lex->thd,0))
+ {
+ send_error(&lex->thd->net, ER_SET_CONSTANTS_ONLY);
+ YYABORT;
+ }
+ lex->sql_command=SQLCOM_KILL;
+ lex->thread_id= (ulong) $2->val_int();
}
/* change database */
use: USE_SYM ident
- { Lex->sql_command=SQLCOM_CHANGE_DB; Lex->db= $2.str; }
+ {
+ LEX *lex=Lex;
+ lex->sql_command=SQLCOM_CHANGE_DB; lex->select->db= $2.str;
+ }
/* import, export of files */
load: LOAD DATA_SYM load_data_lock opt_local INFILE TEXT_STRING
{
- LEX *lex= Lex;
+ LEX *lex=Lex;
lex->sql_command= SQLCOM_LOAD;
lex->local_file= $4;
- if (!(Lex->exchange= new sql_exchange($6.str,0)))
+ if (!(lex->exchange= new sql_exchange($6.str,0)))
YYABORT;
- Lex->field_list.empty();
+ lex->field_list.empty();
}
opt_duplicate INTO TABLE_SYM table_ident opt_field_term opt_line_term
opt_ignore_lines opt_field_spec
@@ -2385,6 +2755,11 @@ load: LOAD DATA_SYM load_data_lock opt_local INFILE TEXT_STRING
YYABORT;
}
+ |
+ LOAD DATA_SYM FROM MASTER_SYM
+ {
+ Lex->sql_command = SQLCOM_LOAD_MASTER_DATA;
+ }
opt_local:
/* empty */ { $$=0;}
@@ -2412,7 +2787,11 @@ field_term_list:
field_term:
TERMINATED BY text_string { Lex->exchange->field_term= $3;}
| OPTIONALLY ENCLOSED BY text_string
- { Lex->exchange->enclosed= $4; Lex->exchange->opt_enclosed=1;}
+ {
+ LEX *lex=Lex;
+ lex->exchange->enclosed= $4;
+ lex->exchange->opt_enclosed=1;
+ }
| ENCLOSED BY text_string { Lex->exchange->enclosed= $3;}
| ESCAPED BY text_string { Lex->exchange->escaped= $3;}
@@ -2452,6 +2831,7 @@ literal:
text_literal { $$ = $1; }
| NUM { $$ = new Item_int($1.str, (longlong) atol($1.str),$1.length); }
| LONG_NUM { $$ = new Item_int($1.str); }
+ | ULONGLONG_NUM { $$ = new Item_uint($1.str, $1.length); }
| REAL_NUM { $$ = new Item_real($1.str, $1.length); }
| FLOAT_NUM { $$ = new Item_float($1.str, $1.length); }
| NULL_SYM { $$ = new Item_null();
@@ -2479,13 +2859,25 @@ order_ident:
simple_ident:
ident
- { $$ = !Lex->create_refs || Lex->in_sum_expr > 0 ? (Item*) new Item_field(NullS,NullS,$1.str) : (Item*) new Item_ref(NullS,NullS,$1.str); }
+ {
+ SELECT_LEX *sel=Select;
+ $$ = !sel->create_refs || sel->in_sum_expr > 0 ? (Item*) new Item_field(NullS,NullS,$1.str) : (Item*) new Item_ref(NullS,NullS,$1.str);
+ }
| ident '.' ident
- { $$ = !Lex->create_refs || Lex->in_sum_expr > 0 ? (Item*) new Item_field(NullS,$1.str,$3.str) : (Item*) new Item_ref(NullS,$1.str,$3.str); }
+ {
+ SELECT_LEX *sel=Select;
+ $$ = !sel->create_refs || sel->in_sum_expr > 0 ? (Item*) new Item_field(NullS,$1.str,$3.str) : (Item*) new Item_ref(NullS,$1.str,$3.str);
+ }
| '.' ident '.' ident
- { $$ = !Lex->create_refs || Lex->in_sum_expr > 0 ? (Item*) new Item_field(NullS,$2.str,$4.str) : (Item*) new Item_ref(NullS,$2.str,$4.str); }
+ {
+ SELECT_LEX *sel=Select;
+ $$ = !sel->create_refs || sel->in_sum_expr > 0 ? (Item*) new Item_field(NullS,$2.str,$4.str) : (Item*) new Item_ref(NullS,$2.str,$4.str);
+ }
| ident '.' ident '.' ident
- { $$ = !Lex->create_refs || Lex->in_sum_expr > 0 ? (Item*) new Item_field((current_thd->client_capabilities & CLIENT_NO_SCHEMA ? NullS :$1.str),$3.str,$5.str) : (Item*) new Item_ref((current_thd->client_capabilities & CLIENT_NO_SCHEMA ? NullS :$1.str),$3.str,$5.str); }
+ {
+ SELECT_LEX *sel=Select;
+ $$ = !sel->create_refs || sel->in_sum_expr > 0 ? (Item*) new Item_field((current_thd->client_capabilities & CLIENT_NO_SCHEMA ? NullS :$1.str),$3.str,$5.str) : (Item*) new Item_ref((current_thd->client_capabilities & CLIENT_NO_SCHEMA ? NullS :$1.str),$3.str,$5.str);
+ }
field_ident:
@@ -2502,10 +2894,11 @@ ident:
IDENT { $$=$1; }
| keyword
{
+ LEX *lex;
$$.str=sql_strmake($1.str,$1.length);
$$.length=$1.length;
- if (Lex->next_state != STATE_END)
- Lex->next_state=STATE_OPERATOR_OR_IDENT;
+ if ((lex=Lex)->next_state != STATE_END)
+ lex->next_state=STATE_OPERATOR_OR_IDENT;
}
ident_or_text:
@@ -2541,14 +2934,19 @@ keyword:
| BACKUP_SYM {}
| BEGIN_SYM {}
| BERKELEY_DB_SYM {}
+ | BINLOG_SYM {}
| BIT_SYM {}
| BOOL_SYM {}
+ | BOOLEAN_SYM {}
+ | CACHE_SYM {}
| CHANGED {}
| CHECKSUM_SYM {}
| CHECK_SYM {}
+ | CIPHER_SYM {}
+ | CLOSE_SYM {}
| COMMENT_SYM {}
- | COMMIT_SYM {}
| COMMITTED_SYM {}
+ | COMMIT_SYM {}
| COMPRESSED_SYM {}
| CONCURRENT {}
| DATA_SYM {}
@@ -2556,29 +2954,39 @@ keyword:
| DATE_SYM {}
| DAY_SYM {}
| DELAY_KEY_WRITE_SYM {}
+ | DEMAND_SYM {}
+ | DES_KEY_FILE {}
+ | DIRECTORY_SYM {}
| DO_SYM {}
| DUMPFILE {}
| DYNAMIC_SYM {}
| END {}
| ENUM {}
| ESCAPE_SYM {}
+ | EVENTS_SYM {}
| EXTENDED_SYM {}
| FAST_SYM {}
+ | DISABLE_SYM {}
+ | ENABLE_SYM {}
| FULL {}
| FILE_SYM {}
| FIRST_SYM {}
| FIXED_SYM {}
| FLUSH_SYM {}
| GRANTS {}
- | GEMINI_SYM {}
| GLOBAL_SYM {}
| HEAP_SYM {}
+ | HANDLER_SYM {}
| HOSTS_SYM {}
| HOUR_SYM {}
| IDENTIFIED_SYM {}
+ | INDEXES {}
| ISOLATION {}
| ISAM_SYM {}
+ | ISSUER_SYM {}
| INNOBASE_SYM {}
+ | INSERT_METHOD {}
+ | LAST_SYM {}
| LEVEL_SYM {}
| LOCAL_SYM {}
| LOCKS_SYM {}
@@ -2592,6 +3000,7 @@ keyword:
| MASTER_USER_SYM {}
| MASTER_PASSWORD_SYM {}
| MASTER_CONNECT_RETRY_SYM {}
+ | MAX_QUERIES_PER_HOUR {}
| MEDIUM_SYM {}
| MERGE_SYM {}
| MINUTE_SYM {}
@@ -2602,12 +3011,17 @@ keyword:
| MYISAM_SYM {}
| NATIONAL_SYM {}
| NCHAR_SYM {}
+ | NEXT_SYM {}
+ | NEW_SYM {}
| NO_SYM {}
+ | OFF {}
| OPEN_SYM {}
| PACK_KEYS_SYM {}
| PASSWORD {}
+ | PREV_SYM {}
| PROCESS {}
| PROCESSLIST_SYM {}
+ | QUERY_SYM {}
| QUICK {}
| RAID_0_SYM {}
| RAID_CHUNKS {}
@@ -2626,12 +3040,18 @@ keyword:
| SECOND_SYM {}
| SERIALIZABLE_SYM {}
| SESSION_SYM {}
+ | SIGNED_SYM {}
| SHARE_SYM {}
| SHUTDOWN {}
+ | SLAVE {}
+ | SQL_CACHE_SYM {}
+ | SQL_NO_CACHE_SYM {}
+ | SQL_QUERY_CACHE_TYPE_SYM {}
| START_SYM {}
| STATUS_SYM {}
| STOP_SYM {}
| STRING_SYM {}
+ | SUBJECT_SYM {}
| TEMPORARY {}
| TEXT_SYM {}
| TRANSACTION_SYM {}
@@ -2651,13 +3071,13 @@ keyword:
set:
SET opt_option
{
- THD *thd=current_thd;
- LEX *lex= &thd->lex;
+ LEX *lex=Lex;
lex->sql_command= SQLCOM_SET_OPTION;
- lex->options=thd->options;
- lex->select_limit=thd->default_select_limit;
- lex->gemini_spin_retries=thd->gemini_spin_retries;
- lex->tx_isolation=thd->tx_isolation;
+ lex->select->options=lex->thd->options;
+ lex->select->select_limit=lex->thd->default_select_limit;
+ lex->tx_isolation=lex->thd->tx_isolation;
+ lex->option_type=0;
+ lex->option_list.empty()
}
option_value_list
@@ -2667,36 +3087,41 @@ opt_option:
option_value_list:
option_value
+ | GLOBAL_SYM { Lex->option_type=1; } option_value
+ | LOCAL_SYM { Lex->option_type=0; } option_value
| option_value_list ',' option_value
option_value:
set_option equal NUM
{
+ SELECT_LEX *sel=Select;
if (atoi($3.str) == 0)
- Lex->options&= ~$1;
+ sel->options&= ~$1;
else
- Lex->options|= $1;
+ sel->options|= $1;
}
| set_isolation
| AUTOCOMMIT equal NUM
{
+ SELECT_LEX *sel=Select;
if (atoi($3.str) != 0) /* Test NOT AUTOCOMMIT */
- Lex->options&= ~(OPTION_NOT_AUTO_COMMIT);
+ sel->options&= ~(OPTION_NOT_AUTO_COMMIT);
else
- Lex->options|= OPTION_NOT_AUTO_COMMIT;
+ sel->options|= OPTION_NOT_AUTO_COMMIT;
}
| SQL_SELECT_LIMIT equal ULONG_NUM
{
- Lex->select_limit= $3;
+ Select->select_limit= $3;
}
| SQL_SELECT_LIMIT equal DEFAULT
{
- Lex->select_limit= HA_POS_ERROR;
+ Select->select_limit= HA_POS_ERROR;
}
| SQL_MAX_JOIN_SIZE equal ULONG_NUM
{
- current_thd->max_join_size= $3;
- Lex->options&= ~OPTION_BIG_SELECTS;
+ LEX *lex=Lex;
+ lex->thd->max_join_size= $3;
+ lex->select->options&= ~OPTION_BIG_SELECTS;
}
| SQL_MAX_JOIN_SIZE equal DEFAULT
{
@@ -2710,22 +3135,14 @@ option_value:
{
current_thd->user_time=0;
}
- | LAST_INSERT_ID equal ULONGLONG_NUM
+ | LAST_INSERT_ID equal ulonglong_num
{
current_thd->insert_id($3);
}
- | INSERT_ID equal ULONGLONG_NUM
+ | INSERT_ID equal ulonglong_num
{
current_thd->next_insert_id=$3;
}
- | GEMINI_SPIN_RETRIES equal ULONG_NUM
- {
- Lex->gemini_spin_retries= $3;
- }
- | GEMINI_SPIN_RETRIES equal DEFAULT
- {
- Lex->gemini_spin_retries= 1;
- }
| CHAR_SYM SET IDENT
{
CONVERT *tmp;
@@ -2753,6 +3170,7 @@ option_value:
$3->user.str,$5))
YYABORT;
}
+ | SQL_QUERY_CACHE_TYPE_SYM equal query_cache_type
| '@' ident_or_text equal expr
{
Item_func_set_user_var *item = new Item_func_set_user_var($2,$4);
@@ -2764,13 +3182,46 @@ option_value:
}
| SQL_SLAVE_SKIP_COUNTER equal ULONG_NUM
{
- pthread_mutex_lock(&LOCK_slave);
- if(slave_running)
+ LOCK_ACTIVE_MI;
+ pthread_mutex_lock(&active_mi->rli.run_lock);
+ if (active_mi->rli.slave_running)
send_error(&current_thd->net, ER_SLAVE_MUST_STOP);
else
- slave_skip_counter = $3;
- pthread_mutex_unlock(&LOCK_slave);
+ {
+ pthread_mutex_lock(&active_mi->rli.data_lock);
+ active_mi->rli.slave_skip_counter = $3;
+ pthread_mutex_unlock(&active_mi->rli.data_lock);
+ }
+ pthread_mutex_unlock(&active_mi->rli.run_lock);
+ UNLOCK_ACTIVE_MI;
}
+ | ident equal DEFAULT
+ {
+ LEX *lex=Lex;
+ lex->option_list.push_back(new Set_option(lex->option_type,
+ $1.str,$1.length,
+ (Item*) 0));
+ }
+ | ident equal expr
+ {
+ THD *thd=current_thd;
+ Item *item= $3;
+ if (item->fix_fields(current_thd,0))
+ {
+ send_error(&thd->net, ER_SET_CONSTANTS_ONLY);
+ YYABORT;
+ }
+ thd->lex.option_list.
+ push_back(new Set_option(thd->lex.option_type,
+ $1.str,$1.length,
+ item));
+ }
+
+query_cache_type:
+ NUM { current_thd->query_cache_type = set_zone(atoi($1.str),0,3); }
+ | OFF { current_thd->query_cache_type = 0; }
+ | ON { current_thd->query_cache_type = 1; }
+ | DEMAND_SYM { current_thd->query_cache_type = 2; }
text_or_password:
TEXT_STRING { $$=$1.str;}
@@ -2819,7 +3270,10 @@ set_isolation:
default_tx_isolation_name=tx_isolation_typelib.type_names[default_tx_isolation];
}
| SESSION_SYM tx_isolation
- { current_thd->session_tx_isolation= Lex->tx_isolation= $2; }
+ {
+ LEX *lex=Lex;
+ lex->thd->session_tx_isolation= lex->tx_isolation= $2;
+ }
| tx_isolation
{ Lex->tx_isolation= $1; }
@@ -2863,30 +3317,93 @@ unlock:
UNLOCK_SYM table_or_tables { Lex->sql_command=SQLCOM_UNLOCK_TABLES; }
+/*
+** Handler: direct access to ISAM functions
+*/
+
+handler:
+ HANDLER_SYM table_ident OPEN_SYM opt_table_alias
+ {
+ Lex->sql_command = SQLCOM_HA_OPEN;
+ if (!add_table_to_list($2,$4,0))
+ YYABORT;
+ }
+ | HANDLER_SYM table_ident CLOSE_SYM
+ {
+ Lex->sql_command = SQLCOM_HA_CLOSE;
+ if (!add_table_to_list($2,0,0))
+ YYABORT;
+ }
+ | HANDLER_SYM table_ident READ_SYM
+ {
+ LEX *lex=Lex;
+ lex->sql_command = SQLCOM_HA_READ;
+ lex->ha_rkey_mode= HA_READ_KEY_EXACT; /* Avoid purify warnings */
+ lex->select->select_limit= 1;
+ lex->select->offset_limit= 0L;
+ if (!add_table_to_list($2,0,0))
+ YYABORT;
+ }
+ handler_read_or_scan where_clause limit_clause { }
+
+handler_read_or_scan:
+ handler_scan_function { Lex->backup_dir= 0; }
+ | ident handler_rkey_function { Lex->backup_dir= $1.str; }
+
+handler_scan_function:
+ FIRST_SYM { Lex->ha_read_mode = RFIRST; }
+ | NEXT_SYM { Lex->ha_read_mode = RNEXT; }
+
+handler_rkey_function:
+ FIRST_SYM { Lex->ha_read_mode = RFIRST; }
+ | NEXT_SYM { Lex->ha_read_mode = RNEXT; }
+ | PREV_SYM { Lex->ha_read_mode = RPREV; }
+ | LAST_SYM { Lex->ha_read_mode = RLAST; }
+ | handler_rkey_mode
+ {
+ LEX *lex=Lex;
+ lex->ha_read_mode = RKEY;
+ lex->ha_rkey_mode=$1;
+ if (!(lex->insert_list = new List_item))
+ YYABORT;
+ } '(' values ')' { }
+
+handler_rkey_mode:
+ EQ { $$=HA_READ_KEY_EXACT; }
+ | GE { $$=HA_READ_KEY_OR_NEXT; }
+ | LE { $$=HA_READ_KEY_OR_PREV; }
+ | GT_SYM { $$=HA_READ_AFTER_KEY; }
+ | LT { $$=HA_READ_BEFORE_KEY; }
+
/* GRANT / REVOKE */
revoke:
REVOKE
{
- Lex->sql_command = SQLCOM_REVOKE;
- Lex->users_list.empty();
- Lex->columns.empty();
- Lex->grant= Lex->grant_tot_col=0;
- Lex->db=0;
+ LEX *lex=Lex;
+ lex->sql_command = SQLCOM_REVOKE;
+ lex->users_list.empty();
+ lex->columns.empty();
+ lex->grant= lex->grant_tot_col=0;
+ lex->select->db=0;
}
grant_privileges ON opt_table FROM user_list
grant:
GRANT
{
- Lex->sql_command = SQLCOM_GRANT;
- Lex->users_list.empty();
- Lex->columns.empty();
- Lex->grant= Lex->grant_tot_col=0;
- Lex->db=0;
+ LEX *lex=Lex;
+ lex->sql_command = SQLCOM_GRANT;
+ lex->users_list.empty();
+ lex->columns.empty();
+ lex->grant= lex->grant_tot_col=0;
+ lex->select->db=0;
+ lex->ssl_type=SSL_TYPE_NONE;
+ lex->ssl_cipher=lex->x509_subject=lex->x509_issuer=0;
+ lex->mqh=0;
}
grant_privileges ON opt_table TO_SYM user_list
- grant_option
+ require_clause grant_options
grant_privileges:
grant_privilege_list {}
@@ -2920,46 +3437,84 @@ grant_privilege:
| FILE_SYM { Lex->grant |= FILE_ACL;}
| GRANT OPTION { Lex->grant |= GRANT_ACL;}
+require_list: require_list_element AND require_list
+| require_list_element
+
+require_list_element: SUBJECT_SYM TEXT_STRING
+ {
+ LEX *lex=Lex;
+ if (lex->x509_subject)
+ {
+ net_printf(&lex->thd->net,ER_DUP_ARGUMENT, "SUBJECT");
+ YYABORT;
+ }
+ lex->x509_subject=$2.str;
+ }
+ | ISSUER_SYM TEXT_STRING
+ {
+ LEX *lex=Lex;
+ if (lex->x509_issuer)
+ {
+ net_printf(&lex->thd->net,ER_DUP_ARGUMENT, "ISSUER");
+ YYABORT;
+ }
+ lex->x509_issuer=$2.str;
+ }
+ | CIPHER_SYM TEXT_STRING
+ {
+ LEX *lex=Lex;
+ if (lex->ssl_cipher)
+ {
+ net_printf(&lex->thd->net,ER_DUP_ARGUMENT, "CHIPER");
+ YYABORT;
+ }
+ lex->ssl_cipher=$2.str;
+ }
+
opt_table:
'*'
{
- Lex->db=current_thd->db;
- if (Lex->grant == UINT_MAX)
- Lex->grant = DB_ACLS & ~GRANT_ACL;
- else if (Lex->columns.elements)
+ LEX *lex=Lex;
+ lex->select->db=lex->thd->db;
+ if (lex->grant == UINT_MAX)
+ lex->grant = DB_ACLS & ~GRANT_ACL;
+ else if (lex->columns.elements)
{
- net_printf(&current_thd->net,ER_ILLEGAL_GRANT_FOR_TABLE);
+ send_error(&lex->thd->net,ER_ILLEGAL_GRANT_FOR_TABLE);
YYABORT;
- }
+ }
}
| ident '.' '*'
{
- Lex->db = $1.str;
- if (Lex->grant == UINT_MAX)
- Lex->grant = DB_ACLS & ~GRANT_ACL;
- else if (Lex->columns.elements)
+ LEX *lex=Lex;
+ lex->select->db = $1.str;
+ if (lex->grant == UINT_MAX)
+ lex->grant = DB_ACLS & ~GRANT_ACL;
+ else if (lex->columns.elements)
{
- net_printf(&current_thd->net,ER_ILLEGAL_GRANT_FOR_TABLE);
+ send_error(&lex->thd->net,ER_ILLEGAL_GRANT_FOR_TABLE);
YYABORT;
}
}
| '*' '.' '*'
{
- Lex->db = NULL;
- if (Lex->grant == UINT_MAX)
- Lex->grant = GLOBAL_ACLS & ~GRANT_ACL;
- else if (Lex->columns.elements)
+ LEX *lex=Lex;
+ lex->select->db = NULL;
+ if (lex->grant == UINT_MAX)
+ lex->grant = GLOBAL_ACLS & ~GRANT_ACL;
+ else if (lex->columns.elements)
{
- net_printf(&current_thd->net,ER_ILLEGAL_GRANT_FOR_TABLE);
+ send_error(&lex->thd->net,ER_ILLEGAL_GRANT_FOR_TABLE);
YYABORT;
}
}
| table_ident
{
+ LEX *lex=Lex;
if (!add_table_to_list($1,NULL,0))
YYABORT;
- if (Lex->grant == UINT_MAX)
- Lex->grant = TABLE_ACLS & ~GRANT_ACL;
+ if (lex->grant == UINT_MAX)
+ lex->grant = TABLE_ACLS & ~GRANT_ACL;
}
@@ -2990,7 +3545,11 @@ grant_user:
opt_column_list:
- /* empty */ { Lex->grant |= Lex->which_columns; }
+ /* empty */
+ {
+ LEX *lex=Lex;
+ lex->grant |= lex->which_columns;
+ }
| '(' column_list ')'
column_list:
@@ -3003,21 +3562,48 @@ column_list_id:
String *new_str = new String((const char*) $1.str,$1.length);
List_iterator <LEX_COLUMN> iter(Lex->columns);
class LEX_COLUMN *point;
+ LEX *lex=Lex;
while ((point=iter++))
{
if (!my_strcasecmp(point->column.ptr(),new_str->ptr()))
break;
}
- Lex->grant_tot_col|= Lex->which_columns;
+ lex->grant_tot_col|= lex->which_columns;
if (point)
- point->rights |= Lex->which_columns;
+ point->rights |= lex->which_columns;
else
- Lex->columns.push_back(new LEX_COLUMN (*new_str,Lex->which_columns));
+ lex->columns.push_back(new LEX_COLUMN (*new_str,lex->which_columns));
}
-grant_option:
+
+require_clause: /* empty */
+ | REQUIRE_SYM require_list
+ {
+ Lex->ssl_type=SSL_TYPE_SPECIFIED;
+ }
+ | REQUIRE_SYM SSL_SYM
+ {
+ Lex->ssl_type=SSL_TYPE_ANY;
+ }
+ | REQUIRE_SYM X509_SYM
+ {
+ Lex->ssl_type=SSL_TYPE_X509;
+ }
+
+grant_options:
/* empty */ {}
- | WITH GRANT OPTION { Lex->grant |= GRANT_ACL;}
+ | WITH grant_option_list
+
+grant_option_list:
+ grant_option_list grant_option {}
+ | grant_option {}
+
+grant_option:
+ GRANT OPTION { Lex->grant |= GRANT_ACL;}
+ | MAX_QUERIES_PER_HOUR EQ NUM
+ {
+ Lex->mqh=atoi($3.str);
+ }
begin:
BEGIN_SYM { Lex->sql_command = SQLCOM_BEGIN;} opt_work
@@ -3031,3 +3617,50 @@ commit:
rollback:
ROLLBACK_SYM { Lex->sql_command = SQLCOM_ROLLBACK;}
+
+
+/*
+** UNIONS : glue selects together
+*/
+
+
+union:
+ /* empty */ {}
+ | union_list
+
+union_list:
+ UNION_SYM union_option
+ {
+ LEX *lex=Lex;
+ if (lex->exchange)
+ {
+ /* Only the last SELECT can have INTO...... */
+ net_printf(&lex->thd->net, ER_WRONG_USAGE,"UNION","INTO");
+ YYABORT;
+ }
+ if (lex->select->linkage == NOT_A_SELECT || mysql_new_select(lex))
+ YYABORT;
+ lex->select->linkage=UNION_TYPE;
+ }
+ select_init
+
+union_opt:
+ union {}
+ | optional_order_or_limit {}
+
+optional_order_or_limit:
+ /* emty */ {}
+ |
+ {
+ LEX *lex=Lex;
+ if (!lex->select->braces || mysql_new_select(lex))
+ YYABORT;
+ mysql_init_select(lex);
+ lex->select->linkage=NOT_A_SELECT;
+ lex->select->select_limit=lex->thd->default_select_limit;
+ }
+ opt_order_clause limit_clause
+
+union_option:
+ /* empty */ {}
+ | ALL {Lex->union_option=1;}
diff --git a/sql/stacktrace.c b/sql/stacktrace.c
index f4415571f1b..d86d65f567e 100644
--- a/sql/stacktrace.c
+++ b/sql/stacktrace.c
@@ -14,7 +14,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-#include <global.h>
+#include <my_global.h>
#include "stacktrace.h"
#include <signal.h>
#include <my_pthread.h>
@@ -122,8 +122,8 @@ terribly wrong...\n");
return;
}
#endif /* __alpha__ */
-
- if (!stack_bottom)
+
+ if (!stack_bottom || (gptr) stack_bottom > (gptr) &fp)
{
ulong tmp= min(0x10000,thread_stack);
/* Assume that the stack starts at the previous even 65K */
@@ -150,7 +150,7 @@ terribly wrong...\n");
:"=r"(pc)
:"r"(pc));
#endif /* __alpha__ */
-
+
while (fp < (uchar**) stack_bottom)
{
#ifdef __i386__
@@ -165,7 +165,7 @@ terribly wrong...\n");
{
new_fp += 90;
}
-
+
if (fp && pc)
{
pc = find_prev_pc(pc, fp);
@@ -195,7 +195,7 @@ terribly wrong...\n");
}
fprintf(stderr, "Stack trace seems successful - bottom reached\n");
-
+
end:
fprintf(stderr, "Please read http://www.mysql.com/doc/U/s/Using_stack_trace.html and follow instructions on how to resolve the stack trace. Resolved\n\
stack trace is much more helpful in diagnosing the problem, so please do \n\
diff --git a/sql/structs.h b/sql/structs.h
index 36f503312c0..9e577128c8d 100644
--- a/sql/structs.h
+++ b/sql/structs.h
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -125,7 +125,23 @@ typedef struct {
enum SHOW_TYPE { SHOW_LONG,SHOW_CHAR,SHOW_INT,SHOW_CHAR_PTR,SHOW_BOOL,
SHOW_MY_BOOL,SHOW_OPENTABLES,SHOW_STARTTIME,SHOW_QUESTION,
- SHOW_LONG_CONST, SHOW_INT_CONST, SHOW_HAVE};
+ SHOW_LONG_CONST, SHOW_INT_CONST, SHOW_HAVE
+#ifdef HAVE_OPENSSL
+ ,SHOW_SSL_CTX_SESS_ACCEPT, SHOW_SSL_CTX_SESS_ACCEPT_GOOD
+ ,SHOW_SSL_GET_VERSION, SHOW_SSL_CTX_GET_SESSION_CACHE_MODE
+ ,SHOW_SSL_CTX_SESS_CB_HITS, SHOW_SSL_CTX_SESS_ACCEPT_RENEGOTIATE
+ ,SHOW_SSL_CTX_SESS_NUMBER, SHOW_SSL_SESSION_REUSED
+ ,SHOW_SSL_CTX_SESS_GET_CACHE_SIZE, SHOW_SSL_GET_CIPHER
+ ,SHOW_SSL_GET_DEFAULT_TIMEOUT, SHOW_SSL_GET_VERIFY_MODE
+ ,SHOW_SSL_CTX_GET_VERIFY_MODE, SHOW_SSL_GET_VERIFY_DEPTH
+ ,SHOW_SSL_CTX_GET_VERIFY_DEPTH, SHOW_SSL_CTX_SESS_CONNECT
+ ,SHOW_SSL_CTX_SESS_CONNECT_RENEGOTIATE, SHOW_SSL_CTX_SESS_CONNECT_GOOD
+ ,SHOW_SSL_CTX_SESS_HITS, SHOW_SSL_CTX_SESS_MISSES
+ ,SHOW_SSL_CTX_SESS_TIMEOUTS, SHOW_SSL_CTX_SESS_CACHE_FULL
+ ,SHOW_SSL_GET_CIPHER_LIST
+#endif /* HAVE_OPENSSL */
+ ,SHOW_RPL_STATUS, SHOW_SLAVE_RUNNING
+};
enum SHOW_COMP_OPTION { SHOW_OPTION_YES, SHOW_OPTION_NO, SHOW_OPTION_DISABLED};
@@ -144,6 +160,14 @@ typedef struct st_lex_user {
LEX_STRING user, host, password;
} LEX_USER;
+
+typedef struct user_conn {
+ char *user;
+ uint len, connections, questions, max_questions;
+ time_t intime;
+} UC;
+
+
/* Bits in form->update */
#define REG_MAKE_DUPP 1 /* Make a copy of record when read */
#define REG_NEW_RECORD 2 /* Write a new record if not found */
@@ -154,13 +178,14 @@ typedef struct st_lex_user {
#define REG_MAY_BE_UPDATED 64
#define REG_AUTO_UPDATE 64 /* Used in D-forms for scroll-tables */
#define REG_OVERWRITE 128
-#define REG_SKIPP_DUPP 256
+#define REG_SKIP_DUP 256
/* Bits in form->status */
#define STATUS_NO_RECORD (1+2) /* Record isn't usably */
#define STATUS_GARBAGE 1
-#define STATUS_NOT_FOUND 2 /* No record in database when neaded */
+#define STATUS_NOT_FOUND 2 /* No record in database when needed */
#define STATUS_NO_PARENT 4 /* Parent record wasn't found */
#define STATUS_NOT_READ 8 /* Record isn't read */
#define STATUS_UPDATED 16 /* Record is updated by formula */
#define STATUS_NULL_ROW 32 /* table->null_row is set */
+#define STATUS_DELETED 64
diff --git a/sql/table.cc b/sql/table.cc
index 1ab6c50add9..9aae9e17e5a 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -259,7 +259,7 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
outparam->comment=strdup_root(&outparam->mem_root,
(char*) head+47);
- DBUG_PRINT("form",("i_count: %d i_parts: %d index: %d n_length: %d int_length: %d", interval_count,interval_parts, outparam->keys,n_length,int_length));
+ DBUG_PRINT("info",("i_count: %d i_parts: %d index: %d n_length: %d int_length: %d", interval_count,interval_parts, outparam->keys,n_length,int_length));
if (!(field_ptr = (Field **)
alloc_root(&outparam->mem_root,
@@ -453,15 +453,20 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
if (key == primary_key)
{
field->flags|= PRI_KEY_FLAG;
+ /*
+ If this field is part of the primary key and all keys contains
+ the primary key, then we can use any key to find this column
+ */
if (ha_option & HA_PRIMARY_KEY_IN_READ_INDEX)
- field->part_of_key|= ((key_map) 1 << primary_key);
+ field->part_of_key= outparam->keys_in_use;
}
if (field->key_length() != key_part->length)
{
key_part->key_part_flag|= HA_PART_KEY;
if (field->type() != FIELD_TYPE_BLOB)
{ // Create a new field
- field=key_part->field=field->new_field(outparam);
+ field=key_part->field=field->new_field(&outparam->mem_root,
+ outparam);
field->field_length=key_part->length;
}
}
@@ -478,8 +483,6 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
(outparam->keys_in_use & ((key_map) 1 << primary_key)))
{
outparam->primary_key=primary_key;
- if (outparam->file->option_flag() & HA_PRIMARY_KEY_IN_READ_INDEX)
- outparam->ref_primary_key= (key_map) 1 << primary_key;
/*
If we are using an integer as the primary key then allow the user to
refer to it as '_rowid'
@@ -820,7 +823,7 @@ fix_type_pointers(const char ***array, TYPELIB *point_to_type, uint types,
*type_name= '\0'; /* End string */
ptr=type_name;
}
- ptr+=2; /* Skipp end mark and last 0 */
+ ptr+=2; /* Skip end mark and last 0 */
}
else
ptr++;
@@ -994,6 +997,7 @@ File create_frm(register my_string name, uint reclength, uchar *fileinfo,
void update_create_info_from_table(HA_CREATE_INFO *create_info, TABLE *table)
{
+ DBUG_ENTER("update_create_info_from_table");
create_info->max_rows=table->max_rows;
create_info->min_rows=table->min_rows;
create_info->table_options=table->db_create_options;
@@ -1002,7 +1006,8 @@ void update_create_info_from_table(HA_CREATE_INFO *create_info, TABLE *table)
create_info->raid_type=table->raid_type;
create_info->raid_chunks=table->raid_chunks;
create_info->raid_chunksize=table->raid_chunksize;
-}
+ DBUG_VOID_RETURN;
+}
int
rename_file_ext(const char * from,const char * to,const char * ext)
diff --git a/sql/table.h b/sql/table.h
index b627a158556..259c34030b2 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -89,7 +89,7 @@ struct st_table {
my_bool copy_blobs; /* copy_blobs when storing */
my_bool null_row; /* All columns are null */
my_bool maybe_null,outer_join; /* Used with OUTER JOIN */
- my_bool distinct,const_table;
+ my_bool distinct,const_table,no_rows;
my_bool key_read;
my_bool crypted;
my_bool db_low_byte_first; /* Portable row format */
@@ -97,6 +97,7 @@ struct st_table {
my_bool locked_by_name;
my_bool crashed;
my_bool is_view;
+ my_bool no_keyread;
Field *next_number_field, /* Set if next_number is activated */
*found_next_number_field, /* Set on open */
*rowid_field;
@@ -117,7 +118,7 @@ struct st_table {
byte *record_pointers; /* If sorted in memory */
ha_rows found_records; /* How many records in sort */
ORDER *group;
- key_map quick_keys, used_keys, ref_primary_key;
+ key_map quick_keys, used_keys;
ha_rows quick_rows[MAX_KEY];
uint quick_key_parts[MAX_KEY];
key_part_map const_key_parts[MAX_KEY];
@@ -145,4 +146,12 @@ typedef struct st_table_list {
uint outer_join; /* Which join type */
bool straight; /* optimize with prev table */
bool updating; /* for replicate-do/ignore table */
+ bool shared; /* Used twice in union */
} TABLE_LIST;
+
+typedef struct st_open_table_list
+{
+ struct st_open_table_list *next;
+ char *db,*table;
+ uint32 in_use,locked;
+} OPEN_TABLE_LIST;
diff --git a/sql/thr_malloc.cc b/sql/thr_malloc.cc
index deb304443df..8b9baa6f045 100644
--- a/sql/thr_malloc.cc
+++ b/sql/thr_malloc.cc
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -22,7 +22,9 @@
extern "C" {
void sql_alloc_error_handler(void)
{
- current_thd->fatal_error=1; /* purecov: inspected */
+ THD *thd=current_thd;
+ if (thd) // QQ; To be removed
+ thd->fatal_error=1; /* purecov: inspected */
sql_print_error(ER(ER_OUT_OF_RESOURCES));
}
}
diff --git a/sql/time.cc b/sql/time.cc
index 1d7e055f682..aab886648e3 100644
--- a/sql/time.cc
+++ b/sql/time.cc
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -24,7 +24,7 @@ static ulong const days_at_timestart=719528; /* daynr at 1970.01.01 */
uchar *days_in_month= (uchar*) "\037\034\037\036\037\036\037\037\036\037\036\037";
- /* Init some variabels neaded when using my_local_time */
+ /* Init some variabels needed when using my_local_time */
/* Currently only my_time_zone is inited */
static long my_time_zone=0;
@@ -54,7 +54,7 @@ void init_time(void)
This code handles also day light saving time.
The idea is to cache the time zone (including daylight saving time)
for the next call to make things faster.
-
+
*/
long my_gmt_sec(TIME *t)
@@ -128,7 +128,7 @@ long calc_daynr(uint year,uint month,uint day)
DBUG_ENTER("calc_daynr");
if (year == 0 && month == 0 && day == 0)
- DBUG_RETURN(0); /* Skipp errors */
+ DBUG_RETURN(0); /* Skip errors */
if (year < 200)
{
if ((year=year+1900) < 1900+YY_PART_YEAR)
@@ -176,7 +176,9 @@ uint calc_week(TIME *l_time, bool with_year, bool sunday_first_day_of_week,
ulong first_daynr=calc_daynr(l_time->year,1,1);
uint weekday=calc_weekday(first_daynr,sunday_first_day_of_week);
*year=l_time->year;
- if (l_time->month == 1 && weekday >= 4 && l_time->day <= 7-weekday)
+ if (l_time->month == 1 && l_time->day <= 7-weekday &&
+ ((!sunday_first_day_of_week && weekday >= 4) ||
+ (sunday_first_day_of_week && weekday != 0)))
{
/* Last week of the previous year */
if (!with_year)
@@ -186,7 +188,8 @@ uint calc_week(TIME *l_time, bool with_year, bool sunday_first_day_of_week,
first_daynr-= (days=calc_days_in_year(*year));
weekday= (weekday + 53*7- days) % 7;
}
- if (weekday >= 4)
+ if ((sunday_first_day_of_week && weekday != 0) ||
+ (!sunday_first_day_of_week && weekday >= 4))
days= daynr - (first_daynr+ (7-weekday));
else
days= daynr - (first_daynr - weekday);
@@ -431,7 +434,7 @@ str_to_TIME(const char *str, uint length, TIME *l_time,bool fuzzy_date)
DBUG_ENTER("str_to_TIME");
DBUG_PRINT("enter",("str: %.*s",length,str));
- for (; str != end && !isdigit(*str) ; str++) ; // Skipp garbage
+ for (; str != end && !isdigit(*str) ; str++) ; // Skip garbage
if (str == end)
DBUG_RETURN(TIMESTAMP_NONE);
/*
@@ -591,7 +594,7 @@ bool str_to_time(const char *str,uint length,TIME *l_time)
date[0]=value;
state=1; // Assume next is hours
found_days=1;
- str++; // Skipp space;
+ str++; // Skip space;
}
else if ((end-str) > 1 && *str == ':' && isdigit(str[1]))
{
@@ -599,7 +602,7 @@ bool str_to_time(const char *str,uint length,TIME *l_time)
date[1]=value;
state=2;
found_hours=1;
- str++; // skipp ':'
+ str++; // skip ':'
}
else
{
@@ -620,7 +623,7 @@ bool str_to_time(const char *str,uint length,TIME *l_time)
date[state++]=value;
if (state == 4 || (end-str) < 2 || *str != ':' || !isdigit(str[1]))
break;
- str++; // Skipp ':'
+ str++; // Skip ':'
}
if (state != 4)
diff --git a/sql/udf_example.cc b/sql/udf_example.cc
index a91db5ee1cc..a5ec77f88e4 100644
--- a/sql/udf_example.cc
+++ b/sql/udf_example.cc
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -110,7 +110,7 @@
#include <stdio.h>
#include <string.h>
#else
-#include <global.h>
+#include <my_global.h>
#include <my_sys.h>
#endif
#include <mysql.h>
diff --git a/sql/uniques.cc b/sql/uniques.cc
new file mode 100644
index 00000000000..6b05618bcc7
--- /dev/null
+++ b/sql/uniques.cc
@@ -0,0 +1,166 @@
+/* Copyright (C) 2001 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+/*
+ Function to handle quick removal of duplicates
+ This code is used when doing multi-table deletes to find the rows in
+ reference tables that needs to be deleted.
+
+ The basic idea is as follows:
+
+ Store first all strings in a binary tree, ignoring duplicates.
+ When the three uses more memory than 'max_heap_table_size',
+ write the tree (in sorted order) out to disk and start with a new tree.
+ When all data has been generated, merge the trees (removing any found
+ duplicates).
+
+ The unique entries will be returned in sort order, to ensure that we do the
+ deletes in disk order.
+*/
+
+#include "mysql_priv.h"
+#include "sql_sort.h"
+
+
+int unique_write_to_file(gptr key, element_count count, Unique *unique)
+{
+ return my_b_write(&unique->file, (byte*) key,
+ unique->tree.size_of_element) ? 1 : 0;
+}
+
+int unique_write_to_ptrs(gptr key, element_count count, Unique *unique)
+{
+ memcpy(unique->record_pointers, key, unique->tree.size_of_element);
+ unique->record_pointers+=unique->tree.size_of_element;
+ return 0;
+}
+
+Unique::Unique(qsort_cmp2 comp_func, void * comp_func_fixed_arg,
+ uint size, ulong max_in_memory_size_arg)
+ :max_in_memory_size(max_in_memory_size_arg),elements(0)
+{
+ my_b_clear(&file);
+ init_tree(&tree, max_in_memory_size / 16, 0, size, comp_func, 0, NULL, comp_func_fixed_arg);
+ /* If the following fail's the next add will also fail */
+ init_dynamic_array(&file_ptrs, sizeof(BUFFPEK), 16, 16);
+ max_elements= max_in_memory_size / ALIGN_SIZE(sizeof(TREE_ELEMENT)+size);
+ open_cached_file(&file, mysql_tmpdir,TEMP_PREFIX, DISK_BUFFER_SIZE,
+ MYF(MY_WME));
+}
+
+
+Unique::~Unique()
+{
+ close_cached_file(&file);
+ delete_tree(&tree);
+ delete_dynamic(&file_ptrs);
+}
+
+
+ /* Write tree to disk; clear tree */
+bool Unique::flush()
+{
+ BUFFPEK file_ptr;
+ elements+= tree.elements_in_tree;
+ file_ptr.count=tree.elements_in_tree;
+ file_ptr.file_pos=my_b_tell(&file);
+ if (tree_walk(&tree, (tree_walk_action) unique_write_to_file,
+ (void*) this, left_root_right) ||
+ insert_dynamic(&file_ptrs, (gptr) &file_ptr))
+ return 1;
+ delete_tree(&tree);
+ return 0;
+}
+
+
+/*
+ Modify the TABLE element so that when one calls init_records()
+ the rows will be read in priority order.
+*/
+
+bool Unique::get(TABLE *table)
+{
+ SORTPARAM sort_param;
+ table->found_records=elements+tree.elements_in_tree;
+
+ if (my_b_tell(&file) == 0)
+ {
+ /* Whole tree is in memory; Don't use disk if you don't need to */
+ if ((record_pointers=table->record_pointers= (byte*)
+ my_malloc(tree.size_of_element * tree.elements_in_tree, MYF(0))))
+ {
+ (void) tree_walk(&tree, (tree_walk_action) unique_write_to_ptrs,
+ this, left_root_right);
+ return 0;
+ }
+ }
+ /* Not enough memory; Save the result to file */
+ if (flush())
+ return 1;
+
+ IO_CACHE *outfile=table->io_cache;
+ BUFFPEK *file_ptr= (BUFFPEK*) file_ptrs.buffer;
+ uint maxbuffer= file_ptrs.elements - 1;
+ uchar *sort_buffer;
+ my_off_t save_pos;
+ bool error=1;
+
+ /* Open cached file if it isn't open */
+ outfile=table->io_cache=(IO_CACHE*) my_malloc(sizeof(IO_CACHE),
+ MYF(MY_ZEROFILL));
+
+ if (!outfile || ! my_b_inited(outfile) &&
+ open_cached_file(outfile,mysql_tmpdir,TEMP_PREFIX,READ_RECORD_BUFFER,
+ MYF(MY_WME)))
+ return 1;
+ reinit_io_cache(outfile,WRITE_CACHE,0L,0,0);
+
+ bzero((char*) &sort_param,sizeof(sort_param));
+ sort_param.max_rows= elements;
+ sort_param.sort_form=table;
+ sort_param.sort_length=sort_param.ref_length=tree.size_of_element;
+ sort_param.keys= max_in_memory_size / sort_param.sort_length;
+ sort_param.not_killable=1;
+
+ if (!(sort_buffer=(uchar*) my_malloc((sort_param.keys+1) *
+ sort_param.sort_length,
+ MYF(0))))
+ return 1;
+ sort_param.unique_buff= sort_buffer+(sort_param.keys*
+ sort_param.sort_length);
+
+ /* Merge the buffers to one file, removing duplicates */
+ if (merge_many_buff(&sort_param,sort_buffer,file_ptr,&maxbuffer,&file))
+ goto err;
+ if (flush_io_cache(&file) ||
+ reinit_io_cache(&file,READ_CACHE,0L,0,0))
+ goto err;
+ if (merge_buffers(&sort_param, &file, outfile, sort_buffer, file_ptr,
+ file_ptr, file_ptr+maxbuffer,0))
+ goto err;
+ error=0;
+err:
+ x_free((gptr) sort_buffer);
+ if (flush_io_cache(outfile))
+ error=1;
+
+ /* Setup io_cache for reading */
+ save_pos=outfile->pos_in_file;
+ if (reinit_io_cache(outfile,READ_CACHE,0L,0,0))
+ error=1;
+ outfile->end_of_file=save_pos;
+ return error;
+}
diff --git a/sql/unireg.cc b/sql/unireg.cc
index f7b040adebe..16ba8c7d58b 100644
--- a/sql/unireg.cc
+++ b/sql/unireg.cc
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -20,7 +20,7 @@
struct.
In the following functions FIELD * is an ordinary field-structure with
the following exeptions:
- sc_length,typepos,row,kol,dtype,regnr and field nead not to be set.
+ sc_length,typepos,row,kol,dtype,regnr and field need not to be set.
str is a (long) to record position where 0 is the first position.
*/
@@ -391,8 +391,8 @@ static bool pack_header(uchar *forminfo, enum db_type table_type,
int2store(forminfo+272,int_parts);
int2store(forminfo+274,int_length);
int2store(forminfo+276,time_stamp_pos);
- int2store(forminfo+278,80); /* Columns neaded */
- int2store(forminfo+280,22); /* Rows neaded */
+ int2store(forminfo+278,80); /* Columns needed */
+ int2store(forminfo+280,22); /* Rows needed */
int2store(forminfo+282,null_fields);
DBUG_RETURN(0);
} /* pack_header */
diff --git a/sql/unireg.h b/sql/unireg.h
index f8f5edd5156..c4d2052d1da 100644
--- a/sql/unireg.h
+++ b/sql/unireg.h
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -80,7 +80,7 @@
#define MYF_RW MYF(MY_WME+MY_NABP) /* Vid my_read & my_write */
#define SPECIAL_USE_LOCKS 1 /* Lock used databases */
-#define SPECIAL_NO_NEW_FUNC 2 /* Skipp new functions */
+#define SPECIAL_NO_NEW_FUNC 2 /* Skip new functions */
#define SPECIAL_NEW_FUNC 4 /* New nonstandard functions */
#define SPECIAL_WAIT_IF_LOCKED 8 /* Wait if locked database */
#define SPECIAL_SAME_DB_NAME 16 /* form name = file name */
diff --git a/strings/Makefile.am b/strings/Makefile.am
index 6bf21d630f3..3bce48045b3 100644
--- a/strings/Makefile.am
+++ b/strings/Makefile.am
@@ -22,7 +22,7 @@ pkglib_LIBRARIES = libmystrings.a
# Exact one of ASSEMBLER_X
if ASSEMBLER_x86
ASRCS = strings-x86.s longlong2str-x86.s
-CSRCS = bfill.c bmove.c bmove512.c bchange.c strxnmov.c int2str.c str2int.c r_strinstr.c atof.c bcmp.c strtol.c strtoul.c strtoll.c strtoull.c strxmov.c bmove_upp.c strappend.c strcont.c strend.c strfill.c strcend.c is_prefix.c strstr.c strinstr.c strmake.c strnmov.c strmov.c longlong2str.c llstr.c ctype.c strnlen.c
+CSRCS = bfill.c bmove.c bmove512.c bchange.c strxnmov.c int2str.c str2int.c r_strinstr.c atof.c bcmp.c strtol.c strtoul.c strtoll.c strtoull.c llstr.c ctype.c strnlen.c
else
if ASSEMBLER_sparc
# These file MUST all be on the same line!! Otherwise automake
@@ -43,7 +43,7 @@ noinst_PROGRAMS = conf_to_src
# Default charset definitions
EXTRA_DIST = ctype-big5.c ctype-czech.c ctype-euc_kr.c \
ctype-gb2312.c ctype-gbk.c ctype-sjis.c \
- ctype-tis620.c ctype-ujis.c \
+ ctype-tis620.c ctype-ujis.c ctype-latin1_de.c \
ctype_autoconf.c \
strto.c strings-x86.s longlong2str-x86.s \
strxmov.c bmove_upp.c strappend.c strcont.c strend.c \
diff --git a/strings/atof.c b/strings/atof.c
index 1ce16027089..0e0aa598718 100644
--- a/strings/atof.c
+++ b/strings/atof.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/*
A quicker atof. About 2-10 times faster than standard atof on sparc.
@@ -23,7 +22,7 @@
Must be inited with init_my_atof to handle possibly overflows.
*/
-#include <global.h>
+#include <my_global.h>
#ifdef USE_MY_ATOF /* Skipp if we don't want it */
#include <m_ctype.h>
#include <floatingpoint.h>
diff --git a/strings/bchange.c b/strings/bchange.c
index 99066cf1e95..034dd3382e1 100644
--- a/strings/bchange.c
+++ b/strings/bchange.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/* File : bchange.c
Author : Michael widenius
@@ -25,10 +24,11 @@
src in a buffer with tot_length bytes.
*/
-#include <global.h>
+#include <my_global.h>
#include "m_string.h"
-void bchange(register char *dst, uint old_length, register const char *src, uint new_length, uint tot_length)
+void bchange(register char *dst, uint old_length, register const char *src,
+ uint new_length, uint tot_length)
{
uint rest=tot_length-old_length;
if (old_length < new_length)
diff --git a/strings/bcmp.c b/strings/bcmp.c
index 3dce5025b64..64a6b72c443 100644
--- a/strings/bcmp.c
+++ b/strings/bcmp.c
@@ -1,30 +1,35 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/*
bcmp(s1, s2, len) returns 0 if the "len" bytes starting at "s1" are
identical to the "len" bytes starting at "s2", non-zero if they are
different.
- Now only used with purify.
+ Now only used with purify because purify gives wrong warnings when
+ comparing a shorter string with bcmp.
*/
-#include <global.h>
+#include <my_global.h>
#include "m_string.h"
+#ifdef HAVE_purify
+#undef bcmp
+#undef HAVE_BCMP
+#endif
+
#if !defined(bcmp) && !defined(HAVE_BCMP)
#if defined(MC68000) && defined(DS90)
@@ -46,14 +51,11 @@ uint len; /* 0 <= len <= 65535 */
#else
-#ifdef HAVE_purify
-int my_bcmp(s1, s2, len)
+#ifndef HAVE_purify
+int bcmp(register const char *s1,register const char *s2, register uint len)
#else
-int bcmp(s1, s2, len)
+int my_bcmp(register const char *s1,register const char *s2, register uint len)
#endif
- register const char *s1;
- register const char *s2;
- register uint len;
{
while (len-- != 0 && *s1++ == *s2++) ;
return len+1;
diff --git a/strings/bcopy-duff.c b/strings/bcopy-duff.c
index 2f5a709c3a0..5ac6a716dab 100644
--- a/strings/bcopy-duff.c
+++ b/strings/bcopy-duff.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
#define IFACTOR 4
diff --git a/strings/bfill.c b/strings/bfill.c
index ac5d3096b14..e0e22a7023e 100644
--- a/strings/bfill.c
+++ b/strings/bfill.c
@@ -1,3 +1,19 @@
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
/* File : bfill.c
Author : Richard A. O'Keefe.
Michael Widenius; ifdef MC68000
@@ -12,7 +28,7 @@
code is presented for your interest and amusement.
*/
-#include <global.h>
+#include <my_global.h>
#include "m_string.h"
#if !defined(bfill) && !defined(HAVE_BFILL)
diff --git a/strings/bmove.c b/strings/bmove.c
index f63ff0bd4f8..3a76e783dda 100644
--- a/strings/bmove.c
+++ b/strings/bmove.c
@@ -1,3 +1,19 @@
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
/* File : bmove.c
Author : Richard A. O'Keefe.
Michael Widenius; ifdef MC68000
@@ -19,7 +35,7 @@
code is presented for your interest and amusement.
*/
-#include <global.h>
+#include <my_global.h>
#include "m_string.h"
#if !defined(HAVE_BMOVE) && !defined(bmove)
diff --git a/strings/bmove512.c b/strings/bmove512.c
index 11dc282d05c..30ac4b744b6 100644
--- a/strings/bmove512.c
+++ b/strings/bmove512.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/* File : bmove512.c
Author : Michael Widenius;
@@ -27,7 +26,7 @@
fastest way to move a mutiple of 512 byte.
*/
-#include <global.h>
+#include <my_global.h>
#include "m_string.h"
#ifndef bmove512
diff --git a/strings/bmove_upp.c b/strings/bmove_upp.c
index af6575ebf41..5319cd9611a 100644
--- a/strings/bmove_upp.c
+++ b/strings/bmove_upp.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/* File : bmove.c
Author : Michael widenius
@@ -24,7 +23,7 @@
"src-len" to the destination "dst-len" counting downwards.
*/
-#include <global.h>
+#include <my_global.h>
#include "m_string.h"
#if defined(MC68000) && defined(DS90)
diff --git a/strings/bzero.c b/strings/bzero.c
index cc628e05277..a2b780cb396 100644
--- a/strings/bzero.c
+++ b/strings/bzero.c
@@ -1,3 +1,19 @@
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
/* File : bzero.c
Author : Richard A. O'Keefe.
Michael Widenius; ifdef MC68000
diff --git a/strings/conf_to_src.c b/strings/conf_to_src.c
index 89415d31820..22e04337b14 100644
--- a/strings/conf_to_src.c
+++ b/strings/conf_to_src.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/* can't use -lmysys because this prog is used to create -lstrings */
diff --git a/strings/ctype-big5.c b/strings/ctype-big5.c
index cccf6730046..44f8a100897 100644
--- a/strings/ctype-big5.c
+++ b/strings/ctype-big5.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 is basicly usa7 character sets with some extra functions
@@ -28,7 +27,7 @@
* .configure. mbmaxlen_big5=2
*/
-#include <global.h>
+#include <my_global.h>
#include "m_string.h"
#include "m_ctype.h"
diff --git a/strings/ctype-czech.c b/strings/ctype-czech.c
index b47eaf3a63f..70f95e0d5d6 100644
--- a/strings/ctype-czech.c
+++ b/strings/ctype-czech.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/* File strings/ctype-czech.c for MySQL.
@@ -67,7 +66,7 @@
#ifdef REAL_MYSQL
-#include <global.h>
+#include <my_global.h>
#include "m_string.h"
#else
@@ -427,7 +426,7 @@ my_bool my_like_range_czech(const char *ptr,uint ptr_length,pchar escape,
*
* definition table reworked by Jaromir Dolecek <dolecek@ics.muni.cz>
*/
-#include <global.h>
+#include <my_global.h>
#include "m_string.h"
uchar NEAR ctype_czech[257] = {
diff --git a/strings/ctype-euc_kr.c b/strings/ctype-euc_kr.c
index df6f8c496bc..d05ca518283 100644
--- a/strings/ctype-euc_kr.c
+++ b/strings/ctype-euc_kr.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 is for Korean EUC charset, and created by powerm90@tinc.co.kr.
@@ -27,7 +26,7 @@
* .configure. mbmaxlen_euc_kr=2
*/
-#include <global.h>
+#include <my_global.h>
#include "m_string.h"
uchar NEAR ctype_euc_kr[257] =
diff --git a/strings/ctype-gb2312.c b/strings/ctype-gb2312.c
index a587d72905e..28717d98403 100644
--- a/strings/ctype-gb2312.c
+++ b/strings/ctype-gb2312.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 is for Chinese EUC character sets (GB2312), and created by Miles Tsai (net-bull@126.com).
*/
@@ -25,7 +24,7 @@
* .configure. mbmaxlen_gb2312=2
*/
-#include <global.h>
+#include <my_global.h>
#include "m_string.h"
uchar NEAR ctype_gb2312[257] =
diff --git a/strings/ctype-gbk.c b/strings/ctype-gbk.c
index a5d55789bb8..9fccce175d8 100644
--- a/strings/ctype-gbk.c
+++ b/strings/ctype-gbk.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 is for Chinese character sets GBK, created by Wei He
(hewei@mail.ied.ac.cn)
@@ -28,7 +27,7 @@
*/
-#include <global.h>
+#include <my_global.h>
#include "m_string.h"
#include "m_ctype.h"
@@ -2629,12 +2628,12 @@ int my_strnxfrm_gbk(uchar * dest, const uchar * src, int len, int srclen)
}
return srclen;
}
-
+
int my_strxfrm_gbk(uchar * dest, const uchar * src, int len)
{
return my_strnxfrm_gbk(dest,src,len,(uint) strlen((char*) src));
}
-
+
/*
** Calculate min_str and max_str that ranges a LIKE string.
** Arguments:
diff --git a/strings/ctype-latin1_de.c b/strings/ctype-latin1_de.c
new file mode 100644
index 00000000000..86b667b8f40
--- /dev/null
+++ b/strings/ctype-latin1_de.c
@@ -0,0 +1,361 @@
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+/*
+ * This file is the latin1 character set with German sorting
+ *
+ * The modern sort order is used, where:
+ *
+ * 'ä' -> "ae"
+ * 'ö' -> "oe"
+ * 'ü' -> "ue"
+ * 'ß' -> "ss"
+ */
+
+/*
+ * This comment is parsed by configure to create ctype.c,
+ * so don't change it unless you know what you are doing.
+ *
+ * .configure. strxfrm_multiply_latin1_de=2
+ */
+
+#include <my_global.h>
+#include "m_string.h"
+#include "m_ctype.h"
+
+uchar ctype_latin1_de[] = {
+ 0,
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 32, 32,
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+ 72, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 132,132,132,132,132,132,132,132,132,132, 16, 16, 16, 16, 16, 16,
+ 16,129,129,129,129,129,129, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 16, 16, 16, 16,
+ 16,130,130,130,130,130,130, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 16, 16, 16, 16, 32,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 72, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 16, 1, 1, 1, 1, 1, 1, 1, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 16, 2, 2, 2, 2, 2, 2, 2, 2
+};
+
+uchar to_lower_latin1_de[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111,
+ 112,113,114,115,116,117,118,119,120,121,122, 91, 92, 93, 94, 95,
+ 96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111,
+ 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,
+ 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
+ 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
+ 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
+ 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
+ 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
+ 240,241,242,243,244,245,246,215,248,249,250,251,252,253,254,223,
+ 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
+ 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255
+};
+
+uchar to_upper_latin1_de[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
+ 96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,123,124,125,126,127,
+ 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
+ 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
+ 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
+ 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
+ 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
+ 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,
+ 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
+ 208,209,210,211,212,213,214,247,216,217,218,219,220,221,222,255
+};
+
+/*
+ * This is a simple latin1 mapping table, which maps all accented
+ * characters to their non-accented equivalents. Note: in this
+ * table, 'ä' is mapped to 'A', 'ÿ' is mapped to 'Y', etc. - all
+ * accented characters except the following are treated the same way.
+ * Ü, ü, Ö, ö, Ä, ä
+ */
+
+uchar sort_order_latin1_de[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
+ 96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,123,124,125,126,127,
+ 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
+ 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
+ 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
+ 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
+ 65, 65, 65, 65,196, 65, 92, 67, 69, 69, 69, 69, 73, 73, 73, 73,
+ 68, 78, 79, 79, 79, 79,214,215,216, 85, 85, 85,220, 89,222,223,
+ 65, 65, 65, 65,196, 65, 92, 67, 69, 69, 69, 69, 73, 73, 73, 73,
+ 68, 78, 79, 79, 79, 79,214,247,216, 85, 85, 85,220, 89,222, 89
+};
+
+#define L1_AE 196
+#define L1_ae 228
+#define L1_OE 214
+#define L1_oe 246
+#define L1_UE 220
+#define L1_ue 252
+#define L1_ss 223
+
+
+/*
+ Some notes about the following comparison rules:
+ By definition, my_strnncoll_latin_de must works exactly as if had called
+ my_strnxfrm_latin_de() on both strings and compared the result strings.
+
+ This means that:
+ Ä must also matches ÁE and Aè, because my_strxn_frm_latin_de() will convert
+ both to AE.
+
+ The other option would be to not do any accent removal in
+ sort_order_latin_de[] at all
+*/
+
+
+#define CHECK_S1_COMBO(ch1, ch2, str1, str1_end, res_if_str1_smaller, str2, fst, snd, accent) \
+ /* Invariant: ch1 == fst == sort_order_latin1_de[accent] && ch1 != ch2 */ \
+ if (ch2 != accent) \
+ { \
+ ch1= fst; \
+ goto normal; \
+ } \
+ if (str1 == str1_end) \
+ return res_if_str1_smaller; \
+ { \
+ int diff = (int) sort_order_latin1_de[*str1] - snd; \
+ if (diff) \
+ return diff*(-(res_if_str1_smaller)); \
+ /* They are equal (e.g., "Ae" == 'ä') */ \
+ str1++; \
+ }
+
+
+int my_strnncoll_latin1_de(const uchar * s1, int len1,
+ const uchar * s2, int len2)
+{
+ const uchar *e1 = s1 + len1;
+ const uchar *e2 = s2 + len2;
+
+ while (s1 < e1 && s2 < e2)
+ {
+ /*
+ Because sort_order_latin1_de doesn't convert 'Ä', Ü or ß we
+ can use it here.
+ */
+ uchar c1 = sort_order_latin1_de[*s1++];
+ uchar c2 = sort_order_latin1_de[*s2++];
+ if (c1 != c2)
+ {
+ switch (c1) {
+ case 'A':
+ CHECK_S1_COMBO(c1, c2, s1, e1, -1, s2, 'A', 'E', L1_AE);
+ break;
+ case 'O':
+ CHECK_S1_COMBO(c1, c2, s1, e1, -1, s2, 'O', 'E', L1_OE);
+ break;
+ case 'U':
+ CHECK_S1_COMBO(c1, c2, s1, e1, -1, s2, 'U', 'E', L1_UE);
+ break;
+ case 'S':
+ CHECK_S1_COMBO(c1, c2, s1, e1, -1, s2, 'S', 'S', L1_ss);
+ break;
+ case L1_AE:
+ CHECK_S1_COMBO(c1, c2, s2, e2, 1, s1, 'A', 'E', 'A');
+ break;
+ case L1_OE:
+ CHECK_S1_COMBO(c1, c2, s2, e2, 1, s1, 'O', 'E', 'O');
+ break;
+ case L1_UE:
+ CHECK_S1_COMBO(c1, c2, s2, e2, 1, s1, 'U', 'E', 'U');
+ break;
+ case L1_ss:
+ CHECK_S1_COMBO(c1, c2, s2, e2, 1, s1, 'S', 'S', 'S');
+ break;
+ default:
+ /*
+ Handle the case where 'c2' is a special character
+ If this is true, we know that c1 can't match this character.
+ */
+ normal:
+ switch (c2) {
+ case L1_AE:
+ return (int) c1 - (int) 'A';
+ case L1_OE:
+ return (int) c1 - (int) 'O';
+ case L1_UE:
+ return (int) c1 - (int) 'U';
+ case L1_ss:
+ return (int) c1 - (int) 'S';
+ default:
+ {
+ int diff= (int) c1 - (int) c2;
+ if (diff)
+ return diff;
+ }
+ break;
+ }
+ }
+ }
+ }
+ /* A simple test of string lengths won't work -- we test to see
+ * which string ran out first */
+ return s1 < e1 ? 1 : s2 < e2 ? -1 : 0;
+}
+
+
+int my_strnxfrm_latin1_de(uchar * dest, const uchar * src, int len, int srclen)
+{
+ const uchar *dest_orig = dest;
+ const uchar *de = dest + len;
+ const uchar *se = src + srclen;
+ while (src < se && dest < de)
+ {
+ uchar chr=sort_order_latin1_de[*src];
+ switch (chr) {
+ case L1_AE:
+ *dest++ = 'A';
+ if (dest < de)
+ *dest++ = 'E';
+ break;
+ case L1_OE:
+ *dest++ = 'O';
+ if (dest < de)
+ *dest++ = 'E';
+ break;
+ case L1_UE:
+ *dest++ = 'U';
+ if (dest < de)
+ *dest++ = 'E';
+ break;
+ case L1_ss:
+ *dest++ = 'S';
+ if (dest < de)
+ *dest++ = 'S';
+ break;
+ default:
+ *dest++= chr;
+ break;
+ }
+ ++src;
+ }
+ return dest - dest_orig;
+}
+
+
+int my_strcoll_latin1_de(const uchar * s1, const uchar * s2)
+{
+ /* XXX QQ: This should be fixed to not call strlen */
+ return my_strnncoll_latin1_de(s1, strlen((char*) s1),
+ s2, strlen((char*) s2));
+}
+
+int my_strxfrm_latin1_de(uchar * dest, const uchar * src, int len)
+{
+ /* XXX QQ: This should be fixed to not call strlen */
+ return my_strnxfrm_latin1_de(dest, src, len, strlen((char*) src));
+}
+
+/*
+ * Calculate min_str and max_str that ranges a LIKE string.
+ * Arguments:
+ * ptr IN: Pointer to LIKE string.
+ * ptr_length IN: Length of LIKE string.
+ * escape IN: Escape character in LIKE. (Normally '\').
+ * No escape characters should appear in min_str or max_str
+ * res_length IN: Length of min_str and max_str.
+ * min_str IN/OUT: Smallest case sensitive string that ranges LIKE.
+ * Should be space padded to res_length.
+ * max_str IN/OUT: Largest case sensitive string that ranges LIKE.
+ * Normally padded with the biggest character sort value.
+ * min_length OUT: Length of min_str without space padding.
+ * max_length OUT: Length of max_str without space padding.
+ *
+ * The function should return 0 if ok and 1 if the LIKE string can't be
+ * optimized !
+ */
+
+#define min_sort_char ((char) 0)
+#define max_sort_char ((char) 255)
+#define wild_one '_'
+#define wild_many '%'
+
+my_bool my_like_range_latin1_de(const char *ptr, uint ptr_length,
+ pchar escape, uint res_length,
+ char *min_str, char *max_str,
+ uint *min_length, uint *max_length)
+{
+ const char *end = ptr + ptr_length;
+ char *min_org = min_str;
+ char *min_end = min_str + res_length;
+
+ for (; ptr != end && min_str != min_end; ptr++)
+ {
+ if (*ptr == escape && ptr + 1 != end)
+ {
+ ptr++; /* Skip escape */
+ *min_str++ = *max_str++ = *ptr;
+ continue;
+ }
+ if (*ptr == wild_one) /* '_' in SQL */
+ {
+ *min_str++ = min_sort_char;
+ *max_str++ = max_sort_char;
+ continue;
+ }
+ if (*ptr == wild_many) /* '%' in SQL */
+ {
+ *min_length = (uint)(min_str - min_org);
+ *max_length = res_length;
+ do {
+ *min_str++ = ' '; // Because if key compression
+ *max_str++ = max_sort_char;
+ } while (min_str != min_end);
+ return 0;
+ }
+ *min_str++ = *max_str++ = *ptr;
+ }
+ *min_length = *max_length = (uint) (min_str - min_org);
+
+ /* Temporary fix for handling wild_one at end of string (key compression) */
+ {
+ char *tmp;
+ for (tmp= min_str ; tmp > min_org && tmp[-1] == '\0';)
+ *--tmp=' ';
+ }
+
+ while (min_str != min_end)
+ *min_str++ = *max_str++ = ' '; // Because if key compression
+ return 0;
+}
diff --git a/strings/ctype-sjis.c b/strings/ctype-sjis.c
index 9f23d69eb12..5d5f64cc5fe 100644
--- a/strings/ctype-sjis.c
+++ b/strings/ctype-sjis.c
@@ -1,24 +1,23 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 is for Shift JIS charset, and created by tommy@valley.ne.jp.
*/
-#include <global.h>
+#include <my_global.h>
#include "m_string.h"
#include "m_ctype.h"
diff --git a/strings/ctype-tis620.c b/strings/ctype-tis620.c
index 1c0acc38e24..370c4c773c6 100644
--- a/strings/ctype-tis620.c
+++ b/strings/ctype-tis620.c
@@ -1,3 +1,19 @@
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
/*
Copyright (C) 2001 by Korakot Chaovavanich <korakot@iname.com> and
Apisilp Trunganont <apisilp@pantip.inet.co.th>
@@ -27,7 +43,7 @@
* .configure. strxfrm_multiply_tis620=4
*/
-#include <global.h>
+#include <my_global.h>
#include <my_sys.h>
#include "m_string.h"
#include "m_ctype.h"
diff --git a/strings/ctype-ujis.c b/strings/ctype-ujis.c
index d994a2e5e96..2091a610d19 100644
--- a/strings/ctype-ujis.c
+++ b/strings/ctype-ujis.c
@@ -1,3 +1,19 @@
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
/* This file is for Japanese EUC charset, and created by tommy@valley.ne.jp.
*/
@@ -8,7 +24,7 @@
* .configure. mbmaxlen_ujis=3
*/
-#include <global.h>
+#include <my_global.h>
#include "m_string.h"
uchar NEAR ctype_ujis[257] =
diff --git a/strings/ctype.c b/strings/ctype.c
index e66c9771d78..8e3571b1b88 100644
--- a/strings/ctype.c
+++ b/strings/ctype.c
@@ -1,23 +1,24 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-#include <global.h>
+#include <my_global.h>
#include <m_ctype.h>
+#ifndef SCO
#include <m_string.h>
+#endif
/* generated by make, using conf_to_src */
#include "ctype_extra_sources.c"
diff --git a/strings/do_ctype.c b/strings/do_ctype.c
index e05926bf8d3..14ede6891da 100644
--- a/strings/do_ctype.c
+++ b/strings/do_ctype.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/* Prints case-convert and sort-convert tabell on stdout. This is used to
make _ctype.c easyer */
@@ -22,7 +21,7 @@
#undef DBUG_OFF
#endif
-#include <global.h>
+#include <my_global.h>
#include <ctype.h>
#include <my_sys.h>
#include "m_string.h"
diff --git a/strings/int2str.c b/strings/int2str.c
index 4003e8a6167..38e8a5182a3 100644
--- a/strings/int2str.c
+++ b/strings/int2str.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/*
Defines: int2str(), itoa(), ltoa()
@@ -39,7 +38,7 @@
itoa assumes that 10 -base numbers are allways signed and other arn't.
*/
-#include <global.h>
+#include <my_global.h>
#include "m_string.h"
char NEAR _dig_vec[] =
diff --git a/strings/is_prefix.c b/strings/is_prefix.c
index d3f2b148de2..37d8002703b 100644
--- a/strings/is_prefix.c
+++ b/strings/is_prefix.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/* File : is_prefix.c
Author : Michael Widenius
@@ -23,7 +22,7 @@
A empty t is allways a prefix.
*/
-#include <global.h>
+#include <my_global.h>
#include "m_string.h"
int is_prefix(register const char *s, register const char *t)
diff --git a/strings/llstr.c b/strings/llstr.c
index 470645a4f65..966b347ac7e 100644
--- a/strings/llstr.c
+++ b/strings/llstr.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/*
Defines: llstr();
@@ -26,7 +25,7 @@
*/
-#include <global.h>
+#include <my_global.h>
#include "m_string.h"
char *llstr(longlong value,char *buff)
diff --git a/strings/longlong2str.c b/strings/longlong2str.c
index 5c4eaf98c85..a991c57b4d9 100644
--- a/strings/longlong2str.c
+++ b/strings/longlong2str.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/*
Defines: longlong2str();
@@ -39,7 +38,7 @@
itoa assumes that 10 -base numbers are allways signed and other arn't.
*/
-#include <global.h>
+#include <my_global.h>
#include "m_string.h"
#if defined(HAVE_LONG_LONG) && !defined(longlong2str) && !defined(HAVE_LONGLONG2STR)
diff --git a/strings/memcmp.c b/strings/memcmp.c
index 1bb8deaeac0..2f1e4e2ea1f 100644
--- a/strings/memcmp.c
+++ b/strings/memcmp.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/* memcmp(lhs, rhs, len)
compares the two memory areas lhs[0..len-1] ?? rhs[0..len-1]. It
diff --git a/strings/memcpy.c b/strings/memcpy.c
index 4fc84fb6052..de79e43ae72 100644
--- a/strings/memcpy.c
+++ b/strings/memcpy.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/*
memcpy(dst, src, len)
diff --git a/strings/memset.c b/strings/memset.c
index 57c8fea5ebe..53383beb170 100644
--- a/strings/memset.c
+++ b/strings/memset.c
@@ -1,3 +1,19 @@
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
/* File : memset.c
Author : Richard A. O'Keefe.
Updated: 25 May 1984
@@ -27,7 +43,7 @@ char *memset(char *dst,int chr, int len)
char *memset(char *dst, register pchar chr, register int len)
{
register char *d;
-
+
for (d = dst; --len >= 0; *d++ = chr) ;
return dst;
}
diff --git a/strings/r_strinstr.c b/strings/r_strinstr.c
index 882a4eda412..76d310a3fda 100644
--- a/strings/r_strinstr.c
+++ b/strings/r_strinstr.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/*
Author : David
@@ -24,7 +23,7 @@
the pattern counted from the begining of the string.
*/
-#include <global.h>
+#include <my_global.h>
#include "m_string.h"
uint r_strinstr(reg1 my_string str,int from, reg4 my_string search)
diff --git a/strings/str2int.c b/strings/str2int.c
index 55fcd56adb9..58669287473 100644
--- a/strings/str2int.c
+++ b/strings/str2int.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/*
str2int(src, radix, lower, upper, &val)
@@ -39,7 +38,7 @@
call has no problems.
*/
-#include <global.h>
+#include <my_global.h>
#include "m_string.h"
#include "m_ctype.h"
#include "my_sys.h" /* defines errno */
@@ -50,7 +49,8 @@
X >= 'a' && X <= 'z' ? X-'a'+10 :\
'\177')
-char *str2int(register const char *src, register int radix, long int lower, long int upper, long int *val)
+char *str2int(register const char *src, register int radix, long int lower,
+ long int upper, long int *val)
{
int sign; /* is number negative (+1) or positive (-1) */
int n; /* number of digits yet to be converted */
diff --git a/strings/str_test.c b/strings/str_test.c
index bd54bc6d806..bef48814f6d 100644
--- a/strings/str_test.c
+++ b/strings/str_test.c
@@ -1,23 +1,22 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/* Test of all stringfunktions that is coded in assembler */
-#include <global.h>
+#include <my_global.h>
#include <stdarg.h>
#include "m_string.h"
diff --git a/strings/strappend.c b/strings/strappend.c
index d5defaeb0bf..9912bd5197d 100644
--- a/strings/strappend.c
+++ b/strings/strappend.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/* File : strappend.c
Author : Monty
@@ -25,7 +24,7 @@
trunked. The des+len character is allways set to NULL.
*/
-#include <global.h>
+#include <my_global.h>
#include "m_string.h"
@@ -39,5 +38,3 @@ void strappend(register char *s, uint len, pchar fill)
while (s<endpos) *(s++) = fill;
*(endpos) = '\0';
} /* strappend */
-
-
diff --git a/strings/strcat.c b/strings/strcat.c
index 699729cd7b5..3c571514701 100644
--- a/strings/strcat.c
+++ b/strings/strcat.c
@@ -1,3 +1,19 @@
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
/* File : strcat.c
Author : Richard A. O'Keefe.
Updated: 10 April 1984
diff --git a/strings/strcend.c b/strings/strcend.c
index 246b81d7f7b..a3f00a1057b 100644
--- a/strings/strcend.c
+++ b/strings/strcend.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/* File : strcend.c
Author : Michael Widenius: ifdef MC68000
@@ -24,7 +23,7 @@
occurs, or a pointer to the end-null of s if c does not occur in s.
*/
-#include <global.h>
+#include <my_global.h>
#include "m_string.h"
#if defined(MC68000) && defined(DS90)
diff --git a/strings/strchr.c b/strings/strchr.c
index ef117d85635..3f1a569c296 100644
--- a/strings/strchr.c
+++ b/strings/strchr.c
@@ -1,3 +1,19 @@
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
/* File : strchr.c
Author : Richard A. O'Keefe.
Michael Widenius: ifdef MC68000
diff --git a/strings/strcmp.c b/strings/strcmp.c
index d911b2daa17..d673c035dbc 100644
--- a/strings/strcmp.c
+++ b/strings/strcmp.c
@@ -1,3 +1,19 @@
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
/* File : strcmp.c
Author : Richard A. O'Keefe.
Updated: 10 April 1984
diff --git a/strings/strcont.c b/strings/strcont.c
index 5c7d5d2e55f..1d89be89517 100644
--- a/strings/strcont.c
+++ b/strings/strcont.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/* File : strcont.c
Author : Monty
@@ -26,7 +25,7 @@
*/
-#include <global.h>
+#include <my_global.h>
#include "m_string.h"
my_string strcont(reg1 const char *str,reg2 const char *set)
diff --git a/strings/strend.c b/strings/strend.c
index 18b9d1fbd0d..d21abc79e2b 100644
--- a/strings/strend.c
+++ b/strings/strend.c
@@ -1,3 +1,19 @@
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
/* File : strend.c
Author : Richard A. O'Keefe.
Updated: 23 April 1984
@@ -10,7 +26,7 @@
Beware: the asm version works only if strlen(s) < 65535.
*/
-#include <global.h>
+#include <my_global.h>
#include "m_string.h"
#if VaxAsm
diff --git a/strings/strfill.c b/strings/strfill.c
index ef0ccb567d1..0ef56a67706 100644
--- a/strings/strfill.c
+++ b/strings/strfill.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/* File : strfill.c
Author : Monty
@@ -25,7 +24,7 @@
strfill() returns pointer to dest+len;
*/
-#include <global.h>
+#include <my_global.h>
#include "m_string.h"
my_string strfill(my_string s,uint len,pchar fill)
diff --git a/strings/strings-not-used.h b/strings/strings-not-used.h
index fa4dff318f5..e0dc1eac3a5 100644
--- a/strings/strings-not-used.h
+++ b/strings/strings-not-used.h
@@ -1,3 +1,19 @@
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
/* File : strings.h
Author : Richard A. O'Keefe.
Updated: 1 June 1984
@@ -13,7 +29,7 @@
#ifndef NullS
-#include <global.h> /* Define standar vars */
+#include <my_global.h> /* Define standar vars */
#include "m_string.h"
#define NUL '\0'
diff --git a/strings/strinstr.c b/strings/strinstr.c
index e1d502f4004..1c814d19d47 100644
--- a/strings/strinstr.c
+++ b/strings/strinstr.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/* File : strinstr.c
Author : Monty & David
@@ -27,7 +26,7 @@
char is 1.
*/
-#include <global.h>
+#include <my_global.h>
#include "m_string.h"
uint strinstr(reg1 const char *str,reg4 const char *search)
diff --git a/strings/strlen.c b/strings/strlen.c
index c142a7f2b14..b9be374fa6e 100644
--- a/strings/strlen.c
+++ b/strings/strlen.c
@@ -1,3 +1,19 @@
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
/* File : strlen.c
Author : Richard A. O'Keefe. / Monty
Michael Widenius; ifdef MC68000
diff --git a/strings/strmake.c b/strings/strmake.c
index 66a230338a1..2e384fc168a 100644
--- a/strings/strmake.c
+++ b/strings/strmake.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/* File : strmake.c
Author : Michael Widenius
@@ -26,7 +25,7 @@
strmake() returns pointer to closing null
*/
-#include <global.h>
+#include <my_global.h>
#include "m_string.h"
#ifdef BAD_STRING_COMPILER
diff --git a/strings/strmov.c b/strings/strmov.c
index 8f5beb41f41..507c2b6d997 100644
--- a/strings/strmov.c
+++ b/strings/strmov.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/*
strmov(dst, src) moves all the characters of src (including the
@@ -23,7 +22,7 @@
into dst, which seems useful.
*/
-#include <global.h>
+#include <my_global.h>
#include "m_string.h"
#ifdef BAD_STRING_COMPILER
diff --git a/strings/strnlen.c b/strings/strnlen.c
index 3d625f7d48a..fc8879b3a41 100644
--- a/strings/strnlen.c
+++ b/strings/strnlen.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/* File : strnlen.c
Author : Michael Widenius
@@ -22,7 +21,7 @@
strnlen(s, len) returns the length of s or len if s is longer than len.
*/
-#include <global.h>
+#include <my_global.h>
#include "m_string.h"
#ifndef HAVE_STRNLEN
diff --git a/strings/strnmov.c b/strings/strnmov.c
index ffc4a62f75e..362f3d6c4a8 100644
--- a/strings/strnmov.c
+++ b/strings/strnmov.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/*
strnmov(dst,src,length) moves length characters, or until end, of src to
@@ -22,7 +21,7 @@
truncated.
*/
-#include <global.h>
+#include <my_global.h>
#include "m_string.h"
char *strnmov(register char *dst, register const char *src, uint n)
diff --git a/strings/strrchr.c b/strings/strrchr.c
index 5a045ac3740..fb588c015f2 100644
--- a/strings/strrchr.c
+++ b/strings/strrchr.c
@@ -1,3 +1,19 @@
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
/* File : strrchr.c
Author : Richard A. O'Keefe.
Updated: 10 April 1984
diff --git a/strings/strstr.c b/strings/strstr.c
index 572bf88c95c..66e9358b493 100644
--- a/strings/strstr.c
+++ b/strings/strstr.c
@@ -1,3 +1,19 @@
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
/* File : strstr.c
Author : Monty
Updated: 1986.11.24
@@ -10,7 +26,7 @@
*/
-#include <global.h>
+#include <my_global.h>
#include "m_string.h"
#ifndef HAVE_STRSTR
diff --git a/strings/strto.c b/strings/strto.c
index d3392c794e9..84dccbcbeb8 100644
--- a/strings/strto.c
+++ b/strings/strto.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/*
strtol,strtoul,strtoll,strtoull
@@ -36,7 +35,7 @@
it can be compiled with the UNSIGNED and/or LONGLONG flag set
*/
-#include <global.h>
+#include <my_global.h>
#include "m_string.h"
#include "m_ctype.h"
#include "my_sys.h" /* defines errno */
diff --git a/strings/strtol.c b/strings/strtol.c
index 87fe0d22cf3..10d7f8f9da6 100644
--- a/strings/strtol.c
+++ b/strings/strtol.c
@@ -1,23 +1,22 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 defines strtol() if neaded */
-#include <global.h>
+#include <my_global.h>
#if !defined(MSDOS) && !defined(HAVE_STRTOL) && !defined(__WIN__)
#include "strto.c"
#endif
diff --git a/strings/strtoll.c b/strings/strtoll.c
index 678c28649ef..8d0ba21d576 100644
--- a/strings/strtoll.c
+++ b/strings/strtoll.c
@@ -1,23 +1,22 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 is defines strtoll() if neaded */
-#include <global.h>
+#include <my_global.h>
#include <m_string.h>
#if !defined(HAVE_STRTOLL) && defined(HAVE_LONG_LONG)
#define USE_LONGLONG
diff --git a/strings/strtoul.c b/strings/strtoul.c
index e49a9ebea6a..00e1f820942 100644
--- a/strings/strtoul.c
+++ b/strings/strtoul.c
@@ -1,23 +1,22 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 is defines strtoul() if neaded */
-#include <global.h>
+#include <my_global.h>
#if !defined(MSDOS) && !defined(HAVE_STRTOUL)
#define USE_UNSIGNED
#include "strto.c"
diff --git a/strings/strtoull.c b/strings/strtoull.c
index 74dab95b801..25201e546ce 100644
--- a/strings/strtoull.c
+++ b/strings/strtoull.c
@@ -1,23 +1,22 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 is defines strtoull() */
-#include <global.h>
+#include <my_global.h>
#include <m_string.h>
#if !defined(HAVE_STRTOULL) && defined(HAVE_LONG_LONG)
#define USE_UNSIGNED
diff --git a/strings/strxmov.c b/strings/strxmov.c
index 7ee1d303ee8..d8532bac8b4 100644
--- a/strings/strxmov.c
+++ b/strings/strxmov.c
@@ -1,3 +1,19 @@
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
/* File : strxmov.c
Author : Richard A. O'Keefe.
Updated: 25 may 1984
@@ -13,7 +29,7 @@
character pointer, or not the same bit pattern as NullS.
*/
-#include <global.h>
+#include <my_global.h>
#include "m_string.h"
#include <stdarg.h>
diff --git a/strings/strxnmov.c b/strings/strxnmov.c
index b55a2e0ab79..5e764e49e5a 100644
--- a/strings/strxnmov.c
+++ b/strings/strxnmov.c
@@ -1,3 +1,19 @@
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
/* File : strxnmov.c
Author : Richard A. O'Keefe.
Updated: 2 June 1984
@@ -20,7 +36,7 @@
needed.
*/
-#include <global.h>
+#include <my_global.h>
#include "m_string.h"
#include <stdarg.h>
diff --git a/strings/t_ctype.h b/strings/t_ctype.h
index 6699244c1f4..ac1fa408c0e 100644
--- a/strings/t_ctype.h
+++ b/strings/t_ctype.h
@@ -1,3 +1,19 @@
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
/*
Copyright (C) 1998, 1999 by Pruet Boonma, all rights reserved.
Copyright (C) 1998 by Theppitak Karoonboonyanan, all rights reserved.
@@ -125,7 +141,7 @@ enum l1_symbols {
L1_SARA_AI_MAIMUAN,
L1_SARA_AI_MAIMALAI
};
-
+
// level 2 symbols & order
enum l2_symbols {
L2_BLANK = TOT_LEVELS,
@@ -139,7 +155,7 @@ enum l2_symbols {
L2_TONE3,
L2_TONE4
};
-
+
// level 3 symbols & order
enum l3_symbols {
L3_BLANK = TOT_LEVELS,
diff --git a/strings/udiv.c b/strings/udiv.c
index 07af323a706..25f3f4685f0 100644
--- a/strings/udiv.c
+++ b/strings/udiv.c
@@ -1,23 +1,22 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/* Do udiv and urem if machine dosn't have it */
-#include <global.h>
+#include <my_global.h>
#include <math.h>
unsigned long udiv(long unsigned int a, long unsigned int b)
diff --git a/support-files/binary-configure.sh b/support-files/binary-configure.sh
index 682ea570b25..107f468bffc 100644
--- a/support-files/binary-configure.sh
+++ b/support-files/binary-configure.sh
@@ -20,5 +20,5 @@ then
echo "Starting the mysqld server. You can test that it is up and running"
echo "with the command:"
echo "./bin/mysqladmin version"
- ./bin/safe_mysqld &
+ ./bin/mysqld_safe &
fi
diff --git a/support-files/build-tags b/support-files/build-tags
new file mode 100755
index 00000000000..d5f9fbf5100
--- /dev/null
+++ b/support-files/build-tags
@@ -0,0 +1,9 @@
+#! /bin/sh
+
+rm -f TAGS
+filter='\.cc$\|\.c$\|\.h$\|\.yy$'
+files=`bk -r sfiles -gU | grep $filter `
+for f in $files ;
+do
+ etags -o TAGS --append $f
+done
diff --git a/support-files/mysql-max.spec.sh b/support-files/mysql-max.spec.sh
index 49f131154c0..5c4b16f0e9d 100644
--- a/support-files/mysql-max.spec.sh
+++ b/support-files/mysql-max.spec.sh
@@ -208,7 +208,7 @@ chmod -R og-rw $mysql_datadir/mysql
# Restart in the same way that mysqld will be started normally.
/etc/rc.d/init.d/mysql start
-# Allow safe_mysqld to start mysqld and print a message before we exit
+# Allow mysqld_safe to start mysqld and print a message before we exit
sleep 2
%preun
@@ -244,7 +244,7 @@ fi
%attr(755, root, root) /usr/bin/perror
%attr(755, root, root) /usr/bin/replace
%attr(755, root, root) /usr/bin/resolveip
-%attr(755, root, root) /usr/bin/safe_mysqld
+%attr(755, root, root) /usr/bin/mysqld_safe
%attr(755, root, root) /usr/bin/mysqld_multi
%attr(755, root, root) /usr/bin/my_print_defaults
diff --git a/support-files/mysql-multi.server.sh b/support-files/mysql-multi.server.sh
index 6c940630427..31020029354 100644
--- a/support-files/mysql-multi.server.sh
+++ b/support-files/mysql-multi.server.sh
@@ -133,14 +133,14 @@ case "$mode" in
'start')
# Start daemon
- if test -x $bindir/safe_mysqld
+ if test -x $bindir/mysqld_safe
then
# We only need to specify datadir and pid-file here and we
# get all other instance-specific config from $datadir/my.cnf.
# We have to explicitly pass --defaults-extra-file because it
# reads the config files before the command line options.
- # Also it must be first because of the way safe_mysqld works.
- $bindir/safe_mysqld --defaults-extra-file=$datadir/my.cnf \
+ # Also it must be first because of the way mysqld_safe works.
+ $bindir/mysqld_safe --defaults-extra-file=$datadir/my.cnf \
--datadir=$datadir --pid-file=$pid_file &
# Make lock for RedHat / SuSE
if test -d /var/lock/subsys
@@ -148,7 +148,7 @@ case "$mode" in
touch /var/lock/subsys/mysql
fi
else
- echo "Can't execute $bindir/safe_mysqld"
+ echo "Can't execute $bindir/mysqld_safe"
fi
;;
diff --git a/support-files/mysql.server.sh b/support-files/mysql.server.sh
index 62381ccf0d3..eed749bf5b2 100644
--- a/support-files/mysql.server.sh
+++ b/support-files/mysql.server.sh
@@ -100,25 +100,25 @@ case "$mode" in
'start')
# Start daemon
- if test -x $bindir/safe_mysqld
+ if test -x $bindir/mysqld_safe
then
# Give extra arguments to mysqld with the my.cnf file. This script may
# be overwritten at next upgrade.
- $bindir/safe_mysqld --datadir=$datadir --pid-file=$pid_file &
+ $bindir/mysqld_safe --datadir=$datadir --pid-file=$pid_file &
# Make lock for RedHat / SuSE
if test -w /var/lock/subsys
then
touch /var/lock/subsys/mysql
fi
else
- echo "Can't execute $bindir/safe_mysqld"
+ echo "Can't execute $bindir/mysqld_safe"
fi
;;
'stop')
# Stop daemon. We use a signal here to avoid having to know the
# root password.
- if test -f "$pid_file"
+ if test -s "$pid_file"
then
mysqld_pid=`cat $pid_file`
echo "Killing mysqld with pid $mysqld_pid"
diff --git a/support-files/mysql.spec.sh b/support-files/mysql.spec.sh
index fcc09aa8302..f619bc0ee7b 100644
--- a/support-files/mysql.spec.sh
+++ b/support-files/mysql.spec.sh
@@ -1,6 +1,6 @@
%define mysql_version @VERSION@
%define shared_lib_version @SHARED_LIB_VERSION@
-%define release 1
+%define release 2
%define mysqld_user mysql
%define see_base For a description of MySQL see the base MySQL RPM or http://www.mysql.com
@@ -139,6 +139,20 @@ Optional MySQL server binary that supports features
like transactional tables. To active this binary, just install this
package after the MySQL package.
+%package embedded
+Release: %{release}
+Requires: devel
+Summary: MySQL - embedded library
+Group: Applications/Databases
+Summary(pt_BR): MySQL - Medições de desempenho
+Group(pt_BR): Aplicações/Banco_de_Dados
+Obsoletes: embedded
+
+%description embedded
+This package contains the MySQL server as library.
+
+%{see_base}
+
%prep
%setup -n mysql-%{mysql_version}
@@ -173,6 +187,8 @@ sh -c "PATH=\"${MYSQL_BUILD_PATH:-/bin:/usr/bin}\" \
--infodir=/usr/info \
--includedir=/usr/include \
--mandir=/usr/man \
+ --with-embedded-server \
+ --enable-thread-safe-client \
--with-comment=\"Official MySQL RPM\";
# Add this for more debugging support
# --with-debug
@@ -198,7 +214,7 @@ mkdir -p $RBR
# Build the shared libraries and mysqld-max
-BuildMySQL "--enable-shared --enable-thread-safe-client --with-berkeley-db --with-innodb --with-mysqld-ldflags='-all-static' --with-server-suffix='-Max'"
+BuildMySQL "--enable-shared --with-berkeley-db --with-innodb --with-mysqld-ldflags='-all-static' --with-server-suffix='-Max'"
# Save everything for debug
# tar cf $RBR/all.tar .
@@ -220,7 +236,7 @@ automake
BuildMySQL "--disable-shared" \
"--with-mysqld-ldflags='-all-static'" \
"--with-client-ldflags='-all-static'" \
- "--without-berkeley-db --without-innodb"
+ "--without-berkeley-db --with-innodb"
nm --numeric-sort sql/mysqld > sql/mysqld.sym
%install -n mysql-%{mysql_version}
@@ -303,7 +319,7 @@ chmod -R og-rw $mysql_datadir/mysql
# Restart in the same way that mysqld will be started normally.
/etc/rc.d/init.d/mysql start
-# Allow safe_mysqld to start mysqld and print a message before we exit
+# Allow mysqld_safe to start mysqld and print a message before we exit
sleep 2
%post Max
@@ -346,11 +362,12 @@ fi
%attr(755, root, root) /usr/bin/mysqlbug
%attr(755, root, root) /usr/bin/mysqltest
%attr(755, root, root) /usr/bin/mysqlhotcopy
+%attr(755, root, root) /usr/bin/mysql_explain_log
%attr(755, root, root) /usr/bin/perror
%attr(755, root, root) /usr/bin/replace
%attr(755, root, root) /usr/bin/resolveip
+%attr(755, root, root) /usr/bin/mysqld_safe
%attr(755, root, root) /usr/bin/resolve_stack_dump
-%attr(755, root, root) /usr/bin/safe_mysqld
%attr(755, root, root) /usr/bin/mysqld_multi
%attr(755, root, root) /usr/bin/my_print_defaults
@@ -388,7 +405,7 @@ fi
%attr(644, root, man) %doc /usr/man/man1/mysqlshow.1*
%attr(644, root, man) %doc /usr/man/man1/perror.1*
%attr(644, root, man) %doc /usr/man/man1/replace.1*
-%attr(644, root, man) %doc /usr/man/man1/safe_mysqld.1*
+%attr(644, root, man) %doc /usr/man/man1/mysqld_safe.1*
%post shared
/sbin/ldconfig
@@ -409,13 +426,23 @@ fi
%files bench
%attr(-, root, root) /usr/share/sql-bench
%attr(-, root, root) /usr/share/mysql-test
+%attr(755, root, root) /usr/bin/mysqlmanager
+%attr(755, root, root) /usr/bin/mysqlmanager-pwgen
+%attr(755, root, root) /usr/bin/mysqlmanagerc
%files Max
%attr(755, root, root) /usr/sbin/mysqld-max
%attr(644, root, root) /usr/lib/mysql/mysqld-max.sym
+%files embedded
+%attr(755, root, root) /usr/lib/mysql/libmysqld.a
+
%changelog
+* Mon Oct 8 2001 Monty
+
+- Added embedded server as a separate RPM
+
* Fri Apr 13 2001 Monty
- Added mysqld-max to the distribution
diff --git a/tests/fork2_test.pl b/tests/fork2_test.pl
index b5564e99c3f..19fab5a67d6 100755
--- a/tests/fork2_test.pl
+++ b/tests/fork2_test.pl
@@ -92,7 +92,7 @@ $errors=0;
while (($pid=wait()) != -1)
{
$ret=$?/256;
- print "thread '" . $work{$pid} . "' finnished with exit code $ret\n";
+ print "thread '" . $work{$pid} . "' finished with exit code $ret\n";
$errors++ if ($ret != 0);
}
diff --git a/tests/fork_big.pl b/tests/fork_big.pl
index e082225604c..c72eb59946b 100755
--- a/tests/fork_big.pl
+++ b/tests/fork_big.pl
@@ -106,7 +106,7 @@ $running_insert_threads=$opt_threads+$numtables;
while (($pid=wait()) != -1)
{
$ret=$?/256;
- print "thread '" . $work{$pid} . "' finnished with exit code $ret\n";
+ print "thread '" . $work{$pid} . "' finished with exit code $ret\n";
if ($work{$pid} =~ /^insert/)
{
if (!--$running_insert_threads)
diff --git a/tests/insert_and_repair.pl b/tests/insert_and_repair.pl
index 4d68c2ab9a0..1c7186bb651 100755
--- a/tests/insert_and_repair.pl
+++ b/tests/insert_and_repair.pl
@@ -56,7 +56,7 @@ $errors=0;
while (($pid=wait()) != -1)
{
$ret=$?/256;
- print "thread '" . $work{$pid} . "' finnished with exit code $ret\n";
+ print "thread '" . $work{$pid} . "' finished with exit code $ret\n";
$errors++ if ($ret != 0);
}
diff --git a/tests/mail_to_db.pl b/tests/mail_to_db.pl
index b758a171c77..671e8b23599 100755
--- a/tests/mail_to_db.pl
+++ b/tests/mail_to_db.pl
@@ -17,7 +17,7 @@ use DBI;
use Getopt::Long;
$| = 1;
-$VER = "2.3";
+$VER = "2.6";
$opt_help = 0;
$opt_version = 0;
@@ -152,19 +152,77 @@ sub main
$dbh->disconnect if (!$opt_test);
$ignored = ($mail_no_from_f + $mail_no_subject_f + $mail_no_txt_f +
- $mail_too_big + $mail_duplicates);
- print "Mails inserted:\t\t\t$mail_inserted\n";
- print "Mails ignored:\t\t\t$ignored\n";
- print "Mails without \"From:\" -field:\t$mail_no_from_f\n";
- print "Mails without message:\t\t$mail_no_txt_f\n";
- print "Mails without subject:\t\t$mail_no_subject_f\n";
- print "Too big mails (> $opt_max_mail_size):\t$mail_too_big\n";
- print "Duplicate mails:\t\t$mail_duplicates\n";
- print "Forwarded mails:\t\t$mail_forwarded\n";
- print "Total number of mails:\t\t";
+ $mail_too_big + $mail_duplicates + $mail_fixed);
+ print "################################ Mail Report #################################\n\n";
+ print "Mails inserted:\t\t\t\t\t$mail_inserted\n";
+ print "--------------- ";
+ print "=" . "=" x length("$mail_inserted") . "=\n\n";
+ if ($ignored)
+ {
+ print "Ignored mails\n";
+ print "-------------\n";
+ if ($mail_no_from_f)
+ {
+ print "Reason: mail without \"From:\" -field:\t\t$mail_no_from_f\n";
+ }
+ else
+ {
+ print "";
+ }
+ if ($mail_no_txt_f)
+ {
+ print "Reason: mail without message:\t\t\t$mail_no_txt_f\n";
+ }
+ else
+ {
+ print "";
+ }
+ if ($mail_no_subject_f)
+ {
+ print "Reason: mail without subject:\t\t\t$mail_no_subject_f\n";
+ }
+ else
+ {
+ print "";
+ }
+ if ($mail_too_big)
+ {
+ print "Reason: mail too big, over $opt_max_mail_size bytes:\t\t";
+ print $mail_too_big;
+ print " (see --max_mail_size=#)\n";
+ }
+ else
+ {
+ print "";
+ }
+ if ($mail_duplicates)
+ {
+ print "Reason: duplicate mail, or in db already:\t$mail_duplicates\n";
+ }
+ else
+ {
+ print "";
+ }
+ if ($mail_fixed)
+ {
+ print "Reason: mail was an unsubscribe - mail:\t\t$mail_fixed\n";
+ }
+ else
+ {
+ print "";
+ }
+ print " ";
+ print "=" . "=" x length("$ignored") . "=\n";
+ print "Total number of ignored mails:\t\t\t$ignored\n\n";
+ }
+ print "Total number of mails:\t\t\t\t";
print $mail_inserted + $ignored;
- print "\n";
- print "Mails with unsubscribe removed:\t$mail_fixed\n";
+ print " (OK: ";
+ print sprintf("%.1f", (($mail_inserted / ($mail_inserted+$ignored)) * 100));
+ print "% Ignored: ";
+ print sprintf("%.1f", (($ignored / ($mail_inserted + $ignored)) * 100));
+ print "%)\n";
+ print "################################ End Report ##################################\n";
exit(0);
}
@@ -213,10 +271,10 @@ sub process_mail_file
%values = ();
$type = "";
$check = 0;
-
while (<FILE>)
{
chop;
+ chop if (substr($_, -1, 1) eq "\r");
if ($type ne "message")
{
if (/^Reply-To: (.*)/i)
@@ -269,7 +327,8 @@ sub process_mail_file
$values{$type} .= "\n" . $_;
$check--;
}
- elsif (/^From .* \d\d:\d\d:\d\d\s\d\d\d\d$/)
+ elsif (/^From .* \d\d:\d\d:\d\d\s\d\d\d\d/ ||
+ /^From .* \d\d\d\d\s\d\d:\d\d:\d\d/)
{
$values{'hash'} = checksum("$values{'message'}");
update_table($dbh, $file_name, \%values);
@@ -288,8 +347,11 @@ sub process_mail_file
$values{$type} .= "\n" . $_;
}
}
- $values{'hash'} = checksum("$values{'message'}");
- update_table($dbh, $file_name, \%values);
+ if (defined($values{'message'}))
+ {
+ $values{'hash'} = checksum("$values{'message'}");
+ update_table($dbh, $file_name, \%values);
+ }
}
####
@@ -335,26 +397,26 @@ sub date_parser
sub update_table
{
my($dbh, $file_name, $values) = @_;
- my($q,$tail,$message);
+ my($q, $tail, $message);
if (!defined($values->{'subject'}) || !defined($values->{'to'}))
{
$mail_no_subject_f++;
return; # Ignore these
}
- $message=$values->{'message'};
- $message =~ s/^\s*//; #removes whitespaces from the beginning
+ $message = $values->{'message'};
+ $message =~ s/^\s*//; # removes whitespaces from the beginning
restart:
- $message =~ s/[\s\n>]*$//; #removes whitespaces and '>' from the end
- $values->{'message'}=$message;
+ $message =~ s/[\s\n>]*$//; # removes whitespaces and '>' from the end
+ $values->{'message'} = $message;
foreach $tail (@remove_tail)
{
$message =~ s/$tail//;
}
if ($message ne $values->{'message'})
{
- $message =~ s/\s*$//; #removes whitespaces from the end
+ $message =~ s/\s*$//; # removes whitespaces from the end
$mail_fixed++;
goto restart; # Some mails may have duplicated messages
}
@@ -442,7 +504,7 @@ sub update_table
sub checksum
{
my ($txt)= @_;
- my ($crc,$i,$count);
+ my ($crc, $i, $count);
$count = length($txt);
for ($crc = $i = 0; $i < $count ; $i++)
{
diff --git a/tests/myisam-big-rows.tst b/tests/myisam-big-rows.tst
new file mode 100644
index 00000000000..56c06f4820f
--- /dev/null
+++ b/tests/myisam-big-rows.tst
@@ -0,0 +1,72 @@
+#
+# Test rows with length above > 16M
+# Note that for this to work, you should start mysqld with
+# -O max_allowed_packet=32M
+#
+
+drop table if exists t1;
+create table t1 (a tinyint not null auto_increment, b longblob not null, primary key (a)) checksum=1;
+
+insert into t1 (b) values(repeat(char(65),10));
+insert into t1 (b) values(repeat(char(66),10));
+insert into t1 (b) values(repeat(char(67),10));
+update t1 set b=repeat(char(68),16777216) where a=1;
+check table t1;
+update t1 set b=repeat(char(69),16777000) where a=2;
+update t1 set b=repeat(char(70),167) where a=3;
+update t1 set b=repeat(char(71),16778000) where a=1;
+update t1 set b=repeat(char(72),16778000) where a=3;
+select a,length(b) from t1;
+set @a=1;
+insert into t1 (b) values (repeat(char(73+@a),16777200+@a));
+set @a=@a+1;
+insert into t1 (b) values (repeat(char(73+@a),16777200+@a));
+set @a=@a+1;
+insert into t1 (b) values (repeat(char(73+@a),16777200+@a));
+set @a=@a+1;
+insert into t1 (b) values (repeat(char(73+@a),16777200+@a));
+set @a=@a+1;
+insert into t1 (b) values (repeat(char(73+@a),16777200+@a));
+set @a=@a+1;
+insert into t1 (b) values (repeat(char(73+@a),16777200+@a));
+set @a=@a+1;
+insert into t1 (b) values (repeat(char(73+@a),16777200+@a));
+set @a=@a+1;
+insert into t1 (b) values (repeat(char(73+@a),16777200+@a));
+set @a=@a+1;
+insert into t1 (b) values (repeat(char(73+@a),16777200+@a));
+set @a=@a+1;
+insert into t1 (b) values (repeat(char(73+@a),16777200+@a));
+set @a=@a+1;
+insert into t1 (b) values (repeat(char(73+@a),16777200+@a));
+set @a=@a+1;
+insert into t1 (b) values (repeat(char(73+@a),16777200+@a));
+set @a=@a+1;
+insert into t1 (b) values (repeat(char(73+@a),16777200+@a));
+set @a=@a+1;
+insert into t1 (b) values (repeat(char(73+@a),16777200+@a));
+set @a=@a+1;
+insert into t1 (b) values (repeat(char(73+@a),16777200+@a));
+set @a=@a+1;
+insert into t1 (b) values (repeat(char(73+@a),16777200+@a));
+set @a=@a+1;
+insert into t1 (b) values (repeat(char(73+@a),16777200+@a));
+set @a=@a+1;
+insert into t1 (b) values (repeat(char(73+@a),16777200+@a));
+update t1 set b=('A') where a=5;
+delete from t1 where a=7;
+set @a=@a+1;
+insert into t1 (b) values (repeat(char(73+@a),16777200+@a));
+update t1 set b=repeat(char(73+@a+1),17000000+@a) where a=last_insert_id();
+
+select a,mid(b,1,5),length(b) from t1;
+check table t1;
+repair table t1;
+check table t1;
+select a from table where b<>repeat(mid(b,1,1),length(b));
+delete from t1 where (a & 1);
+select a from table where b<>repeat(mid(b,1,1),length(b));
+check table t1;
+repair table t1;
+check table t1;
+drop table t1;
diff --git a/tests/rename_test.pl b/tests/rename_test.pl
index bdfb14be927..edf3216a62f 100755
--- a/tests/rename_test.pl
+++ b/tests/rename_test.pl
@@ -79,7 +79,7 @@ print "Total time: " .
exit(0);
#
-# Insert records in the table. Delete table when test is finnished
+# Insert records in the table. Delete table when test is finished
#
sub test_insert
diff --git a/tests/test_delayed_insert.pl b/tests/test_delayed_insert.pl
index e49d73a19bd..c7a8f0ca4b7 100755
--- a/tests/test_delayed_insert.pl
+++ b/tests/test_delayed_insert.pl
@@ -65,7 +65,7 @@ $errors=0;
while (($pid=wait()) != -1)
{
$ret=$?/256;
- print "thread '" . $work{$pid} . "' finnished with exit code $ret\n";
+ print "thread '" . $work{$pid} . "' finished with exit code $ret\n";
$errors++ if ($ret != 0);
}
diff --git a/tools/Makefile.am b/tools/Makefile.am
new file mode 100644
index 00000000000..e5130865a89
--- /dev/null
+++ b/tools/Makefile.am
@@ -0,0 +1,20 @@
+INCLUDES = @MT_INCLUDES@ -I$(srcdir)/../include \
+ $(openssl_includes) -I../include
+LDADD= @CLIENT_EXTRA_LDFLAGS@ ../libmysql_r/libmysqlclient_r.la @openssl_libs@
+bin_PROGRAMS= mysqlmanager
+mysqlmanager_SOURCES= mysqlmanager.c
+mysqlmanager_DEPENDENCIES= $(LIBRARIES) $(pkglib_LTLIBRARIES)
+DEF= -DUNDEF_THREADS_HACK
+
+OMIT_DEPENDENCIES = pthread.h stdio.h __stdio.h stdlib.h __stdlib.h math.h\
+ __math.h time.h __time.h unistd.h __unistd.h types.h \
+ xtypes.h ac-types.h posix.h string.h __string.h \
+ errno.h socket.h inet.h dirent.h netdb.h \
+ cleanup.h cond.h debug_out.h fd.h kernel.h mutex.h \
+ prio_queue.h pthread_attr.h pthread_once.h queue.h\
+ sleep.h specific.h version.h pwd.h timers.h uio.h \
+ cdefs.h machdep.h signal.h __signal.h util.h lex.h \
+ wait.h
+
+# Don't update the files from bitkeeper
+%::SCCS/s.%
diff --git a/tools/managertest1.nc b/tools/managertest1.nc
new file mode 100644
index 00000000000..bf1b82ed406
--- /dev/null
+++ b/tools/managertest1.nc
@@ -0,0 +1,16 @@
+def_exec server /usr/sbin/mysqld --socket=/tmp/temp.sock --skip-grant --skip-net --datadir=/tmp
+set_exec_con server root localhost /tmp/temp.sock
+set_exec_stdout server /tmp/mysqld.err
+set_exec_stderr server /tmp/mysqld.err
+start_exec server 3
+show_exec
+query server show variables like '%max_heap%';
+stop_exec server 3
+def_exec server /usr/sbin/mysqld --socket=/tmp/temp.sock --skip-grant --skip-net --datadir=/tmp -O max_heap_table_size=5000
+show_exec
+start_exec server 3
+query server show variables like '%max_heap%';
+show_exec
+stop_exec server 3
+show_exec
+quit
diff --git a/tools/mysqlmanager-sample.pwd b/tools/mysqlmanager-sample.pwd
new file mode 100644
index 00000000000..51c1ade1b77
--- /dev/null
+++ b/tools/mysqlmanager-sample.pwd
@@ -0,0 +1 @@
+root:5ebe2294ecd0e0f08eab7690d2a6ee69
diff --git a/tools/mysqlmanager.c b/tools/mysqlmanager.c
new file mode 100644
index 00000000000..bd43c6bc0ec
--- /dev/null
+++ b/tools/mysqlmanager.c
@@ -0,0 +1,1857 @@
+/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+/* MySQL server management daemon
+ *
+ * Written by:
+ * Sasha Pachev <sasha@mysql.com>
+ **/
+
+#include <my_global.h>
+#include <my_pthread.h>
+#include <mysql.h>
+#include <mysql_version.h>
+#include <mysqld_error.h>
+#include <my_sys.h>
+#include <my_dir.h>
+#include <m_string.h>
+#include <m_ctype.h>
+#include <hash.h>
+#include <getopt.h>
+#include <stdarg.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <violite.h>
+#include <md5.h>
+#include <signal.h>
+#ifdef HAVE_SYS_WAIT_H
+#include <sys/wait.h>
+#endif
+
+#define MANAGER_VERSION "1.0"
+#define MANAGER_GREETING "MySQL Server Management Daemon v. 1.0"
+
+#define LOG_ERR 1
+#define LOG_WARN 2
+#define LOG_INFO 3
+#define LOG_DEBUG 4
+
+#define CHILD_START 1
+#define CHILD_STOP 2
+
+#ifndef MANAGER_PORT
+#define MANAGER_PORT 23546
+#endif
+
+#ifndef MANAGER_CONNECT_RETRIES
+#define MANAGER_CONNECT_RETRIES 5
+#endif
+
+#ifndef MANAGER_MAX_CMD_LEN
+#define MANAGER_MAX_CMD_LEN 16384
+#endif
+
+#ifndef MANAGER_LOG_FILE
+#define MANAGER_LOG_FILE "/var/log/mysqlmanager.log"
+#endif
+
+#ifndef MANAGER_BACK_LOG
+#define MANAGER_BACK_LOG 50
+#endif
+
+#ifndef MAX_USER_NAME
+#define MAX_USER_NAME 16
+#endif
+
+#ifndef MANAGER_PW_FILE
+#define MANAGER_PW_FILE "/etc/mysqlmanager.passwd"
+#endif
+
+#ifndef MAX_HOST
+#define MAX_HOST 128
+#endif
+
+#ifndef MAX_LAUNCHER_MSG
+#define MAX_LAUNCHER_MSG 256
+#endif
+
+#define MAX_RETRY_COUNT 100
+
+/* Variable naming convention - if starts with manager_, either is set
+ directly by the user, or used closely in ocnjunction with a variable
+ set by the user
+*/
+
+#if defined(__i386__) && defined(HAVE_LINUXTHREADS)
+#define DO_STACKTRACE 1
+#endif
+
+uint manager_port = MANAGER_PORT;
+FILE* errfp;
+const char* manager_log_file = MANAGER_LOG_FILE;
+pthread_mutex_t lock_log,lock_shutdown,lock_exec_hash,lock_launch_thd;
+pthread_cond_t cond_launch_thd;
+pthread_t loop_th,launch_msg_th;
+int manager_sock = -1;
+uchar* stack_bottom=0;
+struct sockaddr_in manager_addr;
+ulong manager_bind_addr = INADDR_ANY;
+int manager_back_log = MANAGER_BACK_LOG;
+int in_shutdown = 0, shutdown_requested=0;
+int manager_connect_retries=MANAGER_CONNECT_RETRIES;
+const char* manager_greeting = MANAGER_GREETING;
+uint manager_max_cmd_len = MANAGER_MAX_CMD_LEN;
+const char* manager_pw_file=MANAGER_PW_FILE;
+int one_thread = 0; /* for debugging */
+
+typedef enum {PARAM_STDOUT,PARAM_STDERR} PARAM_TYPE;
+
+/* messages */
+
+#define MAX_CLIENT_MSG_LEN 256
+#define NET_BLOCK 2048
+#define MD5_LEN 16
+#define ESCAPE_CHAR '\\'
+#define EOL_CHAR '\n'
+
+/* access flags */
+
+#define PRIV_SHUTDOWN 1
+
+struct manager_thd
+{
+ NET net;
+ char user[MAX_USER_NAME+1];
+ int priv_flags;
+ char* cmd_buf;
+ int fatal,finished;
+};
+
+struct manager_user
+{
+ char user[MAX_USER_NAME+1];
+ char md5_pass[MD5_LEN];
+ int user_len;
+ const char* error;
+};
+
+HASH exec_hash,user_hash;
+struct manager_exec* cur_launch_exec=0;
+
+static struct manager_thd* manager_thd_new(Vio* vio);
+
+static struct manager_exec* manager_exec_new(char* arg_start,char* arg_end);
+static void manager_exec_print(NET* net,struct manager_exec* e);
+static void manager_thd_free(struct manager_thd* thd);
+static void manager_exec_free(void* e);
+static void manager_exec_connect(struct manager_exec* e);
+static int manager_exec_launch(struct manager_exec* e);
+static struct manager_exec* manager_exec_by_pid(pid_t pid);
+
+static struct manager_user* manager_user_new(char* buf);
+static void manager_user_free(void* u);
+
+static char* arg_strmov(char* dest, const char* src, int n);
+static byte* get_exec_key(const byte* e, uint* len,
+ my_bool __attribute__((unused)) t);
+static byte* get_user_key(const byte* u, uint* len,
+ my_bool __attribute__((unused)) t);
+static uint tokenize_args(char* arg_start,char** arg_end);
+static void init_arg_array(char* arg_str,char** args,uint arg_count);
+static int hex_val(char c);
+static int open_and_dup(int fd,char* path);
+static void update_req_len(struct manager_exec* e);
+
+typedef int (*manager_cmd_handler)(struct manager_thd*,char*,char*);
+
+static void handle_child(int __attribute__((unused)) sig);
+static void handle_sigpipe(int __attribute__((unused)) sig);
+
+/* exec() in a threaded application is full of problems
+ to solve this, we fork off a launcher at the very start
+ and communicate with it through a pipe
+*/
+static void fork_launcher();
+static void run_launcher_loop();
+int to_launcher_pipe[2],from_launcher_pipe[2];
+pid_t launcher_pid;
+int in_segfault=0;
+const char* pid_file = "/var/run/mysqlmanager.pid";
+int created_pid_file = 0;
+
+struct manager_cmd
+{
+ const char* name;
+ const char* help;
+ manager_cmd_handler handler_func;
+ int len;
+};
+
+struct manager_exec
+{
+ char* ident;
+ int ident_len;
+ const char* error;
+ char* bin_path;
+ char** args;
+ char con_user[16];
+ char con_pass[16];
+ int con_port;
+ pid_t pid;
+ int exit_code;
+ pthread_mutex_t lock;
+ pthread_cond_t cond;
+ pthread_t th;
+ char con_sock[FN_REFLEN];
+ char con_host[MAX_HOST];
+ char stderr_path[FN_REFLEN];
+ char stdout_path[FN_REFLEN];
+ MYSQL mysql;
+ char* data_buf;
+ int req_len;
+ int start_wait_timeout;
+ int stderr_path_size,stdout_path_size,data_buf_size;
+ int num_args;
+};
+
+static int set_exec_param(struct manager_thd* thd, char* args_start,
+ char* args_end, PARAM_TYPE param_type);
+
+#define HANDLE_DECL(com) static int com (struct manager_thd* thd, char* args_start,char* args_end)
+#define HANDLE_NOARG_DECL(com) static int com \
+ (struct manager_thd* thd, char* __attribute__((unused)) args_start,\
+ char* __attribute__((unused)) args_end)
+
+
+HANDLE_NOARG_DECL(handle_ping);
+HANDLE_NOARG_DECL(handle_quit);
+HANDLE_NOARG_DECL(handle_help);
+HANDLE_NOARG_DECL(handle_shutdown);
+HANDLE_DECL(handle_def_exec);
+HANDLE_DECL(handle_start_exec);
+HANDLE_DECL(handle_stop_exec);
+HANDLE_DECL(handle_set_exec_con);
+HANDLE_DECL(handle_set_exec_stdout);
+HANDLE_DECL(handle_set_exec_stderr);
+HANDLE_NOARG_DECL(handle_show_exec);
+HANDLE_DECL(handle_query);
+
+
+struct manager_cmd commands[] =
+{
+ {"ping", "Check if this server is alive", handle_ping,4},
+ {"quit", "Finish session", handle_quit,4},
+ {"shutdown", "Shutdown this server", handle_shutdown,8},
+ {"def_exec", "Define executable entry", handle_def_exec,8},
+ {"start_exec", "Launch process defined by executable entry",
+ handle_start_exec,10},
+ {"stop_exec", "Stop process defined by executable entry",
+ handle_stop_exec,9},
+ {"set_exec_con", "Set connection parameters for executable entry",
+ handle_set_exec_con,12},
+ {"set_exec_stdout", "Set stdout path for executable entry",
+ handle_set_exec_stdout,15},
+ {"set_exec_stderr", "Set stderr path for executable entry",
+ handle_set_exec_stderr,15},
+ {"query","Run query against MySQL server",handle_query,5},
+ {"show_exec","Show defined executable entries",handle_show_exec,9},
+ {"help", "Print this message", handle_help,4},
+ {0,0,0,0}
+};
+
+struct option long_options[] =
+{
+ {"debug", optional_argument, 0, '#'},
+ {"help", no_argument, 0, 'h'},
+ {"port", required_argument, 0, 'P'},
+ {"log", required_argument, 0, 'l'},
+ {"bind-address", required_argument, 0, 'b'},
+ {"tcp-backlog", required_argument, 0, 'B'},
+ {"greeting", required_argument, 0, 'g'},
+ {"max-command-len",required_argument,0,'m'},
+ {"one-thread",no_argument,0,'d'},
+ {"connect-retries",required_argument,0,'C'},
+ {"password-file",required_argument,0,'p'},
+ {"pid-file",required_argument,0,'f'},
+ {"version", no_argument, 0, 'V'},
+ {0, 0, 0, 0}
+};
+
+static void die(const char* fmt,...);
+static void print_time(FILE* fp);
+static void clean_up();
+static struct manager_cmd* lookup_cmd(char* s,int len);
+static int client_msg(NET* net,int err_code,const char* fmt,...);
+static int client_msg_pre(NET* net,int err_code,const char* fmt,...);
+static int client_msg_raw(NET* net,int err_code,int pre,const char* fmt,
+ va_list args);
+static int authenticate(struct manager_thd* thd);
+static char* read_line(struct manager_thd* thd); /* returns pointer to end of
+ line
+ */
+static pthread_handler_decl(process_connection, arg);
+static pthread_handler_decl(process_launcher_messages, arg);
+static int exec_line(struct manager_thd* thd,char* buf,char* buf_end);
+
+#ifdef DO_STACKTRACE
+void print_stacktrace();
+#endif
+
+static void log_msg(const char* fmt, int msg_type, va_list args);
+
+/* No 'inline' here becasue functions with ... can't do that portable */
+#define LOG_MSG_FUNC(type,TYPE) static void type \
+ (const char* fmt,...) { \
+ va_list args; \
+ va_start(args,fmt); \
+ log_msg(fmt,TYPE,args);\
+ }
+
+LOG_MSG_FUNC(log_err,LOG_ERR)
+LOG_MSG_FUNC(log_warn,LOG_WARN)
+LOG_MSG_FUNC(log_info,LOG_INFO)
+
+#ifndef DBUG_OFF
+LOG_MSG_FUNC(log_debug,LOG_DEBUG)
+#else
+void log_debug(const char* __attribute__((unused)) fmt,...) {}
+#endif
+
+static void handle_sigterm(int sig __attribute__((unused)))
+{
+ log_info("Got SIGTERM");
+ if (!one_thread)
+ {
+ kill(launcher_pid,SIGTERM);
+ pthread_kill(loop_th,SIGTERM);
+ }
+ clean_up();
+ exit(0);
+}
+
+#ifdef DO_STACKTRACE
+static void handle_segfault(int sig)
+{
+ if (in_segfault)
+ exit(1);
+ in_segfault=1;
+ fprintf(errfp,"Got fatal signal %d\n",sig);
+ print_stacktrace();
+ exit(1);
+}
+#endif
+
+static void handle_sigpipe(int __attribute__((unused)) sig)
+{
+ signal(SIGPIPE,handle_sigpipe);
+}
+
+#ifdef DO_STACKTRACE
+
+#define MAX_DEPTH 25
+#define SIGRETURN_FRAME_COUNT 1
+
+void print_stacktrace()
+{
+ uchar** fp;
+ int i;
+ LINT_INIT(fp);
+ fprintf(errfp,"Fatal errror, stacktrace follows:\n");
+#ifdef __i386__
+ __asm__ __volatile__("movl %%ebp,%0" :"=r"(fp) :"r"(fp));
+#endif
+ if (!fp)
+ {
+ fprintf(errfp,"frame points is NULL, cannot trace stack\n");
+ return;
+ }
+ for(i=0;i<MAX_DEPTH && fp<(uchar**)stack_bottom;i++)
+ {
+#ifdef __i386__
+ uchar** new_fp = (uchar**)*fp;
+ fprintf(errfp, "%p\n", i == SIGRETURN_FRAME_COUNT ?
+ *(fp+17) : *(fp+1));
+#endif /* __386__ */
+ if (new_fp <= fp )
+ {
+ fprintf(errfp, "New value of fp=%p failed sanity check,\
+ terminating stack trace!\n", new_fp);
+ return;
+ }
+ fp = new_fp;
+ }
+ fprintf(errfp,"Stack trace successful\n");
+ fflush(errfp);
+}
+#endif
+
+static int exec_line(struct manager_thd* thd,char* buf,char* buf_end)
+{
+ char* p=buf;
+ struct manager_cmd* cmd;
+ for (;p<buf_end && !isspace(*p);p++)
+ *p=tolower(*p);
+ log_info("Command '%s'", buf);
+ if (!(cmd=lookup_cmd(buf,(int)(p-buf))))
+ {
+ if(client_msg(&thd->net,MANAGER_CLIENT_ERR,
+ "Unrecognized command '%s', type help to see list of supported\
+ commands", buf))
+ thd->fatal=1;
+ return 1;
+ }
+ for (;p<buf_end && isspace(*p);p++);
+ return cmd->handler_func(thd,p,buf_end);
+}
+
+static struct manager_cmd* lookup_cmd(char* s,int len)
+{
+ struct manager_cmd* cmd = commands;
+ for (;cmd->name;cmd++)
+ {
+ if (cmd->len == len && !memcmp(cmd->name,s,len))
+ return cmd;
+ }
+ return 0;
+}
+
+HANDLE_NOARG_DECL(handle_ping)
+{
+ client_msg(&thd->net,MANAGER_OK,"Server management daemon is alive");
+ return 0;
+}
+
+HANDLE_NOARG_DECL(handle_quit)
+{
+ client_msg(&thd->net,MANAGER_OK,"Goodbye");
+ thd->finished=1;
+ return 0;
+}
+
+HANDLE_NOARG_DECL(handle_help)
+{
+ struct manager_cmd* cmd = commands;
+ NET* net = &thd->net;
+ client_msg_pre(net,MANAGER_INFO,"Available commands:");
+ for (;cmd->name;cmd++)
+ {
+ client_msg_pre(net,MANAGER_INFO,"%s - %s", cmd->name, cmd->help);
+ }
+ client_msg_pre(net,MANAGER_INFO,"End of help");
+ return 0;
+}
+
+HANDLE_NOARG_DECL(handle_shutdown)
+{
+ client_msg(&thd->net,MANAGER_OK,"Shutdown started, goodbye");
+ thd->finished=1;
+ shutdown_requested = 1;
+ if (!one_thread)
+ {
+ kill(launcher_pid,SIGTERM);
+ pthread_kill(loop_th,SIGTERM);
+ }
+ return 0;
+}
+
+HANDLE_DECL(handle_set_exec_con)
+{
+ int num_args;
+ const char* error=0;
+ struct manager_exec* e;
+ char* arg_p;
+ if ((num_args=tokenize_args(args_start,&args_end))<2)
+ {
+ error="Too few arguments";
+ goto err;
+ }
+ arg_p=args_start;
+ pthread_mutex_lock(&lock_exec_hash);
+ if (!(e=(struct manager_exec*)hash_search(&exec_hash,arg_p,
+ strlen(arg_p))))
+ {
+ pthread_mutex_unlock(&lock_exec_hash);
+ error="Exec definition entry does not exist";
+ goto err;
+ }
+ arg_p+=strlen(arg_p)+1;
+ arg_p+=(strnmov(e->con_user,arg_p,sizeof(e->con_user))-e->con_user)+1;
+ if (num_args >= 3)
+ {
+ arg_p+=(strnmov(e->con_host,arg_p,sizeof(e->con_host))-e->con_host)+1;
+ if (num_args == 4)
+ {
+ if (!(e->con_port=atoi(arg_p)))
+ strnmov(e->con_sock,arg_p,sizeof(e->con_sock));
+ else
+ e->con_sock[0]=0;
+ }
+ else if(num_args > 4)
+ {
+ pthread_mutex_unlock(&lock_exec_hash);
+ error="Too many arguments";
+ goto err;
+ }
+ }
+ pthread_mutex_unlock(&lock_exec_hash);
+ client_msg(&thd->net,MANAGER_OK,"Entry updated");
+ return 0;
+err:
+ client_msg(&thd->net,MANAGER_CLIENT_ERR,error);
+ return 1;
+}
+
+HANDLE_DECL(handle_set_exec_stdout)
+{
+ return set_exec_param(thd,args_start,args_end,PARAM_STDOUT);
+}
+
+HANDLE_DECL(handle_set_exec_stderr)
+{
+ return set_exec_param(thd,args_start,args_end,PARAM_STDERR);
+}
+
+static int set_exec_param(struct manager_thd* thd, char* args_start,
+ char* args_end, PARAM_TYPE param_type)
+{
+ int num_args;
+ const char* error=0;
+ struct manager_exec* e;
+ char* arg_p;
+ char* param;
+ int param_size;
+
+ if ((num_args=tokenize_args(args_start,&args_end))<2)
+ {
+ error="Too few arguments";
+ goto err;
+ }
+ arg_p=args_start;
+ pthread_mutex_lock(&lock_exec_hash);
+ if (!(e=(struct manager_exec*)hash_search(&exec_hash,arg_p,
+ strlen(arg_p))))
+ {
+ pthread_mutex_unlock(&lock_exec_hash);
+ error="Exec definition entry does not exist";
+ goto err;
+ }
+ arg_p+=strlen(arg_p)+1;
+ param_size=strlen(arg_p)+1;
+ switch (param_type)
+ {
+ case PARAM_STDOUT:
+ param=e->stdout_path;
+ e->req_len+=(param_size-e->stdout_path_size);
+ e->stdout_path_size=param_size;
+ break;
+ case PARAM_STDERR:
+ param=e->stderr_path;
+ e->req_len+=(param_size-e->stderr_path_size);
+ e->stderr_path_size=param_size;
+ break;
+ default:
+ error="Internal error";
+ goto err;
+ }
+ strnmov(param,arg_p,FN_REFLEN);
+ pthread_mutex_unlock(&lock_exec_hash);
+ client_msg(&thd->net,MANAGER_OK,"Entry updated");
+ return 0;
+err:
+ client_msg(&thd->net,MANAGER_CLIENT_ERR,error);
+ return 1;
+}
+
+
+HANDLE_DECL(handle_start_exec)
+{
+ int num_args;
+ struct manager_exec* e;
+ int ident_len;
+ const char* error=0;
+ struct timespec t;
+ if ((num_args=tokenize_args(args_start,&args_end))<1)
+ {
+ error="Too few arguments";
+ goto err;
+ }
+ ident_len=strlen(args_start);
+ pthread_mutex_lock(&lock_exec_hash);
+ if (!(e=(struct manager_exec*)hash_search(&exec_hash,args_start,
+ ident_len)))
+ {
+ pthread_mutex_unlock(&lock_exec_hash);
+ error="Exec definition entry does not exist";
+ goto err;
+ }
+ pthread_mutex_unlock(&lock_exec_hash);
+ manager_exec_launch(e);
+ if ((error=e->error))
+ goto err;
+ pthread_mutex_lock(&e->lock);
+ t.tv_sec=time(0)+(e->start_wait_timeout=atoi(args_start+ident_len+1));
+ t.tv_nsec=0;
+ if (!e->pid)
+ pthread_cond_timedwait(&e->cond,&e->lock,&t);
+ if (!e->pid)
+ {
+ pthread_mutex_unlock(&e->lock);
+ error="Process failed to start withing alotted time";
+ goto err;
+ }
+ mysql_close(&e->mysql);
+ manager_exec_connect(e);
+ error=e->error;
+ pthread_mutex_unlock(&e->lock);
+ if (error)
+ goto err;
+ client_msg(&thd->net,MANAGER_OK,"'%s' started",e->ident);
+ return 0;
+err:
+ client_msg(&thd->net,MANAGER_CLIENT_ERR,error);
+ return 1;
+}
+
+HANDLE_DECL(handle_stop_exec)
+{
+ int num_args;
+ struct timespec abstime;
+ struct manager_exec* e;
+ int ident_len;
+ const char* error=0;
+ if ((num_args=tokenize_args(args_start,&args_end))<2)
+ {
+ error="Too few arguments";
+ goto err;
+ }
+ ident_len=strlen(args_start);
+ abstime.tv_sec=time(0)+atoi(args_start+1+ident_len);
+ abstime.tv_nsec=0;
+ pthread_mutex_lock(&lock_exec_hash);
+ if (!(e=(struct manager_exec*)hash_search(&exec_hash,args_start,
+ ident_len)))
+ {
+ pthread_mutex_unlock(&lock_exec_hash);
+ error="Exec definition entry does not exist";
+ goto err;
+ }
+ pthread_mutex_unlock(&lock_exec_hash);
+ pthread_mutex_lock(&e->lock);
+ e->th=pthread_self();
+ if (!e->pid)
+ {
+ /* e->th=0; */ /* th may be a struct */
+ pthread_mutex_unlock(&e->lock);
+ error="Process not running";
+ goto err;
+ }
+ if (mysql_shutdown(&e->mysql))
+ {
+ /* e->th=0; */ /* th may be a struct */
+ pthread_mutex_unlock(&e->lock);
+ error="Could not send shutdown command";
+ goto err;
+ }
+ if (e->pid)
+ pthread_cond_timedwait(&e->cond,&e->lock,&abstime);
+ if (e->pid)
+ error="Process failed to terminate within alotted time";
+ /* e->th=0; */ /* th may be a struct */
+ pthread_mutex_unlock(&e->lock);
+ if (!error)
+ {
+ client_msg(&thd->net,MANAGER_OK,"'%s' terminated",e->ident);
+ return 0;
+ }
+err:
+ client_msg(&thd->net,MANAGER_CLIENT_ERR,error);
+ return 1;
+}
+
+HANDLE_DECL(handle_query)
+{
+ const char* error=0;
+ struct manager_exec* e;
+ MYSQL_RES* res=0;
+ MYSQL_ROW row;
+ MYSQL_FIELD* fields;
+ int num_fields,i,ident_len;
+ char* ident,*query;
+ query=ident=args_start;
+ while (!isspace(*query))
+ query++;
+ if (query == ident)
+ {
+ error="Missing server identifier";
+ goto err;
+ }
+ ident_len=(int)(query-ident);
+ while (query<args_end && isspace(*query))
+ query++;
+ if (query == args_end)
+ {
+ error="Missing query";
+ goto err;
+ }
+ pthread_mutex_lock(&lock_exec_hash);
+ if (!(e=(struct manager_exec*)hash_search(&exec_hash,ident,
+ ident_len)))
+ {
+ pthread_mutex_unlock(&lock_exec_hash);
+ error="Exec definition entry does not exist";
+ goto err;
+ }
+ pthread_mutex_unlock(&lock_exec_hash);
+ pthread_mutex_lock(&e->lock);
+ if (!e->pid)
+ {
+ error="Process is not running";
+ pthread_mutex_unlock(&e->lock);
+ goto err;
+ }
+
+ if (mysql_query(&e->mysql,query))
+ {
+ error=mysql_error(&e->mysql);
+ pthread_mutex_unlock(&e->lock);
+ goto err;
+ }
+ if ((res=mysql_store_result(&e->mysql)))
+ {
+ char buf[MAX_CLIENT_MSG_LEN],*p,*buf_end;
+ fields=mysql_fetch_fields(res);
+ num_fields=mysql_num_fields(res);
+ p=buf;
+ buf_end=buf+sizeof(buf);
+ for (i=0;i<num_fields && p<buf_end-2;i++)
+ {
+ p=arg_strmov(p,fields[i].name,buf_end-p-2);
+ *p++='\t';
+ }
+ *p=0;
+ client_msg_pre(&thd->net,MANAGER_OK,buf);
+
+ while ((row=mysql_fetch_row(res)))
+ {
+ p=buf;
+ for (i=0;i<num_fields && p<buf_end-2;i++)
+ {
+ p=arg_strmov(p,row[i],buf_end-p-2);
+ *p++='\t';
+ }
+ *p=0;
+ client_msg_pre(&thd->net,MANAGER_OK,buf);
+ }
+ }
+ pthread_mutex_unlock(&e->lock);
+ client_msg(&thd->net,MANAGER_OK,"End");
+ return 0;
+err:
+ client_msg(&thd->net,MANAGER_CLIENT_ERR,error);
+ return 1;
+}
+
+HANDLE_DECL(handle_def_exec)
+{
+ struct manager_exec* e=0,*old_e;
+ const char* error=0;
+ if (!(e=manager_exec_new(args_start,args_end)))
+ {
+ error="Out of memory";
+ goto err;
+ }
+ if (e->error)
+ {
+ error=e->error;
+ goto err;
+ }
+ pthread_mutex_lock(&lock_exec_hash);
+ if ((old_e=(struct manager_exec*)hash_search(&exec_hash,(byte*)e->ident,
+ e->ident_len)))
+ {
+ strnmov(e->stdout_path,old_e->stdout_path,sizeof(e->stdout_path));
+ strnmov(e->stderr_path,old_e->stderr_path,sizeof(e->stderr_path));
+ strnmov(e->con_user,old_e->con_user,sizeof(e->con_user));
+ strnmov(e->con_host,old_e->con_host,sizeof(e->con_host));
+ strnmov(e->con_sock,old_e->con_sock,sizeof(e->con_sock));
+ e->con_port=old_e->con_port;
+ update_req_len(e);
+ hash_delete(&exec_hash,(byte*)old_e);
+ }
+ hash_insert(&exec_hash,(byte*)e);
+ pthread_mutex_unlock(&lock_exec_hash);
+ client_msg(&thd->net,MANAGER_OK,"Exec definition created");
+ return 0;
+err:
+ client_msg(&thd->net,MANAGER_CLIENT_ERR,error);
+ if (e)
+ manager_exec_free(e);
+ return 1;
+}
+
+HANDLE_NOARG_DECL(handle_show_exec)
+{
+ uint i;
+ client_msg_pre(&thd->net,MANAGER_INFO,"Exec_def\tPid\tExit_status\tCon_info\
+\tStdout\tStderr\tArguments");
+ pthread_mutex_lock(&lock_exec_hash);
+ for (i=0;i<exec_hash.records;i++)
+ {
+ struct manager_exec* e=(struct manager_exec*)hash_element(&exec_hash,i);
+ manager_exec_print(&thd->net,e);
+ }
+ pthread_mutex_unlock(&lock_exec_hash);
+ client_msg(&thd->net,MANAGER_INFO,"End");
+ return 0;
+}
+
+static struct manager_exec* manager_exec_by_pid(pid_t pid)
+{
+ struct manager_exec* e;
+ uint i;
+ pthread_mutex_lock(&lock_exec_hash);
+ for (i=0;i<exec_hash.records;i++)
+ {
+ e=(struct manager_exec*)hash_element(&exec_hash,i);
+ if (e->pid==pid)
+ {
+ pthread_mutex_unlock(&lock_exec_hash);
+ return e;
+ }
+ }
+ pthread_mutex_unlock(&lock_exec_hash);
+ return 0;
+}
+
+static void manager_exec_connect(struct manager_exec* e)
+{
+ int i;
+ int connect_retries;
+
+ if (!(connect_retries=e->start_wait_timeout))
+ connect_retries=manager_connect_retries;
+
+ for (i=0;i<connect_retries;i++)
+ {
+ if (mysql_real_connect(&e->mysql,e->con_host,e->con_user,e->con_pass,0,
+ e->con_port,e->con_sock,0))
+ return;
+ sleep(1);
+ }
+ e->error="Could not connect to MySQL server withing the number of tries";
+}
+
+static int manager_exec_launch(struct manager_exec* e)
+{
+ if (one_thread)
+ {
+ pid_t tmp_pid;
+ switch ((tmp_pid=fork()))
+ {
+ case -1:
+ e->error="Cannot fork";
+ return 1;
+ case 0:
+ {
+ int err_code;
+ close(manager_sock);
+ err_code=execv(e->bin_path,e->args);
+ exit(err_code);
+ }
+ default:
+ e->pid=tmp_pid;
+ manager_exec_connect(e);
+ return 0;
+ }
+ }
+ else
+ {
+ if (my_write(to_launcher_pipe[1],(byte*)&e->req_len,
+ sizeof(int),MYF(MY_NABP))||
+ my_write(to_launcher_pipe[1],(byte*)&e->num_args,
+ sizeof(int),MYF(MY_NABP)) ||
+ my_write(to_launcher_pipe[1],e->stdout_path,e->stdout_path_size,
+ MYF(MY_NABP)) ||
+ my_write(to_launcher_pipe[1],e->stderr_path,e->stderr_path_size,
+ MYF(MY_NABP)) ||
+ my_write(to_launcher_pipe[1],e->data_buf,e->data_buf_size,
+ MYF(MY_NABP)))
+ {
+ e->error="Failed write request to launcher";
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static char* arg_strmov(char* dest, const char* src, int n)
+{
+ char* dest_end = dest+n-1;
+ char c;
+ for (;dest<dest_end && (c=*src++);)
+ {
+ if (c=='%')
+ *dest++='%';
+ *dest++=c;
+ }
+ return dest;
+}
+
+static void manager_exec_print(NET* net,struct manager_exec* e)
+{
+ char buf[MAX_MYSQL_MANAGER_MSG];
+ char* p=buf,*buf_end=buf+sizeof(buf)-1;
+ char** args=e->args;
+
+ p=arg_strmov(p,e->ident,(int)(buf_end-p)-1);
+ *p++='\t';
+ if (p>buf_end-15)
+ goto end;
+ p=int10_to_str(e->pid,p,10);
+ *p++='\t';
+ p=int10_to_str(e->exit_code,p,10);
+ *p++='\t';
+
+ p=arg_strmov(p,e->con_user,(int)(buf_end-p)-1);
+ *p++='@';
+ if (p==buf_end)
+ goto end;
+ p=arg_strmov(p,e->con_host,(int)(buf_end-p)-11);
+ *p++=':';
+ if (p==buf_end-10)
+ goto end;
+ if (e->con_sock[0])
+ {
+ p=arg_strmov(p,e->con_sock,(int)(buf_end-p)-1);
+ }
+ else
+ {
+ p=int10_to_str(e->con_port,p,10);
+ }
+ *p++='\t';
+ p=arg_strmov(p,e->stdout_path,(int)(buf_end-p)-1);
+ if (p==buf_end-1)
+ goto end;
+ *p++='\t';
+ p=arg_strmov(p,e->stderr_path,(int)(buf_end-p)-1);
+ if (p==buf_end-1)
+ goto end;
+ *p++='\t';
+
+ for(;p<buf_end && *args;args++)
+ {
+ p=arg_strmov(p,*args,(int)(buf_end-p)-1);
+ *p++='\t';
+ }
+end:
+ *p=0;
+ client_msg_pre(net,MANAGER_INFO,buf);
+ return;
+}
+
+static int authenticate(struct manager_thd* thd)
+{
+ char* buf_end,*buf,*p,*p_end;
+ my_MD5_CTX context;
+ uchar digest[MD5_LEN];
+ struct manager_user* u;
+ char c;
+
+ client_msg(&thd->net,MANAGER_INFO, manager_greeting);
+ if (!(buf_end=read_line(thd)))
+ return -1;
+ for (buf=thd->cmd_buf,p=thd->user,p_end=p+MAX_USER_NAME;
+ buf<buf_end && (c=*buf) && p<p_end; buf++,p++)
+ {
+ if (isspace(c))
+ {
+ *p=0;
+ break;
+ }
+ else
+ *p=c;
+ }
+ if (p==p_end || buf==buf_end)
+ return 1;
+ if (!(u=(struct manager_user*)hash_search(&user_hash,thd->user,
+ (uint)(p-thd->user))))
+ return 1;
+ for (;isspace(*buf) && buf<buf_end;buf++) /* empty */;
+
+ my_MD5Init(&context);
+ my_MD5Update(&context,(uchar*) buf,(uint)(buf_end-buf));
+ my_MD5Final(digest,&context);
+ if (memcmp(u->md5_pass,digest,MD5_LEN))
+ return 1;
+ client_msg(&thd->net,MANAGER_OK,"OK");
+ return 0;
+}
+
+static void print_time(FILE* fp)
+{
+ struct tm now;
+ time_t t;
+ time(&t);
+ localtime_r(&t,&now);
+ fprintf(fp,"[%d-%02d-%02d %02d:%02d:%02d] ", now.tm_year+1900,
+ now.tm_mon+1,now.tm_mday,now.tm_hour,now.tm_min,
+ now.tm_sec);
+}
+
+static void die(const char* fmt, ...)
+{
+ va_list args;
+ va_start(args,fmt);
+ if (fmt)
+ {
+ if (errfp==stderr)
+ fprintf(errfp, "%s: ", my_progname);
+ else
+ {
+ print_time(errfp);
+ fprintf(errfp,"Fatal error: ");
+ }
+ vfprintf(errfp, fmt, args);
+ if (errno)
+ fprintf(errfp, " errno=%d", errno);
+ fprintf(errfp, "\n");
+ fflush(errfp);
+ }
+ va_end(args);
+ clean_up();
+ exit(1);
+}
+
+void print_msg_type(int msg_type)
+{
+ const char* msg;
+ switch (msg_type)
+ {
+ case LOG_ERR: msg = "ERROR"; break;
+ case LOG_WARN: msg = "WARNING"; break;
+ case LOG_INFO: msg = "INFO"; break;
+#ifndef DBUG_OFF
+ case LOG_DEBUG: msg = "DEBUG"; break;
+#endif
+ default: msg = "UNKNOWN TYPE"; break;
+ }
+ fprintf(errfp," %s: ", msg);
+}
+
+static void log_msg(const char* fmt, int msg_type, va_list args)
+{
+ pthread_mutex_lock(&lock_log);
+ print_time(errfp);
+ print_msg_type(msg_type);
+ vfprintf(errfp,fmt,args);
+ fputc('\n',errfp);
+ fflush(errfp);
+ pthread_mutex_unlock(&lock_log);
+}
+
+static pthread_handler_decl(process_launcher_messages,
+ __attribute__((unused)) arg)
+{
+ my_thread_init();
+ for (;!in_shutdown;)
+ {
+ pid_t pid;
+ struct manager_exec* e;
+ char buf[MAX_LAUNCHER_MSG];
+ if (read(from_launcher_pipe[0],buf,MAX_LAUNCHER_MSG)<0)
+ {
+ log_err("error reading launcher message");
+ sleep(1);
+ continue;
+ }
+ switch (buf[0])
+ {
+ case CHILD_START:
+ {
+ char* ident=buf+1;
+ int ident_len=strlen(ident);
+ memcpy(&pid,ident+ident_len+1,sizeof(pid));
+ log_debug("process message - ident=%s ident_len=%d pid=%d",ident,
+ ident_len,pid);
+ pthread_mutex_lock(&lock_exec_hash);
+ log_debug("hash has %d records",exec_hash.records);
+ e=(struct manager_exec*)hash_search(&exec_hash,ident,ident_len);
+ if (e)
+ {
+ pthread_mutex_lock(&e->lock);
+ e->pid=pid;
+ pthread_cond_broadcast(&e->cond);
+ pthread_mutex_unlock(&e->lock);
+ }
+ pthread_mutex_unlock(&lock_exec_hash);
+ log_debug("unlocked mutex");
+ break;
+ }
+ case CHILD_STOP:
+ memcpy(&pid,buf+1,sizeof(pid));
+ e=manager_exec_by_pid(pid);
+ if (e)
+ {
+ pthread_mutex_lock(&e->lock);
+ e->pid=0;
+ memcpy(&e->exit_code,buf+1+sizeof(pid),sizeof(int));
+ pthread_cond_broadcast(&e->cond);
+ pthread_mutex_unlock(&e->lock);
+ }
+ break;
+ default:
+ log_err("Got invalid launcher message");
+ break;
+ }
+ }
+ return 0;
+}
+
+static pthread_handler_decl(process_connection,arg)
+{
+ struct manager_thd* thd = (struct manager_thd*)arg;
+ my_thread_init();
+ pthread_detach_this_thread();
+ for (;!thd->finished;)
+ {
+ char* buf_end;
+ if ((!(buf_end=read_line(thd)) || exec_line(thd,thd->cmd_buf,buf_end))
+ && thd->fatal)
+ {
+ log_err("Thread aborted");
+ break;
+ }
+ }
+ manager_thd_free(thd);
+ pthread_exit(0);
+ return 0; /* Don't get cc warning */
+}
+
+static int client_msg_raw(NET* net, int err_code, int pre, const char* fmt,
+ va_list args)
+{
+ char buf[MAX_CLIENT_MSG_LEN],*p,*buf_end;
+ p=buf;
+ buf_end=buf+sizeof(buf);
+ p=int10_to_str(err_code,p,10);
+ if (pre)
+ *p++='-';
+ *p++=' ';
+ p+=my_vsnprintf(p,buf_end-p,fmt,args);
+ if (p>buf_end-2)
+ p=buf_end - 2;
+ *p++='\r';
+ *p++='\n';
+ log_debug("message to client: %-.*s",p-buf-2,buf);
+ if (my_net_write(net,buf,(uint)(p-buf)) || net_flush(net))
+ {
+ p[-2]=0;
+ log_err("Failed writing '%s' to client: errno=%d",buf,errno);
+ net_end(net);
+ return 1;
+ }
+ return 0;
+}
+
+static int client_msg(NET* net, int err_code, const char* fmt, ...)
+{
+ va_list args;
+ va_start(args,fmt);
+ return client_msg_raw(net,err_code,0,fmt,args);
+}
+
+static int client_msg_pre(NET* net, int err_code, const char* fmt, ...)
+{
+ va_list args;
+ va_start(args,fmt);
+ return client_msg_raw(net,err_code,1,fmt,args);
+}
+
+static char* read_line(struct manager_thd* thd)
+{
+ int len;
+ char* p, *buf_end;
+ if ((len=my_net_read(&thd->net)) == (int)packet_error || !len)
+ {
+ log_err("Error reading command from client (Error: %d)",
+ errno);
+ thd->fatal=1;
+ return 0;
+ }
+ buf_end=thd->cmd_buf+len;
+ for (p=thd->cmd_buf;p<buf_end;p++)
+ if (*p == '\r' || *p == '\n')
+ {
+ *p=0;
+ break;
+ }
+
+ return p;
+}
+
+static void handle_child(int __attribute__((unused)) sig)
+{
+ pid_t child;
+ int child_status;
+
+ for(;(child=waitpid(-1,&child_status,WNOHANG))>0;)
+ {
+ char msg_buf[1+sizeof(int)+sizeof(int)];
+ msg_buf[0]=CHILD_STOP;
+ memcpy(msg_buf+1,&child,sizeof(int));
+ memcpy(msg_buf+1+sizeof(int),&child_status,sizeof(int));
+ if (write(from_launcher_pipe[1],msg_buf,sizeof(msg_buf))!=sizeof(msg_buf))
+ log_err("launcher: error writing message on child exit");
+ }
+ signal(SIGCHLD,handle_child);
+}
+
+struct manager_thd* manager_thd_new(Vio* vio)
+{
+ struct manager_thd* tmp;
+ if (!(tmp=(struct manager_thd*)my_malloc(sizeof(*tmp),
+ MYF(0))))
+ {
+ log_err("Out of memory in manager_thd_new");
+ return 0;
+ }
+ my_net_init(&tmp->net,vio);
+ tmp->user[0]=0;
+ tmp->priv_flags=0;
+ tmp->fatal=tmp->finished=0;
+ tmp->cmd_buf= (char*) tmp->net.read_pos;
+ return tmp;
+}
+
+static void manager_thd_free(struct manager_thd* thd)
+{
+ NET* net=&thd->net;
+ if (net->vio)
+ {
+ vio_delete(net->vio);
+ net->vio=0;
+ }
+ net_end(&thd->net);
+}
+
+static void clean_up()
+{
+ pthread_mutex_lock(&lock_shutdown);
+ if (in_shutdown)
+ {
+ pthread_mutex_unlock(&lock_shutdown);
+ return;
+ }
+ in_shutdown = 1;
+ pthread_mutex_unlock(&lock_shutdown);
+ log_info("Shutdown started");
+ if (manager_sock)
+ close(manager_sock);
+ log_info("Ended");
+ if (errfp != stderr)
+ fclose(errfp);
+ hash_free(&exec_hash);
+ if (created_pid_file)
+ my_delete(pid_file, MYF(0));
+}
+
+static void print_version(void)
+{
+ printf("%s Ver %s Distrib %s, for %s (%s)\n",my_progname,MANAGER_VERSION,
+ MYSQL_SERVER_VERSION,SYSTEM_TYPE,MACHINE_TYPE);
+}
+
+static void usage()
+{
+ print_version();
+ printf("MySQL AB, by Sasha\n");
+ printf("This software comes with ABSOLUTELY NO WARRANTY\n\n");
+ printf("Manages instances of MySQL server.\n\n");
+ printf("Usage: %s [OPTIONS]", my_progname);
+ printf("\n\
+ -?, --help Display this help and exit.\n");
+#ifndef DBUG_OFF
+ puts("\
+ -#, --debug=[...] Output debug log. Often this is 'd:t:o,filename`");
+#endif
+ printf("\
+ -P, --port=... Port number to listen on.\n\
+ -l, --log=... Path to log file.\n\
+ -b, --bind-address=... Address to listen on.\n\
+ -B, --tcp-backlog==... Size of TCP/IP listen queue.\n\
+ -g, --greeting= Set greeting on connect \n\
+ -m, --max-command-len Maximum command length \n\
+ -d, --one-thread Use one thread ( for debugging) \n\
+ -C, --connect-retries Number of attempts to establish MySQL connection \n\
+ -m, --max-command-len Maximum command length \n\
+ -V, --version Output version information and exit.\n\n");
+}
+
+static int parse_args(int argc, char **argv)
+{
+ int c, option_index = 0;
+ while ((c=getopt_long(argc,argv,"P:?#:Vl:b:B:g:m:dC:p:f:",
+ long_options,&option_index)) != EOF)
+ {
+ switch (c)
+ {
+ case '#':
+ DBUG_PUSH(optarg ? optarg : "d:t:O,/tmp/mysqlmgrd.trace");
+ break;
+ case 'd':
+ one_thread=1;
+ break;
+ case 'p':
+ manager_pw_file=optarg;
+ break;
+ case 'f':
+ pid_file=optarg;
+ break;
+ case 'C':
+ manager_connect_retries=atoi(optarg);
+ break;
+ case 'P':
+ manager_port=atoi(optarg);
+ break;
+ case 'm':
+ manager_max_cmd_len=atoi(optarg);
+ break;
+ case 'g':
+ manager_greeting=optarg;
+ case 'b':
+ manager_bind_addr = inet_addr(optarg);
+ break;
+ case 'B':
+ manager_back_log = atoi(optarg);
+ break;
+ case 'l':
+ manager_log_file=optarg;
+ break;
+ case 'V':
+ print_version();
+ exit(0);
+ case '?':
+ usage();
+ exit(0);
+ default:
+ usage();
+ exit(1);
+ }
+ }
+ return 0;
+}
+
+static int init_server()
+{
+ int arg=1;
+ log_info("Started");
+ if ((manager_sock=socket(PF_INET,SOCK_STREAM,0)) < 0)
+ die("Could not create socket");
+ bzero((char*)&manager_addr, sizeof(manager_addr));
+ manager_addr.sin_family = AF_INET;
+ manager_addr.sin_addr.s_addr = manager_bind_addr;
+ manager_addr.sin_port = htons(manager_port);
+ setsockopt(manager_sock,SOL_SOCKET, SO_REUSEADDR,(char*)&arg,sizeof(arg));
+ if (bind(manager_sock,(struct sockaddr*)&manager_addr, sizeof(manager_addr)) < 0)
+ die("Could not bind");
+ if (listen(manager_sock,manager_back_log) < 0)
+ die("Could not listen");
+
+ return 0;
+}
+
+static int run_server_loop()
+{
+ pthread_t th;
+ struct manager_thd *thd;
+ int client_sock;
+ Vio* vio;
+ pthread_attr_t thr_attr;
+ (void) pthread_attr_init(&thr_attr);
+#if !defined(HAVE_DEC_3_2_THREADS)
+ pthread_attr_setscope(&thr_attr,PTHREAD_SCOPE_SYSTEM);
+ (void) pthread_attr_setdetachstate(&thr_attr,PTHREAD_CREATE_DETACHED);
+#endif
+
+ for (;!shutdown_requested;)
+ {
+ size_socket len=sizeof(struct sockaddr_in);
+ if ((client_sock=accept(manager_sock,(struct sockaddr*)&manager_addr,
+ &len)) <0)
+ {
+ if (shutdown_requested)
+ break;
+ if (errno != EAGAIN)
+ {
+ log_warn("Error in accept, errno=%d", errno);
+ sleep(1); /* avoid tying up CPU if accept is broken */
+ }
+ continue;
+ }
+ if (shutdown_requested)
+ break;
+ if (!(vio=vio_new(client_sock,VIO_TYPE_TCPIP,FALSE)))
+ {
+ log_err("Could not create I/O object");
+ close(client_sock);
+ continue;
+ }
+ if (!(thd=manager_thd_new(vio)))
+ {
+ log_err("Could not create thread object");
+ vio_close(vio);
+ continue;
+ }
+ if (authenticate(thd))
+ {
+ client_msg(&thd->net,MANAGER_ACCESS, "Access denied");
+ manager_thd_free(thd);
+ log_info("Client failed to authenticate");
+ continue;
+ }
+ if (shutdown_requested)
+ {
+ manager_thd_free(thd);
+ break;
+ }
+ if (one_thread)
+ {
+ process_connection((void*)thd);
+ manager_thd_free(thd);
+ continue;
+ }
+ else if (pthread_create(&th,&thr_attr,process_connection,(void*)thd))
+ {
+ client_msg(&thd->net,MANAGER_INTERNAL_ERR,
+ "Could not create thread, errno=%d",
+ errno);
+ manager_thd_free(thd);
+ continue;
+ }
+ }
+ (void) pthread_attr_destroy(&thr_attr);
+ return 0;
+}
+
+static FILE* open_log_stream()
+{
+ FILE* fp;
+ if (!(fp=fopen(manager_log_file,"a")))
+ die("Could not open log file '%s'", manager_log_file);
+ return fp;
+}
+
+static byte* get_user_key(const byte* u, uint* len,
+ my_bool __attribute__((unused)) t)
+{
+ register const char* key;
+ key = ((struct manager_user*)u)->user;
+ *len = ((struct manager_user*)u)->user_len;
+ return (byte*)key;
+}
+
+static byte* get_exec_key(const byte* e, uint* len,
+ my_bool __attribute__((unused)) t)
+{
+ register const char* key;
+ key = ((struct manager_exec*)e)->ident;
+ *len = ((struct manager_exec*)e)->ident_len;
+ return (byte*)key;
+}
+
+static void init_arg_array(char* arg_str,char** args,uint arg_count)
+{
+ char* p = arg_str;
+ for (;arg_count>0;arg_count--)
+ {
+ *args++=p;
+ p += strlen(p)+1;
+ }
+ *args=0;
+}
+
+static uint tokenize_args(char* arg_start,char** arg_end)
+{
+ char* p, *p_write,*p_end;
+ uint arg_count=0;
+ int quoted=0,escaped=0,last_space=0;
+ p_end=*arg_end;
+ p_write=p=arg_start;
+ for(;p<p_end;p++)
+ {
+ char c = *p;
+ switch (c)
+ {
+ case ' ':
+ case '\r':
+ case '\n':
+ if (!quoted)
+ {
+ if (!last_space)
+ {
+ *p_write++=0;
+ arg_count++;
+ last_space=1;
+ }
+ }
+ else
+ *p_write++=c;
+ escaped=0;
+ break;
+ case '"':
+ if (!escaped)
+ quoted=!quoted;
+ else
+ *p_write++=c;
+ last_space=0;
+ escaped=0;
+ break;
+ case '\\':
+ if (!escaped)
+ escaped=1;
+ else
+ {
+ *p_write++=c;
+ escaped=0;
+ }
+ last_space=0;
+ break;
+ default:
+ escaped=last_space=0;
+ *p_write++=c;
+ break;
+ }
+ }
+ if (!last_space && p_write>arg_start)
+ arg_count++;
+ *p_write=0;
+ *arg_end=p_write;
+ log_debug("arg_count=%d,arg_start='%s'",arg_count,arg_start);
+ return arg_count;
+}
+
+static void update_req_len(struct manager_exec* e)
+{
+ e->req_len=e->data_buf_size+
+ (e->stdout_path_size=strlen(e->stdout_path)+1)+
+ (e->stderr_path_size=strlen(e->stderr_path)+1);
+ }
+
+static struct manager_exec* manager_exec_new(char* arg_start,char* arg_end)
+{
+ struct manager_exec* tmp;
+ char* first_arg;
+ uint arg_len,num_args;
+ num_args=tokenize_args(arg_start,&arg_end);
+ arg_len=(uint)(arg_end-arg_start)+1; /* include \0 terminator*/
+ if (!(tmp=(struct manager_exec*)my_malloc(sizeof(*tmp)+arg_len+
+ sizeof(char*)*num_args,
+ MYF(MY_ZEROFILL))))
+ return 0;
+ if (num_args<2)
+ {
+ tmp->error="Too few arguments";
+ return tmp;
+ }
+ /* We have to allocate 'args' first as this must be alligned */
+ tmp->args=(char**)(tmp +1);
+ tmp->data_buf= (char*) (tmp->args + num_args);
+ memcpy(tmp->data_buf,arg_start,arg_len);
+ tmp->data_buf_size=arg_len;
+ tmp->num_args=num_args;
+ tmp->ident=tmp->data_buf;
+ tmp->ident_len=strlen(tmp->ident);
+ first_arg=tmp->ident+tmp->ident_len+1;
+ init_arg_array(first_arg,tmp->args,num_args-1);
+ strmov(tmp->con_user,"root");
+ tmp->con_port=MYSQL_PORT;
+ memcpy(tmp->con_host,"localhost",10);
+ tmp->bin_path=tmp->args[0];
+ tmp->stdout_path_size=tmp->stderr_path_size=1;
+ tmp->req_len=tmp->data_buf_size+2;
+ pthread_mutex_init(&tmp->lock,0);
+ pthread_cond_init(&tmp->cond,0);
+ mysql_init(&tmp->mysql);
+ return tmp;
+}
+
+static void manager_exec_free(void* e)
+{
+ mysql_close(&((struct manager_exec*)e)->mysql);
+ my_free(e,MYF(0));
+}
+
+static int hex_val(char c)
+{
+ if (isdigit(c))
+ return c-'0';
+ c=tolower(c);
+ return c-'a'+10;
+}
+
+static struct manager_user* manager_user_new(char* buf)
+{
+ struct manager_user* tmp;
+ char* p,*user_end,*p_end;
+ char c;
+ if (!(tmp=(struct manager_user*)my_malloc(sizeof(*tmp),MYF(0))))
+ return 0;
+ p=tmp->user;
+ tmp->error=0;
+ user_end=p+MAX_USER_NAME;
+ for (;(c=*buf) && p<user_end;buf++)
+ {
+ if (c == ':')
+ {
+ *p=0;
+ tmp->user_len=p-tmp->user;
+ buf++;
+ break;
+ }
+ else
+ *p++=c;
+ }
+ if (!c)
+ tmp->error="Missing ':'";
+ if (p == user_end)
+ tmp->error="Username too long";
+ if (tmp->error)
+ return tmp;
+ if (strlen(buf) < 2*MD5_LEN)
+ {
+ tmp->error="Invalid MD5 sum, too short";
+ return tmp;
+ }
+ p=tmp->md5_pass;
+ p_end=p+MD5_LEN;
+ for (; p<p_end;p++,buf+=2)
+ {
+ *p=hex_val(*buf)*16+hex_val(buf[1]);
+ }
+
+ return tmp;
+}
+
+static void manager_user_free(void* u)
+{
+ my_free((gptr)u,MYF(0));
+}
+
+static void init_user_hash()
+{
+ FILE* f;
+ char buf[80];
+ int line_num=1;
+ if (hash_init(&user_hash,1024,0,0,get_user_key,manager_user_free,MYF(0)))
+ die("Could not initialize user hash");
+ if (!(f=fopen(manager_pw_file,"r")))
+ die("Could not open password file '%s'", manager_pw_file);
+ for (;;line_num++)
+ {
+ struct manager_user* u;
+ if (!fgets(buf,sizeof(buf),f) || feof(f))
+ break;
+ if (buf[0] == '#')
+ continue;
+ if (!(u=manager_user_new(buf)))
+ die("Out of memory while reading user line");
+ if (u->error)
+ {
+ die("Error on line %d of '%s': %s",line_num,manager_pw_file, u->error);
+ }
+ else
+ {
+ hash_insert(&user_hash,(gptr)u);
+ }
+ }
+ fclose(f);
+}
+
+static void init_pid_file()
+{
+ FILE* fp = fopen(pid_file, "w");
+ if (!fp)
+ die("Could not open pid file %s", pid_file);
+ created_pid_file=1;
+ fprintf(fp, "%d\n", (int) getpid());
+ fclose(fp);
+}
+
+static void init_globals()
+{
+ pthread_attr_t thr_attr;
+ if (hash_init(&exec_hash,1024,0,0,get_exec_key,manager_exec_free,MYF(0)))
+ die("Exec hash initialization failed");
+ if (!one_thread)
+ {
+ (void) pthread_attr_init(&thr_attr);
+#if !defined(HAVE_DEC_3_2_THREADS)
+ pthread_attr_setscope(&thr_attr,PTHREAD_SCOPE_SYSTEM);
+ (void) pthread_attr_setdetachstate(&thr_attr,PTHREAD_CREATE_DETACHED);
+#endif
+ fork_launcher();
+ if (pthread_create(&launch_msg_th,&thr_attr,process_launcher_messages,0))
+ die("Could not start launcher message handler thread");
+ /* (void) pthread_attr_destroy(&thr_attr); */
+ }
+ init_user_hash();
+ init_pid_file();
+ loop_th=pthread_self();
+ signal(SIGPIPE,handle_sigpipe);
+ signal(SIGTERM,handle_sigterm);
+}
+
+static int open_and_dup(int fd,char* path)
+{
+ int old_fd;
+ if ((old_fd=my_open(path,O_WRONLY|O_APPEND|O_CREAT,MYF(0)))<0)
+ {
+ log_err("Could not open '%s' for append, errno=%d",path,errno);
+ return 1;
+ }
+ if (dup2(old_fd,fd)<0)
+ {
+ log_err("Failed in dup2(), errno=%d",errno);
+ return 1;
+ }
+ my_close(old_fd,MYF(0));
+ return 0;
+}
+
+static void run_launcher_loop()
+{
+ for (;;)
+ {
+ int req_len,ident_len,num_args;
+ char* request_buf=0;
+ pid_t pid;
+ char* exec_path,*ident,*stdout_path,*stderr_path;
+ char** args=0;
+
+ if (my_read(to_launcher_pipe[0],(byte*)&req_len,
+ sizeof(int),MYF(MY_NABP|MY_FULL_IO)) ||
+ my_read(to_launcher_pipe[0],(byte*)&num_args,
+ sizeof(int),MYF(MY_NABP|MY_FULL_IO)) ||
+ !(request_buf=(char*)my_malloc(req_len+sizeof(pid)+2,MYF(0))) ||
+ !(args=(char**)my_malloc(num_args*sizeof(char*),MYF(0))) ||
+ my_read(to_launcher_pipe[0],request_buf,req_len,
+ MYF(MY_NABP|MY_FULL_IO)))
+ {
+ log_err("launcher: Error reading request");
+ my_free((gptr)request_buf,MYF(MY_ALLOW_ZERO_PTR));
+ my_free((gptr)args,MYF(MY_ALLOW_ZERO_PTR));
+ sleep(1);
+ continue;
+ }
+ stdout_path=request_buf;
+ stderr_path=stdout_path+strlen(stdout_path)+1;
+ request_buf=stderr_path+strlen(stderr_path); /* black magic */
+ ident=request_buf+1;
+ ident_len=strlen(ident);
+ exec_path=ident+ident_len+1;
+ log_debug("num_args=%d,req_len=%d,ident=%s,ident_len=%d,exec_path=%s,\
+stdout_path=%s,stderr_path=%s",
+ num_args,
+ req_len,ident,ident_len,exec_path,stdout_path,stderr_path);
+ init_arg_array(exec_path,args,num_args-1);
+
+ switch ((pid=fork()))
+ {
+ case -1:
+ log_err("launcher: cannot fork");
+ sleep(1);
+ break;
+ case 0:
+ if (open_and_dup(1,stdout_path) || open_and_dup(2,stderr_path))
+ exit(1);
+ if (execv(exec_path,args))
+ log_err("launcher: cannot exec %s",exec_path);
+ exit(1);
+ default:
+ request_buf[0]=CHILD_START;
+ memcpy(request_buf+ident_len+2,&pid,sizeof(pid));
+ if (write(from_launcher_pipe[1],request_buf,ident_len+2+sizeof(pid))<0)
+ log_err("launcher: error sending launch status report");
+ break;
+ }
+ my_free((gptr)(stdout_path),MYF(0));
+ my_free((gptr)args,MYF(0));
+ }
+}
+
+static void fork_launcher()
+{
+ if (pipe(to_launcher_pipe) || pipe(from_launcher_pipe))
+ die("Could not create launcher pipes");
+ switch ((launcher_pid=fork()))
+ {
+ case 0:
+ signal(SIGCHLD,handle_child);
+ run_launcher_loop();
+ exit(0);
+ case -1: die("Could not fork the launcher");
+ default: return;
+ }
+}
+
+static int daemonize()
+{
+ switch (fork())
+ {
+ case -1:
+ die("Cannot fork");
+ case 0:
+ errfp = open_log_stream();
+ init_globals();
+ close(0);
+ close(1);
+ close(2);
+ init_server();
+ run_server_loop();
+ clean_up();
+ break;
+ default:
+ break;
+ }
+ return 0;
+}
+
+int main(int argc, char** argv)
+{
+ char c;
+ stack_bottom= (uchar *) &c;
+ MY_INIT(argv[0]);
+ errfp = stderr;
+ parse_args(argc,argv);
+ pthread_mutex_init(&lock_log,0);
+ pthread_mutex_init(&lock_shutdown,0);
+ pthread_mutex_init(&lock_exec_hash,0);
+ pthread_mutex_init(&lock_launch_thd,0);
+ pthread_cond_init(&cond_launch_thd,0);
+#ifdef DO_STACKTRACE
+ signal(SIGSEGV,handle_segfault);
+#endif
+ if (one_thread)
+ {
+ init_globals();
+ init_server();
+ run_server_loop();
+ clean_up();
+ return 0;
+ }
+ else
+ return daemonize();
+}
diff --git a/vio/Makefile.am b/vio/Makefile.am
index 9bb8691eee6..7119c278862 100644
--- a/vio/Makefile.am
+++ b/vio/Makefile.am
@@ -14,20 +14,21 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-INCLUDES = -I$(srcdir)/../include -I../include \
- @OPENSSL_INCLUDES@
-LDADD = libvio.la
-pkglib_LTLIBRARIES = libvio.la
-noinst_PROGRAMS =
+INCLUDES = -I$(srcdir)/../include -I../include $(openssl_includes)
+LDADD = libvio.a $(openssl_libs)
+pkglib_LIBRARIES = libvio.a
+noinst_PROGRAMS = test-ssl test-sslserver test-sslclient
noinst_HEADERS =
-libvio_la_SOURCES = \
- Vio.cc VioAcceptorFd.cc \
- VioConnectorFd.cc VioFd.cc \
- VioHandle.cc VioSSL.cc \
- VioSSLFactoriesFd.cc VioSocket.cc \
- auto.cc hostnamexx.cc \
- vdbug.cc version.cc \
- vmem.cc violitexx.cc
+test_ssl_SOURCES = test-ssl.c
+test_ssl_LDADD = ../dbug/libdbug.a libvio.a ../mysys/libmysys.a \
+ ../strings/libmystrings.a libvio.a $(openssl_libs)
+test_sslserver_SOURCES = test-sslserver.c
+test_sslserver_LDADD = ../dbug/libdbug.a libvio.a ../mysys/libmysys.a \
+ ../strings/libmystrings.a libvio.a $(openssl_libs)
+test_sslclient_SOURCES = test-sslclient.c
+test_sslclient_LDADD = ../dbug/libdbug.a libvio.a ../mysys/libmysys.a \
+ ../strings/libmystrings.a libvio.a $(openssl_libs)
+libvio_a_SOURCES = vio.c viosocket.c viossl.c viosslfactories.c
OMIT_DEPENDENCIES = pthread.h stdio.h __stdio.h stdlib.h __stdlib.h math.h\
__math.h time.h __time.h unistd.h __unistd.h types.h \
diff --git a/vio/Vio.cc b/vio/Vio.cc
deleted file mode 100644
index b15f9cfa6d2..00000000000
--- a/vio/Vio.cc
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
-** Virtual I/O library
-** Written by Andrei Errapart <andreie@no.spam.ee>
-*/
-
-#ifdef __GNUC__
-#pragma implementation // gcc: Class implementation
-#endif
-#include "vio-global.h"
-
-VIO_NS_BEGIN
-
-void
-Vio::release()
-{
- delete this;
-}
-
-Vio::~Vio()
-{
-}
-
-VIO_NS_END
diff --git a/vio/Vio.h b/vio/Vio.h
deleted file mode 100644
index 959d472873f..00000000000
--- a/vio/Vio.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Abstract Virtual IO interface - class Vio. Heavily
- * influenced by Berkeley sockets and oriented toward MySQL.
- */
-
-/*
-** Virtual I/O library
-** Written by Andrei Errapart <andreie@no.spam.ee>
-** Modified by Monty
-*/
-
-#ifdef __GNUC__
-#pragma interface /* gcc class implementation */
-#endif
-
-VIO_NS_BEGIN
-
-enum enum_vio_type { VIO_CLOSED, VIO_TYPE_TCPIP, VIO_TYPE_SOCKET,
- VIO_TYPE_NAMEDPIPE, VIO_TYPE_SSL};
-
-class Vio {
-public:
- virtual bool is_open() const = 0;
- virtual int read(vio_ptr buf, int size) = 0;
- virtual int write(const vio_ptr buf, int size) = 0;
- virtual int blocking(bool onoff) = 0;
- virtual bool blocking() const = 0;
- virtual bool fcntl() const = 0;
- virtual int fastsend(bool onoff = true) = 0;
- virtual int keepalive(bool onoff) = 0;
- virtual bool should_retry() const = 0;
- virtual int close() = 0;
- virtual void release();
- virtual const char* description() const = 0;
- virtual bool peer_addr(char *buf) const = 0;
- virtual const char* cipher_description() const = 0;
- virtual int vio_errno();
- virtual ~Vio();
-};
-
-/* Macros to simulate the violite C interface */
-
-
-Vio *vio_new(my_socket sd, enum enum_vio_type type,
- my_bool localhost);
-#ifdef __WIN__
-Vio* vio_new_win32pipe(HANDLE hPipe);
-#endif
-
-#define vio_delete(vio) delete vio
-#define vio_read(vio,buf,size) vio->read(buf,size)
-#define vio_write(vio,buf,size) vio->write(buf,size)
-#define vio_blocking(vio,mode) vio->blocking(mode)
-#define vio_is_blocking(vio) vio->is_blocking()
-#define vio_fastsend(vio,mode) vio->fastsend(mode)
-#define vio_keepalive(vio,mode) vio->keepalive(mode)
-#define vio_shouldretry(vio) vio->shouldretry(mode)
-#define vio_close(vio) vio->close()
-#define vio_description(vio) vio->description()
-#define vio_errno(Vio *vio) vio->errno()
-#define vio_peer_addr(vio,buf) vio->peer_addr(buf)
-#define vio_in_addr(vio,in) vio->in_addr(in)
-
-VIO_NS_END
diff --git a/vio/VioAcceptorFd.cc b/vio/VioAcceptorFd.cc
deleted file mode 100644
index 4572e2cb71b..00000000000
--- a/vio/VioAcceptorFd.cc
+++ /dev/null
@@ -1,18 +0,0 @@
-
-/*
-** Virtual I/O library
-** Written by Andrei Errapart <andreie@no.spam.ee>
-*/
-
-#include "vio-global.h"
-#ifdef __GNUC__
-#pragma implementation // gcc: Class implementation
-#endif
-
-VIO_NS_BEGIN
-
-VioAcceptorFd::~VioAcceptorFd()
-{
-}
-
-VIO_NS_END
diff --git a/vio/VioAcceptorFd.h b/vio/VioAcceptorFd.h
deleted file mode 100644
index e0441780db9..00000000000
--- a/vio/VioAcceptorFd.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
-** Virtual I/O library
-** Written by Andrei Errapart <andreie@no.spam.ee>
-*/
-
-/*
- * Abstract acceptor.
- */
-
-#ifdef __GNUC__
-#pragma interface /* gcc class implementation */
-#endif
-
-VIO_NS_BEGIN
-
-class VioAcceptorFd
-{
-public:
- virtual ~VioAcceptorFd();
- virtual Vio* accept( int fd) = 0;
-};
-
-VIO_NS_END
diff --git a/vio/VioConnectorFd.cc b/vio/VioConnectorFd.cc
deleted file mode 100644
index 49f81077a84..00000000000
--- a/vio/VioConnectorFd.cc
+++ /dev/null
@@ -1,22 +0,0 @@
-
-/*
- * Unneccessary virtual destructor.
- */
-
-#include "vio-global.h"
-#include <unistd.h>
-#include <fcntl.h>
-#include <assert.h>
-
-#include "viotypes.h"
-#include "Vio.h"
-#include "VioConnectorFd.h"
-
-VIO_NS_BEGIN
-
-VioConnectorFd::~VioConnectorFd()
-{
-}
-
-VIO_NS_END
-
diff --git a/vio/VioConnectorFd.h b/vio/VioConnectorFd.h
deleted file mode 100644
index da684df5f1b..00000000000
--- a/vio/VioConnectorFd.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Abstract connector. The file (or socket) descriptor has to be
- * prepared.
- */
-
-#ifdef __GNUC__
-#pragma interface /* gcc class implementation */
-#endif
-
-VIO_NS_BEGIN
-
-class VioConnectorFd
-{
-public:
- virtual ~VioConnectorFd();
- virtual Vio* connect(int fd) = 0;
-};
-
-VIO_NS_END
diff --git a/vio/VioFd.cc b/vio/VioFd.cc
deleted file mode 100644
index da59798fc25..00000000000
--- a/vio/VioFd.cc
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
-** Virtual I/O library for files
-** Written by Andrei Errapart <andreie@no.spam.ee>
-** Checked and modfied by Monty
-*/
-
-#include "vio-global.h"
-#include <assert.h>
-
-#ifdef __GNUC__
-#pragma implementation // gcc: Class implementation
-#endif
-
-VIO_NS_BEGIN
-
-VioFd::VioFd( int fd) : fd_(fd)
-{
- sprintf(desc_, "VioFd(%d)", fd_);
-}
-
-VioFd:: ~VioFd()
-{
- if (fd_ >= 0)
- {
- it r = ::close(fd_);
- if ( r < 0)
- {
- /* FIXME: error handling (Not Critical for MySQL) */
- }
- }
-}
-
-
-bool
-VioFd::open() const
-{
- return fd_ >= 0;
-}
-
-int
-VioFd::read(vio_ptr buf, int size)
-{
- assert(fd_>=0);
- return ::read(fd_, buf, size);
-}
-
-int
-VioFd::write(const vio_ptr buf, int size)
-{
- assert(fd_>=0);
- return ::write(fd_, buf, size);
-}
-
-int
-VioFd::blocking(bool onoff)
-{
- if (onoff)
- return 0;
- else
- return -1;
-}
-
-bool
-VioFd::blocking() const
-{
- return true;
-}
-
-int
-VioFd::fastsend(bool tmp)
-{
- return 0;
-}
-
-
-int
-VioFd::keepalive(boolonoff)
-{
- return -2; // Why -2 ? (monty)
-}
-
-bool
-VioFd::fcntl() const
-{
- return FALSE;
-}
-
-bool
-VioFd::should_retry() const
-{
- return FALSE;
-}
-
-int
-VioFd::fcntl(int cmd)
-{
- assert(fd_>=0);
- return ::fcntl(fd_, cmd);
-}
-
-int
-VioFd::fcntl(int cmd, long arg)
-{
- assert(fd_>=0);
- return ::fcntl(fd_, cmd, arg);
-}
-
-int
-VioFd::fcntl(int cmd, struct flock* lock)
-{
- assert(fd_>=0);
- return ::fcntl(fd_, cmd, lock);
-}
-
-int
-VioFd::close()
-{
- int r = -2;
- if (fd_>=0)
- {
-
- if ((r= ::close(fd_)) == 0)
- fd_ = -1;
- }
- else
- {
- /* FIXME: error handling */
- }
- return r;
-}
-
-const char*
-VioFd::description() const
-{
- return desc_;
-}
-
-const char*
-VioFd::peer_addr() const
-{
- return "";
-}
-
-const char*
-VioFd::peer_name() const
-{
- return "localhost";
-}
-
-const char*
-VioFd::cipher_description() const
-{
- return "";
-}
-
-VIO_NS_END
diff --git a/vio/VioFd.h b/vio/VioFd.h
deleted file mode 100644
index f1c009d848c..00000000000
--- a/vio/VioFd.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Concrete Vio around a file descriptor.
- */
-
-#ifdef __GNUC__
-#pragma interface /* gcc class implementation */
-#endif
-
-VIO_NS_BEGIN
-
-class VioFd : public Vio
-{
-public:
- VioFd( int fd);
- virtual ~VioFd();
- virtual bool open() const;
- virtual int read( vio_ptr buf, int size);
- virtual int write( const vio_ptr buf, int size);
- virtual bool blocking() const;
- virtual int blocking(bool onoff);
- virtual int fastsend(bool onoff=true);
- virtual int keepalive( bool onoff);
- virtual bool fcntl() const;
- virtual bool should_retry() const;
- virtual int fcntl( int cmd);
- virtual int fcntl( int cmd, long arg);
- virtual int fcntl( int cmd, struct flock* lock);
- virtual int close();
- virtual const char* description() const;
- virtual const char* peer_addr() const;
- virtual bool peer_name(char *buf) const;
- virtual const char* cipher_description() const;
-private:
- int fd_;
- char desc_[100];
-};
-
-VIO_NS_END
diff --git a/vio/VioPipe.cc b/vio/VioPipe.cc
deleted file mode 100644
index 5d6f9f36496..00000000000
--- a/vio/VioPipe.cc
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
-** Virtual I/O library for Windows named pipes
-** Written by Monty
-*/
-
-
-#ifdef __WIN32__
-#include "vio-global.h"
-
-#ifdef __GNUC__
-#pragma implementation // gcc: Class implementation
-#endif
-
-VIO_NS_BEGIN
-
-
-
-
-
-
-
-
-VIO_NS_END
-
-#endif /* WIN32 */
diff --git a/vio/VioPipe.h b/vio/VioPipe.h
deleted file mode 100644
index a6bb587c548..00000000000
--- a/vio/VioPipe.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Concrete Vio around Handle.
- */
-
-#ifdef __WIN__
-
-#ifdef __GNUC__
-#pragma interface /* gcc class implementation */
-#endif
-
-VIO_NS_BEGIN
-
-class VioPipe : public Vio
-{
-public:
- VioPipe(int fd);
- virtual ~VioPipe();
- virtual bool is_open() const;
- virtual int read(vio_ptr buf, int size);
- virtual int write(const vio_ptr buf, int size);
- virtual int blocking(bool onoff);
- virtual bool blocking() const;
- virtual bool fcntl() const;
- virtual int fastsend(bool onoff = true);
- virtual int keepalive(bool onoff);
- virtual bool should_retry() const;
- virtual int close();
- virtual void release();
- virtual const char* description() const;
- virtual bool peer_addr(char *buf) const;
- virtual const char* cipher_description() const { return "";}
- virtual int vio_errno();
-private:
-};
-
-VIO_NS_END
-
-#endif /* WIN32 */
diff --git a/vio/VioSSL.cc b/vio/VioSSL.cc
deleted file mode 100644
index 15964c09aba..00000000000
--- a/vio/VioSSL.cc
+++ /dev/null
@@ -1,292 +0,0 @@
-/*
-** Virtual I/O library for SSL wrapper
-** Written by Andrei Errapart <andreie@no.spam.ee>
-*/
-
-/*
- * This file has some huge DBUG_ statements. Boy, this is silly...
- */
-
-#include "vio-global.h"
-#ifdef VIO_HAVE_OPENSSL
-#include <assert.h>
-#include <netinet/in.h>
-#include <openssl/x509.h>
-#include <openssl/ssl.h>
-#include <openssl/err.h>
-#include <openssl/pem.h>
-
-#ifdef __GNUC__
-#pragma implementation // gcc: Class implementation
-#endif
-
-VIO_NS_BEGIN
-
-#define this_ssl_con my_static_cast(SSL*)(this->ssl_con_)
-#define this_bio my_static_cast(BIO*)(this->bio_)
-typedef char* dataptr_t;
-
-static void
-report_errors()
-{
- unsigned long l;
- const char* file;
- const char* data;
- int line,flags;
- DBUG_ENTER("VioSSLConnectorFd::report_errors");
-
- while ((l=ERR_get_error_line_data(&file,&line,&data,&flags)) != 0)
- {
- char buf[200];
- DBUG_PRINT("error", ("OpenSSL: %s:%s:%d:%s\n", ERR_error_string(l,buf),
- file,line,(flags&ERR_TXT_STRING)?data:"")) ;
- }
- DBUG_VOID_RETURN;
-}
-
-//FIXME: duplicate code!
-VioSSL::VioSSL(int fd,
- vio_ptr ssl_context,
- int state)
- : bio_(0), ssl_con_(0), open_(FALSE), sd_(new VioSocket(fd))
-{
- DBUG_ENTER("VioSSL::VioSSL");
- DBUG_PRINT("enter", ("this=%p, fd=%d, ssl_context=%p, state=%d",
- this, fd, ssl_context, state));
- assert(fd!=0);
- assert(ssl_context!=0);
- assert(state==state_connect || state==state_accept);
-
- if (!init_bio_(fd, ssl_context, state, BIO_NOCLOSE))
- open_ = true;
- DBUG_VOID_RETURN;
-}
-
-
-VioSSL::VioSSL(VioSocket* sd,
- vio_ptr ssl_context,
- int state)
- :bio_(0), ssl_con_(0), open_(FALSE), sd_(sd)
-{
- DBUG_ENTER("VioSSL::VioSSL");
- DBUG_PRINT("enter",
- ("this=%p, sd=%s, ssl_context=%p, state=%d",
- this, sd ? sd->description() : "0", ssl_context, state));
- assert(sd != 0);
- assert(ssl_context != 0);
- assert(state == state_connect || state==state_accept);
-
- if (!init_bio_(sd->sd_, ssl_context, state, BIO_NOCLOSE))
- open_ = true;
- DBUG_VOID_RETURN;
-}
-
-VioSSL::~VioSSL()
-{
- DBUG_ENTER("VioSSL::~VioSSL");
- DBUG_PRINT("enter", ("this=%p", this));
- if (ssl_con_!=0)
- {
- SSL_shutdown(this_ssl_con);
- SSL_free(this_ssl_con);
- }
- if (sd_!=0)
- delete sd_;
- /* FIXME: no need to close bio? */
- /*
- if (bio_!=0)
- BIO_free(this_bio);
- */
- DBUG_VOID_RETURN;
-}
-
-bool
-VioSSL::is_open() const
-{
- return open_;
-}
-
-int
-VioSSL::read(vio_ptr buf, int size)
-{
- int r;
- DBUG_ENTER("VioSSL::read");
- DBUG_PRINT("enter", ("this=%p, buf=%p, size=%d", this, buf, size));
- assert(this_ssl_con != 0);
- r = SSL_read(this_ssl_con, my_static_cast(dataptr_t)(buf), size);
- if ( r< 0)
- report_errors();
- DBUG_PRINT("exit", ("r=%d", r));
- DBUG_RETURN(r);
-}
-
-int
-VioSSL::write(const vio_ptr buf, int size)
-{
- int r;
- DBUG_ENTER("VioSSL::write");
- DBUG_PRINT("enter", ("this=%p, buf=%p, size=%d", this, buf, size));
- assert(this_ssl_con!=0);
- r = SSL_write(this_ssl_con, my_static_cast(dataptr_t)(buf), size);
- if (r<0)
- report_errors();
- DBUG_PRINT("exit", ("r=%d", r));
- DBUG_RETURN(r);
-}
-
-int
-VioSSL::blocking(bool onoff)
-{
- int r;
- DBUG_ENTER("VioSSL::blocking");
- DBUG_PRINT("enter", ("this=%p, onoff=%s", this, onoff?"true":"false"));
- r = sd_->blocking(onoff);
- DBUG_PRINT("exit", ("r=%d", (int)r ));
- DBUG_RETURN(r);
-}
-
-bool
-VioSSL::blocking() const
-{
- bool r;
- DBUG_ENTER("VioSSL::blocking");
- DBUG_PRINT("enter", ("this=%p", this));
- r = sd_->blocking();
- DBUG_PRINT("exit", ("r=%d", (int)r ));
- DBUG_RETURN(r);
-}
-
-int
-VioSSL::fastsend(bool onoff)
-{
- int r;
- DBUG_ENTER("VioSSL::fastsend");
- DBUG_PRINT("enter", ("this=%p, onoff=%d", this, (int) onoff));
- r = sd_->fastsend(onoff);
- DBUG_PRINT("exit", ("r=%d", (int)r ));
- DBUG_RETURN(r);
-}
-
-int VioSSL::keepalive(bool onoff)
-{
- int r;
- DBUG_ENTER("VioSSL::keepalive");
- DBUG_PRINT("enter", ("this=%p, onoff=%d", this, (int) onoff));
- r = sd_->keepalive(onoff);
- DBUG_PRINT("exit", ("r=%d", int(r) ));
- DBUG_RETURN(r);
-}
-
-bool
-VioSSL::fcntl() const
-{
- bool r;
- DBUG_ENTER("VioSSL::fcntl");
- DBUG_PRINT("enter", ("this=%p", this));
- r = sd_->fcntl();
- DBUG_PRINT("exit", ("r=%d", (int)r ));
- DBUG_RETURN(r);
-}
-
-bool
-VioSSL::should_retry() const
-{
- bool r;
- DBUG_ENTER("VioSSL::should_retry");
- DBUG_PRINT("enter", ("this=%p", this));
- r = sd_->should_retry();
- DBUG_PRINT("exit", ("r=%d", (int)r ));
- DBUG_RETURN(r);
-}
-
-int
-VioSSL::close()
-{
- int r= -2;
- DBUG_ENTER("VioSSL::close");
- DBUG_PRINT("enter", ("this=%p", this));
- if (ssl_con)
- {
- r = SSL_shutdown(this_ssl_con);
- SSL_free(this_ssl_con);
- ssl_con_ = 0;
- BIO_free(this_bio);
- bio_ = 0;
- }
- DBUG_PRINT("exit", ("r=%d", r));
- DBUG_RETURN(r);
-}
-
-const char*
-VioSSL::description() const
-{
- return desc_;
-}
-
-const char*
-VioSSL::peer_addr() const
-{
- if (sd_!=0)
- return sd != 0 ? sd_->peer_addr() : "";
-}
-
-const char*
-VioSSL::peer_name() const
-{
- return sd != 0 ? sd_->peer_name() : "";
-}
-
-const char*
-VioSSL::cipher_description() const
-{
- return SSL_get_cipher_name(this_ssl_con);
-}
-
-
-int
-VioSSL::init_bio_(int fd,
- vio_ptr ssl_context,
- int state,
- int bio_flags)
-{
- DBUG_ENTER("VioSSL::init_bio_");
- DBUG_PRINT("enter",
- ("this=%p, fd=%p, ssl_context=%p, state=%d, bio_flags=%d",
- this, fd, ssl_context, state, bio_flags));
-
-
- if (!(ssl_con_ = SSL_new(my_static_cast(SSL_CTX*)(ssl_context))))
- {
- DBUG_PRINT("error", ("SSL_new failure"));
- report_errors();
- DBUG_RETURN(-1);
- }
- if (!(bio_ = BIO_new_socket(fd, bio_flags)))
- {
- DBUG_PRINT("error", ("BIO_new_socket failure"));
- report_errors();
- SSL_free(ssl_con_);
- ssl_con_ =0;
- DBUG_RETURN(-1);
- }
- SSL_set_bio(this_ssl_con, this_bio, this_bio);
- switch(state) {
- case state_connect:
- SSL_set_connect_state(this_ssl_con);
- break;
- case state_accept:
- SSL_set_accept_state(this_ssl_con);
- break;
- default:
- assert(0);
- }
- sprintf(desc_, "VioSSL(%d)", fd);
- ssl_cip_ = new SSL_CIPHER ;
- DBUG_RETURN(0);
-}
-
-
-VIO_NS_END
-
-#endif /* VIO_HAVE_OPENSSL */
-
diff --git a/vio/VioSSL.h b/vio/VioSSL.h
deleted file mode 100644
index 6446c10700e..00000000000
--- a/vio/VioSSL.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Concrete Vio around OpenSSL's SSL structure.
- */
-
-#ifdef __GNUC__
-#pragma interface /* gcc class implementation */
-#endif
-
-VIO_NS_BEGIN
-
-class VioSocket;
-
-class VioSSL : public Vio
-{
-public:
- enum {
- state_connect = 1,
- state_accept = 2
- };
-public:
- VioSSL(int fd, vio_ptr ssl_context, int state);
- VioSSL(VioSocket* sd, vio_ptr ssl_context, int state);
- virtual ~VioSSL();
- virtual bool open() const;
- virtual int read( vio_ptr buf, int size);
- virtual int write( const vio_ptr buf, int size);
- virtual bool blocking() const;
- virtual int blocking(bool onoff);
- virtual int fastsend(bool onoff=true);
- virtual int keepalive(bool onoff);
- virtual bool fcntl() const;
- virtual bool should_retry() const;
- virtual int close();
- virtual const char* description() const;
- virtual const char* peer_addr() const;
- virtual const char* peer_name() const;
- virtual const char* cipher_description() const;
-
-private:
- int init_bio_(int fd,
- vio_ptr ssl_context,
- int state,
- int bio_flags);
- vio_ptr bio_;
- vio_ptr ssl_con_;
- vio_ptr ssl_cip_;
- char desc_[100];
- bool open_;
- VioSocket* sd_;
-};
-
-VIO_NS_END
-
-#endif /* VIO_HAVE_OPENSSL */
diff --git a/vio/VioSSLAcceptorFd.cc b/vio/VioSSLAcceptorFd.cc
deleted file mode 100644
index f821685430e..00000000000
--- a/vio/VioSSLAcceptorFd.cc
+++ /dev/null
@@ -1,4 +0,0 @@
-
-#ifdef __GNUC__
-#pragma interface /* gcc class implementation */
-#endif
diff --git a/vio/VioSSLFactoriesFd.cc b/vio/VioSSLFactoriesFd.cc
deleted file mode 100644
index bd64202770a..00000000000
--- a/vio/VioSSLFactoriesFd.cc
+++ /dev/null
@@ -1,360 +0,0 @@
-/*
-** Virtual I/O library
-** Written by Andrei Errapart <andreie@no.spam.ee>
-*/
-
-#include "vio-global.h"
-
-#ifdef VIO_HAVE_OPENSSL
-
-#ifdef __GNUC__
-#pragma implementation // gcc: Class implementation
-#endif
-
-#include <netinet/in.h>
-#include <openssl/x509.h>
-#include <openssl/ssl.h>
-#include <openssl/err.h>
-#include <openssl/pem.h>
-#include <openssl/asn1.h>
-
-VIO_NS_BEGIN
-
-#define this_ssl_method my_static_cast(SSL_METHOD*)(this->ssl_method_)
-#define this_ssl_context my_static_cast(SSL_CTX*)(this->ssl_context_)
-typedef unsigned char* ssl_data_ptr_t;
-
-static bool ssl_algorithms_added = FALSE;
-static bool ssl_error_strings_loaded= FALSE;
-static int verify_depth = 0;
-static int verify_error = X509_V_OK;
-
-static int
-vio_verify_callback(int ok, X509_STORE_CTX *ctx)
-{
- DBUG_ENTER("vio_verify_callback");
- DBUG_PRINT("enter", ("ok=%d, ctx=%p", ok, ctx));
- char buf[256];
- X509* err_cert;
- int err,depth;
-
- err_cert=X509_STORE_CTX_get_current_cert(ctx);
- err= X509_STORE_CTX_get_error(ctx);
- depth= X509_STORE_CTX_get_error_depth(ctx);
-
- X509_NAME_oneline(X509_get_subject_name(err_cert),buf,sizeof(buff));
- if (!ok)
- {
- DBUG_PRINT("error",("verify error:num=%d:%s\n",err,
- X509_verify_cert_error_string(err)));
- if (verify_depth >= depth)
- {
- ok=1;
- verify_error=X509_V_OK;
- }
- else
- {
- ok=0;
- verify_error=X509_V_ERR_CERT_CHAIN_TOO_LONG;
- }
- }
- switch (ctx->error) {
- case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
- X509_NAME_oneline(X509_get_issuer_name(ctx->current_cert),buf,256);
- DBUG_PRINT("info",("issuer= %s\n",buf));
- break;
- case X509_V_ERR_CERT_NOT_YET_VALID:
- case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
- DBUG_PRINT("error", ("notBefore"));
- //ASN1_TIME_print_fp(stderr,X509_get_notBefore(ctx->current_cert));
- break;
- case X509_V_ERR_CERT_HAS_EXPIRED:
- case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
- DBUG_PRINT("error", ("notAfter error"));
- //ASN1_TIME_print_fp(stderr,X509_get_notAfter(ctx->current_cert));
- break;
- }
- DBUG_PRINT("exit", ("r=%d", ok));
- DBUG_RETURN(ok);
-}
-
-
-static int
-vio_set_cert_stuff(SSL_CTX *ctx, const char *cert_file, const char *key_file)
-{
- DBUG_ENTER("vio_set_cert_stuff");
- DBUG_PRINT("enter", ("ctx=%p, cert_file=%p, key_file=%p",
- ctx, cert_file, key_file));
- if (cert_file != NULL)
- {
- if (SSL_CTX_use_certificate_file(ctx,cert_file,SSL_FILETYPE_PEM) <= 0)
- {
- DBUG_PRINT("error",("unable to get certificate from '%s'\n",cert_file));
- /* FIX stderr */
- ERR_print_errors_fp(stderr);
- DBUG_RETURN(0);
- }
- if (key_file == NULL)
- key_file = cert_file;
- if (SSL_CTX_use_PrivateKey_file(ctx,key_file,
- SSL_FILETYPE_PEM) <= 0)
- {
- DBUG_PRINT("error", ("unable to get private key from '%s'\n",key_file));
- /* FIX stderr */
- ERR_print_errors_fp(stderr);
- DBUG_RETURN(0);
- }
-
- /* If we are using DSA, we can copy the parameters from
- * the private key */
- /* Now we know that a key and cert have been set against
- * the SSL context */
- if (!SSL_CTX_check_private_key(ctx))
- {
- DBUG_PRINT("error", ("Private key does not match the certificate public key\n"));
- DBUG_RETURN(0);
- }
- }
- DBUG_RETURN(1);
-}
-
-/************************ VioSSLConnectorFd **********************************/
-VioSSLConnectorFd::VioSSLConnectorFd(const char* key_file,
- const char* cert_file,
- const char* ca_file,
- const char* ca_path)
-:ssl_context_(0),ssl_method_(0)
-{
- DBUG_ENTER("VioSSLConnectorFd::VioSSLConnectorFd");
- DBUG_PRINT("enter",
- ("this=%p, key_file=%s, cert_file=%s, ca_path=%s, ca_file=%s",
- this, key_file, cert_file, ca_path, ca_file));
-
- /* FIXME: constants! */
- int verify = SSL_VERIFY_PEER;
-
- if (!ssl_algorithms_added)
- {
- DBUG_PRINT("info", ("todo: SSLeay_add_ssl_algorithms()"));
- ssl_algorithms_added = true;
- SSLeay_add_ssl_algorithms();
- }
- if (!ssl_error_strings_loaded)
- {
- DBUG_PRINT("info", ("todo:SSL_load_error_strings()"));
- ssl_error_strings_loaded = true;
- SSL_load_error_strings();
- }
- ssl_method_ = SSLv3_client_method();
- ssl_context_ = SSL_CTX_new(this_ssl_method);
- if (ssl_context_ == 0)
- {
- DBUG_PRINT("error", ("SSL_CTX_new failed"));
- report_errors();
- goto ctor_failure;
- }
- /*
- * SSL_CTX_set_options
- * SSL_CTX_set_info_callback
- * SSL_CTX_set_cipher_list
- */
- SSL_CTX_set_verify(this_ssl_context, verify, vio_verify_callback);
- if (vio_set_cert_stuff(this_ssl_context, cert_file, key_file) == -1)
- {
- DBUG_PRINT("error", ("vio_set_cert_stuff failed"));
- report_errors();
- goto ctor_failure;
- }
- if (SSL_CTX_load_verify_locations( this_ssl_context, ca_file,ca_path)==0)
- {
- DBUG_PRINT("warning", ("SSL_CTX_load_verify_locations failed"));
- if (SSL_CTX_set_default_verify_paths(this_ssl_context)==0)
- {
- DBUG_PRINT("error", ("SSL_CTX_set_default_verify_paths failed"));
- report_errors();
- goto ctor_failure;
- }
- }
- DBUG_VOID_RETURN;
-ctor_failure:
- DBUG_PRINT("exit", ("there was an error"));
- DBUG_VOID_RETURN;
-}
-
-VioSSLConnectorFd::~VioSSLConnectorFd()
-{
- DBUG_ENTER("VioSSLConnectorFd::~VioSSLConnectorFd");
- DBUG_PRINT("enter", ("this=%p", this));
- if (ssl_context_!=0)
- SSL_CTX_free(this_ssl_context);
- DBUG_VOID_RETURN;
-}
-
-VioSSL* VioSSLConnectorFd::connect( int fd)
-{
- DBUG_ENTER("VioSSLConnectorFd::connect");
- DBUG_PRINT("enter", ("this=%p, fd=%d", this, fd));
- DBUG_RETURN(new VioSSL(fd, ssl_context_, VioSSL::state_connect));
-}
-
-VioSSL*
-VioSSLConnectorFd::connect( VioSocket* sd)
-{
- DBUG_ENTER("VioSSLConnectorFd::connect");
- DBUG_PRINT("enter", ("this=%p, sd=%s", this, sd->description()));
- DBUG_RETURN(new VioSSL(sd, ssl_context_, VioSSL::state_connect));
-}
-
-void
-VioSSLConnectorFd::report_errors()
-{
- unsigned long l;
- const char* file;
- const char* data;
- int line,flags;
-
- DBUG_ENTER("VioSSLConnectorFd::report_errors");
- DBUG_PRINT("enter", ("this=%p", this));
-
- while ((l=ERR_get_error_line_data(&file,&line,&data,&flags)) != 0)
- {
- char buf[200];
- DBUG_PRINT("error", ("OpenSSL: %s:%s:%d:%s\n", ERR_error_string(l,buf),
- file,line,(flags&ERR_TXT_STRING)?data:"")) ;
- }
- DBUG_VOID_RETURN;
-}
-
-/************************ VioSSLAcceptorFd **********************************/
-
-VioSSLAcceptorFd::VioSSLAcceptorFd(const char* key_file,
- const char* cert_file,
- const char* ca_file,
- const char* ca_path)
- :ssl_context_(0), ssl_method_(0)
-{
- DBUG_ENTER("VioSSLAcceptorFd::VioSSLAcceptorFd");
- DBUG_PRINT("enter",
- ("this=%p, key_file=%s, cert_file=%s, ca_path=%s, ca_file=%s",
- this, key_file, cert_file, ca_path, ca_file));
-
- /* FIXME: constants! */
- int verify = (SSL_VERIFY_PEER |
- SSL_VERIFY_FAIL_IF_NO_PEER_CERT |
- SSL_VERIFY_CLIENT_ONCE);
- session_id_context_ = static_cast<vio_ptr>(this);
-
- if (!ssl_algorithms_added)
- {
- DBUG_PRINT("info", ("todo: SSLeay_add_ssl_algorithms()"));
- ssl_algorithms_added = true;
- SSLeay_add_ssl_algorithms();
- }
- if (!ssl_error_strings_loaded)
- {
- DBUG_PRINT("info", ("todo: SSL_load_error_strings()"));
- ssl_error_strings_loaded = true;
- SSL_load_error_strings();
- }
- ssl_method_ = SSLv3_server_method();
- ssl_context_ = SSL_CTX_new(this_ssl_method);
- if (ssl_context_==0)
- {
- DBUG_PRINT("error", ("SSL_CTX_new failed"));
- report_errors();
- goto ctor_failure;
- }
- /*
- * SSL_CTX_set_quiet_shutdown(ctx,1);
- *
- */
- SSL_CTX_sess_set_cache_size(this_ssl_context,128);
-
- /* DH?
- */
- SSL_CTX_set_verify(this_ssl_context, verify, vio_verify_callback);
- /*
- * Double cast needed at least for egcs-1.1.2 to
- * supress warnings:
- * 1) ANSI C++ blaah implicit cast from 'void*' to 'unsigned char*'
- * 2) static_cast from 'void**' to 'unsigned char*'
- * Wish I had a copy of standard handy...
- */
- SSL_CTX_set_session_id_context(this_ssl_context,
- my_static_cast(ssl_data_ptr_t)
- (my_static_cast(void*)(&session_id_context_)),
- sizeof(session_id_context_));
-
- /*
- * SSL_CTX_set_client_CA_list(ctx,SSL_load_client_CA_file(CAfile));
- */
- if (vio_set_cert_stuff(this_ssl_context, cert_file, key_file) == -1)
- {
- DBUG_PRINT("error", ("vio_set_cert_stuff failed"));
- report_errors();
- goto ctor_failure;
- }
- if (SSL_CTX_load_verify_locations( this_ssl_context, ca_file, ca_path)==0)
- {
- DBUG_PRINT("warning", ("SSL_CTX_load_verify_locations failed"));
- if (SSL_CTX_set_default_verify_paths(this_ssl_context)==0)
- {
- DBUG_PRINT("error", ("SSL_CTX_set_default_verify_paths failed"));
- report_errors();
- goto ctor_failure;
- }
- }
- DBUG_VOID_RETURN;
-ctor_failure:
- DBUG_PRINT("exit", ("there was an error"));
- DBUG_VOID_RETURN;
-}
-
-VioSSLAcceptorFd::~VioSSLAcceptorFd()
-{
- DBUG_ENTER("VioSSLAcceptorFd::~VioSSLAcceptorFd");
- DBUG_PRINT("enter", ("this=%p", this));
- if (ssl_context_!=0)
- SSL_CTX_free(this_ssl_context);
- DBUG_VOID_RETURN;
-}
-
-VioSSL*
-VioSSLAcceptorFd::accept(int fd)
-{
- DBUG_ENTER("VioSSLAcceptorFd::accept");
- DBUG_PRINT("enter", ("this=%p, fd=%d", this, fd));
- DBUG_RETURN(new VioSSL(fd, ssl_context_, VioSSL::state_accept));
-}
-
-VioSSL*
-VioSSLAcceptorFd::accept(VioSocket* sd)
-{
- DBUG_ENTER("VioSSLAcceptorFd::accept");
- DBUG_PRINT("enter", ("this=%p, sd=%s", this, sd->description()));
- DBUG_RETURN(new VioSSL(sd, ssl_context_, VioSSL::state_accept));
-}
-
-void
-VioSSLAcceptorFd::report_errors()
-{
- unsigned long l;
- const char* file;
- const char* data;
- int line,flags;
-
- DBUG_ENTER("VioSSLConnectorFd::report_errors");
- DBUG_PRINT("enter", ("this=%p", this));
-
- while ((l=ERR_get_error_line_data(&file,&line,&data,&flags)) != 0)
- {
- char buf[200];
- DBUG_PRINT("error", ("OpenSSL: %s:%s:%d:%s\n", ERR_error_string(l,buf),
- file,line,(flags&ERR_TXT_STRING)?data:"")) ;
- }
- DBUG_VOID_RETURN;
-}
-
-VIO_NS_END
-
-#endif /* VIO_HAVE_OPENSSL */
diff --git a/vio/VioSSLFactoriesFd.h b/vio/VioSSLFactoriesFd.h
deleted file mode 100644
index ed5a24f6b4a..00000000000
--- a/vio/VioSSLFactoriesFd.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Wrapper around SSL_CTX.
- */
-
-#ifdef VIO_HAVE_OPENSSL
-
-#ifdef __GNUC__
-#pragma interface /* gcc class implementation */
-#endif
-
-VIO_NS_BEGIN
-
-class VioSSLAcceptorFd : public VioAcceptorFd
-{
-public:
- VioSSLAcceptorFd(const char* key_file,
- const char* cert_file,
- const char* ca_file,
- const char* ca_path);
-
- virtual ~VioSSLAcceptorFd();
- virtual VioSSL* accept(int fd);
- virtual VioSSL* accept(VioSocket* sd);
-private:
- VioSSLAcceptorFd(const VioSSLAcceptorFd& rhs);//undefined
- VioSSLAcceptorFd& operator=(const VioSSLAcceptorFd& rhs);//undefined
-private:
- void report_errors();
- vio_ptr ssl_;
- vio_ptr ssl_context_;
- vio_ptr ssl_method_;
- vio_ptr session_id_context_;
-};
-
-VIO_NS_END
-
-/*
- * The Factory where Vio's are made!
- */
-
-class VioSSLConnectorFd : public VioConnectorFd
-{
-public:
- VioSSLConnectorFd(const char* key_file,
- const char* cert_file,
- const char* ca_file,
- const char* ca_path);
-
- virtual ~VioSSLConnectorFd();
- virtual VioSSL* connect(int fd);
- virtual VioSSL* connect(VioSocket* sd);
-private:
- VioSSLConnectorFd(const VioSSLConnectorFd& rhs);//undefined
- VioSSLConnectorFd& operator=(const VioSSLConnectorFd& rhs);//undefined
-private:
- void report_errors();
- vio_ptr ssl_context_;
- vio_ptr ssl_method_;
- vio_ptr ssl_;
-};
-
-VIO_NS_END
-
-#endif /* VIO_HAVE_OPENSSL */
diff --git a/vio/VioSocket.cc b/vio/VioSocket.cc
deleted file mode 100644
index e8390edb98a..00000000000
--- a/vio/VioSocket.cc
+++ /dev/null
@@ -1,326 +0,0 @@
-/* Copyright Abandoned 2000 Monty Program KB
-
- This file is public domain and comes with NO WARRANTY of any kind */
-
-/*
-** Virtual I/O library
-** Written by Andrei Errapart <andreie@no.spam.ee>
-*/
-
-#include "vio-global.h"
-#ifdef __GNUC__
-#pragma implementation // gcc: Class implementation
-#endif
-#include <assert.h>
-
-/*
- * Probably no need to clean this up
- */
-
-#ifdef _WIN32
-#include <winsock.h>
-#endif
-#include <sys/types.h>
-#if !defined(__WIN32__) && !defined(MSDOS)
-#include <sys/socket.h>
-#endif
-#if !defined(MSDOS) && !defined(__WIN32__) && !defined(HAVE_BROKEN_NETINET_INCLUDES)
-#include <netinet/in_systm.h>
-#include <netinet/in.h>
-#include <netinet/ip.h>
-#if !defined(alpha_linux_port)
-#include <netinet/tcp.h>
-#endif
-#if defined(__EMX__)
-#include <sys/ioctl.h>
-#define ioctlsocket(A,B,C) ioctl((A),(B),(void *)(C),sizeof(*(C)))
-#undef HAVE_FCNTL
-#endif
-#endif
-
-#if defined(MSDOS) || defined(__WIN32__)
-#ifdef __WIN32__
-#undef errno
-#undef EINTR
-#undef EAGAIN
-#define errno WSAGetLastError()
-#define EINTR WSAEINTR
-#define EAGAIN WSAEINPROGRESS
-#endif
-#endif
-#ifndef EWOULDBLOCK
-#define EWOULDBLOCK EAGAIN
-#endif
-
-#ifdef __cplusplus
-extern "C" { // Because of SCO 3.2V4.2
-#endif
-#ifndef __WIN32__
-#include <sys/resource.h>
-#ifdef HAVE_SYS_UN_H
-#include <sys/un.h>
-#endif
-#include <netdb.h>
-#include <sys/utsname.h>
-#endif // __WIN32__
-#ifdef __cplusplus
-}
-#endif
-
-VIO_NS_BEGIN
-
-#define this_ssl_cip my_static_cast(SSL_CIPHER*)(this->ssl_cip_)
-
-VioSocket::VioSocket(vio_socket sd, enum_vio_type type, bool localhost)
-:sd_(sd), localhost_(localhost), fcntl_(0),
- fcntl_set_(FALSE), cipher_description_(0)
-{
- DBUG_ENTER("VioSocket::VioSocket");
- DBUG_PRINT("enter", ("sd=%d", sd));
- if (type == VIO_TYPE_SOCKET)
- sprintf(desc_,"Socket (%d)",sd_);
- else
- sprintf(desc_,"TCP/IP (%d)",sd_);
- DBUG_VOID_RETURN;
-}
-
-VioSocket::~VioSocket()
-{
- DBUG_ENTER("VioSocket::~VioSocket");
- DBUG_PRINT("enter", ("sd_=%d", sd_));
- if (sd_>=0)
- close();
- DBUG_VOID_RETURN;
-}
-
-bool
-VioSocket::is_open() const
-{
- return sd_>=0;
-}
-
-int
-VioSocket::read(vio_ptr buf, int size)
-{
- int r;
- DBUG_ENTER("VioSocket::read");
- DBUG_PRINT("enter", ("sd_=%d, buf=%p, size=%d", sd_, buf, size));
- assert(sd_>=0);
-#if defined(MSDOS) || defined(__WIN32__)
- r = ::recv(sd_, buf, size,0);
-#else
- r = ::read(sd_, buf, size);
-#endif
-#ifndef DBUG_OFF
- if ( r < 0)
- {
- DBUG_PRINT("error", ("Got error %d during read",errno));
- }
-#endif /* DBUG_OFF */
- DBUG_PRINT("exit", ("%d", r));
- DBUG_RETURN(r);
-}
-
-int
-VioSocket::write(vio_ptr buf, int size)
-{
- int r;
- DBUG_ENTER("VioSocket::write");
- DBUG_PRINT("enter", ("sd_=%d, buf=%p, size=%d", sd_, buf, size));
- assert(sd_>=0);
-#if defined(__WIN32__)
- r = ::send(sd_, buf, size,0);
-#else
- r = ::write(sd_, buf, size);
-#endif /* __WIN32__ */
-#ifndef DBUG_OFF
- if (r < 0)
- {
- DBUG_PRINT("error", ("Got error %d on write",errno));
- }
-#endif /* DBUG_OFF */
- DBUG_RETURN(r);
-}
-
-int
-VioSocket::blocking(bool set_blocking_mode)
-{
- int r= 0;
- DBUG_ENTER("VioSocket::blocking");
- DBUG_PRINT("enter", ("set_blocking_mode: %d", (int) set_blocking_mode));
-
-#if !defined(___WIN32__) && !defined(__EMX__)
-#if !defined(NO_FCNTL_NONBLOCK)
- assert(sd_>=0);
-
- int old_fcntl=fcntl_;
- if (!fcntl_set_)
- {
- fcntl_set_ = true;
- old_fcntl= fcntl_ = fcntl(F_GETFL);
- }
- if (set_blocking_mode)
- fcntl_&=~O_NONBLOCK; //clear bit
- else
- fcntl_|=O_NONBLOCK; //set bit
- if (old_fcntl != fcntl_)
- r = ::fcntl(sd_, F_SETFL, fcntl_);
-#endif /* !defined(NO_FCNTL_NONBLOCK) */
-#else /* !defined(__WIN32__) && !defined(__EMX__) */
- {
- ulong arg;
- int old_fcntl=vio->fcntl_mode;
- if (!vio->fcntl_set)
- {
- vio->fcntl_set = TRUE;
- old_fnctl=vio->fcntl_mode=0;
- }
- if (set_blocking_mode)
- {
- arg = 0;
- fcntl_&=~ O_NONBLOCK; //clear bit
- }
- else
- {
- arg = 1;
- fcntl_|= O_NONBLOCK; //set bit
- }
- if (old_fcntl != fcntl_)
- r = ioctlsocket(sd_,FIONBIO,(void*)&arg,sizeof(arg));
- }
-#endif
- DBUG_RETURN(r);
-}
-
-bool
-VioSocket::blocking() const
-{
- DBUG_ENTER("VioSocket::blocking");
- bool r = !(fcntl_ & O_NONBLOCK);
- DBUG_PRINT("exit", ("%d", (int)r));
- DBUG_RETURN(r);
-}
-
-int
-VioSocket::fastsend(bool onoff)
-{
- int r=0;
- DBUG_ENTER("VioSocket::fastsend");
- DBUG_PRINT("enter", ("onoff:%d", (int)onoff));
- assert(sd_>=0);
-
-#ifdef IPTOS_THROUGHPUT
-#ifndef __EMX__
- int tos = IPTOS_THROUGHPUT;
- if (!setsockopt(sd_, IPPROTO_IP, IP_TOS, (void*) &tos, sizeof(tos)))
-#endif /* !__EMX__ */
- {
- int nodelay = 1;
- if (setsockopt(sd_, IPPROTO_TCP, TCP_NODELAY, (void*) &nodelay,
- sizeof(nodelay)))
- {
- DBUG_PRINT("warning",
- ("Couldn't set socket option for fast send"));
- r= -1;
- }
- }
-#endif /* IPTOS_THROUGHPUT */
- DBUG_PRINT("exit", ("%d", r));
- DBUG_RETURN(0);
-}
-
-
-int
-VioSocket::keepalive(bool set_keep_alive)
-{
- DBUG_ENTER("VioSocket::keepalive");
- DBUG_PRINT("enter", ("sd_=%d, set_keep_alive=%d", sd_,
- (int) set_keep_alive));
- assert(sd_>=0);
- uint opt= set_keep_alive ? 1 : 0;
- DBUG_RETURN(setsockopt(sd_, SOL_SOCKET, SO_KEEPALIVE, (char*) &opt,
- sizeof(opt)));
-}
-
-
-bool
-VioSocket::should_retry() const
-{
- int en = errno;
- return en == EAGAIN || en == EINTR || en == EWOULDBLOCK;
-}
-
-int
-VioSocket::close()
-{
- DBUG_ENTER("VioSocket::close");
- assert(sd_>=0);
- int r=0;
- if (::shutdown(sd_,2))
- r= -1;
- if (::closesocket(sd_))
- r= -1;
- if (r)
- {
- DBUG_PRINT("error", ("close() failed, error: %d",errno));
- /* FIXME: error handling (not critical for MySQL) */
- }
- sd_ = -1;
- DBUG_RETURN(r);
-}
-
-
-int
-VioSocket::shutdown(int how)
-{
- DBUG_ENTER("VioSocket::shutdown");
- DBUG_PRINT("enter", ("how=%d", how));
- assert(sd_>=0);
- int r = ::shutdown(sd_, how);
- DBUG_PRINT("exit", ("%d", r));
- DBUG_RETURN(r);
-}
-
-
-const char*
-VioSocket::description() const
-{
- return desc_;
-}
-
-
-bool
-VioSocket::peer_addr(char *buf) const
-{
- DBUG_ENTER("VioSocket::peer_addr");
- DBUG_PRINT("enter", ("sd_=%d", sd_));
- if (localhost_)
- {
- strmov(buf,"127.0.0.1");
- }
- else
- {
- size_socket addrLen= sizeof(struct sockaddr);
- if (getpeername(sd_, my_reinterpret_cast(struct sockaddr *) (&remote_),
- &addrLen) != 0)
- {
- DBUG_PRINT("exit", ("getpeername, error: %d", errno));
- DBUG_RETURN(1);
- }
- my_inet_ntoa(remote_.sin_addr,buf);
- }
- DBUG_PRINT("exit", ("addr=%s", buf));
- DBUG_RETURN(0);
-}
-
-
-const char*
-VioSocket::cipher_description() const
-{
- DBUG_ENTER("VioSocket::cipher_description");
- char *r = cipher_description_ ? cipher_description_:"";
- DBUG_PRINT("exit", ("name: %s", r));
- DBUG_RETURN(r);
-}
-
-VIO_NS_END
diff --git a/vio/VioSocket.h b/vio/VioSocket.h
deleted file mode 100644
index e2c6eafa516..00000000000
--- a/vio/VioSocket.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
-** Virtual I/O library
-** Written by Andrei Errapart <andreie@no.spam.ee>
-*/
-
-/*
- * Concrete Vio around socket. Doesn't differ much from VioFd.
- */
-
-#ifdef WIN32
- typedef SOCKET vio_socket;
-#else
- typedef int vio_socket;
-#endif /* WIN32 */
-
-VIO_NS_BEGIN
-
-class VioSSL;
-class VioSocket : public Vio
-{
-public:
- VioSocket(vio_socket sd, bool localhost=true);
- virtual ~VioSocket();
- virtual bool is_open() const;
- virtual int read(vio_ptr buf, int size);
- virtual int write(const vio_ptr buf, int size);
- virtual int blocking(bool onoff);
- virtual bool blocking() const;
- virtual int fastsend(bool onoff=true);
- virtual int keepalive(bool onoff);
- virtual bool should_retry() const;
- virtual int close();
- virtual const char* description() const;
- virtual bool peer_addr(char *buf) const;
- virtual const char* cipher_description() const;
- virtual int vio_errno();
- int shutdown(int how);
-
-private:
- vio_socket sd_;
- const bool localhost_;
- int fcntl_;
- bool fcntl_set_;
- char desc_[30];
- mutable struct sockaddr_in local_;
- mutable struct sockaddr_in remote_;
- mutable char* cipher_description_;
-
- friend class VioSSL; // he wants to tinker with this->sd_;
-};
-
-VIO_NS_END
-
-#endif /* vio_VioSocket_h_ */
-
diff --git a/vio/test-ssl.c b/vio/test-ssl.c
new file mode 100644
index 00000000000..09dae7ad5cf
--- /dev/null
+++ b/vio/test-ssl.c
@@ -0,0 +1,147 @@
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <my_global.h>
+#ifdef HAVE_OPENSSL
+#include <my_sys.h>
+#include <m_string.h>
+#include <m_ctype.h>
+#include "mysql.h"
+#include "errmsg.h"
+#include <my_dir.h>
+#ifndef __GNU_LIBRARY__
+#define __GNU_LIBRARY__ // Skip warnings in getopt.h
+#endif
+#include <getopt.h>
+#include <signal.h>
+#include <violite.h>
+
+const char *VER="0.1";
+
+
+#ifndef DBUG_OFF
+const char *default_dbug_option="d:t:O,-";
+#endif
+
+void
+fatal_error( const char* r)
+{
+ perror(r);
+ exit(0);
+}
+
+void
+print_usage()
+{
+ printf("viossl-test: testing SSL virtual IO. Usage:\n");
+ printf("viossl-test server-key server-cert client-key client-cert [CAfile] [CApath]\n");
+}
+
+int
+main( int argc,
+ char** argv)
+{
+ char* server_key = 0, *server_cert = 0;
+ char* client_key = 0, *client_cert = 0;
+ char* ca_file = 0, *ca_path = 0;
+ char* cipher=0;
+ int child_pid,sv[2];
+ struct st_VioSSLAcceptorFd* ssl_acceptor=0;
+ struct st_VioSSLConnectorFd* ssl_connector=0;
+ Vio* client_vio=0, *server_vio=0;
+ MY_INIT(argv[0]);
+ DBUG_PROCESS(argv[0]);
+ DBUG_PUSH(default_dbug_option);
+
+ if (argc<5)
+ {
+ print_usage();
+ return 1;
+ }
+
+ server_key = argv[1];
+ server_cert = argv[2];
+ client_key = argv[3];
+ client_cert = argv[4];
+ if (argc>5)
+ ca_file = argv[5];
+ if (argc>6)
+ ca_path = argv[6];
+ printf("Server key/cert : %s/%s\n", server_key, server_cert);
+ printf("Client key/cert : %s/%s\n", client_key, client_cert);
+ if (ca_file!=0)
+ printf("CAfile : %s\n", ca_file);
+ if (ca_path!=0)
+ printf("CApath : %s\n", ca_path);
+
+
+ if (socketpair(PF_UNIX, SOCK_STREAM, IPPROTO_IP, sv)==-1)
+ fatal_error("socketpair");
+
+ ssl_acceptor = new_VioSSLAcceptorFd(server_key, server_cert, ca_file, ca_path, cipher);
+ ssl_connector = new_VioSSLConnectorFd(client_key, client_cert, ca_file, ca_path, cipher);
+
+ client_vio = (struct st_vio*)my_malloc(sizeof(struct st_vio),MYF(0));
+ client_vio->sd = sv[0];
+ client_vio->vioblocking(client_vio,0);
+ sslconnect(ssl_connector,client_vio,60L);
+ server_vio = (struct st_vio*)my_malloc(sizeof(struct st_vio),MYF(0));
+ server_vio->sd = sv[1];
+ server_vio->vioblocking(client_vio,0);
+ sslaccept(ssl_acceptor,server_vio,60L);
+
+ printf("Socketpair: %d , %d\n", client_vio->sd, server_vio->sd);
+
+ child_pid = fork();
+ if (child_pid==-1) {
+ my_free((gptr)ssl_acceptor,MYF(0));
+ my_free((gptr)ssl_connector,MYF(0));
+ fatal_error("fork");
+ }
+ if (child_pid==0) {
+ //child, therefore, client
+ char xbuf[100];
+ int r = client_vio->read(client_vio,xbuf, sizeof(xbuf));
+ if (r<=0) {
+ my_free((gptr)ssl_acceptor,MYF(0));
+ my_free((gptr)ssl_connector,MYF(0));
+ fatal_error("client:SSL_read");
+ }
+ xbuf[r] = 0;
+ printf("client:got %s\n", xbuf);
+ my_free((gptr)client_vio,MYF(0));
+ my_free((gptr)ssl_acceptor,MYF(0));
+ my_free((gptr)ssl_connector,MYF(0));
+ } else {
+ const char* s = "Huhuhuh";
+ int r = server_vio->write(server_vio,(gptr)s, strlen(s));
+ if (r<=0) {
+ my_free((gptr)ssl_acceptor,MYF(0));
+ my_free((gptr)ssl_connector,MYF(0));
+ fatal_error("server:SSL_write");
+ }
+ my_free((gptr)server_vio,MYF(0));
+ my_free((gptr)ssl_acceptor,MYF(0));
+ my_free((gptr)ssl_connector,MYF(0));
+ }
+ return 0;
+}
+#else /* HAVE_OPENSSL */
+
+int main() {
+return 0;
+}
+#endif /* HAVE_OPENSSL */
diff --git a/vio/test-sslclient.c b/vio/test-sslclient.c
new file mode 100644
index 00000000000..51a78485642
--- /dev/null
+++ b/vio/test-sslclient.c
@@ -0,0 +1,105 @@
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <my_global.h>
+#ifdef HAVE_OPENSSL
+#include <my_sys.h>
+#include <m_string.h>
+#include <m_ctype.h>
+#include "mysql.h"
+#include "errmsg.h"
+#include <my_dir.h>
+#ifndef __GNU_LIBRARY__
+#define __GNU_LIBRARY__ // Skip warnings in getopt.h
+#endif
+#include <getopt.h>
+#include <signal.h>
+#include <violite.h>
+
+const char *VER="0.1";
+
+
+#ifndef DBUG_OFF
+const char *default_dbug_option="d:t:O,-";
+#endif
+
+void
+fatal_error( const char* r)
+{
+ perror(r);
+ exit(0);
+}
+
+int
+main( int argc __attribute__((unused)),
+ char** argv)
+{
+ char client_key[] = "../SSL/client-key.pem", client_cert[] = "../SSL/client-cert.pem";
+ char ca_file[] = "../SSL/cacert.pem", *ca_path = 0, *cipher=0;
+ struct st_VioSSLConnectorFd* ssl_connector=0;
+ struct sockaddr_in sa;
+ Vio* client_vio=0;
+ int err;
+ char xbuf[100]="Ohohhhhoh1234";
+ MY_INIT(argv[0]);
+ DBUG_PROCESS(argv[0]);
+ DBUG_PUSH(default_dbug_option);
+
+ printf("Client key/cert : %s/%s\n", client_key, client_cert);
+ if (ca_file!=0)
+ printf("CAfile : %s\n", ca_file);
+ if (ca_path!=0)
+ printf("CApath : %s\n", ca_path);
+
+ ssl_connector = new_VioSSLConnectorFd(client_key, client_cert, ca_file, ca_path, cipher);
+ if(!ssl_connector) {
+ fatal_error("client:new_VioSSLConnectorFd failed");
+ }
+
+ /* ----------------------------------------------- */
+ /* Create a socket and connect to server using normal socket calls. */
+
+ client_vio = vio_new(socket (AF_INET, SOCK_STREAM, 0), VIO_TYPE_TCPIP, TRUE);
+
+ memset (&sa, '\0', sizeof(sa));
+ sa.sin_family = AF_INET;
+ sa.sin_addr.s_addr = inet_addr ("127.0.0.1"); /* Server IP */
+ sa.sin_port = htons (1111); /* Server Port number */
+
+ err = connect(client_vio->sd, (struct sockaddr*) &sa,
+ sizeof(sa));
+
+ /* ----------------------------------------------- */
+ /* Now we have TCP conncetion. Start SSL negotiation. */
+ read(client_vio->sd,xbuf, sizeof(xbuf));
+ sslconnect(ssl_connector,client_vio,60L);
+ err = client_vio->read(client_vio,xbuf, sizeof(xbuf));
+ if (err<=0) {
+ my_free((gptr)ssl_connector,MYF(0));
+ fatal_error("client:SSL_read");
+ }
+ xbuf[err] = 0;
+ printf("client:got %s\n", xbuf);
+ my_free((gptr)client_vio,MYF(0));
+ my_free((gptr)ssl_connector,MYF(0));
+ return 0;
+}
+#else /* HAVE_OPENSSL */
+
+int main() {
+return 0;
+}
+#endif /* HAVE_OPENSSL */
diff --git a/vio/test-sslserver.c b/vio/test-sslserver.c
new file mode 100644
index 00000000000..988019a012b
--- /dev/null
+++ b/vio/test-sslserver.c
@@ -0,0 +1,157 @@
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <my_global.h>
+#ifdef HAVE_OPENSSL
+#include <my_sys.h>
+#include <m_string.h>
+#include <m_ctype.h>
+#include "mysql.h"
+#include "errmsg.h"
+#include <my_dir.h>
+#ifndef __GNU_LIBRARY__
+#define __GNU_LIBRARY__ // Skip warnings in getopt.h
+#endif
+#include <getopt.h>
+#include <signal.h>
+#include <violite.h>
+
+const char *VER="0.1";
+
+
+#ifndef DBUG_OFF
+const char *default_dbug_option="d:t:O,-";
+#endif
+
+static void
+fatal_error( const char* r)
+{
+ perror(r);
+ exit(0);
+}
+
+typedef struct {
+ int sd;
+ struct st_VioSSLAcceptorFd* ssl_acceptor;
+} TH_ARGS;
+
+static void
+do_ssl_stuff( TH_ARGS* args)
+{
+ const char* s = "Huhuhuhuuu";
+ Vio* server_vio;
+ int err;
+ DBUG_ENTER("do_ssl_stuff");
+
+ server_vio = vio_new(args->sd, VIO_TYPE_TCPIP, TRUE);
+
+ /* ----------------------------------------------- */
+ /* TCP connection is ready. Do server side SSL. */
+
+ err = write(server_vio->sd,(gptr)s, strlen(s));
+ sslaccept(args->ssl_acceptor,server_vio,60L);
+ err = server_vio->write(server_vio,(gptr)s, strlen(s));
+ DBUG_VOID_RETURN;
+}
+
+static void*
+client_thread( void* arg)
+{
+ my_thread_init();
+ do_ssl_stuff((TH_ARGS*)arg);
+}
+
+int
+main( int argc __attribute__((unused)),
+ char** argv)
+{
+ char server_key[] = "../SSL/server-key.pem",
+ server_cert[] = "../SSL/server-cert.pem";
+ char ca_file[] = "../SSL/cacert.pem",
+ *ca_path = 0,
+ *cipher = 0;
+ struct st_VioSSLAcceptorFd* ssl_acceptor;
+ pthread_t th;
+ TH_ARGS th_args;
+
+
+ struct sockaddr_in sa_serv;
+ struct sockaddr_in sa_cli;
+ int listen_sd;
+ int err;
+ size_t client_len;
+ int reuseaddr = 1; /* better testing, uh? */
+
+ MY_INIT(argv[0]);
+ DBUG_PROCESS(argv[0]);
+ DBUG_PUSH(default_dbug_option);
+
+ printf("Server key/cert : %s/%s\n", server_key, server_cert);
+ if (ca_file!=0)
+
+ printf("CAfile : %s\n", ca_file);
+ if (ca_path!=0)
+ printf("CApath : %s\n", ca_path);
+
+ th_args.ssl_acceptor = ssl_acceptor = new_VioSSLAcceptorFd(server_key, server_cert, ca_file, ca_path,cipher);
+
+ /* ----------------------------------------------- */
+ /* Prepare TCP socket for receiving connections */
+
+ listen_sd = socket (AF_INET, SOCK_STREAM, 0);
+ setsockopt(listen_sd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(&reuseaddr));
+
+ memset (&sa_serv, '\0', sizeof(sa_serv));
+ sa_serv.sin_family = AF_INET;
+ sa_serv.sin_addr.s_addr = INADDR_ANY;
+ sa_serv.sin_port = htons (1111); /* Server Port number */
+
+ err = bind(listen_sd, (struct sockaddr*) &sa_serv,
+ sizeof (sa_serv));
+
+ /* Receive a TCP connection. */
+
+ err = listen (listen_sd, 5);
+ client_len = sizeof(sa_cli);
+ th_args.sd = accept (listen_sd, (struct sockaddr*) &sa_cli, &client_len);
+ close (listen_sd);
+
+ printf ("Connection from %lx, port %x\n",
+ (long)sa_cli.sin_addr.s_addr, sa_cli.sin_port);
+
+ /* ----------------------------------------------- */
+ /* TCP connection is ready. Do server side SSL. */
+
+ err = pthread_create(&th, NULL, client_thread, (void*)&th_args);
+ DBUG_PRINT("info", ("pthread_create: %d", err));
+ pthread_join(th, NULL);
+
+#if 0
+ if (err<=0) {
+ my_free((gptr)ssl_acceptor,MYF(0));
+ fatal_error("server:SSL_write");
+ }
+#endif /* 0 */
+
+ my_free((gptr)ssl_acceptor,MYF(0));
+ return 0;
+}
+#else /* HAVE_OPENSSL */
+
+int main() {
+return 0;
+}
+#endif /* HAVE_OPENSSL */
diff --git a/vio/version.cc b/vio/version.cc
deleted file mode 100644
index 7c09d431a9d..00000000000
--- a/vio/version.cc
+++ /dev/null
@@ -1,7 +0,0 @@
-#include "vio-global.h"
-
-extern "C" const char*
-vio_version()
-{
- return "0.2";
-}
diff --git a/vio/vio-global.h b/vio/vio-global.h
deleted file mode 100644
index 0c3d279695d..00000000000
--- a/vio/vio-global.h
+++ /dev/null
@@ -1,33 +0,0 @@
-#include <global.h>
-
-#if !defined(VIO_HAVE_OPENSSL) && defined(HAVE_OPENSSL)
-#define VIO_HAVE_OPENSSL HAVE_OPENSSL
-#endif /* !defined(VIO_HAVE_OPENSSL) && defined(HAVE_OPENSSL) */
-
-#include "viotypes.h"
-#include "Vio.h"
-#include "VioAcceptorFd.h"
-#include "VioFd.h"
-#include "VioPipe.h"
-#include "VioSocket.h"
-#ifdef VIO_HAVE_OPENSSL
-#include "VioSSL.h"
-#include "VioSSLFactoriesFd.h"
-#endif /* VIO_HAVE_OPENSSL */
-
-
-#if VIO_HAVE_NAMESPACES
-#define VIO_STD_NS std
-#define VIO_STD_NS_USING using namespace std;
-#define VIO_NS VirtualIO
-#define VIO_NS_BEGIN namespace VIO_NS {
-#define VIO_NS_END }
-#define VIO_NS_USING using namespace VIO_NS;
-#else
-#define VIO_STD_NS
-#define VIO_STD_NS_USING
-#define VIO_NS
-#define VIO_NS_BEGIN
-#define VIO_NS_END
-#define VIO_NS_USING
-#endif
diff --git a/vio/vio.c b/vio/vio.c
new file mode 100644
index 00000000000..62814e50240
--- /dev/null
+++ b/vio/vio.c
@@ -0,0 +1,132 @@
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+/*
+ Note that we can't have assertion on file descriptors; The reason for
+ this is that during mysql shutdown, another thread can close a file
+ we are working on. In this case we should just return read errors from
+ the file descriptior.
+*/
+
+#define DONT_MAP_VIO
+#include <my_global.h>
+#include <mysql_com.h>
+#include <violite.h>
+#include <errno.h>
+#include <my_sys.h>
+#include <my_net.h>
+#include <m_string.h>
+
+/*
+ * Helper to fill most of the Vio* with defaults.
+ */
+
+void vio_reset(Vio* vio, enum enum_vio_type type,
+ my_socket sd, HANDLE hPipe,
+ my_bool localhost)
+{
+ DBUG_ENTER("vio_reset");
+ DBUG_PRINT("enter", ("type=%d sd=%d localhost=%d", type, sd, localhost));
+
+ bzero((char*) vio, sizeof(*vio));
+ vio->type = type;
+ vio->sd = sd;
+ vio->hPipe = hPipe;
+ vio->localhost= localhost;
+#ifdef HAVE_VIO
+#ifdef HAVE_OPENSSL
+ if (type == VIO_TYPE_SSL)
+ {
+ vio->viodelete =vio_ssl_delete;
+ vio->vioerrno =vio_ssl_errno;
+ vio->read =vio_ssl_read;
+ vio->write =vio_ssl_write;
+ vio->fastsend =vio_ssl_fastsend;
+ vio->viokeepalive =vio_ssl_keepalive;
+ vio->should_retry =vio_ssl_should_retry;
+ vio->vioclose =vio_ssl_close;
+ vio->peer_addr =vio_ssl_peer_addr;
+ vio->in_addr =vio_ssl_in_addr;
+ vio->vioblocking =vio_blocking;
+ vio->is_blocking =vio_is_blocking;
+ }
+ else /* default is VIO_TYPE_TCPIP */
+#endif /* HAVE_OPENSSL */
+ {
+ vio->viodelete =vio_delete;
+ vio->vioerrno =vio_errno;
+ vio->read =vio_read;
+ vio->write =vio_write;
+ vio->fastsend =vio_fastsend;
+ vio->viokeepalive =vio_keepalive;
+ vio->should_retry =vio_should_retry;
+ vio->vioclose =vio_close;
+ vio->peer_addr =vio_peer_addr;
+ vio->in_addr =vio_in_addr;
+ vio->vioblocking =vio_blocking;
+ vio->is_blocking =vio_is_blocking;
+ }
+#endif /* HAVE_VIO */
+ DBUG_VOID_RETURN;
+}
+
+/* Open the socket or TCP/IP connection and read the fnctl() status */
+
+Vio *vio_new(my_socket sd, enum enum_vio_type type, my_bool localhost)
+{
+ Vio *vio;
+ DBUG_ENTER("vio_new");
+ DBUG_PRINT("enter", ("sd=%d", sd));
+ if ((vio = (Vio*) my_malloc(sizeof(*vio),MYF(MY_WME))))
+ {
+ vio_reset(vio, type, sd, 0, localhost);
+ sprintf(vio->desc,
+ (vio->type == VIO_TYPE_SOCKET ? "socket (%d)" : "TCP/IP (%d)"),
+ vio->sd);
+#if !defined(___WIN__) && !defined(__EMX__)
+#if !defined(NO_FCNTL_NONBLOCK)
+ vio->fcntl_mode = fcntl(sd, F_GETFL);
+#elif defined(HAVE_SYS_IOCTL_H) /* hpux */
+ /* Non blocking sockets doesn't work good on HPUX 11.0 */
+ (void) ioctl(sd,FIOSNBIO,0);
+#endif
+#else /* !defined(__WIN__) && !defined(__EMX__) */
+ {
+ /* set to blocking mode by default */
+ ulong arg=0, r;
+ r = ioctlsocket(sd,FIONBIO,(void*) &arg, sizeof(arg));
+ }
+#endif
+ }
+ DBUG_RETURN(vio);
+}
+
+
+#ifdef __WIN__
+
+Vio *vio_new_win32pipe(HANDLE hPipe)
+{
+ Vio *vio;
+ DBUG_ENTER("vio_new_handle");
+ if ((vio = (Vio*) my_malloc(sizeof(Vio),MYF(MY_WME))))
+ {
+ vio_reset(vio, VIO_TYPE_NAMEDPIPE, 0, hPipe, TRUE);
+ strmov(vio->desc, "named pipe");
+ }
+ DBUG_RETURN(vio);
+}
+
+#endif
diff --git a/vio/vioelitexx.cc b/vio/vioelitexx.cc
deleted file mode 100644
index 0eac28eaf55..00000000000
--- a/vio/vioelitexx.cc
+++ /dev/null
@@ -1,26 +0,0 @@
-/* Copyright Abandoned 2000 Monty Program KB
- This file is public domain and comes with NO WARRANTY of any kind */
-
-/*
- * Renamed of violite.cc to violitexx.cc because of clashes
- * with violite.c
- * This file implements the same functions as in violite.c, but now using
- * the Vio class
- */
-
-#include "vio-global.h"
-
-Vio*
-vio_new(my_socket sd, enum_vio_type type, my_bool localhost)
-{
- return my_reinterpret_cast(Vio*) (new VioSocket(sd, type, localhost));
-}
-
-
-#ifdef __WIN32__
-Vio
-*vio_new_win32pipe(HANDLE hPipe)
-{
- return my_reinterpret_cast(Vio*) (new VioPipe(hPipe));
-}
-#endif
diff --git a/vio/violite.h b/vio/violite.h
deleted file mode 100644
index fc480f59db1..00000000000
--- a/vio/violite.h
+++ /dev/null
@@ -1,101 +0,0 @@
-/* Copyright Abandoned 2000 Monty Program KB
- This file is public domain and comes with NO WARRANTY of any kind */
-
-/*
- * Vio Lite.
- * Purpose: include file for Vio that will work with C and C++
- */
-
-#ifndef vio_violite_h_
-#define vio_violite_h_
-
-#include "my_net.h" /* needed because of struct in_addr */
-
-#ifdef HAVE_VIO
-#include <Vio.h> /* Full VIO interface */
-#else
-
-/* Simple vio interface in C; The functions are implemented in violite.c */
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-#ifndef Vio_defined
-#define Vio_defined
-struct st_vio; /* Only C */
-typedef struct st_vio Vio;
-#endif
-
-enum enum_vio_type { VIO_CLOSED, VIO_TYPE_TCPIP, VIO_TYPE_SOCKET,
- VIO_TYPE_NAMEDPIPE, VIO_TYPE_SSL};
-
-Vio* vio_new(my_socket sd,
- enum enum_vio_type type,
- my_bool localhost);
-#ifdef __WIN__
-Vio* vio_new_win32pipe(HANDLE hPipe);
-#endif
-void vio_delete(Vio* vio);
-
-/*
- * vio_read and vio_write should have the same semantics
- * as read(2) and write(2).
- */
-int vio_read( Vio* vio,
- gptr buf, int size);
-int vio_write( Vio* vio,
- const gptr buf,
- int size);
-/*
- * Whenever the socket is set to blocking mode or not.
- */
-int vio_blocking( Vio* vio,
- my_bool onoff);
-my_bool vio_is_blocking( Vio* vio);
-/*
- * setsockopt TCP_NODELAY at IPPROTO_TCP level, when possible.
- */
-int vio_fastsend( Vio* vio,
- my_bool onoff);
-/*
- * setsockopt SO_KEEPALIVE at SOL_SOCKET level, when possible.
- */
-int vio_keepalive( Vio* vio,
- my_bool onoff);
-/*
- * Whenever we should retry the last read/write operation.
- */
-my_bool vio_should_retry( Vio* vio);
-/*
- * When the workday is over...
- */
-int vio_close( Vio* vio);
-/*
- * Short text description of the socket for those, who are curious..
- */
-const char* vio_description( Vio* vio);
-
-/* Return the type of the connection */
- enum enum_vio_type vio_type(Vio* vio);
-
-/* Return last error number */
-int vio_errno(Vio *vio);
-
-/* Get socket number */
-my_socket vio_fd(Vio *vio);
-
-/*
- * Remote peer's address and name in text form.
- */
-my_bool vio_peer_addr(Vio * vio, char *buf);
-
-/* Remotes in_addr */
-
-void vio_in_addr(Vio *vio, struct in_addr *in);
-
-#ifdef __cplusplus
-}
-#endif
-#endif /* HAVE_VIO */
-#endif /* vio_violite_h_ */
diff --git a/sql/violite.c b/vio/viosocket.c
index 37fee6fad3d..14b4305b95a 100644
--- a/sql/violite.c
+++ b/vio/viosocket.c
@@ -1,19 +1,18 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 */
/*
Note that we can't have assertion on file descriptors; The reason for
@@ -22,128 +21,21 @@
the file descriptior.
*/
-#include <global.h>
-
-#ifndef HAVE_VIO /* is Vio suppored by the Vio lib ? */
+#define DONT_MAP_VIO
+#include <my_global.h>
+#include <mysql_com.h>
#include <errno.h>
-#include <assert.h>
#include <violite.h>
#include <my_sys.h>
#include <my_net.h>
#include <m_string.h>
-#ifdef HAVE_POLL
-#include <sys/poll.h>
-#endif
-#ifdef HAVE_SYS_IOCTL_H
-#include <sys/ioctl.h>
-#endif
-#ifdef HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
-
-#if !defined(MSDOS) && !defined(__WIN__) && !defined(HAVE_BROKEN_NETINET_INCLUDES) && !defined(__BEOS__) && !defined(__FreeBSD__)
-#include <netinet/in_systm.h>
-#include <netinet/ip.h>
-#if !defined(alpha_linux_port)
-#include <netinet/tcp.h>
-#endif
-#endif
-
-#if defined(__EMX__) || defined(OS2)
-#define ioctlsocket ioctl
-#endif /* defined(__EMX__) */
-
-#if defined(MSDOS) || defined(__WIN__)
-#define O_NONBLOCK 1 /* For emulation of fcntl() */
-#endif
-#ifndef EWOULDBLOCK
-#define SOCKET_EWOULDBLOCK SOCKET_EAGAIN
-#endif
#ifndef __WIN__
#define HANDLE void *
#endif
-struct st_vio
-{
- my_socket sd; /* my_socket - real or imaginary */
- HANDLE hPipe;
- my_bool localhost; /* Are we from localhost? */
- int fcntl_mode; /* Buffered fcntl(sd,F_GETFL) */
- struct sockaddr_in local; /* Local internet address */
- struct sockaddr_in remote; /* Remote internet address */
- enum enum_vio_type type; /* Type of connection */
- char desc[30]; /* String description */
-};
-
-typedef void *vio_ptr;
-typedef char *vio_cstring;
-
-/*
- * Helper to fill most of the Vio* with defaults.
- */
-
-static void vio_reset(Vio* vio, enum enum_vio_type type,
- my_socket sd, HANDLE hPipe,
- my_bool localhost)
-{
- bzero((char*) vio, sizeof(*vio));
- vio->type = type;
- vio->sd = sd;
- vio->hPipe = hPipe;
- vio->localhost= localhost;
-}
-
-/* Open the socket or TCP/IP connection and read the fnctl() status */
-
-Vio *vio_new(my_socket sd, enum enum_vio_type type, my_bool localhost)
-{
- Vio *vio;
- DBUG_ENTER("vio_new");
- DBUG_PRINT("enter", ("sd=%d", sd));
- if ((vio = (Vio*) my_malloc(sizeof(*vio),MYF(MY_WME))))
- {
- vio_reset(vio, type, sd, 0, localhost);
- sprintf(vio->desc,
- (vio->type == VIO_TYPE_SOCKET ? "socket (%d)" : "TCP/IP (%d)"),
- vio->sd);
-#if !defined(___WIN__) && !defined(__EMX__) && !defined(OS2)
-#if !defined(NO_FCNTL_NONBLOCK)
- vio->fcntl_mode = fcntl(sd, F_GETFL);
-#elif defined(HAVE_SYS_IOCTL_H) /* hpux */
- /* Non blocking sockets doesn't work good on HPUX 11.0 */
- (void) ioctl(sd,FIOSNBIO,0);
-#endif
-#else /* !defined(__WIN__) && !defined(__EMX__) */
- {
- /* set to blocking mode by default */
- ulong arg=0, r;
- r = ioctlsocket(vio->sd,FIONBIO,(void*) &arg, sizeof(arg));
- }
-#endif
- }
- DBUG_RETURN(vio);
-}
-
-
-#ifdef __WIN__
-
-Vio *vio_new_win32pipe(HANDLE hPipe)
-{
- Vio *vio;
- DBUG_ENTER("vio_new_handle");
- if ((vio = (Vio*) my_malloc(sizeof(Vio),MYF(MY_WME))))
- {
- vio_reset(vio, VIO_TYPE_NAMEDPIPE, 0, hPipe, TRUE);
- strmov(vio->desc, "named pipe");
- }
- DBUG_RETURN(vio);
-}
-
-#endif
-
-void vio_delete(Vio * vio)
+void vio_delete(Vio* vio)
{
/* It must be safe to delete null pointers. */
/* This matches the semantics of C++'s delete operator. */
@@ -165,18 +57,13 @@ int vio_read(Vio * vio, gptr buf, int size)
{
int r;
DBUG_ENTER("vio_read");
- DBUG_PRINT("enter", ("sd=%d size=%d", vio->sd, size));
-#if defined( __WIN__) || defined(OS2)
+ DBUG_PRINT("enter", ("sd=%d, buf=%p, size=%d", vio->sd, buf, size));
+#ifdef __WIN__
if (vio->type == VIO_TYPE_NAMEDPIPE)
{
DWORD length;
-#ifdef OS2
- if (!DosRead((HFILE)vio->hPipe, buf, size, &length))
- DBUG_RETURN(-1);
-#else
if (!ReadFile(vio->hPipe, buf, size, &length, NULL))
DBUG_RETURN(-1);
-#endif
DBUG_RETURN(length);
}
r = recv(vio->sd, buf, size,0);
@@ -187,7 +74,7 @@ int vio_read(Vio * vio, gptr buf, int size)
#ifndef DBUG_OFF
if (r < 0)
{
- DBUG_PRINT("vio_error", ("Got error %d during read",socket_errno));
+ DBUG_PRINT("vio_error", ("Got error %d during read",errno));
}
#endif /* DBUG_OFF */
DBUG_PRINT("exit", ("%d", r));
@@ -199,18 +86,13 @@ int vio_write(Vio * vio, const gptr buf, int size)
{
int r;
DBUG_ENTER("vio_write");
- DBUG_PRINT("enter", ("sd=%d size=%d", vio->sd, size));
-#if defined( __WIN__) || defined(OS2)
+ DBUG_PRINT("enter", ("sd=%d, buf=%p, size=%d", vio->sd, buf, size));
+#ifdef __WIN__
if ( vio->type == VIO_TYPE_NAMEDPIPE)
{
DWORD length;
-#ifdef OS2
- if (!DosWrite((HFILE)vio->hPipe, (char*) buf, size, &length))
- DBUG_RETURN(-1);
-#else
if (!WriteFile(vio->hPipe, (char*) buf, size, &length, NULL))
DBUG_RETURN(-1);
-#endif
DBUG_RETURN(length);
}
r = send(vio->sd, buf, size,0);
@@ -228,13 +110,14 @@ int vio_write(Vio * vio, const gptr buf, int size)
}
-int vio_blocking(Vio * vio, my_bool set_blocking_mode)
+int vio_blocking(Vio * vio __attribute__((unused)), my_bool set_blocking_mode)
{
int r=0;
DBUG_ENTER("vio_blocking");
DBUG_PRINT("enter", ("set_blocking_mode: %d", (int) set_blocking_mode));
-#if !defined(___WIN__) && !defined(__EMX__) && !defined(OS2)
+#if !defined(HAVE_OPENSSL)
+#if !defined(___WIN__) && !defined(__EMX__)
#if !defined(NO_FCNTL_NONBLOCK)
if (vio->sd >= 0)
@@ -269,6 +152,8 @@ int vio_blocking(Vio * vio, my_bool set_blocking_mode)
r = ioctlsocket(vio->sd,FIONBIO,(void*) &arg, sizeof(arg));
}
#endif /* !defined(__WIN__) && !defined(__EMX__) */
+#endif /* !defined (HAVE_OPENSSL) */
+ DBUG_PRINT("exit", ("return %d", r));
DBUG_RETURN(r);
}
@@ -314,7 +199,7 @@ int vio_keepalive(Vio* vio, my_bool set_keep_alive)
int r=0;
uint opt = 0;
DBUG_ENTER("vio_keepalive");
- DBUG_PRINT("enter", ("sd=%d set_keep_alive=%d", vio->sd, (int)
+ DBUG_PRINT("enter", ("sd=%d, set_keep_alive=%d", vio->sd, (int)
set_keep_alive));
if (vio->type != VIO_TYPE_NAMEDPIPE)
{
@@ -331,7 +216,8 @@ my_bool
vio_should_retry(Vio * vio __attribute__((unused)))
{
int en = socket_errno;
- return en == SOCKET_EAGAIN || en == SOCKET_EINTR || en == SOCKET_EWOULDBLOCK;
+ return (en == SOCKET_EAGAIN || en == SOCKET_EINTR ||
+ en == SOCKET_EWOULDBLOCK);
}
@@ -439,5 +325,3 @@ my_bool vio_poll_read(Vio *vio,uint timeout)
DBUG_RETURN(fds.revents & POLLIN ? 0 : 1);
#endif
}
-
-#endif /* HAVE_VIO */
diff --git a/vio/viossl.c b/vio/viossl.c
new file mode 100644
index 00000000000..6d85b119f20
--- /dev/null
+++ b/vio/viossl.c
@@ -0,0 +1,360 @@
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+/*
+ Note that we can't have assertion on file descriptors; The reason for
+ this is that during mysql shutdown, another thread can close a file
+ we are working on. In this case we should just return read errors from
+ the file descriptior.
+*/
+
+#include <my_global.h>
+
+#ifdef HAVE_OPENSSL
+
+#include <mysql_com.h>
+
+#include <errno.h>
+#include <assert.h>
+#include <violite.h>
+#include <my_sys.h>
+#include <my_net.h>
+#include <m_string.h>
+
+#ifndef __WIN__
+#define HANDLE void *
+#endif
+
+static void
+report_errors()
+{
+ unsigned long l;
+ const char* file;
+ const char* data;
+ int line,flags, any_ssl_error = 0;
+ DBUG_ENTER("report_errors");
+
+ while ((l=ERR_get_error_line_data(&file,&line,&data,&flags)) != 0)
+ {
+ char buf[200];
+ any_ssl_error = 1;
+ DBUG_PRINT("error", ("OpenSSL: %s:%s:%d:%s\n", ERR_error_string(l,buf),
+ file,line,(flags&ERR_TXT_STRING)?data:"")) ;
+ }
+ if (!any_ssl_error) {
+ DBUG_PRINT("info", ("No OpenSSL errors."));
+ }
+ DBUG_PRINT("info", ("BTW, errno=%d", socket_errno));
+ DBUG_VOID_RETURN;
+}
+
+
+void vio_ssl_delete(Vio * vio)
+{
+ /* It must be safe to delete null pointers. */
+ /* This matches the semantics of C++'s delete operator. */
+ if (vio)
+ {
+ if (vio->type != VIO_CLOSED)
+ vio_close(vio);
+ my_free((gptr) vio,MYF(0));
+ }
+}
+
+int vio_ssl_errno(Vio *vio __attribute__((unused)))
+{
+ return socket_errno; /* On Win32 this mapped to WSAGetLastError() */
+}
+
+
+int vio_ssl_read(Vio * vio, gptr buf, int size)
+{
+ int r;
+ DBUG_ENTER("vio_ssl_read");
+ DBUG_PRINT("enter", ("sd=%d, buf=%p, size=%d, ssl_=%p",
+ vio->sd, buf, size, vio->ssl_));
+
+#ifndef DBUG_OFF
+ errno = 0;
+#endif /* DBUG_OFF */
+ r = SSL_read(vio->ssl_, buf, size);
+#ifndef DBUG_OFF
+ if ( r<= 0) {
+ r=SSL_get_error(vio->ssl_, r);
+ DBUG_PRINT("info",("SSL_get_error returned %d",r));
+ report_errors();
+ }
+#endif /* DBUG_OFF */
+ DBUG_PRINT("exit", ("%d", r));
+ DBUG_RETURN(r);
+}
+
+
+int vio_ssl_write(Vio * vio, const gptr buf, int size)
+{
+ int r;
+ DBUG_ENTER("vio_ssl_write");
+ DBUG_PRINT("enter", ("sd=%d, buf=%p, size=%d", vio->sd, buf, size));
+
+#ifndef DBUG_OFF
+ errno = 0;
+#endif /* DBUG_OFF */
+ r = SSL_write(vio->ssl_, buf, size);
+#ifndef DBUG_OFF
+ if (r<0)
+ report_errors();
+#endif /* DBUG_OFF */
+ DBUG_PRINT("exit", ("%d", r));
+ DBUG_RETURN(r);
+}
+
+
+int vio_ssl_fastsend(Vio * vio __attribute__((unused)))
+{
+ int r=0;
+ DBUG_ENTER("vio_ssl_fastsend");
+
+#ifdef IPTOS_THROUGHPUT
+ {
+#ifndef __EMX__
+ int tos = IPTOS_THROUGHPUT;
+ if (!setsockopt(vio->sd, IPPROTO_IP, IP_TOS, (void *) &tos, sizeof(tos)))
+#endif /* !__EMX__ */
+ {
+ int nodelay = 1;
+ if (setsockopt(vio->sd, IPPROTO_TCP, TCP_NODELAY, (void *) &nodelay,
+ sizeof(nodelay))) {
+ DBUG_PRINT("warning",
+ ("Couldn't set socket option for fast send"));
+ r= -1;
+ }
+ }
+ }
+#endif /* IPTOS_THROUGHPUT */
+ DBUG_PRINT("exit", ("%d", r));
+ DBUG_RETURN(r);
+}
+
+int vio_ssl_keepalive(Vio* vio, my_bool set_keep_alive)
+{
+ int r=0;
+ uint opt = 0;
+ DBUG_ENTER("vio_ssl_keepalive");
+ DBUG_PRINT("enter", ("sd=%d, set_keep_alive=%d", vio->sd, (int)
+ set_keep_alive));
+ if (vio->type != VIO_TYPE_NAMEDPIPE)
+ {
+ if (set_keep_alive)
+ opt = 1;
+ r = setsockopt(vio->sd, SOL_SOCKET, SO_KEEPALIVE, (char *) &opt,
+ sizeof(opt));
+ }
+ DBUG_RETURN(r);
+}
+
+
+my_bool
+vio_ssl_should_retry(Vio * vio __attribute__((unused)))
+{
+ int en = socket_errno;
+ return (en == SOCKET_EAGAIN || en == SOCKET_EINTR ||
+ en == SOCKET_EWOULDBLOCK);
+}
+
+
+int vio_ssl_close(Vio * vio)
+{
+ int r;
+ DBUG_ENTER("vio_ssl_close");
+ r=0;
+ if (vio->ssl_)
+ {
+ r = SSL_shutdown(vio->ssl_);
+ SSL_free(vio->ssl_);
+ vio->ssl_= 0;
+ }
+ if (shutdown(vio->sd,2))
+ r= -1;
+ if (closesocket(vio->sd))
+ r= -1;
+ if (r)
+ {
+ DBUG_PRINT("error", ("close() failed, error: %d",socket_errno));
+ report_errors();
+ /* FIXME: error handling (not critical for MySQL) */
+ }
+ vio->type= VIO_CLOSED;
+ vio->sd= -1;
+ DBUG_RETURN(r);
+}
+
+
+const char *vio_ssl_description(Vio * vio)
+{
+ return vio->desc;
+}
+
+enum enum_vio_type vio_ssl_type(Vio* vio)
+{
+ return vio->type;
+}
+
+my_socket vio_ssl_fd(Vio* vio)
+{
+ return vio->sd;
+}
+
+
+my_bool vio_ssl_peer_addr(Vio * vio, char *buf)
+{
+ DBUG_ENTER("vio_ssl_peer_addr");
+ DBUG_PRINT("enter", ("sd=%d", vio->sd));
+ if (vio->localhost)
+ {
+ strmov(buf,"127.0.0.1");
+ }
+ else
+ {
+ size_socket addrLen = sizeof(struct sockaddr);
+ if (getpeername(vio->sd, (struct sockaddr *) (& (vio->remote)),
+ &addrLen) != 0)
+ {
+ DBUG_PRINT("exit", ("getpeername, error: %d", socket_errno));
+ DBUG_RETURN(1);
+ }
+ /* FIXME */
+/* my_inet_ntoa(vio->remote.sin_addr,buf); */
+ }
+ DBUG_PRINT("exit", ("addr=%s", buf));
+ DBUG_RETURN(0);
+}
+
+
+void vio_ssl_in_addr(Vio *vio, struct in_addr *in)
+{
+ DBUG_ENTER("vio_ssl_in_addr");
+ if (vio->localhost)
+ bzero((char*) in, sizeof(*in)); /* This should never be executed */
+ else
+ *in=vio->remote.sin_addr;
+ DBUG_VOID_RETURN;
+}
+
+
+void sslaccept(struct st_VioSSLAcceptorFd* ptr, Vio* vio, long timeout)
+{
+ char *str;
+ char buf[1024];
+ X509* client_cert;
+ DBUG_ENTER("sslaccept");
+ DBUG_PRINT("enter", ("sd=%d ptr=%p", vio->sd,ptr));
+ vio_reset(vio,VIO_TYPE_SSL,vio->sd,0,FALSE);
+ vio->ssl_=0;
+ vio->open_=FALSE;
+ if (!(vio->ssl_ = SSL_new(ptr->ssl_context_)))
+ {
+ DBUG_PRINT("error", ("SSL_new failure"));
+ report_errors();
+ DBUG_VOID_RETURN;
+ }
+ DBUG_PRINT("info", ("ssl_=%p timeout=%ld",vio->ssl_, timeout));
+ SSL_clear(vio->ssl_);
+ vio_blocking(vio, FALSE);
+ SSL_SESSION_set_timeout(SSL_get_session(vio->ssl_), timeout);
+ SSL_set_fd(vio->ssl_,vio->sd);
+ SSL_set_accept_state(vio->ssl_);
+ SSL_do_handshake(vio->ssl_);
+ vio->open_ = TRUE;
+#ifndef DBUF_OFF
+ DBUG_PRINT("info",("SSL_get_cipher_name() = '%s'"
+ ,SSL_get_cipher_name(vio->ssl_)));
+ client_cert = SSL_get_peer_certificate (vio->ssl_);
+ if (client_cert != NULL) {
+ DBUG_PRINT("info",("Client certificate:"));
+ str = X509_NAME_oneline (X509_get_subject_name (client_cert), 0, 0);
+ DBUG_PRINT("info",("\t subject: %s", str));
+ free (str);
+
+ str = X509_NAME_oneline (X509_get_issuer_name (client_cert), 0, 0);
+ DBUG_PRINT("info",("\t issuer: %s", str));
+ free (str);
+
+ X509_free (client_cert);
+ } else
+ DBUG_PRINT("info",("Client does not have certificate."));
+
+ str=SSL_get_shared_ciphers(vio->ssl_, buf, sizeof(buf));
+ if(str)
+ {
+ DBUG_PRINT("info",("SSL_get_shared_ciphers() returned '%s'",str));
+ }
+ else
+ {
+ DBUG_PRINT("info",("no shared ciphers!"));
+ }
+
+#endif
+ DBUG_VOID_RETURN;
+}
+
+void sslconnect(struct st_VioSSLConnectorFd* ptr, Vio* vio, long timeout)
+{
+ char *str;
+ X509* server_cert;
+ DBUG_ENTER("sslconnect");
+ DBUG_PRINT("enter", ("sd=%d ptr=%p ctx: %p", vio->sd,ptr,ptr->ssl_context_));
+ vio_reset(vio,VIO_TYPE_SSL,vio->sd,0,FALSE);
+ vio->ssl_=0;
+ vio->open_=FALSE;
+ if (!(vio->ssl_ = SSL_new(ptr->ssl_context_)))
+ {
+ DBUG_PRINT("error", ("SSL_new failure"));
+ report_errors();
+ DBUG_VOID_RETURN;
+ }
+ DBUG_PRINT("info", ("ssl_=%p timeout=%ld",vio->ssl_, timeout));
+ SSL_clear(vio->ssl_);
+ vio_blocking(vio, FALSE);
+ SSL_SESSION_set_timeout(SSL_get_session(vio->ssl_), timeout);
+ SSL_set_fd (vio->ssl_, vio->sd);
+ SSL_set_connect_state(vio->ssl_);
+ SSL_do_handshake(vio->ssl_);
+ vio->open_ = TRUE;
+#ifndef DBUG_OFF
+ DBUG_PRINT("info",("SSL_get_cipher_name() = '%s'"
+ ,SSL_get_cipher_name(vio->ssl_)));
+ server_cert = SSL_get_peer_certificate (vio->ssl_);
+ if (server_cert != NULL) {
+ DBUG_PRINT("info",("Server certificate:"));
+ str = X509_NAME_oneline (X509_get_subject_name (server_cert), 0, 0);
+ DBUG_PRINT("info",("\t subject: %s", str));
+ free (str);
+
+ str = X509_NAME_oneline (X509_get_issuer_name (server_cert), 0, 0);
+ DBUG_PRINT("info",("\t issuer: %s", str));
+ free (str);
+
+ /* We could do all sorts of certificate verification stuff here before
+ * deallocating the certificate. */
+
+ X509_free (server_cert);
+ } else
+ DBUG_PRINT("info",("Server does not have certificate."));
+#endif
+ DBUG_VOID_RETURN;
+}
+
+#endif /* HAVE_OPENSSL */
diff --git a/vio/viosslfactories.c b/vio/viosslfactories.c
new file mode 100644
index 00000000000..322c1ce01e4
--- /dev/null
+++ b/vio/viosslfactories.c
@@ -0,0 +1,344 @@
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <my_global.h>
+
+#ifdef HAVE_OPENSSL
+
+#include <my_sys.h>
+#include <mysql_com.h>
+#include <violite.h>
+
+
+static bool ssl_algorithms_added = FALSE;
+static bool ssl_error_strings_loaded= FALSE;
+static int verify_depth = 0;
+static int verify_error = X509_V_OK;
+
+static unsigned char dh512_p[]={
+ 0xDA,0x58,0x3C,0x16,0xD9,0x85,0x22,0x89,0xD0,0xE4,0xAF,0x75,
+ 0x6F,0x4C,0xCA,0x92,0xDD,0x4B,0xE5,0x33,0xB8,0x04,0xFB,0x0F,
+ 0xED,0x94,0xEF,0x9C,0x8A,0x44,0x03,0xED,0x57,0x46,0x50,0xD3,
+ 0x69,0x99,0xDB,0x29,0xD7,0x76,0x27,0x6B,0xA2,0xD3,0xD4,0x12,
+ 0xE2,0x18,0xF4,0xDD,0x1E,0x08,0x4C,0xF6,0xD8,0x00,0x3E,0x7C,
+ 0x47,0x74,0xE8,0x33,
+};
+static unsigned char dh512_g[]={
+ 0x02,
+};
+
+static DH *get_dh512(void)
+{
+ DH *dh=NULL;
+
+ if ((dh=DH_new()) == NULL) return(NULL);
+ dh->p=BN_bin2bn(dh512_p,sizeof(dh512_p),NULL);
+ dh->g=BN_bin2bn(dh512_g,sizeof(dh512_g),NULL);
+ if ((dh->p == NULL) || (dh->g == NULL))
+ return(NULL);
+ return(dh);
+}
+
+static void
+report_errors()
+{
+ unsigned long l;
+ const char* file;
+ const char* data;
+ int line,flags;
+
+ DBUG_ENTER("report_errors");
+
+ while ((l=ERR_get_error_line_data(&file,&line,&data,&flags)) != 0)
+ {
+ char buf[200];
+ DBUG_PRINT("error", ("OpenSSL: %s:%s:%d:%s\n", ERR_error_string(l,buf),
+ file,line,(flags&ERR_TXT_STRING)?data:"")) ;
+ }
+ DBUG_VOID_RETURN;
+}
+
+
+static int
+vio_set_cert_stuff(SSL_CTX *ctx, const char *cert_file, const char *key_file)
+{
+ DBUG_ENTER("vio_set_cert_stuff");
+ DBUG_PRINT("enter", ("ctx=%p, cert_file=%s, key_file=%s",
+ ctx, cert_file, key_file));
+ if (cert_file != NULL)
+ {
+ if (SSL_CTX_use_certificate_file(ctx,cert_file,SSL_FILETYPE_PEM) <= 0)
+ {
+ DBUG_PRINT("error",("unable to get certificate from '%s'\n",cert_file));
+ /* FIX stderr */
+ ERR_print_errors_fp(stderr);
+ DBUG_RETURN(0);
+ }
+ if (key_file == NULL)
+ key_file = cert_file;
+ if (SSL_CTX_use_PrivateKey_file(ctx,key_file,
+ SSL_FILETYPE_PEM) <= 0)
+ {
+ DBUG_PRINT("error", ("unable to get private key from '%s'\n",key_file));
+ /* FIX stderr */
+ ERR_print_errors_fp(stderr);
+ DBUG_RETURN(0);
+ }
+
+ /* If we are using DSA, we can copy the parameters from
+ * the private key */
+ /* Now we know that a key and cert have been set against
+ * the SSL context */
+ if (!SSL_CTX_check_private_key(ctx))
+ {
+ DBUG_PRINT("error", ("Private key does not match the certificate public key\n"));
+ DBUG_RETURN(0);
+ }
+ }
+ DBUG_RETURN(1);
+}
+
+
+static int
+vio_verify_callback(int ok, X509_STORE_CTX *ctx)
+{
+ char buf[256];
+ X509* err_cert;
+ int err,depth;
+
+ DBUG_ENTER("vio_verify_callback");
+ DBUG_PRINT("enter", ("ok=%d, ctx=%p", ok, ctx));
+ err_cert=X509_STORE_CTX_get_current_cert(ctx);
+ err= X509_STORE_CTX_get_error(ctx);
+ depth= X509_STORE_CTX_get_error_depth(ctx);
+
+ X509_NAME_oneline(X509_get_subject_name(err_cert),buf,sizeof(buf));
+ if (!ok)
+ {
+ DBUG_PRINT("error",("verify error:num=%d:%s\n",err,
+ X509_verify_cert_error_string(err)));
+ if (verify_depth >= depth)
+ {
+ ok=1;
+ verify_error=X509_V_OK;
+ }
+ else
+ {
+ ok=0;
+ verify_error=X509_V_ERR_CERT_CHAIN_TOO_LONG;
+ }
+ }
+ switch (ctx->error) {
+ case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
+ X509_NAME_oneline(X509_get_issuer_name(ctx->current_cert),buf,256);
+ DBUG_PRINT("info",("issuer= %s\n",buf));
+ break;
+ case X509_V_ERR_CERT_NOT_YET_VALID:
+ case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
+ DBUG_PRINT("error", ("notBefore"));
+ /*ASN1_TIME_print_fp(stderr,X509_get_notBefore(ctx->current_cert));*/
+ break;
+ case X509_V_ERR_CERT_HAS_EXPIRED:
+ case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
+ DBUG_PRINT("error", ("notAfter error"));
+ /*ASN1_TIME_print_fp(stderr,X509_get_notAfter(ctx->current_cert));*/
+ break;
+ }
+ DBUG_PRINT("exit", ("r=%d", ok));
+ DBUG_RETURN(ok);
+}
+
+
+/************************ VioSSLConnectorFd **********************************/
+struct st_VioSSLConnectorFd* new_VioSSLConnectorFd(const char* key_file,
+ const char* cert_file,
+ const char* ca_file,
+ const char* ca_path,
+ const char* cipher)
+{
+ int verify = SSL_VERIFY_PEER;
+ struct st_VioSSLConnectorFd* ptr;
+ int result;
+ DH *dh=NULL;
+ DBUG_ENTER("new_VioSSLConnectorFd");
+ DBUG_PRINT("enter",
+ ("key_file=%s, cert_file=%s, ca_path=%s, ca_file=%s, cipher=%s",
+ key_file, cert_file, ca_path, ca_file, cipher));
+ ptr=(struct st_VioSSLConnectorFd*)my_malloc(sizeof(struct st_VioSSLConnectorFd),MYF(0));
+ ptr->ssl_context_=0;
+ ptr->ssl_method_=0;
+ /* FIXME: constants! */
+
+ if (!ssl_algorithms_added)
+ {
+ DBUG_PRINT("info", ("todo: OpenSSL_add_all_algorithms()"));
+ ssl_algorithms_added = TRUE;
+ OpenSSL_add_all_algorithms();
+ }
+ if (!ssl_error_strings_loaded)
+ {
+ DBUG_PRINT("info", ("todo:SSL_load_error_strings()"));
+ ssl_error_strings_loaded = TRUE;
+ SSL_load_error_strings();
+ }
+ ptr->ssl_method_ = TLSv1_client_method();
+ ptr->ssl_context_ = SSL_CTX_new(ptr->ssl_method_);
+ DBUG_PRINT("info", ("ssl_context_: %p",ptr->ssl_context_));
+ if (ptr->ssl_context_ == 0)
+ {
+ DBUG_PRINT("error", ("SSL_CTX_new failed"));
+ report_errors();
+ goto ctor_failure;
+ }
+ /*
+ * SSL_CTX_set_options
+ * SSL_CTX_set_info_callback
+ */
+ if(cipher)
+ {
+ result=SSL_CTX_set_cipher_list(ptr->ssl_context_, cipher);
+ DBUG_PRINT("info",("SSL_set_cipher_list() returned %d",result));
+ }
+ SSL_CTX_set_verify(ptr->ssl_context_, verify, vio_verify_callback);
+ if (vio_set_cert_stuff(ptr->ssl_context_, cert_file, key_file) == -1)
+ {
+ DBUG_PRINT("error", ("vio_set_cert_stuff failed"));
+ report_errors();
+ goto ctor_failure;
+ }
+ if (SSL_CTX_load_verify_locations( ptr->ssl_context_, ca_file,ca_path)==0)
+ {
+ DBUG_PRINT("warning", ("SSL_CTX_load_verify_locations failed"));
+ if (SSL_CTX_set_default_verify_paths(ptr->ssl_context_)==0)
+ {
+ DBUG_PRINT("error", ("SSL_CTX_set_default_verify_paths failed"));
+ report_errors();
+ goto ctor_failure;
+ }
+ }
+
+ /* DH stuff */
+ dh=get_dh512();
+ SSL_CTX_set_tmp_dh(ptr->ssl_context_,dh);
+ DH_free(dh);
+
+ DBUG_RETURN(ptr);
+ctor_failure:
+ DBUG_PRINT("exit", ("there was an error"));
+ my_free((gptr)ptr,MYF(0));
+ DBUG_RETURN(0);
+}
+
+
+/************************ VioSSLAcceptorFd **********************************/
+
+struct st_VioSSLAcceptorFd*
+new_VioSSLAcceptorFd(const char* key_file,
+ const char* cert_file,
+ const char* ca_file,
+ const char* ca_path,
+ const char* cipher)
+{
+ int verify = (SSL_VERIFY_PEER |
+ SSL_VERIFY_FAIL_IF_NO_PEER_CERT |
+ SSL_VERIFY_CLIENT_ONCE);
+
+ struct st_VioSSLAcceptorFd* ptr;
+ int result;
+ DH *dh=NULL;
+ DBUG_ENTER("new_VioSSLAcceptorFd");
+ DBUG_PRINT("enter",
+ ("key_file=%s, cert_file=%s, ca_path=%s, ca_file=%s, cipher=%s",
+ key_file, cert_file, ca_path, ca_file, cipher));
+
+ ptr=(struct st_VioSSLAcceptorFd*)my_malloc(sizeof(struct st_VioSSLAcceptorFd),MYF(0));
+ ptr->ssl_context_=0;
+ ptr->ssl_method_=0;
+ /* FIXME: constants! */
+ ptr->session_id_context_ = ptr;
+
+ if (!ssl_algorithms_added)
+ {
+ DBUG_PRINT("info", ("todo: OpenSSL_add_all_algorithms()"));
+ ssl_algorithms_added = TRUE;
+ OpenSSL_add_all_algorithms();
+
+ }
+ if (!ssl_error_strings_loaded)
+ {
+ DBUG_PRINT("info", ("todo: SSL_load_error_strings()"));
+ ssl_error_strings_loaded = TRUE;
+ SSL_load_error_strings();
+ }
+ ptr->ssl_method_ = TLSv1_server_method();
+ ptr->ssl_context_ = SSL_CTX_new(ptr->ssl_method_);
+ if (ptr->ssl_context_==0)
+ {
+ DBUG_PRINT("error", ("SSL_CTX_new failed"));
+ report_errors();
+ goto ctor_failure;
+ }
+ if(cipher)
+ {
+ result=SSL_CTX_set_cipher_list(ptr->ssl_context_, cipher);
+ DBUG_PRINT("info",("SSL_set_cipher_list() returned %d",result));
+ }
+ /*
+ * SSL_CTX_set_quiet_shutdown(ctx,1);
+ *
+ */
+ SSL_CTX_sess_set_cache_size(ptr->ssl_context_,128);
+
+
+
+ /* DH?
+ */
+ SSL_CTX_set_verify(ptr->ssl_context_, verify, vio_verify_callback);
+ SSL_CTX_set_session_id_context(ptr->ssl_context_,(const uchar*)&(ptr->session_id_context_),sizeof(ptr->session_id_context_));
+
+ /*
+ * SSL_CTX_set_client_CA_list(ctx,SSL_load_client_CA_file(CAfile));
+ */
+ if (vio_set_cert_stuff(ptr->ssl_context_, cert_file, key_file) == -1)
+ {
+ DBUG_PRINT("error", ("vio_set_cert_stuff failed"));
+ report_errors();
+ goto ctor_failure;
+ }
+ if (SSL_CTX_load_verify_locations( ptr->ssl_context_, ca_file, ca_path)==0)
+ {
+ DBUG_PRINT("warning", ("SSL_CTX_load_verify_locations failed"));
+ if (SSL_CTX_set_default_verify_paths(ptr->ssl_context_)==0)
+ {
+ DBUG_PRINT("error", ("SSL_CTX_set_default_verify_paths failed"));
+ report_errors();
+ goto ctor_failure;
+ }
+ }
+ /* DH stuff */
+ dh=get_dh512();
+ SSL_CTX_set_tmp_dh(ptr->ssl_context_,dh);
+ DH_free(dh);
+
+ DBUG_RETURN(ptr);
+ctor_failure:
+ DBUG_PRINT("exit", ("there was an error"));
+ my_free((gptr)ptr,MYF(0));
+ DBUG_RETURN(0);
+}
+
+
+#endif /* HAVE_OPENSSL */
diff --git a/vio/viotest-ssl.c b/vio/viotest-ssl.c
new file mode 100644
index 00000000000..8c549ae1d38
--- /dev/null
+++ b/vio/viotest-ssl.c
@@ -0,0 +1,156 @@
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <my_global.h>
+#ifdef HAVE_OPENSSL
+#include <my_sys.h>
+#include <m_string.h>
+#include <m_ctype.h>
+#include "mysql.h"
+#include "errmsg.h"
+#include <my_dir.h>
+#ifndef __GNU_LIBRARY__
+#define __GNU_LIBRARY__ // Skip warnings in getopt.h
+#endif
+#include <getopt.h>
+//#include "my_readline.h"
+#include <signal.h>
+#include <violite.h>
+
+const char *VER="0.1";
+
+
+#ifndef DBUG_OFF
+const char *default_dbug_option="d:t:O,/tmp/viotest-ssl.trace";
+#endif
+
+void
+fatal_error( const char* r)
+{
+ perror(r);
+ exit(0);
+}
+
+void
+print_usage()
+{
+ printf("viossl-test: testing SSL virtual IO. Usage:\n");
+ printf("viossl-test server-key server-cert client-key client-cert [CAfile] [CApath]\n");
+}
+
+int
+main( int argc,
+ char** argv)
+{
+ char* server_key = 0;
+ char* server_cert = 0;
+ char* client_key = 0;
+ char* client_cert = 0;
+ char* ca_file = 0;
+ char* ca_path = 0;
+ int child_pid,sv[2];
+ struct st_VioSSLAcceptorFd* ssl_acceptor=0;
+ struct st_VioSSLConnectorFd* ssl_connector=0;
+ Vio* client_vio=0;
+ Vio* server_vio=0;
+ MY_INIT(argv[0]);
+// DBUG_ENTER("main");
+ DBUG_PROCESS(argv[0]);
+ DBUG_PUSH(default_dbug_option);
+
+
+
+ if (argc<5)
+ {
+ print_usage();
+ return 1;
+ }
+
+ server_key = argv[1];
+ server_cert = argv[2];
+ client_key = argv[3];
+ client_cert = argv[4];
+ if (argc>5)
+ ca_file = argv[5];
+ if (argc>6)
+ ca_path = argv[6];
+ printf("Server key/cert : %s/%s\n", server_key, server_cert);
+ printf("Client key/cert : %s/%s\n", client_key, client_cert);
+ if (ca_file!=0)
+ printf("CAfile : %s\n", ca_file);
+ if (ca_path!=0)
+ printf("CApath : %s\n", ca_path);
+
+
+ if (socketpair(PF_UNIX, SOCK_STREAM, IPPROTO_IP, sv)==-1)
+ fatal_error("socketpair");
+
+ ssl_acceptor = new_VioSSLAcceptorFd(server_key, server_cert, ca_file, ca_path);
+ ssl_connector = new_VioSSLConnectorFd(client_key, client_cert, ca_file, ca_path);
+
+ client_vio = (Vio*)my_malloc(sizeof(struct st_vio),MYF(0));
+ client_vio->sd = sv[0];
+ sslconnect(ssl_connector,client_vio);
+ server_vio = (Vio*)my_malloc(sizeof(struct st_vio),MYF(0));
+ server_vio->sd = sv[1];
+ sslaccept(ssl_acceptor,server_vio);
+
+ printf("Socketpair: %d , %d\n", client_vio->sd, server_vio->sd);
+
+ child_pid = fork();
+ if (child_pid==-1) {
+ my_free((gptr)ssl_acceptor,MYF(0));
+ my_free((gptr)ssl_connector,MYF(0));
+ fatal_error("fork");
+ }
+ if (child_pid==0) {
+ //child, therefore, client
+ char xbuf[100];
+ int r = vio_ssl_read(client_vio,xbuf, sizeof(xbuf));
+ if (r<=0) {
+ my_free((gptr)ssl_acceptor,MYF(0));
+ my_free((gptr)ssl_connector,MYF(0));
+ fatal_error("client:SSL_read");
+ }
+// printf("*** client cipher %s\n",client_vio->cipher_description());
+ xbuf[r] = 0;
+ printf("client:got %s\n", xbuf);
+ my_free((gptr)client_vio,MYF(0));
+ my_free((gptr)ssl_acceptor,MYF(0));
+ my_free((gptr)ssl_connector,MYF(0));
+ sleep(1);
+ } else {
+ const char* s = "Huhuhuh";
+ int r = vio_ssl_write(server_vio,(gptr)s, strlen(s));
+ if (r<=0) {
+ my_free((gptr)ssl_acceptor,MYF(0));
+ my_free((gptr)ssl_connector,MYF(0));
+ fatal_error("server:SSL_write");
+ }
+// printf("*** server cipher %s\n",server_vio->cipher_description());
+ my_free((gptr)server_vio,MYF(0));
+ my_free((gptr)ssl_acceptor,MYF(0));
+ my_free((gptr)ssl_connector,MYF(0));
+ sleep(1);
+ }
+ return 0;
+}
+#else /* HAVE_OPENSSL */
+
+int main() {
+return 0;
+}
+#endif /* HAVE_OPENSSL */
diff --git a/vio/viotest-ssl.cc b/vio/viotest-ssl.cc
deleted file mode 100644
index a3ad92a7c9c..00000000000
--- a/vio/viotest-ssl.cc
+++ /dev/null
@@ -1,104 +0,0 @@
-#include "all.h"
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <stdio.h>
-#include <unistd.h>
-
-
-void
-fatal_error( const char* r)
-{
- perror(r);
- exit(0);
-}
-
-void
-print_usage()
-{
- printf("viossltest: testing SSL virtual IO. Usage:\n");
- printf("viossltest server-key server-cert client-key client-cert [CAfile] [CApath]\n");
-}
-
-int
-main( int argc,
- char** argv)
-{
- char* server_key = 0;
- char* server_cert = 0;
- char* client_key = 0;
- char* client_cert = 0;
- char* ca_file = 0;
- char* ca_path = 0;
- int sv[2];
-
- if (argc<5)
- {
- print_usage();
- return 1;
- }
-
- if (socketpair(PF_UNIX, SOCK_STREAM, IPPROTO_IP, sv)==-1)
- fatal_error("socketpair");
-
- server_key = argv[1];
- server_cert = argv[2];
- client_key = argv[3];
- client_cert = argv[4];
- if (argc>5)
- ca_file = argv[5];
- if (argc>6)
- ca_path = argv[6];
- printf("Server key/cert : %s/%s\n", server_key, server_cert);
- printf("Client key/cert : %s/%s\n", client_key, client_cert);
- if (ca_file!=0)
- printf("CAfile : %s\n", ca_file);
- if (ca_path!=0)
- printf("CApath : %s\n", ca_path);
-
- VIO_NS::VioSSLAcceptorFd* ssl_acceptor = new VIO_NS::VioSSLAcceptorFd(server_key, server_cert, ca_file, ca_path);
- VIO_NS::VioSSLConnectorFd* ssl_connector = new VIO_NS::VioSSLConnectorFd(client_key, client_cert, ca_file, ca_path);
-
- printf("Socketpair: %d , %d\n", sv[0], sv[1]);
-
- VIO_NS::VioSSL* client_vio = ssl_connector->connect(sv[0]);
- VIO_NS::VioSSL* server_vio = ssl_acceptor->accept(sv[1]);
-
-
- int child_pid = fork();
- if (child_pid==-1) {
- delete ssl_acceptor;
- delete ssl_connector;
- fatal_error("fork");
- }
- if (child_pid==0) {
- //child, therefore, client
- char xbuf[100];
- int r = client_vio->read(xbuf, sizeof(xbuf));
- if (r<=0) {
- delete ssl_acceptor;
- delete ssl_connector;
- fatal_error("client:SSL_read");
- }
- printf("*** client cipher %s\n",client_vio->cipher_description());
- xbuf[r] = 0;
- printf("client:got %s\n", xbuf);
- delete client_vio;
- delete ssl_acceptor;
- delete ssl_connector;
- sleep(1);
- } else {
- const char* s = "Huhuhuh";
- int r = server_vio->write((void *)s, strlen(s));
- if (r<=0) {
- delete ssl_acceptor;
- delete ssl_connector;
- fatal_error("server:SSL_write");
- }
- printf("*** server cipher %s\n",server_vio->cipher_description());
- delete server_vio;
- delete ssl_acceptor;
- delete ssl_connector;
- sleep(1);
- }
-}
diff --git a/vio/viotypes.h b/vio/viotypes.h
deleted file mode 100644
index 8d36a35c86f..00000000000
--- a/vio/viotypes.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
-** Virtual I/O library
-** Written by Andrei Errapart <andreie@no.spam.ee>
-*/
-
-/*
- * Some typedefs to external types.
- */
-#ifndef vio_viotypes_h_
-#define vio_viotypes_h_
-
-#include <stdarg.h>
-#include <stdio.h>
-#include <sys/types.h>
-
-typedef int vio_bool_t;
-typedef void* vio_ptr_t;
-
-#ifdef __cplusplus
-VIO_NS_BEGIN
-
-typedef vio_ptr_t vio_ptr;
-typedef char* vio_cstring;
-typedef int32_t vio_int32;
-typedef u_int32_t vio_uint32;
-typedef vio_bool_t vio_bool;
-
-VIO_NS_END
-#endif /* __cplusplus */
-
-#endif /* vio_types_h_ */
-